Loading files
This file is pinned to the selected release. Download the original to open it in your design tool.
import ScadFile from "./ast/ScadFile";
import ASTVisitor from "./ast/ASTVisitor";
import {
UnaryOpExpr,
BinaryOpExpr,
TernaryExpr,
ArrayLookupExpr,
LiteralExpr,
RangeExpr,
VectorExpr,
LookupExpr,
MemberLookupExpr,
FunctionCallExpr,
LetExpr,
AssertExpr,
EchoExpr,
LcIfExpr,
LcEachExpr,
LcForExpr,
LcForCExpr,
LcLetExpr,
GroupingExpr,
AnonymousFunctionExpr,
} from "./ast/expressions";
import {
UseStmt,
IncludeStmt,
ModuleInstantiationStmt,
ModuleDeclarationStmt,
FunctionDeclarationStmt,
BlockStmt,
NoopStmt,
IfElseStatement,
} from "./ast/statements";
import DocComment from "./comments/DocComment";
import {
ASTVisitorForNodesWithScopes,
BlockStmtWithScope,
LetExprWithScope,
ScadFileWithScope,
FunctionDeclarationStmtWithScope,
ModuleDeclarationStmtWithScope,
LcLetExprWithScope,
LcForExprWithScope,
LcForCExprWithScope,
ModuleInstantiationStmtWithScope,
AnonymousFunctionExprWithScope,
} from "./semantic/nodesWithScopes";
import AssignmentNode from "./ast/AssignmentNode";
import ASTNode from "./ast/ASTNode";
import ErrorNode from "./ast/ErrorNode";
export default class ASTMutator
implements ASTVisitorForNodesWithScopes<ASTNode>
{
visitScadFile(n: ScadFile): ASTNode {
const stmts = n.statements.map((s) => s.accept(this));
if (stmts.length === n.statements.length) {
let modified = false;
for (let i = 0; i < stmts.length; i++) {
if (stmts[i] !== n.statements[i]) {
modified = true;
break;
}
}
if (!modified) {
return n;
}
}
return new ScadFile(stmts, n.tokens);
}
visitAssignmentNode(n: AssignmentNode): ASTNode {
const newValue = n.value ? n.value.accept(this) : null;
if (newValue === n.value) {
return n;
}
return new AssignmentNode(n.name, newValue, n.role, n.tokens);
}
visitUnaryOpExpr(n: UnaryOpExpr): ASTNode {
const newRight = n.right.accept(this);
if (newRight === n.right) {
return n;
}
return new UnaryOpExpr(n.operation, newRight, n.tokens);
}
visitBinaryOpExpr(n: BinaryOpExpr): ASTNode {
const newLeft = n.left.accept(this);
const newRight = n.right.accept(this);
if (newRight === n.right && newLeft === n.left) {
return n;
}
return new BinaryOpExpr(newLeft, n.operation, newRight, n.tokens);
}
visitTernaryExpr(n: TernaryExpr): ASTNode {
const newCond = n.cond.accept(this);
const newIfExpr = n.ifExpr.accept(this);
const newElseExpr = n.elseExpr.accept(this);
if (
newCond === n.cond &&
newIfExpr === n.ifExpr &&
newElseExpr === n.elseExpr
) {
return n;
}
return new TernaryExpr(n.cond, n.ifExpr, n.elseExpr, n.tokens);
}
visitArrayLookupExpr(n: ArrayLookupExpr): ASTNode {
const newArray = n.array.accept(this);
const newIndex = n.index.accept(this);
if (newArray === n.array && newIndex === n.index) {
return n;
}
return new ArrayLookupExpr(newArray, newIndex, n.tokens);
}
visitLiteralExpr(n: LiteralExpr<any>): ASTNode {
return n;
}
visitRangeExpr(n: RangeExpr): ASTNode {
const newBegin = n.begin.accept(this);
const newStep = n.step ? n.step.accept(this) : null;
const newEnd = n.end.accept(this);
if (newBegin === n.begin && newStep === n.step && newEnd === n.end) {
return n;
}
return new RangeExpr(newBegin, newStep, newEnd, n.tokens);
}
visitVectorExpr(n: VectorExpr): ASTNode {
const newChildren = n.children.map((c) => c.accept(this));
if (newChildren.length === n.children.length) {
let modified = false;
for (let i = 0; i < newChildren.length; i++) {
if (newChildren[i] !== n.children[i]) {
modified = true;
break;
}
}
if (!modified) return n;
}
return new VectorExpr(newChildren, n.tokens);
}
visitLookupExpr(n: LookupExpr): ASTNode {
return n;
}
visitMemberLookupExpr(n: MemberLookupExpr): ASTNode {
const newExpr = n.expr.accept(this);
if (newExpr === n.expr) {
return n;
}
return new MemberLookupExpr(newExpr, n.member, n.tokens);
}
visitFunctionCallExpr(n: FunctionCallExpr): ASTNode {
const newArgs = n.args.map((a) => a.accept(this)) as AssignmentNode[];
const newCalee = n.callee.accept(this);
if (newArgs.length === n.args.length && newCalee === n.callee) {
let modified = false;
for (let i = 0; i < newArgs.length; i++) {
if (newArgs[i] !== n.args[i]) {
modified = true;
break;
}
}
if (!modified) return n;
}
return new FunctionCallExpr(newCalee, newArgs, n.tokens);
}
visitLetExpr(n: LetExpr): ASTNode {
const newExpr = n.expr.accept(this);
const newArgs = n.args.map((a) => a.accept(this)) as AssignmentNode[];
if (newArgs.length === n.args.length && newExpr === n.expr) {
let modified = false;
for (let i = 0; i < newArgs.length; i++) {
if (newArgs[i] !== n.args[i]) {
modified = true;
break;
}
}
if (!modified) return n;
}
return new LetExpr(newArgs, newExpr, n.tokens);
}
visitAssertExpr(n: AssertExpr): ASTNode {
const newExpr = n.expr.accept(this);
const newArgs = n.args.map((a) => a.accept(this)) as AssignmentNode[];
if (newArgs.length === n.args.length && newExpr === n.expr) {
let modified = false;
for (let i = 0; i < newArgs.length; i++) {
if (newArgs[i] !== n.args[i]) {
modified = true;
break;
}
}
if (!modified) return n;
}
return new AssertExpr(newArgs, newExpr, n.tokens);
}
visitEchoExpr(n: EchoExpr): ASTNode {
const newExpr = n.expr.accept(this);
const newArgs = n.args.map((a) => a.accept(this)) as AssignmentNode[];
if (newArgs.length === n.args.length && newExpr === n.expr) {
let modified = false;
for (let i = 0; i < newArgs.length; i++) {
if (newArgs[i] !== n.args[i]) {
modified = true;
break;
}
}
if (!modified) return n;
}
return new EchoExpr(newArgs, newExpr, n.tokens);
}
visitLcIfExpr(n: LcIfExpr): ASTNode {
const newCond = n.cond.accept(this);
const newIfExpr = n.ifExpr.accept(this);
const newElseExpr = n.elseExpr ? n.elseExpr.accept(this) : null;
if (
newCond === n.cond &&
newIfExpr === n.ifExpr &&
newElseExpr === n.elseExpr
) {
return n;
}
return new LcIfExpr(newCond, newIfExpr, newElseExpr, n.tokens);
}
visitLcEachExpr(n: LcEachExpr): ASTNode {
const newExpr = n.expr.accept(this);
if (newExpr === n.expr) {
return n;
}
return new LcEachExpr(newExpr, n.tokens);
}
visitLcForExpr(n: LcForExpr): ASTNode {
const newExpr = n.expr.accept(this);
const newArgs = n.args.map((a) => a.accept(this)) as AssignmentNode[];
if (newArgs.length === n.args.length && newExpr === n.expr) {
let modified = false;
for (let i = 0; i < newArgs.length; i++) {
if (newArgs[i] !== n.args[i]) {
modified = true;
break;
}
}
if (!modified) return n;
}
return new LcForExpr(newArgs, newExpr, n.tokens);
}
visitLcForCExpr(n: LcForCExpr): ASTNode {
const newArgs = n.args.map((a) => a.accept(this)) as AssignmentNode[];
const newIncrArgs = n.incrArgs.map((a) =>
a.accept(this)
) as AssignmentNode[];
const newExpr = n.expr.accept(this);
const newCond = n.cond.accept(this);
if (
newArgs.length === n.args.length &&
newIncrArgs.length === n.incrArgs.length &&
newExpr === n.expr &&
newCond === n.cond
) {
let modified = false;
for (let i = 0; i < newArgs.length; i++) {
if (newArgs[i] !== n.args[i]) {
modified = true;
break;
}
}
for (let i = 0; i < newIncrArgs.length; i++) {
if (newIncrArgs[i] !== n.incrArgs[i]) {
modified = true;
break;
}
}
if (!modified) return n;
}
return new LcForCExpr(newArgs, newIncrArgs, newCond, newExpr, n.tokens);
}
visitLcLetExpr(n: LcLetExpr): ASTNode {
const newExpr = n.expr.accept(this);
const newArgs = n.args.map((a) => a.accept(this)) as AssignmentNode[];
if (newArgs.length === n.args.length && newExpr === n.expr) {
let modified = false;
for (let i = 0; i < newArgs.length; i++) {
if (newArgs[i] !== n.args[i]) {
modified = true;
break;
}
}
if (!modified) return n;
}
return new LcLetExpr(newArgs, newExpr, n.tokens);
}
visitGroupingExpr(n: GroupingExpr): ASTNode {
const newInner = n.inner.accept(this);
if (newInner === n.inner) {
return n;
}
return new GroupingExpr(n.inner.accept(this), n.tokens);
}
visitUseStmt(n: UseStmt): ASTNode {
return n;
}
visitIncludeStmt(n: IncludeStmt): ASTNode {
return n;
}
visitModuleInstantiationStmt(n: ModuleInstantiationStmt): ASTNode {
// TODO: add cached check
const inst = new ModuleInstantiationStmt(
n.name,
n.args.map((a) => a.accept(this)) as AssignmentNode[],
n.child ? n.child.accept(this) : null,
n.tokens
);
inst.tagRoot = n.tagRoot;
inst.tagHighlight = n.tagHighlight;
inst.tagBackground = n.tagBackground;
inst.tagDisabled = n.tagDisabled;
return inst;
}
visitModuleDeclarationStmt(n: ModuleDeclarationStmt): ASTNode {
const newDefinitionArgs = n.definitionArgs.map((a) =>
a.accept(this)
) as AssignmentNode[];
const newStmt = n.stmt.accept(this);
if (
newDefinitionArgs.length === n.definitionArgs.length &&
newStmt === n.stmt
) {
let modified = false;
for (let i = 0; i < newDefinitionArgs.length; i++) {
if (newDefinitionArgs[i] !== n.definitionArgs[i]) {
modified = true;
break;
}
}
if (!modified) return n;
}
return new ModuleDeclarationStmt(
n.name,
newDefinitionArgs,
newStmt,
n.tokens,
n.docComment
);
}
visitFunctionDeclarationStmt(n: FunctionDeclarationStmt): ASTNode {
const newDefinitionArgs = n.definitionArgs.map((a) =>
a.accept(this)
) as AssignmentNode[];
const newExpr = n.expr.accept(this);
if (
newDefinitionArgs.length === n.definitionArgs.length &&
newExpr === n.expr
) {
let modified = false;
for (let i = 0; i < newDefinitionArgs.length; i++) {
if (newDefinitionArgs[i] !== n.definitionArgs[i]) {
modified = true;
break;
}
}
if (!modified) return n;
}
return new FunctionDeclarationStmt(
n.name,
newDefinitionArgs,
newExpr,
n.tokens,
n.docComment
);
}
visitBlockStmt(n: BlockStmt): ASTNode {
const children = n.children.map((s) => s.accept(this));
if (children.length === n.children.length) {
let modified = false;
for (let i = 0; i < children.length; i++) {
if (children[i] !== n.children[i]) {
modified = true;
break;
}
}
if (!modified) {
return n;
}
}
return new BlockStmt(children, n.tokens);
}
visitNoopStmt(n: NoopStmt): ASTNode {
return n;
}
visitIfElseStatement(n: IfElseStatement): ASTNode {
const newCond = n.cond.accept(this);
const newThenBranch = n.thenBranch.accept(this);
const newElseBranch = n.elseBranch ? n.elseBranch.accept(this) : null;
if (
newCond === n.cond &&
newThenBranch === n.thenBranch &&
newElseBranch === n.elseBranch
) {
return n;
}
return new IfElseStatement(newCond, newThenBranch, newElseBranch, n.tokens);
}
visitErrorNode(n: ErrorNode): ASTNode {
return n;
}
visitAnonymousFunctionExpr(n: AnonymousFunctionExpr): ASTNode {
const newArgs = n.definitionArgs.map((a) =>
a.accept(this)
) as AssignmentNode[];
const newBody = n.expr.accept(this);
if (newArgs.length === n.definitionArgs.length && newBody === n.expr) {
let modified = false;
for (let i = 0; i < newArgs.length; i++) {
if (newArgs[i] !== n.definitionArgs[i]) {
modified = true;
break;
}
}
if (!modified) return n;
}
return new AnonymousFunctionExpr(newArgs, newBody, n.tokens);
}
visitBlockStmtWithScope(n: BlockStmtWithScope): ASTNode {
const oldNode = this.visitBlockStmt(n) as BlockStmt;
const newNode = new BlockStmtWithScope(oldNode.children, oldNode.tokens);
newNode.scope = n.scope;
return newNode;
}
visitLetExprWithScope(n: LetExprWithScope): ASTNode {
const oldNode = this.visitLetExpr(n) as LetExpr;
const newNode = new LetExprWithScope(
oldNode.args,
oldNode.expr,
oldNode.tokens
);
newNode.scope = n.scope;
return newNode;
}
visitScadFileWithScope(n: ScadFileWithScope): ASTNode {
const oldNode = this.visitScadFile(n) as ScadFile;
const newNode = new ScadFileWithScope(oldNode.statements, oldNode.tokens);
newNode.scope = n.scope;
return newNode;
}
visitFunctionDeclarationStmtWithScope(
n: FunctionDeclarationStmtWithScope
): ASTNode {
const oldNode = this.visitFunctionDeclarationStmt(
n
) as FunctionDeclarationStmt;
const newNode = new FunctionDeclarationStmtWithScope(
oldNode.name,
oldNode.definitionArgs,
oldNode.expr,
oldNode.tokens,
oldNode.docComment
);
newNode.scope = n.scope;
return newNode;
}
visitModuleDeclarationStmtWithScope(
n: ModuleDeclarationStmtWithScope
): ASTNode {
const oldNode = this.visitModuleDeclarationStmt(n) as ModuleDeclarationStmt;
const newNode = new ModuleDeclarationStmtWithScope(
oldNode.name,
oldNode.definitionArgs,
oldNode.stmt,
oldNode.tokens,
n.docComment
);
newNode.scope = n.scope;
return newNode;
}
visitModuleInstantiationStmtWithScope(n: ModuleInstantiationStmtWithScope) {
const oldNode = this.visitModuleInstantiationStmt(
n
) as ModuleInstantiationStmt;
const newNode = new ModuleInstantiationStmtWithScope(
oldNode.name,
oldNode.args,
oldNode.child,
oldNode.tokens
);
newNode.scope = n.scope;
return newNode;
}
visitLcLetExprWithScope(n: LcLetExprWithScope): ASTNode {
const oldNode = this.visitLcLetExpr(n) as LcLetExpr;
const newNode = new LcLetExprWithScope(
oldNode.args,
oldNode.expr,
oldNode.tokens
);
newNode.scope = n.scope;
return newNode;
}
visitLcForExprWithScope(n: LcForExprWithScope): ASTNode {
const oldNode = this.visitLcForExpr(n) as LcForExpr;
const newNode = new LcForExprWithScope(
oldNode.args,
oldNode.expr,
oldNode.tokens
);
newNode.scope = n.scope;
return newNode;
}
visitLcForCExprWithScope(n: LcForCExprWithScope): ASTNode {
const oldNode = this.visitLcForCExpr(n) as LcForCExpr;
const newNode = new LcForCExprWithScope(
oldNode.args,
oldNode.incrArgs,
oldNode.cond,
oldNode.expr,
oldNode.tokens
);
newNode.scope = n.scope;
return newNode;
}
visitAnonymousFunctionExprWithScope(n: AnonymousFunctionExprWithScope) {
const oldNode = this.visitAnonymousFunctionExpr(n) as AnonymousFunctionExpr;
const newNode = new AnonymousFunctionExprWithScope(
oldNode.definitionArgs,
oldNode.expr,
oldNode.tokens
);
newNode.scope = n.scope;
return newNode;
}
}
2d56448eaThis file is pinned to the selected release. Download the original to open it in your design tool.