This project is aimed to define a minimum specification of a LISP self-compiling compiler implementation and a SECD-style virtual machine for fun, education or research of bootstrapping.
See the shell scripts for details to bootstrap. A already-existed Scheme implementation is supposed to bootstrap because the compiler is written in btLISP itself as a Scheme-subset. VM implementations are now written in C and Python only but other languages or system may be supposed in future.
The compiler is written in the following syntax in Scheme subset except built-in functions in the VM, called blSECD
.
lambda
with Lisp-1 and lexical scopeif
,quote
You can bootstrap to self-compile by using any Scheme subset implementations, including playgrounds on the Web, like the following. Once you get VM codes derived from bt-comp.scm
, you do not need a Scheme implementation but a VM only to compile btLISP codes.
$ scm bl-comp.scm < bl-comp.scm > bl-comp.blSECD
$ python3 blSECD.py bl-comp.blSECD | python3 blSECD.py
(write ((lambda (x y) (cons x (cdr y))) (quote a) (quote (x y z))))
[Ctrl-D](a y z)
$ cc -o blSECD blSECD.c
$ ./blSECD bl-comp.blSECD | ./blSECD
(write ((lambda (x y) (cons x (cdr y))) (quote a) (quote (x y z))))
(a y z)
$ python3 blSECD.py bl-comp.blSECD < bl-comp.scm > out.blSECD
$ python3 blSECD.py out.blSECD | ./blSECD
(write ((lambda (x y) (cons x (cdr y))) (quote a) (quote (x y z))))
[Ctrl-D](a y z)
$ ./blSECD out.blSECD < bl-comp.scm > out2.blSECD
$ ./blSECD out2.blSECD | python3 blSECD.py
(write ((lambda (x y) (cons x (cdr y))) (quote a) (quote (x y z))))
(a y z)
I do not put VM codes derived from bt-comp.scm
in this repository on purpose. Enjoy bootstrapping!
The specification of the VM is a SECD-style but customized to be minimum as possible to enjoy bootstrapping.
(ldc () ldc read app ldc cdr app ldc write app stp)
= (write (cdr (read (current-input-port))))
=> [input](a b c) => [output](b c)
(ldc (x y z) ldc a ldf (ldf (ldv 0 ldc cdr app ldv 1 ldc cons app app rtn) rtn) app app ldc write app stp)
= (write
((lambda (x y) (cons x (cdr y)))
(quote a) (quote (x y z))))
=> [output](a y z)
Stacks | Description |
---|---|
S |
stack to work |
E |
env to keep closure values |
C |
VM codes |
D |
stack to dump to recur or branch |
ldv
: pop a closure value specified by a C code from E and push it to Sldf
: pop a closure from C and push it with the current E to Sldc
: load a constant value or a built-in function and push it to Sapp
: pop a function with a value from S to apply- if the function is a built-in function:
- apply and push the result to S
- if the function is a closure:
- dump (S E C) to D
- clear S
- set the closure body to C
- set the pair of the value and the closure variable to E
- if the function is a built-in function:
rtn
: pop (S E C) from D and set it to the each one to return- push the result value in the top of the current S to poped S
btf
: pop true and false codes from C to branch- dump the current C to D
- pop a conditional value from C and set the true or false code to C
jtf
: pop C from D and push it to C to joinstp
: stop vm
Note that closures in the VM are supposed to have just one argument only so you must curry to write lamda expressions with multiple arguments.
cons
,car
,cdr
,eq?
,pair?
as Pure-oriented list processingread
withcurrent-input-port
as standard input portwrite
,+
needed to self-compile
Note that the above functions are curried, same as closures in VM, so you must app
twice if the function needs two arguments.
- comments between
;
and end of the line - NO
#t
NOR#f
as boolean values - NO dot notation NOR single quotation as
quote
- NO global environment
(C) 2022 TAKIZAWA Yozo
The codes in this repository are licensed under CC0, Creative Commons Zero v1.0 Universal