X-Git-Url: https://git.martlubbers.net/?a=blobdiff_plain;f=gen.icl;h=be2c3ce839adfe58a2b7b68e8024879fcd1eafd6;hb=6f22285a7309dce751de352f92632ce2b40742ae;hp=c8b45d3ab0415ef5863e683e040ec14d25ae4c37;hpb=bc78930bacf1a3b835acf68889f178600af0e5d4;p=cc1516.git diff --git a/gen.icl b/gen.icl index c8b45d3..be2c3ce 100644 --- a/gen.icl +++ b/gen.icl @@ -7,6 +7,8 @@ import StdOverloaded import StdString from StdFunc import id import StdTuple +import StdEnum +from StdEnv import const import Data.Func import qualified Data.Map as Map @@ -14,48 +16,123 @@ 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 +//completely change to either Stack, Heap, Register? :: LoadPlace = LDA Int | LDC Int | LDH Int | LDL Int | LDR Int | LDS Int -:: Gen a :== StateT (GenMap, [Label]) (Either GenError) a + | FUNC Label +:: Gen a :== RWST Label SSMProgram (GenMap, [Label]) (Either GenError) a +labelStream :: [Label] +labelStream = map (\i-> concat ["lab_", toString i]) [1..] + +gen :: AST -> String +gen _ = prog + where + expr = (Op2Expr zero (Op1Expr zero UnMinus (IntExpr zero 4)) BiPlus (IntExpr zero 7)) + expr2 = (FunExpr zero "test" [IntExpr zero 4] []) + stmt = (IfStmt (BoolExpr zero True) [] []) + prog = case evalRWST (g stmt) "end" ('Map'.newMap, labelStream) of + Left (Error e) = abort e + Right (_, prog) = toString prog +//gen _ = toString [Lab "Test" +// ,Instr "ldc" [Lit 1] "Eerste instructie" +// ,Instr "ldc" [Lit 2] "Tweede instructie"] + + +//helper functions for the gen monad genMap :: Gen GenMap genMap = gets fst -class g a :: a -> Gen SSMProgram +fresh :: Gen Label +fresh = gets snd >>= \vars-> + modify (appSnd $ const $ tail vars) >>| + pure (head vars) + +class g a :: a -> Gen () instance g Expr where - g (VarExpr _ (VarDef k fs)) = pure <$> load k //note: pure is pure for list, i.e. [] + g (VarExpr _ (VarDef k fs)) = load k >>= \instr-> tell [instr] //note: pure is pure for list, i.e. [] + g (IntExpr _ i) = loadP (LDC i) >>= \instr-> tell [instr] + g (CharExpr _ c) = undef //how to deal with strings? + g (BoolExpr _ True) = loadP (LDC TRUE) >>= \instr-> tell [instr] + g (BoolExpr _ False) = loadP (LDC FALSE) >>= \instr-> tell [instr] + g (Op2Expr _ e1 op e2) = g e1 >>| g e2 >>| tell [Instr (op2ins op) [] ""] + g (Op1Expr _ UnNegation e) = g e >>| tell [Instr "not" [] ""] + g (Op1Expr _ UnMinus e) = g e >>| tell [Instr "neg" [] ""] + g (EmptyListExpr _) = abort "Shit, empty list expr" + g (TupleExpr p (e1,e2)) = abort "How to deal with tuples?" + g (FunExpr _ k es fs) = mapM g es >>| jump "bsr" k >>= \instr-> tell [instr] + //bra is probably not right, figure out function call way + +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" + g (FunStmt _ _) = abort "CodeGen FunStmt unused" //not used + g (ReturnStmt Nothing) = tell [Instr "ret" [] ""] + g (ReturnStmt (Just e)) = + g e >>| + tell [Instr "str" [Raw "RR"] ""] >>| + g (ReturnStmt Nothing) + + + +op2ins :: Op2 -> String +op2ins op = case op 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?" load :: String -> Gen Instr load k = genMap >>= \g-> case 'Map'.member k g of @@ -73,6 +150,15 @@ where 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] instance print Instr where @@ -87,7 +173,4 @@ instance toString Arg where toString (Lit int) = toString int 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 + toString p = concat $ intersperse " " $ map (\i-> concat $ intersperse " " $ print i) p \ No newline at end of file