+ g (IntExpr _ i) = tell [Instr "ldc" [Lit i] ""]
+ g (CharExpr _ c) = tell [Instr "ldc" [Lit (toInt c)] ""]
+ g (BoolExpr _ b) = tell [Instr "ldc" [Lit (if b TRUE FALSE)] ""]
+ g (EmptyListExpr _) = tell [Instr "ldc" [Lit 0] ""]
+ >>| tell [Instr "sth" [] ""]
+ g (Op1Expr _ o e) = g e >>| g o
+ g (Op2Expr _ e1 BiCons e2) = g e2 >>| g e1
+ >>| tell [Instr "sth" [] ""]
+ >>| tell [Instr "ajs" [Lit -1] ""]
+ >>| tell [Instr "sth" [] ""]
+ g (Op2Expr _ e1 op e2) = g e1 >>| g e2 >>| g op
+ g (TupleExpr _ (e1,e2)) = g e1
+ >>| g e2
+ >>| tell [Instr "stmh" [Lit 2] ""]
+ g (VarExpr _ (VarDef k fs)) = getAdressbook >>= \ab->case 'Map'.get k ab of
+ Just (ADDR t arity) = tell [Instr "ldl" [Lit t] ""] >>| mapM_ g fs >>| pure ()
+ Just (LAB l _ fn) = tell
+ [Instr "ldc" [Lit fn] ""
+ ,Instr "ldc" [Lit 0] ""
+ ,Instr "stmh" [Lit 2] ""]
+ g (FunExpr _ k es fs) = getAdressbook >>= \ab->case 'Map'.get k ab of
+ //Identifier points to function
+ Just (LAB l arity fn) = if (arity <> (length es))
+ //Function is not complete
+ ( tell
+ [Instr "ldc" [Lit fn] "Store function number"
+ ,Instr "sth" [] ""
+ ,Instr "ldc" [Lit $ length es] "Store arity"
+ ,Instr "sth" [] ""
+ ,Instr "ajs" [Lit -1] ""]
+ >>| mapM_ g es
+ >>| if (isEmpty es) (pure ()) (tell
+ [Instr "stmh" [Lit $ length es] "Store arguments"
+ ,Instr "ajs" [Lit -1] ""]))
+ //Function is complete
+ ( mapM_ g es
+ >>| jump "bsr" k
+ >>| tell
+ [Instr "ajs" [Lit $ ~(length es)] "Clean arguments"
+ ,Instr "ldr" [Raw "RR"] ""])
+ //Identifier points to variable, thus higher order function
+ Just (ADDR t arity) = if (arity <> (length es))
+ //Function is still not complete
+ ( fresh >>= \finish->fresh >>= \start->tell [
+ //Store function number
+ Instr "ldl" [Lit t] "STARTING HIGHER ORDER UPDATE"
+ ,Instr "ldh" [Lit 0] "get function number"
+ ,Instr "sth" [] "Store"
+ //Store function arity
+ ,Instr "ldl" [Lit t] "get pointer again"
+ ,Instr "ldh" [Lit 1] "get function arity"
+ ,Instr "ldc" [Lit $ length es] "add argument number"
+ ,Instr "add" [] "add"
+ ,Instr "sth" [] "Store"
+ ,Instr "ajs" [Lit -1] "Adjust pointer"
+ //load the arguments
+ ,Instr "ldl" [Lit t] ""
+ ,Instr "ldh" [Lit 1] "Load available arguments"
+ ,Instr "str" [Raw "R5"] "Store available args in register"
+ ,Instr "ldc" [Lit 0] "Store offset"
+ ,Instr "str" [Raw "R6"] "Store offset in register"
+ ,Lab start
+ ,Instr "ldr" [Raw "R5"] ""
+ ,Instr "ldc" [Lit 0] ""
+ ,Instr "eq" [] ""
+ ,Instr "brt" [L finish] "Done pushing arg, bye"
+ //Load heapadress
+ ,Instr "ldl" [Lit t] ""
+ ,Instr "ldr" [Raw "R6"] ""
+ ,Instr "add" [] "Corrected heapaddress"
+ ,Instr "ldh" [Lit 2] "Load argument"
+ ,Instr "sth" [] "And store it immediatly after"
+ //Decrease available arguments
+ ,Instr "ldr" [Raw "R5"] ""
+ ,Instr "ldc" [Lit 1] ""
+ ,Instr "sub" [] ""
+ ,Instr "str" [Raw "R5"] ""
+ //Increase available arguments
+ ,Instr "ldr" [Raw "R6"] ""
+ ,Instr "ldc" [Lit 1] ""
+ ,Instr "add" [] ""
+ ,Instr "str" [Raw "R6"] ""
+ ,Instr "bra" [L start] ""
+ ,Lab finish
+ ]
+ >>| mapM_ g es
+ >>| tell
+ [Instr "stmh" [Lit $ length es] "Store extra args"
+ ,Instr "ajs" [Lit -1] ""]
+ )
+ //Function is complete
+ ( fresh >>= \finish->fresh >>= \start->tell [
+ Instr "ldl" [Lit t] "STARTING HIGHER ORDER CALL"
+ ,Instr "ldh" [Lit 1] "Load available arguments"
+ ,Instr "str" [Raw "R5"] "Store available args in register"
+ ,Instr "ldc" [Lit 0] "Store offset"
+ ,Instr "str" [Raw "R6"] "Store offset in register"
+
+ ,Lab start
+ ,Instr "ldr" [Raw "R5"] ""
+ ,Instr "ldc" [Lit 0] ""
+ ,Instr "eq" [] ""
+ ,Instr "brt" [L finish] "Done pushing arg, bye"
+ //Load heapadress
+ ,Instr "ldl" [Lit t] ""
+ ,Instr "ldr" [Raw "R6"] ""
+ ,Instr "add" [] "Corrected heapaddress"
+ ,Instr "ldh" [Lit 2] "Load argument"
+ //Decrease available arguments
+ ,Instr "ldr" [Raw "R5"] ""
+ ,Instr "ldc" [Lit 1] ""
+ ,Instr "sub" [] ""
+ ,Instr "str" [Raw "R5"] ""
+ //Increase available arguments
+ ,Instr "ldr" [Raw "R6"] ""
+ ,Instr "ldc" [Lit 1] ""
+ ,Instr "add" [] ""
+ ,Instr "str" [Raw "R6"] ""
+ ,Instr "bra" [L start] ""
+ ,Lab finish
+ ]
+ >>| mapM_ g es
+ >>| tell
+ [Instr "ldl" [Lit t] ""
+ ,Instr "ldh" [Lit 0] "Get function number"
+ ,Instr "str" [Raw "R5"] ""
+ ,Instr "bsr" [L "1func"] ""
+ ,Instr "ldr" [Raw "MP"] ""
+ ,Instr "ldc" [Lit t] ""
+ ,Instr "add" [] ""
+ ,Instr "str" [Raw "SP"] ""
+ ,Instr "ldr" [Raw "RR"] ""
+ ]
+ )
+ Nothing = liftT (Left $ Error "Undefined function!!!")
+
+jump :: String String -> Gen ()
+jump instr k = getAdressbook >>= \ab->case 'Map'.get k ab of
+ Nothing = liftT (Left $ Error $ concat ["PANIC: ", k, " not found as function"])
+ Just (LAB t _ _) = tell [Instr instr [L t] (k +++"()")]
+ Just (ADDR t arity) = abort "NO ADDRESS JUMPING FFS"