from Text import class Text(concat), instance Text String
import AST
-from parse import :: ParserOutput, :: Error
:: Gamma :== ('Map'.Map String Type, [String])
:: Env a :== StateT Gamma (Either SemError) a
Right ((vds, fds), gamma) = Right ((AST vds fds), gamma)
where
m :: Env ([VarDecl], [FunDecl])
- m = mapM semVarDecl vd >>= \vds ->
- mapM semFunDecl fd >>= \fds1 ->
- mapM semFunDecl fds1 >>= \fds2 ->
- pure (vds, fds2)
+ m = mapM semVarDecl vd >>= \vd1 ->
+ mapM semFunDecl fd >>= \fd1 ->
+ mapM semVarDecl vd1 >>= \vd2 ->
+ mapM semFunDecl fd1 >>= \fd2 ->
+ mapM semVarDecl vd2 >>= \vd3 ->
+ mapM semFunDecl fd2 >>= \fd3 ->
+ mapM semVarDecl vd3 >>= \vd4 ->
+ mapM semFunDecl fd3 >>= \fd4 -> //Dit is puur om te proberen
+ pure (vd4, fd4)
semFunDecl :: FunDecl -> Env FunDecl
semFunDecl fd=:(FunDecl p f args mt vds stmts) =
matchFunctions args ft >>= \tres->
mapM semVarDecl vds >>= \newvds->
mapM (checkStmt tres) stmts >>= \newstmts->
+ inferReturnType stmts >>= \returntype`->
+ unify returntype` tres >>= \returntype->
case mt of
- Nothing = inferReturnType stmts
- >>= \returntype->reconstructType args returntype
+ Nothing = reconstructType args tres
+ >>= \ftype`->recoverType ftype`
>>= \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)
+ FunDecl p f args (Just ftype) newvds newstmts)
+ Just t = restoreGamma gamma >>| updateFunType t returntype
+ >>= \tt-> pure (FunDecl p f args (Just tt) newvds newstmts)
+
+recoverType :: Type -> Env Type
+recoverType (IdType ident) = gets (\(st, r)->'Map'.get ident st)
+ >>= \mt->case mt of
+ Nothing = pure (IdType ident)
+ Just t = pure t
+recoverType (t1 ->> t2) = recoverType t1 >>= \t1`->recoverType t2
+ >>= \t2`->pure (t1` ->> t2`)
+recoverType t = pure t
+
+updateFunType :: Type Type -> Env Type
+updateFunType (t1 ->> t2) t3 = updateFunType t2 t3 >>= \t2`->pure $ t1 ->> t2`
+updateFunType t1 t2 = unify t1 t2
inferReturnType :: [Stmt] -> Env Type
inferReturnType [] = pure VoidType
-inferReturnType [ReturnStmt (Just t):rest] = typeExpr t
-inferReturnType [ReturnStmt _:rest] = pure VoidType
+inferReturnType [ReturnStmt (Just t):rest] = typeExpr t
+ >>= \tx->inferReturnType rest >>= \ty->unify tx ty
+inferReturnType [ReturnStmt _:rest] =
+ inferReturnType rest >>= \tx-> unify VoidType tx
inferReturnType [_:rest] = inferReturnType rest
reconstructType :: [String] Type -> Env Type
(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 [] (_ ->> _) = liftT $ Left $
+ ArgumentMisMatchError zero "Not enough arguments"
+matchFunctions _ (VoidType ->> _) = liftT $ Left $
+ ArgumentMisMatchError zero "Void can't be a non return type"
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"
+matchFunctions _ t = liftT $ Left $
+ ArgumentMisMatchError zero "Too much argumnts"
semVarDecl :: VarDecl -> Env VarDecl
semVarDecl (VarDecl pos type ident ex) = unify type ex
Just t = unify t fs
typeOp2 :: Expr Expr Op2 [Type] Type -> Env Type
typeOp2 e1 e2 op ts ret = typeExpr e1 >>= \t1-> typeExpr e2 >>= \t2->
- unify t1 t2 >>= \t3->if (isMember t3 ts) (pure ret)
+ unify t1 t2 >>= \t3->if (isMember t3 [IdType "":ts]) (pure ret)
(liftT $ Left $ OperatorError (extrPos e1) op t3)
buildFunctionType :: String [Expr] -> Env Type
// "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=:(IdType id) e = typeExpr e >>= \tex->unify t tex
+ >>= \type->putIdent id type >>| pure type
unify t e = StateT $ \s0 -> let res = runStateT m s0 in case res of
Left err = Left $ decErr e err
Right t = Right t //note, t :: (Type, Gamma)
unify (ListType t1) (ListType t2) = unify t1 t2 >>| (pure $ ListType t1)
unify (ta1 ->> ta2) (tb1 ->> tb2) = unify ta1 tb1 >>= \ta-> unify ta2 tb2
>>= \tb-> pure (ta ->> tb)
+ unify VoidType VoidType = pure VoidType
+ unify VoidType t = pure t
+ unify t VoidType = pure t
unify t1 t2 = liftT $ Left $ UnifyError zero t1 t2
instance zero Pos where
itupdate _ _ k = k
instance toString SemError where
- toString (ParseError p e) = concat [
- toString p,"SemError: ParseError: ", e]
- toString (Error e) = "SemError: " +++ e
- toString (UnifyError p t1 t2) = concat [
- toString p,
+ toString (ParseError p e) = concat [toString p,
+ "SemError: ParseError: ", e]
+ toString (UnifyError p t1 t2) = concat [ toString p,
"SemError: Cannot unify types. Expected: ",
toString t1, ". Given: ", toString t2]
- toString (FieldSelectorError p t fs) = concat [
- toString p,
+ toString (FieldSelectorError p t fs) = concat [ toString p,
"SemError: Cannot select ", toString fs, " from type: ",
toString t]
toString (OperatorError p o t) = concat [
toString t]
toString (UndeclaredVariableError p ident) = concat [
toString p, "SemError: identifier: ", ident, " undefined."]
+ toString (ArgumentMisMatchError p s) = concat [toString p,
+ "SemError: Argument mismatch: ", s]
+ toString (Error e) = "SemError: " +++ e
saveGamma :: Env Gamma
saveGamma = get