Compare commits
8 Commits
v5.8.5
...
release-5.
Author | SHA1 | Date | |
---|---|---|---|
![]() |
2c99e6cd32 | ||
![]() |
a38b254a98 | ||
![]() |
77231461ca | ||
![]() |
0d4a99af82 | ||
![]() |
9f30d84f39 | ||
![]() |
508729ec77 | ||
![]() |
ab07872857 | ||
![]() |
23c13e6570 |
@@ -103,7 +103,7 @@ set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/description.txt"
|
||||
|
||||
set(CPACK_PACKAGE_VERSION_MAJOR 5)
|
||||
set(CPACK_PACKAGE_VERSION_MINOR 8)
|
||||
set(CPACK_PACKAGE_VERSION_PATCH 5)
|
||||
set(CPACK_PACKAGE_VERSION_PATCH 6)
|
||||
|
||||
set(CPACK_PACKAGE_EXECUTABLES "chai;ChaiScript Eval")
|
||||
set(CPACK_PACKAGE_VENDOR "ChaiScript.com")
|
||||
|
@@ -84,6 +84,33 @@ chai.add(chaiscript::user_type<MyClass>(), "MyClass");
|
||||
|
||||
User defined type conversions are possible, defined in either script or in C++.
|
||||
|
||||
|
||||
### ChaiScript Defined Conversions
|
||||
|
||||
Function objects (including lambdas) can be used to add type conversions
|
||||
from inside of ChaiScript:
|
||||
|
||||
```
|
||||
add_type_conversion(type("string"), type("Type_Info"), fun(s) { return type(s); });
|
||||
```
|
||||
|
||||
### C++ Defined Conversions
|
||||
|
||||
Invoking a C++ type conversion possible with `static_cast`
|
||||
|
||||
```
|
||||
chai.add(chaiscript::type_conversion<T, bool>());
|
||||
```
|
||||
|
||||
Calling a user defined type conversion that takes a lambda
|
||||
|
||||
```
|
||||
chai.add(chaiscript::type_conversion<TestBaseType, Type2>([](const TestBaseType &t_bt) { /* return converted thing */ }));
|
||||
```
|
||||
|
||||
|
||||
### Helpers
|
||||
|
||||
A helper function exists for strongly typed and ChaiScript `Vector` function conversion definition:
|
||||
|
||||
```
|
||||
@@ -97,6 +124,7 @@ chai.add(chaiscript::map_conversion<std::map<std::string, int>>());
|
||||
```
|
||||
|
||||
|
||||
|
||||
This allows you to pass a ChaiScript function to a function requiring `std::vector<int>`
|
||||
|
||||
## Adding Objects
|
||||
|
@@ -99,7 +99,7 @@
|
||||
namespace chaiscript {
|
||||
static const int version_major = 5;
|
||||
static const int version_minor = 8;
|
||||
static const int version_patch = 5;
|
||||
static const int version_patch = 6;
|
||||
|
||||
static const char *compiler_version = CHAISCRIPT_COMPILER_VERSION;
|
||||
static const char *compiler_name = CHAISCRIPT_COMPILER_NAME;
|
||||
|
@@ -963,14 +963,20 @@ namespace chaiscript
|
||||
|
||||
This_Foist fi(*this, l_params.front());
|
||||
|
||||
auto func = boxed_cast<std::shared_ptr<const dispatch::Proxy_Function_Base>>(bv);
|
||||
try {
|
||||
return (*func)({l_params.begin() + l_num_params, l_params.end()}, l_conversions);
|
||||
auto func = boxed_cast<std::shared_ptr<const dispatch::Proxy_Function_Base>>(bv);
|
||||
try {
|
||||
return (*func)({l_params.begin() + l_num_params, l_params.end()}, l_conversions);
|
||||
} catch (const chaiscript::exception::bad_boxed_cast &) {
|
||||
} catch (const chaiscript::exception::arity_error &) {
|
||||
} catch (const chaiscript::exception::guard_error &) {
|
||||
}
|
||||
throw chaiscript::exception::dispatch_error({l_params.begin() + l_num_params, l_params.end()}, std::vector<Const_Proxy_Function>{func});
|
||||
} catch (const chaiscript::exception::bad_boxed_cast &) {
|
||||
} catch (const chaiscript::exception::arity_error &) {
|
||||
} catch (const chaiscript::exception::guard_error &) {
|
||||
// unable to convert bv into a Proxy_Function_Base
|
||||
throw chaiscript::exception::dispatch_error({l_params.begin() + l_num_params, l_params.end()},
|
||||
std::vector<Const_Proxy_Function>(l_funs.begin(), l_funs.end()));
|
||||
}
|
||||
throw chaiscript::exception::dispatch_error({l_params.begin() + l_num_params, l_params.end()}, std::vector<Const_Proxy_Function>{func});
|
||||
} else {
|
||||
return bv;
|
||||
}
|
||||
|
@@ -489,9 +489,9 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
static bool get_bool_condition(const Boxed_Value &t_bv) {
|
||||
static bool get_bool_condition(const Boxed_Value &t_bv, const chaiscript::detail::Dispatch_State &t_ss) {
|
||||
try {
|
||||
return boxed_cast<bool>(t_bv);
|
||||
return t_ss->boxed_cast<bool>(t_bv);
|
||||
}
|
||||
catch (const exception::bad_boxed_cast &) {
|
||||
throw exception::eval_error("Condition not boolean");
|
||||
|
@@ -809,7 +809,7 @@ namespace chaiscript
|
||||
chaiscript::eval::detail::Scope_Push_Pop spp(t_ss);
|
||||
|
||||
try {
|
||||
while (get_bool_condition(this->children[0]->eval(t_ss))) {
|
||||
while (get_bool_condition(this->children[0]->eval(t_ss), t_ss)) {
|
||||
try {
|
||||
this->children[1]->eval(t_ss);
|
||||
} catch (detail::Continue_Loop &) {
|
||||
@@ -851,7 +851,7 @@ namespace chaiscript
|
||||
{ assert(children.size() == 3); }
|
||||
virtual ~Ternary_Cond_AST_Node() {}
|
||||
virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE {
|
||||
if (get_bool_condition(children[0]->eval(t_ss))) {
|
||||
if (get_bool_condition(children[0]->eval(t_ss), t_ss)) {
|
||||
return children[1]->eval(t_ss);
|
||||
}
|
||||
else {
|
||||
@@ -868,7 +868,7 @@ namespace chaiscript
|
||||
virtual ~If_AST_Node() {}
|
||||
virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE{
|
||||
|
||||
if (get_bool_condition(children[0]->eval(t_ss))) {
|
||||
if (get_bool_condition(children[0]->eval(t_ss), t_ss)) {
|
||||
return children[1]->eval(t_ss);
|
||||
} else {
|
||||
if (children.size() > 2) {
|
||||
@@ -878,7 +878,7 @@ namespace chaiscript
|
||||
return children[i+1]->eval(t_ss);
|
||||
}
|
||||
else if (children[i]->text == "else if") {
|
||||
if (get_bool_condition(children[i+1]->eval(t_ss))) {
|
||||
if (get_bool_condition(children[i+1]->eval(t_ss), t_ss)) {
|
||||
return children[i+2]->eval(t_ss);
|
||||
}
|
||||
}
|
||||
@@ -905,7 +905,7 @@ namespace chaiscript
|
||||
try {
|
||||
for (
|
||||
children[0]->eval(t_ss);
|
||||
get_bool_condition(children[1]->eval(t_ss));
|
||||
get_bool_condition(children[1]->eval(t_ss), t_ss);
|
||||
children[2]->eval(t_ss)
|
||||
) {
|
||||
try {
|
||||
@@ -1313,11 +1313,8 @@ namespace chaiscript
|
||||
try {
|
||||
retval = this->children[0]->eval(t_ss);
|
||||
}
|
||||
catch (exception::eval_error &) {
|
||||
if (this->children.back()->identifier == AST_Node_Type::Finally) {
|
||||
this->children.back()->children[0]->eval(t_ss);
|
||||
}
|
||||
throw;
|
||||
catch (const exception::eval_error &e) {
|
||||
retval = handle_exception(t_ss, Boxed_Value(std::ref(e)));
|
||||
}
|
||||
catch (const std::runtime_error &e) {
|
||||
retval = handle_exception(t_ss, Boxed_Value(std::ref(e)));
|
||||
@@ -1498,8 +1495,8 @@ namespace chaiscript
|
||||
|
||||
virtual ~Logical_And_AST_Node() {}
|
||||
virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE{
|
||||
return const_var(get_bool_condition(children[0]->eval(t_ss))
|
||||
&& get_bool_condition(children[2]->eval(t_ss)));
|
||||
return const_var(get_bool_condition(children[0]->eval(t_ss), t_ss)
|
||||
&& get_bool_condition(children[2]->eval(t_ss), t_ss));
|
||||
}
|
||||
|
||||
virtual std::string pretty_print() const CHAISCRIPT_OVERRIDE
|
||||
@@ -1515,8 +1512,8 @@ namespace chaiscript
|
||||
{ assert(children.size() == 3); }
|
||||
virtual ~Logical_Or_AST_Node() {}
|
||||
virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE{
|
||||
return const_var(get_bool_condition(children[0]->eval(t_ss))
|
||||
|| get_bool_condition(children[2]->eval(t_ss)));
|
||||
return const_var(get_bool_condition(children[0]->eval(t_ss), t_ss)
|
||||
|| get_bool_condition(children[2]->eval(t_ss), t_ss));
|
||||
}
|
||||
|
||||
virtual std::string pretty_print() const CHAISCRIPT_OVERRIDE
|
||||
|
@@ -347,7 +347,7 @@ namespace chaiscript
|
||||
{
|
||||
for (auto &c : p->children)
|
||||
{
|
||||
if (c->identifier == AST_Node_Type::Def && c->children.size() > 0) {
|
||||
if ( (c->identifier == AST_Node_Type::Def || c->identifier == AST_Node_Type::Lambda) && c->children.size() > 0) {
|
||||
auto &last_child = c->children.back();
|
||||
if (last_child->identifier == AST_Node_Type::Block) {
|
||||
auto &block_last_child = last_child->children.back();
|
||||
@@ -1700,12 +1700,16 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
/// Reads a class block from input
|
||||
bool Class() {
|
||||
bool Class(const bool t_class_allowed) {
|
||||
bool retval = false;
|
||||
|
||||
size_t prev_stack_top = m_match_stack.size();
|
||||
|
||||
if (Keyword("class")) {
|
||||
if (!t_class_allowed) {
|
||||
throw exception::eval_error("Class definitions only allowed at top scope", File_Position(m_position.line, m_position.col), *m_filename);
|
||||
}
|
||||
|
||||
retval = true;
|
||||
|
||||
if (!Id()) {
|
||||
@@ -2375,7 +2379,7 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
/// Top level parser, starts parsing of all known parses
|
||||
bool Statements() {
|
||||
bool Statements(const bool t_class_allowed = false) {
|
||||
bool retval = false;
|
||||
|
||||
bool has_more = true;
|
||||
@@ -2383,7 +2387,7 @@ namespace chaiscript
|
||||
|
||||
while (has_more) {
|
||||
const auto start = m_position;
|
||||
if (Def() || Try() || If() || While() || Class() || For() || Switch()) {
|
||||
if (Def() || Try() || If() || While() || Class(t_class_allowed) || For() || Switch()) {
|
||||
if (!saw_eol) {
|
||||
throw exception::eval_error("Two function definitions missing line separator", File_Position(start.line, start.col), *m_filename);
|
||||
}
|
||||
@@ -2424,7 +2428,7 @@ namespace chaiscript
|
||||
/// \todo respect // -*- coding: utf-8 -*- on line 1 or 2 see: http://evanjones.ca/python-utf8.html)
|
||||
}
|
||||
|
||||
if (Statements()) {
|
||||
if (Statements(true)) {
|
||||
if (m_position.has_more()) {
|
||||
throw exception::eval_error("Unparsed input", File_Position(m_position.line, m_position.col), t_fname);
|
||||
} else {
|
||||
|
@@ -1,6 +1,13 @@
|
||||
Notes:
|
||||
=======
|
||||
Current Version: 5.8.5
|
||||
|
||||
Current Version: 5.8.6
|
||||
|
||||
### Changes since 5.8.5
|
||||
* Optimize away `return` statements in lambdas also
|
||||
* Allow conversions to bool in conditionals
|
||||
* Don't allow `class` statements inside of scopes
|
||||
* Properly error when a dynamic object non-function member is called
|
||||
|
||||
### Changes since 5.8.4
|
||||
* Fix order of operations for prefix operators
|
||||
|
8
unittests/class_inside_scope.chai
Normal file
8
unittests/class_inside_scope.chai
Normal file
@@ -0,0 +1,8 @@
|
||||
|
||||
|
||||
try {
|
||||
parse("{ class C { var data; def C() {} } }")
|
||||
assert_false(true)
|
||||
} catch (e) {
|
||||
assert_true(true)
|
||||
}
|
17
unittests/conversion_to_bool.chai
Normal file
17
unittests/conversion_to_bool.chai
Normal file
@@ -0,0 +1,17 @@
|
||||
|
||||
// all we care is that this executes, really
|
||||
|
||||
add_type_conversion(type("int"), type("bool"), fun(int i) { return i != 0; });
|
||||
|
||||
if (0) {
|
||||
assert_true(false);
|
||||
}
|
||||
|
||||
while (0) {
|
||||
assert_true(false);
|
||||
}
|
||||
|
||||
for (; 0; ) {
|
||||
assert_true(false);
|
||||
}
|
||||
|
Reference in New Issue
Block a user