1 FileStream fileIn: 'readline.st'.
2 FileStream fileIn: 'reader.st'.
3 FileStream fileIn: 'printer.st'.
4 FileStream fileIn: 'env.st'.
5 FileStream fileIn: 'core.st'.
8 MAL class >>
READ: input
[
12 MAL class >>
evalAst: sexp
env: env
[
13 sexp type
= #symbol ifTrue: [
17 sexp type
= #list ifTrue: [
18 ^self evalList: sexp
env: env
class: MALList
20 sexp type
= #vector ifTrue: [
21 ^self evalList: sexp
env: env
class: MALVector
23 sexp type
= #map ifTrue: [
24 ^self evalList: sexp
env: env
class: MALMap
30 MAL class >>
evalList: sexp
env: env
class: aClass
[
32 items
:= sexp value
collect:
33 [ :item |
self EVAL: item
env: env
].
37 MAL class >>
EVAL: sexp
env: env
[
38 | ast a0_ a1 a1_ a1_n a2 a3 forms function args |
39 sexp type ~
= #list ifTrue: [
40 ^self evalAst: sexp
env: env
42 sexp value isEmpty
ifTrue: [
47 a0_
:= ast first value
.
48 a0_
= #'def!' ifTrue: [
50 a1_
:= ast second value
.
52 result
:= self EVAL: a2
env: env
.
53 env
set: a1_
value: result
.
57 a0_
= #'let*' ifTrue: [
60 a1_
:= ast second value
.
62 1 to: a1_ size
by: 2 do:
63 [ :i | env_
set: (a1_
at: i
) value
64 value: (self EVAL: (a1_
at: i
+ 1) env: env_
) ].
65 ^self EVAL: a2
env: env_
69 a1_n
:= ast allButFirst
.
70 ^(a1_n
collect: [ :item |
self EVAL: item
env: env
]) last
77 a3
:= ast
at: 4 ifAbsent: [ MALObject Nil ].
78 condition
:= self EVAL: a1
env: env
.
80 (condition type
= #false or: [ condition type
= #nil ]) ifTrue: [
81 ^self EVAL: a3
env: env
83 ^self EVAL: a2
env: env
87 a0_
= #'fn*' ifTrue: [
89 a1_
:= ast second value
.
90 binds
:= a1_
collect: [ :item | item value
].
92 ^[ :args |
self EVAL: a2
env:
93 (Env new: env
binds: binds
exprs: args
) ]
96 forms
:= (self evalAst: sexp
env: env
) value
.
97 function
:= forms first
.
98 args
:= forms allButFirst asArray
.
102 MAL class >>
PRINT: sexp
[
103 ^Printer prStr: sexp
printReadably: true
106 MAL class >>
rep: input
env: env
[
107 ^self PRINT: (self EVAL: (self READ: input
) env: env
)
111 | input historyFile replEnv |
113 historyFile
:= '.mal_history'.
114 ReadLine readHistory: historyFile
.
115 replEnv
:= Env new: nil.
117 Core Ns keysAndValuesDo: [ :op :block | replEnv
set: op
value: block
].
119 MAL rep: '(def! not (fn* (a) (if a false true)))' env: replEnv
.
121 [ input
:= ReadLine readLine: 'user> '. input isNil
] whileFalse: [
122 input isEmpty
ifFalse: [
123 ReadLine addHistory: input
.
124 ReadLine writeHistory: historyFile
.
125 [ (MAL rep: input
env: replEnv
) displayNl
]
126 on: MALEmptyInput do: [ #return ]
128 [ :err |
('error: ', err messageText
) displayNl
. #return ].