[muscript] No more inner-classes for expressions

This commit is contained in:
Johannes Frohnmeyer 2022-06-07 13:36:48 +02:00
parent 4f3fdbb9fd
commit 5447174c90
Signed by: Johannes
GPG Key ID: E76429612C2929F4
45 changed files with 715 additions and 439 deletions

View File

@ -1,185 +0,0 @@
package io.gitlab.jfronny.muscript.compiler;
import io.gitlab.jfronny.muscript.dynamic.*;
import io.gitlab.jfronny.commons.StringFormatter;
public abstract class Expr<T> {
public abstract Type getResultType();
public abstract T get(Dynamic<?> branch, Dynamic<?> dataRoot);
public T get(Dynamic<?> branch) {
return get(branch, branch);
}
public BoolExpr asBoolExpr() {
if (this instanceof BoolExpr e) return e;
throw new IllegalArgumentException("Expected boolean but is " + getResultType());
}
public StringExpr asStringExpr() {
if (this instanceof StringExpr e) return e;
return new StringExpr() {
@Override
public String get(Dynamic<?> branch, Dynamic<?> dataRoot) {
return StringFormatter.toString(Expr.this.get(branch, dataRoot));
}
};
}
public NumberExpr asNumberExpr() {
if (this instanceof NumberExpr e) return e;
throw new IllegalArgumentException("Expected number but is " + getResultType());
}
public abstract DynamicExpr asDynamicExpr();
public boolean isNull() {
return this instanceof NullExpr;
}
public static abstract class BoolExpr extends Expr<Boolean> {
@Override
public Type getResultType() {
return Type.Boolean;
}
@Override
public DynamicExpr asDynamicExpr() {
return new DynamicExpr() {
@Override
public Dynamic<?> get(Dynamic<?> branch, Dynamic<?> dataRoot) {
return DFinal.of(BoolExpr.this.get(branch, dataRoot));
}
};
}
}
public static abstract class StringExpr extends Expr<String> {
@Override
public Type getResultType() {
return Type.String;
}
@Override
public DynamicExpr asDynamicExpr() {
return new DynamicExpr() {
@Override
public Dynamic<?> get(Dynamic<?> branch, Dynamic<?> dataRoot) {
return DFinal.of(StringExpr.this.get(branch, dataRoot));
}
};
}
}
public static abstract class NumberExpr extends Expr<Double> {
@Override
public Type getResultType() {
return Type.Number;
}
@Override
public DynamicExpr asDynamicExpr() {
return new DynamicExpr() {
@Override
public Dynamic<?> get(Dynamic<?> branch, Dynamic<?> dataRoot) {
return DFinal.of(NumberExpr.this.get(branch, dataRoot));
}
};
}
}
public static abstract class DynamicExpr extends Expr<Dynamic<?>> {
@Override
public Type getResultType() {
return Type.Dynamic;
}
@Override
public BoolExpr asBoolExpr() {
return new BoolExpr() {
@Override
public Boolean get(Dynamic<?> branch, Dynamic<?> dataRoot) {
return DynamicExpr.this.get(branch, dataRoot).asBool().getValue();
}
};
}
@Override
public StringExpr asStringExpr() {
return new StringExpr() {
@Override
public String get(Dynamic<?> branch, Dynamic<?> dataRoot) {
return DynamicExpr.this.get(branch, dataRoot).asString().getValue();
}
};
}
@Override
public NumberExpr asNumberExpr() {
return new NumberExpr() {
@Override
public Double get(Dynamic<?> branch, Dynamic<?> dataRoot) {
return DynamicExpr.this.get(branch, dataRoot).asNumber().getValue();
}
};
}
@Override
public DynamicExpr asDynamicExpr() {
return this;
}
}
public static final class NullExpr extends Expr<Object> {
@Override
public Type getResultType() {
return Type.Dynamic;
}
@Override
public Object get(Dynamic<?> branch, Dynamic<?> dataRoot) {
return null;
}
@Override
public DynamicExpr asDynamicExpr() {
return new DynamicExpr() {
@Override
public Dynamic<?> get(Dynamic<?> branch, Dynamic<?> dataRoot) {
return new DNull();
}
};
}
}
public static BoolExpr literal(boolean bool) {
return new BoolExpr() {
@Override
public Boolean get(Dynamic<?> branch, Dynamic<?> dataRoot) {
return bool;
}
};
}
public static StringExpr literal(String string) {
return new StringExpr() {
@Override
public String get(Dynamic<?> branch, Dynamic<?> dataRoot) {
return string;
}
};
}
public static NumberExpr literal(double number) {
return new NumberExpr() {
@Override
public Double get(Dynamic<?> branch, Dynamic<?> dataRoot) {
return number;
}
};
}
public static Expr<?> literalNull() {
return new NullExpr();
}
}

View File

@ -1,6 +1,13 @@
package io.gitlab.jfronny.muscript.compiler; package io.gitlab.jfronny.muscript.compiler;
import io.gitlab.jfronny.muscript.compiler.expr.*; import io.gitlab.jfronny.muscript.compiler.expr.*;
import io.gitlab.jfronny.muscript.compiler.expr.bool.*;
import io.gitlab.jfronny.muscript.compiler.expr.common.*;
import io.gitlab.jfronny.muscript.compiler.expr.dynamic.*;
import io.gitlab.jfronny.muscript.compiler.expr.number.compare.*;
import io.gitlab.jfronny.muscript.compiler.expr.number.math.*;
import io.gitlab.jfronny.muscript.compiler.expr.string.*;
import io.gitlab.jfronny.muscript.compiler.expr.unresolved.*;
import java.util.*; import java.util.*;
@ -41,7 +48,7 @@ public class Parser {
Expr<?> trueExpr = expression(); Expr<?> trueExpr = expression();
consume(Token.Colon, "Expected ':' after first part of condition."); consume(Token.Colon, "Expected ':' after first part of condition.");
Expr<?> falseExpr = expression(); Expr<?> falseExpr = expression();
expr = new Conditional(expr.asBoolExpr(), trueExpr, falseExpr); expr = new UnresolvedConditional(expr.asBoolExpr(), trueExpr, falseExpr);
} }
return expr; return expr;
@ -52,7 +59,7 @@ public class Parser {
while (match(Token.And)) { while (match(Token.And)) {
Expr<?> right = or(); Expr<?> right = or();
expr = new LogicBiExpr(expr.asBoolExpr(), right.asBoolExpr(), Token.And); expr = new And(expr.asBoolExpr(), right.asBoolExpr());
} }
return expr; return expr;
@ -63,7 +70,7 @@ public class Parser {
while (match(Token.Or)) { while (match(Token.Or)) {
Expr<?> right = equality(); Expr<?> right = equality();
expr = new LogicBiExpr(expr.asBoolExpr(), right.asBoolExpr(), Token.Or); expr = new Or(expr.asBoolExpr(), right.asBoolExpr());
} }
return expr; return expr;
@ -75,7 +82,7 @@ public class Parser {
while (match(Token.EqualEqual, Token.BangEqual)) { while (match(Token.EqualEqual, Token.BangEqual)) {
Token op = previous.token; Token op = previous.token;
Expr<?> right = concat(); Expr<?> right = concat();
Expr.BoolExpr e = new Equal(expr, right); BoolExpr e = new Equal(expr, right);
if (op == Token.BangEqual) e = new Not(e); if (op == Token.BangEqual) e = new Not(e);
expr = e; expr = e;
} }
@ -87,7 +94,6 @@ public class Parser {
Expr<?> expr = comparison(); Expr<?> expr = comparison();
while (match(Token.Concat)) { while (match(Token.Concat)) {
Token op = previous.token;
Expr<?> right = comparison(); Expr<?> right = comparison();
expr = new Concatenate(expr.asStringExpr(), right.asStringExpr()); expr = new Concatenate(expr.asStringExpr(), right.asStringExpr());
} }
@ -100,8 +106,14 @@ public class Parser {
while (match(Token.Greater, Token.GreaterEqual, Token.Less, Token.LessEqual)) { while (match(Token.Greater, Token.GreaterEqual, Token.Less, Token.LessEqual)) {
Token op = previous.token; Token op = previous.token;
Expr<?> right = term(); NumberExpr right = term().asNumberExpr();
expr = new Compare(expr.asNumberExpr(), right.asNumberExpr(), op); expr = switch (op) {
case Greater -> new Greater(expr.asNumberExpr(), right);
case GreaterEqual -> new Not(new Less(expr.asNumberExpr(), right));
case Less -> new Less(expr.asNumberExpr(), right);
case LessEqual -> new Not(new Greater(expr.asNumberExpr(), right));
default -> throw new IllegalStateException();
};
} }
return expr; return expr;
@ -112,8 +124,12 @@ public class Parser {
while (match(Token.Plus, Token.Minus)) { while (match(Token.Plus, Token.Minus)) {
Token op = previous.token; Token op = previous.token;
Expr<?> right = factor(); NumberExpr right = factor().asNumberExpr();
expr = new MathBiExpr(expr.asNumberExpr(), right.asNumberExpr(), op); expr = switch (op) {
case Plus -> new Plus(expr.asNumberExpr(), right);
case Minus -> new Minus(expr.asNumberExpr(), right);
default -> throw new IllegalStateException();
};
} }
return expr; return expr;
@ -122,10 +138,15 @@ public class Parser {
private Expr<?> factor() { private Expr<?> factor() {
Expr<?> expr = exp(); Expr<?> expr = exp();
while (match(Token.Star, Token.Slash, Token.Percentage, Token.UpArrow)) { while (match(Token.Star, Token.Slash, Token.Percentage)) {
Token op = previous.token; Token op = previous.token;
Expr<?> right = exp(); NumberExpr right = exp().asNumberExpr();
expr = new MathBiExpr(expr.asNumberExpr(), right.asNumberExpr(), op); expr = switch (op) {
case Star -> new Multiply(expr.asNumberExpr(), right);
case Slash -> new Divide(expr.asNumberExpr(), right);
case Percentage -> new Modulo(expr.asNumberExpr(), right);
default -> throw new IllegalStateException();
};
} }
return expr; return expr;
@ -135,9 +156,8 @@ public class Parser {
Expr<?> expr = unary(); Expr<?> expr = unary();
while (match(Token.UpArrow)) { while (match(Token.UpArrow)) {
Token op = previous.token; NumberExpr right = unary().asNumberExpr();
Expr<?> right = unary(); expr = new Power(expr.asNumberExpr(), right);
expr = new MathBiExpr(expr.asNumberExpr(), right.asNumberExpr(), op);
} }
return expr; return expr;
@ -147,7 +167,11 @@ public class Parser {
if (match(Token.Bang, Token.Minus)) { if (match(Token.Bang, Token.Minus)) {
Token op = previous.token; Token op = previous.token;
Expr<?> right = unary(); Expr<?> right = unary();
return op == Token.Bang ? new Not(right.asBoolExpr()) : new Invert(right.asNumberExpr()); return switch (op) {
case Bang -> new Not(right.asBoolExpr());
case Minus -> new Invert(right.asNumberExpr());
default -> throw new IllegalStateException();
};
} }
return call(); return call();
@ -156,28 +180,27 @@ public class Parser {
private Expr<?> call() { private Expr<?> call() {
Expr<?> expr = primary(); Expr<?> expr = primary();
while (true) { while (match(Token.LeftParen, Token.Dot, Token.LeftBracket)) {
if (match(Token.LeftParen)) { expr = switch (previous.token) {
expr = finishCall(expr); case LeftParen -> finishCall(expr);
} case Dot -> {
else if (match(Token.Dot)) { TokenData name = consume(Token.Identifier, "Expected field name after '.'.");
TokenData name = consume(Token.Identifier, "Expected field name after '.'."); yield new Get(expr.asDynamicExpr(), Expr.literal(name.lexeme));
expr = new Get(expr.asDynamicExpr(), Expr.literal(name.lexeme)); }
} case LeftBracket -> {
else if (match(Token.LeftBracket)) { expr = new Get(expr.asDynamicExpr(), expression());
expr = new Get(expr.asDynamicExpr(), expression()); consume(Token.RightBracket, "Expected closing bracket");
consume(Token.RightBracket, "Expected closing bracket"); yield expr;
} }
else { default -> throw new IllegalStateException();
break; };
}
} }
return expr; return expr;
} }
private Expr<?> finishCall(Expr<?> callee) { private Expr<?> finishCall(Expr<?> callee) {
List<Expr.DynamicExpr> args = new ArrayList<>(2); List<DynamicExpr> args = new ArrayList<>(2);
if (!check(Token.RightParen)) { if (!check(Token.RightParen)) {
do { do {
@ -199,7 +222,7 @@ public class Parser {
if (match(Token.LeftParen)) { if (match(Token.LeftParen)) {
Expr<?> expr = expression(); Expr<?> expr = expression();
consume(Token.RightParen, "Expected ')' after expression."); consume(Token.RightParen, "Expected ')' after expression.");
return new Group(expr); return expr;
} }
throw error("Expected expression."); throw error("Expected expression.");

View File

@ -0,0 +1,16 @@
package io.gitlab.jfronny.muscript.compiler.expr;
import io.gitlab.jfronny.muscript.compiler.*;
import io.gitlab.jfronny.muscript.compiler.expr.dynamic.*;
public abstract non-sealed class BoolExpr extends Expr<Boolean> {
@Override
public Type getResultType() {
return Type.Boolean;
}
@Override
public DynamicExpr asDynamicExpr() {
return new DynamicCoerce(this);
}
}

View File

@ -1,31 +0,0 @@
package io.gitlab.jfronny.muscript.compiler.expr;
import io.gitlab.jfronny.muscript.compiler.*;
import io.gitlab.jfronny.muscript.dynamic.*;
public class Compare extends Expr.BoolExpr {
private final NumberExpr left;
private final NumberExpr right;
private final Token comparator;
public Compare(NumberExpr left, NumberExpr right, Token comparator) {
this.left = left;
this.right = right;
this.comparator = comparator;
if (comparator != Token.Greater && comparator != Token.GreaterEqual && comparator != Token.Less && comparator != Token.LessEqual)
throw new IllegalArgumentException("Compare only supports > >= < <= operators");
}
@Override
public Boolean get(Dynamic<?> branch, Dynamic<?> dataRoot) {
double left = this.left.get(branch, dataRoot);
double right = this.right.get(branch, dataRoot);
return switch (comparator) {
case Greater -> left > right;
case GreaterEqual -> left >= right;
case Less -> left < right;
case LessEqual -> left <= right;
default -> throw new IllegalArgumentException();
};
}
}

View File

@ -1,76 +0,0 @@
package io.gitlab.jfronny.muscript.compiler.expr;
import io.gitlab.jfronny.muscript.compiler.*;
import io.gitlab.jfronny.muscript.dynamic.*;
public class Conditional extends Expr {
public final BoolExpr condition;
public final Expr<?> trueExpr;
public final Expr<?> falseExpr;
public Conditional(BoolExpr condition, Expr<?> trueExpr, Expr<?> falseExpr) {
this.condition = condition;
this.trueExpr = trueExpr;
this.falseExpr = falseExpr;
if (trueExpr.getResultType() != falseExpr.getResultType())
throw new IllegalArgumentException("Values used in conditional operator must be of the same type");
}
@Override
public Type getResultType() {
return trueExpr.getResultType();
}
@Override
public Object get(Dynamic branch, Dynamic dataRoot) {
return condition.get(branch, dataRoot) ? trueExpr.get(branch, dataRoot) : falseExpr.get(branch, dataRoot);
}
@Override
public BoolExpr asBoolExpr() {
BoolExpr trueExpr = this.trueExpr.asBoolExpr();
BoolExpr falseExpr = this.falseExpr.asBoolExpr();
return new BoolExpr() {
@Override
public Boolean get(Dynamic<?> branch, Dynamic<?> dataRoot) {
return condition.get(branch, dataRoot) ? trueExpr.get(branch, dataRoot) : falseExpr.get(branch, dataRoot);
}
};
}
@Override
public StringExpr asStringExpr() {
StringExpr trueExpr = this.trueExpr.asStringExpr();
StringExpr falseExpr = this.falseExpr.asStringExpr();
return new StringExpr() {
@Override
public String get(Dynamic<?> branch, Dynamic<?> dataRoot) {
return condition.get(branch, dataRoot) ? trueExpr.get(branch, dataRoot) : falseExpr.get(branch, dataRoot);
}
};
}
@Override
public NumberExpr asNumberExpr() {
NumberExpr trueExpr = this.trueExpr.asNumberExpr();
NumberExpr falseExpr = this.falseExpr.asNumberExpr();
return new NumberExpr() {
@Override
public Double get(Dynamic<?> branch, Dynamic<?> dataRoot) {
return condition.get(branch, dataRoot) ? trueExpr.get(branch, dataRoot) : falseExpr.get(branch, dataRoot);
}
};
}
@Override
public DynamicExpr asDynamicExpr() {
DynamicExpr trueExpr = this.trueExpr.asDynamicExpr();
DynamicExpr falseExpr = this.falseExpr.asDynamicExpr();
return new DynamicExpr() {
@Override
public Dynamic<?> get(Dynamic<?> branch, Dynamic<?> dataRoot) {
return condition.get(branch, dataRoot) ? trueExpr.get(branch, dataRoot) : falseExpr.get(branch, dataRoot);
}
};
}
}

View File

@ -1,42 +1,32 @@
package io.gitlab.jfronny.muscript.compiler.expr; package io.gitlab.jfronny.muscript.compiler.expr;
import io.gitlab.jfronny.muscript.compiler.*; import io.gitlab.jfronny.muscript.compiler.*;
import io.gitlab.jfronny.muscript.compiler.expr.dynamic.unpack.*;
import io.gitlab.jfronny.muscript.dynamic.*; import io.gitlab.jfronny.muscript.dynamic.*;
public class Group extends Expr { public abstract non-sealed class DynamicExpr extends Expr<Dynamic<?>> {
public final Expr expr;
public Group(Expr expr) {
this.expr = expr;
}
@Override @Override
public Type getResultType() { public Type getResultType() {
return expr.getResultType(); return Type.Dynamic;
}
@Override
public Object get(Dynamic branch, Dynamic dataRoot) {
return expr.get(branch, dataRoot);
} }
@Override @Override
public BoolExpr asBoolExpr() { public BoolExpr asBoolExpr() {
return expr.asBoolExpr(); return new BoolUnpack(this);
} }
@Override @Override
public StringExpr asStringExpr() { public StringExpr asStringExpr() {
return expr.asStringExpr(); return new StringUnpack(this);
} }
@Override @Override
public NumberExpr asNumberExpr() { public NumberExpr asNumberExpr() {
return expr.asNumberExpr(); return new NumberUnpack(this);
} }
@Override @Override
public DynamicExpr asDynamicExpr() { public DynamicExpr asDynamicExpr() {
return expr.asDynamicExpr(); return this;
} }
} }

View File

@ -0,0 +1,52 @@
package io.gitlab.jfronny.muscript.compiler.expr;
import io.gitlab.jfronny.muscript.compiler.*;
import io.gitlab.jfronny.muscript.compiler.expr.common.literal.*;
import io.gitlab.jfronny.muscript.compiler.expr.string.*;
import io.gitlab.jfronny.muscript.dynamic.*;
public sealed abstract class Expr<T> permits BoolExpr, DynamicExpr, NullLiteral, NumberExpr, StringExpr {
public abstract Type getResultType();
public abstract T get(Dynamic<?> branch, Dynamic<?> dataRoot);
public T get(Dynamic<?> branch) {
return get(branch, branch);
}
public BoolExpr asBoolExpr() {
if (this instanceof BoolExpr e) return e;
throw new IllegalArgumentException("Expected boolean but is " + getResultType());
}
public StringExpr asStringExpr() {
if (this instanceof StringExpr e) return e;
return new StringCoerce(this);
}
public NumberExpr asNumberExpr() {
if (this instanceof NumberExpr e) return e;
throw new IllegalArgumentException("Expected number but is " + getResultType());
}
public abstract DynamicExpr asDynamicExpr();
public boolean isNull() {
return this instanceof NullLiteral;
}
public static BoolExpr literal(boolean bool) {
return new BoolLiteral(bool);
}
public static StringExpr literal(String string) {
return new StringLiteral(string);
}
public static NumberExpr literal(double number) {
return new NumberLiteral(number);
}
public static Expr<?> literalNull() {
return new NullLiteral();
}
}

View File

@ -1,17 +0,0 @@
package io.gitlab.jfronny.muscript.compiler.expr;
import io.gitlab.jfronny.muscript.compiler.*;
import io.gitlab.jfronny.muscript.dynamic.*;
public class Invert extends Expr.NumberExpr {
private final Expr.NumberExpr inner;
public Invert(Expr.NumberExpr inner) {
this.inner = inner;
}
@Override
public Double get(Dynamic<?> branch, Dynamic<?> dataRoot) {
return -inner.get(branch, dataRoot);
}
}

View File

@ -1,30 +0,0 @@
package io.gitlab.jfronny.muscript.compiler.expr;
import io.gitlab.jfronny.muscript.compiler.*;
import io.gitlab.jfronny.muscript.dynamic.*;
public class LogicBiExpr extends Expr.BoolExpr {
private final Expr.BoolExpr left;
private final Expr.BoolExpr right;
private final Token comparator;
public LogicBiExpr(Expr.BoolExpr left, Expr.BoolExpr right, Token fnc) {
this.left = left;
this.right = right;
this.comparator = fnc;
if (fnc != Token.And && fnc != Token.Or && fnc != Token.UpArrow)
throw new IllegalArgumentException("Logic only supports & | ^ operators");
}
@Override
public Boolean get(Dynamic<?> branch, Dynamic<?> dataRoot) {
boolean left = this.left.get(branch, dataRoot);
boolean right = this.right.get(branch, dataRoot);
return switch (comparator) {
case And -> left & right;
case Or -> left | right;
case UpArrow -> left ^ right;
default -> throw new IllegalArgumentException();
};
}
}

View File

@ -1,33 +0,0 @@
package io.gitlab.jfronny.muscript.compiler.expr;
import io.gitlab.jfronny.muscript.compiler.*;
import io.gitlab.jfronny.muscript.dynamic.*;
public class MathBiExpr extends Expr.NumberExpr {
private final NumberExpr left;
private final NumberExpr right;
private final Token comparator;
public MathBiExpr(NumberExpr left, NumberExpr right, Token fnc) {
this.left = left;
this.right = right;
this.comparator = fnc;
if (fnc != Token.Plus && fnc != Token.Minus && fnc != Token.Star && fnc != Token.Slash && fnc != Token.UpArrow && fnc != Token.Percentage)
throw new IllegalArgumentException("Math only supports + - * / operators");
}
@Override
public Double get(Dynamic<?> branch, Dynamic<?> dataRoot) {
double left = this.left.get(branch, dataRoot);
double right = this.right.get(branch, dataRoot);
return switch (comparator) {
case Plus -> left + right;
case Minus -> left - right;
case Star -> left * right;
case Slash -> left / right;
case UpArrow -> Math.pow(left, right);
case Percentage -> left % right;
default -> throw new IllegalArgumentException();
};
}
}

View File

@ -0,0 +1,22 @@
package io.gitlab.jfronny.muscript.compiler.expr;
import io.gitlab.jfronny.muscript.compiler.*;
import io.gitlab.jfronny.muscript.compiler.expr.common.literal.*;
import io.gitlab.jfronny.muscript.dynamic.*;
public final class NullLiteral extends Expr<Object> {
@Override
public Type getResultType() {
return Type.Dynamic;
}
@Override
public Object get(Dynamic<?> branch, Dynamic<?> dataRoot) {
return null;
}
@Override
public DynamicExpr asDynamicExpr() {
return new DynamicLiteral<>(new DNull());
}
}

View File

@ -0,0 +1,16 @@
package io.gitlab.jfronny.muscript.compiler.expr;
import io.gitlab.jfronny.muscript.compiler.*;
import io.gitlab.jfronny.muscript.compiler.expr.dynamic.*;
public abstract non-sealed class NumberExpr extends Expr<Double> {
@Override
public Type getResultType() {
return Type.Number;
}
@Override
public DynamicExpr asDynamicExpr() {
return new DynamicCoerce(this);
}
}

View File

@ -0,0 +1,16 @@
package io.gitlab.jfronny.muscript.compiler.expr;
import io.gitlab.jfronny.muscript.compiler.*;
import io.gitlab.jfronny.muscript.compiler.expr.dynamic.*;
public abstract non-sealed class StringExpr extends Expr<String> {
@Override
public Type getResultType() {
return Type.String;
}
@Override
public DynamicExpr asDynamicExpr() {
return new DynamicCoerce(this);
}
}

View File

@ -0,0 +1,19 @@
package io.gitlab.jfronny.muscript.compiler.expr.bool;
import io.gitlab.jfronny.muscript.compiler.expr.*;
import io.gitlab.jfronny.muscript.dynamic.*;
public class And extends BoolExpr {
private final BoolExpr left;
private final BoolExpr right;
public And(BoolExpr left, BoolExpr right) {
this.left = left;
this.right = right;
}
@Override
public Boolean get(Dynamic<?> branch, Dynamic<?> dataRoot) {
return left.get(branch, dataRoot) && right.get(branch, dataRoot);
}
}

View File

@ -1,9 +1,9 @@
package io.gitlab.jfronny.muscript.compiler.expr; package io.gitlab.jfronny.muscript.compiler.expr.bool;
import io.gitlab.jfronny.muscript.compiler.*; import io.gitlab.jfronny.muscript.compiler.expr.*;
import io.gitlab.jfronny.muscript.dynamic.*; import io.gitlab.jfronny.muscript.dynamic.*;
public class Not extends Expr.BoolExpr { public class Not extends BoolExpr {
private final BoolExpr inner; private final BoolExpr inner;
public Not(BoolExpr inner) { public Not(BoolExpr inner) {

View File

@ -0,0 +1,19 @@
package io.gitlab.jfronny.muscript.compiler.expr.bool;
import io.gitlab.jfronny.muscript.compiler.expr.*;
import io.gitlab.jfronny.muscript.dynamic.*;
public class Or extends BoolExpr {
private final BoolExpr left;
private final BoolExpr right;
public Or(BoolExpr left, BoolExpr right) {
this.left = left;
this.right = right;
}
@Override
public Boolean get(Dynamic<?> branch, Dynamic<?> dataRoot) {
return left.get(branch, dataRoot) || right.get(branch, dataRoot);
}
}

View File

@ -1,11 +1,11 @@
package io.gitlab.jfronny.muscript.compiler.expr; package io.gitlab.jfronny.muscript.compiler.expr.common;
import io.gitlab.jfronny.muscript.compiler.*; import io.gitlab.jfronny.muscript.compiler.expr.*;
import io.gitlab.jfronny.muscript.dynamic.*; import io.gitlab.jfronny.muscript.dynamic.*;
import java.util.*; import java.util.*;
public class Equal extends Expr.BoolExpr { public class Equal extends BoolExpr {
private final Expr<?> left; private final Expr<?> left;
private final Expr<?> right; private final Expr<?> right;

View File

@ -0,0 +1,23 @@
package io.gitlab.jfronny.muscript.compiler.expr.common.conditional;
import io.gitlab.jfronny.muscript.compiler.expr.*;
import io.gitlab.jfronny.muscript.dynamic.*;
public class BoolConditional extends BoolExpr {
public final BoolExpr condition;
public final BoolExpr trueExpr;
public final BoolExpr falseExpr;
public BoolConditional(BoolExpr condition, BoolExpr trueExpr, BoolExpr falseExpr) {
this.condition = condition;
this.trueExpr = trueExpr;
this.falseExpr = falseExpr;
if (trueExpr.getResultType() != falseExpr.getResultType())
throw new IllegalArgumentException("Values used in conditional operator must be of the same type");
}
@Override
public Boolean get(Dynamic<?> branch, Dynamic<?> dataRoot) {
return condition.get(branch, dataRoot) ? trueExpr.get(branch, dataRoot) : falseExpr.get(branch, dataRoot);
}
}

View File

@ -0,0 +1,23 @@
package io.gitlab.jfronny.muscript.compiler.expr.common.conditional;
import io.gitlab.jfronny.muscript.compiler.expr.*;
import io.gitlab.jfronny.muscript.dynamic.*;
public class DynamicConditional extends DynamicExpr {
public final BoolExpr condition;
public final DynamicExpr trueExpr;
public final DynamicExpr falseExpr;
public DynamicConditional(BoolExpr condition, DynamicExpr trueExpr, DynamicExpr falseExpr) {
this.condition = condition;
this.trueExpr = trueExpr;
this.falseExpr = falseExpr;
if (trueExpr.getResultType() != falseExpr.getResultType())
throw new IllegalArgumentException("Values used in conditional operator must be of the same type");
}
@Override
public Dynamic get(Dynamic<?> branch, Dynamic<?> dataRoot) {
return condition.get(branch, dataRoot) ? trueExpr.get(branch, dataRoot) : falseExpr.get(branch, dataRoot);
}
}

View File

@ -0,0 +1,23 @@
package io.gitlab.jfronny.muscript.compiler.expr.common.conditional;
import io.gitlab.jfronny.muscript.compiler.expr.*;
import io.gitlab.jfronny.muscript.dynamic.*;
public class NumberConditional extends NumberExpr {
public final BoolExpr condition;
public final NumberExpr trueExpr;
public final NumberExpr falseExpr;
public NumberConditional(BoolExpr condition, NumberExpr trueExpr, NumberExpr falseExpr) {
this.condition = condition;
this.trueExpr = trueExpr;
this.falseExpr = falseExpr;
if (trueExpr.getResultType() != falseExpr.getResultType())
throw new IllegalArgumentException("Values used in conditional operator must be of the same type");
}
@Override
public Double get(Dynamic<?> branch, Dynamic<?> dataRoot) {
return condition.get(branch, dataRoot) ? trueExpr.get(branch, dataRoot) : falseExpr.get(branch, dataRoot);
}
}

View File

@ -0,0 +1,23 @@
package io.gitlab.jfronny.muscript.compiler.expr.common.conditional;
import io.gitlab.jfronny.muscript.compiler.expr.*;
import io.gitlab.jfronny.muscript.dynamic.*;
public class StringConditional extends StringExpr {
public final BoolExpr condition;
public final StringExpr trueExpr;
public final StringExpr falseExpr;
public StringConditional(BoolExpr condition, StringExpr trueExpr, StringExpr falseExpr) {
this.condition = condition;
this.trueExpr = trueExpr;
this.falseExpr = falseExpr;
if (trueExpr.getResultType() != falseExpr.getResultType())
throw new IllegalArgumentException("Values used in conditional operator must be of the same type");
}
@Override
public String get(Dynamic<?> branch, Dynamic<?> dataRoot) {
return condition.get(branch, dataRoot) ? trueExpr.get(branch, dataRoot) : falseExpr.get(branch, dataRoot);
}
}

View File

@ -0,0 +1,17 @@
package io.gitlab.jfronny.muscript.compiler.expr.common.literal;
import io.gitlab.jfronny.muscript.compiler.expr.*;
import io.gitlab.jfronny.muscript.dynamic.*;
public final class BoolLiteral extends BoolExpr {
private final boolean value;
public BoolLiteral(boolean value) {
this.value = value;
}
@Override
public Boolean get(Dynamic<?> branch, Dynamic<?> dataRoot) {
return value;
}
}

View File

@ -0,0 +1,17 @@
package io.gitlab.jfronny.muscript.compiler.expr.common.literal;
import io.gitlab.jfronny.muscript.compiler.expr.*;
import io.gitlab.jfronny.muscript.dynamic.*;
public final class DynamicLiteral<T> extends DynamicExpr {
private final Dynamic<T> value;
public DynamicLiteral(Dynamic<T> value) {
this.value = value;
}
@Override
public Dynamic<T> get(Dynamic<?> branch, Dynamic<?> dataRoot) {
return value;
}
}

View File

@ -0,0 +1,17 @@
package io.gitlab.jfronny.muscript.compiler.expr.common.literal;
import io.gitlab.jfronny.muscript.compiler.expr.*;
import io.gitlab.jfronny.muscript.dynamic.*;
public final class NumberLiteral extends NumberExpr {
private final double value;
public NumberLiteral(double value) {
this.value = value;
}
@Override
public Double get(Dynamic<?> branch, Dynamic<?> dataRoot) {
return value;
}
}

View File

@ -0,0 +1,17 @@
package io.gitlab.jfronny.muscript.compiler.expr.common.literal;
import io.gitlab.jfronny.muscript.compiler.expr.*;
import io.gitlab.jfronny.muscript.dynamic.*;
public final class StringLiteral extends StringExpr {
private final String value;
public StringLiteral(String value) {
this.value = value;
}
@Override
public String get(Dynamic<?> branch, Dynamic<?> dataRoot) {
return value;
}
}

View File

@ -1,11 +1,11 @@
package io.gitlab.jfronny.muscript.compiler.expr; package io.gitlab.jfronny.muscript.compiler.expr.dynamic;
import io.gitlab.jfronny.muscript.compiler.*; import io.gitlab.jfronny.muscript.compiler.expr.*;
import io.gitlab.jfronny.muscript.dynamic.*; import io.gitlab.jfronny.muscript.dynamic.*;
import java.util.*; import java.util.*;
public class Call extends Expr.DynamicExpr { public class Call extends DynamicExpr {
private final DynamicExpr left; private final DynamicExpr left;
private final List<DynamicExpr> args; private final List<DynamicExpr> args;

View File

@ -0,0 +1,27 @@
package io.gitlab.jfronny.muscript.compiler.expr.dynamic;
import io.gitlab.jfronny.muscript.compiler.expr.*;
import io.gitlab.jfronny.muscript.dynamic.*;
public class DynamicCoerce extends DynamicExpr {
private final Expr<?> inner;
public DynamicCoerce(Expr<?> inner) {
this.inner = inner;
if (!(inner instanceof DynamicExpr)
&& !(inner instanceof BoolExpr)
&& !(inner instanceof StringExpr)
&& !(inner instanceof NumberExpr)) {
throw new IllegalArgumentException("A DynamicCoerce can only be created with a well-defined expression type");
}
}
@Override
public Dynamic<?> get(Dynamic<?> branch, Dynamic<?> dataRoot) {
if (inner instanceof DynamicExpr e) return e.get(branch, dataRoot);
if (inner instanceof BoolExpr e) return DFinal.of(e.get(branch, dataRoot));
if (inner instanceof StringExpr e) return DFinal.of(e.get(branch, dataRoot));
if (inner instanceof NumberExpr e) return DFinal.of(e.get(branch, dataRoot));
throw new IllegalStateException("The inner expression of DynamicCoerce should never be of undefined type");
}
}

View File

@ -1,9 +1,10 @@
package io.gitlab.jfronny.muscript.compiler.expr; package io.gitlab.jfronny.muscript.compiler.expr.dynamic;
import io.gitlab.jfronny.muscript.compiler.*; import io.gitlab.jfronny.muscript.compiler.*;
import io.gitlab.jfronny.muscript.compiler.expr.*;
import io.gitlab.jfronny.muscript.dynamic.*; import io.gitlab.jfronny.muscript.dynamic.*;
public class Get extends Expr.DynamicExpr { public class Get extends DynamicExpr {
private final DynamicExpr left; private final DynamicExpr left;
private final Expr<?> name; private final Expr<?> name;

View File

@ -1,9 +1,9 @@
package io.gitlab.jfronny.muscript.compiler.expr; package io.gitlab.jfronny.muscript.compiler.expr.dynamic;
import io.gitlab.jfronny.muscript.compiler.*; import io.gitlab.jfronny.muscript.compiler.expr.*;
import io.gitlab.jfronny.muscript.dynamic.*; import io.gitlab.jfronny.muscript.dynamic.*;
public class Variable extends Expr.DynamicExpr { public class Variable extends DynamicExpr {
private final String name; private final String name;
public Variable(String name) { public Variable(String name) {

View File

@ -0,0 +1,17 @@
package io.gitlab.jfronny.muscript.compiler.expr.dynamic.unpack;
import io.gitlab.jfronny.muscript.compiler.expr.*;
import io.gitlab.jfronny.muscript.dynamic.*;
public class BoolUnpack extends BoolExpr {
private final DynamicExpr inner;
public BoolUnpack(DynamicExpr inner) {
this.inner = inner;
}
@Override
public Boolean get(Dynamic<?> branch, Dynamic<?> dataRoot) {
return inner.get(branch, dataRoot).asBool().getValue();
}
}

View File

@ -0,0 +1,17 @@
package io.gitlab.jfronny.muscript.compiler.expr.dynamic.unpack;
import io.gitlab.jfronny.muscript.compiler.expr.*;
import io.gitlab.jfronny.muscript.dynamic.*;
public class NumberUnpack extends NumberExpr {
private final DynamicExpr inner;
public NumberUnpack(DynamicExpr inner) {
this.inner = inner;
}
@Override
public Double get(Dynamic<?> branch, Dynamic<?> dataRoot) {
return inner.get(branch, dataRoot).asNumber().getValue();
}
}

View File

@ -0,0 +1,17 @@
package io.gitlab.jfronny.muscript.compiler.expr.dynamic.unpack;
import io.gitlab.jfronny.muscript.compiler.expr.*;
import io.gitlab.jfronny.muscript.dynamic.*;
public class StringUnpack extends StringExpr {
private final DynamicExpr inner;
public StringUnpack(DynamicExpr inner) {
this.inner = inner;
}
@Override
public String get(Dynamic<?> branch, Dynamic<?> dataRoot) {
return inner.get(branch, dataRoot).asString().getValue();
}
}

View File

@ -0,0 +1,19 @@
package io.gitlab.jfronny.muscript.compiler.expr.number.compare;
import io.gitlab.jfronny.muscript.compiler.expr.*;
import io.gitlab.jfronny.muscript.dynamic.*;
public class Greater extends BoolExpr {
private final NumberExpr left;
private final NumberExpr right;
public Greater(NumberExpr left, NumberExpr right) {
this.left = left;
this.right = right;
}
@Override
public Boolean get(Dynamic<?> branch, Dynamic<?> dataRoot) {
return left.get(branch, dataRoot) > right.get(branch, dataRoot);
}
}

View File

@ -0,0 +1,19 @@
package io.gitlab.jfronny.muscript.compiler.expr.number.compare;
import io.gitlab.jfronny.muscript.compiler.expr.*;
import io.gitlab.jfronny.muscript.dynamic.*;
public class Less extends BoolExpr {
private final NumberExpr left;
private final NumberExpr right;
public Less(NumberExpr left, NumberExpr right) {
this.left = left;
this.right = right;
}
@Override
public Boolean get(Dynamic<?> branch, Dynamic<?> dataRoot) {
return left.get(branch, dataRoot) < right.get(branch, dataRoot);
}
}

View File

@ -0,0 +1,19 @@
package io.gitlab.jfronny.muscript.compiler.expr.number.math;
import io.gitlab.jfronny.muscript.compiler.expr.*;
import io.gitlab.jfronny.muscript.dynamic.*;
public class Divide extends NumberExpr {
private final NumberExpr dividend;
private final NumberExpr divisor;
public Divide(NumberExpr dividend, NumberExpr divisor) {
this.dividend = dividend;
this.divisor = divisor;
}
@Override
public Double get(Dynamic<?> branch, Dynamic<?> dataRoot) {
return dividend.get(branch, dataRoot) / divisor.get(branch, dataRoot);
}
}

View File

@ -0,0 +1,17 @@
package io.gitlab.jfronny.muscript.compiler.expr.number.math;
import io.gitlab.jfronny.muscript.compiler.expr.*;
import io.gitlab.jfronny.muscript.dynamic.*;
public class Invert extends NumberExpr {
private final NumberExpr inner;
public Invert(NumberExpr inner) {
this.inner = inner;
}
@Override
public Double get(Dynamic<?> branch, Dynamic<?> dataRoot) {
return -inner.get(branch, dataRoot);
}
}

View File

@ -0,0 +1,19 @@
package io.gitlab.jfronny.muscript.compiler.expr.number.math;
import io.gitlab.jfronny.muscript.compiler.expr.*;
import io.gitlab.jfronny.muscript.dynamic.*;
public class Minus extends NumberExpr {
private final NumberExpr minuend;
private final NumberExpr subtrahend;
public Minus(NumberExpr minuend, NumberExpr subtrahend) {
this.minuend = minuend;
this.subtrahend = subtrahend;
}
@Override
public Double get(Dynamic<?> branch, Dynamic<?> dataRoot) {
return minuend.get(branch, dataRoot) - subtrahend.get(branch, dataRoot);
}
}

View File

@ -0,0 +1,19 @@
package io.gitlab.jfronny.muscript.compiler.expr.number.math;
import io.gitlab.jfronny.muscript.compiler.expr.*;
import io.gitlab.jfronny.muscript.dynamic.*;
public class Modulo extends NumberExpr {
private final NumberExpr dividend;
private final NumberExpr divisor;
public Modulo(NumberExpr dividend, NumberExpr divisor) {
this.dividend = dividend;
this.divisor = divisor;
}
@Override
public Double get(Dynamic<?> branch, Dynamic<?> dataRoot) {
return dividend.get(branch, dataRoot) % divisor.get(branch, dataRoot);
}
}

View File

@ -0,0 +1,19 @@
package io.gitlab.jfronny.muscript.compiler.expr.number.math;
import io.gitlab.jfronny.muscript.compiler.expr.*;
import io.gitlab.jfronny.muscript.dynamic.*;
public class Multiply extends NumberExpr {
private final NumberExpr multiplier;
private final NumberExpr multiplicand;
public Multiply(NumberExpr multiplier, NumberExpr multiplicand) {
this.multiplier = multiplier;
this.multiplicand = multiplicand;
}
@Override
public Double get(Dynamic<?> branch, Dynamic<?> dataRoot) {
return multiplier.get(branch, dataRoot) * multiplicand.get(branch, dataRoot);
}
}

View File

@ -0,0 +1,19 @@
package io.gitlab.jfronny.muscript.compiler.expr.number.math;
import io.gitlab.jfronny.muscript.compiler.expr.*;
import io.gitlab.jfronny.muscript.dynamic.*;
public class Plus extends NumberExpr {
private final NumberExpr augend;
private final NumberExpr addend;
public Plus(NumberExpr augend, NumberExpr addend) {
this.augend = augend;
this.addend = addend;
}
@Override
public Double get(Dynamic<?> branch, Dynamic<?> dataRoot) {
return augend.get(branch, dataRoot) + addend.get(branch, dataRoot);
}
}

View File

@ -0,0 +1,19 @@
package io.gitlab.jfronny.muscript.compiler.expr.number.math;
import io.gitlab.jfronny.muscript.compiler.expr.*;
import io.gitlab.jfronny.muscript.dynamic.*;
public class Power extends NumberExpr {
private final NumberExpr base;
private final NumberExpr exponent;
public Power(NumberExpr base, NumberExpr exponent) {
this.base = base;
this.exponent = exponent;
}
@Override
public Double get(Dynamic<?> branch, Dynamic<?> dataRoot) {
return Math.pow(base.get(branch, dataRoot), exponent.get(branch, dataRoot));
}
}

View File

@ -1,9 +1,9 @@
package io.gitlab.jfronny.muscript.compiler.expr; package io.gitlab.jfronny.muscript.compiler.expr.string;
import io.gitlab.jfronny.muscript.compiler.*; import io.gitlab.jfronny.muscript.compiler.expr.*;
import io.gitlab.jfronny.muscript.dynamic.*; import io.gitlab.jfronny.muscript.dynamic.*;
public class Concatenate extends Expr.StringExpr { public class Concatenate extends StringExpr {
private final StringExpr left; private final StringExpr left;
private final StringExpr right; private final StringExpr right;

View File

@ -0,0 +1,18 @@
package io.gitlab.jfronny.muscript.compiler.expr.string;
import io.gitlab.jfronny.commons.*;
import io.gitlab.jfronny.muscript.compiler.expr.*;
import io.gitlab.jfronny.muscript.dynamic.*;
public class StringCoerce extends StringExpr {
private final Expr<?> inner;
public StringCoerce(Expr<?> inner) {
this.inner = inner;
}
@Override
public String get(Dynamic<?> branch, Dynamic<?> dataRoot) {
return StringFormatter.toString(inner.get(branch, dataRoot));
}
}

View File

@ -0,0 +1,48 @@
package io.gitlab.jfronny.muscript.compiler.expr.unresolved;
import io.gitlab.jfronny.muscript.compiler.*;
import io.gitlab.jfronny.muscript.compiler.expr.*;
import io.gitlab.jfronny.muscript.compiler.expr.common.conditional.*;
import io.gitlab.jfronny.muscript.dynamic.*;
public class UnresolvedConditional extends DynamicExpr {
private final BoolExpr condition;
private final Expr<?> trueExpr;
private final Expr<?> falseExpr;
public UnresolvedConditional(BoolExpr condition, Expr<?> trueExpr, Expr<?> falseExpr) {
this.condition = condition;
this.trueExpr = trueExpr;
this.falseExpr = falseExpr;
}
@Override
public Type getResultType() {
return trueExpr.getResultType();
}
@Override
public Dynamic get(Dynamic branch, Dynamic dataRoot) {
throw new UnsupportedOperationException("Conditional was kept unresolved. This is not supported!");
}
@Override
public DynamicExpr asDynamicExpr() {
return new DynamicConditional(condition, trueExpr.asDynamicExpr(), falseExpr.asDynamicExpr());
}
@Override
public BoolExpr asBoolExpr() {
return new BoolConditional(condition, trueExpr.asBoolExpr(), falseExpr.asBoolExpr());
}
@Override
public StringExpr asStringExpr() {
return new StringConditional(condition, trueExpr.asStringExpr(), falseExpr.asStringExpr());
}
@Override
public NumberExpr asNumberExpr() {
return new NumberConditional(condition, trueExpr.asNumberExpr(), falseExpr.asNumberExpr());
}
}

View File

@ -1,6 +1,7 @@
package io.gitlab.jfronny.muscript.test; package io.gitlab.jfronny.muscript.test;
import io.gitlab.jfronny.muscript.compiler.*; import io.gitlab.jfronny.muscript.compiler.*;
import io.gitlab.jfronny.muscript.compiler.expr.*;
import io.gitlab.jfronny.muscript.debug.*; import io.gitlab.jfronny.muscript.debug.*;
import io.gitlab.jfronny.muscript.dynamic.*; import io.gitlab.jfronny.muscript.dynamic.*;