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

View file

@ -3,6 +3,9 @@
import "reflect-metadata"
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 { Program } from "../program"
@ -10,9 +13,9 @@ import { parseSourceFile } from "../parser"
import { BoltSourceFile} from "../ast"
import { Frontend } from "../frontend"
global.debug = function (value: any) {
console.error(require('util').inspect(value, { depth: Infinity, colors: true }))
}
//global.print = function (value: any) {
// console.error(require('util').inspect(value, { depth: Infinity, colors: true }))
//}
function toArray<T>(value: T | T[]): T[] {
if (Array.isArray(value)) {
@ -40,6 +43,18 @@ function flatMap<T>(array: T[], proc: (element: T) => T[]) {
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
.command(
@ -75,7 +90,7 @@ yargs
, 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 frontend = new Frontend();
frontend.typeCheck(program);

View file

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

View file

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

View file

@ -9,6 +9,15 @@ export class Emitter {
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.BoltOperator:
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 {
SyntaxKind,

View file

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

View file

@ -1122,6 +1122,12 @@ export class Parser {
body = parseForeignLanguage(target, t3.text, t3.span!.file, t3.span!.start);
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(
@ -1148,16 +1154,21 @@ export class Parser {
assertToken(t0, SyntaxKind.BoltTraitKeyword);
const t1 = tokens.get();
assertToken(t1, SyntaxKind.BoltIdentifier);
let typeParams = null
let lastToken = t1;
const t2 = tokens.peek();
let typeParams = null
let elements = null;
if (t2.kind === SyntaxKind.BoltLtSign || t2.kind === SyntaxKind.BoltBraced) {
if (t2.kind === SyntaxKind.BoltLtSign) {
typeParams = this.parseGenericTypeParameters(tokens);
}
const t3 = tokens.get();
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[]);
setOrigNodeRange(result, firstToken, t3);
setOrigNodeRange(result, firstToken, lastToken);
return result;
}

View file

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