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