diff --git a/src/ast-spec.ts b/src/ast-spec.ts index 61b52ee94..2ddd3d200 100644 --- a/src/ast-spec.ts +++ b/src/ast-spec.ts @@ -21,6 +21,25 @@ export abstract class Syntax { public errors: Diagnostic[] = []; + // -------------------------------------------------------------------------------- + // NOTE The following properties and methods are only valid when inside a BoltTraitDeclaration + // TODO Move this to BoltTraitDeclaration as soon as tsastgen supports this + + private impls?: BoltImplDeclaration[] = []; + + public addImplDeclaration(node: BoltImplDeclaration) { + if (this.impls === undefined) { + this.impls = []; + } + this.impls.push(node); + } + + public getImplDeclarations(): BoltImplDeclaration[] { + return this.impls ?? []; + } + + // -------------------------------------------------------------------------------- + public abstract kind: SyntaxKind; public abstract parentNode: Syntax | null = null; @@ -31,7 +50,7 @@ export abstract class Syntax { this.id = nextNodeId++; } - protected [inspectTag](depth: number | null, options: InspectOptionsStylized) { + private [inspectTag](depth: number | null, options: InspectOptionsStylized) { const proto = Object.getPrototypeOf(this); if (depth !== null && depth < 0) { return options.stylize(`[${proto.constructor.name}]`, 'special') @@ -51,7 +70,7 @@ export abstract class Syntax { return out; } - [serializeTag]() { + private [serializeTag]() { const result: any[] = []; for (const key of Object.keys(this)) { if (key === 'kind' || key === 'span' || key === 'parentNode' || key === 'errors' || key === 'type' || key === 'id') { @@ -63,7 +82,7 @@ export abstract class Syntax { return result; } - *preorder() { + public *preorder() { const stack: Syntax[] = [ this as unknown as Syntax ] ; while (stack.length > 0) { const node = stack.pop()!; @@ -75,11 +94,11 @@ export abstract class Syntax { } mayContainKind(kind: SyntaxKind) { - // TODO + // TODO should be generated by tsastgen return true; } - getParentOfKind(kind: SyntaxKind) { + public getParentOfKind(kind: SyntaxKind) { let currNode = this.parentNode; while (currNode !== null) { if (currNode.kind === kind) { @@ -90,7 +109,7 @@ export abstract class Syntax { return null; } - *findAllChildrenOfKind(kind: K): IterableIterator> { + public *findAllChildrenOfKind(kind: K): IterableIterator> { for (const node of this.preorder()) { if (!node.mayContainKind(kind)) { break; @@ -426,7 +445,7 @@ export interface BoltExportDirective extends BoltSourceElement { export interface BoltTraitOrImplElement {} -export interface BoltTraitDeclaration extends BoltDeclarationLike, BoltTypeDeclaration { +export interface BoltTraitDeclaration extends BoltDeclarationLike { modifiers: BoltModifiers, typeParams: BoltTypeParameter[] | null, name: BoltIdentifier, @@ -434,11 +453,11 @@ export interface BoltTraitDeclaration extends BoltDeclarationLike, BoltTypeDecla elements: BoltTraitOrImplElement[] | null, } -export interface BoltImplDeclaration extends BoltTypeDeclaration, BoltDeclarationLike { +export interface BoltImplDeclaration extends BoltDeclarationLike { modifiers: BoltModifiers, typeParams: BoltTypeParameter[] | null, - name: BoltIdentifier, - traitTypeExpr: BoltTypeExpression | null, + traitTypeExpr: BoltReferenceTypeExpression, + typeExpr: BoltReferenceTypeExpression, elements: BoltTraitOrImplElement[], } diff --git a/src/ast.ts b/src/ast.ts index 98db0961e..718f6a451 100644 --- a/src/ast.ts +++ b/src/ast.ts @@ -22,13 +22,27 @@ export abstract class SyntaxBase { public id: number; public type?: Type; public errors: Diagnostic[] = []; + // -------------------------------------------------------------------------------- + // NOTE The following properties and methods are only valid when inside a BoltTraitDeclaration + // TODO Move this to BoltTraitDeclaration as soon as tsastgen supports this + private impls?: BoltImplDeclaration[] = []; + public addImplDeclaration(node: BoltImplDeclaration) { + if (this.impls === undefined) { + this.impls = []; + } + this.impls.push(node); + } + public getImplDeclarations(): BoltImplDeclaration[] { + return this.impls ?? []; + } + // -------------------------------------------------------------------------------- public abstract kind: SyntaxKind; public abstract parentNode: Syntax | null = null; public abstract getChildNodes(): IterableIterator; constructor(public span: TextSpan | null = null) { this.id = nextNodeId++; } - protected [inspectTag](depth: number | null, options: InspectOptionsStylized) { + private [inspectTag](depth: number | null, options: InspectOptionsStylized) { const proto = Object.getPrototypeOf(this); if (depth !== null && depth < 0) { return options.stylize(`[${proto.constructor.name}]`, 'special'); @@ -47,7 +61,7 @@ export abstract class SyntaxBase { out += '}\n'; return out; } - [serializeTag]() { + private [serializeTag]() { const result: any[] = []; for (const key of Object.keys(this)) { if (key === 'kind' || key === 'span' || key === 'parentNode' || key === 'errors' || key === 'type' || key === 'id') { @@ -58,7 +72,7 @@ export abstract class SyntaxBase { result.push(this.span); return result; } - *preorder() { + public *preorder() { const stack: Syntax[] = [this as unknown as Syntax]; while (stack.length > 0) { const node = stack.pop()!; @@ -69,10 +83,10 @@ export abstract class SyntaxBase { } } mayContainKind(kind: SyntaxKind) { - // TODO + // TODO should be generated by tsastgen return true; } - getParentOfKind(kind: SyntaxKind) { + public getParentOfKind(kind: SyntaxKind) { let currNode = this.parentNode; while (currNode !== null) { if (currNode.kind === kind) { @@ -82,7 +96,7 @@ export abstract class SyntaxBase { } return null; } - *findAllChildrenOfKind(kind: K): IterableIterator> { + public *findAllChildrenOfKind(kind: K): IterableIterator> { for (const node of this.preorder()) { if (!node.mayContainKind(kind)) { break; @@ -132,7 +146,7 @@ export type FunctionBodyElement = JSLetDeclaration | JSArrowFunctionDeclaration export type ReturnStatement = JSReturnStatement | BoltReturnStatement; -export type BoltSyntax = BoltMacroCall | BoltRecordField | BoltPlainExportSymbol | BoltImportDirective | BoltPlainImportSymbol | BoltModule | BoltRecordDeclaration | BoltTypeAliasDeclaration | BoltImplDeclaration | BoltTraitDeclaration | BoltVariableDeclaration | BoltFunctionDeclaration | BoltParameter | BoltConditionalCase | BoltLoopStatement | BoltExpressionStatement | BoltResumeStatement | BoltConditionalStatement | BoltReturnStatement | BoltCase | BoltMatchArm | BoltConstantExpression | BoltBlockExpression | BoltCaseExpression | BoltMatchExpression | BoltYieldExpression | BoltCallExpression | BoltFunctionExpression | BoltMemberExpression | BoltReferenceExpression | BoltTupleExpression | BoltQuoteExpression | BoltRecordFieldPattern | BoltTuplePatternElement | BoltRecordPattern | BoltTuplePattern | BoltExpressionPattern | BoltTypePattern | BoltBindPattern | BoltTypeParameter | BoltLiftedTypeExpression | BoltFunctionTypeExpression | BoltReferenceTypeExpression | BoltTypeOfExpression | BoltQualName | BoltSourceFile | BoltBracketed | BoltBraced | BoltParenthesized | BoltImplKeyword | BoltTraitKeyword | BoltTypeKeyword | BoltStructKeyword | BoltEnumKeyword | BoltMutKeyword | BoltModKeyword | BoltPubKeyword | BoltExportKeyword | BoltImportKeyword | BoltMatchKeyword | BoltYieldKeyword | BoltLoopKeyword | BoltReturnKeyword | BoltLetKeyword | BoltForKeyword | BoltForeignKeyword | BoltFnKeyword | BoltQuoteKeyword | BoltWhereKeyword | BoltVBar | BoltLtSign | BoltExMark | BoltGtSign | BoltEqSign | BoltLArrow | BoltRArrowAlt | BoltRArrow | BoltDotDot | BoltDot | BoltColonColon | BoltColon | BoltSemi | BoltComma | BoltAssignment | BoltOperator | BoltIdentifier | BoltIntegerLiteral | BoltStringLiteral | EndOfFile; +export type BoltSyntax = BoltMacroCall | BoltRecordField | BoltPlainExportSymbol | BoltImportDirective | BoltPlainImportSymbol | BoltModule | BoltRecordDeclaration | BoltTypeAliasDeclaration | BoltVariableDeclaration | BoltFunctionDeclaration | BoltParameter | BoltConditionalCase | BoltLoopStatement | BoltExpressionStatement | BoltResumeStatement | BoltConditionalStatement | BoltReturnStatement | BoltCase | BoltMatchArm | BoltConstantExpression | BoltBlockExpression | BoltCaseExpression | BoltMatchExpression | BoltYieldExpression | BoltCallExpression | BoltFunctionExpression | BoltMemberExpression | BoltReferenceExpression | BoltTupleExpression | BoltQuoteExpression | BoltRecordFieldPattern | BoltTuplePatternElement | BoltRecordPattern | BoltTuplePattern | BoltExpressionPattern | BoltTypePattern | BoltBindPattern | BoltTypeParameter | BoltLiftedTypeExpression | BoltFunctionTypeExpression | BoltReferenceTypeExpression | BoltTypeOfExpression | BoltQualName | BoltSourceFile | BoltBracketed | BoltBraced | BoltParenthesized | BoltImplKeyword | BoltTraitKeyword | BoltTypeKeyword | BoltStructKeyword | BoltEnumKeyword | BoltMutKeyword | BoltModKeyword | BoltPubKeyword | BoltExportKeyword | BoltImportKeyword | BoltMatchKeyword | BoltYieldKeyword | BoltLoopKeyword | BoltReturnKeyword | BoltLetKeyword | BoltForKeyword | BoltForeignKeyword | BoltFnKeyword | BoltQuoteKeyword | BoltWhereKeyword | BoltVBar | BoltLtSign | BoltExMark | BoltGtSign | BoltEqSign | BoltLArrow | BoltRArrowAlt | BoltRArrow | BoltDotDot | BoltDot | BoltColonColon | BoltColon | BoltSemi | BoltComma | BoltAssignment | BoltOperator | BoltIdentifier | BoltIntegerLiteral | BoltStringLiteral | EndOfFile; export type BoltToken = BoltBracketed | BoltBraced | BoltParenthesized | BoltImplKeyword | BoltTraitKeyword | BoltTypeKeyword | BoltStructKeyword | BoltEnumKeyword | BoltMutKeyword | BoltModKeyword | BoltPubKeyword | BoltExportKeyword | BoltImportKeyword | BoltMatchKeyword | BoltYieldKeyword | BoltLoopKeyword | BoltReturnKeyword | BoltLetKeyword | BoltForKeyword | BoltForeignKeyword | BoltFnKeyword | BoltQuoteKeyword | BoltWhereKeyword | BoltVBar | BoltLtSign | BoltExMark | BoltGtSign | BoltEqSign | BoltLArrow | BoltRArrowAlt | BoltRArrow | BoltDotDot | BoltDot | BoltColonColon | BoltColon | BoltSemi | BoltComma | BoltAssignment | BoltOperator | BoltIdentifier | BoltIntegerLiteral | BoltStringLiteral | EndOfFile; @@ -167,7 +181,7 @@ export class BoltIdentifier extends SyntaxBase { *getChildNodes(): IterableIterator { } } -type BoltIdentifierParent = BoltQualName | BoltTypeParameter | BoltBindPattern | BoltRecordFieldPattern | BoltMemberExpression | BoltPlainImportSymbol | BoltPlainExportSymbol | BoltRecordField | BoltFunctionDeclaration | BoltTraitDeclaration | BoltImplDeclaration | BoltTypeAliasDeclaration | BoltRecordDeclaration | BoltModule | BoltMacroCall | never; +type BoltIdentifierParent = BoltQualName | BoltTypeParameter | BoltBindPattern | BoltRecordFieldPattern | BoltMemberExpression | BoltPlainImportSymbol | BoltPlainExportSymbol | BoltTraitDeclaration | BoltRecordField | BoltFunctionDeclaration | BoltTypeAliasDeclaration | BoltRecordDeclaration | BoltModule | BoltMacroCall | never; type BoltIdentifierChild = never; @@ -616,7 +630,7 @@ export class BoltSourceFile extends SyntaxBase { type BoltSourceFileParent = never; -type BoltSourceFileChild = BoltMacroCall | BoltExportDirective | BoltImportDirective | BoltModule | BoltRecordDeclaration | BoltTypeAliasDeclaration | BoltImplDeclaration | BoltTraitDeclaration | BoltVariableDeclaration | BoltFunctionDeclaration | BoltLoopStatement | BoltExpressionStatement | BoltResumeStatement | BoltConditionalStatement | BoltReturnStatement | never; +type BoltSourceFileChild = BoltMacroCall | BoltExportDirective | BoltImportDirective | BoltModule | BoltRecordDeclaration | BoltTypeAliasDeclaration | BoltVariableDeclaration | BoltFunctionDeclaration | BoltLoopStatement | BoltExpressionStatement | BoltResumeStatement | BoltConditionalStatement | BoltReturnStatement | never; export class BoltQualName extends SyntaxBase { parentNode: null | BoltQualNameParent = null; @@ -639,7 +653,7 @@ export class BoltTypeOfExpression extends SyntaxBase { *getChildNodes(): IterableIterator { yield this.expression; } } -type BoltTypeOfExpressionParent = BoltReferenceTypeExpression | BoltFunctionTypeExpression | BoltTypeParameter | BoltTypePattern | BoltRecordPattern | BoltFunctionExpression | BoltParameter | BoltRecordField | BoltFunctionDeclaration | BoltVariableDeclaration | BoltTraitDeclaration | BoltImplDeclaration | BoltTypeAliasDeclaration | never; +type BoltTypeOfExpressionParent = BoltReferenceTypeExpression | BoltFunctionTypeExpression | BoltTypeParameter | BoltTypePattern | BoltRecordPattern | BoltFunctionExpression | BoltParameter | BoltTraitDeclaration | BoltRecordField | BoltFunctionDeclaration | BoltVariableDeclaration | BoltTypeAliasDeclaration | never; type BoltTypeOfExpressionChild = BoltConstantExpression | BoltBlockExpression | BoltCaseExpression | BoltMatchExpression | BoltYieldExpression | BoltCallExpression | BoltFunctionExpression | BoltMemberExpression | BoltReferenceExpression | BoltTupleExpression | BoltQuoteExpression | never; @@ -652,7 +666,7 @@ export class BoltReferenceTypeExpression extends SyntaxBase { yield element; } } -type BoltReferenceTypeExpressionParent = BoltReferenceTypeExpression | BoltFunctionTypeExpression | BoltTypeParameter | BoltTypePattern | BoltRecordPattern | BoltFunctionExpression | BoltParameter | BoltRecordField | BoltFunctionDeclaration | BoltVariableDeclaration | BoltTraitDeclaration | BoltImplDeclaration | BoltTypeAliasDeclaration | never; +type BoltReferenceTypeExpressionParent = BoltReferenceTypeExpression | BoltFunctionTypeExpression | BoltTypeParameter | BoltTypePattern | BoltRecordPattern | BoltFunctionExpression | BoltParameter | BoltTraitDeclaration | BoltImplDeclaration | BoltRecordField | BoltFunctionDeclaration | BoltVariableDeclaration | BoltTypeAliasDeclaration | never; type BoltReferenceTypeExpressionChild = BoltLiftedTypeExpression | BoltFunctionTypeExpression | BoltReferenceTypeExpression | BoltTypeOfExpression | BoltQualName | never; @@ -665,7 +679,7 @@ export class BoltFunctionTypeExpression extends SyntaxBase { yield this.returnType; } } -type BoltFunctionTypeExpressionParent = BoltReferenceTypeExpression | BoltFunctionTypeExpression | BoltTypeParameter | BoltTypePattern | BoltRecordPattern | BoltFunctionExpression | BoltParameter | BoltRecordField | BoltFunctionDeclaration | BoltVariableDeclaration | BoltTraitDeclaration | BoltImplDeclaration | BoltTypeAliasDeclaration | never; +type BoltFunctionTypeExpressionParent = BoltReferenceTypeExpression | BoltFunctionTypeExpression | BoltTypeParameter | BoltTypePattern | BoltRecordPattern | BoltFunctionExpression | BoltParameter | BoltTraitDeclaration | BoltRecordField | BoltFunctionDeclaration | BoltVariableDeclaration | BoltTypeAliasDeclaration | never; type BoltFunctionTypeExpressionChild = BoltLiftedTypeExpression | BoltFunctionTypeExpression | BoltReferenceTypeExpression | BoltTypeOfExpression | BoltParameter | never; @@ -676,7 +690,7 @@ export class BoltLiftedTypeExpression extends SyntaxBase { *getChildNodes(): IterableIterator { yield this.expression; } } -type BoltLiftedTypeExpressionParent = BoltReferenceTypeExpression | BoltFunctionTypeExpression | BoltTypeParameter | BoltTypePattern | BoltRecordPattern | BoltFunctionExpression | BoltParameter | BoltRecordField | BoltFunctionDeclaration | BoltVariableDeclaration | BoltTraitDeclaration | BoltImplDeclaration | BoltTypeAliasDeclaration | never; +type BoltLiftedTypeExpressionParent = BoltReferenceTypeExpression | BoltFunctionTypeExpression | BoltTypeParameter | BoltTypePattern | BoltRecordPattern | BoltFunctionExpression | BoltParameter | BoltTraitDeclaration | BoltRecordField | BoltFunctionDeclaration | BoltVariableDeclaration | BoltTypeAliasDeclaration | never; type BoltLiftedTypeExpressionChild = BoltConstantExpression | BoltBlockExpression | BoltCaseExpression | BoltMatchExpression | BoltYieldExpression | BoltCallExpression | BoltFunctionExpression | BoltMemberExpression | BoltReferenceExpression | BoltTupleExpression | BoltQuoteExpression | never; @@ -689,7 +703,7 @@ export class BoltTypeParameter extends SyntaxBase { yield this.defaultType; } } -type BoltTypeParameterParent = BoltFunctionDeclaration | BoltTraitDeclaration | BoltImplDeclaration | BoltTypeAliasDeclaration | BoltRecordDeclaration | never; +type BoltTypeParameterParent = BoltTraitDeclaration | BoltImplDeclaration | BoltFunctionDeclaration | BoltTypeAliasDeclaration | BoltRecordDeclaration | never; type BoltTypeParameterChild = BoltLiftedTypeExpression | BoltFunctionTypeExpression | BoltReferenceTypeExpression | BoltTypeOfExpression | BoltIdentifier | never; @@ -1018,7 +1032,7 @@ type BoltParameterChild = BoltConstantExpression | BoltBlockExpression | BoltCas export type BoltDeclaration = BoltRecordDeclaration | BoltVariableDeclaration | BoltFunctionDeclaration; -export type BoltTypeDeclaration = BoltRecordDeclaration | BoltTypeAliasDeclaration | BoltImplDeclaration | BoltTraitDeclaration; +export type BoltTypeDeclaration = BoltRecordDeclaration | BoltTypeAliasDeclaration; export class BoltModule extends SyntaxBase { parentNode: null | BoltModuleParent = null; @@ -1031,7 +1045,7 @@ export class BoltModule extends SyntaxBase { type BoltModuleParent = BoltSourceFile | BoltModule | never; -type BoltModuleChild = BoltMacroCall | BoltExportDirective | BoltImportDirective | BoltModule | BoltRecordDeclaration | BoltTypeAliasDeclaration | BoltImplDeclaration | BoltTraitDeclaration | BoltVariableDeclaration | BoltFunctionDeclaration | BoltLoopStatement | BoltExpressionStatement | BoltResumeStatement | BoltConditionalStatement | BoltReturnStatement | BoltIdentifier | never; +type BoltModuleChild = BoltMacroCall | BoltExportDirective | BoltImportDirective | BoltModule | BoltRecordDeclaration | BoltTypeAliasDeclaration | BoltVariableDeclaration | BoltFunctionDeclaration | BoltLoopStatement | BoltExpressionStatement | BoltResumeStatement | BoltConditionalStatement | BoltReturnStatement | BoltIdentifier | never; export type BoltDeclarationLike = BoltRecordDeclaration | BoltTypeAliasDeclaration | BoltImplDeclaration | BoltTraitDeclaration | BoltVariableDeclaration | BoltFunctionDeclaration; @@ -1049,7 +1063,7 @@ export class BoltFunctionDeclaration extends SyntaxBase { yield element; } } -type BoltFunctionDeclarationParent = BoltSourceFile | BoltFunctionExpression | BoltBlockExpression | BoltConditionalCase | BoltLoopStatement | BoltFunctionDeclaration | BoltTraitDeclaration | BoltImplDeclaration | BoltModule | never; +type BoltFunctionDeclarationParent = BoltSourceFile | BoltFunctionExpression | BoltBlockExpression | BoltConditionalCase | BoltTraitDeclaration | BoltImplDeclaration | BoltLoopStatement | BoltFunctionDeclaration | BoltModule | never; type BoltFunctionDeclarationChild = BoltMacroCall | BoltVariableDeclaration | BoltFunctionDeclaration | BoltLoopStatement | BoltExpressionStatement | BoltResumeStatement | BoltConditionalStatement | BoltReturnStatement | BoltTypeParameter | BoltLiftedTypeExpression | BoltFunctionTypeExpression | BoltReferenceTypeExpression | BoltTypeOfExpression | BoltParameter | BoltOperator | BoltVBar | BoltLtSign | BoltExMark | BoltGtSign | BoltIdentifier | never; @@ -1132,24 +1146,23 @@ export class BoltTraitDeclaration extends SyntaxBase { yield element; } } -type BoltTraitDeclarationParent = BoltSourceFile | BoltModule | never; +type BoltTraitDeclarationParent = never; type BoltTraitDeclarationChild = BoltMacroCall | BoltTypeAliasDeclaration | BoltFunctionDeclaration | BoltLiftedTypeExpression | BoltFunctionTypeExpression | BoltReferenceTypeExpression | BoltTypeOfExpression | BoltIdentifier | BoltTypeParameter | never; export class BoltImplDeclaration extends SyntaxBase { parentNode: null | BoltImplDeclarationParent = null; kind: SyntaxKind.BoltImplDeclaration = SyntaxKind.BoltImplDeclaration; - constructor(public modifiers: BoltModifiers, public typeParams: BoltTypeParameter[] | null, public name: BoltIdentifier, public traitTypeExpr: BoltTypeExpression | null, public elements: BoltTraitOrImplElement[], span: TextSpan | null = null) { super(span); } + constructor(public modifiers: BoltModifiers, public typeParams: BoltTypeParameter[] | null, public traitTypeExpr: BoltReferenceTypeExpression, public typeExpr: BoltReferenceTypeExpression, public elements: BoltTraitOrImplElement[], span: TextSpan | null = null) { super(span); } *getChildNodes(): IterableIterator { if (this.typeParams !== null) for (let element of this.typeParams) - yield element; yield this.name; if (this.traitTypeExpr !== null) - yield this.traitTypeExpr; for (let element of this.elements) + yield element; yield this.traitTypeExpr; yield this.typeExpr; for (let element of this.elements) yield element; } } -type BoltImplDeclarationParent = BoltSourceFile | BoltModule | never; +type BoltImplDeclarationParent = never; -type BoltImplDeclarationChild = BoltMacroCall | BoltTypeAliasDeclaration | BoltFunctionDeclaration | BoltLiftedTypeExpression | BoltFunctionTypeExpression | BoltReferenceTypeExpression | BoltTypeOfExpression | BoltIdentifier | BoltTypeParameter | never; +type BoltImplDeclarationChild = BoltMacroCall | BoltTypeAliasDeclaration | BoltFunctionDeclaration | BoltReferenceTypeExpression | BoltTypeParameter | never; export class BoltTypeAliasDeclaration extends SyntaxBase { parentNode: null | BoltTypeAliasDeclarationParent = null; @@ -1192,7 +1205,7 @@ type BoltRecordDeclarationParent = BoltSourceFile | BoltModule | never; type BoltRecordDeclarationChild = BoltMacroCall | BoltRecordField | BoltTypeParameter | BoltIdentifier | never; -export type BoltSourceElement = BoltMacroCall | BoltExportDirective | BoltImportDirective | BoltModule | BoltRecordDeclaration | BoltTypeAliasDeclaration | BoltImplDeclaration | BoltTraitDeclaration | BoltVariableDeclaration | BoltFunctionDeclaration | BoltLoopStatement | BoltExpressionStatement | BoltResumeStatement | BoltConditionalStatement | BoltReturnStatement; +export type BoltSourceElement = BoltMacroCall | BoltExportDirective | BoltImportDirective | BoltModule | BoltRecordDeclaration | BoltTypeAliasDeclaration | BoltVariableDeclaration | BoltFunctionDeclaration | BoltLoopStatement | BoltExpressionStatement | BoltResumeStatement | BoltConditionalStatement | BoltReturnStatement; export class BoltMacroCall extends SyntaxBase { parentNode: null | BoltMacroCallParent = null; @@ -1201,7 +1214,7 @@ export class BoltMacroCall extends SyntaxBase { *getChildNodes(): IterableIterator { yield this.name; } } -type BoltMacroCallParent = BoltSourceFile | BoltFunctionExpression | BoltBlockExpression | BoltConditionalCase | BoltLoopStatement | BoltFunctionDeclaration | BoltTraitDeclaration | BoltImplDeclaration | BoltRecordDeclaration | BoltModule | never; +type BoltMacroCallParent = BoltSourceFile | BoltFunctionExpression | BoltBlockExpression | BoltConditionalCase | BoltTraitDeclaration | BoltImplDeclaration | BoltLoopStatement | BoltFunctionDeclaration | BoltRecordDeclaration | BoltModule | never; type BoltMacroCallChild = BoltIdentifier | never; @@ -2109,7 +2122,7 @@ export function createBoltExportDirective(file: string, symbols: BoltExportSymbo export function createBoltTraitDeclaration(modifiers: BoltModifiers, typeParams: BoltTypeParameter[] | null, name: BoltIdentifier, typeBoundExpr: BoltTypeExpression | null, elements: BoltTraitOrImplElement[] | null, span: TextSpan | null = null): BoltTraitDeclaration { return new BoltTraitDeclaration(modifiers, typeParams, name, typeBoundExpr, elements, span); } -export function createBoltImplDeclaration(modifiers: BoltModifiers, typeParams: BoltTypeParameter[] | null, name: BoltIdentifier, traitTypeExpr: BoltTypeExpression | null, elements: BoltTraitOrImplElement[], span: TextSpan | null = null): BoltImplDeclaration { return new BoltImplDeclaration(modifiers, typeParams, name, traitTypeExpr, elements, span); } +export function createBoltImplDeclaration(modifiers: BoltModifiers, typeParams: BoltTypeParameter[] | null, traitTypeExpr: BoltReferenceTypeExpression, typeExpr: BoltReferenceTypeExpression, elements: BoltTraitOrImplElement[], span: TextSpan | null = null): BoltImplDeclaration { return new BoltImplDeclaration(modifiers, typeParams, traitTypeExpr, typeExpr, elements, span); } export function createBoltTypeAliasDeclaration(modifiers: BoltModifiers, name: BoltIdentifier, typeParams: BoltTypeParameter[] | null, typeExpr: BoltTypeExpression, span: TextSpan | null = null): BoltTypeAliasDeclaration { return new BoltTypeAliasDeclaration(modifiers, name, typeParams, typeExpr, span); } @@ -2255,7 +2268,7 @@ export function isFunctionBodyElement(value: any): value is FunctionBodyElement export function isReturnStatement(value: any): value is ReturnStatement { return value.kind === SyntaxKind.JSReturnStatement || value.kind === SyntaxKind.BoltReturnStatement; } -export function isBoltSyntax(value: any): value is BoltSyntax { return value.kind === SyntaxKind.BoltMacroCall || value.kind === SyntaxKind.BoltRecordField || value.kind === SyntaxKind.BoltPlainExportSymbol || value.kind === SyntaxKind.BoltImportDirective || value.kind === SyntaxKind.BoltPlainImportSymbol || value.kind === SyntaxKind.BoltModule || value.kind === SyntaxKind.BoltRecordDeclaration || value.kind === SyntaxKind.BoltTypeAliasDeclaration || value.kind === SyntaxKind.BoltImplDeclaration || value.kind === SyntaxKind.BoltTraitDeclaration || value.kind === SyntaxKind.BoltVariableDeclaration || value.kind === SyntaxKind.BoltFunctionDeclaration || value.kind === SyntaxKind.BoltParameter || value.kind === SyntaxKind.BoltConditionalCase || value.kind === SyntaxKind.BoltLoopStatement || value.kind === SyntaxKind.BoltExpressionStatement || value.kind === SyntaxKind.BoltResumeStatement || value.kind === SyntaxKind.BoltConditionalStatement || value.kind === SyntaxKind.BoltReturnStatement || value.kind === SyntaxKind.BoltCase || value.kind === SyntaxKind.BoltMatchArm || value.kind === SyntaxKind.BoltConstantExpression || value.kind === SyntaxKind.BoltBlockExpression || value.kind === SyntaxKind.BoltCaseExpression || value.kind === SyntaxKind.BoltMatchExpression || value.kind === SyntaxKind.BoltYieldExpression || value.kind === SyntaxKind.BoltCallExpression || value.kind === SyntaxKind.BoltFunctionExpression || value.kind === SyntaxKind.BoltMemberExpression || value.kind === SyntaxKind.BoltReferenceExpression || value.kind === SyntaxKind.BoltTupleExpression || value.kind === SyntaxKind.BoltQuoteExpression || value.kind === SyntaxKind.BoltRecordFieldPattern || value.kind === SyntaxKind.BoltTuplePatternElement || value.kind === SyntaxKind.BoltRecordPattern || value.kind === SyntaxKind.BoltTuplePattern || value.kind === SyntaxKind.BoltExpressionPattern || value.kind === SyntaxKind.BoltTypePattern || value.kind === SyntaxKind.BoltBindPattern || value.kind === SyntaxKind.BoltTypeParameter || value.kind === SyntaxKind.BoltLiftedTypeExpression || value.kind === SyntaxKind.BoltFunctionTypeExpression || value.kind === SyntaxKind.BoltReferenceTypeExpression || value.kind === SyntaxKind.BoltTypeOfExpression || value.kind === SyntaxKind.BoltQualName || value.kind === SyntaxKind.BoltSourceFile || value.kind === SyntaxKind.BoltBracketed || value.kind === SyntaxKind.BoltBraced || value.kind === SyntaxKind.BoltParenthesized || value.kind === SyntaxKind.BoltImplKeyword || value.kind === SyntaxKind.BoltTraitKeyword || value.kind === SyntaxKind.BoltTypeKeyword || value.kind === SyntaxKind.BoltStructKeyword || value.kind === SyntaxKind.BoltEnumKeyword || value.kind === SyntaxKind.BoltMutKeyword || value.kind === SyntaxKind.BoltModKeyword || value.kind === SyntaxKind.BoltPubKeyword || value.kind === SyntaxKind.BoltExportKeyword || value.kind === SyntaxKind.BoltImportKeyword || value.kind === SyntaxKind.BoltMatchKeyword || value.kind === SyntaxKind.BoltYieldKeyword || value.kind === SyntaxKind.BoltLoopKeyword || value.kind === SyntaxKind.BoltReturnKeyword || value.kind === SyntaxKind.BoltLetKeyword || value.kind === SyntaxKind.BoltForKeyword || value.kind === SyntaxKind.BoltForeignKeyword || value.kind === SyntaxKind.BoltFnKeyword || value.kind === SyntaxKind.BoltQuoteKeyword || value.kind === SyntaxKind.BoltWhereKeyword || value.kind === SyntaxKind.BoltVBar || value.kind === SyntaxKind.BoltLtSign || value.kind === SyntaxKind.BoltExMark || value.kind === SyntaxKind.BoltGtSign || value.kind === SyntaxKind.BoltEqSign || value.kind === SyntaxKind.BoltLArrow || value.kind === SyntaxKind.BoltRArrowAlt || value.kind === SyntaxKind.BoltRArrow || value.kind === SyntaxKind.BoltDotDot || value.kind === SyntaxKind.BoltDot || value.kind === SyntaxKind.BoltColonColon || value.kind === SyntaxKind.BoltColon || value.kind === SyntaxKind.BoltSemi || value.kind === SyntaxKind.BoltComma || value.kind === SyntaxKind.BoltAssignment || value.kind === SyntaxKind.BoltOperator || value.kind === SyntaxKind.BoltIdentifier || value.kind === SyntaxKind.BoltIntegerLiteral || value.kind === SyntaxKind.BoltStringLiteral || value.kind === SyntaxKind.EndOfFile; } +export function isBoltSyntax(value: any): value is BoltSyntax { return value.kind === SyntaxKind.BoltMacroCall || value.kind === SyntaxKind.BoltRecordField || value.kind === SyntaxKind.BoltPlainExportSymbol || value.kind === SyntaxKind.BoltImportDirective || value.kind === SyntaxKind.BoltPlainImportSymbol || value.kind === SyntaxKind.BoltModule || value.kind === SyntaxKind.BoltRecordDeclaration || value.kind === SyntaxKind.BoltTypeAliasDeclaration || value.kind === SyntaxKind.BoltVariableDeclaration || value.kind === SyntaxKind.BoltFunctionDeclaration || value.kind === SyntaxKind.BoltParameter || value.kind === SyntaxKind.BoltConditionalCase || value.kind === SyntaxKind.BoltLoopStatement || value.kind === SyntaxKind.BoltExpressionStatement || value.kind === SyntaxKind.BoltResumeStatement || value.kind === SyntaxKind.BoltConditionalStatement || value.kind === SyntaxKind.BoltReturnStatement || value.kind === SyntaxKind.BoltCase || value.kind === SyntaxKind.BoltMatchArm || value.kind === SyntaxKind.BoltConstantExpression || value.kind === SyntaxKind.BoltBlockExpression || value.kind === SyntaxKind.BoltCaseExpression || value.kind === SyntaxKind.BoltMatchExpression || value.kind === SyntaxKind.BoltYieldExpression || value.kind === SyntaxKind.BoltCallExpression || value.kind === SyntaxKind.BoltFunctionExpression || value.kind === SyntaxKind.BoltMemberExpression || value.kind === SyntaxKind.BoltReferenceExpression || value.kind === SyntaxKind.BoltTupleExpression || value.kind === SyntaxKind.BoltQuoteExpression || value.kind === SyntaxKind.BoltRecordFieldPattern || value.kind === SyntaxKind.BoltTuplePatternElement || value.kind === SyntaxKind.BoltRecordPattern || value.kind === SyntaxKind.BoltTuplePattern || value.kind === SyntaxKind.BoltExpressionPattern || value.kind === SyntaxKind.BoltTypePattern || value.kind === SyntaxKind.BoltBindPattern || value.kind === SyntaxKind.BoltTypeParameter || value.kind === SyntaxKind.BoltLiftedTypeExpression || value.kind === SyntaxKind.BoltFunctionTypeExpression || value.kind === SyntaxKind.BoltReferenceTypeExpression || value.kind === SyntaxKind.BoltTypeOfExpression || value.kind === SyntaxKind.BoltQualName || value.kind === SyntaxKind.BoltSourceFile || value.kind === SyntaxKind.BoltBracketed || value.kind === SyntaxKind.BoltBraced || value.kind === SyntaxKind.BoltParenthesized || value.kind === SyntaxKind.BoltImplKeyword || value.kind === SyntaxKind.BoltTraitKeyword || value.kind === SyntaxKind.BoltTypeKeyword || value.kind === SyntaxKind.BoltStructKeyword || value.kind === SyntaxKind.BoltEnumKeyword || value.kind === SyntaxKind.BoltMutKeyword || value.kind === SyntaxKind.BoltModKeyword || value.kind === SyntaxKind.BoltPubKeyword || value.kind === SyntaxKind.BoltExportKeyword || value.kind === SyntaxKind.BoltImportKeyword || value.kind === SyntaxKind.BoltMatchKeyword || value.kind === SyntaxKind.BoltYieldKeyword || value.kind === SyntaxKind.BoltLoopKeyword || value.kind === SyntaxKind.BoltReturnKeyword || value.kind === SyntaxKind.BoltLetKeyword || value.kind === SyntaxKind.BoltForKeyword || value.kind === SyntaxKind.BoltForeignKeyword || value.kind === SyntaxKind.BoltFnKeyword || value.kind === SyntaxKind.BoltQuoteKeyword || value.kind === SyntaxKind.BoltWhereKeyword || value.kind === SyntaxKind.BoltVBar || value.kind === SyntaxKind.BoltLtSign || value.kind === SyntaxKind.BoltExMark || value.kind === SyntaxKind.BoltGtSign || value.kind === SyntaxKind.BoltEqSign || value.kind === SyntaxKind.BoltLArrow || value.kind === SyntaxKind.BoltRArrowAlt || value.kind === SyntaxKind.BoltRArrow || value.kind === SyntaxKind.BoltDotDot || value.kind === SyntaxKind.BoltDot || value.kind === SyntaxKind.BoltColonColon || value.kind === SyntaxKind.BoltColon || value.kind === SyntaxKind.BoltSemi || value.kind === SyntaxKind.BoltComma || value.kind === SyntaxKind.BoltAssignment || value.kind === SyntaxKind.BoltOperator || value.kind === SyntaxKind.BoltIdentifier || value.kind === SyntaxKind.BoltIntegerLiteral || value.kind === SyntaxKind.BoltStringLiteral || value.kind === SyntaxKind.EndOfFile; } export function isBoltToken(value: any): value is BoltToken { return value.kind === SyntaxKind.BoltBracketed || value.kind === SyntaxKind.BoltBraced || value.kind === SyntaxKind.BoltParenthesized || value.kind === SyntaxKind.BoltImplKeyword || value.kind === SyntaxKind.BoltTraitKeyword || value.kind === SyntaxKind.BoltTypeKeyword || value.kind === SyntaxKind.BoltStructKeyword || value.kind === SyntaxKind.BoltEnumKeyword || value.kind === SyntaxKind.BoltMutKeyword || value.kind === SyntaxKind.BoltModKeyword || value.kind === SyntaxKind.BoltPubKeyword || value.kind === SyntaxKind.BoltExportKeyword || value.kind === SyntaxKind.BoltImportKeyword || value.kind === SyntaxKind.BoltMatchKeyword || value.kind === SyntaxKind.BoltYieldKeyword || value.kind === SyntaxKind.BoltLoopKeyword || value.kind === SyntaxKind.BoltReturnKeyword || value.kind === SyntaxKind.BoltLetKeyword || value.kind === SyntaxKind.BoltForKeyword || value.kind === SyntaxKind.BoltForeignKeyword || value.kind === SyntaxKind.BoltFnKeyword || value.kind === SyntaxKind.BoltQuoteKeyword || value.kind === SyntaxKind.BoltWhereKeyword || value.kind === SyntaxKind.BoltVBar || value.kind === SyntaxKind.BoltLtSign || value.kind === SyntaxKind.BoltExMark || value.kind === SyntaxKind.BoltGtSign || value.kind === SyntaxKind.BoltEqSign || value.kind === SyntaxKind.BoltLArrow || value.kind === SyntaxKind.BoltRArrowAlt || value.kind === SyntaxKind.BoltRArrow || value.kind === SyntaxKind.BoltDotDot || value.kind === SyntaxKind.BoltDot || value.kind === SyntaxKind.BoltColonColon || value.kind === SyntaxKind.BoltColon || value.kind === SyntaxKind.BoltSemi || value.kind === SyntaxKind.BoltComma || value.kind === SyntaxKind.BoltAssignment || value.kind === SyntaxKind.BoltOperator || value.kind === SyntaxKind.BoltIdentifier || value.kind === SyntaxKind.BoltIntegerLiteral || value.kind === SyntaxKind.BoltStringLiteral || value.kind === SyntaxKind.EndOfFile; } @@ -2429,7 +2442,7 @@ export function isBoltParameter(value: any): value is BoltParameter { return val export function isBoltDeclaration(value: any): value is BoltDeclaration { return value.kind === SyntaxKind.BoltRecordDeclaration || value.kind === SyntaxKind.BoltVariableDeclaration || value.kind === SyntaxKind.BoltFunctionDeclaration; } -export function isBoltTypeDeclaration(value: any): value is BoltTypeDeclaration { return value.kind === SyntaxKind.BoltRecordDeclaration || value.kind === SyntaxKind.BoltTypeAliasDeclaration || value.kind === SyntaxKind.BoltImplDeclaration || value.kind === SyntaxKind.BoltTraitDeclaration; } +export function isBoltTypeDeclaration(value: any): value is BoltTypeDeclaration { return value.kind === SyntaxKind.BoltRecordDeclaration || value.kind === SyntaxKind.BoltTypeAliasDeclaration; } export function isBoltModule(value: any): value is BoltModule { return value.kind === SyntaxKind.BoltModule; } @@ -2467,7 +2480,7 @@ export function isBoltRecordField(value: any): value is BoltRecordField { return export function isBoltRecordDeclaration(value: any): value is BoltRecordDeclaration { return value.kind === SyntaxKind.BoltRecordDeclaration; } -export function isBoltSourceElement(value: any): value is BoltSourceElement { return value.kind === SyntaxKind.BoltMacroCall || value.kind === SyntaxKind.BoltExportDirective || value.kind === SyntaxKind.BoltImportDirective || value.kind === SyntaxKind.BoltModule || value.kind === SyntaxKind.BoltRecordDeclaration || value.kind === SyntaxKind.BoltTypeAliasDeclaration || value.kind === SyntaxKind.BoltImplDeclaration || value.kind === SyntaxKind.BoltTraitDeclaration || value.kind === SyntaxKind.BoltVariableDeclaration || value.kind === SyntaxKind.BoltFunctionDeclaration || value.kind === SyntaxKind.BoltLoopStatement || value.kind === SyntaxKind.BoltExpressionStatement || value.kind === SyntaxKind.BoltResumeStatement || value.kind === SyntaxKind.BoltConditionalStatement || value.kind === SyntaxKind.BoltReturnStatement; } +export function isBoltSourceElement(value: any): value is BoltSourceElement { return value.kind === SyntaxKind.BoltMacroCall || value.kind === SyntaxKind.BoltExportDirective || value.kind === SyntaxKind.BoltImportDirective || value.kind === SyntaxKind.BoltModule || value.kind === SyntaxKind.BoltRecordDeclaration || value.kind === SyntaxKind.BoltTypeAliasDeclaration || value.kind === SyntaxKind.BoltVariableDeclaration || value.kind === SyntaxKind.BoltFunctionDeclaration || value.kind === SyntaxKind.BoltLoopStatement || value.kind === SyntaxKind.BoltExpressionStatement || value.kind === SyntaxKind.BoltResumeStatement || value.kind === SyntaxKind.BoltConditionalStatement || value.kind === SyntaxKind.BoltReturnStatement; } export function isBoltMacroCall(value: any): value is BoltMacroCall { return value.kind === SyntaxKind.BoltMacroCall; } @@ -3187,8 +3200,8 @@ export class Visitor { protected visitBoltPlainExportSymbol(node: BoltPlainExportSymbol): void { this.visitBoltExportSymbol(node); } protected visitBoltExportDirective(node: BoltExportDirective): void { this.visitBoltSourceElement(node); } protected visitBoltTraitOrImplElement(node: BoltTraitOrImplElement): void { this.visitSyntax(node); } - protected visitBoltTraitDeclaration(node: BoltTraitDeclaration): void { this.visitBoltDeclarationLike(node); this.visitBoltTypeDeclaration(node); } - protected visitBoltImplDeclaration(node: BoltImplDeclaration): void { this.visitBoltTypeDeclaration(node); this.visitBoltDeclarationLike(node); } + protected visitBoltTraitDeclaration(node: BoltTraitDeclaration): void { this.visitBoltDeclarationLike(node); } + protected visitBoltImplDeclaration(node: BoltImplDeclaration): void { this.visitBoltDeclarationLike(node); } protected visitBoltTypeAliasDeclaration(node: BoltTypeAliasDeclaration): void { this.visitBoltDeclarationLike(node); this.visitBoltTypeDeclaration(node); this.visitBoltTraitOrImplElement(node); } protected visitBoltRecordMember(node: BoltRecordMember): void { this.visitBoltSyntax(node); } protected visitBoltRecordField(node: BoltRecordField): void { this.visitBoltRecordMember(node); } diff --git a/src/bin/bolt-test.ts b/src/bin/bolt-test.ts index cc8cb962f..23bb18ef8 100644 --- a/src/bin/bolt-test.ts +++ b/src/bin/bolt-test.ts @@ -21,8 +21,6 @@ import { Parser } from "../parser" import { Scanner } from "../scanner" import { TextFile, TextPos, TextSpan } from "../text" import { deserializable, deserialize, Json, JsonObject, MapLike, serialize, serializeTag, upsearchSync, assert } from "../util" -import { resolve } from "path" -import { expect } from "chai" const PACKAGE_ROOT = path.resolve(path.dirname(upsearchSync('package.json')!)); const DEFAULT_STORAGE_DIR = 'test-storage'; diff --git a/src/common.ts b/src/common.ts index caa007d75..876ac7a4b 100644 --- a/src/common.ts +++ b/src/common.ts @@ -20,7 +20,7 @@ import { BOLT_SUPPORTED_LANGUAGES } from "./constants" import { FastStringMap, enumOr, escapeChar, assert, registerClass, Newable } from "./util"; import { TextSpan, TextPos, TextFile } from "./text"; import { Scanner } from "./scanner"; -import { convertNodeToSymbolPath } from "./resolver"; +import { convertNodeToSymbolPath, SymbolPath } from "./resolver"; import { TYPE_ERROR_MESSAGES } from "./diagnostics"; import { NODE_TYPES } from "./ast" @@ -231,7 +231,7 @@ export function hasDiagnostic(node: Syntax, message: string): boolean { return node.errors.some(d => d.message === message); } -export function getFullyQualifiedPathToNode(node: Syntax) { +export function getFullyQualifiedPathToNode(node: Syntax): SymbolPath { const symbolPath = convertNodeToSymbolPath(node); while (true) { const parentNode = node.parentNode; diff --git a/src/parser.ts b/src/parser.ts index dceaf71aa..83bb2e684 100644 --- a/src/parser.ts +++ b/src/parser.ts @@ -1300,8 +1300,8 @@ export class Parser { let modifiers = 0; let typeParams = null; - let traitTypeExpr = null; - let name; + let traitTypeExpr; + let typeExpr = null; // Parse the 'pub' keyword let t0 = tokens.get(); @@ -1337,16 +1337,26 @@ export class Parser { if (foundForKeyword) { + // Parse the type expression that references the trait the user wants to implement traitTypeExpr = this.parseTypeExpression(tokens); // Skip the 'for' keyword itself - tokens.get(); - } + assertToken(tokens.get(), SyntaxKind.BoltForKeyword); - // Parse the name of the type that this implementation is for - const t3 = tokens.get(); - assertToken(t3, SyntaxKind.BoltIdentifier); - name = t3 as BoltIdentifier; + // Parse the type that this implementation is for + typeExpr = this.parseTypeExpression(tokens); + + } else { + + // Just parse the trait the user wants to implement and leave the rest as is + const resultTypeExpr = this.parseTypeExpression(tokens); + + // We cheat a bit by assigning the referenced trait to both fields + // NOTE Assigning the same node by reference to different fields should be done with great care. + typeExpr = resultTypeExpr; + traitTypeExpr = resultTypeExpr; + + } // Parse all 'fn ...' and 'type ...' elements const t5 = tokens.get(); @@ -1354,7 +1364,7 @@ export class Parser { const elements = this.parseTraitOrImplElements(createTokenStream(t5)); // Create and return the result - const result = createBoltImplDeclaration(modifiers, typeParams, name, traitTypeExpr, elements); + const result = createBoltImplDeclaration(modifiers, typeParams, typeExpr, traitTypeExpr, elements); setOrigNodeRange(result, firstToken, t5); return result; } diff --git a/src/resolver.ts b/src/resolver.ts index cc70b9fed..74f6cc791 100644 --- a/src/resolver.ts +++ b/src/resolver.ts @@ -57,7 +57,13 @@ export function convertNodeToSymbolPath(node: Syntax): SymbolPath { return new SymbolPath( node.name.modulePath.map(id => id.text), node.name.isAbsolute, - emitNode(node.name), + emitNode(node.name.name), + ); + case SyntaxKind.BoltReferenceTypeExpression: + return new SymbolPath( + node.name.modulePath.map(id => id.text), + node.name.isAbsolute, + emitNode(node.name.name), ); case SyntaxKind.BoltIdentifier: return new SymbolPath([], false, emitNode(node)); @@ -164,7 +170,7 @@ export class BoltSymbolResolutionStrategy implements ResolutionStrategy { case SyntaxKind.BoltTraitDeclaration: return node.name.text; case SyntaxKind.BoltImplDeclaration: - return node.name.text; + return node.type; default: throw new Error(`Could not derive symbol name of node ${kindToString(node.kind)}`) } diff --git a/src/types.ts b/src/types.ts index f28ec09d0..35791e1fd 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,6 +1,6 @@ import { FastStringMap, assert, isPlainObject, some, prettyPrintTag, map, flatMap, filter, memoize, comparator, createTransparentProxy, TransparentProxy, every, FastMultiMap, getKeyTag } from "./util"; -import { SyntaxKind, Syntax, isBoltTypeExpression, BoltExpression, BoltFunctionDeclaration, BoltFunctionBodyElement, kindToString, SourceFile, isBoltExpression, BoltCallExpression, BoltIdentifier, isBoltDeclarationLike, isBoltPattern, isJSExpression, isBoltStatement, isJSStatement, isJSPattern, isJSParameter, isBoltParameter, isBoltMatchArm, isBoltRecordField, isBoltRecordFieldPattern, isEndOfFile, isSyntax, isBoltFunctionDeclaration, isBoltTypeDeclaration, isBoltRecordDeclaration, } from "./ast"; +import { SyntaxKind, Syntax, isBoltTypeExpression, BoltExpression, BoltFunctionDeclaration, BoltFunctionBodyElement, kindToString, SourceFile, isBoltExpression, BoltCallExpression, BoltIdentifier, isBoltDeclarationLike, isBoltPattern, isJSExpression, isBoltStatement, isJSStatement, isJSPattern, isJSParameter, isBoltParameter, isBoltMatchArm, isBoltRecordField, isBoltRecordFieldPattern, isEndOfFile, isSyntax, isBoltFunctionDeclaration, isBoltTypeDeclaration, isBoltRecordDeclaration, BoltImplDeclaration, isBoltTraitDeclaration, isBoltImplDeclaration, BoltTypeExpression, BoltDeclaration, BoltTypeDeclaration, BoltReferenceExpression, BoltReferenceTypeExpression, } from "./ast"; import { convertNodeToSymbolPath, ScopeType, SymbolResolver, SymbolInfo, SymbolPath } from "./resolver"; import { Value, Record } from "./evaluator"; import { getReturnStatementsInFunctionBody, getAllReturnStatementsInFunctionBody, getFullyQualifiedPathToNode, hasDiagnostic, hasTypeError } from "./common"; @@ -27,6 +27,7 @@ enum TypeKind { UnionType, TupleType, ReturnType, + TraitType, } export type Type @@ -40,6 +41,7 @@ export type Type | TupleType | UnionType | PlainRecordFieldType + | TraitType let nextTypeId = 1; @@ -65,6 +67,9 @@ function areTypesLexicallyEquivalent(a: Type, b: Type): boolean { if (a.kind === TypeKind.RecordType && b.kind === TypeKind.RecordType) { return a.source.id === b.source.id; } + if (a.kind === TypeKind.TraitType && b.kind === TypeKind.TraitType) { + return a.source.id === b.source.id; + } throw new Error(`I did not expected to see the provided type combination.`) @@ -107,6 +112,9 @@ function areTypesLexicallyLessThan(a: Type, b: Type): boolean { assert(b.source.id !== undefined) return a.source.id < b.source.id; } + if (a.kind === TypeKind.TraitType && b.kind === TypeKind.TraitType) { + return a.source.id < b.source.id; + } throw new Error(`I did not expected to see the provided type combination.`) } @@ -238,6 +246,21 @@ class PlainRecordFieldType extends TypeBase { } +export class TraitType extends TypeBase { + + public kind: TypeKind.TraitType = TypeKind.TraitType; + + private functionTypesByName = new FastStringMap(); + + constructor(public source: Syntax, public memberTypes: Iterable<[string, FunctionType]>) { + super(); + for (const [name, type] of memberTypes) { + this.functionTypesByName.set(name, type); + } + } + +} + export class RecordType extends TypeBase { public kind: TypeKind.RecordType = TypeKind.RecordType; @@ -491,7 +514,7 @@ export class TypeChecker { } private *diagnoseTypeMismatch(a: Type, b: Type): IterableIterator { - + // FIXME Implement this method } public registerSourceFile(sourceFile: SourceFile): void { @@ -499,6 +522,14 @@ export class TypeChecker { if (introducesType(node)) { node.type = new AnyType; } + if (isBoltImplDeclaration(node)) { + const scope = this.resolver.getScopeSurroundingNode(node, ScopeType.Type); + assert(scope !== null); + const traitSymbol = this.resolver.resolveSymbolPath(convertNodeToSymbolPath(node.traitTypeExpr), scope!) + for (const traitDecl of traitSymbol!.declarations) { + traitDecl.addImplDeclaration(node); + } + } } } @@ -564,9 +595,12 @@ export class TypeChecker { node.type!.solved.nextType = narrowedType; } for (const dependantNode of this.getParentsThatMightNeedUpdate(node)) { - nextQueue.add(dependantNode); + if (introducesType(dependantNode)) { + nextQueue.add(dependantNode); + } } for (const dependantNode of this.getNodesRequiringUpdate(node)) { + assert(introducesType(dependantNode)); nextQueue.add(dependantNode); } } @@ -644,6 +678,7 @@ export class TypeChecker { case TypeKind.OpaqueType: case TypeKind.FunctionType: case TypeKind.RecordType: + case TypeKind.TraitType: elementTypes.push(elementType); break; @@ -676,6 +711,7 @@ export class TypeChecker { case TypeKind.FunctionType: case TypeKind.RecordType: case TypeKind.OpaqueType: + case TypeKind.TraitType: elementTypes.push(elementType); break @@ -838,16 +874,27 @@ export class TypeChecker { return new AnyType; } - case SyntaxKind.BoltImplDeclaration: - { - return new AnyType; - } + //case SyntaxKind.BoltImplDeclaration: + //{ + // return new TraitType( + // node, + // node.elements + // .filter(isBoltFunctionDeclaration) + // .map(element => { + // this.markNodeAsRequiringUpdate(element, node); + // return [ + // emitNode(element.name), + // element.type!.solved + // ] as [string, FunctionType]; + // }) + // ); + //} - case SyntaxKind.BoltTraitDeclaration: - { - // TODO - return new AnyType; - } + //case SyntaxKind.BoltTraitDeclaration: + //{ + // // TODO + // return new AnyType; + //} case SyntaxKind.BoltVariableDeclaration: { @@ -1121,9 +1168,13 @@ export class TypeChecker { if (a.kind === TypeKind.RecordType && b.kind === TypeKind.RecordType) { return a.source === b.source; } + if (a.kind === TypeKind.TraitType && b.kind === TypeKind.TraitType) { + return a.source === b.source; + } // FIXME There are probably more cases that should be covered. - throw new Error(`I did not know how to calculate the equivalence of ${TypeKind[a.kind]} and ${TypeKind[b.kind]}`) + return false; + //throw new Error(`I did not know how to calculate the equivalence of ${TypeKind[a.kind]} and ${TypeKind[b.kind]}`) } private resolveReturnType(type: ReturnType): Type { @@ -1318,11 +1369,12 @@ export class TypeChecker { case TypeKind.FunctionType: case TypeKind.NeverType: case TypeKind.OpaqueType: + case TypeKind.TraitType: resultTypes.push(elementType); break; default: - throw new Error(`I did not know how to simpllify type ${TypeKind[elementType.kind]}`) + throw new Error(`I did not know how to simplify type ${TypeKind[elementType.kind]}`) }