@@ -7,8 +7,8 @@ data LVar = Loc Int | Glob Name
8data LExp = LV LVar
8data LExp = LV LVar
9 | LApp Name [LExp]
9 | LApp Name [LExp]
10− | LLet LVar LExp LExp
10+ | LLet Name LExp LExp -- name just for pretty printing
11− | LCon Int [LExp]
11+ | LCon Int Name [LExp]
12 | LCase LExp [LAlt]
12 | LCase LExp [LAlt]
13 | LConst Const
13 | LConst Const
14 | LOp PrimFn [LExp]
14 | LOp PrimFn [LExp]
@@ -29,5 +29,71 @@ data LDecl = LFun Name [Name] LExp -- name, arg names, definition
30type LDefs = Ctxt LDecl
30type LDefs = Ctxt LDecl
32−-- TODO: Add constructor tags, then scope and arity checker.
32+-- TODO: scope and arity checker.
34+addTags :: [(Name, LDecl)] -> [(Name, LDecl)]
36+ where tag i ((n, LConstructor n' t a) : as)
37+ = (n, LConstructor n' i a) : tag (i + 1) as
38+ tag i (x : as) = x : tag i as
41+checkDefs :: LDefs -> [(Name, LDecl)] -> TC [(Name, LDecl)]
42+checkDefs ctxt [] = return []
43+checkDefs ctxt (con@(n, LConstructor _ _ _) : xs) = do xs' <- checkDefs ctxt xs
45+checkDefs ctxt ((n, LFun n' args exp) : xs)
46+ = do exp' <- scopecheck ctxt (zip args [0..]) exp
47+ xs' <- checkDefs ctxt xs
48+ return ((n, LFun n' args exp') : xs')
50+scopecheck :: LDefs -> [(Name, Int)] -> LExp -> TC LExp
51+scopecheck ctxt env tm = sc env tm where
53+ = case lookup n (reverse env) of -- most recent first
54+ Just i -> return (LV (Loc i))
55+ Nothing -> case lookupCtxt Nothing n ctxt of
56+ [LConstructor _ i ar] ->
57+ if ar == 0 then return (LCon i n [])
58+ else fail $ "Codegen error: Constructor " ++ show n ++
59+ " has arity " ++ show ar
60+ [_] -> return (LV (Glob n))
61+ [] -> fail $ "Codegen error: No such variable " ++ show n
63+ = do args' <- mapM (sc env) args
64+ case lookupCtxt Nothing f ctxt of
65+ [LConstructor n tag ar] ->
66+ if (ar == length args)
67+ then return $ LCon tag n args'
68+ else fail $ "Codegen error: Constructor " ++ show f ++
69+ " has arity " ++ show ar
70+ [_] -> return $ LApp f args'
71+ [] -> fail $ "Codegen error: No such variable " ++ show f
72+ sc env (LCase e alts)
74+ alts' <- mapM (scalt env) alts
75+ return (LCase e' alts')
78+ e' <- sc (env ++ [(n, length env)]) e
79+ return (LLet n v' e')
80+ sc env (LOp prim args)
81+ = do args' <- mapM (sc env) args
82+ return (LOp prim args')
85+ scalt env (LConCase i n args e)
86+ = do let env' = env ++ zip args [length env..]
87+ tag <- case lookupCtxt Nothing n ctxt of
88+ [LConstructor _ i ar] ->
89+ if (length args == ar) then return i
90+ else fail $ "Codegen error: Constructor " ++ show n ++
91+ " has arity " ++ show ar
92+ _ -> fail $ "Codegen error: No constructor " ++ show n
94+ return (LConCase tag n args e')
95+ scalt env (LConstCase c e) = do e' <- sc env e
96+ return (LConstCase c e')
97+ scalt env (LDefaultCase e) = do e' <- sc env e
98+ return (LDefaultCase e')