Dialect of Python with explicit variable declaration and block scoping, with a lightweight and easy-to-embed bytecode compiler and interpreter.
Go to file
2021-02-10 14:44:59 +09:00
.github Make that slightly smaller 2021-01-09 13:01:31 +09:00
modules Eliminate builtins.krk 2021-02-05 17:22:08 +09:00
src Fix up binpath discovery which was totally broken 2021-02-10 14:44:59 +09:00
test Wrap some things in readers-writer locks and now more stuff doesn't break 2021-02-10 10:20:56 +09:00
.gitignore Improve build support and prep a 1.0.1 bugfix 2021-01-31 11:00:01 +09:00
LICENSE meta stuff 2020-12-26 16:59:43 +09:00
Makefile Threading 2021-02-09 18:51:09 +09:00
README.md cmd.exe actually does work with the Windows build 2021-02-09 19:11:35 +09:00

logo

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.

Features

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: list, dict, tuple, 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 str class providing methods like .format())
  • Exception handling, with try/except/raise.
  • Modules, both for native C code and managed Kuroko code.
  • Unicode strings and identifiers.

Building Kuroko

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.

Generally, 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:

CC=x86_64-w64-mingw32-gcc make

A capable terminal, such as Windows Terminal, is required to run the interpreter's REPL correctly; CMD.exe has also been tested successfully.

Code Samples

Please see the wiki for examples of Kuroko code, or follow the interactive tutorial.

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.