mirror of
https://github.com/ChaiScript/ChaiScript.git
synced 2025-12-06 16:57:04 +08:00
Fix up some error handling
This commit is contained in:
parent
e0f29e0f7c
commit
805e7c0917
@ -647,8 +647,6 @@ namespace chaiscript
|
|||||||
/// Special type for returned values
|
/// Special type for returned values
|
||||||
struct Return_Value {
|
struct Return_Value {
|
||||||
Boxed_Value retval;
|
Boxed_Value retval;
|
||||||
|
|
||||||
explicit Return_Value(Boxed_Value t_return_value) : retval(std::move(t_return_value)) { }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -448,19 +448,22 @@ namespace chaiscript
|
|||||||
Boxed_Value rhs = this->children[1]->eval(t_ss);
|
Boxed_Value rhs = this->children[1]->eval(t_ss);
|
||||||
Boxed_Value lhs = this->children[0]->eval(t_ss);
|
Boxed_Value lhs = this->children[0]->eval(t_ss);
|
||||||
|
|
||||||
|
if (lhs.is_return_value()) {
|
||||||
|
throw exception::eval_error("Error, cannot assign to temporary value.");
|
||||||
|
} else if (lhs.is_const()) {
|
||||||
|
throw exception::eval_error("Error, cannot assign to constant value.");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (m_oper != Operators::Opers::invalid && lhs.get_type_info().is_arithmetic() &&
|
if (m_oper != Operators::Opers::invalid && lhs.get_type_info().is_arithmetic() &&
|
||||||
rhs.get_type_info().is_arithmetic())
|
rhs.get_type_info().is_arithmetic())
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
return Boxed_Number::do_oper(m_oper, lhs, rhs);
|
return Boxed_Number::do_oper(m_oper, lhs, rhs);
|
||||||
} catch (const std::exception &) {
|
} catch (const std::exception &) {
|
||||||
throw exception::eval_error("Error with unsupported arithmetic assignment operation");
|
throw exception::eval_error("Error with unsupported arithmetic assignment operation.");
|
||||||
}
|
}
|
||||||
} else if (m_oper == Operators::Opers::assign) {
|
} else if (m_oper == Operators::Opers::assign) {
|
||||||
if (lhs.is_return_value()) {
|
|
||||||
throw exception::eval_error("Error, cannot assign to temporary value.");
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
if (lhs.is_undef()) {
|
if (lhs.is_undef()) {
|
||||||
@ -1141,10 +1144,10 @@ namespace chaiscript
|
|||||||
|
|
||||||
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{
|
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{
|
||||||
if (!this->children.empty()) {
|
if (!this->children.empty()) {
|
||||||
throw detail::Return_Value(this->children[0]->eval(t_ss));
|
throw detail::Return_Value{this->children[0]->eval(t_ss)};
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
throw detail::Return_Value(void_var());
|
throw detail::Return_Value{void_var()};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -1201,6 +1204,10 @@ namespace chaiscript
|
|||||||
// short circuit arithmetic operations
|
// short circuit arithmetic operations
|
||||||
if (m_oper != Operators::Opers::invalid && m_oper != Operators::Opers::bitwise_and && bv.get_type_info().is_arithmetic())
|
if (m_oper != Operators::Opers::invalid && m_oper != Operators::Opers::bitwise_and && bv.get_type_info().is_arithmetic())
|
||||||
{
|
{
|
||||||
|
if ((m_oper == Operators::Opers::pre_increment || m_oper == Operators::Opers::pre_decrement) && bv.is_const())
|
||||||
|
{
|
||||||
|
throw exception::eval_error("Error with prefix operator evaluation: cannot modify constant value.");
|
||||||
|
}
|
||||||
return Boxed_Number::do_oper(m_oper, bv);
|
return Boxed_Number::do_oper(m_oper, bv);
|
||||||
} else {
|
} else {
|
||||||
chaiscript::eval::detail::Function_Push_Pop fpp(t_ss);
|
chaiscript::eval::detail::Function_Push_Pop fpp(t_ss);
|
||||||
|
|||||||
@ -356,7 +356,7 @@ namespace chaiscript {
|
|||||||
|
|
||||||
const auto make_constant = [&node, &fun_name](auto val){
|
const auto make_constant = [&node, &fun_name](auto val){
|
||||||
const auto match = fun_name + "(" + node->children[1]->children[0]->text + ")";
|
const auto match = fun_name + "(" + node->children[1]->children[0]->text + ")";
|
||||||
return chaiscript::make_unique<eval::AST_Node_Impl<T>, eval::Constant_AST_Node<T>>(std::move(match), node->location, Boxed_Value(val));
|
return chaiscript::make_unique<eval::AST_Node_Impl<T>, eval::Constant_AST_Node<T>>(std::move(match), node->location, const_var(val));
|
||||||
};
|
};
|
||||||
|
|
||||||
if (fun_name == "double") {
|
if (fun_name == "double") {
|
||||||
|
|||||||
@ -164,15 +164,15 @@ void help(int n) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool throws_exception(const std::function<void ()> &f)
|
std::string throws_exception(const std::function<void ()> &f)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
f();
|
f();
|
||||||
} catch (...) {
|
} catch (const std::exception &e) {
|
||||||
return true;
|
return e.what();
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
chaiscript::exception::eval_error get_eval_error(const std::function<void ()> &f)
|
chaiscript::exception::eval_error get_eval_error(const std::function<void ()> &f)
|
||||||
|
|||||||
@ -1,2 +1,2 @@
|
|||||||
assert_throws("Mismatched types in equation, lhs is const.", fun() { 1 = 2 } );
|
assert_throws("Error: \"Error, cannot assign to constant value.\"", fun() { 1 = 2 } );
|
||||||
assert_throws("Mismatched types in equation, lhs is const.", fun() { 1 + 2 = 2 } );
|
assert_throws("Error: \"Error, cannot assign to constant value.\"", fun() { 1 + 2 = 2 } );
|
||||||
|
|||||||
@ -66,10 +66,10 @@ var group = group_guard.get_contained_functions();
|
|||||||
assert_equal(true, group[0].has_guard())
|
assert_equal(true, group[0].has_guard())
|
||||||
assert_equal(false, group[1].has_guard())
|
assert_equal(false, group[1].has_guard())
|
||||||
|
|
||||||
assert_throws("Function does not have a guard", fun() { group[0].get_guard(); } );
|
assert_throws("Function does not have a guard", fun[group]() { group[1].get_guard(); } );
|
||||||
assert_throws("Function does not have a guard", fun() { without_guard.get_guard(); } );
|
assert_throws("Function does not have a guard", fun[without_guard]() { without_guard.get_guard(); } );
|
||||||
|
|
||||||
var guard = with_guard.get_guard();
|
var guard = with_guard.get_guard();
|
||||||
|
|
||||||
assert_equal(false, guard.has_guard());
|
assert_equal(false, guard.has_guard());
|
||||||
assert_throws("Function does not have a guard", fun() { guard.get_guard(); } );
|
assert_throws("Function does not have a guard", fun[guard]() { guard.get_guard(); } );
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
assert_throws("Illegal const function assignment", fun() { clone = `-` } );
|
assert_throws("Error: \"Error, cannot assign to constant value.\"", fun() { clone = `-` } );
|
||||||
|
|||||||
@ -1 +1,2 @@
|
|||||||
assert_throws("Invalid function reassignment", fun() { var x = 5; x = `-`; } );
|
assert_throws("Error: \"Unable to find appropriate'=' operator.\" With parameters: (int, const Function)", fun() { auto x = 5; x = `-`; } );
|
||||||
|
|
||||||
|
|||||||
@ -1,2 +1,8 @@
|
|||||||
|
|
||||||
assert_throws("Parse failure", fun() { eval("[\"hello\":5,\"j\",\"k\"]") } );
|
try {
|
||||||
|
eval("[\"hello\":5,\"j\",\"k\"]");
|
||||||
|
assert_true(false);
|
||||||
|
} catch (eval_error ee) {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -13,4 +13,4 @@ assert_equal(0, i -= i)
|
|||||||
assert_equal(3, j *= 1.5)
|
assert_equal(3, j *= 1.5)
|
||||||
assert_equal(1.5, j /= 2)
|
assert_equal(1.5, j /= 2)
|
||||||
assert_equal(2.5, j += 1)
|
assert_equal(2.5, j += 1)
|
||||||
assert_throws("No modulus for float", fun() { k % 2 } );
|
assert_throws("Error: \"Error with numeric operator calling: %\"", fun[k]() { k % 2 } );
|
||||||
|
|||||||
@ -1,2 +1,2 @@
|
|||||||
assert_throws("Mismatched types in equation, lhs is const.", fun() { 1 = 2 } );
|
assert_throws("Error: \"Error, cannot assign to constant value.\"", fun() { 1 = 2 } );
|
||||||
assert_throws("Mismatched types in equation, lhs is const.", fun() { 1 + 2 = 2 } );
|
assert_throws("Error: \"Error, cannot assign to constant value.\"", fun() { 1 + 2 = 2 } );
|
||||||
|
|||||||
@ -10,5 +10,7 @@ var o = MyClass();
|
|||||||
|
|
||||||
assert_true(o.is_explicit());
|
assert_true(o.is_explicit());
|
||||||
|
|
||||||
assert_throws("error", fun[o](){o.x = 2})
|
assert_throws("Error: \"'x' is not a function.\"", fun[o](){o.x = 2})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -66,10 +66,10 @@ auto group = group_guard.get_contained_functions();
|
|||||||
assert_equal(true, group[0].has_guard())
|
assert_equal(true, group[0].has_guard())
|
||||||
assert_equal(false, group[1].has_guard())
|
assert_equal(false, group[1].has_guard())
|
||||||
|
|
||||||
assert_throws("Function does not have a guard", fun() { group[0].get_guard(); } );
|
assert_throws("Function does not have a guard", fun[group]() { group[1].get_guard(); } );
|
||||||
assert_throws("Function does not have a guard", fun() { without_guard.get_guard(); } );
|
assert_throws("Function does not have a guard", fun[without_guard]() { without_guard.get_guard(); } );
|
||||||
|
|
||||||
auto guard = with_guard.get_guard();
|
auto guard = with_guard.get_guard();
|
||||||
|
|
||||||
assert_equal(false, guard.has_guard());
|
assert_equal(false, guard.has_guard());
|
||||||
assert_throws("Function does not have a guard", fun() { guard.get_guard(); } );
|
assert_throws("Function does not have a guard", fun[guard]() { guard.get_guard(); } );
|
||||||
|
|||||||
@ -1,2 +1,2 @@
|
|||||||
assert_throws("Function already defined", fun(){ def foo(x) { x + 1 }; def foo(x) { x + 1 } } );
|
assert_throws("Error: \"Function redefined 'foo'\"", fun(){ def foo(x) { x + 1 }; def foo(x) { x + 1 } } );
|
||||||
|
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
assert_throws("Illegal const function assignment", fun() { clone = `-` } );
|
assert_throws("Error: \"Error, cannot assign to constant value.\"", fun() { clone = `-` } );
|
||||||
|
|||||||
@ -1 +1,4 @@
|
|||||||
assert_throws("Invalid function reassignment", fun() { auto x = 5; x = `-`; } );
|
assert_throws("Error: \"Unable to find appropriate'=' operator.\" With parameters: (int, const Function)", fun() { auto x = 5; x = `-`; } );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -1,2 +1,8 @@
|
|||||||
|
|
||||||
assert_throws("Parse failure", fun() { eval("[\"hello\":5,\"j\",\"k\"]") } );
|
try {
|
||||||
|
eval("[\"hello\":5,\"j\",\"k\"]");
|
||||||
|
assert_true(false);
|
||||||
|
} catch (eval_error ee) {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -13,4 +13,6 @@ assert_equal(0, i -= i)
|
|||||||
assert_equal(3, j *= 1.5)
|
assert_equal(3, j *= 1.5)
|
||||||
assert_equal(1.5, j /= 2)
|
assert_equal(1.5, j /= 2)
|
||||||
assert_equal(2.5, j += 1)
|
assert_equal(2.5, j += 1)
|
||||||
assert_throws("No modulus for float", fun() { k % 2 } );
|
assert_throws("Error: \"Error with numeric operator calling: %\"", fun[k]() { k % 2 } );
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -29,3 +29,13 @@ assert_equal(2, j += 1);
|
|||||||
assert_equal(1, --j);
|
assert_equal(1, --j);
|
||||||
assert_equal(2, ++j);
|
assert_equal(2, ++j);
|
||||||
|
|
||||||
|
|
||||||
|
assert_throws("Error: \"Error with prefix operator evaluation: cannot modify constant value.\"", fun() { ++4; });
|
||||||
|
assert_throws("Error: \"Error with prefix operator evaluation: cannot modify constant value.\"", fun() { --4; });
|
||||||
|
|
||||||
|
assert_throws("Error: \"Error, cannot assign to constant value.\"", fun() { 5 = 5; });
|
||||||
|
assert_throws("Error: \"Error, cannot assign to constant value.\"", fun() { int(5) = 5; });
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -6,6 +6,20 @@ try {
|
|||||||
print("Caught Error: " + e.what());
|
print("Caught Error: " + e.what());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def get_value()
|
||||||
|
{
|
||||||
|
var i = 5;
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
def get_value_2()
|
||||||
|
{
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO these should be fixed somehow
|
||||||
|
//assert_throws("Cannot assign to temporary", fun[](){ get_value() = 3; });
|
||||||
|
//assert_throws("Cannot assign to temporary", fun[](){ get_value_2() = 3; });
|
||||||
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|||||||
@ -8,8 +8,8 @@ assert_equal("Test\u2022Me", "Test•Me")
|
|||||||
assert_equal("\xF0\x9F\x8D\x8C", "🍌")
|
assert_equal("\xF0\x9F\x8D\x8C", "🍌")
|
||||||
assert_equal("\U0001F34C", "🍌")
|
assert_equal("\U0001F34C", "🍌")
|
||||||
|
|
||||||
assert_throws("Invalid 16 bit universal character", fun(){ parse("\"\\uD83C\""); });
|
assert_throws("Error: \"Invalid 16 bit universal character\"", fun(){ parse("\"\\uD83C\""); });
|
||||||
assert_throws("Incomplete unicode escape sequence", fun(){ parse("\"\\uD83 \""); });
|
assert_throws("Error: \"Incomplete unicode escape sequence\"", fun(){ parse("\"\\uD83 \""); });
|
||||||
|
|
||||||
assert_equal("\U00024B62", "𤭢")
|
assert_equal("\U00024B62", "𤭢")
|
||||||
|
|
||||||
|
|||||||
@ -42,12 +42,14 @@ def assert_not_equal(x, y)
|
|||||||
|
|
||||||
def assert_throws(desc, x)
|
def assert_throws(desc, x)
|
||||||
{
|
{
|
||||||
if (throws_exception(x))
|
auto result = trim(throws_exception(x));
|
||||||
|
if (result == desc)
|
||||||
{
|
{
|
||||||
// Passes
|
// Passes
|
||||||
} else {
|
} else {
|
||||||
// Fails
|
// Fails
|
||||||
print("assert_throws failure, function did not throw exception: " + to_string(desc));
|
print("assert_throws failed: got '${result}' expected '${desc}'");
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,2 +1,2 @@
|
|||||||
assert_throws("Variable already defined", fun() { auto y = 10; auto y = 20; })
|
assert_throws("Error: \"Variable redefined 'y'\"", fun() { auto y = 10; auto y = 20; })
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user