From f765ba6115c28b2cefd125f4a51d0bd1dcdc094c Mon Sep 17 00:00:00 2001 From: Sam Vervaeck Date: Wed, 27 May 2020 17:17:27 +0200 Subject: [PATCH] Fix issue in launch.json --- .vscode/launch.json | 2 +- src/ast-spec.txt | 5 +- src/ast.d.ts | 9 ++- src/common.ts | 2 +- src/debugServer.ts | 5 -- src/emitter.ts | 7 +- src/evaluator.ts | 53 +++++++------ src/frontend.ts | 23 ++---- src/{di.ts => ioc.ts} | 0 src/parser.ts | 157 ++++++++++++++++++++++----------------- src/transforms/expand.ts | 10 +-- 11 files changed, 146 insertions(+), 127 deletions(-) delete mode 100644 src/debugServer.ts rename src/{di.ts => ioc.ts} (100%) diff --git a/.vscode/launch.json b/.vscode/launch.json index 682a3ba4b..b92d0e60a 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -11,7 +11,7 @@ "outputCapture": "std", "skipFiles": [ "${workspaceFolder}/node_modules/**/*.js", - "${workspaceFolder}/lib/***/*.js", + "${workspaceFolder}/lib/**/*.js", "/**" ], "program": "${workspaceFolder}/lib/bin/bolt.js", diff --git a/src/ast-spec.txt b/src/ast-spec.txt index 56834cf8f..dcf76d363 100644 --- a/src/ast-spec.txt +++ b/src/ast-spec.txt @@ -103,7 +103,8 @@ node BoltModulePath { node BoltTypeExpression; node BoltReferenceTypeExpression > BoltTypeExpression { - path: BoltModulePath, + modulePath: Option, + name: BoltIdentifier, arguments: Option>, } @@ -115,7 +116,7 @@ node BoltFunctionTypeExpression > BoltTypeExpression { node BoltTypeParameter { index: usize, name: BoltIdentifier, - typeNode: BoltTypeExpression, + typeNode: Option, defaultType: Option, } diff --git a/src/ast.d.ts b/src/ast.d.ts index 49193d7e7..02f724460 100644 --- a/src/ast.d.ts +++ b/src/ast.d.ts @@ -2393,7 +2393,8 @@ export type BoltTypeExpression export interface BoltReferenceTypeExpression extends SyntaxBase { kind: SyntaxKind.BoltReferenceTypeExpression; - path: BoltModulePath; + modulePath: BoltModulePath | null; + name: BoltIdentifier; arguments: BoltTypeExpression[] | null; parentNode: BoltReferenceTypeExpressionParent; getChildNodes(): IterableIterator @@ -2513,7 +2514,7 @@ export interface BoltTypeParameter extends SyntaxBase { kind: SyntaxKind.BoltTypeParameter; index: number; name: BoltIdentifier; - typeNode: BoltTypeExpression; + typeNode: BoltTypeExpression | null; defaultType: BoltTypeExpression | null; parentNode: BoltTypeParameterParent; getChildNodes(): IterableIterator @@ -6952,9 +6953,9 @@ export function createBoltBracketed(text: string, span?: TextSpan | null): BoltB export function createBoltSourceFile(elements: BoltSourceElement[], package: Package, span?: TextSpan | null): BoltSourceFile; export function createBoltQualName(modulePath: BoltModulePath | null, name: BoltSymbol, span?: TextSpan | null): BoltQualName; export function createBoltModulePath(isAbsolute: boolean, elements: BoltIdentifier[], span?: TextSpan | null): BoltModulePath; -export function createBoltReferenceTypeExpression(path: BoltModulePath, arguments: BoltTypeExpression[] | null, span?: TextSpan | null): BoltReferenceTypeExpression; +export function createBoltReferenceTypeExpression(modulePath: BoltModulePath | null, name: BoltIdentifier, arguments: BoltTypeExpression[] | null, span?: TextSpan | null): BoltReferenceTypeExpression; export function createBoltFunctionTypeExpression(params: BoltParameter[], returnType: BoltTypeExpression | null, span?: TextSpan | null): BoltFunctionTypeExpression; -export function createBoltTypeParameter(index: number, name: BoltIdentifier, typeNode: BoltTypeExpression, defaultType: BoltTypeExpression | null, span?: TextSpan | null): BoltTypeParameter; +export function createBoltTypeParameter(index: number, name: BoltIdentifier, typeNode: BoltTypeExpression | null, defaultType: BoltTypeExpression | null, span?: TextSpan | null): BoltTypeParameter; export function createBoltBindPattern(name: BoltIdentifier, span?: TextSpan | null): BoltBindPattern; export function createBoltTypePattern(type: BoltTypeExpression, nestedPattern: BoltPattern, span?: TextSpan | null): BoltTypePattern; export function createBoltExpressionPattern(expression: BoltExpression, span?: TextSpan | null): BoltExpressionPattern; diff --git a/src/common.ts b/src/common.ts index de9a2e643..734e92987 100644 --- a/src/common.ts +++ b/src/common.ts @@ -56,7 +56,7 @@ export class Package { } -export function getLanguage(node: Syntax): string { +export function getNodeLanguage(node: Syntax): string { const kindStr = kindToString(node.kind); for (const prefix of BOLT_SUPPORTED_LANGUAGES) { if (kindStr.startsWith(prefix)) { diff --git a/src/debugServer.ts b/src/debugServer.ts deleted file mode 100644 index 40b4e7047..000000000 --- a/src/debugServer.ts +++ /dev/null @@ -1,5 +0,0 @@ - -export function connectToInspector(address: string) { - -} - diff --git a/src/emitter.ts b/src/emitter.ts index 3f25d0edf..7094921d7 100644 --- a/src/emitter.ts +++ b/src/emitter.ts @@ -15,8 +15,11 @@ export class Emitter { case SyntaxKind.BoltQualName: if (node.modulePath !== null) { - for (const element of node.modulePath) { - out += '.' + element.text; + if (node.modulePath.isAbsolute) { + out += '::' + } + for (const element of node.modulePath.elements) { + out += '::' + element.text; } } out += this.emit(node.name); diff --git a/src/evaluator.ts b/src/evaluator.ts index e439df32b..1e94111fa 100644 --- a/src/evaluator.ts +++ b/src/evaluator.ts @@ -4,31 +4,38 @@ import { FastStringMap, assert } from "./util" import { emitNode } from "./emitter"; import { Type, TypeChecker, RecordType } from "./types"; -//export class Record { +export class Record { -// private fields: Map; - -// constructor(fields: Iterable<[string, Value]>) { -// this.fields = new Map(fields); -// } + private fields: Map; -// public clone(): Record { -// return new Record(this.fields); -// } + constructor(fields: Iterable<[string, Value]>) { + this.fields = new Map(fields); + } -// public addField(name: string, value: Value): void { -// this.fields.set(name, value); -// } + public clone(): Record { + return new Record(this.fields); + } -// public deleteField(name: string): void { -// this.fields.delete(name); -// } + public getFieldValue(name: string): Value { + if (!this.fields.has(name)) { + throw new Error(`Trying to access non-existent field ${name} of a record.`); + } + return this.fields.get(name); + } -// public clear(): void { -// this.fields.clear(); -// } + public addField(name: string, value: Value): void { + this.fields.set(name, value); + } -//} + public deleteField(name: string): void { + this.fields.delete(name); + } + + public clear(): void { + this.fields.clear(); + } + +} export type Value = string @@ -108,14 +115,14 @@ export class Evaluator { case SyntaxKind.BoltRecordPattern: { - if (!(value.data instanceof Record)) { + if (!(value instanceof Record)) { throw new EvaluationError(`A deconstructing record pattern received a value that is not a record.`); } - const record = value.data.clone(); + const record = value.clone(); for (const fieldPatt of node.fields) { if (fieldPatt.isRest) { if (fieldPatt.name !== null) { - env.setValue(fieldPatt.name.text, { data: fields.clone() }); + env.setValue(fieldPatt.name.text, { data: record.clone() }); } record.clear(); } else { @@ -136,7 +143,7 @@ export class Evaluator { case SyntaxKind.BoltTypePattern: { const expectedType = this.checker.getTypeOfNode(node.type); - if (!this.checker.isTypeAssignableTo(expectedType, getTypeOfValue(value))) { + if (!this.checker.isTypeAssignableTo(expectedType, this.checker.getTypeOfValue(value))) { return false; } return false; diff --git a/src/frontend.ts b/src/frontend.ts index d93f84613..844d3201b 100644 --- a/src/frontend.ts +++ b/src/frontend.ts @@ -9,7 +9,7 @@ import { emitNode } from "./emitter" import { Syntax, BoltSourceFile, SourceFile, NodeVisitor, createBoltConditionalCase } from "./ast" import { getFileStem, MapLike } from "./util" import { verbose, memoize } from "./util" -import { Container, Newable } from "./di" +import { Container, Newable } from "./ioc" import ExpandBoltTransform from "./transforms/expand" import CompileBoltToJSTransform from "./transforms/boltToJS" import ConstFoldTransform from "./transforms/constFold" @@ -19,6 +19,8 @@ import { TypeChecker } from "./types" import { checkServerIdentity } from "tls" import { CheckInvalidFilePaths, CheckTypeAssignments, CheckReferences } from "./checks" import { SymbolResolver, BoltSymbolResolutionStrategy } from "./resolver" +import { Evaluator } from "./evaluator" +import { getNodeLanguage } from "./common" const targetExtensions: MapLike = { 'JS': '.mjs', @@ -71,20 +73,8 @@ export class Frontend { this.timing = new Timing(); } - //@memoize(filepath => path.resolve(filepath)) - //public getPackage(filepath: string) { - // const file = this.getTextFile(filepath) - // const projectFile = upsearchSync('Boltfile', path.dirname(file.fullPath)); - // if (projectFile === null) { - // return null; - // } - // const projectDir = path.resolve(path.dirname(projectFile)); - // return new Package(projectDir); - //} - public check(program: Program) { - const resolver = new SymbolResolver(program, new BoltSymbolResolutionStrategy); const checker = new TypeChecker(resolver); @@ -144,12 +134,15 @@ export class Frontend { } private mapToTargetFile(node: SourceFile) { - return path.join('.bolt-work', getFileStem(node.span!.file.fullPath) + getDefaultExtension(getLanguage(node))); + return path.join('.bolt-work', getFileStem(node.span!.file.fullPath) + getDefaultExtension(getNodeLanguage(node))); } public eval(program: Program) { + const resolver = new SymbolResolver(program, new BoltSymbolResolutionStrategy); + const checker = new TypeChecker(resolver); + const evaluator = new Evaluator(checker) for (const sourceFile of program.getAllSourceFiles()) { - this.evaluator.eval(sourceFile) + evaluator.eval(sourceFile) } } diff --git a/src/di.ts b/src/ioc.ts similarity index 100% rename from src/di.ts rename to src/ioc.ts diff --git a/src/parser.ts b/src/parser.ts index 950c5716c..91f3e9cd3 100644 --- a/src/parser.ts +++ b/src/parser.ts @@ -202,46 +202,51 @@ export class Parser { return (this as any)['parse' + kindToString(kind).substring('Bolt'.length)](tokens); } - public parseModulePath(tokens: BoltTokenStream): BoltModulePath { + public parseModulePath(tokens: BoltTokenStream): BoltModulePath | null { + let firstToken = tokens.peek();; + let lastToken: Token; let isAbsolute = false; let elements = []; - while (true) { - const t1 = tokens.get(); - assertToken(t1, SyntaxKind.BoltIdentifier); - elements.push(t1 as BoltIdentifier) - const t2 = tokens.peek(); - if (t2.kind !== SyntaxKind.BoltColonColon) { - break; - } + const t0 = tokens.peek(); + if (t0.kind === SyntaxKind.BoltColonColon) { + isAbsolute = true; tokens.get(); + lastToken = t0; } + if (tokens.peek(2).kind === SyntaxKind.BoltColonColon) { + while (true) { + const t1 = tokens.get(); + assertToken(t1, SyntaxKind.BoltIdentifier); + elements.push(t1 as BoltIdentifier) + const t2 = tokens.get(); + if (tokens.peek(2).kind !== SyntaxKind.BoltColonColon) { + lastToken = t2; + break; + } + } + } + + if (!isAbsolute && elements.length === 0) { + return null; + } const result = createBoltModulePath(isAbsolute, elements); - setOrigNodeRange(result, elements[0], elements[elements.length-1]); + setOrigNodeRange(result, firstToken, lastToken!); return result; } public parseQualName(tokens: BoltTokenStream): BoltQualName { let modulePath = null; - if (tokens.peek(2).kind === SyntaxKind.BoltDot) { - modulePath = []; - while (true) { - modulePath.push(tokens.get() as BoltIdentifier) - tokens.get(); - const t0 = tokens.peek(2); - if (t0.kind !== SyntaxKind.BoltDot) { - break; - } - } + modulePath = this.parseModulePath(tokens); } const name = tokens.get(); assertToken(name, SyntaxKind.BoltIdentifier); - const startNode = modulePath !== null ? modulePath[0] : name; + const startNode = modulePath !== null ? modulePath : name; const endNode = name; const node = createBoltQualName(modulePath, name as BoltIdentifier, null); setOrigNodeRange(node, startNode, endNode); @@ -343,7 +348,7 @@ export class Parser { const t1 = tokens.get(); assertToken(t1, SyntaxKind.BoltStringLiteral); - const symbols: BoltImportSymbol[] = null; + const symbols: BoltImportSymbol[] = []; const t2 = tokens.get(); if (t2.kind === SyntaxKind.BoltParenthesized) { // TODO implement grammar and parsing logic for symbols @@ -389,13 +394,19 @@ export class Parser { public parseReferenceTypeExpression(tokens: BoltTokenStream): BoltReferenceTypeExpression { - const path = this.parseModulePath(tokens) - const t1 = tokens.peek(); + const firstToken = tokens.peek(); + let modulePath = null; + if (tokens.peek(2).kind === SyntaxKind.BoltColonColon) { + modulePath = this.parseModulePath(tokens) + } + + const t1 = tokens.get(); + assertToken(t1, SyntaxKind.BoltIdentifier); + let lastToken = t1; let typeArgs: BoltTypeExpression[] | null = null; - let lastToken: BoltToken = path.elements[path.elements.length-1]; - if (t1.kind === SyntaxKind.BoltLtSign) { + if (tokens.peek().kind === SyntaxKind.BoltLtSign) { typeArgs = []; tokens.get(); let first = true; @@ -417,8 +428,8 @@ export class Parser { lastToken = t4; } - const node = createBoltReferenceTypeExpression(path, typeArgs); - setOrigNodeRange(node, path.elements[0], lastToken); + const node = createBoltReferenceTypeExpression(modulePath, t1 as BoltIdentifier, typeArgs); + setOrigNodeRange(node, firstToken, lastToken); return node; } @@ -433,40 +444,45 @@ export class Parser { } } - private parseTypeExpressionOperators(tokens: BoltTokenStream, lhs: BoltTypeExpression, minPrecedence: number): BoltTypeExpression { - while (true) { - const t0 = tokens.peek(); - if (!isBoltOperatorLike(t0)) { - break; - } - let desc0 = this.typeOperatorTable.lookup(emitNode(t0)); - if (desc0 === null || desc0.arity !== 2 || desc0.precedence < minPrecedence) { - break; - } - tokens.get(); - let rhs = this.parsePrimTypeExpression(tokens); - while (true) { - const t1 = tokens.peek() - if (!isBoltOperatorLike(t1.kind)) { - break; - } - const desc1 = this.typeOperatorTable.lookup(emitNode(t1)) - if (desc1 === null || desc1.arity !== 2 || desc1.precedence < desc0.precedence || !isRightAssoc(desc1.kind)) { - break; - } - rhs = this.parseTypeExpressionOperators(tokens, rhs, desc1.precedence); - } - const name = createBoltQualName([], t0); - setOrigNodeRange(name, t0, t0); - lhs = createBoltReferenceTypeExpression(name, [lhs, rhs]); - setOrigNodeRange(lhs, t0, rhs); - } - return lhs - } + //private parseTypeExpressionOperators(tokens: BoltTokenStream, lhs: BoltTypeExpression, minPrecedence: number): BoltTypeExpression { + // while (true) { + // const t0 = tokens.peek(); + // if (!isBoltOperatorLike(t0)) { + // break; + // } + // let desc0 = this.typeOperatorTable.lookup(emitNode(t0)); + // if (desc0 === null || desc0.arity !== 2 || desc0.precedence < minPrecedence) { + // break; + // } + // tokens.get(); + // let rhs = this.parsePrimTypeExpression(tokens); + // while (true) { + // const t1 = tokens.peek() + // if (!isBoltOperatorLike(t1.kind)) { + // break; + // } + // const desc1 = this.typeOperatorTable.lookup(emitNode(t1)) + // if (desc1 === null || desc1.arity !== 2 || desc1.precedence < desc0.precedence || !isRightAssoc(desc1.kind)) { + // break; + // } + // rhs = this.parseTypeExpressionOperators(tokens, rhs, desc1.precedence); + // } + // const name = emitNode(t0); + // switch (name) { + // case '|': + // return createBoltFunctionTypeExpression(); + // ) + // } + // lhs = createBoltReferenceTypeExpression(null, t0, [lhs, rhs]); + // setOrigNodeRange(lhs, t0, rhs); + // } + // return lhs + //} public parseTypeExpression(tokens: BoltTokenStream) { - const lhs = this.parsePrimTypeExpression(tokens); - return this.parseTypeExpressionOperators(tokens, lhs, 0); + //const lhs = this.parsePrimTypeExpression(tokens); + //return this.parseTypeExpressionOperators(tokens, lhs, 0); + return this.parsePrimTypeExpression(tokens); } public parseConstantExpression(tokens: BoltTokenStream): BoltConstantExpression { @@ -744,7 +760,7 @@ export class Parser { const t1 = tokens.peek(); if (t1.kind === SyntaxKind.BoltMutKeyword) { tokens.get(); - modifiers |= BoltModifiers.Mutable; + modifiers |= BoltModifiers.IsMutable; } const bindings = this.parsePattern(tokens) @@ -1268,8 +1284,6 @@ export class Parser { return this.parseTraitDeclaration(tokens); case SyntaxKind.BoltTypeKeyword: return this.parseTypeAliasDeclaration(tokens); - case SyntaxKind.BoltModKeyword: - return this.parseModuleDeclaration(tokens); case SyntaxKind.BoltFnKeyword: return this.parseFunctionDeclaration(tokens); case SyntaxKind.BoltLetKeyword: @@ -1317,14 +1331,19 @@ export class Parser { if (this.lookaheadIsMacroCall(tokens)) { return this.parseMacroCall(tokens); } - const t0 = this.getFirstTokenAfterModifiers(tokens); - if (t0.kind === SyntaxKind.BoltImportKeyword) { + const t0 = tokens.peek(); + const t1 = this.getFirstTokenAfterModifiers(tokens); + if (t1.kind === SyntaxKind.BoltImportKeyword) { return this.parseImportDirective(tokens); - } else if (KIND_STATEMENT_T0.indexOf(t0.kind) !== -1) { + } else if (t1.kind === SyntaxKind.BoltModKeyword) { + return this.parseModuleDeclaration(tokens); + } else if (KIND_STATEMENT_T0.indexOf(t1.kind) !== -1) { return this.parseStatement(tokens); + } else if (KIND_DECLARATION_KEYWORD.indexOf(t1.kind) !== -1) { + return this.parseDeclaration(tokens); + } else { + throw new ParseError(t0, KIND_SOURCEELEMENT_T0); } - // FIXME This should only parse when the tokens are valid and otherwise display a friendly error message. - return this.parseDeclaration(tokens); } public parseFunctionBodyElement(tokens: BoltTokenStream): BoltFunctionBodyElement { @@ -1561,6 +1580,8 @@ import { TextFile, TextSpan, TextPos } from "./text" import * as fs from "fs" import {JSScanner} from "./foreign/js/scanner"; import {emitNode} from "./emitter"; +import { timingSafeEqual } from "crypto"; +import { isatty } from "tty"; export function parseSourceFile(filepath: string, pkg: Package): BoltSourceFile { const file = new TextFile(filepath); diff --git a/src/transforms/expand.ts b/src/transforms/expand.ts index 1e41dfb38..5855cb2df 100644 --- a/src/transforms/expand.ts +++ b/src/transforms/expand.ts @@ -13,9 +13,9 @@ import { import { TypeChecker } from "../types" import { BoltTokenStream, Parser, isModifierKeyword } from "../parser" -import { Evaluator, TRUE, FALSE } from "../evaluator" +import { Evaluator } from "../evaluator" import { Transformer, TransformManager } from "./index" -import { inject } from "../di" +import { inject } from "../ioc" import { SourceFile } from "../ast" interface SyntaxTransformer { @@ -63,10 +63,8 @@ export class ExpandBoltTransform implements Transformer { private expand(node: BoltSyntax) { - for (const identNode of node.findAllChildrenOfKind(SyntaxKind.BoltIdentifier)) { - if (identNode.text.endsWith('1')) { - this.toExpand.push(node.parentNode!); - } + for (const macroCall of node.findAllChildrenOfKind(SyntaxKind.BoltMacroCall)) { + this.toExpand.push(macroCall); } // FIXME