diff --git a/CMakeLists.txt b/CMakeLists.txt index fcd9c3f..fa2335b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -136,6 +136,11 @@ IF(BUILD_TESTING) target_link_libraries(boxed_cast_test ${LIBS}) add_test(NAME Boxed_Cast_Test COMMAND boxed_cast_test) + add_executable(multifile_test unittests/multifile_test_main.cpp unittests/multifile_test_chai.cpp + unittests/multifile_test_module.cpp) + target_link_libraries(multifile_test ${LIBS}) + add_test(NAME MultiFile_Test COMMAND multifile_test) + add_library(test_module MODULE src/test_module.cpp) target_link_libraries(test_module ${LIBS}) diff --git a/include/chaiscript/dispatchkit/dynamic_cast_conversion.hpp b/include/chaiscript/dispatchkit/dynamic_cast_conversion.hpp index 63fab9b..579935d 100644 --- a/include/chaiscript/dispatchkit/dynamic_cast_conversion.hpp +++ b/include/chaiscript/dispatchkit/dynamic_cast_conversion.hpp @@ -251,7 +251,7 @@ namespace chaiscript return dynamic_cast_converts(user_type(), user_type()); } - bool dynamic_cast_converts(const Type_Info &base, const Type_Info &derived) + static bool dynamic_cast_converts(const Type_Info &base, const Type_Info &derived) { return detail::Dynamic_Conversions::get().has_conversion(base, derived); } diff --git a/include/chaiscript/language/chaiscript_common.hpp b/include/chaiscript/language/chaiscript_common.hpp index 956bd31..fba22b8 100644 --- a/include/chaiscript/language/chaiscript_common.hpp +++ b/include/chaiscript/language/chaiscript_common.hpp @@ -117,332 +117,8 @@ namespace chaiscript } }; - struct Binary_Operator_AST_Node : public AST_Node { - public: - Binary_Operator_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Bitwise_Xor, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : - AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } - virtual ~Binary_Operator_AST_Node() {} - virtual Boxed_Value eval(Dispatch_Engine &ss); - }; - struct Error_AST_Node : public AST_Node { - public: - Error_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Error, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : - AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } - - virtual ~Error_AST_Node() {} - }; - struct Int_AST_Node : public AST_Node { - public: - Int_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Int, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : - AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } - virtual ~Int_AST_Node() {} - virtual Boxed_Value eval(Dispatch_Engine &ss); - }; - struct Float_AST_Node : public AST_Node { - public: - Float_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Float, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : - AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } - virtual ~Float_AST_Node() {} - virtual Boxed_Value eval(Dispatch_Engine &ss); - }; - struct Id_AST_Node : public AST_Node { - public: - Id_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Id, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : - AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } - virtual ~Id_AST_Node() {} - virtual Boxed_Value eval(Dispatch_Engine &ss); - }; - struct Char_AST_Node : public AST_Node { - public: - Char_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Char, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : - AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } - virtual ~Char_AST_Node() {} - }; - struct Str_AST_Node : public AST_Node { - public: - Str_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Str, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : - AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } - virtual ~Str_AST_Node() {} - }; - struct Eol_AST_Node : public AST_Node { - public: - Eol_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Eol, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : - AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } - virtual ~Eol_AST_Node() {} - }; - struct Fun_Call_AST_Node : public AST_Node { - public: - Fun_Call_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Fun_Call, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : - AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } - virtual ~Fun_Call_AST_Node() {} - virtual Boxed_Value eval(Dispatch_Engine &ss); - }; - struct Inplace_Fun_Call_AST_Node : public AST_Node { - public: - Inplace_Fun_Call_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Inplace_Fun_Call, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : - AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } - virtual ~Inplace_Fun_Call_AST_Node() {} - virtual Boxed_Value eval(Dispatch_Engine &ss); - }; - struct Arg_List_AST_Node : public AST_Node { - public: - Arg_List_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Arg_List, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : - AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } - virtual ~Arg_List_AST_Node() {} - }; - struct Variable_AST_Node : public AST_Node { - public: - Variable_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Variable, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : - AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } - virtual ~Variable_AST_Node() {} - }; - struct Equation_AST_Node : public AST_Node { - public: - Equation_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Equation, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : - AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } - virtual ~Equation_AST_Node() {} - virtual Boxed_Value eval(Dispatch_Engine &ss); - }; - struct Var_Decl_AST_Node : public AST_Node { - public: - Var_Decl_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Var_Decl, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : - AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } - virtual ~Var_Decl_AST_Node() {} - virtual Boxed_Value eval(Dispatch_Engine &ss); - }; - struct Comparison_AST_Node : public Binary_Operator_AST_Node { - public: - Comparison_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Comparison, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : - Binary_Operator_AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } - virtual ~Comparison_AST_Node() {} - }; - struct Additive_AST_Node : public Binary_Operator_AST_Node { - public: - Additive_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Additive, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : - Binary_Operator_AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } - virtual ~Additive_AST_Node() {} - }; - struct Multiplicative_AST_Node : public Binary_Operator_AST_Node { - public: - Multiplicative_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Multiplicative, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : - Binary_Operator_AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } - virtual ~Multiplicative_AST_Node() {} - }; - struct Array_Call_AST_Node : public AST_Node { - public: - Array_Call_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Array_Call, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : - AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } - virtual ~Array_Call_AST_Node() {} - virtual Boxed_Value eval(Dispatch_Engine &ss); - }; - struct Dot_Access_AST_Node : public AST_Node { - public: - Dot_Access_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Dot_Access, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : - AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } - virtual ~Dot_Access_AST_Node() {} - virtual Boxed_Value eval(Dispatch_Engine &ss); - }; - struct Quoted_String_AST_Node : public AST_Node { - public: - Quoted_String_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Quoted_String, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : - AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } - virtual ~Quoted_String_AST_Node() {} - virtual Boxed_Value eval(Dispatch_Engine &ss); - }; - struct Single_Quoted_String_AST_Node : public AST_Node { - public: - Single_Quoted_String_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Single_Quoted_String, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : - AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } - virtual ~Single_Quoted_String_AST_Node() {} - virtual Boxed_Value eval(Dispatch_Engine &ss); - }; - struct Lambda_AST_Node : public AST_Node { - public: - Lambda_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Lambda, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : - AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } - virtual ~Lambda_AST_Node() {} - virtual Boxed_Value eval(Dispatch_Engine &ss); - }; - struct Block_AST_Node : public AST_Node { - public: - Block_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Block, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : - AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } - virtual ~Block_AST_Node() {} - virtual Boxed_Value eval(Dispatch_Engine &ss); - }; - struct Def_AST_Node : public AST_Node { - public: - Def_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Def, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : - AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } - virtual ~Def_AST_Node() {} - virtual Boxed_Value eval(Dispatch_Engine &ss); - }; - struct While_AST_Node : public AST_Node { - public: - While_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::While, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : - AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } - virtual ~While_AST_Node() {} - virtual Boxed_Value eval(Dispatch_Engine &ss); - }; - struct If_AST_Node : public AST_Node { - public: - If_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::If, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : - AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } - virtual ~If_AST_Node() {} - virtual Boxed_Value eval(Dispatch_Engine &ss); - }; - struct For_AST_Node : public AST_Node { - public: - For_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::For, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : - AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } - virtual ~For_AST_Node() {} - virtual Boxed_Value eval(Dispatch_Engine &ss); - }; - struct Inline_Array_AST_Node : public AST_Node { - public: - Inline_Array_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Inline_Array, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : - AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } - virtual ~Inline_Array_AST_Node() {} - virtual Boxed_Value eval(Dispatch_Engine &ss); - }; - struct Inline_Map_AST_Node : public AST_Node { - public: - Inline_Map_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Inline_Map, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : - AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } - virtual ~Inline_Map_AST_Node() {} - virtual Boxed_Value eval(Dispatch_Engine &ss); - }; - struct Return_AST_Node : public AST_Node { - public: - Return_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Return, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : - AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } - virtual ~Return_AST_Node() {} - virtual Boxed_Value eval(Dispatch_Engine &ss); - }; - struct File_AST_Node : public AST_Node { - public: - File_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::File, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : - AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } - virtual ~File_AST_Node() {} - virtual Boxed_Value eval(Dispatch_Engine &ss); - }; - struct Prefix_AST_Node : public AST_Node { - public: - Prefix_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Prefix, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : - AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } - virtual ~Prefix_AST_Node() {} - virtual Boxed_Value eval(Dispatch_Engine &ss); - }; - struct Break_AST_Node : public AST_Node { - public: - Break_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Break, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : - AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } - virtual ~Break_AST_Node() {} - virtual Boxed_Value eval(Dispatch_Engine &ss); - }; - struct Map_Pair_AST_Node : public AST_Node { - public: - Map_Pair_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Map_Pair, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : - AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } - virtual ~Map_Pair_AST_Node() {} - }; - struct Value_Range_AST_Node : public AST_Node { - public: - Value_Range_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Value_Range, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : - AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } - virtual ~Value_Range_AST_Node() {} - }; - struct Inline_Range_AST_Node : public AST_Node { - public: - Inline_Range_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Inline_Range, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : - AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } - virtual ~Inline_Range_AST_Node() {} - virtual Boxed_Value eval(Dispatch_Engine &ss); - }; - struct Annotation_AST_Node : public AST_Node { - public: - Annotation_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Annotation, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : - AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } - virtual ~Annotation_AST_Node() {} - }; - struct Try_AST_Node : public AST_Node { - public: - Try_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Try, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : - AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } - virtual ~Try_AST_Node() {} - virtual Boxed_Value eval(Dispatch_Engine &ss); - }; - struct Catch_AST_Node : public AST_Node { - public: - Catch_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Catch, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : - AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } - virtual ~Catch_AST_Node() {} - }; - struct Finally_AST_Node : public AST_Node { - public: - Finally_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Finally, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : - AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } - virtual ~Finally_AST_Node() {} - }; - struct Method_AST_Node : public AST_Node { - public: - Method_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Method, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : - AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } - virtual ~Method_AST_Node() {} - virtual Boxed_Value eval(Dispatch_Engine &ss); - }; - struct Attr_Decl_AST_Node : public AST_Node { - public: - Attr_Decl_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Attr_Decl, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : - AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } - virtual ~Attr_Decl_AST_Node() {} - virtual Boxed_Value eval(Dispatch_Engine &ss); - }; - struct Shift_AST_Node : public Binary_Operator_AST_Node { - public: - Shift_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Shift, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : - Binary_Operator_AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } - virtual ~Shift_AST_Node() {} - }; - struct Equality_AST_Node : public Binary_Operator_AST_Node { - public: - Equality_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Equality, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : - Binary_Operator_AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } - virtual ~Equality_AST_Node() {} - }; - struct Bitwise_And_AST_Node : public Binary_Operator_AST_Node { - public: - Bitwise_And_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Bitwise_And, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : - Binary_Operator_AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } - virtual ~Bitwise_And_AST_Node() {} - }; - struct Bitwise_Xor_AST_Node : public Binary_Operator_AST_Node { - public: - Bitwise_Xor_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Bitwise_Xor, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : - Binary_Operator_AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } - virtual ~Bitwise_Xor_AST_Node() {} - }; - struct Bitwise_Or_AST_Node : public Binary_Operator_AST_Node { - public: - Bitwise_Or_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Bitwise_Or, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : - Binary_Operator_AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } - virtual ~Bitwise_Or_AST_Node() {} - }; - struct Logical_And_AST_Node : public AST_Node { - public: - Logical_And_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Logical_And, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : - AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } - virtual ~Logical_And_AST_Node() {} - virtual Boxed_Value eval(Dispatch_Engine &ss); - }; - struct Logical_Or_AST_Node : public AST_Node { - public: - Logical_Or_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Logical_Or, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : - AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } - virtual ~Logical_Or_AST_Node() {} - virtual Boxed_Value eval(Dispatch_Engine &ss); - }; + /** * Errors generated during parsing or evaluation diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index 0288b4b..e2a6873 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -17,912 +17,649 @@ namespace chaiscript * Helper function that will set up the scope around a function call, including handling the named function parameters */ template - const Boxed_Value eval_function (Eval_System &ss, const AST_NodePtr &node, const std::vector ¶m_names, const std::vector &vals) { - ss.new_scope(); + const Boxed_Value eval_function (Eval_System &ss, const AST_NodePtr &node, const std::vector ¶m_names, const std::vector &vals) { + ss.new_scope(); - for (unsigned int i = 0; i < param_names.size(); ++i) { - ss.add_object(param_names[i], vals[i]); - } - - try { - Boxed_Value retval(node->eval(ss)); - ss.pop_scope(); - return retval; - } catch (const Return_Value &rv) { - ss.pop_scope(); - return rv.retval; - } catch (Eval_Error &ee) { - ee.call_stack.push_back(node); - ss.pop_scope(); - throw; - } catch (...) { - ss.pop_scope(); - throw; - } - } - - /** - * Evaluates the top-level file node - */ - Boxed_Value File_AST_Node::eval(Dispatch_Engine &ss) { - const unsigned int size = this->children.size(); - for (unsigned int i = 0; i < size; ++i) { - try { - const Boxed_Value &retval = this->children[i]->eval(ss); - if (i + 1 == size) { - return retval; - } + for (unsigned int i = 0; i < param_names.size(); ++i) { + ss.add_object(param_names[i], vals[i]); } - catch (Eval_Error &ee) { - ee.call_stack.push_back(this->children[i]); - throw; - } - } - return Boxed_Value(); - } - - /** - * Evaluates a variable or function name identifier - */ - Boxed_Value Id_AST_Node::eval(Dispatch_Engine &ss) { - if (this->text == "true") { - return const_var(true); - } - else if (this->text == "false") { - return const_var(false); - } - else if (this->text == "Infinity") { - return const_var(std::numeric_limits::infinity()); - } - else if (this->text == "NaN") { - return const_var(std::numeric_limits::quiet_NaN()); - } - else { - try { - return ss.get_object(this->text); - } - catch (std::exception &) { - throw Eval_Error("Can not find object: " + this->text); - } - } - } - - /** - * Evaluates a floating point number - */ - Boxed_Value Float_AST_Node::eval(Dispatch_Engine &) { - return const_var(double(atof(this->text.c_str()))); - } - - /** - * Evaluates an integer - */ - Boxed_Value Int_AST_Node::eval(Dispatch_Engine &) { - return const_var(int(atoi(this->text.c_str()))); - } - - /** - * Evaluates a quoted string - */ - Boxed_Value Quoted_String_AST_Node::eval(Dispatch_Engine &) { - return const_var(this->text); - } - - /** - * Evaluates a char group - */ - - Boxed_Value Single_Quoted_String_AST_Node::eval(Dispatch_Engine &) { - return const_var(char(this->text[0])); - } - - /** - * Evaluates a string of equations in reverse order so that the right-most side has precedence - */ - Boxed_Value Equation_AST_Node::eval(Dispatch_Engine &ss) { - Boxed_Value retval; - try { - retval = this->children.back()->eval(ss); - } - catch (Eval_Error &ee) { - ee.call_stack.push_back(this->children.back()); - throw; - } - - if (this->children.size() > 1) { - for (int i = this->children.size()-3; i >= 0; i -= 2) { - if (this->children[i+1]->text == "=") { - try { - Boxed_Value lhs = this->children[i]->eval(ss); - - try { - if (lhs.is_undef()) { - retval = ss.call_function("clone", retval); - retval.clear_dependencies(); - } - - try { - retval = ss.call_function(this->children[i+1]->text, lhs, retval); - } - catch(const dispatch_error &){ - throw Eval_Error(std::string("Mismatched types in equation") + (lhs.is_const()?", lhs is const.":".")); - } - } - catch(const dispatch_error &){ - throw Eval_Error("Can not clone right hand side of equation"); - } - } - catch(Eval_Error &ee) { - ee.call_stack.push_back(this->children[i]); - throw; - } - } - else if (this->children[i+1]->text == ":=") { - try { - Boxed_Value lhs = this->children[i]->eval(ss); - if (lhs.is_undef() || type_match(lhs, retval)) { - lhs.assign(retval); - } - else { - throw Eval_Error("Mismatched types in equation"); - } - } - catch (Eval_Error &ee) { - ee.call_stack.push_back(this->children[i]); - throw; - } - } - else { - try { - retval = ss.call_function(this->children[i+1]->text, this->children[i]->eval(ss), retval); - } - catch(const dispatch_error &){ - throw Eval_Error("Can not find appropriate '" + this->children[i+1]->text + "'"); - } - catch(Eval_Error &ee) { - ee.call_stack.push_back(this->children[i]); - throw; - } - } - } - } - return retval; - } - - /** - * Evaluates a variable declaration - */ - Boxed_Value Var_Decl_AST_Node::eval(Dispatch_Engine &ss) { - try { - ss.add_object(this->children[0]->text, Boxed_Value()); - } - catch (reserved_word_error &) { - throw Eval_Error("Reserved word used as variable '" + this->children[0]->text + "'"); - } - return ss.get_object(this->children[0]->text); - } - - /** - * Evaluates an attribute declaration - */ - Boxed_Value Attr_Decl_AST_Node::eval(Dispatch_Engine &ss) { - try { - ss.add(fun(boost::function(boost::bind(&Dynamic_Object_Attribute::func, this->children[0]->text, - this->children[1]->text, _1))), this->children[1]->text); - - } - catch (reserved_word_error &) { - throw Eval_Error("Reserved word used as attribute '" + this->children[1]->text + "'"); - } - return Boxed_Value(); - } - - /** - * Evaluates binary boolean operators. Respects short-circuiting rules. - */ - Boxed_Value Logical_And_AST_Node::eval(Dispatch_Engine &ss) { - Boxed_Value retval; - try { - retval = this->children[0]->eval(ss); - } - catch (Eval_Error &ee) { - ee.call_stack.push_back(this->children[0]); - throw; - } - - if (this->children.size() > 1) { - for (size_t i = 1; i < this->children.size(); i += 2) { - bool lhs; - try { - lhs = boxed_cast(retval); - } - catch (const bad_boxed_cast &) { - throw Eval_Error("Condition not boolean"); - } - if (lhs) { - try { - retval = this->children[i+1]->eval(ss); - } - catch (Eval_Error &ee) { - ee.call_stack.push_back(this->children[i+1]); - throw; - } - } - else { - retval = Boxed_Value(false); - } - } - } - return retval; - } - - Boxed_Value Logical_Or_AST_Node::eval(Dispatch_Engine &ss) { - Boxed_Value retval; - - try { - retval = this->children[0]->eval(ss); - } - catch (Eval_Error &ee) { - ee.call_stack.push_back(this->children[0]); - throw; - } - - if (this->children.size() > 1) { - for (size_t i = 1; i < this->children.size(); i += 2) { - bool lhs; - try { - lhs = boxed_cast(retval); - } - catch (const bad_boxed_cast &) { - throw Eval_Error("Condition not boolean"); - } - if (lhs) { - retval = Boxed_Value(true); - } - else { - try { - retval = this->children[i+1]->eval(ss); - } - catch (Eval_Error &ee) { - ee.call_stack.push_back(this->children[i+1]); - throw; - } - } - } - } - return retval; - } - - /** - * Evaluates comparison, additions, and multiplications and their relatives - */ - Boxed_Value Binary_Operator_AST_Node::eval(Dispatch_Engine &ss) { - Boxed_Value retval; - - try { - retval = this->children[0]->eval(ss); - } - catch (Eval_Error &ee) { - ee.call_stack.push_back(this->children[0]); - throw; - } - - for (size_t i = 1; i < this->children.size(); i += 2) { - try { - retval = ss.call_function(this->children[i]->text, retval, this->children[i+1]->eval(ss)); - } - catch(const dispatch_error &){ - throw Eval_Error("Can not find appropriate '" + this->children[i]->text + "'"); - } - catch(Eval_Error &ee) { - ee.call_stack.push_back(this->children[i+1]); - throw; - } - } - - return retval; - } - - /** - * Evaluates an array lookup - */ - Boxed_Value Array_Call_AST_Node::eval(Dispatch_Engine &ss) { - Boxed_Value retval; - - try { - retval = this->children[0]->eval(ss); - } - catch (Eval_Error &ee) { - ee.call_stack.push_back(this->children[0]); - throw; - } - - for (size_t i = 1; i < this->children.size(); ++i) { - try { - retval = ss.call_function("[]", retval, this->children[i]->eval(ss)); - } - catch(std::out_of_range &) { - throw Eval_Error("Out of bounds exception"); - } - catch(const dispatch_error &){ - throw Eval_Error("Can not find appropriate array lookup '[]' "); - } - catch(Eval_Error &ee) { - ee.call_stack.push_back(this->children[i]); - throw; - } - } - - return retval; - } - - /** - * Evaluates any unary prefix - */ - Boxed_Value Prefix_AST_Node::eval(Dispatch_Engine &ss) { - try { - return ss.call_function(this->children[0]->text, this->children[1]->eval(ss)); - } - catch(std::exception &){ - throw Eval_Error("Can not find appropriate unary '" + this->children[0]->text + "'"); - } - } - - /** - * Evaluates (and generates) an inline array initialization - */ - Boxed_Value Inline_Array_AST_Node::eval(Dispatch_Engine &ss) { - std::vector vec; - if (this->children.size() > 0) { - for (size_t i = 0; i < this->children[0]->children.size(); ++i) { - try { - vec.push_back(this->children[0]->children[i]->eval(ss)); - } - catch(Eval_Error &ee) { - ee.call_stack.push_back(this->children[0]->children[i]); - throw; - } - } - } - - return const_var(vec); - } - - /** - * Evaluates (and generates) an inline range initialization - */ - Boxed_Value Inline_Range_AST_Node::eval(Dispatch_Engine &ss) { - try { - return ss.call_function("generate_range", - this->children[0]->children[0]->children[0]->eval(ss), - this->children[0]->children[0]->children[1]->eval(ss)); - } - catch (const dispatch_error &) { - throw Eval_Error("Unable to generate range vector"); - } - catch(Eval_Error &ee) { - ee.call_stack.push_back(this->children[0]->children[0]); - throw; - } - } - - /** - * Evaluates (and generates) an inline map initialization - */ - Boxed_Value Inline_Map_AST_Node::eval(Dispatch_Engine &ss) { - try { - std::map retval; - for (size_t i = 0; i < this->children[0]->children.size(); ++i) { - try { - retval[boxed_cast(this->children[0]->children[i]->children[0]->eval(ss))] - = ss.call_function("clone", this->children[0]->children[i]->children[1]->eval(ss)); - } - catch(Eval_Error &ee) { - ee.call_stack.push_back(this->children[0]->children[i]); - throw; - } - } - return const_var(retval); - } - catch (const dispatch_error &) { - throw Eval_Error("Can not find appropriate 'Map()'"); - } - } - - /** - * Evaluates a function call, starting with its arguments. Handles resetting the scope to the previous one after the call. - */ - Boxed_Value Fun_Call_AST_Node::eval(Dispatch_Engine &ss) { - Param_List_Builder plb; - - if ((this->children.size() > 1) && (this->children[1]->identifier == AST_Node_Type::Arg_List)) { - for (size_t i = 0; i < this->children[1]->children.size(); ++i) { - try { - plb << this->children[1]->children[i]->eval(ss); - } - catch(Eval_Error &ee) { - ee.call_stack.push_back(this->children[1]->children[i]); - throw; - } - } - } - - Dispatch_Engine::Stack prev_stack = ss.get_stack(); - Dispatch_Engine::Stack new_stack = ss.new_stack(); - - try { - Boxed_Value fn = this->children[0]->eval(ss); try { - ss.set_stack(new_stack); - const Boxed_Value &retval = (*boxed_cast(fn))(plb); - ss.set_stack(prev_stack); + Boxed_Value retval(node->eval(ss)); + ss.pop_scope(); return retval; - } - catch(const dispatch_error &e){ - ss.set_stack(prev_stack); - throw Eval_Error(std::string(e.what()) + " with function '" + this->children[0]->text + "'"); - } - catch(Return_Value &rv) { - ss.set_stack(prev_stack); + } catch (const Return_Value &rv) { + ss.pop_scope(); return rv.retval; - } - catch(...) { - ss.set_stack(prev_stack); + } catch (Eval_Error &ee) { + ee.call_stack.push_back(node); + ss.pop_scope(); throw; - } - } - catch(Eval_Error &ee) { - ee.call_stack.push_back(this->children[0]); - ss.set_stack(prev_stack); - throw Eval_Error(ee.reason); - } - - } - - /** - * Evaluates a function call, starting with its arguments. Does NOT change scope. - */ - Boxed_Value Inplace_Fun_Call_AST_Node::eval(Dispatch_Engine &ss) { - Param_List_Builder plb; - - if ((this->children.size() > 1) && (this->children[1]->identifier == AST_Node_Type::Arg_List)) { - for (size_t i = 0; i < this->children[1]->children.size(); ++i) { - try { - plb << this->children[1]->children[i]->eval(ss); - } - catch (Eval_Error &ee) { - ee.call_stack.push_back(this->children[1]->children[i]); - throw; - } - } - } - - try { - Boxed_Value fn = this->children[0]->eval(ss); - - try { - return (*boxed_cast(fn))(plb); - } - catch(const dispatch_error &e){ - throw Eval_Error(std::string(e.what()) + " with function '" + this->children[0]->text + "'"); - } - catch(Return_Value &rv) { - return rv.retval; - } - catch(...) { - throw; - } - } - catch(Eval_Error &ee) { - ee.call_stack.push_back(this->children[0]); - throw Eval_Error(ee.reason); - } - - } - - /** - * Evaluates a method/attributes invocation - */ - Boxed_Value Dot_Access_AST_Node::eval(Dispatch_Engine &ss) { - Boxed_Value retval; - try { - retval = this->children[0]->eval(ss); - } - catch (Eval_Error &ee) { - ee.call_stack.push_back(this->children[0]); - throw; - } - - if (this->children.size() > 1) { - for (size_t i = 2; i < this->children.size(); i+=2) { - Param_List_Builder plb; - plb << retval; - - if (this->children[i]->children.size() > 1) { - for (size_t j = 0; j < this->children[i]->children[1]->children.size(); ++j) { - try { - plb << this->children[i]->children[1]->children[j]->eval(ss); - } - catch (Eval_Error &ee) { - ee.call_stack.push_back(this->children[i]->children[1]->children[j]); - throw; - } - } - } - - std::string fun_name; - std::vector > funs; - if ((this->children[i]->identifier == AST_Node_Type::Fun_Call) || (this->children[i]->identifier == AST_Node_Type::Array_Call)) { - fun_name = this->children[i]->children[0]->text; - } - else { - fun_name = this->children[i]->text; - } - - Dispatch_Engine::Stack prev_stack = ss.get_stack(); - Dispatch_Engine::Stack new_stack = ss.new_stack(); - - try { - ss.set_stack(new_stack); - retval = ss.call_function(fun_name, plb); - ss.set_stack(prev_stack); - } - catch(const dispatch_error &e){ - ss.set_stack(prev_stack); - throw Eval_Error(std::string(e.what())); - } - catch(Return_Value &rv) { - ss.set_stack(prev_stack); - retval = rv.retval; - } - catch(...) { - ss.set_stack(prev_stack); - throw; - } - if (this->children[i]->identifier == AST_Node_Type::Array_Call) { - for (size_t j = 1; j < this->children[i]->children.size(); ++j) { - try { - retval = ss.call_function("[]", retval, this->children[i]->children[j]->eval(ss)); - } - catch(std::out_of_range &) { - throw Eval_Error("Out of bounds exception"); - } - catch(const dispatch_error &){ - throw Eval_Error("Can not find appropriate array lookup '[]' "); - } - catch(Eval_Error &ee) { - ee.call_stack.push_back(this->children[i]->children[j]); - throw; - } - } - } - } - } - - return retval; - } - - /** - * Evaluates an if/elseif/else block - */ - Boxed_Value Try_AST_Node::eval(Dispatch_Engine &ss) { - Boxed_Value retval; - - ss.new_scope(); - try { - retval = this->children[0]->eval(ss); - } - catch (Eval_Error &ee) { - ee.call_stack.push_back(this->children[0]); - if (this->children.back()->identifier == AST_Node_Type::Finally) { - try { - this->children.back()->children[0]->eval(ss); - } - catch (Eval_Error &ee) { - ee.call_stack.push_back(this->children.back()->children[0]); - ss.pop_scope(); - throw; - } - } - ss.pop_scope(); - throw; - } - catch (const std::exception &e) { - Boxed_Value except = Boxed_Value(boost::ref(e)); - - unsigned int end_point = this->children.size(); - if (this->children.back()->identifier == AST_Node_Type::Finally) { - end_point = this->children.size() - 1; - } - for (unsigned int i = 1; i < end_point; ++i) { - AST_NodePtr catch_block = this->children[i]; - - if (catch_block->children.size() == 1) { - //No variable capture, no guards - try { - retval = catch_block->children[0]->eval(ss); - } - catch (Eval_Error &ee) { - ee.call_stack.push_back(catch_block->children[0]); - throw; - } - break; - } - else if (catch_block->children.size() == 2) { - //Variable capture, no guards - ss.add_object(catch_block->children[0]->text, except); - try { - retval = catch_block->children[1]->eval(ss); - } - catch (Eval_Error &ee) { - ee.call_stack.push_back(catch_block->children[1]); - throw; - } - - 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(catch_block->children[1]->eval(ss)); - } catch (const bad_boxed_cast &) { - if (this->children.back()->identifier == AST_Node_Type::Finally) { - try { - this->children.back()->children[0]->eval(ss); - } - catch (Eval_Error &ee) { - ee.call_stack.push_back(this->children.back()->children[0]); - ss.pop_scope(); - throw; - } - } - ss.pop_scope(); - throw Eval_Error("Guard condition not boolean"); - } - if (guard) { - try { - retval = catch_block->children[2]->eval(ss); - } - catch (Eval_Error &ee) { - ee.call_stack.push_back(catch_block->children[2]); - throw; - } - - break; - } - } - else { - if (this->children.back()->identifier == AST_Node_Type::Finally) { - try { - this->children.back()->children[0]->eval(ss); - } - catch (Eval_Error &ee) { - ee.call_stack.push_back(this->children.back()->children[0]); - ss.pop_scope(); - throw; - } - } - ss.pop_scope(); - throw Eval_Error("Internal error: catch block size unrecognized"); - } - } - } - catch (Boxed_Value &bv) { - Boxed_Value except = bv; - for (size_t i = 1; i < this->children.size(); ++i) { - AST_NodePtr catch_block = this->children[i]; - - if (catch_block->children.size() == 1) { - //No variable capture, no guards - try { - retval = catch_block->children[0]->eval(ss); - } - catch (Eval_Error &ee) { - ee.call_stack.push_back(catch_block->children[0]); - throw; - } - - break; - } - else if (catch_block->children.size() == 2) { - //Variable capture, no guards - ss.add_object(catch_block->children[0]->text, except); - try { - retval = catch_block->children[1]->eval(ss); - } - catch (Eval_Error &ee) { - ee.call_stack.push_back(catch_block->children[1]); - throw; - } - - 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(catch_block->children[1]->eval(ss)); - } - catch (const bad_boxed_cast &) { - if (this->children.back()->identifier == AST_Node_Type::Finally) { - try { - this->children.back()->children[0]->eval(ss); - } - catch (Eval_Error &ee) { - ee.call_stack.push_back(this->children.back()->children[0]); - ss.pop_scope(); - throw; - } - } - - ss.pop_scope(); - throw Eval_Error("Guard condition not boolean"); - } - catch (Eval_Error &ee) { - ee.call_stack.push_back(catch_block->children[1]); - throw; - } - if (guard) { - try { - retval = catch_block->children[2]->eval(ss); - } - catch (Eval_Error &ee) { - ee.call_stack.push_back(catch_block->children[2]); - throw; - } - break; - } - } - else { - if (this->children.back()->identifier == AST_Node_Type::Finally) { - try { - this->children.back()->children[0]->eval(ss); - } - catch (Eval_Error &ee) { - ee.call_stack.push_back(this->children.back()->children[0]); - ss.pop_scope(); - throw; - } - } - ss.pop_scope(); - throw Eval_Error("Internal error: catch block size unrecognized"); - } - } - } - catch (...) { - if (this->children.back()->identifier == AST_Node_Type::Finally) { - try { - this->children.back()->children[0]->eval(ss); - } - catch (Eval_Error &ee) { - ee.call_stack.push_back(this->children.back()->children[0]); - ss.pop_scope(); - throw; - } - } - ss.pop_scope(); - throw; - } - - if (this->children.back()->identifier == AST_Node_Type::Finally) { - try { - retval = this->children.back()->children[0]->eval(ss); - } - catch (Eval_Error &ee) { - ee.call_stack.push_back(this->children.back()->children[0]); + } catch (...) { ss.pop_scope(); throw; } } - ss.pop_scope(); - return retval; - } + struct Binary_Operator_AST_Node : public AST_Node { + public: + Binary_Operator_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Bitwise_Xor, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : + AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } + virtual ~Binary_Operator_AST_Node() {} + virtual Boxed_Value eval(Dispatch_Engine &ss){ + Boxed_Value retval; - /** - * Evaluates an if/elseif/else block - */ - Boxed_Value If_AST_Node::eval(Dispatch_Engine &ss) { - bool cond; - try { - cond = boxed_cast(this->children[0]->eval(ss)); - } - catch (const bad_boxed_cast &) { - throw Eval_Error("If condition not boolean"); - } - catch (Eval_Error &ee) { - ee.call_stack.push_back(this->children[0]); - throw; - } - - if (cond) { - try { - return this->children[1]->eval(ss); + try { + retval = this->children[0]->eval(ss); + } + catch (Eval_Error &ee) { + ee.call_stack.push_back(this->children[0]); + throw; + } + + for (size_t i = 1; i < this->children.size(); i += 2) { + try { + retval = ss.call_function(this->children[i]->text, retval, this->children[i+1]->eval(ss)); + } + catch(const dispatch_error &){ + throw Eval_Error("Can not find appropriate '" + this->children[i]->text + "'"); + } + catch(Eval_Error &ee) { + ee.call_stack.push_back(this->children[i+1]); + throw; + } + } + + return retval; } - catch (Eval_Error &ee) { - ee.call_stack.push_back(this->children[1]); - throw; + + }; + + struct Error_AST_Node : public AST_Node { + public: + Error_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Error, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : + AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } + + virtual ~Error_AST_Node() {} + }; + + struct Int_AST_Node : public AST_Node { + public: + Int_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Int, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : + AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } + virtual ~Int_AST_Node() {} + virtual Boxed_Value eval(Dispatch_Engine &){ + return const_var(int(atoi(this->text.c_str()))); } - } - else { - if (this->children.size() > 2) { - size_t i = 2; - while ((!cond) && (i < this->children.size())) { - if (this->children[i]->text == "else") { + + }; + + struct Float_AST_Node : public AST_Node { + public: + Float_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Float, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : + AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } + virtual ~Float_AST_Node() {} + virtual Boxed_Value eval(Dispatch_Engine &){ + return const_var(double(atof(this->text.c_str()))); + } + + }; + + struct Id_AST_Node : public AST_Node { + public: + Id_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Id, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : + AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } + virtual ~Id_AST_Node() {} + virtual Boxed_Value eval(Dispatch_Engine &ss){ + if (this->text == "true") { + return const_var(true); + } + else if (this->text == "false") { + return const_var(false); + } + else if (this->text == "Infinity") { + return const_var(std::numeric_limits::infinity()); + } + else if (this->text == "NaN") { + return const_var(std::numeric_limits::quiet_NaN()); + } + else { + try { + return ss.get_object(this->text); + } + catch (std::exception &) { + throw Eval_Error("Can not find object: " + this->text); + } + } + } + }; + + struct Char_AST_Node : public AST_Node { + public: + Char_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Char, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : + AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } + virtual ~Char_AST_Node() {} + }; + + struct Str_AST_Node : public AST_Node { + public: + Str_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Str, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : + AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } + virtual ~Str_AST_Node() {} + }; + + struct Eol_AST_Node : public AST_Node { + public: + Eol_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Eol, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : + AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } + virtual ~Eol_AST_Node() {} + }; + + struct Fun_Call_AST_Node : public AST_Node { + public: + Fun_Call_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Fun_Call, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : + AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } + virtual ~Fun_Call_AST_Node() {} + virtual Boxed_Value eval(Dispatch_Engine &ss){ + Param_List_Builder plb; + + if ((this->children.size() > 1) && (this->children[1]->identifier == AST_Node_Type::Arg_List)) { + for (size_t i = 0; i < this->children[1]->children.size(); ++i) { try { - return this->children[i+1]->eval(ss); + plb << this->children[1]->children[i]->eval(ss); } - catch (Eval_Error &ee) { - ee.call_stack.push_back(this->children[i+1]); + catch(Eval_Error &ee) { + ee.call_stack.push_back(this->children[1]->children[i]); throw; } } - else if (this->children[i]->text == "else if") { + } + + Dispatch_Engine::Stack prev_stack = ss.get_stack(); + Dispatch_Engine::Stack new_stack = ss.new_stack(); + + try { + Boxed_Value fn = this->children[0]->eval(ss); + + try { + ss.set_stack(new_stack); + const Boxed_Value &retval = (*boxed_cast(fn))(plb); + ss.set_stack(prev_stack); + return retval; + } + catch(const dispatch_error &e){ + ss.set_stack(prev_stack); + throw Eval_Error(std::string(e.what()) + " with function '" + this->children[0]->text + "'"); + } + catch(Return_Value &rv) { + ss.set_stack(prev_stack); + return rv.retval; + } + catch(...) { + ss.set_stack(prev_stack); + throw; + } + } + catch(Eval_Error &ee) { + ee.call_stack.push_back(this->children[0]); + ss.set_stack(prev_stack); + throw Eval_Error(ee.reason); + } + + } + + }; + + struct Inplace_Fun_Call_AST_Node : public AST_Node { + public: + Inplace_Fun_Call_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Inplace_Fun_Call, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : + AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } + virtual ~Inplace_Fun_Call_AST_Node() {} + virtual Boxed_Value eval(Dispatch_Engine &ss){ + Param_List_Builder plb; + + if ((this->children.size() > 1) && (this->children[1]->identifier == AST_Node_Type::Arg_List)) { + for (size_t i = 0; i < this->children[1]->children.size(); ++i) { try { - cond = boxed_cast(this->children[i+1]->eval(ss)); - } - catch (const bad_boxed_cast &) { - throw Eval_Error("'else if' condition not boolean"); + plb << this->children[1]->children[i]->eval(ss); } catch (Eval_Error &ee) { - ee.call_stack.push_back(this->children[i+1]); + ee.call_stack.push_back(this->children[1]->children[i]); throw; } - if (cond) { + } + } + + try { + Boxed_Value fn = this->children[0]->eval(ss); + + try { + return (*boxed_cast(fn))(plb); + } + catch(const dispatch_error &e){ + throw Eval_Error(std::string(e.what()) + " with function '" + this->children[0]->text + "'"); + } + catch(Return_Value &rv) { + return rv.retval; + } + catch(...) { + throw; + } + } + catch(Eval_Error &ee) { + ee.call_stack.push_back(this->children[0]); + throw Eval_Error(ee.reason); + } + + } + + }; + + struct Arg_List_AST_Node : public AST_Node { + public: + Arg_List_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Arg_List, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : + AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } + virtual ~Arg_List_AST_Node() {} + }; + + struct Variable_AST_Node : public AST_Node { + public: + Variable_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Variable, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : + AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } + virtual ~Variable_AST_Node() {} + }; + + struct Equation_AST_Node : public AST_Node { + public: + Equation_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Equation, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : + AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } + virtual ~Equation_AST_Node() {} + virtual Boxed_Value eval(Dispatch_Engine &ss){ + Boxed_Value retval; + try { + retval = this->children.back()->eval(ss); + } + catch (Eval_Error &ee) { + ee.call_stack.push_back(this->children.back()); + throw; + } + + if (this->children.size() > 1) { + for (int i = this->children.size()-3; i >= 0; i -= 2) { + if (this->children[i+1]->text == "=") { try { - return this->children[i+2]->eval(ss); + Boxed_Value lhs = this->children[i]->eval(ss); + + try { + if (lhs.is_undef()) { + retval = ss.call_function("clone", retval); + retval.clear_dependencies(); + } + + try { + retval = ss.call_function(this->children[i+1]->text, lhs, retval); + } + catch(const dispatch_error &){ + throw Eval_Error(std::string("Mismatched types in equation") + (lhs.is_const()?", lhs is const.":".")); + } + } + catch(const dispatch_error &){ + throw Eval_Error("Can not clone right hand side of equation"); + } + } + catch(Eval_Error &ee) { + ee.call_stack.push_back(this->children[i]); + throw; + } + } + else if (this->children[i+1]->text == ":=") { + try { + Boxed_Value lhs = this->children[i]->eval(ss); + if (lhs.is_undef() || type_match(lhs, retval)) { + lhs.assign(retval); + } + else { + throw Eval_Error("Mismatched types in equation"); + } } catch (Eval_Error &ee) { - ee.call_stack.push_back(this->children[i+2]); + ee.call_stack.push_back(this->children[i]); + throw; + } + } + else { + try { + retval = ss.call_function(this->children[i+1]->text, this->children[i]->eval(ss), retval); + } + catch(const dispatch_error &){ + throw Eval_Error("Can not find appropriate '" + this->children[i+1]->text + "'"); + } + catch(Eval_Error &ee) { + ee.call_stack.push_back(this->children[i]); throw; } } } - i = i + 3; } + return retval; } - } + }; - return Boxed_Value(false); - } - - /** - * Evaluates a while block - */ - Boxed_Value While_AST_Node::eval(Dispatch_Engine &ss) { - bool cond; - - ss.new_scope(); - - try { - cond = boxed_cast(this->children[0]->eval(ss)); - } - catch (const bad_boxed_cast &) { - ss.pop_scope(); - throw Eval_Error("While condition not boolean"); - } - catch (Eval_Error &ee) { - ee.call_stack.push_back(this->children[0]); - ss.pop_scope(); - throw; - } - while (cond) { - try { + struct Var_Decl_AST_Node : public AST_Node { + public: + Var_Decl_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Var_Decl, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : + AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } + virtual ~Var_Decl_AST_Node() {} + virtual Boxed_Value eval(Dispatch_Engine &ss){ try { - this->children[1]->eval(ss); + ss.add_object(this->children[0]->text, Boxed_Value()); + } + catch (reserved_word_error &) { + throw Eval_Error("Reserved word used as variable '" + this->children[0]->text + "'"); + } + return ss.get_object(this->children[0]->text); + } + + }; + + struct Comparison_AST_Node : public Binary_Operator_AST_Node { + public: + Comparison_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Comparison, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : + Binary_Operator_AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } + virtual ~Comparison_AST_Node() {} + }; + + struct Additive_AST_Node : public Binary_Operator_AST_Node { + public: + Additive_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Additive, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : + Binary_Operator_AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } + virtual ~Additive_AST_Node() {} + }; + + struct Multiplicative_AST_Node : public Binary_Operator_AST_Node { + public: + Multiplicative_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Multiplicative, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : + Binary_Operator_AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } + virtual ~Multiplicative_AST_Node() {} + }; + + struct Array_Call_AST_Node : public AST_Node { + public: + Array_Call_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Array_Call, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : + AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } + virtual ~Array_Call_AST_Node() {} + virtual Boxed_Value eval(Dispatch_Engine &ss){ + Boxed_Value retval; + + try { + retval = this->children[0]->eval(ss); } catch (Eval_Error &ee) { - ee.call_stack.push_back(this->children[1]); + ee.call_stack.push_back(this->children[0]); throw; } + for (size_t i = 1; i < this->children.size(); ++i) { + try { + retval = ss.call_function("[]", retval, this->children[i]->eval(ss)); + } + catch(std::out_of_range &) { + throw Eval_Error("Out of bounds exception"); + } + catch(const dispatch_error &){ + throw Eval_Error("Can not find appropriate array lookup '[]' "); + } + catch(Eval_Error &ee) { + ee.call_stack.push_back(this->children[i]); + throw; + } + } + + return retval; + } + }; + + struct Dot_Access_AST_Node : public AST_Node { + public: + Dot_Access_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Dot_Access, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : + AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } + virtual ~Dot_Access_AST_Node() {} + virtual Boxed_Value eval(Dispatch_Engine &ss){ + Boxed_Value retval; + try { + retval = this->children[0]->eval(ss); + } + catch (Eval_Error &ee) { + ee.call_stack.push_back(this->children[0]); + throw; + } + + if (this->children.size() > 1) { + for (size_t i = 2; i < this->children.size(); i+=2) { + Param_List_Builder plb; + plb << retval; + + if (this->children[i]->children.size() > 1) { + for (size_t j = 0; j < this->children[i]->children[1]->children.size(); ++j) { + try { + plb << this->children[i]->children[1]->children[j]->eval(ss); + } + catch (Eval_Error &ee) { + ee.call_stack.push_back(this->children[i]->children[1]->children[j]); + throw; + } + } + } + + std::string fun_name; + std::vector > funs; + if ((this->children[i]->identifier == AST_Node_Type::Fun_Call) || (this->children[i]->identifier == AST_Node_Type::Array_Call)) { + fun_name = this->children[i]->children[0]->text; + } + else { + fun_name = this->children[i]->text; + } + + Dispatch_Engine::Stack prev_stack = ss.get_stack(); + Dispatch_Engine::Stack new_stack = ss.new_stack(); + + try { + ss.set_stack(new_stack); + retval = ss.call_function(fun_name, plb); + ss.set_stack(prev_stack); + } + catch(const dispatch_error &e){ + ss.set_stack(prev_stack); + throw Eval_Error(std::string(e.what())); + } + catch(Return_Value &rv) { + ss.set_stack(prev_stack); + retval = rv.retval; + } + catch(...) { + ss.set_stack(prev_stack); + throw; + } + if (this->children[i]->identifier == AST_Node_Type::Array_Call) { + for (size_t j = 1; j < this->children[i]->children.size(); ++j) { + try { + retval = ss.call_function("[]", retval, this->children[i]->children[j]->eval(ss)); + } + catch(std::out_of_range &) { + throw Eval_Error("Out of bounds exception"); + } + catch(const dispatch_error &){ + throw Eval_Error("Can not find appropriate array lookup '[]' "); + } + catch(Eval_Error &ee) { + ee.call_stack.push_back(this->children[i]->children[j]); + throw; + } + } + } + } + } + + return retval; + } + + }; + + struct Quoted_String_AST_Node : public AST_Node { + public: + Quoted_String_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Quoted_String, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : + AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } + virtual ~Quoted_String_AST_Node() {} + virtual Boxed_Value eval(Dispatch_Engine &){ + return const_var(this->text); + } + + }; + + struct Single_Quoted_String_AST_Node : public AST_Node { + public: + Single_Quoted_String_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Single_Quoted_String, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : + AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } + virtual ~Single_Quoted_String_AST_Node() {} + virtual Boxed_Value eval(Dispatch_Engine &){ + return const_var(char(this->text[0])); + } + + }; + + struct Lambda_AST_Node : public AST_Node { + public: + Lambda_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Lambda, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : + AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } + virtual ~Lambda_AST_Node() {} + virtual Boxed_Value eval(Dispatch_Engine &ss){ + std::vector param_names; + size_t numparams = 0; + + if ((this->children.size() > 0) && (this->children[0]->identifier == AST_Node_Type::Arg_List)) { + numparams = this->children[0]->children.size(); + for (size_t i = 0; i < numparams; ++i) { + param_names.push_back(this->children[0]->children[i]->text); + } + + } + else { + //no parameters + numparams = 0; + } + + return Boxed_Value(Proxy_Function(new Dynamic_Proxy_Function + (boost::bind(&eval_function, boost::ref(ss), this->children.back(), param_names, _1), + numparams))); + } + + }; + + struct Block_AST_Node : public AST_Node { + public: + Block_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Block, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : + AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } + virtual ~Block_AST_Node() {} + virtual Boxed_Value eval(Dispatch_Engine &ss){ + unsigned int num_children = this->children.size(); + + ss.new_scope(); + for (size_t i = 0; i < num_children; ++i) { + try { + const Boxed_Value &retval = this->children[i]->eval(ss); + + if (i + 1 == num_children) + { + ss.pop_scope(); + return retval; + } + } + catch (const chaiscript::Return_Value &) { + ss.pop_scope(); + throw; + } + catch (Eval_Error &ee) { + ee.call_stack.push_back(this->children[i]); + ss.pop_scope(); + throw; + } + catch (...) { + ss.pop_scope(); + throw; + } + } + + ss.pop_scope(); + return Boxed_Value(); + } + + }; + + struct Def_AST_Node : public AST_Node { + public: + Def_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Def, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : + AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } + virtual ~Def_AST_Node() {} + virtual Boxed_Value eval(Dispatch_Engine &ss){ + std::vector param_names; + size_t numparams = 0; + AST_NodePtr guardnode; + + if ((this->children.size() > 2) && (this->children[1]->identifier == AST_Node_Type::Arg_List)) { + numparams = this->children[1]->children.size(); + for (size_t i = 0; i < numparams; ++i) { + param_names.push_back(this->children[1]->children[i]->text); + } + + if (this->children.size() > 3) { + guardnode = this->children[2]; + } + } + else { + //no parameters + numparams = 0; + + if (this->children.size() > 2) { + guardnode = this->children[1]; + } + } + + boost::shared_ptr guard; + if (guardnode) { + guard = boost::shared_ptr + (new Dynamic_Proxy_Function(boost::bind(&eval_function, + boost::ref(ss), guardnode, + param_names, _1), numparams)); + } + + try { + const std::string & function_name = this->children[0]->text; + const std::string & annotation = this->annotation?this->annotation->text:""; + ss.add(Proxy_Function + (new Dynamic_Proxy_Function(boost::bind(&eval_function, + boost::ref(ss), this->children.back(), + param_names, _1), numparams, + annotation, guard)), function_name); + } + catch (reserved_word_error &e) { + throw Eval_Error("Reserved word used as function name '" + e.word + "'"); + } + return Boxed_Value(); + } + + }; + + struct While_AST_Node : public AST_Node { + public: + While_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::While, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : + AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } + virtual ~While_AST_Node() {} + virtual Boxed_Value eval(Dispatch_Engine &ss){ + bool cond; + + ss.new_scope(); + try { cond = boxed_cast(this->children[0]->eval(ss)); } @@ -935,77 +672,60 @@ namespace chaiscript ss.pop_scope(); throw; } - } - catch (Break_Loop &) { - cond = false; - } - } - ss.pop_scope(); - return Boxed_Value(); - } + while (cond) { + try { + try { + this->children[1]->eval(ss); + } + catch (Eval_Error &ee) { + ee.call_stack.push_back(this->children[1]); + throw; + } - /** - * Evaluates a for block, including the for's conditions, from left to right - */ - Boxed_Value For_AST_Node::eval(Dispatch_Engine &ss) { - bool cond; - - ss.new_scope(); - - try { - if (this->children.size() == 4) { - try { - this->children[0]->eval(ss); - } - catch (Eval_Error &ee) { - ee.call_stack.push_back(this->children[0]); - throw; - } - - try { - cond = boxed_cast(this->children[1]->eval(ss)); - } - catch (Eval_Error &ee) { - ee.call_stack.push_back(this->children[1]); - throw; + try { + cond = boxed_cast(this->children[0]->eval(ss)); + } + catch (const bad_boxed_cast &) { + ss.pop_scope(); + throw Eval_Error("While condition not boolean"); + } + catch (Eval_Error &ee) { + ee.call_stack.push_back(this->children[0]); + ss.pop_scope(); + throw; + } + } + catch (Break_Loop &) { + cond = false; + } } + ss.pop_scope(); + return Boxed_Value(); } - else { + ; + }; + + struct If_AST_Node : public AST_Node { + public: + If_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::If, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : + AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } + virtual ~If_AST_Node() {} + virtual Boxed_Value eval(Dispatch_Engine &ss){ + bool cond; try { cond = boxed_cast(this->children[0]->eval(ss)); } + catch (const bad_boxed_cast &) { + throw Eval_Error("If condition not boolean"); + } catch (Eval_Error &ee) { ee.call_stack.push_back(this->children[0]); - ss.pop_scope(); throw; } - } - } - catch (const bad_boxed_cast &) { - ss.pop_scope(); - throw Eval_Error("For condition not boolean"); - } - while (cond) { - try { - if (this->children.size() == 4) { - try { - this->children[3]->eval(ss); - } - catch (Eval_Error &ee) { - ee.call_stack.push_back(this->children[3]); - throw; - } + if (cond) { try { - this->children[2]->eval(ss); - } - catch (Eval_Error &ee) { - ee.call_stack.push_back(this->children[2]); - throw; - } - - try { - cond = boxed_cast(this->children[1]->eval(ss)); + return this->children[1]->eval(ss); } catch (Eval_Error &ee) { ee.call_stack.push_back(this->children[1]); @@ -1013,250 +733,783 @@ namespace chaiscript } } else { - try { - this->children[2]->eval(ss); - } - catch (Eval_Error &ee) { - ee.call_stack.push_back(this->children[2]); - throw; + if (this->children.size() > 2) { + size_t i = 2; + while ((!cond) && (i < this->children.size())) { + if (this->children[i]->text == "else") { + try { + return this->children[i+1]->eval(ss); + } + catch (Eval_Error &ee) { + ee.call_stack.push_back(this->children[i+1]); + throw; + } + } + else if (this->children[i]->text == "else if") { + try { + cond = boxed_cast(this->children[i+1]->eval(ss)); + } + catch (const bad_boxed_cast &) { + throw Eval_Error("'else if' condition not boolean"); + } + catch (Eval_Error &ee) { + ee.call_stack.push_back(this->children[i+1]); + throw; + } + if (cond) { + try { + return this->children[i+2]->eval(ss); + } + catch (Eval_Error &ee) { + ee.call_stack.push_back(this->children[i+2]); + throw; + } + } + } + i = i + 3; + } } + } - try { - this->children[1]->eval(ss); + return Boxed_Value(false); + } + + }; + + struct For_AST_Node : public AST_Node { + public: + For_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::For, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : + AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } + virtual ~For_AST_Node() {} + virtual Boxed_Value eval(Dispatch_Engine &ss){ + bool cond; + + ss.new_scope(); + + try { + if (this->children.size() == 4) { + try { + this->children[0]->eval(ss); + } + catch (Eval_Error &ee) { + ee.call_stack.push_back(this->children[0]); + throw; + } + + try { + cond = boxed_cast(this->children[1]->eval(ss)); + } + catch (Eval_Error &ee) { + ee.call_stack.push_back(this->children[1]); + throw; + } } - catch (Eval_Error &ee) { - ee.call_stack.push_back(this->children[1]); - throw; + else { + try { + cond = boxed_cast(this->children[0]->eval(ss)); + } + catch (Eval_Error &ee) { + ee.call_stack.push_back(this->children[0]); + ss.pop_scope(); + throw; + } } - + } + catch (const bad_boxed_cast &) { + ss.pop_scope(); + throw Eval_Error("For condition not boolean"); + } + while (cond) { try { - cond = boxed_cast(this->children[0]->eval(ss)); + if (this->children.size() == 4) { + try { + this->children[3]->eval(ss); + } + catch (Eval_Error &ee) { + ee.call_stack.push_back(this->children[3]); + throw; + } + + try { + this->children[2]->eval(ss); + } + catch (Eval_Error &ee) { + ee.call_stack.push_back(this->children[2]); + throw; + } + + try { + cond = boxed_cast(this->children[1]->eval(ss)); + } + catch (Eval_Error &ee) { + ee.call_stack.push_back(this->children[1]); + throw; + } + } + else { + try { + this->children[2]->eval(ss); + } + catch (Eval_Error &ee) { + ee.call_stack.push_back(this->children[2]); + throw; + } + + try { + this->children[1]->eval(ss); + } + catch (Eval_Error &ee) { + ee.call_stack.push_back(this->children[1]); + throw; + } + + try { + cond = boxed_cast(this->children[0]->eval(ss)); + } + catch (Eval_Error &ee) { + ee.call_stack.push_back(this->children[0]); + ss.pop_scope(); + throw; + } + } + } + catch (const bad_boxed_cast &) { + ss.pop_scope(); + throw Eval_Error("For condition not boolean"); + } + catch (Break_Loop &) { + cond = false; + } + } + ss.pop_scope(); + return Boxed_Value(); + } + + }; + + struct Inline_Array_AST_Node : public AST_Node { + public: + Inline_Array_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Inline_Array, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : + AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } + virtual ~Inline_Array_AST_Node() {} + virtual Boxed_Value eval(Dispatch_Engine &ss){ + std::vector vec; + if (this->children.size() > 0) { + for (size_t i = 0; i < this->children[0]->children.size(); ++i) { + try { + vec.push_back(this->children[0]->children[i]->eval(ss)); + } + catch(Eval_Error &ee) { + ee.call_stack.push_back(this->children[0]->children[i]); + throw; + } + } + } + + return const_var(vec); + } + + }; + + struct Inline_Map_AST_Node : public AST_Node { + public: + Inline_Map_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Inline_Map, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : + AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } + virtual ~Inline_Map_AST_Node() {} + virtual Boxed_Value eval(Dispatch_Engine &ss){ + try { + std::map retval; + for (size_t i = 0; i < this->children[0]->children.size(); ++i) { + try { + retval[boxed_cast(this->children[0]->children[i]->children[0]->eval(ss))] + = ss.call_function("clone", this->children[0]->children[i]->children[1]->eval(ss)); + } + catch(Eval_Error &ee) { + ee.call_stack.push_back(this->children[0]->children[i]); + throw; + } + } + return const_var(retval); + } + catch (const dispatch_error &) { + throw Eval_Error("Can not find appropriate 'Map()'"); + } + } + + }; + + struct Return_AST_Node : public AST_Node { + public: + Return_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Return, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : + AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } + virtual ~Return_AST_Node() {} + virtual Boxed_Value eval(Dispatch_Engine &ss){ + if (this->children.size() > 0) { + try { + throw Return_Value(this->children[0]->eval(ss)); } catch (Eval_Error &ee) { ee.call_stack.push_back(this->children[0]); + throw; + } + } + else { + throw Return_Value(Boxed_Value()); + } + } + + }; + + struct File_AST_Node : public AST_Node { + public: + File_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::File, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : + AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } + virtual ~File_AST_Node() {} + virtual Boxed_Value eval(Dispatch_Engine &ss) { + const unsigned int size = this->children.size(); + for (unsigned int i = 0; i < size; ++i) { + try { + const Boxed_Value &retval = this->children[i]->eval(ss); + if (i + 1 == size) { + return retval; + } + } + catch (Eval_Error &ee) { + ee.call_stack.push_back(this->children[i]); + throw; + } + } + return Boxed_Value(); + } + }; + + struct Prefix_AST_Node : public AST_Node { + public: + Prefix_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Prefix, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : + AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } + virtual ~Prefix_AST_Node() {} + virtual Boxed_Value eval(Dispatch_Engine &ss){ + try { + return ss.call_function(this->children[0]->text, this->children[1]->eval(ss)); + } + catch(std::exception &){ + throw Eval_Error("Can not find appropriate unary '" + this->children[0]->text + "'"); + } + } + + }; + + struct Break_AST_Node : public AST_Node { + public: + Break_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Break, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : + AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } + virtual ~Break_AST_Node() {} + virtual Boxed_Value eval(Dispatch_Engine &){ + throw Break_Loop(); + } + }; + + struct Map_Pair_AST_Node : public AST_Node { + public: + Map_Pair_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Map_Pair, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : + AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } + virtual ~Map_Pair_AST_Node() {} + }; + + struct Value_Range_AST_Node : public AST_Node { + public: + Value_Range_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Value_Range, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : + AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } + virtual ~Value_Range_AST_Node() {} + }; + + struct Inline_Range_AST_Node : public AST_Node { + public: + Inline_Range_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Inline_Range, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : + AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } + virtual ~Inline_Range_AST_Node() {} + virtual Boxed_Value eval(Dispatch_Engine &ss){ + try { + return ss.call_function("generate_range", + this->children[0]->children[0]->children[0]->eval(ss), + this->children[0]->children[0]->children[1]->eval(ss)); + } + catch (const dispatch_error &) { + throw Eval_Error("Unable to generate range vector"); + } + catch(Eval_Error &ee) { + ee.call_stack.push_back(this->children[0]->children[0]); + throw; + } + } + + }; + + struct Annotation_AST_Node : public AST_Node { + public: + Annotation_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Annotation, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : + AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } + virtual ~Annotation_AST_Node() {} + }; + + struct Try_AST_Node : public AST_Node { + public: + Try_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Try, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : + AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } + virtual ~Try_AST_Node() {} + virtual Boxed_Value eval(Dispatch_Engine &ss){ + Boxed_Value retval; + + ss.new_scope(); + try { + retval = this->children[0]->eval(ss); + } + catch (Eval_Error &ee) { + ee.call_stack.push_back(this->children[0]); + if (this->children.back()->identifier == AST_Node_Type::Finally) { + try { + this->children.back()->children[0]->eval(ss); + } + catch (Eval_Error &ee) { + ee.call_stack.push_back(this->children.back()->children[0]); + ss.pop_scope(); + throw; + } + } + ss.pop_scope(); + throw; + } + catch (const std::exception &e) { + Boxed_Value except = Boxed_Value(boost::ref(e)); + + unsigned int end_point = this->children.size(); + if (this->children.back()->identifier == AST_Node_Type::Finally) { + end_point = this->children.size() - 1; + } + for (unsigned int i = 1; i < end_point; ++i) { + AST_NodePtr catch_block = this->children[i]; + + if (catch_block->children.size() == 1) { + //No variable capture, no guards + try { + retval = catch_block->children[0]->eval(ss); + } + catch (Eval_Error &ee) { + ee.call_stack.push_back(catch_block->children[0]); + throw; + } + break; + } + else if (catch_block->children.size() == 2) { + //Variable capture, no guards + ss.add_object(catch_block->children[0]->text, except); + try { + retval = catch_block->children[1]->eval(ss); + } + catch (Eval_Error &ee) { + ee.call_stack.push_back(catch_block->children[1]); + throw; + } + + 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(catch_block->children[1]->eval(ss)); + } catch (const bad_boxed_cast &) { + if (this->children.back()->identifier == AST_Node_Type::Finally) { + try { + this->children.back()->children[0]->eval(ss); + } + catch (Eval_Error &ee) { + ee.call_stack.push_back(this->children.back()->children[0]); + ss.pop_scope(); + throw; + } + } + ss.pop_scope(); + throw Eval_Error("Guard condition not boolean"); + } + if (guard) { + try { + retval = catch_block->children[2]->eval(ss); + } + catch (Eval_Error &ee) { + ee.call_stack.push_back(catch_block->children[2]); + throw; + } + + break; + } + } + else { + if (this->children.back()->identifier == AST_Node_Type::Finally) { + try { + this->children.back()->children[0]->eval(ss); + } + catch (Eval_Error &ee) { + ee.call_stack.push_back(this->children.back()->children[0]); + ss.pop_scope(); + throw; + } + } + ss.pop_scope(); + throw Eval_Error("Internal error: catch block size unrecognized"); + } + } + } + catch (Boxed_Value &bv) { + Boxed_Value except = bv; + for (size_t i = 1; i < this->children.size(); ++i) { + AST_NodePtr catch_block = this->children[i]; + + if (catch_block->children.size() == 1) { + //No variable capture, no guards + try { + retval = catch_block->children[0]->eval(ss); + } + catch (Eval_Error &ee) { + ee.call_stack.push_back(catch_block->children[0]); + throw; + } + + break; + } + else if (catch_block->children.size() == 2) { + //Variable capture, no guards + ss.add_object(catch_block->children[0]->text, except); + try { + retval = catch_block->children[1]->eval(ss); + } + catch (Eval_Error &ee) { + ee.call_stack.push_back(catch_block->children[1]); + throw; + } + + 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(catch_block->children[1]->eval(ss)); + } + catch (const bad_boxed_cast &) { + if (this->children.back()->identifier == AST_Node_Type::Finally) { + try { + this->children.back()->children[0]->eval(ss); + } + catch (Eval_Error &ee) { + ee.call_stack.push_back(this->children.back()->children[0]); + ss.pop_scope(); + throw; + } + } + + ss.pop_scope(); + throw Eval_Error("Guard condition not boolean"); + } + catch (Eval_Error &ee) { + ee.call_stack.push_back(catch_block->children[1]); + throw; + } + if (guard) { + try { + retval = catch_block->children[2]->eval(ss); + } + catch (Eval_Error &ee) { + ee.call_stack.push_back(catch_block->children[2]); + throw; + } + break; + } + } + else { + if (this->children.back()->identifier == AST_Node_Type::Finally) { + try { + this->children.back()->children[0]->eval(ss); + } + catch (Eval_Error &ee) { + ee.call_stack.push_back(this->children.back()->children[0]); + ss.pop_scope(); + throw; + } + } + ss.pop_scope(); + throw Eval_Error("Internal error: catch block size unrecognized"); + } + } + } + catch (...) { + if (this->children.back()->identifier == AST_Node_Type::Finally) { + try { + this->children.back()->children[0]->eval(ss); + } + catch (Eval_Error &ee) { + ee.call_stack.push_back(this->children.back()->children[0]); + ss.pop_scope(); + throw; + } + } + ss.pop_scope(); + throw; + } + + if (this->children.back()->identifier == AST_Node_Type::Finally) { + try { + retval = this->children.back()->children[0]->eval(ss); + } + catch (Eval_Error &ee) { + ee.call_stack.push_back(this->children.back()->children[0]); ss.pop_scope(); throw; } } - } - catch (const bad_boxed_cast &) { + ss.pop_scope(); - throw Eval_Error("For condition not boolean"); - } - catch (Break_Loop &) { - cond = false; - } - } - ss.pop_scope(); - return Boxed_Value(); - } - /** - * Evaluates a function definition - */ - Boxed_Value Def_AST_Node::eval(Dispatch_Engine &ss) { - std::vector param_names; - size_t numparams = 0; - AST_NodePtr guardnode; - - if ((this->children.size() > 2) && (this->children[1]->identifier == AST_Node_Type::Arg_List)) { - numparams = this->children[1]->children.size(); - for (size_t i = 0; i < numparams; ++i) { - param_names.push_back(this->children[1]->children[i]->text); + return retval; } - if (this->children.size() > 3) { - guardnode = this->children[2]; - } - } - else { - //no parameters - numparams = 0; + }; - if (this->children.size() > 2) { - guardnode = this->children[1]; - } - } + struct Catch_AST_Node : public AST_Node { + public: + Catch_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Catch, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : + AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } + virtual ~Catch_AST_Node() {} + }; - boost::shared_ptr guard; - if (guardnode) { - guard = boost::shared_ptr - (new Dynamic_Proxy_Function(boost::bind(&eval_function, - boost::ref(ss), guardnode, - param_names, _1), numparams)); - } + struct Finally_AST_Node : public AST_Node { + public: + Finally_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Finally, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : + AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } + virtual ~Finally_AST_Node() {} + }; - try { - const std::string & function_name = this->children[0]->text; - const std::string & annotation = this->annotation?this->annotation->text:""; - ss.add(Proxy_Function - (new Dynamic_Proxy_Function(boost::bind(&eval_function, - boost::ref(ss), this->children.back(), - param_names, _1), numparams, - annotation, guard)), function_name); - } - catch (reserved_word_error &e) { - throw Eval_Error("Reserved word used as function name '" + e.word + "'"); - } - return Boxed_Value(); - } + struct Method_AST_Node : public AST_Node { + public: + Method_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Method, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : + AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } + virtual ~Method_AST_Node() {} + virtual Boxed_Value eval(Dispatch_Engine &ss){ - /** - * Evaluates a function definition - */ - Boxed_Value Method_AST_Node::eval(Dispatch_Engine &ss) { + std::vector param_names; + AST_NodePtr guardnode; - std::vector param_names; - AST_NodePtr guardnode; + //The first param of a method is always the implied this ptr. + param_names.push_back("this"); - //The first param of a method is always the implied this ptr. - param_names.push_back("this"); - - if ((this->children.size() > 3) && (this->children[2]->identifier == AST_Node_Type::Arg_List)) { - for (size_t i = 0; i < this->children[2]->children.size(); ++i) { - param_names.push_back(this->children[2]->children[i]->text); - } - - if (this->children.size() > 4) { - guardnode = this->children[3]; - } - } - else { - //no parameters - - if (this->children.size() > 3) { - guardnode = this->children[2]; - } - } - - size_t numparams = param_names.size(); - - boost::shared_ptr guard; - if (guardnode) { - guard = boost::shared_ptr - (new Dynamic_Proxy_Function(boost::bind(&eval_function, - boost::ref(ss), guardnode, - param_names, _1), numparams)); - } - - try { - const std::string & annotation = this->annotation?this->annotation->text:""; - const std::string & class_name = this->children[0]->text; - const std::string & function_name = this->children[1]->text; - if (function_name == class_name) { - ss.add(Proxy_Function - (new Dynamic_Object_Constructor(class_name, Proxy_Function - (new Dynamic_Proxy_Function(boost::bind(&eval_function, - boost::ref(ss), this->children.back(), - param_names, _1), numparams, - annotation, guard)))), function_name); - - } - else { - boost::optional ti; - try { - ti = ss.get_type(class_name); - } catch (const std::range_error &) { - // No biggie, the type name is just not known - } - ss.add(Proxy_Function - (new Dynamic_Object_Function(class_name, Proxy_Function - (new Dynamic_Proxy_Function(boost::bind(&eval_function, - boost::ref(ss), this->children.back(), - param_names, _1), numparams, - annotation, guard)), ti)), function_name); - - } - } - catch (reserved_word_error &e) { - throw Eval_Error("Reserved word used as method name '" + e.word + "'"); - } - return Boxed_Value(); - } - - /** - * Evaluates a lambda (anonymous function) - */ - Boxed_Value Lambda_AST_Node::eval(Dispatch_Engine &ss) { - std::vector param_names; - size_t numparams = 0; - - if ((this->children.size() > 0) && (this->children[0]->identifier == AST_Node_Type::Arg_List)) { - numparams = this->children[0]->children.size(); - for (size_t i = 0; i < numparams; ++i) { - param_names.push_back(this->children[0]->children[i]->text); - } - - } - else { - //no parameters - numparams = 0; - } - - return Boxed_Value(Proxy_Function(new Dynamic_Proxy_Function - (boost::bind(&eval_function, boost::ref(ss), this->children.back(), param_names, _1), - numparams))); - } - - /** - * Evaluates a scoped block. Handles resetting the scope after the block has completed. - */ - Boxed_Value Block_AST_Node::eval(Dispatch_Engine &ss) { - unsigned int num_children = this->children.size(); - - ss.new_scope(); - for (size_t i = 0; i < num_children; ++i) { - try { - const Boxed_Value &retval = this->children[i]->eval(ss); - - if (i + 1 == num_children) - { - ss.pop_scope(); - return retval; + if ((this->children.size() > 3) && (this->children[2]->identifier == AST_Node_Type::Arg_List)) { + for (size_t i = 0; i < this->children[2]->children.size(); ++i) { + param_names.push_back(this->children[2]->children[i]->text); } - } - catch (const chaiscript::Return_Value &) { - ss.pop_scope(); - throw; - } - catch (Eval_Error &ee) { - ee.call_stack.push_back(this->children[i]); - ss.pop_scope(); - throw; - } - catch (...) { - ss.pop_scope(); - throw; - } - } - ss.pop_scope(); - return Boxed_Value(); - } + if (this->children.size() > 4) { + guardnode = this->children[3]; + } + } + else { + //no parameters + + if (this->children.size() > 3) { + guardnode = this->children[2]; + } + } + + size_t numparams = param_names.size(); + + boost::shared_ptr guard; + if (guardnode) { + guard = boost::shared_ptr + (new Dynamic_Proxy_Function(boost::bind(&eval_function, + boost::ref(ss), guardnode, + param_names, _1), numparams)); + } + + try { + const std::string & annotation = this->annotation?this->annotation->text:""; + const std::string & class_name = this->children[0]->text; + const std::string & function_name = this->children[1]->text; + if (function_name == class_name) { + ss.add(Proxy_Function + (new Dynamic_Object_Constructor(class_name, Proxy_Function + (new Dynamic_Proxy_Function(boost::bind(&eval_function, + boost::ref(ss), this->children.back(), + param_names, _1), numparams, + annotation, guard)))), function_name); + + } + else { + boost::optional ti; + try { + ti = ss.get_type(class_name); + } catch (const std::range_error &) { + // No biggie, the type name is just not known + } + ss.add(Proxy_Function + (new Dynamic_Object_Function(class_name, Proxy_Function + (new Dynamic_Proxy_Function(boost::bind(&eval_function, + boost::ref(ss), this->children.back(), + param_names, _1), numparams, + annotation, guard)), ti)), function_name); + + } + } + catch (reserved_word_error &e) { + throw Eval_Error("Reserved word used as method name '" + e.word + "'"); + } + return Boxed_Value(); + } + + }; + + struct Attr_Decl_AST_Node : public AST_Node { + public: + Attr_Decl_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Attr_Decl, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : + AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } + virtual ~Attr_Decl_AST_Node() {} + virtual Boxed_Value eval(Dispatch_Engine &ss){ + try { + ss.add(fun(boost::function(boost::bind(&Dynamic_Object_Attribute::func, this->children[0]->text, + this->children[1]->text, _1))), this->children[1]->text); + + } + catch (reserved_word_error &) { + throw Eval_Error("Reserved word used as attribute '" + this->children[1]->text + "'"); + } + return Boxed_Value(); + } + + }; + + struct Shift_AST_Node : public Binary_Operator_AST_Node { + public: + Shift_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Shift, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : + Binary_Operator_AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } + virtual ~Shift_AST_Node() {} + }; + + struct Equality_AST_Node : public Binary_Operator_AST_Node { + public: + Equality_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Equality, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : + Binary_Operator_AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } + virtual ~Equality_AST_Node() {} + }; + + struct Bitwise_And_AST_Node : public Binary_Operator_AST_Node { + public: + Bitwise_And_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Bitwise_And, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : + Binary_Operator_AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } + virtual ~Bitwise_And_AST_Node() {} + }; + + struct Bitwise_Xor_AST_Node : public Binary_Operator_AST_Node { + public: + Bitwise_Xor_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Bitwise_Xor, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : + Binary_Operator_AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } + virtual ~Bitwise_Xor_AST_Node() {} + }; + + struct Bitwise_Or_AST_Node : public Binary_Operator_AST_Node { + public: + Bitwise_Or_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Bitwise_Or, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : + Binary_Operator_AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } + virtual ~Bitwise_Or_AST_Node() {} + }; + + struct Logical_And_AST_Node : public AST_Node { + public: + Logical_And_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Logical_And, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : + AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } + virtual ~Logical_And_AST_Node() {} + virtual Boxed_Value eval(Dispatch_Engine &ss){ + Boxed_Value retval; + try { + retval = this->children[0]->eval(ss); + } + catch (Eval_Error &ee) { + ee.call_stack.push_back(this->children[0]); + throw; + } + + if (this->children.size() > 1) { + for (size_t i = 1; i < this->children.size(); i += 2) { + bool lhs; + try { + lhs = boxed_cast(retval); + } + catch (const bad_boxed_cast &) { + throw Eval_Error("Condition not boolean"); + } + if (lhs) { + try { + retval = this->children[i+1]->eval(ss); + } + catch (Eval_Error &ee) { + ee.call_stack.push_back(this->children[i+1]); + throw; + } + } + else { + retval = Boxed_Value(false); + } + } + } + return retval; + } + }; + + struct Logical_Or_AST_Node : public AST_Node { + public: + Logical_Or_AST_Node(const std::string &ast_node_text = "", int id = AST_Node_Type::Logical_Or, const char *fname = NULL, int start_line = 0, int start_col = 0, int end_line = 0, int end_col = 0) : + AST_Node(ast_node_text, id, fname, start_line, start_col, end_line, end_col) { } + virtual ~Logical_Or_AST_Node() {} + virtual Boxed_Value eval(Dispatch_Engine &ss){ + Boxed_Value retval; + + try { + retval = this->children[0]->eval(ss); + } + catch (Eval_Error &ee) { + ee.call_stack.push_back(this->children[0]); + throw; + } + + if (this->children.size() > 1) { + for (size_t i = 1; i < this->children.size(); i += 2) { + bool lhs; + try { + lhs = boxed_cast(retval); + } + catch (const bad_boxed_cast &) { + throw Eval_Error("Condition not boolean"); + } + if (lhs) { + retval = Boxed_Value(true); + } + else { + try { + retval = this->children[i+1]->eval(ss); + } + catch (Eval_Error &ee) { + ee.call_stack.push_back(this->children[i+1]); + throw; + } + } + } + } + return retval; + } + + }; - /** - * Evaluates a return statement - */ - Boxed_Value Return_AST_Node::eval(Dispatch_Engine &ss) { - if (this->children.size() > 0) { - try { - throw Return_Value(this->children[0]->eval(ss)); - } - catch (Eval_Error &ee) { - ee.call_stack.push_back(this->children[0]); - throw; - } - } - else { - throw Return_Value(Boxed_Value()); - } - } - /** - * Evaluates a break statement - */ - Boxed_Value Break_AST_Node::eval(Dispatch_Engine &) { - throw Break_Loop(); - } } #endif /* CHAISCRIPT_EVAL_HPP_ */ diff --git a/unittests/multifile_test_chai.cpp b/unittests/multifile_test_chai.cpp new file mode 100644 index 0000000..57b8952 --- /dev/null +++ b/unittests/multifile_test_chai.cpp @@ -0,0 +1,12 @@ +#include "multifile_test_chai.hpp" + +Multi_Test_Chai::Multi_Test_Chai() + : m_chai(new chaiscript::ChaiScript()) +{ +} + + +boost::shared_ptr Multi_Test_Chai::get_chai() +{ + return m_chai; +} diff --git a/unittests/multifile_test_chai.hpp b/unittests/multifile_test_chai.hpp new file mode 100644 index 0000000..430b6bc --- /dev/null +++ b/unittests/multifile_test_chai.hpp @@ -0,0 +1,14 @@ +#include + +class Multi_Test_Chai +{ + public: + Multi_Test_Chai(); + + boost::shared_ptr get_chai(); + + private: + boost::shared_ptr m_chai; +}; + + diff --git a/unittests/multifile_test_main.cpp b/unittests/multifile_test_main.cpp new file mode 100644 index 0000000..8352ec8 --- /dev/null +++ b/unittests/multifile_test_main.cpp @@ -0,0 +1,14 @@ +#include "multifile_test_chai.hpp" +#include "multifile_test_module.hpp" + +#include + +int main() +{ + Multi_Test_Chai chaitest; + Multi_Test_Module chaimodule; + + boost::shared_ptr chai = chaitest.get_chai(); + chai->add(chaimodule.get_module()); + return chai->eval("get_module_value()"); +} diff --git a/unittests/multifile_test_module.cpp b/unittests/multifile_test_module.cpp new file mode 100644 index 0000000..2457416 --- /dev/null +++ b/unittests/multifile_test_module.cpp @@ -0,0 +1,21 @@ +#include + +#include "multifile_test_module.hpp" + +Multi_Test_Module::Multi_Test_Module() +{ +} + +int Multi_Test_Module::get_module_value() +{ + return 0; +} + +chaiscript::ModulePtr Multi_Test_Module::get_module() +{ + chaiscript::ModulePtr module(new chaiscript::Module()); + + module->add(chaiscript::fun(&Multi_Test_Module::get_module_value), "get_module_value"); + + return module; +} diff --git a/unittests/multifile_test_module.hpp b/unittests/multifile_test_module.hpp new file mode 100644 index 0000000..f01d8f1 --- /dev/null +++ b/unittests/multifile_test_module.hpp @@ -0,0 +1,11 @@ +#include + +class Multi_Test_Module +{ + public: + static int get_module_value(); + + Multi_Test_Module(); + + chaiscript::ModulePtr get_module(); +};