@@ -1,5 +1,4 @@
11{-# OPTIONS_GHC -Wall #-}
2−{-# LANGUAGE OverloadedStrings #-}
32module Type.Constrain.Expression
43 ( constrain
54 )
@@ -17,6 +16,7 @@ import qualified Reporting.Annotation as A
1716import qualified Reporting.Region as R
1817import Type.Constraint
1918import qualified Type.Constrain.Pattern as Pattern
19+import qualified Type.Instantiate as Instantiate
2020import Type.Type as Type hiding (Descriptor(..))
2121
2222
@@ -61,7 +61,7 @@ constrain rtv (A.A region expression) expectation =
6161
6262 Can.Int _ ->
6363 do var <- mkFlexNumber
64− return $ ex [var] $ CEqual region Number (VarN var) expectation
64+ return $ exists [var] $ CEqual region Number (VarN var) expectation
6565
6666 Can.Float _ ->
6767 return $ CEqual region Float Type.float expectation
@@ -74,16 +74,13 @@ constrain rtv (A.A region expression) expectation =
7474 let numberType = VarN numberVar
7575 numberCon <- constrain rtv expr (FromContext region Negate numberType)
7676 let negateCon = CEqual region Number numberType expectation
77− return $ ex [numberVar] $ CAnd [ numberCon, negateCon ]
77+ return $ exists [numberVar] $ CAnd [ numberCon, negateCon ]
7878
7979 Can.Binop op _ _ annotation leftExpr rightExpr ->
8080 constrainBinop rtv region op annotation leftExpr rightExpr expectation
8181
8282 Can.Lambda args _ body ->
83− do (lambdaType, resultType, scheme) <- Pattern.constrainArgs args
84− bodyCon <- constrain rtv body (NoExpectation resultType)
85− let lambdaCon = CEqual region Lambda lambdaType expectation
86− return $ CLet [scheme] $ CAnd [ bodyCon, lambdaCon ]
83+ constrainLambda rtv region args body expectation
8784
8885 Can.Call func args ->
8986 constrainCall rtv region func args expectation
@@ -95,13 +92,16 @@ constrain rtv (A.A region expression) expectation =
9592 constrainCase rtv region expr branches expectation
9693
9794 Can.Let def body ->
98− constrainDef rtv def =<< constrain rtv body expectation
95+ constrainDef rtv def
96+ =<< constrain rtv body expectation
9997
10098 Can.LetRec defs body ->
101− error "TODO let rec" defs body
99+ constrainRecursiveDefs rtv defs
100+ =<< constrain rtv body expectation
102101
103− Can.LetDestruct pattern destructors expr body ->
104− error "TODO let destruct" pattern destructors expr body
102+ Can.LetDestruct pattern _ expr body ->
103+ constrainDestruct rtv region pattern expr
104+ =<< constrain rtv body expectation
105105
106106 Can.Accessor field ->
107107 do extVar <- mkFlexVar
@@ -109,7 +109,7 @@ constrain rtv (A.A region expression) expectation =
109109 let extType = VarN extVar
110110 let fieldType = VarN fieldVar
111111 let recordType = RecordN (Map.singleton field fieldType) extType
112− return $ ex [ fieldVar, extVar ] $
112+ return $ exists [ fieldVar, extVar ] $
113113 CEqual region (Accessor field) (FunN recordType fieldType) expectation
114114
115115 Can.Access expr field ->
@@ -122,7 +122,7 @@ constrain rtv (A.A region expression) expectation =
122122 recordCon <-
123123 constrain rtv expr (FromContext region (RecordAccess field) recordType)
124124
125− return $ ex [ fieldVar, extVar ] $
125+ return $ exists [ fieldVar, extVar ] $
126126 CAnd
127127 [ recordCon
128128 , CEqual region (Access field) recordType expectation
@@ -145,6 +145,31 @@ constrain rtv (A.A region expression) expectation =
145145
146146
147147
148+-- CONSTRAIN LAMBDA
149+
150+
151+constrainLambda :: RTV -> R.Region -> [Can.Arg] -> Can.Expr -> Expectation -> IO Constraint
152+constrainLambda rtv region args body expectation =
153+ do (Args vars tipe resultType (Pattern.State headers pvars revCons)) <-
154+ constrainArgs args
155+
156+ bodyCon <-
157+ constrain rtv body (NoExpectation resultType)
158+
159+ return $ exists vars $
160+ CAnd
161+ [ CLet
162+ { _rigidVars = []
163+ , _flexVars = pvars
164+ , _header = headers
165+ , _headerCon = CAnd (reverse revCons)
166+ , _bodyCon = bodyCon
167+ }
168+ , CEqual region Lambda tipe expectation
169+ ]
170+
171+
172+
148173-- CONSTRAIN CALL
149174
150175
@@ -165,7 +190,7 @@ constrainCall rtv region func args expectation =
165190 let arityType = foldr FunN resultType argTypes
166191 let resultCon = CEqual region (CallResult maybeFuncName) resultType expectation
167192
168− return $ ex (funcVar:resultVar:argVars) $
193+ return $ exists (funcVar:resultVar:argVars) $
169194 CAnd
170195 [ funcCon
171196 , CBranch
@@ -196,7 +221,7 @@ constrainCallBackup rtv region maybeFuncName func args =
196221
197222 funcCon <- constrain rtv func (FromContext region BadArity arityType)
198223
199− return $ ex (resultVar:argVars) $ CAnd [ CAnd argCons, funcCon ]
224+ return $ exists (resultVar:argVars) $ CAnd [ CAnd argCons, funcCon ]
200225
201226
202227getFuncName :: Can.Expr -> Maybe FuncName
@@ -240,7 +265,7 @@ constrainBinop rtv region op annotation leftExpr rightExpr expectation =
240265 leftCon <- constrain rtv leftExpr (FromContext region (OpLeft op) leftType)
241266 rightCon <- constrain rtv rightExpr (FromContext region (OpRight op) rightType)
242267
243− return $ ex [ leftVar, rightVar, answerVar ] $
268+ return $ exists [ leftVar, rightVar, answerVar ] $
244269 CAnd
245270 [ opCon
246271 , leftCon
@@ -262,7 +287,7 @@ constrainList rtv region entries expectation =
262287 entryCons <-
263288 Index.indexedTraverse (constrainListEntry rtv region entryType) entries
264289
265− return $ ex [entryVar] $
290+ return $ exists [entryVar] $
266291 CAnd
267292 [ CAnd entryCons
268293 , CEqual region List listType expectation
@@ -303,7 +328,7 @@ constrainIf rtv region branches final expectation =
303328 branchCons <- Index.indexedForA exprs $ \index expr ->
304329 constrain rtv expr (FromContext region (IfBranch index) branchType)
305330
306− return $ ex [branchVar] $
331+ return $ exists [branchVar] $
307332 CAnd
308333 [ CAnd condCons
309334 , CAnd branchCons
@@ -328,7 +353,7 @@ constrainCase rtv region expr branches expectation =
328353 (PatternExpectation region (PCaseMatch index) ptrnType)
329354 (FromAnnotation name arity (TypedCaseBranch index) tipe)
330355
331− return $ ex [ptrnVar] $ CAnd (exprCon:branchCons)
356+ return $ exists [ptrnVar] $ CAnd (exprCon:branchCons)
332357
333358 _ ->
334359 do branchVar <- mkFlexVar
@@ -339,7 +364,7 @@ constrainCase rtv region expr branches expectation =
339364 (PatternExpectation region (PCaseMatch index) ptrnType)
340365 (FromContext region (CaseBranch index) branchType)
341366
342− return $ ex [ptrnVar,branchVar] $
367+ return $ exists [ptrnVar,branchVar] $
343368 CAnd
344369 [ exprCon
345370 , CAnd branchCons
@@ -349,9 +374,11 @@ constrainCase rtv region expr branches expectation =
349374
350375constrainCaseBranch :: RTV -> Can.CaseBranch -> PatternExpectation -> Expectation -> IO Constraint
351376constrainCaseBranch rtv (Can.CaseBranch pattern _ expr) pExpect bExpect =
352− do scheme <- Pattern.constrain pattern pExpect
353− constraint <- constrain rtv expr bExpect
354− return $ CLet [scheme] constraint
377+ do (Pattern.State headers pvars revCons) <-
378+ Pattern.add pattern pExpect Pattern.emptyState
379+
380+ CLet [] pvars headers (CAnd (reverse revCons))
381+ <$> constrain rtv expr bExpect
355382
356383
357384
@@ -369,7 +396,7 @@ constrainRecord rtv region fields expectation =
369396 let vars = Map.foldr (\(v,_,_) vs -> v:vs) [] dict
370397 let cons = Map.foldr (\(_,_,c) cs -> c:cs) [recordCon] dict
371398
372− return $ ex vars (CAnd cons)
399+ return $ exists vars (CAnd cons)
373400
374401
375402constrainField :: RTV -> Can.Expr -> IO (Variable, Type, Constraint)
@@ -403,7 +430,7 @@ constrainUpdate rtv region expr fields expectation =
403430 let vars = Map.foldr (\(v,_,_) vs -> v:vs) (sharedVar : Map.elems oldVars) newDict
404431 let cons = Map.foldr (\(_,_,c) cs -> c:cs) [newCon] newDict
405432
406− return $ ex vars (CAnd (oldCon:cons))
433+ return $ exists vars (CAnd (oldCon:cons))
407434
408435
409436
@@ -424,7 +451,7 @@ constrainTuple rtv region a b maybeC expectation =
424451 Nothing ->
425452 do let tupleType = TupleN aType bType Nothing
426453 let tupleCon = CEqual region Tuple tupleType expectation
427− return $ ex [ aVar, bVar ] $ CAnd [ aCon, bCon, tupleCon ]
454+ return $ exists [ aVar, bVar ] $ CAnd [ aCon, bCon, tupleCon ]
428455
429456 Just c ->
430457 do cVar <- mkFlexVar
@@ -435,7 +462,7 @@ constrainTuple rtv region a b maybeC expectation =
435462 let tupleType = TupleN aType bType (Just cType)
436463 let tupleCon = CEqual region Tuple tupleType expectation
437464
438− return $ ex [ aVar, bVar, cVar ] $ CAnd [ aCon, bCon, cCon, tupleCon ]
465+ return $ exists [ aVar, bVar, cVar ] $ CAnd [ aCon, bCon, cCon, tupleCon ]
439466
440467
441468
@@ -456,7 +483,7 @@ constrainShader region (Shader.Shader attributes uniforms varyings) expectation
456483 , toShaderRecord varyings EmptyRecordN
457484 ]
458485
459− return $ ex [ attrVar, unifVar ] $
486+ return $ exists [ attrVar, unifVar ] $
460487 CEqual region Shader shaderType expectation
461488
462489
@@ -481,33 +508,242 @@ glToType glType =
481508
482509
483510
484−-- CONSTRAIN LET
511+-- CONSTRAIN DESTRUCTURES
512+
513+
514+constrainDestruct :: RTV -> R.Region -> Can.Pattern -> Can.Expr -> Constraint -> IO Constraint
515+constrainDestruct rtv region pattern expr bodyCon =
516+ do patternVar <- mkFlexVar
517+ let patternType = VarN patternVar
518+
519+ (Pattern.State headers pvars revCons) <-
520+ Pattern.add pattern (NoPatternExpectation patternType) Pattern.emptyState
521+
522+ exprCon <-
523+ constrain rtv expr (FromContext region Destructure patternType)
524+
525+ return $ CLet [] pvars headers (CAnd (reverse (exprCon:revCons))) bodyCon
526+
527+
528+
529+-- CONSTRAIN DEF
485530
486531
487532constrainDef :: RTV -> Can.Def -> Constraint -> IO Constraint
488533constrainDef rtv def bodyCon =
489534 case def of
490535 Can.Def (A.A region name) args _ expr ->
491− do (lambdaType, resultType, scheme) <-
492− Pattern.constrainArgs args
493−
494− defCon <-
495− CLet [scheme] <$> constrain rtv expr (NoExpectation resultType)
496−
497− let headers = Map.singleton name (A.A region lambdaType)
498− return $ CLet [Scheme [] [] headers defCon] bodyCon
536+ do (Args vars tipe resultType (Pattern.State headers pvars revCons)) <-
537+ constrainArgs args
538+
539+ exprCon <-
540+ constrain rtv expr (NoExpectation resultType)
541+
542+ return $
543+ CLet
544+ { _rigidVars = []
545+ , _flexVars = vars
546+ , _header = Map.singleton name (A.A region tipe)
547+ , _headerCon =
548+ CLet
549+ { _rigidVars = []
550+ , _flexVars = pvars
551+ , _header = headers
552+ , _headerCon = CAnd (reverse revCons)
553+ , _bodyCon = exprCon
554+ }
555+ , _bodyCon = bodyCon
556+ }
499557
500558 Can.TypedDef (A.A region name) freeVars typedArgs _ expr srcResultType ->
501559 do let newNames = Map.difference freeVars rtv
502560 newRigids <- Map.traverseWithKey (\n _ -> nameToRigid n) newNames
503561 let newRtv = Map.union rtv (Map.map VarN newRigids)
504562
505− (lambdaType, resultType, scheme) <-
506− Pattern.constrainTypedArgs newRtv typedArgs srcResultType
563+ (TypedArgs tipe resultType (Pattern.State headers pvars revCons)) <-
564+ constrainTypedArgs newRtv name typedArgs srcResultType
507565
508566 let expectation = FromAnnotation name (length typedArgs) TypedBody resultType
509− defCon <-
510− CLet [scheme] <$> constrain newRtv expr expectation
567+ exprCon <-
568+ constrain newRtv expr expectation
569+
570+ return $
571+ CLet
572+ { _rigidVars = Map.elems newRigids
573+ , _flexVars = []
574+ , _header = Map.singleton name (A.A region tipe)
575+ , _headerCon =
576+ CLet
577+ { _rigidVars = []
578+ , _flexVars = pvars
579+ , _header = headers
580+ , _headerCon = CAnd (reverse revCons)
581+ , _bodyCon = exprCon
582+ }
583+ , _bodyCon = bodyCon
584+ }
585+
586+
587+
588+-- CONSTRAIN RECURSIVE DEFS
589+
590+
591+data Info =
592+ Info
593+ { _vars :: [Variable]
594+ , _cons :: [Constraint]
595+ , _headers :: Map.Map N.Name (A.Located Type)
596+ }
597+
598+
599+{-# NOINLINE emptyInfo #-}
600+emptyInfo :: Info
601+emptyInfo =
602+ Info [] [] Map.empty
603+
604+
605+constrainRecursiveDefs :: RTV -> [Can.Def] -> Constraint -> IO Constraint
606+constrainRecursiveDefs rtv defs bodyCon =
607+ recDefsHelp rtv defs bodyCon emptyInfo emptyInfo
608+
609+
610+recDefsHelp :: RTV -> [Can.Def] -> Constraint -> Info -> Info -> IO Constraint
611+recDefsHelp rtv defs bodyCon rigidInfo flexInfo =
612+ case defs of
613+ [] ->
614+ do let (Info rigidVars rigidCons rigidHeaders) = rigidInfo
615+ let (Info flexVars flexCons flexHeaders ) = flexInfo
616+ return $
617+ CLet rigidVars [] rigidHeaders CTrue $
618+ CLet [] flexVars flexHeaders (CLet [] [] flexHeaders CTrue (CAnd flexCons)) $
619+ CAnd [ CAnd rigidCons, bodyCon ]
620+
621+ def : otherDefs ->
622+ case def of
623+ Can.Def (A.A region name) args _ expr ->
624+ do let (Info flexVars flexCons flexHeaders) = flexInfo
625+
626+ (Args newFlexVars tipe resultType (Pattern.State headers pvars revCons)) <-
627+ argsHelp args (Pattern.State Map.empty flexVars [])
628+
629+ exprCon <-
630+ constrain rtv expr (NoExpectation resultType)
631+
632+ let defCon =
633+ CLet
634+ { _rigidVars = []
635+ , _flexVars = pvars
636+ , _header = headers
637+ , _headerCon = CAnd (reverse revCons)
638+ , _bodyCon = exprCon
639+ }
640+
641+ recDefsHelp rtv otherDefs bodyCon rigidInfo $
642+ Info
643+ { _vars = newFlexVars
644+ , _cons = defCon : flexCons
645+ , _headers = Map.insert name (A.A region tipe) flexHeaders
646+ }
647+
648+ Can.TypedDef (A.A region name) freeVars typedArgs _ expr srcResultType ->
649+ do let newNames = Map.difference freeVars rtv
650+ newRigids <- Map.traverseWithKey (\n _ -> nameToRigid n) newNames
651+ let newRtv = Map.union rtv (Map.map VarN newRigids)
652+
653+ (TypedArgs tipe resultType (Pattern.State headers pvars revCons)) <-
654+ constrainTypedArgs newRtv name typedArgs srcResultType
655+
656+ exprCon <-
657+ constrain newRtv expr $
658+ FromAnnotation name (length typedArgs) TypedBody resultType
659+
660+ let defCon =
661+ CLet
662+ { _rigidVars = []
663+ , _flexVars = pvars
664+ , _header = headers
665+ , _headerCon = CAnd (reverse revCons)
666+ , _bodyCon = exprCon
667+ }
668+
669+ let (Info rigidVars rigidCons rigidHeaders) = rigidInfo
670+ recDefsHelp rtv otherDefs bodyCon
671+ ( Info
672+ { _vars = Map.foldr (:) rigidVars newRigids
673+ , _cons = defCon : rigidCons
674+ , _headers = Map.insert name (A.A region tipe) rigidHeaders
675+ }
676+ )
677+ flexInfo
678+
679+
680+
681+-- CONSTRAIN ARGS
682+
683+
684+data Args =
685+ Args
686+ { _a_vars :: [Variable]
687+ , _a_type :: Type
688+ , _a_result :: Type
689+ , _a_state :: Pattern.State
690+ }
691+
692+
693+constrainArgs :: [Can.Arg] -> IO Args
694+constrainArgs args =
695+ argsHelp args Pattern.emptyState
696+
697+
698+argsHelp :: [Can.Arg] -> Pattern.State -> IO Args
699+argsHelp args state =
700+ case args of
701+ [] ->
702+ do resultVar <- mkFlexVar
703+ let resultType = VarN resultVar
704+ return $ Args [resultVar] resultType resultType state
705+
706+ (Can.Arg _ pattern) : otherArgs ->
707+ do argVar <- mkFlexVar
708+ let argType = VarN argVar
709+
710+ (Args vars tipe result newState) <-
711+ argsHelp otherArgs =<<
712+ Pattern.add pattern (NoPatternExpectation argType) state
713+
714+ return (Args (argVar:vars) (FunN argType tipe) result newState)
715+
716+
717+
718+-- CONSTRAIN TYPED ARGS
719+
720+
721+data TypedArgs =
722+ TypedArgs
723+ { _t_type :: Type
724+ , _t_result :: Type
725+ , _t_state :: Pattern.State
726+ }
727+
728+
729+constrainTypedArgs :: Map.Map N.Name Type -> N.Name -> [Can.TypedArg] -> Can.Type -> IO TypedArgs
730+constrainTypedArgs rtv name args srcResultType =
731+ do resultType <- Instantiate.fromSrcType rtv srcResultType
732+ typedArgsHelp rtv name args resultType Pattern.emptyState
733+
734+
735+typedArgsHelp :: Map.Map N.Name Type -> N.Name -> [Can.TypedArg] -> Type -> Pattern.State -> IO TypedArgs
736+typedArgsHelp rtv name args resultType state =
737+ case args of
738+ [] ->
739+ return $ TypedArgs resultType resultType state
740+
741+ (Can.TypedArg index srcType pattern@(A.A region _)) : otherArgs ->
742+ do argType <- Instantiate.fromSrcType rtv srcType
743+ let expect = PatternExpectation region (PTypedArg name index) argType
744+
745+ (TypedArgs tipe result newState) <-
746+ typedArgsHelp rtv name otherArgs resultType =<<
747+ Pattern.add pattern expect state
511748
512− let headers = Map.singleton name (A.A region lambdaType)
513− return $ CLet [ Scheme (Map.elems newRigids) [] headers defCon ] bodyCon
749+ return (TypedArgs (FunN argType tipe) result newState)