84 lines
2.6 KiB
Org Mode
84 lines
2.6 KiB
Org Mode
#+title: closure-conversion
|
|
|
|
the closure-conversion phase makes closed-over variables explicit by addition of the primitive ~make-closure~, taking a code pointer (in the CPS language, bare lambda) and the environment.
|
|
|
|
* scratchpad
|
|
|
|
#+begin_src scheme
|
|
(letrec ((make-adder
|
|
(lambda (n)
|
|
(lambda (x)
|
|
(+ n x)))))
|
|
((make-adder 3) 2))
|
|
#+end_src
|
|
|
|
#+begin_src scheme
|
|
(define add-code
|
|
(lambda (n env)
|
|
(+ n (env-ref env 'x))))
|
|
|
|
(define make-adder-code
|
|
(lambda (n)
|
|
(make-closure add-code ('x n))))
|
|
|
|
(define make-adder (make-closure make-adder-code))
|
|
|
|
(apply-closure (apply-closure make-addder 3) 2)
|
|
#+end_src
|
|
|
|
#+begin_src wat
|
|
(module
|
|
(type $heap-object (sub (struct (field $hash (mut i32)))))
|
|
(type $closure (sub $heap-object
|
|
(struct (field $hash (mut i32))
|
|
(field $code (ref $cont-type)))))
|
|
(type $closure1 (sub $closure
|
|
(struct (field $hash (mut i32))
|
|
(field $code (ref $cont-type))
|
|
(field $env0 (ref eq)))))
|
|
(global $arg0 (mut (ref null eq)) (ref.null eq))
|
|
(global $arg1 (mut (ref null eq)) (ref.null eq))
|
|
(global $arg2 (mut (ref null eq)) (ref.null eq))
|
|
(global $arg3 (mut (ref null eq)) (ref.null eq))
|
|
(global $arg4 (mut (ref null eq)) (ref.null eq))
|
|
(global $arg5 (mut (ref null eq)) (ref.null eq))
|
|
;; ⋮
|
|
;; (global $argn (mut (ref null eq)) (ref.null eq))
|
|
|
|
(global $current-closure (mut (ref null $closure)) (ref.null $closure))
|
|
|
|
(func $add-code (param $nargs i32)
|
|
(local $n (ref eq))
|
|
(local $x (ref eq))
|
|
(local.set $n (global.get $arg0))
|
|
(local.set $x (struct.get $closure1
|
|
(global.get $current-closure)
|
|
$env0))
|
|
(return (i32.add $n $x)))
|
|
|
|
(func $make-adder-code (param $nargs i32)
|
|
(local $n (ref eq))
|
|
(local.set $n (global.get $arg0))
|
|
(return (struct.new $closure1
|
|
0
|
|
$add-code)))
|
|
|
|
(func $main
|
|
(local.set $make-adder
|
|
(struct.new $closure
|
|
0
|
|
$make-adder-code))
|
|
(global.set $current-closure $make-adder)
|
|
(global.set $arg0 (i32.const 3))
|
|
(local.set $f (call (struct.get $closure
|
|
$make-adder
|
|
$code)
|
|
1))
|
|
(global.set $current-closure $f)
|
|
(global.set $arg0 (i32.const 2))
|
|
(return (call (struct.get $closure
|
|
$f
|
|
$code)
|
|
1))))
|
|
#+end_src
|