X-Git-Url: https://git.martlubbers.net/?a=blobdiff_plain;f=sem.icl;h=a041cee3215065f1210481973b65b49cf02dff12;hb=8259ed46f53f70bc732ce8756ddf2b6f000df6a4;hp=addadad6c3f33fdd3bcc0255d3d582ea0c75f1b5;hpb=1c2e08dc9d18c9ffb2b26ef936a407a813e4822e;p=cc1516.git diff --git a/sem.icl b/sem.icl index addadad..a041cee 100644 --- a/sem.icl +++ b/sem.icl @@ -3,6 +3,7 @@ implementation module sem import qualified Data.Map as Map from Data.Func import $ import Data.Maybe +import Data.Void import Data.Either import Data.Functor import Control.Applicative @@ -40,19 +41,47 @@ sem (AST vd fd) = case runStateT m ('Map'.newMap, getRandomStream 1) of where m :: Env ([VarDecl], [FunDecl]) m = mapM semVarDecl vd >>= \vds -> - mapM semFunDecl fd >>= \fds -> - pure (vds, fds) + mapM semFunDecl fd >>= \fds1 -> + mapM semFunDecl fds1 >>= \fds2 -> + pure (vds, fds2) semFunDecl :: FunDecl -> Env FunDecl semFunDecl fd=:(FunDecl p f args mt vds stmts) = - saveGamma >>= \gamma -> (case mt of - Nothing = let t = IdType f in putIdent f t >>| pure t + Nothing = genType args >>= \infft->putIdent f infft >>| pure infft Just t = putIdent f t >>| pure t) >>= \ft -> - mapM_ (\a-> putIdent a (IdType <$> freshIdent)) args >>| - mapM_ semVarDecl vds >>| - mapM_ (checkStmt $ resultType ft) stmts >>| - restoreGamma gamma >>| pure fd + saveGamma >>= \gamma -> + matchFunctions args ft >>= \tres-> + mapM semVarDecl vds >>= \newvds-> + mapM (checkStmt tres) stmts >>= \newstmts-> + pure IntType >>= \returntype-> + case mt of + Nothing = reconstructType args returntype + >>= \ftype->restoreGamma gamma + >>| putIdent f ftype >>| pure ( + FunDecl p f args (Just ftype) newvds newstmts) + Just t = restoreGamma gamma + >>| pure (FunDecl p f args mt newvds newstmts) + +reconstructType :: [String] Type -> Env Type +reconstructType [] t = pure t +reconstructType [x:xs] t = gets (\(st, r)->'Map'.get x st) + >>= \mtype->case mtype of + Nothing = liftT $ Left $ Error "Not used ????" + Just type = reconstructType xs t >>= \resttype->pure (type ->> resttype) + +genType :: [String] -> Env Type +genType [] = freshIdent >>= \fi->pure $ IdType fi +genType [x:xs] = liftM2 (->>) (freshIdent >>= \fi->pure $ IdType fi) + (genType xs) + +matchFunctions :: [String] Type -> Env Type +matchFunctions [] (_ ->> _) = liftT $ Left $ Error "Not enough arguments" +matchFunctions _ (VoidType ->> _) = liftT $ Left $ Error "Cannot have a void type in the middle of the function definition" +matchFunctions [x:xs] (t1 ->> t2) = + modify (\(st, r)->('Map'.put x t1 st, r)) >>| matchFunctions xs t2 +matchFunctions [] t = pure t +matchFunctions _ t = liftT $ Left $ Error "Too much argumnts" semVarDecl :: VarDecl -> Env VarDecl semVarDecl (VarDecl pos type ident ex) = unify type ex @@ -63,7 +92,10 @@ checkStmt t (IfStmt c st se) = unify BoolType c >>| mapM (checkStmt t) st >>= \st1-> mapM (checkStmt t) se >>= \se1-> pure (IfStmt c st1 se1) checkStmt t w=:(WhileStmt c et) = unify BoolType c >>| mapM (checkStmt t) et >>= \et1-> pure w -checkStmt t (AssStmt (VarDef ident fs) e) = undef +checkStmt t a=:(AssStmt (VarDef ident fs) e) = gets (\(st, r)->'Map'.get ident st) + >>= \mt->case mt of + Nothing = liftT $ Left $ UndeclaredVariableError zero ident + Just t = unify t fs >>= \t1 -> unify t1 e >>| pure a checkStmt t r=:(FunStmt (FunCall f es)) = typeFun f es >>| pure r checkStmt VoidType r=:(ReturnStmt Nothing) = pure r checkStmt t r=:(ReturnStmt (Just e)) = unify t e >>| pure r @@ -134,8 +166,8 @@ instance unify Expr where "Expression cannot be a higher order function. Yet..." unify VoidType e = liftT $ Left $ ParseError (extrPos e) "Expression cannot be a Void type." - unify (IdType _) e = liftT $ Left $ ParseError (extrPos e) - "Expression cannot be an polymorf type." +// unify (IdType _) e = liftT $ Left $ ParseError (extrPos e) +// "Expression cannot be an polymorf type." unify VarType e = typeExpr e //we have to cheat to decorate the error, can be done nicer? unify t e = StateT $ \s0 -> let res = runStateT m s0 in case res of @@ -238,4 +270,4 @@ saveGamma :: Env Gamma saveGamma = get restoreGamma :: Gamma -> Env Void -restoreGamma g = put g \ No newline at end of file +restoreGamma (oldstate, _) = gets snd >>= \newr->put (oldstate, newr)