Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1868315x 1868315x 1x 1x 1x 1x 1x 1x 235705x 97218x 235705x 80085x 138487x 58402x 58402x 235705x 1x 1x 1686502x 1059281x 1686502x 627221x 627221x 627221x 1686502x 1x 1x 12077512x 12077512x 12077512x 1x 1x 17624x 17624x 17624x 1x 1x 324415x 324415x 324415x 1x 1x | import {INode} from "./_inode";
import {AbstractToken} from "../1_lexer/tokens/abstract_token";
// shared constant, so nodes without children don't waste memory on empty arrays
const EMPTY: readonly INode[] = Object.freeze([]);
export abstract class AbstractNode<T extends INode> implements INode {
// a single child is stored directly, most nodes have exactly one child and an array costs ~56 bytes
private children: T | T[];
public constructor() {
this.children = EMPTY as T[];
}
public abstract get(): any;
public abstract getFirstToken(): AbstractToken;
public abstract getLastToken(): AbstractToken;
public addChild(n: T) {
if (this.children === EMPTY) {
this.children = n;
} else if (Array.isArray(this.children)) {
this.children.push(n);
} else {
this.children = [this.children, n];
}
}
public setChildren(children: T[]) {
if (children.length === 1) {
this.children = children[0];
} else {
// copy, input arrays are built via push() and carry over-allocated backing stores
this.children = children.length === 0 ? EMPTY as T[] : children.slice();
}
}
public getChildren(): readonly T[] {
const children = this.children;
return Array.isArray(children) ? children : [children];
}
public getFirstChild(): T | undefined {
const children = this.children;
return Array.isArray(children) ? children[0] : children;
}
public getLastChild(): T | undefined {
const children = this.children;
return Array.isArray(children) ? children[children.length - 1] : children;
}
}
|