Fix multiple issues with symbol resolver
This commit is contained in:
parent
e0566233c0
commit
828af8432e
6 changed files with 261 additions and 184 deletions
|
@ -95,10 +95,15 @@ node BoltQualName {
|
|||
name: BoltSymbol,
|
||||
}
|
||||
|
||||
node BoltModulePath {
|
||||
isAbsolute: bool,
|
||||
elements: Vec<BoltIdentifier>,
|
||||
}
|
||||
|
||||
node BoltTypeExpression;
|
||||
|
||||
node BoltReferenceTypeExpression > BoltTypeExpression {
|
||||
name: BoltQualName,
|
||||
path: BoltModulePath,
|
||||
arguments: Option<Vec<BoltTypeExpression>>,
|
||||
}
|
||||
|
||||
|
@ -144,7 +149,7 @@ node BoltRecordFieldPattern {
|
|||
}
|
||||
|
||||
node BoltRecordPattern > BoltPattern {
|
||||
name: BoltQualName,
|
||||
name: BoltTypeExpression,
|
||||
fields: Vec<BoltRecordFieldPattern>,
|
||||
}
|
||||
|
||||
|
@ -246,7 +251,7 @@ enum BoltModifiers {
|
|||
|
||||
node BoltModule > BoltSourceElement {
|
||||
modifiers: BoltModifiers,
|
||||
name: BoltQualName,
|
||||
name: Vec<BoltIdentifier>,
|
||||
elements: Vec<BoltSourceElement>,
|
||||
}
|
||||
|
||||
|
|
233
src/ast.d.ts
vendored
233
src/ast.d.ts
vendored
|
@ -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<SyntaxKind.EndOfFile> {
|
||||
|
@ -563,6 +564,12 @@ export interface BoltQualName extends SyntaxBase<SyntaxKind.BoltQualName> {
|
|||
name: BoltSymbol;
|
||||
}
|
||||
|
||||
export interface BoltModulePath extends SyntaxBase<SyntaxKind.BoltModulePath> {
|
||||
kind: SyntaxKind.BoltModulePath;
|
||||
isAbsolute: boolean;
|
||||
elements: BoltIdentifier[];
|
||||
}
|
||||
|
||||
export type BoltTypeExpression
|
||||
= BoltReferenceTypeExpression
|
||||
| BoltFunctionTypeExpression
|
||||
|
@ -570,7 +577,7 @@ export type BoltTypeExpression
|
|||
|
||||
export interface BoltReferenceTypeExpression extends SyntaxBase<SyntaxKind.BoltReferenceTypeExpression> {
|
||||
kind: SyntaxKind.BoltReferenceTypeExpression;
|
||||
name: BoltQualName;
|
||||
path: BoltModulePath;
|
||||
arguments: BoltTypeExpression[] | null;
|
||||
}
|
||||
|
||||
|
@ -631,7 +638,7 @@ export interface BoltRecordFieldPattern extends SyntaxBase<SyntaxKind.BoltRecord
|
|||
|
||||
export interface BoltRecordPattern extends SyntaxBase<SyntaxKind.BoltRecordPattern> {
|
||||
kind: SyntaxKind.BoltRecordPattern;
|
||||
name: BoltQualName;
|
||||
name: BoltTypeExpression;
|
||||
fields: BoltRecordFieldPattern[];
|
||||
}
|
||||
|
||||
|
@ -780,7 +787,7 @@ export const enum BoltModifiers {
|
|||
export interface BoltModule extends SyntaxBase<SyntaxKind.BoltModule> {
|
||||
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;
|
||||
|
|
133
src/checker.ts
133
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:
|
||||
{
|
||||
const symbolName = emit(node.name);
|
||||
const sym = self.lookupSymbolInScope(symbolName, typeScope, SymbolKind.Type)
|
||||
checkAndAddNode(node.name.text, node, typeScope, SymbolKind.Type);
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
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:
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in a new issue