Java-Gaming.org    
Featured games (81)
games approved by the League of Dukes
Games in Showcase (494)
Games in Android Showcase (114)
games submitted by our members
Games in WIP (563)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  Yet Another Wrapper: Rhino (JavaScript in Java)  (Read 3935 times)
0 Members and 1 Guest are viewing this topic.
Offline Riven
« League of Dukes »

JGO Overlord


Medals: 796
Projects: 4
Exp: 16 years


Hand over your head.


« Posted 2009-07-20 09:40:31 »

For everybody that had to deal with Rhino, or was scared off when walking through the tutorials... how to mix Contexts in interpreted mode and how all those Scriptables interact with eachother, and all those other quirks.

I got sick of all the boilerplate code I had to write, so I simplified it so the extend of being maybe even a bit too easy persecutioncomplex


As always, sourcecode and JAR available:
http://www.katav.nl/html_stuff2/ => jawnae.js.*


Example 1: (creating a script)

String code = "var my = 'javascript code';";
JsScript script = new JsScript(code);
script.execute();



Example 2: (creating a function)

String code = "function sum(a, b) { return a + b; }";
JsFunction func = new JsFunction(code);
func.invoke(13, 14);



Example 3: (using a function from an external script)

JsScope shared = new JsScope();

String sumCode = "function sum(a, b) { return a + b; }";
JsFunction func = new JsFunction(code, shared);

String useCode = "var x=3; var y=4; var z=sum(x, y)";
JsScript script = new JsScript(useCode, shared);
script.execute();
script.eval("x = y + z;");



Example 4: (green threads!!)

JsScope scope = new JsScope();
scope.setInterpretedContext(true);
scope.put("out", System.out);

String code = "";
code += "out.println("step 1");";
code += "Thread.yield();"; // continuation!
code += "out.println("step 2");";
code += "Thread.sleep(1000);"; // continuation!
code += "out.println("step 3");";
// thread1: code += "Thread.wait('this_is_a_lock');";
// thread2: code += "Thread.notify('this_is_a_lock');";

JsScript script1 = new JsScript(code);
JsScript script2 = new JsScript(code);

JsCPU cpu = new JsCPU();
cpu.addThread(new JsThread(script1));
cpu.addThread(new JsThread(script2));

while(cpu.hasThreads())
{
    cpu.tick();
}



There is also a debug mode (JsStepper), so that you can read the (local) scope of a function while it is executing.

For more examples: http://www.katav.nl/html_stuff2/source/test/jawnae/js/JsUnitTest.html


Have fun!

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Offline Mr_Light

Senior Member


Medals: 1


shiny.


« Reply #1 - Posted 2009-07-20 18:43:34 »

somehow example 3 doesn't jive with me.

Have you opted going for something like this?:

1  
2  
3  
4  
JsScope scope = new JsScope();
scope.addFunction("sum(a, b) { return a + b; }");
scope.executeScript("var x=3; var y=4; var z=sum(x, y)");
scope.executeScript("x = y + z;");


or probably better and more sophisticated:

1  
2  
3  
4  
JsScope scope = new JsScope();
scope.addFunction("sum(a, b) { return a + b; }"); // Convience method for scope.add(new JsFunction("sum(a, b) { return a + b; }"));
scope.addScript("var x=3; var y=4; var z=sum(x, y)"); // Convience method for scope.add(new JsScript("sum(a, b) { return a + b; }"));
script.eval("x = y + z;"); // execute scripts in the scope then eval the script.


Having to inspect the Function to see what scope belongs to kinda makes it useless and leaves it dangling. This way you can share functions among scopes though the way JS works this is probably bad(lets make a function an abstraction of a a function definition and we're in the clear) Hopefully this would allow some form of caching of optimalisations under the hood somewhere.



Keep up the good work Smiley

It's harder to read code than to write it. - it's even harder to write readable code.

The gospel of brother Riven: "The guarantee that all bugs are in *your* code is worth gold." Amen brother a-m-e-n.
Offline Riven
« League of Dukes »

JGO Overlord


Medals: 796
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #2 - Posted 2009-07-20 20:11:57 »

Well, that's all possible, and easy to implement, because nothing changes under the hood.

scope.addScript(JsScript) makes little sense however, because you don't have a handle to execute it, unless I return that, but then you end up with:

JsScript script = scope.addScript(code);
as opposed to
JsScript script = new JsScript(code, scope);


JsFunction and JsScript both extend JsScope, so those convenience methods really can get quirky:
scope.addFunction("code1").addFunction("code2").addFunction("code3");
which are nested scopes.

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline DzzD
« Reply #3 - Posted 2009-07-20 20:38:28 »

dont have much time to look at it right now but seems so cool that I answer just to track this thread Wink

Offline Riven
« League of Dukes »

JGO Overlord


Medals: 796
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #4 - Posted 2009-07-20 20:39:17 »

I added your suggestions, and I made some further changes.

scope.printProperties();
which is like PHP var_dump


It is now possible to modify the prototype of an Object.



      String printlnCode = "";
      printlnCode += "println( obj )";
      printlnCode += "{";
      printlnCode += "   if(typeof obj == 'undefined')";
      printlnCode += "      obj = 'undefined';";
      printlnCode += "   else if(typeof obj == 'object')";
      printlnCode += "      obj = obj.toString();";
      printlnCode += "   out.println(obj);";
      printlnCode += "}";

      JsScope scope = new JsScope();
      scope.putVariable("out", System.out);
      scope.addFunction(printlnCode);

      JsFunction vector = scope.addFunction("Vector( x, y, z ) { this.x=x; this.y=y; this.z=z; }");

      scope.eval("var vec1 = new Vector(3,4,5);");
      scope.eval("var vec2 = new Vector(8,5,2);");

      // this will now print "[Object object]"
      scope.eval("println('vector.toString() => '+Vector.prototype.toString);");
      scope.eval("println(vec1);");

      // modify the prototype
      JsScope prototype = vector.getPrototype();
      prototype.putVariable("isUnitVector", Boolean.FALSE);
      prototype.addFunction("add( that ) { this.x+=that.x; this.y+=that.y; this.z+=that.z; }");
      prototype.addFunction("toString()  { return this.x+','+this.y+','+this.z; }");
      prototype.printProperties(); // very useful for debugging

      // this will now print "{x},{y},{z}"
      scope.eval("println('vector.toString() => '+Vector.prototype.toString);");
      scope.eval("println(vec1);");
      scope.eval("println(vec2);");
      
      scope.eval("println('sum is: ');");
      scope.eval("vec1.add(vec2);"); // prototype function
      scope.eval("println(vec1);");

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Offline Riven
« League of Dukes »

JGO Overlord


Medals: 796
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #5 - Posted 2009-07-20 20:45:04 »

dont have much time to look at it right now but seems so cool that I answer just to track this thread Wink

Thanks Smiley


P.S.
You can scroll to the first post and press Notify to get... notified:
[Reply] [Notify] [Mark unread] [Send this topic] [Print]

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Offline Mr_Light

Senior Member


Medals: 1


shiny.


« Reply #6 - Posted 2009-07-20 23:40:32 »

Well, that's all possible, and easy to implement, because nothing changes under the hood.

scope.addScript(JsScript) makes little sense however, because you don't have a handle to execute it, unless I return that, but then you end up with:

JsScript script = scope.addScript(code);
as opposed to
JsScript script = new JsScript(code, scope);
Well my notion was that addScript simply adds inline javascript

1  
2  
function foo() { .. }
var inline = ...

and eval was run against the scope(as opposed to added and executed)

whats the difference between eval vs (addscript + execute)

JsFunction and JsScript both extend JsScope, so those convenience methods really can get quirky:
scope.addFunction("code1").addFunction("code2").addFunction("code3");
which are nested scopes.

that would be the equivialent of:
Quote
code1() {
 code2() {
  code3() {
  }
 }
}
that's screwy indeed. I suppose you could return this and if ppl need the handle they just need to create it manually. which would make if you wanted the above kinda scewy:

Quote
scope.add(
 new JsFunction("code1").add(
  new JsFunction("code2").add(
   new Function("code3")   
  )
 )
);
Quote
JsFunction code1 = new JsFunction("code1");
JsFunction code2 = new JsFunction("code2");
JsFunction code3 = new JsFunction("code3");
code1.add(code2);
code2.add(code3);
scope.add(code1);
Or something it's getting late :p I'll have a closer look tomorro

It's harder to read code than to write it. - it's even harder to write readable code.

The gospel of brother Riven: "The guarantee that all bugs are in *your* code is worth gold." Amen brother a-m-e-n.
Offline Riven
« League of Dukes »

JGO Overlord


Medals: 796
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #7 - Posted 2009-07-20 23:43:23 »

Quote
whats the difference between eval vs (addscript + execute)


addScript + execute compiles the javascript, eval interprets it - massive diff in performance.

with compiled javascript, you can get up to 10% of Java's performance - which is surprisingly good.

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Offline Riven
« League of Dukes »

JGO Overlord


Medals: 796
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #8 - Posted 2009-07-21 00:20:43 »

Boy was I wrong...

No difference between [eval] and [script] at all...! Both are compiled, as long as the optimisation levels are set in the Context. Functions however are twice as fast!


Java code
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
      int count = 0;
      for (int i = 2; i < 7500; i++)
      {
         boolean isPrime = true;

         for (int k = 2; k < i; k++)
         {
            if (i % k == 0)
            {
               isPrime = false;
               break;
            }
         }

         if (isPrime)
         {
            count++;
         }
      }
      return count;



Javascript code
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
for(var i=2; i<7500; i++)
{
   var isPrime = true;
   for(var k=2; k<i; k++)
   {
      if(i%k==0)
      {
         isPrime = false;
         break;
      }
   }
   if(isPrime)
   {
      count++;
   }
}




js [script opt level 9] took: 848ms
js [script opt level 9] took: 834ms
js [script opt level 9] took: 796ms
js [script opt level 9] took: 839ms

js [script opt level -1] took: 2405ms
js [script opt level -1] took: 2537ms
js [script opt level -1] took: 2641ms
js [script opt level -1] took: 2246ms

js [function opt level 9] took: 438ms Shocked
js [function opt level 9] took: 420ms
js [function opt level 9] took: 399ms 
js [function opt level 9] took: 328ms

js [function opt level -1] took: 1646ms
js [function opt level -1] took: 1967ms
js [function opt level -1] took: 1722ms
js [function opt level -1] took: 1670ms

java took: 27ms  Roll Eyes
java took: 27ms
java took: 26ms
java took: 22ms



So in this example, with compiled functions, we're dealing with factor 20 performance loss.
Interpreted scripts (required for continuations / green threads) are factor 100 slower.

Use with caution Smiley


Update:
Appearantly not that bad:
http://www.citengineering.com/luaview/performance.html
   Lua is about twenty to thirty times slower than C

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Offline jezek2
« Reply #9 - Posted 2009-07-21 06:58:05 »

So in this example, with compiled functions, we're dealing with factor 20 performance loss.
Interpreted scripts (required for continuations / green threads) are factor 100 slower.

If the main reason are continuations, you can use them in Java too: Continuations Library

And good thing is that performance is very good as most compute heavy methods can stay untouched, just the control code gets modified (thus somewhat slower).
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline Riven
« League of Dukes »

JGO Overlord


Medals: 796
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #10 - Posted 2009-07-21 07:29:12 »

Hrrr... everytime that link shows up. No, the continuations are not the main reason. This is a Javascript wrapper, as Rhino is just a pain in the ass to get up and running - it's a lot of trial and error to figure things out. I 'extended' it with fancy Thread.* functionality, like wait/notify/notifyAll among green threads, yielding and sleeping.

Anyway, I'm not a huge fan of Java continuations. I've never needed them, they only come in handy when writing scripts, in which case I use Javascript.

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Offline jezek2
« Reply #11 - Posted 2009-07-21 08:36:27 »

Anyway, I'm not a huge fan of Java continuations. I've never needed them, they only come in handy when writing scripts, in which case I use Javascript.

I have good experience with using them in game code, it's nice to have everything in Java as you can reuse the same stuff, etc. and can mix it without need to hard separate things. Of course it's separated somehow, but the softer borderline allowed nicer overall architecture of my engine Smiley
Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

Dwinin (23 views)
2014-09-12 09:08:26

Norakomi (56 views)
2014-09-10 13:57:51

TehJavaDev (69 views)
2014-09-10 06:39:09

Tekkerue (34 views)
2014-09-09 02:24:56

mitcheeb (56 views)
2014-09-08 06:06:29

BurntPizza (40 views)
2014-09-07 01:13:42

Longarmx (25 views)
2014-09-07 01:12:14

Longarmx (31 views)
2014-09-07 01:11:22

Longarmx (31 views)
2014-09-07 01:10:19

mitcheeb (38 views)
2014-09-04 23:08:59
List of Learning Resources
by Longor1996
2014-08-16 10:40:00

List of Learning Resources
by SilverTiger
2014-08-05 19:33:27

Resources for WIP games
by CogWheelz
2014-08-01 16:20:17

Resources for WIP games
by CogWheelz
2014-08-01 16:19:50

List of Learning Resources
by SilverTiger
2014-07-31 16:29:50

List of Learning Resources
by SilverTiger
2014-07-31 16:26:06

List of Learning Resources
by SilverTiger
2014-07-31 11:54:12

HotSpot Options
by dleskov
2014-07-08 01:59:08
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!