diff --git a/src/typecheck/typecheck.ts b/src/typecheck/typecheck.ts index 73e1300e..fa2503f6 100644 --- a/src/typecheck/typecheck.ts +++ b/src/typecheck/typecheck.ts @@ -2,15 +2,15 @@ import { ConstLiteral, Expr, Program, Statement } from "../ast"; import { TVar, Type, unify, Context, generalize, instantiate } from "./unify"; export type UnifyErrorType = "type-mismatch" | "occurs-check"; -export type TypeError = +export type TypeError = | { type: "unbound-variable"; ident: string; - node: Node; + node: Expr; } | { type: UnifyErrorType; - node: Node; + node: Expr; left: Type; right: Type; }; @@ -20,9 +20,9 @@ export type TypeMeta = { $: TVar }; export function typecheck( ast: Program, initialContext: Context = {}, -): [Program, TypeError>[]] { +): [Program, TypeError[]] { TVar.resetId(); - const errors: TypeError>[] = []; + const errors: TypeError[] = []; let context: Context = { ...initialContext }; const typedStatements = ast.statements.map>( @@ -50,7 +50,7 @@ export function typecheck( function* typecheckAnnotatedExpr( ast: Expr, context: Context, -): Generator>> { +): Generator> { switch (ast.type) { case "constant": { const t = inferConstant(ast.value); @@ -86,6 +86,7 @@ function* typecheckAnnotatedExpr( return; case "application": + yield* typecheckAnnotatedExpr(ast.caller, context); yield* unifyYieldErr(ast, ast.caller.$.asType(), { type: "fn", args: ast.args.map((arg) => arg.$.asType()), @@ -94,7 +95,6 @@ function* typecheckAnnotatedExpr( for (const arg of ast.args) { yield* typecheckAnnotatedExpr(arg, context); } - yield* typecheckAnnotatedExpr(ast.caller, context); return; case "let": @@ -173,7 +173,7 @@ function* unifyYieldErr( ast: Expr, t1: Type, t2: Type, -): Generator>> { +): Generator> { const e = unify(t1, t2); if (e !== undefined) { yield { type: e.type, left: e.left, right: e.right, node: ast };