added functional equivalence. Added element, define, modulo, exponent, match, assign, append, swap, opposite, identity, not, unpack,
This commit is contained in:
1 parent
234c176670
commit
eb1ca9702c
5 files changed
+306
-111
No files matched your search
@@ -111,12 +111,20 @@ public class Expression
|
|||||||
}
|
}
|
||||||
|
|
||||||
private final Map<String, String> functionalEquivalence = new Object2ObjectOpenHashMap<>();
|
private final Map<String, String> functionalEquivalence = new Object2ObjectOpenHashMap<>();
|
||||||
|
private final Map<String, String> functionalAliases = new Object2ObjectOpenHashMap<>();
|
||||||
|
|
||||||
public void addFunctionalEquivalence(String operator, String function)
|
private void addFunctionalEquivalence(String operator, String function)
|
||||||
{
|
{
|
||||||
assert operators.containsKey(operator);
|
assert operators.containsKey(operator);
|
||||||
assert functions.containsKey(function);
|
assert functions.containsKey(function);
|
||||||
functionalEquivalence.put(operator, function);
|
functionalEquivalence.put(operator, function);
|
||||||
|
functionalAliases.put(operator, function);
|
||||||
|
}
|
||||||
|
private void addFunctionalAlias(String operator, String function)
|
||||||
|
{
|
||||||
|
assert operators.containsKey(operator);
|
||||||
|
assert functions.containsKey(function);
|
||||||
|
functionalAliases.put(operator, function);
|
||||||
}
|
}
|
||||||
|
|
||||||
private final Map<String, Value> constants = Map.of(
|
private final Map<String, Value> constants = Map.of(
|
||||||
@@ -191,7 +199,7 @@ public class Expression
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void addLazyUnaryOperator(String surface, int precedence, boolean leftAssoc, boolean pure, Function<Context.Type, Context.Type> staticTyper,
|
public void addLazyUnaryOperator(String surface, String function, int precedence, boolean leftAssoc, boolean pure, Function<Context.Type, Context.Type> staticTyper,
|
||||||
TriFunction<Context, Context.Type, LazyValue, LazyValue> lazyfun)
|
TriFunction<Context, Context.Type, LazyValue, LazyValue> lazyfun)
|
||||||
{
|
{
|
||||||
operators.put(surface + "u", new AbstractLazyOperator(precedence, leftAssoc)
|
operators.put(surface + "u", new AbstractLazyOperator(precedence, leftAssoc)
|
||||||
@@ -227,10 +235,45 @@ public class Expression
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
functions.put(function, new AbstractLazyFunction(1, function)
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public boolean pure()
|
||||||
|
{
|
||||||
|
return pure;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean transitive()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Context.Type staticType(Context.Type outerType)
|
||||||
|
{
|
||||||
|
return staticTyper.apply(outerType);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LazyValue lazyEval(Context c, Context.Type t, Expression e, Token token, List<LazyValue> v)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return lazyfun.apply(c, t, v.get(0));
|
||||||
|
}
|
||||||
|
catch (RuntimeException exc)
|
||||||
|
{
|
||||||
|
throw handleCodeException(c, exc, e, token);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
addFunctionalAlias(surface + "u", function);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void addLazyBinaryOperatorWithDelegation(String surface, int precedence, boolean leftAssoc, boolean pure,
|
public void addLazyBinaryOperatorWithDelegation(String surface, String function, int precedence, boolean leftAssoc, boolean pure,
|
||||||
SexFunction<Context, Context.Type, Expression, Token, LazyValue, LazyValue, LazyValue> lazyfun)
|
SexFunction<Context, Context.Type, Expression, Token, LazyValue, LazyValue, LazyValue> lazyfun)
|
||||||
{
|
{
|
||||||
operators.put(surface, new AbstractLazyOperator(precedence, leftAssoc)
|
operators.put(surface, new AbstractLazyOperator(precedence, leftAssoc)
|
||||||
@@ -260,6 +303,36 @@ public class Expression
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
functions.put(function, new AbstractLazyFunction(2, function)
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public boolean pure()
|
||||||
|
{
|
||||||
|
return pure;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean transitive()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LazyValue lazyEval(Context c, Context.Type type, Expression e, Token t, List<LazyValue> v)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return lazyfun.apply(c, type, e, t, v.get(0), v.get(1));
|
||||||
|
}
|
||||||
|
catch (RuntimeException exc)
|
||||||
|
{
|
||||||
|
throw handleCodeException(c, exc, e, t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
addFunctionalAlias(surface, function);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addCustomFunction(String name, ILazyFunction fun)
|
public void addCustomFunction(String name, ILazyFunction fun)
|
||||||
@@ -333,7 +406,84 @@ public class Expression
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addLazyBinaryOperator(String surface, int precedence, boolean leftAssoc, boolean pure, Function<Context.Type, Context.Type> typer,
|
public void addLazyBinaryOperator(String surface, String function, int precedence, boolean leftAssoc, boolean pure, Function<Context.Type, Context.Type> typer,
|
||||||
|
QuadFunction<Context, Context.Type, LazyValue, LazyValue, LazyValue> lazyfun, TriFunction<Context, Context.Type, List<LazyValue>, LazyValue> multiFun)
|
||||||
|
{
|
||||||
|
operators.put(surface, new AbstractLazyOperator(precedence, leftAssoc)
|
||||||
|
{
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean pure()
|
||||||
|
{
|
||||||
|
return pure;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean transitive()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Context.Type staticType(Context.Type outerType)
|
||||||
|
{
|
||||||
|
return typer.apply(outerType);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LazyValue lazyEval(Context c, Context.Type t, Expression e, Token token, LazyValue v1, LazyValue v2)
|
||||||
|
{
|
||||||
|
ILazyFunction.checkInterrupts();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return lazyfun.apply(c, t, v1, v2);
|
||||||
|
}
|
||||||
|
catch (RuntimeException exc)
|
||||||
|
{
|
||||||
|
throw handleCodeException(c, exc, e, token);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
functions.put(function, new AbstractLazyFunction(-1, function)
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public boolean pure()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean transitive()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Context.Type staticType(Context.Type outerType)
|
||||||
|
{
|
||||||
|
return typer.apply(outerType);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LazyValue lazyEval(Context c, Context.Type i, Expression e, Token t, List<LazyValue> lazyParams)
|
||||||
|
{
|
||||||
|
ILazyFunction.checkInterrupts();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return multiFun.apply(c, i, lazyParams);
|
||||||
|
}
|
||||||
|
catch (RuntimeException exc)
|
||||||
|
{
|
||||||
|
throw handleCodeException(c, exc, e, t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
addFunctionalEquivalence(surface, function);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addLazyBinaryOperator(String surface, String function, int precedence, boolean leftAssoc, boolean pure, Function<Context.Type, Context.Type> typer,
|
||||||
QuadFunction<Context, Context.Type, LazyValue, LazyValue, LazyValue> lazyfun)
|
QuadFunction<Context, Context.Type, LazyValue, LazyValue, LazyValue> lazyfun)
|
||||||
{
|
{
|
||||||
operators.put(surface, new AbstractLazyOperator(precedence, leftAssoc)
|
operators.put(surface, new AbstractLazyOperator(precedence, leftAssoc)
|
||||||
@@ -371,9 +521,45 @@ public class Expression
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
functions.put(function, new AbstractLazyFunction(2, function)
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public boolean pure()
|
||||||
|
{
|
||||||
|
return pure;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean transitive()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Context.Type staticType(Context.Type outerType)
|
||||||
|
{
|
||||||
|
return typer.apply(outerType);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LazyValue lazyEval(Context c, Context.Type t, Expression e, Token token, List<LazyValue> v)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return lazyfun.apply(c, t, v.get(0), v.get(1));
|
||||||
|
}
|
||||||
|
catch (RuntimeException exc)
|
||||||
|
{
|
||||||
|
throw handleCodeException(c, exc, e, token);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
addFunctionalAlias(surface, function);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addBinaryContextOperator(String surface, int precedence, boolean leftAssoc, boolean pure, boolean transitive,
|
public void addBinaryContextOperator(String surface, String function, int precedence, boolean leftAssoc, boolean pure, boolean transitive,
|
||||||
QuadFunction<Context, Context.Type, Value, Value, Value> fun)
|
QuadFunction<Context, Context.Type, Value, Value, Value> fun)
|
||||||
{
|
{
|
||||||
operators.put(surface, new AbstractLazyOperator(precedence, leftAssoc)
|
operators.put(surface, new AbstractLazyOperator(precedence, leftAssoc)
|
||||||
@@ -404,6 +590,37 @@ public class Expression
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
functions.put(function, new AbstractLazyFunction(2, function)
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public boolean pure()
|
||||||
|
{
|
||||||
|
return pure;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean transitive()
|
||||||
|
{
|
||||||
|
return transitive;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LazyValue lazyEval(Context c, Context.Type t, Expression e, Token token, List<LazyValue> v)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Value ret = fun.apply(c, t, v.get(0).evalValue(c, Context.NONE), v.get(1).evalValue(c, Context.NONE));
|
||||||
|
return (cc, tt) -> ret;
|
||||||
|
}
|
||||||
|
catch (RuntimeException exc)
|
||||||
|
{
|
||||||
|
throw handleCodeException(c, exc, e, token);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
addFunctionalAlias(surface, function);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static RuntimeException handleCodeException(Context c, RuntimeException exc, Expression e, Token token)
|
public static RuntimeException handleCodeException(Context c, RuntimeException exc, Expression e, Token token)
|
||||||
@@ -433,7 +650,7 @@ public class Expression
|
|||||||
return new ExpressionException(c, e, token, "Internal error (please report this issue to Carpet) while evaluating: " + exc);
|
return new ExpressionException(c, e, token, "Internal error (please report this issue to Carpet) while evaluating: " + exc);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addUnaryOperator(String surface, boolean leftAssoc, Function<Value, Value> fun)
|
public void addUnaryOperator(String surface, String function, boolean leftAssoc, Function<Value, Value> fun)
|
||||||
{
|
{
|
||||||
operators.put(surface + "u", new AbstractUnaryOperator(Operators.precedence.get("unary+-!..."), leftAssoc)
|
operators.put(surface + "u", new AbstractUnaryOperator(Operators.precedence.get("unary+-!..."), leftAssoc)
|
||||||
{
|
{
|
||||||
@@ -443,18 +660,57 @@ public class Expression
|
|||||||
return fun.apply(v1);
|
return fun.apply(v1);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
functions.put(function, new AbstractFunction(1, function)
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public Value eval(List<Value> v1)
|
||||||
|
{
|
||||||
|
return fun.apply(v1.get(0));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
addFunctionalAlias(surface + "u", function);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addBinaryOperator(String surface, int precedence, boolean leftAssoc, BiFunction<Value, Value, Value> fun)
|
public void addBinaryOperator(String surface, String function, int precedence, boolean leftAssoc, BiFunction<Value, Value, Value> fun, Function<List<Value>, Value> multiFun)
|
||||||
{
|
{
|
||||||
operators.put(surface, new AbstractOperator(precedence, leftAssoc)
|
operators.put(surface, new AbstractOperator(precedence, leftAssoc)
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
public Value eval(Value v1, Value v2)
|
public Value eval(Value v1, Value v2) {
|
||||||
{
|
|
||||||
return fun.apply(v1, v2);
|
return fun.apply(v1, v2);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
functions.put(function, new AbstractFunction(-1, function)
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public Value eval(List<Value> parameters)
|
||||||
|
{
|
||||||
|
return multiFun.apply(parameters);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
addFunctionalEquivalence(surface, function);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addBinaryOperator(String surface, String name, int precedence, boolean leftAssoc, BiFunction<Value, Value, Value> fun)
|
||||||
|
{
|
||||||
|
operators.put(surface, new AbstractOperator(precedence, leftAssoc)
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public Value eval(Value v1, Value v2) {
|
||||||
|
return fun.apply(v1, v2);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
functions.put(name, new AbstractFunction(2, name)
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public Value eval(List<Value> parameters)
|
||||||
|
{
|
||||||
|
return fun.apply(parameters.get(0), parameters.get(1));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
addFunctionalAlias(surface, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -623,44 +879,6 @@ public class Expression
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addPureLazyFunction(String name, int num_params, Function<Context.Type, Context.Type> typer, TriFunction<Context, Context.Type, List<LazyValue>, LazyValue> fun)
|
|
||||||
{
|
|
||||||
functions.put(name, new AbstractLazyFunction(num_params, name)
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public boolean pure()
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean transitive()
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Context.Type staticType(Context.Type outerType)
|
|
||||||
{
|
|
||||||
return typer.apply(outerType);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public LazyValue lazyEval(Context c, Context.Type i, Expression e, Token t, List<LazyValue> lazyParams)
|
|
||||||
{
|
|
||||||
ILazyFunction.checkInterrupts();
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return fun.apply(c, i, lazyParams);
|
|
||||||
}
|
|
||||||
catch (RuntimeException exc)
|
|
||||||
{
|
|
||||||
throw handleCodeException(c, exc, e, t);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addContextFunction(String name, int num_params, TriFunction<Context, Context.Type, List<Value>, Value> fun)
|
public void addContextFunction(String name, int num_params, TriFunction<Context, Context.Type, List<Value>, Value> fun)
|
||||||
{
|
{
|
||||||
functions.put(name, new AbstractLazyFunction(num_params, name)
|
functions.put(name, new AbstractLazyFunction(num_params, name)
|
||||||
@@ -859,6 +1077,9 @@ public class Expression
|
|||||||
Threading.apply(this);
|
Threading.apply(this);
|
||||||
Loops.apply(this);
|
Loops.apply(this);
|
||||||
DataStructures.apply(this);
|
DataStructures.apply(this);
|
||||||
|
for(String op : operators.keySet()) {
|
||||||
|
assert functionalAliases.containsKey(op) : "Missing function for operator " + op;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1381,6 +1602,13 @@ public class Expression
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (toFunctional && functionalAliases.containsKey(symbol) && !node.args.isEmpty())
|
||||||
|
{
|
||||||
|
optimized = true;
|
||||||
|
node.token.morph(Token.TokenType.FUNCTION, functionalAliases.get(symbol));
|
||||||
|
}
|
||||||
|
|
||||||
return optimized;
|
return optimized;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,14 +22,12 @@ public class ControlFlow
|
|||||||
public static void apply(Expression expression) // public just to get the javadoc right
|
public static void apply(Expression expression) // public just to get the javadoc right
|
||||||
{
|
{
|
||||||
// needs to be lazy cause of custom contextualization
|
// needs to be lazy cause of custom contextualization
|
||||||
expression.addLazyBinaryOperator(";", Operators.precedence.get("nextop;"), true, true, t -> Context.Type.VOID, (c, t, lv1, lv2) ->
|
expression.addLazyBinaryOperator(";", "then", Operators.precedence.get("nextop;"), true, true, t -> Context.Type.VOID, (c, t, lv1, lv2) ->
|
||||||
{
|
{
|
||||||
lv1.evalValue(c, Context.VOID);
|
lv1.evalValue(c, Context.VOID);
|
||||||
Value v2 = lv2.evalValue(c, t);
|
Value v2 = lv2.evalValue(c, t);
|
||||||
return (cc, tt) -> v2;
|
return (cc, tt) -> v2;
|
||||||
});
|
}, (c, t, lv) -> {
|
||||||
|
|
||||||
expression.addPureLazyFunction("then", -1, t -> Context.Type.VOID, (c, t, lv) -> {
|
|
||||||
int imax = lv.size() - 1;
|
int imax = lv.size() - 1;
|
||||||
for (int i = 0; i < imax; i++)
|
for (int i = 0; i < imax; i++)
|
||||||
{
|
{
|
||||||
@@ -38,7 +36,6 @@ public class ControlFlow
|
|||||||
Value v = lv.get(imax).evalValue(c, t);
|
Value v = lv.get(imax).evalValue(c, t);
|
||||||
return (cc, tt) -> v;
|
return (cc, tt) -> v;
|
||||||
});
|
});
|
||||||
expression.addFunctionalEquivalence(";", "then");
|
|
||||||
|
|
||||||
|
|
||||||
// obvious lazy due to conditional evaluation of arguments
|
// obvious lazy due to conditional evaluation of arguments
|
||||||
|
|||||||
@@ -188,7 +188,7 @@ public class DataStructures
|
|||||||
? ListValue.wrap(map.getMap().entrySet().stream().map(p -> ListValue.of(p.getKey(), p.getValue())))
|
? ListValue.wrap(map.getMap().entrySet().stream().map(p -> ListValue.of(p.getKey(), p.getValue())))
|
||||||
: Value.NULL);
|
: Value.NULL);
|
||||||
|
|
||||||
expression.addBinaryContextOperator(":", Operators.precedence.get("attribute~:"), true, true, false, (ctx, t, container, address) ->
|
expression.addBinaryContextOperator(":", "element", Operators.precedence.get("attribute~:"), true, true, false, (ctx, t, container, address) ->
|
||||||
{
|
{
|
||||||
if (container instanceof final LContainerValue lcv)
|
if (container instanceof final LContainerValue lcv)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -126,7 +126,7 @@ public class Functions
|
|||||||
|
|
||||||
//assigns const procedure to the lhs, returning its previous value
|
//assigns const procedure to the lhs, returning its previous value
|
||||||
// must be lazy due to RHS being an expression to save to execute
|
// must be lazy due to RHS being an expression to save to execute
|
||||||
expression.addLazyBinaryOperatorWithDelegation("->", Operators.precedence.get("def->"), false, false, (c, type, e, t, lv1, lv2) ->
|
expression.addLazyBinaryOperatorWithDelegation("->", "define", Operators.precedence.get("def->"), false, false, (c, type, e, t, lv1, lv2) ->
|
||||||
{
|
{
|
||||||
if (type == Context.MAPDEF)
|
if (type == Context.MAPDEF)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -41,8 +41,7 @@ public class Operators
|
|||||||
|
|
||||||
public static void apply(Expression expression)
|
public static void apply(Expression expression)
|
||||||
{
|
{
|
||||||
expression.addBinaryOperator("+", precedence.get("addition+-"), true, Value::add);
|
expression.addBinaryOperator("+", "sum", precedence.get("addition+-"), true, Value::add, lv -> {
|
||||||
expression.addFunction("sum", lv -> {
|
|
||||||
int size = lv.size();
|
int size = lv.size();
|
||||||
if (size == 0)
|
if (size == 0)
|
||||||
{
|
{
|
||||||
@@ -55,10 +54,8 @@ public class Operators
|
|||||||
}
|
}
|
||||||
return accumulator;
|
return accumulator;
|
||||||
});
|
});
|
||||||
expression.addFunctionalEquivalence("+", "sum");
|
|
||||||
|
|
||||||
expression.addBinaryOperator("-", precedence.get("addition+-"), true, Value::subtract);
|
expression.addBinaryOperator("-", "difference", precedence.get("addition+-"), true, Value::subtract, lv -> {
|
||||||
expression.addFunction("difference", lv -> {
|
|
||||||
int size = lv.size();
|
int size = lv.size();
|
||||||
if (size == 0)
|
if (size == 0)
|
||||||
{
|
{
|
||||||
@@ -71,10 +68,8 @@ public class Operators
|
|||||||
}
|
}
|
||||||
return accumulator;
|
return accumulator;
|
||||||
});
|
});
|
||||||
expression.addFunctionalEquivalence("-", "difference");
|
|
||||||
|
|
||||||
expression.addBinaryOperator("*", precedence.get("multiplication*/%"), true, Value::multiply);
|
expression.addBinaryOperator("*", "product", precedence.get("multiplication*/%"), true, Value::multiply, lv -> {
|
||||||
expression.addFunction("product", lv -> {
|
|
||||||
int size = lv.size();
|
int size = lv.size();
|
||||||
if (size == 0)
|
if (size == 0)
|
||||||
{
|
{
|
||||||
@@ -87,10 +82,8 @@ public class Operators
|
|||||||
}
|
}
|
||||||
return accumulator;
|
return accumulator;
|
||||||
});
|
});
|
||||||
expression.addFunctionalEquivalence("*", "product");
|
|
||||||
|
|
||||||
expression.addBinaryOperator("/", precedence.get("multiplication*/%"), true, Value::divide);
|
expression.addBinaryOperator("/", "quotient", precedence.get("multiplication*/%"), true, Value::divide, lv -> {
|
||||||
expression.addFunction("quotient", lv -> {
|
|
||||||
int size = lv.size();
|
int size = lv.size();
|
||||||
if (size == 0)
|
if (size == 0)
|
||||||
{
|
{
|
||||||
@@ -103,11 +96,11 @@ public class Operators
|
|||||||
}
|
}
|
||||||
return accumulator;
|
return accumulator;
|
||||||
});
|
});
|
||||||
expression.addFunctionalEquivalence("/", "quotient");
|
|
||||||
|
|
||||||
expression.addBinaryOperator("%", precedence.get("multiplication*/%"), true, (v1, v2) ->
|
expression.addBinaryOperator("%", "modulo", precedence.get("multiplication*/%"), true, (v1, v2) ->
|
||||||
NumericValue.asNumber(v1).mod(NumericValue.asNumber(v2)));
|
NumericValue.asNumber(v1).mod(NumericValue.asNumber(v2)));
|
||||||
expression.addBinaryOperator("^", precedence.get("exponent^"), false, (v1, v2) ->
|
|
||||||
|
expression.addBinaryOperator("^", "exponent", precedence.get("exponent^"), false, (v1, v2) ->
|
||||||
new NumericValue(java.lang.Math.pow(NumericValue.asNumber(v1).getDouble(), NumericValue.asNumber(v2).getDouble())));
|
new NumericValue(java.lang.Math.pow(NumericValue.asNumber(v1).getDouble(), NumericValue.asNumber(v2).getDouble())));
|
||||||
|
|
||||||
expression.addFunction("bitwise_and", lv -> {
|
expression.addFunction("bitwise_and", lv -> {
|
||||||
@@ -153,13 +146,11 @@ public class Operators
|
|||||||
});
|
});
|
||||||
|
|
||||||
// lazy cause RHS is only conditional
|
// lazy cause RHS is only conditional
|
||||||
expression.addLazyBinaryOperator("&&", precedence.get("and&&"), false, true, t -> Context.Type.BOOLEAN, (c, t, lv1, lv2) ->
|
expression.addLazyBinaryOperator("&&", "and", precedence.get("and&&"), false, true, t -> Context.Type.BOOLEAN, (c, t, lv1, lv2) ->
|
||||||
{ // todo check how is optimizations going
|
{ // todo check how is optimizations going
|
||||||
Value v1 = lv1.evalValue(c, Context.BOOLEAN);
|
Value v1 = lv1.evalValue(c, Context.BOOLEAN);
|
||||||
return v1.getBoolean() ? lv2 : ((cc, tt) -> v1);
|
return v1.getBoolean() ? lv2 : ((cc, tt) -> v1);
|
||||||
});
|
}, (c, t, lv) -> {
|
||||||
|
|
||||||
expression.addPureLazyFunction("and", -1, t -> Context.Type.BOOLEAN, (c, t, lv) -> {
|
|
||||||
int last = lv.size() - 1;
|
int last = lv.size() - 1;
|
||||||
if (last == -1)
|
if (last == -1)
|
||||||
{
|
{
|
||||||
@@ -168,7 +159,7 @@ public class Operators
|
|||||||
for (LazyValue l : lv.subList(0, last))
|
for (LazyValue l : lv.subList(0, last))
|
||||||
{
|
{
|
||||||
Value val = l.evalValue(c, Context.Type.BOOLEAN);
|
Value val = l.evalValue(c, Context.Type.BOOLEAN);
|
||||||
if (val instanceof final FunctionUnpackedArgumentsValue fuav)
|
if (val instanceof FunctionUnpackedArgumentsValue fuav)
|
||||||
{
|
{
|
||||||
for (Value it : fuav)
|
for (Value it : fuav)
|
||||||
{
|
{
|
||||||
@@ -188,16 +179,13 @@ public class Operators
|
|||||||
}
|
}
|
||||||
return lv.get(last);
|
return lv.get(last);
|
||||||
});
|
});
|
||||||
expression.addFunctionalEquivalence("&&", "and");
|
|
||||||
|
|
||||||
// lazy cause RHS is only conditional
|
// lazy cause RHS is only conditional
|
||||||
expression.addLazyBinaryOperator("||", precedence.get("or||"), false, true, t -> Context.Type.BOOLEAN, (c, t, lv1, lv2) ->
|
expression.addLazyBinaryOperator("||", "or", precedence.get("or||"), false, true, t -> Context.Type.BOOLEAN, (c, t, lv1, lv2) ->
|
||||||
{
|
{
|
||||||
Value v1 = lv1.evalValue(c, Context.BOOLEAN);
|
Value v1 = lv1.evalValue(c, Context.BOOLEAN);
|
||||||
return v1.getBoolean() ? ((cc, tt) -> v1) : lv2;
|
return v1.getBoolean() ? ((cc, tt) -> v1) : lv2;
|
||||||
});
|
}, (c, t, lv) -> {
|
||||||
|
|
||||||
expression.addPureLazyFunction("or", -1, t -> Context.Type.BOOLEAN, (c, t, lv) -> {
|
|
||||||
int last = lv.size() - 1;
|
int last = lv.size() - 1;
|
||||||
if (last == -1)
|
if (last == -1)
|
||||||
{
|
{
|
||||||
@@ -226,13 +214,10 @@ public class Operators
|
|||||||
}
|
}
|
||||||
return lv.get(last);
|
return lv.get(last);
|
||||||
});
|
});
|
||||||
expression.addFunctionalEquivalence("||", "or");
|
|
||||||
|
|
||||||
expression.addBinaryOperator("~", precedence.get("attribute~:"), true, Value::in);
|
expression.addBinaryOperator("~", "match", precedence.get("attribute~:"), true, Value::in);
|
||||||
|
|
||||||
expression.addBinaryOperator(">", precedence.get("compare>=><=<"), false, (v1, v2) ->
|
expression.addBinaryOperator(">", "decreasing", precedence.get("compare>=><=<"), false, (v1, v2) -> BooleanValue.of(v1.compareTo(v2) > 0), lv -> {
|
||||||
BooleanValue.of(v1.compareTo(v2) > 0));
|
|
||||||
expression.addFunction("decreasing", lv -> {
|
|
||||||
int size = lv.size();
|
int size = lv.size();
|
||||||
if (size < 2)
|
if (size < 2)
|
||||||
{
|
{
|
||||||
@@ -249,11 +234,8 @@ public class Operators
|
|||||||
}
|
}
|
||||||
return Value.TRUE;
|
return Value.TRUE;
|
||||||
});
|
});
|
||||||
expression.addFunctionalEquivalence(">", "decreasing");
|
|
||||||
|
|
||||||
expression.addBinaryOperator(">=", precedence.get("compare>=><=<"), false, (v1, v2) ->
|
expression.addBinaryOperator(">=", "nonincreasing", precedence.get("compare>=><=<"), false, (v1, v2) -> BooleanValue.of(v1.compareTo(v2) >= 0), lv -> {
|
||||||
BooleanValue.of(v1.compareTo(v2) >= 0));
|
|
||||||
expression.addFunction("nonincreasing", lv -> {
|
|
||||||
int size = lv.size();
|
int size = lv.size();
|
||||||
if (size < 2)
|
if (size < 2)
|
||||||
{
|
{
|
||||||
@@ -270,11 +252,8 @@ public class Operators
|
|||||||
}
|
}
|
||||||
return Value.TRUE;
|
return Value.TRUE;
|
||||||
});
|
});
|
||||||
expression.addFunctionalEquivalence(">=", "nonincreasing");
|
|
||||||
|
|
||||||
expression.addBinaryOperator("<", precedence.get("compare>=><=<"), false, (v1, v2) ->
|
expression.addBinaryOperator("<", "increasing", precedence.get("compare>=><=<"), false, (v1, v2) -> BooleanValue.of(v1.compareTo(v2) < 0), lv -> {
|
||||||
BooleanValue.of(v1.compareTo(v2) < 0));
|
|
||||||
expression.addFunction("increasing", lv -> {
|
|
||||||
int size = lv.size();
|
int size = lv.size();
|
||||||
if (size < 2)
|
if (size < 2)
|
||||||
{
|
{
|
||||||
@@ -291,11 +270,8 @@ public class Operators
|
|||||||
}
|
}
|
||||||
return Value.TRUE;
|
return Value.TRUE;
|
||||||
});
|
});
|
||||||
expression.addFunctionalEquivalence("<", "increasing");
|
|
||||||
|
|
||||||
expression.addBinaryOperator("<=", precedence.get("compare>=><=<"), false, (v1, v2) ->
|
expression.addBinaryOperator("<=", "nondecreasing", precedence.get("compare>=><=<"), false, (v1, v2) -> BooleanValue.of(v1.compareTo(v2) <= 0), lv -> {
|
||||||
BooleanValue.of(v1.compareTo(v2) <= 0));
|
|
||||||
expression.addFunction("nondecreasing", lv -> {
|
|
||||||
int size = lv.size();
|
int size = lv.size();
|
||||||
if (size < 2)
|
if (size < 2)
|
||||||
{
|
{
|
||||||
@@ -312,7 +288,7 @@ public class Operators
|
|||||||
}
|
}
|
||||||
return Value.TRUE;
|
return Value.TRUE;
|
||||||
});
|
});
|
||||||
expression.addFunctionalEquivalence("<=", "nondecreasing");
|
|
||||||
expression.addMathematicalBinaryIntFunction("bitwise_shift_left", (num, amount) -> num << amount);
|
expression.addMathematicalBinaryIntFunction("bitwise_shift_left", (num, amount) -> num << amount);
|
||||||
expression.addMathematicalBinaryIntFunction("bitwise_shift_right", (num, amount) -> num >>> amount);
|
expression.addMathematicalBinaryIntFunction("bitwise_shift_right", (num, amount) -> num >>> amount);
|
||||||
expression.addMathematicalBinaryIntFunction("bitwise_arithmetic_shift_right", (num, amount) -> num >> amount);
|
expression.addMathematicalBinaryIntFunction("bitwise_arithmetic_shift_right", (num, amount) -> num >> amount);
|
||||||
@@ -326,9 +302,7 @@ public class Operators
|
|||||||
expression.addMathematicalUnaryIntFunction("double_to_long_bits", Double::doubleToLongBits);
|
expression.addMathematicalUnaryIntFunction("double_to_long_bits", Double::doubleToLongBits);
|
||||||
expression.addUnaryFunction("long_to_double_bits", v ->
|
expression.addUnaryFunction("long_to_double_bits", v ->
|
||||||
new NumericValue(Double.longBitsToDouble(NumericValue.asNumber(v).getLong())));
|
new NumericValue(Double.longBitsToDouble(NumericValue.asNumber(v).getLong())));
|
||||||
expression.addBinaryOperator("==", precedence.get("equal==!="), false, (v1, v2) ->
|
expression.addBinaryOperator("==", "equal", precedence.get("equal==!="), false, (v1, v2) -> v1.equals(v2) ? Value.TRUE : Value.FALSE, lv -> {
|
||||||
v1.equals(v2) ? Value.TRUE : Value.FALSE);
|
|
||||||
expression.addFunction("equal", lv -> {
|
|
||||||
int size = lv.size();
|
int size = lv.size();
|
||||||
if (size < 2)
|
if (size < 2)
|
||||||
{
|
{
|
||||||
@@ -345,11 +319,8 @@ public class Operators
|
|||||||
}
|
}
|
||||||
return Value.TRUE;
|
return Value.TRUE;
|
||||||
});
|
});
|
||||||
expression.addFunctionalEquivalence("==", "equal");
|
|
||||||
|
|
||||||
expression.addBinaryOperator("!=", precedence.get("equal==!="), false, (v1, v2) ->
|
expression.addBinaryOperator("!=", "unique", precedence.get("equal==!="), false, (v1, v2) -> v1.equals(v2) ? Value.FALSE : Value.TRUE, lv -> {
|
||||||
v1.equals(v2) ? Value.FALSE : Value.TRUE);
|
|
||||||
expression.addFunction("unique", lv -> {
|
|
||||||
int size = lv.size();
|
int size = lv.size();
|
||||||
if (size < 2)
|
if (size < 2)
|
||||||
{
|
{
|
||||||
@@ -368,10 +339,9 @@ public class Operators
|
|||||||
}
|
}
|
||||||
return Value.TRUE;
|
return Value.TRUE;
|
||||||
});
|
});
|
||||||
expression.addFunctionalEquivalence("!=", "unique");
|
|
||||||
|
|
||||||
// lazy cause of assignment which is non-trivial
|
// lazy cause of assignment which is non-trivial
|
||||||
expression.addLazyBinaryOperator("=", precedence.get("assign=<>"), false, false, t -> Context.Type.LVALUE, (c, t, lv1, lv2) ->
|
expression.addLazyBinaryOperator("=", "assign", precedence.get("assign=<>"), false, false, t -> Context.Type.LVALUE, (c, t, lv1, lv2) ->
|
||||||
{
|
{
|
||||||
Value v1 = lv1.evalValue(c, Context.LVALUE);
|
Value v1 = lv1.evalValue(c, Context.LVALUE);
|
||||||
Value v2 = lv2.evalValue(c);
|
Value v2 = lv2.evalValue(c);
|
||||||
@@ -424,7 +394,7 @@ public class Operators
|
|||||||
});
|
});
|
||||||
|
|
||||||
// lazy due to assignment
|
// lazy due to assignment
|
||||||
expression.addLazyBinaryOperator("+=", precedence.get("assign=<>"), false, false, t -> Context.Type.LVALUE, (c, t, lv1, lv2) ->
|
expression.addLazyBinaryOperator("+=", "append", precedence.get("assign=<>"), false, false, t -> Context.Type.LVALUE, (c, t, lv1, lv2) ->
|
||||||
{
|
{
|
||||||
Value v1 = lv1.evalValue(c, Context.LVALUE);
|
Value v1 = lv1.evalValue(c, Context.LVALUE);
|
||||||
Value v2 = lv2.evalValue(c);
|
Value v2 = lv2.evalValue(c);
|
||||||
@@ -493,7 +463,7 @@ public class Operators
|
|||||||
return boundedLHS;
|
return boundedLHS;
|
||||||
});
|
});
|
||||||
|
|
||||||
expression.addBinaryContextOperator("<>", precedence.get("assign=<>"), false, false, false, (c, t, v1, v2) ->
|
expression.addBinaryContextOperator("<>", "swap", precedence.get("assign=<>"), false, false, false, (c, t, v1, v2) ->
|
||||||
{
|
{
|
||||||
if (v1 instanceof final ListValue.ListConstructorValue lcv1 && v2 instanceof final ListValue.ListConstructorValue lcv2)
|
if (v1 instanceof final ListValue.ListConstructorValue lcv1 && v2 instanceof final ListValue.ListConstructorValue lcv2)
|
||||||
{
|
{
|
||||||
@@ -541,17 +511,17 @@ public class Operators
|
|||||||
return lval;
|
return lval;
|
||||||
});
|
});
|
||||||
|
|
||||||
expression.addUnaryOperator("-", false, v -> NumericValue.asNumber(v).opposite());
|
expression.addUnaryOperator("-", "opposite", false, v -> NumericValue.asNumber(v).opposite());
|
||||||
|
|
||||||
expression.addUnaryOperator("+", false, NumericValue::asNumber);
|
expression.addUnaryOperator("+", "identity", false, NumericValue::asNumber);
|
||||||
|
|
||||||
// could be non-lazy, but who cares - its a small one.
|
// could be non-lazy, but who cares - its a small one.
|
||||||
expression.addLazyUnaryOperator("!", precedence.get("unary+-!..."), false, true, x -> Context.Type.BOOLEAN, (c, t, lv) ->
|
expression.addLazyUnaryOperator("!", "not", 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
|
lv.evalValue(c, Context.BOOLEAN).getBoolean() ? (cc, tt) -> Value.FALSE : (cc, tt) -> Value.TRUE
|
||||||
); // might need context boolean
|
); // might need context boolean
|
||||||
|
|
||||||
// lazy because of typed evaluation of the argument
|
// lazy because of typed evaluation of the argument
|
||||||
expression.addLazyUnaryOperator("...", Operators.precedence.get("unary+-!..."), false, true, t -> t == Context.Type.LOCALIZATION ? Context.NONE : t, (c, t, lv) ->
|
expression.addLazyUnaryOperator("...", "unpack", Operators.precedence.get("unary+-!..."), false, true, t -> t == Context.Type.LOCALIZATION ? Context.NONE : t, (c, t, lv) ->
|
||||||
{
|
{
|
||||||
if (t == Context.LOCALIZATION)
|
if (t == Context.LOCALIZATION)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in new issue
Block a user