Compare commits

...

47 Commits

Author SHA1 Message Date
Jason Turner
2c99e6cd32 Update release notes 2016-10-28 11:03:31 -06:00
Jason Turner
a38b254a98 Only allow class in top level scope
* Throw error if class is in unexpected place
 * Allow catching of `eval_error` from inside of script

closes #297
2016-10-28 10:56:12 -06:00
Jason Turner
77231461ca Add test for class inside of scope
Addresses #297
2016-10-28 09:01:40 -06:00
Jason Turner
0d4a99af82 Enable conversion to bool in conditionals
closes #295
2016-10-26 13:52:03 -06:00
Jason Turner
9f30d84f39 Add conversion to bool tests as conditionals 2016-10-26 12:29:30 -06:00
Jason Turner
508729ec77 Properly handle error reporting with method_missing 2016-10-26 10:08:53 -06:00
Jason Turner
ab07872857 Update to 5.8.6 2016-10-10 19:46:29 -06:00
Jason Turner
23c13e6570 Apply return optimization to lambdas
closes #289
2016-10-10 18:52:54 -06:00
Jason Turner
7339ff2c2f Update release notes for 5.8.5 2016-10-09 19:59:48 -06:00
Jason Turner
665125665a Bump to 5.8.5
- remove parsing of unary &, it was unused
2016-10-06 22:32:55 -06:00
Jason Turner
d1c7645a4e Backport inits for g++4.6 2016-10-06 15:19:47 -06:00
Jason Turner
58faea1cf2 Add conversion to bool compile test
Re: #275
2016-10-06 14:52:34 -06:00
Jason Turner
8b7fe33bf1 Fix order of operations for prefix and '*', '/'
The problem is that Prefix did not properly participate in
operator precedence. I've fixed this, at least for the moment,
by adding a final depth of precedence that can be called when
the depth gets to the bottom.

closes #285
2016-10-06 14:44:30 -06:00
Jason Turner
21495ebb40 Make sure atomics are initialized 2016-10-06 09:09:50 -06:00
Jason Turner
bec1b91b7b Increment to 5.8.4 2016-09-24 17:17:40 -06:00
Jason Turner
4b81a24a0a Fix numeric mixed-convesion operations 2016-09-24 17:15:17 -06:00
Jason Turner
cefb4d3c78 Update release notes for 5.x 2016-09-16 12:33:07 -06:00
Jason Turner
41c1c490c8 Add support for *& return types 2016-04-29 08:31:59 -06:00
Jason Turner
1e62eb4e12 Update to 5.8.2 release notes 2016-03-30 12:52:53 -06:00
Jason Turner
c07c2a9cc2 Make sure type_info works with shared_ptr & 2016-03-28 15:57:26 -06:00
Jason Turner
46c45e8fc7 Update boxed_cast_tests to account for new features 2016-03-27 20:50:15 -06:00
Jason Turner
91a3ae1f14 Add ability to take non-const & shared_ptr params 2016-03-27 20:02:27 -06:00
Jason Turner
328aef10d7 Add failing test for non-const shared_ptr & 2016-03-27 18:24:38 -06:00
Jason Turner
71c67bc763 Move debug over to windows build 2016-03-05 12:04:30 -07:00
Jason Turner
539ee3c84f Ignore unknown pragmas in older apple clang 2016-03-05 10:44:40 -07:00
Jason Turner
594958ea8b Address MSVC2013 specific warnings 2016-03-05 07:46:28 -07:00
Jason Turner
83b966df47 Address g++4.8 warnings 2016-03-05 07:45:33 -07:00
Jason Turner
c24004c70e Disable more warnings for catch/gcc 2016-03-04 22:09:26 -07:00
Jason Turner
a0ee8d1137 Address more catch/msvc warnings 2016-03-04 21:48:08 -07:00
Jason Turner
765e6ed8df Update release notes for 5.8.1 2016-03-04 18:26:14 -07:00
Jason Turner
0cb4c18638 Fix some more windows warnings 2016-03-04 18:22:21 -07:00
Jason Turner
ad7e2138d9 Various Windows fixes 2016-03-04 17:39:32 -07:00
Jason Turner
0eee23109e Upgrade catch to new version 2016-03-04 16:05:08 -07:00
Jason Turner
b663654a6d Add missing header for locale 2016-03-04 15:49:31 -07:00
Jason Turner
2a8c248167 Implement locale dependent float parser
closes #250
2016-03-04 15:18:12 -07:00
Jason Turner
457367ea7b Add failing tests for locale changes
re #250
2016-03-04 14:31:19 -07:00
Jason Turner
8feff5bc76 Clean up some more warnings 2016-03-04 10:03:39 -07:00
Jason Turner
a6dcbb1f1c Fix multithreaded test 2016-03-04 08:28:49 -07:00
Jason Turner
d4f02b5e67 Address sign promotion warnings, add todo test 2016-03-04 07:58:21 -07:00
Jason Turner
645377e191 Remove memory_order_relaxed usage 2016-03-02 20:36:05 -07:00
Jason Turner
5a03c88ee3 Add -Wconvert and address the warnings from it
closes #254
2016-03-02 17:40:15 -07:00
Jason Turner
abc30ba573 Create CONTRIBUTING.md 2016-02-23 14:08:22 -07:00
Jason Turner
f36b1fc5eb Rename PULL_REQUEST_TEMPLATE to PULL_REQUEST_TEMPLATE.md 2016-02-23 13:39:07 -07:00
Jason Turner
feb7775d21 Rename ISSUE_TEMPLATE to ISSUE_TEMPLATE.md 2016-02-23 13:38:50 -07:00
Jason Turner
8d50160cd9 Create ISSUE_TEMPLATE 2016-02-23 13:37:42 -07:00
Jason Turner
871ad10e0e Create PULL_REQUEST_TEMPLATE 2016-02-23 13:31:38 -07:00
Jason Turner
c0664d778c Merge pull request #248 from ChaiScript/release-5.x
Release 5.x
2016-02-16 17:52:50 -07:00
37 changed files with 2728 additions and 1291 deletions

View File

@@ -38,4 +38,5 @@ compilers:
- name: custom_check
commands:
- ./contrib/check_for_tabs.rb
- ./contrib/check_for_todos.rb

View File

@@ -2,8 +2,4 @@ compilers:
- name: clang
cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=$COMMIT_SHA
build_package_generator: TBZ2
- name: clang
build_type: Debug
cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=$COMMIT_SHA
skip_packaging: true

View File

@@ -17,4 +17,11 @@ compilers:
version: 12
architecture: Win64
cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=%COMMIT_SHA%
- name: Visual Studio
version: 14
build_type: Debug
architecture: Win64
cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=%COMMIT_SHA%
compiler_extra_flags: /analyze
skip_packaging: true

41
.github/CONTRIBUTING.md vendored Normal file
View File

@@ -0,0 +1,41 @@
# Contributing to ChaiScript
Thank you for contributing!
# Pull Requests
Please follow the existing style in the code you are patching.
- two space indent
- no tabs EVER
- match the existing indentation level
All ChaiScript commits are run through a large set of builds and analysis on all supported platforms. Those results are posted on the
[build dashboard](http://chaiscript.com/ChaiScript-BuildResults/index.html). No PR will be accepted until all tests pass.
The build system has full integration with GitHub and you will be notified automatically if all tests have passed.
# Issues
Please do not post a "chaiscript is too slow", "chaiscript compiles too slowly", or "chaiscript needs more documentation" issue
without first reading the following notes.
## ChaiScript is Too Slow
We are actively working on constently improving the runtime performance of ChaiScript. With the performance being
[monitored with each commit](http://chaiscript.com/ChaiScript-BuildResults/performance.html).
If you feel you *must* post an issue about performance, please post a complete example that illustrates the exact case you
feel should be better optimized.
Any issue request regarding performance without a complete example of the issue experienced will be closed.
## ChaiScript Compiles Too Slowly
This is also something we are actively working on. If you need highly optimized build times, please see [this discussion
on the discourse site](http://discourse.chaiscript.com/t/slow-build-times/94).
## ChaiScript Needs More Documentation
If you have a question that is not addressed in the [cheatsheet](https://github.com/ChaiScript/ChaiScript/blob/develop/cheatsheet.md)
please open an issue so we can get the Cheatsheet updated.

10
.github/ISSUE_TEMPLATE.md vendored Normal file
View File

@@ -0,0 +1,10 @@
* Compiler Used:
* Operating System:
* Architecture (ARM/x86/32bit/64bit/etc):
### Expected Behavior
### Actual Behavior
### Minimal Example to Reproduce Behavior

8
.github/PULL_REQUEST_TEMPLATE.md vendored Normal file
View File

@@ -0,0 +1,8 @@
Issue this pull request references: #
Changes proposed in this pull request
-
-
-

View File

@@ -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 0)
set(CPACK_PACKAGE_VERSION_PATCH 6)
set(CPACK_PACKAGE_EXECUTABLES "chai;ChaiScript Eval")
set(CPACK_PACKAGE_VENDOR "ChaiScript.com")
@@ -158,11 +158,14 @@ else()
endif()
if(MSVC)
add_definitions(/W4)
add_definitions(/W4 /w14545 /w34242 /w34254 /w34287 /w44263 /w44265 /w44296 /w44311 /w44826 /we4289 /w14546 /w14547 /w14549 /w14555 /w14619 /w14905 /w14906 /w14928)
# VS2013 doesn't have magic statics
if (MSVC_VERSION STREQUAL "1800")
# VS2013 doesn't have magic statics
add_definitions(/w44640)
else()
# enum warnings are too noisy on MSVC2013
add_definitions(/w34062)
endif()
add_definitions(/bigobj)
@@ -175,10 +178,10 @@ if(MSVC)
# how to workaround or fix the error. So I'm disabling it globally.
add_definitions(/wd4503)
else()
add_definitions(-Wall -Wextra -Wshadow -Wnon-virtual-dtor -Wold-style-cast -Wcast-align -Wcast-qual -Wunused -Woverloaded-virtual -pedantic ${CPP11_FLAG})
add_definitions(-Wall -Wextra -Wconversion -Wshadow -Wnon-virtual-dtor -Wold-style-cast -Wcast-align -Wcast-qual -Wunused -Woverloaded-virtual -pedantic ${CPP11_FLAG})
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
add_definitions(-Weverything -Wno-c++98-compat-pedantic -Wno-c++98-compat -Wno-documentation -Wno-switch-enum -Wno-weak-vtables -Wno-sign-conversion -Wno-missing-prototypes -Wno-padded -Wno-missing-noreturn -Wno-exit-time-destructors -Wno-documentation-unknown-command)
add_definitions(-Weverything -Wno-c++98-compat-pedantic -Wno-c++98-compat -Wno-documentation -Wno-switch-enum -Wno-weak-vtables -Wno-missing-prototypes -Wno-padded -Wno-missing-noreturn -Wno-exit-time-destructors -Wno-documentation-unknown-command)
else()
add_definitions(-Wnoexcept)
endif()

View File

@@ -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
@@ -163,6 +191,28 @@ chaiscript::Boxed_Number(chai.eval("5.3 + 2.1")).get_as<int>(); // works with an
static_cast<int>(chai.eval<double>("5.3+2.1")); // this version only works if we know that it's a double
```
### Conversion Caveats
Conversion to `std::shared_ptr<T> &` is supported for function calls, but if you attempt to keep a reference to a `shared_ptr<>` you might invoke undefined behavior
```cpp
// ok this is supported, you can register it with chaiscript engine
void nullify_shared_ptr(std::shared_ptr<int> &t) {
t == nullptr
}
```
```cpp
int main()
{
// do some stuff and create a chaiscript instance
std::shared_ptr<int> &ptr = chai.eval<std::shared_ptr<int> &>(somevalue);
// DO NOT do this. Taking a non-const reference to a shared_ptr is not
// supported and causes undefined behavior in the chaiscript engine
}
```
## Sharing Values
```

11
contrib/check_for_todos.rb Executable file
View File

@@ -0,0 +1,11 @@
#!/usr/bin/env ruby
require 'json'
`grep -rPIHni 'todo' src/* include/* samples/*`.lines { |line|
if /(?<filename>.+(hpp|cpp|chai)):(?<linenumber>[0-9]+):(?<restofline>.+)/ =~ line
puts(JSON.dump({:line => linenumber, :filename => filename, :tool => "todo_checker", :message => "todo: #{restofline.strip}", :messagetype => "info"}))
end
}

View File

@@ -93,11 +93,13 @@
#endif
#include <memory>
#include <string>
#include <cmath>
namespace chaiscript {
static const int version_major = 5;
static const int version_minor = 8;
static const int version_patch = 0;
static const int version_patch = 6;
static const char *compiler_version = CHAISCRIPT_COMPILER_VERSION;
static const char *compiler_name = CHAISCRIPT_COMPILER_NAME;
@@ -113,6 +115,78 @@ namespace chaiscript {
#endif
}
template<typename Iter, typename Distance>
Iter advance_copy(Iter iter, Distance distance) {
std::advance(iter, static_cast<typename std::iterator_traits<Iter>::difference_type>(distance));
return iter;
}
template<typename T>
auto parse_num(const char *t_str) -> typename std::enable_if<std::is_integral<T>::value, T>::type
{
T t = 0;
for (char c = *t_str; (c = *t_str); ++t_str) {
if (c < '0' || c > '9') {
return t;
}
t *= 10;
t += c - '0';
}
return t;
}
template<typename T>
auto parse_num(const char *t_str) -> typename std::enable_if<!std::is_integral<T>::value, T>::type
{
T t = 0;
T base = 0;
T decimal_place = 0;
bool exponent = false;
bool neg_exponent = false;
const auto final_value = [](const T val, const T baseval, const bool hasexp, const bool negexp) -> T {
if (!hasexp) {
return val;
} else {
return baseval * std::pow(T(10), val*T(negexp?-1:1));
}
};
for(; *t_str != '\0'; ++t_str) {
char c = *t_str;
if (c == '.') {
decimal_place = 10;
} else if (c == 'e' || c == 'E') {
exponent = true;
decimal_place = 0;
base = t;
t = 0;
} else if (c == '-' && exponent) {
neg_exponent = true;
} else if (c == '+' && exponent) {
neg_exponent = false;
} else if (c < '0' || c > '9') {
return final_value(t, base, exponent, neg_exponent);
} else if (decimal_place < T(10)) {
t *= T(10);
t += T(c - '0');
} else {
t += (T(c - '0') / (T(decimal_place)));
decimal_place *= 10;
}
}
return final_value(t, base, exponent, neg_exponent);
}
template<typename T>
T parse_num(const std::string &t_str)
{
return parse_num<T>(t_str.c_str());
}
}
#endif

View File

@@ -248,13 +248,17 @@ namespace chaiscript
m->add(
fun(
[](ContainerType &c, int index) -> typename ContainerType::reference {
return c.at(index);
/// \todo we are prefering to keep the key as 'int' to avoid runtime conversions
/// during dispatch. reevaluate
return c.at(static_cast<typename ContainerType::size_type>(index));
}), "[]");
m->add(
fun(
[](const ContainerType &c, int index) -> typename ContainerType::const_reference {
return c.at(index);
/// \todo we are prefering to keep the key as 'int' to avoid runtime conversions
/// during dispatch. reevaluate
return c.at(static_cast<typename ContainerType::size_type>(index));
}), "[]");
return m;

View File

@@ -173,6 +173,21 @@ namespace chaiscript
{
};
template<typename Result>
struct Cast_Helper_Inner<std::shared_ptr<Result> &>
{
static_assert(!std::is_const<Result>::value, "Non-const reference to std::shared_ptr<const T> is not supported");
typedef Boxed_Value::Sentinel<Result> Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *)
{
std::shared_ptr<Result> &res = ob.get().cast<std::shared_ptr<Result> >();
return ob.pointer_sentinel(res);
}
};
/// Cast_Helper_Inner for casting to a const std::shared_ptr<const> & type
template<typename Result>
struct Cast_Helper_Inner<const std::shared_ptr<const Result> > : Cast_Helper_Inner<std::shared_ptr<const Result> >

View File

@@ -43,16 +43,19 @@ namespace chaiscript
// this is OK, so we're disabling size/and sign type warnings
#ifdef CHAISCRIPT_MSVC
#pragma warning(push)
#pragma warning(disable : 4244 4018 4389 4146 4365 4267)
#pragma warning(disable : 4244 4018 4389 4146 4365 4267 4242)
#endif
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunknown-pragmas"
#pragma GCC diagnostic ignored "-Wpragmas"
#pragma GCC diagnostic ignored "-Wsign-compare"
#pragma GCC diagnostic ignored "-Wfloat-equal"
#pragma GCC diagnostic ignored "-Wconversion"
#pragma GCC diagnostic ignored "-Wsign-conversion"
#pragma GCC diagnostic ignored "-Wfloat-conversion"
#endif
/// \brief Represents any numeric type, generically. Used internally for generic operations between POD values

View File

@@ -231,6 +231,50 @@ namespace chaiscript
return m_data->m_type_info.bare_equal(ti);
}
template<typename T>
struct Sentinel {
Sentinel(std::shared_ptr<T> &ptr, Data &data)
: m_ptr(ptr), m_data(data)
{
}
~Sentinel()
{
// save new pointer data
m_data.get().m_data_ptr = m_ptr.get().get();
m_data.get().m_const_data_ptr = m_ptr.get().get();
}
Sentinel& operator=(Sentinel&&s) {
m_ptr = std::move(s.m_ptr);
m_data = std::move(s.m_data);
}
Sentinel(Sentinel &&s)
: m_ptr(std::move(s.m_ptr)),
m_data(std::move(s.m_data))
{
}
operator std::shared_ptr<T>&() const
{
return m_ptr.get();
}
Sentinel &operator=(const Sentinel &) = delete;
Sentinel(Sentinel&) = delete;
std::reference_wrapper<std::shared_ptr<T>> m_ptr;
std::reference_wrapper<Data> m_data;
};
template<typename T>
Sentinel<T> pointer_sentinel(std::shared_ptr<T> &ptr) const
{
return Sentinel<T>(ptr, *(m_data.get()));
}
bool is_null() const CHAISCRIPT_NOEXCEPT
{
return (m_data->m_data_ptr == nullptr && m_data->m_const_data_ptr == nullptr);

View File

@@ -430,7 +430,8 @@ namespace chaiscript
};
Dispatch_Engine()
: m_stack_holder(this)
: m_stack_holder(this),
m_method_missing_loc(0)
{
}
@@ -591,14 +592,14 @@ namespace chaiscript
}
/// Adds a new scope to the stack
void new_scope(Stack_Holder &t_holder)
static void new_scope(Stack_Holder &t_holder)
{
get_stack_data(t_holder).emplace_back();
t_holder.call_params.emplace_back();
}
/// Pops the current scope from the stack
void pop_scope(Stack_Holder &t_holder)
static void pop_scope(Stack_Holder &t_holder)
{
t_holder.call_params.pop_back();
StackData &stack = get_stack_data(t_holder);
@@ -635,7 +636,7 @@ namespace chaiscript
loc_mask = 0x0000FFFF
};
uint_fast32_t loc = t_loc.load(std::memory_order_relaxed);
uint_fast32_t loc = t_loc;
if (loc == 0)
{
@@ -647,17 +648,16 @@ namespace chaiscript
for (auto s = stack_elem->begin(); s != stack_elem->end(); ++s )
{
if (s->first == name) {
t_loc.store( static_cast<uint_fast32_t>(std::distance(stack.rbegin(), stack_elem) << 16)
| static_cast<uint_fast32_t>(std::distance(stack_elem->begin(), s))
| static_cast<uint_fast32_t>(Loc::located)
| static_cast<uint_fast32_t>(Loc::is_local),
std::memory_order_relaxed);
t_loc = static_cast<uint_fast32_t>(std::distance(stack.rbegin(), stack_elem) << 16)
| static_cast<uint_fast32_t>(std::distance(stack_elem->begin(), s))
| static_cast<uint_fast32_t>(Loc::located)
| static_cast<uint_fast32_t>(Loc::is_local);
return s->second;
}
}
}
t_loc.store( static_cast<uint_fast32_t>(Loc::located), std::memory_order_relaxed);
t_loc = static_cast<uint_fast32_t>(Loc::located);
} else if (loc & static_cast<uint_fast32_t>(Loc::is_local)) {
auto &stack = get_stack_data();
@@ -675,7 +675,7 @@ namespace chaiscript
// no? is it a function object?
auto obj = get_function_object_int(name, loc);
if (obj.first != loc) t_loc.store(uint_fast32_t(obj.first), std::memory_order_relaxed);
if (obj.first != loc) t_loc = uint_fast32_t(obj.first);
return obj.second;
@@ -738,9 +738,9 @@ namespace chaiscript
std::shared_ptr<std::vector<Proxy_Function>> get_method_missing_functions() const
{
uint_fast32_t method_missing_loc = m_method_missing_loc.load(std::memory_order_relaxed);
uint_fast32_t method_missing_loc = m_method_missing_loc;
auto method_missing_funs = get_function("method_missing", method_missing_loc);
if (method_missing_funs.first != method_missing_loc) m_method_missing_loc.store(uint_fast32_t(method_missing_funs.first), std::memory_order_relaxed);
if (method_missing_funs.first != method_missing_loc) m_method_missing_loc = uint_fast32_t(method_missing_funs.first);
return std::move(method_missing_funs.second);
}
@@ -911,8 +911,8 @@ namespace chaiscript
return m_conversions;
}
bool is_attribute_call(const std::vector<Proxy_Function> &t_funs, const std::vector<Boxed_Value> &t_params,
bool t_has_params, const Type_Conversions_State &t_conversions) const
static bool is_attribute_call(const std::vector<Proxy_Function> &t_funs, const std::vector<Boxed_Value> &t_params,
bool t_has_params, const Type_Conversions_State &t_conversions)
{
if (!t_has_params || t_params.empty()) {
return false;
@@ -938,9 +938,9 @@ namespace chaiscript
Boxed_Value call_member(const std::string &t_name, std::atomic_uint_fast32_t &t_loc, const std::vector<Boxed_Value> &params, bool t_has_params,
const Type_Conversions_State &t_conversions)
{
uint_fast32_t loc = t_loc.load(std::memory_order_relaxed);
uint_fast32_t loc = t_loc;
const auto funs = get_function(t_name, loc);
if (funs.first != loc) t_loc.store(uint_fast32_t(funs.first), std::memory_order_relaxed);
if (funs.first != loc) t_loc = uint_fast32_t(funs.first);
const auto do_attribute_call =
[this](int l_num_params, const std::vector<Boxed_Value> &l_params, const std::vector<Proxy_Function> &l_funs, const Type_Conversions_State &l_conversions)->Boxed_Value
@@ -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;
}
@@ -1051,9 +1057,9 @@ namespace chaiscript
Boxed_Value call_function(const std::string &t_name, std::atomic_uint_fast32_t &t_loc, const std::vector<Boxed_Value> &params,
const Type_Conversions_State &t_conversions) const
{
uint_fast32_t loc = t_loc.load(std::memory_order_relaxed);
uint_fast32_t loc = t_loc;
const auto funs = get_function(t_name, loc);
if (funs.first != loc) t_loc.store(uint_fast32_t(funs.first), std::memory_order_relaxed);
if (funs.first != loc) t_loc = uint_fast32_t(funs.first);
return dispatch::dispatch(*funs.second, params, t_conversions);
}
@@ -1446,7 +1452,7 @@ namespace chaiscript
static typename Container::const_iterator find_keyed_value(const Container &t_c, const Key &t_key, const size_t t_hint)
{
if (t_c.size() > t_hint && t_c[t_hint].first == t_key) {
return t_c.begin() + t_hint;
return advance_copy(t_c.begin(), t_hint);
} else {
return find_keyed_value(t_c, t_key);
}

View File

@@ -115,6 +115,24 @@ namespace chaiscript
}
};
template<typename Ret>
struct Handle_Return<Ret *&>
{
static Boxed_Value handle(Ret *p)
{
return Boxed_Value(p, true);
}
};
template<typename Ret>
struct Handle_Return<const Ret *&>
{
static Boxed_Value handle(const Ret *p)
{
return Boxed_Value(p, true);
}
};
template<typename Ret>
struct Handle_Return<Ret *>
{

View File

@@ -846,7 +846,8 @@ namespace chaiscript
plist.begin(),
std::back_inserter(newplist),
[](const Type_Info &ti, const Boxed_Value &param) -> Boxed_Value {
if (ti.is_arithmetic() && param.get_type_info().is_arithmetic()) {
if (ti.is_arithmetic() && param.get_type_info().is_arithmetic()
&& param.get_type_info() != ti) {
return Boxed_Number(param).get_as(ti).bv;
} else {
return param;
@@ -854,8 +855,6 @@ namespace chaiscript
}
);
try {
return (*(matching_func->second))(newplist, t_conversions);
} catch (const exception::bad_boxed_cast &) {

View File

@@ -32,11 +32,11 @@ namespace chaiscript
CHAISCRIPT_CONSTEXPR Type_Info(bool t_is_const, bool t_is_reference, bool t_is_pointer, bool t_is_void,
bool t_is_arithmetic, const std::type_info *t_ti, const std::type_info *t_bare_ti)
: m_type_info(t_ti), m_bare_type_info(t_bare_ti),
m_flags((t_is_const << is_const_flag)
+ (t_is_reference << is_reference_flag)
+ (t_is_pointer << is_pointer_flag)
+ (t_is_void << is_void_flag)
+ (t_is_arithmetic << is_arithmetic_flag))
m_flags((static_cast<unsigned int>(t_is_const) << is_const_flag)
+ (static_cast<unsigned int>(t_is_reference) << is_reference_flag)
+ (static_cast<unsigned int>(t_is_pointer) << is_pointer_flag)
+ (static_cast<unsigned int>(t_is_void) << is_void_flag)
+ (static_cast<unsigned int>(t_is_arithmetic) << is_arithmetic_flag))
{
}
@@ -60,6 +60,16 @@ namespace chaiscript
return m_type_info < ti.m_type_info;
}
CHAISCRIPT_CONSTEXPR bool operator!=(const Type_Info &ti) const CHAISCRIPT_NOEXCEPT
{
return !(operator==(ti));
}
CHAISCRIPT_CONSTEXPR bool operator!=(const std::type_info &ti) const CHAISCRIPT_NOEXCEPT
{
return !(operator==(ti));
}
CHAISCRIPT_CONSTEXPR bool operator==(const Type_Info &ti) const CHAISCRIPT_NOEXCEPT
{
return ti.m_type_info == m_type_info
@@ -162,6 +172,11 @@ namespace chaiscript
}
};
template<typename T>
struct Get_Type_Info<std::shared_ptr<T> &> : Get_Type_Info<std::shared_ptr<T>>
{
};
template<typename T>
struct Get_Type_Info<const std::shared_ptr<T> &>
{

View File

@@ -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");

View File

@@ -505,10 +505,10 @@ namespace chaiscript
// Let's see if this is a link that we should expand
std::vector<char> buf(2048);
const size_t pathlen = readlink(dllpath.c_str(), &buf.front(), buf.size());
if (pathlen > 0 && pathlen < buf.size())
const auto pathlen = readlink(dllpath.c_str(), &buf.front(), buf.size());
if (pathlen > 0 && static_cast<size_t>(pathlen) < buf.size())
{
dllpath = std::string(&buf.front(), pathlen);
dllpath = std::string(&buf.front(), static_cast<size_t>(pathlen));
}
m_module_paths.insert(m_module_paths.begin(), dllpath+"/");

View File

@@ -85,7 +85,8 @@ namespace chaiscript
public:
Binary_Operator_AST_Node(const std::string &t_oper, Parse_Location t_loc, std::vector<AST_NodePtr> t_children) :
AST_Node(t_oper, AST_Node_Type::Binary, std::move(t_loc), std::move(t_children)),
m_oper(Operators::to_operator(t_oper))
m_oper(Operators::to_operator(t_oper)),
m_loc(0)
{ }
virtual ~Binary_Operator_AST_Node() {}
@@ -166,7 +167,7 @@ namespace chaiscript
Id_AST_Node(const std::string &t_ast_node_text, Parse_Location t_loc) :
AST_Node(t_ast_node_text, AST_Node_Type::Id, std::move(t_loc)),
m_value(get_value(t_ast_node_text)), m_loc(0)
{ }
{ }
virtual ~Id_AST_Node() {}
virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE {
@@ -393,7 +394,10 @@ namespace chaiscript
public:
Equation_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_NodePtr> t_children) :
AST_Node(std::move(t_ast_node_text), AST_Node_Type::Equation, std::move(t_loc), std::move(t_children)),
m_oper(Operators::to_operator(children[1]->text))
m_oper(Operators::to_operator(children[1]->text)),
m_loc(0),
m_clone_loc(0)
{ assert(children.size() == 3); }
Operators::Opers m_oper;
@@ -535,7 +539,7 @@ namespace chaiscript
struct Array_Call_AST_Node : public AST_Node {
public:
Array_Call_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_NodePtr> t_children) :
AST_Node(std::move(t_ast_node_text), AST_Node_Type::Array_Call, std::move(t_loc), std::move(t_children)) { }
AST_Node(std::move(t_ast_node_text), AST_Node_Type::Array_Call, std::move(t_loc), std::move(t_children)), m_loc(0) { }
virtual ~Array_Call_AST_Node() {}
virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE{
chaiscript::eval::detail::Function_Push_Pop fpp(t_ss);
@@ -574,6 +578,8 @@ namespace chaiscript
public:
Dot_Access_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_NodePtr> t_children) :
AST_Node(std::move(t_ast_node_text), AST_Node_Type::Dot_Access, std::move(t_loc), std::move(t_children)),
m_loc(0),
m_array_loc(0),
m_fun_name(
((children[2]->identifier == AST_Node_Type::Fun_Call) || (children[2]->identifier == AST_Node_Type::Array_Call))?
children[2]->children[0]->text:children[2]->text) { }
@@ -803,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 &) {
@@ -845,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 {
@@ -862,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) {
@@ -872,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);
}
}
@@ -899,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 {
@@ -923,7 +929,7 @@ namespace chaiscript
struct Switch_AST_Node : public AST_Node {
public:
Switch_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_NodePtr> t_children) :
AST_Node(std::move(t_ast_node_text), AST_Node_Type::Switch, std::move(t_loc), std::move(t_children)) { }
AST_Node(std::move(t_ast_node_text), AST_Node_Type::Switch, std::move(t_loc), std::move(t_children)), m_loc(0) { }
virtual ~Switch_AST_Node() {}
virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE {
bool breaking = false;
@@ -999,7 +1005,10 @@ namespace chaiscript
struct Inline_Array_AST_Node : public AST_Node {
public:
Inline_Array_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_NodePtr> t_children) :
AST_Node(std::move(t_ast_node_text), AST_Node_Type::Inline_Array, std::move(t_loc), std::move(t_children)) { }
AST_Node(std::move(t_ast_node_text), AST_Node_Type::Inline_Array, std::move(t_loc), std::move(t_children)),
m_loc(0)
{ }
virtual ~Inline_Array_AST_Node() {}
virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE {
try {
@@ -1033,7 +1042,7 @@ namespace chaiscript
struct Inline_Map_AST_Node : public AST_Node {
public:
Inline_Map_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_NodePtr> t_children) :
AST_Node(std::move(t_ast_node_text), AST_Node_Type::Inline_Map, std::move(t_loc), std::move(t_children)) { }
AST_Node(std::move(t_ast_node_text), AST_Node_Type::Inline_Map, std::move(t_loc), std::move(t_children)), m_loc(0) { }
virtual ~Inline_Map_AST_Node() {}
virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE{
try {
@@ -1123,7 +1132,8 @@ namespace chaiscript
public:
Prefix_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_NodePtr> t_children) :
AST_Node(std::move(t_ast_node_text), AST_Node_Type::Prefix, std::move(t_loc), std::move(t_children)),
m_oper(Operators::to_operator(children[0]->text, true))
m_oper(Operators::to_operator(children[0]->text, true)),
m_loc(0)
{ }
virtual ~Prefix_AST_Node() {}
@@ -1204,7 +1214,7 @@ namespace chaiscript
struct Inline_Range_AST_Node : public AST_Node {
public:
Inline_Range_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_NodePtr> t_children) :
AST_Node(std::move(t_ast_node_text), AST_Node_Type::Inline_Range, std::move(t_loc), std::move(t_children)) { }
AST_Node(std::move(t_ast_node_text), AST_Node_Type::Inline_Range, std::move(t_loc), std::move(t_children)), m_loc(0) { }
virtual ~Inline_Range_AST_Node() {}
virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE{
try {
@@ -1303,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)));
@@ -1488,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
@@ -1505,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

View File

@@ -147,7 +147,7 @@ namespace chaiscript
}
size_t remaining() const {
return std::distance(m_pos, m_end);
return static_cast<size_t>(std::distance(m_pos, m_end));
}
char operator*() const {
@@ -219,6 +219,10 @@ namespace chaiscript
m_operators.emplace_back(AST_Node_Type::Multiplication);
m_operator_matches.emplace_back(std::initializer_list<std::string>({"*", "/", "%"}));
// Prefix placeholder
m_operators.emplace_back(AST_Node_Type::Prefix);
m_operator_matches.emplace_back(std::initializer_list<std::string>({}));
for (auto & elem : m_alphabet) {
std::fill(std::begin(elem), std::end(elem), false);
}
@@ -343,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();
@@ -621,11 +625,11 @@ namespace chaiscript
if (float_)
{
return const_var(std::stof(t_val.substr(0,i)));
return const_var(parse_num<float>(t_val.substr(0,i)));
} else if (long_) {
return const_var(std::stold(t_val.substr(0,i)));
return const_var(parse_num<long double>(t_val.substr(0,i)));
} else {
return const_var(std::stod(t_val.substr(0,i)));
return const_var(parse_num<double>(t_val.substr(0,i)));
}
}
@@ -1696,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()) {
@@ -2160,7 +2168,7 @@ namespace chaiscript
/// Reads a unary prefixed expression from input
bool Prefix() {
const auto prev_stack_top = m_match_stack.size();
const std::vector<std::string> prefix_opers{"++", "--", "-", "+", "!", "~", "&"};
const std::vector<std::string> prefix_opers{"++", "--", "-", "+", "!", "~"};
for (const auto &oper : prefix_opers)
{
@@ -2197,7 +2205,7 @@ namespace chaiscript
bool retval = false;
const auto prev_stack_top = m_match_stack.size();
if (t_precedence < m_operators.size()) {
if (m_operators[t_precedence] != AST_Node_Type::Prefix) {
if (Operator(t_precedence+1)) {
retval = true;
if (Operator_Helper(t_precedence)) {
@@ -2213,8 +2221,8 @@ namespace chaiscript
switch (m_operators[t_precedence]) {
case(AST_Node_Type::Ternary_Cond) :
m_match_stack.erase(m_match_stack.begin() + m_match_stack.size() - 2,
m_match_stack.begin() + m_match_stack.size() - 1);
m_match_stack.erase(advance_copy(m_match_stack.begin(), m_match_stack.size() - 2),
advance_copy(m_match_stack.begin(), m_match_stack.size() - 1));
if (Symbol(":")) {
if (!Operator(t_precedence+1)) {
throw exception::eval_error("Incomplete "
@@ -2239,7 +2247,8 @@ namespace chaiscript
case(AST_Node_Type::Bitwise_Or) :
case(AST_Node_Type::Comparison) :
assert(m_match_stack.size() > 1);
m_match_stack.erase(m_match_stack.begin() + m_match_stack.size() - 2, m_match_stack.begin() + m_match_stack.size() - 1);
m_match_stack.erase(advance_copy(m_match_stack.begin(), m_match_stack.size() - 2),
advance_copy(m_match_stack.begin(), m_match_stack.size() - 1));
build_match<eval::Binary_Operator_AST_Node>(prev_stack_top, oper->text);
break;
@@ -2256,8 +2265,7 @@ namespace chaiscript
} while (Operator_Helper(t_precedence));
}
}
}
else {
} else {
return Value();
}
@@ -2371,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;
@@ -2379,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);
}
@@ -2420,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 {

View File

@@ -212,16 +212,16 @@ class JSON
}
template <typename T>
JSON( T b, typename enable_if<is_same<T,bool>::value>::type* = 0 ) : Internal( b ), Type( Class::Boolean ){}
JSON( T b, typename enable_if<is_same<T,bool>::value>::type* = nullptr ) : Internal( b ), Type( Class::Boolean ){}
template <typename T>
JSON( T i, typename enable_if<is_integral<T>::value && !is_same<T,bool>::value>::type* = 0 ) : Internal( long(i) ), Type( Class::Integral ){}
JSON( T i, typename enable_if<is_integral<T>::value && !is_same<T,bool>::value>::type* = nullptr ) : Internal( long(i) ), Type( Class::Integral ){}
template <typename T>
JSON( T f, typename enable_if<is_floating_point<T>::value>::type* = 0 ) : Internal( double(f) ), Type( Class::Floating ){}
JSON( T f, typename enable_if<is_floating_point<T>::value>::type* = nullptr ) : Internal( double(f) ), Type( Class::Floating ){}
template <typename T>
JSON( T s, typename enable_if<is_convertible<T,string>::value>::type* = 0 ) : Internal( string( s ) ), Type( Class::String ){}
JSON( T s, typename enable_if<is_convertible<T,string>::value>::type* = nullptr ) : Internal( string( s ) ), Type( Class::String ){}
JSON( std::nullptr_t ) : Internal(), Type( Class::Null ){}
@@ -605,7 +605,7 @@ namespace {
Number = std::stod( val ) * std::pow( 10, exp );
else {
if( !exp_str.empty() )
Number = std::stol( val ) * std::pow( 10, exp );
Number = static_cast<double>(std::stol( val )) * std::pow( 10, exp );
else
Number = std::stol( val );
}

View File

@@ -1,6 +1,33 @@
Notes:
=======
Current Version: 5.8.0
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
* Make sure atomics are initialized properly
* Remove parsing of unused prefix `&` operator
### Changes since 5.8.3
* Fix case with some numeric conversions mixed with numerics that do not need conversion
### Changes since 5.8.2
* Add support for reference of pointer return types
### Changes since 5.8.1
* Allow casting to non-const & std::shared_ptr<T>
### Changes since 5.8.0
* Fix parsing of floats to be locale independent #250
* Various warning fixes on various platforms
### Changes since 5.7.1
* Make all parser iterator operations range checked

View File

@@ -89,24 +89,24 @@ std::vector<std::string> default_search_paths()
std::vector<char> buf(2048);
ssize_t size = -1;
if ((size = readlink("/proc/self/exe", &buf.front(), buf.size())) != -1)
if ((size = readlink("/proc/self/exe", &buf.front(), buf.size())) > 0)
{
exepath = std::string(&buf.front(), size);
exepath = std::string(&buf.front(), static_cast<size_t>(size));
}
if (exepath.empty())
{
if ((size = readlink("/proc/curproc/file", &buf.front(), buf.size())) != -1)
if ((size = readlink("/proc/curproc/file", &buf.front(), buf.size())) > 0)
{
exepath = std::string(&buf.front(), size);
exepath = std::string(&buf.front(), static_cast<size_t>(size));
}
}
if (exepath.empty())
{
if ((size = readlink("/proc/self/path/a.out", &buf.front(), buf.size())) != -1)
if ((size = readlink("/proc/self/path/a.out", &buf.front(), buf.size())) > 0)
{
exepath = std::string(&buf.front(), size);
exepath = std::string(&buf.front(), static_cast<size_t>(size));
}
}

View File

@@ -88,24 +88,24 @@ std::vector<std::string> default_search_paths()
std::vector<char> buf(2048);
ssize_t size = -1;
if ((size = readlink("/proc/self/exe", &buf.front(), buf.size())) != -1)
if ((size = readlink("/proc/self/exe", &buf.front(), buf.size())) >= 0)
{
exepath = std::string(&buf.front(), size);
exepath = std::string(&buf.front(), static_cast<size_t>(size));
}
if (exepath.empty())
{
if ((size = readlink("/proc/curproc/file", &buf.front(), buf.size())) != -1)
if ((size = readlink("/proc/curproc/file", &buf.front(), buf.size())) >= 0)
{
exepath = std::string(&buf.front(), size);
exepath = std::string(&buf.front(), static_cast<size_t>(size));
}
}
if (exepath.empty())
{
if ((size = readlink("/proc/self/path/a.out", &buf.front(), buf.size())) != -1)
if ((size = readlink("/proc/self/path/a.out", &buf.front(), buf.size())) >= 0)
{
exepath = std::string(&buf.front(), size);
exepath = std::string(&buf.front(), static_cast<size_t>(size));
}
}

View File

@@ -114,6 +114,16 @@ std::shared_ptr<TestBaseType> null_factory()
return std::shared_ptr<TestBaseType>();
}
void update_shared_ptr(std::shared_ptr<TestBaseType> &ptr)
{
ptr = std::make_shared<TestDerivedType>();
}
void nullify_shared_ptr(std::shared_ptr<TestBaseType> &ptr)
{
ptr = nullptr;
}
std::string hello_world()
{
return "Hello World";
@@ -209,6 +219,10 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_test_mo
m->add(chaiscript::type_conversion<const char *, std::string>());
m->add(chaiscript::constructor<Type2 (const TestBaseType &)>(), "Type2");
m->add(chaiscript::fun(&update_shared_ptr), "update_shared_ptr");
m->add(chaiscript::fun(&nullify_shared_ptr), "nullify_shared_ptr");
return m;
}

View File

@@ -54,12 +54,13 @@ bool test_type_conversion(const Boxed_Value &bv, bool expectedpass)
}
template<typename Type>
bool do_test(const Boxed_Value &bv, bool T, bool ConstT, bool TRef, bool ConstTRef, bool TPtr, bool ConstTPtr, bool TPtrConst,
bool ConstTPtrConst, bool SharedPtrT, bool SharedConstPtrT,
bool ConstSharedPtrT, bool ConstSharedConstPtrT, bool ConstSharedPtrTRef, bool ConstSharedPtrTConstRef,
bool WrappedRef, bool WrappedConstRef, bool ConstWrappedRef, bool ConstWrappedConstRef,
bool ConstWrappedRefRef, bool ConstWrappedConstRefRef, bool Number,
bool ConstNumber, bool ConstNumberRef, bool TPtrConstRef, bool ConstTPtrConstRef)
bool do_test(const Boxed_Value &bv,
bool T, bool ConstT, bool TRef, bool ConstTRef, bool TPtr,
bool ConstTPtr, bool TPtrConst, bool ConstTPtrConst, bool SharedPtrT, bool SharedConstPtrT,
bool SharedPtrTRef, bool ConstSharedPtrT, bool ConstSharedConstPtrT, bool ConstSharedPtrTRef, bool ConstSharedPtrTConstRef,
bool WrappedRef, bool WrappedConstRef, bool ConstWrappedRef, bool ConstWrappedConstRef, bool ConstWrappedRefRef,
bool ConstWrappedConstRefRef, bool Number, bool ConstNumber, bool ConstNumberRef, bool TPtrConstRef,
bool ConstTPtrConstRef)
{
bool passed = true;
passed &= test_type_conversion<Type>(bv, T);
@@ -72,8 +73,8 @@ bool do_test(const Boxed_Value &bv, bool T, bool ConstT, bool TRef, bool ConstTR
passed &= test_type_conversion<const Type * const>(bv, ConstTPtrConst);
passed &= test_type_conversion<std::shared_ptr<Type> >(bv, SharedPtrT);
passed &= test_type_conversion<std::shared_ptr<const Type> >(bv, SharedConstPtrT);
passed &= test_type_conversion<std::shared_ptr<Type> &>(bv, false);
passed &= test_type_conversion<std::shared_ptr<const Type> &>(bv, false);
passed &= test_type_conversion<std::shared_ptr<Type> &>(bv, SharedPtrTRef);
//passed &= test_type_conversion<std::shared_ptr<const Type> &>(bv, false);
passed &= test_type_conversion<const std::shared_ptr<Type> >(bv, ConstSharedPtrT);
passed &= test_type_conversion<const std::shared_ptr<const Type> >(bv, ConstSharedConstPtrT);
passed &= test_type_conversion<const std::shared_ptr<Type> &>(bv, ConstSharedPtrTRef);
@@ -115,37 +116,37 @@ bool built_in_type_test(const T &initial, bool ispod)
T i = T(initial);
passed &= do_test<T>(var(i), true, true, true, true, true,
true, true, true, true, true,
true, true, true, true, true,
true, true, true, true, true, true,
true, true, true, true, true,
ispod, ispod, ispod, true, true);
passed &= do_test<T>(const_var(i), true, true, false, true, false,
true, false, true, false, true,
false, true, false, true, false,
false, false, true, false, true, false,
true, false, true, false, true,
ispod, ispod, ispod, false, true);
passed &= do_test<T>(var(&i), true, true, true, true, true,
true, true, true, false, false,
false, false, false, false, true,
false, false, false, false, false, true,
true, true, true, true, true,
ispod, ispod, ispod, true, true);
passed &= do_test<T>(const_var(&i), true, true, false, true, false,
true, false, true, false, false,
false, false, false, false, false,
false, false, false, false, false, false,
true, false, true, false, true,
ispod, ispod, ispod, false, true);
passed &= do_test<T>(var(std::ref(i)), true, true, true, true, true,
true, true, true, false, false,
false, false, false, false, true,
false, false, false, false, false, true,
true, true, true, true, true,
ispod, ispod, ispod, true, true);
passed &= do_test<T>(var(std::cref(i)), true, true, false, true, false,
true, false, true, false, false,
false, false, false, false, false,
false, false, false, false, false, false,
true, false, true, false, true,
ispod, ispod, ispod, false, true);
@@ -156,33 +157,33 @@ bool built_in_type_test(const T &initial, bool ispod)
passed &= do_test<T>(var(i), true, true, true, true, true,
true, true, true, true, true,
true, true, true, true, true,
true, true, true, true, true, true,
true, true, true, true, true,
ispod, ispod, ispod, true, true);
// But a pointer or reference to it should be necessarily const
passed &= do_test<T>(var(&ir), true, true, false, true, false,
true, false, true, false, false,
false, false, false, false, false,
false, false, false, false, false, false,
true, false, true, false, true,
ispod, ispod, ispod, false, true);
passed &= do_test<T>(var(std::ref(ir)), true, true, false, true, false,
true, false, true, false, false,
false, false, false, false, false,
false, false, false, false, false, false,
true, false, true, false, true,
ispod, ispod, ispod, false, true);
// Make sure const of const works too
passed &= do_test<T>(const_var(&ir), true, true, false, true, false,
true, false, true, false, false,
false, false, false, false, false,
false, false, false, false, false, false,
true, false, true, false, true,
ispod, ispod, ispod, false, true);
passed &= do_test<T>(const_var(std::ref(ir)), true, true, false, true, false,
true, false, true, false, false,
false, false, false, false, false,
false, false, false, false, false, false,
true, false, true, false, true,
ispod, ispod, ispod, false, true);
@@ -192,14 +193,14 @@ bool built_in_type_test(const T &initial, bool ispod)
const T*cip = &i;
passed &= do_test<T>(var(cip), true, true, false, true, false,
true, false, true, false, false,
false, false, false, false, false,
false, false, false, false, false, false,
true, false, true, false, true,
ispod, ispod, ispod, false, true);
// make sure const of const works
passed &= do_test<T>(const_var(cip), true, true, false, true, false,
true, false, true, false, false,
false, false, false, false, false,
false, false, false, false, false, false,
true, false, true, false, true,
ispod, ispod, ispod, false, true);
@@ -209,13 +210,13 @@ bool built_in_type_test(const T &initial, bool ispod)
passed &= do_test<T>(var(ip), true, true, true, true, true,
true, true, true, true, true,
true, true, true, true, true,
true, true, true, true, true, true,
true, true, true, true, true,
ispod, ispod, ispod, true, true);
passed &= do_test<T>(const_var(ip), true, true, false, true, false,
true, false, true, false, true,
false, true, false, true, false,
false, false, true, false, true, false,
true, false, true, false, true,
ispod, ispod, ispod, false, true);
@@ -224,14 +225,14 @@ bool built_in_type_test(const T &initial, bool ispod)
passed &= do_test<T>(var(ipc), true, true, false, true, false,
true, false, true, false, true,
false, true, false, true, false,
false, false, true, false, true, false,
true, false, true, false, true,
ispod, ispod, ispod, false, true);
// const of this should be the same, making sure it compiles
passed &= do_test<T>(const_var(ipc), true, true, false, true, false,
true, false, true, false, true,
false, true, false, true, false,
false, false, true, false, true, false,
true, false, true, false, true,
ispod, ispod, ispod, false, true);

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,8 @@
try {
parse("{ class C { var data; def C() {} } }")
assert_false(true)
} catch (e) {
assert_true(true)
}

View File

@@ -1,33 +1,31 @@
// All of these are necessary because of catch.hpp. It's OK, they'll be
// caught in other cpp files if chaiscript causes them
#include <chaiscript/utility/utility.hpp>
#include <chaiscript/dispatchkit/bootstrap_stl.hpp>
#ifdef CHAISCRIPT_MSVC
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable : 4190 4640 28251 4702 6330)
#pragma warning(disable : 4062 4242 4640 4702 6330 28251)
#endif
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wshadow"
#pragma GCC diagnostic ignored "-Wold-style-cast"
#pragma GCC diagnostic ignored "-Wunknown-pragmas"
#pragma GCC diagnostic ignored "-Wparentheses"
#endif
#ifdef __llvm__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wreturn-type-c-linkage"
#pragma clang diagnostic ignored "-Wold-style-cast"
#pragma clang diagnostic ignored "-Wexit-time-destructors"
#pragma clang diagnostic ignored "-Wfloat-equal"
#pragma clang diagnostic ignored "-Wunreachable-code"
#endif
#include <chaiscript/chaiscript.hpp>
#include <chaiscript/utility/utility.hpp>
#include <chaiscript/dispatchkit/bootstrap_stl.hpp>
#define CATCH_CONFIG_MAIN
#include <clocale>
#include "catch.hpp"
// lambda_tests
@@ -933,9 +931,53 @@ TEST_CASE("Map conversions")
)");
CHECK(c == 42);
}
TEST_CASE("Parse floats with non-posix locale")
{
#ifdef CHAISCRIPT_MSVC
std::setlocale(LC_ALL, "en-ZA");
#else
std::setlocale(LC_ALL, "en_ZA.utf8");
#endif
chaiscript::ChaiScript chai;
const double parsed = chai.eval<double>("print(1.3); 1.3");
CHECK(parsed == Approx(1.3));
const std::string str = chai.eval<std::string>("to_string(1.3)");
CHECK(str == "1.3");
}
bool FindBitmap(int &ox, int &oy, long) {
ox = 1;
oy = 2;
return true;
}
TEST_CASE("Mismatched numeric types only convert necessary params")
{
chaiscript::ChaiScript chai;
chai.add(chaiscript::fun(&FindBitmap), "FindBitmap");
int x = 0;
int y = 0;
chai.add(chaiscript::var(&x), "x");
chai.add(chaiscript::var(&y), "y");
chai.eval( "if ( FindBitmap ( x, y, 0) ) { print(\"found at \" + to_string(x) + \", \" + to_string(y))}" );
CHECK(x == 1);
CHECK(y == 2);
}
TEST_CASE("type_conversion to bool")
{
auto module = std::make_shared<chaiscript::Module>();
struct T {
operator bool() const { return true; }
};
module->add(chaiscript::type_conversion<T, bool>());
}

View 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);
}

View File

@@ -15,7 +15,7 @@ int expected_value(int num_iters)
return i;
}
void do_work(chaiscript::ChaiScript &c, int id)
void do_work(chaiscript::ChaiScript &c, const size_t id)
{
try{
std::stringstream ss;
@@ -67,23 +67,23 @@ int main()
std::vector<std::shared_ptr<std::thread> > threads;
// Ensure at least two, but say only 7 on an 8 core processor
int num_threads = std::max(static_cast<int>(std::thread::hardware_concurrency()) - 1, 2);
size_t num_threads = static_cast<size_t>(std::max(static_cast<int>(std::thread::hardware_concurrency()) - 1, 2));
std::cout << "Num threads: " << num_threads << '\n';
for (int i = 0; i < num_threads; ++i)
for (size_t i = 0; i < num_threads; ++i)
{
threads.push_back(std::make_shared<std::thread>(do_work, std::ref(chai), i));
}
for (int i = 0; i < num_threads; ++i)
for (size_t i = 0; i < num_threads; ++i)
{
threads[i]->join();
}
for (int i = 0; i < num_threads; ++i)
for (size_t i = 0; i < num_threads; ++i)
{
std::stringstream ss;
ss << i;
@@ -92,7 +92,7 @@ int main()
return EXIT_FAILURE;
}
if (chai.eval<int>("getid(" + ss.str() + ")") != i)
if (chai.eval<int>("getid(" + ss.str() + ")") != static_cast<int>(i))
{
return EXIT_FAILURE;
}

View File

@@ -0,0 +1,4 @@
var i = 2;
assert_equal(++i * i, 9)

View File

@@ -0,0 +1,25 @@
load_module("test_module")
auto o := null_factory();
assert_true(o.is_var_null());
update_shared_ptr(o);
assert_false(o.is_var_null());
assert_true(o.base_only_func() == -9);
nullify_shared_ptr(o);
o.nullify_shared_ptr();
assert_true(o.is_var_null());
try {
o.func();
} catch (e) {
exit(0);
}
assert_true(false);

View File

@@ -1,30 +1,22 @@
// Tests to make sure that the order in which function dispatches occur is correct
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable : 4062 4242 4640 4702 6330 28251)
#endif
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunknown-pragmas"
#pragma GCC diagnostic ignored "-Wparentheses"
#endif
#include <chaiscript/chaiscript_defines.hpp>
#include <chaiscript/dispatchkit/type_info.hpp>
#include <iostream>
#include <cstdlib>
#ifdef CHAISCRIPT_MSVC
#pragma warning(push)
#pragma warning(disable : 4190 4640 28251 4702 6330)
#endif
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wshadow"
#pragma GCC diagnostic ignored "-Wold-style-cast"
#endif
#ifdef __llvm__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wreturn-type-c-linkage"
#pragma clang diagnostic ignored "-Wold-style-cast"
#pragma clang diagnostic ignored "-Wexit-time-destructors"
#pragma clang diagnostic ignored "-Wfloat-equal"
#pragma clang diagnostic ignored "-Wunreachable-code"
#endif