diff --git a/CMakeLists.txt b/CMakeLists.txt index 54b124c..3ec158c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,13 +15,11 @@ else(READLINE_LIBRARY) SET (READLINE_FLAG ) endif(READLINE_LIBRARY) -#SET (CMAKE_BUILD_TYPE rel) SET (CMAKE_C_FLAGS_REL " -Wall -O3 ${READLINE_FLAG}") SET (CMAKE_CXX_FLAGS_REL " -Wall -O3 ${READLINE_FLAG}") -#SET (CMAKE_BUILD_TYPE gdb) -SET (CMAKE_C_FLAGS_GDB " -Wall -ggdb ${READLINE_FLAG}") -SET (CMAKE_CXX_FLAGS_GDB " -Wall -ggdb ${READLINE_FLAG}") +SET (CMAKE_C_FLAGS " -Wall -ggdb ${READLINE_FLAG}") +SET (CMAKE_CXX_FLAGS " -Wall -ggdb ${READLINE_FLAG}") include_directories(include) diff --git a/include/chaiscript/chaiscript.hpp b/include/chaiscript/chaiscript.hpp index 8579e56..b5ed774 100644 --- a/include/chaiscript/chaiscript.hpp +++ b/include/chaiscript/chaiscript.hpp @@ -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, 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, - Inline_Range, Annotation }; }; + Inline_Range, Annotation, Try }; }; /** * 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", "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", - "Inline_Range", "Annotation"}; + "Inline_Range", "Annotation", "Try"}; return token_types[tokentype]; } diff --git a/include/chaiscript/dispatchkit/bootstrap.hpp b/include/chaiscript/dispatchkit/bootstrap.hpp index 7c64668..95afb03 100644 --- a/include/chaiscript/dispatchkit/bootstrap.hpp +++ b/include/chaiscript/dispatchkit/bootstrap.hpp @@ -638,12 +638,21 @@ namespace chaiscript return Boxed_Value(f->call_match(std::vector(params.begin() + 1, params.end()))); } + static void throw_exception(const Boxed_Value &bv) { + throw bv; + } + static boost::shared_ptr bootstrap2(boost::shared_ptr e = boost::shared_ptr (new Dispatch_Engine())) { e->add(user_type(), "void"); return e; } + static std::string what(const std::exception &e) + { + return e.what(); + } + public: /** * perform all common bootstrap functions for std::string, void and POD types @@ -655,6 +664,7 @@ namespace chaiscript m->add(user_type(), "Object"); m->add(user_type(), "PODObject"); m->add(user_type(), "function"); + m->add(user_type(), "exception"); basic_constructors("bool", m); oper_assign(m); @@ -663,6 +673,7 @@ namespace chaiscript m->add(fun(&to_string), "internal_to_string"); m->add(fun(&to_string), "internal_to_string"); m->add(fun(&unknown_assign), "="); + m->add(fun(&throw_exception), "throw"); bootstrap_pod_type("double", m); bootstrap_pod_type("int", m); diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index bde105b..04e600c 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -579,6 +579,40 @@ namespace chaiscript return retval; } + /** + * Evaluates an if/elseif/else block + */ + template + Boxed_Value eval_try(Eval_System &ss, const TokenPtr &node) { + Boxed_Value retval; + retval = Boxed_Value(); + + ss.new_scope(); + try { + retval = eval_token(ss, node->children[0]); + } + catch (std::exception &) { + // nothing + std::cout << "DEBUG: std::exception caught" << std::endl; + } + catch (Boxed_Value &bv) { + if (node->children.size() > 2) { + if (node->children[1]->text == "catch") { + if (node->children.size() > 3) { + ss.add_object(node->children[2]->text, bv); + retval = eval_token(ss, node->children[3]); + } + else { + retval = eval_token(ss, node->children[2]); + } + } + } + } + ss.pop_scope(); + + return retval; + } + /** * Evaluates an if/elseif/else block */ @@ -924,6 +958,10 @@ namespace chaiscript return eval_dot_access(ss, node); break; + case(Token_Type::Try) : + return eval_try(ss, node); + break; + case(Token_Type::If) : return eval_if(ss, node); break; diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index 69e6dc1..dcbb5f0 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -916,6 +916,60 @@ namespace chaiscript return retval; } + /** + * Reads a function definition from input + */ + bool Try() { + bool retval = false; + bool is_annotated = false; + + TokenPtr annotation; + + if (Annotation()) { + while (Eol_()); + annotation = match_stack.back(); + match_stack.pop_back(); + is_annotated = true; + } + + int prev_stack_top = match_stack.size(); + + if (Keyword("try")) { + retval = true; + + while (Eol()); + + if (!Block()) { + throw Eval_Error("Incomplete 'try' block", File_Position(line, col), filename); + } + + bool has_matches = true; + while (has_matches) { + while (Eol()); + has_matches = false; + if (Keyword("catch", true)) { + if (Char('(')) { + if (!(Id(true) && Char(')'))) { + throw Eval_Error("Incomplete 'catch' expression", File_Position(line, col), filename); + } + } + + while (Eol()); + + if (!Block()) { + throw Eval_Error("Incomplete 'catch' block", File_Position(line, col), filename); + } + + has_matches = true; + } + } + + build_match(Token_Type::Try, prev_stack_top); + } + + return retval; + } + /** * Reads an if/elseif/else block from input */ @@ -1550,6 +1604,14 @@ namespace chaiscript retval = true; saw_eol = true; } + else if (Try()) { + if (!saw_eol) { + throw Eval_Error("Two function definitions missing line separator", match_stack.back()); + } + has_more = true; + retval = true; + saw_eol = true; + } else if (If()) { if (!saw_eol) { throw Eval_Error("Two function definitions missing line separator", match_stack.back());