Most of the discussions on scripting languages tend to be focused on the syntax, or sometimes the performance comparison. However, it is also important to know how scripting engines are integrated into applications.
Scripting engine is said to be embeddable if it provides an explicitly documented API, so that it can be integrated into Java applications. And such API is called an embedding API of scripting language.
This document investigates embedding APIs of selected scripting engines, focusing on how the following common tasks are implemented.
| Jacl | Interp interp = new Interp();
Object result = interp.eval("1+2");
|
| Beanshell | Interpreter interp = new Interpreter();
Object result = interp.exec("1+2");
|
| Jython | PythonInterpreter interp = new PythonInterpreter();
PyObject result = interp.eval("1+2");
|
| Rhino | Context cx = Context.enter();
try {
Scriptable scope = cx.initStandardObjects();
Object result = cx.evaluateString(scope, "1+2", "
|
| Groovy | GroovyShell gs = new GroovyShell();
Object result = gs.evaluate("1+2");
|
| Pnuts |
Context context = new Context();
Object result = Pnuts.eval("1+2", contenxt);
|
| Jacl |
Not available |
| Beanshell | Interpreter interp = new Interpreter(); Object result = interp.eval(reader); |
| Jython | PythonInterpreter interp = new PythonInterpreter(); interp.execfile(inputStream); |
| Rhino | Context cx = Context.enter();
try {
Scriptable scope = cx.initStandardObjects();
Object result = cx.evaluateReader(scope, reader, "
|
| Groovy |
GroovyShell gs = new GroovyShell(); Object result = gs.evaluate(in); |
| Pnuts | Context context = new Context(); Object result = Pnuts.load(reader, contenxt); |
| Jacl |
Interp interp = new Interp();
try {
Object result = interp.eval("1+2");
} catch (TclException e){
int code = e.getCompletionCode();
}
|
| Beanshell |
Interpreter interp = new Interpreter();
try {
Object result = interp.exec(...);
} catch (EvalError e){
String text = e.getErrorText();
int line = e.getErrorLineNumber();
String file = e.getErrorSourceFile();
String trace = e.getScriptStackTrace();
String msg = e.getMessage();
}
|
| Jython |
PythonInterpreter interp = new PythonInterpreter();
try {
interp.execfile(file);
} catch (PyException e){
PyObject type = e.type;
PyObject value = e.value;
PyTraceback traceback = e.traceback;
}
|
| Rhino |
Context cx = Context.enter();
try {
Scriptable scope = cx.initStandardObjects();
Object result = cx.evaluateReader(scope, reader, "
|
| Groovy |
try {
GroovyShell gs = new GroovyShell();
Object result = gs.evaluate("1+2");
} catch (GroovyRuntimeException e0){
String location = e0.getLocationText();
} catch (SyntaxException e1){
} catch (ClassNotFoundException e2){
} catch (IOException e3){
}
|
| Pnuts |
try {
Context context = new Context();
Pnuts.eval("...", context);
} catch (PnutsException e){
Throwable t = e.getThrowable();
}
|
| Jacl |
Interp interp = new Interp();
interp.setVar("foo", "stringValue", TCL.GLOBAL_ONLY);
interp.getVar("foo", TCL.GLOBAL_ONLY);
|
| Beanshell |
Interpreter interp = new Interpreter();
interp.set("a", new Integer(1));
Object result = interp.get("a");
|
| Jython | PythonInterpreter interp = new PythonInterpreter();
interp.set("a", new Integer(1));
PyObject result = interp.get("a");
|
| Rhino | Context cx = Context.enter();
try {
Scriptable scope = cx.initStandardObjects();
scope.put("symbol", scope, new Integer(1));
Object result = scope.get("symbol", scope);
} finally {
cx.exit();
}
|
| Groovy |
GroovyShell gs = new GroovyShell();
Binding b = gs.getContext();
b.setVariable("a", new Integer(1));
Object result = b.getVariable("a");
|
| Pnuts |
Package pkg = context.getCurrentPackage(); String symbol = "symbol".intern(); pkg.set(symbol, new Integer(1)); Object value = pkg.get(symbol); |
| Jacl |
Command cmd = interp.getCommand(cmdName); TclObject[] args = ...; cmd.cmdProc(interp, args); |
| Beanshell |
Interpreter interp = new Interpreter();
NameSpace namespace = interp.getNameSpace();
BshMethod cmd = (BshMethod)namespace.getCommand("cmdname", new Class[]{...}, interp);
Object result = cmd.invoke(new Object[]{...}, interp);
|
| Jython |
PythonInterpreter interp = new PythonInterpreter();
interp.exec("def foo():\r\n 0;");
PyFunction f = (PyFunction)interp.get("foo");
PyObject result = f.__call__();
|
| Rhino | Context cx = Context.enter();
try {
Scriptable scope = cx.initStandardObjects();
Function func = ...;
Object result = func.call(cx, scope, func, new Object[]{args, ...});
} finally {
cx.exit();
}
|
| Groovy |
GroovyShell gs = new GroovyShell();
Closure closure = (Closure)gs.evaluate("Object.hashCode");
closure.call();
|
| Pnuts |
Context context = new Context();
Object result = func.call(new Object[]{...}, context);
|
| Jacl |
Not available |
| Beanshell |
Parser parser = new Parser(input);
while(!(eof = parser.Line())) {
parser.popNode();
}
// This usage is just for syntax checking
// No public interface to execute the AST
|
| Jython | Not documented. |
| Rhino | Rhino always compiles scripts |
| Groovy |
Groovy always compiles scripts |
| Pnuts |
Context context = new Context();
try {
Pnuts pn = Pnuts.parse(input, "", context);
pn.run(context);
} catch (ParseException e){
int line = e.getErrorLine();
int column = e.getErrorColumn();
String token = e.currentToken.image;
}
|
| Jacl |
Compiler is not available. |
| Beanshell |
Not documented. |
| Jython | Not documented. |
| Rhino | Context cx = Context.enter();
try {
Scriptable scope = cx.initStandardObjects();
Script compiled = scope.compileReader(reader, "", 1, null);
// Object result = compiled.exec(cx, scope);
} finally {
cx.exit();
}
|
| Groovy |
GroovyShell gs = new GroovyShell(); Script script = gc.parse(input); // Object result = script.run(); |
| Pnuts |
Context context = new Context();
Compiler compiler = new Compiler();
Pnuts pn = Pnuts.parse(input);
try {
pn = compiler.compile(pn, context);
} catch (ClassFormatError e){
// exceeds JVM limitation
}
//Object result = pn.run(context);
|