Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit c419e44

Browse files
authoredDec 16, 2019
feat: traits, initial implementation (#46)
* trait impl * use traits for References * checkpoint * use Self reference in Reference impl
1 parent 4a00ac4 commit c419e44

File tree

164 files changed

+18508
-11423
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

164 files changed

+18508
-11423
lines changed
 

‎src/compiler/nodes.ts

+25-4
Original file line numberDiff line numberDiff line change
@@ -143,9 +143,8 @@ export namespace Nodes {
143143
export abstract class ExpressionNode extends Node {}
144144

145145
export class NameIdentifierNode extends Node {
146+
impls = new Set<ImplDirective>();
146147
internalIdentifier?: string;
147-
namespaceNames?: Map<string, NameIdentifierNode>;
148-
parentNamespace?: NameIdentifierNode;
149148

150149
get childrenOrEmpty(): Node[] {
151150
return [];
@@ -489,16 +488,25 @@ export namespace Nodes {
489488
}
490489

491490
export class ImplDirective extends DirectiveNode {
491+
baseImpl?: ReferenceNode;
492+
selfTypeName?: NameIdentifierNode;
493+
readonly namespaceNames: Map<string, NameIdentifierNode> = new Map();
494+
492495
constructor(
493496
astNode: ASTNode,
494-
public readonly reference: ReferenceNode,
497+
public readonly targetImpl: ReferenceNode,
495498
public readonly directives: DirectiveNode[]
496499
) {
497500
super(astNode);
498501
}
499502

500503
get childrenOrEmpty() {
501-
return [...(this.decorators || []), this.reference, ...(this.directives || [])];
504+
return [
505+
...(this.decorators || []),
506+
this.targetImpl,
507+
...(this.baseImpl ? [this.baseImpl] : []),
508+
...(this.directives || [])
509+
];
502510
}
503511
}
504512

@@ -593,6 +601,19 @@ export namespace Nodes {
593601
}
594602
}
595603

604+
export class TraitDirectiveNode extends DirectiveNode {
605+
readonly namespaceNames: Map<string, NameIdentifierNode> = new Map();
606+
selfTypeName?: NameIdentifierNode;
607+
608+
constructor(astNode: ASTNode, public readonly traitName: NameIdentifierNode, public directives: DirectiveNode[]) {
609+
super(astNode);
610+
}
611+
612+
get childrenOrEmpty() {
613+
return [...(this.decorators || []), this.traitName, ...this.directives];
614+
}
615+
}
616+
596617
export class EnumDirectiveNode extends DirectiveNode {
597618
constructor(
598619
astNode: ASTNode,

‎src/compiler/phases/canonicalPhase.ts

+45-3
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,10 @@ const visitor = {
112112
return ret;
113113
},
114114
ImplDirective(astNode: Nodes.ASTNode) {
115-
const reference = visit(findChildrenTypeOrFail(astNode, 'Reference'));
115+
const references = astNode.children.filter($ => $.type === 'Reference');
116+
117+
// the last Reference is the target
118+
const target = visit(references.pop()!);
116119

117120
const directivesNode = findChildrenType(astNode, 'NamespaceElementList');
118121

@@ -121,7 +124,11 @@ const visitor = {
121124
: [];
122125
// TODO: warn
123126

124-
const ret = new Nodes.ImplDirective(astNode, reference, directives);
127+
const ret = new Nodes.ImplDirective(astNode, target, directives);
128+
129+
if (references.length) {
130+
ret.baseImpl = visit(references.pop()!);
131+
}
125132

126133
ret.isPublic = !findChildrenType(astNode, 'PrivateModifier');
127134

@@ -199,6 +206,8 @@ const visitor = {
199206

200207
const variableName = visit(child);
201208

209+
console.assert(!!variableName, 'missing variable name');
210+
202211
const ret = new Nodes.TypeDirectiveNode(astNode, variableName);
203212

204213
ret.isPublic = isPublic;
@@ -230,6 +239,34 @@ const visitor = {
230239

231240
return ret;
232241
},
242+
TraitDirective(astNode: Nodes.ASTNode) {
243+
const children = astNode.children.slice();
244+
245+
let child = children.shift()!;
246+
let isPublic = true;
247+
248+
if (child.type === 'PrivateModifier') {
249+
isPublic = false;
250+
child = children.shift()!;
251+
}
252+
253+
const variableName = visit(child);
254+
255+
const typeDeclElements = findChildrenType(astNode, 'TraitDeclElements');
256+
257+
const declarations = typeDeclElements ? typeDeclElements.children.map($ => visit($)) : [];
258+
259+
declarations.forEach($ => {
260+
if ($ instanceof Nodes.FunDirectiveNode && !$.functionNode.body) {
261+
$.functionNode.annotate(new annotations.SignatureDeclaration());
262+
}
263+
});
264+
265+
const ret = new Nodes.TraitDirectiveNode(astNode, variableName, declarations);
266+
ret.isPublic = isPublic;
267+
268+
return ret;
269+
},
233270
FunDeclaration(astNode: Nodes.ASTNode) {
234271
const functionName = visit(
235272
findChildrenTypeOrFail(astNode, 'FunctionName', 'A function name is required').children[0]
@@ -251,7 +288,12 @@ const visitor = {
251288
}
252289

253290
fun.parameters = params.children.map($ => visit($));
254-
fun.body = visitLastChild(astNode);
291+
292+
const body = findChildrenType(astNode, 'FunAssignExpression');
293+
294+
if (body) {
295+
fun.body = visitLastChild(body);
296+
}
255297

256298
return fun;
257299
},
There was a problem loading the remainder of the diff.

0 commit comments

Comments
 (0)
Failed to load comments.