on master help sign in
Simplify validation phase a bunch

Things that moved to canonicalization include: - Checking for free variables in unions and aliases. - Checking for duplicate argument names. - Checking for duplicate declaration names. The checks for duplicates now result in Map.Map which should reduce the number of times we build and unbuild those dictionaries during compilation.

commit5fab52a59c2b26cfdf176275fc79043b0c0a75a1 authorEvan Czaplicki <evancz@users.noreply.github.com> dateWed 25 Oct 2017, 19:16 (9 years ago) parent087045f
1 file changed+186−588
src/Validate.hs+186−588
src/Validate.hs+186−588
@@ -2,25 +2,16 @@
22{-# LANGUAGE OverloadedStrings #-}
33module Validate (Result, validate) where
44
5−import Control.Monad (foldM_, when)
6−import qualified Data.Foldable as F
5+import Control.Applicative (liftA2)
6+import Control.Monad (forM_)
77import qualified Data.Map as Map
8−import qualified Data.Maybe as Maybe
9−import qualified Data.Set as Set
108import Data.Text (Text)
119
12−import qualified AST.Effects as Effects
1310import qualified AST.Expression.Source as Src
14−import qualified AST.Declaration as D
15−import qualified AST.Literal as L
16−import qualified AST.Module as Module
17−import qualified AST.Module.Name as ModuleName
11+import qualified AST.Expression.Valid as Valid
1812import qualified AST.Pattern as Pattern
1913import qualified AST.Type as Type
20−import qualified AST.Variable as Var
21−import qualified Elm.Compiler.Imports as Imports
22−import qualified Elm.Package as Package
23−import Elm.Utils ((|>))
14+import qualified Elm.Name as N
2415import qualified Reporting.Annotation as A
2516import qualified Reporting.Error.Syntax as Error
2617import qualified Reporting.Region as R
@@ -28,688 +19,295 @@ import qualified Reporting.Result as Result
2819
2920
3021
31−type Result warning a =
32− Result.Result () warning Error.Error a
33−
34−
35−
36−-- MODULES
37−
38−
39−validate :: Module.Source -> Result w Module.Valid
40−validate (Module.Module name info) =
41− let
42− (ModuleName.Canonical pkgName _) =
43− name
44−
45− (Module.Source tag settings docs exports imports decls) =
46− info
47− in
48− do (ValidStuff ports structure) <- validateDecls decls
49−
50− validEffects <- validateEffects tag settings ports (D._defs structure)
51−
52− return $ Module.Module name $
53− Module.Valid docs exports (addDefaults pkgName imports) structure validEffects
54−
55−
56−
57−-- IMPORTS
58−
5922
60−addDefaults
61− :: Package.Name
62− -> [Module.UserImport]
63− -> ([Module.DefaultImport], [Module.UserImport])
64−addDefaults pkgName imports =
65− flip (,) imports $
66− if pkgName == Package.core then
67− []
68−
69− else
70− Imports.defaults
23+-- VALIDATE
7124
7225
26+type Result warning a =
27+ Result.Result () warning Error.Error a
7328
74−-- EFFECTS
7529
30+validate :: Src.Module [Src.Decl] -> Result w Valid.Module
31+validate (Src.Module name srcEffects overview exports imports srcDecls) =
32+ do (Stuff decls unions aliases binops ports docs) <- validateDecls srcDecls
33+ effects <- validateEffects srcEffects ports
34+ return $ Valid.Module name overview docs exports imports decls unions aliases binops effects
7635
77−validateEffects
78− :: Module.SourceTag
79− -> Module.SourceSettings
80− -> [A.Commented Effects.PortRaw]
81− -> [A.Commented Src.ValidDef]
82− -> Result w Effects.Raw
83−validateEffects tag settings@(A.A _ pairs) ports validDefs =
84− case tag of
85− Module.Normal ->
86− do noSettings Error.SettingsOnNormalModule settings
87− noPorts ports
88− return Effects.None
8936
90− Module.Port _ ->
91− do noSettings Error.SettingsOnPortModule settings
92− return (Effects.Port ports)
9337
94− Module.Effect tagRegion ->
95− let
96− collectSettings (A.A region setting, userValue) dict =
97− Map.insertWith (++) setting [(region, userValue)] dict
38+-- VALIDATE DECLARATIONS
9839
99− settingsDict =
100− foldr collectSettings Map.empty pairs
101− in
102− do noPorts ports
103− managerType <- toManagerType tagRegion settingsDict
104− (r0, r1, r2) <- checkManager tagRegion managerType validDefs
105− return (Effects.Manager () (Effects.Info tagRegion r0 r1 r2 managerType))
10640
41+data Stuff =
42+ Stuff
43+ { _decls :: [Valid.Decl]
44+ , _unions :: [Valid.Union]
45+ , _aliases :: [Valid.Alias]
46+ , _binops :: [Valid.Binop]
47+ , _ports :: [Valid.Port]
48+ , _docs :: Map.Map N.Name Text
49+ }
10750
108−noSettings :: Error.Error -> Module.SourceSettings -> Result w ()
109−noSettings errorMsg (A.A region settings) =
110− case settings of
111− [] ->
112− Result.ok ()
11351
114− _ : _ ->
115− Result.throw region errorMsg
52+validateDecls :: [Src.Decl] -> Result w Stuff
53+validateDecls decls =
54+ vsdHelp decls (Stuff [] [] [] [] [] Map.empty)
11655
11756
118−noPorts :: [A.Commented Effects.PortRaw] -> Result w ()
119−noPorts ports =
120− case ports of
57+vsdHelp :: [Src.Decl] -> Stuff -> Result w Stuff
58+vsdHelp decls stuff =
59+ case decls of
12160 [] ->
122− Result.ok ()
123−
124− _ : _ ->
125− let
126− toError (A.A (region, _) (Effects.PortRaw name _)) =
127− A.A region (Error.UnexpectedPort name)
128− in
129− Result.throwMany (map toError ports)
130−
131−
132−toManagerType
133− :: R.Region
134− -> Map.Map Text [(R.Region, A.Located Text)]
135− -> Result w Effects.RawManagerType
136−toManagerType tagRegion settingsDict =
137− let
138− toErrors name entries =
139− map (\entry -> A.A (fst entry) (Error.BadSettingOnEffectModule name)) entries
140−
141− errors =
142− settingsDict
143− |> Map.delete "command"
144− |> Map.delete "subscription"
145− |> Map.mapWithKey toErrors
146− |> Map.elems
147− |> concat
148− in
149− do when (not (null errors)) (Result.throwMany errors)
150− maybeEffects <-
151− (,) <$> extractOne "command" settingsDict
152− <*> extractOne "subscription" settingsDict
153−
154− -- TODO check that cmd and sub types exist?
155− case maybeEffects of
156− (Nothing, Nothing) ->
157− Result.throw tagRegion Error.NoSettingsOnEffectModule
158−
159− (Just cmd, Nothing) ->
160− return (Effects.CmdManager cmd)
161−
162− (Nothing, Just sub) ->
163− return (Effects.SubManager sub)
164−
165− (Just cmd, Just sub) ->
166− return (Effects.FxManager cmd sub)
167−
168−
169−extractOne
170− :: Text
171− -> Map.Map Text [(R.Region, A.Located Text)]
172− -> Result w (Maybe (A.Located Text))
173−extractOne name settingsDict =
174− case Map.lookup name settingsDict of
175− Nothing ->
176− return Nothing
177−
178− Just [] ->
179− error "Empty lists should never be added to the dictionary of effect module settings."
180−
181− Just [(_, userType)] ->
182− return (Just userType)
183−
184− Just ((region, _) : _) ->
185− Result.throw region (Error.DuplicateSettingOnEffectModule name)
186−
187−
188−
189−-- CHECK EFFECT MANAGER
190−
191−
192−checkManager
193− :: R.Region
194− -> Effects.RawManagerType
195− -> [A.Commented Src.ValidDef]
196− -> Result w (R.Region, R.Region, R.Region)
197−checkManager tagRegion managerType validDefs =
198− let
199− regionDict =
200− Map.fromList (Maybe.mapMaybe getSimpleDefRegion validDefs)
201− in
202− const (,,)
203− <$> requireMaps tagRegion regionDict managerType
204− <*> requireRegion tagRegion regionDict "init"
205− <*> requireRegion tagRegion regionDict "onEffects"
206− <*> requireRegion tagRegion regionDict "onSelfMsg"
207−
208−
209−getSimpleDefRegion :: A.Commented Src.ValidDef -> Maybe (Text, R.Region)
210−getSimpleDefRegion decl =
211− case decl of
212− A.A _ (Src.Def region (A.A _ (Pattern.Var name)) _ _) ->
213− Just (name, region)
214−
215− _ ->
216− Nothing
61+ Result.ok stuff
21762
63+ A.A _ decl : otherDecls ->
64+ case decl of
65+ Src.Union name tvars ctors ->
66+ do let union = Valid.Union name tvars ctors
67+ vsdHelp otherDecls $ stuff { _unions = union : _unions stuff }
21868
219−requireMaps
220− :: R.Region
221− -> Map.Map Text R.Region
222− -> Effects.RawManagerType
223− -> Result w ()
224−requireMaps tagRegion regionDict managerType =
225− let
226− check name =
227− when (Map.notMember name regionDict) $
228− Result.throw tagRegion (Error.MissingManagerOnEffectModule name)
229− in
230− case managerType of
231− Effects.CmdManager _ ->
232− check "cmdMap"
69+ Src.Alias name tvars tipe ->
70+ do let alias = Valid.Alias name tvars tipe
71+ vsdHelp otherDecls $ stuff { _aliases = alias : _aliases stuff }
23372
234− Effects.SubManager _ ->
235− check "subMap"
73+ Src.Binop op assoc prec val ->
74+ do let binop = Valid.Binop op assoc prec val
75+ vsdHelp otherDecls $ stuff { _binops = binop : _binops stuff }
23676
237− Effects.FxManager _ _ ->
238− check "cmdMap" <* check "subMap"
77+ Src.Port name tipe ->
78+ do let port_ = Valid.Port name tipe
79+ vsdHelp otherDecls $ stuff { _ports = port_ : _ports stuff }
23980
81+ Src.Docs docs ->
82+ validateDocs docs otherDecls stuff
24083
241−requireRegion :: R.Region -> Map.Map Text R.Region -> Text -> Result w R.Region
242−requireRegion tagRegion regionDict name =
243− case Map.lookup name regionDict of
244− Just region ->
245− return region
84+ Src.Annotation (A.A _ name) tipe ->
85+ validateAnnotation name tipe otherDecls stuff
24686
247− Nothing ->
248− Result.throw tagRegion (Error.MissingManagerOnEffectModule name)
87+ Src.Definition name args body ->
88+ do validBody <- expression body
89+ let validDecl = Valid.Decl name args validBody Nothing
90+ vsdHelp otherDecls $ stuff { _decls = validDecl : _decls stuff }
24991
25092
25193
252−-- COLLAPSE COMMENTS
94+-- VALIDATE DOCS
25395
25496
255−collapseComments :: [D.CommentOr (A.Located a)] -> Result w [A.Commented a]
256−collapseComments listWithComments =
257− case listWithComments of
97+validateDocs :: Text -> [Src.Decl] -> Stuff -> Result w Stuff
98+validateDocs docs decls stuff =
99+ case decls of
258100 [] ->
259− Result.ok []
260−
261− D.Comment (A.A _ msg) : D.Whatever (A.A region a) : rest ->
262− let
263− entry =
264− A.A (region, Just msg) a
265− in
266− fmap (entry:) (collapseComments rest)
267−
268− D.Comment (A.A region _) : rest ->
269− collapseComments rest
270− <* Result.throw region Error.CommentOnNothing
271−
101+ error "TODO no docs on nothing"
272102
273− D.Whatever (A.A region a) : rest ->
274− let
275− entry =
276− A.A (region, Nothing) a
277− in
278− fmap (entry:) (collapseComments rest)
103+ A.A _ decl : _ ->
104+ do name <- getNameForDocs decl
105+ vsdHelp decls $ stuff { _docs = Map.insert name docs (_docs stuff) }
279106
280107
108+getNameForDocs :: Src.Decl_ -> Result w N.Name
109+getNameForDocs decl =
110+ case decl of
111+ Src.Union (A.A _ name) _ _ ->
112+ return name
281113
282−-- VALIDATE STRUCTURED SOURCE
283−
284−
285−validateDecls :: [D.Source] -> Result w ValidStuff
286−validateDecls sourceDecls =
287− do rawDecls <- collapseComments sourceDecls
288−
289− validStuff <- validateRawDecls rawDecls
290−
291− let (D.Decls _ unions aliases _) = _structure validStuff
114+ Src.Alias (A.A _ name) _ _ ->
115+ return name
292116
293− return validStuff
294− <* F.traverse_ checkTypeVarsInUnion unions
295− <* F.traverse_ checkTypeVarsInAlias aliases
296− <* checkDuplicates validStuff
117+ Src.Binop _ _ _ _ ->
118+ error "TODO no docs on binop"
297119
120+ Src.Port _ _ ->
121+ error "TODO no docs on ports"
298122
123+ Src.Docs _ ->
124+ error "TODO no docs on docs"
299125
300−-- VALIDATE DECLARATIONS
126+ Src.Annotation (A.A _ name) _ ->
127+ return name
301128
129+ Src.Definition (A.A _ name) _ _ ->
130+ return name
302131
303−data ValidStuff =
304− ValidStuff
305− { _ports :: [A.Commented Effects.PortRaw]
306− , _structure :: D.Valid
307− }
308132
309133
310−validateRawDecls :: [A.Commented D.Raw] -> Result w ValidStuff
311−validateRawDecls commentedDecls =
312− vrdHelp commentedDecls [] (D.Decls [] [] [] [])
134+-- VALIDATE ANNOTATION
313135
314136
315−vrdHelp
316− :: [A.Commented D.Raw]
317− -> [A.Commented Effects.PortRaw]
318− -> D.Valid
319− -> Result w ValidStuff
320−vrdHelp commentedDecls ports structure =
321− case commentedDecls of
137+validateAnnotation :: N.Name -> Type.Raw -> [Src.Decl] -> Stuff -> Result w Stuff
138+validateAnnotation annotationName tipe decls stuff =
139+ case decls of
322140 [] ->
323− Result.ok (ValidStuff ports structure)
141+ error "TODO no attotations on nothing"
324142
325− A.A ann decl : rest ->
143+ A.A _ decl : otherDecls ->
326144 case decl of
327− D.Union (D.Type name tvars ctors) ->
328− vrdHelp rest ports (D.addUnion (A.A ann (D.Type name tvars ctors)) structure)
329−
330− D.Alias (D.Type name tvars alias) ->
331− vrdHelp rest ports (D.addAlias (A.A ann (D.Type name tvars alias)) structure)
332−
333− D.Fixity fixity ->
334− vrdHelp rest ports (D.addInfix fixity structure)
335−
336− D.Def (A.A region def) ->
337− vrdDefHelp rest (A.A (region, snd ann) def) ports structure
338−
339− D.Port name tipe ->
340− do checkDuplicateFieldsInType tipe
341− vrdHelp rest (A.A ann (Effects.PortRaw name tipe) : ports) structure
342−
343−
344−vrdDefHelp
345− :: [A.Commented D.Raw]
346− -> A.Commented Src.RawDef'
347− -> [A.Commented Effects.PortRaw]
348− -> D.Valid
349− -> Result w ValidStuff
350−vrdDefHelp remainingDecls (A.A ann def) ports structure =
351− let
352− addDef validDef (ValidStuff finalPorts struct) =
353− ValidStuff finalPorts (D.addDef (A.A ann validDef) struct)
354− in
355− case def of
356− Src.Definition pat expr ->
357− addDef
358− <$> validateDef (fst ann) pat expr Nothing
359− <*> vrdHelp remainingDecls ports structure
360−
361− Src.Annotation name tipe ->
362− case remainingDecls of
363− A.A _ (D.Def (A.A defRegion (Src.Definition pat expr))) : rest
364− | Pattern.isVar name pat ->
365− addDef
366− <$> validateDef (R.merge (fst ann) defRegion) pat expr (Just tipe)
367− <*> vrdHelp rest ports structure
368−
369− _ ->
370− vrdHelp remainingDecls ports structure
371− <* Result.throw (fst ann) (Error.TypeWithoutDefinition name)
372−
373−
374−
375−-- VALIDATE DEFINITIONS
376−
377−
378−definitions :: [Src.RawDef] -> Result w [Src.ValidDef]
379−definitions sourceDefs =
380− do validDefs <- definitionsHelp sourceDefs
381−
382− validDefs
383− |> map Src.getPattern
384− |> concatMap Pattern.boundVars
385− |> detectDuplicates Error.DuplicateDefinition
386−
387− return validDefs
388−
145+ Src.Definition name@(A.A _ definitionName) args body ->
146+ if annotationName == definitionName then
147+ do validBody <- expression body
148+ let validDecl = Valid.Decl name args validBody (Just tipe)
149+ vsdHelp otherDecls $ stuff { _decls = validDecl : _decls stuff }
389150
390−definitionsHelp :: [Src.RawDef] -> Result w [Src.ValidDef]
391−definitionsHelp sourceDefs =
392− case sourceDefs of
393− [] ->
394− return []
395−
396− A.A defRegion (Src.Definition pat expr) : rest ->
397− (:)
398− <$> validateDef defRegion pat expr Nothing
399− <*> definitionsHelp rest
400−
401− A.A annRegion (Src.Annotation name tipe) : rest ->
402− case rest of
403− A.A defRegion (Src.Definition pat expr) : rest'
404− | Pattern.isVar name pat ->
405− (:)
406− <$> validateDef (R.merge annRegion defRegion) pat expr (Just tipe)
407− <*> definitionsHelp rest'
151+ else
152+ error "TODO annotation does not match following definition"
408153
409154 _ ->
410− Result.throw annRegion (Error.TypeWithoutDefinition name)
411−
412−
413−validateDef
414− :: R.Region
415− -> Pattern.Raw
416− -> Src.RawExpr
417− -> Maybe Type.Raw
418− -> Result w Src.ValidDef
419−validateDef region pat expr maybeType =
420− do validExpr <- expression expr
421− validateDefPattern pat validExpr
422− F.traverse_ checkDuplicateFieldsInType maybeType
423− return $ Src.Def region pat validExpr maybeType
424−
425−
426−validateDefPattern :: Pattern.Raw -> Src.ValidExpr -> Result w ()
427−validateDefPattern pattern body =
428− case fst (Src.collectLambdas body) of
429− [] ->
430− return ()
431−
432− args ->
433− case pattern of
434− A.A _ (Pattern.Var funcName) ->
435− checkArguments funcName args
436−
437− _ ->
438− let
439− (A.A start _) = pattern
440− (A.A end _) = last args
441− in
442− Result.throw (R.merge start end) (Error.BadFunctionName (length args))
443−
444−
445−checkArguments :: Text -> [Pattern.Raw] -> Result w ()
446−checkArguments funcName args =
447− let
448− vars =
449− concatMap Pattern.boundVars args
450−
451− checkDups seenArgs (A.A region arg) =
452− if Set.member arg seenArgs then
453− Result.throw region (Error.DuplicateArgument funcName arg)
454−
455− else
456− return (Set.insert arg seenArgs)
457− in
458− foldM_ checkDups Set.empty vars
155+ error "TODO annotation needs to be on a definition"
459156
460157
461158
462159-- VALIDATE EXPRESSIONS
463160
464161
465−expression :: Src.RawExpr -> Result w Src.ValidExpr
466−expression (A.A ann sourceExpression) =
467− A.A ann <$>
162+expression :: Src.Expr -> Result w Valid.Expr
163+expression (A.A region sourceExpression) =
164+ A.A region <$>
468165 case sourceExpression of
469− Src.Var (Var.Raw "True") ->
470− return (Src.Literal (L.Boolean True))
166+ Src.Var prefix name ->
167+ pure (Valid.Var prefix name)
471168
472− Src.Var (Var.Raw "False") ->
473− return (Src.Literal (L.Boolean False))
169+ Src.Lambda pattern body ->
170+ Valid.Lambda pattern <$> expression body
474171
475− Src.Var x ->
476− return (Src.Var x)
172+ Src.Op name ->
173+ pure (Valid.Op name)
477174
478− Src.Lambda pattern body ->
479− Src.Lambda
480− <$> validatePattern pattern
481− <*> expression body
175+ Src.Negate expr ->
176+ Valid.Negate <$> expression expr
482177
483− Src.Binop ops lastExpr ->
484− Src.Binop
178+ Src.Binops ops lastExpr ->
179+ Valid.Binops
485180 <$> traverse (\(expr,op) -> (,) <$> expression expr <*> pure op) ops
486181 <*> expression lastExpr
487182
488− Src.Case e branches ->
489− Src.Case
490− <$> expression e
491− <*> traverse (\(p,b) -> (,) <$> validatePattern p <*> expression b) branches
492−
493− Src.Ctor name args ->
494− Src.Ctor name <$> traverse expression args
183+ Src.Case expr branches ->
184+ Valid.Case
185+ <$> expression expr
186+ <*> traverse (traverse expression) branches
495187
496188 Src.Literal lit ->
497− return (Src.Literal lit)
189+ pure (Valid.Literal lit)
498190
499− Src.List expressions ->
500− Src.List
501− <$> traverse expression expressions
191+ Src.List exprs ->
192+ Valid.List <$> traverse expression exprs
502193
503− Src.App funcExpr argExpr ->
504− Src.App
505− <$> expression funcExpr
506− <*> expression argExpr
194+ Src.Call func args ->
195+ Valid.Call
196+ <$> expression func
197+ <*> traverse expression args
507198
508199 Src.If branches finally ->
509− Src.If
200+ Valid.If
510201 <$> traverse both branches
511202 <*> expression finally
512203
204+ Src.Accessor field ->
205+ pure (Valid.Accessor field)
206+
513207 Src.Access record field ->
514− Src.Access
208+ Valid.Access
515209 <$> expression record
516− <*> return field
210+ <*> pure field
517211
518212 Src.Update record fields ->
519− do checkDuplicateFields ann fields
520− Src.Update <$> expression record <*> traverse second fields
213+ Valid.Update record <$> traverse (traverse expression) fields
521214
522215 Src.Record fields ->
523− do checkDuplicateFields ann fields
524− Src.Record <$> traverse second fields
216+ Valid.Record <$> traverse (traverse expression) fields
217+
218+ Src.Unit ->
219+ pure Valid.Unit
220+
221+ Src.Tuple a b cs ->
222+ Valid.Tuple
223+ <$> expression a
224+ <*> expression b
225+ <*> traverse expression cs
525226
526227 Src.Let defs body ->
527− Src.Let
228+ Valid.Let
528229 <$> definitions defs
529230 <*> expression body
530231
531232 Src.GLShader uid src gltipe ->
532− return (Src.GLShader uid src gltipe)
533−
534−
535−second :: (a, Src.RawExpr) -> Result w (a, Src.ValidExpr)
536−second (value, expr) =
537− (,) value <$> expression expr
538−
539−
540−both :: (Src.RawExpr, Src.RawExpr) -> Result w (Src.ValidExpr, Src.ValidExpr)
541−both (expr1, expr2) =
542− (,) <$> expression expr1 <*> expression expr2
543−
544−
545−checkDuplicateFields :: R.Region -> [(A.Located Text, a)] -> Result w ()
546−checkDuplicateFields recordRegion fields =
547− let
548− checkDups seenFields ( A.A region field, _ ) =
549− if Set.member field seenFields then
550− Result.throw recordRegion (Error.DuplicateFieldName region field)
551− else
552− Result.ok (Set.insert field seenFields)
553− in
554− foldM_ checkDups Set.empty fields
555−
556−
557−
558−-- VALIDATE PATTERNS
559−
233+ pure (Valid.GLShader uid src gltipe)
560234
561−validatePattern :: Pattern.Raw -> Result w Pattern.Raw
562−validatePattern pattern =
563− do detectDuplicates Error.BadPattern (Pattern.boundVars pattern)
564− return pattern
565235
236+both :: (Src.Expr, Src.Expr) -> Result w (Valid.Expr, Valid.Expr)
237+both (a, b) =
238+ liftA2 (,) (expression a) (expression b)
566239
567240
568−-- DETECT DUPLICATES
569241
242+-- VALIDATE DEFINITIONS
570243
571−checkDuplicates :: ValidStuff -> Result w ()
572−checkDuplicates (ValidStuff ports (D.Decls defs unions aliases _)) =
573− let
574− -- SIMPLE NAMES
575−
576− defValues =
577− concatMap (Pattern.boundVars . Src.getPattern . A.drop) defs
578−
579− portValues =
580− map fromPort ports
581−
582− fromPort (A.A (region, _) (Effects.PortRaw name _)) =
583− A.A region name
584−
585− -- TYPE NAMES
586−
587− (types, typeValues) =
588− unzip (map fromUnion unions ++ map fromAlias aliases)
589−
590− fromUnion (A.A (region, _) (D.Type name _ ctors)) =
591− ( A.A region name
592− , map (A.A region . fst) ctors
593− )
594−
595− fromAlias (A.A (region, _) (D.Type name _ (A.A _ tipe))) =
596− (,) (A.A region name) $
597− case tipe of
598− Type.RRecord _ _ ->
599− [A.A region name]
600−
601− _ ->
602− []
603− in
604− F.sequenceA_
605− [ detectDuplicates Error.DuplicateValueDeclaration (portValues ++ defValues)
606− , detectDuplicates Error.DuplicateValueDeclaration (concat typeValues)
607− , detectDuplicates Error.DuplicateTypeDeclaration types
608− ]
609244
245+definitions :: [A.Located Src.Def] -> Result w [Valid.Def]
246+definitions sourceDefs =
247+ case sourceDefs of
248+ [] ->
249+ return []
610250
611−detectDuplicates :: (Text -> Error.Error) -> [A.Located Text] -> Result w ()
612−detectDuplicates tag names =
613− let
614− add (A.A region name) dict =
615− Map.insertWith (++) name [region] dict
251+ A.A region (Src.Destruct pattern expr) : otherDefs ->
252+ (:)
253+ <$> validateDestruct region pattern expr
254+ <*> definitions otherDefs
616255
617− makeGroups pairs =
618− Map.toList (foldr add Map.empty pairs)
256+ A.A region (Src.Define name args expr) : otherDefs ->
257+ (:)
258+ <$> validateDefinition region name args expr Nothing
259+ <*> definitions otherDefs
619260
620− check (name, regions) =
621− case regions of
622− _ : region : _ ->
623− Result.throw region (tag name)
261+ A.A annRegion (Src.Annotate annotationName tipe) : otherDefs ->
262+ case otherDefs of
263+ A.A defRegion (Src.Define name args expr) : otherOtherDefs | name == annotationName ->
264+ (:)
265+ <$> validateDefinition (R.merge annRegion defRegion) name args expr (Just tipe)
266+ <*> definitions otherOtherDefs
624267
625268 _ ->
626− return ()
627− in
628− F.traverse_ check (makeGroups names)
629−
630−
631−
632−-- UNBOUND TYPE VARIABLES
633−
634−
635−checkTypeVarsInUnion :: A.Commented (D.Union Type.Raw) -> Result w ()
636−checkTypeVarsInUnion (A.A (region,_) (D.Type name boundVars ctors)) =
637− do allFreeVars <- concat <$> traverse freeVars (concatMap snd ctors)
638− case diff boundVars allFreeVars of
639− (_, []) ->
640− return ()
269+ Result.throw annRegion (Error.TypeWithoutDefinition annotationName)
641270
642− (_, unbound) ->
643− Result.throw region
644− (Error.UnboundTypeVarsInUnion name boundVars unbound)
645271
646−
647−checkTypeVarsInAlias :: A.Commented (D.Alias Type.Raw) -> Result w ()
648−checkTypeVarsInAlias (A.A (region,_) (D.Type name boundVars tipe)) =
649− do allFreeVars <- freeVars tipe
650− case diff boundVars allFreeVars of
651− ([], []) ->
652− return ()
653−
654− ([], unbound) ->
655− Result.throw region
656− (Error.UnboundTypeVarsInAlias name boundVars unbound)
657−
658− (unused, []) ->
659− Result.throw region
660− (Error.UnusedTypeVarsInAlias name boundVars unused)
661−
662− (unused, unbound) ->
663− Result.throw region
664− (Error.MessyTypeVarsInAlias name boundVars unused unbound)
272+validateDefinition :: R.Region -> Text -> [Pattern.Raw] -> Src.Expr -> Maybe Type.Raw -> Result w Valid.Def
273+validateDefinition region name args expr maybeType =
274+ do validExpr <- expression expr
275+ return $ Valid.Define region name args validExpr maybeType
665276
666277
667−diff :: [Text] -> [A.Located Text] -> ([Text], [Text])
668−diff left right =
669− let
670− leftSet =
671− Set.fromList left
278+validateDestruct :: R.Region -> Pattern.Raw -> Src.Expr -> Result w Valid.Def
279+validateDestruct region pattern expr =
280+ Valid.Destruct region pattern <$> expression expr
672281
673− rightSet =
674− Set.fromList (map A.drop right)
675− in
676− ( Set.toList (Set.difference leftSet rightSet)
677− , Set.toList (Set.difference rightSet leftSet)
678− )
679282
680283
681−freeVars :: Type.Raw -> Result w [A.Located Text]
682−freeVars (A.A region tipe) =
683− case tipe of
684− Type.RLambda t1 t2 ->
685− (++) <$> freeVars t1 <*> freeVars t2
284+-- VALIDATE EFFECTS
686285
687− Type.RVar x ->
688− Result.ok [A.A region x]
689286
690− Type.RType _ args ->
691− concat <$> traverse freeVars args
287+validateEffects :: Src.Effects -> [Valid.Port] -> Result w Valid.Effects
288+validateEffects effects ports =
289+ case effects of
290+ Src.NoEffects ->
291+ do noPorts ports
292+ return Valid.NoEffects
692293
693− Type.RRecord fields ext ->
694− do checkDuplicateFields region fields
695− let types = Maybe.maybeToList ext ++ map snd fields
696− concat <$> traverse freeVars types
294+ Src.Ports _ ->
295+ return (Valid.Ports ports)
697296
297+ Src.Effects _ manager ->
298+ do noPorts ports
299+ case manager of
300+ Src.Cmd cmd ->
301+ return (Valid.Cmd cmd)
698302
699−checkDuplicateFieldsInType :: Type.Raw -> Result w ()
700−checkDuplicateFieldsInType (A.A region tipe) =
701− case tipe of
702− Type.RLambda t1 t2 ->
703− checkDuplicateFieldsInType t1
704− <* checkDuplicateFieldsInType t2
303+ Src.Sub sub ->
304+ return (Valid.Sub sub)
705305
706− Type.RVar _ ->
707− Result.ok ()
306+ Src.Fx cmd sub ->
307+ return (Valid.Fx cmd sub)
708308
709− Type.RType _ args ->
710− F.traverse_ checkDuplicateFieldsInType args
711309
712− Type.RRecord fields ext ->
713− do checkDuplicateFields region fields
714− let types = Maybe.maybeToList ext ++ map snd fields
715− F.traverse_ checkDuplicateFieldsInType types
310+noPorts :: [Valid.Port] -> Result w ()
311+noPorts ports =
312+ forM_ ports $ \(Valid.Port (A.A region name) _) ->
313+ Result.throw region (Error.UnexpectedPort name)