blob: a86e036a07e6db3de392e4b793f8074c9f36e9d1 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
|
(types.ps) run
(reader.ps) run
% read
/_readline { print flush (%stdin) (r) file 99 string readline } def
/READ {
/str exch def
str read_str
} def
% eval
/eval_ast { 2 dict begin
/env exch def
/ast exch def
%(eval_ast: ) print ast ==
ast _symbol? { %if symbol
env ast env_get
}{ ast _list? { %elseif list
[
ast {
env EVAL
} forall
]
}{ % else
ast
} ifelse } ifelse
end } def
/EVAL { 8 dict begin
/env exch def
/ast exch def
%(EVAL: ) print ast true _pr_str print (\n) print
ast _list? not { %if not a list
ast env eval_ast
}{ %else apply the list
/a0 ast 0 get def
/def! a0 eq { %if def!
/a1 ast 1 get def
/a2 ast 2 get def
env a1 a2 env EVAL env_set
}{ /let* a0 eq { %if let*
/a1 ast 1 get def
/a2 ast 2 get def
/let_env env [ ] [ ] env_new def
0 2 a1 length 1 sub { %for each pair
/idx exch def
let_env
a1 idx get
a1 idx 1 add get let_env EVAL
env_set
pop % discard the return value
} for
a2 let_env EVAL
}{
/el ast env eval_ast def
el _rest el _first % stack: ast function
exec % apply function to args
} ifelse } ifelse
} ifelse
end } def
% print
/PRINT {
true _pr_str
} def
% repl
/repl_env null [ ] [ ] env_new def
/REP { READ repl_env EVAL PRINT } def
/_ref { repl_env 3 1 roll env_set pop } def
(+) { dup 0 get exch 1 get add } _ref
(-) { dup 0 get exch 1 get sub } _ref
(*) { dup 0 get exch 1 get mul } _ref
(/) { dup 0 get exch 1 get idiv } _ref
{ % loop
(user> ) _readline
not { exit } if % exit if EOF
{ %try
REP print (\n) print
} stopped {
(Error: ) print
get_error_data false _pr_str print (\n) print
$error /newerror false put
$error /errorinfo null put
clear
cleardictstack
} if
} bind loop
(\n) print % final newline before exit for cleanliness
quit
|