@@ -10,24 +10,23 @@ import Elara.Core.ANF qualified as ANF
10
10
11
11
import Data.Set qualified as Set
12
12
13
- import Data.Map qualified as Map
14
13
import Elara.AST.VarRef
15
- import Elara.Core (CoreExpr , Expr ( .. ), TyCon , Var (.. ), typeArity )
14
+ import Elara.Core (CoreExpr , Var (.. ))
16
15
import Elara.Core qualified as Core
17
16
import Elara.Core.Generic
18
17
import Elara.Core.Module
19
- import Elara.Core.ToANF (fromANF , fromANFAtom , fromANFCExpr )
18
+ import Elara.Core.ToANF (fromANF , fromANFAtom )
20
19
import Elara.Data.Pretty
21
20
import Elara.Error
22
21
import Elara.Prim.Core
23
22
import Polysemy
24
23
import Polysemy.Error
25
- import Polysemy.State (State , evalState , gets , modify )
24
+ import Polysemy.State (State , evalState , get , modify )
26
25
import Polysemy.State.Extra (locally , scoped )
27
26
import TODO (todo )
28
27
29
28
data TypeCheckError
30
- = UnboundVariable Var (Set. Set Var )
29
+ = UnboundVariable Var (Set. Set ( UnlocatedVarRef Text ) )
31
30
| TypeMismatch
32
31
{ expected :: Core. Type
33
32
, actual :: Core. Type
@@ -48,24 +47,33 @@ instance Pretty TypeCheckError
48
47
instance ReportableError TypeCheckError
49
48
50
49
data TcState = TcState
51
- { scope :: Set. Set Var
50
+ { scope :: Set. Set ( UnlocatedVarRef Text )
52
51
-- ^ The 'Var' already holds the variable's type so we don't need to track that.
53
52
-- However we do need to track scoping, as an optimisation could pull a variable out of scope
54
53
}
55
54
55
+ addToScope :: Var -> TcState -> TcState
56
+ addToScope (Id name _ _) s = s{scope = Set. insert name (scope s)}
57
+ addToScope _ s = s
58
+
59
+ isInScope :: Var -> TcState -> Bool
60
+ isInScope (Id name@ (Local _) _ _) s = Set. member name (scope s)
61
+ isInScope (Id (Global _) _ _) _ = True -- Global vars are always in scope
62
+ isInScope _ _ = False
63
+
56
64
typeCheckCoreModule :: Member (Error TypeCheckError ) r => CoreModule (Bind Var ANF. Expr ) -> Sem r ()
57
65
typeCheckCoreModule (CoreModule n m) = do
58
66
let initialState = TcState {scope = mempty }
59
67
60
68
_ <- evalState initialState $ do
61
69
for_ m $ \ case
62
70
CoreValue (NonRecursive (v, e)) -> scoped $ do
63
- modify (\ s -> s{scope = Set. insert v (scope s)} )
71
+ modify (addToScope v )
64
72
eType <- typeCheck e
65
73
pure ()
66
74
CoreValue (Recursive bs) -> scoped $ do
67
75
for_ bs $ \ (v, e) -> do
68
- modify (\ s -> s{scope = Set. insert v (scope s)} )
76
+ modify (addToScope v )
69
77
70
78
for_ bs $ \ (v, e) -> typeCheck e
71
79
CoreType _ -> pure ()
@@ -81,12 +89,12 @@ typeCheck (ANF.Let bind in') = do
81
89
case bind of
82
90
NonRecursive (v, e) -> do
83
91
eType <- typeCheckC e
84
- locally (( \ s -> s{scope = Set. insert v (scope s)}) ) $
92
+ locally (addToScope v ) $
85
93
typeCheck in'
86
- Recursive binds -> do
94
+ Recursive binds -> scoped $ do
87
95
let vars = map fst binds
88
- modify ( \ s -> s{scope = Set. union ( Set. fromList vars) (scope s)} )
89
- for_ binds $ \ (v , e) -> typeCheckC e
96
+ for_ vars $ \ v -> modify (addToScope v )
97
+ for_ binds $ \ (_ , e) -> typeCheckC e
90
98
typeCheck in'
91
99
typeCheck (ANF. CExpr cExp) = typeCheckC cExp
92
100
@@ -103,7 +111,7 @@ typeCheckC (ANF.App f x) = do
103
111
typeCheckC (ANF. AExpr aExp) = typeCheckA aExp
104
112
typeCheckC (ANF. Match e of' alts) = scoped $ do
105
113
eType <- typeCheckA e
106
- whenJust of' $ \ v -> modify (\ s -> s{scope = Set. insert v (scope s)} )
114
+ whenJust of' $ \ v -> modify (addToScope v )
107
115
altTypes <- for alts $ \ (con, bs, e) -> do
108
116
case con of
109
117
Core. DEFAULT -> do
@@ -138,16 +146,16 @@ typeCheckLit lit = case lit of
138
146
typeCheckA :: (Member (Error TypeCheckError ) r , Member (State TcState ) r ) => ANF. AExpr Var -> Sem r Core. Type
139
147
typeCheckA (ANF. Lit lit) = pure $ typeCheckLit lit
140
148
-- Globally qualified vars are always in scope
141
- typeCheckA (ANF. Var (Id (Global _) t _)) = pure t
142
149
typeCheckA (ANF. Var v) = do
143
- env <- gets scope
144
- case Set. member v env of
150
+ env <- get
151
+
152
+ case isInScope v env of
145
153
True -> pure (varType v)
146
- False -> throw $ UnboundVariable v env
154
+ False -> throw $ UnboundVariable v ( env. scope)
147
155
typeCheckA (ANF. Lam v body) = do
148
156
let t = varType v
149
157
150
- eType <- locally (\ s -> s{scope = Set. insert v (s . scope)} ) $ typeCheck body
158
+ eType <- locally (addToScope v ) $ typeCheck body
151
159
pure $ Core. FuncTy t eType
152
160
typeCheckA (ANF. TyApp e t) = do
153
161
eType <- typeCheckA e
0 commit comments