Typeclasses
This commit is contained in:
parent
a4daf88085
commit
8020f9d1a0
6 changed files with 123 additions and 19 deletions
|
|
@ -1,4 +1,4 @@
|
|||
import type { AST, TypeAST, Pattern, Definition, TypeDefinition } from './ast'
|
||||
import type { AST, TypeAST, Pattern, Definition, TypeDefinition, ClassDefinition, InstanceDeclaration } from './ast'
|
||||
import { prettyPrintType } from './ast'
|
||||
|
||||
// Map type var names to their types
|
||||
|
|
@ -155,6 +155,24 @@ function infer(expr: AST, env: TypeEnv, subst: Subst): TypeAST | null {
|
|||
if (err) warn(err, arg);
|
||||
current = applySubst(current.result, subst);
|
||||
}
|
||||
|
||||
// Check typeclass constraints
|
||||
if (expr.func.kind === 'variable') {
|
||||
const constraint = moduleConstraints.get(expr.func.name);
|
||||
if (constraint) {
|
||||
const argType = infer(expr.args[0], env, subst);
|
||||
if (argType) {
|
||||
const resolved = applySubst(argType, subst);
|
||||
if (resolved.kind === 'type-name') {
|
||||
const instances = moduleInstances.get(constraint.className);
|
||||
if (!instances || !instances.has(resolved.name)) {
|
||||
warn(`No instance ${constraint.className} ${resolved.name}`, expr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return current;
|
||||
}
|
||||
|
||||
|
|
@ -309,9 +327,28 @@ function bindPattern(pattern: Pattern, type: TypeAST, env: TypeEnv, subst: Subst
|
|||
}
|
||||
}
|
||||
|
||||
export function typecheck(defs: Definition[], typeDefs: TypeDefinition[] = []) {
|
||||
let moduleConstraints = new Map<string, { param: string, className: string }>();
|
||||
let moduleInstances = new Map<string, Set<string>>();
|
||||
|
||||
export function typecheck(defs: Definition[], typeDefs: TypeDefinition[] = [], classDefs: ClassDefinition[] = [], instances: InstanceDeclaration[] = []) {
|
||||
const env: TypeEnv = new Map();
|
||||
|
||||
// Register instances as a lookup: className -> Set of type names
|
||||
const instanceMap = new Map<string, Set<string>>();
|
||||
for (const inst of instances) {
|
||||
if (!instanceMap.has(inst.className)) instanceMap.set(inst.className, new Set());
|
||||
instanceMap.get(inst.className)!.add(inst.typeName);
|
||||
}
|
||||
moduleInstances = instanceMap;
|
||||
|
||||
// Register class methods with constraints in env
|
||||
for (const cls of classDefs) {
|
||||
for (const method of cls.methods) {
|
||||
env.set(method.name, method.type);
|
||||
moduleConstraints.set(method.name, { param: cls.param, className: cls.name });
|
||||
}
|
||||
}
|
||||
|
||||
// Register constructors
|
||||
for (const td of typeDefs) {
|
||||
const resultType: TypeAST = td.params.length === 0
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue