1 module Core exposing (..)
3 import Types exposing (MalExpr(..), MalFunction(..), Eval, Env)
6 import Printer exposing (printString)
9 import IO exposing (IO(..))
11 import Utils exposing (zip)
18 CoreFunc >> MalFunction
20 binaryOp fn retType args =
22 [ MalInt x, MalInt y ] ->
23 Eval.succeed (retType (fn x y))
26 Eval.fail "unsupported arguments"
30 Eval.succeed << MalList
36 Eval.succeed (MalBool True)
39 Eval.succeed (MalBool False)
45 Eval.succeed <| MalBool (List.isEmpty list)
48 Eval.succeed <| MalBool (Array.isEmpty vec)
51 Eval.fail "unsupported arguments"
57 Eval.succeed (MalInt 0)
60 Eval.succeed <| MalInt (List.length list)
63 Eval.succeed <| MalInt (Array.length vec)
66 Eval.fail "unsupported arguments"
73 ( x :: xs, y :: ys ) ->
74 if deepEquals x y then
82 compareListTo list other =
85 equalLists list otherList
88 equalLists list (Array.toList vec)
94 if Dict.keys a /= Dict.keys b then
97 zip (Dict.values a) (Dict.values b)
98 |> List.map (uncurry deepEquals)
103 ( MalList list, MalList otherList ) ->
104 equalLists list otherList
106 ( MalList list, MalVector vec ) ->
107 equalLists list (Array.toList vec)
112 ( MalVector vec, MalList list ) ->
113 equalLists (Array.toList vec) list
115 ( MalVector vec, MalVector otherVec ) ->
116 equalLists (Array.toList vec) (Array.toList otherVec)
118 ( MalVector _, _ ) ->
121 ( MalMap map, MalMap otherMap ) ->
122 equalMaps map otherMap
137 Eval.succeed <| MalBool (deepEquals a b)
140 Eval.fail "unsupported arguments"
147 |> List.map (printString env True)
158 |> List.map (printString env False)
164 {- helper function to write a string to stdout -}
166 Eval.io (IO.writeLine str)
173 Eval.fail "wrong IO, expected LineWritten"
180 |> List.map (printString env True)
189 |> List.map (printString env False)
197 Eval.withEnv (Printer.printEnv >> writeLine)
200 Eval.fail "unsupported arguments"
205 case Reader.readString str of
216 Eval.fail "unsupported arguments"
220 [ MalString filename ] ->
221 Eval.io (IO.readFile filename)
225 Eval.succeed <| MalString contents
231 Eval.fail "wrong IO, expected FileRead"
235 Eval.fail "unsupported arguments"
242 case Env.newAtom value env of
243 ( newEnv, atomId ) ->
245 |> Eval.map (\_ -> MalAtom atomId)
249 Eval.fail "unsupported arguments"
254 Eval.succeed <| MalBool True
257 Eval.succeed <| MalBool False
261 [ MalAtom atomId ] ->
262 Eval.withEnv (Env.getAtom atomId >> Eval.succeed)
265 Eval.fail "unsupported arguments"
269 [ MalAtom atomId, value ] ->
270 Eval.modifyEnv (Env.setAtom atomId value)
271 |> Eval.map (always value)
274 Eval.fail "unsupported arguments"
276 {- helper function for calling a core or user function -}
282 UserFunc { eagerFn } ->
287 (MalAtom atomId) :: (MalFunction func) :: args ->
288 -- TODO eval apply here!
293 Env.getAtom atomId env
295 callFn func (value :: args)
299 Eval.modifyEnv (Env.setAtom atomId res)
300 |> Eval.map (always res)
304 Eval.fail "unsupported arguments"
307 Eval.withEnv (Env.gc >> Printer.printEnv >> writeLine)
312 { env | debug = enabled }
314 |> Eval.andThen (\_ -> Eval.succeed MalNil)
327 Eval.succeed <| MalSymbol "int"
330 Eval.succeed <| MalSymbol "bool"
333 Eval.succeed <| MalSymbol "string"
336 Eval.succeed <| MalSymbol "keyword"
339 Eval.succeed <| MalSymbol "symbol"
342 Eval.succeed <| MalSymbol "nil"
345 Eval.succeed <| MalSymbol "vector"
348 Eval.succeed <| MalSymbol "vector"
351 Eval.succeed <| MalSymbol "vector"
354 Eval.succeed <| MalSymbol "function"
357 Eval.succeed <| MalSymbol "atom"
360 Eval.fail "unsupported arguments"
364 [ e, MalList list ] ->
365 Eval.succeed <| MalList (e :: list)
368 Eval.fail "unsupported arguments"
375 Eval.succeed (acc ++ list)
378 Eval.succeed (acc ++ Array.toList vec)
381 Eval.fail "unsupported arguments"
383 List.foldl (go >> Eval.andThen) (Eval.succeed []) args
387 |> Env.set "+" (makeFn <| binaryOp (+) MalInt)
388 |> Env.set "-" (makeFn <| binaryOp (-) MalInt)
389 |> Env.set "*" (makeFn <| binaryOp (*) MalInt)
390 |> Env.set "/" (makeFn <| binaryOp (//) MalInt)
391 |> Env.set "<" (makeFn <| binaryOp (<) MalBool)
392 |> Env.set ">" (makeFn <| binaryOp (>) MalBool)
393 |> Env.set "<=" (makeFn <| binaryOp (<=) MalBool)
394 |> Env.set ">=" (makeFn <| binaryOp (>=) MalBool)
395 |> Env.set "list" (makeFn list)
396 |> Env.set "list?" (makeFn isList)
397 |> Env.set "empty?" (makeFn isEmpty)
398 |> Env.set "count" (makeFn count)
399 |> Env.set "=" (makeFn equals)
400 |> Env.set "pr-str" (makeFn prStr)
401 |> Env.set "str" (makeFn str)
402 |> Env.set "prn" (makeFn prn)
403 |> Env.set "println" (makeFn println)
404 |> Env.set "pr-env" (makeFn printEnv)
405 |> Env.set "read-string" (makeFn readString)
406 |> Env.set "slurp" (makeFn slurp)
407 |> Env.set "atom" (makeFn atom)
408 |> Env.set "atom?" (makeFn isAtom)
409 |> Env.set "deref" (makeFn deref)
410 |> Env.set "reset!" (makeFn reset)
411 |> Env.set "swap!" (makeFn swap)
412 |> Env.set "gc" (makeFn gc)
413 |> Env.set "debug!" (makeFn debug)
414 |> Env.set "typeof" (makeFn typeof)
415 |> Env.set "cons" (makeFn cons)
416 |> Env.set "concat" (makeFn concat)
419 malInit : List String
423 (if a false true)))"""
427 (str "(do " (slurp f) ")")))))"""