kukel

package module
v0.8.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 14, 2026 License: MIT Imports: 28 Imported by: 0

README

kukel

A simple programming language, just for fun: Kukel, with C-like syntax, classes, closures and exceptions, compiled to bytecode for a small stack machine written in Go.

// shapes.kkl
class Shape { name; Shape(name); area(); describe(); }
Shape::Shape(name) { this->name = name; }
Shape::describe() { return name + ": " + str(area()); }

class Circle : Shape { r; Circle(r); area(); }
Circle::Circle(r) { Shape::Shape("circle"); this->r = r; }
Circle::area() { return 3.14159 * r * r; }

class Square : Shape { side; Square(side); area(); }
Square::Square(side) { Shape::Shape("square"); this->side = side; }
Square::area() { return side * side; }

main(args) {
    local shapes = [new Circle(1), new Square(3), new Circle(2)];
    sort(shapes, fn(a, b) { return a->area() < b->area(); });
    for (local s in shapes) println(s->describe());

    try {
        println(shapes[5]);
    } catch (e) {
        println("caught", e->kind + ":", e->message);
    }
}
$ kukel run shapes.kkl
circle: 3.14159
square: 9
circle: 12.56636
caught RangeError: index 5 out of range for vector of length 3

What is in the language

  • ints (64-bit, wrapping), floats, strings (bytes), booleans, nil
  • vectors and maps (insertion order) with literals, indexing and for-each
  • functions with default and rest parameters, spread arguments (f(v..))
  • function literals (fn (x) { ... }) that capture variables by reference
  • classes with single inheritance, constructors, static members, virtual member functions and bound methods (p->method)
  • try/catch/finally, throw, and runtime errors as Error objects
  • switch with fall-through, labelled break/continue
  • modules: use geometry; loads geometry.kkl, reached as geometry::name; modules written in Go: db (SQL with SQLite), events (an event loop with timers), json, strings (a string builder), time, worker (interpreters that run in parallel and exchange messages) and zmq (ZeroMQ sockets, to talk with other programs and machines)
  • 55 built-in functions (strings, collections, math, files, ...)

The full description is in docs/reference.md; the grammar is in syntax.ebnf (and as a Lark grammar in syntax.lark). How programs are compiled and run (the virtual machine, every instruction, the .kkc format) is specified in docs/vm.md.

Installing

With Go 1.25 or newer:

go install github.com/maarten-boot/kukel/cmd/kukel@latest

or from a clone:

make            # vet, test and build bin/kukel
make install    # install kukel into $(go env GOPATH)/bin

Using it

Command What it does
kukel run a.kkl b.kkl [-- args] compile the files as one program and run it
kukel check a.kkl ... compile only and report the errors
kukel build [-o prog.kkc] a.kkl ... compile to a bytecode file
kukel build -module [-o m.kkc] m.kkl compile a module on its own; use m; finds m.kkc when there is no m.kkl
kukel exec prog.kkc [--] [args] run a bytecode file
kukel disasm prog.kkc (or a.kkl ...) show the bytecode
kukel fmt [-w | -l] a.kkl ... format source files (indentation and spacing)
kukel repl [a.kkl ...] read declarations and statements and run them as they come
kukel tokens a.kkl ..., kukel ast [-pos] a.kkl ... show the tokens or the syntax tree
kukel version show the version and the modules written in Go
kukel help show the commands

tests/run has example programs: FizzBuzz, a JSON parser, word counting, closures, exceptions and more. Each comes with its expected output.

Embedding in Go

Go programs can run Kukel code, call its functions and give it Go functions of their own:

import "github.com/maarten-boot/kukel"

app := kukel.NewModule("app").Func("notify",
    func(in *kukel.Interp, args []kukel.Value) (kukel.Value, error) {
        log.Println(args[0])
        return kukel.Nil, nil
    })
prog, err := kukel.CompileFiles([]string{"rules.kkl"}, kukel.CompileOptions{
    Modules:      []*kukel.Module{app},   // rules.kkl: use app; ... app::notify(x);
    DenyBuiltins: kukel.SystemBuiltins,   // no files, no environment, no exit
})
in, err := kukel.New(prog, kukel.Options{StepLimit: 1_000_000})
result, err := in.CallContext(ctx, "discount", kukel.Int(250))

See docs/embedding.md and the package documentation.

How it works

source ──lexer──▶ tokens ──parser──▶ syntax tree ──compiler──▶ bytecode ──VM──▶ run
                                                                  │
                                                       .kkc file ◀┘ (build / exec)
Package Role
kukel (the repository root) the Go API for embedding (docs/embedding.md)
internal/token, internal/diag token kinds and source positions; the error type all stages share
internal/lexer, internal/parser, internal/ast source to syntax tree
internal/loader finds and reads the modules a program uses
internal/native, internal/modules/... modules written in Go (db, events, json, strings, time, worker, zmq) and native classes
internal/compiler name resolution, the language's rules, code generation
internal/bytecode instruction set, .kkc files, the verifier that checks loaded files
internal/vm the stack machine: calls, objects, closures, exceptions (specified in docs/vm.md)
internal/value, internal/builtins values with their operators, built-in functions

TODO.md holds the plan the interpreter was built from, with all design decisions (Q1–Q50). Ideas for later are in docs/future.md.

Development

Make target
make gofmt check, go vet, tests, build
make install install kukel into $(go env GOPATH)/bin
make fuzz FUZZTIME=1m fuzz the lexer, parser, compiler, bytecode loader and verifier (what they accept runs in the VM with a step limit), json::decode, time parsing and kukel fmt
make bench benchmarks
make golden rewrite the expected outputs in tests/ after an intended change

License

MIT, see LICENSE.

Documentation

Overview

Package kukel embeds the Kukel language in Go programs: compile Kukel source once, run it in as many interpreters as needed, call its functions, and give it Go functions of your own.

app := kukel.NewModule("app").
	Func("greet", func(in *kukel.Interp, args []kukel.Value) (kukel.Value, error) {
		return kukel.String("hello, " + args[0].String()), nil
	})
prog, err := kukel.CompileSource("rules.kkl", `
	use app;
	discount(total) { return total > 100 ? 0.1 : 0; }
	main() { println(app::greet("world")); }`,
	kukel.CompileOptions{Modules: []*kukel.Module{app}})
in, err := kukel.New(prog, kukel.Options{Stdout: os.Stdout, StepLimit: 1_000_000})
d, err := in.Call("discount", kukel.Int(250))   // 0.1

The language is described in docs/reference.md of the repository, the virtual machine in docs/vm.md, and this package in docs/embedding.md.

For code that is not trusted, CompileOptions limit what a program may use (modules, built-in functions such as readfile), Options.StepLimit bounds the work of every call, and CallContext stops a call when its context ends. Memory is not limited.

Example

Compile a program once and call its functions from Go.

package main

import (
	"fmt"

	"github.com/maarten-boot/kukel"
)

func main() {
	prog, err := kukel.CompileSource("pricing.kkl", `
const VAT = 0.21;
price(net, qty) {
    local total = net * qty;
    if (qty >= 10) total *= 0.9;       // volume discount
    return round(total * (1 + VAT) * 100) / 100.0;
}
main() {}`, kukel.CompileOptions{})
	if err != nil {
		fmt.Println(err)
		return
	}
	in, err := kukel.New(prog, kukel.Options{})
	if err != nil {
		fmt.Println(err)
		return
	}
	for _, qty := range []int64{1, 10} {
		p, err := in.Call("price", kukel.Float(9.99), kukel.Int(qty))
		fmt.Println(qty, p, err)
	}
}
Output:
1 12.09 <nil>
10 108.79 <nil>

Index

Examples

Constants

This section is empty.

Variables

View Source
var Nil = Value{}

Nil is the Kukel value nil.

View Source
var SystemBuiltins = []string{"readfile", "writefile", "appendfile", "readline", "getenv", "exit"}

SystemBuiltins are the built-in functions that reach outside the program: files (readfile, writefile, appendfile), standard input (readline), the environment (getenv) and ending the process (exit). CompileOptions{DenyBuiltins: kukel.SystemBuiltins} keeps them away from a program.

Functions

func Builtins

func Builtins() []string

Builtins lists the names of all built-in functions.

func StandardModules

func StandardModules() []string

StandardModules lists the modules written in Go that come with Kukel: db, events, json, strings, time, worker, zmq.

Types

type CompileError

type CompileError struct {
	File      string
	Line, Col int
	Message   string
	More      []*CompileError
}

CompileError is an error in Kukel source. A compile can find several: the first is the CompileError itself, the others are in More (in the order of the source), and Error() gives all of them, one per line.

func (*CompileError) Error

func (e *CompileError) Error() string

type CompileOptions

type CompileOptions struct {
	// Modules are the program's own modules, written in Go ("use app;").
	// A module here hides a standard module of the same name.
	Modules []*Module
	// StandardModules lists the standard modules the program may use
	// (nil: all of them; an empty, non-nil slice: none).
	StandardModules []string
	// DenyBuiltins lists built-in functions the program may not use
	// (using one is a compile error); see SystemBuiltins.
	DenyBuiltins []string
	// Path lists directories where "use name;" looks for name.kkl (or
	// name.kkc, a module compiled on its own), after the directory of the
	// file that uses it (CompileFiles only).
	Path []string
	// NoFileModules forbids reading program files: "use" finds only
	// modules written in Go, and worker::startfile is refused.
	NoFileModules bool
}

CompileOptions say what a program may use beyond its own code.

type Error

type Error struct {
	Kind    string  // "TypeError", "ValueError", ...
	Message string  // the Error object's message
	Value   Value   // the thrown Error object (Nil for the step limit and cancellation)
	Trace   []Frame // the calls, innermost first
	// contains filtered or unexported fields
}

Error is an exception of a Kukel program that nothing caught, or the end of a call by its step limit (Kind "StepLimitError") or its context (Kind "CancelledError").

func Errorf

func Errorf(kind, format string, args ...any) *Error

Errorf makes an error for a Func to return: Kukel code sees an exception (an Error object) with that kind (or "HostError" if kind is "") and message.

func (*Error) Error

func (e *Error) Error() string

Error gives the kind and message, then the trace if there is one (one " at f (file:line)" line per call).

type ExitError

type ExitError struct{ Code int }

ExitError is what Call, CallContext, CallValue and Global give when the program calls exit(code) (Run gives the code instead). A Func may return one to end the program as exit(code) does.

func (*ExitError) Error

func (e *ExitError) Error() string

type Frame

type Frame struct {
	Func string
	File string
	Line int
}

Frame is one call in a trace.

type Func

type Func func(in *Interp, args []Value) (Value, error)

Func is a Go function that Kukel code calls. in is the interpreter that calls it (to call back into Kukel with in.CallValue). The arguments are valid during the call only; keep copies (ToGo) of what is needed later. An error becomes a Kukel exception: an *Error keeps its kind (see Errorf), any other error has the kind "HostError".

type Interp

type Interp struct {
	// contains filtered or unexported fields
}

Interp is an interpreter running a Program: it has its own globals, output and state. Its methods must not be called from several goroutines at once; use one Interp per goroutine (they can share a Program). A Func may call back into the Interp that called it.

func New

func New(p *Program, opts Options) (*Interp, error)

New makes an interpreter for p. It fails if p uses a built-in or module that its CompileOptions do not allow (a program from LoadProgram).

func (*Interp) Call

func (in *Interp) Call(name string, args ...Value) (Value, error)

Call calls the program's function name ("discount", or a module's: "util::f", also a private "util::_g", or "json::encode" of a Go module the program may use) with args and gives its result. A Kukel exception that nothing catches is an *Error; exit(code) gives an *ExitError.

func (*Interp) CallContext

func (in *Interp) CallContext(ctx context.Context, name string, args ...Value) (Value, error)

CallContext is Call, stopped when ctx ends: the program stops at its next step (a function written in Go that waits, such as time::sleep, returns at once) with an *Error of kind "CancelledError" that it cannot catch. This also holds for a call a Func makes back into Kukel. Workers started during the call are cancelled if ctx ends while it runs; Close cancels those that outlive it.

Example

Run code that is not trusted: no files, no workers, a step budget and a time limit.

package main

import (
	"context"
	"fmt"
	"strings"
	"time"

	"github.com/maarten-boot/kukel"
)

func main() {
	opts := kukel.CompileOptions{
		DenyBuiltins:    kukel.SystemBuiltins,
		StandardModules: []string{"json", "strings"},
		NoFileModules:   true,
	}
	if _, err := kukel.CompileSource("evil.kkl", `main() { println(readfile("/etc/passwd")); }`, opts); err != nil {
		fmt.Println(err)
	}

	prog, _ := kukel.CompileSource("slow.kkl", `spin() { while (true) {} } main() {}`, opts)
	in, _ := kukel.New(prog, kukel.Options{})
	ctx, cancel := context.WithTimeout(context.Background(), 20*time.Millisecond)
	defer cancel()
	_, err := in.CallContext(ctx, "spin")
	fmt.Println(strings.SplitN(err.Error(), "\n", 2)[0])
}
Output:
evil.kkl:1:18: built-in function readfile is not available in this program
CancelledError: the program was cancelled: context deadline exceeded

func (*Interp) CallValue

func (in *Interp) CallValue(fn Value, args ...Value) (Value, error)

CallValue calls a Kukel function value (such as a callback a Func received) with args.

func (*Interp) Close added in v0.2.1

func (in *Interp) Close()

Close stops the interpreter for good: workers it started that are still running are cancelled, and what they write later is dropped. Calls after Close give an error. Close may be called more than once.

func (*Interp) Global

func (in *Interp) Global(name string) (Value, error)

Global gives the value of a global of the program (a variable, function or class), after the global initializers have run.

func (*Interp) Run

func (in *Interp) Run(args ...string) (int, error)

Run runs the program's main, with args as its parameter (a vector of strings) if it has one, and gives the exit code: main's result if that is an int, else 0; or the code of exit(code). If the program fails, Run gives 1 and the error. The global initializers run first, the first time anything is called; if they throw an exception, every call gives it (a step limit or cancellation lets the next call run them again). Run does not wait for workers the program started (see Close).

func (*Interp) RunContext

func (in *Interp) RunContext(ctx context.Context, args ...string) (int, error)

RunContext is Run, stopped when ctx ends (see CallContext).

type Module

type Module struct {
	// contains filtered or unexported fields
}

Module is a module written in Go for one program: Kukel code that says "use name;" reaches its functions and constants as name::f and name::K. Add everything before the module is first used in CompileOptions.

func NewModule

func NewModule(name string) *Module

NewModule makes an empty module. name must be a Kukel identifier that is not a keyword. NewModule, Func and Const panic on such programming mistakes: a bad name, a nil function, a name used twice, a constant that is not nil, a boolean, a number or a string, or an addition after the module is in use.

Example

Give Kukel code functions written in Go, in a module of its own.

package main

import (
	"fmt"
	"os"

	"github.com/maarten-boot/kukel"
)

func main() {
	stock := map[string]int64{"pen": 12, "ink": 0}
	shop := kukel.NewModule("shop").
		Const("currency", kukel.String("EUR")).
		Func("stock", func(in *kukel.Interp, args []kukel.Value) (kukel.Value, error) {
			item, ok := args[0].AsString()
			if !ok {
				return kukel.Nil, kukel.Errorf("TypeError", "an item is a string")
			}
			n, known := stock[item]
			if !known {
				return kukel.Nil, kukel.Errorf("KeyError", "no item %q", item)
			}
			return kukel.Int(n), nil
		})
	prog, err := kukel.CompileSource("shop.kkl", `use shop;
main() {
    for (local item in ["pen", "ink", "cap"]) {
        try {
            println(item, shop::stock(item) > 0 ? "in stock" : "sold out");
        } catch (e) {
            println(item, e->kind, e->message);
        }
    }
    println("prices in", shop::currency);
}`, kukel.CompileOptions{Modules: []*kukel.Module{shop}})
	if err != nil {
		fmt.Println(err)
		return
	}
	in, _ := kukel.New(prog, kukel.Options{Stdout: os.Stdout})
	in.Run()
}
Output:
pen in stock
ink sold out
cap KeyError no item "cap"
prices in EUR

func (*Module) Const

func (m *Module) Const(name string, v Value) *Module

Const adds a constant: nil, a boolean, a number or a string. Kukel code can use it in constant expressions.

func (*Module) Func

func (m *Module) Func(name string, fn Func) *Module

Func adds a function; it gives m, so that calls can be chained.

type Options

type Options struct {
	Stdout io.Writer // what print writes to; nil: discarded
	Stderr io.Writer // what eprint writes to; nil: discarded
	Stdin  io.Reader // what readline reads; nil: empty

	// StepLimit bounds each call from Go (Run, Call, CallValue): after that
	// many steps (backward jumps, calls and throws, so every loop counts)
	// the call ends with an *Error of kind "StepLimitError" that the
	// program cannot catch. Calls a Func makes back into Kukel share the
	// budget of the call that runs the Func. 0: no limit. Workers the
	// program starts get the same limit for their whole run.
	StepLimit int
}

Options configure an interpreter.

type Program

type Program struct {
	// contains filtered or unexported fields
}

Program is a compiled program. It does not change when it runs, so any number of interpreters (New) may run it, also at the same time.

func CompileFiles

func CompileFiles(files []string, opts CompileOptions) (*Program, error)

CompileFiles compiles source files as one program, with the modules they use. An error in the source is a *CompileError.

func CompileSource

func CompileSource(name, src string, opts CompileOptions) (*Program, error)

CompileSource compiles a program given as text; name is used in messages. Modules written in Kukel are looked for in opts.Path only.

func LoadProgram

func LoadProgram(data []byte, opts CompileOptions) (*Program, error)

LoadProgram reads a program from the bytes of a .kkc file (Encode, or kukel build). opts say what it may use; New refuses a program that uses more.

func (*Program) Encode

func (p *Program) Encode() ([]byte, error)

Encode gives the program as the bytes of a .kkc file.

type Value

type Value struct {
	// contains filtered or unexported fields
}

Value is a Kukel value: nil, a boolean, an int (64 bits), a float, a string (bytes), a vector, a map, a function, a class or an object. The zero Value is nil.

Vectors, maps and objects are shared, not copied: a Value taken from an interpreter refers to the interpreter's data. Use it only while that interpreter does not run on another goroutine.

func Bool

func Bool(b bool) Value

Bool makes a boolean.

func Float

func Float(f float64) Value

Float makes a float.

func FromGo

func FromGo(x any) (Value, error)

FromGo makes a Value of a Go value: nil, any bool, integer, float or string type, []byte (a string), a Value, a slice or array (a vector) or a map with string keys (a map, keys in sorted order), also nested.

Example

Convert between Go and Kukel values.

package main

import (
	"fmt"

	"github.com/maarten-boot/kukel"
)

func main() {
	v, _ := kukel.FromGo(map[string]any{"name": "Kukel", "tags": []string{"small", "fun"}})
	fmt.Println(v, v.Get(kukel.String("tags")).Len())
	g, _ := v.ToGo()
	fmt.Printf("%v\n", g)
}
Output:
{"name": "Kukel", "tags": ["small", "fun"]} 2
map[name:Kukel tags:[small fun]]

func Int

func Int(i int64) Value

Int makes an int.

func MapOf

func MapOf(m map[string]Value) Value

MapOf makes a new map of m, with the keys in sorted order (Kukel maps keep the order in which keys were added).

func NewMap

func NewMap() Value

NewMap makes a new, empty map; add entries with SetKey.

func String

func String(s string) Value

String makes a string.

func Vector

func Vector(elems ...Value) Value

Vector makes a new vector of the elements.

func (Value) AsBool

func (v Value) AsBool() (b, ok bool)

AsBool gives a boolean's value.

func (Value) AsFloat

func (v Value) AsFloat() (float64, bool)

AsFloat gives a float's value, or an int's as a float.

func (Value) AsInt

func (v Value) AsInt() (int64, bool)

AsInt gives an int's value.

func (Value) AsString

func (v Value) AsString() (string, bool)

AsString gives a string's value.

func (Value) Get

func (v Value) Get(key Value) Value

Get gives the value of key in a map (Nil if v is not a map or has no such key).

func (Value) Index

func (v Value) Index(i int) Value

Index gives element i of a vector (Nil if v is not a vector or i is out of range).

func (Value) IsNil

func (v Value) IsNil() bool

IsNil reports whether v is nil.

func (Value) Keys

func (v Value) Keys() []Value

Keys gives a map's keys, in order.

func (Value) Kind

func (v Value) Kind() string

Kind is what typeof gives in Kukel: "nil", "bool", "int", "float", "string", "vector", "map", "function", "class" or "object".

func (Value) Len

func (v Value) Len() int

Len is the length of a string (in bytes), vector or map, else -1.

func (Value) Push

func (v Value) Push(e Value) error

Push appends e to a vector.

func (Value) SetKey

func (v Value) SetKey(key, val Value) error

SetKey sets key to val in a map. Keys are strings and numbers.

func (Value) String

func (v Value) String() string

String gives v as Kukel's print and str() show it.

func (Value) ToGo

func (v Value) ToGo() (any, error)

ToGo gives v as a Go value: nil, bool, int64, float64, string, []any for a vector and map[string]any for a map (keys as str() shows them), nested. A function, class or object stays a Value. A vector or map that contains itself is an error, and so is a map with two keys that give the same Go key (1 and "1").

func (Value) Truthy

func (v Value) Truthy() bool

Truthy reports whether v counts as true in a condition (everything but nil, false, 0 and 0.0).

Directories

Path Synopsis
cmd
kukel command
Command kukel compiles and runs Kukel programs.
Command kukel compiles and runs Kukel programs.
internal
ast
Package ast declares the syntax tree of Kukel programs (syntax.ebnf, sections 1-3).
Package ast declares the syntax tree of Kukel programs (syntax.ebnf, sections 1-3).
builtins
Package builtins implements Kukel's built-in functions.
Package builtins implements Kukel's built-in functions.
bytecode
Package bytecode defines the instruction set of the Kukel stack machine and the compiled program image.
Package bytecode defines the instruction set of the Kukel stack machine and the compiled program image.
compiler
Package compiler translates syntax trees into bytecode for the stack machine.
Package compiler translates syntax trees into bytecode for the stack machine.
diag
Package diag defines the error type shared by the lexer, parser and compiler: a message at a source position.
Package diag defines the error type shared by the lexer, parser and compiler: a message at a source position.
format
Package format formats Kukel source (kukel fmt): it re-indents lines and normalizes the spaces between tokens.
Package format formats Kukel source (kukel fmt): it re-indents lines and normalizes the spaces between tokens.
lexer
Package lexer turns Kukel source text into tokens (syntax.ebnf, section 4).
Package lexer turns Kukel source text into tokens (syntax.ebnf, section 4).
loader
Package loader reads the source files of a program together with the modules they use ("use name;"), directly or through other modules.
Package loader reads the source files of a program together with the modules they use ("use name;"), directly or through other modules.
modules/dbmod
Package dbmod is the native module "db": SQL databases through Go's database/sql.
Package dbmod is the native module "db": SQL databases through Go's database/sql.
modules/eventsmod
Package eventsmod is the native module "events": an event loop that calls Kukel functions when timers expire or other modules post events.
Package eventsmod is the native module "events": an event loop that calls Kukel functions when timers expire or other modules post events.
modules/jsonmod
Package jsonmod is the native module "json": encode Kukel values as JSON text and decode JSON text into Kukel values.
Package jsonmod is the native module "json": encode Kukel values as JSON text and decode JSON text into Kukel values.
modules/stringsmod
Package stringsmod is the native module "strings": a Builder class that builds a long string piece by piece without copying it again for every piece (s += x copies s each time).
Package stringsmod is the native module "strings": a Builder class that builds a long string piece by piece without copying it again for every piece (s += x copies s each time).
modules/timemod
Package timemod is the native module "time": the class time::Time (an instant with a time zone), and sleep.
Package timemod is the native module "time": the class time::Time (an instant with a time zone), and sleep.
modules/workermod
Package workermod is the native module "worker": workers are Kukel interpreters that run in parallel, each on its own goroutine, and talk to the interpreter that started them only through messages.
Package workermod is the native module "worker": workers are Kukel interpreters that run in parallel, each on its own goroutine, and talk to the interpreter that started them only through messages.
modules/zmqmod
Package zmqmod is the native module "zmq": ZeroMQ sockets, to talk with other programs (in any language) and other machines.
Package zmqmod is the native module "zmq": ZeroMQ sockets, to talk with other programs (in any language) and other machines.
native
Package native lets Go code define Kukel modules: functions, constants and native classes, whose objects carry a Go value and whose member functions are written in Go.
Package native lets Go code define Kukel modules: functions, constants and native classes, whose objects carry a Go value and whose member functions are written in Go.
parser
Package parser builds the syntax tree of a Kukel source file (syntax.ebnf, sections 1-3) by recursive descent.
Package parser builds the syntax tree of a Kukel source file (syntax.ebnf, sections 1-3) by recursive descent.
token
Package token defines the lexical tokens of Kukel (syntax.ebnf, section 4).
Package token defines the lexical tokens of Kukel (syntax.ebnf, section 4).
value
Package value defines Kukel's runtime values and the semantics of the operators on them.
Package value defines Kukel's runtime values and the semantics of the operators on them.
vm
Package vm executes compiled Kukel programs on a stack machine.
Package vm executes compiled Kukel programs on a stack machine.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL