JS-Interpreter
JS-Interpreter copied to clipboard
Creating a function?
Hi,
Is it possible to create a function, and then run the interpreter while passing arguments to the created function?
I need to replicate this:
var f = new Function('return a + b);
res = f(10,5)
But without using new Function (which is obviously an eval)
I "kind of" managed by writing a function that creates the string that defines the function and passes it the params:
global.jsRun = function (code, ...args) {
var fullCode = `function run(){${code}\n}\nrun(${args.map(a => JSON.stringify(a)).join(',')})`
console.log(`code: ${fullCode}`)
var myInterpreter = new global.JSInterpreter.Interpreter(fullCode)
myInterpreter.run()
return myInterpreter.value
}
However, one of the parameters is a rather large object, and it messses up the code. Is there a way to create a function and then pass it parameters directly from the API, rather than just evaluate code?
THANK YOU!!!
Well I think I got somewhere. Here it is: (remember that this is node)
global.acorn = require('./node_modules/js-interpreter/acorn.js')
global.JSInterpreter = require('./node_modules/js-interpreter/interpreter.js')
global.jsRun = function (code, ...args) {
var fullCode = `var arguments = JSON.parse(_args);${code}`
var initFunc = function (interpreter, scope) {
interpreter.setProperty(scope, '_args', JSON.stringify(args))
}
var myInterpreter = new global.JSInterpreter.Interpreter(fullCode, initFunc)
myInterpreter.run()
return myInterpreter.value
}
console.log(jsRun('arguments[0]', 10, 20))
OR, to actually run it in a function (so that 38472384 already written calculators don't have to be rewritten since they use return):
// JSInterpreter runner function
global.acorn = require('./node_modules/js-interpreter/acorn.js')
global.JSInterpreter = require('./node_modules/js-interpreter/interpreter.js')
global.jsRun = function (code, ...args) {
var fullCode = `var args = JSON.parse(_args);function f(){${code}};f(args)`
var initFunc = function (interpreter, scope) {
interpreter.setProperty(scope, '_args', JSON.stringify(args))
}
var myInterpreter = new global.JSInterpreter.Interpreter(fullCode, initFunc)
myInterpreter.run()
return myInterpreter.value
}
console.log(global.jsRun('return args[0] + args[1]', 10, 20))
Sounds OK doesn't it? The code itself doesn't have anything extra except the very first line; so, any errors will give out the right line...
A better approach is to put the values you want to pass into variables in the global scope:
var a = /* ... */, b = /* ... */;
var myInterpreter = new Interpreter('a + b');
myInterpreter.setValueToScope('a', myInterpreter.nativeToPseudo(a));
myInterpreter.setValueToScope('b', myInterpreter.nativeToPseudo(b));
myInterpreter.run();
var r = myInterpreter.pseudoToNative(myInterpreter.value);
Of course if you want to treat user-supplied code as the body of a function (so the user can use return to explicitly specify the result value) then just wrap the user code in an IIFE:
var userCode = /* ... */;
var code = '(function(a, b) {' + userCode + '})(a, b)';
var myInterpreter = new Interpreter(code);
/* ... */
Hey... just one note: neither of them are documented. Or did I miss them? Would you mind me doing a PR to improve documentation? If so, are there other methods that are worthwhile knowing?