X-Git-Url: https://git.martlubbers.net/?a=blobdiff_plain;f=gen.icl;h=4bf1bb8fda6853ac980fbf107d0778460c521db6;hb=a961d52fe0e9269af7d5581e07155f6701c09dbc;hp=c8b45d3ab0415ef5863e683e040ec14d25ae4c37;hpb=bc78930bacf1a3b835acf68889f178600af0e5d4;p=cc1516.git diff --git a/gen.icl b/gen.icl index c8b45d3..4bf1bb8 100644 --- a/gen.icl +++ b/gen.icl @@ -1,12 +1,12 @@ implementation module gen - import StdMisc import StdList import StdOverloaded import StdString -from StdFunc import id +from StdFunc import id, const import StdTuple +import StdEnum import Data.Func import qualified Data.Map as Map @@ -14,64 +14,189 @@ import Data.List import Data.Either import Data.Tuple import Data.Functor +import Data.Monoid +import Data.Maybe import Control.Applicative import Control.Monad -import Control.Monad.State import Control.Monad.Trans from Text import class Text(concat), instance Text String import AST +import RWST -//Instruction is an instruction, with possible arguments and a possible comment -//Or is a label +TRUE :== -1 +FALSE :== 0 :: Instr = Instr String [Arg] String - | Lab String + | Lab Label :: Label :== String -:: Arg = L Label | Lit Int +:: Arg = L Label | Lit Int | Raw String :: SSMProgram :== [Instr] - - -gen :: AST -> String -gen _ = toString [Lab "Test" - ,Instr "ldc" [Lit 1] "Eerste instructie" - ,Instr "ldc" [Lit 2] "Tweede instructie"] - - -//Scrap this, we'll need shared state when generating -//i.e. to figure out the positions of vars relative to the -//SP/MP/whatever or in which register they are -//and to supply with fresh labels - -//The generation monad :: GenError = Error String -:: GenMap :== 'Map'.Map String LoadPlace -:: LoadPlace = LDA Int | LDC Int | LDH Int | LDL Int - | LDR Int | LDS Int -:: Gen a :== StateT (GenMap, [Label]) (Either GenError) a - -genMap :: Gen GenMap -genMap = gets fst - -class g a :: a -> Gen SSMProgram +:: Addressbook :== 'Map'.Map String Address +:: Address = LAB String | ADDR Int +:: Gen a :== RWST () SSMProgram (Addressbook, [Label]) (Either GenError) a + +labelStream :: [Label] +labelStream = ["lbl_" +++ toString i\\i<-[1..]] + +gen :: AST -> Either String String +gen (AST fds) = case evalRWST prog () ('Map'.newMap, labelStream) of + Left (Error e) = Left e + Right (_, p) = Right $ toString p + where + prog = tell [Instr "bra" [L "main"] ""] >>| mapM_ g fds + +//Current issues: +//All VarDecls are added as function, how to deal with assignments? +// (And when we deal with assignments, how to deal with assignments to higher order functions?) +//Dealing with arguments +//Dealing with types that do not fit on the Stack +// Probably completely change LoadPlace to a Type and a position relative to *something* +// And where the type determines if this position is a pointer to the heap or an +// unboxed value + +//helper functions for the gen monad +getAdressbook :: Gen Addressbook +getAdressbook = gets fst + +updateAdressbook :: (Addressbook -> Addressbook) -> Gen Addressbook +updateAdressbook f = modify (appFst f) >>| getAdressbook + +extend :: String Address Addressbook -> Addressbook +extend k pl g = 'Map'.put k pl g + +fresh :: Gen Label +fresh = gets snd >>= \vars-> + modify (appSnd $ const $ tail vars) >>| + pure (head vars) + +class g a :: a -> Gen () +// +instance g Op1 where + g UnNegation = tell [Instr "not" [] ""] + g UnMinus = tell [Instr "neg" [] ""] + +instance g Op2 where + g o = tell [Instr s [] ""] + where + s = case o of + BiPlus = "add" + BiMinus = "sub" + BiTimes = "mul" + BiDivide = "div" + BiMod = "mod" + BiEquals = "eq" + BiLesser = "lt" + BiGreater = "gt" + BiLesserEq = "le" + BiGreaterEq = "ge" + BiUnEqual = "ne" + BiAnd = "and" + BiOr = "or" + BiCons = abort "Shit, Cons, how to deal with this?" instance g Expr where - g (VarExpr _ (VarDef k fs)) = pure <$> load k //note: pure is pure for list, i.e. [] - -load :: String -> Gen Instr -load k = genMap >>= \g-> case 'Map'.member k g of - False = liftT (Left $ Error $ concat ["PANIC: ", k, " not found in variable mapping"]) - True = loadP $ 'Map'.find k g - -loadP :: LoadPlace -> Gen Instr -loadP pl = dec pl >>= \(instr, arg)-> pure $ Instr instr [arg] "" -where - dec (LDA i) = pure ("lda", Lit i) - dec (LDC i) = pure ("ldc", Lit i) - dec (LDH i) = pure ("ldh", Lit i) - dec (LDL i) = pure ("ldl", Lit i) - dec (LDR i) = pure ("ldr", Lit i) - dec (LDS i) = pure ("lds", Lit i) - dec _ = liftT (Left $ Error "PANIC: trying to load non adres") +// g (VarExpr _ (VarDef k fs)) = load k >>= \instr-> tell [instr] //note: pure is pure for list, i.e. [] + 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 + >>| tell [Instr "sth" [] ""] + >>| g e2 + >>| tell [Instr "sth" [] ""] + >>| tell [Instr "ajs" [Lit -1] ""] + g _ = abort "hoi" + g (FunExpr _ k es fs) = abort "FunExpr unsupported modderfokker" + // mapM g es >>| //put all arguments on the stack (todo: fix argument handling!) + // jump "bsr" k >>= \instr-> + // tell [instr] >>| //actually branch to function + // tell [Instr "ldr" [Raw "RR"] ""] //push return value on stack, todo: check for VOID +// +//instance g Stmt where +// g (IfStmt cond th el) = +// fresh >>= \elseLabel-> +// fresh >>= \endLabel-> +// g cond >>| +// tell [Instr "brf" [L elseLabel] "branch else"] >>| +// mapM_ g th >>| +// tell [Instr "bra" [L endLabel] "branch end if"] >>| +// tell [Lab elseLabel] >>| +// mapM_ g el >>| +// tell [Lab endLabel] +// g (WhileStmt cond th) = +// fresh >>= \startLabel-> +// fresh >>= \endLabel -> +// tell [Lab startLabel] >>| +// g cond >>| +// tell [Instr "brf" [L endLabel] "branch end while"] >>| +// mapM_ g th >>| +// tell [Instr "bra" [L startLabel] "branch start while"] >>| +// tell [Lab endLabel] +// g (AssStmt (VarDef k fs) e) = +// g e >>| +// abort "Shit, an assignment, figure out something with storing vars or something" +// //vars will be on stack in locals (possible pointers to heap) +// g (FunStmt _ _) = abort "CodeGen, FunStmt unused" //not used +// g (ReturnStmt Nothing) = tell [Instr "ret" [] ""] //NOTE! Assumes only return address on stack, safe? +// g (ReturnStmt (Just e)) = +// g e >>| +// tell [Instr "str" [Raw "RR"] ""] >>| +// g (ReturnStmt Nothing) + +instance g VarDecl where + g (VarDecl _ Nothing _ _) = liftT (Left $ Error "PANIC: untyped vardecl") + g (VarDecl _ (Just t) k e) = g e +// TupleType (t1, t2) = g e +// ListType t = abort "listtype" +// IdType _ = liftT (Left $ Error "PANIC: unresolved typevariable") +// t1 ->> t2 = abort "funtype" +// VoidType = liftT (Left $ Error "PANIC: Void vardecl") +// _ = g e + +instance g FunDecl where + g (FunDecl _ k _ _ vds stms) = + //varDecls can call the enclosing function, so first reserve a label for it + updateAdressbook (extend k (LAB k)) >>| + tell [Lab k] >>| + //then generate functions for the VarDecls + getAdressbook >>= \oldMap -> + mapM_ g vds >>| + //then the main function +// mapM_ g stms >>| + updateAdressbook (const oldMap) >>| pure () +// +//load :: String -> Gen Instr +//load k = genMap >>= \g-> case 'Map'.member k g of +// False = liftT (Left $ Error $ concat ["PANIC: ", k, " not found in variable mapping"]) +// True = loadP $ 'Map'.find k g +// +//loadP :: LoadPlace -> Gen Instr +//loadP pl = dec pl >>= \(instr, arg)-> pure $ Instr instr [arg] "" +//where +// dec (LDA i) = pure ("lda", Lit i) +// dec (LDC i) = pure ("ldc", Lit i) +// dec (LDH i) = pure ("ldh", Lit i) +// dec (LDL i) = pure ("ldl", Lit i) +// dec (LDR i) = pure ("ldr", Lit i) +// dec (LDS i) = pure ("lds", Lit i) +// dec _ = liftT (Left $ Error "PANIC: trying to load non adres") +// +////Instruction (String), key of function to jump to +//jump :: String String -> Gen Instr +//jump instr k = genMap >>= \g-> case 'Map'.member k g of +// False = liftT (Left $ Error $ concat ["PANIC: ", k, " not found as function"]) +// True = dec ('Map'.find k g) >>= \lbl-> pure $ Instr instr [lbl] (k +++"()") +//where +// dec (FUNC l) = pure (L l) +// dec _ = liftT (Left $ Error "PANIC: trying to jump to non label") class print a :: a -> [String] @@ -85,9 +210,7 @@ instance print [Arg] where instance toString Arg where toString (L l) = l toString (Lit int) = toString int + toString (Raw s) = s instance toString SSMProgram where toString p = concat $ intersperse " " $ map (\i-> concat $ intersperse " " $ print i) p - -instance MonadTrans (StateT (GenMap,[Label])) where - liftT m = StateT \s-> m >>= \a-> return (a, s) \ No newline at end of file