script compile time optimizations.
This commit is contained in:
1 parent
06c9aea326
commit
8d97ab26a9
27 files changed
+1071
-193
No files matched your search
@@ -5,6 +5,7 @@ import carpet.script.Expression;
|
||||
import carpet.script.LazyValue;
|
||||
import carpet.script.exception.InternalExpressionException;
|
||||
import carpet.script.value.AbstractListValue;
|
||||
import carpet.script.value.BooleanValue;
|
||||
import carpet.script.value.ContainerValueInterface;
|
||||
import carpet.script.value.FunctionAnnotationValue;
|
||||
import carpet.script.value.FunctionUnpackedArgumentsValue;
|
||||
@@ -14,6 +15,7 @@ import carpet.script.value.MapValue;
|
||||
import carpet.script.value.NumericValue;
|
||||
import carpet.script.value.Value;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
@@ -38,47 +40,203 @@ public class Operators {
|
||||
public static void apply(Expression expression)
|
||||
{
|
||||
expression.addBinaryOperator("+", precedence.get("addition+-"), true, Value::add);
|
||||
expression.addFunction("sum", lv -> {
|
||||
int size = lv.size();
|
||||
if (size == 0) return Value.NULL;
|
||||
Value accumulator = lv.get(0);
|
||||
for (Value v: lv.subList(1, size)) accumulator = accumulator.add(v);
|
||||
return accumulator;
|
||||
});
|
||||
expression.addFunctionalEquivalence("+", "sum");
|
||||
|
||||
expression.addBinaryOperator("-", precedence.get("addition+-"), true, Value::subtract);
|
||||
expression.addFunction("difference", lv -> {
|
||||
int size = lv.size();
|
||||
if (size == 0) return Value.NULL;
|
||||
Value accumulator = lv.get(0);
|
||||
for (Value v: lv.subList(1, size)) accumulator = accumulator.subtract(v);
|
||||
return accumulator;
|
||||
});
|
||||
expression.addFunctionalEquivalence("-", "difference");
|
||||
|
||||
expression.addBinaryOperator("*", precedence.get("multiplication*/%"), true, Value::multiply);
|
||||
expression.addFunction("product", lv -> {
|
||||
int size = lv.size();
|
||||
if (size == 0) return Value.NULL;
|
||||
Value accumulator = lv.get(0);
|
||||
for (Value v: lv.subList(1, size)) accumulator = accumulator.multiply(v);
|
||||
return accumulator;
|
||||
});
|
||||
expression.addFunctionalEquivalence("*", "product");
|
||||
|
||||
expression.addBinaryOperator("/", precedence.get("multiplication*/%"), true, Value::divide);
|
||||
expression.addFunction("quotient", lv -> {
|
||||
int size = lv.size();
|
||||
if (size == 0) return Value.NULL;
|
||||
Value accumulator = lv.get(0);
|
||||
for (Value v: lv.subList(1, size)) accumulator = accumulator.multiply(v);
|
||||
return accumulator;
|
||||
});
|
||||
expression.addFunctionalEquivalence("/", "quotient");
|
||||
|
||||
expression.addBinaryOperator("%", precedence.get("multiplication*/%"), true, (v1, v2) ->
|
||||
new NumericValue(NumericValue.asNumber(v1).getDouble() % NumericValue.asNumber(v2).getDouble()));
|
||||
expression.addBinaryOperator("^", precedence.get("exponent^"), false, (v1, v2) ->
|
||||
new NumericValue(java.lang.Math.pow(NumericValue.asNumber(v1).getDouble(), NumericValue.asNumber(v2).getDouble())));
|
||||
|
||||
// lazy cause RHS is only conditional
|
||||
expression.addLazyBinaryOperator("&&", precedence.get("and&&"), false, (c, t, lv1, lv2) ->
|
||||
{
|
||||
expression.addLazyBinaryOperator("&&", precedence.get("and&&"), false, true, t -> Context.Type.BOOLEAN, (c, t, lv1, lv2) ->
|
||||
{ // todo check how is optimizations going
|
||||
Value v1 = lv1.evalValue(c, Context.BOOLEAN);
|
||||
if (!v1.getBoolean()) return (cc, tt) -> v1;
|
||||
return lv2;
|
||||
});
|
||||
|
||||
expression.addPureLazyFunction("and", -1, t -> Context.Type.BOOLEAN, (c, t, lv) -> {
|
||||
int last = lv.size()-1;
|
||||
if (last == -1) return LazyValue.TRUE;
|
||||
for (LazyValue l: lv.subList(0, last))
|
||||
{
|
||||
Value val = l.evalValue(c, Context.Type.BOOLEAN);
|
||||
if (val instanceof FunctionUnpackedArgumentsValue)
|
||||
{
|
||||
for (Value it : (FunctionUnpackedArgumentsValue) val)
|
||||
if (!it.getBoolean()) return (cc, tt) -> it;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!val.getBoolean()) return (cc, tt) -> val;
|
||||
}
|
||||
}
|
||||
return lv.get(last);
|
||||
});
|
||||
expression.addFunctionalEquivalence("&&", "and");
|
||||
|
||||
// lazy cause RHS is only conditional
|
||||
expression.addLazyBinaryOperator("||", precedence.get("or||"), false, (c, t, lv1, lv2) ->
|
||||
expression.addLazyBinaryOperator("||", precedence.get("or||"), false, true, t -> Context.Type.BOOLEAN, (c, t, lv1, lv2) ->
|
||||
{
|
||||
Value v1 = lv1.evalValue(c, Context.BOOLEAN);
|
||||
if (v1.getBoolean()) return (cc, tt) -> v1;
|
||||
return lv2;
|
||||
});
|
||||
|
||||
expression.addPureLazyFunction("or", -1, t -> Context.Type.BOOLEAN, (c, t, lv) -> {
|
||||
int last = lv.size()-1;
|
||||
if (last == -1) return LazyValue.FALSE;
|
||||
for (LazyValue l: lv.subList(0, last))
|
||||
{
|
||||
Value val = l.evalValue(c, Context.Type.BOOLEAN);
|
||||
if (val instanceof FunctionUnpackedArgumentsValue)
|
||||
{
|
||||
for (Value it : (FunctionUnpackedArgumentsValue) val)
|
||||
if (it.getBoolean()) return (cc, tt) -> it;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (val.getBoolean()) return (cc, tt) -> val;
|
||||
}
|
||||
}
|
||||
return lv.get(last);
|
||||
});
|
||||
expression.addFunctionalEquivalence("||", "or");
|
||||
|
||||
expression.addBinaryOperator("~", precedence.get("attribute~:"), true, Value::in);
|
||||
|
||||
expression.addBinaryOperator(">", precedence.get("compare>=><=<"), false, (v1, v2) ->
|
||||
v1.compareTo(v2) > 0 ? Value.TRUE : Value.FALSE);
|
||||
BooleanValue.of(v1.compareTo(v2) > 0));
|
||||
expression.addFunction("decreasing", lv -> {
|
||||
int size = lv.size();
|
||||
if (size < 2) return Value.TRUE;
|
||||
Value prev = lv.get(0);
|
||||
for (Value next: lv.subList(1, size))
|
||||
{
|
||||
if (prev.compareTo(next) <= 0) return Value.FALSE;
|
||||
prev = next;
|
||||
}
|
||||
return Value.TRUE;
|
||||
});
|
||||
expression.addFunctionalEquivalence(">", "decreasing");
|
||||
|
||||
expression.addBinaryOperator(">=", precedence.get("compare>=><=<"), false, (v1, v2) ->
|
||||
v1.compareTo(v2) >= 0 ? Value.TRUE : Value.FALSE);
|
||||
BooleanValue.of(v1.compareTo(v2) >= 0));
|
||||
expression.addFunction("nonincreasing", lv -> {
|
||||
int size = lv.size();
|
||||
if (size < 2) return Value.TRUE;
|
||||
Value prev = lv.get(0);
|
||||
for (Value next: lv.subList(1, size))
|
||||
{
|
||||
if (prev.compareTo(next) < 0) return Value.FALSE;
|
||||
prev = next;
|
||||
}
|
||||
return Value.TRUE;
|
||||
});
|
||||
expression.addFunctionalEquivalence(">=", "nonincreasing");
|
||||
|
||||
expression.addBinaryOperator("<", precedence.get("compare>=><=<"), false, (v1, v2) ->
|
||||
v1.compareTo(v2) < 0 ? Value.TRUE : Value.FALSE);
|
||||
BooleanValue.of(v1.compareTo(v2) < 0));
|
||||
expression.addFunction("increasing", lv -> {
|
||||
int size = lv.size();
|
||||
if (size < 2) return Value.TRUE;
|
||||
Value prev = lv.get(0);
|
||||
for (Value next: lv.subList(1, size))
|
||||
{
|
||||
if (prev.compareTo(next) >= 0) return Value.FALSE;
|
||||
prev = next;
|
||||
}
|
||||
return Value.TRUE;
|
||||
});
|
||||
expression.addFunctionalEquivalence("<", "increasing");
|
||||
|
||||
expression.addBinaryOperator("<=", precedence.get("compare>=><=<"), false, (v1, v2) ->
|
||||
v1.compareTo(v2) <= 0 ? Value.TRUE : Value.FALSE);
|
||||
BooleanValue.of(v1.compareTo(v2) <= 0));
|
||||
expression.addFunction("nondecreasing", lv -> {
|
||||
int size = lv.size();
|
||||
if (size < 2) return Value.TRUE;
|
||||
Value prev = lv.get(0);
|
||||
for (Value next: lv.subList(1, size))
|
||||
{
|
||||
if (prev.compareTo(next) > 0) return Value.FALSE;
|
||||
prev = next;
|
||||
}
|
||||
return Value.TRUE;
|
||||
});
|
||||
expression.addFunctionalEquivalence("<=", "nondecreasing");
|
||||
|
||||
expression.addBinaryOperator("==", precedence.get("equal==!="), false, (v1, v2) ->
|
||||
v1.equals(v2) ? Value.TRUE : Value.FALSE);
|
||||
expression.addFunction("equal", lv -> {
|
||||
int size = lv.size();
|
||||
if (size < 2) return Value.TRUE;
|
||||
Value prev = lv.get(0);
|
||||
for (Value next: lv.subList(1, size))
|
||||
{
|
||||
if (!prev.equals(next)) return Value.FALSE;
|
||||
prev = next;
|
||||
}
|
||||
return Value.TRUE;
|
||||
});
|
||||
expression.addFunctionalEquivalence("==", "equal");
|
||||
|
||||
|
||||
expression.addBinaryOperator("!=", precedence.get("equal==!="), false, (v1, v2) ->
|
||||
v1.equals(v2) ? Value.FALSE : Value.TRUE);
|
||||
expression.addFunction("unique", lv -> {
|
||||
int size = lv.size();
|
||||
if (size < 2) return Value.TRUE;
|
||||
// need to order them so same obejects will be next to each other.
|
||||
lv.sort(Comparator.comparingInt(Value::hashCode));
|
||||
Value prev = lv.get(0);
|
||||
for (Value next: lv.subList(1, size))
|
||||
{
|
||||
if (prev.equals(next)) return Value.FALSE;
|
||||
prev = next;
|
||||
}
|
||||
return Value.TRUE;
|
||||
});
|
||||
expression.addFunctionalEquivalence("!=", "unique");
|
||||
|
||||
// lazy cause of assignment which is non-trivial
|
||||
expression.addLazyBinaryOperator("=", precedence.get("assign=<>"), false, (c, t, lv1, lv2) ->
|
||||
expression.addLazyBinaryOperator("=", precedence.get("assign=<>"), false, false, t -> Context.Type.LVALUE, (c, t, lv1, lv2) ->
|
||||
{
|
||||
Value v1 = lv1.evalValue(c, Context.LVALUE);
|
||||
Value v2 = lv2.evalValue(c);
|
||||
@@ -117,7 +275,7 @@ public class Operators {
|
||||
});
|
||||
|
||||
// lazy due to assignment
|
||||
expression.addLazyBinaryOperator("+=", precedence.get("assign=<>"), false, (c, t, lv1, lv2) ->
|
||||
expression.addLazyBinaryOperator("+=", precedence.get("assign=<>"), false, false, t -> Context.Type.LVALUE, (c, t, lv1, lv2) ->
|
||||
{
|
||||
Value v1 = lv1.evalValue(c, Context.LVALUE);
|
||||
Value v2 = lv2.evalValue(c);
|
||||
@@ -177,7 +335,7 @@ public class Operators {
|
||||
return boundedLHS;
|
||||
});
|
||||
|
||||
expression.addBinaryContextOperator("<>", precedence.get("assign=<>"), false, (c, t, v1, v2) ->
|
||||
expression.addBinaryContextOperator("<>", precedence.get("assign=<>"), false, false, false, (c, t, v1, v2) ->
|
||||
{
|
||||
if (v1 instanceof ListValue.ListConstructorValue && v2 instanceof ListValue.ListConstructorValue)
|
||||
{
|
||||
@@ -218,12 +376,12 @@ public class Operators {
|
||||
expression.addUnaryOperator("+", false, NumericValue::asNumber);
|
||||
|
||||
// could be non-lazy, but who cares - its a small one.
|
||||
expression.addLazyUnaryOperator("!", precedence.get("unary+-!..."), false, (c, t, lv) ->
|
||||
expression.addLazyUnaryOperator("!", precedence.get("unary+-!..."), false, true, x -> Context.Type.BOOLEAN, (c, t, lv) ->
|
||||
lv.evalValue(c, Context.BOOLEAN).getBoolean() ? (cc, tt)-> Value.FALSE : (cc, tt) -> Value.TRUE
|
||||
); // might need context boolean
|
||||
|
||||
// lazy because of typed evaluation of the argument
|
||||
expression.addLazyUnaryOperator("...", Operators.precedence.get("unary+-!..."), false, (c, t, lv) ->
|
||||
expression.addLazyUnaryOperator("...", Operators.precedence.get("unary+-!..."), false, true, t -> t== Context.Type.LOCALIZATION?Context.NONE:t, (c, t, lv) ->
|
||||
{
|
||||
if (t == Context.LOCALIZATION)
|
||||
return (cc, tt) -> new FunctionAnnotationValue(lv.evalValue(c), FunctionAnnotationValue.Type.VARARG);
|
||||
|
||||
Reference in new issue
Block a user