Skip to content

Commit

Permalink
emit type error
Browse files Browse the repository at this point in the history
  • Loading branch information
ascandone committed Aug 15, 2024
1 parent 1a5a2b2 commit d75c752
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 5 deletions.
42 changes: 41 additions & 1 deletion src/typecheck/analyse.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import { test, expect } from "vitest";
import { Analysis } from "./analyse";
import { typeToString } from "./type";
import { DuplicateDeclaration, ErrorInfo, UnboundVariable } from "../errors";
import {
DuplicateDeclaration,
ErrorInfo,
TypeMismatch,
UnboundVariable,
} from "../errors";
import { spanOf } from "./typedAst/__test__/utils";

test("infer int", () => {
Expand Down Expand Up @@ -157,6 +162,41 @@ test("application return type", () => {
});
});

test("application args should be typechecked", () => {
const a = new Analysis(
"Main",
`
extern type Ret
extern type T
extern let c: T
extern let f: Fn(T, T) -> Ret
pub let x = f(42, c)
`,
);

expect(a.errors).toEqual<ErrorInfo[]>([
{
description: new TypeMismatch(
{
type: "named",
args: [],
moduleName: "Main",
name: "T",
},
{
type: "named",
moduleName: "Int",
name: "Int",
args: [],
},
),
span: spanOf(a.source, "42"),
},
]);
});

function getTypes(a: Analysis): Record<string, string> {
const kvs = [...a.getPublicDeclarations()].map((decl) => {
return [decl.binding.name, typeToString(a.getType(decl.binding))];
Expand Down
37 changes: 33 additions & 4 deletions src/typecheck/analyse.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
/* eslint-disable require-yield */
import { ErrorInfo, UnboundVariable } from "../errors";
import {
ErrorInfo,
OccursCheck,
TraitNotSatified,
TypeMismatch,
UnboundVariable,
} from "../errors";
import {
Binding,
ConstLiteral,
SpanMeta,
TypeAst,
UntypedDeclaration,
UntypedExpr,
Expand All @@ -14,7 +21,7 @@ import {
} from "../parser";
import { char, float, int, string, task, unit } from "./core";
import { Deps } from "./resolutionStep";
import { TVar, Type, unify } from "./type";
import { TVar, Type, UnifyError, unify } from "./type";

export type AnalyseOptions = {
dependencies?: Deps;
Expand Down Expand Up @@ -83,8 +90,11 @@ export class Analysis {
}

private unifyNode(node: TypedNode, type: Type) {
unify(this.getType(node), type);
// TODO push err when not undef
const err = unify(this.getType(node), type);
if (err !== undefined) {
this.errors.push(unifyErrToErrorInfo(node, err));
return;
}
}

private unifyNodes(left: TypedNode, right: TypedNode) {
Expand Down Expand Up @@ -246,6 +256,25 @@ export class Analysis {
}
}

function unifyErrToErrorInfo(node: SpanMeta, e: UnifyError): ErrorInfo {
switch (e.type) {
case "missing-trait":
return {
span: node.span,
description: new TraitNotSatified(e.type_, e.trait),
};

case "type-mismatch":
return {
span: node.span,
description: new TypeMismatch(e.left, e.right),
};

case "occurs-check":
return { span: node.span, description: new OccursCheck() };
}
}

// Keep this in sync with core
function getConstantType(x: ConstLiteral): Type {
// Keep this in sync with core
Expand Down

0 comments on commit d75c752

Please sign in to comment.