14 MalType
READ(string
str)
19 MalType
eval_ast(MalType ast
, Env env
)
21 if (typeid(ast
) == typeid(MalSymbol
))
23 auto sym
= verify_cast
!MalSymbol(ast
);
26 else if (typeid(ast
) == typeid(MalList
))
28 auto lst
= verify_cast
!MalList(ast
);
29 auto el
= array(lst
.elements
.map
!(e
=> EVAL(e
, env
)));
30 return new MalList(el
);
32 else if (typeid(ast
) == typeid(MalVector
))
34 auto lst
= verify_cast
!MalVector(ast
);
35 auto el
= array(lst
.elements
.map
!(e
=> EVAL(e
, env
)));
36 return new MalVector(el
);
38 else if (typeid(ast
) == typeid(MalHashmap
))
40 auto hm
= verify_cast
!MalHashmap(ast
);
41 typeof(hm
.data
) new_data
;
42 foreach (string k
, MalType v
; hm
.data
)
44 new_data
[k
] = EVAL(v
, env
);
46 return new MalHashmap(new_data
);
54 MalType
EVAL(MalType ast
, Env env
)
56 MalList ast_list
= cast(MalList
) ast
;
59 return eval_ast(ast
, env
);
61 if (ast_list
.elements
.length
== 0)
66 auto a0_sym
= verify_cast
!MalSymbol(ast_list
.elements
[0]);
70 auto a1
= verify_cast
!MalSymbol(ast_list
.elements
[1]);
71 return env
.set(a1
, EVAL(ast_list
.elements
[2], env
));
74 auto a1
= verify_cast
!MalSequential(ast_list
.elements
[1]);
75 auto let_env
= new Env(env
);
76 foreach (kv
; chunks(a1
.elements
, 2))
78 if (kv
.length
< 2) throw new Exception("let* requires even number of elements");
79 auto var_name
= verify_cast
!MalSymbol(kv
[0]);
80 let_env
.set(var_name
, EVAL(kv
[1], let_env
));
82 return EVAL(ast_list
.elements
[2], let_env
);
85 auto el
= verify_cast
!MalList(eval_ast(ast_list
, env
));
86 auto fobj
= verify_cast
!MalBuiltinFunc(el
.elements
[0]);
87 auto args
= el
.elements
[1..$];
92 string
PRINT(MalType ast
)
97 string
rep(string
str, Env env
)
99 return PRINT(EVAL(READ(str), env
));
102 static MalType
mal_add(MalType
[] a
...)
104 verify_args_count(a
, 2);
105 MalInteger i0
= verify_cast
!MalInteger(a
[0]);
106 MalInteger i1
= verify_cast
!MalInteger(a
[1]);
107 return new MalInteger(i0
.val
+ i1
.val
);
110 static MalType
mal_sub(MalType
[] a
...)
112 verify_args_count(a
, 2);
113 MalInteger i0
= verify_cast
!MalInteger(a
[0]);
114 MalInteger i1
= verify_cast
!MalInteger(a
[1]);
115 return new MalInteger(i0
.val
- i1
.val
);
118 static MalType
mal_mul(MalType
[] a
...)
120 verify_args_count(a
, 2);
121 MalInteger i0
= verify_cast
!MalInteger(a
[0]);
122 MalInteger i1
= verify_cast
!MalInteger(a
[1]);
123 return new MalInteger(i0
.val
* i1
.val
);
126 static MalType
mal_div(MalType
[] a
...)
128 verify_args_count(a
, 2);
129 MalInteger i0
= verify_cast
!MalInteger(a
[0]);
130 MalInteger i1
= verify_cast
!MalInteger(a
[1]);
131 return new MalInteger(i0
.val
/ i1
.val
);
136 auto repl_env
= new Env(null);
137 repl_env
.set(new MalSymbol("+"), new MalBuiltinFunc(&mal_add
, "+"));
138 repl_env
.set(new MalSymbol("-"), new MalBuiltinFunc(&mal_sub
, "-"));
139 repl_env
.set(new MalSymbol("*"), new MalBuiltinFunc(&mal_mul
, "*"));
140 repl_env
.set(new MalSymbol("/"), new MalBuiltinFunc(&mal_div
, "/"));
144 string line
= _readline("user> ");
145 if (line
is null) break;
146 if (line
.length
== 0) continue;
149 writeln(rep(line
, repl_env
));
153 writeln("Error: ", e
.msg
);