UNPKG

@eagleoutice/flowr

Version:

Static Dataflow Analyzer and Program Slicer for the R Programming Language

165 lines 8.24 kB
"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