@eagleoutice/flowr
Version:
Static Dataflow Analyzer and Program Slicer for the R Programming Language
104 lines • 3.68 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.NodeVisitor = void 0;
const type_1 = require("../type");
const assert_1 = require("../../../../../util/assert");
const r_access_1 = require("../nodes/r-access");
const graph_1 = require("../../../../../dataflow/graph/graph");
// capsuled as a class to avoid passing onExit and onEnter on *each* visit call
class NodeVisitor {
onEnter;
onExit;
constructor(onEnter, onExit) {
this.onEnter = onEnter;
this.onExit = onExit;
}
visitSingle(node) {
if (this.onEnter?.(node)) {
return;
}
/* let the type system know that the type does not change */
const type = node.type;
switch (type) {
case type_1.RType.FunctionCall:
this.visitSingle(node.named ? node.functionName : node.calledFunction);
this.visit(node.arguments);
break;
case type_1.RType.FunctionDefinition:
this.visit(node.parameters);
this.visitSingle(node.body);
break;
case type_1.RType.ExpressionList:
this.visit(node.grouping);
this.visit(node.children);
break;
case type_1.RType.ForLoop:
this.visitSingle(node.variable);
this.visitSingle(node.vector);
this.visitSingle(node.body);
break;
case type_1.RType.WhileLoop:
this.visitSingle(node.condition);
this.visitSingle(node.body);
break;
case type_1.RType.RepeatLoop:
this.visitSingle(node.body);
break;
case type_1.RType.IfThenElse:
this.visitSingle(node.condition);
this.visitSingle(node.then);
this.visit(node.otherwise);
break;
case type_1.RType.BinaryOp:
case type_1.RType.Pipe:
this.visitSingle(node.lhs);
this.visitSingle(node.rhs);
break;
case type_1.RType.UnaryOp:
this.visitSingle(node.operand);
break;
case type_1.RType.Parameter:
this.visitSingle(node.name);
this.visit(node.defaultValue);
break;
case type_1.RType.Argument:
this.visit(node.name);
this.visit(node.value);
break;
case type_1.RType.Access:
this.visitSingle(node.accessed);
if (r_access_1.RAccess.isIndex(node)) {
this.visit(node.access);
}
break;
case type_1.RType.Symbol:
case type_1.RType.Logical:
case type_1.RType.Number:
case type_1.RType.String:
case type_1.RType.Comment:
case type_1.RType.Break:
case type_1.RType.Next:
case type_1.RType.LineDirective:
// leafs
break;
default:
(0, assert_1.assertUnreachable)(type);
}
this.onExit?.(node);
}
visit(nodes) {
if (Array.isArray(nodes)) {
const n = nodes;
for (const node of n) {
if (node && graph_1.FunctionArgument.isNotEmpty(node)) {
this.visitSingle(node);
}
}
}
else if (nodes) {
this.visitSingle(nodes);
}
}
}
exports.NodeVisitor = NodeVisitor;
//# sourceMappingURL=visitor.js.map