| 1 | MalCore := Object clone do( |
| 2 | slurp := block(a, |
| 3 | f := File with(a at(0)) |
| 4 | res := f contents |
| 5 | f close |
| 6 | res |
| 7 | ) |
| 8 | |
| 9 | dissoc := block(a, |
| 10 | res := MalMap withMap(a at(0)) |
| 11 | a rest foreach(k, res removeKey(k)) |
| 12 | res |
| 13 | ) |
| 14 | |
| 15 | nth := block(a, |
| 16 | if(a at(1) < a at(0) size, |
| 17 | a at(0) at(a at(1)), |
| 18 | Exception raise("nth: index out of range") |
| 19 | ) |
| 20 | ) |
| 21 | |
| 22 | conj := block(a, |
| 23 | coll := a at(0) |
| 24 | coll type switch( |
| 25 | "MalList", |
| 26 | MalList with(a rest reverse appendSeq(coll)), |
| 27 | "MalVector", |
| 28 | MalVector with(coll appendSeq(a rest)) |
| 29 | ) |
| 30 | ) |
| 31 | |
| 32 | seq := block(a, |
| 33 | obj := a at(0) |
| 34 | (obj isNil) ifTrue(return(nil)) |
| 35 | (obj type == "MalList") ifTrue(return(if(obj isEmpty, nil, obj))) |
| 36 | (obj type == "MalVector") ifTrue(return(if(obj isEmpty, nil, MalList with(obj)))) |
| 37 | (obj type == "Sequence") ifTrue( |
| 38 | if(obj isEmpty, return(nil)) |
| 39 | lst := list() |
| 40 | obj foreach(i, c, lst append(obj inclusiveSlice(i, i))) |
| 41 | return(MalList with(lst)) |
| 42 | ) |
| 43 | nil |
| 44 | ) |
| 45 | |
| 46 | swapBang := block(a, |
| 47 | atom := a at(0) |
| 48 | newVal := a at(1) call(MalList with(list(atom val)) appendSeq(a slice(2))) |
| 49 | atom setVal(newVal) val |
| 50 | ) |
| 51 | |
| 52 | ioToMal := method(v, |
| 53 | (v isNil) ifTrue(return(v)) |
| 54 | (v == true) ifTrue(return(v)) |
| 55 | (v == false) ifTrue(return(v)) |
| 56 | (v type == "Number") ifTrue(return(v)) |
| 57 | (v type == "Sequence") ifTrue(return(v)) |
| 58 | (v type == "List") ifTrue(return(MalList with(v map(e, ioToMal(e))))) |
| 59 | (v type == "Map") ifTrue( |
| 60 | lst := list() |
| 61 | v foreach(key, val, |
| 62 | lst push(key asString) |
| 63 | lst push(ioToMal(val)) |
| 64 | ) |
| 65 | return(MalMap withList(lst)) |
| 66 | ) |
| 67 | v asString |
| 68 | ) |
| 69 | |
| 70 | ioEval := block(a, |
| 71 | MalCore ioToMal(doString(a at(0))) |
| 72 | ) |
| 73 | |
| 74 | NS := Map with( |
| 75 | "=", block(a, a at(0) == a at(1)), |
| 76 | "throw", block(a, MalException with(a at(0)) raise), |
| 77 | |
| 78 | "nil?", block(a, a at(0) isNil), |
| 79 | "true?", block(a, a at(0) == true), |
| 80 | "false?", block(a, a at(0) == false), |
| 81 | "string?", block(a, a at(0) type == "Sequence"), |
| 82 | "symbol", block(a, MalSymbol with(a at(0))), |
| 83 | "symbol?", block(a, a at(0) type == "MalSymbol"), |
| 84 | "keyword", block(a, MalKeyword with(a at(0))), |
| 85 | "keyword?", block(a, a at(0) type == "MalKeyword"), |
| 86 | "number?", block(a, a at(0) type == "Number"), |
| 87 | "fn?", block(a, (a at(0) type == "Block") or |
| 88 | ((a at(0) type == "MalFunc") and (a at(0) isMacro not))), |
| 89 | "macro?", block(a, (a at(0) type == "MalFunc") and (a at(0) isMacro)), |
| 90 | |
| 91 | "pr-str", block(a, a map(s, s malPrint(true)) join(" ")), |
| 92 | "str", block(a, a map(s, s malPrint(false)) join("")), |
| 93 | "prn", block(a, a map(s, s malPrint(true)) join(" ") println ; nil), |
| 94 | "println", block(a, a map(s, s malPrint(false)) join(" ") println ; nil), |
| 95 | "read-string", block(a, MalReader read_str(a at(0))), |
| 96 | "readline", block(a, MalReadline readLine(a at(0))), |
| 97 | "slurp", slurp, |
| 98 | |
| 99 | "<", block(a, a at(0) < a at(1)), |
| 100 | "<=", block(a, a at(0) <= a at(1)), |
| 101 | ">", block(a, a at(0) > a at(1)), |
| 102 | ">=", block(a, a at(0) >= a at(1)), |
| 103 | "+", block(a, a at(0) + a at(1)), |
| 104 | "-", block(a, a at(0) - a at(1)), |
| 105 | "*", block(a, a at(0) * a at(1)), |
| 106 | "/", block(a, a at(0) / a at(1)), |
| 107 | "time-ms", block(a, (Date now asNumber * 1000.0) round), |
| 108 | |
| 109 | "list", block(a, a), |
| 110 | "list?", block(a, a at(0) type == "MalList"), |
| 111 | "vector", block(a, MalVector with(a)), |
| 112 | "vector?", block(a, a at(0) type == "MalVector"), |
| 113 | "hash-map", block(a, MalMap withList(a)), |
| 114 | "map?", block(a, a at(0) type == "MalMap"), |
| 115 | "assoc", block(a, MalMap withMap(a at(0) merge(MalMap withList(a rest)))), |
| 116 | "dissoc", dissoc, |
| 117 | "get", block(a, a at(0) ifNil(return nil) get(a at(1))), |
| 118 | "contains?", block(a, a at(0) ifNil(return nil) contains(a at(1))), |
| 119 | "keys", block(a, a at(0) malKeys), |
| 120 | "vals", block(a, a at(0) malVals), |
| 121 | |
| 122 | "sequential?", block(a, if(a at(0) ?isSequential, true, false)), |
| 123 | "cons", block(a, MalList with(list(a at(0)) appendSeq(a at(1)))), |
| 124 | "concat", block(a, MalList with(a reduce(appendSeq, list()))), |
| 125 | "nth", nth, |
| 126 | "first", block(a, a at(0) ifNil(return nil) first), |
| 127 | "rest", block(a, a at(0) ifNil(return MalList with(list())) rest), |
| 128 | "empty?", block(a, a at(0) ifNil(true) isEmpty), |
| 129 | "count", block(a, a at(0) ifNil(return(0)) size), |
| 130 | "apply", block(a, a at(0) call(MalList with(a slice(1, -1) appendSeq(a last)))), |
| 131 | "map", block(a, MalList with(a at(1) map(e, a at(0) call(MalList with(list(e)))))), |
| 132 | |
| 133 | "conj", conj, |
| 134 | "seq", seq, |
| 135 | |
| 136 | "meta", block(a, a at(0) ?meta), |
| 137 | "with-meta", block(a, a at(0) clone setMeta(a at(1))), |
| 138 | "atom", block(a, MalAtom with(a at(0))), |
| 139 | "atom?", block(a, a at(0) type == "MalAtom"), |
| 140 | "deref", block(a, a at(0) val), |
| 141 | "reset!", block(a, a at(0) setVal(a at(1)) ; a at(1)), |
| 142 | "swap!", swapBang, |
| 143 | |
| 144 | "io-eval", ioEval |
| 145 | ) |
| 146 | ) |