Kuroko - A bytecode-compiled scripting language
Kuroko is a bytecode-compiled, dynamic, interpreted programming language with familiar Python-like syntax and a small, embeddable core
The bytecode VM / compiler is substantially based on Robert Nystrom's Crafting Interpreters.
This project was originally started to add a proper scripting language to Bim to support syntax highlighting and plugins, as well as to give ToaruOS a general-purpose user language for applications and utilities.
Kuroko inherits some core features by virtue of following Crafting Interpreters, including its basic type system, classes/methods/functions, and the design of its compiler and bytecode VM.
On top of this, Kuroko adds a number of features inspired by Python, such as:
- Indentation-based block syntax.
- Collection types:
set, with compiler literal syntax (
- List, dict, tuple, and set comprehensions (
[foo(x) for x in [1,2,3,4]]and similar expressions).
- Iterable types, with
for ... in ...syntax.
- Class methods for basic types (eg. strings are instances of a
strclass providing methods like
- Exception handling, with
- Modules, both for native C code and managed Kuroko code.
- Unicode strings and identifiers.
Building as a Shared Library
Kuroko has a minimal set of C standard library dependencies as well as optional dependencies on
ldl (for runtime C extension loading) and
lpthread (for threads).
When built against
rline (the rich line editing library that provides tab completion and syntax highlighting for the REPL), additional termios-related functions are required;
rline will only be built into the interpreter binary and not the shared library.
make should suffice to build from the repository and
sudo make install should work Debian-style multiarch environments, but check whether the default
libdir and so on are appropriate for your platform.
Source files are found in
src; those beginning with
module_ are normally built as a separate C extension modules and may have different requirements from the rest of the VM.
Building as a Single Static Binary
Configuration options are available in the Makefile to build Kuroko as a static binary.
make clean; make KRK_ENABLE_STATIC=1
This will produce a static binary without
dlopen support, so it will not be able to load additional C modules at runtime.
The standard set of C modules can be bundled into the interpreter, whether building statically or normally:
make clean; make KRK_ENABLE_BUNDLE=1
Additional options include
KRK_DISABLE_RLINE=1 to not link with the included rich line editing library (will lose tab completion and syntax highlighting in the repl) and
KRK_DISABLE_DEBUG=1 to disable debugging features (which has not been demonstrated to provide any meaningful performance improvement when the VM is built with optimizations enabled).
Building for WASM
See klange/kuroko-wasm-repl for information on building Kuroko with Emscripten for use in a web browser.
Building for Windows
Experimental support is available for building Kuroko to run on Windows using MingW:
A capable terminal, such as Windows Terminal, is required to run the interpreter's REPL correctly; CMD.exe has also been tested successfully.
About the REPL
Kuroko's repl provides an interactive environment for executing code and seeing results.
When entering code at the repl, lines ending with colons (
:) are treated specially - the repl will continue to accept input and automatically insert indentation on a new line. Please note that the repl's understanding of colons is naive: Whitespace or comments after a colon which would normally be accepted by Kuroko's parser will not be understood by the repl - if you want to place a comment after the start of a block statement, be sure that it ends in a colon so you can continue to enter statements.
Pressing backspace when the cursor is preceded by whitespace will delete up to the last column divisible by 4, which should generally delete one level of indentation automatically.
The tab key will also produce spaces when the cursor is at the beginning of the line or preceded entirely with white space.
The repl will display indentation level indicators in preceding whitespace as a helpful guide.
When a blank line or a line consisting entirely of whitespace is entered, the repl will process the full input.
Code executed in the repl runs in a global scope and reused variable names will overwrite previous definitions, allowing function and class names to be reused.
The repl will display the last value popped from the stack before returning.
Tab completion will provide the names of globals, as well as the fields and methods of objects.
What's different from Python?
You may be looking at the code examples and thinking Kuroko looks a lot more like Python than "syntax similar to Python" suggests. Still, there are some differences, and they come in two forms: Intentional differences and unintentional differences.
Unintentional differences likely represent incomplete features. Intentional differences are design decisions specifically meant to differentiate Kuroko from Python and usually are an attempt to improve upon or "fix" perceived mistakes.
Two notable intentional differences thus far are:
- Kuroko's variable scoping requires explicit declarations. This was done because Python's function-level scoping, and particularly how it interacts with globals, is often a thorn in the side of beginner and seasoned programmers alike. It's not so much seen as a mistake as it is something we don't wish to replicate.
- Default arguments to functions are evaluated at call time, not at definition time. How many times have you accidentally assigned an empty list as a default argument, only to be burned by its mutated descendent appearing in further calls? Kuroko doesn't do that - it works more like Ruby.
Interfacing C with Kuroko
Please see the wiki for detailed instructions on embedded Kuroko or building new C extensions.