git.iko.soy/rowtype-yoga/purescript-native
on golang help sign in
Better error messages
commitcfac1b7ca35095936f1ea34029f34add074796da authorPhil Freeman <paf31@cantab.net> dateSun 24 Nov 2013, 15:24 (13 years ago) parent1e6bac6
3 files changed+37−44
examples/failing/Arrays.ps+1−1 src/Language/PureScript/TypeChecker.hs+7−7 src/Language/PureScript/TypeChecker/Types.hs+29−36
examples/failing/Arrays.ps+1−1
@@ -1 +1 @@
1−test = \arr -> arr ! 0 ! 0
1+test = \arr -> arr !! (0 !! 0)
src/Language/PureScript/TypeChecker.hs+7−7
@@ -42,14 +42,14 @@ import Control.Monad.Error
4242typeCheckAll :: [Declaration] -> Check ()
4343typeCheckAll [] = return ()
4444typeCheckAll (DataDeclaration name args dctors : rest) = do
45− rethrow (("Error in type constructor " ++ show name ++ ": ") ++) $ do
45+ rethrow (("Error in type constructor " ++ show name ++ ":\n") ++) $ do
4646 env <- getEnv
4747 modulePath <- checkModulePath `fmap` get
4848 guardWith (show name ++ " is already defined") $ not $ M.member (modulePath, name) (types env)
4949 ctorKind <- kindsOf (Just name) args (mapMaybe snd dctors)
5050 putEnv $ env { types = M.insert (modulePath, name) (ctorKind, Data) (types env) }
5151 forM_ dctors $ \(dctor, maybeTy) ->
52− rethrow (("Error in data constructor " ++ show name ++ ": ") ++) $ do
52+ rethrow (("Error in data constructor " ++ show name ++ ":\n") ++) $ do
5353 env' <- getEnv
5454 guardWith (show dctor ++ " is already defined") $ not $ M.member (modulePath, dctor) (dataConstructors env')
5555 let retTy = foldl TypeApp (TypeConstructor (Qualified modulePath name)) (map TypeVar args)
@@ -58,7 +58,7 @@ typeCheckAll (DataDeclaration name args dctors : rest) = do
5858 putEnv $ env' { dataConstructors = M.insert (modulePath, dctor) polyType (dataConstructors env') }
5959 typeCheckAll rest
6060typeCheckAll (TypeSynonymDeclaration name args ty : rest) = do
61− rethrow (("Error in type synonym " ++ show name ++ ": ") ++) $ do
61+ rethrow (("Error in type synonym " ++ show name ++ ":\n") ++) $ do
6262 env <- getEnv
6363 modulePath <- checkModulePath `fmap` get
6464 guardWith (show name ++ " is already defined") $ not $ M.member (modulePath, name) (types env)
@@ -70,7 +70,7 @@ typeCheckAll (TypeDeclaration name ty : ValueDeclaration name' val : rest) | nam
7070 typeCheckAll (ValueDeclaration name (TypedValue val ty) : rest)
7171typeCheckAll (TypeDeclaration name _ : _) = throwError $ "Orphan type declaration for " ++ show name
7272typeCheckAll (ValueDeclaration name val : rest) = do
73− rethrow (("Error in declaration " ++ show name ++ ": ") ++) $ do
73+ rethrow (("Error in declaration " ++ show name ++ ":\n") ++) $ do
7474 env <- getEnv
7575 modulePath <- checkModulePath `fmap` get
7676 case M.lookup (modulePath, name) (names env) of
@@ -86,7 +86,7 @@ typeCheckAll (ExternDataDeclaration name kind : rest) = do
8686 putEnv $ env { types = M.insert (modulePath, name) (kind, TypeSynonym) (types env) }
8787 typeCheckAll rest
8888typeCheckAll (ExternMemberDeclaration member name ty : rest) = do
89− rethrow (("Error in foreign import member declaration " ++ show name ++ ": ") ++) $ do
89+ rethrow (("Error in foreign import member declaration " ++ show name ++ ":\n") ++) $ do
9090 env <- getEnv
9191 modulePath <- checkModulePath `fmap` get
9292 kind <- kindOf ty
@@ -100,7 +100,7 @@ typeCheckAll (ExternMemberDeclaration member name ty : rest) = do
100100 _ -> throwError "Foreign member declarations must have function types, with an single argument."
101101 typeCheckAll rest
102102typeCheckAll (ExternDeclaration name ty : rest) = do
103− rethrow (("Error in foreign import declaration " ++ show name ++ ": ") ++) $ do
103+ rethrow (("Error in foreign import declaration " ++ show name ++ ":\n") ++) $ do
104104 env <- getEnv
105105 modulePath <- checkModulePath `fmap` get
106106 kind <- kindOf ty
@@ -126,7 +126,7 @@ typeCheckAll (ImportDeclaration modulePath idents : rest) = do
126126 Nothing -> bindIdents (map snd $ filterModule env) currentModule env
127127 Just idents -> bindIdents idents currentModule env
128128 typeCheckAll rest
129− where errorMessage = (("Error in import declaration " ++ show modulePath ++ ": ") ++)
129+ where errorMessage = (("Error in import declaration " ++ show modulePath ++ ":\n") ++)
130130 filterModule = filter ((== modulePath) . fst) . M.keys . names
131131 moduleExists env = not $ null $ filterModule env
132132 bindIdents idents currentModule env =
src/Language/PureScript/TypeChecker/Types.hs+29−36
@@ -289,27 +289,29 @@ ensureNoDuplicateProperties :: [(String, Value)] -> Check ()
289289ensureNoDuplicateProperties ps = guardWith "Duplicate property names" $ length (nub . map fst $ ps) == length ps
290290
291291infer :: M.Map Ident Type -> Value -> Subst Check Type
292−infer _ (NumericLiteral _) = return Number
293−infer _ (StringLiteral _) = return String
294−infer _ (BooleanLiteral _) = return Boolean
295−infer m (ArrayLiteral vals) = do
292+infer m val = rethrow (\e -> "Error inferring type of term " ++ prettyPrintValue val ++ ":\n" ++ e) $ infer' m val
293+
294+infer' _ (NumericLiteral _) = return Number
295+infer' _ (StringLiteral _) = return String
296+infer' _ (BooleanLiteral _) = return Boolean
297+infer' m (ArrayLiteral vals) = do
296298 ts <- mapM (infer m) vals
297299 arr <- fresh
298300 forM_ ts $ \t -> arr ~~ Array t
299301 return arr
300−infer m (Unary op val) = do
302+infer' m (Unary op val) = do
301303 t <- infer m val
302304 inferUnary op t
303−infer m (Binary op left right) = do
305+infer' m (Binary op left right) = do
304306 t1 <- infer m left
305307 t2 <- infer m right
306308 inferBinary op t1 t2
307−infer m (ObjectLiteral ps) = do
309+infer' m (ObjectLiteral ps) = do
308310 lift $ ensureNoDuplicateProperties ps
309311 ts <- mapM (infer m . snd) ps
310312 let fields = zipWith (\(name, _) t -> (name, t)) ps ts
311313 return $ Object $ typesToRow fields
312−infer m (ObjectUpdate o ps) = do
314+infer' m (ObjectUpdate o ps) = do
313315 lift $ ensureNoDuplicateProperties ps
314316 obj <- infer m o
315317 row <- fresh
@@ -317,29 +319,27 @@ infer m (ObjectUpdate o ps) = do
317319 let tys = zipWith (\(name, _) t -> (name, t)) ps ts
318320 obj ~~ Object (rowFromList (tys, row))
319321 return obj
320−infer m (Indexer index val) = do
322+infer' m (Indexer index val) = do
321323 el <- fresh
322324 check m index Number
323− t2 <- infer m val
324− t2 ~~ Array el
325+ check m val (Array el)
325326 return el
326−infer m (Accessor prop val) = do
327− obj <- infer m val
327+infer' m (Accessor prop val) = do
328328 field <- fresh
329329 rest <- fresh
330− obj ~~ Object (RCons prop field rest)
330+ check m val (Object (RCons prop field rest))
331331 return field
332−infer m v@(Abs args ret) = do
332+infer' m v@(Abs args ret) = do
333333 ts <- replicateM (length args) fresh
334334 let m' = m `M.union` M.fromList (zip args ts)
335335 body <- infer m' ret
336336 return $ Function ts body
337−infer m v@(App f xs) = do
337+infer' m v@(App f xs) = do
338338 t1 <- infer m f
339339 ret <- fresh
340340 checkFunctionApplication m t1 xs ret
341341 return ret
342−infer m v@(Var var@(Qualified mp name)) = do
342+infer' m v@(Var var@(Qualified mp name)) = do
343343 case mp of
344344 ModulePath [] ->
345345 case M.lookup name m of
@@ -353,29 +353,29 @@ infer m v@(Var var@(Qualified mp name)) = do
353353 case M.lookup (qualify modulePath var) (names env) of
354354 Nothing -> throwError $ show var ++ " is undefined"
355355 Just (ty, _) -> lift $ replaceAllTypeSynonyms ty
356−infer m (Block ss) = do
356+infer' m (Block ss) = do
357357 ret <- fresh
358358 (allCodePathsReturn, _) <- checkBlock m M.empty ret ss
359359 guardWith "Block is missing a return statement" allCodePathsReturn
360360 return ret
361−infer m v@(Constructor c) = do
361+infer' m v@(Constructor c) = do
362362 env <- lift getEnv
363363 modulePath <- checkModulePath `fmap` lift get
364364 case M.lookup (qualify modulePath c) (dataConstructors env) of
365365 Nothing -> throwError $ "Constructor " ++ show c ++ " is undefined"
366366 Just ty -> lift $ replaceAllTypeSynonyms ty
367−infer m (Case val binders) = do
367+infer' m (Case val binders) = do
368368 t1 <- infer m val
369369 ret <- fresh
370370 checkBinders m t1 ret binders
371371 return ret
372−infer m v@(IfThenElse cond th el) = do
372+infer' m v@(IfThenElse cond th el) = do
373373 check m cond Boolean
374374 t2 <- infer m th
375375 t3 <- infer m el
376376 t2 ~~ t3
377377 return t2
378−infer m v@(TypedValue val ty) = do
378+infer' m v@(TypedValue val ty) = do
379379 kind <- lift $ kindOf ty
380380 guardWith ("Expected type of kind *, was " ++ prettyPrintKind kind) $ kind == Star
381381 ty' <- lift $ replaceAllTypeSynonyms ty
@@ -514,8 +514,7 @@ checkBinders :: M.Map Ident Type -> Type -> Type -> [(Binder, Value)] -> Subst C
514514checkBinders _ _ _ [] = return ()
515515checkBinders m nval ret ((binder, val):bs) = do
516516 m1 <- inferGuardedBinder m nval binder
517− t <- infer (m `M.union` m1) val
518− t ~~ ret
517+ check (m `M.union` m1) val ret
519518 checkBinders m nval ret bs
520519
521520assignVariable :: Ident -> M.Map Ident Type -> Subst Check ()
@@ -536,8 +535,7 @@ checkStatement m mass ret (Assignment ident val) = do
536535 Just ty -> do t ~~ ty
537536 return (False, mass)
538537checkStatement m mass ret (While val inner) = do
539− t1 <- infer m val
540− t1 ~~ Boolean
538+ check m val Boolean
541539 (allCodePathsReturn, _) <- checkBlock m mass ret inner
542540 return (allCodePathsReturn, mass)
543541checkStatement m mass ret (If ifst) = do
@@ -545,18 +543,15 @@ checkStatement m mass ret (If ifst) = do
545543 return (allCodePathsReturn, mass)
546544checkStatement m mass ret (For ident start end inner) = do
547545 assignVariable ident (m `M.union` mass)
548− t1 <- infer (m `M.union` mass) start
549− t1 ~~ Number
550− t2 <- infer (m `M.union` mass) end
551− t2 ~~ Number
546+ check (m `M.union` mass) start Number
547+ check (m `M.union` mass) end Number
552548 let mass1 = M.insert ident Number mass
553549 (allCodePathsReturn, _) <- checkBlock (m `M.union` mass1) mass1 ret inner
554550 return (allCodePathsReturn, mass)
555551checkStatement m mass ret (ForEach ident vals inner) = do
556552 assignVariable ident (m `M.union` mass)
557553 val <- fresh
558− t1 <- infer (m `M.union` mass) vals
559− t1 ~~ Array val
554+ check (m `M.union` mass) vals (Array val)
560555 let mass1 = M.insert ident val mass
561556 (allCodePathsReturn, _) <- checkBlock (m `M.union` mass1) mass1 ret inner
562557 guardWith "Cannot return from within a foreach block" $ not allCodePathsReturn
@@ -567,13 +562,11 @@ checkStatement m mass ret (Return val) = do
567562
568563checkIfStatement :: M.Map Ident Type -> M.Map Ident Type -> Type -> IfStatement -> Subst Check Bool
569564checkIfStatement m mass ret (IfStatement val thens Nothing) = do
570− t1 <- infer m val
571− t1 ~~ Boolean
565+ check m val Boolean
572566 _ <- checkBlock m mass ret thens
573567 return False
574568checkIfStatement m mass ret (IfStatement val thens (Just elses)) = do
575− t1 <- infer m val
576− t1 ~~ Boolean
569+ check m val Boolean
577570 (allCodePathsReturn1, _) <- checkBlock m mass ret thens
578571 allCodePathsReturn2 <- checkElseStatement m mass ret elses
579572 return $ allCodePathsReturn1 && allCodePathsReturn2