Skip to content

Commit 732e884

Browse files
authored
Merge pull request killme2008#412 from killme2008/feature/interpreter
interpreter
2 parents efffdb5 + 55164ef commit 732e884

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+3142
-1173
lines changed

src/main/java/com/googlecode/aviator/AviatorEvaluator.java

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -79,16 +79,27 @@ public final class AviatorEvaluator {
7979
public static int BYTECODE_VER = getInstance().getBytecodeVersion();
8080

8181
/**
82-
* Create a aviator evaluator instance.
82+
* Create a aviator script engine instance with eval mode
8383
*
84-
* @return
84+
* @since 5.3
85+
* @return the script engine
86+
*/
87+
public static AviatorEvaluatorInstance newInstance(final EvalMode evalMode) {
88+
return new AviatorEvaluatorInstance(evalMode);
89+
}
90+
91+
/**
92+
* Create a aviator script engine instance.
93+
*
94+
* @return the script engine
8595
*/
8696
public static AviatorEvaluatorInstance newInstance() {
87-
return new AviatorEvaluatorInstance();
97+
return newInstance(Options.getDefaultEvalMode().evalMode);
8898
}
8999

90100
private static class StaticHolder {
91-
private static AviatorEvaluatorInstance INSTANCE = new AviatorEvaluatorInstance();
101+
private static AviatorEvaluatorInstance INSTANCE =
102+
new AviatorEvaluatorInstance(Options.getDefaultEvalMode().evalMode);
92103
}
93104

94105
/**

src/main/java/com/googlecode/aviator/AviatorEvaluatorInstance.java

Lines changed: 63 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,11 @@
5151
import com.googlecode.aviator.annotation.ImportScope;
5252
import com.googlecode.aviator.asm.Opcodes;
5353
import com.googlecode.aviator.code.CodeGenerator;
54+
import com.googlecode.aviator.code.EvalCodeGenerator;
5455
import com.googlecode.aviator.code.NoneCodeGenerator;
5556
import com.googlecode.aviator.code.OptimizeCodeGenerator;
5657
import com.googlecode.aviator.code.asm.ASMCodeGenerator;
58+
import com.googlecode.aviator.code.interpreter.InterpretCodeGenerator;
5759
import com.googlecode.aviator.exception.CompileExpressionErrorException;
5860
import com.googlecode.aviator.exception.ExpressionNotFoundException;
5961
import com.googlecode.aviator.exception.ExpressionSyntaxErrorException;
@@ -204,9 +206,11 @@ public final class AviatorEvaluatorInstance {
204206
/** internal libs in main resources */
205207
private static final String[] libs = new String[] {"aviator.av"};
206208

207-
/** cached compiled internal lib functions */
208-
private static volatile Map<String, AviatorFunction> internalLibFunctions;
209+
/** cached compiled internal ASM lib functions */
210+
private static volatile Map<String, AviatorFunction> internalASMLibFunctions;
209211

212+
/** cached compiled internal interpred lib functions */
213+
private static volatile Map<String, AviatorFunction> internalInterpretedLibFunctions;
210214

211215
/**
212216
* Adds a function loader
@@ -1020,32 +1024,46 @@ private void loadSystemFunctions() {
10201024
}
10211025

10221026
private void loadInternalLibs() {
1023-
if (internalLibFunctions == null) {
1024-
Map<String, AviatorFunction> funcs = new HashMap<>();
1025-
for (String lib : libs) {
1026-
try (final InputStream in = this.getClass().getResourceAsStream("/" + lib);
1027-
final BufferedInputStream bis = new BufferedInputStream(in);
1028-
final Reader reader = new InputStreamReader(bis)) {
1029-
Expression exp = this.compile(lib, Utils.readFully(reader), false);
1030-
Map<String, Object> exports = executeModule(exp, lib);
1031-
for (Map.Entry<String, Object> entry : exports.entrySet()) {
1032-
if (entry.getValue() instanceof AviatorFunction) {
1033-
final AviatorFunction fn = (AviatorFunction) entry.getValue();
1034-
addFunction(entry.getKey(), fn);
1035-
funcs.put(entry.getKey(), fn);
1036-
}
1037-
}
1038-
} catch (IOException e) {
1039-
throw new IllegalStateException("Fail to load internal lib: " + lib, e);
1027+
if (getEvalMode() == EvalMode.ASM) {
1028+
if (internalASMLibFunctions == null) {
1029+
internalASMLibFunctions = loadInternalFunctions(); // cache it
1030+
} else {
1031+
for (Map.Entry<String, AviatorFunction> entry : internalASMLibFunctions.entrySet()) {
1032+
addFunction(entry.getKey(), entry.getValue());
10401033
}
10411034
}
1042-
1043-
internalLibFunctions = funcs; // cache it
10441035
} else {
1045-
for (Map.Entry<String, AviatorFunction> entry : internalLibFunctions.entrySet()) {
1046-
addFunction(entry.getKey(), entry.getValue());
1036+
if (internalInterpretedLibFunctions == null) {
1037+
internalInterpretedLibFunctions = loadInternalFunctions(); // cache it
1038+
} else {
1039+
for (Map.Entry<String, AviatorFunction> entry : internalInterpretedLibFunctions
1040+
.entrySet()) {
1041+
addFunction(entry.getKey(), entry.getValue());
1042+
}
1043+
}
1044+
}
1045+
}
1046+
1047+
private Map<String, AviatorFunction> loadInternalFunctions() {
1048+
Map<String, AviatorFunction> funcs = new HashMap<>();
1049+
for (String lib : libs) {
1050+
try (final InputStream in = this.getClass().getResourceAsStream("/" + lib);
1051+
final BufferedInputStream bis = new BufferedInputStream(in);
1052+
final Reader reader = new InputStreamReader(bis)) {
1053+
Expression exp = this.compile(lib, Utils.readFully(reader), false);
1054+
Map<String, Object> exports = executeModule(exp, lib);
1055+
for (Map.Entry<String, Object> entry : exports.entrySet()) {
1056+
if (entry.getValue() instanceof AviatorFunction) {
1057+
final AviatorFunction fn = (AviatorFunction) entry.getValue();
1058+
addFunction(entry.getKey(), fn);
1059+
funcs.put(entry.getKey(), fn);
1060+
}
1061+
}
1062+
} catch (IOException e) {
1063+
throw new IllegalStateException("Fail to load internal lib: " + lib, e);
10471064
}
10481065
}
1066+
return funcs;
10491067
}
10501068

10511069
/**
@@ -1066,8 +1084,9 @@ private void loadInternalLibs() {
10661084
/**
10671085
* Create a aviator evaluator instance.
10681086
*/
1069-
AviatorEvaluatorInstance() {
1087+
AviatorEvaluatorInstance(final EvalMode evalMode) {
10701088
fillDefaultOpts();
1089+
setOption(Options.EVAL_MODE, evalMode);
10711090
loadFeatureFunctions();
10721091
loadLib();
10731092
loadModule();
@@ -1498,6 +1517,10 @@ private Expression innerCompile(final String expression, final String sourceFile
14981517
return exp;
14991518
}
15001519

1520+
private EvalMode getEvalMode() {
1521+
return getOptionValue(Options.EVAL_MODE).evalMode;
1522+
}
1523+
15011524
private int getOptimizeLevel() {
15021525
return getOptionValue(Options.OPTIMIZE_LEVEL).number;
15031526
}
@@ -1509,14 +1532,26 @@ public CodeGenerator newCodeGenerator(final String sourceFile, final boolean cac
15091532

15101533
}
15111534

1535+
public EvalCodeGenerator newEvalCodeGenerator(final AviatorClassLoader classLoader,
1536+
final String sourceFile) {
1537+
switch (getEvalMode()) {
1538+
case ASM:
1539+
return new ASMCodeGenerator(this, sourceFile, classLoader, this.traceOutputStream);
1540+
case INTERPRETER:
1541+
return new InterpretCodeGenerator(this, sourceFile, classLoader);
1542+
default:
1543+
throw new IllegalArgumentException("Unknown eval mode: " + getEvalMode());
1544+
1545+
}
1546+
}
1547+
15121548
public CodeGenerator newCodeGenerator(final AviatorClassLoader classLoader,
15131549
final String sourceFile) {
15141550
switch (getOptimizeLevel()) {
15151551
case AviatorEvaluator.COMPILE:
1516-
ASMCodeGenerator asmCodeGenerator =
1517-
new ASMCodeGenerator(this, sourceFile, classLoader, this.traceOutputStream);
1518-
asmCodeGenerator.start();
1519-
return asmCodeGenerator;
1552+
final EvalCodeGenerator codeGen = newEvalCodeGenerator(classLoader, sourceFile);
1553+
codeGen.start();
1554+
return codeGen;
15201555
case AviatorEvaluator.EVAL:
15211556
return new OptimizeCodeGenerator(this, sourceFile, classLoader, this.traceOutputStream);
15221557
default:

src/main/java/com/googlecode/aviator/BaseExpression.java

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,13 @@
1414
import java.util.concurrent.ExecutionException;
1515
import java.util.concurrent.FutureTask;
1616
import com.googlecode.aviator.AviatorEvaluatorInstance.StringSegments;
17+
import com.googlecode.aviator.exception.ExpressionNotFoundException;
1718
import com.googlecode.aviator.lexer.SymbolTable;
1819
import com.googlecode.aviator.lexer.token.Variable;
1920
import com.googlecode.aviator.parser.VariableMeta;
2021
import com.googlecode.aviator.runtime.FunctionArgument;
22+
import com.googlecode.aviator.runtime.LambdaFunctionBootstrap;
23+
import com.googlecode.aviator.runtime.function.LambdaFunction;
2124
import com.googlecode.aviator.utils.Constants;
2225
import com.googlecode.aviator.utils.Env;
2326
import com.googlecode.aviator.utils.Reflector;
@@ -45,6 +48,7 @@ public abstract class BaseExpression implements Expression {
4548
new ConcurrentHashMap<String, FutureTask<StringSegments>>();
4649

4750
protected String sourceFile;
51+
protected Map<String, LambdaFunctionBootstrap> lambdaBootstraps;
4852

4953

5054
@Override
@@ -95,7 +99,23 @@ private void populateNames() {
9599

96100
protected void afterPopulateFullNames(final Map<String, VariableMeta> fullNames,
97101
final Set<String> parentVars) {
98-
102+
if (this.lambdaBootstraps != null && !this.lambdaBootstraps.isEmpty()) {
103+
for (LambdaFunctionBootstrap bootstrap : this.lambdaBootstraps.values()) {
104+
for (VariableMeta meta : bootstrap.getClosureOverFullVarNames()) {
105+
VariableMeta existsMeta = fullNames.get(meta.getName());
106+
if (existsMeta == null) {
107+
if (!parentVars.contains(meta.getName())) {
108+
fullNames.put(meta.getName(), meta);
109+
}
110+
} else {
111+
// Appear first, update the meta
112+
if (existsMeta.getFirstIndex() > meta.getFirstIndex()) {
113+
fullNames.put(meta.getName(), meta);
114+
}
115+
}
116+
}
117+
}
118+
}
99119
}
100120

101121
private void populateFullNames() {
@@ -328,4 +348,20 @@ protected Env newEnv(final Map<String, Object> map) {
328348
return newEnv(map, false);
329349
}
330350

351+
public Map<String, LambdaFunctionBootstrap> getLambdaBootstraps() {
352+
return this.lambdaBootstraps;
353+
}
354+
355+
public void setLambdaBootstraps(final Map<String, LambdaFunctionBootstrap> lambdaBootstraps) {
356+
this.lambdaBootstraps = lambdaBootstraps;
357+
}
358+
359+
public LambdaFunction newLambda(final Env env, final String name) {
360+
LambdaFunctionBootstrap bootstrap = this.lambdaBootstraps.get(name);
361+
if (bootstrap == null) {
362+
throw new ExpressionNotFoundException("Lambda " + name + " not found");
363+
}
364+
return bootstrap.newInstance(env);
365+
}
366+
331367
}

src/main/java/com/googlecode/aviator/ClassExpression.java

Lines changed: 0 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,10 @@
1717

1818
import java.util.List;
1919
import java.util.Map;
20-
import java.util.Set;
21-
import com.googlecode.aviator.exception.ExpressionNotFoundException;
2220
import com.googlecode.aviator.exception.ExpressionRuntimeException;
2321
import com.googlecode.aviator.lexer.SymbolTable;
2422
import com.googlecode.aviator.parser.VariableMeta;
25-
import com.googlecode.aviator.runtime.LambdaFunctionBootstrap;
2623
import com.googlecode.aviator.runtime.RuntimeUtils;
27-
import com.googlecode.aviator.runtime.function.LambdaFunction;
2824
import com.googlecode.aviator.utils.Env;
2925
import com.googlecode.aviator.utils.Reflector;
3026

@@ -37,30 +33,11 @@
3733
*/
3834
public abstract class ClassExpression extends BaseExpression {
3935

40-
protected Map<String, LambdaFunctionBootstrap> lambdaBootstraps;
41-
42-
43-
public Map<String, LambdaFunctionBootstrap> getLambdaBootstraps() {
44-
return this.lambdaBootstraps;
45-
}
46-
47-
public void setLambdaBootstraps(final Map<String, LambdaFunctionBootstrap> lambdaBootstraps) {
48-
this.lambdaBootstraps = lambdaBootstraps;
49-
}
50-
5136
public ClassExpression(final AviatorEvaluatorInstance instance, final List<VariableMeta> vars,
5237
final SymbolTable symbolTable) {
5338
super(instance, vars, symbolTable);
5439
}
5540

56-
public LambdaFunction newLambda(final Env env, final String name) {
57-
LambdaFunctionBootstrap bootstrap = this.lambdaBootstraps.get(name);
58-
if (bootstrap == null) {
59-
throw new ExpressionNotFoundException("Lambda " + name + " not found");
60-
}
61-
return bootstrap.newInstance(env);
62-
}
63-
6441
@Override
6542
public Object executeDirectly(final Map<String, Object> env) {
6643
try {
@@ -76,28 +53,6 @@ public Object executeDirectly(final Map<String, Object> env) {
7653
}
7754
}
7855

79-
@Override
80-
protected void afterPopulateFullNames(final Map<String, VariableMeta> fullNames,
81-
final Set<String> parentVars) {
82-
if (this.lambdaBootstraps != null) {
83-
for (LambdaFunctionBootstrap bootstrap : this.lambdaBootstraps.values()) {
84-
for (VariableMeta meta : bootstrap.getClosureOverFullVarNames()) {
85-
VariableMeta existsMeta = fullNames.get(meta.getName());
86-
if (existsMeta == null) {
87-
if (!parentVars.contains(meta.getName())) {
88-
fullNames.put(meta.getName(), meta);
89-
}
90-
} else {
91-
// Appear first, update the meta
92-
if (existsMeta.getFirstIndex() > meta.getFirstIndex()) {
93-
fullNames.put(meta.getName(), meta);
94-
}
95-
}
96-
}
97-
}
98-
}
99-
}
100-
10156
public abstract Object execute0(Env env);
10257

10358

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package com.googlecode.aviator;
2+
3+
/**
4+
* Expression engine evaluate mode
5+
*
6+
* @author dennis(killme2008@gmail.com)
7+
* @since 5.3
8+
*/
9+
public enum EvalMode {
10+
/**
11+
* Generate JVM byecode by ASM and eval it by JVM.
12+
*/
13+
ASM,
14+
/**
15+
* Interpreter mode.
16+
*/
17+
INTERPRETER
18+
}

0 commit comments

Comments
 (0)