1{-# OPTIONS_GHC -Wall #-}
2module Type.Constrain.Expression where
4import Control.Arrow (second)
5import qualified Control.Monad as Monad
6import qualified Data.Map as Map
8import qualified AST.Expression.General as E
9import qualified AST.Expression.Canonical as Canonical
10import qualified AST.Literal as Lit
11import qualified AST.Pattern as P
12import qualified AST.Type as ST
13import qualified AST.Variable as V
14import qualified Reporting.Annotation as A
15import qualified Reporting.Error.Type as Error
16import qualified Reporting.Region as R
17import qualified Type.Constrain.Effects as Effects
18import qualified Type.Constrain.Literal as Literal
19import qualified Type.Constrain.Pattern as Pattern
20import qualified Type.Environment as Env
21import qualified Type.Fragment as Fragment
22import Type.Type hiding (Descriptor(..))
31constrain env annotatedExpr@(A.A region expression) tipe =
34 Env.getType env "List" <| t
38 Literal.constrain env region lit tipe
53 error "DANGER - Program AST nodes should not be in type inference."
55 E.SaveEnv moduleName effects ->
56 Effects.constrain env moduleName effects
58 E.GLShader _uid _src gltipe ->
63 Env.getType env "WebGL.Shader" <| a <| u <| v
66 Env.getType env (Lit.glTipeName glTipe)
68 makeRec accessor baseRec =
69 let decls = accessor gltipe
71 if Map.size decls == 0 then
74 record (Map.map glToType decls) baseRec
76 attribute = makeRec Lit.attribute attr
77 uniform = makeRec Lit.uniform unif
78 varying = makeRec Lit.varying (TermN EmptyRecord1)
80 return (CEqual Error.Shader region (shaderTipe attribute uniform varying) tipe)
83 return (CInstance region (V.toString var) tipe)
85 E.Range lowExpr highExpr ->
87 do lowCon <- constrain env lowExpr n
88 highCon <- constrain env highExpr n
92 , CEqual Error.Range region (list n) tipe
95 E.ExplicitList exprs ->
96 constrainList env region exprs tipe
98 E.Binop op leftExpr rightExpr ->
99 constrainBinop env region op leftExpr rightExpr tipe
101 E.Lambda pattern body ->
104 do fragment <- Pattern.constrain env pattern argType
105 bodyCon <- constrain env body resType
107 ex (Fragment.vars fragment)
108 (CLet [monoscheme (Fragment.typeEnv fragment)]
109 (Fragment.typeConstraint fragment /\ bodyCon)
111 return $ con /\ CEqual Error.Lambda region (argType ==> resType) tipe
115 (f:args) = E.collectApps annotatedExpr
117 constrainApp env region f args tipe
119 E.If branches finally ->
120 constrainIf env region branches finally tipe
122 E.Case expr branches ->
123 constrainCase env region expr branches tipe
126 do vars <- Monad.forM exprs $ \_ -> mkVar Nothing
127 let pairs = zip exprs (map VarN vars)
128 (ctipe, cs) <- Monad.foldM step (tipe, CTrue) (reverse pairs)
129 return $ ex vars (cs /\ CInstance region name ctipe)
132 do c' <- constrain env e x
133 return (x ==> t, c /\ c')
135 E.Access expr label ->
137 constrain env expr (record (Map.singleton label tipe) t)
139 E.Update expr fields ->
141 do oldVars <- mapM (\_ -> mkVar Nothing) fields
142 let oldFields = Map.fromList (zip (map fst fields) (map VarN oldVars))
143 cOld <- ex oldVars <$> constrain env expr (record oldFields t)
145 newVars <- mapM (\_ -> mkVar Nothing) fields
146 let newFields = Map.fromList (zip (map fst fields) (map VarN newVars))
147 let cNew = CEqual Error.Record region (record newFields t) tipe
149 cs <- Monad.zipWithM (constrain env) (map snd fields) (map VarN newVars)
151 return $ cOld /\ ex newVars (CAnd (cNew : cs))
154 do vars <- Monad.forM fields (\_ -> mkVar Nothing)
160 let fields' = Map.fromList (zip (map fst fields) (map VarN vars))
161 let recordType = record fields' (TermN EmptyRecord1)
162 return (ex vars (CAnd (fieldCons ++ [CEqual Error.Record region recordType tipe])))
165 do bodyCon <- constrain env body tipe
167 (Info schemes rqs fqs headers c2 c1) <-
170 (Info [] [] [] Map.empty CTrue CTrue)
171 (concatMap expandPattern defs)
174 [ Scheme rqs fqs (CLet [monoscheme headers] c2) headers ]
176 return $ CLet schemes (CLet letScheme (c1 /\ bodyCon))
190constrainApp env region f args tipe =
191 do funcVar <- mkVar Nothing
192 funcCon <- constrain env f (VarN funcVar)
194 (vars, argCons, numberOfArgsCons, argMatchCons, _, returnVar) <-
195 argConstraints env maybeName region (length args) funcVar 1 args
198 CEqual (Error.Function maybeName) region (VarN returnVar) tipe
200 return $ ex (funcVar : vars) $
201 CAnd (funcCon : argCons ++ numberOfArgsCons ++ argMatchCons ++ [returnCon])
205 A.A _ (E.Var canonicalName) ->
220 -> IO ([Variable], [TypeConstraint], [TypeConstraint], [TypeConstraint], Maybe R.Region, Variable)
221argConstraints env name region totalArgs overallVar index args =
224 return ([], [], [], [], Nothing, overallVar)
226 expr@(A.A subregion _) : rest ->
227 do argVar <- mkVar Nothing
228 argCon <- constrain env expr (VarN argVar)
229 argIndexVar <- mkVar Nothing
230 localReturnVar <- mkVar Nothing
232 (vars, argConRest, numberOfArgsRest, argMatchRest, restRegion, returnVar) <-
233 argConstraints env name region totalArgs localReturnVar (index + 1) rest
236 maybe subregion (R.merge subregion) restRegion
238 let numberOfArgsCon =
240 (Error.FunctionArity name (index - 1) totalArgs arityRegion)
242 (VarN argIndexVar ==> VarN localReturnVar)
247 (Error.UnexpectedArg name index totalArgs subregion)
253 ( argVar : argIndexVar : localReturnVar : vars
254 , argCon : argConRest
255 , numberOfArgsCon : numberOfArgsRest
256 , argMatchCon : argMatchRest
274constrainBinop env region op leftExpr@(A.A leftRegion _) rightExpr@(A.A rightRegion _) tipe =
275 do leftVar <- mkVar Nothing
276 rightVar <- mkVar Nothing
278 leftCon <- constrain env leftExpr (VarN leftVar)
279 rightCon <- constrain env rightExpr (VarN rightVar)
281 leftVar' <- mkVar Nothing
282 rightVar' <- mkVar Nothing
283 answerVar <- mkVar Nothing
285 let opType = VarN leftVar' ==> VarN rightVar' ==> VarN answerVar
288 ex [leftVar,rightVar,leftVar',rightVar',answerVar] $ CAnd $
291 , CInstance region (V.toString op) opType
292 , CEqual (Error.BinopLeft op leftRegion) region (VarN leftVar') (VarN leftVar)
293 , CEqual (Error.BinopRight op rightRegion) region (VarN rightVar') (VarN rightVar)
294 , CEqual (Error.Binop op) region (VarN answerVar) tipe
308constrainList env region exprs tipe =
309 do (exprInfo, exprCons) <-
310 unzip <$> mapM elementConstraint exprs
312 (vars, cons) <- pairCons region Error.ListElement varToCon exprInfo
314 return $ ex vars (CAnd (exprCons ++ cons))
316 elementConstraint expr@(A.A region' _) =
317 do var <- mkVar Nothing
318 con <- constrain env expr (VarN var)
319 return ( (var, region'), con )
322 CEqual Error.List region (Env.getType env "List" <| VarN var) tipe
326-- CONSTRAIN IF EXPRESSIONS
332 -> [(Canonical.Expr, Canonical.Expr)]
336constrainIf env region branches finally tipe =
337 do let (conditions, branchExprs) =
338 second (++ [finally]) (unzip branches)
340 (condVars, condCons) <-
341 unzip <$> mapM constrainCondition conditions
343 (branchInfo, branchExprCons) <-
344 unzip <$> mapM constrainBranch branchExprs
346 (vars,cons) <- branchCons branchInfo
348 return $ ex (condVars ++ vars) (CAnd (condCons ++ branchExprCons ++ cons))
351 Env.getType env "Bool"
353 constrainCondition condition@(A.A condRegion _) =
354 do condVar <- mkVar Nothing
355 condCon <- constrain env condition (VarN condVar)
356 let boolCon = CEqual Error.IfCondition condRegion (VarN condVar) bool
357 return (condVar, CAnd [ condCon, boolCon ])
359 constrainBranch expr@(A.A branchRegion _) =
360 do branchVar <- mkVar Nothing
361 exprCon <- constrain env expr (VarN branchVar)
363 ( (branchVar, branchRegion)
367 branchCons branchInfo =
369 [(thenVar, _), (elseVar, _)] ->
372 , [ CEqual Error.IfBranches region (VarN thenVar) (VarN elseVar)
378 pairCons region Error.MultiIfBranch varToCon branchInfo
381 CEqual Error.If region (VarN var) tipe
385-- CONSTRAIN CASE EXPRESSIONS
392 -> [(P.Canonical, Canonical.Expr)]
395constrainCase env region expr branches tipe =
396 do exprVar <- mkVar Nothing
397 exprCon <- constrain env expr (VarN exprVar)
399 (branchInfo, branchExprCons) <-
400 unzip <$> mapM (branch (VarN exprVar)) branches
402 (vars, cons) <- pairCons region Error.CaseBranch varToCon branchInfo
404 return $ ex (exprVar : vars) (CAnd (exprCon : branchExprCons ++ cons))
406 branch patternType (pattern, branchExpr@(A.A branchRegion _)) =
407 do branchVar <- mkVar Nothing
408 fragment <- Pattern.constrain env pattern patternType
409 branchCon <- constrain env branchExpr (VarN branchVar)
411 ( (branchVar, branchRegion)
412 , CLet [Fragment.toScheme fragment] branchCon
416 CEqual Error.Case region tipe (VarN var)
427 , _region :: R.Region
433 -> (Int -> R.Region -> Error.Hint)
434 -> (Variable -> TypeConstraint)
435 -> [(Variable, R.Region)]
436 -> IO ([Variable], [TypeConstraint])
437pairCons region pairHint varToCon items =
439 pairToCon (Pair index var1 var2 subregion) =
440 CEqual (pairHint index subregion) region (VarN var1) (VarN var2)
442 case collectPairs 2 items of
444 do var <- mkVar Nothing
445 return ([var], [varToCon var])
448 return (map fst items, map pairToCon pairs ++ [varToCon var])
451collectPairs :: Int -> [(Variable, R.Region)] -> Maybe ([Pair], Variable)
452collectPairs index items =
460 (var,_) : rest@((var',region) : _) ->
461 do (pairs, summaryVar) <- collectPairs (index+1) rest
462 return (Pair index var var' region : pairs, summaryVar)
469expandPattern :: Canonical.Def -> [Canonical.Def]
470expandPattern def@(Canonical.Def facts lpattern expr maybeType) =
472 (A.A patternRegion pattern) =
480 mainDef : map toDef vars
483 P.boundVarList lpattern
489 A.A patternRegion (P.Var name)
492 A.A patternRegion (E.localVar name)
495 Canonical.Def facts (pvar combinedName) expr maybeType
500 E.Case (localVar combinedName) [(lpattern, localVar name)]
502 Canonical.Def facts (pvar name) (A.A patternRegion extract) Nothing
506-- CONSTRAIN DEFINITIONS
510 { iSchemes :: [TypeScheme]
511 , iRigid :: [Variable]
512 , iFlex :: [Variable]
513 , iHeaders :: Map.Map String (A.Located Type)
514 , iC2 :: TypeConstraint
515 , iC1 :: TypeConstraint
519constrainDef :: Env.Environment -> Info -> Canonical.Def -> IO Info
520constrainDef env info (Canonical.Def _ (A.A patternRegion pattern) expr maybeTipe) =
521 let qs = [] -- should come from the def, but I'm not sure what would live there...
523 case (pattern, maybeTipe) of
524 (P.Var name, Just (A.A typeRegion tipe)) ->
525 constrainAnnotatedDef env info qs patternRegion typeRegion name expr tipe
527 (P.Var name, Nothing) ->
528 constrainUnannotatedDef env info qs patternRegion name expr
531 error "canonical definitions must not have complex patterns as names in the contstraint generation phase"
544constrainAnnotatedDef env info qs patternRegion typeRegion name expr tipe =
545 do -- Some mistake may be happening here. Currently, qs is always [].
546 rigidVars <- mapM mkRigid qs
548 flexiVars <- mapM mkNamedVar qs
550 let env' = Env.addValues env (zip qs flexiVars)
552 (vars, typ) <- Env.instantiateType env tipe Map.empty
556 { _rigidQuantifiers = []
557 , _flexibleQuantifiers = flexiVars ++ vars
558 , _constraint = CTrue
559 , _header = Map.singleton name (A.A patternRegion typ)
563 defCon <- constrain env' expr (VarN var)
565 CEqual (Error.BadTypeAnnotation name) typeRegion typ (VarN var)
568 { iSchemes = scheme : iSchemes info
569 , iC1 = iC1 info /\ ex [var] (defCon /\ fl rigidVars annCon)
573constrainUnannotatedDef
581constrainUnannotatedDef env info qs patternRegion name expr =
582 do -- Some mistake may be happening here. Currently, qs is always [].
583 rigidVars <- mapM mkRigid qs
589 let env' = Env.addValues env (zip qs rigidVars)
591 con <- constrain env' expr tipe
594 { iRigid = rigidVars ++ iRigid info
595 , iFlex = v : iFlex info
596 , iHeaders = Map.insert name (A.A patternRegion tipe) (iHeaders info)
597 , iC2 = con /\ iC2 info
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list