#### Howdy, Stranger!

We are about to switch to a new forum software. Until then we have removed the registration on this forum.

# eval JS with power // general help on eval js.eval

edited April 2017

Hello,

I have a question to gotoloops for js.eval

How can I say 3 to the power of 2 (3^2)? How can I say 3! or 6 % 2 or squareroot of 81?

Is there a general help on the beast?

thanks!

Best, Chrisir ;-)

``````import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;

// for evaluation of math
javax.script.ScriptEngine js1;

//
String textLocal = "3 * 4" ;

void setup() {

js1 = new ScriptEngineManager().getEngineByName("js");
}

void draw() {

textLocal = "4 ^ 2" ;

if (!textLocal.equals("")) {

String test1 = evalJS(this, js1, textLocal);

if (!test1.equals("")) {

println( test1 ) ; // success
}
}
}
//

String evalJS(PApplet pa, ScriptEngine js, String expression) {
js.put("p", pa);

try {
Object obj1=js.eval("" + expression);
return obj1.toString();
}

catch (ScriptException cause) {
//throw new RuntimeException(cause);
return "";
}
} //
//
``````
Tagged:

• JavaScript, Java, C, C++, C# share almost all of their operators.
"4 ^ 2" is in JS as it is in Java: the XOR bitwise operator.

The way to get 4 power 2 is via Math's pow() method: `"Math.pow(4, 2);"` https://developer.Mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/pow

• ??

what do I put in line 20 above for "Math.pow(4, 2);" and for 6! and 4%3 .... ? And 81 sqrt ?

• but thanks...... ;-)

• @gotoloop

Or did you mean line 20 ??

Thanks!

• ups, I see....

• @Chrisir, just like Java, JS doesn't have a factorial operator.
The `!` operator is the logical NOT operator:

Complete JS operators: https://developer.Mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators

BtW, do you remember some sketches using ScriptEngine for JS not too long ago?

• Reposting ScriptEngine wrapper functions here.
initJSProcessingEnv(), evalJS(), compileJS(), runJS(), invokeJS().

They're about 150 lines. So it's best to paste them in a separate ".pde" tab, away from our sight. :P

``````import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;

import javax.script.Invocable;
import javax.script.Compilable;
import javax.script.CompiledScript;

static final void initJSProcessingEnv
(final ScriptEngine js, final PApplet pa) {
js.put("p", pa); // puts sketch's PApplet as p into JS.

js.put("w", pa.width);  // puts width's  current value as w into JS.
js.put("h", pa.height); // puts height's current value as h into JS.

evalJS(js, // imports Processing's core classes.
"var PApplet         = Java.type('processing.core.PApplet'),",
"    PConstants      = Java.type('processing.core.PConstants')",
"    PFont           = Java.type('processing.core.PFont'),",
"    PGraphics       = Java.type('processing.core.PGraphics'),",
"    PImage          = Java.type('processing.core.PImage'),",
"    PMatrix         = Java.type('processing.core.PMatrix'),",
"    PMatrix2D       = Java.type('processing.core.PMatrix2D'),",
"    PMatrix3D       = Java.type('processing.core.PMatrix3D'),",
"    PShape          = Java.type('processing.core.PShape'),",
"    PShapeOBJ       = Java.type('processing.core.PShapeOBJ'),",
"    PShapeSVG       = Java.type('processing.core.PShapeSVG'),",
"    PStyle          = Java.type('processing.core.PStyle'),",
"    PSurface        = Java.type('processing.core.PSurface'),",
"    PSurfaceNone    = Java.type('processing.core.PSurfaceNone'),",
"    PVector         = Java.type('processing.core.PVector')");

evalJS(js, // imports Processing's data classes.
"var FloatDict       = Java.type('processing.data.FloatDict'),",
"    FloatList       = Java.type('processing.data.FloatList'),",
"    IntDict         = Java.type('processing.data.IntDict'),",
"    IntList         = Java.type('processing.data.IntList'),",
"    JSONArray       = Java.type('processing.data.JSONArray'),",
"    JSONObject      = Java.type('processing.data.JSONObject'),",
"    JSONTokener     = Java.type('processing.data.JSONTokener'),",
"    Sort            = Java.type('processing.data.Sort'),",
"    StringDict      = Java.type('processing.data.StringDict'),",
"    StringList      = Java.type('processing.data.StringList'),",
"    Table           = Java.type('processing.data.Table'),",
"    TableRow        = Java.type('processing.data.TableRow'),",
"    XML             = Java.type('processing.data.XML')");

evalJS(js, // imports Processing's event classes.
"var Event           = Java.type('processing.event.Event'),",
"    KeyEvent        = Java.type('processing.event.KeyEvent'),",
"    MouseEvent      = Java.type('processing.event.MouseEvent'),",
"    TouchEvent      = Java.type('processing.event.TouchEvent')");

evalJS(js, // imports Processing's opengl classes.
"var FontTexture     = Java.type('processing.opengl.FontTexture'),",
"    FrameBuffer     = Java.type('processing.opengl.FrameBuffer')",
"    LinePath        = Java.type('processing.opengl.LinePath'),",
"    LineStroker     = Java.type('processing.opengl.LineStroker'),",
"    PGL             = Java.type('processing.opengl.PGL'),",
"    PGraphics2D     = Java.type('processing.opengl.PGraphics2D'),",
"    PGraphics3D     = Java.type('processing.opengl.PGraphics3D'),",
"    PGraphicsOpenGL = Java.type('processing.opengl.PGraphicsOpenGL'),",
"    PJOGL           = Java.type('processing.opengl.PJOGL'),",
"    PShapeOpenGL    = Java.type('processing.opengl.PShapeOpenGL'),",
"    PSurfaceJOGL    = Java.type('processing.opengl.PSurfaceJOGL'),",
"    Texture         = Java.type('processing.opengl.Texture'),",
"    VertexBuffer    = Java.type('processing.opengl.VertexBuffer')");

evalJS(js, // imports some Java's classes.
"var ArrayList       = java.util.ArrayList,",
"    HashMap         = java.util.HashMap,",
"    File            = java.io.File,",
"    PrintWriter     = java.io.PrintWriter,",
"    InputStream     = java.io.InputStream,",
"    OutputStream    = java.io.OutputStream,",
"    IOException     = java.io.IOException");

evalJS(js, // transfers all PConstants' to JS global scope.
"for each (var f in PConstants.class.getFields()) {",
"  var name = f.getName(), field = PConstants[name]",
"  if (!this[name])  this[name] = field",
"}");

evalJS(js, // transfers all PApplet's static fields to JS global scope.
"for each (var f in PApplet.class.getFields()) {",
"  var name = f.getName(), field = PApplet[name]",
"  if (field && !this[name])  this[name] = field",
"}");

evalJS(js, // transfers all PApplet's static methods to JS global scope.
"for each (var m in PApplet.class.getDeclaredMethods()) {",
"  var name = m.getName(), method = PApplet[name]",
"  if (method && !this[name])  this[name] = method",
"}");

evalJS(js, // transfers all JS' Math static properties to global scope.
"for each (var prop in Object.getOwnPropertyNames(Math))"
+ "if (!this[prop])  this[prop] = Math[prop]");
}

@ SafeVarargs static final Object evalJS
(final ScriptEngine js, final String... statements) {
final String expression = PApplet.join(statements, PConstants.ENTER);

try {
return js.eval(expression);
}
catch (final ScriptException cause) {
PApplet.println(cause);
System.err.println(expression);
throw new RuntimeException(cause);
}
}

@ SafeVarargs static final CompiledScript compileJS
(final ScriptEngine js, final String... statements) {
final String expression = PApplet.join(statements, PConstants.ENTER);

try {
return ((Compilable) js).compile(expression);
}
catch (final ScriptException cause) {
PApplet.println(cause);
System.err.println(expression);
throw new RuntimeException(cause);
}
}

static final Object runJS
(final CompiledScript compiled) {
try {
return compiled.eval();
}
catch (final ScriptException cause) {
PApplet.println(cause);
throw new RuntimeException(cause);
}
}

@ SafeVarargs static final Object invokeJS
(final ScriptEngine js, final String funct, final Object... args) {
try {
return ((Invocable) js).invokeFunction(funct, args);
}
catch (final Exception cause) {
PApplet.println(cause);
System.err.println(funct);
PApplet.printArray(args);
throw new RuntimeException(cause);
}
}
``````
• And I've also tweaked some factorial JS function from:
http://StackOverflow.com/questions/3959211/fast-factorial-function-in-javascript#3959275

``````// StackOverflow.com/questions/3959211/
// fast-factorial-function-in-javascript#3959275

// Mod by GoToLoop (2016-Jun-17)

final CompiledScript factorial = compileJS(js,
"factorial.MAX  = 100",
"_fact._memoize = [1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800]",

"function factorial(n) _fact(min(abs(n | 0), factorial.MAX), _fact._memoize)",
"function _fact(n, f)  f[n] || (f[n] = _fact(n-1, f) * n)");
``````

And some sample on how to use it:

``````runJS(factorial);

long fact20 = (long) (double) evalJS(js,
"var fact = factorial(20)",
"print('Factorial of 20 ->', fact)",
"fact");
println("Factorial of 20 ->", fact20, ENTER);

double fact60 = (double) evalJS(js,
"var fact = factorial(60)",
"print('Factorial of 60 ->', fact)",
"fact");
println("Factorial of 60 ->", fact60);
``````
• To finalize, a full old sketch converted to Nashorn JS:

Don't forget to paste the 2 tabs above, since the main tab here depends on them all: >-)

``````/**
* Talking Faces [Nashorn JS] (v1.12)
* by  Casselli (2015/Feb/07)
* mod GoToLoop (2016/Jun/16)
*
* forum.Processing.org/two/discussion/17161/
* eval-js-with-power-general-help-on-eval-js-eval#Item_9
*
* forum.Processing.org/two/discussion/15151/
* how-to-convert-string-to-a-line-of-code#Item_9
*
* forum.Processing.org/two/discussion/9323/
* creating-a-extra-function-in-order-to-create-
* multiple-instances-of-the-same-group-of-primitives#Item_6
*
*/

final ScriptEngine js = new ScriptEngineManager().getEngineByName("Nashorn");

final CompiledScript globals = compileJS(js,
"BG = ~~0xff403090, FACES = 4, FPS = 12",
"faces = Array(FACES)");

final CompiledScript setup = compileJS(js,
"p.frameRate(FPS)",
"p.ellipseMode(Face.MODE), p.rectMode(Face.MODE)",
"p.stroke(Face.STROKE), p.strokeWeight(Face.WEIGHT)");

final CompiledScript draw = compileJS(js,
"p.background(BG)",
"for each (var f in faces)  f.display()");

final CompiledScript initFaces = compileJS(js,
"faces = new Face(w>>2,   h>>2,   w/3,     h/2.5)",
"faces = new Face(3*w>>2, h>>2,   w/3/1.2, h/2.5/1.2)",
"faces = new Face(w>>2,   3*h>>2, w/3/2,   h/2.5/2)",
"faces = new Face(3*w>>2, 3*h>>2, w/3*1.2, h/2.5*1.2)");

final CompiledScript classFace = compileJS(js,
"function Face(x, y, w, h) {", // Face's constructor + properties.
"  this.x = x, this.y = y, this.w = w, this.h = h, this.m = .5*(w+h)",
"}",

// Face's static constant(s):
"Face.MODE = CENTER, Face.WEIGHT = 1.5, Face.STROKE = 0",
"Face.FACE = ~~0xffFFFF00, Face.NOSE = ~~0xffFF0000",
"Face.EYES = 0, Face.MOUTH = ~~0xffFF00FF",

// Face's prototype method(s):
"Face.prototype.display = function () {",
"  p.fill(Face.FACE), p.ellipse(this.x, this.y, this.w, this.h)",
"  p.fill(Face.NOSE), p.ellipse(this.x, this.y, this.w/6, this.h>>2)",

"  var ww = this.w/6.5, yh = this.y - (this.h>>3), mm = this.m/9.65",
"  p.fill(Face.EYES)",
"  p.ellipse(this.x - ww, yh, mm, mm)",
"  p.ellipse(this.x + ww, yh, mm, mm)",

"  p.fill(Face.MOUTH)",
"  p.rect(this.x, this.y + this.h/3.2, this.w/2.6, p.random(this.h>>4))",
"}");

void setup() {
size(600, 600);
smooth(4);

initJSProcessingEnv(js, this);

runJS(globals);
runJS(classFace);
runJS(setup);
runJS(initFaces);

runJS(factorial);

long fact20 = ((Number) evalJS(js,
"var fact = factorial(20)",
"print('Factorial of 20 ->', fact)",
"fact")).longValue();
println("Factorial of 20 ->", fact20, ENTER);

double fact80 = ((Number) evalJS(js,
"var fact = factorial(80)",
"print('Factorial of 80 ->', fact)",
"fact")).doubleValue();
println("Factorial of 80 ->", fact80);
}

void draw() {
runJS(draw);
}
``````
• Thank you so much.

To be honest , I wanted a way to eval equations like 3 + 4 for my little ChatBot. Google can answer stuff like 3+4 or 4^3 (4 to the power of 3).

So I tried eval and some of it like 3*4 worked right away.

Now I realized that this eval can do full codes and not only formulas

Is there another way to just evaluate math formulas typed by the user?

Thanks, Chrisir

• Now I realized that this eval() can do full codes and not only formulas.

Yup! Nashorn is a full ECMA5 JS implementation embedded into Java's API. ~O)

And here's a nice trick for wrappers evalJS() & compileJS():
Their last parameter is `String... statements`. It means they can accept an array of strings.
Thus we can pass loadStrings() to them. That is, we can load scripts from files. *-:)

Is there another way to just evaluate math formulas typed by the user?

My initJSProcessingEnv() transfers all Processing's static API to the JS' global scope.
Therefore we can eval() strings like: `sqrt(9)`, `pow(3, 2)`, `cos(TAU)`, etc.

But watch out: Nashorn got access to the whole Java's API + Processing's API.
It means n1 can type in whole programs for eval() w/ malicious intent and hack the computer! :-SS

• initJSProcessingEnv

seems great

Is there a way only eval math formula without the security issue big as a truck?

• Gotoloop could you answer this bit for me

Thank you...

• edited June 2016 Answer ✓

Hmm. That's gonna need some study from here:

Maybe I may try out to come up w/ some solution based on it... :-\"