@eagleoutice/flowr
Version:
Static Dataflow Analyzer and Program Slicer for the R Programming Language
189 lines • 8.87 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 dfg_get_origin_1 = require("../../origin/dfg-get-origin");
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_consatnts_1 = require("../values/scalar/scalar-consatnts");
/**
* 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 a vector).
*
* @param a - Ast node to resolve
* @param resolve - Variable resolve mode
* @param env - Environment to use
* @param graph - Dataflow Graph to use
* @param map - Idmap of Dataflow Graph
* @returns resolved value or top/bottom
*/
function resolveNode(resolve, a, env, graph, map) {
if (a.type === type_1.RType.String) {
return (0, string_constants_1.stringFrom)(a.content.str);
}
else if (a.type === type_1.RType.Number) {
return (0, interval_constants_1.intervalFrom)(a.content.num, a.content.num);
}
else if (a.type === type_1.RType.Logical) {
return a.content.valueOf() ? logical_constants_1.ValueLogicalTrue : logical_constants_1.ValueLogicalFalse;
}
else if ((a.type === type_1.RType.FunctionCall || a.type === type_1.RType.BinaryOp || a.type === type_1.RType.UnaryOp) && graph) {
const origin = (0, dfg_get_origin_1.getOriginInDfg)(graph, a.info.id)?.[0];
if (origin === undefined || origin.type !== 3 /* OriginType.BuiltInFunctionOrigin */) {
return r_value_2.Top;
}
let builtInName;
if ((0, built_in_1.isBuiltIn)(origin.proc)) {
builtInName = origin.proc;
}
else if (a.type === type_1.RType.FunctionCall && a.named) {
builtInName = (0, built_in_1.builtInId)(a.functionName.content);
}
else if (a.type === type_1.RType.BinaryOp || a.type === type_1.RType.UnaryOp) {
builtInName = (0, built_in_1.builtInId)(a.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, a, env, graph, map);
}
}
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}
*
* @param resolve - Variable resolve mode
* @param node - Node of the vector function to resolve
* @param env - Environment to use
* @param graph - Dataflow graph
* @param map - Id map of the dataflow graph
* @returns ValueVector or Top
*/
function resolveAsVector(resolve, node, environment, graph, idMap) {
if (node.type !== type_1.RType.FunctionCall) {
return r_value_2.Top;
}
const resolveInfo = { environment, graph, idMap, full: true, resolve };
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}
*
* @param resolve - Variable resolve mode
* @param operator - Node of the sequence operator to resolve
* @param env - Environment to use
* @param graph - Dataflow graph
* @param map - Id map of the dataflow graph
* @returns ValueVector of ValueNumbers or Top
*/
function resolveAsSeq(resolve, operator, environment, graph, idMap) {
if (operator.type !== type_1.RType.BinaryOp) {
return r_value_2.Top;
}
const resolveInfo = { environment, graph, idMap, full: true, resolve };
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_consatnts_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}
*
* @param resolve - Variable resolve mode
* @param operator - Node of the plus operator to resolve
* @param env - Environment to use
* @param graph - Dataflow graph
* @param map - Id map of the dataflow graph
* @returns ValueNumber, ValueVector of ValueNumbers, or Top
*/
function resolveAsPlus(resolve, operator, environment, graph, idMap) {
if (operator.type !== type_1.RType.UnaryOp) {
return r_value_2.Top;
}
const resolveInfo = { environment, graph, idMap, full: true, resolve };
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_consatnts_1.liftScalar)(argValue);
}
else if (Array.isArray(argValue) && argValue.every(r_value_1.isRNumberValue)) {
return (0, vector_constants_1.vectorFrom)(argValue.map(scalar_consatnts_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}
*
* @param resolve - Variable resolve mode
* @param operator - Node of the minus operator to resolve
* @param env - Environment to use
* @param graph - Dataflow graph
* @param map - Id map of the dataflow graph
* @returns ValueNumber, ValueVector of ValueNumbers, or Top
*/
function resolveAsMinus(resolve, operator, environment, graph, idMap) {
if (operator.type !== type_1.RType.UnaryOp) {
return r_value_2.Top;
}
const resolveInfo = { environment, graph, idMap, full: true, resolve };
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_consatnts_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_consatnts_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