diff --git a/src/ast-spec.txt b/src/ast-spec.txt index 469fbb927..aa011c24a 100644 --- a/src/ast-spec.txt +++ b/src/ast-spec.txt @@ -95,10 +95,15 @@ node BoltQualName { name: BoltSymbol, } +node BoltModulePath { + isAbsolute: bool, + elements: Vec, +} + node BoltTypeExpression; node BoltReferenceTypeExpression > BoltTypeExpression { - name: BoltQualName, + path: BoltModulePath, arguments: Option>, } @@ -144,7 +149,7 @@ node BoltRecordFieldPattern { } node BoltRecordPattern > BoltPattern { - name: BoltQualName, + name: BoltTypeExpression, fields: Vec, } @@ -246,7 +251,7 @@ enum BoltModifiers { node BoltModule > BoltSourceElement { modifiers: BoltModifiers, - name: BoltQualName, + name: Vec, elements: Vec, } diff --git a/src/ast.d.ts b/src/ast.d.ts index 04ad38347..83854216d 100644 --- a/src/ast.d.ts +++ b/src/ast.d.ts @@ -71,111 +71,112 @@ export const enum SyntaxKind { BoltBracketed = 53, BoltSourceFile = 54, BoltQualName = 55, - BoltReferenceTypeExpression = 57, - BoltFunctionTypeExpression = 58, - BoltTypeParameter = 59, - BoltBindPattern = 61, - BoltTypePattern = 62, - BoltExpressionPattern = 63, - BoltTuplePatternElement = 64, - BoltTuplePattern = 65, - BoltRecordFieldPattern = 66, - BoltRecordPattern = 67, - BoltQuoteExpression = 69, - BoltReferenceExpression = 70, - BoltMemberExpression = 71, - BoltFunctionExpression = 72, - BoltCallExpression = 73, - BoltYieldExpression = 74, - BoltMatchArm = 75, - BoltMatchExpression = 76, - BoltCase = 77, - BoltCaseExpression = 78, - BoltBlockExpression = 79, - BoltConstantExpression = 80, - BoltReturnStatement = 82, - BoltConditionalCase = 83, - BoltConditionalStatement = 84, - BoltResumeStatement = 85, - BoltExpressionStatement = 86, - BoltParameter = 87, - BoltModule = 91, - BoltFunctionDeclaration = 93, - BoltVariableDeclaration = 94, - BoltPlainImportSymbol = 96, - BoltImportDirective = 97, - BoltExportSymbol = 98, - BoltPlainExportSymbol = 99, - BoltExportDirective = 100, - BoltTraitDeclaration = 101, - BoltImplDeclaration = 102, - BoltTypeAliasDeclaration = 103, - BoltRecordField = 105, - BoltRecordDeclaration = 106, - BoltMacroCall = 108, - JSOperator = 111, - JSIdentifier = 112, - JSString = 113, - JSInteger = 114, - JSFromKeyword = 115, - JSReturnKeyword = 116, - JSTryKeyword = 117, - JSFinallyKeyword = 118, - JSCatchKeyword = 119, - JSImportKeyword = 120, - JSAsKeyword = 121, - JSConstKeyword = 122, - JSLetKeyword = 123, - JSExportKeyword = 124, - JSFunctionKeyword = 125, - JSWhileKeyword = 126, - JSForKeyword = 127, - JSCloseBrace = 128, - JSCloseBracket = 129, - JSCloseParen = 130, - JSOpenBrace = 131, - JSOpenBracket = 132, - JSOpenParen = 133, - JSSemi = 134, - JSComma = 135, - JSDot = 136, - JSDotDotDot = 137, - JSMulOp = 138, - JSAddOp = 139, - JSDivOp = 140, - JSSubOp = 141, - JSLtOp = 142, - JSGtOp = 143, - JSBOrOp = 144, - JSBXorOp = 145, - JSBAndOp = 146, - JSBNotOp = 147, - JSNotOp = 148, - JSBindPattern = 150, - JSConstantExpression = 152, - JSMemberExpression = 153, - JSCallExpression = 154, - JSBinaryExpression = 155, - JSUnaryExpression = 156, - JSNewExpression = 157, - JSSequenceExpression = 158, - JSConditionalExpression = 159, - JSLiteralExpression = 161, - JSReferenceExpression = 162, - JSCatchBlock = 166, - JSTryCatchStatement = 167, - JSExpressionStatement = 168, - JSConditionalCase = 169, - JSConditionalStatement = 170, - JSReturnStatement = 171, - JSParameter = 172, - JSImportStarBinding = 176, - JSImportAsBinding = 177, - JSImportDeclaration = 178, - JSFunctionDeclaration = 179, - JSArrowFunctionDeclaration = 180, - JSLetDeclaration = 181, - JSSourceFile = 182, + BoltModulePath = 56, + BoltReferenceTypeExpression = 58, + BoltFunctionTypeExpression = 59, + BoltTypeParameter = 60, + BoltBindPattern = 62, + BoltTypePattern = 63, + BoltExpressionPattern = 64, + BoltTuplePatternElement = 65, + BoltTuplePattern = 66, + BoltRecordFieldPattern = 67, + BoltRecordPattern = 68, + BoltQuoteExpression = 70, + BoltReferenceExpression = 71, + BoltMemberExpression = 72, + BoltFunctionExpression = 73, + BoltCallExpression = 74, + BoltYieldExpression = 75, + BoltMatchArm = 76, + BoltMatchExpression = 77, + BoltCase = 78, + BoltCaseExpression = 79, + BoltBlockExpression = 80, + BoltConstantExpression = 81, + BoltReturnStatement = 83, + BoltConditionalCase = 84, + BoltConditionalStatement = 85, + BoltResumeStatement = 86, + BoltExpressionStatement = 87, + BoltParameter = 88, + BoltModule = 92, + BoltFunctionDeclaration = 94, + BoltVariableDeclaration = 95, + BoltPlainImportSymbol = 97, + BoltImportDirective = 98, + BoltExportSymbol = 99, + BoltPlainExportSymbol = 100, + BoltExportDirective = 101, + BoltTraitDeclaration = 102, + BoltImplDeclaration = 103, + BoltTypeAliasDeclaration = 104, + BoltRecordField = 106, + BoltRecordDeclaration = 107, + BoltMacroCall = 109, + JSOperator = 112, + JSIdentifier = 113, + JSString = 114, + JSInteger = 115, + JSFromKeyword = 116, + JSReturnKeyword = 117, + JSTryKeyword = 118, + JSFinallyKeyword = 119, + JSCatchKeyword = 120, + JSImportKeyword = 121, + JSAsKeyword = 122, + JSConstKeyword = 123, + JSLetKeyword = 124, + JSExportKeyword = 125, + JSFunctionKeyword = 126, + JSWhileKeyword = 127, + JSForKeyword = 128, + JSCloseBrace = 129, + JSCloseBracket = 130, + JSCloseParen = 131, + JSOpenBrace = 132, + JSOpenBracket = 133, + JSOpenParen = 134, + JSSemi = 135, + JSComma = 136, + JSDot = 137, + JSDotDotDot = 138, + JSMulOp = 139, + JSAddOp = 140, + JSDivOp = 141, + JSSubOp = 142, + JSLtOp = 143, + JSGtOp = 144, + JSBOrOp = 145, + JSBXorOp = 146, + JSBAndOp = 147, + JSBNotOp = 148, + JSNotOp = 149, + JSBindPattern = 151, + JSConstantExpression = 153, + JSMemberExpression = 154, + JSCallExpression = 155, + JSBinaryExpression = 156, + JSUnaryExpression = 157, + JSNewExpression = 158, + JSSequenceExpression = 159, + JSConditionalExpression = 160, + JSLiteralExpression = 162, + JSReferenceExpression = 163, + JSCatchBlock = 167, + JSTryCatchStatement = 168, + JSExpressionStatement = 169, + JSConditionalCase = 170, + JSConditionalStatement = 171, + JSReturnStatement = 172, + JSParameter = 173, + JSImportStarBinding = 177, + JSImportAsBinding = 178, + JSImportDeclaration = 179, + JSFunctionDeclaration = 180, + JSArrowFunctionDeclaration = 181, + JSLetDeclaration = 182, + JSSourceFile = 183, } export interface EndOfFile extends SyntaxBase { @@ -563,6 +564,12 @@ export interface BoltQualName extends SyntaxBase { name: BoltSymbol; } +export interface BoltModulePath extends SyntaxBase { + kind: SyntaxKind.BoltModulePath; + isAbsolute: boolean; + elements: BoltIdentifier[]; +} + export type BoltTypeExpression = BoltReferenceTypeExpression | BoltFunctionTypeExpression @@ -570,7 +577,7 @@ export type BoltTypeExpression export interface BoltReferenceTypeExpression extends SyntaxBase { kind: SyntaxKind.BoltReferenceTypeExpression; - name: BoltQualName; + path: BoltModulePath; arguments: BoltTypeExpression[] | null; } @@ -631,7 +638,7 @@ export interface BoltRecordFieldPattern extends SyntaxBase { kind: SyntaxKind.BoltRecordPattern; - name: BoltQualName; + name: BoltTypeExpression; fields: BoltRecordFieldPattern[]; } @@ -780,7 +787,7 @@ export const enum BoltModifiers { export interface BoltModule extends SyntaxBase { kind: SyntaxKind.BoltModule; modifiers: BoltModifiers; - name: BoltQualName; + name: BoltIdentifier[]; elements: BoltSourceElement[]; } @@ -1362,6 +1369,7 @@ export type BoltSyntax | BoltBracketed | BoltSourceFile | BoltQualName + | BoltModulePath | BoltReferenceTypeExpression | BoltFunctionTypeExpression | BoltTypeParameter @@ -1519,6 +1527,7 @@ export type Syntax | BoltBracketed | BoltSourceFile | BoltQualName + | BoltModulePath | BoltReferenceTypeExpression | BoltFunctionTypeExpression | BoltTypeParameter @@ -1674,7 +1683,8 @@ export function createBoltBraced(text: string, span?: TextSpan | null): BoltBrac export function createBoltBracketed(text: string, span?: TextSpan | null): BoltBracketed; export function createBoltSourceFile(elements: BoltSourceElement[], package: Package, span?: TextSpan | null): BoltSourceFile; export function createBoltQualName(modulePath: BoltIdentifier[] | null, name: BoltSymbol, span?: TextSpan | null): BoltQualName; -export function createBoltReferenceTypeExpression(name: BoltQualName, arguments: BoltTypeExpression[] | null, span?: TextSpan | null): BoltReferenceTypeExpression; +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 createBoltFunctionTypeExpression(params: BoltParameter[], returnType: BoltTypeExpression | null, span?: TextSpan | null): BoltFunctionTypeExpression; export function createBoltTypeParameter(index: number, name: BoltIdentifier, defaultType: BoltTypeExpression | null, span?: TextSpan | null): BoltTypeParameter; export function createBoltBindPattern(name: BoltIdentifier, span?: TextSpan | null): BoltBindPattern; @@ -1683,7 +1693,7 @@ export function createBoltExpressionPattern(expression: BoltExpression, span?: T export function createBoltTuplePatternElement(index: number, pattern: BoltPattern, span?: TextSpan | null): BoltTuplePatternElement; export function createBoltTuplePattern(elements: BoltTuplePatternElement[], span?: TextSpan | null): BoltTuplePattern; export function createBoltRecordFieldPattern(isRest: boolean, name: BoltIdentifier | null, pattern: BoltPattern | null, span?: TextSpan | null): BoltRecordFieldPattern; -export function createBoltRecordPattern(name: BoltQualName, fields: BoltRecordFieldPattern[], span?: TextSpan | null): BoltRecordPattern; +export function createBoltRecordPattern(name: BoltTypeExpression, fields: BoltRecordFieldPattern[], span?: TextSpan | null): BoltRecordPattern; export function createBoltQuoteExpression(tokens: Token[], span?: TextSpan | null): BoltQuoteExpression; export function createBoltReferenceExpression(name: BoltQualName, span?: TextSpan | null): BoltReferenceExpression; export function createBoltMemberExpression(expression: BoltExpression, path: BoltIdentifier[], span?: TextSpan | null): BoltMemberExpression; @@ -1702,7 +1712,7 @@ export function createBoltConditionalStatement(cases: BoltConditionalCase[], spa export function createBoltResumeStatement(value: BoltExpression, span?: TextSpan | null): BoltResumeStatement; export function createBoltExpressionStatement(expression: BoltExpression, span?: TextSpan | null): BoltExpressionStatement; export function createBoltParameter(index: number, bindings: BoltPattern, type: BoltTypeExpression | null, defaultValue: BoltExpression | null, span?: TextSpan | null): BoltParameter; -export function createBoltModule(modifiers: BoltModifiers, name: BoltQualName, elements: BoltSourceElement[], span?: TextSpan | null): BoltModule; +export function createBoltModule(modifiers: BoltModifiers, name: BoltIdentifier[], elements: BoltSourceElement[], span?: TextSpan | null): BoltModule; export function createBoltFunctionDeclaration(modifiers: BoltModifiers, target: string, name: BoltSymbol, params: BoltParameter[], returnType: BoltTypeExpression | null, typeParams: BoltTypeParameter[] | null, body: BoltFunctionBodyElement[], span?: TextSpan | null): BoltFunctionDeclaration; export function createBoltVariableDeclaration(modifiers: BoltModifiers, bindings: BoltPattern, type: BoltTypeExpression | null, value: BoltExpression | null, span?: TextSpan | null): BoltVariableDeclaration; export function createBoltPlainImportSymbol(name: BoltQualName, span?: TextSpan | null): BoltPlainImportSymbol; @@ -1833,6 +1843,7 @@ export function isBoltBraced(value: any): value is BoltBraced; export function isBoltBracketed(value: any): value is BoltBracketed; export function isBoltSourceFile(value: any): value is BoltSourceFile; export function isBoltQualName(value: any): value is BoltQualName; +export function isBoltModulePath(value: any): value is BoltModulePath; export function isBoltTypeExpression(value: any): value is BoltTypeExpression; export function isBoltReferenceTypeExpression(value: any): value is BoltReferenceTypeExpression; export function isBoltFunctionTypeExpression(value: any): value is BoltFunctionTypeExpression; diff --git a/src/checker.ts b/src/checker.ts index 3362da583..9e637efb6 100644 --- a/src/checker.ts +++ b/src/checker.ts @@ -47,7 +47,7 @@ import { SourceFile, BoltModifiers } from "./ast"; -import {FastStringMap, countDigits, assert, verbose} from "./util"; +import {warn, FastStringMap, countDigits, assert, verbose} from "./util"; import { DiagnosticPrinter, E_TYPES_NOT_ASSIGNABLE, @@ -87,6 +87,22 @@ class SymbolPath { } +function getModulePathToNode(node: BoltSyntax): string[] { + let elements = []; + while (true) { + if (node.kind === SyntaxKind.BoltModule) { + for (const element of node.name) { + elements.unshift(element.text); + } + } + if (node.parentNode === null) { + break; + } + node = node.parentNode; + } + return elements; +} + function nodeToSymbolPath(node: BoltSyntax): SymbolPath { switch (node.kind) { case SyntaxKind.BoltIdentifier: @@ -97,6 +113,12 @@ function nodeToSymbolPath(node: BoltSyntax): SymbolPath { return new SymbolPath([], false, name); } return new SymbolPath(node.modulePath.map(id => id.text), false, name); + case SyntaxKind.BoltModulePath: + return new SymbolPath( + node.elements.slice(0, -1).map(el => el.text), + node.isAbsolute, + node.elements[node.elements.length-1].text + ); default: throw new Error(`Could not extract a symbol path from the given node.`); } @@ -109,8 +131,7 @@ enum SymbolKind { } function* getAllSymbolKindsInMask(symbolKindMask: SymbolKind) { - const n = countDigits(symbolKindMask, 2); - for (let i = 1; i <= n; i++) { + for (let i = 1; i <= symbolKindMask; i *= 2) { if ((symbolKindMask & i) > 0) { yield i; } @@ -233,7 +254,7 @@ export class TypeChecker { if (self.resolveTypeReferenceExpression(node) === null) { self.diagnostics.add({ message: E_TYPE_DECLARATION_NOT_FOUND, - args: { name: emit(node.name.name) }, + args: { name: emit(node.path) }, severity: 'error', node: node, }) @@ -520,7 +541,8 @@ export class TypeChecker { this.getScopeForNode(node, SymbolKind.Module) ); - function addAllSymbolsToScope(node: BoltSyntax, variableScope: ScopeInfo, typeScope: ScopeInfo, moduleScope: ScopeInfo, allowDuplicates = false): void { + + function addAllSymbolsToScope(node: BoltSyntax, variableScope: ScopeInfo, typeScope: ScopeInfo, moduleScope: ScopeInfo): void { switch (node.kind) { @@ -533,6 +555,7 @@ export class TypeChecker { } else { const sourceFile = self.program.resolveToSourceFile(node.file.value, node) as BoltSourceFile; if (sourceFile === null) { + // FIXME should be moved to checkNode() self.diagnostics.add({ severity: 'error', message: E_FILE_NOT_FOUND, @@ -541,15 +564,24 @@ export class TypeChecker { }); } else { for (const exportedNode of self.getAllExportedNodes(sourceFile)) { - addAllSymbolsToScope(exportedNode, variableScope, typeScope, moduleScope, true); + addNodeAsSymbol(exportedNode, true); } } } break; } - case SyntaxKind.BoltSourceFile: case SyntaxKind.BoltModule: + { + addNodeAsSymbol(node); + // TODO check for duplicates + for (const element of node.elements) { + addAllSymbolsToScope(element, variableScope, typeScope, moduleScope); + } + break; + } + + case SyntaxKind.BoltSourceFile: { for (const element of node.elements) { addAllSymbolsToScope(element, variableScope, typeScope, moduleScope); @@ -557,38 +589,42 @@ export class TypeChecker { break; } + case SyntaxKind.BoltRecordDeclaration: case SyntaxKind.BoltFunctionDeclaration: - { - const symbolName = emit(node.name); - const sym = self.lookupSymbolInScope(symbolName, variableScope, SymbolKind.Variable) - if (sym !== null) { - if (!allowDuplicates) { - throw new Error(`Symbol '${name}' is already defined.`); - } - if (sym.declarations.indexOf(node) === -1) { - throw new Error(`Different symbols imported under the same name.`); - } - } else { - self.addSymbolToScope(symbolName, node, variableScope, SymbolKind.Variable); - } + addNodeAsSymbol(node); break; + + } + + function addNodeAsSymbol(node: BoltSyntax, allowDuplicates = false) { + + switch (node.kind) { + + case SyntaxKind.BoltModule: + checkAndAddNode(node.name[node.name.length-1].text, node, moduleScope, SymbolKind.Module); + break; + + case SyntaxKind.BoltFunctionDeclaration: + checkAndAddNode(emit(node.name), node, variableScope, SymbolKind.Variable); + break; + + case SyntaxKind.BoltRecordDeclaration: + checkAndAddNode(node.name.text, node, typeScope, SymbolKind.Type); + break; + } - case SyntaxKind.BoltRecordDeclaration: - { - const symbolName = emit(node.name); - const sym = self.lookupSymbolInScope(symbolName, typeScope, SymbolKind.Type) + function checkAndAddNode(symbolName: string, node: BoltSyntax, scope: ScopeInfo, symbolKind: SymbolKind) { + const sym = self.lookupSymbolInScope(symbolName, variableScope, symbolKind) if (sym !== null) { if (!allowDuplicates) { - throw new Error(`Symbol '${name}' is already defined.`); + throw new Error(`Symbol '${symbolName}' is already defined.`); } if (sym.declarations.indexOf(node) === -1) { throw new Error(`Different symbols imported under the same name.`); } - } else { - self.addSymbolToScope(node.name.text, node, typeScope, SymbolKind.Type); } - break; + self.addSymbolToScope(symbolName, node, scope, symbolKind); } } @@ -604,23 +640,30 @@ export class TypeChecker { return nodes; function visit(node: BoltSyntax) { - if (isBoltDeclaration(node) || isBoltTypeDeclaration(node)) { - if ((node.modifiers & BoltModifiers.IsPublic) > 0) { - nodes.push(node); - } - } + switch (node.kind) { + case SyntaxKind.BoltFunctionDeclaration: case SyntaxKind.BoltRecordDeclaration: case SyntaxKind.BoltTypeAliasDeclaration: - nodes.push(node); + case SyntaxKind.BoltVariableDeclaration: + if ((node.modifiers & BoltModifiers.IsPublic) > 0) { + nodes.push(node); + } break; - case SyntaxKind.BoltModule: + case SyntaxKind.BoltSourceFile: for (const element of node.elements) { visit(element); } break; + + case SyntaxKind.BoltModule: + if ((node.modifiers & BoltModifiers.IsPublic) > 0) { + nodes.push(node); + } + break; + } } @@ -628,13 +671,14 @@ export class TypeChecker { private resolveReferenceExpression(node: BoltReferenceExpression): BoltDeclaration | null { const symbolPath = nodeToSymbolPath(node.name) - return this.resolveSymbolPath(symbolPath, node, SymbolKind.Variable); + const scope = this.getScopeForNode(node, SymbolKind.Variable); + return this.resolveSymbolPath(symbolPath, scope, SymbolKind.Variable) as BoltDeclaration; } private resolveTypeReferenceExpression(node: BoltReferenceTypeExpression): BoltTypeDeclaration | null { - const symbolPath = nodeToSymbolPath(node.name); + const symbolPath = nodeToSymbolPath(node.path); const scope = this.getScopeForNode(node, SymbolKind.Type); - return this.resolveSymbolPath(symbolPath, scope, SymbolKind.Type); + return this.resolveSymbolPath(symbolPath, scope, SymbolKind.Type) as BoltTypeDeclaration; } public addSymbol(name: string, node: BoltSyntax, kind: SymbolKind): void { @@ -643,10 +687,22 @@ export class TypeChecker { } public addSymbolToScope(name: string, node: BoltSyntax, scope: ScopeInfo, symbolKindMask: SymbolKind): void { - verbose(`Adding symbol ${name} in scope #${scope.id}`); + //let message = `Adding symbol ${name} in scope #${scope.id}`; + //const modulePath = getModulePathToNode(scope.declaration); + //if (modulePath.length > 0) { + // message += ` of module ${modulePath.join('::')} in file ${scope.declaration.span!.file.origPath}`; + //} else { + // message += ` of file ${scope.declaration.span!.file.origPath}`; + //} + //verbose(message); const sym = { kind: symbolKindMask, declarations: [ node ] } as SymbolInfo; for (const symbolKind of getAllSymbolKindsInMask(symbolKindMask)) { - this.symbols.set(`${symbolKind}:${name}:${scope.id}`, sym); + const key = `${symbolKind}:${name}:${scope.id}`; + if (this.symbols.has(key)) { + warn(`Warninig: silently skipping introduction of duplicate symbol '${name}'`); + } else { + this.symbols.set(key, sym); + } } } @@ -772,6 +828,7 @@ export class TypeChecker { shouldSearchParentScopes = true; break; } + // FIXME it should be possible to directly get the scope of a symbol currScope = this.getScopeForNode(sym.declarations[0], SymbolKind.Module); } diff --git a/src/emitter.ts b/src/emitter.ts index 573dab8a8..4f75df0bf 100644 --- a/src/emitter.ts +++ b/src/emitter.ts @@ -9,6 +9,10 @@ export class Emitter { switch (node.kind) { + case SyntaxKind.BoltModulePath: + out += node.elements.map(el => el.text).join('::'); + break; + case SyntaxKind.BoltQualName: if (node.modulePath !== null) { for (const element of node.modulePath) { diff --git a/src/parser.ts b/src/parser.ts index e0ff16454..0a192958c 100644 --- a/src/parser.ts +++ b/src/parser.ts @@ -77,7 +77,8 @@ import { BoltMacroCall, createBoltMacroCall, createBoltMemberExpression, - BoltSourceFileModifiers, + createBoltModulePath, + BoltModulePath, } from "./ast" import { parseForeignLanguage } from "./foreign" @@ -193,29 +194,25 @@ export class Parser { return (this as any)['parse' + kindToString(kind).substring('Bolt'.length)](tokens); } - public parseNamespacePath(tokens: BoltTokenStream): BoltQualName { + public parseNamespacePath(tokens: BoltTokenStream): BoltModulePath { - let modulePath = null; + let isAbsolute = false; + let elements = []; - if (tokens.peek(2).kind === SyntaxKind.BoltColonColon) { - modulePath = []; - while (true) { - modulePath.push(tokens.get() as BoltIdentifier) - tokens.get(); - const t0 = tokens.peek(2); - if (t0.kind !== SyntaxKind.BoltColonColon) { - break; - } + 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; } + tokens.get(); } - const name = tokens.get(); - assertToken(name, SyntaxKind.BoltIdentifier); - const startNode = modulePath !== null ? modulePath[0] : name; - const endNode = name; - const node = createBoltQualName(modulePath, name as BoltIdentifier, null); - setOrigNodeRange(node, startNode, endNode); - return node; + const result = createBoltModulePath(isAbsolute, elements); + setOrigNodeRange(result, elements[0], elements[elements.length-1]); + return result; } public parseQualName(tokens: BoltTokenStream): BoltQualName { @@ -253,7 +250,7 @@ export class Parser { public parseRecordPattern(tokens: BoltTokenStream): BoltRecordPattern { - const name = this.parseNamespacePath(tokens); + const name = this.parseTypeExpression(tokens); const t1 = tokens.get(); assertToken(t1, SyntaxKind.BoltBraced); @@ -384,11 +381,11 @@ export class Parser { public parseReferenceTypeExpression(tokens: BoltTokenStream): BoltReferenceTypeExpression { - const name = this.parseNamespacePath(tokens) - + const path = this.parseNamespacePath(tokens) const t1 = tokens.peek(); let typeArgs: BoltTypeExpression[] | null = null; + let lastToken: BoltToken = path.elements[path.elements.length-1]; if (t1.kind === SyntaxKind.BoltLtSign) { typeArgs = []; @@ -409,10 +406,11 @@ export class Parser { } const t4 = tokens.get(); assertToken(t4, SyntaxKind.BoltGtSign); + lastToken = t4; } - const node = createBoltReferenceTypeExpression(name, typeArgs); - setOrigNodeRange(node, name, name); + const node = createBoltReferenceTypeExpression(path, typeArgs); + setOrigNodeRange(node, path.elements[0], lastToken); return node; } @@ -836,9 +834,7 @@ export class Parser { t0 = tokens.get(); } - if (t0.kind !== SyntaxKind.BoltStructKeyword) { - throw new ParseError(t0, [SyntaxKind.BoltStructKeyword]) - } + assertToken(t0, SyntaxKind.BoltStructKeyword); const t1 = tokens.get(); assertToken(t1, SyntaxKind.BoltIdentifier); @@ -925,15 +921,15 @@ export class Parser { let t0 = tokens.get(); const firstToken = t0; if (t0.kind === SyntaxKind.BoltPubKeyword) { - tokens.get(); modifiers |= BoltModifiers.IsPublic; - t0 = tokens.peek(); + t0 = tokens.get(); } if (t0.kind !== SyntaxKind.BoltModKeyword) { throw new ParseError(t0, [SyntaxKind.BoltModKeyword]) } + // FIXME should fail to parse absolute paths const name = this.parseNamespacePath(tokens); const t1 = tokens.get(); @@ -942,7 +938,7 @@ export class Parser { } const sentences = this.parseSourceElements(createTokenStream(t1)); - const node = createBoltModule(modifiers, name, sentences); + const node = createBoltModule(modifiers, name.elements, sentences); setOrigNodeRange(node, firstToken, t1); return node; } diff --git a/src/util.ts b/src/util.ts index 8534ba97a..b34d4684c 100644 --- a/src/util.ts +++ b/src/util.ts @@ -190,6 +190,10 @@ export function verbose(message: string) { console.error(chalk.gray('[') + chalk.magenta('verb') + ' ' + chalk.gray(moment().format(DATETIME_FORMAT) + ']') + ' ' + message); } +export function warn(message: string) { + console.error(chalk.gray('[') + chalk.red('warn') + ' ' + chalk.gray(moment().format(DATETIME_FORMAT) + ']') + ' ' + message); +} + export function upsearchSync(filename: string, startDir = '.') { let currDir = startDir; while (true) {