Add exception hierarchy

This commit is contained in:
altrisi committed 2021-02-21 00:57:37 +01:00
1 parent a155494d11
commit 86dabe0080
13 files changed
+216 -74

No files matched your search

@@ -6,15 +6,14 @@ import carpet.script.Context;
import carpet.script.Expression;
import carpet.script.Tokenizer.Token;
import carpet.script.value.FunctionValue;
import carpet.script.value.Value;
public class ProcessedThrowStatement extends ExpressionException {
public final Value exceptionName;
public final Throwables.Exception exception;
public final String message;
public ProcessedThrowStatement(Context c, Expression e, Token token, String message, List<FunctionValue> stack, Value exceptionName) {
public ProcessedThrowStatement(Context c, Expression e, Token token, String message, List<FunctionValue> stack, Throwables.Exception exception) {
super(c, e, token, "Unhandled exception: "+message, stack);
this.exceptionName = exceptionName;
this.exception = exception;
this.message = message;
}
}
@@ -3,47 +3,35 @@ package carpet.script.exception;
import carpet.script.Context;
import carpet.script.Expression;
import carpet.script.Tokenizer.Token;
import carpet.script.value.StringValue;
import carpet.script.value.Value;
import static carpet.script.exception.Throwables.Exception;
public class ThrowStatement extends InternalExpressionException
{
public static final String UNKNOWN_ITEM = "unknown_item";
public static final String UNKNOWN_BLOCK = "unknown_block";
public static final String UNKNOWN_BIOME = "unknown_biome";
public static final String UNKNOWN_SOUND = "unknown_sound";
public static final String UNKNOWN_PARTICLE = "unknown_particle";
public static final String UNKNOWN_POI_TYPE = "unknown_poi_type";
public static final String UNKNOWN_DIMENSION = "unknown_dimension";
public static final String UNKNOWN_STRUCTURE = "unknown_structure";
public static final String UNKNOWN_CRITERION = "unknown_criterion";
public static final String NBT_READ_EXCEPTION = "nbt_read_exception";
public static final String JSON_READ_EXCEPTION = "json_read_exception";
public final Value retval;
private final Exception exception;
/**
* Creates a throw exception from a value.
* That value will also be used as the message.<br>
* To use when throwing from Scarpet's {@code throw}
* 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)
{
super(value.getString());
retval = value;
this(value, value, Value.NULL);
}
/**
* Creates a throw exception from a value, and
* assigns it a specified message.<br>
* To use when throwing from Scarpet's {@code throw}
* function
* 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
* @param message The message to display if uncaught
* @param value The value to pass
* @param parent A parent's name
*/
public ThrowStatement(String message, Value value)
public ThrowStatement(Value message, Value value, Value parent)
{
super(message);
retval = value;
super(message.getString());
exception = new Exception(value, parent);
}
/**
@@ -54,15 +42,16 @@ public class ThrowStatement extends InternalExpressionException
* @param value A String that will be converted
* to a value to pass to {@code catch}
* blocks
* @param parent This exception's data
*/
public ThrowStatement(String message, String value)
public ThrowStatement(String message, Exception exception)
{
super(message);
retval = new StringValue(value);
this.exception = exception;
}
@Override
public ExpressionException promote(Context c, Expression e, Token token) {
return new ProcessedThrowStatement(c, e, token, getMessage(), stack, retval);
return new ProcessedThrowStatement(c, e, token, getMessage(), stack, exception);
}
}
@@ -0,0 +1,127 @@
package carpet.script.exception;
import java.util.HashMap;
import java.util.Map;
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
* 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}
*/
public class Throwables {
private static final Map<Value, Exception> byValue = new HashMap<>();
public static final Exception EXCEPTION = register("exception", null);
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() {}
/**
* Creates an exception and registers it to be used as parent for
* user defined exceptions in Scarpet's throw function.
* <p>Scarpet exceptions should, in general, have a top-level parent being {@link Throwables#EXCEPTION}
* @param name The name for the exception. Will be converted into a {@link StringValue}
* @param parent The parent of the exception being created, or <code>null</code> if top-level
* @return The created exception
*/
protected static Exception register(String value, Exception parent)
{
Exception exc = new Exception(value, parent);
byValue.put(exc.getValue(), exc);
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}.
* @param name The name/id of the exception
* @param parentValue An optional Value matching the name of a parent exception.
* <br>Accepts a {@link NullValue}, but not a <code>null</code>
*/
public Exception(Value value, Value parentValue)
{
if (byValue.containsKey(value))
throw new InternalExpressionException("Exception id 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.
* <p>Not suitable for creating exceptions that can't be caught.
* Use an {@link InternalExpressionException} for that
* @param name The exception's name/id
* @param parent The parent exception, or <code>null</code> if no parent is available
*/
protected Exception(String value, Exception parent)
{
this.value = StringValue.of(value);
this.parent = parent;
this.isError = false;
}
/**
* Checks whether the given filter matches an instance of this exception, including checking equality
* with itself and possible parents.
* @param filter The value to check against
* @return Whether or not the given value matches this exception's hierarchy
*/
public boolean isInstance(Value filter) {
return getValue().equals(filter) || (parent != null && parent.isInstance(filter));
}
/**
* Returns the {@link Value} provided when creating this exception
* @return The {@link Value} of this exception
*/
public Value getValue() {
return value;
}
/**
* 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;
}
}
}