10 alias Env
= MalType
[string
];
12 MalType
READ(string
str)
17 MalType
eval_ast(MalType ast
, Env env
)
19 if (auto sym
= cast(MalSymbol
)ast
)
21 auto v
= (sym
.name
in env
);
22 if (v
is null) throw new Exception("'" ~ sym
.name
~ "' not found");
25 else if (auto lst
= cast(MalList
)ast
)
27 auto el
= array(lst
.elements
.map
!(e
=> EVAL(e
, env
)));
28 return new MalList(el
);
30 else if (auto lst
= cast(MalVector
)ast
)
32 auto el
= array(lst
.elements
.map
!(e
=> EVAL(e
, env
)));
33 return new MalVector(el
);
35 else if (auto hm
= cast(MalHashmap
)ast
)
37 typeof(hm
.data
) new_data
;
38 foreach (string k
, MalType v
; hm
.data
)
40 new_data
[k
] = EVAL(v
, env
);
42 return new MalHashmap(new_data
);
50 MalType
EVAL(MalType ast
, Env env
)
52 if (typeid(ast
) != typeid(MalList
))
54 return eval_ast(ast
, env
);
56 if ((cast(MalList
) ast
).elements
.length
== 0)
61 auto el
= verify_cast
!MalList(eval_ast(ast
, env
));
62 auto fobj
= verify_cast
!MalBuiltinFunc(el
.elements
[0]);
63 auto args
= el
.elements
[1..$];
67 string
PRINT(MalType ast
)
72 string
rep(string
str, Env env
)
74 return PRINT(EVAL(READ(str), env
));
77 static MalType
mal_add(MalType
[] a
...)
79 verify_args_count(a
, 2);
80 MalInteger i0
= verify_cast
!MalInteger(a
[0]);
81 MalInteger i1
= verify_cast
!MalInteger(a
[1]);
82 return new MalInteger(i0
.val
+ i1
.val
);
85 static MalType
mal_sub(MalType
[] a
...)
87 verify_args_count(a
, 2);
88 MalInteger i0
= verify_cast
!MalInteger(a
[0]);
89 MalInteger i1
= verify_cast
!MalInteger(a
[1]);
90 return new MalInteger(i0
.val
- i1
.val
);
93 static MalType
mal_mul(MalType
[] a
...)
95 verify_args_count(a
, 2);
96 MalInteger i0
= verify_cast
!MalInteger(a
[0]);
97 MalInteger i1
= verify_cast
!MalInteger(a
[1]);
98 return new MalInteger(i0
.val
* i1
.val
);
101 static MalType
mal_div(MalType
[] a
...)
103 verify_args_count(a
, 2);
104 MalInteger i0
= verify_cast
!MalInteger(a
[0]);
105 MalInteger i1
= verify_cast
!MalInteger(a
[1]);
106 return new MalInteger(i0
.val
/ i1
.val
);
112 repl_env
["+"] = new MalBuiltinFunc(&mal_add
, "+");
113 repl_env
["-"] = new MalBuiltinFunc(&mal_sub
, "-");
114 repl_env
["*"] = new MalBuiltinFunc(&mal_mul
, "*");
115 repl_env
["/"] = new MalBuiltinFunc(&mal_div
, "/");
119 string line
= _readline("user> ");
120 if (line
is null) break;
121 if (line
.length
== 0) continue;
124 writeln(rep(line
, repl_env
));
128 writeln("Error: ", e
.msg
);