Merge pull request #156 from omarrayward/explain-regexp-tokenizer
[jackhill/mal.git] / ps / step2_eval.ps
1 /runlibfile where { pop }{ /runlibfile { run } def } ifelse %
2 (types.ps) runlibfile
3 (reader.ps) runlibfile
4 (printer.ps) runlibfile
5
6 % read
7 /_readline { print flush (%stdin) (r) file 1024 string readline } def
8
9 /READ {
10 /str exch def
11 str read_str
12 } def
13
14
15 % eval
16 /eval_ast { 2 dict begin
17 /env exch def
18 /ast exch def
19 %(eval_ast: ) print ast ==
20 ast _symbol? { %if symbol
21 env ast known {
22 env ast get
23 }{
24 (') ast false _pr_str (' not found)
25 concatenate concatenate _throw
26 } ifelse
27 }{ ast _sequential? { %elseif list or vector
28 [
29 ast /data get { %forall items
30 env EVAL
31 } forall
32 ] ast _list? { _list_from_array }{ _vector_from_array } ifelse
33 }{ ast _hash_map? { %elseif list or vector
34 <<
35 ast /data get { %forall entries
36 env EVAL
37 } forall
38 >> _hash_map_from_dict
39 }{ % else
40 ast
41 } ifelse } ifelse } ifelse
42 end } def
43
44 /EVAL { 3 dict begin
45 /env exch def
46 /ast exch def
47
48 %(EVAL: ) print ast true _pr_str print (\n) print
49 ast _list? not { %if not a list
50 ast env eval_ast
51 }{ %else apply the list
52 /el ast env eval_ast def
53 el _rest el _first % stack: ast function
54 exec % apply function to args
55 } ifelse
56 end } def
57
58
59 % print
60 /PRINT {
61 true _pr_str
62 } def
63
64
65 % repl
66 /repl_env <<
67 (+) { dup 0 _nth exch 1 _nth add }
68 (-) { dup 0 _nth exch 1 _nth sub }
69 (*) { dup 0 _nth exch 1 _nth mul }
70 (/) { dup 0 _nth exch 1 _nth idiv }
71 >> def
72
73 /REP { READ repl_env EVAL PRINT } def
74
75 % repl loop
76 { %loop
77 (user> ) _readline
78 not { exit } if % exit if EOF
79
80 { %try
81 REP print (\n) print
82 } stopped {
83 (Error: ) print
84 get_error_data false _pr_str print (\n) print
85 $error /newerror false put
86 $error /errorinfo null put
87 clear
88 cleardictstack
89 } if
90 } bind loop
91
92 (\n) print % final newline before exit for cleanliness
93 quit