Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Creating a function? #143

Open
mercmobily opened this issue Sep 12, 2018 · 3 comments
Open

Creating a function? #143

mercmobily opened this issue Sep 12, 2018 · 3 comments
Labels

Comments

@mercmobily
Copy link

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!!!

@mercmobily
Copy link
Author

mercmobily commented Sep 12, 2018

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...

@cpcallen
Copy link
Collaborator

cpcallen commented Sep 12, 2018

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);
/* ... */

@mercmobily
Copy link
Author

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?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants