@@ -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