simplfy
This commit is contained in:
1 parent
36eccbc2df
commit
d48f78ff7b
5 files changed
+98
-146
No files matched your search
@@ -37,6 +37,14 @@ public class ExpressionException extends RuntimeException implements ResolvedExc
|
|||||||
context = c;
|
context = c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ExpressionException(Context c, Expression e, Tokenizer.Token t, Supplier<String> messageSupplier, List<FunctionValue> stack)
|
||||||
|
{
|
||||||
|
super("Error");
|
||||||
|
this.stack.addAll(stack);
|
||||||
|
lazyStacktrace = messageSupplier;
|
||||||
|
context = c;
|
||||||
|
}
|
||||||
|
|
||||||
private static final Fluff.TriFunction<Expression, Tokenizer.Token, String, List<String>> errorMaker = (expr, /*Nullable*/ token, errmessage) ->
|
private static final Fluff.TriFunction<Expression, Tokenizer.Token, String, List<String>> errorMaker = (expr, /*Nullable*/ token, errmessage) ->
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|||||||
@@ -6,14 +6,15 @@ import carpet.script.Context;
|
|||||||
import carpet.script.Expression;
|
import carpet.script.Expression;
|
||||||
import carpet.script.Tokenizer.Token;
|
import carpet.script.Tokenizer.Token;
|
||||||
import carpet.script.value.FunctionValue;
|
import carpet.script.value.FunctionValue;
|
||||||
|
import carpet.script.value.Value;
|
||||||
|
|
||||||
public class ProcessedThrowStatement extends ExpressionException {
|
public class ProcessedThrowStatement extends ExpressionException {
|
||||||
public final Throwables.Exception exception;
|
public final Throwables thrownExceptionType;
|
||||||
public final String message;
|
public final Value data;
|
||||||
|
|
||||||
public ProcessedThrowStatement(Context c, Expression e, Token token, String message, List<FunctionValue> stack, Throwables.Exception exception) {
|
public ProcessedThrowStatement(Context c, Expression e, Token token, List<FunctionValue> stack, Throwables thrownExceptionType, Value data) {
|
||||||
super(c, e, token, "Unhandled exception: "+message, stack);
|
super(c, e, token, () -> "Unhandled "+thrownExceptionType.getId()+" exception: "+data.getString(), stack);
|
||||||
this.exception = exception;
|
this.thrownExceptionType = thrownExceptionType;
|
||||||
this.message = message;
|
this.data = data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3,35 +3,25 @@ package carpet.script.exception;
|
|||||||
import carpet.script.Context;
|
import carpet.script.Context;
|
||||||
import carpet.script.Expression;
|
import carpet.script.Expression;
|
||||||
import carpet.script.Tokenizer.Token;
|
import carpet.script.Tokenizer.Token;
|
||||||
|
import carpet.script.value.StringValue;
|
||||||
import carpet.script.value.Value;
|
import carpet.script.value.Value;
|
||||||
|
|
||||||
import static carpet.script.exception.Throwables.Exception;
|
|
||||||
|
|
||||||
public class ThrowStatement extends InternalExpressionException
|
public class ThrowStatement extends InternalExpressionException
|
||||||
{
|
{
|
||||||
private final Exception exception;
|
private final Throwables thrownExceptionType;
|
||||||
/**
|
private final Value exceptionData;
|
||||||
* Creates a throw exception from a value.
|
|
||||||
* That value will also be used as the message.<br>
|
|
||||||
* To be used when throwing from Scarpet's {@code throw} function with a single argument
|
|
||||||
* @param value The value to pass
|
|
||||||
*/
|
|
||||||
public ThrowStatement(Value value)
|
|
||||||
{
|
|
||||||
this(value, value, Value.NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a throw exception from a value, and assigns it a specified message.
|
* Creates a throw exception from a value, and assigns it a specified message.
|
||||||
* <p>To be used when throwing from Scarpet's {@code throw} function
|
* <p>To be used when throwing from Scarpet's {@code throw} function
|
||||||
* @param message The message to display if uncaught
|
* @param data The value to pass
|
||||||
* @param value The value to pass
|
* @param type Exception type
|
||||||
* @param parent A parent's name
|
|
||||||
*/
|
*/
|
||||||
public ThrowStatement(Value message, Value value, Value parent)
|
public ThrowStatement(Value data, Throwables type)
|
||||||
{
|
{
|
||||||
super(message.getString());
|
super(type.getId());
|
||||||
exception = new Exception(value, parent);
|
exceptionData = data;
|
||||||
|
thrownExceptionType = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -39,20 +29,19 @@ public class ThrowStatement extends InternalExpressionException
|
|||||||
* Conveniently creates a value from the {@code value} String
|
* Conveniently creates a value from the {@code value} String
|
||||||
* to be used easily in Java code
|
* to be used easily in Java code
|
||||||
* @param message The message to display when not handled
|
* @param message The message to display when not handled
|
||||||
* @param exception An {@link Exception} containing the inheritance data
|
* @param thrownExceptionType An {@link Throwables} containing the inheritance data
|
||||||
* for this exception. When throwing from Java,
|
* for this exception. When throwing from Java,
|
||||||
* those exceptions should be pre-registered and used
|
* those exceptions should be pre-registered.
|
||||||
* instead of creating new ones each time.
|
|
||||||
* @param parent This exception's data
|
|
||||||
*/
|
*/
|
||||||
public ThrowStatement(String message, Exception exception)
|
public ThrowStatement(String message, Throwables thrownExceptionType)
|
||||||
{
|
{
|
||||||
super(message);
|
super(message);
|
||||||
this.exception = exception;
|
this.exceptionData = StringValue.of(message);
|
||||||
|
this.thrownExceptionType = thrownExceptionType;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ExpressionException promote(Context c, Expression e, Token token) {
|
public ExpressionException promote(Context c, Expression e, Token token) {
|
||||||
return new ProcessedThrowStatement(c, e, token, getMessage(), stack, exception);
|
return new ProcessedThrowStatement(c, e, token, stack, thrownExceptionType, exceptionData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,129 +1,98 @@
|
|||||||
package carpet.script.exception;
|
package carpet.script.exception;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
import carpet.script.value.NullValue;
|
|
||||||
import carpet.script.value.StringValue;
|
|
||||||
import carpet.script.value.Value;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class contains default Scarpet catchable exception's ids, as well as their inheritance and
|
* This class contains default Scarpet catchable types, as well as their inheritance and
|
||||||
* methods to check whether filters are compatible with those.
|
* methods to check whether filters are compatible with those.
|
||||||
*
|
|
||||||
* Exceptions here cannot be thrown as an actual {@link Throwable}, they are just part of the metadata for
|
|
||||||
* {@link ThrowStatement} and {@link ProcessedThrowStatement}
|
|
||||||
*/
|
*/
|
||||||
public class Throwables {
|
public class Throwables {
|
||||||
protected static final Map<Value, Exception> byValue = new HashMap<>();
|
private final String id;
|
||||||
public static final Exception EXCEPTION = register("exception", null);
|
private final Throwables parent;
|
||||||
public static final Exception VALUE_EXCEPTION = register("value_exception", EXCEPTION);
|
|
||||||
public static final Exception UNKNOWN_ITEM = register("unknown_item", VALUE_EXCEPTION);
|
|
||||||
public static final Exception UNKNOWN_BLOCK = register("unknown_block", VALUE_EXCEPTION);
|
|
||||||
public static final Exception UNKNOWN_BIOME = register("unknown_biome", VALUE_EXCEPTION);
|
|
||||||
public static final Exception UNKNOWN_SOUND = register("unknown_sound", VALUE_EXCEPTION);
|
|
||||||
public static final Exception UNKNOWN_PARTICLE = register("unknown_particle", VALUE_EXCEPTION);
|
|
||||||
public static final Exception UNKNOWN_POI_TYPE = register("unknown_poi_type", VALUE_EXCEPTION);
|
|
||||||
public static final Exception UNKNOWN_DIMENSION = register("unknown_dimension", VALUE_EXCEPTION);
|
|
||||||
public static final Exception UNKNOWN_STRUCTURE = register("unknown_structure", VALUE_EXCEPTION);
|
|
||||||
public static final Exception UNKNOWN_CRITERION = register("unknown_criterion", VALUE_EXCEPTION);
|
|
||||||
public static final Exception FILE_READ_EXCEPTION = register("file_read_exception", EXCEPTION);
|
|
||||||
public static final Exception NBT_READ = register("nbt_read_exception", FILE_READ_EXCEPTION);
|
|
||||||
public static final Exception JSON_READ = register("json_read_exception", FILE_READ_EXCEPTION);
|
|
||||||
public static final Exception USER_DEFINED = register("user_defined_exception", EXCEPTION);
|
|
||||||
protected static final Exception ERROR = register("error", null);
|
|
||||||
|
|
||||||
private Throwables() {}
|
private static final Map<String, Throwables> byValue = new HashMap<>();
|
||||||
|
private static final Map<String, Set<Throwables>> handles = new HashMap<>();
|
||||||
|
|
||||||
|
public static final Throwables THROWN_EXCEPTION_TYPE = register("exception", null);
|
||||||
|
public static final Throwables VALUE_EXCEPTION = register("value_exception", THROWN_EXCEPTION_TYPE);
|
||||||
|
public static final Throwables UNKNOWN_ITEM = register("unknown_item", VALUE_EXCEPTION);
|
||||||
|
public static final Throwables UNKNOWN_BLOCK = register("unknown_block", VALUE_EXCEPTION);
|
||||||
|
public static final Throwables UNKNOWN_BIOME = register("unknown_biome", VALUE_EXCEPTION);
|
||||||
|
public static final Throwables UNKNOWN_SOUND = register("unknown_sound", VALUE_EXCEPTION);
|
||||||
|
public static final Throwables UNKNOWN_PARTICLE = register("unknown_particle", VALUE_EXCEPTION);
|
||||||
|
public static final Throwables UNKNOWN_POI_TYPE = register("unknown_poi_type", VALUE_EXCEPTION);
|
||||||
|
public static final Throwables UNKNOWN_DIMENSION = register("unknown_dimension", VALUE_EXCEPTION);
|
||||||
|
public static final Throwables UNKNOWN_STRUCTURE = register("unknown_structure", VALUE_EXCEPTION);
|
||||||
|
public static final Throwables UNKNOWN_CRITERION = register("unknown_criterion", VALUE_EXCEPTION);
|
||||||
|
public static final Throwables FILE_READ_EXCEPTION = register("file_read_exception", THROWN_EXCEPTION_TYPE);
|
||||||
|
public static final Throwables NBT_READ = register("nbt_read_exception", FILE_READ_EXCEPTION);
|
||||||
|
public static final Throwables JSON_READ = register("json_read_exception", FILE_READ_EXCEPTION);
|
||||||
|
public static final Throwables USER_DEFINED = register("user_defined_exception", THROWN_EXCEPTION_TYPE);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an exception and registers it to be used as parent for
|
* Creates an exception and registers it to be used as parent for
|
||||||
* user defined exceptions in Scarpet's throw function.
|
* user defined exceptions in Scarpet's throw function.
|
||||||
* <p>Scarpet exceptions should, in general, have a top-level parent being {@link Throwables#EXCEPTION}
|
* <p>Scarpet exceptions should have a top-level parent being {@link Throwables#THROWN_EXCEPTION_TYPE}
|
||||||
* @param value The value for the exception as a {@link String}. Will be converted into a {@link StringValue}
|
* @param id The value for the exception as a {@link String}.
|
||||||
* @param parent The parent of the exception being created, or <code>null</code> if top-level
|
* @param parent The parent of the exception being created, or <code>null</code> if top-level
|
||||||
* @return The created exception
|
* @return The created exception
|
||||||
*/
|
*/
|
||||||
public static Exception register(String value, Exception parent)
|
public static Throwables register(String id, Throwables parent)
|
||||||
{
|
{
|
||||||
Exception exc = new Exception(value, parent);
|
Throwables exc = new Throwables(id, parent);
|
||||||
byValue.put(exc.getValue(), exc);
|
byValue.put(id, exc);
|
||||||
return exc;
|
Set<Throwables> itHandles = new HashSet<>();
|
||||||
|
itHandles.add(exc);
|
||||||
|
while (parent!=null)
|
||||||
|
{
|
||||||
|
handles.get(parent.id).add(exc);
|
||||||
|
parent = parent.parent;
|
||||||
}
|
}
|
||||||
|
handles.put(id, itHandles);
|
||||||
/**
|
return exc;
|
||||||
* The data of a {@link ThrowStatement} exception. Supports creating with inheritance and
|
|
||||||
* checking whether a filter is compatible with them.
|
|
||||||
*/
|
|
||||||
public static class Exception {
|
|
||||||
private final Value value;
|
|
||||||
private final Exception parent;
|
|
||||||
private final boolean isError;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new exception, with an optional parent.
|
|
||||||
* <p>To be used in Scarpet's throw command
|
|
||||||
* <p>Parent will default to {@link Throwables#USER_DEFINED} if provided
|
|
||||||
* parentValue meets Value#isNull, else it will create a new {@link Exception},
|
|
||||||
* with its parent being {@link Throwables#USER_DEFINED}.
|
|
||||||
* <p>If passed parent matches {@link Throwables#ERROR}, it will create an error
|
|
||||||
* exception, which cannot be caught.
|
|
||||||
* @param value The {@link Value} of the exception
|
|
||||||
* @param parentValue An optional {@link Value} matching the name of a parent exception.
|
|
||||||
* <br>Accepts a {@link NullValue}, but not a {@code null}
|
|
||||||
*/
|
|
||||||
public Exception(Value value, Value parentValue)
|
|
||||||
{
|
|
||||||
if (byValue.containsKey(value))
|
|
||||||
throw new InternalExpressionException("Exception value can't be the same as existing exception. Use it as parent instead");
|
|
||||||
this.value = value;
|
|
||||||
if (!parentValue.isNull())
|
|
||||||
{
|
|
||||||
Exception possibleParent = byValue.get(parentValue);
|
|
||||||
parent = possibleParent == null ? new Exception(parentValue, Value.NULL) : possibleParent;
|
|
||||||
} else
|
|
||||||
parent = USER_DEFINED;
|
|
||||||
isError = this.parent == ERROR;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new exception.
|
* Creates a new exception.
|
||||||
* <p>Not suitable for creating exceptions that can't be caught.
|
* <p>Not suitable for creating exceptions that can't be caught.
|
||||||
* Use an {@link InternalExpressionException} for that
|
* Use an {@link InternalExpressionException} for that
|
||||||
* @param value The exception's value as a {@link String}
|
* @param id The exception's value as a {@link String}
|
||||||
* @param parent The parent exception, or <code>null</code> if no parent is available
|
|
||||||
*/
|
*/
|
||||||
protected Exception(String value, Exception parent)
|
protected Throwables(String id, Throwables parent)
|
||||||
{
|
{
|
||||||
this.value = StringValue.of(value);
|
this.id = id;
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
this.isError = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Throwables getTypeForException(String type)
|
||||||
|
{
|
||||||
|
Throwables properType = byValue.get(type);
|
||||||
|
if (properType == null) throw new InternalExpressionException("Unknown exception type: "+type);
|
||||||
|
return properType;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks whether the given filter matches an instance of this exception, by checking equality
|
* Checks whether the given filter matches an instance of this exception, by checking equality
|
||||||
* with itself and possible parents.
|
* with itself and possible parents.
|
||||||
* @param filter The {@link Value} to check against
|
* @param filter The type to check against
|
||||||
* @return Whether or not the given value matches this exception's hierarchy
|
* @return Whether or not the given value matches this exception's hierarchy
|
||||||
*/
|
*/
|
||||||
public boolean isInstance(Value filter) {
|
public boolean isRelevantFor(String filter)
|
||||||
return getValue().equals(filter) || (parent != null && parent.isInstance(filter));
|
{
|
||||||
|
Set<Throwables> relevantSet = handles.get(filter);
|
||||||
|
if (relevantSet == null) throw new InternalExpressionException("Unknown exception type: "+filter);
|
||||||
|
return relevantSet.contains(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the {@link Value} provided when creating this exception
|
* Returns the throwable type
|
||||||
* @return The {@link Value} of this exception
|
* @return The type of this exception
|
||||||
*/
|
*/
|
||||||
public Value getValue() {
|
public String getId() {
|
||||||
return value;
|
return id;
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns whether this exception has been defined as an error.
|
|
||||||
* <p> Error exceptions cannot be caught in Scarpet
|
|
||||||
* @return Whether this exception has been defined as an error
|
|
||||||
*/
|
|
||||||
public boolean isError() {
|
|
||||||
return isError;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -8,7 +8,6 @@ import carpet.script.exception.InternalExpressionException;
|
|||||||
import carpet.script.exception.ProcessedThrowStatement;
|
import carpet.script.exception.ProcessedThrowStatement;
|
||||||
import carpet.script.exception.ThrowStatement;
|
import carpet.script.exception.ThrowStatement;
|
||||||
import carpet.script.exception.Throwables;
|
import carpet.script.exception.Throwables;
|
||||||
import carpet.script.value.StringValue;
|
|
||||||
import carpet.script.value.Value;
|
import carpet.script.value.Value;
|
||||||
|
|
||||||
public class ControlFlow {
|
public class ControlFlow {
|
||||||
@@ -50,15 +49,13 @@ public class ControlFlow {
|
|||||||
switch (lv.size())
|
switch (lv.size())
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
throw new ThrowStatement(new StringValue("No further information"), Value.NULL, Value.NULL);
|
throw new ThrowStatement(Value.NULL, Throwables.USER_DEFINED);
|
||||||
case 1:
|
case 1:
|
||||||
throw new ThrowStatement(lv.get(0).evalValue(c));
|
throw new ThrowStatement(lv.get(0).evalValue(c), Throwables.USER_DEFINED );
|
||||||
case 2:
|
case 2:
|
||||||
throw new ThrowStatement(lv.get(1).evalValue(c), lv.get(0).evalValue(c), Value.NULL);
|
throw new ThrowStatement(lv.get(1).evalValue(c), Throwables.getTypeForException(lv.get(0).evalValue(c).getString()));
|
||||||
case 3:
|
|
||||||
throw new ThrowStatement(lv.get(1).evalValue(c), lv.get(0).evalValue(c), lv.get(2).evalValue(c));
|
|
||||||
default:
|
default:
|
||||||
throw new InternalExpressionException("throw() can't accept more than 3 parameters");
|
throw new InternalExpressionException("throw() can't accept more than 2 parameters");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -73,55 +70,43 @@ public class ControlFlow {
|
|||||||
}
|
}
|
||||||
catch (ProcessedThrowStatement ret)
|
catch (ProcessedThrowStatement ret)
|
||||||
{
|
{
|
||||||
if (ret.exception.isError())
|
|
||||||
throw ret;
|
|
||||||
if (lv.size() == 1)
|
if (lv.size() == 1)
|
||||||
{
|
{
|
||||||
if (!ret.exception.isInstance(Throwables.USER_DEFINED.getValue()))
|
if (ret.thrownExceptionType != Throwables.USER_DEFINED)
|
||||||
throw ret;
|
throw ret;
|
||||||
return (c_, t_) -> Value.NULL;
|
return (c_, t_) -> Value.NULL;
|
||||||
}
|
}
|
||||||
if (lv.size() == 0 || lv.size() % 2 == 0)
|
if (lv.size() > 3 && lv.size() % 2 == 0)
|
||||||
{
|
{
|
||||||
throw new InternalExpressionException("Try-catch block needs the code to run, and either a catch_expr or a number of pairs of filters and catch_expr");
|
throw new InternalExpressionException("Try-catch block needs the code to run, and either a catch expression for user thrown exceptions, or a number of pairs of filters and catch expressions");
|
||||||
}
|
}
|
||||||
|
|
||||||
Value val = null; // This is always assigned at some point, just the compiler doesn't know
|
Value val = null; // This is always assigned at some point, just the compiler doesn't know
|
||||||
|
|
||||||
LazyValue __ = c.getVariable("_");
|
LazyValue __ = c.getVariable("_");
|
||||||
c.setVariable("_", (__c, __t) -> ret.exception.getValue().reboundedTo("_"));
|
c.setVariable("_", (__c, __t) -> ret.data.reboundedTo("_"));
|
||||||
LazyValue __msg = c.getVariable("_msg");
|
|
||||||
c.setVariable("_msg", (__c, __t) -> StringValue.of(ret.message).reboundedTo("_msg"));
|
|
||||||
|
|
||||||
boolean handled;
|
|
||||||
if (lv.size() == 2)
|
if (lv.size() == 2)
|
||||||
{
|
{
|
||||||
if (!ret.exception.isInstance(Throwables.USER_DEFINED.getValue()))
|
if (ret.thrownExceptionType == Throwables.USER_DEFINED)
|
||||||
handled = false;
|
|
||||||
else {
|
|
||||||
val = lv.get(1).evalValue(c, t);
|
val = lv.get(1).evalValue(c, t);
|
||||||
handled = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int pointer = 1;
|
int pointer = 1;
|
||||||
handled = false;
|
|
||||||
while (pointer < lv.size() -1)
|
while (pointer < lv.size() -1)
|
||||||
{
|
{
|
||||||
if (ret.exception.isInstance(lv.get(pointer).evalValue(c)))
|
if (ret.thrownExceptionType.isRelevantFor(lv.get(pointer).evalValue(c).getString()))
|
||||||
{
|
{
|
||||||
val = lv.get(pointer + 1).evalValue(c, t);
|
val = lv.get(pointer + 1).evalValue(c, t);
|
||||||
handled = true;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
pointer += 2;
|
pointer += 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
c.setVariable("_", __);
|
c.setVariable("_", __);
|
||||||
c.setVariable("_msg", __msg);
|
|
||||||
|
|
||||||
if (!handled)
|
if (val == null) // not handled
|
||||||
{
|
{
|
||||||
throw ret;
|
throw ret;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user