Expression parser improvements

- Fixed calling nullary functions.
- Improved error reporting for missing functions
- Added random() and randint(max)
- Improved Sequence.optimize() to eliminate statements with no effect
- Adjusted a comment
This commit is contained in:
TomyLobo 2011-11-24 11:02:02 +01:00
parent adf326e2bf
commit 9456c9e58f
4 changed files with 26 additions and 2 deletions

View File

@ -351,6 +351,7 @@ public class Parser {
try { try {
if (peek().id() == ')') { if (peek().id() == ')') {
++position;
return Functions.getFunction(identifierToken.getPosition(), identifierToken.value); return Functions.getFunction(identifierToken.getPosition(), identifierToken.value);
} }
@ -376,7 +377,7 @@ public class Parser {
return Functions.getFunction(identifierToken.getPosition(), identifierToken.value, args.toArray(new RValue[args.size()])); return Functions.getFunction(identifierToken.getPosition(), identifierToken.value, args.toArray(new RValue[args.size()]));
} catch (NoSuchMethodException e) { } catch (NoSuchMethodException e) {
throw new ParserException(identifierToken.getPosition(), "Function not found", e); throw new ParserException(identifierToken.getPosition(), "Function '"+identifierToken.value+"' not found", e);
} }
} }

View File

@ -31,7 +31,8 @@ import java.lang.reflect.Method;
*/ */
public class Function extends Node { public class Function extends Node {
/** /**
* Add this annotation on functions that don't always return the same value for the same inputs. * Add this annotation on functions that don't always return the same value
* for the same inputs and on functions with side-effects.
*/ */
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
public @interface Dynamic { } public @interface Dynamic { }

View File

@ -24,6 +24,7 @@ import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Random;
import com.sk89q.worldedit.expression.runtime.Function.Dynamic; import com.sk89q.worldedit.expression.runtime.Function.Dynamic;
@ -281,4 +282,17 @@ public final class Functions {
final int intIndex = (int) index.getValue(); final int intIndex = (int) index.getValue();
return getSubBuffer(intIndex & ~1023)[intIndex & 1023] = value; return getSubBuffer(intIndex & ~1023)[intIndex & 1023] = value;
} }
private static final Random random = new Random();
@Dynamic
public static final double random() {
return random.nextDouble();
}
@Dynamic
public static final double randint(RValue max) throws EvaluationException {
return random.nextInt((int) Math.floor(max.getValue()));
}
} }

View File

@ -69,17 +69,25 @@ public class Sequence extends Node {
public Node optimize() throws EvaluationException { public Node optimize() throws EvaluationException {
List<RValue> newSequence = new ArrayList<RValue>(); List<RValue> newSequence = new ArrayList<RValue>();
RValue droppedLast = null;
for (RValue invokable : sequence) { for (RValue invokable : sequence) {
droppedLast = null;
invokable = invokable.optimize(); invokable = invokable.optimize();
if (invokable instanceof Sequence) { if (invokable instanceof Sequence) {
for (RValue subInvokable : ((Sequence) invokable).sequence) { for (RValue subInvokable : ((Sequence) invokable).sequence) {
newSequence.add(subInvokable); newSequence.add(subInvokable);
} }
} else if (invokable instanceof Constant) {
droppedLast = invokable;
} else { } else {
newSequence.add(invokable); newSequence.add(invokable);
} }
} }
if (droppedLast != null) {
newSequence.add(droppedLast);
}
return new Sequence(getPosition(), newSequence.toArray(new RValue[newSequence.size()])); return new Sequence(getPosition(), newSequence.toArray(new RValue[newSequence.size()]));
} }
} }