Merge tag 'v5.6.0'

This commit is contained in:
Jason Turner 2015-03-13 21:59:37 -06:00
commit aa0ed17e43
54 changed files with 1003 additions and 504 deletions

View File

@ -21,5 +21,5 @@ compilers:
skip_packaging: true skip_packaging: true
cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON
- name: cppcheck - name: cppcheck
compiler_extra_flags: --enable=all -I include --inline-suppr compiler_extra_flags: --enable=all -I include --inline-suppr -Umax --suppress="*:cmake*"

View File

@ -1,6 +1,7 @@
compilers: compilers:
- name: clang - name: clang
cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=$COMMIT_SHA 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 - name: clang
build_type: Debug build_type: Debug
cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=$COMMIT_SHA cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=$COMMIT_SHA

View File

@ -2,21 +2,21 @@ compilers:
- name: Visual Studio - name: Visual Studio
version: 14 version: 14
cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=%COMMIT_SHA% cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=%COMMIT_SHA%
compiler_extra_flags: /ANALYZE compiler_extra_flags: /analyze
skip_packaging: true skip_packaging: true
- name: Visual Studio - name: Visual Studio
version: 14 version: 14
architecture: Win64 architecture: Win64
cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=%COMMIT_SHA% cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=%COMMIT_SHA%
compiler_extra_flags: /ANALYZE compiler_extra_flags: /analyze
skip_packaging: true skip_packaging: true
- name: Visual Studio - name: Visual Studio
version: 12 version: 12
cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=%COMMIT_SHA% cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=%COMMIT_SHA%
compiler_extra_flags: /ANALYZE compiler_extra_flags: /analyze
- name: Visual Studio - name: Visual Studio
version: 12 version: 12
architecture: Win64 architecture: Win64
cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=%COMMIT_SHA% cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=%COMMIT_SHA%
compiler_extra_flags: /ANALYZE compiler_extra_flags: /analyze

View File

@ -81,8 +81,8 @@ set(CPACK_RESOURCE_FILE_README "${CMAKE_CURRENT_SOURCE_DIR}/readme.md")
set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/description.txt") set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/description.txt")
set(CPACK_PACKAGE_VERSION_MAJOR 5) set(CPACK_PACKAGE_VERSION_MAJOR 5)
set(CPACK_PACKAGE_VERSION_MINOR 5) set(CPACK_PACKAGE_VERSION_MINOR 6)
set(CPACK_PACKAGE_VERSION_PATCH 1) set(CPACK_PACKAGE_VERSION_PATCH 0)
set(CPACK_PACKAGE_EXECUTABLES "chai;ChaiScript Eval") set(CPACK_PACKAGE_EXECUTABLES "chai;ChaiScript Eval")
set(CPACK_PACKAGE_VENDOR "ChaiScript.com") set(CPACK_PACKAGE_VENDOR "ChaiScript.com")
@ -152,7 +152,13 @@ if(MSVC)
# how to workaround or fix the error. So I'm disabling it globally. # how to workaround or fix the error. So I'm disabling it globally.
add_definitions(/wd4503) add_definitions(/wd4503)
else() else()
add_definitions(-Wall -Wextra -Wshadow -Wnon-virtual-dtor -pedantic ${CPP11_FLAG}) add_definitions(-Wall -Wextra -Wshadow -Wnon-virtual-dtor -Wold-style-cast -Wcast-align -Wcast-qual -Woverloaded-virtual -pedantic ${CPP11_FLAG})
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
add_definitions(-Weverything -Wno-c++98-compat -Wno-documentation -Wno-switch-enum -Wno-weak-vtables -Wno-sign-conversion -Wno-missing-prototypes -Wno-padded -Wno-missing-noreturn)
else()
add_definitions(-Wnoexcept)
endif()
if(APPLE) if(APPLE)
add_definitions(-Wno-sign-compare) add_definitions(-Wno-sign-compare)

View File

@ -40,7 +40,7 @@ PROJECT_NUMBER = ${CHAI_VERSION}
# for a project that appears at the top of each page and should give viewer # for a project that appears at the top of each page and should give viewer
# a quick idea about the purpose of the project. Keep the description short. # a quick idea about the purpose of the project. Keep the description short.
PROJECT_BRIEF = ${CMAKE_BINARY_DIR}/docs PROJECT_BRIEF = "An easy to use embedded scripting language for C++."
# With the PROJECT_LOGO tag one can specify an logo or icon that is # With the PROJECT_LOGO tag one can specify an logo or icon that is
# included in the documentation. The maximum height of the logo should not # included in the documentation. The maximum height of the logo should not

View File

@ -1,7 +1,7 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com) // Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
#ifndef CHAISCRIPT_HPP_ #ifndef CHAISCRIPT_HPP_

View File

@ -1,7 +1,7 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com) // Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
#ifndef CHAISCRIPT_DEFINES_HPP_ #ifndef CHAISCRIPT_DEFINES_HPP_
@ -17,7 +17,7 @@
#endif #endif
#if (defined(__GNUC__) && __GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) #if (defined(__GNUC__) && __GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
/// Currently only g++>=4.8supports this natively /// Currently only g++>=4.8 supports this natively
/// \todo Make this support other compilers when possible /// \todo Make this support other compilers when possible
#define CHAISCRIPT_HAS_THREAD_LOCAL #define CHAISCRIPT_HAS_THREAD_LOCAL
#endif #endif
@ -45,8 +45,8 @@
namespace chaiscript { namespace chaiscript {
static const int version_major = 5; static const int version_major = 5;
static const int version_minor = 5; static const int version_minor = 6;
static const int version_patch = 1; static const int version_patch = 0;
} }
#endif #endif

View File

@ -19,6 +19,11 @@
#include "dispatchkit/bootstrap_stl.hpp" #include "dispatchkit/bootstrap_stl.hpp"
#include "dispatchkit/boxed_value.hpp" #include "dispatchkit/boxed_value.hpp"
#ifndef CHAISCRIPT_NO_THREADS
#include <future>
#endif
/// @file /// @file
/// ///
/// This file generates the standard library that normal ChaiScript usage requires. /// This file generates the standard library that normal ChaiScript usage requires.
@ -40,6 +45,11 @@ namespace chaiscript
lib->add(standard_library::map_type<std::map<std::string, Boxed_Value> >("Map")); lib->add(standard_library::map_type<std::map<std::string, Boxed_Value> >("Map"));
lib->add(standard_library::pair_type<std::pair<Boxed_Value, Boxed_Value > >("Pair")); lib->add(standard_library::pair_type<std::pair<Boxed_Value, Boxed_Value > >("Pair"));
#ifndef CHAISCRIPT_NO_THREADS
lib->add(standard_library::future_type<std::future<chaiscript::Boxed_Value>>("future"));
lib->add(chaiscript::fun<std::future<Boxed_Value> (const std::function<chaiscript::Boxed_Value ()> &)>([](const std::function<chaiscript::Boxed_Value ()> &t_func){ return std::async(std::launch::async, t_func);}), "async");
#endif
return lib; return lib;
} }

View File

@ -1,7 +1,7 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com) // Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
#ifndef CHAISCRIPT_THREADING_HPP_ #ifndef CHAISCRIPT_THREADING_HPP_
@ -82,16 +82,27 @@ namespace chaiscript
t().erase(m_key); t().erase(m_key);
} }
inline T *operator->() const inline const T *operator->() const
{ {
return &(t()[m_key]); return &(t()[m_key]);
} }
inline T &operator*() const inline const T &operator*() const
{ {
return t()[m_key]; return t()[m_key];
} }
inline T *operator->()
{
return &(t()[m_key]);
}
inline T &operator*()
{
return t()[m_key];
}
void *m_key; void *m_key;
private: private:
@ -117,12 +128,22 @@ namespace chaiscript
{ {
} }
inline T *operator->() const inline const T *operator->() const
{ {
return get_tls().get(); return get_tls().get();
} }
inline T &operator*() const inline const T &operator*() const
{
return *get_tls();
}
inline T *operator->()
{
return get_tls().get();
}
inline T &operator*()
{ {
return *get_tls(); return *get_tls();
} }

View File

@ -26,6 +26,8 @@ namespace chaiscript {
{ {
} }
bad_any_cast(const bad_any_cast &) = default;
virtual ~bad_any_cast() CHAISCRIPT_NOEXCEPT {} virtual ~bad_any_cast() CHAISCRIPT_NOEXCEPT {}
/// \brief Description of what error occurred /// \brief Description of what error occurred
@ -105,7 +107,7 @@ namespace chaiscript {
} }
} }
#if _MSC_VER != 1800 #if !defined(_MSC_VER) || _MSC_VER != 1800
Any(Any &&) = default; Any(Any &&) = default;
Any &operator=(Any &&t_any) = default; Any &operator=(Any &&t_any) = default;
#endif #endif

View File

@ -1,7 +1,7 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com) // Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
#ifndef CHAISCRIPT_BAD_BOXED_CAST_HPP_ #ifndef CHAISCRIPT_BAD_BOXED_CAST_HPP_
@ -45,7 +45,8 @@ namespace chaiscript
{ {
} }
virtual ~bad_boxed_cast() CHAISCRIPT_NOEXCEPT {} bad_boxed_cast(const bad_boxed_cast &) = default;
virtual ~bad_boxed_cast() CHAISCRIPT_NOEXCEPT {}
/// \brief Description of what error occurred /// \brief Description of what error occurred
virtual const char * what() const CHAISCRIPT_NOEXCEPT CHAISCRIPT_OVERRIDE virtual const char * what() const CHAISCRIPT_NOEXCEPT CHAISCRIPT_OVERRIDE

View File

@ -1,7 +1,7 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com) // Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
#ifndef CHAISCRIPT_BIND_FIRST_HPP_ #ifndef CHAISCRIPT_BIND_FIRST_HPP_

View File

@ -1,7 +1,7 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com) // Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
#ifndef CHAISCRIPT_BOOTSTRAP_HPP_ #ifndef CHAISCRIPT_BOOTSTRAP_HPP_
@ -396,10 +396,9 @@ namespace chaiscript
m->add(user_type<std::runtime_error>(), "runtime_error"); m->add(user_type<std::runtime_error>(), "runtime_error");
m->add(chaiscript::base_class<std::exception, std::runtime_error>()); m->add(chaiscript::base_class<std::exception, std::runtime_error>());
m->add(constructor<std::runtime_error (const std::string &)>(), "runtime_error"); m->add(constructor<std::runtime_error (const std::string &)>(), "runtime_error");
m->add(fun(std::function<std::string (const std::runtime_error &)>(&what)), "what"); m->add(fun(std::function<std::string (const std::runtime_error &)>(&what)), "what");
m->add(user_type<dispatch::Dynamic_Object>(), "Dynamic_Object"); m->add(user_type<dispatch::Dynamic_Object>(), "Dynamic_Object");
m->add(constructor<dispatch::Dynamic_Object (const std::string &)>(), "Dynamic_Object"); m->add(constructor<dispatch::Dynamic_Object (const std::string &)>(), "Dynamic_Object");
@ -487,7 +486,12 @@ namespace chaiscript
m->add(chaiscript::fun(&has_parse_tree), "has_parse_tree"); m->add(chaiscript::fun(&has_parse_tree), "has_parse_tree");
m->add(chaiscript::fun(&get_parse_tree), "get_parse_tree"); m->add(chaiscript::fun(&get_parse_tree), "get_parse_tree");
m->add(chaiscript::base_class<std::exception, chaiscript::exception::eval_error>()); m->add(chaiscript::user_type<chaiscript::exception::eval_error>(), "eval_error");
m->add(chaiscript::base_class<std::runtime_error, chaiscript::exception::eval_error>());
m->add(chaiscript::user_type<chaiscript::exception::arithmetic_error>(), "arithmetic_error");
m->add(chaiscript::base_class<std::runtime_error, chaiscript::exception::arithmetic_error>());
// chaiscript::bootstrap::standard_library::vector_type<std::vector<std::shared_ptr<chaiscript::AST_Node> > >("AST_NodeVector", m); // chaiscript::bootstrap::standard_library::vector_type<std::vector<std::shared_ptr<chaiscript::AST_Node> > >("AST_NodeVector", m);

View File

@ -1,7 +1,7 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com) // Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
/// \file /// \file
@ -246,6 +246,7 @@ namespace chaiscript
template<typename ContainerType> template<typename ContainerType>
ModulePtr random_access_container_type(const std::string &/*type*/, ModulePtr m = ModulePtr(new Module())) ModulePtr random_access_container_type(const std::string &/*type*/, ModulePtr m = ModulePtr(new Module()))
{ {
// cppcheck-suppress syntaxError
typedef typename ContainerType::reference(ContainerType::*indexoper)(size_t); typedef typename ContainerType::reference(ContainerType::*indexoper)(size_t);
typedef typename ContainerType::const_reference(ContainerType::*constindexoper)(size_t) const; typedef typename ContainerType::const_reference(ContainerType::*constindexoper)(size_t) const;
@ -564,6 +565,25 @@ namespace chaiscript
return m; return m;
} }
/// Add a MapType container
/// http://www.sgi.com/tech/stl/Map.html
template<typename FutureType>
ModulePtr future_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
{
m->add(user_type<FutureType>(), type);
m->add(fun<bool (const FutureType &)>([](const FutureType &t) { return t.valid(); }), "valid");
m->add(fun(&FutureType::get), "get");
m->add(fun(&FutureType::wait), "wait");
return m;
}
} }
} }
} }

View File

@ -1,7 +1,7 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com) // Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
#ifndef CHAISCRIPT_BOXED_CAST_HPP_ #ifndef CHAISCRIPT_BOXED_CAST_HPP_

View File

@ -1,7 +1,7 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com) // Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
#ifndef CHAISCRIPT_BOXED_CAST_HELPER_HPP_ #ifndef CHAISCRIPT_BOXED_CAST_HELPER_HPP_

View File

@ -1,7 +1,7 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com) // Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
#ifndef CHAISCRIPT_BOXED_NUMERIC_HPP_ #ifndef CHAISCRIPT_BOXED_NUMERIC_HPP_
@ -22,6 +22,19 @@ namespace chaiscript {
class Type_Conversions; class Type_Conversions;
} // namespace chaiscript } // namespace chaiscript
namespace chaiscript
{
namespace exception
{
struct arithmetic_error : public std::runtime_error
{
arithmetic_error(const std::string& reason) : std::runtime_error("Arithmetic error: " + reason) {}
arithmetic_error(const arithmetic_error &) = default;
virtual ~arithmetic_error() CHAISCRIPT_NOEXCEPT {}
};
}
}
namespace chaiscript namespace chaiscript
{ {
@ -33,16 +46,37 @@ namespace chaiscript
#pragma warning(disable : 4244 4018 4389 4146 4365) #pragma warning(disable : 4244 4018 4389 4146 4365)
#endif #endif
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wsign-compare"
#pragma GCC diagnostic ignored "-Wfloat-equal"
#pragma GCC diagnostic ignored "-Wconversion"
#pragma GCC diagnostic ignored "-Wsign-conversion"
#endif
/// \brief Represents any numeric type, generically. Used internally for generic operations between POD values /// \brief Represents any numeric type, generically. Used internally for generic operations between POD values
class Boxed_Number class Boxed_Number
{ {
private: private:
template<typename T>
static void check_divide_by_zero(T t, typename std::enable_if<std::is_integral<T>::value>::type* = 0)
{
#ifndef CHAISCRIPT_NO_PROTECT_DIVIDEBYZERO
if (t == 0) {
throw chaiscript::exception::arithmetic_error("divide by zero");
}
#endif
}
template<typename T>
static void check_divide_by_zero(T, typename std::enable_if<std::is_floating_point<T>::value>::type* = 0)
{
}
struct boolean struct boolean
{ {
#ifdef __GNUC__
#pragma GCC diagnostic ignored "-Wsign-compare"
#endif
template<typename T, typename U> template<typename T, typename U>
static Boxed_Value go(Operators::Opers t_oper, const T &t, const U &u, const Boxed_Value &) static Boxed_Value go(Operators::Opers t_oper, const T &t, const U &u, const Boxed_Value &)
{ {
@ -61,7 +95,7 @@ namespace chaiscript
case Operators::not_equal: case Operators::not_equal:
return const_var(t != u); return const_var(t != u);
default: default:
throw chaiscript::detail::exception::bad_any_cast(); throw chaiscript::detail::exception::bad_any_cast();
} }
} }
}; };
@ -89,13 +123,14 @@ namespace chaiscript
t += u; t += u;
break; break;
case Operators::assign_quotient: case Operators::assign_quotient:
check_divide_by_zero(u);
t /= u; t /= u;
break; break;
case Operators::assign_difference: case Operators::assign_difference:
t -= u; t -= u;
break; break;
default: default:
throw chaiscript::detail::exception::bad_any_cast(); throw chaiscript::detail::exception::bad_any_cast();
} }
return t_lhs; return t_lhs;
@ -122,13 +157,14 @@ namespace chaiscript
t >>= u; t >>= u;
break; break;
case Operators::assign_remainder: case Operators::assign_remainder:
check_divide_by_zero(u);
t %= u; t %= u;
break; break;
case Operators::assign_bitwise_xor: case Operators::assign_bitwise_xor:
t ^= u; t ^= u;
break; break;
default: default:
throw chaiscript::detail::exception::bad_any_cast(); throw chaiscript::detail::exception::bad_any_cast();
} }
return t_lhs; return t_lhs;
} }
@ -146,6 +182,7 @@ namespace chaiscript
case Operators::shift_right: case Operators::shift_right:
return const_var(t >> u); return const_var(t >> u);
case Operators::remainder: case Operators::remainder:
check_divide_by_zero(u);
return const_var(t % u); return const_var(t % u);
case Operators::bitwise_and: case Operators::bitwise_and:
return const_var(t & u); return const_var(t & u);
@ -156,7 +193,7 @@ namespace chaiscript
case Operators::bitwise_complement: case Operators::bitwise_complement:
return const_var(~t); return const_var(~t);
default: default:
throw chaiscript::detail::exception::bad_any_cast(); throw chaiscript::detail::exception::bad_any_cast();
} }
} }
}; };
@ -171,6 +208,7 @@ namespace chaiscript
case Operators::sum: case Operators::sum:
return const_var(t + u); return const_var(t + u);
case Operators::quotient: case Operators::quotient:
check_divide_by_zero(u);
return const_var(t / u); return const_var(t / u);
case Operators::product: case Operators::product:
return const_var(t * u); return const_var(t * u);
@ -181,7 +219,7 @@ namespace chaiscript
case Operators::unary_plus: case Operators::unary_plus:
return const_var(+t); return const_var(+t);
default: default:
throw chaiscript::detail::exception::bad_any_cast(); throw chaiscript::detail::exception::bad_any_cast();
} }
} }
}; };
@ -327,7 +365,6 @@ namespace chaiscript
return oss.str(); return oss.str();
} }
public: public:
Boxed_Number() Boxed_Number()
: bv(Boxed_Value(0)) : bv(Boxed_Value(0))
@ -340,6 +377,13 @@ namespace chaiscript
validate_boxed_number(bv); validate_boxed_number(bv);
} }
Boxed_Number(const Boxed_Number &) = default;
#if !defined(_MSC_VER) || _MSC_VER != 1800
Boxed_Number(Boxed_Number &&) = default;
Boxed_Number& operator=(Boxed_Number &&) = default;
#endif
template<typename T> explicit Boxed_Number(T t) template<typename T> explicit Boxed_Number(T t)
: bv(Boxed_Value(t)) : bv(Boxed_Value(t))
{ {
@ -547,6 +591,7 @@ namespace chaiscript
} }
} }
// cppcheck-suppress operatorEq
Boxed_Number operator=(const Boxed_Value &v) Boxed_Number operator=(const Boxed_Value &v)
{ {
validate_boxed_number(v); validate_boxed_number(v);
@ -554,6 +599,7 @@ namespace chaiscript
return *this; return *this;
} }
// cppcheck-suppress operatorEq
Boxed_Number operator=(const Boxed_Number &t_rhs) const Boxed_Number operator=(const Boxed_Number &t_rhs) const
{ {
return oper(Operators::assign, this->bv, t_rhs.bv); return oper(Operators::assign, this->bv, t_rhs.bv);
@ -843,14 +889,18 @@ namespace chaiscript
struct Cast_Helper<const Boxed_Number &> : Cast_Helper<Boxed_Number> struct Cast_Helper<const Boxed_Number &> : Cast_Helper<Boxed_Number>
{ {
}; };
/// Cast_Helper for converting from Boxed_Value to Boxed_Number /// Cast_Helper for converting from Boxed_Value to Boxed_Number
template<> template<>
struct Cast_Helper<const Boxed_Number> : Cast_Helper<Boxed_Number> struct Cast_Helper<const Boxed_Number> : Cast_Helper<Boxed_Number>
{ {
}; };
} }
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
#ifdef CHAISCRIPT_MSVC #ifdef CHAISCRIPT_MSVC
#pragma warning(pop) #pragma warning(pop)
#endif #endif

View File

@ -1,7 +1,7 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com) // Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
#ifndef CHAISCRIPT_BOXED_VALUE_HPP_ #ifndef CHAISCRIPT_BOXED_VALUE_HPP_
@ -72,8 +72,8 @@ namespace chaiscript
chaiscript::detail::Any m_obj; chaiscript::detail::Any m_obj;
void *m_data_ptr; void *m_data_ptr;
const void *m_const_data_ptr; const void *m_const_data_ptr;
bool m_is_ref;
std::unique_ptr<std::map<std::string, Boxed_Value>> m_attrs; std::unique_ptr<std::map<std::string, Boxed_Value>> m_attrs;
bool m_is_ref;
}; };
struct Object_Data struct Object_Data

View File

@ -1,7 +1,7 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com) // Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
#ifndef CHAISCRIPT_DISPATCHKIT_HPP_ #ifndef CHAISCRIPT_DISPATCHKIT_HPP_
@ -62,6 +62,8 @@ namespace chaiscript
{ {
} }
reserved_word_error(const reserved_word_error &) = default;
virtual ~reserved_word_error() CHAISCRIPT_NOEXCEPT {} virtual ~reserved_word_error() CHAISCRIPT_NOEXCEPT {}
std::string word() const std::string word() const
@ -82,6 +84,8 @@ namespace chaiscript
{ {
} }
illegal_name_error(const illegal_name_error &) = default;
virtual ~illegal_name_error() CHAISCRIPT_NOEXCEPT {} virtual ~illegal_name_error() CHAISCRIPT_NOEXCEPT {}
std::string name() const std::string name() const
@ -103,6 +107,8 @@ namespace chaiscript
{ {
} }
name_conflict_error(const name_conflict_error &) = default;
virtual ~name_conflict_error() CHAISCRIPT_NOEXCEPT {} virtual ~name_conflict_error() CHAISCRIPT_NOEXCEPT {}
std::string name() const std::string name() const
@ -125,6 +131,7 @@ namespace chaiscript
{ {
} }
global_non_const(const global_non_const &) = default;
virtual ~global_non_const() CHAISCRIPT_NOEXCEPT {} virtual ~global_non_const() CHAISCRIPT_NOEXCEPT {}
}; };
} }
@ -389,6 +396,8 @@ namespace chaiscript
std::set<std::string> m_reserved_words; std::set<std::string> m_reserved_words;
State &operator=(const State &) = default; State &operator=(const State &) = default;
State() = default;
State(const State &) = default;
}; };
Dispatch_Engine() Dispatch_Engine()
@ -445,7 +454,7 @@ namespace chaiscript
/// Adds a named object to the current scope /// Adds a named object to the current scope
/// \warning This version does not check the validity of the name /// \warning This version does not check the validity of the name
/// it is meant for internal use only /// it is meant for internal use only
void add_object(const std::string &name, const Boxed_Value &obj) const void add_object(const std::string &name, const Boxed_Value &obj)
{ {
if (!get_stack_data().back().insert(std::make_pair(name, obj)).second) if (!get_stack_data().back().insert(std::make_pair(name, obj)).second)
{ {
@ -695,10 +704,10 @@ namespace chaiscript
/// ///
std::map<std::string, Boxed_Value> get_scripting_objects() const std::map<std::string, Boxed_Value> get_scripting_objects() const
{ {
Stack_Holder &s = *m_stack_holder; const Stack_Holder &s = *m_stack_holder;
// We don't want the current context, but one up if it exists // We don't want the current context, but one up if it exists
StackData &stack = (s.stacks.size()==1)?(s.stacks.back()):(s.stacks[s.stacks.size()-2]); const StackData &stack = (s.stacks.size()==1)?(s.stacks.back()):(s.stacks[s.stacks.size()-2]);
std::map<std::string, Boxed_Value> retval; std::map<std::string, Boxed_Value> retval;
@ -965,7 +974,12 @@ namespace chaiscript
private: private:
/// Returns the current stack /// Returns the current stack
/// make const/non const versions /// make const/non const versions
StackData &get_stack_data() const const StackData &get_stack_data() const
{
return m_stack_holder->stacks.back();
}
StackData &get_stack_data()
{ {
return m_stack_holder->stacks.back(); return m_stack_holder->stacks.back();
} }

View File

@ -1,7 +1,7 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com) // Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
#ifndef CHAISCRIPT_DYNAMIC_OBJECT_HPP_ #ifndef CHAISCRIPT_DYNAMIC_OBJECT_HPP_
@ -19,7 +19,6 @@
#include "boxed_cast.hpp" #include "boxed_cast.hpp"
#include "boxed_cast_helper.hpp" #include "boxed_cast_helper.hpp"
#include "boxed_value.hpp" #include "boxed_value.hpp"
#include "proxy_functions.hpp"
#include "type_info.hpp" #include "type_info.hpp"
namespace chaiscript { namespace chaiscript {
@ -62,217 +61,6 @@ namespace chaiscript
std::map<std::string, Boxed_Value> m_attrs; std::map<std::string, Boxed_Value> m_attrs;
}; };
namespace detail
{
/// A Proxy_Function implementation designed for calling a function
/// that is automatically guarded based on the first param based on the
/// param's type name
class Dynamic_Object_Function : public Proxy_Function_Base
{
public:
Dynamic_Object_Function(
std::string t_type_name,
const Proxy_Function &t_func)
: Proxy_Function_Base(t_func->get_param_types(), t_func->get_arity()),
m_type_name(std::move(t_type_name)), m_func(t_func), m_doti(user_type<Dynamic_Object>())
{
assert( (t_func->get_arity() > 0 || t_func->get_arity() < 0)
&& "Programming error, Dynamic_Object_Function must have at least one parameter (this)");
}
Dynamic_Object_Function(
std::string t_type_name,
const Proxy_Function &t_func,
const Type_Info &t_ti)
: Proxy_Function_Base(build_param_types(t_func->get_param_types(), t_ti), t_func->get_arity()),
m_type_name(std::move(t_type_name)), m_func(t_func), m_ti(new Type_Info(t_ti)), m_doti(user_type<Dynamic_Object>())
{
assert( (t_func->get_arity() > 0 || t_func->get_arity() < 0)
&& "Programming error, Dynamic_Object_Function must have at least one parameter (this)");
}
virtual ~Dynamic_Object_Function() {}
Dynamic_Object_Function &operator=(const Dynamic_Object_Function) = delete;
Dynamic_Object_Function(Dynamic_Object_Function &) = delete;
virtual bool operator==(const Proxy_Function_Base &f) const CHAISCRIPT_OVERRIDE
{
if (const auto *df = dynamic_cast<const Dynamic_Object_Function *>(&f))
{
return df->m_type_name == m_type_name && (*df->m_func) == (*m_func);
} else {
return false;
}
}
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
{
if (dynamic_object_typename_match(vals, m_type_name, m_ti, t_conversions))
{
return m_func->call_match(vals, t_conversions);
} else {
return false;
}
}
virtual std::vector<Const_Proxy_Function> get_contained_functions() const CHAISCRIPT_OVERRIDE
{
return {m_func};
}
virtual std::string annotation() const CHAISCRIPT_OVERRIDE
{
return m_func->annotation();
}
protected:
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
{
if (dynamic_object_typename_match(params, m_type_name, m_ti, t_conversions))
{
return (*m_func)(params, t_conversions);
} else {
throw exception::guard_error();
}
}
virtual bool compare_first_type(const Boxed_Value &bv, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
{
return dynamic_object_typename_match(bv, m_type_name, m_ti, t_conversions);
}
private:
static std::vector<Type_Info> build_param_types(
const std::vector<Type_Info> &t_inner_types, const Type_Info& t_objectti)
{
std::vector<Type_Info> types(t_inner_types);
assert(types.size() > 1);
assert(types[1].bare_equal(user_type<Boxed_Value>()));
types[1] = t_objectti;
return types;
}
bool dynamic_object_typename_match(const Boxed_Value &bv, const std::string &name,
const std::unique_ptr<Type_Info> &ti, const Type_Conversions &t_conversions) const
{
if (bv.get_type_info().bare_equal(m_doti))
{
try {
const Dynamic_Object &d = boxed_cast<const Dynamic_Object &>(bv, &t_conversions);
return name == "Dynamic_Object" || d.get_type_name() == name;
} catch (const std::bad_cast &) {
return false;
}
} else {
if (ti)
{
return bv.get_type_info().bare_equal(*ti);
} else {
return false;
}
}
}
bool dynamic_object_typename_match(const std::vector<Boxed_Value> &bvs, const std::string &name,
const std::unique_ptr<Type_Info> &ti, const Type_Conversions &t_conversions) const
{
if (bvs.size() > 0)
{
return dynamic_object_typename_match(bvs[0], name, ti, t_conversions);
} else {
return false;
}
}
std::string m_type_name;
Proxy_Function m_func;
std::unique_ptr<Type_Info> m_ti;
const Type_Info m_doti;
};
/**
* A Proxy_Function implementation designed for creating a new
* Dynamic_Object
* that is automatically guarded based on the first param based on the
* param's type name
*/
class Dynamic_Object_Constructor : public Proxy_Function_Base
{
public:
Dynamic_Object_Constructor(
std::string t_type_name,
const Proxy_Function &t_func)
: Proxy_Function_Base(build_type_list(t_func->get_param_types()), t_func->get_arity() - 1),
m_type_name(std::move(t_type_name)), m_func(t_func)
{
assert( (t_func->get_arity() > 0 || t_func->get_arity() < 0)
&& "Programming error, Dynamic_Object_Function must have at least one parameter (this)");
}
static std::vector<Type_Info> build_type_list(const std::vector<Type_Info> &tl)
{
auto begin = tl.begin();
auto end = tl.end();
if (begin != end)
{
++begin;
}
return std::vector<Type_Info>(begin, end);
}
virtual ~Dynamic_Object_Constructor() {}
virtual bool operator==(const Proxy_Function_Base &f) const CHAISCRIPT_OVERRIDE
{
const Dynamic_Object_Constructor *dc = dynamic_cast<const Dynamic_Object_Constructor*>(&f);
if (dc)
{
return dc->m_type_name == m_type_name && (*dc->m_func) == (*m_func);
} else {
return false;
}
}
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
{
std::vector<Boxed_Value> new_vals{Boxed_Value(Dynamic_Object(m_type_name))};
new_vals.insert(new_vals.end(), vals.begin(), vals.end());
return m_func->call_match(new_vals, t_conversions);
}
virtual std::string annotation() const CHAISCRIPT_OVERRIDE
{
return m_func->annotation();
}
protected:
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
{
auto bv = var(Dynamic_Object(m_type_name));
std::vector<Boxed_Value> new_params{bv};
new_params.insert(new_params.end(), params.begin(), params.end());
(*m_func)(new_params, t_conversions);
return bv;
}
private:
std::string m_type_name;
Proxy_Function m_func;
};
}
} }
} }
#endif #endif

View File

@ -0,0 +1,251 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_DYNAMIC_OBJECT_DETAIL_HPP_
#define CHAISCRIPT_DYNAMIC_OBJECT_DETAIL_HPP_
#include <cassert>
#include <map>
#include <memory>
#include <string>
#include <typeinfo>
#include <utility>
#include <vector>
#include "../chaiscript_defines.hpp"
#include "boxed_cast.hpp"
#include "boxed_cast_helper.hpp"
#include "boxed_value.hpp"
#include "proxy_functions.hpp"
#include "type_info.hpp"
#include "dynamic_object.hpp"
namespace chaiscript {
class Type_Conversions;
namespace dispatch {
class Proxy_Function_Base;
} // namespace dispatch
} // namespace chaiscript
namespace chaiscript
{
namespace dispatch
{
namespace detail
{
/// A Proxy_Function implementation designed for calling a function
/// that is automatically guarded based on the first param based on the
/// param's type name
class Dynamic_Object_Function : public Proxy_Function_Base
{
public:
Dynamic_Object_Function(
std::string t_type_name,
const Proxy_Function &t_func)
: Proxy_Function_Base(t_func->get_param_types(), t_func->get_arity()),
m_type_name(std::move(t_type_name)), m_func(t_func), m_doti(user_type<Dynamic_Object>())
{
assert( (t_func->get_arity() > 0 || t_func->get_arity() < 0)
&& "Programming error, Dynamic_Object_Function must have at least one parameter (this)");
}
Dynamic_Object_Function(
std::string t_type_name,
const Proxy_Function &t_func,
const Type_Info &t_ti)
: Proxy_Function_Base(build_param_types(t_func->get_param_types(), t_ti), t_func->get_arity()),
m_type_name(std::move(t_type_name)), m_func(t_func), m_ti(new Type_Info(t_ti)), m_doti(user_type<Dynamic_Object>())
{
assert( (t_func->get_arity() > 0 || t_func->get_arity() < 0)
&& "Programming error, Dynamic_Object_Function must have at least one parameter (this)");
}
virtual ~Dynamic_Object_Function() {}
Dynamic_Object_Function &operator=(const Dynamic_Object_Function) = delete;
Dynamic_Object_Function(Dynamic_Object_Function &) = delete;
virtual bool operator==(const Proxy_Function_Base &f) const CHAISCRIPT_OVERRIDE
{
if (const auto *df = dynamic_cast<const Dynamic_Object_Function *>(&f))
{
return df->m_type_name == m_type_name && (*df->m_func) == (*m_func);
} else {
return false;
}
}
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
{
if (dynamic_object_typename_match(vals, m_type_name, m_ti, t_conversions))
{
return m_func->call_match(vals, t_conversions);
} else {
return false;
}
}
virtual std::vector<Const_Proxy_Function> get_contained_functions() const CHAISCRIPT_OVERRIDE
{
return {m_func};
}
virtual std::string annotation() const CHAISCRIPT_OVERRIDE
{
return m_func->annotation();
}
protected:
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
{
if (dynamic_object_typename_match(params, m_type_name, m_ti, t_conversions))
{
return (*m_func)(params, t_conversions);
} else {
throw exception::guard_error();
}
}
virtual bool compare_first_type(const Boxed_Value &bv, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
{
return dynamic_object_typename_match(bv, m_type_name, m_ti, t_conversions);
}
private:
static std::vector<Type_Info> build_param_types(
const std::vector<Type_Info> &t_inner_types, const Type_Info& t_objectti)
{
std::vector<Type_Info> types(t_inner_types);
assert(types.size() > 1);
//assert(types[1].bare_equal(user_type<Boxed_Value>()));
types[1] = t_objectti;
return types;
}
bool dynamic_object_typename_match(const Boxed_Value &bv, const std::string &name,
const std::unique_ptr<Type_Info> &ti, const Type_Conversions &t_conversions) const
{
if (bv.get_type_info().bare_equal(m_doti))
{
try {
const Dynamic_Object &d = boxed_cast<const Dynamic_Object &>(bv, &t_conversions);
return name == "Dynamic_Object" || d.get_type_name() == name;
} catch (const std::bad_cast &) {
return false;
}
} else {
if (ti)
{
return bv.get_type_info().bare_equal(*ti);
} else {
return false;
}
}
}
bool dynamic_object_typename_match(const std::vector<Boxed_Value> &bvs, const std::string &name,
const std::unique_ptr<Type_Info> &ti, const Type_Conversions &t_conversions) const
{
if (bvs.size() > 0)
{
return dynamic_object_typename_match(bvs[0], name, ti, t_conversions);
} else {
return false;
}
}
std::string m_type_name;
Proxy_Function m_func;
std::unique_ptr<Type_Info> m_ti;
const Type_Info m_doti;
};
/**
* A Proxy_Function implementation designed for creating a new
* Dynamic_Object
* that is automatically guarded based on the first param based on the
* param's type name
*/
class Dynamic_Object_Constructor : public Proxy_Function_Base
{
public:
Dynamic_Object_Constructor(
std::string t_type_name,
const Proxy_Function &t_func)
: Proxy_Function_Base(build_type_list(t_func->get_param_types()), t_func->get_arity() - 1),
m_type_name(std::move(t_type_name)), m_func(t_func)
{
assert( (t_func->get_arity() > 0 || t_func->get_arity() < 0)
&& "Programming error, Dynamic_Object_Function must have at least one parameter (this)");
}
static std::vector<Type_Info> build_type_list(const std::vector<Type_Info> &tl)
{
auto begin = tl.begin();
auto end = tl.end();
if (begin != end)
{
++begin;
}
return std::vector<Type_Info>(begin, end);
}
virtual ~Dynamic_Object_Constructor() {}
virtual bool operator==(const Proxy_Function_Base &f) const CHAISCRIPT_OVERRIDE
{
const Dynamic_Object_Constructor *dc = dynamic_cast<const Dynamic_Object_Constructor*>(&f);
if (dc)
{
return dc->m_type_name == m_type_name && (*dc->m_func) == (*m_func);
} else {
return false;
}
}
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
{
std::vector<Boxed_Value> new_vals{Boxed_Value(Dynamic_Object(m_type_name))};
new_vals.insert(new_vals.end(), vals.begin(), vals.end());
return m_func->call_match(new_vals, t_conversions);
}
virtual std::string annotation() const CHAISCRIPT_OVERRIDE
{
return m_func->annotation();
}
protected:
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
{
auto bv = var(Dynamic_Object(m_type_name));
std::vector<Boxed_Value> new_params{bv};
new_params.insert(new_params.end(), params.begin(), params.end());
(*m_func)(new_params, t_conversions);
return bv;
}
private:
std::string m_type_name;
Proxy_Function m_func;
};
}
}
}
#endif

View File

@ -1,7 +1,7 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com) // Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
#ifndef CHAISCRIPT_EXCEPTION_SPECIFICATION_HPP_ #ifndef CHAISCRIPT_EXCEPTION_SPECIFICATION_HPP_

View File

@ -1,7 +1,7 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com) // Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
#ifndef CHAISCRIPT_FUNCTION_CALL_HPP_ #ifndef CHAISCRIPT_FUNCTION_CALL_HPP_

View File

@ -1,7 +1,7 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com) // Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
#ifndef CHAISCRIPT_FUNCTION_CALL_DETAIL_HPP_ #ifndef CHAISCRIPT_FUNCTION_CALL_DETAIL_HPP_

View File

@ -1,7 +1,7 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com) // Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
#ifndef CHAISCRIPT_HANDLE_RETURN_HPP_ #ifndef CHAISCRIPT_HANDLE_RETURN_HPP_
@ -37,6 +37,11 @@ namespace chaiscript
{ {
return const_var(r); return const_var(r);
} }
static Boxed_Value handle(Ret &&r)
{
return Boxed_Value(std::move(r));
}
}; };
template<typename Ret> template<typename Ret>

View File

@ -1,7 +1,7 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com) // Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
#ifndef CHAISCRIPT_OPERATORS_HPP_ #ifndef CHAISCRIPT_OPERATORS_HPP_

View File

@ -1,13 +1,15 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com) // Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
#ifndef CHAISCRIPT_PROXY_CONSTRUCTORS_HPP_ #ifndef CHAISCRIPT_PROXY_CONSTRUCTORS_HPP_
#define CHAISCRIPT_PROXY_CONSTRUCTORS_HPP_ #define CHAISCRIPT_PROXY_CONSTRUCTORS_HPP_
#include "proxy_functions.hpp"
namespace chaiscript namespace chaiscript
{ {
namespace dispatch namespace dispatch

View File

@ -1,7 +1,7 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com) // Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
@ -24,6 +24,7 @@
#include "boxed_value.hpp" #include "boxed_value.hpp"
#include "proxy_functions_detail.hpp" #include "proxy_functions_detail.hpp"
#include "type_info.hpp" #include "type_info.hpp"
#include "dynamic_object.hpp"
namespace chaiscript { namespace chaiscript {
class Type_Conversions; class Type_Conversions;
@ -42,6 +43,95 @@ namespace chaiscript
namespace dispatch namespace dispatch
{ {
class Param_Types
{
public:
Param_Types()
: m_has_types(false),
m_doti(user_type<Dynamic_Object>())
{}
Param_Types(std::vector<std::pair<std::string, Type_Info>> t_types)
: m_types(std::move(t_types)),
m_has_types(false),
m_doti(user_type<Dynamic_Object>())
{
update_has_types();
}
void push_front(std::string t_name, Type_Info t_ti)
{
m_types.emplace(m_types.begin(), std::move(t_name), std::move(t_ti));
update_has_types();
}
bool operator==(const Param_Types &t_rhs) const
{
return m_types == t_rhs.m_types;
}
bool match(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const
{
if (!m_has_types) return true;
if (vals.size() != m_types.size()) return false;
for (size_t i = 0; i < vals.size(); ++i)
{
const auto &name = m_types[i].first;
if (!name.empty()) {
const auto &bv = vals[i];
if (bv.get_type_info().bare_equal(m_doti))
{
try {
const Dynamic_Object &d = boxed_cast<const Dynamic_Object &>(bv, &t_conversions);
return name == "Dynamic_Object" || d.get_type_name() == name;
} catch (const std::bad_cast &) {
return false;
}
} else {
const auto &ti = m_types[i].second;
if (!ti.is_undef())
{
if (!bv.get_type_info().bare_equal(ti)) {
return false;
}
} else {
return false;
}
}
}
}
return true;
}
const std::vector<std::pair<std::string, Type_Info>> &types() const
{
return m_types;
}
private:
void update_has_types()
{
for (const auto &type : m_types)
{
if (!type.first.empty())
{
m_has_types = true;
return;
}
}
m_has_types = false;
}
std::vector<std::pair<std::string, Type_Info>> m_types;
bool m_has_types;
Type_Info m_doti;
};
/** /**
* Pure virtual base class for all Proxy_Function implementations * Pure virtual base class for all Proxy_Function implementations
* Proxy_Functions are a type erasure of type safe C++ * Proxy_Functions are a type erasure of type safe C++
@ -129,7 +219,7 @@ namespace chaiscript
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions &t_conversions) const = 0; virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions &t_conversions) const = 0;
Proxy_Function_Base(std::vector<Type_Info> t_types, int t_arity) Proxy_Function_Base(std::vector<Type_Info> t_types, int t_arity)
: m_types(std::move(t_types)), m_has_arithmetic_param(false), m_arity(t_arity) : m_types(std::move(t_types)), m_arity(t_arity), m_has_arithmetic_param(false)
{ {
for (size_t i = 1; i < m_types.size(); ++i) for (size_t i = 1; i < m_types.size(); ++i)
{ {
@ -175,8 +265,8 @@ namespace chaiscript
} }
std::vector<Type_Info> m_types; std::vector<Type_Info> m_types;
bool m_has_arithmetic_param;
int m_arity; int m_arity;
bool m_has_arithmetic_param;
}; };
} }
@ -197,6 +287,8 @@ namespace chaiscript
: std::runtime_error("Guard evaluation failed") : std::runtime_error("Guard evaluation failed")
{ } { }
guard_error(const guard_error &) = default;
virtual ~guard_error() CHAISCRIPT_NOEXCEPT virtual ~guard_error() CHAISCRIPT_NOEXCEPT
{ } { }
}; };
@ -215,10 +307,13 @@ namespace chaiscript
std::function<Boxed_Value (const std::vector<Boxed_Value> &)> t_f, std::function<Boxed_Value (const std::vector<Boxed_Value> &)> t_f,
int t_arity=-1, int t_arity=-1,
AST_NodePtr t_parsenode = AST_NodePtr(), AST_NodePtr t_parsenode = AST_NodePtr(),
Param_Types t_param_types = Param_Types(),
std::string t_description = "", std::string t_description = "",
Proxy_Function t_guard = Proxy_Function()) Proxy_Function t_guard = Proxy_Function())
: Proxy_Function_Base(build_param_type_list(t_arity), t_arity), : Proxy_Function_Base(build_param_type_list(t_param_types), t_arity),
m_f(std::move(t_f)), m_arity(t_arity), m_description(std::move(t_description)), m_guard(std::move(t_guard)), m_parsenode(std::move(t_parsenode)) m_param_types(std::move(t_param_types)),
m_guard(std::move(t_guard)), m_parsenode(std::move(t_parsenode)), m_description(std::move(t_description)),
m_f(std::move(t_f))
{ {
} }
@ -231,14 +326,15 @@ namespace chaiscript
return this == &rhs return this == &rhs
|| (prhs || (prhs
&& this->m_arity == prhs->m_arity && this->m_arity == prhs->m_arity
&& !this->m_guard && !prhs->m_guard); && !this->m_guard && !prhs->m_guard
&& this->m_param_types == prhs->m_param_types);
} }
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
{ {
return (m_arity < 0 || vals.size() == size_t(m_arity)) return (m_arity < 0 || (vals.size() == size_t(m_arity) && m_param_types.match(vals, t_conversions)))
&& test_guard(vals, t_conversions); && test_guard(vals, t_conversions);
} }
Proxy_Function get_guard() const Proxy_Function get_guard() const
@ -261,8 +357,7 @@ namespace chaiscript
{ {
if (m_arity < 0 || params.size() == size_t(m_arity)) if (m_arity < 0 || params.size() == size_t(m_arity))
{ {
if (call_match(params, t_conversions) && test_guard(params, t_conversions))
if (test_guard(params, t_conversions))
{ {
return m_f(params); return m_f(params);
} else { } else {
@ -291,29 +386,30 @@ namespace chaiscript
} }
} }
static std::vector<Type_Info> build_param_type_list(int arity) static std::vector<Type_Info> build_param_type_list(const Param_Types &t_types)
{ {
std::vector<Type_Info> types; std::vector<Type_Info> types;
// For the return type // For the return type
types.push_back(chaiscript::detail::Get_Type_Info<Boxed_Value>::get()); types.push_back(chaiscript::detail::Get_Type_Info<Boxed_Value>::get());
if (arity > 0) for (const auto &t : t_types.types())
{ {
for (int i = 0; i < arity; ++i) if (t.second.is_undef()) {
{
types.push_back(chaiscript::detail::Get_Type_Info<Boxed_Value>::get()); types.push_back(chaiscript::detail::Get_Type_Info<Boxed_Value>::get());
} else {
types.push_back(t.second);
} }
} }
return types; return types;
} }
std::function<Boxed_Value (const std::vector<Boxed_Value> &)> m_f; Param_Types m_param_types;
int m_arity;
std::string m_description;
Proxy_Function m_guard; Proxy_Function m_guard;
AST_NodePtr m_parsenode; AST_NodePtr m_parsenode;
std::string m_description;
std::function<Boxed_Value (const std::vector<Boxed_Value> &)> m_f;
}; };
/** /**
@ -560,7 +656,7 @@ namespace chaiscript
} }
} else { } else {
throw exception::arity_error(static_cast<int>(params.size()), 1); throw exception::arity_error(static_cast<int>(params.size()), 1);
} }
} }
private: private:
@ -589,6 +685,7 @@ namespace chaiscript
{ {
} }
dispatch_error(const dispatch_error &) = default;
virtual ~dispatch_error() CHAISCRIPT_NOEXCEPT {} virtual ~dispatch_error() CHAISCRIPT_NOEXCEPT {}
std::vector<Boxed_Value> parameters; std::vector<Boxed_Value> parameters;

View File

@ -1,7 +1,7 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com) // Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
#ifndef CHAISCRIPT_PROXY_FUNCTIONS_DETAIL_HPP_ #ifndef CHAISCRIPT_PROXY_FUNCTIONS_DETAIL_HPP_
@ -42,6 +42,8 @@ namespace chaiscript
{ {
} }
arity_error(const arity_error &) = default;
virtual ~arity_error() CHAISCRIPT_NOEXCEPT {} virtual ~arity_error() CHAISCRIPT_NOEXCEPT {}
int got; int got;
@ -72,7 +74,7 @@ namespace chaiscript
template<typename Param, typename ... Rest> template<typename Param, typename ... Rest>
struct Try_Cast<Param, Rest...> struct Try_Cast<Param, Rest...>
{ {
static void do_try(const std::vector<Boxed_Value> &params, int generation, const Type_Conversions &t_conversions) static void do_try(const std::vector<Boxed_Value> &params, size_t generation, const Type_Conversions &t_conversions)
{ {
boxed_cast<Param>(params[generation], &t_conversions); boxed_cast<Param>(params[generation], &t_conversions);
Try_Cast<Rest...>::do_try(params, generation+1, t_conversions); Try_Cast<Rest...>::do_try(params, generation+1, t_conversions);
@ -83,7 +85,7 @@ namespace chaiscript
template<> template<>
struct Try_Cast<> struct Try_Cast<>
{ {
static void do_try(const std::vector<Boxed_Value> &, int, const Type_Conversions &) static void do_try(const std::vector<Boxed_Value> &, size_t, const Type_Conversions &)
{ {
} }
}; };

View File

@ -1,7 +1,7 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com) // Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
#ifndef CHAISCRIPT_REGISTER_FUNCTION_HPP_ #ifndef CHAISCRIPT_REGISTER_FUNCTION_HPP_

View File

@ -1,7 +1,7 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com) // Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
#ifndef CHAISCRIPT_DYNAMIC_CAST_CONVERSION_HPP_ #ifndef CHAISCRIPT_DYNAMIC_CAST_CONVERSION_HPP_
@ -44,6 +44,8 @@ namespace chaiscript
{ {
} }
bad_boxed_dynamic_cast(const bad_boxed_dynamic_cast &) = default;
virtual ~bad_boxed_dynamic_cast() CHAISCRIPT_NOEXCEPT {} virtual ~bad_boxed_dynamic_cast() CHAISCRIPT_NOEXCEPT {}
}; };
@ -66,6 +68,8 @@ namespace chaiscript
{ {
} }
bad_boxed_type_cast(const bad_boxed_type_cast &) = default;
virtual ~bad_boxed_type_cast() CHAISCRIPT_NOEXCEPT {} virtual ~bad_boxed_type_cast() CHAISCRIPT_NOEXCEPT {}
}; };
} }
@ -213,14 +217,20 @@ namespace chaiscript
}; };
Type_Conversions() Type_Conversions()
: m_num_types(0), : m_mutex(),
m_conversions(),
m_convertableTypes(),
m_num_types(0),
m_thread_cache(this), m_thread_cache(this),
m_conversion_saves(this) m_conversion_saves(this)
{ {
} }
Type_Conversions(const Type_Conversions &t_other) Type_Conversions(const Type_Conversions &t_other)
: m_conversions(t_other.get_conversions()), m_num_types(m_conversions.size()), : m_mutex(),
m_conversions(t_other.get_conversions()),
m_convertableTypes(),
m_num_types(m_conversions.size()),
m_thread_cache(this), m_thread_cache(this),
m_conversion_saves(this) m_conversion_saves(this)
@ -366,8 +376,8 @@ namespace chaiscript
std::set<std::shared_ptr<detail::Type_Conversion_Base>> m_conversions; std::set<std::shared_ptr<detail::Type_Conversion_Base>> m_conversions;
std::set<const std::type_info *, Less_Than> m_convertableTypes; std::set<const std::type_info *, Less_Than> m_convertableTypes;
std::atomic_size_t m_num_types; std::atomic_size_t m_num_types;
chaiscript::detail::threading::Thread_Storage<std::set<const std::type_info *, Less_Than>> m_thread_cache; mutable chaiscript::detail::threading::Thread_Storage<std::set<const std::type_info *, Less_Than>> m_thread_cache;
chaiscript::detail::threading::Thread_Storage<Conversion_Saves> m_conversion_saves; mutable chaiscript::detail::threading::Thread_Storage<Conversion_Saves> m_conversion_saves;
}; };
typedef std::shared_ptr<chaiscript::detail::Type_Conversion_Base> Type_Conversion; typedef std::shared_ptr<chaiscript::detail::Type_Conversion_Base> Type_Conversion;

View File

@ -1,7 +1,7 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com) // Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
#ifndef CHAISCRIPT_TYPE_INFO_HPP_ #ifndef CHAISCRIPT_TYPE_INFO_HPP_

View File

@ -1,7 +1,7 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com) // Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
#ifndef CHAISCRIPT_ALGEBRAIC_HPP_ #ifndef CHAISCRIPT_ALGEBRAIC_HPP_

View File

@ -1,7 +1,7 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com) // Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
#ifndef CHAISCRIPT_COMMON_HPP_ #ifndef CHAISCRIPT_COMMON_HPP_
@ -37,7 +37,7 @@ namespace chaiscript
Comparison, Addition, Subtraction, Multiplication, Division, Modulus, Array_Call, Dot_Access, Quoted_String, Single_Quoted_String, Comparison, Addition, Subtraction, Multiplication, Division, Modulus, Array_Call, Dot_Access, Quoted_String, Single_Quoted_String,
Lambda, Block, Def, While, If, For, Inline_Array, Inline_Map, Return, File, Prefix, Break, Continue, Map_Pair, Value_Range, Lambda, Block, Def, While, If, For, Inline_Array, Inline_Map, Return, File, Prefix, Break, Continue, Map_Pair, Value_Range,
Inline_Range, Annotation, Try, Catch, Finally, Method, Attr_Decl, Shift, Equality, Bitwise_And, Bitwise_Xor, Bitwise_Or, Inline_Range, Annotation, Try, Catch, Finally, Method, Attr_Decl, Shift, Equality, Bitwise_And, Bitwise_Xor, Bitwise_Or,
Logical_And, Logical_Or, Reference, Switch, Case, Default, Ternary_Cond, Noop, Class, Binary Logical_And, Logical_Or, Reference, Switch, Case, Default, Ternary_Cond, Noop, Class, Binary, Arg
}; };
}; };
@ -50,7 +50,7 @@ namespace chaiscript
"Comparison", "Addition", "Subtraction", "Multiplication", "Division", "Modulus", "Array_Call", "Dot_Access", "Quoted_String", "Single_Quoted_String", "Comparison", "Addition", "Subtraction", "Multiplication", "Division", "Modulus", "Array_Call", "Dot_Access", "Quoted_String", "Single_Quoted_String",
"Lambda", "Block", "Def", "While", "If", "For", "Inline_Array", "Inline_Map", "Return", "File", "Prefix", "Break", "Continue", "Map_Pair", "Value_Range", "Lambda", "Block", "Def", "While", "If", "For", "Inline_Array", "Inline_Map", "Return", "File", "Prefix", "Break", "Continue", "Map_Pair", "Value_Range",
"Inline_Range", "Annotation", "Try", "Catch", "Finally", "Method", "Attr_Decl", "Shift", "Equality", "Bitwise_And", "Bitwise_Xor", "Bitwise_Or", "Inline_Range", "Annotation", "Try", "Catch", "Finally", "Method", "Attr_Decl", "Shift", "Equality", "Bitwise_And", "Bitwise_Xor", "Bitwise_Or",
"Logical_And", "Logical_Or", "Reference", "Switch", "Case", "Default", "Ternary Condition", "Noop", "Class", "Binary"}; "Logical_And", "Logical_Or", "Reference", "Switch", "Case", "Default", "Ternary Condition", "Noop", "Class", "Binary", "Arg"};
return ast_node_types[ast_node_type]; return ast_node_types[ast_node_type];
} }
@ -112,6 +112,8 @@ namespace chaiscript
reason(t_why) reason(t_why)
{} {}
eval_error(const eval_error &) = default;
std::string pretty_print() const std::string pretty_print() const
{ {
std::ostringstream ss; std::ostringstream ss;
@ -395,6 +397,7 @@ namespace chaiscript
: std::runtime_error("File Not Found: " + t_filename) : std::runtime_error("File Not Found: " + t_filename)
{ } { }
file_not_found_error(const file_not_found_error &) = default;
virtual ~file_not_found_error() CHAISCRIPT_NOEXCEPT {} virtual ~file_not_found_error() CHAISCRIPT_NOEXCEPT {}
}; };

View File

@ -1,7 +1,7 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com) // Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
#ifndef CHAISCRIPT_ENGINE_HPP_ #ifndef CHAISCRIPT_ENGINE_HPP_
@ -61,9 +61,8 @@ namespace chaiscript
{ {
} }
virtual ~load_module_error() CHAISCRIPT_NOEXCEPT load_module_error(const load_module_error &) = default;
{ virtual ~load_module_error() CHAISCRIPT_NOEXCEPT {}
}
}; };
} }
@ -371,10 +370,10 @@ namespace chaiscript
m_engine.add(fun(&ChaiScript::internal_eval, this), "eval"); m_engine.add(fun(&ChaiScript::internal_eval, this), "eval");
m_engine.add(fun(&ChaiScript::internal_eval_ast, this), "eval"); m_engine.add(fun(&ChaiScript::internal_eval_ast, this), "eval");
m_engine.add(fun(&ChaiScript::version_major, this), "version_major"); m_engine.add(fun(&ChaiScript::version_major), "version_major");
m_engine.add(fun(&ChaiScript::version_minor, this), "version_minor"); m_engine.add(fun(&ChaiScript::version_minor), "version_minor");
m_engine.add(fun(&ChaiScript::version_patch, this), "version_patch"); m_engine.add(fun(&ChaiScript::version_patch), "version_patch");
m_engine.add(fun(&ChaiScript::version, this), "version"); m_engine.add(fun(&ChaiScript::version), "version");
m_engine.add(fun(&ChaiScript::add_global_const, this), "add_global_const"); m_engine.add(fun(&ChaiScript::add_global_const, this), "add_global_const");
m_engine.add(fun(&ChaiScript::add_global, this), "add_global"); m_engine.add(fun(&ChaiScript::add_global, this), "add_global");
@ -464,7 +463,7 @@ namespace chaiscript
memset( &rInfo, 0, sizeof(rInfo) ); memset( &rInfo, 0, sizeof(rInfo) );
cast_union u; cast_union u;
u.in_ptr = &ChaiScript::use; u.in_ptr = &ChaiScript::use;
if ( dladdr((void*)(u.out_ptr), &rInfo) && rInfo.dli_fname ) { if ( dladdr(static_cast<void*>(u.out_ptr), &rInfo) && rInfo.dli_fname ) {
std::string dllpath(rInfo.dli_fname); std::string dllpath(rInfo.dli_fname);
const size_t lastslash = dllpath.rfind('/'); const size_t lastslash = dllpath.rfind('/');
if (lastslash != std::string::npos) if (lastslash != std::string::npos)
@ -491,22 +490,22 @@ namespace chaiscript
build_eval_system(ModulePtr()); build_eval_system(ModulePtr());
} }
int version_major() const static int version_major()
{ {
return chaiscript::version_major; return chaiscript::version_major;
} }
int version_minor() const static int version_minor()
{ {
return chaiscript::version_minor; return chaiscript::version_minor;
} }
int version_patch() const static int version_patch()
{ {
return chaiscript::version_patch; return chaiscript::version_patch;
} }
std::string version() const static std::string version()
{ {
std::stringstream ss; std::stringstream ss;
ss << version_major() << "." << version_minor() << "." << version_patch(); ss << version_major() << "." << version_minor() << "." << version_patch();
@ -581,6 +580,8 @@ namespace chaiscript
} }
/// \brief Represents the current state of the ChaiScript system. State and be saved and restored /// \brief Represents the current state of the ChaiScript system. State and be saved and restored
/// \warning State object does not contain the user defined type conversions of the engine. They
/// are left out due to performance considerations involved in tracking the state
/// \sa ChaiScript::get_state /// \sa ChaiScript::get_state
/// \sa ChaiScript::set_state /// \sa ChaiScript::set_state
struct State struct State
@ -603,7 +604,7 @@ namespace chaiscript
/// chaiscript::ChaiScript chai; /// chaiscript::ChaiScript chai;
/// chaiscript::ChaiScript::State s = chai.get_state(); // represents bootstrapped initial state /// chaiscript::ChaiScript::State s = chai.get_state(); // represents bootstrapped initial state
/// \endcode /// \endcode
State get_state() State get_state() const
{ {
chaiscript::detail::threading::lock_guard<chaiscript::detail::threading::recursive_mutex> l(m_use_mutex); chaiscript::detail::threading::lock_guard<chaiscript::detail::threading::recursive_mutex> l(m_use_mutex);
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l2(m_mutex); chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l2(m_mutex);
@ -706,7 +707,7 @@ namespace chaiscript
/// \param[in] t_module_name Name of the module to load /// \param[in] t_module_name Name of the module to load
/// ///
/// The module is searched for in the registered module path folders (chaiscript::ChaiScript::ChaiScript) /// The module is searched for in the registered module path folders (chaiscript::ChaiScript::ChaiScript)
/// and with standard prefixes and postfixes: ("lib"|"")\<t_module_name\>(".dll"|".so"|""). /// and with standard prefixes and postfixes: ("lib"|"")\<t_module_name\>(".dll"|".so"|".bundle"|"").
/// ///
/// Once the file is located, the system looks for the symbol "create_chaiscript_module_\<t_module_name\>". /// Once the file is located, the system looks for the symbol "create_chaiscript_module_\<t_module_name\>".
/// If no file can be found matching the search criteria and containing the appropriate entry point /// If no file can be found matching the search criteria and containing the appropriate entry point
@ -725,7 +726,7 @@ namespace chaiscript
std::vector<std::string> prefixes{"lib", "cyg", ""}; std::vector<std::string> prefixes{"lib", "cyg", ""};
std::vector<std::string> postfixes{".dll", ".so", ""}; std::vector<std::string> postfixes{".dll", ".so", ".bundle", ""};
for (auto & elem : m_modulepaths) for (auto & elem : m_modulepaths)
{ {

View File

@ -1,7 +1,7 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com) // Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
#ifndef CHAISCRIPT_EVAL_HPP_ #ifndef CHAISCRIPT_EVAL_HPP_
@ -25,6 +25,7 @@
#include "../dispatchkit/boxed_number.hpp" #include "../dispatchkit/boxed_number.hpp"
#include "../dispatchkit/boxed_value.hpp" #include "../dispatchkit/boxed_value.hpp"
#include "../dispatchkit/dispatchkit.hpp" #include "../dispatchkit/dispatchkit.hpp"
#include "../dispatchkit/dynamic_object_detail.hpp"
#include "../dispatchkit/proxy_functions.hpp" #include "../dispatchkit/proxy_functions.hpp"
#include "../dispatchkit/proxy_functions_detail.hpp" #include "../dispatchkit/proxy_functions_detail.hpp"
#include "../dispatchkit/register_function.hpp" #include "../dispatchkit/register_function.hpp"
@ -93,6 +94,8 @@ namespace chaiscript
// If it's an arithmetic operation we want to short circuit dispatch // If it's an arithmetic operation we want to short circuit dispatch
try{ try{
return Boxed_Number::do_oper(t_oper, t_lhs, t_rhs); return Boxed_Number::do_oper(t_oper, t_lhs, t_rhs);
} catch (const chaiscript::exception::arithmetic_error &) {
throw;
} catch (...) { } catch (...) {
throw exception::eval_error("Error with numeric operator calling: " + t_oper_string); throw exception::eval_error("Error with numeric operator calling: " + t_oper_string);
} }
@ -349,6 +352,28 @@ namespace chaiscript
}; };
struct Arg_AST_Node : public AST_Node {
public:
Arg_AST_Node(std::string t_ast_node_text = "", const std::shared_ptr<std::string> &t_fname=std::shared_ptr<std::string>(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
AST_Node(std::move(t_ast_node_text), AST_Node_Type::Arg_List, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
virtual ~Arg_AST_Node() {}
virtual std::string pretty_print() const CHAISCRIPT_OVERRIDE
{
std::ostringstream oss;
for (size_t j = 0; j < this->children.size(); ++j) {
if (j != 0)
{
oss << " ";
}
oss << this->children[j]->pretty_print();
}
return oss.str();
}
};
struct Arg_List_AST_Node : public AST_Node { struct Arg_List_AST_Node : public AST_Node {
public: public:
Arg_List_AST_Node(std::string t_ast_node_text = "", const std::shared_ptr<std::string> &t_fname=std::shared_ptr<std::string>(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : Arg_List_AST_Node(std::string t_ast_node_text = "", const std::shared_ptr<std::string> &t_fname=std::shared_ptr<std::string>(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
@ -369,6 +394,53 @@ namespace chaiscript
return oss.str(); return oss.str();
} }
static std::string get_arg_name(const AST_NodePtr &t_node) {
if (t_node->children.empty())
{
return t_node->text;
} else if (t_node->children.size() == 1) {
return t_node->children[0]->text;
} else {
return t_node->children[1]->text;
}
}
static std::vector<std::string> get_arg_names(const AST_NodePtr &t_node) {
std::vector<std::string> retval;
for (const auto &node : t_node->children)
{
retval.push_back(get_arg_name(node));
}
return retval;
}
static std::pair<std::string, Type_Info> get_arg_type(const AST_NodePtr &t_node, chaiscript::detail::Dispatch_Engine &t_ss)
{
if (t_node->children.size() < 2)
{
return std::pair<std::string, Type_Info>();
} else {
try {
return std::pair<std::string, Type_Info>(t_node->children[0]->text, t_ss.get_type(t_node->children[0]->text));
} catch (const std::range_error &) {
return std::pair<std::string, Type_Info>(t_node->children[0]->text, Type_Info());
}
}
}
static dispatch::Param_Types get_arg_types(const AST_NodePtr &t_node, chaiscript::detail::Dispatch_Engine &t_ss) {
std::vector<std::pair<std::string, Type_Info>> retval;
for (const auto &child : t_node->children)
{
retval.push_back(get_arg_type(child, t_ss));
}
return dispatch::Param_Types(std::move(retval));
}
}; };
struct Equation_AST_Node : public AST_Node { struct Equation_AST_Node : public AST_Node {
@ -636,13 +708,12 @@ namespace chaiscript
size_t numparams = 0; size_t numparams = 0;
dispatch::Param_Types param_types;
if (!this->children.empty() && (this->children[0]->identifier == AST_Node_Type::Arg_List)) { if (!this->children.empty() && (this->children[0]->identifier == AST_Node_Type::Arg_List)) {
numparams = this->children[0]->children.size(); numparams = this->children[0]->children.size();
t_param_names = Arg_List_AST_Node::get_arg_names(this->children[0]);
for (const auto &child : this->children[0]->children) param_types = Arg_List_AST_Node::get_arg_types(this->children[0], t_ss);
{
t_param_names.push_back(child->text);
}
} }
const auto &lambda_node = this->children.back(); const auto &lambda_node = this->children.back();
@ -652,7 +723,7 @@ namespace chaiscript
{ {
return detail::eval_function(t_ss, lambda_node, t_param_names, t_params); return detail::eval_function(t_ss, lambda_node, t_param_names, t_params);
}, },
static_cast<int>(numparams), lambda_node))); static_cast<int>(numparams), lambda_node, param_types)));
} }
}; };
@ -696,13 +767,12 @@ namespace chaiscript
size_t numparams = 0; size_t numparams = 0;
AST_NodePtr guardnode; AST_NodePtr guardnode;
dispatch::Param_Types param_types;
if ((this->children.size() > 2) && (this->children[1]->identifier == AST_Node_Type::Arg_List)) { if ((this->children.size() > 2) && (this->children[1]->identifier == AST_Node_Type::Arg_List)) {
numparams = this->children[1]->children.size(); numparams = this->children[1]->children.size();
t_param_names = Arg_List_AST_Node::get_arg_names(this->children[1]);
for (const auto &child : this->children[1]->children) param_types = Arg_List_AST_Node::get_arg_types(this->children[1], t_ss);
{
t_param_names.push_back(child->text);
}
if (this->children.size() > 3) { if (this->children.size() > 3) {
guardnode = this->children[2]; guardnode = this->children[2];
@ -735,7 +805,7 @@ namespace chaiscript
{ {
return detail::eval_function(t_ss, func_node, t_param_names, t_params); return detail::eval_function(t_ss, func_node, t_param_names, t_params);
}, static_cast<int>(numparams), this->children.back(), }, static_cast<int>(numparams), this->children.back(),
l_annotation, guard)), l_function_name); param_types, l_annotation, guard)), l_function_name);
} }
catch (const exception::reserved_word_error &e) { catch (const exception::reserved_word_error &e) {
throw exception::eval_error("Reserved word used as function name '" + e.word() + "'"); throw exception::eval_error("Reserved word used as function name '" + e.word() + "'");
@ -1186,11 +1256,74 @@ namespace chaiscript
Try_AST_Node(const std::string &t_ast_node_text = "", const std::shared_ptr<std::string> &t_fname=std::shared_ptr<std::string>(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : Try_AST_Node(const std::string &t_ast_node_text = "", const std::shared_ptr<std::string> &t_fname=std::shared_ptr<std::string>(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
AST_Node(t_ast_node_text, AST_Node_Type::Try, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } AST_Node(t_ast_node_text, AST_Node_Type::Try, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
virtual ~Try_AST_Node() {} virtual ~Try_AST_Node() {}
Boxed_Value handle_exception(chaiscript::detail::Dispatch_Engine &t_ss, const Boxed_Value &t_except) const
{
Boxed_Value retval;
size_t end_point = this->children.size();
if (this->children.back()->identifier == AST_Node_Type::Finally) {
assert(end_point > 0);
end_point = this->children.size() - 1;
}
for (size_t i = 1; i < end_point; ++i) {
chaiscript::eval::detail::Scope_Push_Pop catchscope(t_ss);
AST_NodePtr catch_block = this->children[i];
if (catch_block->children.size() == 1) {
//No variable capture, no guards
retval = catch_block->children[0]->eval(t_ss);
break;
} else if (catch_block->children.size() == 2 || catch_block->children.size() == 3) {
const auto name = Arg_List_AST_Node::get_arg_name(catch_block->children[0]);
if (dispatch::Param_Types(
std::vector<std::pair<std::string, Type_Info>>{Arg_List_AST_Node::get_arg_type(catch_block->children[0], t_ss)}
).match(std::vector<Boxed_Value>{t_except}, t_ss.conversions()))
{
t_ss.add_object(name, t_except);
if (catch_block->children.size() == 2) {
//Variable capture, no guards
retval = catch_block->children[1]->eval(t_ss);
break;
}
else if (catch_block->children.size() == 3) {
//Variable capture, guards
bool guard = false;
try {
guard = boxed_cast<bool>(catch_block->children[1]->eval(t_ss));
} catch (const exception::bad_boxed_cast &) {
if (this->children.back()->identifier == AST_Node_Type::Finally) {
this->children.back()->children[0]->eval(t_ss);
}
throw exception::eval_error("Guard condition not boolean");
}
if (guard) {
retval = catch_block->children[2]->eval(t_ss);
break;
}
}
}
}
else {
if (this->children.back()->identifier == AST_Node_Type::Finally) {
this->children.back()->children[0]->eval(t_ss);
}
throw exception::eval_error("Internal error: catch block size unrecognized");
}
}
return retval;
}
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE{ virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE{
Boxed_Value retval; Boxed_Value retval;
chaiscript::eval::detail::Scope_Push_Pop spp(t_ss); chaiscript::eval::detail::Scope_Push_Pop spp(t_ss);
try { try {
retval = this->children[0]->eval(t_ss); retval = this->children[0]->eval(t_ss);
} }
@ -1201,98 +1334,11 @@ namespace chaiscript
throw; throw;
} }
catch (const std::exception &e) { catch (const std::exception &e) {
Boxed_Value except(std::ref(e)); retval = handle_exception(t_ss, Boxed_Value(std::ref(e)));
size_t end_point = this->children.size();
if (this->children.back()->identifier == AST_Node_Type::Finally) {
assert(end_point > 0);
end_point = this->children.size() - 1;
}
for (size_t i = 1; i < end_point; ++i) {
chaiscript::eval::detail::Scope_Push_Pop catchscope(t_ss);
AST_NodePtr catch_block = this->children[i];
if (catch_block->children.size() == 1) {
//No variable capture, no guards
retval = catch_block->children[0]->eval(t_ss);
break;
}
else if (catch_block->children.size() == 2) {
//Variable capture, no guards
t_ss.add_object(catch_block->children[0]->text, except);
retval = catch_block->children[1]->eval(t_ss);
break;
}
else if (catch_block->children.size() == 3) {
//Variable capture, no guards
t_ss.add_object(catch_block->children[0]->text, except);
bool guard = false;
try {
guard = boxed_cast<bool>(catch_block->children[1]->eval(t_ss));
} catch (const exception::bad_boxed_cast &) {
if (this->children.back()->identifier == AST_Node_Type::Finally) {
this->children.back()->children[0]->eval(t_ss);
}
throw exception::eval_error("Guard condition not boolean");
}
if (guard) {
retval = catch_block->children[2]->eval(t_ss);
break;
}
}
else {
if (this->children.back()->identifier == AST_Node_Type::Finally) {
this->children.back()->children[0]->eval(t_ss);
}
throw exception::eval_error("Internal error: catch block size unrecognized");
}
}
} }
catch (Boxed_Value &except) { catch (Boxed_Value &e) {
for (size_t i = 1; i < this->children.size(); ++i) { retval = handle_exception(t_ss, e);
chaiscript::eval::detail::Scope_Push_Pop catchscope(t_ss);
const auto &catch_block = this->children[i];
if (catch_block->children.size() == 1) {
//No variable capture, no guards
retval = catch_block->children[0]->eval(t_ss);
break;
}
else if (catch_block->children.size() == 2) {
//Variable capture, no guards
t_ss.add_object(catch_block->children[0]->text, except);
retval = catch_block->children[1]->eval(t_ss);
break;
}
else if (catch_block->children.size() == 3) {
//Variable capture, guards
t_ss.add_object(catch_block->children[0]->text, except);
bool guard;
try {
guard = boxed_cast<bool>(catch_block->children[1]->eval(t_ss));
}
catch (const exception::bad_boxed_cast &) {
if (this->children.back()->identifier == AST_Node_Type::Finally) {
this->children.back()->children[0]->eval(t_ss);
}
throw exception::eval_error("Guard condition not boolean");
}
if (guard) {
retval = catch_block->children[2]->eval(t_ss);
break;
}
}
else {
if (this->children.back()->identifier == AST_Node_Type::Finally) {
this->children.back()->children[0]->eval(t_ss);
}
throw exception::eval_error("Internal error: catch block size unrecognized");
}
}
} }
catch (...) { catch (...) {
if (this->children.back()->identifier == AST_Node_Type::Finally) { if (this->children.back()->identifier == AST_Node_Type::Finally) {
@ -1301,6 +1347,7 @@ namespace chaiscript
throw; throw;
} }
if (this->children.back()->identifier == AST_Node_Type::Finally) { if (this->children.back()->identifier == AST_Node_Type::Finally) {
retval = this->children.back()->children[0]->eval(t_ss); retval = this->children.back()->children[0]->eval(t_ss);
} }
@ -1333,29 +1380,29 @@ namespace chaiscript
AST_NodePtr guardnode; AST_NodePtr guardnode;
auto d = t_ss.get_parent_locals(); const auto d = t_ss.get_parent_locals();
auto itr = d.find("_current_class_name"); const auto itr = d.find("_current_class_name");
int class_offset = 0; const auto class_offset = (itr != d.end())?-1:0;
if (itr != d.end()) class_offset = -1;
const std::string & class_name = (itr != d.end())?std::string(boxed_cast<std::string>(itr->second)):this->children[0]->text; const std::string & class_name = (itr != d.end())?std::string(boxed_cast<std::string>(itr->second)):this->children[0]->text;
//The first param of a method is always the implied this ptr. //The first param of a method is always the implied this ptr.
std::vector<std::string> t_param_names{"this"}; std::vector<std::string> t_param_names{"this"};
dispatch::Param_Types param_types;
if ((this->children.size() > static_cast<size_t>(3 + class_offset)) && (this->children[(2 + class_offset)]->identifier == AST_Node_Type::Arg_List)) { if ((this->children.size() > static_cast<size_t>(3 + class_offset)) && (this->children[static_cast<size_t>(2 + class_offset)]->identifier == AST_Node_Type::Arg_List)) {
for (const auto &child : this->children[(2 + class_offset)]->children) { auto args = Arg_List_AST_Node::get_arg_names(this->children[static_cast<size_t>(2 + class_offset)]);
t_param_names.push_back(child->text); t_param_names.insert(t_param_names.end(), args.begin(), args.end());
} param_types = Arg_List_AST_Node::get_arg_types(this->children[static_cast<size_t>(2 + class_offset)], t_ss);
if (this->children.size() > static_cast<size_t>(4 + class_offset)) { if (this->children.size() > static_cast<size_t>(4 + class_offset)) {
guardnode = this->children[(3 + class_offset)]; guardnode = this->children[static_cast<size_t>(3 + class_offset)];
} }
} }
else { else {
//no parameters //no parameters
if (this->children.size() > static_cast<size_t>(3 + class_offset)) { if (this->children.size() > static_cast<size_t>(3 + class_offset)) {
guardnode = this->children[(2 + class_offset)]; guardnode = this->children[static_cast<size_t>(2 + class_offset)];
} }
} }
@ -1372,32 +1419,38 @@ namespace chaiscript
try { try {
const std::string & l_annotation = this->annotation?this->annotation->text:""; const std::string & l_annotation = this->annotation?this->annotation->text:"";
const std::string & function_name = this->children[(1 + class_offset)]->text; const std::string & function_name = this->children[static_cast<size_t>(1 + class_offset)]->text;
if (function_name == class_name) { if (function_name == class_name) {
param_types.push_front(class_name, Type_Info());
t_ss.add(std::make_shared<dispatch::detail::Dynamic_Object_Constructor>(class_name, std::make_shared<dispatch::Dynamic_Proxy_Function>(std::bind(chaiscript::eval::detail::eval_function, t_ss.add(std::make_shared<dispatch::detail::Dynamic_Object_Constructor>(class_name, std::make_shared<dispatch::Dynamic_Proxy_Function>(std::bind(chaiscript::eval::detail::eval_function,
std::ref(t_ss), this->children.back(), t_param_names, std::placeholders::_1), std::ref(t_ss), this->children.back(), t_param_names, std::placeholders::_1),
static_cast<int>(numparams), this->children.back(), l_annotation, guard)), static_cast<int>(numparams), this->children.back(), param_types, l_annotation, guard)),
function_name); function_name);
} }
else { else {
try { try {
// Do know type name // Do know type name (if this line fails, the catch block is called and the
// other version is called, with no Type_Info object known)
auto type = t_ss.get_type(class_name);
param_types.push_front(class_name, type);
t_ss.add( t_ss.add(
std::make_shared<dispatch::detail::Dynamic_Object_Function>(class_name, std::make_shared<dispatch::detail::Dynamic_Object_Function>(class_name,
std::make_shared<dispatch::Dynamic_Proxy_Function>(std::bind(chaiscript::eval::detail::eval_function, std::make_shared<dispatch::Dynamic_Proxy_Function>(std::bind(chaiscript::eval::detail::eval_function,
std::ref(t_ss), this->children.back(), std::ref(t_ss), this->children.back(),
t_param_names, std::placeholders::_1), static_cast<int>(numparams), this->children.back(), t_param_names, std::placeholders::_1), static_cast<int>(numparams), this->children.back(),
l_annotation, guard), t_ss.get_type(class_name)), function_name); param_types, l_annotation, guard), type), function_name);
} catch (const std::range_error &) { } catch (const std::range_error &) {
param_types.push_front(class_name, Type_Info());
// Do not know type name // Do not know type name
t_ss.add( t_ss.add(
std::make_shared<dispatch::detail::Dynamic_Object_Function>(class_name, std::make_shared<dispatch::detail::Dynamic_Object_Function>(class_name,
std::make_shared<dispatch::Dynamic_Proxy_Function>(std::bind(chaiscript::eval::detail::eval_function, std::make_shared<dispatch::Dynamic_Proxy_Function>(std::bind(chaiscript::eval::detail::eval_function,
std::ref(t_ss), this->children.back(), std::ref(t_ss), this->children.back(),
t_param_names, std::placeholders::_1), static_cast<int>(numparams), this->children.back(), t_param_names, std::placeholders::_1), static_cast<int>(numparams), this->children.back(),
l_annotation, guard)), function_name); param_types, l_annotation, guard)), function_name);
} }
} }
} }
@ -1420,24 +1473,23 @@ namespace chaiscript
{ {
const auto &d = t_ss.get_parent_locals(); const auto &d = t_ss.get_parent_locals();
const auto itr = d.find("_current_class_name"); const auto itr = d.find("_current_class_name");
int class_offset = 0; const auto class_offset = (itr != d.end())?-1:0;
if (itr != d.end()) class_offset = -1;
std::string class_name = (itr != d.end())?std::string(boxed_cast<std::string>(itr->second)):this->children[0]->text; std::string class_name = (itr != d.end())?std::string(boxed_cast<std::string>(itr->second)):this->children[0]->text;
try { try {
t_ss.add( t_ss.add(
std::make_shared<dispatch::detail::Dynamic_Object_Function>( std::make_shared<dispatch::detail::Dynamic_Object_Function>(
class_name, std::move(class_name),
fun(std::function<Boxed_Value (dispatch::Dynamic_Object &)>(std::bind(&dispatch::Dynamic_Object::get_attr, fun(std::function<Boxed_Value (dispatch::Dynamic_Object &)>(std::bind(&dispatch::Dynamic_Object::get_attr,
std::placeholders::_1, std::placeholders::_1,
this->children[(1 + class_offset)]->text this->children[static_cast<size_t>(1 + class_offset)]->text
)) ))
) )
), this->children[(1 + class_offset)]->text); ), this->children[static_cast<size_t>(1 + class_offset)]->text);
} }
catch (const exception::reserved_word_error &) { catch (const exception::reserved_word_error &) {
throw exception::eval_error("Reserved word used as attribute '" + this->children[(1 + class_offset)]->text + "'"); throw exception::eval_error("Reserved word used as attribute '" + this->children[static_cast<size_t>(1 + class_offset)]->text + "'");
} catch (const exception::name_conflict_error &e) { } catch (const exception::name_conflict_error &e) {
throw exception::eval_error("Attribute redefined '" + e.name() + "'"); throw exception::eval_error("Attribute redefined '" + e.name() + "'");
} }

View File

@ -1,7 +1,7 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com) // Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
#ifndef CHAISCRIPT_PARSER_HPP_ #ifndef CHAISCRIPT_PARSER_HPP_
@ -223,8 +223,8 @@ namespace chaiscript
t_t->end.column = pos_col_stop; t_t->end.column = pos_col_stop;
if (is_deep) { if (is_deep) {
t_t->children.assign(m_match_stack.begin() + t_match_start, m_match_stack.end()); t_t->children.assign(m_match_stack.begin() + static_cast<int>(t_match_start), m_match_stack.end());
m_match_stack.erase(m_match_stack.begin() + t_match_start, m_match_stack.end()); m_match_stack.erase(m_match_stack.begin() + static_cast<int>(t_match_start), m_match_stack.end());
} }
/// \todo fix the fact that a successful match that captured no ast_nodes doesn't have any real start position /// \todo fix the fact that a successful match that captured no ast_nodes doesn't have any real start position
@ -431,21 +431,13 @@ namespace chaiscript
} }
} }
std::stringstream ss(t_val.substr(0, i));
if (float_) if (float_)
{ {
float f; return const_var(std::stof(t_val.substr(0,i)));
ss >> f;
return const_var(f);
} else if (long_) { } else if (long_) {
long double f; return const_var(std::stold(t_val.substr(0,i)));
ss >> f;
return const_var(f);
} else { } else {
double f; return const_var(std::stod(t_val.substr(0,i)));
ss >> f;
return const_var(f);
} }
} }
@ -699,6 +691,25 @@ namespace chaiscript
} }
} }
/// Reads an argument from input
bool Arg() {
const auto prev_stack_top = m_match_stack.size();
SkipWS();
if (!Id(true)) {
return false;
}
SkipWS();
Id(true);
build_match(std::make_shared<eval::Arg_AST_Node>(), prev_stack_top);
return true;
}
/// Checks for a node annotation of the form "#<annotation>" /// Checks for a node annotation of the form "#<annotation>"
bool Annotation() { bool Annotation() {
SkipWS(); SkipWS();
@ -1109,6 +1120,33 @@ namespace chaiscript
} }
} }
/// Reads a comma-separated list of values from input, for function declarations
bool Decl_Arg_List() {
SkipWS(true);
bool retval = false;
const auto prev_stack_top = m_match_stack.size();
if (Arg()) {
retval = true;
while (Eol()) {}
if (Char(',')) {
do {
while (Eol()) {}
if (!Arg()) {
throw exception::eval_error("Unexpected value in parameter list", File_Position(m_line, m_col), *m_filename);
}
} while (Char(','));
}
build_match(std::make_shared<eval::Arg_List_AST_Node>(), prev_stack_top);
}
SkipWS(true);
return retval;
}
/// Reads a comma-separated list of values from input /// Reads a comma-separated list of values from input
bool Arg_List() { bool Arg_List() {
SkipWS(true); SkipWS(true);
@ -1186,7 +1224,7 @@ namespace chaiscript
retval = true; retval = true;
if (Char('(')) { if (Char('(')) {
Arg_List(); Decl_Arg_List();
if (!Char(')')) { if (!Char(')')) {
throw exception::eval_error("Incomplete anonymous function", File_Position(m_line, m_col), *m_filename); throw exception::eval_error("Incomplete anonymous function", File_Position(m_line, m_col), *m_filename);
} }
@ -1236,7 +1274,7 @@ namespace chaiscript
} }
if (Char('(')) { if (Char('(')) {
Arg_List(); Decl_Arg_List();
if (!Char(')')) { if (!Char(')')) {
throw exception::eval_error("Incomplete function definition", File_Position(m_line, m_col), *m_filename); throw exception::eval_error("Incomplete function definition", File_Position(m_line, m_col), *m_filename);
} }
@ -1291,7 +1329,7 @@ namespace chaiscript
if (Keyword("catch", false)) { if (Keyword("catch", false)) {
const auto catch_stack_top = m_match_stack.size(); const auto catch_stack_top = m_match_stack.size();
if (Char('(')) { if (Char('(')) {
if (!(Id(true) && Char(')'))) { if (!(Arg() && Char(')'))) {
throw exception::eval_error("Incomplete 'catch' expression", File_Position(m_line, m_col), *m_filename); throw exception::eval_error("Incomplete 'catch' expression", File_Position(m_line, m_col), *m_filename);
} }
if (Char(':')) { if (Char(':')) {
@ -1918,6 +1956,7 @@ namespace chaiscript
case(AST_Node_Type::Bitwise_Xor) : case(AST_Node_Type::Bitwise_Xor) :
case(AST_Node_Type::Bitwise_Or) : case(AST_Node_Type::Bitwise_Or) :
case(AST_Node_Type::Comparison) : 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(m_match_stack.begin() + m_match_stack.size() - 2, m_match_stack.begin() + m_match_stack.size() - 1);
build_match(std::make_shared<eval::Binary_Operator_AST_Node>(oper->text), prev_stack_top); build_match(std::make_shared<eval::Binary_Operator_AST_Node>(oper->text), prev_stack_top);
break; break;

View File

@ -455,37 +455,37 @@ def zip(x, y) {
# Returns the position of the second value string in the first value string # Returns the position of the second value string in the first value string
def string::find(substr) : is_type(substr, "string") { def string::find(string substr) {
find(this, substr, size_t(0)); find(this, substr, size_t(0));
} }
# Returns the position of last match of the second value string in the first value string # Returns the position of last match of the second value string in the first value string
def string::rfind(substr) : is_type(substr, "string") { def string::rfind(string substr) {
rfind(this, substr, size_t(-1)); rfind(this, substr, size_t(-1));
} }
# Returns the position of the first match of elements in the second value string in the first value string # Returns the position of the first match of elements in the second value string in the first value string
def string::find_first_of(list) : is_type(list, "string") { def string::find_first_of(string list) {
find_first_of(this, list, size_t(0)); find_first_of(this, list, size_t(0));
} }
# Returns the position of the last match of elements in the second value string in the first value string # Returns the position of the last match of elements in the second value string in the first value string
def string::find_last_of(list) : is_type(list, "string") { def string::find_last_of(string list) {
find_last_of(this, list, size_t(-1)); find_last_of(this, list, size_t(-1));
} }
# Returns the position of the first non-matching element in the second value string in the first value string # Returns the position of the first non-matching element in the second value string in the first value string
def string::find_first_not_of(list) : is_type(list, "string") { def string::find_first_not_of(string list) {
find_first_not_of(this, list, size_t(0)); find_first_not_of(this, list, size_t(0));
} }
# Returns the position of the last non-matching element in the second value string in the first value string # Returns the position of the last non-matching element in the second value string in the first value string
def string::find_last_not_of(list) : is_type(list, "string") { def string::find_last_not_of(string list) {
find_last_not_of(this, list, size_t(-1)); find_last_not_of(this, list, size_t(-1));
} }
@ -505,7 +505,7 @@ def string::trim() {
} }
def find(container, value, compare_func) : call_exists(range, container) && is_type(compare_func, "Function") { def find(container, value, Function compare_func) : call_exists(range, container) {
auto range := range(container); auto range := range(container);
while (!range.empty()) { while (!range.empty()) {
if (compare_func(range.front(), value)) { if (compare_func(range.front(), value)) {

View File

@ -1,7 +1,7 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com) // Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
#ifndef CHAISCRIPT_UTILITY_UTILITY_HPP_ #ifndef CHAISCRIPT_UTILITY_UTILITY_HPP_

View File

@ -1,4 +1,4 @@
Copyright 2009-2014 Jason Turner Copyright 2009-2015 Jason Turner
Copyright 2009-2012 Jonathan Turner. Copyright 2009-2012 Jonathan Turner.
All Rights Reserved. All Rights Reserved.

View File

@ -8,7 +8,7 @@ ChaiScript
http://www.chaiscript.com http://www.chaiscript.com
(c) 2009-2012 Jonathan Turner (c) 2009-2012 Jonathan Turner
(c) 2009-2014 Jason Turner (c) 2009-2015 Jason Turner
Release under the BSD license, see "license.txt" for details. Release under the BSD license, see "license.txt" for details.
@ -35,9 +35,10 @@ Requirements
============ ============
ChaiScript requires a C++11 compiler to build with support for variadic ChaiScript requires a C++11 compiler to build with support for variadic
templates. It has been tested with gcc 4.7 and clang 3.1 (with libcxx). MacOS templates. It has been tested with gcc 4.6 and clang 3.1 (with libcxx). MacOS
10.8 (Mountain Lion) is also known to support the C++11 build with Apple's 10.8 (Mountain Lion) is also known to support the C++11 build with Apple's
clang 4.0. clang 4.0. MSVC 2013 or newer is supports also. For more information see the build
[dashboard](http://chaiscript.com/ChaiScript-BuildResults/index.html).
Usage Usage
===== =====

View File

@ -1,6 +1,31 @@
Notes: Notes:
======= =======
Current Version: 5.5.1 Current Version: 5.6.0
### Changes since 5.5.1
* Throw exception on integer divide by 0
* Add optional type specification to function declarations
```
def func(int i, j, double k) {
// i must be an int.
// j can be anything
// k must be a double
// normal conversion rules still apply
}
```
* Many minor fixes for compiler warnings
* Add support for `std::future` and `std::async`
```
var f := async(someFunction);
var f2 := async(someFunction2);
// someFunction and someFunction2 are running in parallel now
f.get();
f2.get();
```
* Fully support r-value returns, supporting move-only objects and reducing object copies
### Changes since 5.5.0 ### Changes since 5.5.0
* 30% performance increase * 30% performance increase

View File

@ -1,14 +1,17 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com) // Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
#include <iostream> #include <iostream>
#include <list> #include <list>
#include <regex> #include <regex>
#ifdef _MSC_VER
#define _CRT_SECURE_NO_WARNINGS #define _CRT_SECURE_NO_WARNINGS
#endif
#include <chaiscript/chaiscript.hpp> #include <chaiscript/chaiscript.hpp>
#include <chaiscript/chaiscript_stdlib.hpp> #include <chaiscript/chaiscript_stdlib.hpp>
@ -154,10 +157,6 @@ void help(int n) {
} }
} }
void version(int){
std::cout << "chai: compiled " << __TIME__ << " " << __DATE__ << std::endl;
}
std::string helloWorld(const std::string &t_name) std::string helloWorld(const std::string &t_name)
{ {
return "Hello " + t_name + "!"; return "Hello " + t_name + "!";
@ -297,7 +296,6 @@ int main(int argc, char *argv[])
chai.add(chaiscript::fun(&myexit), "exit"); chai.add(chaiscript::fun(&myexit), "exit");
chai.add(chaiscript::fun(&myexit), "quit"); chai.add(chaiscript::fun(&myexit), "quit");
chai.add(chaiscript::fun(&help), "help"); chai.add(chaiscript::fun(&help), "help");
chai.add(chaiscript::fun(&version), "version");
chai.add(chaiscript::fun(&throws_exception), "throws_exception"); chai.add(chaiscript::fun(&throws_exception), "throws_exception");
chai.add(chaiscript::fun(&get_eval_error), "get_eval_error"); chai.add(chaiscript::fun(&get_eval_error), "get_eval_error");
@ -356,7 +354,7 @@ int main(int argc, char *argv[])
} }
} }
else if (arg == "-v" || arg == "--version") { else if (arg == "-v" || arg == "--version") {
arg = "version(0)"; arg = "version()";
} }
else if (arg == "-h" || arg == "--help") { else if (arg == "-h" || arg == "--help") {
arg = "help(-1)"; arg = "help(-1)";
@ -388,7 +386,7 @@ int main(int argc, char *argv[])
printf("**ChaiScript::time= %.10f\n", elapsed_secs1); printf("**ChaiScript::time= %.10f\n", elapsed_secs1);
break; break;
} }
default: std::cout << "Unrecognized execution mode" << std::endl; return EXIT_FAILURE;
} }
} }
catch (const chaiscript::exception::eval_error &ee) { catch (const chaiscript::exception::eval_error &ee) {

View File

@ -8,6 +8,8 @@ class BaseClass
{ {
} }
BaseClass(const BaseClass &) = default;
virtual ~BaseClass() {} virtual ~BaseClass() {}
virtual std::string doSomething(float, double) const = 0; virtual std::string doSomething(float, double) const = 0;

View File

@ -1,14 +1,17 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com) // Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
#include <iostream> #include <iostream>
#include <list> #include <list>
#include <regex> #include <regex>
#ifdef _MSC_VER
#define _CRT_SECURE_NO_WARNINGS #define _CRT_SECURE_NO_WARNINGS
#endif
#include <chaiscript/chaiscript.hpp> #include <chaiscript/chaiscript.hpp>
#ifdef READLINE_AVAILABLE #ifdef READLINE_AVAILABLE
@ -18,7 +21,7 @@
char *mystrdup (const char *s) { char *mystrdup (const char *s) {
size_t len = strlen(s); // Space for length plus nul size_t len = strlen(s); // Space for length plus nul
char *d = static_cast<char*>(malloc (len+1)); char *d = static_cast<char*>(malloc (len+1));
if (d == nullptr) return nullptr; // No memory if (d == nullptr) return nullptr; // No memory
#ifdef CHAISCRIPT_MSVC #ifdef CHAISCRIPT_MSVC
strcpy_s(d, len, s); // Copy the characters strcpy_s(d, len, s); // Copy the characters
@ -152,10 +155,6 @@ void help(int n) {
} }
} }
void version(int){
std::cout << "chai: compiled " << __TIME__ << " " << __DATE__ << '\n';
}
bool throws_exception(const std::function<void ()> &f) bool throws_exception(const std::function<void ()> &f)
{ {
try { try {
@ -287,7 +286,6 @@ int main(int argc, char *argv[])
chai.add(chaiscript::fun(&myexit), "exit"); chai.add(chaiscript::fun(&myexit), "exit");
chai.add(chaiscript::fun(&myexit), "quit"); chai.add(chaiscript::fun(&myexit), "quit");
chai.add(chaiscript::fun(&help), "help"); chai.add(chaiscript::fun(&help), "help");
chai.add(chaiscript::fun(&version), "version");
chai.add(chaiscript::fun(&throws_exception), "throws_exception"); chai.add(chaiscript::fun(&throws_exception), "throws_exception");
chai.add(chaiscript::fun(&get_eval_error), "get_eval_error"); chai.add(chaiscript::fun(&get_eval_error), "get_eval_error");
@ -317,7 +315,7 @@ int main(int argc, char *argv[])
arg += line + '\n' ; arg += line + '\n' ;
} }
} else if ( arg == "-v" || arg == "--version" ) { } else if ( arg == "-v" || arg == "--version" ) {
arg = "version(0)" ; arg = "version()" ;
} else if ( arg == "-h" || arg == "--help" ) { } else if ( arg == "-h" || arg == "--help" ) {
arg = "help(-1)"; arg = "help(-1)";
} else if ( arg == "-i" || arg == "--interactive" ) { } else if ( arg == "-i" || arg == "--interactive" ) {
@ -332,10 +330,14 @@ int main(int argc, char *argv[])
chaiscript::Boxed_Value val ; chaiscript::Boxed_Value val ;
try { try {
switch ( mode ) { switch ( mode ) {
case eInteractive : interactive(chai); break; case eInteractive:
case eCommand : val = chai.eval(arg); break; interactive(chai);
case eFile : val = chai.eval_file(arg); break; break;
default : std::cout << "Unrecognized execution mode\n"; return EXIT_FAILURE; case eCommand:
val = chai.eval(arg);
break;
case eFile:
val = chai.eval_file(arg);
} }
} }
catch (const chaiscript::exception::eval_error &ee) { catch (const chaiscript::exception::eval_error &ee) {

View File

@ -1,7 +1,7 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com) // Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
#include <chaiscript/chaiscript.hpp> #include <chaiscript/chaiscript.hpp>

View File

@ -9,7 +9,8 @@ class TestBaseType
public: public:
TestBaseType() : val(10), const_val(15) { } TestBaseType() : val(10), const_val(15) { }
TestBaseType(int) : val(10), const_val(15) {} TestBaseType(int) : val(10), const_val(15) {}
TestBaseType(int *) : val(10), const_val(15) {} TestBaseType(int *) : val(10), const_val(15) { }
TestBaseType(const TestBaseType &) = default;
virtual ~TestBaseType() {} virtual ~TestBaseType() {}
virtual int func() { return 0; } virtual int func() { return 0; }
@ -62,6 +63,8 @@ class TestDerivedType : public TestBaseType
{ {
public: public:
virtual ~TestDerivedType() {} virtual ~TestDerivedType() {}
TestDerivedType(const TestDerivedType &) = default;
TestDerivedType() = default;
virtual int func() CHAISCRIPT_OVERRIDE { return 1; } virtual int func() CHAISCRIPT_OVERRIDE { return 1; }
int derived_only_func() { return 19; } int derived_only_func() { return 19; }
@ -72,6 +75,8 @@ class TestDerivedType : public TestBaseType
class TestMoreDerivedType : public TestDerivedType class TestMoreDerivedType : public TestDerivedType
{ {
public: public:
TestMoreDerivedType(const TestMoreDerivedType &) = default;
TestMoreDerivedType() = default;
virtual ~TestMoreDerivedType() {} virtual ~TestMoreDerivedType() {}
}; };
@ -95,9 +100,11 @@ std::string hello_world()
return "Hello World"; return "Hello World";
} }
static int global_i = 1;
int *get_new_int() int *get_new_int()
{ {
return new int(1); return &global_i;
} }
// MSVC doesn't like that we are using C++ return types from our C declared module // MSVC doesn't like that we are using C++ return types from our C declared module

View File

@ -265,20 +265,25 @@ bool pointer_test(const T& default_value, const T& new_value)
if (p != (*result) ) { if (p != (*result) ) {
std::cerr << "Pointer passed in different than one returned\n"; std::cerr << "Pointer passed in different than one returned\n";
delete p;
return false; return false;
} }
if (*p != *(*result) ) { if (*p != *(*result) ) {
std::cerr << "Somehow dereferenced pointer values are not the same?\n"; std::cerr << "Somehow dereferenced pointer values are not the same?\n";
delete p;
return false; return false;
} }
delete p;
return true; return true;
} catch (const exception::bad_boxed_cast &) { } catch (const exception::bad_boxed_cast &) {
std::cerr << "Bad boxed cast performing ** to ** test\n"; std::cerr << "Bad boxed cast performing ** to ** test\n";
delete p;
return false; return false;
} catch (...) { } catch (...) {
std::cerr << "Unknown exception performing ** to ** test\n"; std::cerr << "Unknown exception performing ** to ** test\n";
delete p;
return false; return false;
} }

View File

@ -0,0 +1,9 @@
try {
3/0
assert_true(false); // should never get here
} catch (e) {
assert_equal("Arithmetic error: divide by zero", e.what())
}
assert_equal(3/0.0, Infinity)

View File

@ -0,0 +1,21 @@
auto x = 1
try {
throw(x)
x = 2
}
catch(int e) {
x = e + 3
}
assert_equal(4, x);
x = 1
try {
throw(x)
x = 2
}
catch(string e) {
}
catch(e) {
x = e + 4
}
assert_equal(5, x);

View File

@ -0,0 +1,34 @@
auto results = [];
for (auto i = 2; i < 6; ++i) {
try {
throw(i)
}
catch(int e) : e < 2 {
results.push_back("c1: " + e.to_string());
}
catch(int e) : e < 4 {
results.push_back("c2: " + e.to_string());
}
catch(e) {
results.push_back("c3: " + e.to_string());
}
catch {
// Should never get called
assert_equal(false, true)
}
}
try {
throw(3)
}
catch(int e) : e < 3
{
// Should never get called
assert_equal(false, true);
}
catch {
results.push_back("defaultcatch");
}
assert_equal(["c2: 2", "c2: 3", "c3: 4", "c3: 5", "defaultcatch"], results);

View File

@ -1,6 +1,6 @@
#include <chaiscript/utility/utility.hpp> #include <chaiscript/utility/utility.hpp>
double test_call(const std::function<double (int)> &f, int val) int test_call(const std::function<int (int)> &f, int val)
{ {
return f(val); return f(val);
} }
@ -9,15 +9,15 @@ int main()
{ {
chaiscript::ChaiScript chai; chaiscript::ChaiScript chai;
chai.add(chaiscript::fun(&test_call), "test_call"); chai.add(chaiscript::fun(&test_call), "test_call");
chai.eval("def func(i) { return i * 3.5; };"); chai.eval("def func(i) { return i * 6; };");
double d = chai.eval<double>("test_call(func, 3)"); int d = chai.eval<int>("test_call(func, 3)");
if (d == 3 * 3.5) if (d == 3 * 6)
{ {
return EXIT_SUCCESS; return EXIT_SUCCESS;
} else { } else {
return EXIT_FAILURE; return EXIT_FAILURE;
} }

15
unittests/future.chai Normal file
View File

@ -0,0 +1,15 @@
var func = fun(){
var ret = 0;
for (var i = 0; i < 50000; ++i) {
ret += i;
}
return ret;
}
var fut1 := async(func);
var fut2 := async(func);
// simply executing without crashing is good enough for this test
print(" ${fut1.get()} ${fut2.get()} ")

View File

@ -4,9 +4,9 @@
template<typename T> template<typename T>
struct Vector2 struct Vector2
{ {
Vector2() : x(0), y(0) {}; Vector2() : x(0), y(0) {}
Vector2(T px, T py) : x(px), y(py) {}; Vector2(T px, T py) : x(px), y(py) {}
Vector2(const Vector2& cp) : x(cp.x), y(cp.y) {}; Vector2(const Vector2& cp) : x(cp.x), y(cp.y) {}
Vector2& operator+=(const Vector2& vec_r) Vector2& operator+=(const Vector2& vec_r)
{ {
@ -20,10 +20,11 @@ struct Vector2
return Vector2(*this += vec_r); return Vector2(*this += vec_r);
} }
void operator=(const Vector2& ver_r) Vector2 &operator=(const Vector2& ver_r)
{ {
x = ver_r.x; x = ver_r.x;
y = ver_r.y; y = ver_r.y;
return *this;
} }