A Racket implementation of the Kal language, a project by my friend, @maxeonyx.
We wanted to see the performance difference between a quickfire Racket impl and his optimised Rust interpreter.
Benchmarks to come!
$ git clone https://github.com/liamdiprose/kal.rkt.git kal
$ cd kal
$ racket
> (require "main.rkt")
evens.kal.rkt
(fn (even_numbers)
(let count 0)
(loop
(send yield with count)
(set! count (+ count 2))))
evens.kal
fn even_numbers() {
let mut count = 0;
loop {
send yield with count;
count += 2;
}
}
handle.kal.rkt
(handle (even_numbers)
[(yield num)
(log num)
(continue)])
handle.kal
handle even_numbers() {
yield num {
log(num);
continue;
}
}
for.kal.rkt
(for ([num (even_numbers)])
(log num))
Lines 95 to 99 in e4fdfe2
for.kal
for num in even_numbers() {
log(num);
}
- Dynamic type system (:free:)
- Explicit mutability
- No Garbage collection
- Object/List spread operators
- Implicit cast to big integers on overflow (:free:)
- Symbols for private fields and langauage-defined behaviour (:free:)
- Let bindings (:free:)
- Functions
fn
(:free:) - Anonymous functions (only
lambda
at the moment) - Addition, multiplication, subtraction, division (:free:)
- Comparision and boolean operators (:free:)
- If expressions (:free:)
- Non-recursive (stack-based)
- Scheme has tail call optimisation
- Chez has an efficient implementation of continuations
- Booleans (:free:)
- Integers (:free:)
- Floats (:free:)
- Big Integers (:free:)
- Lists (:free:)
- Objects (:free:)
- Strings (:free:)
- Symbols (:free:)
- Effects
-
send [with <value>]
-
handle
-
break [with <value>]
-
continue [with <value>]
-
- Explicit effect propagation?
- Forever loops
- For-each loops
- Intrinsics
- Mutable let bindings (:free:)
- Mutable assignment operators
- Mutable object values and list elements (:free:)
- Non-string object keys (:free:)
- Import / export (Racket:
require
andprovide
) (:free:) - Print (:free:)
- Patterns
- List spread operator
- List destructuring in
let
- Destructure when receiving function parameters
- Spread lists into function calls
- Object spread operator
- Object destructure in
let
- Object destructure in
- Nested destructuring in
let
and function parameters -
import
pattern - Renaming in object destructuring
- Proper type-error support (:free:)
- Proper syntax-error support (:free:)
- Integer division operator (:free:)
- Remainder operator (:free:)
- Integer modulo operator (:free:)
- Exponent operator (:free:)
- Numpy-style tensors using
ndarray
(Racket:math/matrix
) - Floating point numbers (:free:)
- Markdown-like comments
- Doc comments and builtin
help
function - CLI binary
- Embeddable Rust library
- JS/WASM runtime
- Native runtime
- Typed Racket can optimise code based on type proofs,
especially used in Racket's
math
libraries. - Kal.rkt is syntax agnostic with BNF notation: lang/ast.rkt
- Port Kal.rkt to Kal.gerbil.scm to get an optimised, standalone binary
- Racket bundles standalone executables using the
include_str
method @maxeonyx describes
- Racket bundles standalone executables using the
- Compiling to Javascript can be acheived via Gerbil or it's parent, Gambit.