Some minor fixes and extensions to parser and type checker

This commit is contained in:
Sam Vervaeck 2020-05-24 22:23:18 +02:00
parent 95d1b8825e
commit d0aed2405f
9 changed files with 198 additions and 144 deletions

264
src/ast.d.ts vendored
View file

@ -21,131 +21,132 @@ export const enum SyntaxKind {
BoltExMark = 26, BoltExMark = 26,
BoltLtSign = 27, BoltLtSign = 27,
BoltVBar = 28, BoltVBar = 28,
BoltQuoteKeyword = 30, BoltWhereKeyword = 30,
BoltFnKeyword = 31, BoltQuoteKeyword = 31,
BoltForeignKeyword = 32, BoltFnKeyword = 32,
BoltForKeyword = 33, BoltForeignKeyword = 33,
BoltLetKeyword = 34, BoltForKeyword = 34,
BoltReturnKeyword = 35, BoltLetKeyword = 35,
BoltLoopKeyword = 36, BoltReturnKeyword = 36,
BoltYieldKeyword = 37, BoltLoopKeyword = 37,
BoltMatchKeyword = 38, BoltYieldKeyword = 38,
BoltImportKeyword = 39, BoltMatchKeyword = 39,
BoltPubKeyword = 40, BoltImportKeyword = 40,
BoltModKeyword = 41, BoltPubKeyword = 41,
BoltMutKeyword = 42, BoltModKeyword = 42,
BoltEnumKeyword = 43, BoltMutKeyword = 43,
BoltStructKeyword = 44, BoltEnumKeyword = 44,
BoltTypeKeyword = 45, BoltStructKeyword = 45,
BoltTraitKeyword = 46, BoltTypeKeyword = 46,
BoltImplKeyword = 47, BoltTraitKeyword = 47,
BoltParenthesized = 49, BoltImplKeyword = 48,
BoltBraced = 50, BoltParenthesized = 50,
BoltBracketed = 51, BoltBraced = 51,
BoltSourceFile = 52, BoltBracketed = 52,
BoltQualName = 53, BoltSourceFile = 53,
BoltReferenceTypeExpression = 55, BoltQualName = 54,
BoltFunctionTypeExpression = 56, BoltReferenceTypeExpression = 56,
BoltTypeParameter = 57, BoltFunctionTypeExpression = 57,
BoltBindPattern = 59, BoltTypeParameter = 58,
BoltTypePattern = 60, BoltBindPattern = 60,
BoltExpressionPattern = 61, BoltTypePattern = 61,
BoltTuplePatternElement = 62, BoltExpressionPattern = 62,
BoltTuplePattern = 63, BoltTuplePatternElement = 63,
BoltRecordFieldPattern = 64, BoltTuplePattern = 64,
BoltRecordPattern = 65, BoltRecordFieldPattern = 65,
BoltQuoteExpression = 67, BoltRecordPattern = 66,
BoltReferenceExpression = 68, BoltQuoteExpression = 68,
BoltMemberExpression = 69, BoltReferenceExpression = 69,
BoltFunctionExpression = 70, BoltMemberExpression = 70,
BoltCallExpression = 71, BoltFunctionExpression = 71,
BoltYieldExpression = 72, BoltCallExpression = 72,
BoltMatchArm = 73, BoltYieldExpression = 73,
BoltMatchExpression = 74, BoltMatchArm = 74,
BoltCase = 75, BoltMatchExpression = 75,
BoltCaseExpression = 76, BoltCase = 76,
BoltBlockExpression = 77, BoltCaseExpression = 77,
BoltConstantExpression = 78, BoltBlockExpression = 78,
BoltReturnStatement = 80, BoltConstantExpression = 79,
BoltConditionalCase = 81, BoltReturnStatement = 81,
BoltConditionalStatement = 82, BoltConditionalCase = 82,
BoltResumeStatement = 83, BoltConditionalStatement = 83,
BoltExpressionStatement = 84, BoltResumeStatement = 84,
BoltParameter = 85, BoltExpressionStatement = 85,
BoltModule = 89, BoltParameter = 86,
BoltFunctionDeclaration = 91, BoltModule = 90,
BoltVariableDeclaration = 92, BoltFunctionDeclaration = 92,
BoltPlainImportSymbol = 94, BoltVariableDeclaration = 93,
BoltImportDeclaration = 95, BoltPlainImportSymbol = 95,
BoltTraitDeclaration = 96, BoltImportDeclaration = 96,
BoltImplDeclaration = 97, BoltTraitDeclaration = 97,
BoltTypeAliasDeclaration = 98, BoltImplDeclaration = 98,
BoltRecordField = 100, BoltTypeAliasDeclaration = 99,
BoltRecordDeclaration = 101, BoltRecordField = 101,
BoltMacroCall = 103, BoltRecordDeclaration = 102,
JSOperator = 106, BoltMacroCall = 104,
JSIdentifier = 107, JSOperator = 107,
JSString = 108, JSIdentifier = 108,
JSInteger = 109, JSString = 109,
JSFromKeyword = 110, JSInteger = 110,
JSReturnKeyword = 111, JSFromKeyword = 111,
JSTryKeyword = 112, JSReturnKeyword = 112,
JSFinallyKeyword = 113, JSTryKeyword = 113,
JSCatchKeyword = 114, JSFinallyKeyword = 114,
JSImportKeyword = 115, JSCatchKeyword = 115,
JSAsKeyword = 116, JSImportKeyword = 116,
JSConstKeyword = 117, JSAsKeyword = 117,
JSLetKeyword = 118, JSConstKeyword = 118,
JSExportKeyword = 119, JSLetKeyword = 119,
JSFunctionKeyword = 120, JSExportKeyword = 120,
JSWhileKeyword = 121, JSFunctionKeyword = 121,
JSForKeyword = 122, JSWhileKeyword = 122,
JSCloseBrace = 123, JSForKeyword = 123,
JSCloseBracket = 124, JSCloseBrace = 124,
JSCloseParen = 125, JSCloseBracket = 125,
JSOpenBrace = 126, JSCloseParen = 126,
JSOpenBracket = 127, JSOpenBrace = 127,
JSOpenParen = 128, JSOpenBracket = 128,
JSSemi = 129, JSOpenParen = 129,
JSComma = 130, JSSemi = 130,
JSDot = 131, JSComma = 131,
JSDotDotDot = 132, JSDot = 132,
JSMulOp = 133, JSDotDotDot = 133,
JSAddOp = 134, JSMulOp = 134,
JSDivOp = 135, JSAddOp = 135,
JSSubOp = 136, JSDivOp = 136,
JSLtOp = 137, JSSubOp = 137,
JSGtOp = 138, JSLtOp = 138,
JSBOrOp = 139, JSGtOp = 139,
JSBXorOp = 140, JSBOrOp = 140,
JSBAndOp = 141, JSBXorOp = 141,
JSBNotOp = 142, JSBAndOp = 142,
JSNotOp = 143, JSBNotOp = 143,
JSBindPattern = 145, JSNotOp = 144,
JSConstantExpression = 147, JSBindPattern = 146,
JSMemberExpression = 148, JSConstantExpression = 148,
JSCallExpression = 149, JSMemberExpression = 149,
JSBinaryExpression = 150, JSCallExpression = 150,
JSUnaryExpression = 151, JSBinaryExpression = 151,
JSNewExpression = 152, JSUnaryExpression = 152,
JSSequenceExpression = 153, JSNewExpression = 153,
JSConditionalExpression = 154, JSSequenceExpression = 154,
JSLiteralExpression = 156, JSConditionalExpression = 155,
JSReferenceExpression = 157, JSLiteralExpression = 157,
JSCatchBlock = 161, JSReferenceExpression = 158,
JSTryCatchStatement = 162, JSCatchBlock = 162,
JSExpressionStatement = 163, JSTryCatchStatement = 163,
JSConditionalCase = 164, JSExpressionStatement = 164,
JSConditionalStatement = 165, JSConditionalCase = 165,
JSReturnStatement = 166, JSConditionalStatement = 166,
JSParameter = 167, JSReturnStatement = 167,
JSImportStarBinding = 171, JSParameter = 168,
JSImportAsBinding = 172, JSImportStarBinding = 172,
JSImportDeclaration = 173, JSImportAsBinding = 173,
JSFunctionDeclaration = 174, JSImportDeclaration = 174,
JSArrowFunctionDeclaration = 175, JSFunctionDeclaration = 175,
JSLetDeclaration = 176, JSArrowFunctionDeclaration = 176,
JSSourceFile = 177, JSLetDeclaration = 177,
JSSourceFile = 178,
} }
@ -195,6 +196,7 @@ export type Token
| BoltExMark | BoltExMark
| BoltLtSign | BoltLtSign
| BoltVBar | BoltVBar
| BoltWhereKeyword
| BoltQuoteKeyword | BoltQuoteKeyword
| BoltFnKeyword | BoltFnKeyword
| BoltForeignKeyword | BoltForeignKeyword
@ -291,6 +293,7 @@ export type BoltToken
| BoltExMark | BoltExMark
| BoltLtSign | BoltLtSign
| BoltVBar | BoltVBar
| BoltWhereKeyword
| BoltQuoteKeyword | BoltQuoteKeyword
| BoltFnKeyword | BoltFnKeyword
| BoltForeignKeyword | BoltForeignKeyword
@ -412,7 +415,8 @@ export interface BoltVBar extends SyntaxBase<SyntaxKind.BoltVBar> {
} }
export type BoltKeyword export type BoltKeyword
= BoltQuoteKeyword = BoltWhereKeyword
| BoltQuoteKeyword
| BoltFnKeyword | BoltFnKeyword
| BoltForeignKeyword | BoltForeignKeyword
| BoltForKeyword | BoltForKeyword
@ -432,6 +436,10 @@ export type BoltKeyword
| BoltImplKeyword | BoltImplKeyword
export interface BoltWhereKeyword extends SyntaxBase<SyntaxKind.BoltWhereKeyword> {
kind: SyntaxKind.BoltWhereKeyword;
}
export interface BoltQuoteKeyword extends SyntaxBase<SyntaxKind.BoltQuoteKeyword> { export interface BoltQuoteKeyword extends SyntaxBase<SyntaxKind.BoltQuoteKeyword> {
kind: SyntaxKind.BoltQuoteKeyword; kind: SyntaxKind.BoltQuoteKeyword;
} }
@ -1294,6 +1302,7 @@ export type BoltSyntax
| BoltExMark | BoltExMark
| BoltLtSign | BoltLtSign
| BoltVBar | BoltVBar
| BoltWhereKeyword
| BoltQuoteKeyword | BoltQuoteKeyword
| BoltFnKeyword | BoltFnKeyword
| BoltForeignKeyword | BoltForeignKeyword
@ -1446,6 +1455,7 @@ export type Syntax
| BoltExMark | BoltExMark
| BoltLtSign | BoltLtSign
| BoltVBar | BoltVBar
| BoltWhereKeyword
| BoltQuoteKeyword | BoltQuoteKeyword
| BoltFnKeyword | BoltFnKeyword
| BoltForeignKeyword | BoltForeignKeyword
@ -1596,6 +1606,7 @@ export function createBoltGtSign(span?: TextSpan | null): BoltGtSign;
export function createBoltExMark(span?: TextSpan | null): BoltExMark; export function createBoltExMark(span?: TextSpan | null): BoltExMark;
export function createBoltLtSign(span?: TextSpan | null): BoltLtSign; export function createBoltLtSign(span?: TextSpan | null): BoltLtSign;
export function createBoltVBar(span?: TextSpan | null): BoltVBar; export function createBoltVBar(span?: TextSpan | null): BoltVBar;
export function createBoltWhereKeyword(span?: TextSpan | null): BoltWhereKeyword;
export function createBoltQuoteKeyword(span?: TextSpan | null): BoltQuoteKeyword; export function createBoltQuoteKeyword(span?: TextSpan | null): BoltQuoteKeyword;
export function createBoltFnKeyword(span?: TextSpan | null): BoltFnKeyword; export function createBoltFnKeyword(span?: TextSpan | null): BoltFnKeyword;
export function createBoltForeignKeyword(span?: TextSpan | null): BoltForeignKeyword; export function createBoltForeignKeyword(span?: TextSpan | null): BoltForeignKeyword;
@ -1749,6 +1760,7 @@ export function isBoltExMark(value: any): value is BoltExMark;
export function isBoltLtSign(value: any): value is BoltLtSign; export function isBoltLtSign(value: any): value is BoltLtSign;
export function isBoltVBar(value: any): value is BoltVBar; export function isBoltVBar(value: any): value is BoltVBar;
export function isBoltKeyword(value: any): value is BoltKeyword; export function isBoltKeyword(value: any): value is BoltKeyword;
export function isBoltWhereKeyword(value: any): value is BoltWhereKeyword;
export function isBoltQuoteKeyword(value: any): value is BoltQuoteKeyword; export function isBoltQuoteKeyword(value: any): value is BoltQuoteKeyword;
export function isBoltFnKeyword(value: any): value is BoltFnKeyword; export function isBoltFnKeyword(value: any): value is BoltFnKeyword;
export function isBoltForeignKeyword(value: any): value is BoltForeignKeyword; export function isBoltForeignKeyword(value: any): value is BoltForeignKeyword;

View file

@ -3,6 +3,9 @@
import "reflect-metadata" import "reflect-metadata"
import "source-map-support/register" import "source-map-support/register"
import { sync as globSync } from "glob"
import * as path from "path"
import * as fs from "fs"
import yargs from "yargs" import yargs from "yargs"
import { Program } from "../program" import { Program } from "../program"
@ -10,9 +13,9 @@ import { parseSourceFile } from "../parser"
import { BoltSourceFile} from "../ast" import { BoltSourceFile} from "../ast"
import { Frontend } from "../frontend" import { Frontend } from "../frontend"
global.debug = function (value: any) { //global.print = function (value: any) {
console.error(require('util').inspect(value, { depth: Infinity, colors: true })) // console.error(require('util').inspect(value, { depth: Infinity, colors: true }))
} //}
function toArray<T>(value: T | T[]): T[] { function toArray<T>(value: T | T[]): T[] {
if (Array.isArray(value)) { if (Array.isArray(value)) {
@ -40,6 +43,18 @@ function flatMap<T>(array: T[], proc: (element: T) => T[]) {
return out return out
} }
function loadAllSourceFiles(filenames: string[]): BoltSourceFile[] {
const sourceFiles = [];
for (const filename of filenames) {
if (fs.statSync(filename).isDirectory()) {
for (const filepath of globSync(path.join(filename, '**/*.bolt'))) {
sourceFiles.push(parseSourceFile(filepath));
}
}
}
return sourceFiles;
}
yargs yargs
.command( .command(
@ -75,7 +90,7 @@ yargs
, args => { , args => {
const sourceFiles = toArray(args.files as string[] | string).map(parseSourceFile); const sourceFiles = loadAllSourceFiles(toArray(args.files as string[] | string));
const program = new Program(sourceFiles); const program = new Program(sourceFiles);
const frontend = new Frontend(); const frontend = new Frontend();
frontend.typeCheck(program); frontend.typeCheck(program);

View file

@ -54,6 +54,7 @@ import {
} from "./diagnostics"; } from "./diagnostics";
import { createAnyType, isOpaqueType, createOpaqueType, Type, createVoidType, createVariantType, isVoidType } from "./types"; import { createAnyType, isOpaqueType, createOpaqueType, Type, createVoidType, createVariantType, isVoidType } from "./types";
import { getReturnStatementsInFunctionBody } from "./common"; import { getReturnStatementsInFunctionBody } from "./common";
import {emit} from "./emitter";
interface SymbolInfo { interface SymbolInfo {
declarations: BoltDeclaration[]; declarations: BoltDeclaration[];
@ -207,6 +208,7 @@ export class TypeChecker {
for (const element of node.elements) { for (const element of node.elements) {
visitSourceElement(element); visitSourceElement(element);
} }
break;
} }
case SyntaxKind.BoltRecordDeclaration: case SyntaxKind.BoltRecordDeclaration:
@ -457,7 +459,7 @@ export class TypeChecker {
{ {
const scope = this.getScopeSurroundingNode(node); const scope = this.getScopeSurroundingNode(node);
const sym = createSymbol(node); const sym = createSymbol(node);
this.addSymbol(node.name.text, scope, sym); this.addSymbol(emit(node.name), scope, sym);
break; break;
} }
@ -473,10 +475,12 @@ export class TypeChecker {
} }
private addSymbol(name: string, scope: Scope, sym: SymbolInfo): void { private addSymbol(name: string, scope: Scope, sym: SymbolInfo): void {
console.error(`Adding symbol ${name}`);
this.symbols.set(`${name}@${(scope as any).id}`, sym); this.symbols.set(`${name}@${(scope as any).id}`, sym);
} }
private addTypeSymbol(name: string, scope: TypeScope, sym: TypeSymbolInfo): void { private addTypeSymbol(name: string, scope: TypeScope, sym: TypeSymbolInfo): void {
console.error(`Adding type symbol ${name}`);
this.typeSymbols.set(`${name}@${(scope as any).id}`, sym); this.typeSymbols.set(`${name}@${(scope as any).id}`, sym);
} }
@ -615,7 +619,7 @@ export class TypeChecker {
scope = parentScope; scope = parentScope;
} }
} }
const sym = this.findSymbolInScopeOf(node.name.name.text, scope); const sym = this.findSymbolInScopeOf(emit(node.name.name), scope);
if (sym === null) { if (sym === null) {
return null; return null;
} }
@ -624,7 +628,7 @@ export class TypeChecker {
public resolveTypeReferenceExpression(node: BoltReferenceTypeExpression): BoltTypeDeclaration | null { public resolveTypeReferenceExpression(node: BoltReferenceTypeExpression): BoltTypeDeclaration | null {
const typeScope = this.getTypeScopeSurroundingNode(node); const typeScope = this.getTypeScopeSurroundingNode(node);
const typeSym = this.findSymbolInTypeScopeOf(node.name.name.text, typeScope); const typeSym = this.findSymbolInTypeScopeOf(emit(node.name.name), typeScope);
if (typeSym === null) { if (typeSym === null) {
return null; return null;
} }

View file

@ -178,6 +178,8 @@ export function describeKind(kind: SyntaxKind): string {
return "an integer" return "an integer"
case SyntaxKind.BoltFnKeyword: case SyntaxKind.BoltFnKeyword:
return "'fn'" return "'fn'"
case SyntaxKind.BoltWhereKeyword:
return "'where'";
case SyntaxKind.BoltQuoteKeyword: case SyntaxKind.BoltQuoteKeyword:
return "'quote'"; return "'quote'";
case SyntaxKind.BoltModKeyword: case SyntaxKind.BoltModKeyword:

View file

@ -9,6 +9,15 @@ export class Emitter {
switch (node.kind) { switch (node.kind) {
case SyntaxKind.BoltQualName:
if (node.modulePath !== null) {
for (const element of node.modulePath) {
out += '.' + element.text;
}
}
out += this.emit(node.name);
break;
case SyntaxKind.BoltIdentifier: case SyntaxKind.BoltIdentifier:
case SyntaxKind.BoltOperator: case SyntaxKind.BoltOperator:
out += node.text; out += node.text;

View file

@ -1,5 +1,6 @@
import { Stream, assertToken, setOrigNodeRange, ParseError } from "../../util" import { Stream } from "../../util"
import { assertToken, setOrigNodeRange, ParseError } from "../../common"
import { import {
SyntaxKind, SyntaxKind,

View file

@ -1,8 +1,6 @@
import XRegExp from "xregexp"
import { TextPos, TextSpan, TextFile } from "../../text" import { TextPos, TextSpan, TextFile } from "../../text"
import { EOF, ScanError } from "../../util" import { EOF, ScanError } from "../../common"
import { import {
JSToken, JSToken,

View file

@ -1122,6 +1122,12 @@ export class Parser {
body = parseForeignLanguage(target, t3.text, t3.span!.file, t3.span!.start); body = parseForeignLanguage(target, t3.text, t3.span!.file, t3.span!.start);
break; break;
} }
} else if (t3.kind !== SyntaxKind.BoltSemi) {
const expected = [ SyntaxKind.BoltBraced, SyntaxKind.BoltSemi ];
if (returnType === null) {
expected.push(SyntaxKind.BoltRArrow);
}
throw new ParseError(t3, expected);
} }
const result = createBoltFunctionDeclaration( const result = createBoltFunctionDeclaration(
@ -1148,16 +1154,21 @@ export class Parser {
assertToken(t0, SyntaxKind.BoltTraitKeyword); assertToken(t0, SyntaxKind.BoltTraitKeyword);
const t1 = tokens.get(); const t1 = tokens.get();
assertToken(t1, SyntaxKind.BoltIdentifier); assertToken(t1, SyntaxKind.BoltIdentifier);
let typeParams = null let lastToken = t1;
const t2 = tokens.peek(); const t2 = tokens.peek();
let typeParams = null
let elements = null;
if (t2.kind === SyntaxKind.BoltLtSign || t2.kind === SyntaxKind.BoltBraced) {
if (t2.kind === SyntaxKind.BoltLtSign) { if (t2.kind === SyntaxKind.BoltLtSign) {
typeParams = this.parseGenericTypeParameters(tokens); typeParams = this.parseGenericTypeParameters(tokens);
} }
const t3 = tokens.get(); const t3 = tokens.get();
assertToken(t3, SyntaxKind.BoltBraced); assertToken(t3, SyntaxKind.BoltBraced);
const elements = this.parseSourceElements(createTokenStream(t3)); elements = this.parseSourceElements(createTokenStream(t3));
lastToken = t3;
}
const result = createBoltTraitDeclaration(modifiers, t1 as BoltIdentifier, typeParams, elements as BoltDeclaration[]); const result = createBoltTraitDeclaration(modifiers, t1 as BoltIdentifier, typeParams, elements as BoltDeclaration[]);
setOrigNodeRange(result, firstToken, t3); setOrigNodeRange(result, firstToken, lastToken);
return result; return result;
} }

View file

@ -48,6 +48,7 @@ import {
createBoltVBar, createBoltVBar,
createBoltColonColon, createBoltColonColon,
createBoltExMark, createBoltExMark,
createBoltWhereKeyword,
} from "./ast" } from "./ast"
export enum PunctType { export enum PunctType {
@ -299,6 +300,7 @@ export class Scanner {
case 'pub': return createBoltPubKeyword(span); case 'pub': return createBoltPubKeyword(span);
case 'mod': return createBoltModKeyword(span); case 'mod': return createBoltModKeyword(span);
case 'fn': return createBoltFnKeyword(span); case 'fn': return createBoltFnKeyword(span);
case 'where': return createBoltWhereKeyword(span);
case 'return': return createBoltReturnKeyword(span); case 'return': return createBoltReturnKeyword(span);
case 'match': return createBoltMatchKeyword(span); case 'match': return createBoltMatchKeyword(span);
case 'yield': return createBoltYieldKeyword(span); case 'yield': return createBoltYieldKeyword(span);