Added guarded exception catches
This commit is contained in:
@@ -41,7 +41,7 @@ namespace chaiscript
|
|||||||
class Token_Type { public: enum Type { Error, Int, Float, Id, Char, Str, Eol, Fun_Call, Inplace_Fun_Call, Arg_List, Variable, Equation, Var_Decl,
|
class Token_Type { public: enum Type { Error, Int, Float, Id, Char, Str, Eol, Fun_Call, Inplace_Fun_Call, Arg_List, Variable, Equation, Var_Decl,
|
||||||
Expression, Comparison, Additive, Multiplicative, Negate, Not, Array_Call, Dot_Access, Quoted_String, Single_Quoted_String,
|
Expression, Comparison, Additive, Multiplicative, Negate, Not, Array_Call, Dot_Access, Quoted_String, Single_Quoted_String,
|
||||||
Lambda, Block, Def, While, If, For, Inline_Array, Inline_Map, Return, File, Prefix, Break, Map_Pair, Value_Range,
|
Lambda, Block, Def, While, If, For, Inline_Array, Inline_Map, Return, File, Prefix, Break, Map_Pair, Value_Range,
|
||||||
Inline_Range, Annotation, Try }; };
|
Inline_Range, Annotation, Try, Catch }; };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper lookup to get the name of each node type
|
* Helper lookup to get the name of each node type
|
||||||
@@ -50,7 +50,7 @@ namespace chaiscript
|
|||||||
const char *token_types[] = { "Internal Parser Error", "Int", "Float", "Id", "Char", "Str", "Eol", "Fun_Call", "Inplace_Fun_Call", "Arg_List", "Variable", "Equation", "Var_Decl",
|
const char *token_types[] = { "Internal Parser Error", "Int", "Float", "Id", "Char", "Str", "Eol", "Fun_Call", "Inplace_Fun_Call", "Arg_List", "Variable", "Equation", "Var_Decl",
|
||||||
"Expression", "Comparison", "Additive", "Multiplicative", "Negate", "Not", "Array_Call", "Dot_Access", "Quoted_String", "Single_Quoted_String",
|
"Expression", "Comparison", "Additive", "Multiplicative", "Negate", "Not", "Array_Call", "Dot_Access", "Quoted_String", "Single_Quoted_String",
|
||||||
"Lambda", "Block", "Def", "While", "If", "For", "Inline_Array", "Inline_Map", "Return", "File", "Prefix", "Break", "Map_Pair", "Value_Range",
|
"Lambda", "Block", "Def", "While", "If", "For", "Inline_Array", "Inline_Map", "Return", "File", "Prefix", "Break", "Map_Pair", "Value_Range",
|
||||||
"Inline_Range", "Annotation", "Try"};
|
"Inline_Range", "Annotation", "Try", "Catch"};
|
||||||
|
|
||||||
return token_types[tokentype];
|
return token_types[tokentype];
|
||||||
}
|
}
|
||||||
|
@@ -586,19 +586,25 @@ namespace chaiscript
|
|||||||
Boxed_Value eval_try(Eval_System &ss, const TokenPtr &node) {
|
Boxed_Value eval_try(Eval_System &ss, const TokenPtr &node) {
|
||||||
Boxed_Value retval;
|
Boxed_Value retval;
|
||||||
retval = Boxed_Value();
|
retval = Boxed_Value();
|
||||||
|
Boxed_Value except;
|
||||||
|
bool succeeded = false;
|
||||||
|
|
||||||
ss.new_scope();
|
ss.new_scope();
|
||||||
try {
|
try {
|
||||||
retval = eval_token(ss, node->children[0]);
|
retval = eval_token(ss, node->children[0]);
|
||||||
|
succeeded = true;
|
||||||
}
|
}
|
||||||
catch (const Eval_Error &) {
|
catch (const Eval_Error &) {
|
||||||
|
ss.pop_scope();
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
catch (const std::exception &e) {
|
catch (const std::exception &e) {
|
||||||
|
except = Boxed_Value(boost::ref(e));
|
||||||
|
/*
|
||||||
if (node->children.size() > 2) {
|
if (node->children.size() > 2) {
|
||||||
if (node->children[1]->text == "catch") {
|
if (node->children[1]->text == "catch") {
|
||||||
if (node->children.size() > 3) {
|
if (node->children.size() > 3) {
|
||||||
ss.add_object(node->children[2]->text, Boxed_Value(boost::ref(e)));
|
ss.add_object(node->children[2]->text, );
|
||||||
retval = eval_token(ss, node->children[3]);
|
retval = eval_token(ss, node->children[3]);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -606,8 +612,11 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
catch (Boxed_Value &bv) {
|
catch (Boxed_Value &bv) {
|
||||||
|
except = bv;
|
||||||
|
/*
|
||||||
if (node->children.size() > 2) {
|
if (node->children.size() > 2) {
|
||||||
if (node->children[1]->text == "catch") {
|
if (node->children[1]->text == "catch") {
|
||||||
if (node->children.size() > 3) {
|
if (node->children.size() > 3) {
|
||||||
@@ -619,7 +628,52 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
catch (...) {
|
||||||
|
ss.pop_scope();
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!succeeded) {
|
||||||
|
|
||||||
|
for (unsigned int i = 1; i < node->children.size(); ++i) {
|
||||||
|
TokenPtr catch_block = node->children[i];
|
||||||
|
|
||||||
|
if (catch_block->children.size() == 1) {
|
||||||
|
//No variable capture, no guards
|
||||||
|
retval = eval_token(ss, catch_block->children[0]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (catch_block->children.size() == 2) {
|
||||||
|
//Variable capture, no guards
|
||||||
|
ss.add_object(catch_block->children[0]->text, except);
|
||||||
|
retval = eval_token(ss, catch_block->children[1]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (catch_block->children.size() == 3) {
|
||||||
|
//Variable capture, no guards
|
||||||
|
ss.add_object(catch_block->children[0]->text, except);
|
||||||
|
|
||||||
|
bool guard;
|
||||||
|
try {
|
||||||
|
guard = boxed_cast<bool>(eval_token(ss, catch_block->children[1]));
|
||||||
|
} catch (const bad_boxed_cast &) {
|
||||||
|
ss.pop_scope();
|
||||||
|
throw Eval_Error("Guard condition not boolean", catch_block->children[1]);
|
||||||
|
}
|
||||||
|
if (guard) {
|
||||||
|
retval = eval_token(ss, catch_block->children[2]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ss.pop_scope();
|
||||||
|
throw Eval_Error("Internal error: catch block size unrecognized", catch_block);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ss.pop_scope();
|
ss.pop_scope();
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
|
@@ -947,11 +947,17 @@ namespace chaiscript
|
|||||||
while (has_matches) {
|
while (has_matches) {
|
||||||
while (Eol());
|
while (Eol());
|
||||||
has_matches = false;
|
has_matches = false;
|
||||||
if (Keyword("catch", true)) {
|
if (Keyword("catch", false)) {
|
||||||
|
int catch_stack_top = match_stack.size();
|
||||||
if (Char('(')) {
|
if (Char('(')) {
|
||||||
if (!(Id(true) && Char(')'))) {
|
if (!(Id(true) && Char(')'))) {
|
||||||
throw Eval_Error("Incomplete 'catch' expression", File_Position(line, col), filename);
|
throw Eval_Error("Incomplete 'catch' expression", File_Position(line, col), filename);
|
||||||
}
|
}
|
||||||
|
if (Char(':')) {
|
||||||
|
if (!Expression()) {
|
||||||
|
throw Eval_Error("Missing guard expression for catch", File_Position(line, col), filename);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while (Eol());
|
while (Eol());
|
||||||
@@ -959,7 +965,7 @@ namespace chaiscript
|
|||||||
if (!Block()) {
|
if (!Block()) {
|
||||||
throw Eval_Error("Incomplete 'catch' block", File_Position(line, col), filename);
|
throw Eval_Error("Incomplete 'catch' block", File_Position(line, col), filename);
|
||||||
}
|
}
|
||||||
|
build_match(Token_Type::Catch, catch_stack_top);
|
||||||
has_matches = true;
|
has_matches = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
28
unittests/exception_guards.chai
Normal file
28
unittests/exception_guards.chai
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
for (var i = 2; i < 6; ++i) {
|
||||||
|
try {
|
||||||
|
throw(i)
|
||||||
|
}
|
||||||
|
catch(e) : e < 2 {
|
||||||
|
print("Catch 1: " + e.to_string())
|
||||||
|
}
|
||||||
|
catch(e) : e < 4 {
|
||||||
|
print("Catch 2: " + e.to_string())
|
||||||
|
}
|
||||||
|
catch(e) {
|
||||||
|
print("Catch 3: " + e.to_string())
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
print("This is never called")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
throw(3)
|
||||||
|
}
|
||||||
|
catch(e) : e < 3
|
||||||
|
{
|
||||||
|
print("Caught less than 3")
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
print("Backup catch")
|
||||||
|
}
|
5
unittests/exception_guards.txt
Normal file
5
unittests/exception_guards.txt
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
Catch 2: 2
|
||||||
|
Catch 2: 3
|
||||||
|
Catch 3: 4
|
||||||
|
Catch 3: 5
|
||||||
|
Backup catch
|
Reference in New Issue
Block a user