diff --git a/package-lock.json b/package-lock.json index 0a64b7349..3ed725d4f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,6 +15,11 @@ "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==" }, + "@types/events": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz", + "integrity": "sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g==" + }, "@types/fs-extra": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.1.tgz", @@ -23,11 +28,26 @@ "@types/node": "*" } }, + "@types/glob": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.1.tgz", + "integrity": "sha512-1Bh06cbWJUHMC97acuD6UMG29nMt0Aqz1vF3guLfG+kHHJhy3AyohZFFxYk2f7Q1SQIrNwvncxAE0N/9s70F2w==", + "requires": { + "@types/events": "*", + "@types/minimatch": "*", + "@types/node": "*" + } + }, "@types/microtime": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/@types/microtime/-/microtime-2.1.0.tgz", "integrity": "sha1-rb2Z9QGoXIhpXrHv01FYEPJWOTI=" }, + "@types/minimatch": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", + "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==" + }, "@types/minimist": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.0.tgz", diff --git a/package.json b/package.json index c7598c0f6..1d4699819 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "repository": "https://github.com/samvv/Bolt", "dependencies": { "@types/fs-extra": "^9.0.1", + "@types/glob": "^7.1.1", "@types/microtime": "^2.1.0", "@types/minimist": "^1.2.0", "@types/node": "^14.0.5", diff --git a/spec/ast.txt b/spec/ast.txt index 7be3ed512..94bd12c0b 100644 --- a/spec/ast.txt +++ b/spec/ast.txt @@ -56,6 +56,7 @@ node BoltVBar > BoltToken, BoltOperatorLike; node BoltKeyword; +node BoltWhereKeyword > BoltToken, BoltKeyword; node BoltQuoteKeyword > BoltToken, BoltKeyword; node BoltFnKeyword > BoltToken, BoltKeyword; node BoltForeignKeyword > BoltToken, BoltKeyword; @@ -257,6 +258,7 @@ node BoltFunctionDeclaration > BoltFunctionBodyElement, BoltDeclaration { name: BoltSymbol, params: Vec, returnType: Option, + typeParams: Option>, body: Vec, } diff --git a/src/ast.d.ts b/src/ast.d.ts index 817745b48..04ff283a3 100644 --- a/src/ast.d.ts +++ b/src/ast.d.ts @@ -784,6 +784,7 @@ export interface BoltFunctionDeclaration extends SyntaxBase 0) { - tokens.get(); - assertToken(t1, SyntaxKind.BoltComma); - t1 = tokens.peek(); - } - if (t1.kind === SyntaxKind.EndOfFile) { - throw new ParseError(t1, [SyntaxKind.BoltGtSign, SyntaxKind.BoltIdentifier]); - } typeParams.push(this.parseGenericTypeParameter(tokens)); + const t2 = tokens.peek(); + if (t2.kind !== SyntaxKind.BoltComma) { + break; + } + tokens.get(); } - const t3 = tokens.get(); - assertToken(t3, SyntaxKind.BoltGtSign); return typeParams; } @@ -849,7 +842,10 @@ export class Parser { } if (t2.kind === SyntaxKind.BoltLtSign) { + tokens.get(); typeParams = this.parseGenericTypeParameters(tokens); + const t3 = tokens.get(); + assertToken(t3, SyntaxKind.BoltGtSign); t2 = tokens.peek(); } @@ -963,7 +959,10 @@ export class Parser { const t2 = tokens.peek(); if (t2.kind === SyntaxKind.BoltLtSign) { + tokens.get(); typeParams = this.parseGenericTypeParameters(tokens); + const t3 = tokens.get(); + assertToken(t3, SyntaxKind.BoltGtSign); } const t3 = tokens.get(); @@ -982,7 +981,6 @@ export class Parser { let modifiers = 0; let k0 = tokens.peek(); - let lastToken: BoltSyntax; const firstToken = k0; if (k0.kind === SyntaxKind.BoltPubKeyword) { @@ -1012,6 +1010,7 @@ export class Parser { let returnType = null; let body: any = null; // FIXME type-checking should not be disabled let params: BoltParameter[] = []; + let typeParams = null; // Parse parameters @@ -1095,24 +1094,26 @@ export class Parser { } - if (params.length > 0) { - lastToken = params[params.length-1]; - } - // Parse return type const t2 = tokens.peek(); if (t2.kind === SyntaxKind.BoltRArrow) { - lastToken = t2; tokens.get(); returnType = this.parseTypeExpression(tokens); } + // Parse second possible version of generic type parameters + + const t4 = tokens.peek(); + if (t4.kind === SyntaxKind.BoltWhereKeyword) { + tokens.get(); + typeParams = this.parseGenericTypeParameters(tokens); + } + // Parse function body const t3 = tokens.peek(); if (t3.kind === SyntaxKind.BoltBraced) { - lastToken = t3; tokens.get(); switch (target) { case "Bolt": @@ -1136,9 +1137,10 @@ export class Parser { name, params, returnType, + typeParams, body ); - setOrigNodeRange(result, firstToken, lastToken!); + setOrigNodeRange(result, firstToken, t3); return result; } @@ -1160,7 +1162,9 @@ export class Parser { let elements = null; if (t2.kind === SyntaxKind.BoltLtSign || t2.kind === SyntaxKind.BoltBraced) { if (t2.kind === SyntaxKind.BoltLtSign) { + tokens.get(); typeParams = this.parseGenericTypeParameters(tokens); + tokens.get(); } const t3 = tokens.get(); assertToken(t3, SyntaxKind.BoltBraced); diff --git a/stdlib/math.bolt b/stdlib/math.bolt index bb2fea185..adba90709 100644 --- a/stdlib/math.bolt +++ b/stdlib/math.bolt @@ -27,10 +27,9 @@ fn (a: N) * (b: N) -> N where N: Num { // precedence a + b < a * b; pub fn fac(n: I) -> I where I: int { - if n == 0 { - return 1 - } else { - return fac(n-1) + match n { + 0 => 1, + i => i * fac(i-1), } }