only tested on x86_64 linux with clang 21.1.6. almost certainly doesn't work with anything else.
compiler for a subset of scheme. emits a stack machine assembly language.
rust.
assembler for the stack machine assembly language. emits bytecode.
python.
interpreter for the bytecode. bytecode opcodes are the addresses of their implementations in the interpreter. in other words, the bytecode programs are ropchains for the interpreter.
x86_64 asm and a little bit of c (without libc).
./build.bashcat <<EOF | ./run.bash
(string
(let ((sum (lambda (l) (fold + 0 l))))
(integer->char (sum (list 1 2 3 4 5 6 7 8 9 10 11))))
#\N
#\G
#\U
#\L
#\A
#\R)
EOF"BNGULAR"
- integer
- represents the range
$[-2^{61}, 2^{61} - 1]$ - e.g.,
-1
- represents the range
- character
- represents the ascii range.
- e.g.,
#\a
- bool
- good ol' boolean
- e.g.,
#f
- cons
- represents a pair of objects.
- e.g.,
(cons 1 '())
- lambda
- represents a function.
- e.g.,
(lambda (x) (+ x 1))
- vector
- represents a list that isn't slow.
- e.g.,
(vector #\b #\n #\g #\u #\l #\a #\r)
- string
- a vector, but special-cased for chars to not waste space
- e.g.,
"bngular"
- null
- special value that means the end of a list
'()
- unspecified
- special value that is the result of evaluating an expression with no result
- e.g.,
(begin)
(zero? x)- returns whether
xis zero.
- returns whether
(integer? x)- returns whether
xis an integer.
- returns whether
(boolean? x)- returns whether
xis a boolean.
- returns whether
(char? x)- returns whether
xis a character.
- returns whether
(null? x)- returns whether
xis'().
- returns whether
(not x)- returns
#tifxis#f, and#fotherwise.
- returns
(char->integer x)- converts
x, which must be an integer in the appropriate range, to a character.
- converts
(+ ...args)- sums
args, which must be integers.
- sums
(- ...args)- subtracts
args, which must be integers.
- subtracts
(* ...args)- multiplies
args, which must be integers.
- multiplies
(< ...args)- returns whether
args, which must be integers, are strictly increasing.
- returns whether
(= ...args)- returns whether
args, which must be integers, are equal.
- returns whether
(eq? ...args)- returns whether everything in
argsis pointer-equal. for objects that are not heap-allocated, they are pointer-equal if they hold the same value. for objects that are heap-allocated, they are pointer-equal if they are the same object.
- returns whether everything in
(string ...args)- constructs a string by concatenating
args, which must be characters.
- constructs a string by concatenating
(string-append ...args)- constructs a string by concatenating
args, which must be strings.
- constructs a string by concatenating
(string-ref s n)- returns the
nth character froms.
- returns the
(string-set! s n c)- sets the
nth character ofstoc.
- sets the
(vector ...args)- constructs a vector containing each of
args.
- constructs a vector containing each of
(vector-ref v n)- returns the
nth character fromv.
- returns the
(vector-set! v n x)- sets the
nth item ofvtox.
- sets the
(cons first second)- makes a
conscontainingfirstandsecond.
- makes a
(car l)- returns the first thing in
l, which must be acons.
- returns the first thing in
(cdr l)- returns the second thing in
l, which must be acons.
- returns the second thing in
(list ...args)- returns
args
- returns
(map f l)- maps
f, which must be a lambda, overl, which must be a list.
- maps
(fold f i l)- folds
f, which must be a lambda, overl, which must be a list, with initial valuei.
- folds
(foldr f i l)- folds
f, which must be a lambda, overl, which must be a list, with initial valuei, right-associative.
- folds
(reverse l)- reverses
l, which must be a list.
- reverses
(let (...bindings) ...statements)- for each item in
bindings, which must be a list ofconses in which the first element is a symbol, binds each of these symbols to the result of evaluating the second element in itscons, then evaluates each statement instatementsin a new environment that includes the fresh bindings. - e.g.,
(let ((a 1) (b 2)) (+ a b))
- for each item in
(let* (...bindings) ...statements)- the same as
let, but bindings are permitted to use previous bindings. - e.g.,
(let* ((a 1) (b a)) b)
- the same as
(begin ...statements)- the same as
let, but no bindings.
- the same as
(apply f (...args))- calls
fwith the arguments inargs, which must be a list.
- calls
(if cond conseq alt)- evaluates
cond, executesaltif it resulted in#f, andconseqotherwise.
- evaluates
(if cond conseq)- evaluates
cond, executesconseqif it did not result in#f, and returns#<unspecified>otherwise.
- evaluates
(lambda (...args) ...statements)- makes a lambda.
- e.g.,
(lambda (n) (+ n 1))
(lambda (...args . rest) ...statements)- makes a variadic lambda with some required arguments.
- e.g.,
(lambda (head . rest) rest)
(lambda args ...statements)- makes a variadic lambda with no required arguments
- e.g.,
(lambda args (car args))
(lambdarec name ...)- exactly like
lambda, but takes an extra argumentname, which is bound to the resulting lambda when it is executed. allows for recursive lambdas. - e.g.,
(lambdarec fact (n) (* n (fact (- n 1))))
- exactly like