Self-hosting fix
[jackhill/mal.git] / gst / step2_eval.st
CommitLineData
1b18f359
VS
1FileStream fileIn: 'readline.st'.
2FileStream fileIn: 'reader.st'.
3FileStream fileIn: 'printer.st'.
4
5Object subclass: MAL [
6 MAL class >> READ: input [
7 ^Reader readStr: input
8 ]
9
10 MAL class >> evalAst: sexp env: env [
11 sexp type = #symbol ifTrue: [
12 ^env at: sexp value ifAbsent: [
13 ^MALUnknownSymbol new signal: sexp value
14 ].
15 ].
16
17 sexp type = #list ifTrue: [
18 ^self evalList: sexp env: env class: MALList
19 ].
20 sexp type = #vector ifTrue: [
21 ^self evalList: sexp env: env class: MALVector
22 ].
23 sexp type = #map ifTrue: [
24 ^self evalList: sexp env: env class: MALMap
25 ].
26
27 ^sexp
28 ]
29
30 MAL class >> evalList: sexp env: env class: aClass [
31 | items |
32 items := sexp value collect:
33 [ :item | self EVAL: item env: env ].
34 ^aClass new: items
35 ]
36
37 MAL class >> EVAL: sexp env: env [
38 | forms function args |
39 sexp type ~= #list ifTrue: [
40 ^self evalAst: sexp env: env
41 ].
42 sexp value isEmpty ifTrue: [
43 ^sexp
44 ].
45
46 forms := (self evalAst: sexp env: env) value.
47 function := forms first.
48 args := forms allButFirst asArray.
49 ^function valueWithArguments: args
50 ]
51
52 MAL class >> PRINT: sexp [
53 ^Printer prStr: sexp printReadably: true
54 ]
55
56 MAL class >> rep: input env: env [
57 ^self PRINT: (self EVAL: (self READ: input) env: env)
58 ]
59]
60
61| input historyFile replEnv |
62
63historyFile := '.mal_history'.
64ReadLine readHistory: historyFile.
65replEnv := Dictionary from:
66 { #+ -> [ :a :b | MALNumber new: a value + b value ].
67 #- -> [ :a :b | MALNumber new: a value - b value ].
68 #* -> [ :a :b | MALNumber new: a value * b value ].
69 #/ -> [ :a :b | MALNumber new: a value // b value ] }.
70
71[ input := ReadLine readLine: 'user> '. input isNil ] whileFalse: [
72 input isEmpty ifFalse: [
73 ReadLine addHistory: input.
74 ReadLine writeHistory: historyFile.
75 [ (MAL rep: input env: replEnv) displayNl ]
76 on: MALEmptyInput do: [ #return ]
77 on: MALError do:
78 [ :err | ('error: ', err messageText) displayNl. #return ].
79 ]
80]
81
82'' displayNl.