def _printLn(s string) MalVal { printLn(s) return gNil } const ns StringMap) MalVal> = { "eval": (a List) => EVAL(a[0], repl_env), "=": (a List) => MalVal.fromBool(a[0].equal(a[1])), "throw": (a List) => { throw MalUserError.new(a[0]) }, "nil?": (a List) => MalVal.fromBool(a[0] is MalNil), "true?": (a List) => MalVal.fromBool(a[0] is MalTrue), "false?": (a List) => MalVal.fromBool(a[0] is MalFalse), "string?": (a List) => MalVal.fromBool(a[0] is MalString), "symbol": (a List) => MalSymbol.new((a[0] as MalString).val), "symbol?": (a List) => MalVal.fromBool(a[0] is MalSymbol), "keyword": (a List) => MalKeyword.new((a[0] as MalString).val), "keyword?": (a List) => MalVal.fromBool(a[0] is MalKeyword), "number?": (a List) => MalVal.fromBool(a[0] is MalNumber), "fn?": (a List) => MalVal.fromBool(a[0] is MalNativeFunc || (a[0] is MalFunc && !(a[0] as MalFunc).isMacro)), "macro?": (a List) => MalVal.fromBool(a[0] is MalFunc && (a[0] as MalFunc).isMacro), "pr-str": (a List) => MalString.new(" ".join(a.map(e => pr_str(e, true)))), "str": (a List) => MalString.new("".join(a.map(e => pr_str(e, false)))), "prn": (a List) => _printLn(" ".join(a.map(e => pr_str(e, true)))), "println": (a List) => _printLn(" ".join(a.map(e => pr_str(e, false)))), "read-string": (a List) => read_str((a[0] as MalString).val), "readline": (a List) => { const line = readLine((a[0] as MalString).val) return line == null ? gNil : MalString.new(line) }, "slurp": (a List) => MalString.new(readFile((a[0] as MalString).val)), "<": (a List) => MalVal.fromBool((a[0] as MalNumber).val < (a[1] as MalNumber).val), "<=": (a List) => MalVal.fromBool((a[0] as MalNumber).val <= (a[1] as MalNumber).val), ">": (a List) => MalVal.fromBool((a[0] as MalNumber).val > (a[1] as MalNumber).val), ">=": (a List) => MalVal.fromBool((a[0] as MalNumber).val >= (a[1] as MalNumber).val), "+": (a List) => MalNumber.new((a[0] as MalNumber).val + (a[1] as MalNumber).val), "-": (a List) => MalNumber.new((a[0] as MalNumber).val - (a[1] as MalNumber).val), "*": (a List) => MalNumber.new((a[0] as MalNumber).val * (a[1] as MalNumber).val), "/": (a List) => MalNumber.new((a[0] as MalNumber).val / (a[1] as MalNumber).val), "time-ms": (a List) => MalNumber.new(timeMs), "list": (a List) => MalList.new(a), "list?": (a List) => MalVal.fromBool(a[0] is MalList), "vector": (a List) => MalVector.new(a), "vector?": (a List) => MalVal.fromBool(a[0] is MalVector), "hash-map": (a List) => MalHashMap.fromList(a), "map?": (a List) => MalVal.fromBool(a[0] is MalHashMap), "assoc": (a List) => (a[0] as MalHashMap).assoc(a.slice(1)), "dissoc": (a List) => (a[0] as MalHashMap).dissoc(a.slice(1)), "get": (a List) => a[0] is MalNil ? gNil : (a[0] as MalHashMap).get(a[1]), "contains?": (a List) => MalVal.fromBool((a[0] as MalHashMap).contains(a[1])), "keys": (a List) => MalList.new((a[0] as MalHashMap).keys), "vals": (a List) => MalList.new((a[0] as MalHashMap).vals), "sequential?": (a List) => MalVal.fromBool(a[0] is MalSequential), "cons": (a List) => { var list List = (a[1] as MalSequential).val.clone list.prepend(a[0]) return MalList.new(list) }, "concat": (a List) => { var list List = [] a.each(e => list.append((e as MalSequential).val)) return MalList.new(list) }, "nth": (a List) => (a[0] as MalSequential).nth((a[1] as MalNumber).val), "first": (a List) => a[0] is MalNil ? gNil : (a[0] as MalSequential).first, "rest": (a List) => a[0] is MalNil ? MalList.new([]) : (a[0] as MalSequential).rest, "empty?": (a List) => MalVal.fromBool((a[0] as MalSequential).count == 0), "count": (a List) => a[0] is MalNil ? MalNumber.new(0) : MalNumber.new((a[0] as MalSequential).count), "apply": (a List) => { const f = a[0] as MalCallable var args = a.slice(1, a.count - 1) args.append((a[a.count - 1] as MalSequential).val) return f.call(args) }, "map": (a List) => { const f = a[0] as MalCallable return MalList.new((a[1] as MalSequential).val.map(e => f.call([e]))) }, "conj": (a List) => (a[0] as MalSequential).conj(a.slice(1)), "seq": (a List) => a[0].seq, "meta": (a List) => a[0].meta, "with-meta": (a List) => a[0].withMeta(a[1]), "atom": (a List) => MalAtom.new(a[0]), "atom?": (a List) => MalVal.fromBool(a[0] is MalAtom), "deref": (a List) => (a[0] as MalAtom).val, "reset!": (a List) => (a[0] as MalAtom).resetBang(a[1]), "swap!": (a List) => { var atom = a[0] as MalAtom const oldVal = atom.val var callArgs = a.slice(2) callArgs.prepend(oldVal) const newVal = (a[1] as MalCallable).call(callArgs) return atom.resetBang(newVal) }, }