UNPKG

@eagleoutice/flowr

Version:

Static Dataflow Analyzer and Program Slicer for the R Programming Language

157 lines 5.04 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.RNull = exports.RNa = exports.RInf = exports.RIntegerMarker = exports.RImaginaryMarker = exports.RNumHexFloatRegex = exports.RFalse = exports.RTrue = void 0; exports.ts2r = ts2r; exports.isBoolean = isBoolean; exports.boolean2ts = boolean2ts; exports.number2ts = number2ts; exports.string2ts = string2ts; exports.isNA = isNA; class ValueConversionError extends Error { constructor(message) { super(message); this.name = 'ValueConversionError'; } } /** * transforms a value to something R can understand (e.g., booleans to TRUE/FALSE) */ function ts2r(value) { if (typeof value === 'string') { return JSON.stringify(value); } else if (typeof value === 'number') { if (isNaN(value)) { return exports.RNa; } else if (!isFinite(value)) { return exports.RInf; } return value.toString(); } else if (typeof value === 'boolean') { return value ? 'TRUE' : 'FALSE'; } else if (value === null) { return 'NULL'; } else if (typeof value === 'undefined') { return 'NA'; } else if (Array.isArray(value)) { return `c(${value.map(ts2r).join(', ')})`; } else if (typeof value === 'object') { const obj = Object.entries(value) .map(([key, value]) => `${key} = ${ts2r(value)}`) .join(', '); return `list(${obj})`; } throw new ValueConversionError(`cannot convert value of type ${typeof value} to R code`); } /** The R literal for the logical true */ exports.RTrue = 'TRUE'; /** The R literal for the logical false */ exports.RFalse = 'FALSE'; function isBoolean(value) { return value === exports.RTrue || value === exports.RFalse; } function boolean2ts(value) { if (value === exports.RTrue) { return true; } else if (value === exports.RFalse) { return false; } throw new ValueConversionError(`value ${value} is not a legal R boolean`); } exports.RNumHexFloatRegex = /^\s*0x(?<intPart>[0-9a-f]+)?(\.(?<floatPart>[0-9a-f]*))?p(?<exp>[-+]?\d+)\s*$/; function getDecimalPlacesWithRadix(floatPart, radix) { return [...floatPart].reduce((acc, c, idx) => acc + parseInt(c, radix) / (radix ** (idx + 1)), 0); } exports.RImaginaryMarker = 'i'; exports.RIntegerMarker = 'L'; exports.RInf = 'Inf'; function number2ts(value) { // check for hexadecimal number with floating point addon which is supported by R but not by JS :/ let lcValue = value.toLowerCase(); /* both checks are case-sensitive! */ const last = value[value.length - 1]; const markedAsInt = last === exports.RIntegerMarker; const complexNumber = last === exports.RImaginaryMarker; if (markedAsInt || complexNumber) { lcValue = lcValue.slice(0, -1); } if (value === exports.RInf) { return { num: Infinity, complexNumber, markedAsInt }; } if (value === exports.RNa) { return { num: NaN, complexNumber, markedAsInt }; } const floatHex = lcValue.match(exports.RNumHexFloatRegex); if (floatHex == null) { return { num: Number(lcValue), complexNumber, markedAsInt }; } else { const { intPart, floatPart, exp } = floatHex.groups; const base = intPart === undefined ? 0 : parseInt(`${intPart}`, 16); const floatSuffix = floatPart === undefined ? 0 : getDecimalPlacesWithRadix(floatPart, 16); const exponent = parseInt(exp, 10); return { num: (base + floatSuffix) * Math.pow(2, exponent), complexNumber, markedAsInt }; } } /** * Convert a valid R string into a {@link RStringValue}. * * @throws {@link ValueConversionError} if the string has an unknown starting quote */ function string2ts(value) { if (value.length < 2) { throw new ValueConversionError(`cannot parse string '${value}' as it is too short`); } const init = value[0]; if (init === '"' || init === '\'') { return { str: value.slice(1, -1), quotes: init }; } else if (init === 'r' || init === 'R' && value.length >= 3) { const flags = value[1]; if (flags === '"' || flags === '\'') { return { str: value.slice(2, -1), quotes: flags, flag: 'raw' }; } else { throw new ValueConversionError(`expected string to start with a known quote (' or "), or raw, yet received ${value}`); } } else { throw new ValueConversionError(`expected string to start with a known quote (' or "), or raw, yet received ${value}`); } } exports.RNa = 'NA'; exports.RNull = 'NULL'; function isNA(value) { return value === exports.RNa; } //# sourceMappingURL=convert-values.js.map