Type constraints
This commit is contained in:
parent
f1bba4f58d
commit
784e095345
4 changed files with 46 additions and 4 deletions
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue