X-Git-Url: https://git.martlubbers.net/?a=blobdiff_plain;f=sem.icl;h=8224a4f2a3da4a72f5cee69199337e42e1cc2ba1;hb=f5e125920d85bc53eda7b51f3f03e89fcaf3a0ce;hp=fc8614b0c2a462501b364cc5cb52ad855d85a03b;hpb=249bdba5121bca15012597a09e63a242781b001b;p=cc1516.git diff --git a/sem.icl b/sem.icl index fc8614b..8224a4f 100644 --- a/sem.icl +++ b/sem.icl @@ -9,10 +9,12 @@ import Control.Applicative import Control.Monad import Control.Monad.State import Control.Monad.Identity +import Math.Random import Control.Monad.Trans import StdMisc -from StdFunc import id, const +from StdFunc import id, const, o import StdString +import StdTuple import StdList from Text import class Text(concat), instance Text String @@ -20,8 +22,9 @@ from Text import class Text(concat), instance Text String import AST from parse import :: ParserOutput, :: Error -:: Gamma :== 'Map'.Map String Type +:: Gamma :== ('Map'.Map String Type, [String]) :: Env a :== StateT Gamma (Either SemError) a +//StateT (Gamma -> Either SemError (a, Gamma)) //we need to redefine this even though it is in Control.Monad.State instance MonadTrans (StateT Gamma) where @@ -29,23 +32,34 @@ instance MonadTrans (StateT Gamma) where get = gets id -instance toString SemError where - toString (ParseError p e) = concat [ - toString p,"SemError: ParseError: ", e] - toString (Error e) = "SemError: " +++ e - toString (UnifyErrorStub t1 t2) = toString (UnifyError {line=0,col=0} t1 t2) - toString (UnifyError p t1 t2) = concat [ - toString p, - "SemError: Cannot unify types. Expected: ", - toString t1, ". Given: ", toString t2] +getRandomStream :: Int -> [String] +getRandomStream i = genIdents $ filter (isAlpha o toChar) (genRandInt i) + where + genIdents r = let (ic, r) = splitAt 5 r in [toString ic: genIdents r] + +freshIdent :: Env String +freshIdent = get >>= \(st, [ident:rest])-> put (st, rest) + >>| case 'Map'.get ident st of + Nothing = pure ident + _ = freshIdent putIdent :: String Type -> Env Void -putIdent i t = gets ('Map'.get i) >>= \mt -> case mt of - Nothing = modify ('Map'.put i t) - Just t2 = unify t t2 >>= \t3-> modify ('Map'.put i t3) +putIdent i t = gets (\(st, r)->'Map'.get i st) >>= \mt -> case mt of + Nothing = modify (\(st, r)->('Map'.put i t st, r)) + Just t2 = unify t t2 >>= \t3-> modify (\(st, r)->('Map'.put i t3 st, r)) + +instance toString SemError where + toString (ParseError p e) = concat [ + toString p,"SemError: ParseError: ", e] + toString (Error e) = "SemError: " +++ e + toString (UnifyErrorStub t1 t2) = toString (UnifyError {line=0,col=0} t1 t2) + toString (UnifyError p t1 t2) = concat [ + toString p, + "SemError: Cannot unify types. Expected: ", + toString t1, ". Given: ", toString t2] sem :: AST -> SemOutput -sem (AST vd fd) = case evalStateT m 'Map'.newMap of +sem (AST vd fd) = case evalStateT m ('Map'.newMap, getRandomStream 0) of Left e = Left [e] Right (vds, fds) = Right (AST vds fds) where @@ -54,11 +68,6 @@ where mapM semFunDecl fd >>= \fds -> pure (vds, fds) -splitEithers :: [Either a b] -> Either [a] [b] -splitEithers [] = Right [] -splitEithers [Right x:xs] = splitEithers xs >>= \rest->Right [x:rest] -splitEithers xs = Left $ [x\\(Left x)<-xs] - semFunDecl :: FunDecl -> Env FunDecl semFunDecl f = pure f @@ -81,22 +90,26 @@ typeExpr (Op2Expr p e1 BiTimes e2) = unify IntType e1 >>| unify IntType e2 typeExpr (Op2Expr p e1 BiDivide e2) = unify IntType e1 >>| unify IntType e2 typeExpr (Op2Expr p e1 BiMod e2) = unify IntType e1 >>| unify IntType e2 //bool, char of int -typeExpr (Op2Expr p e1 BiEquals e2) = undef -typeExpr (Op2Expr p e1 BiUnEqual e2) = undef +typeExpr (Op2Expr p e1 BiEquals e2) = typeExpr e1 >>= \t1 -> unify t1 e2 + >>| pure BoolType //todo, actually check t1 in Char,Bool,Int +typeExpr (Op2Expr p e1 BiUnEqual e2) = typeExpr (Op2Expr p e1 BiEquals e2) //char of int -typeExpr (Op2Expr p e1 BiLesser e2) = undef -typeExpr (Op2Expr p e1 BiGreater e2) = undef -typeExpr (Op2Expr p e1 BiLesserEq e2) = undef -typeExpr (Op2Expr p e1 BiGreaterEq e2) = undef +typeExpr (Op2Expr p e1 BiLesser e2) = typeExpr e1 >>= \t1 -> unify t1 e2 + >>| pure BoolType //todo, actually check t1 in Char, Int +typeExpr (Op2Expr p e1 BiGreater e2) = typeExpr (Op2Expr p e1 BiLesser e2) +typeExpr (Op2Expr p e1 BiLesserEq e2) = typeExpr (Op2Expr p e1 BiLesser e2) +typeExpr (Op2Expr p e1 BiGreaterEq e2) = typeExpr (Op2Expr p e1 BiLesser e2) //bool -typeExpr (Op2Expr p e1 BiAnd e2) = undef -typeExpr (Op2Expr p e1 BiOr e2) = undef +typeExpr (Op2Expr p e1 BiAnd e2) = unify BoolType e1 >>| unify BoolType e2 +typeExpr (Op2Expr p e1 BiOr e2) = unify BoolType e1 >>| unify BoolType e2 //a -typeExpr (Op2Expr p e1 BiCons e2) = undef -//typeExpr (FunExpr Pos FunCall) = undef -//typeExpr (EmptyListExpr Pos) = undef -//typeExpr (VarExpr Pos VarDef) = undef //when checking var-expr, be sure to put the infered type - //in the context +typeExpr (Op2Expr p e1 BiCons e2) = typeExpr e1 >>= \t1-> typeExpr e2 + >>= \t2-> unify (ListType t1) t2 +//typeExpr (FunExpr p FunCall) = undef +typeExpr (EmptyListExpr p) = freshIdent >>= \frsh-> let t = IdType frsh in + putIdent frsh t >>| pure t +//typeExpr (VarExpr Pos VarDef) = undef //when checking var-expr, be sure to + //put the infered type in the context class unify a :: Type a -> Env Type @@ -118,6 +131,7 @@ instance unify Type where unify IntType IntType = pure IntType unify BoolType BoolType = pure BoolType unify CharType CharType = pure CharType + unify (ListType t1) (ListType t2) = unify t1 t2 unify t1 t2 = liftT $ Left $ UnifyError zero t1 t2 instance zero Pos where