Add multi-catch to try block
This commit is contained in:
2 files changed
+27
-8
No files matched your search
@@ -234,13 +234,17 @@ returns everywhere, but it would often lead to a messy code.
|
|||||||
|
|
||||||
It terminates entire program passing `expr` as the result of the program execution, or null if omitted.
|
It terminates entire program passing `expr` as the result of the program execution, or null if omitted.
|
||||||
|
|
||||||
### `try(expr, id_filter?, catch_expr(_, _msg)?)`
|
### `try(expr, id_filter?, catch_expr(_, _msg)?, id_filter2?, catch_expr2(_, _msg), ...)`
|
||||||
|
|
||||||
`try` function evaluates expression, and continues further unless an exception is thrown anywhere inside `expr`,
|
`try` function evaluates expression, and continues further unless an exception is thrown anywhere inside `expr`,
|
||||||
it being produced by `throw` or a catchable exception being thrown by Carpet. In that case the `catch_expr` is evaluated with
|
it being produced by `throw` or a catchable exception being thrown by Carpet. In that case the `catch_expr` is evaluated with
|
||||||
`_` set to the id of the exception and `_msg` set to the exception message. If an `id_filter` is present, only exceptions
|
`_` set to the id of the exception and `_msg` set to the exception message. If an `id_filter` is present, only exceptions
|
||||||
with an id equal to that value will be caught, and any other exception will continue up the stack. It is recommended to filter
|
with an id equal to that value will be caught, and any other exception will continue up the stack. You can specify multiple filters
|
||||||
the exceptions to catch to be able to distinguish from an exception that is known that may happen from one that shouldn't.
|
and their respective `catch_expr` to be able to catch different exceptions within the same code. When an exception occurs, the script
|
||||||
|
will try to find an equality with every provided filter in order. Therefore, even if the caught exception matches multiple filters, only
|
||||||
|
the first matching block will be executed. It is recommended to filter the exceptions to catch to be able to distinguish from an exception
|
||||||
|
that is known that may happen from one that shouldn't.
|
||||||
|
|
||||||
This mechanic accepts skipping catch expression - then try returns `null`. This mechanism allows to terminate large
|
This mechanic accepts skipping catch expression - then try returns `null`. This mechanism allows to terminate large
|
||||||
portion of a convoluted call stack and continue program execution.
|
portion of a convoluted call stack and continue program execution.
|
||||||
|
|
||||||
|
|||||||
@@ -76,20 +76,34 @@ public class ControlFlow {
|
|||||||
throw ret;
|
throw ret;
|
||||||
if (lv.size() == 1)
|
if (lv.size() == 1)
|
||||||
return (c_, t_) -> Value.NULL;
|
return (c_, t_) -> Value.NULL;
|
||||||
|
// This is outside since it is also used in try(expr,catch_expr).
|
||||||
LazyValue __ = c.getVariable("_");
|
LazyValue __ = c.getVariable("_");
|
||||||
c.setVariable("_", (__c, __t) -> ret.exception.getValue().reboundedTo("_"));
|
c.setVariable("_", (__c, __t) -> ret.exception.getValue().reboundedTo("_"));
|
||||||
LazyValue __msg = c.getVariable("_msg");
|
LazyValue __msg = c.getVariable("_msg");
|
||||||
c.setVariable("_msg", (__c, __t) -> StringValue.of(ret.message).reboundedTo("_msg"));
|
c.setVariable("_msg", (__c, __t) -> StringValue.of(ret.message).reboundedTo("_msg"));
|
||||||
Value val;
|
Value val = null; // This is always assigned, just the compiler doesn't know
|
||||||
if (lv.size() == 3)
|
if (lv.size() >= 3)
|
||||||
{
|
{
|
||||||
if (!ret.exception.isInstance(lv.get(1).evalValue(c)))
|
if (lv.size() % 2 == 0)
|
||||||
|
throw new InternalExpressionException("Multi-catch block needs a catch expression for every filter");
|
||||||
|
int pointer = 1;
|
||||||
|
boolean handled = false;
|
||||||
|
while (pointer < lv.size() -1)
|
||||||
|
{
|
||||||
|
if (ret.exception.isInstance(lv.get(pointer).evalValue(c)))
|
||||||
|
{
|
||||||
|
val = lv.get(pointer + 1).evalValue(c, t);
|
||||||
|
handled = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
pointer += 2;
|
||||||
|
}
|
||||||
|
if (!handled)
|
||||||
{
|
{
|
||||||
c.setVariable("_", __);
|
c.setVariable("_", __);
|
||||||
c.setVariable("_msg", __msg);
|
c.setVariable("_msg", __msg);
|
||||||
throw ret;
|
throw ret;
|
||||||
}
|
}
|
||||||
val = lv.get(2).evalValue(c, t);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -97,7 +111,8 @@ public class ControlFlow {
|
|||||||
}
|
}
|
||||||
c.setVariable("_",__);
|
c.setVariable("_",__);
|
||||||
c.setVariable("_msg", __msg);
|
c.setVariable("_msg", __msg);
|
||||||
return (c_, t_) -> val;
|
Value retval = val;
|
||||||
|
return (c_, t_) -> retval;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user