Skip to content

DELOLCAT/koniscript

Repository files navigation

koniscript logo
Simple · Readable · Cross-Platform · Dynamic

⚠️ NOTICE: koniscript is still in early development, expect breaking changes


AI Policy

If you don't plan on contributing, continue to the next heading.

I am quite strict about AI use in programming. I have supplied a GEMINI.md file (you can rename to agents.md for support with other tools) for agents, as they can be quite useful for finding the origin of a bug, reviewing code, suggesting enhancements, and also writing tests. I've also added sourcery-ai to this repo, as its code reviews can also be nice.

However, I do NOT like using AI for anything more than above. If a PR is LLM generated, or violates any of the guidelines above, it would get discarded, although any ideas it created may be considered. Anybody can type out prompts - that's not useful, but everybody can't review code that clearly has low quality, not aligned with goals, or are created by people that don't even know how the code works.

See CONTRIBUTING.md for more info

About

koniscript is a dynamic programming language that focuses on these main features:

  • A ridiculously simple stack based VM (konivm, shortened to kovm) that you could implement almost anywhere - even in Scratch mods. The instruction set only has 14 required instructions, and 7 optional ones (managed through @require flags)
  • Readability of code
  • Single file packaging - code compiles down to a single .knc bytecode file
  • Compatibility, with @require flags (ex. @require fs, gui, see the syntax example for more) so koniscript can work smoothly across multiple runtime environments. This also means that runtimes can be even smaller, and also on embedded systems.

Usage

Writing a program

  • Types: 'string', integer: 2, float: 3.14, and booleans true/false
  • Function calls: name(args)
  • Comments (multi-line soon): # I am a comment

For example, using the above:

println('foo, bar', 'baz') # The println function takes multiple arguments, and concatenates them with a space
  • Variables:
let this_is_a_var = 'foo'
println(this_is_a_var)
  • Arithmetic:
println(5 + 5 / 2)
  • Conditionals:
let num = input('Enter a number\n>>> ') # The input function prints a message and waits for user input, returning the input given by the user.

println(num == 5)
if num == 5 {
  println('The number is equal to 5')
} else if num == 10 {
  println('The number is equal to 10')
} else {
  println('The number is not equal to 5 or 10')
}
  • While loops
let i = 0
while i < 5 {
  println(i)
  i+=1 # There is no `let` here, so it uses the variable `i` declared above
}

The break keyword is also supported

  • Functions (and recursion):
func fib(n) {
  if n <= 1 {
    return n
  }
  return fib(n - 1) + fib(n - 2)
}

println(fib(10)) # => 55

Functions are also first class

func run_with_message(f) {
  println('Running...')
  let val = f() # Note that this will raise a warning, as the compiler can't check the number of arguments. This will be fixed when the type checker is released.
  println('Completed!')
  return val
}

func some_callback() {
  println('Hello from the inner callback!')
}

run_with_message(some_callback)
  • Requirements:
@require strings.methods, attributes # A bare require statement will cause the VM to exit when starting to execute.
println('hi'.upper())

@require types.arrays {
  let arr = []
  arr.push('test')
} else {
  println('Arrays not supported') # Any code that tries to use arrays in here will fail to compile
}

@require indexes # All bare require statements are collected. This whole program will fail on launch if the runtime doesn't support indexes
# ...

Note that using a feature that is under a requirement will implicitly add the requirement and raise a warning, telling you to make it explicit.

  • Arrays:
@require types.arrays

let a = [
  'foo',
  'bar'
]

println(a[0]) # => foo

a.push('baz')

println(a) # => ['foo', 'bar', 'baz']
  • Dictionaries (indev)
@require types.dicts

let a = %{
  'foo': 'bar',
  'baz': 5,
  5: 'boo'
}

println(a['foo']) # => bar
println(a.foo) # => bar

println(a.baz) # => 5
  • Imports:

main.kn

import some_mod
println(some_mod.hi())

some_mod.kn

export func hi() {
  println('Hello from some_mod!')
  return 'some value'
}
  • Runtime values:
@require runtime_values # Note that runtime values can change during runtime, thus they may be too complex for some runtimes to implement
func main() {
  println('Hello from my program')
}

if _name == '[main]' {
  main()
}

CLI

To run a program, use koni run:

$ koni run examples/fib.kn 
55

To compile a program, use koni compile:

$ koni compile examples/fib.kn
Compiling with debug (source+line info). See `koni compile --help` for more info
Wrote to examples/fib.knc

To run compiled programs, use kovm run:

$ kovm run ./examples/fib.knc
55

Roadmap

View GitHub Milestones to see the full roadmap with versions and progress.

Here are some features that are planned in the future:

Platform Files

A cross-platform, language agnostic, simple way for FFI, with a smart but simple versioning system (yes, I'm proud of that); see the full spec for more.

A type checker

Not much to write here, it'll just be a type checker similar to TypeScript.

Airport

A package manager focusing on DX. Full spec to be written

Build

Prerequisites

  • Rust
  • The uv package manager (will also auto-install the correct Python version for this project)

Steps

Clone the repo:

git clone https://github.com/DELOLCAT/koniscript.git
cd koniscript

Run build.py with uv:

uv run build.py

The output would be stored in dist/

About

No description, website, or topics provided.

Resources

License

Contributing

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages