Type constructors
This commit is contained in:
parent
635f12490d
commit
668ee3e4d8
4 changed files with 50 additions and 17 deletions
|
|
@ -1,4 +1,4 @@
|
|||
import type { AST, TypeAST, Pattern, Definition } from './ast'
|
||||
import type { AST, TypeAST, Pattern, Definition, TypeDefinition } from './ast'
|
||||
import { prettyPrintType } from './ast'
|
||||
|
||||
// Map type var names to their types
|
||||
|
|
@ -241,8 +241,26 @@ function bindPattern(pattern: Pattern, type: TypeAST, env: TypeEnv, subst: Subst
|
|||
case 'literal':
|
||||
return null;
|
||||
case 'constructor':
|
||||
// TODO: look up ctor arg types
|
||||
break;
|
||||
// look up ctor types
|
||||
const ctorType = env.get(pattern.name);
|
||||
if (!ctorType) return null;
|
||||
const fresh = freshen(ctorType, subst);
|
||||
|
||||
if (pattern.args.length === 0) {
|
||||
unify(fresh, t, subst);
|
||||
return null;
|
||||
}
|
||||
|
||||
let cur = fresh;
|
||||
for (const arg of pattern.args) {
|
||||
if (cur.kind !== 'type-function') return null;
|
||||
const err = bindPattern(arg, cur.param, env, subst);
|
||||
if (err) return err;
|
||||
cur = applySubst(cur.result, subst);
|
||||
}
|
||||
|
||||
unify(cur, t, subst);
|
||||
return null;
|
||||
case 'list':
|
||||
case 'list-spread':
|
||||
if (t.kind === 'type-apply' && t.constructor.kind === 'type-name' && t.constructor.name === 'List' && t.args.length === 1) {
|
||||
|
|
@ -274,9 +292,28 @@ function bindPattern(pattern: Pattern, type: TypeAST, env: TypeEnv, subst: Subst
|
|||
}
|
||||
}
|
||||
|
||||
export function typecheck(defs: Definition[]) {
|
||||
export function typecheck(defs: Definition[], typeDefs: TypeDefinition[] = []) {
|
||||
const env: TypeEnv = new Map();
|
||||
|
||||
// Register constructors
|
||||
for (const td of typeDefs) {
|
||||
const resultType: TypeAST = td.params.length === 0
|
||||
? { kind: 'type-name', name: td.name }
|
||||
: { kind: 'type-apply', constructor: { kind: 'type-name', name: td.name }, args: td.params.map(p => ({ kind: 'type-var', name: p })) };
|
||||
|
||||
for (const ctor of td.constructors) {
|
||||
if (ctor.args.length === 0) {
|
||||
env.set(ctor.name, resultType);
|
||||
} else {
|
||||
let fnType: TypeAST = resultType;
|
||||
for (let i = ctor.args.length - 1; i >= 0; i--) {
|
||||
fnType = { kind: 'type-function', param: ctor.args[0], result: fnType };
|
||||
}
|
||||
env.set(ctor.name, fnType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Register all annotated defs in env first so they can ref eachother
|
||||
for (const def of defs) {
|
||||
if (def.annotation) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue