96 lines
5.6 KiB
Java
96 lines
5.6 KiB
Java
package io.gitlab.jfronny.muscript.ast.context;
|
|
|
|
import io.gitlab.jfronny.commons.StringFormatter;
|
|
import io.gitlab.jfronny.muscript.ast.*;
|
|
import io.gitlab.jfronny.muscript.ast.bool.BoolAssign;
|
|
import io.gitlab.jfronny.muscript.ast.bool.BoolConditional;
|
|
import io.gitlab.jfronny.muscript.ast.bool.BoolLiteral;
|
|
import io.gitlab.jfronny.muscript.ast.bool.BoolUnpack;
|
|
import io.gitlab.jfronny.muscript.ast.dynamic.*;
|
|
import io.gitlab.jfronny.muscript.ast.number.NumberAssign;
|
|
import io.gitlab.jfronny.muscript.ast.number.NumberConditional;
|
|
import io.gitlab.jfronny.muscript.ast.number.NumberLiteral;
|
|
import io.gitlab.jfronny.muscript.ast.number.NumberUnpack;
|
|
import io.gitlab.jfronny.muscript.ast.string.*;
|
|
|
|
import java.util.Set;
|
|
|
|
public class ExprUtils {
|
|
public static DynamicExpr asDynamic(Expr expression) {
|
|
expression = unpack(expression);
|
|
return expression instanceof DynamicExpr dynamic ? dynamic : new DynamicCoerce(expression);
|
|
}
|
|
|
|
public static BoolExpr asBool(Expr expression) {
|
|
return switch (unpack(expression)) {
|
|
case BoolExpr bool -> bool;
|
|
case DynamicConditional(var location, var condition, var ifTrue, var ifFalse) -> new BoolConditional(location, condition, asBool(ifTrue), asBool(ifFalse));
|
|
case DynamicAssign(var location, var left, var right) -> new BoolAssign(location, left, asBool(right));
|
|
case DynamicExpr dynamic -> new BoolUnpack(dynamic);
|
|
case NullLiteral nl -> throw new TypeMismatchException("Expected boolean expression but got null");
|
|
case StringExpr string -> throw new TypeMismatchException("Expected boolean expression but got string");
|
|
case NumberExpr number -> throw new TypeMismatchException("Expected boolean expression but got number");
|
|
};
|
|
}
|
|
|
|
public static NumberExpr asNumber(Expr expression) {
|
|
return switch (unpack(expression)) {
|
|
case NumberExpr number -> number;
|
|
case DynamicConditional(var location, var condition, var ifTrue, var ifFalse) -> new NumberConditional(location, condition, asNumber(ifTrue), asNumber(ifFalse));
|
|
case DynamicAssign(var location, var left, var right) -> new NumberAssign(location, left, asNumber(right));
|
|
case DynamicExpr dynamic -> new NumberUnpack(dynamic);
|
|
case NullLiteral nl -> throw new TypeMismatchException("Expected number expression but got null");
|
|
case StringExpr string -> throw new TypeMismatchException("Expected number expression but got string");
|
|
case BoolExpr bool -> throw new TypeMismatchException("Expected number expression but got boolean");
|
|
};
|
|
}
|
|
|
|
public static StringExpr asString(Expr expression) {
|
|
return switch (unpack(expression)) {
|
|
case StringExpr string -> string;
|
|
case NumberLiteral number -> new StringLiteral(expression.location(), StringFormatter.toStringPrecise(number.value()));
|
|
case BoolLiteral bool -> new StringLiteral(expression.location(), bool.value() ? "true" : "false");
|
|
case NullLiteral nl -> new StringLiteral(expression.location(), "null");
|
|
case DynamicConditional(var location, var condition, var ifTrue, var ifFalse) -> new StringConditional(location, condition, asString(ifTrue), asString(ifFalse));
|
|
case BoolConditional(var location, var condition, var ifTrue, var ifFalse) -> new StringConditional(location, condition, asString(ifTrue), asString(ifFalse));
|
|
case NumberConditional(var location, var condition, var ifTrue, var ifFalse) -> new StringConditional(location, condition, asString(ifTrue), asString(ifFalse));
|
|
case DynamicAssign(var location, var left, var right) -> new StringAssign(location, left, asString(right));
|
|
case DynamicExpr dynamic -> new StringUnpack(dynamic);
|
|
default -> new StringCoerce(expression);
|
|
};
|
|
}
|
|
|
|
public static Expr unpack(Expr expression) {
|
|
return switch (expression) {
|
|
case null -> throw new NullPointerException();
|
|
case BoolUnpack(var inner) -> unpack(inner);
|
|
case NumberUnpack(var inner) -> unpack(inner);
|
|
case StringUnpack(var inner) -> unpack(inner);
|
|
case DynamicCoerce(var inner) -> unpack(inner);
|
|
case StringCoerce(var inner) -> unpack(inner);
|
|
default -> expression;
|
|
};
|
|
}
|
|
|
|
private static final Set<String> allowedVariables = Set.of("date", "time", "enum", "listOf");
|
|
public static boolean isDirect(Expr expr) {
|
|
return switch (expr) {
|
|
case NullLiteral ignored -> true;
|
|
case StringLiteral ignored -> true;
|
|
case NumberLiteral ignored -> true;
|
|
case BoolLiteral ignored -> true;
|
|
case DynamicLiteral(var location, var value) -> value.isDirect();
|
|
case DynamicCoerce(var inner) -> isDirect(inner);
|
|
case ObjectLiteral(var location, var content) -> content.values().stream().allMatch(ExprUtils::isDirect);
|
|
case Concatenate(var location, var left, var right) -> isDirect(left) && isDirect(right);
|
|
case BoolUnpack(var inner) -> isDirect(inner);
|
|
case NumberUnpack(var inner) -> isDirect(inner);
|
|
case StringUnpack(var inner) -> isDirect(inner);
|
|
case Bind(var location, var callable, var parameter) -> isDirect(callable) && isDirect(parameter);
|
|
case Call(var location, var left, var args) -> isDirect(left) && args.stream().allMatch(a -> !a.variadic() && isDirect(a.value()));
|
|
case Variable(var location, var name) -> allowedVariables.contains(name);
|
|
default -> false;
|
|
};
|
|
}
|
|
}
|