Skip to content

Latest commit

Β 

History

205 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Kora Kora

Kora is a small, statically typed, programming language with a garbage collector. It compiles to native executables and JavaScript. Your programs run right in the browser with nothing to install.

Read the docs Β· Try the online playground

The Kora playground

Features

  • Familiar C-like syntax: if / while / for, functions, and blocks you already know.
  • Static typing with inference: int, real, char, bool, arrays, and strings.
  • Arrays and strings with handy built-in methods (push, pop, insert, remove, slice, extend, len). A string is just an array of char.
  • Structs and methods: POD types struct, attach behavior with impl.
  • Generics over type parameters for struct, impl, and functions (struct box<T>, T id<T>(x: T)), instantiated with turbofish (id::<int>(5), new box<int>{ v: 1 }). Instances are monomorphized, so generics cost nothing at runtime.
  • Functions are first class values. Pass, store, and return functions by value with the for callbacks, dispatch tables, and higher-order functions.
  • Optionals (T?) instead of null. The billion-dollar mistake
  • Runtime safety is a design choice: array indexing is bounds-checked, integer division by zero, pop() on an empty array, and force-unwrapping none all panic with a clear message instead of corrupting memory.
  • Modules which allow you to split a program, plus a small standard library (I/O, string helpers, math, and conversions) written in Kora.
  • The native runtime written in C, the lingua-franca of programming languages.
  • Runs in the browser through a WebAssembly-powered playground, and compiles to native binaries through an LLVM backend (LLVM 21 is required).

A taste of Kora

A generic stack, showing type inference, arrays, and generics over structs and impls:

import "std/io";
import "std/conv";

# A generic growable stack, built on a plain array.
struct stack<T> { items: [T] }

impl stack<T> {
    void push(self, x: T) { self.items.push(x); }
    T pop(self) { return self.items.pop(); }
    int size(self) { return self.items.len(); }
}

int main() {
    let s = new stack<int>{ items: [] };   # inferred: s : stack<int>
    for x | [1, 2, 3, 4] {
        s.push(x * x);
    }

    let sum = 0;
    while (s.size() > 0) {
        sum = sum + s.pop();
    }

    io.write(conv.to_string::<int>(sum));      # 30
    io.write("\n");
    return 0;
}

The playground has proper Kora syntax highlighting. Sorry for the ruby code blocks here.

For more, res/cli/ has terminal programs (a Sudoku solver, a ray tracer that renders to a PPM file, a calculator REPL, and a word counter) and res/playground/ has playable versions of Snake, Tetris, Pong, Pacman, Doom, and a Mandelbrot renderer.

Architecture

One frontend feeds two backends. Source is lexed and parsed per module, assembled and import-resolved into a single program, monomorphized, then checked in three passes. Both backends lower the checked program to the same typed IR, so the native binary and the JavaScript output stay byte-identical.

╔═══ COMPILER FRONTEND ══════════════════════════════════════════════════╗
β•‘           β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”             β•‘
β•‘           β”‚ Source files  (.kora + imported modules)     β”‚             β•‘
β•‘           β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜             β•‘
β•‘                                  β”‚                                     β•‘
β•‘                                  β–Ό                                     β•‘
β•‘           β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  per module β•‘
β•‘           β”‚ Lexer                             src/lexer  β”‚ ◀───┐       β•‘
β•‘           β”‚ characters ──▢ tokens                        β”‚     β”‚       β•‘
β•‘           β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜     β”‚       β•‘
β•‘                                  β”‚                             β”‚       β•‘
β•‘                                  β–Ό                             β”‚       β•‘
β•‘           β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”‚       β•‘
β•‘           β”‚ Parser                           src/parser  β”‚ ◀────       β•‘
β•‘           β”‚ tokens ──▢ AST                               β”‚     β”‚       β•‘
β•‘           β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜     β”‚       β•‘
β•‘                                  β”‚                             β”‚       β•‘
β•‘                                  β–Ό                             β”‚       β•‘
β•‘           β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”‚       β•‘
β•‘           β”‚ Loader + Import Resolver         src/loader  β”‚ β”€β”€β”€β”€β”˜       β•‘
β•‘           β”‚ assembles parsed modules; resolves imports   β”‚             β•‘
β•‘           β”‚ ──▢ LoadedProgram (module graph)             β”‚             β•‘
β•‘           β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜             β•‘
β•‘                                  β”‚                                     β•‘
β•‘                                  β–Ό                                     β•‘
β•‘           β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”             β•‘
β•‘           β”‚ Generic Instantiator        src/instantiate  β”‚             β•‘
β•‘           β”‚ monomorphize <T>; fill concrete              β”‚             β•‘
β•‘           β”‚ structs / impls / calls; prune type ifs      β”‚             β•‘
β•‘           β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜             β•‘
β•‘                                  β”‚                                     β•‘
β•‘                                  β–Ό                                     β•‘
β•‘           β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”             β•‘
β•‘           β”‚ Symbol Resolver                              β”‚             β•‘
β•‘           β”‚ src/semantic_analyzer/symbol_resolver        β”‚             β•‘
β•‘           β”‚ symbol-table pass; cross-module binding      β”‚             β•‘
β•‘           β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜             β•‘
β•‘                                  β”‚                                     β•‘
β•‘                                  β–Ό                                     β•‘
β•‘           β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”             β•‘
β•‘           β”‚ Constant Evaluation                          β”‚             β•‘
β•‘           β”‚ src/semantic_analyzer/const_eval             β”‚             β•‘
β•‘           β”‚ fold module-level lets, declaration order    β”‚             β•‘
β•‘           β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜             β•‘
β•‘                                  β”‚                                     β•‘
β•‘                                  β–Ό                                     β•‘
β•‘           β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”             β•‘
β•‘           β”‚ Type Checker                                 β”‚             β•‘
β•‘           β”‚ src/semantic_analyzer/type_checker           β”‚             β•‘
β•‘           β”‚ infer & check types; resolve methods         β”‚             β•‘
β•‘           β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜             β•‘
β•‘                                  β”‚                                     β•‘
β•‘                                  β–Ό                                     β•‘
β•‘           β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”             β•‘
β•‘           β”‚ Return-Flow Analysis                         β”‚             β•‘
β•‘           β”‚ src/semantic_analyzer  (ReturnChecker)       β”‚             β•‘
β•‘           β”‚ every path returns a value                   β”‚             β•‘
β•‘           β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜             β•‘
β•‘                                  β”‚                                     β•‘
β•‘                                  β–Ό                                     β•‘
β•‘                                                                        β•‘
β•‘               CompiledProgram   (checked AST + types)                  β•‘
β•‘                                                                        β•‘
β•‘                                  β”‚                                     β•‘
β•‘                                  β–Ό                                     β•‘
β•‘           β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”             β•‘
β•‘           β”‚ Typed IR Lowering                    src/ir  β”‚             β•‘
β•‘           β”‚ Name Mangling                    src/mangle  β”‚             β•‘
β•‘           β”‚ monomorphic ops, finalize mangled symbols,   β”‚             β•‘
β•‘           β”‚ explicit Wrap/Unwrap / Copy, lvalue detectionβ”‚             β•‘
β•‘           β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜             β•‘
β•‘                       typed IR  (ir::Program)                          β•‘
β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•
                                     β”‚
                                     β–Ό
╔═══ COMPILER BACKEND ═══════════════════════════════════════════════════╗
β•‘                                  β”‚                                     β•‘
β•‘                 β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                    β•‘
β•‘                 β–Ό                                 β–Ό                    β•‘
β•‘  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”      β•‘
β•‘  β”‚ JavaScript Transpiler      β”‚    β”‚ LLVM Lowering Pass         β”‚      β•‘
β•‘  β”‚ src/javascript_transpiler  β”‚    β”‚ src/codegen  (inkwell)     β”‚      β•‘
β•‘  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚ emits an LLVM IR module    β”‚      β•‘
β•‘                 β”‚                  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜      β•‘
β•‘                 β–Ό                                 β”‚                    β•‘
β•‘  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                   β–Ό                    β•‘
β•‘  β”‚ Async Coloring pass        β”‚    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”      β•‘
β•‘  β”‚ marks fns that block on    β”‚    β”‚ Object File Emission       β”‚      β•‘
β•‘  β”‚ an async extern as async   β”‚    β”‚ src/codegen (TargetMachine)β”‚      β•‘
β•‘  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚ LLVM IR ──▢ native .o      β”‚      β•‘
β•‘                 β”‚                  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜      β•‘
β•‘                 β–Ό                                 β”‚                    β•‘
β•‘  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                   β–Ό                    β•‘
β•‘  β”‚ Emit JavaScript            β”‚    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”      β•‘
β•‘  β”‚ + runtime inclusion:       β”‚    β”‚ Linking                    β”‚      β•‘
β•‘  β”‚ kora_node_runtime.js /     β”‚    β”‚ src/codegen::link          β”‚      β•‘
β•‘  β”‚ kora_browser_runtime.js    β”‚    β”‚ + libkora.c runtime        β”‚      β•‘
β•‘  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚ + Boehm GC + mbedTLS       β”‚      β•‘
β•‘                 β”‚                  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜      β•‘
β•‘         β”Œβ”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                     β”‚                    β•‘
β•‘         β–Ό                   β–Ό                     β–Ό                    β•‘
β•‘  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”         β•‘
β•‘  β”‚ Node.js     β”‚ β”‚ Playground         β”‚ β”‚ native executable  β”‚         β•‘
β•‘  β”‚ (.js output)β”‚ β”‚ wasm compiler +    β”‚ β”‚ (LLVM 21 + linker) β”‚         β•‘
β•‘  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ browser runtime +  β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜         β•‘
β•‘                  β”‚ canvas host worker β”‚                                β•‘
β•‘                  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                                β•‘
β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•

Try it locally

wasm-pack build --target web --out-name compiler -- --no-default-features # build the wasm compiler
python -m http.server # serve at localhost

Then open the printed URL and start typing.

To compile programs to native executables instead, build the compiler. Building the compiler requires lib LLVM 21 and a C compiler for the platform linker.

cargo build --release # build the compiler
kora program.kora -o program # native standalone binary
kora program.kora --emit-js  # or print the JavaScript

Running the test suite is cargo test (also requires LLVM 21).

Grammar

module      = { import | struct | impl | extern | function } ;

import      = "import" STRING [ ident ] ";" ;

struct      = "struct" ident [ typeparams ] "{" [ member { "," member } [ "," ] ] "}" ;
member      = ident ":" type ;

impl        = "impl" ident [ typeparams ] "{" { method } "}" ;
method      = rettype ident "(" "self" [ "," [ param { "," param } [ "," ] ] ] ")" block ;

typeparams  = "<" ident { "," ident } [ "," ] ">" ;   (* generic parameters, e.g. <T> or <K, V> *)

extern      = "extern" ( "void" | externtype ) ident "(" externparams ")" ";" ;
externparams= [ externparam { "," externparam } [ "," ] ] ;
externparam = ident ":" externtype ;
externtype  = "int8" | "int16" | "int32" | "int64"       (* C types only *)
            | "uint8" | "uint16" | "uint32" | "uint64"
            | "float32" | "float64" | "bool" | "char"
            | "cint" | "cuint" | "clong" | "culong" | "csize"
            | ( "cstring" | "opaque" ) [ "?" ] ;

function    = rettype ident [ typeparams ] "(" params ")" block ;
rettype     = "void" | type ;
params      = [ param { "," param } [ "," ] ] ;
param       = ident ":" type ;

type        = rettype "(" [ type { "," type } [ "," ] ] ")" [ "?" ]  (* function type, e.g. int(int, int) *)
            | basetype [ "?" ] ;                                      (* "?" makes it optional *)
basetype    = "int" | "real" | "char" | "bool" | "string" | "opaque"
            | ident [ typeargs ]         (* struct name, or generic instance *)
            | "[" type "]" ;
typeargs    = "<" type { "," type } [ "," ] ">" ;   (* generic arguments, e.g. <int> or <int, string> *)

statement   = ";"
            | expr ";"
            | "let" ident [ ":" type ] "=" expr ";"
            | "return" [ expr ] ";"
            | "break" ";"
            | "continue" ";"
            | "if" "(" expr ")" statement [ "else" statement ]
            | "while" "(" expr ")" statement
            | "for" "(" forinit expr ";" expr ")" statement
            | "for" ident "|" expr statement
            | block ;
forinit     = ";" | expr ";" | "let" ident [ ":" type ] "=" expr ";" ;
block       = "{" { statement } "}" ;

expr        = assign ;
assign      = or [ "=" assign ] ;
or          = and  { "||" and } ;
and         = eq   { "&&" eq } ;
eq          = rel  { ( "==" | "!=" ) rel } ;
rel         = add  { ( "<" | ">" | "<=" | ">=" ) add } ;
add         = mul  { ( "+" | "-" | "|" | "^" ) mul } ;
mul         = cast { ( "*" | "/" | "%" | "&" | "<<" | ">>" ) cast } ;
cast        = unary { "as" type } ;
unary       = ( "!" | "-" ) unary | postfix ;
postfix     = primary { "(" args ")" | "[" expr "]" | "." ident | "!" | "::" typeargs } ;
                                                            (* "::" typeargs is turbofish: id::<int>() *)
args        = [ expr { "," expr } [ "," ] ] ;
primary     = INT | REAL | CHAR | STRING | "true" | "false" | "none"
            | ident
            | "(" expr ")"
            | "[" [ expr { "," expr } [ "," ] ] "]"
            | "new" type [ "[" expr "]"
                         | "{" [ field { "," field } [ "," ] ] "}" ] ;
field       = ident ":" expr ;

About

Kora is a statically typed programming language with generics, inference and garbage collection. Transpilation to Javascript powers the online playground.

Resources

Stars

3 stars

Watchers

0 watching

Forks

Contributors

Languages