@eagleoutice/flowr
Version:
Static Dataflow Analyzer and Program Slicer for the R Programming Language
165 lines • 8.24 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.resolveNode = resolveNode;
exports.resolveAsVector = resolveAsVector;
exports.resolveAsSeq = resolveAsSeq;
exports.resolveAsPlus = resolveAsPlus;
exports.resolveAsMinus = resolveAsMinus;
const r_function_call_1 = require("../../../r-bridge/lang-4.x/ast/model/nodes/r-function-call");
const type_1 = require("../../../r-bridge/lang-4.x/ast/model/type");
const r_value_1 = require("../../../util/r-value");
const built_in_1 = require("../../environments/built-in");
const interval_constants_1 = require("../values/intervals/interval-constants");
const logical_constants_1 = require("../values/logical/logical-constants");
const r_value_2 = require("../values/r-value");
const string_constants_1 = require("../values/string/string-constants");
const vector_constants_1 = require("../values/vectors/vector-constants");
const alias_tracking_1 = require("./alias-tracking");
const scalar_constants_1 = require("../values/scalar/scalar-constants");
const identifier_1 = require("../../environments/identifier");
const node_id_1 = require("../../../r-bridge/lang-4.x/ast/model/processing/node-id");
const df_helper_1 = require("../../graph/df-helper");
/**
* Helper function used by {@link resolveIdToValue}, please use that instead, if
* you want to resolve the value of an identifier / node
*
* This function converts an RNode to its Value, but also recursively resolves
* aliases and vectors (in case of node vector).
* @returns resolved value or top/bottom
*/
function resolveNode({ resolve, node, ctx, blocked, environment, graph, idMap }) {
const nt = node.type;
if (nt === type_1.RType.String) {
return (0, string_constants_1.stringFrom)(node.content.str);
}
else if (nt === type_1.RType.Number) {
return (0, interval_constants_1.intervalFrom)(node.content.num, node.content.num);
}
else if (nt === type_1.RType.Logical) {
return node.content.valueOf() ? logical_constants_1.ValueLogicalTrue : logical_constants_1.ValueLogicalFalse;
}
else if (nt === type_1.RType.FunctionDefinition) {
return { type: 'function-definition' };
}
else if ((nt === type_1.RType.FunctionCall || nt === type_1.RType.BinaryOp || nt === type_1.RType.UnaryOp) && graph) {
const origin = df_helper_1.Dataflow.origin(graph, node.info.id)?.[0];
if (origin === undefined || origin.type !== 3 /* OriginType.BuiltInFunctionOrigin */) {
return r_value_2.Top;
}
let builtInName;
if (node_id_1.NodeId.isBuiltIn(origin.proc)) {
builtInName = origin.proc;
}
else if (nt === type_1.RType.FunctionCall && node.named) {
builtInName = node_id_1.NodeId.toBuiltIn(identifier_1.Identifier.getName(node.functionName.content));
}
else if (nt === type_1.RType.BinaryOp || nt === type_1.RType.UnaryOp) {
builtInName = node_id_1.NodeId.toBuiltIn(node.operator);
}
else {
return r_value_2.Top;
}
if (Object.hasOwn(built_in_1.BuiltInEvalHandlerMapper, builtInName)) {
const handler = built_in_1.BuiltInEvalHandlerMapper[builtInName];
return handler({ resolve, node, ctx, blocked, environment, graph, idMap });
}
}
return r_value_2.Top;
}
/**
* Helper function used by {@link resolveIdToValue}, please use that instead, if
* you want to resolve the value of an identifier / node
*
* This function resolves a vector function call `c` to a {@link ValueVector}
* by recursively resolving the values of the arguments by calling {@link resolveIdToValue}
* @returns ValueVector or Top
*/
function resolveAsVector({ resolve, environment, node, graph, idMap, ctx, blocked }) {
if (node.type !== type_1.RType.FunctionCall) {
return r_value_2.Top;
}
const resolveInfo = { environment, graph, idMap, full: true, resolve, ctx, blocked };
const values = node.arguments.map(arg => arg !== r_function_call_1.EmptyArgument ? (0, alias_tracking_1.resolveIdToValue)(arg.value, resolveInfo) : r_value_2.Top);
return (0, vector_constants_1.vectorFrom)((0, vector_constants_1.flattenVectorElements)(values));
}
/**
* Helper function used by {@link resolveIdToValue}, please use that instead, if
* you want to resolve the value of an identifier / node
*
* This function resolves a binary sequence operator `:` to a {@link ValueVector} of {@link ValueNumber}s
* by recursively resolving the values of the arguments by calling {@link resolveIdToValue}
* @returns ValueVector of ValueNumbers or Top
*/
function resolveAsSeq({ node: operator, environment, resolve, ctx, graph, idMap, blocked }) {
if (operator.type !== type_1.RType.BinaryOp) {
return r_value_2.Top;
}
const resolveInfo = { environment, graph, idMap, full: true, resolve, ctx, blocked };
const leftArg = (0, alias_tracking_1.resolveIdToValue)(operator.lhs, resolveInfo);
const rightArg = (0, alias_tracking_1.resolveIdToValue)(operator.rhs, resolveInfo);
const leftValue = (0, r_value_1.unliftRValue)(leftArg);
const rightValue = (0, r_value_1.unliftRValue)(rightArg);
if ((0, r_value_1.isRNumberValue)(leftValue) && (0, r_value_1.isRNumberValue)(rightValue)) {
return (0, vector_constants_1.vectorFrom)(createNumberSequence(leftValue, rightValue).map(scalar_constants_1.liftScalar));
}
return r_value_2.Top;
}
/**
* Helper function used by {@link resolveIdToValue}, please use that instead, if
* you want to resolve the value of an identifier / node
*
* This function resolves a unary plus operator `+` to a {@link ValueNumber} or {@link ValueVector} of ValueNumbers
* by recursively resolving the values of the arguments by calling {@link resolveIdToValue}
* @returns ValueNumber, ValueVector of ValueNumbers, or Top
*/
function resolveAsPlus({ node: operator, environment, resolve, ctx, graph, idMap, blocked }) {
if (operator.type !== type_1.RType.UnaryOp) {
return r_value_2.Top;
}
const resolveInfo = { environment, graph, idMap, full: true, resolve, ctx, blocked };
const arg = (0, alias_tracking_1.resolveIdToValue)(operator.operand, resolveInfo);
const argValue = (0, r_value_1.unliftRValue)(arg);
if ((0, r_value_1.isRNumberValue)(argValue)) {
return (0, scalar_constants_1.liftScalar)(argValue);
}
else if (Array.isArray(argValue) && argValue.every(r_value_1.isRNumberValue)) {
return (0, vector_constants_1.vectorFrom)(argValue.map(scalar_constants_1.liftScalar));
}
return r_value_2.Top;
}
/**
* Helper function used by {@link resolveIdToValue}, please use that instead, if
* you want to resolve the value of an identifier / node
*
* This function resolves a unary minus operator `-` to a {@link ValueNumber} or {@link ValueVector} of ValueNumbers
* by recursively resolving the values of the arguments by calling {@link resolveIdToValue}
* @returns ValueNumber, ValueVector of ValueNumbers, or Top
*/
function resolveAsMinus({ node: operator, environment, resolve, ctx, graph, idMap, blocked }) {
if (operator.type !== type_1.RType.UnaryOp) {
return r_value_2.Top;
}
const resolveInfo = { environment, graph, idMap, full: true, resolve, ctx, blocked };
const arg = (0, alias_tracking_1.resolveIdToValue)(operator.operand, resolveInfo);
const argValue = (0, r_value_1.unliftRValue)(arg);
if ((0, r_value_1.isRNumberValue)(argValue)) {
return (0, scalar_constants_1.liftScalar)({ ...argValue, num: -argValue.num });
}
else if (Array.isArray(argValue) && argValue.every(r_value_1.isRNumberValue)) {
return (0, vector_constants_1.vectorFrom)(argValue.map(element => (0, scalar_constants_1.liftScalar)({ ...element, num: -element.num })));
}
return r_value_2.Top;
}
function createNumberSequence(start, end) {
const sequence = [];
const min = Math.min(start.num, end.num);
const max = Math.max(start.num, end.num);
for (let i = min; i <= max; i++) {
sequence.push({ ...start, num: i });
}
if (start > end) {
sequence.reverse();
}
return sequence;
}
//# sourceMappingURL=resolve.js.map