diff --git a/cheatsheet.md b/cheatsheet.md index dbaf5da..700d422 100644 --- a/cheatsheet.md +++ b/cheatsheet.md @@ -278,6 +278,18 @@ while (some_condition()) { /* do something */ } for (x : [1,2,3]) { print(i); } ``` +## Conditionals + +``` +if (expression) { } +``` + +``` +// C++17-style init-if blocks +// Value of 'statement' is scoped for entire `if` block +if (statement; expression) { } +``` + ## Built in Types ``` diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index 717a3b3..ee9eba7 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -823,6 +823,29 @@ namespace chaiscript }; + template + struct If_Init_AST_Node final : AST_Node_Impl { + If_Init_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : + AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::If, std::move(t_loc), std::move(t_children)) + { + assert(this->children.size() == 3 || this->children.size() == 4); + } + + Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { + chaiscript::eval::detail::Scope_Push_Pop spp(t_ss); + this->children[0]->eval(t_ss); + if (this->get_bool_condition(this->children[1]->eval(t_ss))) { + return this->children[2]->eval(t_ss); + } else { + if (this->children.size() == 4) { + return this->children[3]->eval(t_ss); + } else { + return void_var(); + } + } + } + }; + template struct If_AST_Node final : AST_Node_Impl { If_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index 5fc7e27..0601d90 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -1557,7 +1557,13 @@ namespace chaiscript throw exception::eval_error("Incomplete 'if' expression", File_Position(m_position.line, m_position.col), *m_filename); } - if (!(Operator() && Char(')'))) { + if (!Equation()) { + throw exception::eval_error("Incomplete 'if' expression", File_Position(m_position.line, m_position.col), *m_filename); + } + + const bool is_if_init = Eol() && Equation(); + + if (!Char(')')) { throw exception::eval_error("Incomplete 'if' expression", File_Position(m_position.line, m_position.col), *m_filename); } @@ -1585,7 +1591,11 @@ namespace chaiscript } } - build_match>(prev_stack_top); + if (!is_if_init) { + build_match>(prev_stack_top); + } else { + build_match>(prev_stack_top); + } } return retval; diff --git a/unittests/init_if.chai b/unittests/init_if.chai new file mode 100644 index 0000000..01c05c7 --- /dev/null +++ b/unittests/init_if.chai @@ -0,0 +1,7 @@ +if (var x = 2; x == 3) { + assert_true(false); +} else if (var y = 3; y == 6) { + assert_true(false); +} else { + assert_equal(5, y + x); +}