forked from luaj/luaj
-
Notifications
You must be signed in to change notification settings - Fork 0
/
ScriptEngineSample.java
202 lines (178 loc) · 8.97 KB
/
ScriptEngineSample.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
import java.io.CharArrayReader;
import java.io.CharArrayWriter;
import java.io.Reader;
import javax.script.Bindings;
import javax.script.Compilable;
import javax.script.CompiledScript;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineFactory;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import javax.script.SimpleBindings;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.lib.OneArgFunction;
/** Sample code that uses the JSE-223 pluggable scripting language interface
* to instantiate and use luaj.
*
* <p>In this case, Globals are only indirectly constructed as a side effect
* of using the scripting interface.
*
* <p>All features should be supported including compiled scripts.
*
* <p>Configuration is via system properties:
* <ul><li><b>"org.luaj.luajc"</b> - set to "true" to use the LuaJC lua-to-Java-bytecode compiling.
* Requires the bcel library to be on the class path.
* </li><li><b>"org.luaj.debug"</b> - set to "true" to load the debug library,
* which may provide better stack traces for closures.
* </li></ul>
*
* <p> These flag values can be set on the command line or via code.
*/
public class ScriptEngineSample {
public static void main(String [] args) {
// Set the property 'org.luaj.debug' before getting the engine to get
// the debug libraries, which will be slower, but may provide stack traces
// when luaJC is not used.
// This can also be set on the command line using -Dorg.luaj.debug=true
// System.setProperty("org.luaj.debug", "true");
// Set the property 'org.luaj.luajc' before getting the engine to enable
// the lua-to-java bytecode compiler, which requires the bcel library
// to be on the class path.
// This can also be set on the command line using -Dorg.luaj.luajc=true
// org.luaj.vm2.luajc.LuaJC.install();
ScriptEngineManager sem = new ScriptEngineManager();
ScriptEngine e = sem.getEngineByName("luaj");
ScriptEngineFactory f = e.getFactory();
System.out.println( "Engine name: " +f.getEngineName() );
System.out.println( "Engine Version: " +f.getEngineVersion() );
System.out.println( "LanguageName: " +f.getLanguageName() );
System.out.println( "Language Version: " +f.getLanguageVersion() );
String statement = f.getOutputStatement("\"hello, world\"");
System.out.println(statement);
try {
// Simple evaluations. Each tiny script is compiled then evaluated.
e.eval(statement);
e.put("x", 25);
e.eval("y = math.sqrt(x)");
System.out.println( "y="+e.get("y") );
e.put("x", 2);
e.eval("y = math.sqrt(x)");
System.out.println( "y="+e.get("y") );
e.put("f", new OneArgFunction() {
public LuaValue call(LuaValue arg) {
System.out.println("arg "+arg.tojstring());
return LuaValue.valueOf(123);
}
});
System.out.println("eval: "+e.eval("return f('abc')"));
// Example of compiled script tha can be reused once compiled.
CompiledScript cs = ((Compilable)e).compile("y = math.sqrt(x); return y");
Bindings b1 = e.createBindings();
Bindings b2 = e.createBindings();
b1.put("x", 3);
b2.put("x", 144);
System.out.println( "eval: "+cs.eval(b1) );
System.out.println( "eval: "+cs.eval(b2) );
System.out.println( "y="+b1.get("y") );
System.out.println( "y="+b2.get("y") );
// In Luaj 3.0, client bindings can just be SimpleBindings.
Bindings sb = new SimpleBindings();
sb.put("x", 2);
System.out.println( "eval: "+cs.eval(sb) );
// Example of how exceptions are generated.
try {
e.eval("\n\nbuggy lua code\n\n");
} catch ( ScriptException se ) {
System.out.println("script exception thrown for buggy script, message: '"+se.getMessage()+"'");
}
testEngineBindings(e);
testClientBindings(e);
testUserClasses(e);
// Test redirection of input, output, and standard error.
Reader input = new CharArrayReader("abcdefg\nhijk".toCharArray());
CharArrayWriter output = new CharArrayWriter();
CharArrayWriter errors = new CharArrayWriter();
String script =
"print(\"string written using 'print'\")\n" +
"io.write(\"string written using 'io.write()'\\n\")\n" +
"io.stdout:write(\"string written using 'io.stdout:write()'\\n\")\n" +
"io.stderr:write(\"string written using 'io.stderr:write(), hit return to continue...'\\n\")\n" +
"io.write([[string read using 'io.stdin:read(\"*l\")':]]..io.stdin:read(\"*l\")..\"\\n\")\n";
System.out.println("Evaluating script with redirection set.");
e.getContext().setReader(input);
e.getContext().setWriter(output);
e.getContext().setErrorWriter(errors);
e.eval(script);
System.out.println("output::>"+output+"<::output");
System.out.println("errors::>"+errors+"<::errors");
System.out.println("Evaluating script with redirection reset.");
output.reset();
errors.reset();
e.getContext().setReader(null);
e.getContext().setWriter(null);
e.getContext().setErrorWriter(null);
e.eval(script); // Will wait for a line from the user at this step!
System.out.println("output::>"+output+"<::output");
System.out.println("errors::>"+errors+"<::errors");
} catch (ScriptException ex) {
ex.printStackTrace();
}
}
public static class SomeUserClass {
public String toString() {
return "user-class-instance-"+this.hashCode();
}
}
public static void testEngineBindings(ScriptEngine e) throws ScriptException {
testBindings(e, e.createBindings());
}
public static void testClientBindings(ScriptEngine e) throws ScriptException {
testBindings(e, new SimpleBindings());
}
public static void testBindings(ScriptEngine e, Bindings b) throws ScriptException {
CompiledScript cs = ((Compilable)e).compile(
"print( 'somejavaint', type(somejavaint), somejavaint )\n" +
"print( 'somejavadouble', type(somejavadouble), somejavadouble )\n" +
"print( 'somejavastring', type(somejavastring), somejavastring )\n" +
"print( 'somejavaobject', type(somejavaobject), somejavaobject )\n" +
"print( 'somejavaarray', type(somejavaarray), somejavaarray, somejavaarray[1] )\n" +
"someluaint = 444\n" +
"someluadouble = 555.666\n" +
"someluastring = 'def'\n" +
"someluauserdata = somejavaobject\n" +
"someluatable = { 999, 111 }\n" +
"someluafunction = function(x) print( 'hello, world', x ) return 678 end\n" +
"" );
b.put("somejavaint", 111);
b.put("somejavadouble", 222.333);
b.put("somejavastring", "abc");
b.put("somejavaobject", new SomeUserClass());
b.put("somejavaarray", new int[] { 777, 888 } );
System.out.println( "eval: "+cs.eval(b) );
Object someluaint = b.get("someluaint");
Object someluadouble = b.get("someluaint");
Object someluastring = b.get("someluastring");
Object someluauserdata = b.get("someluauserdata");
Object someluatable = b.get("someluatable");
Object someluafunction = b.get("someluafunction");
System.out.println( "someluaint: "+someluaint.getClass()+" "+someluaint );
System.out.println( "someluadouble: "+someluadouble.getClass()+" "+someluadouble );
System.out.println( "someluastring: "+someluastring.getClass()+" "+someluastring );
System.out.println( "someluauserdata: "+someluauserdata.getClass()+" "+someluauserdata );
System.out.println( "someluatable: "+someluatable.getClass()+" "+someluatable );
System.out.println( "someluafunction: "+someluafunction.getClass()+" "+someluafunction );
System.out.println( "someluafunction(345): "+((LuaValue) someluafunction).call(LuaValue.valueOf(345)) );
}
public static void testUserClasses(ScriptEngine e) throws ScriptException {
CompiledScript cs = ((Compilable)e).compile(
"test = test or luajava.newInstance(\"java.lang.String\", \"test\")\n" +
"print( 'test', type(test), test, tostring(test) )\n" +
"return tostring(test)");
Bindings b = e.createBindings();
Object resultstring = cs.eval(b);
b.put("test", new SomeUserClass());
Object resultuserclass = cs.eval(b);
System.out.println( "eval(string): "+resultstring.getClass()+" "+resultstring );
System.out.println( "eval(userclass): "+resultuserclass.getClass()+" "+resultuserclass );
}
}