-(types.ps) run
-(reader.ps) run
-(printer.ps) run
-(env.ps) run
-(core.ps) run
+/runlibfile where { pop }{ /runlibfile { run } def } ifelse %
+(types.ps) runlibfile
+(reader.ps) runlibfile
+(printer.ps) runlibfile
+(env.ps) runlibfile
+(core.ps) runlibfile
% read
-/_readline { print flush (%stdin) (r) file 99 string readline } def
+/_readline { print flush (%stdin) (r) file 1024 string readline } def
/READ {
/str exch def
ast env eval_ast
}{ %else apply the list
/a0 ast 0 _nth def
- /def! a0 eq { %if def!
+ a0 _nil? { %if ()
+ ast
+ }{ /def! a0 eq { %if def!
/a1 ast 1 _nth def
/a2 ast 2 _nth def
env a1 a2 env EVAL env_set
env_set
pop % discard the return value
} for
- a2 let_env EVAL
+ a2
+ let_env
+ /loop? true def % loop
}{ /do a0 eq { %if do
ast _count 2 gt { %if ast has more than 2 elements
ast 1 ast _count 2 sub _slice env eval_ast pop
}{ /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
+ (cannot apply native proc!\n) print quit
+ } ifelse } ifelse
+ } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse
} ifelse
loop? not { exit } if
/RE { READ repl_env EVAL } def
/REP { READ repl_env EVAL PRINT } def
-/_ref { repl_env 3 1 roll env_set pop } def
-core_ns { _ref } forall
-
-(read-string) { 0 _nth read_str } _ref
-(eval) { 0 _nth repl_env EVAL } _ref
-/slurp { (r) file dup bytesavailable string readstring pop } def
-(slurp) { 0 _nth slurp } _ref
+% core.ps: defined using postscript
+/_ref { repl_env 3 1 roll env_set pop } def
+core_ns { _function _ref } forall
+(eval) { 0 _nth repl_env EVAL } _function _ref
+(*ARGV*) [ ] _list_from_array _ref
+% core.mal: defined using the language itself
(\(def! not \(fn* \(a\) \(if a false true\)\)\)) RE pop
(\(def! load-file \(fn* \(f\) \(eval \(read-string \(str "\(do " \(slurp f\) "\)"\)\)\)\)\)) RE pop
userdict /ARGUMENTS known { %if command line arguments
ARGUMENTS length 0 gt { %if more than 0 arguments
- ARGUMENTS {
- (\(load-file ") exch ("\)) concatenate concatenate RE pop
- } forall
+ (*ARGV*) ARGUMENTS 1 ARGUMENTS length 1 sub getinterval
+ _list_from_array _ref
+ ARGUMENTS 0 get
+ (\(load-file ") exch ("\)) concatenate concatenate RE pop
quit
} if
} if
-{ % loop
+
+% repl loop
+{ %loop
(user> ) _readline
not { exit } if % exit if EOF