Skip to content

Commit

Permalink
fix: elsif parser #554, #564 and serialize with constants
Browse files Browse the repository at this point in the history
  • Loading branch information
killme2008 committed Oct 3, 2023
1 parent 976911d commit d097db8
Show file tree
Hide file tree
Showing 21 changed files with 287 additions and 71 deletions.
51 changes: 2 additions & 49 deletions src/main/java/com/googlecode/aviator/AviatorEvaluatorInstance.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
import java.io.OutputStream;
import java.io.Reader;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.net.URL;
import java.nio.charset.Charset;
import java.security.AccessController;
Expand Down Expand Up @@ -493,7 +492,7 @@ public void removeModule(final String ns) {

private Env loadModule(final Class<?> moduleClazz)
throws IllegalAccessException, NoSuchMethodException {
Map<String, List<Method>> methodMap = findMethodsFromClass(moduleClazz, true);
Map<String, List<Method>> methodMap = Reflector.findMethodsFromClass(moduleClazz, true);

if (methodMap == null || methodMap.isEmpty()) {
throw new IllegalArgumentException("Empty module");
Expand Down Expand Up @@ -564,7 +563,7 @@ public List<String> addInstanceFunctions(final String namespace, final Class<?>

private List<String> addMethodFunctions(final String namespace, final boolean isStatic,
final Class<?> clazz) throws IllegalAccessException, NoSuchMethodException {
Map<String, List<Method>> methodMap = findMethodsFromClass(clazz, isStatic);
Map<String, List<Method>> methodMap = Reflector.findMethodsFromClass(clazz, isStatic);
List<String> added = new ArrayList<>();

for (Map.Entry<String, List<Method>> entry : methodMap.entrySet()) {
Expand Down Expand Up @@ -643,52 +642,6 @@ public List<String> importFunctions(final Class<?> clazz)
return result;
}

private Map<String, List<Method>> findMethodsFromClass(final Class<?> clazz,
final boolean isStatic) {
Map<String, List<Method>> methodMap = new HashMap<>();

for (Method method : clazz.getMethods()) {
int modifiers = method.getModifiers();
if (Modifier.isPublic(modifiers)) {
if (isStatic) {
if (!Modifier.isStatic(modifiers)) {
continue;
}
} else {
if (Modifier.isStatic(modifiers)) {
continue;
}
}

if (method.getAnnotation(Ignore.class) != null) {
continue;
}

String methodName = method.getName();
Function func = method.getAnnotation(Function.class);
if (func != null) {
String rename = func.rename();
if (!rename.isEmpty()) {
if (!ExpressionParser.isJavaIdentifier(rename)) {
throw new IllegalArgumentException("Invalid rename `" + rename + "` for method "
+ method.getName() + " in class " + clazz);
}
methodName = func.rename();
}
}

List<Method> methods = methodMap.get(methodName);
if (methods == null) {
methods = new ArrayList<>(3);
methodMap.put(methodName, methods);
}
methods.add(method);
}
}

return methodMap;
}

/**
* Remove a function loader
*
Expand Down
3 changes: 2 additions & 1 deletion src/main/java/com/googlecode/aviator/BaseExpression.java
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public abstract class BaseExpression implements Expression {
private Map<Integer, List<FunctionArgument>> funcsArgs = Collections.emptyMap();
protected SymbolTable symbolTable;
// cached compiled string segments for string interpolation.
private transient final ConcurrentHashMap<String, FutureTask<StringSegments>> stringSegs =
private transient ConcurrentHashMap<String, FutureTask<StringSegments>> stringSegs =
new ConcurrentHashMap<String, FutureTask<StringSegments>>();

protected String sourceFile;
Expand Down Expand Up @@ -383,6 +383,7 @@ public void customReadObject(ObjectInputStream input) throws ClassNotFoundExcept
this.symbolTable = (SymbolTable) input.readObject();
this.sourceFile = (String) input.readObject();
this.lambdaBootstraps = (Map<String, LambdaFunctionBootstrap>) input.readObject();
this.stringSegs = new ConcurrentHashMap<String, FutureTask<StringSegments>>();
}

public void customWriteObject(ObjectOutputStream output) throws IOException {
Expand Down
3 changes: 2 additions & 1 deletion src/main/java/com/googlecode/aviator/FunctionMissing.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
*
*/

import java.io.Serializable;
import java.util.Map;
import com.googlecode.aviator.runtime.type.AviatorObject;

Expand All @@ -22,7 +23,7 @@
* @since 4.2.5
*
*/
public interface FunctionMissing {
public interface FunctionMissing extends Serializable {
/**
* Called when function not found, return the invocation result.
*
Expand Down
10 changes: 10 additions & 0 deletions src/main/java/com/googlecode/aviator/lexer/SymbolTable.java
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,16 @@ public boolean isReserved(final String name) {
return isReservedKeyword(name) || this.table.containsKey(name);
}

/**
* Try to reserve key word, return the reserved variable if success, otherwise return itself.
*
* @param var
* @return
*/
public static Variable tryReserveKeyword(final Variable var) {
Variable reserve = RESERVED.get(var.getLexeme());
return reserve != null ? reserve : var;
}

/**
* Get variable by name
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1965,7 +1965,7 @@ private boolean ifStatement(final boolean isWhile, final boolean isElsif) {
this.scope.leaveBrace();
move(true);

elseBodyHasReturn = elseStatement(isWhile, ifBodyHasReturn);
elseBodyHasReturn = elseStatement(isWhile, isElsif, ifBodyHasReturn);
getCodeGeneratorWithTimes().onMethodParameter(this.lookhead);
}

Expand Down Expand Up @@ -2008,7 +2008,8 @@ private String getLoopKeyword(final boolean isWhile) {
return isWhile ? "while" : "if";
}

private boolean elseStatement(final boolean isWhile, final boolean ifBodyHasReturn) {
private boolean elseStatement(final boolean isWhile, boolean isElsif,
final boolean ifBodyHasReturn) {
if (isWhile) {
// Call __reducer_break(nil)
final CodeGenerator cg = getCodeGeneratorWithTimes();
Expand Down Expand Up @@ -2046,7 +2047,7 @@ private boolean elseStatement(final boolean isWhile, final boolean ifBodyHasRetu
} else if (hasElsif) {
hasReturn = ifStatement(false, true);
getCodeGenerator().onTernaryRight(this.lookhead);
} else if (ifBodyHasReturn) {
} else if (ifBodyHasReturn && !isElsif) {
hasReturn = elseBody(true);
} else {
return withoutElse();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
*/
public class JavaMethodReflectionFunctionMissing implements FunctionMissing {

private static final long serialVersionUID = -7829608231403725185L;

private JavaMethodReflectionFunctionMissing() {

}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
package com.googlecode.aviator.runtime.function;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import com.googlecode.aviator.code.interpreter.IR;
import com.googlecode.aviator.lexer.token.Token;
import com.googlecode.aviator.parser.VariableMeta;
import com.googlecode.aviator.runtime.type.AviatorJavaType;
import com.googlecode.aviator.runtime.type.AviatorObject;
import com.googlecode.aviator.utils.Reflector;

Expand All @@ -20,11 +28,11 @@ public class ClassMethodFunction extends AbstractVariadicFunction {
private static final long serialVersionUID = 5946505010078966461L;
private MethodHandle handle; // Only for one-arity function.
private Class<?>[] pTypes;
private final String name;
private final String methodName;
private String name;
private String methodName;
private List<Method> methods; // For reflection.
private final Class<?> clazz;
private final boolean isStatic;
private Class<?> clazz;
private boolean isStatic;

public ClassMethodFunction(final Class<?> clazz, final boolean isStatic, final String name,
final String methodName, final List<Method> methods)
Expand All @@ -34,6 +42,11 @@ public ClassMethodFunction(final Class<?> clazz, final boolean isStatic, final S
this.isStatic = isStatic;
this.methodName = methodName;

init(isStatic, methodName, methods);
}

private void init(final boolean isStatic, final String methodName, final List<Method> methods)
throws IllegalAccessException, NoSuchMethodException {
if (methods.size() == 1) {
// fast path by method handle.
this.handle = MethodHandles.lookup().unreflect(methods.get(0)).asFixedArity();
Expand All @@ -53,6 +66,32 @@ public ClassMethodFunction(final Class<?> clazz, final boolean isStatic, final S
}
}

private void readObject(ObjectInputStream input) throws ClassNotFoundException, IOException {
this.name = (String) input.readObject();
this.clazz = (Class<?>) input.readObject();
this.isStatic = input.readBoolean();
this.methodName = (String) input.readObject();

Map<String, List<Method>> allMethods = Reflector.findMethodsFromClass(clazz, isStatic);

List<Method> methods = allMethods.get(this.methodName);
if (methods == null) {
methods = Collections.emptyList();
}

try {
this.init(this.isStatic, this.methodName, methods);
} catch (Throwable t) {
throw Reflector.sneakyThrow(t);
}
}

private void writeObject(ObjectOutputStream output) throws IOException {
output.writeObject(this.name);
output.writeObject(this.clazz);
output.writeBoolean(this.isStatic);
output.writeObject(this.methodName);
}

@Override
public String getName() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ private AviatorObject reduce(final Map<String, Object> env, final AviatorObject
long c = 0;

if (coll != Range.LOOP) {

long arities = (long) arg2.meta(Constants.ARITIES_META);
long index = 0;
boolean unboxEntry =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.googlecode.aviator.runtime.type.AviatorObject;
import com.googlecode.aviator.runtime.type.AviatorRuntimeJavaType;
import com.googlecode.aviator.runtime.type.AviatorType;
import com.googlecode.aviator.utils.Env;

/**
* ReducerResult in looping.
Expand Down Expand Up @@ -70,7 +71,12 @@ public Object getValue(final Map<String, Object> env) {

@Override
public String toString() {
return this.obj.toString();
Object val = getValue(Env.EMPTY_ENV);
if (val != this) {
return "<Reducer, " + this.state.name() + ", " + val + ">";
} else {
return "<Reducer, " + this.state.name() + ", this>";
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ public final boolean booleanValue(final Map<String, Object> env) {
return this.value.booleanValue();
}

public boolean getBooleanValue() {
return this.value;
}

@Override
public AviatorObject add(final AviatorObject other, final Map<String, Object> env) {
Expand Down
9 changes: 9 additions & 0 deletions src/main/java/com/googlecode/aviator/runtime/type/Range.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,27 @@ public final class Range extends AviatorObject implements Sequence<Number> {
private static final AviatorLong ZERO = AviatorLong.valueOf(0L);
public static final Range LOOP = new Range(ZERO, ZERO, ZERO);

static {
LOOP.isLoop = true;
}

private final AviatorNumber step;
private final AviatorNumber start;
private final AviatorNumber end;
final boolean forward;
private boolean isLoop;

public boolean isLoop() {
return this.isLoop;
}

public Range(final AviatorNumber start, final AviatorNumber end, final AviatorNumber step) {
super();
this.start = start;
this.end = end;
this.step = step;
this.forward = Range.this.step.compare(ZERO, Env.EMPTY_ENV) >= 0;
this.isLoop = false;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,13 @@
import com.googlecode.aviator.ClassExpression;
import com.googlecode.aviator.Expression;
import com.googlecode.aviator.code.asm.ClassDefiner;
import com.googlecode.aviator.lexer.SymbolTable;
import com.googlecode.aviator.lexer.token.Variable;
import com.googlecode.aviator.parser.AviatorClassLoader;
import com.googlecode.aviator.runtime.type.AviatorBigInt;
import com.googlecode.aviator.runtime.type.AviatorBoolean;
import com.googlecode.aviator.runtime.type.AviatorNil;
import com.googlecode.aviator.runtime.type.Range;
import com.googlecode.aviator.utils.Reflector;

/**
Expand Down Expand Up @@ -50,6 +56,30 @@ protected Object resolveObject(Object obj) throws IOException {
.setClassBytes(this.classBytesCache.get(object.getClass().getName()));
}
}

// Processing some internal constants.
if (object instanceof AviatorBoolean) {
AviatorBoolean bool = (AviatorBoolean) object;
if (bool.getBooleanValue()) {
object = AviatorBoolean.TRUE;
} else {
object = AviatorBoolean.FALSE;
}
}
if (object instanceof AviatorNil) {
object = AviatorNil.NIL;
}

if (object instanceof Range) {
if (((Range) object).isLoop()) {
object = Range.LOOP;
}
}

if (object instanceof Variable) {
object = SymbolTable.tryReserveKeyword((Variable) object);
}

return object;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import java.util.HashMap;
import java.util.Map;
import com.googlecode.aviator.ClassExpression;
import com.googlecode.aviator.runtime.type.Range;

/**
* A special ObjectOutputStream that will write the generated script class byte array.
Expand All @@ -30,6 +31,7 @@ protected Object replaceObject(Object obj) throws IOException {
if (obj instanceof ClassExpression) {
this.classBytesCache.put(obj.getClass().getName(), ((ClassExpression) obj).getClassBytes());
}

return super.replaceObject(obj);
}

Expand Down
Loading

0 comments on commit d097db8

Please sign in to comment.