diff options
| author | Joel Martin <github@martintribe.org> | 2014-04-14 22:46:54 -0500 |
|---|---|---|
| committer | Joel Martin <github@martintribe.org> | 2014-04-14 22:46:54 -0500 |
| commit | 0027e8fed423a24ec93234a6bf0fb701c233d583 (patch) | |
| tree | c1c447a16958fc174f15af15c181b1582506d9ed | |
| parent | 8adb082743f12402d0817018ab1e8ff0c0e4729e (diff) | |
| download | mal-0027e8fed423a24ec93234a6bf0fb701c233d583.tar.gz mal-0027e8fed423a24ec93234a6bf0fb701c233d583.zip | |
PS: fix function closures. Self-hosted up to step7.
| -rw-r--r-- | ps/core.ps | 24 | ||||
| -rw-r--r-- | ps/env.ps | 33 | ||||
| -rw-r--r-- | ps/printer.ps | 37 | ||||
| -rw-r--r-- | ps/reader.ps | 74 | ||||
| -rw-r--r-- | ps/step4_if_fn_do.ps | 23 | ||||
| -rw-r--r-- | ps/step5_tco.ps | 23 | ||||
| -rw-r--r-- | ps/step6_file.ps | 23 | ||||
| -rw-r--r-- | ps/step7_quote.ps | 25 | ||||
| -rw-r--r-- | ps/step8_macros.ps | 24 | ||||
| -rw-r--r-- | ps/step9_interop.ps | 24 | ||||
| -rw-r--r-- | ps/stepA_more.ps | 26 | ||||
| -rw-r--r-- | ps/types.ps | 63 | ||||
| -rw-r--r-- | tests/incB.mal | 3 | ||||
| -rw-r--r-- | tests/step4_if_fn_do.mal | 3 | ||||
| -rw-r--r-- | tests/stepA_more.mal | 15 |
15 files changed, 236 insertions, 184 deletions
@@ -40,12 +40,17 @@ end } def % [hashmap key] -> hash_map_get -> value /hash_map_get { - dup 0 _nth /data get % stack: args dict - exch 1 _nth % stack: dict key - 2 copy known { %if has key - get - }{ + dup 0 _nth % stack: args hash_map + dup null eq { %if hash_map is a nil pop pop null + }{ %else hash_map is not a nil + /data get % stack: args dict + exch 1 _nth % stack: dict key + 2 copy known { %if has key + get + }{ + pop pop null + } ifelse } ifelse } def @@ -172,7 +177,12 @@ end } def % [obj] -> meta -> meta /meta { - 0 _nth dup /meta known { /meta get }{ null } ifelse + 0 _nth % stack: obj + dup type /dicttype eq { %if dictionary + dup /meta known { /meta get }{ null } ifelse + }{ %else + pop null % no meta on non-collections + } ifelse } def @@ -196,7 +206,7 @@ end } def [ atm /data get ] args 2 args _count 2 sub _slice /data get concatenate _list_from_array - args 1 _nth callable % make sure function is callable + args 1 _nth callable % extract proc exec /new_val exch def atm /data new_val put @@ -22,6 +22,8 @@ >> end } def +% env key -> env_find -> env +% env key -> env_find -> null /env_find { 2 dict begin /key exch def /env exch def @@ -34,27 +36,24 @@ end } def } ifelse } ifelse end } def -/env_set { 4 dict begin - dup - /func? exch xcheck def % executable function - /val exch cvlit def - /key exch def - /env exch def - env key val func? { cvx } if put - val func? { cvx } if -end } def +% env key val -> env_set -> val +/env_set { + dup 4 1 roll % stack: val env key val + put % stack: val +} def -/env_get { 2 dict begin - /key exch def - /env exch def - env key env_find +/env_get { + dup 3 1 roll % stack: key env key + env_find % stack: key env/null dup null eq { - (') - key dup length string cvs + pop % stack: key + (') exch % stack: (') key + dup length string cvs (' not found) concatenate concatenate _throw }{ - key get + exch % stack: env key + get } ifelse -end } def +} def diff --git a/ps/printer.ps b/ps/printer.ps index 1be0963..de91d80 100644 --- a/ps/printer.ps +++ b/ps/printer.ps @@ -5,9 +5,8 @@ % ast print_readably -> _pr_str -> string /_pr_str { 4 dict begin /print_readably exch def - dup - /func? exch xcheck def % executable function - /obj exch cvlit def + dup xcheck { (Cannot print proc: ) print dup == quit } if % assert + /obj exch def obj _sequential? { obj _list? { (\() (\)) }{ ([) (]) } ifelse obj /data get ( ) print_readably _pr_str_args @@ -19,7 +18,13 @@ ( ) print_readably _pr_str_args concatenate (}) concatenate - }{ obj _mal_function? { % if user defined function + }{ obj _function? { % if builtin function + (<\(builtin_fn* {) + obj /data get dup length array copy cvlit + ( ) print_readably _pr_str_args + (}>) + concatenate concatenate + }{ obj _mal_function? { % if user defined mal_function (<\(fn* ) obj /params get print_readably _pr_str ( ) @@ -33,10 +38,10 @@ concatenate concatenate }{ /arraytype obj type eq { % if list or code block % accumulate an array of strings - func? { (<builtin_fn* { ) }{ (\() } ifelse + (\() obj ( ) print_readably _pr_str_args concatenate - func? { ( } >) }{ (\)) } ifelse + (\)) concatenate }{ /integertype obj type eq { % if number /slen obj 10 add log ceiling cvi def @@ -60,7 +65,7 @@ obj dup length string cvs }{ (<unknown>) - } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse + } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse end } def % array delim print_readably -> _pr_str_args -> new_string @@ -72,10 +77,26 @@ end } def args length 0 gt { %if any elements [ args { %foreach argument in array - print_readably _pr_str + dup xcheck { %if executable + 255 string cvs + }{ + print_readably _pr_str + } ifelse } forall ] { concatenate delim concatenate } forall dup length delim length sub 0 exch getinterval % strip off final delim } if end } def + +% utility function +/print_dict { + (DICT contents:\n) print + { + ( - ) print + exch dup length string cvs print % key + (: ) print + == + } forall +} def + diff --git a/ps/reader.ps b/ps/reader.ps index 430f0c9..188a121 100644 --- a/ps/reader.ps +++ b/ps/reader.ps @@ -7,7 +7,7 @@ % read_number: read a single number from string/idx % string idx -> read_number -> number string new_idx -/read_number { +/read_number { 5 dict begin %(in read_number\n) print /idx exch def /str exch def @@ -26,12 +26,12 @@ str start cnt getinterval cvi % the matched number str idx % return: number string new_idx -} def +end } def % read_symbol: read a single symbol from string/idx % string idx -> read_symbol -> name string new_idx -/read_symbol { +/read_symbol { 5 dict begin %(in read_symbol\n) print /idx exch def /str exch def @@ -51,12 +51,12 @@ str start cnt getinterval cvn % the matched symbol str idx % return: symbol string new_idx -} def +end } def % read_string: read a single string from string/idx % string idx -> read_string -> new_string string new_idx -/read_string { +/read_string { 5 dict begin %(in read_string\n) print /idx exch 1 add def /str exch def @@ -80,12 +80,12 @@ str start cnt getinterval % the matched string (\\") (") replace str idx % return: new_string string new_idx -} def +end } def % read_atom: read a single atom from string/idx % string idx -> read_atom -> int string new_idx -/read_atom { +/read_atom { 3 dict begin %(in read_atom\n) print /idx exch def /str exch def @@ -114,11 +114,11 @@ }ifelse % return: atom string new_idx -} def +end } def % read_until: read a list from string/idx until stopchar is found % string idx stopchar -> read_until -> list string new_idx -/read_until { +/read_until { 3 dict begin %(in read_until\n) print /stopchar exch def /idx exch 1 add def @@ -135,24 +135,40 @@ } loop ] str idx 1 add -} def +end } def % read_spaces: advance idx to the first non-whitespace % string idx -> read_form -> string new_idx -/read_spaces { +/read_spaces { 3 dict begin %(in read_spaces\n) print /idx exch def /str exch def { % loop str length idx le { exit } if % EOF, break loop /ch str idx get def % current character + %(left1.1:) print str idx str length idx sub getinterval print (\n) print + % eliminate comments + ch 59 eq { %if ';' + { % loop + /idx idx 1 add def % increment idx + str length idx le { exit } if % EOF, break loop + /ch str idx get def % current character + %(left1.2:) print str idx str length idx sub getinterval print (\n) print + % if newline then we are done + ch 10 eq { exit } if + } loop + /idx idx 1 add def + str length idx le { exit } if % EOF, break loop + /ch str idx get def % current character + } if % if not whitespace then exit ch 32 ne ch 10 ne ch 44 ne and and { exit } if /idx idx 1 add def % increment idx } loop + %(left1.3:) print str idx str length idx sub getinterval print (\n) print str idx % return: string new_idx -} def +end } def % read_form: read the next form from string start at idx % string idx -> read_form -> ast string new_idx @@ -162,21 +178,12 @@ /idx exch def /str exch def - idx str length ge { (unexpected EOF) _throw } if % EOF + %idx str length ge { (unexpected EOF) _throw } if % EOF + idx str length ge { null str idx }{ %if EOF + /ch str idx get def % current character - ch 59 eq { %if ';' - { % loop - /idx idx 1 add def % increment idx - str length idx le { exit } if % EOF, break loop - /ch str idx get def % current character - % if newline then add 1 more idx and exit - ch 10 eq { - /idx idx 1 add def - exit - } if - } loop - str idx read_form % recur to get next form - }{ ch 39 eq { %if '\'' + %(LEFT2.1:) print str idx str length idx sub getinterval print (\n) print + ch 39 eq { %if '\'' /idx idx 1 add def str idx read_form 3 -1 roll /quote exch 2 _list 3 1 roll @@ -204,23 +211,28 @@ str idx read_form 3 -1 roll /deref exch 2 _list 3 1 roll }{ ch 40 eq { %if '(' - str idx 41 read_until + str idx 41 read_until dup /idx exch def + %(LEFT2.2:) print str idx str length idx sub getinterval print (\n) print 3 -1 roll _list_from_array 3 1 roll + %(LEFT2.3:) print str idx str length idx sub getinterval print (\n) print }{ ch 41 eq { %elseif ')' (unexpected '\)') _throw - }{ ch 91 eq { %if '(' - str idx 93 read_until + }{ ch 91 eq { %if '[' + str idx 93 read_until dup /idx exch def + %(LEFT2.4:) print str idx str length idx sub getinterval print (\n) print 3 -1 roll _vector_from_array 3 1 roll }{ ch 93 eq { %elseif ']' (unexpected ']') _throw }{ ch 123 eq { %elseif '{' - str idx 125 read_until + str idx 125 read_until dup /idx exch def 3 -1 roll _hash_map_from_array 3 1 roll }{ ch 125 eq { %elseif '}' (unexpected '}') _throw }{ % else str idx read_atom - } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse + } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse + + } ifelse % not EOF % return: ast string new_idx end } def diff --git a/ps/step4_if_fn_do.ps b/ps/step4_if_fn_do.ps index cd14b18..952661a 100644 --- a/ps/step4_if_fn_do.ps +++ b/ps/step4_if_fn_do.ps @@ -83,27 +83,18 @@ end } def }{ /fn* a0 eq { %if fn* /a1 ast 1 _nth def /a2 ast 2 _nth def - << - /_maltype_ /function % user defined function - /params null % close over parameters - /ast null % close over ast - /env null % close over environment - /data { __self__ fload EVAL } - >> - dup length dict copy % make an actual copy/new instance - dup /params a1 put % insert closed over a1 into position 2 - dup /ast a2 put % insert closed over a2 into position 3 - dup /env env put % insert closed over env into position 4 - dup dup /data get exch 0 exch put % insert self reference + a2 env a1 _mal_function }{ /el ast env eval_ast def el _rest el _first % stack: ast function - dup _mal_function? { % if user defined function + dup _mal_function? { %if user defined function fload % stack: ast new_env EVAL + }{ dup _function? { %else if builtin function + /data get exec }{ %else (regular procedure/function) - exec % apply function to args - } ifelse + (cannot apply native proc!\n) print quit + } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse end } def @@ -120,7 +111,7 @@ end } def /RE { READ repl_env EVAL } def /REP { READ repl_env EVAL PRINT } def -/_ref { repl_env 3 1 roll env_set pop } def +/_ref { _function repl_env 3 1 roll env_set pop } def core_ns { _ref } forall diff --git a/ps/step5_tco.ps b/ps/step5_tco.ps index 96c44ee..802f3d3 100644 --- a/ps/step5_tco.ps +++ b/ps/step5_tco.ps @@ -90,27 +90,18 @@ end } def }{ /fn* a0 eq { %if fn* /a1 ast 1 _nth def /a2 ast 2 _nth def - << - /_maltype_ /function % user defined function - /params null % close over parameters - /ast null % close over ast - /env null % close over environment - /data { __self__ fload EVAL } - >> - dup length dict copy % make an actual copy/new instance - dup /params a1 put % insert closed over a1 into position 2 - dup /ast a2 put % insert closed over a2 into position 3 - dup /env env put % insert closed over env into position 4 - dup dup /data get exch 0 exch put % insert self reference + a2 env a1 _mal_function }{ /el ast env eval_ast def el _rest el _first % stack: ast function - dup _mal_function? { % if user defined function + dup _mal_function? { %if user defined function fload % stack: ast new_env /loop? true def + }{ dup _function? { %else if builtin function + /data get exec }{ %else (regular procedure/function) - exec % apply function to args - } ifelse + (cannot apply native proc!\n) print quit + } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse @@ -130,7 +121,7 @@ end } def /RE { READ repl_env EVAL } def /REP { READ repl_env EVAL PRINT } def -/_ref { repl_env 3 1 roll env_set pop } def +/_ref { _function repl_env 3 1 roll env_set pop } def core_ns { _ref } forall diff --git a/ps/step6_file.ps b/ps/step6_file.ps index 1eff14f..fc12cc1 100644 --- a/ps/step6_file.ps +++ b/ps/step6_file.ps @@ -90,27 +90,18 @@ end } def }{ /fn* a0 eq { %if fn* /a1 ast 1 _nth def /a2 ast 2 _nth def - << - /_maltype_ /function % user defined function - /params null % close over parameters - /ast null % close over ast - /env null % close over environment - /data { __self__ fload EVAL } - >> - dup length dict copy % make an actual copy/new instance - dup /params a1 put % insert closed over a1 into position 2 - dup /ast a2 put % insert closed over a2 into position 3 - dup /env env put % insert closed over env into position 4 - dup dup /data get exch 0 exch put % insert self reference + a2 env a1 _mal_function }{ /el ast env eval_ast def el _rest el _first % stack: ast function - dup _mal_function? { % if user defined function + dup _mal_function? { %if user defined function fload % stack: ast new_env /loop? true def + }{ dup _function? { %else if builtin function + /data get exec }{ %else (regular procedure/function) - exec % apply function to args - } ifelse + (cannot apply native proc!\n) print quit + } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse @@ -130,7 +121,7 @@ end } def /RE { READ repl_env EVAL } def /REP { READ repl_env EVAL PRINT } def -/_ref { repl_env 3 1 roll env_set pop } def +/_ref { _function repl_env 3 1 roll env_set pop } def core_ns { _ref } forall diff --git a/ps/step7_quote.ps b/ps/step7_quote.ps index 4708aa0..6913bf6 100644 --- a/ps/step7_quote.ps +++ b/ps/step7_quote.ps @@ -122,28 +122,19 @@ end } def }{ /fn* a0 eq { %if fn* /a1 ast 1 _nth def /a2 ast 2 _nth def - << - /_maltype_ /function % user defined function - /params null % close over parameters - /ast null % close over ast - /env null % close over environment - /data { __self__ fload EVAL } - >> - dup length dict copy % make an actual copy/new instance - dup /params a1 put % insert closed over a1 into position 2 - dup /ast a2 put % insert closed over a2 into position 3 - dup /env env put % insert closed over env into position 4 - dup dup /data get exch 0 exch put % insert self reference + a2 env a1 _mal_function }{ /el ast env eval_ast def el _rest el _first % stack: ast function - dup _mal_function? { % if user defined function + dup _mal_function? { %if user defined function fload % stack: ast new_env /loop? true def + }{ dup _function? { %else if builtin function + /data get exec }{ %else (regular procedure/function) - exec % apply function to args - } ifelse - } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse + (cannot apply native proc!\n) print quit + } ifelse } ifelse + } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse loop? not { exit } if @@ -162,7 +153,7 @@ end } def /RE { READ repl_env EVAL } def /REP { READ repl_env EVAL PRINT } def -/_ref { repl_env 3 1 roll env_set pop } def +/_ref { _function repl_env 3 1 roll env_set pop } def core_ns { _ref } forall diff --git a/ps/step8_macros.ps b/ps/step8_macros.ps index 330f6f7..286c1ab 100644 --- a/ps/step8_macros.ps +++ b/ps/step8_macros.ps @@ -163,28 +163,18 @@ end } def }{ /fn* a0 eq { %if fn* /a1 ast 1 _nth def /a2 ast 2 _nth def - << - /_maltype_ /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 } - >> - dup length dict copy % make an actual copy/new instance - dup /params a1 put % insert closed over a1 into position 2 - dup /ast a2 put % insert closed over a2 into position 3 - dup /env env put % insert closed over env into position 4 - dup dup /data get exch 0 exch put % insert self reference + a2 env a1 _mal_function }{ /el ast env eval_ast def el _rest el _first % stack: ast function - dup _mal_function? { % if user defined function + dup _mal_function? { %if user defined function fload % stack: ast new_env /loop? true def + }{ dup _function? { %else if builtin function + /data get exec }{ %else (regular procedure/function) - exec % apply function to args - } ifelse + (cannot apply native proc!\n) print quit + } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse @@ -205,7 +195,7 @@ end } def /RE { READ repl_env EVAL } def /REP { READ repl_env EVAL PRINT } def -/_ref { repl_env 3 1 roll env_set pop } def +/_ref { _function repl_env 3 1 roll env_set pop } def core_ns { _ref } forall diff --git a/ps/step9_interop.ps b/ps/step9_interop.ps index 5a7f3ec..f4380da 100644 --- a/ps/step9_interop.ps +++ b/ps/step9_interop.ps @@ -177,28 +177,18 @@ end } def }{ /fn* a0 eq { %if fn* /a1 ast 1 _nth def /a2 ast 2 _nth def - << - /_maltype_ /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 } - >> - dup length dict copy % make an actual copy/new instance - dup /params a1 put % insert closed over a1 into position 2 - dup /ast a2 put % insert closed over a2 into position 3 - dup /env env put % insert closed over env into position 4 - dup dup /data get exch 0 exch put % insert self reference + a2 env a1 _mal_function }{ /el ast env eval_ast def el _rest el _first % stack: ast function - dup _mal_function? { % if user defined function + dup _mal_function? { %if user defined function fload % stack: ast new_env /loop? true def + }{ dup _function? { %else if builtin function + /data get exec }{ %else (regular procedure/function) - exec % apply function to args - } ifelse + (cannot apply native proc!\n) print quit + } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse @@ -219,7 +209,7 @@ end } def /RE { READ repl_env EVAL } def /REP { READ repl_env EVAL PRINT } def -/_ref { repl_env 3 1 roll env_set pop } def +/_ref { _function repl_env 3 1 roll env_set pop } def core_ns { _ref } forall diff --git a/ps/stepA_more.ps b/ps/stepA_more.ps index 5704413..91a1fc7 100644 --- a/ps/stepA_more.ps +++ b/ps/stepA_more.ps @@ -213,28 +213,18 @@ end } def }{ /fn* a0 eq { %if fn* /a1 ast 1 _nth def /a2 ast 2 _nth def - << - /_maltype_ /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 } - >> - dup length dict copy % make an actual copy/new instance - dup /params a1 put % insert closed over a1 into position 2 - dup /ast a2 put % insert closed over a2 into position 3 - dup /env env put % insert closed over env into position 4 - dup dup /data get exch 0 exch put % insert self reference + a2 env a1 _mal_function }{ /el ast env eval_ast def el _rest el _first % stack: ast function - dup _mal_function? { % if user defined function + dup _mal_function? { %if user defined function fload % stack: ast new_env /loop? true def + }{ dup _function? { %else if builtin function + /data get exec }{ %else (regular procedure/function) - exec % apply function to args - } ifelse + (cannot apply native proc!\n) print quit + } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse @@ -255,11 +245,11 @@ end } def /RE { READ repl_env EVAL } def /REP { READ repl_env EVAL PRINT } def -/_ref { repl_env 3 1 roll env_set pop } def +/_ref { _function repl_env 3 1 roll env_set pop } def core_ns { _ref } forall -(readline) { 0 _nth _readline not { null } if } _ref +(readline) { 0 _nth _readline not { pop null } if } _ref (read-string) { 0 _nth read_str } _ref (eval) { 0 _nth repl_env EVAL } _ref /slurp { (r) file dup bytesavailable string readstring pop } def 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 diff --git a/tests/incB.mal b/tests/incB.mal index ed28734..86960c5 100644 --- a/tests/incB.mal +++ b/tests/incB.mal @@ -12,3 +12,6 @@ (prn "incB.mal finished") "incB.mal return string" + +;; ending comment + diff --git a/tests/step4_if_fn_do.mal b/tests/step4_if_fn_do.mal index a4ce46f..4d41380 100644 --- a/tests/step4_if_fn_do.mal +++ b/tests/step4_if_fn_do.mal @@ -264,6 +264,9 @@ ( (fn* () 4) ) ;=>4 +( (fn* (f x) (f x)) (fn* (a) (+ 1 a)) 7) +;=>8 + ;; Testing closures ( ( (fn* (a) (fn* (b) (+ a b))) 5) 7) diff --git a/tests/stepA_more.mal b/tests/stepA_more.mal index f6b01f5..892b592 100644 --- a/tests/stepA_more.mal +++ b/tests/stepA_more.mal @@ -117,6 +117,9 @@ (map? []) ;=>false +(get nil "a") +;=>nil + (get hm1 "a") ;=>nil @@ -174,6 +177,9 @@ (meta (fn* (a) a)) ;=>nil +(meta +) +;=>nil + (with-meta [1 2 3] {"a" 1}) ;=>[1 2 3] @@ -276,6 +282,15 @@ (swap! a + 3) ;=>123 +;; Testing swap!/closure interaction +(def! inc-it (fn* (a) (+ 1 a))) +(def! atm (atom 7)) +(def! f (fn* [] (swap! atm inc-it))) +(f) +;=>8 +(f) +;=>9 + ;; ;; Testing read-str and eval (read-string "(1 2 (3 4) nil)") |
