/**
* @author Alberto Cruz Luis <alu0101217734@ull.edu.es>
* @fileoverview constant-folding
*/
/**
* Constant Folding Module - Evaluate Expressions in compile time
* @module constant-folding
*/
const fs = require("fs");
const deb = require('../src/deb.js');
const escodegen = require("escodegen");
const espree = require("espree");
const estraverse = require("estraverse");
"use strict";
module.exports = constantFolding;
/**
* A function that evaluating expressions
* @function constantFolding
* @param {string} code A string that contain a expression
* @returns {string} Returns result of expression
*/
function constantFolding(code) {
const t = espree.parse(code, { ecmaVersion: 6, loc: false });
estraverse.traverse(t, {
leave: function (n, p) {
if (
n.type == "BinaryExpression" &&
n.left.type == "Literal" && n.right.type == "Literal"
) { replaceByLiteral(n); }
if (
n.type == "CallExpression" &&
n.callee.type == "MemberExpression"
) { replaceByCallExpression(n); }
},
});
let c = escodegen.generate(t);
return c
}
/**
* A function that evaluate a Literal
* @function replaceByLiteral
* @param {Object} node Node of AST
*/
function replaceByLiteral(node) {
node.type = "Literal";
node.value = eval(`${node.left.raw} ${node.operator} ${node.right.raw}`);
node.raw = String(node.value);
delete node.left;
delete node.right;
}
/**
* A function that evalute a ArrayExpression
* @function replaceByArrayExpression
* @param {Object} node Node of AST
*/
function replaceByCallExpression(node) {
if (node.callee.object.type == "ArrayExpression") {
node.type = node.callee.object.elements[0].type;
const node_arguments = node.arguments.map((arg) => arg.raw)
if (node.type == "Identifier") {
const elements = node.callee.object.elements.map((element) => element.name)
node.name = eval(`[${elements}].${node.callee.property.name}(${node_arguments})`)
}
if (node.type == "Literal") {
const elements = node.callee.object.elements.map((element) => element.raw)
node.value = eval(`[${elements}].${node.callee.property.name}(${node_arguments})`)
node.raw = String(node.value);
}
delete node.expression;
}
}