on master help sign in
Throw errors for unbound type variables in ADTs and aliases, resolves #302
commit692d8d8eac2f9884a470d76d6f9be0ec5cdf89cd authorEvan Czaplicki <info@elm-lang.org> dateSat 19 Oct 2013, 10:39 (13 years ago) parent56877c0
4 files changed+80−13
compiler/SourceSyntax/Declaration.hs+24−1 compiler/Transform/Check.hs+46−2 libraries/AutomatonV2.elm → libraries/AutomatonV2.elm.hidden libraries/Graphics/Collage.elm+10−10
compiler/SourceSyntax/Declaration.hs+24−1
@@ -4,6 +4,8 @@ module SourceSyntax.Declaration where
44import Data.Data
55import qualified SourceSyntax.Expression as Expr
66import SourceSyntax.Type
7+import SourceSyntax.PrettyPrint
8+import Text.PrettyPrint as P
79
810data Declaration tipe var
911 = Definition (Expr.Def tipe var)
@@ -22,4 +24,25 @@ instance Show Assoc where
2224 case assoc of
2325 L -> "left"
2426 N -> "non"
25− R -> "right"
27+ R -> "right"
28+
29+instance Pretty (Declaration t v) where
30+ pretty decl =
31+ case decl of
32+ Definition def -> pretty def
33+
34+ Datatype tipe tvars ctors ->
35+ P.hang (P.text "data" <+> P.text tipe <+> P.hsep (map P.text tvars)) 4
36+ (P.sep $ zipWith join ("=" : repeat "|") ctors)
37+ where
38+ join c ctor = P.text c <+> prettyCtor ctor
39+ prettyCtor (name, tipes) =
40+ P.hang (P.text name) 2 (P.sep (map prettyParens tipes))
41+
42+ TypeAlias name tvars tipe ->
43+ let alias = P.text name <+> P.hsep (map P.text tvars) in
44+ P.hang (P.text "type" <+> alias <+> P.equals) 4 (pretty tipe)
45+
46+ -- TODO: actually write out the other cases. They are currently unused, but
47+ -- this is probably going to be a bug someday.
48+ _ -> P.text (show decl)
compiler/Transform/Check.hs+46−2
@@ -2,9 +2,11 @@ module Transform.Check (mistakes) where
22
33import Transform.SortDefinitions (boundVars)
44import SourceSyntax.Everything
5+import SourceSyntax.PrettyPrint
56import qualified SourceSyntax.Type as T
67import Data.List as List
78import qualified Data.Map as Map
9+import qualified Data.Maybe as Maybe
810import qualified Data.Set as Set
911import Data.Data
1012import Data.Generics.Uniplate.Data
@@ -13,7 +15,7 @@ import Text.PrettyPrint as P
1315
1416mistakes :: (Data t, Data v) => [Declaration t v] -> [Doc]
1517mistakes decls =
16− map P.text $ concatMap findErrors (getLets decls)
18+ illFormedTypes decls ++ map P.text (concatMap findErrors (getLets decls))
1719 where
1820 findErrors defs = duplicates defs ++ badOrder defs
1921
@@ -60,4 +62,46 @@ badOrder defs = go defs
6062
6163 _ -> []
6264
63−
65+illFormedTypes :: [Declaration t v] -> [Doc]
66+illFormedTypes decls = map report (Maybe.mapMaybe isIllFormed (aliases ++ adts))
67+ where
68+ aliases = [ (decl, tvars, [tipe]) | decl@(TypeAlias _ tvars tipe) <- decls ]
69+ adts = [ (decl, tvars, concatMap snd ctors) | decl@(Datatype _ tvars ctors) <- decls ]
70+
71+ freeVars tipe =
72+ case tipe of
73+ T.Lambda t1 t2 -> Set.union (freeVars t1) (freeVars t2)
74+ T.Var x -> Set.singleton x
75+ T.Data _ ts -> Set.unions (map freeVars ts)
76+ T.EmptyRecord -> Set.empty
77+ T.Record fields ext -> Set.unions (freeVars ext : map (freeVars . snd) fields)
78+
79+ undeclared tvars tipes = Set.difference used declared
80+ where
81+ used = Set.unions (map freeVars tipes)
82+ declared = Set.fromList tvars
83+
84+ isIllFormed (decl, tvars, tipes) =
85+ let unbound = undeclared tvars tipes in
86+ if Set.null unbound then Nothing
87+ else Just (decl, Set.toList unbound)
88+
89+ report (decl, tvars) =
90+ P.vcat [ P.text $ "Error: type variable" ++ listing ++ " unbound in:"
91+ , P.text "\n"
92+ , nest 4 (pretty decl) ]
93+ where
94+ listing =
95+ case tvars of
96+ [tvar] -> " " ++ quote tvar ++ " is"
97+ _ -> "s " ++ addCommas (addAnd (map quote tvars)) ++ " are"
98+
99+ addCommas xs
100+ | length xs < 3 = concat xs
101+ | otherwise = intercalate ", " xs
102+
103+ addAnd xs
104+ | length xs < 2 = xs
105+ | otherwise = zipWith (++) (replicate (length xs - 1) "" ++ ["and "]) xs
106+
107+ quote tvar = "'" ++ tvar ++ "'"
libraries/AutomatonV2.elm → libraries/AutomatonV2.elm.hiddenrenamed

The content is the same.

libraries/Graphics/Collage.elm+10−10
@@ -204,37 +204,37 @@ collage : Int -> Int -> [Form] -> Element
204204collage = Native.Graphics.Collage.collage
205205
206206
207−type Path = [(number,number)]
207+type Path = [(Float,Float)]
208208
209209{-| Create a path that follows a sequence of points. -}
210−path : [(number,number)] -> Path
210+path : [(Float,Float)] -> Path
211211path ps = ps
212212
213213{-| Create a path along a given line segment. -}
214−segment : (number,number) -> (number,number) -> Path
214+segment : (Float,Float) -> (Float,Float) -> Path
215215segment p1 p2 = [p1,p2]
216216
217−type Shape = [(number,number)]
217+type Shape = [(Float,Float)]
218218
219219{-| Create an arbitrary polygon by specifying its corners in order.
220220`polygon` will automatically close all shapes, so the given list
221221of points does not need to start and end with the same position.
222222-}
223−polygon : [(number,number)] -> Shape
223+polygon : [(Float,Float)] -> Shape
224224polygon points = points
225225
226226{-| A rectangle with a given width and height. -}
227−rect : number -> number -> Shape
227+rect : Float -> Float -> Shape
228228rect w h = let hw = w/2
229229 hh = h/2
230230 in [ (0-hw,0-hh), (0-hw,hh), (hw,hh), (hw,0-hh) ]
231231
232232{-| A square with a given edge length. -}
233−square : number -> Shape
233+square : Float -> Shape
234234square n = rect n n
235235
236236{-| An oval with a given width and height. -}
237−oval : number -> number -> Shape
237+oval : Float -> Float -> Shape
238238oval w h =
239239 let n = 50
240240 t = 2 * pi / n
@@ -244,7 +244,7 @@ oval w h =
244244 in List.map f [0..n-1]
245245
246246{-| A circle with a given radius. -}
247−circle : number -> Shape
247+circle : Float -> Shape
248248circle r = oval (2*r) (2*r)
249249
250250{-| A regular polygon with N sides. The first argument specifies the number
@@ -253,7 +253,7 @@ of sides and the second is the radius. So to create a pentagon with radius
253253
254254 ngon 5 30
255255-}
256−ngon : Int -> number -> Shape
256+ngon : Int -> Float -> Shape
257257ngon n r =
258258 let m = toFloat n
259259 t = 2 * pi / m