aboutsummaryrefslogtreecommitdiff
path: root/ps/types.ps
diff options
context:
space:
mode:
authorJoel Martin <github@martintribe.org>2014-04-14 22:46:54 -0500
committerJoel Martin <github@martintribe.org>2014-04-14 22:46:54 -0500
commit0027e8fed423a24ec93234a6bf0fb701c233d583 (patch)
treec1c447a16958fc174f15af15c181b1582506d9ed /ps/types.ps
parent8adb082743f12402d0817018ab1e8ff0c0e4729e (diff)
downloadmal-0027e8fed423a24ec93234a6bf0fb701c233d583.tar.gz
mal-0027e8fed423a24ec93234a6bf0fb701c233d583.zip
PS: fix function closures. Self-hosted up to step7.
Diffstat (limited to 'ps/types.ps')
-rw-r--r--ps/types.ps63
1 files changed, 59 insertions, 4 deletions
diff --git a/ps/types.ps b/ps/types.ps
index a22246f..2b26582 100644
--- a/ps/types.ps
+++ b/ps/types.ps
@@ -182,7 +182,45 @@ end } def
% Functions
-/_mal_function? {
+% block -> _function -> boxed_function
+/_function {
+ <<
+ /_maltype_ /function
+ %/data 5 -1 roll cvlit
+ /data 5 -1 roll
+ >>
+ %%dup length dict copy
+} def
+
+% ast env params -> _mal_function -> boxed_mal_function
+/_mal_function {
+ <<
+ /_maltype_ /mal_function % user defined function
+ /macro? false % macro flag, false by default
+ /params null % close over parameters
+ /ast null % close over ast
+ /env null % close over environment
+ /data { __self__ fload EVAL } % forward reference to EVAL
+ dup length array copy cvx % actual copy/new instance of block
+ >>
+ % make an actual copy/new instance of dict
+ dup length dict copy % stack: ast env params mal_fn
+ % "Close over" parameters
+ dup 3 -1 roll % stack: ast env mal_fn mal_fn params
+ /params exch put % stack: ast env mal_fn
+ dup 3 -1 roll % stack: ast mal_fn mal_fn env
+ /env exch put % stack: ast mal_fn
+ dup 3 -1 roll % stack: mal_fn mal_fn ast
+ /ast exch put % stack: mal_fn
+
+ % insert self reference into position 0 of data
+ dup /data get % stack: mal_fn data
+ 1 index % stack: mal_fn data mal_fn
+ 0 exch % stack: mal_fn data 0 mal_fn
+ put % stack: mal_fn
+} def
+
+/_function? {
dup type /dicttype eq {
/_maltype_ get /function eq
}{
@@ -190,6 +228,14 @@ end } def
} ifelse
} def
+/_mal_function? {
+ dup type /dicttype eq {
+ /_maltype_ get /mal_function eq
+ }{
+ pop false
+ } ifelse
+} def
+
% args mal_function -> fload -> ast new_env
% fload: sets up arguments on the stack for an EVAL call
/fload {
@@ -199,9 +245,18 @@ end } def
env_new % stack: ast new_env
} def
-% function_or_block -> callable -> block
-% if this is a user defined mal function, get its executable block
-/callable { dup _mal_function? { /data get } if } def
+% function_or_mal_function -> callable -> block
+% if this is a function or mal_function, get its executable block
+/callable {
+ dup _mal_function? { %if mal_function
+ /data get
+ }{ dup _function? { %else if function
+ /data get
+ }{ %else something invalid
+ (callable called on non-function!\n) print quit
+ cvx
+ } ifelse } ifelse
+} def
% Lists