argument stack
((: 1 1) (: (+ 2 3) (COMPILED CODE))

(+ 2 3) : (COMPILED CODE)
1 : 1

strategy stack

(NAME NAME)

NAME
NAME

so there'll be an N for the argument stack, and N for the strategy stack

3 : 3
2 : 2
(+ 2 3) : (COMPILED CODE)
1 : 1

ARG (1 : 1) ARG ((+ 2 3) : (ARG 2 ARG 3 APPLY + 2)) APPLY + 2
# won't know size of strategy stack until call time

(+ 1 (* 2 3))
ARG (: 1 1) ARG (: (+ 2 3) (ARG (: 2 2) ARG (: 3 3) APPLY + 2)) APPLY * 2

(+ 1 (* 2 3))
NARG 1 ARG (: (+ 2 3) (NARG 2 NARG 3 APPLY + 2)) APPLY * 2

(+ 1 (* a 3))
ARG (: 1 1) ARG (: (+ 2 3) (VARG a ARG (: 3 3) APPLY + 2)) APPLY * 2


Keccak-256("The quick brown fox jumps over the lazy dog.")
0x 578951e24efd62a3d63a86f7cd19aaa53c898fe287d2552133220370240b572d

>>> hash = "578951e24efd62a3d63a86f7cd19aaa53c898fe287d2552133220370240b572d"
>>> base64.b64encode(bytes.fromhex(hash))
b'V4lR4k79YqPWOob3zRmqpTyJj+KH0lUhMyIDcCQLVy0='

#V4lR4k79YqPWOob3zRmqpTyJj+KH0lUhMyIDcCQLVy0=

(#<sum> 1 2)

(closure (a) (+ a 1))
compiled = #<succ>

(+ 1 (#<succ> 1))

compiler can look up + at compile time
(stored as a mapping in bindings passed at start of compilation)
#<succ> can also be looked up at compile time

so this obviates the call-by-name problem

(+ a 1)

so the runtime will mostly just be replacing variables
and running primitives

essentially when a closure is called, there are *only* the argspec bindings
only problem is then you kind of don't have higher order functions
i.e. you can't call a function. couldn't make "compose", for example

(closure (f g) (closure (a) (f (g a))))

could perhaps do this by manipulating data as code
that way, you'd just be making runtime macros in a way

so, define compose as something like...

(compose <f> <g>) => (<f> (<g> <a>))

basically a regular macro, actually
(#<compose> <f> <g>)

hmm, what if it's already been compiled?
well, you could only compile it if the definition of #<compose> is known
so basically you just get more creative compilation

so instead of regular NAME, VALUE arguments, you have PATTERN arguments

(#<compose> 1 2) should break
(#<compose> #<succ> #<succ>) should work
outputs (closure (a) (#<succ> (#<succ> a)))