js-slang
Version:
Javascript-based implementations of Source, written in Typescript
94 lines • 3.82 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.objectToString = exports.nodeToValueWithContext = exports.nodeToValue = exports.valueToExpression = void 0;
const mocks_1 = require("../utils/testing/mocks");
const parser_1 = require("../parser/parser");
const types_1 = require("../types");
const builtin = require("./lib");
const stepper_1 = require("./stepper");
const util = require("./util");
// the value in the parameter is not an ast node, but a underlying javascript value
// return by evaluateBinaryExpression and evaluateUnaryExpression.
function valueToExpression(value, context) {
if (typeof value === 'object') {
return {
type: 'Literal',
value: value,
raw: objectToString(value)
};
}
if (typeof value === 'function' && context) {
let functionName = 'anonymous_' + generateRandomFunctionName();
while (Object.keys(context.runtime.environments[0]).includes(functionName)) {
functionName = 'anonymous_' + generateRandomFunctionName();
}
util.declareIdentifier(context, functionName, (0, mocks_1.mockImportDeclaration)(), context.runtime.environments[0]);
util.defineVariable(context, functionName, value, true, (0, mocks_1.mockImportDeclaration)());
return {
type: 'Identifier',
name: functionName
};
}
const programString = (typeof value === 'string' ? `"` + value + `"` : String(value)) + ';';
const program = (0, parser_1.parse)(programString, context ? context : (0, mocks_1.mockContext)(types_1.Chapter.SOURCE_2));
return program.body[0].expression;
}
exports.valueToExpression = valueToExpression;
function generateRandomFunctionName() {
const charset = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
let result = '';
for (let i = 0; i < 10; i++) {
const randomIndex = Math.floor(Math.random() * charset.length);
result += charset[randomIndex];
}
return result;
}
function nodeToValue(node) {
return node.type === 'Literal'
? node.value
: util.isBuiltinFunction(node)
? builtin[node.name]
: // tslint:disable-next-line
eval((0, stepper_1.javascriptify)(node));
}
exports.nodeToValue = nodeToValue;
function nodeToValueWithContext(node, context) {
return node.type === 'Literal'
? node.value
: util.isBuiltinFunction(node)
? builtin[node.name]
: node.type === 'Identifier' && util.isImportedFunction(node, context)
? context.runtime.environments[0].head[node.name]
: // tslint:disable-next-line
evaluateFunctionObject(node, context);
}
exports.nodeToValueWithContext = nodeToValueWithContext;
function evaluateFunctionObject(node, context) {
const builtinFunctions = context.runtime.environments[0].head;
// add identifiers used in the node to the global environment
function lookUpIdentifiers(node, visited) {
if (visited.has(node)) {
return;
}
visited.add(node);
if (node.type === 'Identifier' && builtinFunctions[node.name]) {
global[node.name] = builtinFunctions[node.name];
}
for (const key in node) {
if (node[key] && typeof node[key] === 'object') {
lookUpIdentifiers(node[key], visited);
}
}
}
lookUpIdentifiers(node, new Set());
const code = (0, stepper_1.javascriptify)(node);
return eval(code);
}
function objectToString(value) {
if (value !== null && 'toReplString' in value) {
return value.toReplString();
}
return '[Object]';
}
exports.objectToString = objectToString;
//# sourceMappingURL=converter.js.map
;