Type constraints

This commit is contained in:
Dustin Swan 2026-03-28 21:39:53 -06:00
parent f1bba4f58d
commit 784e095345
No known key found for this signature in database
GPG key ID: 30D46587E2100467
4 changed files with 46 additions and 4 deletions

View file

@ -185,7 +185,7 @@ export class Parser {
let annotation: Annotation | undefined;
if (this.current().kind === 'colon') {
this.advance();
annotation = { constraints: [], type: this.parseType() };
annotation = { constraints: this.parsedConstraints, type: this.parseType() };
// Declaration only
if (this.current().kind === 'semicolon') {
@ -629,7 +629,12 @@ export class Parser {
kind === 'open-paren' || kind === 'open-brace';
}
private parsedConstraints: { className: string, typeVar: string }[] = [];
private parseType(): TypeAST {
// Check for constraints: Num a, Eq b :: <type>
this.parsedConstraints = this.tryParseConstraints();
const left = this.parseTypeApply();
if (this.current().kind === 'backslash') {
@ -641,6 +646,34 @@ export class Parser {
return left;
}
private tryParseConstraints(): { className: string, typeVar: string }[] {
// Look ahead for :: to decide if we have constraints
let offset = 0;
let foundDoubleColon = false;
while (true) {
const t = this.peek(offset);
if (t.kind === 'double-colon') { foundDoubleColon = true; break }
if (t.kind === 'backslash' || t.kind === 'semicolon' || t.kind === 'equals' || t.kind === 'eof') break;
offset++;
}
if (!foundDoubleColon) return [];
// Parse constraints: ClassName varName (, ClassName varName)*
const constraints: { className: string, typeVar: string }[] = [];
while (true) {
const className = (this.expect('type-ident') as { value: string }).value;
const typeVar = (this.expect('ident') as { value: string }).value;
constraints.push({ className, typeVar });
if (this.current().kind === 'comma') {
this.advance();
} else {
break;
}
}
this.expect('double-colon');
return constraints;
}
private parseTypeDefinition(): TypeDefinition {
const nameToken = this.advance();
const name = (nameToken as { value: string }).value;