Pages: 1
  Print  
Author Topic: EGMJS  (Read 1224 times)
Offline (Male) Josh @ Dreamland
Posted on: December 14, 2012, 01:57:26 PM

Prince of all Goldfish
Developer
Location: Pittsburgh, PA, USA
Joined: Feb 2008
Posts: 2958

View Profile Email
TGMG's interested in maintaining the EGMJS port I started a while back, and doing that under the new parser will be pretty easy, imo.

This topic is to try to make it even easier for him.

I will record general notes to all implementers on the Wiki. Notes specifically concerning my thoughts on the implementation of EGMJS will go in this topic.

My first concern is on how TGMG will load definitions. Presently, ENIGMA uses a central JDI context to store its definitions. Since JDI is inherently a C++ parser, this is done by invoking it on the engine file directly. JDI is not a JavaScript parser. However, JDI's structure is easy to figure out, and JavaScript is capable of reflection. The way I see it, there are three ways you can go about this:

1) Choose the language that is going to host the crawler.
This can be Java using javax.script.ScriptEngine (javax.script.ScriptEngineManager.getEngineByName("JavaScript")), or in C++ using Google V8. Both methods have their advantages:
  • If you use Java's ScriptEngine class, no additional libraries need included or set up. Java's also pretty good about doing the integration for you, and building V8 for Windows is an impossible task (it requires MSVC++). The difficulty is that you have to get this information back to ENIGMA, and it adds ENIGMA.jar as a dependency to the process (meaning a CLI build without Java will be completely impossible).
  • If you use Google V8, everything can be done from within C++; you can use JavaScript reflection to call native methods directly. The C++ methods can populate JDI structures in memory while the JavaScript engine is doing the iteration. This is bound to be more efficient, as Java does not guarantee its scripting engines are even compiled, to my knowledge.

The bottom line is, by this method, you need to use JavaScript reflection to communicate a list of available functions to ENIGMA so the parser can do syntax checking.

The other method that I can see you using is having emscripten parse the JavaScript engine, and then polling it for definition names to pack into JDI classes. This method has similar advantages. On the downside, it means that EGMJS is dependent on LLVM—that's a heavy dependency that I'm in general not fond of. On the other hand, it means that you'll be asking LLVM for the definitions and (probably) using LLVM to store the code so emscripten can compile the code, which would open doors for ENIGMA to compile to other languages for which LLVM has pretty-printers. It might also introduce some issues in the translation, but from what I can tell, as long as you keep within a relatively decent-sized subset of LLVM instructions, you should avoid such issues.


I see a great amount of merit in each option, so I do not care which method you choose. If you go with the V8/ScriptEngine method, I will be happy to have a two-megabyte JavaScript export extension. If you go with emscripten, I will be happy to have LLVM as an abstraction layer. Let me know what you're thinking, though.
Logged
"That is the single most cryptic piece of code I have ever seen." -Master PobbleWobble
"I disapprove of what you say, but I will defend to the death your right to say it." -Evelyn Beatrice Hall, Friends of Voltaire
Offline (Unknown gender) TGMG
Reply #1 Posted on: December 18, 2012, 12:40:04 PM

Developer
Joined: Jun 2008
Posts: 107

View Profile WWW Email
The initial implementation will be using Java's built in Rhino Javascript implementation just like the original EGMJS which used this to run your javascript gml parser. The reason is that it adds very little overhead since java is already needed for LGM and debugging is much easier when it is not called through JNI/JNA.
V8 is a piece of cake to compile for Mac and Linux but unfortunately as you said windows is a right pain but i'm hoping to work on an ENIGMA extension which will run javascript as a scripting language anyway so it will need to be dealt with.

I wouldn't personally have emscripten do the work, I really don't like the dependence on LLVM and getting everything setup, adds unnecessary headaches. I would rather keep emscripten as a developer tool so users of enigma won't need to run emscripten itself (unless c++ extensions are used). Instead the enigma engine can be compiled by the enigma developers and called by the javascript code which enigma exports. Emscripten is too slow to run on every compile and writing out javascript directly will allow a much faster run-debug cycle.
Logged
me
GMbed 2.0 :: Embed you gm games in websites.
Offline (Male) Josh @ Dreamland
Reply #2 Posted on: December 18, 2012, 12:51:41 PM

Prince of all Goldfish
Developer
Location: Pittsburgh, PA, USA
Joined: Feb 2008
Posts: 2958

View Profile Email
Sounds great. As I see it, this is what you'll have to do:

1) Create methods in C++ to populate a JDI context with function and variable definitions. You'll have, for instance, a define_global(string name), and a define_function(string name, something).  I can write these for you, if you need.

2) Create Java methods which call the C++ methods. Basically, just wrappers through JNA, like we do for everything else that goes on between ENIGMA and LateralGM.

3) Create JavaScript functions through Rhino which call the JNA wrapper functions. So the JavaScript function def_function() calls the Java function DefineFunction, which uses JNA to call the C++ method define_function(). Just for example.

4) Using Rhino and JavaScript reflection, call the JavaScript functions for each member. As I left the system, each function contained a variable representing its minimum and maximum number of parameters.

Depending on if you want to support overloading, they may need to contain more information than that. It's that information which ultimately determines the other parameters to define_function(). JDI supports storing any type of function C++ supports; it's up to you how many to simulate in the JavaScript engine. It may be that all define_function() needs is name, parameter names, and minimum/maximum parameter counts (for variadic functions, the maximum would be -1).
Logged
"That is the single most cryptic piece of code I have ever seen." -Master PobbleWobble
"I disapprove of what you say, but I will defend to the death your right to say it." -Evelyn Beatrice Hall, Friends of Voltaire
Pages: 1
  Print