2016-03-03 23:03:06 +03:00
|
|
|
MalTypes
|
|
|
|
MalReader
|
|
|
|
|
|
|
|
READ := method(str, MalReader read_str(str))
|
|
|
|
|
|
|
|
eval_ast := method(ast, env,
|
|
|
|
(ast type) switch(
|
|
|
|
"MalSymbol", env get(ast),
|
|
|
|
"MalList", MalList with(ast map(a, EVAL(a, env))),
|
|
|
|
"MalVector", MalVector with(ast map(a, EVAL(a, env))),
|
|
|
|
"MalMap",
|
|
|
|
m := MalMap clone
|
|
|
|
ast foreach(k, v,
|
|
|
|
keyObj := MalMap keyToObj(k)
|
|
|
|
m atPut(MalMap objToKey(EVAL(keyObj, env)), EVAL(v, env))
|
|
|
|
)
|
|
|
|
m,
|
|
|
|
ast
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
EVAL := method(ast, env,
|
|
|
|
if(ast type != "MalList", return(eval_ast(ast, env)))
|
2016-03-30 16:02:13 +03:00
|
|
|
if(ast isEmpty, return ast)
|
2016-03-03 23:03:06 +03:00
|
|
|
if(ast at(0) type == "MalSymbol",
|
|
|
|
ast at(0) val switch(
|
|
|
|
"def!",
|
|
|
|
return(env set(ast at(1), EVAL(ast at(2), env))),
|
|
|
|
"do",
|
|
|
|
return(eval_ast(ast rest, env) last),
|
|
|
|
"if",
|
|
|
|
return(EVAL(if(EVAL(ast at(1), env), ast at(2), ast at(3)), env)),
|
|
|
|
"fn*",
|
|
|
|
return(block(a, EVAL(ast at(2), Env with(env, ast at(1), a)))),
|
|
|
|
"let*",
|
|
|
|
letEnv := Env with(env)
|
|
|
|
varName := nil
|
|
|
|
ast at(1) foreach(i, e,
|
|
|
|
if(i % 2 == 0,
|
|
|
|
varName := e,
|
|
|
|
letEnv set(varName, EVAL(e, letEnv))
|
|
|
|
)
|
|
|
|
)
|
|
|
|
return(EVAL(ast at(2), letEnv))
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
// Apply
|
|
|
|
el := eval_ast(ast, env)
|
|
|
|
f := el at(0)
|
|
|
|
args := el rest
|
|
|
|
f call(args)
|
|
|
|
)
|
|
|
|
|
|
|
|
PRINT := method(exp, exp malPrint(true))
|
|
|
|
|
|
|
|
RE := method(str, EVAL(READ(str), repl_env))
|
|
|
|
|
|
|
|
REP := method(str, PRINT(RE(str)))
|
|
|
|
|
|
|
|
repl_env := Env with(nil)
|
2016-03-04 08:11:01 +03:00
|
|
|
MalCore NS foreach(k, v, repl_env set(MalSymbol with(k), v))
|
2016-03-03 23:03:06 +03:00
|
|
|
|
|
|
|
// core.mal: defined using the language itself
|
|
|
|
RE("(def! not (fn* (a) (if a false true)))")
|
|
|
|
|
|
|
|
loop(
|
|
|
|
line := MalReadline readLine("user> ")
|
|
|
|
if(line isNil, break)
|
|
|
|
if(line isEmpty, continue)
|
|
|
|
e := try(REP(line) println)
|
|
|
|
e catch(Exception,
|
Test uncaught throw, catchless try* . Fix 46 impls.
Fixes made to: ada, c, chuck, clojure, coffee, common-lisp, cpp,
crystal, d, dart, elm, erlang, es6, factor, fsharp, gnu-smalltalk,
groovy, guile, haxe, hy, js, livescript, matlab, miniMAL, nasm, nim,
objc, objpascal, ocaml, perl, perl6, php, plsql, ps, python, r,
rpython, ruby, scheme, swift3, tcl, ts, vb, vimscript, wasm, yorick.
Catchless try* test is an optional test. Not all implementations
support catchless try* but a number were fixed so they at least don't
crash on catchless try*.
2018-12-03 22:20:44 +03:00
|
|
|
if(e type == "MalException",
|
|
|
|
("Error: " .. ((e val) malPrint(true))) println,
|
|
|
|
("Error: " .. (e error)) println
|
|
|
|
)
|
2016-03-03 23:03:06 +03:00
|
|
|
)
|
|
|
|
)
|