mirror of
https://github.com/ChaiScript/ChaiScript.git
synced 2025-12-06 16:57:04 +08:00
Merge pull request #557 from BerndAmend/develop
change .clang-format and reformat code with clang-format 11
This commit is contained in:
commit
3aa1fa8278
117
.clang-format
117
.clang-format
@ -1,98 +1,33 @@
|
||||
# clang-format: 11
|
||||
AccessModifierOffset: -2
|
||||
AlignAfterOpenBracket: DontAlign
|
||||
AlignConsecutiveAssignments: false
|
||||
AlignConsecutiveDeclarations: false
|
||||
AlignEscapedNewlines: Left
|
||||
AlignOperands: true
|
||||
AlignTrailingComments: false
|
||||
AllowAllParametersOfDeclarationOnNextLine: false
|
||||
AllowShortBlocksOnASingleLine: true
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: All
|
||||
AllowShortIfStatementsOnASingleLine: true
|
||||
AllowShortLoopsOnASingleLine: true
|
||||
AlwaysBreakAfterDefinitionReturnType: None
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: true
|
||||
AlwaysBreakTemplateDeclarations: false
|
||||
BinPackArguments: false
|
||||
BinPackParameters: false
|
||||
BraceWrapping:
|
||||
AfterClass: true
|
||||
AfterControlStatement: false
|
||||
AfterEnum: false
|
||||
AfterFunction: true
|
||||
AfterNamespace: false
|
||||
AfterObjCDeclaration: false
|
||||
AfterStruct: true
|
||||
AfterUnion: false
|
||||
BeforeCatch: false
|
||||
BeforeElse: false
|
||||
IndentBraces: false
|
||||
SplitEmptyFunction: false
|
||||
SplitEmptyNamespace: true
|
||||
SplitEmptyRecord: true
|
||||
BreakAfterJavaFieldAnnotations: true
|
||||
BreakBeforeBinaryOperators: NonAssignment
|
||||
BreakBeforeBraces: Custom
|
||||
BreakBeforeInheritanceComma: true
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializers: BeforeColon
|
||||
BreakConstructorInitializersBeforeComma: false
|
||||
BreakStringLiterals: true
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignConsecutiveBitFields: false
|
||||
AllowShortBlocksOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: Inline
|
||||
AllowShortLambdasOnASingleLine: All
|
||||
AlwaysBreakTemplateDeclarations: true
|
||||
BasedOnStyle: WebKit
|
||||
BinPackArguments: true
|
||||
BinPackParameters: true
|
||||
BreakBeforeBraces: Attach
|
||||
ColumnLimit: 0
|
||||
CommentPragmas: '^ IWYU pragma:'
|
||||
CompactNamespaces: false
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
||||
ConstructorInitializerIndentWidth: 2
|
||||
ContinuationIndentWidth: 2
|
||||
Cpp11BracedListStyle: false
|
||||
DerivePointerAlignment: true
|
||||
DisableFormat: false
|
||||
ExperimentalAutoDetectBinPacking: true
|
||||
Cpp11BracedListStyle: true
|
||||
FixNamespaceComments: true
|
||||
ForEachMacros:
|
||||
- foreach
|
||||
- Q_FOREACH
|
||||
- BOOST_FOREACH
|
||||
IncludeCategories:
|
||||
- Priority: 2
|
||||
Regex: ^"(llvm|llvm-c|clang|clang-c)/
|
||||
- Priority: 3
|
||||
Regex: ^(<|"(gtest|gmock|isl|json)/)
|
||||
- Priority: 1
|
||||
Regex: .*
|
||||
IncludeIsMainRegex: (Test)?$
|
||||
IndentCaseLabels: false
|
||||
IncludeBlocks: Preserve
|
||||
IndentCaseLabels: true
|
||||
IndentPPDirectives: None
|
||||
IndentWidth: 2
|
||||
IndentWrappedFunctionNames: true
|
||||
JavaScriptQuotes: Leave
|
||||
JavaScriptWrapImports: true
|
||||
KeepEmptyLinesAtTheStartOfBlocks: true
|
||||
Language: Cpp
|
||||
MacroBlockBegin: ''
|
||||
MacroBlockEnd: ''
|
||||
MaxEmptyLinesToKeep: 2
|
||||
NamespaceIndentation: Inner
|
||||
ObjCBlockIndentWidth: 7
|
||||
ObjCSpaceAfterProperty: true
|
||||
ObjCSpaceBeforeProtocolList: false
|
||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||
NamespaceIndentation: All
|
||||
PenaltyBreakBeforeFirstCallParameter: 200
|
||||
PenaltyBreakComment: 5
|
||||
PenaltyBreakFirstLessLess: 50
|
||||
PenaltyExcessCharacter: 4
|
||||
PointerAlignment: Right
|
||||
ReflowComments: true
|
||||
SortIncludes: false
|
||||
SortUsingDeclarations: false
|
||||
SpaceAfterCStyleCast: false
|
||||
SortIncludes: true
|
||||
SpaceAfterTemplateKeyword: false
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeParens: ControlStatements
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesBeforeTrailingComments: 0
|
||||
SpacesInAngles: false
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInContainerLiterals: true
|
||||
SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
Standard: Cpp11
|
||||
TabWidth: 8
|
||||
SpaceBeforeCpp11BracedList: false
|
||||
SpaceInEmptyBlock: false
|
||||
Standard: Latest
|
||||
TabWidth: 2
|
||||
UseTab: Never
|
||||
|
||||
|
||||
@ -7,12 +7,9 @@
|
||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||
|
||||
|
||||
#ifndef CHAISCRIPT_HPP_
|
||||
#define CHAISCRIPT_HPP_
|
||||
|
||||
|
||||
|
||||
/// @mainpage
|
||||
/// [ChaiScript](http://www.chaiscript.com") is a scripting language designed specifically for integration with C++. It provides
|
||||
/// seamless integration with C++ on all levels, including shared_ptr objects, functors and exceptions.
|
||||
@ -22,7 +19,8 @@
|
||||
///
|
||||
/// The end user parts of the API are extremely simple both in size and ease of use.
|
||||
///
|
||||
/// Currently, all source control and project management aspects of ChaiScript occur on [github](http://www.github.com/ChaiScript/ChaiScript").
|
||||
/// Currently, all source control and project management aspects of ChaiScript occur on
|
||||
/// [github](http://www.github.com/ChaiScript/ChaiScript").
|
||||
///
|
||||
/// ------------------------------------------------------------
|
||||
///
|
||||
@ -315,8 +313,8 @@
|
||||
/// As much as possible, ChaiScript attempts to convert between &, *, const &, const *, std::shared_ptr<T>,
|
||||
/// std::shared_ptr<const T>, std::reference_wrapper<T>, std::reference_wrapper<const T> and value types automatically.
|
||||
///
|
||||
/// If a chaiscript::var object was created in C++ from a pointer, it cannot be converted to a shared_ptr (this would add invalid reference counting).
|
||||
/// Const may be added, but never removed.
|
||||
/// If a chaiscript::var object was created in C++ from a pointer, it cannot be converted to a shared_ptr (this would add invalid reference
|
||||
/// counting). Const may be added, but never removed.
|
||||
///
|
||||
/// The take away is that you can pretty much expect function calls to Just Work when you need them to.
|
||||
///
|
||||
@ -470,7 +468,8 @@
|
||||
/// chaiscript::ChaiScript chai;
|
||||
///
|
||||
/// try {
|
||||
/// chai.eval("throw(runtime_error(@"error@"))", chaiscript::exception_specification<int, double, float, const std::string &, const std::exception &>());
|
||||
/// chai.eval("throw(runtime_error(@"error@"))", chaiscript::exception_specification<int, double, float, const std::string &, const
|
||||
/// std::exception &>());
|
||||
/// } catch (const double e) {
|
||||
/// } catch (int) {
|
||||
/// } catch (float) {
|
||||
@ -483,8 +482,6 @@
|
||||
/// @sa chaiscript::Exception_Handler for details on automatic exception unboxing
|
||||
/// @sa chaiscript::exception_specification
|
||||
|
||||
|
||||
|
||||
/// @page LangObjectSystemRef ChaiScript Language Object Model Reference
|
||||
///
|
||||
///
|
||||
@ -652,7 +649,6 @@
|
||||
/// @sa @ref LangKeywordRef
|
||||
/// @sa ChaiScript_Language for Built in Functions
|
||||
|
||||
|
||||
/// @page LangKeywordRef ChaiScript Language Keyword Reference
|
||||
///
|
||||
///
|
||||
@ -813,7 +809,6 @@
|
||||
///
|
||||
/// Synonym for @ref keywordauto
|
||||
|
||||
|
||||
/// @namespace chaiscript
|
||||
/// @brief Namespace chaiscript contains every API call that the average user will be concerned with.
|
||||
|
||||
@ -821,25 +816,22 @@
|
||||
/// @brief Classes and functions reserved for internal use. Items in this namespace are not supported.
|
||||
|
||||
#include "chaiscript_basic.hpp"
|
||||
#include "language/chaiscript_parser.hpp"
|
||||
#include "chaiscript_stdlib.hpp"
|
||||
#include "language/chaiscript_parser.hpp"
|
||||
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
class ChaiScript : public ChaiScript_Basic
|
||||
{
|
||||
namespace chaiscript {
|
||||
class ChaiScript : public ChaiScript_Basic {
|
||||
public:
|
||||
ChaiScript(std::vector<std::string> t_modulepaths = {},
|
||||
std::vector<std::string> t_usepaths = {},
|
||||
std::vector<Options> t_opts = chaiscript::default_options())
|
||||
: ChaiScript_Basic(
|
||||
chaiscript::Std_Lib::library(),
|
||||
: ChaiScript_Basic(chaiscript::Std_Lib::library(),
|
||||
std::make_unique<parser::ChaiScript_Parser<eval::Noop_Tracer, optimizer::Optimizer_Default>>(),
|
||||
std::move(t_modulepaths), std::move(t_usepaths), std::move(t_opts))
|
||||
{
|
||||
std::move(t_modulepaths),
|
||||
std::move(t_usepaths),
|
||||
std::move(t_opts)) {
|
||||
}
|
||||
};
|
||||
}
|
||||
} // namespace chaiscript
|
||||
|
||||
#endif /* CHAISCRIPT_HPP_ */
|
||||
|
||||
@ -9,13 +9,13 @@
|
||||
|
||||
#include "chaiscript_defines.hpp"
|
||||
|
||||
#include "dispatchkit/dispatchkit.hpp"
|
||||
#include "dispatchkit/function_call.hpp"
|
||||
#include "dispatchkit/dynamic_object.hpp"
|
||||
#include "dispatchkit/boxed_number.hpp"
|
||||
#include "dispatchkit/dispatchkit.hpp"
|
||||
#include "dispatchkit/dynamic_object.hpp"
|
||||
#include "dispatchkit/function_call.hpp"
|
||||
|
||||
#include "language/chaiscript_eval.hpp"
|
||||
#include "language/chaiscript_engine.hpp"
|
||||
#include "language/chaiscript_eval.hpp"
|
||||
|
||||
// This file includes all of the basic requirements for ChaiScript,
|
||||
// to use, you might do something like:
|
||||
@ -34,6 +34,4 @@ ChaiScript_Basic chai(
|
||||
|
||||
// If you want a fully packaged ready to go ChaiScript, use chaiscript.hpp
|
||||
|
||||
|
||||
|
||||
#endif /* CHAISCRIPT_BASIC_HPP_ */
|
||||
|
||||
@ -20,10 +20,10 @@ static_assert(_MSC_FULL_VER >= 190024210, "Visual C++ 2015 Update 3 or later req
|
||||
#define CHAISCRIPT_COMPILER_VERSION __VERSION__
|
||||
#endif
|
||||
|
||||
#include <vector>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
#if defined( _LIBCPP_VERSION )
|
||||
#if defined(_LIBCPP_VERSION)
|
||||
#define CHAISCRIPT_LIBCPP
|
||||
#endif
|
||||
|
||||
@ -49,12 +49,10 @@ static_assert(_MSC_FULL_VER >= 190024210, "Visual C++ 2015 Update 3 or later req
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(__llvm__)
|
||||
#define CHAISCRIPT_CLANG
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef CHAISCRIPT_HAS_DECLSPEC
|
||||
#define CHAISCRIPT_MODULE_EXPORT extern "C" __declspec(dllexport)
|
||||
#else
|
||||
@ -71,9 +69,9 @@ static_assert(_MSC_FULL_VER >= 190024210, "Visual C++ 2015 Update 3 or later req
|
||||
#define CHAISCRIPT_DEBUG false
|
||||
#endif
|
||||
|
||||
#include <cmath>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <cmath>
|
||||
|
||||
namespace chaiscript {
|
||||
constexpr static const int version_major = 7;
|
||||
@ -84,77 +82,48 @@ namespace chaiscript {
|
||||
constexpr static const char *compiler_name = CHAISCRIPT_COMPILER_NAME;
|
||||
constexpr static const bool debug_build = CHAISCRIPT_DEBUG;
|
||||
|
||||
template<typename B, typename D, typename ...Arg>
|
||||
inline std::shared_ptr<B> make_shared(Arg && ... arg)
|
||||
{
|
||||
template<typename B, typename D, typename... Arg>
|
||||
inline std::shared_ptr<B> make_shared(Arg &&...arg) {
|
||||
#ifdef CHAISCRIPT_USE_STD_MAKE_SHARED
|
||||
return std::make_shared<D>(std::forward<Arg>(arg)...);
|
||||
#else
|
||||
return std::shared_ptr<B>(static_cast<B*>(new D(std::forward<Arg>(arg)...)));
|
||||
return std::shared_ptr<B>(static_cast<B *>(new D(std::forward<Arg>(arg)...)));
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename B, typename D, typename ...Arg>
|
||||
inline std::unique_ptr<B> make_unique(Arg && ... arg)
|
||||
{
|
||||
template<typename B, typename D, typename... Arg>
|
||||
inline std::unique_ptr<B> make_unique(Arg &&...arg) {
|
||||
#ifdef CHAISCRIPT_USE_STD_MAKE_SHARED
|
||||
return std::make_unique<D>(std::forward<Arg>(arg)...);
|
||||
#else
|
||||
return std::unique_ptr<B>(static_cast<B*>(new D(std::forward<Arg>(arg)...)));
|
||||
return std::unique_ptr<B>(static_cast<B *>(new D(std::forward<Arg>(arg)...)));
|
||||
#endif
|
||||
}
|
||||
|
||||
struct Build_Info {
|
||||
[[nodiscard]] constexpr static int version_major() noexcept
|
||||
{
|
||||
return chaiscript::version_major;
|
||||
}
|
||||
[[nodiscard]] constexpr static int version_major() noexcept { return chaiscript::version_major; }
|
||||
|
||||
[[nodiscard]] constexpr static int version_minor() noexcept
|
||||
{
|
||||
return chaiscript::version_minor;
|
||||
}
|
||||
[[nodiscard]] constexpr static int version_minor() noexcept { return chaiscript::version_minor; }
|
||||
|
||||
[[nodiscard]] constexpr static int version_patch() noexcept
|
||||
{
|
||||
return chaiscript::version_patch;
|
||||
}
|
||||
[[nodiscard]] constexpr static int version_patch() noexcept { return chaiscript::version_patch; }
|
||||
|
||||
[[nodiscard]] static std::string version()
|
||||
{
|
||||
[[nodiscard]] static std::string version() {
|
||||
return std::to_string(version_major()) + '.' + std::to_string(version_minor()) + '.' + std::to_string(version_patch());
|
||||
}
|
||||
|
||||
[[nodiscard]] static std::string compiler_id()
|
||||
{
|
||||
return compiler_name() + '-' + compiler_version();
|
||||
}
|
||||
[[nodiscard]] static std::string compiler_id() { return compiler_name() + '-' + compiler_version(); }
|
||||
|
||||
[[nodiscard]] static std::string build_id()
|
||||
{
|
||||
return compiler_id() + (debug_build()?"-Debug":"-Release");
|
||||
}
|
||||
[[nodiscard]] static std::string build_id() { return compiler_id() + (debug_build() ? "-Debug" : "-Release"); }
|
||||
|
||||
[[nodiscard]] static std::string compiler_version()
|
||||
{
|
||||
return chaiscript::compiler_version;
|
||||
}
|
||||
[[nodiscard]] static std::string compiler_version() { return chaiscript::compiler_version; }
|
||||
|
||||
[[nodiscard]] static std::string compiler_name()
|
||||
{
|
||||
return chaiscript::compiler_name;
|
||||
}
|
||||
[[nodiscard]] static std::string compiler_name() { return chaiscript::compiler_name; }
|
||||
|
||||
[[nodiscard]] constexpr static bool debug_build() noexcept
|
||||
{
|
||||
return chaiscript::debug_build;
|
||||
}
|
||||
[[nodiscard]] constexpr static bool debug_build() noexcept { return chaiscript::debug_build; }
|
||||
};
|
||||
|
||||
|
||||
template<typename T>
|
||||
[[nodiscard]] constexpr auto parse_num(const std::string_view t_str) noexcept -> typename std::enable_if<std::is_integral<T>::value, T>::type
|
||||
{
|
||||
[[nodiscard]] constexpr auto parse_num(const std::string_view t_str) noexcept -> typename std::enable_if<std::is_integral<T>::value, T>::type {
|
||||
T t = 0;
|
||||
for (const auto c : t_str) {
|
||||
if (c < '0' || c > '9') {
|
||||
@ -166,18 +135,15 @@ namespace chaiscript {
|
||||
return t;
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
[[nodiscard]] auto parse_num(const std::string_view t_str) -> typename std::enable_if<!std::is_integral<T>::value, T>::type
|
||||
{
|
||||
[[nodiscard]] auto parse_num(const std::string_view t_str) -> typename std::enable_if<!std::is_integral<T>::value, T>::type {
|
||||
T t = 0;
|
||||
T base{};
|
||||
T decimal_place = 0;
|
||||
int exponent = 0;
|
||||
|
||||
for (const auto c : t_str) {
|
||||
switch (c)
|
||||
{
|
||||
switch (c) {
|
||||
case '.':
|
||||
decimal_place = 10;
|
||||
break;
|
||||
@ -206,8 +172,7 @@ namespace chaiscript {
|
||||
if (decimal_place < 10) {
|
||||
t *= 10;
|
||||
t += static_cast<T>(c - '0');
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
t += static_cast<T>(c - '0') / decimal_place;
|
||||
decimal_place *= 10;
|
||||
}
|
||||
@ -220,30 +185,26 @@ namespace chaiscript {
|
||||
}
|
||||
|
||||
struct str_equal {
|
||||
[[nodiscard]] bool operator()(const std::string &t_lhs, const std::string &t_rhs) const noexcept {
|
||||
return t_lhs == t_rhs;
|
||||
}
|
||||
[[nodiscard]] bool operator()(const std::string &t_lhs, const std::string &t_rhs) const noexcept { return t_lhs == t_rhs; }
|
||||
template<typename LHS, typename RHS>
|
||||
[[nodiscard]] constexpr bool operator()(const LHS &t_lhs, const RHS &t_rhs) const noexcept {
|
||||
return std::equal(t_lhs.begin(), t_lhs.end(), t_rhs.begin(), t_rhs.end());
|
||||
}
|
||||
struct is_transparent{};
|
||||
struct is_transparent {
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
struct str_less {
|
||||
[[nodiscard]] bool operator()(const std::string &t_lhs, const std::string &t_rhs) const noexcept {
|
||||
return t_lhs < t_rhs;
|
||||
}
|
||||
[[nodiscard]] bool operator()(const std::string &t_lhs, const std::string &t_rhs) const noexcept { return t_lhs < t_rhs; }
|
||||
template<typename LHS, typename RHS>
|
||||
[[nodiscard]] constexpr bool operator()(const LHS &t_lhs, const RHS &t_rhs) const noexcept {
|
||||
return std::lexicographical_compare(t_lhs.begin(), t_lhs.end(), t_rhs.begin(), t_rhs.end());
|
||||
}
|
||||
struct is_transparent{};
|
||||
struct is_transparent {
|
||||
};
|
||||
};
|
||||
|
||||
enum class Options
|
||||
{
|
||||
enum class Options {
|
||||
No_Load_Modules,
|
||||
Load_Modules,
|
||||
No_External_Scripts,
|
||||
@ -251,44 +212,33 @@ namespace chaiscript {
|
||||
};
|
||||
|
||||
template<typename From, typename To>
|
||||
struct is_nothrow_forward_constructible
|
||||
: std::bool_constant<noexcept(To{std::declval<From>()})>
|
||||
{
|
||||
struct is_nothrow_forward_constructible : std::bool_constant<noexcept(To{std::declval<From>()})> {
|
||||
};
|
||||
|
||||
template< class From, class To >
|
||||
static inline constexpr bool is_nothrow_forward_constructible_v
|
||||
= is_nothrow_forward_constructible<From, To>::value;
|
||||
template<class From, class To>
|
||||
static inline constexpr bool is_nothrow_forward_constructible_v = is_nothrow_forward_constructible<From, To>::value;
|
||||
|
||||
template<typename Container, typename ... T>
|
||||
[[nodiscard]] constexpr auto make_container(T && ... t)
|
||||
{
|
||||
template<typename Container, typename... T>
|
||||
[[nodiscard]] constexpr auto make_container(T &&...t) {
|
||||
Container c;
|
||||
c.reserve(sizeof...(t));
|
||||
(c.push_back(std::forward<T>(t)), ...);
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
template<typename ... T>
|
||||
[[nodiscard]] auto make_vector(T &&... t) -> std::vector<std::common_type_t<std::decay_t<T>...>>
|
||||
{
|
||||
using container_type =
|
||||
std::vector<std::common_type_t<std::decay_t<T>...>>;
|
||||
template<typename... T>
|
||||
[[nodiscard]] auto make_vector(T &&...t) -> std::vector<std::common_type_t<std::decay_t<T>...>> {
|
||||
using container_type = std::vector<std::common_type_t<std::decay_t<T>...>>;
|
||||
|
||||
return make_container<container_type>(std::forward<T>(t)...);
|
||||
}
|
||||
|
||||
|
||||
|
||||
[[nodiscard]] inline std::vector<Options> default_options()
|
||||
{
|
||||
[[nodiscard]] inline std::vector<Options> default_options() {
|
||||
#ifdef CHAISCRIPT_NO_DYNLOAD
|
||||
return {Options::No_Load_Modules, Options::External_Scripts};
|
||||
#else
|
||||
return {Options::Load_Modules, Options::External_Scripts};
|
||||
#endif
|
||||
}
|
||||
}
|
||||
} // namespace chaiscript
|
||||
#endif
|
||||
|
||||
|
||||
@ -19,53 +19,48 @@
|
||||
#include "dispatchkit/function_call.hpp"
|
||||
|
||||
//#include "dispatchkit/dispatchkit.hpp"
|
||||
#include "dispatchkit/operators.hpp"
|
||||
#include "dispatchkit/bootstrap.hpp"
|
||||
#include "dispatchkit/bootstrap_stl.hpp"
|
||||
#include "dispatchkit/operators.hpp"
|
||||
//#include "dispatchkit/boxed_value.hpp"
|
||||
#include "language/chaiscript_prelude.hpp"
|
||||
#include "dispatchkit/register_function.hpp"
|
||||
#include "language/chaiscript_prelude.hpp"
|
||||
#include "utility/json_wrap.hpp"
|
||||
|
||||
#ifndef CHAISCRIPT_NO_THREADS
|
||||
#include <future>
|
||||
#endif
|
||||
|
||||
|
||||
/// @file
|
||||
///
|
||||
/// This file generates the standard library that normal ChaiScript usage requires.
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
class Std_Lib
|
||||
{
|
||||
namespace chaiscript {
|
||||
class Std_Lib {
|
||||
public:
|
||||
|
||||
[[nodiscard]] static ModulePtr library()
|
||||
{
|
||||
[[nodiscard]] static ModulePtr library() {
|
||||
auto lib = std::make_shared<Module>();
|
||||
bootstrap::Bootstrap::bootstrap(*lib);
|
||||
|
||||
bootstrap::standard_library::vector_type<std::vector<Boxed_Value> >("Vector", *lib);
|
||||
bootstrap::standard_library::vector_type<std::vector<Boxed_Value>>("Vector", *lib);
|
||||
bootstrap::standard_library::string_type<std::string>("string", *lib);
|
||||
bootstrap::standard_library::map_type<std::map<std::string, Boxed_Value> >("Map", *lib);
|
||||
bootstrap::standard_library::pair_type<std::pair<Boxed_Value, Boxed_Value > >("Pair", *lib);
|
||||
bootstrap::standard_library::map_type<std::map<std::string, Boxed_Value>>("Map", *lib);
|
||||
bootstrap::standard_library::pair_type<std::pair<Boxed_Value, Boxed_Value>>("Pair", *lib);
|
||||
|
||||
#ifndef CHAISCRIPT_NO_THREADS
|
||||
bootstrap::standard_library::future_type<std::future<chaiscript::Boxed_Value>>("future", *lib);
|
||||
lib->add(chaiscript::fun([](const std::function<chaiscript::Boxed_Value ()> &t_func){ return std::async(std::launch::async, t_func);}), "async");
|
||||
lib->add(chaiscript::fun(
|
||||
[](const std::function<chaiscript::Boxed_Value()> &t_func) { return std::async(std::launch::async, t_func); }),
|
||||
"async");
|
||||
#endif
|
||||
|
||||
json_wrap::library(*lib);
|
||||
|
||||
lib->eval(ChaiScript_Prelude::chaiscript_prelude() /*, "standard prelude"*/ );
|
||||
lib->eval(ChaiScript_Prelude::chaiscript_prelude() /*, "standard prelude"*/);
|
||||
|
||||
return lib;
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
} // namespace chaiscript
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@ -7,20 +7,18 @@
|
||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||
|
||||
|
||||
#ifndef CHAISCRIPT_THREADING_HPP_
|
||||
#define CHAISCRIPT_THREADING_HPP_
|
||||
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
#ifndef CHAISCRIPT_NO_THREADS
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
#include <shared_mutex>
|
||||
#include <thread>
|
||||
#else
|
||||
#ifndef CHAISCRIPT_NO_THREADS_WARNING
|
||||
#pragma message ("ChaiScript is compiling without thread safety.")
|
||||
#pragma message("ChaiScript is compiling without thread safety.")
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@ -34,16 +32,10 @@
|
||||
/// It also has the side effect that the chaiscript::ChaiScript object may not be accessed from more than
|
||||
/// one thread simultaneously.
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
/// If threading is enabled, then this namespace contains std thread classes.
|
||||
/// If threading is not enabled, then stubbed in wrappers that do nothing are provided.
|
||||
/// This allows us to avoid \#ifdef code in the sections that need thread safety.
|
||||
namespace threading
|
||||
{
|
||||
|
||||
/// If threading is enabled, then this namespace contains std thread classes.
|
||||
/// If threading is not enabled, then stubbed in wrappers that do nothing are provided.
|
||||
/// This allows us to avoid \#ifdef code in the sections that need thread safety.
|
||||
namespace chaiscript::detail::threading {
|
||||
#ifndef CHAISCRIPT_NO_THREADS
|
||||
|
||||
template<typename T>
|
||||
@ -55,7 +47,6 @@ namespace chaiscript
|
||||
template<typename T>
|
||||
using lock_guard = std::lock_guard<T>;
|
||||
|
||||
|
||||
using std::shared_mutex;
|
||||
|
||||
using std::mutex;
|
||||
@ -65,8 +56,7 @@ namespace chaiscript
|
||||
/// Typesafe thread specific storage. If threading is enabled, this class uses a mutex protected map. If
|
||||
/// threading is not enabled, the class always returns the same data, regardless of which thread it is called from.
|
||||
template<typename T>
|
||||
class Thread_Storage
|
||||
{
|
||||
class Thread_Storage {
|
||||
public:
|
||||
Thread_Storage() = default;
|
||||
Thread_Storage(const Thread_Storage &) = delete;
|
||||
@ -74,39 +64,22 @@ namespace chaiscript
|
||||
Thread_Storage &operator=(const Thread_Storage &) = delete;
|
||||
Thread_Storage &operator=(Thread_Storage &&) = delete;
|
||||
|
||||
~Thread_Storage()
|
||||
{
|
||||
t().erase(this);
|
||||
}
|
||||
~Thread_Storage() { t().erase(this); }
|
||||
|
||||
inline const T *operator->() const noexcept
|
||||
{
|
||||
return &(t()[this]);
|
||||
}
|
||||
inline const T *operator->() const noexcept { return &(t()[this]); }
|
||||
|
||||
inline const T &operator*() const noexcept
|
||||
{
|
||||
return t()[this];
|
||||
}
|
||||
inline const T &operator*() const noexcept { return t()[this]; }
|
||||
|
||||
inline T *operator->() noexcept
|
||||
{
|
||||
return &(t()[this]);
|
||||
}
|
||||
|
||||
inline T &operator*() noexcept
|
||||
{
|
||||
return t()[this];
|
||||
}
|
||||
inline T *operator->() noexcept { return &(t()[this]); }
|
||||
|
||||
inline T &operator*() noexcept { return t()[this]; }
|
||||
|
||||
void *m_key;
|
||||
|
||||
private:
|
||||
/// todo: is it valid to make this noexcept? The allocation could fail, but if it
|
||||
/// does there is no possible way to recover
|
||||
static std::unordered_map<const void*, T> &t() noexcept
|
||||
{
|
||||
static std::unordered_map<const void *, T> &t() noexcept {
|
||||
static thread_local std::unordered_map<const void *, T> my_t;
|
||||
return my_t;
|
||||
}
|
||||
@ -114,8 +87,7 @@ namespace chaiscript
|
||||
|
||||
#else // threading disabled
|
||||
template<typename T>
|
||||
class unique_lock
|
||||
{
|
||||
class unique_lock {
|
||||
public:
|
||||
constexpr explicit unique_lock(T &) noexcept {}
|
||||
constexpr void lock() noexcept {}
|
||||
@ -123,8 +95,7 @@ namespace chaiscript
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class shared_lock
|
||||
{
|
||||
class shared_lock {
|
||||
public:
|
||||
constexpr explicit shared_lock(T &) noexcept {}
|
||||
constexpr void lock() noexcept {}
|
||||
@ -132,45 +103,31 @@ namespace chaiscript
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class lock_guard
|
||||
{
|
||||
class lock_guard {
|
||||
public:
|
||||
constexpr explicit lock_guard(T &) noexcept {}
|
||||
};
|
||||
|
||||
class shared_mutex { };
|
||||
|
||||
class recursive_mutex {};
|
||||
class shared_mutex {
|
||||
};
|
||||
|
||||
class recursive_mutex {
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class Thread_Storage
|
||||
{
|
||||
class Thread_Storage {
|
||||
public:
|
||||
constexpr explicit Thread_Storage() noexcept
|
||||
{
|
||||
}
|
||||
constexpr explicit Thread_Storage() noexcept {}
|
||||
|
||||
constexpr inline T *operator->() const noexcept
|
||||
{
|
||||
return &obj;
|
||||
}
|
||||
constexpr inline T *operator->() const noexcept { return &obj; }
|
||||
|
||||
constexpr inline T &operator*() const noexcept
|
||||
{
|
||||
return obj;
|
||||
}
|
||||
constexpr inline T &operator*() const noexcept { return obj; }
|
||||
|
||||
private:
|
||||
mutable T obj;
|
||||
};
|
||||
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // namespace chaiscript::detail::threading
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@ -11,32 +11,24 @@
|
||||
|
||||
namespace chaiscript {
|
||||
namespace detail {
|
||||
namespace exception
|
||||
{
|
||||
namespace exception {
|
||||
/// \brief Thrown in the event that an Any cannot be cast to the desired type
|
||||
///
|
||||
/// It is used internally during function dispatch.
|
||||
///
|
||||
/// \sa chaiscript::detail::Any
|
||||
class bad_any_cast : public std::bad_cast
|
||||
{
|
||||
class bad_any_cast : public std::bad_cast {
|
||||
public:
|
||||
/// \brief Description of what error occurred
|
||||
const char * what() const noexcept override
|
||||
{
|
||||
return "bad any cast";
|
||||
}
|
||||
const char *what() const noexcept override { return "bad any cast"; }
|
||||
};
|
||||
}
|
||||
|
||||
} // namespace exception
|
||||
|
||||
class Any {
|
||||
private:
|
||||
struct Data
|
||||
{
|
||||
struct Data {
|
||||
constexpr explicit Data(const std::type_info &t_type) noexcept
|
||||
: m_type(t_type)
|
||||
{
|
||||
: m_type(t_type) {
|
||||
}
|
||||
|
||||
Data &operator=(const Data &) = delete;
|
||||
@ -45,35 +37,24 @@ namespace chaiscript {
|
||||
|
||||
virtual void *data() noexcept = 0;
|
||||
|
||||
const std::type_info &type() const noexcept
|
||||
{
|
||||
return m_type;
|
||||
}
|
||||
const std::type_info &type() const noexcept { return m_type; }
|
||||
|
||||
virtual std::unique_ptr<Data> clone() const = 0;
|
||||
const std::type_info &m_type;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct Data_Impl : Data
|
||||
{
|
||||
struct Data_Impl : Data {
|
||||
explicit Data_Impl(T t_type)
|
||||
: Data(typeid(T)),
|
||||
m_data(std::move(t_type))
|
||||
{
|
||||
: Data(typeid(T))
|
||||
, m_data(std::move(t_type)) {
|
||||
}
|
||||
|
||||
void *data() noexcept override
|
||||
{
|
||||
return &m_data;
|
||||
}
|
||||
void *data() noexcept override { return &m_data; }
|
||||
|
||||
std::unique_ptr<Data> clone() const override
|
||||
{
|
||||
return std::make_unique<Data_Impl<T>>(m_data);
|
||||
}
|
||||
std::unique_ptr<Data> clone() const override { return std::make_unique<Data_Impl<T>>(m_data); }
|
||||
|
||||
Data_Impl &operator=(const Data_Impl&) = delete;
|
||||
Data_Impl &operator=(const Data_Impl &) = delete;
|
||||
|
||||
T m_data;
|
||||
};
|
||||
@ -87,52 +68,39 @@ namespace chaiscript {
|
||||
Any &operator=(Any &&t_any) = default;
|
||||
|
||||
Any(const Any &t_any)
|
||||
: m_data(t_any.empty() ? nullptr : t_any.m_data->clone())
|
||||
{
|
||||
: m_data(t_any.empty() ? nullptr : t_any.m_data->clone()) {
|
||||
}
|
||||
|
||||
template<typename ValueType,
|
||||
typename = std::enable_if_t<!std::is_same_v<Any, std::decay_t<ValueType>>>>
|
||||
template<typename ValueType, typename = std::enable_if_t<!std::is_same_v<Any, std::decay_t<ValueType>>>>
|
||||
explicit Any(ValueType &&t_value)
|
||||
: m_data(std::make_unique<Data_Impl<std::decay_t<ValueType>>>(std::forward<ValueType>(t_value)))
|
||||
{
|
||||
: m_data(std::make_unique<Data_Impl<std::decay_t<ValueType>>>(std::forward<ValueType>(t_value))) {
|
||||
}
|
||||
|
||||
|
||||
Any & operator=(const Any &t_any)
|
||||
{
|
||||
Any &operator=(const Any &t_any) {
|
||||
Any copy(t_any);
|
||||
swap(copy);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename ToType>
|
||||
ToType &cast() const
|
||||
{
|
||||
if (m_data && typeid(ToType) == m_data->type())
|
||||
{
|
||||
ToType &cast() const {
|
||||
if (m_data && typeid(ToType) == m_data->type()) {
|
||||
return *static_cast<ToType *>(m_data->data());
|
||||
} else {
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// modifiers
|
||||
Any & swap(Any &t_other)
|
||||
{
|
||||
Any &swap(Any &t_other) {
|
||||
std::swap(t_other.m_data, m_data);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// queries
|
||||
bool empty() const noexcept
|
||||
{
|
||||
return !static_cast<bool>(m_data);
|
||||
}
|
||||
bool empty() const noexcept { return !static_cast<bool>(m_data); }
|
||||
|
||||
const std::type_info & type() const noexcept
|
||||
{
|
||||
const std::type_info &type() const noexcept {
|
||||
if (m_data) {
|
||||
return m_data->type();
|
||||
} else {
|
||||
@ -141,9 +109,7 @@ namespace chaiscript {
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
} // namespace detail
|
||||
} // namespace chaiscript
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@ -7,7 +7,6 @@
|
||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||
|
||||
|
||||
#ifndef CHAISCRIPT_BAD_BOXED_CAST_HPP_
|
||||
#define CHAISCRIPT_BAD_BOXED_CAST_HPP_
|
||||
|
||||
@ -19,45 +18,39 @@
|
||||
#include "type_info.hpp"
|
||||
|
||||
namespace chaiscript {
|
||||
class Type_Info;
|
||||
class Type_Info;
|
||||
} // namespace chaiscript
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
namespace exception
|
||||
{
|
||||
namespace chaiscript {
|
||||
namespace exception {
|
||||
/// \brief Thrown in the event that a Boxed_Value cannot be cast to the desired type
|
||||
///
|
||||
/// It is used internally during function dispatch and may be used by the end user.
|
||||
///
|
||||
/// \sa chaiscript::boxed_cast
|
||||
class bad_boxed_cast : public std::bad_cast
|
||||
{
|
||||
class bad_boxed_cast : public std::bad_cast {
|
||||
public:
|
||||
bad_boxed_cast(Type_Info t_from, const std::type_info &t_to,
|
||||
utility::Static_String t_what) noexcept
|
||||
: from(t_from), to(&t_to), m_what(std::move(t_what))
|
||||
{
|
||||
bad_boxed_cast(Type_Info t_from, const std::type_info &t_to, utility::Static_String t_what) noexcept
|
||||
: from(t_from)
|
||||
, to(&t_to)
|
||||
, m_what(std::move(t_what)) {
|
||||
}
|
||||
|
||||
bad_boxed_cast(Type_Info t_from, const std::type_info &t_to) noexcept
|
||||
: from(t_from), to(&t_to), m_what("Cannot perform boxed_cast")
|
||||
{
|
||||
: from(t_from)
|
||||
, to(&t_to)
|
||||
, m_what("Cannot perform boxed_cast") {
|
||||
}
|
||||
|
||||
explicit bad_boxed_cast(utility::Static_String t_what) noexcept
|
||||
: m_what(std::move(t_what))
|
||||
{
|
||||
: m_what(std::move(t_what)) {
|
||||
}
|
||||
|
||||
bad_boxed_cast(const bad_boxed_cast &) noexcept = default;
|
||||
~bad_boxed_cast() noexcept override = default;
|
||||
|
||||
/// \brief Description of what error occurred
|
||||
const char * what() const noexcept override
|
||||
{
|
||||
return m_what.c_str();
|
||||
}
|
||||
const char *what() const noexcept override { return m_what.c_str(); }
|
||||
|
||||
Type_Info from; ///< Type_Info contained in the Boxed_Value
|
||||
const std::type_info *to = nullptr; ///< std::type_info of the desired (but failed) result type
|
||||
@ -65,10 +58,7 @@ namespace chaiscript
|
||||
private:
|
||||
utility::Static_String m_what;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // namespace exception
|
||||
} // namespace chaiscript
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@ -7,79 +7,54 @@
|
||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||
|
||||
|
||||
#ifndef CHAISCRIPT_BIND_FIRST_HPP_
|
||||
#define CHAISCRIPT_BIND_FIRST_HPP_
|
||||
|
||||
#include <functional>
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
|
||||
namespace chaiscript {
|
||||
namespace detail {
|
||||
template<typename T>
|
||||
constexpr T* get_pointer(T *t) noexcept
|
||||
{
|
||||
constexpr T *get_pointer(T *t) noexcept {
|
||||
return t;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T* get_pointer(const std::reference_wrapper<T> &t) noexcept
|
||||
{
|
||||
T *get_pointer(const std::reference_wrapper<T> &t) noexcept {
|
||||
return &t.get();
|
||||
}
|
||||
|
||||
template<typename O, typename Ret, typename P1, typename ... Param>
|
||||
constexpr auto bind_first(Ret (*f)(P1, Param...), O&& o)
|
||||
{
|
||||
return [f, o = std::forward<O>(o)](Param...param) -> Ret {
|
||||
return f(o, std::forward<Param>(param)...);
|
||||
};
|
||||
template<typename O, typename Ret, typename P1, typename... Param>
|
||||
constexpr auto bind_first(Ret (*f)(P1, Param...), O &&o) {
|
||||
return [f, o = std::forward<O>(o)](Param... param) -> Ret { return f(o, std::forward<Param>(param)...); };
|
||||
}
|
||||
|
||||
template<typename O, typename Ret, typename Class, typename ... Param>
|
||||
constexpr auto bind_first(Ret (Class::*f)(Param...), O&& o)
|
||||
{
|
||||
return [f, o = std::forward<O>(o)](Param...param) -> Ret {
|
||||
return (get_pointer(o)->*f)(std::forward<Param>(param)...);
|
||||
};
|
||||
template<typename O, typename Ret, typename Class, typename... Param>
|
||||
constexpr auto bind_first(Ret (Class::*f)(Param...), O &&o) {
|
||||
return [f, o = std::forward<O>(o)](Param... param) -> Ret { return (get_pointer(o)->*f)(std::forward<Param>(param)...); };
|
||||
}
|
||||
|
||||
template<typename O, typename Ret, typename Class, typename ... Param>
|
||||
constexpr auto bind_first(Ret (Class::*f)(Param...) const, O&& o)
|
||||
{
|
||||
return [f, o = std::forward<O>(o)](Param...param) -> Ret {
|
||||
return (get_pointer(o)->*f)(std::forward<Param>(param)...);
|
||||
};
|
||||
|
||||
template<typename O, typename Ret, typename Class, typename... Param>
|
||||
constexpr auto bind_first(Ret (Class::*f)(Param...) const, O &&o) {
|
||||
return [f, o = std::forward<O>(o)](Param... param) -> Ret { return (get_pointer(o)->*f)(std::forward<Param>(param)...); };
|
||||
}
|
||||
|
||||
template<typename O, typename Ret, typename P1, typename ... Param>
|
||||
auto bind_first(const std::function<Ret (P1, Param...)> &f, O&& o)
|
||||
{
|
||||
return [f, o = std::forward<O>(o)](Param...param) -> Ret {
|
||||
return f(o, std::forward<Param>(param)...);
|
||||
};
|
||||
template<typename O, typename Ret, typename P1, typename... Param>
|
||||
auto bind_first(const std::function<Ret(P1, Param...)> &f, O &&o) {
|
||||
return [f, o = std::forward<O>(o)](Param... param) -> Ret { return f(o, std::forward<Param>(param)...); };
|
||||
}
|
||||
|
||||
template<typename F, typename O, typename Ret, typename Class, typename P1, typename ... Param>
|
||||
constexpr auto bind_first(const F &fo, O&& o, Ret (Class::*f)(P1, Param...) const)
|
||||
{
|
||||
return [fo, o = std::forward<O>(o), f](Param ...param) -> Ret {
|
||||
return (fo.*f)(o, std::forward<Param>(param)...);
|
||||
};
|
||||
|
||||
template<typename F, typename O, typename Ret, typename Class, typename P1, typename... Param>
|
||||
constexpr auto bind_first(const F &fo, O &&o, Ret (Class::*f)(P1, Param...) const) {
|
||||
return [fo, o = std::forward<O>(o), f](Param... param) -> Ret { return (fo.*f)(o, std::forward<Param>(param)...); };
|
||||
}
|
||||
|
||||
template<typename F, typename O>
|
||||
constexpr auto bind_first(const F &f, O&& o)
|
||||
{
|
||||
constexpr auto bind_first(const F &f, O &&o) {
|
||||
return bind_first(f, std::forward<O>(o), &F::operator());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace chaiscript
|
||||
|
||||
#endif
|
||||
|
||||
@ -7,52 +7,42 @@
|
||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||
|
||||
|
||||
#ifndef CHAISCRIPT_BOOTSTRAP_HPP_
|
||||
#define CHAISCRIPT_BOOTSTRAP_HPP_
|
||||
|
||||
#include "../utility/utility.hpp"
|
||||
#include "register_function.hpp"
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
/// \brief Classes and functions useful for bootstrapping of ChaiScript and adding of new types
|
||||
namespace bootstrap
|
||||
{
|
||||
template<typename T, typename = typename std::enable_if<std::is_array<T>::value>::type >
|
||||
void array(const std::string &type, Module& m)
|
||||
{
|
||||
/// \brief Classes and functions useful for bootstrapping of ChaiScript and adding of new types
|
||||
namespace chaiscript::bootstrap {
|
||||
template<typename T, typename = typename std::enable_if<std::is_array<T>::value>::type>
|
||||
void array(const std::string &type, Module &m) {
|
||||
using ReturnType = typename std::remove_extent<T>::type;
|
||||
|
||||
m.add(user_type<T>(), type);
|
||||
m.add(fun(
|
||||
[](T& t, size_t index)->ReturnType &{
|
||||
m.add(fun([](T &t, size_t index) -> ReturnType & {
|
||||
constexpr const auto extent = std::extent<T>::value;
|
||||
if (extent > 0 && index >= extent) {
|
||||
throw std::range_error("Array index out of range. Received: " + std::to_string(index) + " expected < " + std::to_string(extent));
|
||||
throw std::range_error("Array index out of range. Received: " + std::to_string(index) + " expected < "
|
||||
+ std::to_string(extent));
|
||||
} else {
|
||||
return t[index];
|
||||
}
|
||||
}
|
||||
), "[]"
|
||||
);
|
||||
}),
|
||||
"[]");
|
||||
|
||||
m.add(fun(
|
||||
[](const T &t, size_t index)->const ReturnType &{
|
||||
m.add(fun([](const T &t, size_t index) -> const ReturnType & {
|
||||
constexpr const auto extent = std::extent<T>::value;
|
||||
if (extent > 0 && index >= extent) {
|
||||
throw std::range_error("Array index out of range. Received: " + std::to_string(index) + " expected < " + std::to_string(extent));
|
||||
throw std::range_error("Array index out of range. Received: " + std::to_string(index) + " expected < "
|
||||
+ std::to_string(extent));
|
||||
} else {
|
||||
return t[index];
|
||||
}
|
||||
}
|
||||
), "[]"
|
||||
);
|
||||
}),
|
||||
"[]");
|
||||
|
||||
m.add(fun(
|
||||
[](const T &) {
|
||||
return std::extent<T>::value;
|
||||
}), "size");
|
||||
m.add(fun([](const T &) { return std::extent<T>::value; }), "size");
|
||||
}
|
||||
|
||||
/// \brief Adds a copy constructor for the given type to the given Model
|
||||
@ -61,9 +51,8 @@ namespace chaiscript
|
||||
/// \tparam T The type to add a copy constructor for
|
||||
/// \returns The passed in Module
|
||||
template<typename T>
|
||||
void copy_constructor(const std::string &type, Module& m)
|
||||
{
|
||||
m.add(constructor<T (const T &)>(), type);
|
||||
void copy_constructor(const std::string &type, Module &m) {
|
||||
m.add(constructor<T(const T &)>(), type);
|
||||
}
|
||||
|
||||
/// \brief Add all comparison operators for the templated type. Used during bootstrap, also available to users.
|
||||
@ -71,8 +60,7 @@ namespace chaiscript
|
||||
/// \param[in,out] m module to add comparison operators to
|
||||
/// \returns the passed in Module.
|
||||
template<typename T>
|
||||
void opers_comparison(Module& m)
|
||||
{
|
||||
void opers_comparison(Module &m) {
|
||||
operators::equal<T>(m);
|
||||
operators::greater_than<T>(m);
|
||||
operators::greater_than_equal<T>(m);
|
||||
@ -81,8 +69,6 @@ namespace chaiscript
|
||||
operators::not_equal<T>(m);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// \brief Adds default and copy constructors for the given type
|
||||
/// \param[in] type The name of the type to add the constructors for.
|
||||
/// \param[in,out] m The Module to add the basic constructors to
|
||||
@ -91,9 +77,8 @@ namespace chaiscript
|
||||
/// \sa copy_constructor
|
||||
/// \sa constructor
|
||||
template<typename T>
|
||||
void basic_constructors(const std::string &type, Module& m)
|
||||
{
|
||||
m.add(constructor<T ()>(), type);
|
||||
void basic_constructors(const std::string &type, Module &m) {
|
||||
m.add(constructor<T()>(), type);
|
||||
copy_constructor<T>(type, m);
|
||||
}
|
||||
|
||||
@ -102,20 +87,15 @@ namespace chaiscript
|
||||
/// \param[in] type The name of the type
|
||||
/// \param[in,out] m The Module to add the constructor to
|
||||
template<typename T>
|
||||
void construct_pod(const std::string &type, Module& m)
|
||||
{
|
||||
m.add(fun([](const Boxed_Number &bn){ return bn.get_as<T>(); }), type);
|
||||
void construct_pod(const std::string &type, Module &m) {
|
||||
m.add(fun([](const Boxed_Number &bn) { return bn.get_as<T>(); }), type);
|
||||
}
|
||||
|
||||
|
||||
/// Internal function for converting from a string to a value
|
||||
/// uses ostream operator >> to perform the conversion
|
||||
template<typename Input>
|
||||
Input parse_string(const std::string &i)
|
||||
{
|
||||
if constexpr (!std::is_same<Input, wchar_t>::value
|
||||
&& !std::is_same<Input, char16_t>::value
|
||||
&& !std::is_same<Input, char32_t>::value) {
|
||||
Input parse_string(const std::string &i) {
|
||||
if constexpr (!std::is_same<Input, wchar_t>::value && !std::is_same<Input, char16_t>::value && !std::is_same<Input, char32_t>::value) {
|
||||
std::stringstream ss(i);
|
||||
Input t;
|
||||
ss >> t;
|
||||
@ -128,46 +108,37 @@ namespace chaiscript
|
||||
/// Add all common functions for a POD type. All operators, and
|
||||
/// common conversions
|
||||
template<typename T>
|
||||
void bootstrap_pod_type(const std::string &name, Module& m)
|
||||
{
|
||||
void bootstrap_pod_type(const std::string &name, Module &m) {
|
||||
m.add(user_type<T>(), name);
|
||||
m.add(constructor<T()>(), name);
|
||||
construct_pod<T>(name, m);
|
||||
|
||||
m.add(fun(&parse_string<T>), "to_" + name);
|
||||
m.add(fun([](const T t){ return t; }), "to_" + name);
|
||||
m.add(fun([](const T t) { return t; }), "to_" + name);
|
||||
}
|
||||
|
||||
|
||||
/// "clone" function for a shared_ptr type. This is used in the case
|
||||
/// where you do not want to make a deep copy of an object during cloning
|
||||
/// but want to instead maintain the shared_ptr. It is needed internally
|
||||
/// for handling of Proxy_Function object (that is,
|
||||
/// function variables.
|
||||
template<typename Type>
|
||||
auto shared_ptr_clone(const std::shared_ptr<Type> &p)
|
||||
{
|
||||
auto shared_ptr_clone(const std::shared_ptr<Type> &p) {
|
||||
return p;
|
||||
}
|
||||
|
||||
/// Specific version of shared_ptr_clone just for Proxy_Functions
|
||||
template<typename Type>
|
||||
std::shared_ptr<std::remove_const_t<Type>> shared_ptr_unconst_clone(const std::shared_ptr<std::add_const_t<Type>> &p)
|
||||
{
|
||||
std::shared_ptr<std::remove_const_t<Type>> shared_ptr_unconst_clone(const std::shared_ptr<std::add_const_t<Type>> &p) {
|
||||
return std::const_pointer_cast<typename std::remove_const<Type>::type>(p);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// Assignment function for shared_ptr objects, does not perform a copy of the
|
||||
/// object pointed to, instead maintains the shared_ptr concept.
|
||||
/// Similar to shared_ptr_clone. Used for Proxy_Function.
|
||||
template<typename Type>
|
||||
Boxed_Value ptr_assign(Boxed_Value lhs, const std::shared_ptr<Type> &rhs)
|
||||
{
|
||||
if (lhs.is_undef()
|
||||
|| (!lhs.get_type_info().is_const() && lhs.get_type_info().bare_equal(chaiscript::detail::Get_Type_Info<Type>::get())))
|
||||
{
|
||||
Boxed_Value ptr_assign(Boxed_Value lhs, const std::shared_ptr<Type> &rhs) {
|
||||
if (lhs.is_undef() || (!lhs.get_type_info().is_const() && lhs.get_type_info().bare_equal(chaiscript::detail::Get_Type_Info<Type>::get()))) {
|
||||
lhs.assign(Boxed_Value(rhs));
|
||||
return lhs;
|
||||
} else {
|
||||
@ -177,34 +148,23 @@ namespace chaiscript
|
||||
|
||||
/// Class consisting of only static functions. All default bootstrapping occurs
|
||||
/// from this class.
|
||||
class Bootstrap
|
||||
{
|
||||
class Bootstrap {
|
||||
private:
|
||||
/// Function allowing for assignment of an unknown type to any other value
|
||||
static Boxed_Value unknown_assign(Boxed_Value lhs, Boxed_Value rhs)
|
||||
{
|
||||
if (lhs.is_undef())
|
||||
{
|
||||
static Boxed_Value unknown_assign(Boxed_Value lhs, Boxed_Value rhs) {
|
||||
if (lhs.is_undef()) {
|
||||
return (lhs.assign(rhs));
|
||||
} else {
|
||||
throw exception::bad_boxed_cast("boxed_value has a set type already");
|
||||
}
|
||||
}
|
||||
|
||||
static void print(const std::string &s) noexcept
|
||||
{
|
||||
fwrite(s.c_str(), 1, s.size(), stdout);
|
||||
}
|
||||
|
||||
static void println(const std::string &s) noexcept
|
||||
{
|
||||
puts(s.c_str());
|
||||
}
|
||||
static void print(const std::string &s) noexcept { fwrite(s.c_str(), 1, s.size(), stdout); }
|
||||
|
||||
static void println(const std::string &s) noexcept { puts(s.c_str()); }
|
||||
|
||||
/// Add all arithmetic operators for PODs
|
||||
static void opers_arithmetic_pod(Module& m)
|
||||
{
|
||||
static void opers_arithmetic_pod(Module &m) {
|
||||
m.add(fun(&Boxed_Number::equals), "==");
|
||||
m.add(fun(&Boxed_Number::less_than), "<");
|
||||
m.add(fun(&Boxed_Number::greater_than), ">");
|
||||
@ -242,35 +202,29 @@ namespace chaiscript
|
||||
|
||||
/// Create a bound function object. The first param is the function to bind
|
||||
/// the remaining parameters are the args to bind into the result
|
||||
static Boxed_Value bind_function(const Function_Params ¶ms)
|
||||
{
|
||||
static Boxed_Value bind_function(const Function_Params ¶ms) {
|
||||
if (params.empty()) {
|
||||
throw exception::arity_error(0, 1);
|
||||
}
|
||||
|
||||
Const_Proxy_Function f = boxed_cast<Const_Proxy_Function>(params[0]);
|
||||
|
||||
if (f->get_arity() != -1 && size_t(f->get_arity()) != params.size() - 1)
|
||||
{
|
||||
if (f->get_arity() != -1 && size_t(f->get_arity()) != params.size() - 1) {
|
||||
throw exception::arity_error(static_cast<int>(params.size()), f->get_arity());
|
||||
}
|
||||
|
||||
return Boxed_Value(Const_Proxy_Function(std::make_shared<dispatch::Bound_Function>(std::move(f),
|
||||
std::vector<Boxed_Value>(params.begin() + 1, params.end()))));
|
||||
return Boxed_Value(Const_Proxy_Function(
|
||||
std::make_shared<dispatch::Bound_Function>(std::move(f), std::vector<Boxed_Value>(params.begin() + 1, params.end()))));
|
||||
}
|
||||
|
||||
|
||||
static bool has_guard(const Const_Proxy_Function &t_pf) noexcept
|
||||
{
|
||||
static bool has_guard(const Const_Proxy_Function &t_pf) noexcept {
|
||||
auto pf = std::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(t_pf);
|
||||
return pf && pf->has_guard();
|
||||
}
|
||||
|
||||
static Const_Proxy_Function get_guard(const Const_Proxy_Function &t_pf)
|
||||
{
|
||||
static Const_Proxy_Function get_guard(const Const_Proxy_Function &t_pf) {
|
||||
const auto pf = std::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(t_pf);
|
||||
if (pf && pf->get_guard())
|
||||
{
|
||||
if (pf && pf->get_guard()) {
|
||||
return pf->get_guard();
|
||||
} else {
|
||||
throw std::runtime_error("Function does not have a guard");
|
||||
@ -278,33 +232,26 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
template<typename FunctionType>
|
||||
static std::vector<Boxed_Value> do_return_boxed_value_vector(FunctionType f,
|
||||
const dispatch::Proxy_Function_Base *b)
|
||||
{
|
||||
static std::vector<Boxed_Value> do_return_boxed_value_vector(FunctionType f, const dispatch::Proxy_Function_Base *b) {
|
||||
auto v = (b->*f)();
|
||||
|
||||
std::vector<Boxed_Value> vbv;
|
||||
|
||||
for (const auto &o: v)
|
||||
{
|
||||
for (const auto &o : v) {
|
||||
vbv.push_back(const_var(o));
|
||||
}
|
||||
|
||||
return vbv;
|
||||
}
|
||||
|
||||
|
||||
static bool has_parse_tree(const chaiscript::Const_Proxy_Function &t_pf) noexcept
|
||||
{
|
||||
static bool has_parse_tree(const chaiscript::Const_Proxy_Function &t_pf) noexcept {
|
||||
const auto pf = std::dynamic_pointer_cast<const chaiscript::dispatch::Dynamic_Proxy_Function>(t_pf);
|
||||
return bool(pf);
|
||||
}
|
||||
|
||||
static const chaiscript::AST_Node &get_parse_tree(const chaiscript::Const_Proxy_Function &t_pf)
|
||||
{
|
||||
static const chaiscript::AST_Node &get_parse_tree(const chaiscript::Const_Proxy_Function &t_pf) {
|
||||
const auto pf = std::dynamic_pointer_cast<const chaiscript::dispatch::Dynamic_Proxy_Function>(t_pf);
|
||||
if (pf)
|
||||
{
|
||||
if (pf) {
|
||||
return pf->get_parse_tree();
|
||||
} else {
|
||||
throw std::runtime_error("Function does not have a parse tree");
|
||||
@ -312,20 +259,15 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
template<typename Function>
|
||||
static auto return_boxed_value_vector(const Function &f)
|
||||
{
|
||||
return [f](const dispatch::Proxy_Function_Base *b) {
|
||||
return do_return_boxed_value_vector(f, b);
|
||||
};
|
||||
static auto return_boxed_value_vector(const Function &f) {
|
||||
return [f](const dispatch::Proxy_Function_Base *b) { return do_return_boxed_value_vector(f, b); };
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
/// \brief perform all common bootstrap functions for std::string, void and POD types
|
||||
/// \param[in,out] m Module to add bootstrapped functions to
|
||||
/// \returns passed in Module
|
||||
static void bootstrap(Module& m)
|
||||
{
|
||||
static void bootstrap(Module &m) {
|
||||
m.add(user_type<void>(), "void");
|
||||
m.add(user_type<bool>(), "bool");
|
||||
m.add(user_type<Boxed_Value>(), "Object");
|
||||
@ -337,11 +279,10 @@ namespace chaiscript
|
||||
m.add(fun(&dispatch::Proxy_Function_Base::get_arity), "get_arity");
|
||||
m.add(fun(&dispatch::Proxy_Function_Base::operator==), "==");
|
||||
|
||||
|
||||
m.add(fun(return_boxed_value_vector(&dispatch::Proxy_Function_Base::get_param_types)), "get_param_types");
|
||||
m.add(fun(return_boxed_value_vector(&dispatch::Proxy_Function_Base::get_contained_functions)), "get_contained_functions");
|
||||
|
||||
m.add(fun([](const std::exception &e){ return std::string(e.what()); }), "what");
|
||||
m.add(fun([](const std::exception &e) { return std::string(e.what()); }), "what");
|
||||
|
||||
m.add(user_type<std::out_of_range>(), "out_of_range");
|
||||
m.add(user_type<std::logic_error>(), "logic_error");
|
||||
@ -352,25 +293,30 @@ namespace chaiscript
|
||||
m.add(user_type<std::runtime_error>(), "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(user_type<dispatch::Dynamic_Object>(), "Dynamic_Object");
|
||||
m.add(constructor<dispatch::Dynamic_Object (const std::string &)>(), "Dynamic_Object");
|
||||
m.add(constructor<dispatch::Dynamic_Object ()>(), "Dynamic_Object");
|
||||
m.add(constructor<dispatch::Dynamic_Object(const std::string &)>(), "Dynamic_Object");
|
||||
m.add(constructor<dispatch::Dynamic_Object()>(), "Dynamic_Object");
|
||||
m.add(fun(&dispatch::Dynamic_Object::get_type_name), "get_type_name");
|
||||
m.add(fun(&dispatch::Dynamic_Object::get_attrs), "get_attrs");
|
||||
m.add(fun(&dispatch::Dynamic_Object::set_explicit), "set_explicit");
|
||||
m.add(fun(&dispatch::Dynamic_Object::is_explicit), "is_explicit");
|
||||
m.add(fun(&dispatch::Dynamic_Object::has_attr), "has_attr");
|
||||
|
||||
m.add(fun(static_cast<Boxed_Value & (dispatch::Dynamic_Object::*)(const std::string &)>(&dispatch::Dynamic_Object::get_attr)), "get_attr");
|
||||
m.add(fun(static_cast<const Boxed_Value & (dispatch::Dynamic_Object::*)(const std::string &) const>(&dispatch::Dynamic_Object::get_attr)), "get_attr");
|
||||
m.add(fun(static_cast<Boxed_Value &(dispatch::Dynamic_Object::*)(const std::string &)>(&dispatch::Dynamic_Object::get_attr)), "get_attr");
|
||||
m.add(fun(static_cast<const Boxed_Value &(dispatch::Dynamic_Object::*)(const std::string &) const>(&dispatch::Dynamic_Object::get_attr)),
|
||||
"get_attr");
|
||||
|
||||
m.add(fun(static_cast<Boxed_Value & (dispatch::Dynamic_Object::*)(const std::string &)>(&dispatch::Dynamic_Object::method_missing)), "method_missing");
|
||||
m.add(fun(static_cast<const Boxed_Value & (dispatch::Dynamic_Object::*)(const std::string &) const>(&dispatch::Dynamic_Object::method_missing)), "method_missing");
|
||||
m.add(fun(static_cast<Boxed_Value &(dispatch::Dynamic_Object::*)(const std::string &)>(&dispatch::Dynamic_Object::method_missing)),
|
||||
"method_missing");
|
||||
m.add(fun(static_cast<const Boxed_Value &(dispatch::Dynamic_Object::*)(const std::string &) const>(
|
||||
&dispatch::Dynamic_Object::method_missing)),
|
||||
"method_missing");
|
||||
|
||||
m.add(fun(static_cast<Boxed_Value & (dispatch::Dynamic_Object::*)(const std::string &)>(&dispatch::Dynamic_Object::get_attr)), "[]");
|
||||
m.add(fun(static_cast<const Boxed_Value & (dispatch::Dynamic_Object::*)(const std::string &) const>(&dispatch::Dynamic_Object::get_attr)), "[]");
|
||||
m.add(fun(static_cast<Boxed_Value &(dispatch::Dynamic_Object::*)(const std::string &)>(&dispatch::Dynamic_Object::get_attr)), "[]");
|
||||
m.add(fun(static_cast<const Boxed_Value &(dispatch::Dynamic_Object::*)(const std::string &) const>(&dispatch::Dynamic_Object::get_attr)),
|
||||
"[]");
|
||||
|
||||
m.eval(R"chaiscript(
|
||||
def Dynamic_Object::clone() {
|
||||
@ -426,8 +372,7 @@ namespace chaiscript
|
||||
|
||||
m.add(fun(&Boxed_Value::get_type_info), "get_type_info");
|
||||
m.add(user_type<Type_Info>(), "Type_Info");
|
||||
m.add(constructor<Type_Info (const Type_Info &)>(), "Type_Info");
|
||||
|
||||
m.add(constructor<Type_Info(const Type_Info &)>(), "Type_Info");
|
||||
|
||||
operators::equal<Type_Info>(m);
|
||||
|
||||
@ -441,21 +386,19 @@ namespace chaiscript
|
||||
m.add(fun(&Type_Info::bare_name), "cpp_bare_name");
|
||||
m.add(fun(&Type_Info::bare_equal), "bare_equal");
|
||||
|
||||
|
||||
basic_constructors<bool>("bool", m);
|
||||
operators::assign<bool>(m);
|
||||
operators::equal<bool>(m);
|
||||
operators::not_equal<bool>(m);
|
||||
|
||||
m.add(fun([](const std::string &s) { return s; }), "to_string");
|
||||
m.add(fun([](const bool b) { return std::string(b?"true":"false"); }), "to_string");
|
||||
m.add(fun([](const bool b) { return std::string(b ? "true" : "false"); }), "to_string");
|
||||
m.add(fun(&unknown_assign), "=");
|
||||
m.add(fun([](const Boxed_Value &bv) { throw bv; }), "throw");
|
||||
|
||||
m.add(fun([](const char c) { return std::string(1, c); }), "to_string");
|
||||
m.add(fun(&Boxed_Number::to_string), "to_string");
|
||||
|
||||
|
||||
bootstrap_pod_type<double>("double", m);
|
||||
bootstrap_pod_type<long double>("long_double", m);
|
||||
bootstrap_pod_type<float>("float", m);
|
||||
@ -479,12 +422,10 @@ namespace chaiscript
|
||||
bootstrap_pod_type<std::uint32_t>("uint32_t", m);
|
||||
bootstrap_pod_type<std::uint64_t>("uint64_t", m);
|
||||
|
||||
|
||||
operators::logical_compliment<bool>(m);
|
||||
|
||||
opers_arithmetic_pod(m);
|
||||
|
||||
|
||||
m.add(fun(&Build_Info::version_major), "version_major");
|
||||
m.add(fun(&Build_Info::version_minor), "version_minor");
|
||||
m.add(fun(&Build_Info::version_patch), "version_patch");
|
||||
@ -494,7 +435,6 @@ namespace chaiscript
|
||||
m.add(fun(&Build_Info::compiler_id), "compiler_id");
|
||||
m.add(fun(&Build_Info::debug_build), "debug_build");
|
||||
|
||||
|
||||
m.add(fun(&print), "print_string");
|
||||
m.add(fun(&println), "println_string");
|
||||
|
||||
@ -504,16 +444,13 @@ namespace chaiscript
|
||||
m.add(fun(&ptr_assign<std::remove_const<dispatch::Proxy_Function_Base>::type>), "=");
|
||||
m.add(fun(&ptr_assign<std::add_const<dispatch::Proxy_Function_Base>::type>), "=");
|
||||
m.add(chaiscript::base_class<dispatch::Proxy_Function_Base, dispatch::Assignable_Proxy_Function>());
|
||||
m.add(fun(
|
||||
[](dispatch::Assignable_Proxy_Function &t_lhs, const std::shared_ptr<const dispatch::Proxy_Function_Base> &t_rhs) {
|
||||
m.add(fun([](dispatch::Assignable_Proxy_Function &t_lhs, const std::shared_ptr<const dispatch::Proxy_Function_Base> &t_rhs) {
|
||||
t_lhs.assign(t_rhs);
|
||||
}
|
||||
), "="
|
||||
);
|
||||
}),
|
||||
"=");
|
||||
|
||||
m.add(fun(&Boxed_Value::type_match), "type_match");
|
||||
|
||||
|
||||
m.add(chaiscript::fun(&has_parse_tree), "has_parse_tree");
|
||||
m.add(chaiscript::fun(&get_parse_tree), "get_parse_tree");
|
||||
|
||||
@ -524,38 +461,34 @@ namespace chaiscript
|
||||
m.add(chaiscript::base_class<std::runtime_error, chaiscript::exception::arithmetic_error>());
|
||||
m.add(chaiscript::base_class<std::exception, 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);
|
||||
|
||||
chaiscript::utility::add_class<chaiscript::exception::eval_error>(m,
|
||||
"eval_error",
|
||||
{ },
|
||||
{ {fun(&chaiscript::exception::eval_error::reason), "reason"},
|
||||
{},
|
||||
{{fun(&chaiscript::exception::eval_error::reason), "reason"},
|
||||
{fun(&chaiscript::exception::eval_error::pretty_print), "pretty_print"},
|
||||
{fun([](const chaiscript::exception::eval_error &t_eval_error) {
|
||||
std::vector<Boxed_Value> retval;
|
||||
std::transform(t_eval_error.call_stack.begin(), t_eval_error.call_stack.end(),
|
||||
std::transform(t_eval_error.call_stack.begin(),
|
||||
t_eval_error.call_stack.end(),
|
||||
std::back_inserter(retval),
|
||||
&chaiscript::var<const chaiscript::AST_Node_Trace &>);
|
||||
return retval;
|
||||
}), "call_stack"} }
|
||||
);
|
||||
|
||||
}),
|
||||
"call_stack"}});
|
||||
|
||||
chaiscript::utility::add_class<chaiscript::File_Position>(m,
|
||||
"File_Position",
|
||||
{ constructor<File_Position()>(),
|
||||
constructor<File_Position(int, int)>() },
|
||||
{ {fun(&File_Position::line), "line"},
|
||||
{fun(&File_Position::column), "column"} }
|
||||
);
|
||||
|
||||
{constructor<File_Position()>(), constructor<File_Position(int, int)>()},
|
||||
{{fun(&File_Position::line), "line"},
|
||||
{fun(&File_Position::column), "column"}});
|
||||
|
||||
chaiscript::utility::add_class<AST_Node>(m,
|
||||
"AST_Node",
|
||||
{ },
|
||||
{ {fun(&AST_Node::text), "text"},
|
||||
{},
|
||||
{{fun(&AST_Node::text), "text"},
|
||||
{fun(&AST_Node::identifier), "identifier"},
|
||||
{fun(&AST_Node::filename), "filename"},
|
||||
{fun(&AST_Node::start), "start"},
|
||||
@ -564,18 +497,15 @@ namespace chaiscript
|
||||
{fun([](const chaiscript::AST_Node &t_node) -> std::vector<Boxed_Value> {
|
||||
std::vector<Boxed_Value> retval;
|
||||
const auto children = t_node.get_children();
|
||||
std::transform(children.begin(), children.end(),
|
||||
std::transform(children.begin(),
|
||||
children.end(),
|
||||
std::back_inserter(retval),
|
||||
&chaiscript::var<const std::reference_wrapper<chaiscript::AST_Node> &>);
|
||||
return retval;
|
||||
}), "children"}
|
||||
}
|
||||
);
|
||||
|
||||
}),
|
||||
"children"}});
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
} // namespace chaiscript::bootstrap
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@ -7,13 +7,11 @@
|
||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||
|
||||
|
||||
/// \file
|
||||
/// This file contains utility functions for registration of STL container
|
||||
/// classes. The methodology used is based on the SGI STL concepts.
|
||||
/// http://www.sgi.com/tech/stl/table_of_contents.html
|
||||
|
||||
|
||||
#ifndef CHAISCRIPT_BOOTSTRAP_STL_HPP_
|
||||
#define CHAISCRIPT_BOOTSTRAP_STL_HPP_
|
||||
|
||||
@ -31,62 +29,44 @@
|
||||
#include "register_function.hpp"
|
||||
#include "type_info.hpp"
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
namespace bootstrap
|
||||
{
|
||||
namespace standard_library
|
||||
{
|
||||
|
||||
namespace chaiscript::bootstrap::standard_library {
|
||||
/// Bidir_Range, based on the D concept of ranges.
|
||||
/// \todo Update the Range code to base its capabilities on
|
||||
/// the user_typetraits of the iterator passed in
|
||||
template<typename Container, typename IterType>
|
||||
struct Bidir_Range
|
||||
{
|
||||
struct Bidir_Range {
|
||||
using container_type = Container;
|
||||
|
||||
constexpr Bidir_Range(Container &c)
|
||||
: m_begin(c.begin()), m_end(c.end())
|
||||
{
|
||||
: m_begin(c.begin())
|
||||
, m_end(c.end()) {
|
||||
}
|
||||
|
||||
constexpr bool empty() const noexcept
|
||||
{
|
||||
return m_begin == m_end;
|
||||
}
|
||||
constexpr bool empty() const noexcept { return m_begin == m_end; }
|
||||
|
||||
constexpr void pop_front()
|
||||
{
|
||||
if (empty())
|
||||
{
|
||||
constexpr void pop_front() {
|
||||
if (empty()) {
|
||||
throw std::range_error("Range empty");
|
||||
}
|
||||
++m_begin;
|
||||
}
|
||||
|
||||
constexpr void pop_back()
|
||||
{
|
||||
if (empty())
|
||||
{
|
||||
constexpr void pop_back() {
|
||||
if (empty()) {
|
||||
throw std::range_error("Range empty");
|
||||
}
|
||||
--m_end;
|
||||
}
|
||||
|
||||
constexpr decltype(auto) front() const
|
||||
{
|
||||
if (empty())
|
||||
{
|
||||
constexpr decltype(auto) front() const {
|
||||
if (empty()) {
|
||||
throw std::range_error("Range empty");
|
||||
}
|
||||
return (*m_begin);
|
||||
}
|
||||
|
||||
constexpr decltype(auto) back() const
|
||||
{
|
||||
if (empty())
|
||||
{
|
||||
constexpr decltype(auto) back() const {
|
||||
if (empty()) {
|
||||
throw std::range_error("Range empty");
|
||||
}
|
||||
auto pos = m_end;
|
||||
@ -99,36 +79,29 @@ namespace chaiscript
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<typename T>
|
||||
size_t count(const T &t_target, const typename T::key_type &t_key)
|
||||
{
|
||||
size_t count(const T &t_target, const typename T::key_type &t_key) {
|
||||
return t_target.count(t_key);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void insert(T &t_target, const T &t_other)
|
||||
{
|
||||
void insert(T &t_target, const T &t_other) {
|
||||
t_target.insert(t_other.begin(), t_other.end());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void insert_ref(T &t_target, const typename T::value_type &t_val)
|
||||
{
|
||||
void insert_ref(T &t_target, const typename T::value_type &t_val) {
|
||||
t_target.insert(t_val);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// Add Bidir_Range support for the given ContainerType
|
||||
template<typename Bidir_Type>
|
||||
void input_range_type_impl(const std::string &type, Module& m)
|
||||
{
|
||||
void input_range_type_impl(const std::string &type, Module &m) {
|
||||
m.add(user_type<Bidir_Type>(), type + "_Range");
|
||||
|
||||
copy_constructor<Bidir_Type>(type + "_Range", m);
|
||||
|
||||
m.add(constructor<Bidir_Type (typename Bidir_Type::container_type &)>(), "range_internal");
|
||||
m.add(constructor<Bidir_Type(typename Bidir_Type::container_type &)>(), "range_internal");
|
||||
|
||||
m.add(fun(&Bidir_Type::empty), "empty");
|
||||
m.add(fun(&Bidir_Type::pop_front), "pop_front");
|
||||
@ -137,16 +110,13 @@ namespace chaiscript
|
||||
m.add(fun(&Bidir_Type::back), "back");
|
||||
}
|
||||
|
||||
|
||||
/// Algorithm for inserting at a specific position into a container
|
||||
template<typename Type>
|
||||
void insert_at(Type &container, int pos, const typename Type::value_type &v)
|
||||
{
|
||||
void insert_at(Type &container, int pos, const typename Type::value_type &v) {
|
||||
auto itr = container.begin();
|
||||
auto end = container.end();
|
||||
|
||||
if (pos < 0 || std::distance(itr, end) < pos)
|
||||
{
|
||||
if (pos < 0 || std::distance(itr, end) < pos) {
|
||||
throw std::range_error("Cannot insert past end of range");
|
||||
}
|
||||
|
||||
@ -154,62 +124,52 @@ namespace chaiscript
|
||||
container.insert(itr, v);
|
||||
}
|
||||
|
||||
|
||||
/// Algorithm for erasing a specific position from a container
|
||||
template<typename Type>
|
||||
void erase_at(Type &container, int pos)
|
||||
{
|
||||
void erase_at(Type &container, int pos) {
|
||||
auto itr = container.begin();
|
||||
auto end = container.end();
|
||||
|
||||
if (pos < 0 || std::distance(itr, end) < (pos-1))
|
||||
{
|
||||
if (pos < 0 || std::distance(itr, end) < (pos - 1)) {
|
||||
throw std::range_error("Cannot erase past end of range");
|
||||
}
|
||||
|
||||
std::advance(itr, pos);
|
||||
container.erase(itr);
|
||||
}
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
template<typename ContainerType>
|
||||
void input_range_type(const std::string &type, Module& m)
|
||||
{
|
||||
detail::input_range_type_impl<Bidir_Range<ContainerType, typename ContainerType::iterator> >(type,m);
|
||||
detail::input_range_type_impl<Bidir_Range<const ContainerType, typename ContainerType::const_iterator> >("Const_" + type,m);
|
||||
void input_range_type(const std::string &type, Module &m) {
|
||||
detail::input_range_type_impl<Bidir_Range<ContainerType, typename ContainerType::iterator>>(type, m);
|
||||
detail::input_range_type_impl<Bidir_Range<const ContainerType, typename ContainerType::const_iterator>>("Const_" + type, m);
|
||||
}
|
||||
|
||||
|
||||
/// Add random_access_container concept to the given ContainerType
|
||||
/// http://www.sgi.com/tech/stl/RandomAccessContainer.html
|
||||
template<typename ContainerType>
|
||||
void random_access_container_type(const std::string &/*type*/, Module& m)
|
||||
{
|
||||
//In the interest of runtime safety for the m, we prefer the at() method for [] access,
|
||||
//to throw an exception in an out of bounds condition.
|
||||
m.add(
|
||||
fun(
|
||||
[](ContainerType &c, int index) -> typename ContainerType::reference {
|
||||
void random_access_container_type(const std::string & /*type*/, Module &m) {
|
||||
// In the interest of runtime safety for the m, we prefer the at() method for [] access,
|
||||
// to throw an exception in an out of bounds condition.
|
||||
m.add(fun([](ContainerType &c, int index) -> typename ContainerType::reference {
|
||||
/// \todo we are preferring to keep the key as 'int' to avoid runtime conversions
|
||||
/// during dispatch. reevaluate
|
||||
return c.at(static_cast<typename ContainerType::size_type>(index));
|
||||
}), "[]");
|
||||
}),
|
||||
"[]");
|
||||
|
||||
m.add(
|
||||
fun(
|
||||
[](const ContainerType &c, int index) -> typename ContainerType::const_reference {
|
||||
m.add(fun([](const ContainerType &c, int index) -> typename ContainerType::const_reference {
|
||||
/// \todo we are preferring to keep the key as 'int' to avoid runtime conversions
|
||||
/// during dispatch. reevaluate
|
||||
return c.at(static_cast<typename ContainerType::size_type>(index));
|
||||
}), "[]");
|
||||
}),
|
||||
"[]");
|
||||
}
|
||||
|
||||
|
||||
/// Add assignable concept to the given ContainerType
|
||||
/// http://www.sgi.com/tech/stl/Assignable.html
|
||||
template<typename ContainerType>
|
||||
void assignable_type(const std::string &type, Module& m)
|
||||
{
|
||||
void assignable_type(const std::string &type, Module &m) {
|
||||
copy_constructor<ContainerType>(type, m);
|
||||
operators::assign<ContainerType>(m);
|
||||
}
|
||||
@ -217,46 +177,43 @@ namespace chaiscript
|
||||
/// Add container resize concept to the given ContainerType
|
||||
/// http://www.cplusplus.com/reference/stl/
|
||||
template<typename ContainerType>
|
||||
void resizable_type(const std::string &/*type*/, Module& m)
|
||||
{
|
||||
m.add(fun([](ContainerType *a, typename ContainerType::size_type n, const typename ContainerType::value_type& val) { return a->resize(n, val); } ), "resize");
|
||||
m.add(fun([](ContainerType *a, typename ContainerType::size_type n) { return a->resize(n); } ), "resize");
|
||||
void resizable_type(const std::string & /*type*/, Module &m) {
|
||||
m.add(fun([](ContainerType *a, typename ContainerType::size_type n, const typename ContainerType::value_type &val) {
|
||||
return a->resize(n, val);
|
||||
}),
|
||||
"resize");
|
||||
m.add(fun([](ContainerType *a, typename ContainerType::size_type n) { return a->resize(n); }), "resize");
|
||||
}
|
||||
|
||||
/// Add container reserve concept to the given ContainerType
|
||||
/// http://www.cplusplus.com/reference/stl/
|
||||
template<typename ContainerType>
|
||||
void reservable_type(const std::string &/*type*/, Module& m)
|
||||
{
|
||||
m.add(fun([](ContainerType *a, typename ContainerType::size_type n) { return a->reserve(n); } ), "reserve");
|
||||
m.add(fun([](const ContainerType *a) { return a->capacity(); } ), "capacity");
|
||||
void reservable_type(const std::string & /*type*/, Module &m) {
|
||||
m.add(fun([](ContainerType *a, typename ContainerType::size_type n) { return a->reserve(n); }), "reserve");
|
||||
m.add(fun([](const ContainerType *a) { return a->capacity(); }), "capacity");
|
||||
}
|
||||
|
||||
/// Add container concept to the given ContainerType
|
||||
/// http://www.sgi.com/tech/stl/Container.html
|
||||
template<typename ContainerType>
|
||||
void container_type(const std::string &/*type*/, Module& m)
|
||||
{
|
||||
m.add(fun([](const ContainerType *a) { return a->size(); } ), "size");
|
||||
m.add(fun([](const ContainerType *a) { return a->empty(); } ), "empty");
|
||||
m.add(fun([](ContainerType *a) { a->clear(); } ), "clear");
|
||||
void container_type(const std::string & /*type*/, Module &m) {
|
||||
m.add(fun([](const ContainerType *a) { return a->size(); }), "size");
|
||||
m.add(fun([](const ContainerType *a) { return a->empty(); }), "empty");
|
||||
m.add(fun([](ContainerType *a) { a->clear(); }), "clear");
|
||||
}
|
||||
|
||||
/// Add default constructable concept to the given Type
|
||||
/// http://www.sgi.com/tech/stl/DefaultConstructible.html
|
||||
template<typename Type>
|
||||
void default_constructible_type(const std::string &type, Module& m)
|
||||
{
|
||||
m.add(constructor<Type ()>(), type);
|
||||
void default_constructible_type(const std::string &type, Module &m) {
|
||||
m.add(constructor<Type()>(), type);
|
||||
}
|
||||
|
||||
/// Add sequence concept to the given ContainerType
|
||||
/// http://www.sgi.com/tech/stl/Sequence.html
|
||||
template<typename ContainerType>
|
||||
void sequence_type(const std::string &/*type*/, Module& m)
|
||||
{
|
||||
m.add(fun(&detail::insert_at<ContainerType>),
|
||||
[]()->std::string{
|
||||
void sequence_type(const std::string & /*type*/, Module &m) {
|
||||
m.add(fun(&detail::insert_at<ContainerType>), []() -> std::string {
|
||||
if (typeid(typename ContainerType::value_type) == typeid(Boxed_Value)) {
|
||||
return "insert_ref_at";
|
||||
} else {
|
||||
@ -270,35 +227,31 @@ namespace chaiscript
|
||||
/// Add back insertion sequence concept to the given ContainerType
|
||||
/// http://www.sgi.com/tech/stl/BackInsertionSequence.html
|
||||
template<typename ContainerType>
|
||||
void back_insertion_sequence_type(const std::string &type, Module& m)
|
||||
{
|
||||
m.add(fun([](ContainerType &container)->decltype(auto){
|
||||
void back_insertion_sequence_type(const std::string &type, Module &m) {
|
||||
m.add(fun([](ContainerType &container) -> decltype(auto) {
|
||||
if (container.empty()) {
|
||||
throw std::range_error("Container empty");
|
||||
} else {
|
||||
return (container.back());
|
||||
}
|
||||
}
|
||||
)
|
||||
, "back");
|
||||
m.add(fun([](const ContainerType &container)->decltype(auto){
|
||||
}),
|
||||
"back");
|
||||
m.add(fun([](const ContainerType &container) -> decltype(auto) {
|
||||
if (container.empty()) {
|
||||
throw std::range_error("Container empty");
|
||||
} else {
|
||||
return (container.back());
|
||||
}
|
||||
}
|
||||
)
|
||||
, "back");
|
||||
|
||||
}),
|
||||
"back");
|
||||
|
||||
using push_back = void (ContainerType::*)(const typename ContainerType::value_type &);
|
||||
m.add(fun(static_cast<push_back>(&ContainerType::push_back)),
|
||||
[&]()->std::string{
|
||||
m.add(fun(static_cast<push_back>(&ContainerType::push_back)), [&]() -> std::string {
|
||||
if (typeid(typename ContainerType::value_type) == typeid(Boxed_Value)) {
|
||||
m.eval(
|
||||
"# Pushes the second value onto the container while making a clone of the value\n"
|
||||
"def push_back(" + type + " container, x)\n"
|
||||
m.eval("# Pushes the second value onto the container while making a clone of the value\n"
|
||||
"def push_back("
|
||||
+ type
|
||||
+ " container, x)\n"
|
||||
"{ \n"
|
||||
" if (x.is_var_return_value()) {\n"
|
||||
" x.reset_var_return_value() \n"
|
||||
@ -306,8 +259,7 @@ namespace chaiscript
|
||||
" } else { \n"
|
||||
" container.push_back_ref(clone(x)); \n"
|
||||
" }\n"
|
||||
"} \n"
|
||||
);
|
||||
"} \n");
|
||||
|
||||
return "push_back_ref";
|
||||
} else {
|
||||
@ -318,42 +270,37 @@ namespace chaiscript
|
||||
m.add(fun(&ContainerType::pop_back), "pop_back");
|
||||
}
|
||||
|
||||
|
||||
/// Front insertion sequence
|
||||
/// http://www.sgi.com/tech/stl/FrontInsertionSequence.html
|
||||
template<typename ContainerType>
|
||||
void front_insertion_sequence_type(const std::string &type, Module& m)
|
||||
{
|
||||
void front_insertion_sequence_type(const std::string &type, Module &m) {
|
||||
using push_ptr = void (ContainerType::*)(typename ContainerType::const_reference);
|
||||
using pop_ptr = void (ContainerType::*)();
|
||||
|
||||
m.add(fun([](ContainerType &container)->decltype(auto){
|
||||
m.add(fun([](ContainerType &container) -> decltype(auto) {
|
||||
if (container.empty()) {
|
||||
throw std::range_error("Container empty");
|
||||
} else {
|
||||
return (container.front());
|
||||
}
|
||||
}
|
||||
)
|
||||
, "front");
|
||||
}),
|
||||
"front");
|
||||
|
||||
m.add(fun([](const ContainerType &container)->decltype(auto){
|
||||
m.add(fun([](const ContainerType &container) -> decltype(auto) {
|
||||
if (container.empty()) {
|
||||
throw std::range_error("Container empty");
|
||||
} else {
|
||||
return (container.front());
|
||||
}
|
||||
}
|
||||
)
|
||||
, "front");
|
||||
}),
|
||||
"front");
|
||||
|
||||
|
||||
m.add(fun(static_cast<push_ptr>(&ContainerType::push_front)),
|
||||
[&]()->std::string{
|
||||
m.add(fun(static_cast<push_ptr>(&ContainerType::push_front)), [&]() -> std::string {
|
||||
if (typeid(typename ContainerType::value_type) == typeid(Boxed_Value)) {
|
||||
m.eval(
|
||||
"# Pushes the second value onto the front of container while making a clone of the value\n"
|
||||
"def push_front(" + type + " container, x)\n"
|
||||
m.eval("# Pushes the second value onto the front of container while making a clone of the value\n"
|
||||
"def push_front("
|
||||
+ type
|
||||
+ " container, x)\n"
|
||||
"{ \n"
|
||||
" if (x.is_var_return_value()) {\n"
|
||||
" x.reset_var_return_value() \n"
|
||||
@ -361,8 +308,7 @@ namespace chaiscript
|
||||
" } else { \n"
|
||||
" container.push_front_ref(clone(x)); \n"
|
||||
" }\n"
|
||||
"} \n"
|
||||
);
|
||||
"} \n");
|
||||
return "push_front_ref";
|
||||
} else {
|
||||
return "push_front";
|
||||
@ -375,32 +321,28 @@ namespace chaiscript
|
||||
/// bootstrap a given PairType
|
||||
/// http://www.sgi.com/tech/stl/pair.html
|
||||
template<typename PairType>
|
||||
void pair_type(const std::string &type, Module& m)
|
||||
{
|
||||
void pair_type(const std::string &type, Module &m) {
|
||||
m.add(user_type<PairType>(), type);
|
||||
|
||||
m.add(fun(&PairType::first), "first");
|
||||
m.add(fun(&PairType::second), "second");
|
||||
|
||||
basic_constructors<PairType>(type, m);
|
||||
m.add(constructor<PairType (const typename PairType::first_type &, const typename PairType::second_type &)>(), type);
|
||||
m.add(constructor<PairType(const typename PairType::first_type &, const typename PairType::second_type &)>(), type);
|
||||
}
|
||||
|
||||
|
||||
/// Add pair associative container concept to the given ContainerType
|
||||
/// http://www.sgi.com/tech/stl/PairAssociativeContainer.html
|
||||
|
||||
template<typename ContainerType>
|
||||
void pair_associative_container_type(const std::string &type, Module& m)
|
||||
{
|
||||
void pair_associative_container_type(const std::string &type, Module &m) {
|
||||
pair_type<typename ContainerType::value_type>(type + "_Pair", m);
|
||||
}
|
||||
|
||||
/// Add unique associative container concept to the given ContainerType
|
||||
/// http://www.sgi.com/tech/stl/UniqueAssociativeContainer.html
|
||||
template<typename ContainerType>
|
||||
void unique_associative_container_type(const std::string &/*type*/, Module& m)
|
||||
{
|
||||
void unique_associative_container_type(const std::string & /*type*/, Module &m) {
|
||||
m.add(fun(detail::count<ContainerType>), "count");
|
||||
|
||||
using erase_ptr = size_t (ContainerType::*)(const typename ContainerType::key_type &);
|
||||
@ -409,8 +351,7 @@ namespace chaiscript
|
||||
|
||||
m.add(fun(&detail::insert<ContainerType>), "insert");
|
||||
|
||||
m.add(fun(&detail::insert_ref<ContainerType>),
|
||||
[]()->std::string{
|
||||
m.add(fun(&detail::insert_ref<ContainerType>), []() -> std::string {
|
||||
if (typeid(typename ContainerType::mapped_type) == typeid(Boxed_Value)) {
|
||||
return "insert_ref";
|
||||
} else {
|
||||
@ -422,8 +363,7 @@ namespace chaiscript
|
||||
/// Add a MapType container
|
||||
/// http://www.sgi.com/tech/stl/Map.html
|
||||
template<typename MapType>
|
||||
void map_type(const std::string &type, Module& m)
|
||||
{
|
||||
void map_type(const std::string &type, Module &m) {
|
||||
m.add(user_type<MapType>(), type);
|
||||
|
||||
using elem_access = typename MapType::mapped_type &(MapType::*)(const typename MapType::key_type &);
|
||||
@ -434,8 +374,7 @@ namespace chaiscript
|
||||
m.add(fun(static_cast<elem_access>(&MapType::at)), "at");
|
||||
m.add(fun(static_cast<const_elem_access>(&MapType::at)), "at");
|
||||
|
||||
if (typeid(MapType) == typeid(std::map<std::string, Boxed_Value>))
|
||||
{
|
||||
if (typeid(MapType) == typeid(std::map<std::string, Boxed_Value>)) {
|
||||
m.eval(R"(
|
||||
def Map::`==`(Map rhs) {
|
||||
if ( rhs.size() != this.size() ) {
|
||||
@ -454,8 +393,7 @@ namespace chaiscript
|
||||
}
|
||||
true;
|
||||
}
|
||||
} )"
|
||||
);
|
||||
} )");
|
||||
}
|
||||
|
||||
container_type<MapType>(type, m);
|
||||
@ -468,8 +406,7 @@ namespace chaiscript
|
||||
|
||||
/// http://www.sgi.com/tech/stl/List.html
|
||||
template<typename ListType>
|
||||
void list_type(const std::string &type, Module& m)
|
||||
{
|
||||
void list_type(const std::string &type, Module &m) {
|
||||
m.add(user_type<ListType>(), type);
|
||||
|
||||
front_insertion_sequence_type<ListType>(type, m);
|
||||
@ -485,32 +422,26 @@ namespace chaiscript
|
||||
/// Create a vector type with associated concepts
|
||||
/// http://www.sgi.com/tech/stl/Vector.html
|
||||
template<typename VectorType>
|
||||
void vector_type(const std::string &type, Module& m)
|
||||
{
|
||||
void vector_type(const std::string &type, Module &m) {
|
||||
m.add(user_type<VectorType>(), type);
|
||||
|
||||
m.add(fun([](VectorType &container)->decltype(auto){
|
||||
m.add(fun([](VectorType &container) -> decltype(auto) {
|
||||
if (container.empty()) {
|
||||
throw std::range_error("Container empty");
|
||||
} else {
|
||||
return (container.front());
|
||||
}
|
||||
}
|
||||
)
|
||||
, "front");
|
||||
}),
|
||||
"front");
|
||||
|
||||
m.add(fun([](const VectorType &container)->decltype(auto){
|
||||
m.add(fun([](const VectorType &container) -> decltype(auto) {
|
||||
if (container.empty()) {
|
||||
throw std::range_error("Container empty");
|
||||
} else {
|
||||
return (container.front());
|
||||
}
|
||||
}
|
||||
)
|
||||
, "front");
|
||||
|
||||
|
||||
|
||||
}),
|
||||
"front");
|
||||
|
||||
back_insertion_sequence_type<VectorType>(type, m);
|
||||
sequence_type<VectorType>(type, m);
|
||||
@ -522,8 +453,7 @@ namespace chaiscript
|
||||
assignable_type<VectorType>(type, m);
|
||||
input_range_type<VectorType>(type, m);
|
||||
|
||||
if (typeid(VectorType) == typeid(std::vector<Boxed_Value>))
|
||||
{
|
||||
if (typeid(VectorType) == typeid(std::vector<Boxed_Value>)) {
|
||||
m.eval(R"(
|
||||
def Vector::`==`(Vector rhs) {
|
||||
if ( rhs.size() != this.size() ) {
|
||||
@ -542,16 +472,14 @@ namespace chaiscript
|
||||
}
|
||||
true;
|
||||
}
|
||||
} )"
|
||||
);
|
||||
} )");
|
||||
}
|
||||
}
|
||||
|
||||
/// Add a String container
|
||||
/// http://www.sgi.com/tech/stl/basic_string.html
|
||||
template<typename String>
|
||||
void string_type(const std::string &type, Module& m)
|
||||
{
|
||||
void string_type(const std::string &type, Module &m) {
|
||||
m.add(user_type<String>(), type);
|
||||
operators::addition<String>(m);
|
||||
operators::assign_sum<String>(m);
|
||||
@ -563,9 +491,8 @@ namespace chaiscript
|
||||
assignable_type<String>(type, m);
|
||||
input_range_type<String>(type, m);
|
||||
|
||||
//Special case: add push_back to string (which doesn't support other back_insertion operations
|
||||
m.add(fun(&String::push_back),
|
||||
[]()->std::string{
|
||||
// Special case: add push_back to string (which doesn't support other back_insertion operations
|
||||
m.add(fun(&String::push_back), []() -> std::string {
|
||||
if (typeid(typename String::value_type) == typeid(Boxed_Value)) {
|
||||
return "push_back_ref";
|
||||
} else {
|
||||
@ -573,42 +500,34 @@ namespace chaiscript
|
||||
}
|
||||
}());
|
||||
|
||||
m.add(fun([](const String *s, const String &f, size_t pos) { return s->find(f, pos); }), "find");
|
||||
m.add(fun([](const String *s, const String &f, size_t pos) { return s->rfind(f, pos); }), "rfind");
|
||||
m.add(fun([](const String *s, const String &f, size_t pos) { return s->find_first_of(f, pos); }), "find_first_of");
|
||||
m.add(fun([](const String *s, const String &f, size_t pos) { return s->find_last_of(f, pos); }), "find_last_of");
|
||||
m.add(fun([](const String *s, const String &f, size_t pos) { return s->find_last_not_of(f, pos); }), "find_last_not_of");
|
||||
m.add(fun([](const String *s, const String &f, size_t pos) { return s->find_first_not_of(f, pos); }), "find_first_not_of");
|
||||
|
||||
m.add(fun([](const String *s, const String &f, size_t pos) { return s->find(f, pos); } ), "find");
|
||||
m.add(fun([](const String *s, const String &f, size_t pos) { return s->rfind(f, pos); } ), "rfind");
|
||||
m.add(fun([](const String *s, const String &f, size_t pos) { return s->find_first_of(f, pos); } ), "find_first_of");
|
||||
m.add(fun([](const String *s, const String &f, size_t pos) { return s->find_last_of(f, pos); } ), "find_last_of");
|
||||
m.add(fun([](const String *s, const String &f, size_t pos) { return s->find_last_not_of(f, pos); } ), "find_last_not_of");
|
||||
m.add(fun([](const String *s, const String &f, size_t pos) { return s->find_first_not_of(f, pos); } ), "find_first_not_of");
|
||||
m.add(fun([](String *s, typename String::value_type c) -> decltype(auto) { return (*s += c); }), "+=");
|
||||
|
||||
m.add(fun([](String *s, typename String::value_type c) -> decltype(auto) { return (*s += c); } ), "+=");
|
||||
m.add(fun([](String *s) { s->clear(); }), "clear");
|
||||
m.add(fun([](const String *s) { return s->empty(); }), "empty");
|
||||
m.add(fun([](const String *s) { return s->size(); }), "size");
|
||||
|
||||
m.add(fun([](String *s) { s->clear(); } ), "clear");
|
||||
m.add(fun([](const String *s) { return s->empty(); } ), "empty");
|
||||
m.add(fun([](const String *s) { return s->size(); } ), "size");
|
||||
|
||||
m.add(fun([](const String *s) { return s->c_str(); } ), "c_str");
|
||||
m.add(fun([](const String *s) { return s->data(); } ), "data");
|
||||
m.add(fun([](const String *s, size_t pos, size_t len) { return s->substr(pos, len); } ), "substr");
|
||||
m.add(fun([](const String *s) { return s->c_str(); }), "c_str");
|
||||
m.add(fun([](const String *s) { return s->data(); }), "data");
|
||||
m.add(fun([](const String *s, size_t pos, size_t len) { return s->substr(pos, len); }), "substr");
|
||||
}
|
||||
|
||||
|
||||
/// Add a MapType container
|
||||
/// http://www.sgi.com/tech/stl/Map.html
|
||||
template<typename FutureType>
|
||||
void future_type(const std::string &type, Module& m)
|
||||
{
|
||||
void future_type(const std::string &type, Module &m) {
|
||||
m.add(user_type<FutureType>(), type);
|
||||
|
||||
m.add(fun([](const FutureType &t) { return t.valid(); }), "valid");
|
||||
m.add(fun([](FutureType &t) { return t.get(); }), "get");
|
||||
m.add(fun(&FutureType::wait), "wait");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace chaiscript::bootstrap::standard_library
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@ -7,7 +7,6 @@
|
||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||
|
||||
|
||||
#ifndef CHAISCRIPT_BOXED_CAST_HPP_
|
||||
#define CHAISCRIPT_BOXED_CAST_HPP_
|
||||
|
||||
@ -19,17 +18,13 @@
|
||||
#include "type_info.hpp"
|
||||
|
||||
namespace chaiscript {
|
||||
class Type_Conversions;
|
||||
namespace detail {
|
||||
namespace exception {
|
||||
class bad_any_cast;
|
||||
} // namespace exception
|
||||
} // namespace detail
|
||||
} // namespace chaiscript
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
class Type_Conversions;
|
||||
}
|
||||
namespace chaiscript::detail::exception {
|
||||
class bad_any_cast;
|
||||
} // namespace chaiscript::detail::exception
|
||||
|
||||
namespace chaiscript {
|
||||
/// \brief Function for extracting a value stored in a Boxed_Value object
|
||||
/// \tparam Type The type to extract from the Boxed_Value
|
||||
/// \param[in] bv The Boxed_Value to extract a typed value from
|
||||
@ -73,26 +68,24 @@ namespace chaiscript
|
||||
/// assert(i == 5);
|
||||
/// \endcode
|
||||
template<typename Type>
|
||||
decltype(auto) boxed_cast(const Boxed_Value &bv, const Type_Conversions_State *t_conversions = nullptr)
|
||||
{
|
||||
decltype(auto) boxed_cast(const Boxed_Value &bv, const Type_Conversions_State *t_conversions = nullptr) {
|
||||
if (!t_conversions || bv.get_type_info().bare_equal(user_type<Type>()) || (t_conversions && !(*t_conversions)->convertable_type<Type>())) {
|
||||
try {
|
||||
return(detail::Cast_Helper<Type>::cast(bv, t_conversions));
|
||||
return detail::Cast_Helper<Type>::cast(bv, t_conversions);
|
||||
} catch (const chaiscript::detail::exception::bad_any_cast &) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (t_conversions && (*t_conversions)->convertable_type<Type>())
|
||||
{
|
||||
if (t_conversions && (*t_conversions)->convertable_type<Type>()) {
|
||||
try {
|
||||
// We will not catch any bad_boxed_dynamic_cast that is thrown, let the user get it
|
||||
// either way, we are not responsible if it doesn't work
|
||||
return(detail::Cast_Helper<Type>::cast((*t_conversions)->boxed_type_conversion<Type>(t_conversions->saves(), bv), t_conversions));
|
||||
return (detail::Cast_Helper<Type>::cast((*t_conversions)->boxed_type_conversion<Type>(t_conversions->saves(), bv), t_conversions));
|
||||
} catch (...) {
|
||||
try {
|
||||
// try going the other way
|
||||
return(detail::Cast_Helper<Type>::cast((*t_conversions)->boxed_type_down_conversion<Type>(t_conversions->saves(), bv), t_conversions));
|
||||
return (detail::Cast_Helper<Type>::cast((*t_conversions)->boxed_type_down_conversion<Type>(t_conversions->saves(), bv),
|
||||
t_conversions));
|
||||
} catch (const chaiscript::detail::exception::bad_any_cast &) {
|
||||
throw exception::bad_boxed_cast(bv.get_type_info(), typeid(Type));
|
||||
}
|
||||
@ -102,12 +95,8 @@ namespace chaiscript
|
||||
// attempted dynamic_cast
|
||||
throw exception::bad_boxed_cast(bv.get_type_info(), typeid(Type));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
} // namespace chaiscript
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@ -7,7 +7,6 @@
|
||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||
|
||||
|
||||
#ifndef CHAISCRIPT_BOXED_CAST_HELPER_HPP_
|
||||
#define CHAISCRIPT_BOXED_CAST_HELPER_HPP_
|
||||
|
||||
@ -17,19 +16,17 @@
|
||||
#include "boxed_value.hpp"
|
||||
#include "type_info.hpp"
|
||||
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
namespace chaiscript {
|
||||
class Type_Conversions_State;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
namespace detail {
|
||||
// Cast_Helper_Inner helper classes
|
||||
|
||||
template<typename T>
|
||||
constexpr T* throw_if_null(T *t)
|
||||
{
|
||||
if (t) { return t; }
|
||||
constexpr T *throw_if_null(T *t) {
|
||||
if (t) {
|
||||
return t;
|
||||
}
|
||||
throw std::runtime_error("Attempted to dereference null Boxed_Value");
|
||||
}
|
||||
|
||||
@ -51,7 +48,6 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
static const T *verify_type(const Boxed_Value &ob, const std::type_info &ti, const T *ptr) {
|
||||
if (ob.get_type_info().bare_equal_type_info(ti)) {
|
||||
@ -72,79 +68,60 @@ namespace chaiscript
|
||||
|
||||
/// Generic Cast_Helper_Inner, for casting to any type
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner
|
||||
{
|
||||
static Result cast(const Boxed_Value &ob, const Type_Conversions_State *)
|
||||
{
|
||||
struct Cast_Helper_Inner {
|
||||
static Result cast(const Boxed_Value &ob, const Type_Conversions_State *) {
|
||||
return *static_cast<const Result *>(verify_type(ob, typeid(Result), ob.get_const_ptr()));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<const Result> : Cast_Helper_Inner<Result>
|
||||
{
|
||||
struct Cast_Helper_Inner<const Result> : Cast_Helper_Inner<Result> {
|
||||
};
|
||||
|
||||
|
||||
/// Cast_Helper_Inner for casting to a const * type
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<const Result *>
|
||||
{
|
||||
static const Result * cast(const Boxed_Value &ob, const Type_Conversions_State *)
|
||||
{
|
||||
struct Cast_Helper_Inner<const Result *> {
|
||||
static const Result *cast(const Boxed_Value &ob, const Type_Conversions_State *) {
|
||||
return static_cast<const Result *>(verify_type_no_throw(ob, typeid(Result), ob.get_const_ptr()));
|
||||
}
|
||||
};
|
||||
|
||||
/// Cast_Helper_Inner for casting to a * type
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<Result *>
|
||||
{
|
||||
static Result * cast(const Boxed_Value &ob, const Type_Conversions_State *)
|
||||
{
|
||||
struct Cast_Helper_Inner<Result *> {
|
||||
static Result *cast(const Boxed_Value &ob, const Type_Conversions_State *) {
|
||||
return static_cast<Result *>(verify_type_no_throw(ob, typeid(Result), ob.get_ptr()));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<Result * const &> : public Cast_Helper_Inner<Result *>
|
||||
{
|
||||
struct Cast_Helper_Inner<Result *const &> : public Cast_Helper_Inner<Result *> {
|
||||
};
|
||||
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<const Result * const &> : public Cast_Helper_Inner<const Result *>
|
||||
{
|
||||
struct Cast_Helper_Inner<const Result *const &> : public Cast_Helper_Inner<const Result *> {
|
||||
};
|
||||
|
||||
|
||||
/// Cast_Helper_Inner for casting to a & type
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<const Result &>
|
||||
{
|
||||
static const Result & cast(const Boxed_Value &ob, const Type_Conversions_State *)
|
||||
{
|
||||
struct Cast_Helper_Inner<const Result &> {
|
||||
static const Result &cast(const Boxed_Value &ob, const Type_Conversions_State *) {
|
||||
return *static_cast<const Result *>(verify_type(ob, typeid(Result), ob.get_const_ptr()));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
/// Cast_Helper_Inner for casting to a & type
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<Result &>
|
||||
{
|
||||
static Result& cast(const Boxed_Value &ob, const Type_Conversions_State *)
|
||||
{
|
||||
struct Cast_Helper_Inner<Result &> {
|
||||
static Result &cast(const Boxed_Value &ob, const Type_Conversions_State *) {
|
||||
return *static_cast<Result *>(verify_type(ob, typeid(Result), ob.get_ptr()));
|
||||
}
|
||||
};
|
||||
|
||||
/// Cast_Helper_Inner for casting to a && type
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<Result &&>
|
||||
{
|
||||
static Result&& cast(const Boxed_Value &ob, const Type_Conversions_State *)
|
||||
{
|
||||
struct Cast_Helper_Inner<Result &&> {
|
||||
static Result &&cast(const Boxed_Value &ob, const Type_Conversions_State *) {
|
||||
return std::move(*static_cast<Result *>(verify_type(ob, typeid(Result), ob.get_ptr())));
|
||||
}
|
||||
};
|
||||
@ -152,10 +129,8 @@ namespace chaiscript
|
||||
/// Cast_Helper_Inner for casting to a std::unique_ptr<> && type
|
||||
/// \todo Fix the fact that this has to be in a shared_ptr for now
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<std::unique_ptr<Result> &&>
|
||||
{
|
||||
static std::unique_ptr<Result> &&cast(const Boxed_Value &ob, const Type_Conversions_State *)
|
||||
{
|
||||
struct Cast_Helper_Inner<std::unique_ptr<Result> &&> {
|
||||
static std::unique_ptr<Result> &&cast(const Boxed_Value &ob, const Type_Conversions_State *) {
|
||||
return std::move(*(ob.get().cast<std::shared_ptr<std::unique_ptr<Result>>>()));
|
||||
}
|
||||
};
|
||||
@ -163,10 +138,8 @@ namespace chaiscript
|
||||
/// Cast_Helper_Inner for casting to a std::unique_ptr<> & type
|
||||
/// \todo Fix the fact that this has to be in a shared_ptr for now
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<std::unique_ptr<Result> &>
|
||||
{
|
||||
static std::unique_ptr<Result> &cast(const Boxed_Value &ob, const Type_Conversions_State *)
|
||||
{
|
||||
struct Cast_Helper_Inner<std::unique_ptr<Result> &> {
|
||||
static std::unique_ptr<Result> &cast(const Boxed_Value &ob, const Type_Conversions_State *) {
|
||||
return *(ob.get().cast<std::shared_ptr<std::unique_ptr<Result>>>());
|
||||
}
|
||||
};
|
||||
@ -174,150 +147,114 @@ namespace chaiscript
|
||||
/// Cast_Helper_Inner for casting to a std::unique_ptr<> & type
|
||||
/// \todo Fix the fact that this has to be in a shared_ptr for now
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<const std::unique_ptr<Result> &>
|
||||
{
|
||||
static std::unique_ptr<Result> &cast(const Boxed_Value &ob, const Type_Conversions_State *)
|
||||
{
|
||||
struct Cast_Helper_Inner<const std::unique_ptr<Result> &> {
|
||||
static std::unique_ptr<Result> &cast(const Boxed_Value &ob, const Type_Conversions_State *) {
|
||||
return *(ob.get().cast<std::shared_ptr<std::unique_ptr<Result>>>());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/// Cast_Helper_Inner for casting to a std::shared_ptr<> type
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<std::shared_ptr<Result> >
|
||||
{
|
||||
static auto cast(const Boxed_Value &ob, const Type_Conversions_State *)
|
||||
{
|
||||
return ob.get().cast<std::shared_ptr<Result> >();
|
||||
}
|
||||
struct Cast_Helper_Inner<std::shared_ptr<Result>> {
|
||||
static auto cast(const Boxed_Value &ob, const Type_Conversions_State *) { return ob.get().cast<std::shared_ptr<Result>>(); }
|
||||
};
|
||||
|
||||
/// Cast_Helper_Inner for casting to a std::shared_ptr<const> type
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<std::shared_ptr<const Result> >
|
||||
{
|
||||
static auto cast(const Boxed_Value &ob, const Type_Conversions_State *)
|
||||
{
|
||||
if (!ob.get_type_info().is_const())
|
||||
{
|
||||
return std::const_pointer_cast<const Result>(ob.get().cast<std::shared_ptr<Result> >());
|
||||
struct Cast_Helper_Inner<std::shared_ptr<const Result>> {
|
||||
static auto cast(const Boxed_Value &ob, const Type_Conversions_State *) {
|
||||
if (!ob.get_type_info().is_const()) {
|
||||
return std::const_pointer_cast<const Result>(ob.get().cast<std::shared_ptr<Result>>());
|
||||
} else {
|
||||
return ob.get().cast<std::shared_ptr<const Result> >();
|
||||
return ob.get().cast<std::shared_ptr<const Result>>();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/// Cast_Helper_Inner for casting to a const std::shared_ptr<> & type
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<const std::shared_ptr<Result> > : Cast_Helper_Inner<std::shared_ptr<Result> >
|
||||
{
|
||||
struct Cast_Helper_Inner<const std::shared_ptr<Result>> : Cast_Helper_Inner<std::shared_ptr<Result>> {
|
||||
};
|
||||
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<const std::shared_ptr<Result> &> : Cast_Helper_Inner<std::shared_ptr<Result> >
|
||||
{
|
||||
struct Cast_Helper_Inner<const std::shared_ptr<Result> &> : Cast_Helper_Inner<std::shared_ptr<Result>> {
|
||||
};
|
||||
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<std::shared_ptr<Result> &>
|
||||
{
|
||||
struct Cast_Helper_Inner<std::shared_ptr<Result> &> {
|
||||
static_assert(!std::is_const<Result>::value, "Non-const reference to std::shared_ptr<const T> is not supported");
|
||||
static auto cast(const Boxed_Value &ob, const Type_Conversions_State *)
|
||||
{
|
||||
std::shared_ptr<Result> &res = ob.get().cast<std::shared_ptr<Result> >();
|
||||
static auto cast(const Boxed_Value &ob, const Type_Conversions_State *) {
|
||||
std::shared_ptr<Result> &res = ob.get().cast<std::shared_ptr<Result>>();
|
||||
return ob.pointer_sentinel(res);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/// Cast_Helper_Inner for casting to a const std::shared_ptr<const> & type
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<const std::shared_ptr<const Result> > : Cast_Helper_Inner<std::shared_ptr<const Result> >
|
||||
{
|
||||
struct Cast_Helper_Inner<const std::shared_ptr<const Result>> : Cast_Helper_Inner<std::shared_ptr<const Result>> {
|
||||
};
|
||||
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<const std::shared_ptr<const Result> &> : Cast_Helper_Inner<std::shared_ptr<const Result> >
|
||||
{
|
||||
struct Cast_Helper_Inner<const std::shared_ptr<const Result> &> : Cast_Helper_Inner<std::shared_ptr<const Result>> {
|
||||
};
|
||||
|
||||
|
||||
/// Cast_Helper_Inner for casting to a Boxed_Value type
|
||||
template<>
|
||||
struct Cast_Helper_Inner<Boxed_Value>
|
||||
{
|
||||
static Boxed_Value cast(const Boxed_Value &ob, const Type_Conversions_State *)
|
||||
{
|
||||
return ob;
|
||||
}
|
||||
struct Cast_Helper_Inner<Boxed_Value> {
|
||||
static Boxed_Value cast(const Boxed_Value &ob, const Type_Conversions_State *) { return ob; }
|
||||
};
|
||||
|
||||
/// Cast_Helper_Inner for casting to a Boxed_Value & type
|
||||
template<>
|
||||
struct Cast_Helper_Inner<Boxed_Value &>
|
||||
{
|
||||
static std::reference_wrapper<Boxed_Value> cast(const Boxed_Value &ob, const Type_Conversions_State *)
|
||||
{
|
||||
struct Cast_Helper_Inner<Boxed_Value &> {
|
||||
static std::reference_wrapper<Boxed_Value> cast(const Boxed_Value &ob, const Type_Conversions_State *) {
|
||||
return std::ref(const_cast<Boxed_Value &>(ob));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/// Cast_Helper_Inner for casting to a const Boxed_Value & type
|
||||
template<>
|
||||
struct Cast_Helper_Inner<const Boxed_Value> : Cast_Helper_Inner<Boxed_Value>
|
||||
{
|
||||
struct Cast_Helper_Inner<const Boxed_Value> : Cast_Helper_Inner<Boxed_Value> {
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Cast_Helper_Inner<const Boxed_Value &> : Cast_Helper_Inner<Boxed_Value>
|
||||
{
|
||||
struct Cast_Helper_Inner<const Boxed_Value &> : Cast_Helper_Inner<Boxed_Value> {
|
||||
};
|
||||
|
||||
|
||||
/// Cast_Helper_Inner for casting to a std::reference_wrapper type
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<std::reference_wrapper<Result> > : Cast_Helper_Inner<Result &>
|
||||
{
|
||||
struct Cast_Helper_Inner<std::reference_wrapper<Result>> : Cast_Helper_Inner<Result &> {
|
||||
};
|
||||
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<const std::reference_wrapper<Result> > : Cast_Helper_Inner<Result &>
|
||||
{
|
||||
struct Cast_Helper_Inner<const std::reference_wrapper<Result>> : Cast_Helper_Inner<Result &> {
|
||||
};
|
||||
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<const std::reference_wrapper<Result> &> : Cast_Helper_Inner<Result &>
|
||||
{
|
||||
struct Cast_Helper_Inner<const std::reference_wrapper<Result> &> : Cast_Helper_Inner<Result &> {
|
||||
};
|
||||
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<std::reference_wrapper<const Result> > : Cast_Helper_Inner<const Result &>
|
||||
{
|
||||
struct Cast_Helper_Inner<std::reference_wrapper<const Result>> : Cast_Helper_Inner<const Result &> {
|
||||
};
|
||||
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<const std::reference_wrapper<const Result> > : Cast_Helper_Inner<const Result &>
|
||||
{
|
||||
struct Cast_Helper_Inner<const std::reference_wrapper<const Result>> : Cast_Helper_Inner<const Result &> {
|
||||
};
|
||||
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<const std::reference_wrapper<const Result> & > : Cast_Helper_Inner<const Result &>
|
||||
{
|
||||
struct Cast_Helper_Inner<const std::reference_wrapper<const Result> &> : Cast_Helper_Inner<const Result &> {
|
||||
};
|
||||
|
||||
/// The exposed Cast_Helper object that by default just calls the Cast_Helper_Inner
|
||||
template<typename T>
|
||||
struct Cast_Helper
|
||||
{
|
||||
static decltype(auto) cast(const Boxed_Value &ob, const Type_Conversions_State *t_conversions)
|
||||
{
|
||||
return(Cast_Helper_Inner<T>::cast(ob, t_conversions));
|
||||
struct Cast_Helper {
|
||||
static decltype(auto) cast(const Boxed_Value &ob, const Type_Conversions_State *t_conversions) {
|
||||
return (Cast_Helper_Inner<T>::cast(ob, t_conversions));
|
||||
}
|
||||
};
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
}
|
||||
} // namespace chaiscript
|
||||
|
||||
#endif
|
||||
|
||||
@ -22,25 +22,20 @@
|
||||
#include "type_info.hpp"
|
||||
|
||||
namespace chaiscript {
|
||||
class Type_Conversions;
|
||||
class Type_Conversions;
|
||||
} // namespace chaiscript
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
namespace exception
|
||||
{
|
||||
struct arithmetic_error : std::runtime_error
|
||||
{
|
||||
explicit arithmetic_error(const std::string& reason) : std::runtime_error("Arithmetic error: " + reason) {}
|
||||
namespace chaiscript::exception {
|
||||
struct arithmetic_error : std::runtime_error {
|
||||
explicit arithmetic_error(const std::string &reason)
|
||||
: std::runtime_error("Arithmetic error: " + reason) {
|
||||
}
|
||||
arithmetic_error(const arithmetic_error &) = default;
|
||||
~arithmetic_error() noexcept override = default;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
} // namespace chaiscript::exception
|
||||
|
||||
namespace chaiscript {
|
||||
// Due to the nature of generating every possible arithmetic operation, there
|
||||
// are going to be warnings generated on every platform regarding size and sign,
|
||||
// this is OK, so we're disabling size/and sign type warnings
|
||||
@ -49,7 +44,6 @@ namespace chaiscript
|
||||
#pragma warning(disable : 4244 4018 4389 4146 4365 4267 4242)
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wunknown-pragmas"
|
||||
@ -63,8 +57,7 @@ namespace chaiscript
|
||||
#endif
|
||||
|
||||
/// \brief Represents any numeric type, generically. Used internally for generic operations between POD values
|
||||
class Boxed_Number
|
||||
{
|
||||
class Boxed_Number {
|
||||
private:
|
||||
enum class Common_Types {
|
||||
t_int32,
|
||||
@ -81,8 +74,7 @@ namespace chaiscript
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
constexpr static inline void check_divide_by_zero([[maybe_unused]] T t)
|
||||
{
|
||||
constexpr static inline void check_divide_by_zero([[maybe_unused]] T t) {
|
||||
#ifndef CHAISCRIPT_NO_PROTECT_DIVIDEBYZERO
|
||||
if constexpr (!std::is_floating_point<T>::value) {
|
||||
if (t == 0) {
|
||||
@ -92,21 +84,18 @@ namespace chaiscript
|
||||
#endif
|
||||
}
|
||||
|
||||
constexpr static Common_Types get_common_type(size_t t_size, bool t_signed) noexcept
|
||||
{
|
||||
return (t_size == 1 && t_signed)?(Common_Types::t_int8)
|
||||
:(t_size == 1)?(Common_Types::t_uint8)
|
||||
:(t_size == 2 && t_signed)?(Common_Types::t_int16)
|
||||
:(t_size == 2)?(Common_Types::t_uint16)
|
||||
:(t_size == 4 && t_signed)?(Common_Types::t_int32)
|
||||
:(t_size == 4)?(Common_Types::t_uint32)
|
||||
:(t_size == 8 && t_signed)?(Common_Types::t_int64)
|
||||
:(Common_Types::t_uint64);
|
||||
constexpr static Common_Types get_common_type(size_t t_size, bool t_signed) noexcept {
|
||||
return (t_size == 1 && t_signed) ? (Common_Types::t_int8)
|
||||
: (t_size == 1) ? (Common_Types::t_uint8)
|
||||
: (t_size == 2 && t_signed) ? (Common_Types::t_int16)
|
||||
: (t_size == 2) ? (Common_Types::t_uint16)
|
||||
: (t_size == 4 && t_signed) ? (Common_Types::t_int32)
|
||||
: (t_size == 4) ? (Common_Types::t_uint32)
|
||||
: (t_size == 8 && t_signed) ? (Common_Types::t_int64)
|
||||
: (Common_Types::t_uint64);
|
||||
}
|
||||
|
||||
|
||||
static Common_Types get_common_type(const Boxed_Value &t_bv)
|
||||
{
|
||||
static Common_Types get_common_type(const Boxed_Value &t_bv) {
|
||||
const Type_Info &inp_ = t_bv.get_type_info();
|
||||
|
||||
if (inp_ == user_type<int>()) {
|
||||
@ -158,11 +147,8 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<typename LHS, typename RHS>
|
||||
static auto go(Operators::Opers t_oper, const Boxed_Value &t_bv, LHS *t_lhs, const LHS &c_lhs, const RHS &c_rhs)
|
||||
{
|
||||
static auto go(Operators::Opers t_oper, const Boxed_Value &t_bv, LHS *t_lhs, const LHS &c_lhs, const RHS &c_rhs) {
|
||||
switch (t_oper) {
|
||||
case Operators::Opers::equals:
|
||||
return const_var(c_lhs == c_rhs);
|
||||
@ -189,7 +175,6 @@ namespace chaiscript
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if constexpr (!std::is_floating_point<LHS>::value && !std::is_floating_point<RHS>::value) {
|
||||
switch (t_oper) {
|
||||
case Operators::Opers::shift_left:
|
||||
@ -263,8 +248,7 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
template<typename Callable>
|
||||
inline static auto visit(const Boxed_Value &bv, Callable &&callable)
|
||||
{
|
||||
inline static auto visit(const Boxed_Value &bv, Callable &&callable) {
|
||||
switch (get_common_type(bv)) {
|
||||
case Common_Types::t_int32:
|
||||
return callable(*static_cast<const std::int32_t *>(bv.get_const_ptr()));
|
||||
@ -292,9 +276,8 @@ namespace chaiscript
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
|
||||
inline static Boxed_Value oper(Operators::Opers t_oper, const Boxed_Value &t_lhs)
|
||||
{
|
||||
auto unary_operator = [t_oper, &t_lhs](const auto &c_lhs){
|
||||
inline static Boxed_Value oper(Operators::Opers t_oper, const Boxed_Value &t_lhs) {
|
||||
auto unary_operator = [t_oper, &t_lhs](const auto &c_lhs) {
|
||||
auto *lhs = static_cast<std::decay_t<decltype(c_lhs)> *>(t_lhs.get_ptr());
|
||||
|
||||
if (lhs) {
|
||||
@ -334,16 +317,11 @@ namespace chaiscript
|
||||
return visit(t_lhs, unary_operator);
|
||||
}
|
||||
|
||||
inline static Boxed_Value oper(Operators::Opers t_oper, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs) {
|
||||
auto lhs_visit = [t_oper, &t_lhs, &t_rhs](const auto &c_lhs) {
|
||||
auto *lhs = t_lhs.is_return_value() ? nullptr : static_cast<std::decay_t<decltype(c_lhs)> *>(t_lhs.get_ptr());
|
||||
|
||||
inline static Boxed_Value oper(Operators::Opers t_oper, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs)
|
||||
{
|
||||
|
||||
auto lhs_visit = [t_oper, &t_lhs, &t_rhs](const auto &c_lhs){
|
||||
auto *lhs = t_lhs.is_return_value()?nullptr:static_cast<std::decay_t<decltype(c_lhs)> *>(t_lhs.get_ptr());
|
||||
|
||||
auto rhs_visit = [t_oper, &t_lhs, lhs, &c_lhs](const auto &c_rhs) {
|
||||
return go(t_oper, t_lhs, lhs, c_lhs, c_rhs);
|
||||
};
|
||||
auto rhs_visit = [t_oper, &t_lhs, lhs, &c_lhs](const auto &c_rhs) { return go(t_oper, t_lhs, lhs, c_lhs, c_rhs); };
|
||||
|
||||
return visit(t_rhs, rhs_visit);
|
||||
};
|
||||
@ -352,14 +330,12 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
template<typename Target, typename Source>
|
||||
static inline Target get_as_aux(const Boxed_Value &t_bv)
|
||||
{
|
||||
static inline Target get_as_aux(const Boxed_Value &t_bv) {
|
||||
return static_cast<Target>(*static_cast<const Source *>(t_bv.get_const_ptr()));
|
||||
}
|
||||
|
||||
template<typename Source>
|
||||
static std::string to_string_aux(const Boxed_Value &v)
|
||||
{
|
||||
static std::string to_string_aux(const Boxed_Value &v) {
|
||||
std::ostringstream oss;
|
||||
oss << *static_cast<const Source *>(v.get_const_ptr());
|
||||
return oss.str();
|
||||
@ -367,32 +343,27 @@ namespace chaiscript
|
||||
|
||||
public:
|
||||
Boxed_Number()
|
||||
: bv(Boxed_Value(0))
|
||||
{
|
||||
: bv(Boxed_Value(0)) {
|
||||
}
|
||||
|
||||
explicit Boxed_Number(Boxed_Value v)
|
||||
: bv(std::move(v))
|
||||
{
|
||||
: bv(std::move(v)) {
|
||||
validate_boxed_number(bv);
|
||||
}
|
||||
|
||||
Boxed_Number(const Boxed_Number &) = default;
|
||||
Boxed_Number(Boxed_Number &&) = default;
|
||||
Boxed_Number& operator=(Boxed_Number &&) = default;
|
||||
Boxed_Number &operator=(Boxed_Number &&) = default;
|
||||
|
||||
template<typename T> explicit Boxed_Number(T t)
|
||||
: bv(Boxed_Value(t))
|
||||
{
|
||||
template<typename T>
|
||||
explicit Boxed_Number(T t)
|
||||
: bv(Boxed_Value(t)) {
|
||||
validate_boxed_number(bv);
|
||||
}
|
||||
|
||||
static Boxed_Value clone(const Boxed_Value &t_bv) {
|
||||
return Boxed_Number(t_bv).get_as(t_bv.get_type_info()).bv;
|
||||
}
|
||||
static Boxed_Value clone(const Boxed_Value &t_bv) { return Boxed_Number(t_bv).get_as(t_bv.get_type_info()).bv; }
|
||||
|
||||
static bool is_floating_point(const Boxed_Value &t_bv)
|
||||
{
|
||||
static bool is_floating_point(const Boxed_Value &t_bv) {
|
||||
const Type_Info &inp_ = t_bv.get_type_info();
|
||||
|
||||
if (inp_ == user_type<double>()) {
|
||||
@ -406,8 +377,7 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
Boxed_Number get_as(const Type_Info &inp_) const
|
||||
{
|
||||
Boxed_Number get_as(const Type_Info &inp_) const {
|
||||
if (inp_.bare_equal(user_type<int>())) {
|
||||
return Boxed_Number(get_as<int>());
|
||||
} else if (inp_.bare_equal(user_type<double>())) {
|
||||
@ -455,21 +425,17 @@ namespace chaiscript
|
||||
} else {
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template<typename Source, typename Target>
|
||||
static void check_type()
|
||||
{
|
||||
static void check_type() {
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
// MSVC complains about this being redundant / tautologica l
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4127 6287)
|
||||
#endif
|
||||
if (sizeof(Source) != sizeof(Target)
|
||||
|| std::is_signed<Source>() != std::is_signed<Target>()
|
||||
|| std::is_floating_point<Source>() != std::is_floating_point<Target>())
|
||||
{
|
||||
if (sizeof(Source) != sizeof(Target) || std::is_signed<Source>() != std::is_signed<Target>()
|
||||
|| std::is_floating_point<Source>() != std::is_floating_point<Target>()) {
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
@ -477,8 +443,8 @@ namespace chaiscript
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename Target> Target get_as_checked() const
|
||||
{
|
||||
template<typename Target>
|
||||
Target get_as_checked() const {
|
||||
switch (get_common_type(bv)) {
|
||||
case Common_Types::t_int32:
|
||||
check_type<int32_t, Target>();
|
||||
@ -518,9 +484,8 @@ namespace chaiscript
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
|
||||
|
||||
template<typename Target> Target get_as() const
|
||||
{
|
||||
template<typename Target>
|
||||
Target get_as() const {
|
||||
switch (get_common_type(bv)) {
|
||||
case Common_Types::t_int32:
|
||||
return get_as_aux<Target, int32_t>(bv);
|
||||
@ -549,8 +514,7 @@ namespace chaiscript
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
|
||||
std::string to_string() const
|
||||
{
|
||||
std::string to_string() const {
|
||||
switch (get_common_type(bv)) {
|
||||
case Common_Types::t_int32:
|
||||
return std::to_string(get_as<int32_t>());
|
||||
@ -579,222 +543,162 @@ namespace chaiscript
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
|
||||
static void validate_boxed_number(const Boxed_Value &v)
|
||||
{
|
||||
static void validate_boxed_number(const Boxed_Value &v) {
|
||||
const Type_Info &inp_ = v.get_type_info();
|
||||
if (inp_ == user_type<bool>())
|
||||
{
|
||||
if (inp_ == user_type<bool>()) {
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
|
||||
if (!inp_.is_arithmetic())
|
||||
{
|
||||
if (!inp_.is_arithmetic()) {
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static bool equals(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
static bool equals(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs) {
|
||||
return boxed_cast<bool>(oper(Operators::Opers::equals, t_lhs.bv, t_rhs.bv));
|
||||
}
|
||||
|
||||
static bool less_than(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
static bool less_than(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs) {
|
||||
return boxed_cast<bool>(oper(Operators::Opers::less_than, t_lhs.bv, t_rhs.bv));
|
||||
}
|
||||
|
||||
static bool greater_than(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
static bool greater_than(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs) {
|
||||
return boxed_cast<bool>(oper(Operators::Opers::greater_than, t_lhs.bv, t_rhs.bv));
|
||||
}
|
||||
|
||||
static bool greater_than_equal(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
static bool greater_than_equal(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs) {
|
||||
return boxed_cast<bool>(oper(Operators::Opers::greater_than_equal, t_lhs.bv, t_rhs.bv));
|
||||
}
|
||||
|
||||
static bool less_than_equal(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
static bool less_than_equal(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs) {
|
||||
return boxed_cast<bool>(oper(Operators::Opers::less_than_equal, t_lhs.bv, t_rhs.bv));
|
||||
}
|
||||
|
||||
static bool not_equal(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
static bool not_equal(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs) {
|
||||
return boxed_cast<bool>(oper(Operators::Opers::not_equal, t_lhs.bv, t_rhs.bv));
|
||||
}
|
||||
|
||||
static Boxed_Number pre_decrement(Boxed_Number t_lhs)
|
||||
{
|
||||
return Boxed_Number(oper(Operators::Opers::pre_decrement, t_lhs.bv));
|
||||
}
|
||||
static Boxed_Number pre_decrement(Boxed_Number t_lhs) { return Boxed_Number(oper(Operators::Opers::pre_decrement, t_lhs.bv)); }
|
||||
|
||||
static Boxed_Number pre_increment(Boxed_Number t_lhs)
|
||||
{
|
||||
return Boxed_Number(oper(Operators::Opers::pre_increment, t_lhs.bv));
|
||||
}
|
||||
static Boxed_Number pre_increment(Boxed_Number t_lhs) { return Boxed_Number(oper(Operators::Opers::pre_increment, t_lhs.bv)); }
|
||||
|
||||
static const Boxed_Number sum(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
static const Boxed_Number sum(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs) {
|
||||
return Boxed_Number(oper(Operators::Opers::sum, t_lhs.bv, t_rhs.bv));
|
||||
}
|
||||
|
||||
static const Boxed_Number unary_plus(const Boxed_Number &t_lhs)
|
||||
{
|
||||
return Boxed_Number(oper(Operators::Opers::unary_plus, t_lhs.bv));
|
||||
}
|
||||
static const Boxed_Number unary_plus(const Boxed_Number &t_lhs) { return Boxed_Number(oper(Operators::Opers::unary_plus, t_lhs.bv)); }
|
||||
|
||||
static const Boxed_Number unary_minus(const Boxed_Number &t_lhs)
|
||||
{
|
||||
return Boxed_Number(oper(Operators::Opers::unary_minus, t_lhs.bv));
|
||||
}
|
||||
static const Boxed_Number unary_minus(const Boxed_Number &t_lhs) { return Boxed_Number(oper(Operators::Opers::unary_minus, t_lhs.bv)); }
|
||||
|
||||
static const Boxed_Number difference(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
static const Boxed_Number difference(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs) {
|
||||
return Boxed_Number(oper(Operators::Opers::difference, t_lhs.bv, t_rhs.bv));
|
||||
}
|
||||
|
||||
static Boxed_Number assign_bitwise_and(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
static Boxed_Number assign_bitwise_and(Boxed_Number t_lhs, const Boxed_Number &t_rhs) {
|
||||
return Boxed_Number(oper(Operators::Opers::assign_bitwise_and, t_lhs.bv, t_rhs.bv));
|
||||
}
|
||||
|
||||
static Boxed_Number assign(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
static Boxed_Number assign(Boxed_Number t_lhs, const Boxed_Number &t_rhs) {
|
||||
return Boxed_Number(oper(Operators::Opers::assign, t_lhs.bv, t_rhs.bv));
|
||||
}
|
||||
|
||||
static Boxed_Number assign_bitwise_or(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
static Boxed_Number assign_bitwise_or(Boxed_Number t_lhs, const Boxed_Number &t_rhs) {
|
||||
return Boxed_Number(oper(Operators::Opers::assign_bitwise_or, t_lhs.bv, t_rhs.bv));
|
||||
}
|
||||
|
||||
static Boxed_Number assign_bitwise_xor(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
static Boxed_Number assign_bitwise_xor(Boxed_Number t_lhs, const Boxed_Number &t_rhs) {
|
||||
return Boxed_Number(oper(Operators::Opers::assign_bitwise_xor, t_lhs.bv, t_rhs.bv));
|
||||
}
|
||||
|
||||
static Boxed_Number assign_remainder(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
static Boxed_Number assign_remainder(Boxed_Number t_lhs, const Boxed_Number &t_rhs) {
|
||||
return Boxed_Number(oper(Operators::Opers::assign_remainder, t_lhs.bv, t_rhs.bv));
|
||||
}
|
||||
|
||||
static Boxed_Number assign_shift_left(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
static Boxed_Number assign_shift_left(Boxed_Number t_lhs, const Boxed_Number &t_rhs) {
|
||||
return Boxed_Number(oper(Operators::Opers::assign_shift_left, t_lhs.bv, t_rhs.bv));
|
||||
}
|
||||
|
||||
static Boxed_Number assign_shift_right(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
static Boxed_Number assign_shift_right(Boxed_Number t_lhs, const Boxed_Number &t_rhs) {
|
||||
return Boxed_Number(oper(Operators::Opers::assign_shift_right, t_lhs.bv, t_rhs.bv));
|
||||
}
|
||||
|
||||
static const Boxed_Number bitwise_and(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
static const Boxed_Number bitwise_and(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs) {
|
||||
return Boxed_Number(oper(Operators::Opers::bitwise_and, t_lhs.bv, t_rhs.bv));
|
||||
}
|
||||
|
||||
static const Boxed_Number bitwise_complement(const Boxed_Number &t_lhs)
|
||||
{
|
||||
static const Boxed_Number bitwise_complement(const Boxed_Number &t_lhs) {
|
||||
return Boxed_Number(oper(Operators::Opers::bitwise_complement, t_lhs.bv, Boxed_Value(0)));
|
||||
}
|
||||
|
||||
static const Boxed_Number bitwise_xor(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
static const Boxed_Number bitwise_xor(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs) {
|
||||
return Boxed_Number(oper(Operators::Opers::bitwise_xor, t_lhs.bv, t_rhs.bv));
|
||||
}
|
||||
|
||||
static const Boxed_Number bitwise_or(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
static const Boxed_Number bitwise_or(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs) {
|
||||
return Boxed_Number(oper(Operators::Opers::bitwise_or, t_lhs.bv, t_rhs.bv));
|
||||
}
|
||||
|
||||
static Boxed_Number assign_product(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
static Boxed_Number assign_product(Boxed_Number t_lhs, const Boxed_Number &t_rhs) {
|
||||
return Boxed_Number(oper(Operators::Opers::assign_product, t_lhs.bv, t_rhs.bv));
|
||||
}
|
||||
|
||||
static Boxed_Number assign_quotient(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
static Boxed_Number assign_quotient(Boxed_Number t_lhs, const Boxed_Number &t_rhs) {
|
||||
return Boxed_Number(oper(Operators::Opers::assign_quotient, t_lhs.bv, t_rhs.bv));
|
||||
}
|
||||
|
||||
static Boxed_Number assign_sum(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
static Boxed_Number assign_sum(Boxed_Number t_lhs, const Boxed_Number &t_rhs) {
|
||||
return Boxed_Number(oper(Operators::Opers::assign_sum, t_lhs.bv, t_rhs.bv));
|
||||
}
|
||||
static Boxed_Number assign_difference(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
static Boxed_Number assign_difference(Boxed_Number t_lhs, const Boxed_Number &t_rhs) {
|
||||
return Boxed_Number(oper(Operators::Opers::assign_difference, t_lhs.bv, t_rhs.bv));
|
||||
}
|
||||
|
||||
static const Boxed_Number quotient(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
static const Boxed_Number quotient(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs) {
|
||||
return Boxed_Number(oper(Operators::Opers::quotient, t_lhs.bv, t_rhs.bv));
|
||||
}
|
||||
|
||||
static const Boxed_Number shift_left(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
static const Boxed_Number shift_left(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs) {
|
||||
return Boxed_Number(oper(Operators::Opers::shift_left, t_lhs.bv, t_rhs.bv));
|
||||
}
|
||||
|
||||
static const Boxed_Number product(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
static const Boxed_Number product(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs) {
|
||||
return Boxed_Number(oper(Operators::Opers::product, t_lhs.bv, t_rhs.bv));
|
||||
}
|
||||
|
||||
static const Boxed_Number remainder(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
static const Boxed_Number remainder(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs) {
|
||||
return Boxed_Number(oper(Operators::Opers::remainder, t_lhs.bv, t_rhs.bv));
|
||||
}
|
||||
|
||||
static const Boxed_Number shift_right(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
static const Boxed_Number shift_right(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs) {
|
||||
return Boxed_Number(oper(Operators::Opers::shift_right, t_lhs.bv, t_rhs.bv));
|
||||
}
|
||||
|
||||
|
||||
|
||||
static Boxed_Value do_oper(Operators::Opers t_oper, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs)
|
||||
{
|
||||
static Boxed_Value do_oper(Operators::Opers t_oper, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs) {
|
||||
return oper(t_oper, t_lhs, t_rhs);
|
||||
}
|
||||
|
||||
static Boxed_Value do_oper(Operators::Opers t_oper, const Boxed_Value &t_lhs)
|
||||
{
|
||||
return oper(t_oper, t_lhs);
|
||||
}
|
||||
|
||||
|
||||
static Boxed_Value do_oper(Operators::Opers t_oper, const Boxed_Value &t_lhs) { return oper(t_oper, t_lhs); }
|
||||
|
||||
Boxed_Value bv;
|
||||
};
|
||||
|
||||
namespace detail
|
||||
{
|
||||
namespace detail {
|
||||
/// Cast_Helper for converting from Boxed_Value to Boxed_Number
|
||||
template<>
|
||||
struct Cast_Helper<Boxed_Number>
|
||||
{
|
||||
static Boxed_Number cast(const Boxed_Value &ob, const Type_Conversions_State *)
|
||||
{
|
||||
return Boxed_Number(ob);
|
||||
}
|
||||
struct Cast_Helper<Boxed_Number> {
|
||||
static Boxed_Number cast(const Boxed_Value &ob, const Type_Conversions_State *) { return Boxed_Number(ob); }
|
||||
};
|
||||
|
||||
/// Cast_Helper for converting from Boxed_Value to Boxed_Number
|
||||
template<>
|
||||
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
|
||||
template<>
|
||||
struct Cast_Helper<const Boxed_Number> : Cast_Helper<Boxed_Number>
|
||||
{
|
||||
struct Cast_Helper<const Boxed_Number> : Cast_Helper<Boxed_Number> {
|
||||
};
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
@ -804,9 +708,6 @@ namespace chaiscript
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
} // namespace chaiscript
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@ -7,7 +7,6 @@
|
||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||
|
||||
|
||||
#ifndef CHAISCRIPT_BOXED_VALUE_HPP_
|
||||
#define CHAISCRIPT_BOXED_VALUE_HPP_
|
||||
|
||||
@ -19,36 +18,29 @@
|
||||
#include "any.hpp"
|
||||
#include "type_info.hpp"
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
|
||||
namespace chaiscript {
|
||||
/// \brief A wrapper for holding any valid C++ type. All types in ChaiScript are Boxed_Value objects
|
||||
/// \sa chaiscript::boxed_cast
|
||||
class Boxed_Value
|
||||
{
|
||||
class Boxed_Value {
|
||||
public:
|
||||
/// used for explicitly creating a "void" object
|
||||
struct Void_Type
|
||||
{
|
||||
struct Void_Type {
|
||||
};
|
||||
|
||||
private:
|
||||
/// structure which holds the internal state of a Boxed_Value
|
||||
/// \todo Get rid of Any and merge it with this, reducing an allocation in the process
|
||||
struct Data
|
||||
{
|
||||
Data(const Type_Info &ti,
|
||||
chaiscript::detail::Any to,
|
||||
bool is_ref,
|
||||
const void *t_void_ptr,
|
||||
bool t_return_value)
|
||||
: m_type_info(ti), m_obj(std::move(to)), m_data_ptr(ti.is_const()?nullptr:const_cast<void *>(t_void_ptr)), m_const_data_ptr(t_void_ptr),
|
||||
m_is_ref(is_ref), m_return_value(t_return_value)
|
||||
{
|
||||
struct Data {
|
||||
Data(const Type_Info &ti, chaiscript::detail::Any to, bool is_ref, const void *t_void_ptr, bool t_return_value)
|
||||
: m_type_info(ti)
|
||||
, m_obj(std::move(to))
|
||||
, m_data_ptr(ti.is_const() ? nullptr : const_cast<void *>(t_void_ptr))
|
||||
, m_const_data_ptr(t_void_ptr)
|
||||
, m_is_ref(is_ref)
|
||||
, m_return_value(t_return_value) {
|
||||
}
|
||||
|
||||
Data &operator=(const Data &rhs)
|
||||
{
|
||||
Data &operator=(const Data &rhs) {
|
||||
m_type_info = rhs.m_type_info;
|
||||
m_obj = rhs.m_obj;
|
||||
m_is_ref = rhs.m_is_ref;
|
||||
@ -56,8 +48,7 @@ namespace chaiscript
|
||||
m_const_data_ptr = rhs.m_const_data_ptr;
|
||||
m_return_value = rhs.m_return_value;
|
||||
|
||||
if (rhs.m_attrs)
|
||||
{
|
||||
if (rhs.m_attrs) {
|
||||
m_attrs = std::make_unique<std::map<std::string, std::shared_ptr<Data>>>(*rhs.m_attrs);
|
||||
}
|
||||
|
||||
@ -69,7 +60,6 @@ namespace chaiscript
|
||||
Data(Data &&) = default;
|
||||
Data &operator=(Data &&rhs) = default;
|
||||
|
||||
|
||||
Type_Info m_type_info;
|
||||
chaiscript::detail::Any m_obj;
|
||||
void *m_data_ptr;
|
||||
@ -79,197 +69,118 @@ namespace chaiscript
|
||||
bool m_return_value;
|
||||
};
|
||||
|
||||
struct Object_Data
|
||||
{
|
||||
static auto get(Boxed_Value::Void_Type, bool t_return_value)
|
||||
{
|
||||
return std::make_shared<Data>(
|
||||
detail::Get_Type_Info<void>::get(),
|
||||
chaiscript::detail::Any(),
|
||||
false,
|
||||
nullptr,
|
||||
t_return_value)
|
||||
;
|
||||
struct Object_Data {
|
||||
static auto get(Boxed_Value::Void_Type, bool t_return_value) {
|
||||
return std::make_shared<Data>(detail::Get_Type_Info<void>::get(), chaiscript::detail::Any(), false, nullptr, t_return_value);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static auto get(const std::shared_ptr<T> *obj, bool t_return_value)
|
||||
{
|
||||
static auto get(const std::shared_ptr<T> *obj, bool t_return_value) {
|
||||
return get(*obj, t_return_value);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static auto get(const std::shared_ptr<T> &obj, bool t_return_value)
|
||||
{
|
||||
return std::make_shared<Data>(
|
||||
detail::Get_Type_Info<T>::get(),
|
||||
chaiscript::detail::Any(obj),
|
||||
false,
|
||||
obj.get(),
|
||||
t_return_value
|
||||
);
|
||||
static auto get(const std::shared_ptr<T> &obj, bool t_return_value) {
|
||||
return std::make_shared<Data>(detail::Get_Type_Info<T>::get(), chaiscript::detail::Any(obj), false, obj.get(), t_return_value);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static auto get(std::shared_ptr<T> &&obj, bool t_return_value)
|
||||
{
|
||||
static auto get(std::shared_ptr<T> &&obj, bool t_return_value) {
|
||||
auto ptr = obj.get();
|
||||
return std::make_shared<Data>(
|
||||
detail::Get_Type_Info<T>::get(),
|
||||
chaiscript::detail::Any(std::move(obj)),
|
||||
false,
|
||||
ptr,
|
||||
t_return_value
|
||||
);
|
||||
return std::make_shared<Data>(detail::Get_Type_Info<T>::get(), chaiscript::detail::Any(std::move(obj)), false, ptr, t_return_value);
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<typename T>
|
||||
static auto get(T *t, bool t_return_value)
|
||||
{
|
||||
static auto get(T *t, bool t_return_value) {
|
||||
return get(std::ref(*t), t_return_value);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static auto get(const T *t, bool t_return_value)
|
||||
{
|
||||
static auto get(const T *t, bool t_return_value) {
|
||||
return get(std::cref(*t), t_return_value);
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
static auto get(std::reference_wrapper<T> obj, bool t_return_value)
|
||||
{
|
||||
static auto get(std::reference_wrapper<T> obj, bool t_return_value) {
|
||||
auto p = &obj.get();
|
||||
return std::make_shared<Data>(
|
||||
detail::Get_Type_Info<T>::get(),
|
||||
chaiscript::detail::Any(std::move(obj)),
|
||||
true,
|
||||
p,
|
||||
t_return_value
|
||||
);
|
||||
return std::make_shared<Data>(detail::Get_Type_Info<T>::get(), chaiscript::detail::Any(std::move(obj)), true, p, t_return_value);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static auto get(std::unique_ptr<T> &&obj, bool t_return_value)
|
||||
{
|
||||
static auto get(std::unique_ptr<T> &&obj, bool t_return_value) {
|
||||
auto ptr = obj.get();
|
||||
return std::make_shared<Data>(
|
||||
detail::Get_Type_Info<T>::get(),
|
||||
return std::make_shared<Data>(detail::Get_Type_Info<T>::get(),
|
||||
chaiscript::detail::Any(std::make_shared<std::unique_ptr<T>>(std::move(obj))),
|
||||
true,
|
||||
ptr,
|
||||
t_return_value
|
||||
);
|
||||
t_return_value);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static auto get(T t, bool t_return_value)
|
||||
{
|
||||
static auto get(T t, bool t_return_value) {
|
||||
auto p = std::make_shared<T>(std::move(t));
|
||||
auto ptr = p.get();
|
||||
return std::make_shared<Data>(
|
||||
detail::Get_Type_Info<T>::get(),
|
||||
chaiscript::detail::Any(std::move(p)),
|
||||
false,
|
||||
ptr,
|
||||
t_return_value
|
||||
);
|
||||
}
|
||||
|
||||
static std::shared_ptr<Data> get()
|
||||
{
|
||||
return std::make_shared<Data>(
|
||||
Type_Info(),
|
||||
chaiscript::detail::Any(),
|
||||
false,
|
||||
nullptr,
|
||||
false
|
||||
);
|
||||
return std::make_shared<Data>(detail::Get_Type_Info<T>::get(), chaiscript::detail::Any(std::move(p)), false, ptr, t_return_value);
|
||||
}
|
||||
|
||||
static std::shared_ptr<Data> get() { return std::make_shared<Data>(Type_Info(), chaiscript::detail::Any(), false, nullptr, false); }
|
||||
};
|
||||
|
||||
public:
|
||||
/// Basic Boxed_Value constructor
|
||||
template<typename T,
|
||||
typename = std::enable_if_t<!std::is_same_v<Boxed_Value, std::decay_t<T>>>>
|
||||
template<typename T, typename = std::enable_if_t<!std::is_same_v<Boxed_Value, std::decay_t<T>>>>
|
||||
explicit Boxed_Value(T &&t, bool t_return_value = false)
|
||||
: m_data(Object_Data::get(std::forward<T>(t), t_return_value))
|
||||
{
|
||||
: m_data(Object_Data::get(std::forward<T>(t), t_return_value)) {
|
||||
}
|
||||
|
||||
/// Unknown-type constructor
|
||||
Boxed_Value() = default;
|
||||
|
||||
Boxed_Value(Boxed_Value&&) = default;
|
||||
Boxed_Value& operator=(Boxed_Value&&) = default;
|
||||
Boxed_Value(const Boxed_Value&) = default;
|
||||
Boxed_Value& operator=(const Boxed_Value&) = default;
|
||||
Boxed_Value(Boxed_Value &&) = default;
|
||||
Boxed_Value &operator=(Boxed_Value &&) = default;
|
||||
Boxed_Value(const Boxed_Value &) = default;
|
||||
Boxed_Value &operator=(const Boxed_Value &) = default;
|
||||
|
||||
void swap(Boxed_Value &rhs) noexcept
|
||||
{
|
||||
std::swap(m_data, rhs.m_data);
|
||||
}
|
||||
void swap(Boxed_Value &rhs) noexcept { std::swap(m_data, rhs.m_data); }
|
||||
|
||||
/// Copy the values stored in rhs.m_data to m_data.
|
||||
/// m_data pointers are not shared in this case
|
||||
Boxed_Value assign(const Boxed_Value &rhs) noexcept
|
||||
{
|
||||
Boxed_Value assign(const Boxed_Value &rhs) noexcept {
|
||||
(*m_data) = (*rhs.m_data);
|
||||
return *this;
|
||||
}
|
||||
|
||||
const Type_Info &get_type_info() const noexcept
|
||||
{
|
||||
return m_data->m_type_info;
|
||||
}
|
||||
const Type_Info &get_type_info() const noexcept { return m_data->m_type_info; }
|
||||
|
||||
/// return true if the object is uninitialized
|
||||
bool is_undef() const noexcept
|
||||
{
|
||||
return m_data->m_type_info.is_undef();
|
||||
}
|
||||
bool is_undef() const noexcept { return m_data->m_type_info.is_undef(); }
|
||||
|
||||
bool is_const() const noexcept
|
||||
{
|
||||
return m_data->m_type_info.is_const();
|
||||
}
|
||||
|
||||
bool is_type(const Type_Info &ti) const noexcept
|
||||
{
|
||||
return m_data->m_type_info.bare_equal(ti);
|
||||
}
|
||||
bool is_const() const noexcept { return m_data->m_type_info.is_const(); }
|
||||
|
||||
bool is_type(const Type_Info &ti) const noexcept { return m_data->m_type_info.bare_equal(ti); }
|
||||
|
||||
template<typename T>
|
||||
auto pointer_sentinel(std::shared_ptr<T> &ptr) const noexcept
|
||||
{
|
||||
auto pointer_sentinel(std::shared_ptr<T> &ptr) const noexcept {
|
||||
struct Sentinel {
|
||||
Sentinel(std::shared_ptr<T> &t_ptr, Data &data)
|
||||
: m_ptr(t_ptr), m_data(data)
|
||||
{
|
||||
: m_ptr(t_ptr)
|
||||
, m_data(data) {
|
||||
}
|
||||
|
||||
~Sentinel()
|
||||
{
|
||||
~Sentinel() {
|
||||
// save new pointer data
|
||||
const auto ptr_ = m_ptr.get().get();
|
||||
m_data.get().m_data_ptr = ptr_;
|
||||
m_data.get().m_const_data_ptr = ptr_;
|
||||
}
|
||||
|
||||
Sentinel& operator=(Sentinel&&s) = default;
|
||||
Sentinel &operator=(Sentinel &&s) = default;
|
||||
Sentinel(Sentinel &&s) = default;
|
||||
|
||||
operator std::shared_ptr<T>&() const noexcept
|
||||
{
|
||||
return m_ptr.get();
|
||||
}
|
||||
operator std::shared_ptr<T> &() const noexcept { return m_ptr.get(); }
|
||||
|
||||
Sentinel &operator=(const Sentinel &) = delete;
|
||||
Sentinel(Sentinel&) = delete;
|
||||
Sentinel(Sentinel &) = delete;
|
||||
|
||||
std::reference_wrapper<std::shared_ptr<T>> m_ptr;
|
||||
std::reference_wrapper<Data> m_data;
|
||||
@ -278,50 +189,24 @@ namespace chaiscript
|
||||
return Sentinel(ptr, *(m_data.get()));
|
||||
}
|
||||
|
||||
bool is_null() const noexcept
|
||||
{
|
||||
return (m_data->m_data_ptr == nullptr && m_data->m_const_data_ptr == nullptr);
|
||||
}
|
||||
bool is_null() const noexcept { return (m_data->m_data_ptr == nullptr && m_data->m_const_data_ptr == nullptr); }
|
||||
|
||||
const chaiscript::detail::Any & get() const noexcept
|
||||
{
|
||||
return m_data->m_obj;
|
||||
}
|
||||
const chaiscript::detail::Any &get() const noexcept { return m_data->m_obj; }
|
||||
|
||||
bool is_ref() const noexcept
|
||||
{
|
||||
return m_data->m_is_ref;
|
||||
}
|
||||
bool is_ref() const noexcept { return m_data->m_is_ref; }
|
||||
|
||||
bool is_return_value() const noexcept
|
||||
{
|
||||
return m_data->m_return_value;
|
||||
}
|
||||
bool is_return_value() const noexcept { return m_data->m_return_value; }
|
||||
|
||||
void reset_return_value() const noexcept
|
||||
{
|
||||
m_data->m_return_value = false;
|
||||
}
|
||||
void reset_return_value() const noexcept { m_data->m_return_value = false; }
|
||||
|
||||
bool is_pointer() const noexcept
|
||||
{
|
||||
return !is_ref();
|
||||
}
|
||||
bool is_pointer() const noexcept { return !is_ref(); }
|
||||
|
||||
void *get_ptr() const noexcept
|
||||
{
|
||||
return m_data->m_data_ptr;
|
||||
}
|
||||
void *get_ptr() const noexcept { return m_data->m_data_ptr; }
|
||||
|
||||
const void *get_const_ptr() const noexcept
|
||||
{
|
||||
return m_data->m_const_data_ptr;
|
||||
}
|
||||
const void *get_const_ptr() const noexcept { return m_data->m_const_data_ptr; }
|
||||
|
||||
Boxed_Value get_attr(const std::string &t_name)
|
||||
{
|
||||
if (!m_data->m_attrs)
|
||||
{
|
||||
Boxed_Value get_attr(const std::string &t_name) {
|
||||
if (!m_data->m_attrs) {
|
||||
m_data->m_attrs = std::make_unique<std::map<std::string, std::shared_ptr<Data>>>();
|
||||
}
|
||||
|
||||
@ -329,38 +214,32 @@ namespace chaiscript
|
||||
if (attr) {
|
||||
return Boxed_Value(attr, Internal_Construction());
|
||||
} else {
|
||||
Boxed_Value bv; //default construct a new one
|
||||
Boxed_Value bv; // default construct a new one
|
||||
attr = bv.m_data;
|
||||
return bv;
|
||||
}
|
||||
}
|
||||
|
||||
Boxed_Value ©_attrs(const Boxed_Value &t_obj)
|
||||
{
|
||||
if (t_obj.m_data->m_attrs)
|
||||
{
|
||||
Boxed_Value ©_attrs(const Boxed_Value &t_obj) {
|
||||
if (t_obj.m_data->m_attrs) {
|
||||
m_data->m_attrs = std::make_unique<std::map<std::string, std::shared_ptr<Data>>>(*t_obj.m_data->m_attrs);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
Boxed_Value &clone_attrs(const Boxed_Value &t_obj)
|
||||
{
|
||||
Boxed_Value &clone_attrs(const Boxed_Value &t_obj) {
|
||||
copy_attrs(t_obj);
|
||||
reset_return_value();
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
/// \returns true if the two Boxed_Values share the same internal type
|
||||
static bool type_match(const Boxed_Value &l, const Boxed_Value &r) noexcept
|
||||
{
|
||||
return l.get_type_info() == r.get_type_info();
|
||||
}
|
||||
static bool type_match(const Boxed_Value &l, const Boxed_Value &r) noexcept { return l.get_type_info() == r.get_type_info(); }
|
||||
|
||||
private:
|
||||
// necessary to avoid hitting the templated && constructor of Boxed_Value
|
||||
struct Internal_Construction{};
|
||||
struct Internal_Construction {
|
||||
};
|
||||
|
||||
Boxed_Value(std::shared_ptr<Data> t_data, Internal_Construction)
|
||||
: m_data(std::move(t_data)) {
|
||||
@ -369,7 +248,8 @@ namespace chaiscript
|
||||
std::shared_ptr<Data> m_data = Object_Data::get();
|
||||
};
|
||||
|
||||
/// @brief Creates a Boxed_Value. If the object passed in is a value type, it is copied. If it is a pointer, std::shared_ptr, or std::reference_type
|
||||
/// @brief Creates a Boxed_Value. If the object passed in is a value type, it is copied. If it is a pointer, std::shared_ptr, or
|
||||
/// std::reference_type
|
||||
/// a copy is not made.
|
||||
/// @param t The value to box
|
||||
///
|
||||
@ -384,8 +264,7 @@ namespace chaiscript
|
||||
///
|
||||
/// @sa @ref adding_objects
|
||||
template<typename T>
|
||||
Boxed_Value var(T &&t)
|
||||
{
|
||||
Boxed_Value var(T &&t) {
|
||||
return Boxed_Value(std::forward<T>(t));
|
||||
}
|
||||
|
||||
@ -395,9 +274,8 @@ namespace chaiscript
|
||||
/// \returns Immutable Boxed_Value
|
||||
/// \sa Boxed_Value::is_const
|
||||
template<typename T>
|
||||
Boxed_Value const_var_impl(const T &t)
|
||||
{
|
||||
return Boxed_Value(std::make_shared<typename std::add_const<T>::type >(t));
|
||||
Boxed_Value const_var_impl(const T &t) {
|
||||
return Boxed_Value(std::make_shared<typename std::add_const<T>::type>(t));
|
||||
}
|
||||
|
||||
/// \brief Takes a pointer to a value, adds const to the pointed to type and returns an immutable Boxed_Value.
|
||||
@ -406,9 +284,8 @@ namespace chaiscript
|
||||
/// \returns Immutable Boxed_Value
|
||||
/// \sa Boxed_Value::is_const
|
||||
template<typename T>
|
||||
Boxed_Value const_var_impl(T *t)
|
||||
{
|
||||
return Boxed_Value( const_cast<typename std::add_const<T>::type *>(t) );
|
||||
Boxed_Value const_var_impl(T *t) {
|
||||
return Boxed_Value(const_cast<typename std::add_const<T>::type *>(t));
|
||||
}
|
||||
|
||||
/// \brief Takes a std::shared_ptr to a value, adds const to the pointed to type and returns an immutable Boxed_Value.
|
||||
@ -417,9 +294,8 @@ namespace chaiscript
|
||||
/// \returns Immutable Boxed_Value
|
||||
/// \sa Boxed_Value::is_const
|
||||
template<typename T>
|
||||
Boxed_Value const_var_impl(const std::shared_ptr<T> &t)
|
||||
{
|
||||
return Boxed_Value( std::const_pointer_cast<typename std::add_const<T>::type>(t) );
|
||||
Boxed_Value const_var_impl(const std::shared_ptr<T> &t) {
|
||||
return Boxed_Value(std::const_pointer_cast<typename std::add_const<T>::type>(t));
|
||||
}
|
||||
|
||||
/// \brief Takes a std::reference_wrapper value, adds const to the referenced type and returns an immutable Boxed_Value.
|
||||
@ -428,11 +304,10 @@ namespace chaiscript
|
||||
/// \returns Immutable Boxed_Value
|
||||
/// \sa Boxed_Value::is_const
|
||||
template<typename T>
|
||||
Boxed_Value const_var_impl(const std::reference_wrapper<T> &t)
|
||||
{
|
||||
return Boxed_Value( std::cref(t.get()) );
|
||||
}
|
||||
Boxed_Value const_var_impl(const std::reference_wrapper<T> &t) {
|
||||
return Boxed_Value(std::cref(t.get()));
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
/// \brief Takes an object and returns an immutable Boxed_Value. If the object is a std::reference or pointer type
|
||||
/// the value is not copied. If it is an object type, it is copied.
|
||||
@ -458,8 +333,7 @@ namespace chaiscript
|
||||
/// \todo support C++11 strongly typed enums
|
||||
/// \sa \ref adding_objects
|
||||
template<typename T>
|
||||
Boxed_Value const_var(const T &t)
|
||||
{
|
||||
Boxed_Value const_var(const T &t) {
|
||||
return detail::const_var_impl(t);
|
||||
}
|
||||
|
||||
@ -479,7 +353,6 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace chaiscript
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@ -12,49 +12,50 @@
|
||||
namespace chaiscript {
|
||||
namespace dispatch {
|
||||
namespace detail {
|
||||
|
||||
template<typename Class, typename ... Param>
|
||||
struct Constructor
|
||||
{
|
||||
template<typename ... Inner>
|
||||
std::shared_ptr<Class> operator()(Inner&& ... inner) const {
|
||||
template<typename Class, typename... Param>
|
||||
struct Constructor {
|
||||
template<typename... Inner>
|
||||
std::shared_ptr<Class> operator()(Inner &&...inner) const {
|
||||
return std::make_shared<Class>(std::forward<Inner>(inner)...);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Ret, typename Class, typename ... Param>
|
||||
struct Const_Caller
|
||||
{
|
||||
explicit Const_Caller(Ret (Class::*t_func)(Param...) const) : m_func(t_func) {}
|
||||
template<typename Ret, typename Class, typename... Param>
|
||||
struct Const_Caller {
|
||||
explicit Const_Caller(Ret (Class::*t_func)(Param...) const)
|
||||
: m_func(t_func) {
|
||||
}
|
||||
|
||||
template<typename ... Inner>
|
||||
Ret operator()(const Class &o, Inner&& ... inner) const {
|
||||
template<typename... Inner>
|
||||
Ret operator()(const Class &o, Inner &&...inner) const {
|
||||
return (o.*m_func)(std::forward<Inner>(inner)...);
|
||||
}
|
||||
|
||||
Ret (Class::*m_func)(Param...) const;
|
||||
};
|
||||
|
||||
template<typename Ret, typename ... Param>
|
||||
struct Fun_Caller
|
||||
{
|
||||
explicit Fun_Caller(Ret( * t_func)(Param...) ) : m_func(t_func) {}
|
||||
template<typename Ret, typename... Param>
|
||||
struct Fun_Caller {
|
||||
explicit Fun_Caller(Ret (*t_func)(Param...))
|
||||
: m_func(t_func) {
|
||||
}
|
||||
|
||||
template<typename ... Inner>
|
||||
Ret operator()(Inner&& ... inner) const {
|
||||
template<typename... Inner>
|
||||
Ret operator()(Inner &&...inner) const {
|
||||
return (m_func)(std::forward<Inner>(inner)...);
|
||||
}
|
||||
|
||||
Ret(*m_func)(Param...);
|
||||
Ret (*m_func)(Param...);
|
||||
};
|
||||
|
||||
template<typename Ret, typename Class, typename ... Param>
|
||||
struct Caller
|
||||
{
|
||||
explicit Caller(Ret (Class::*t_func)(Param...)) : m_func(t_func) {}
|
||||
template<typename Ret, typename Class, typename... Param>
|
||||
struct Caller {
|
||||
explicit Caller(Ret (Class::*t_func)(Param...))
|
||||
: m_func(t_func) {
|
||||
}
|
||||
|
||||
template<typename ... Inner>
|
||||
Ret operator()(Class &o, Inner&& ... inner) const {
|
||||
template<typename... Inner>
|
||||
Ret operator()(Class &o, Inner &&...inner) const {
|
||||
return (o.*m_func)(std::forward<Inner>(inner)...);
|
||||
}
|
||||
|
||||
@ -62,46 +63,37 @@ namespace chaiscript {
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct Arity
|
||||
{
|
||||
struct Arity {
|
||||
};
|
||||
|
||||
template<typename Ret, typename ... Params>
|
||||
struct Arity<Ret (Params...)>
|
||||
{
|
||||
template<typename Ret, typename... Params>
|
||||
struct Arity<Ret(Params...)> {
|
||||
static const size_t arity = sizeof...(Params);
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct Function_Signature {
|
||||
};
|
||||
|
||||
template<typename Ret, typename... Params>
|
||||
struct Function_Signature<Ret(Params...)> {
|
||||
using Return_Type = Ret;
|
||||
using Signature = Ret()(Params...);
|
||||
};
|
||||
|
||||
template<typename Ret, typename T, typename... Params>
|
||||
struct Function_Signature<Ret (T::*)(Params...) const> {
|
||||
using Return_Type = Ret;
|
||||
using Signature = Ret()(Params...);
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct Function_Signature
|
||||
{
|
||||
};
|
||||
|
||||
template<typename Ret, typename ... Params>
|
||||
struct Function_Signature<Ret (Params...)>
|
||||
{
|
||||
using Return_Type = Ret;
|
||||
using Signature = Ret ()(Params...);
|
||||
};
|
||||
|
||||
template<typename Ret, typename T, typename ... Params>
|
||||
struct Function_Signature<Ret (T::*)(Params...) const>
|
||||
{
|
||||
using Return_Type = Ret;
|
||||
using Signature = Ret ()(Params...);
|
||||
};
|
||||
|
||||
|
||||
template<typename T>
|
||||
struct Callable_Traits
|
||||
{
|
||||
struct Callable_Traits {
|
||||
using Signature = typename Function_Signature<decltype(&T::operator())>::Signature;
|
||||
using Return_Type = typename Function_Signature<decltype(&T::operator())>::Return_Type;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace detail
|
||||
} // namespace dispatch
|
||||
} // namespace chaiscript
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -7,7 +7,6 @@
|
||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||
|
||||
|
||||
#ifndef CHAISCRIPT_DYNAMIC_OBJECT_HPP_
|
||||
#define CHAISCRIPT_DYNAMIC_OBJECT_HPP_
|
||||
|
||||
@ -18,21 +17,17 @@
|
||||
#include "boxed_value.hpp"
|
||||
|
||||
namespace chaiscript {
|
||||
class Type_Conversions;
|
||||
namespace dispatch {
|
||||
class Proxy_Function_Base;
|
||||
} // namespace dispatch
|
||||
class Type_Conversions;
|
||||
namespace dispatch {
|
||||
class Proxy_Function_Base;
|
||||
} // namespace dispatch
|
||||
} // namespace chaiscript
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
namespace dispatch
|
||||
{
|
||||
namespace chaiscript {
|
||||
namespace dispatch {
|
||||
struct option_explicit_set : std::runtime_error {
|
||||
explicit option_explicit_set(const std::string &t_param_name)
|
||||
: std::runtime_error("option explicit set and parameter '" + t_param_name + "' does not exist")
|
||||
{
|
||||
|
||||
: std::runtime_error("option explicit set and parameter '" + t_param_name + "' does not exist") {
|
||||
}
|
||||
|
||||
option_explicit_set(const option_explicit_set &) = default;
|
||||
@ -40,43 +35,26 @@ namespace chaiscript
|
||||
~option_explicit_set() noexcept override = default;
|
||||
};
|
||||
|
||||
class Dynamic_Object
|
||||
{
|
||||
class Dynamic_Object {
|
||||
public:
|
||||
explicit Dynamic_Object(std::string t_type_name)
|
||||
: m_type_name(std::move(t_type_name)), m_option_explicit(false)
|
||||
{
|
||||
: m_type_name(std::move(t_type_name))
|
||||
, m_option_explicit(false) {
|
||||
}
|
||||
|
||||
Dynamic_Object() = default;
|
||||
|
||||
bool is_explicit() const noexcept
|
||||
{
|
||||
return m_option_explicit;
|
||||
}
|
||||
bool is_explicit() const noexcept { return m_option_explicit; }
|
||||
|
||||
void set_explicit(const bool t_explicit) noexcept
|
||||
{
|
||||
m_option_explicit = t_explicit;
|
||||
}
|
||||
void set_explicit(const bool t_explicit) noexcept { m_option_explicit = t_explicit; }
|
||||
|
||||
const std::string &get_type_name() const noexcept
|
||||
{
|
||||
return m_type_name;
|
||||
}
|
||||
const std::string &get_type_name() const noexcept { return m_type_name; }
|
||||
|
||||
const Boxed_Value &operator[](const std::string &t_attr_name) const
|
||||
{
|
||||
return get_attr(t_attr_name);
|
||||
}
|
||||
const Boxed_Value &operator[](const std::string &t_attr_name) const { return get_attr(t_attr_name); }
|
||||
|
||||
Boxed_Value &operator[](const std::string &t_attr_name)
|
||||
{
|
||||
return get_attr(t_attr_name);
|
||||
}
|
||||
Boxed_Value &operator[](const std::string &t_attr_name) { return get_attr(t_attr_name); }
|
||||
|
||||
const Boxed_Value &get_attr(const std::string &t_attr_name) const
|
||||
{
|
||||
const Boxed_Value &get_attr(const std::string &t_attr_name) const {
|
||||
auto a = m_attrs.find(t_attr_name);
|
||||
|
||||
if (a != m_attrs.end()) {
|
||||
@ -86,17 +64,11 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
bool has_attr(const std::string &t_attr_name) const {
|
||||
return m_attrs.find(t_attr_name) != m_attrs.end();
|
||||
}
|
||||
bool has_attr(const std::string &t_attr_name) const { return m_attrs.find(t_attr_name) != m_attrs.end(); }
|
||||
|
||||
Boxed_Value &get_attr(const std::string &t_attr_name)
|
||||
{
|
||||
return m_attrs[t_attr_name];
|
||||
}
|
||||
Boxed_Value &get_attr(const std::string &t_attr_name) { return m_attrs[t_attr_name]; }
|
||||
|
||||
Boxed_Value &method_missing(const std::string &t_method_name)
|
||||
{
|
||||
Boxed_Value &method_missing(const std::string &t_method_name) {
|
||||
if (m_option_explicit && m_attrs.find(t_method_name) == m_attrs.end()) {
|
||||
throw option_explicit_set(t_method_name);
|
||||
}
|
||||
@ -104,8 +76,7 @@ namespace chaiscript
|
||||
return get_attr(t_method_name);
|
||||
}
|
||||
|
||||
const Boxed_Value &method_missing(const std::string &t_method_name) const
|
||||
{
|
||||
const Boxed_Value &method_missing(const std::string &t_method_name) const {
|
||||
if (m_option_explicit && m_attrs.find(t_method_name) == m_attrs.end()) {
|
||||
throw option_explicit_set(t_method_name);
|
||||
}
|
||||
@ -113,10 +84,7 @@ namespace chaiscript
|
||||
return get_attr(t_method_name);
|
||||
}
|
||||
|
||||
std::map<std::string, Boxed_Value> get_attrs() const
|
||||
{
|
||||
return m_attrs;
|
||||
}
|
||||
std::map<std::string, Boxed_Value> get_attrs() const { return m_attrs; }
|
||||
|
||||
private:
|
||||
const std::string m_type_name = "";
|
||||
@ -125,7 +93,6 @@ namespace chaiscript
|
||||
std::map<std::string, Boxed_Value> m_attrs;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
} // namespace dispatch
|
||||
} // namespace chaiscript
|
||||
#endif
|
||||
|
||||
|
||||
@ -19,62 +19,51 @@
|
||||
#include "boxed_cast.hpp"
|
||||
#include "boxed_cast_helper.hpp"
|
||||
#include "boxed_value.hpp"
|
||||
#include "dynamic_object.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
|
||||
class Type_Conversions;
|
||||
namespace dispatch {
|
||||
class Proxy_Function_Base;
|
||||
} // namespace dispatch
|
||||
} // namespace chaiscript
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
namespace dispatch
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
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 final : public Proxy_Function_Base
|
||||
{
|
||||
class Dynamic_Object_Function final : public Proxy_Function_Base {
|
||||
public:
|
||||
Dynamic_Object_Function(
|
||||
std::string t_type_name,
|
||||
const Proxy_Function &t_func,
|
||||
bool t_is_attribute = false)
|
||||
: 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>()),
|
||||
m_is_attribute(t_is_attribute)
|
||||
{
|
||||
assert( (t_func->get_arity() > 0 || t_func->get_arity() < 0)
|
||||
Dynamic_Object_Function(std::string t_type_name, const Proxy_Function &t_func, bool t_is_attribute = false)
|
||||
: 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>())
|
||||
, m_is_attribute(t_is_attribute) {
|
||||
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,
|
||||
bool t_is_attribute = false)
|
||||
: 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(t_ti.is_undef()?nullptr:new Type_Info(t_ti)), m_doti(user_type<Dynamic_Object>()),
|
||||
m_is_attribute(t_is_attribute)
|
||||
{
|
||||
assert( (t_func->get_arity() > 0 || t_func->get_arity() < 0)
|
||||
Dynamic_Object_Function(std::string t_type_name, const Proxy_Function &t_func, const Type_Info &t_ti, bool t_is_attribute = false)
|
||||
: 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(t_ti.is_undef() ? nullptr : new Type_Info(t_ti))
|
||||
, m_doti(user_type<Dynamic_Object>())
|
||||
, m_is_attribute(t_is_attribute) {
|
||||
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 &operator=(const Dynamic_Object_Function) = delete;
|
||||
Dynamic_Object_Function(Dynamic_Object_Function &) = delete;
|
||||
|
||||
bool operator==(const Proxy_Function_Base &f) const noexcept override
|
||||
{
|
||||
if (const auto *df = dynamic_cast<const Dynamic_Object_Function *>(&f))
|
||||
{
|
||||
bool operator==(const Proxy_Function_Base &f) const noexcept 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;
|
||||
@ -83,54 +72,44 @@ namespace chaiscript
|
||||
|
||||
bool is_attribute_function() const noexcept override { return m_is_attribute; }
|
||||
|
||||
bool call_match(const chaiscript::Function_Params &vals, const Type_Conversions_State &t_conversions) const noexcept override
|
||||
{
|
||||
if (dynamic_object_typename_match(vals, m_type_name, m_ti, t_conversions))
|
||||
{
|
||||
bool call_match(const chaiscript::Function_Params &vals, const Type_Conversions_State &t_conversions) const noexcept 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;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<Const_Proxy_Function> get_contained_functions() const override
|
||||
{
|
||||
return {m_func};
|
||||
}
|
||||
std::vector<Const_Proxy_Function> get_contained_functions() const override { return {m_func}; }
|
||||
|
||||
protected:
|
||||
Boxed_Value do_call(const chaiscript::Function_Params ¶ms, const Type_Conversions_State &t_conversions) const override
|
||||
{
|
||||
if (dynamic_object_typename_match(params, m_type_name, m_ti, t_conversions))
|
||||
{
|
||||
Boxed_Value do_call(const chaiscript::Function_Params ¶ms, const Type_Conversions_State &t_conversions) const 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();
|
||||
}
|
||||
}
|
||||
|
||||
bool compare_first_type(const Boxed_Value &bv, const Type_Conversions_State &t_conversions) const noexcept override
|
||||
{
|
||||
bool compare_first_type(const Boxed_Value &bv, const Type_Conversions_State &t_conversions) const noexcept 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)
|
||||
{
|
||||
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>()));
|
||||
// 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_State &t_conversions) const noexcept
|
||||
{
|
||||
if (bv.get_type_info().bare_equal(m_doti))
|
||||
{
|
||||
bool dynamic_object_typename_match(const Boxed_Value &bv,
|
||||
const std::string &name,
|
||||
const std::unique_ptr<Type_Info> &ti,
|
||||
const Type_Conversions_State &t_conversions) const noexcept {
|
||||
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;
|
||||
@ -138,21 +117,19 @@ namespace chaiscript
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (ti)
|
||||
{
|
||||
if (ti) {
|
||||
return bv.get_type_info().bare_equal(*ti);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool dynamic_object_typename_match(const chaiscript::Function_Params &bvs, const std::string &name,
|
||||
const std::unique_ptr<Type_Info> &ti, const Type_Conversions_State &t_conversions) const noexcept
|
||||
{
|
||||
if (!bvs.empty())
|
||||
{
|
||||
bool dynamic_object_typename_match(const chaiscript::Function_Params &bvs,
|
||||
const std::string &name,
|
||||
const std::unique_ptr<Type_Info> &ti,
|
||||
const Type_Conversions_State &t_conversions) const noexcept {
|
||||
if (!bvs.empty()) {
|
||||
return dynamic_object_typename_match(bvs[0], name, ti, t_conversions);
|
||||
} else {
|
||||
return false;
|
||||
@ -166,47 +143,39 @@ namespace chaiscript
|
||||
const bool m_is_attribute;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* 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 final : public Proxy_Function_Base
|
||||
{
|
||||
class Dynamic_Object_Constructor final : 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)
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
if (begin != end) {
|
||||
++begin;
|
||||
}
|
||||
|
||||
return std::vector<Type_Info>(begin, end);
|
||||
}
|
||||
|
||||
bool operator==(const Proxy_Function_Base &f) const noexcept override
|
||||
{
|
||||
const Dynamic_Object_Constructor *dc = dynamic_cast<const Dynamic_Object_Constructor*>(&f);
|
||||
bool operator==(const Proxy_Function_Base &f) const noexcept override {
|
||||
const Dynamic_Object_Constructor *dc = dynamic_cast<const Dynamic_Object_Constructor *>(&f);
|
||||
return (dc != nullptr) && dc->m_type_name == m_type_name && (*dc->m_func) == (*m_func);
|
||||
}
|
||||
|
||||
bool call_match(const chaiscript::Function_Params &vals, const Type_Conversions_State &t_conversions) const override
|
||||
{
|
||||
bool call_match(const chaiscript::Function_Params &vals, const Type_Conversions_State &t_conversions) const override {
|
||||
std::vector<Boxed_Value> new_vals{Boxed_Value(Dynamic_Object(m_type_name))};
|
||||
new_vals.insert(new_vals.end(), vals.begin(), vals.end());
|
||||
|
||||
@ -214,8 +183,7 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
protected:
|
||||
Boxed_Value do_call(const chaiscript::Function_Params ¶ms, const Type_Conversions_State &t_conversions) const override
|
||||
{
|
||||
Boxed_Value do_call(const chaiscript::Function_Params ¶ms, const Type_Conversions_State &t_conversions) const override {
|
||||
auto bv = Boxed_Value(Dynamic_Object(m_type_name), true);
|
||||
std::vector<Boxed_Value> new_params{bv};
|
||||
new_params.insert(new_params.end(), params.begin(), params.end());
|
||||
@ -228,10 +196,8 @@ namespace chaiscript
|
||||
private:
|
||||
const std::string m_type_name;
|
||||
const Proxy_Function m_func;
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace detail
|
||||
} // namespace dispatch
|
||||
} // namespace chaiscript
|
||||
#endif
|
||||
|
||||
|
||||
@ -7,7 +7,6 @@
|
||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||
|
||||
|
||||
#ifndef CHAISCRIPT_EXCEPTION_SPECIFICATION_HPP_
|
||||
#define CHAISCRIPT_EXCEPTION_SPECIFICATION_HPP_
|
||||
|
||||
@ -17,39 +16,28 @@
|
||||
#include "boxed_cast.hpp"
|
||||
|
||||
namespace chaiscript {
|
||||
class Boxed_Value;
|
||||
namespace exception {
|
||||
class bad_boxed_cast;
|
||||
} // namespace exception
|
||||
} // namespace chaiscript
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
struct Exception_Handler_Base
|
||||
{
|
||||
namespace detail {
|
||||
struct Exception_Handler_Base {
|
||||
virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine) = 0;
|
||||
|
||||
virtual ~Exception_Handler_Base() = default;
|
||||
|
||||
protected:
|
||||
template<typename T>
|
||||
static void throw_type(const Boxed_Value &bv, const Dispatch_Engine &t_engine)
|
||||
{
|
||||
try { T t = t_engine.boxed_cast<T>(bv); throw t; } catch (const chaiscript::exception::bad_boxed_cast &) {}
|
||||
static void throw_type(const Boxed_Value &bv, const Dispatch_Engine &t_engine) {
|
||||
try {
|
||||
T t = t_engine.boxed_cast<T>(bv);
|
||||
throw t;
|
||||
} catch (const chaiscript::exception::bad_boxed_cast &) {
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename ... T>
|
||||
struct Exception_Handler_Impl : Exception_Handler_Base
|
||||
{
|
||||
void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine) override
|
||||
{
|
||||
(throw_type<T>(bv, t_engine), ...);
|
||||
}
|
||||
template<typename... T>
|
||||
struct Exception_Handler_Impl : Exception_Handler_Base {
|
||||
void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine) override { (throw_type<T>(bv, t_engine), ...); }
|
||||
};
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
/// \brief Used in the automatic unboxing of exceptions thrown during script evaluation
|
||||
///
|
||||
@ -61,7 +49,8 @@ namespace chaiscript
|
||||
/// chaiscript::ChaiScript chai;
|
||||
///
|
||||
/// try {
|
||||
/// chai.eval("throw(runtime_error(\"error\"))", chaiscript::exception_specification<int, double, float, const std::string &, const std::exception &>());
|
||||
/// chai.eval("throw(runtime_error(\"error\"))", chaiscript::exception_specification<int, double, float, const std::string &, const
|
||||
/// std::exception &>());
|
||||
/// } catch (const double e) {
|
||||
/// } catch (int) {
|
||||
/// } catch (float) {
|
||||
@ -105,13 +94,10 @@ namespace chaiscript
|
||||
|
||||
/// \brief creates a chaiscript::Exception_Handler which handles one type of exception unboxing
|
||||
/// \sa \ref exceptions
|
||||
template<typename ... T>
|
||||
Exception_Handler exception_specification()
|
||||
{
|
||||
template<typename... T>
|
||||
Exception_Handler exception_specification() {
|
||||
return std::make_shared<detail::Exception_Handler_Impl<T...>>();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace chaiscript
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@ -7,7 +7,6 @@
|
||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||
|
||||
|
||||
#ifndef CHAISCRIPT_FUNCTION_CALL_HPP_
|
||||
#define CHAISCRIPT_FUNCTION_CALL_HPP_
|
||||
|
||||
@ -20,25 +19,22 @@
|
||||
#include "proxy_functions.hpp"
|
||||
|
||||
namespace chaiscript {
|
||||
class Boxed_Value;
|
||||
class Type_Conversions_State;
|
||||
namespace detail {
|
||||
template <typename T> struct Cast_Helper;
|
||||
} // namespace detail
|
||||
class Boxed_Value;
|
||||
class Type_Conversions_State;
|
||||
namespace detail {
|
||||
template<typename T>
|
||||
struct Cast_Helper;
|
||||
} // namespace detail
|
||||
} // namespace chaiscript
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
namespace dispatch
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
template<typename Ret, typename ... Param>
|
||||
constexpr auto arity(Ret (*)(Param...)) noexcept
|
||||
{
|
||||
namespace chaiscript {
|
||||
namespace dispatch {
|
||||
namespace detail {
|
||||
template<typename Ret, typename... Param>
|
||||
constexpr auto arity(Ret (*)(Param...)) noexcept {
|
||||
return sizeof...(Param);
|
||||
}
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
/// Build a function caller that knows how to dispatch on a set of functions
|
||||
/// example:
|
||||
@ -47,10 +43,8 @@ namespace chaiscript
|
||||
/// \returns A std::function object for dispatching
|
||||
/// \param[in] funcs the set of functions to dispatch on.
|
||||
template<typename FunctionType>
|
||||
std::function<FunctionType> functor(const std::vector<Const_Proxy_Function> &funcs, const Type_Conversions_State *t_conversions)
|
||||
{
|
||||
const bool has_arity_match = std::any_of(funcs.begin(), funcs.end(),
|
||||
[](const Const_Proxy_Function &f) {
|
||||
std::function<FunctionType> functor(const std::vector<Const_Proxy_Function> &funcs, const Type_Conversions_State *t_conversions) {
|
||||
const bool has_arity_match = std::any_of(funcs.begin(), funcs.end(), [](const Const_Proxy_Function &f) {
|
||||
return f->get_arity() == -1 || size_t(f->get_arity()) == detail::arity(static_cast<FunctionType *>(nullptr));
|
||||
});
|
||||
|
||||
@ -58,7 +52,7 @@ namespace chaiscript
|
||||
throw exception::bad_boxed_cast(user_type<Const_Proxy_Function>(), typeid(std::function<FunctionType>));
|
||||
}
|
||||
|
||||
FunctionType *p=nullptr;
|
||||
FunctionType *p = nullptr;
|
||||
return detail::build_function_caller_helper(p, funcs, t_conversions);
|
||||
}
|
||||
|
||||
@ -74,29 +68,24 @@ namespace chaiscript
|
||||
/// \returns A std::function object for dispatching
|
||||
/// \param[in] func A function to execute.
|
||||
template<typename FunctionType>
|
||||
std::function<FunctionType> functor(Const_Proxy_Function func, const Type_Conversions_State *t_conversions)
|
||||
{
|
||||
std::function<FunctionType> functor(Const_Proxy_Function func, const Type_Conversions_State *t_conversions) {
|
||||
return functor<FunctionType>(std::vector<Const_Proxy_Function>({std::move(func)}), t_conversions);
|
||||
}
|
||||
|
||||
/// Helper for automatically unboxing a Boxed_Value that contains a function object
|
||||
/// and creating a typesafe C++ function caller from it.
|
||||
template<typename FunctionType>
|
||||
std::function<FunctionType> functor(const Boxed_Value &bv, const Type_Conversions_State *t_conversions)
|
||||
{
|
||||
return functor<FunctionType>(boxed_cast<Const_Proxy_Function >(bv, t_conversions), t_conversions);
|
||||
}
|
||||
std::function<FunctionType> functor(const Boxed_Value &bv, const Type_Conversions_State *t_conversions) {
|
||||
return functor<FunctionType>(boxed_cast<Const_Proxy_Function>(bv, t_conversions), t_conversions);
|
||||
}
|
||||
} // namespace dispatch
|
||||
|
||||
namespace detail{
|
||||
namespace detail {
|
||||
/// Cast helper to handle automatic casting to const std::function &
|
||||
template<typename Signature>
|
||||
struct Cast_Helper<const std::function<Signature> &>
|
||||
{
|
||||
static std::function<Signature> cast(const Boxed_Value &ob, const Type_Conversions_State *t_conversions)
|
||||
{
|
||||
if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>()))
|
||||
{
|
||||
struct Cast_Helper<const std::function<Signature> &> {
|
||||
static std::function<Signature> cast(const Boxed_Value &ob, const Type_Conversions_State *t_conversions) {
|
||||
if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>())) {
|
||||
return dispatch::functor<Signature>(ob, t_conversions);
|
||||
} else {
|
||||
return Cast_Helper_Inner<const std::function<Signature> &>::cast(ob, t_conversions);
|
||||
@ -106,35 +95,28 @@ namespace chaiscript
|
||||
|
||||
/// Cast helper to handle automatic casting to std::function
|
||||
template<typename Signature>
|
||||
struct Cast_Helper<std::function<Signature> >
|
||||
{
|
||||
static std::function<Signature> cast(const Boxed_Value &ob, const Type_Conversions_State *t_conversions)
|
||||
{
|
||||
if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>()))
|
||||
{
|
||||
struct Cast_Helper<std::function<Signature>> {
|
||||
static std::function<Signature> cast(const Boxed_Value &ob, const Type_Conversions_State *t_conversions) {
|
||||
if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>())) {
|
||||
return dispatch::functor<Signature>(ob, t_conversions);
|
||||
} else {
|
||||
return Cast_Helper_Inner<std::function<Signature> >::cast(ob, t_conversions);
|
||||
return Cast_Helper_Inner<std::function<Signature>>::cast(ob, t_conversions);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/// Cast helper to handle automatic casting to const std::function
|
||||
template<typename Signature>
|
||||
struct Cast_Helper<const std::function<Signature> >
|
||||
{
|
||||
static std::function<Signature> cast(const Boxed_Value &ob, const Type_Conversions_State *t_conversions)
|
||||
{
|
||||
if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>()))
|
||||
{
|
||||
struct Cast_Helper<const std::function<Signature>> {
|
||||
static std::function<Signature> cast(const Boxed_Value &ob, const Type_Conversions_State *t_conversions) {
|
||||
if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>())) {
|
||||
return dispatch::functor<Signature>(ob, t_conversions);
|
||||
} else {
|
||||
return Cast_Helper_Inner<const std::function<Signature> >::cast(ob, t_conversions);
|
||||
return Cast_Helper_Inner<const std::function<Signature>>::cast(ob, t_conversions);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
} // namespace detail
|
||||
} // namespace chaiscript
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@ -7,7 +7,6 @@
|
||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||
|
||||
|
||||
#ifndef CHAISCRIPT_FUNCTION_CALL_DETAIL_HPP_
|
||||
#define CHAISCRIPT_FUNCTION_CALL_DETAIL_HPP_
|
||||
|
||||
@ -20,27 +19,19 @@
|
||||
#include "boxed_cast.hpp"
|
||||
#include "boxed_number.hpp"
|
||||
#include "boxed_value.hpp"
|
||||
#include "type_conversions.hpp"
|
||||
#include "proxy_functions.hpp"
|
||||
#include "type_conversions.hpp"
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
namespace dispatch
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
namespace chaiscript::dispatch::detail {
|
||||
/// used internally for unwrapping a function call's types
|
||||
template<typename Ret, typename ... Param>
|
||||
struct Build_Function_Caller_Helper
|
||||
{
|
||||
template<typename Ret, typename... Param>
|
||||
struct Build_Function_Caller_Helper {
|
||||
Build_Function_Caller_Helper(std::vector<Const_Proxy_Function> t_funcs, const Type_Conversions *t_conversions)
|
||||
: m_funcs(std::move(t_funcs)),
|
||||
m_conversions(t_conversions)
|
||||
{
|
||||
: m_funcs(std::move(t_funcs))
|
||||
, m_conversions(t_conversions) {
|
||||
}
|
||||
|
||||
Ret call(const chaiscript::Function_Params ¶ms, const Type_Conversions_State &t_state)
|
||||
{
|
||||
Ret call(const chaiscript::Function_Params ¶ms, const Type_Conversions_State &t_state) {
|
||||
if constexpr (std::is_arithmetic_v<Ret> && !std::is_same_v<std::remove_cv_t<std::remove_reference_t<Ret>>, bool>) {
|
||||
return Boxed_Number(dispatch::dispatch(m_funcs, params, t_state)).get_as<Ret>();
|
||||
} else if constexpr (std::is_same_v<void, Ret>) {
|
||||
@ -50,9 +41,8 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
template<typename ... P>
|
||||
Ret operator()(P&& ... param)
|
||||
{
|
||||
template<typename... P>
|
||||
Ret operator()(P &&...param) {
|
||||
std::array<Boxed_Value, sizeof...(P)> params{box<P>(std::forward<P>(param))...};
|
||||
|
||||
if (m_conversions) {
|
||||
@ -63,10 +53,8 @@ namespace chaiscript
|
||||
Type_Conversions_State state(conv, conv.conversion_saves());
|
||||
return call(chaiscript::Function_Params{params}, state);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
template<typename P, typename Q>
|
||||
static Boxed_Value box(Q &&q) {
|
||||
if constexpr (std::is_same_v<chaiscript::Boxed_Value, std::decay_t<Q>>) {
|
||||
@ -78,17 +66,14 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::vector<Const_Proxy_Function> m_funcs;
|
||||
const Type_Conversions *m_conversions;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/// \todo what happens if t_conversions is deleted out from under us?!
|
||||
template<typename Ret, typename ... Params>
|
||||
std::function<Ret (Params...)> build_function_caller_helper(Ret (Params...), const std::vector<Const_Proxy_Function> &funcs, const Type_Conversions_State *t_conversions)
|
||||
{
|
||||
template<typename Ret, typename... Params>
|
||||
std::function<Ret(Params...)>
|
||||
build_function_caller_helper(Ret(Params...), const std::vector<Const_Proxy_Function> &funcs, const Type_Conversions_State *t_conversions) {
|
||||
/*
|
||||
if (funcs.size() == 1)
|
||||
{
|
||||
@ -103,13 +88,10 @@ namespace chaiscript
|
||||
// looks like this either wasn't a Proxy_Function_Impl or the types didn't match
|
||||
// we cannot make any other guesses or assumptions really, so continuing
|
||||
}
|
||||
*/
|
||||
*/
|
||||
|
||||
return std::function<Ret (Params...)>(Build_Function_Caller_Helper<Ret, Params...>(funcs, t_conversions?t_conversions->get():nullptr));
|
||||
return std::function<Ret(Params...)>(Build_Function_Caller_Helper<Ret, Params...>(funcs, t_conversions ? t_conversions->get() : nullptr));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace chaiscript::dispatch::detail
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@ -7,66 +7,48 @@
|
||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||
|
||||
|
||||
#ifndef CHAISCRIPT_FUNCTION_PARAMS_HPP
|
||||
#define CHAISCRIPT_FUNCTION_PARAMS_HPP
|
||||
|
||||
|
||||
#include "boxed_value.hpp"
|
||||
|
||||
namespace chaiscript {
|
||||
|
||||
class Function_Params
|
||||
{
|
||||
class Function_Params {
|
||||
public:
|
||||
constexpr Function_Params(const Boxed_Value * const t_begin, const Boxed_Value * const t_end)
|
||||
: m_begin(t_begin), m_end(t_end)
|
||||
{
|
||||
constexpr Function_Params(const Boxed_Value *const t_begin, const Boxed_Value *const t_end)
|
||||
: m_begin(t_begin)
|
||||
, m_end(t_end) {
|
||||
}
|
||||
|
||||
explicit Function_Params(const Boxed_Value &bv)
|
||||
: m_begin(&bv), m_end(m_begin + 1)
|
||||
{
|
||||
: m_begin(&bv)
|
||||
, m_end(m_begin + 1) {
|
||||
}
|
||||
|
||||
explicit Function_Params(const std::vector<Boxed_Value> &vec)
|
||||
: m_begin(vec.empty() ? nullptr : &vec.front()), m_end(vec.empty() ? nullptr : &vec.front() + vec.size())
|
||||
{
|
||||
: m_begin(vec.empty() ? nullptr : &vec.front())
|
||||
, m_end(vec.empty() ? nullptr : &vec.front() + vec.size()) {
|
||||
}
|
||||
|
||||
template<size_t Size>
|
||||
constexpr explicit Function_Params(const std::array<Boxed_Value, Size> &a)
|
||||
: m_begin(&a.front()), m_end(&a.front() + Size)
|
||||
{
|
||||
: m_begin(&a.front())
|
||||
, m_end(&a.front() + Size) {
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr const Boxed_Value &operator[](const std::size_t t_i) const noexcept {
|
||||
return m_begin[t_i];
|
||||
}
|
||||
[[nodiscard]] constexpr const Boxed_Value &operator[](const std::size_t t_i) const noexcept { return m_begin[t_i]; }
|
||||
|
||||
[[nodiscard]] constexpr const Boxed_Value *begin() const noexcept {
|
||||
return m_begin;
|
||||
}
|
||||
[[nodiscard]] constexpr const Boxed_Value *begin() const noexcept { return m_begin; }
|
||||
|
||||
[[nodiscard]] constexpr const Boxed_Value &front() const noexcept {
|
||||
return *m_begin;
|
||||
}
|
||||
[[nodiscard]] constexpr const Boxed_Value &front() const noexcept { return *m_begin; }
|
||||
|
||||
[[nodiscard]] constexpr const Boxed_Value *end() const noexcept {
|
||||
return m_end;
|
||||
}
|
||||
[[nodiscard]] constexpr const Boxed_Value *end() const noexcept { return m_end; }
|
||||
|
||||
[[nodiscard]] constexpr std::size_t size() const noexcept {
|
||||
return std::size_t(m_end - m_begin);
|
||||
}
|
||||
[[nodiscard]] constexpr std::size_t size() const noexcept { return std::size_t(m_end - m_begin); }
|
||||
|
||||
[[nodiscard]] std::vector<Boxed_Value> to_vector() const {
|
||||
return std::vector<Boxed_Value>{m_begin, m_end};
|
||||
}
|
||||
[[nodiscard]] std::vector<Boxed_Value> to_vector() const { return std::vector<Boxed_Value>{m_begin, m_end}; }
|
||||
|
||||
[[nodiscard]] constexpr bool empty() const noexcept {
|
||||
return m_begin == m_end;
|
||||
}
|
||||
[[nodiscard]] constexpr bool empty() const noexcept { return m_begin == m_end; }
|
||||
|
||||
private:
|
||||
const Boxed_Value *m_begin = nullptr;
|
||||
@ -76,10 +58,10 @@ namespace chaiscript {
|
||||
// Constructor specialization for array of size 0
|
||||
template<>
|
||||
constexpr Function_Params::Function_Params(const std::array<Boxed_Value, size_t{0}> & /* a */)
|
||||
: m_begin(nullptr), m_end(nullptr)
|
||||
{
|
||||
: m_begin(nullptr)
|
||||
, m_end(nullptr) {
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace chaiscript
|
||||
|
||||
#endif
|
||||
|
||||
@ -4,142 +4,146 @@
|
||||
#include <type_traits>
|
||||
|
||||
namespace chaiscript::dispatch::detail {
|
||||
template<typename... Param>
|
||||
struct Function_Params {
|
||||
};
|
||||
|
||||
template<typename... Param>
|
||||
struct Function_Params
|
||||
{
|
||||
};
|
||||
|
||||
template<typename Ret, typename Params, bool IsNoExcept = false, bool IsMember = false, bool IsMemberObject = false, bool IsObject = false>
|
||||
struct Function_Signature
|
||||
{
|
||||
template<typename Ret, typename Params, bool IsNoExcept = false, bool IsMember = false, bool IsMemberObject = false, bool IsObject = false>
|
||||
struct Function_Signature {
|
||||
using Param_Types = Params;
|
||||
using Return_Type = Ret;
|
||||
constexpr static const bool is_object = IsObject;
|
||||
constexpr static const bool is_member_object = IsMemberObject;
|
||||
constexpr static const bool is_noexcept = IsNoExcept;
|
||||
template<typename T>
|
||||
constexpr Function_Signature(T &&) noexcept {}
|
||||
constexpr Function_Signature(T &&) noexcept {
|
||||
}
|
||||
constexpr Function_Signature() noexcept = default;
|
||||
};
|
||||
};
|
||||
|
||||
// Free functions
|
||||
// Free functions
|
||||
|
||||
template<typename Ret, typename... Param>
|
||||
Function_Signature(Ret (*f)(Param...))->Function_Signature<Ret, Function_Params<Param...>>;
|
||||
template<typename Ret, typename... Param>
|
||||
Function_Signature(Ret (*f)(Param...)) -> Function_Signature<Ret, Function_Params<Param...>>;
|
||||
|
||||
template<typename Ret, typename... Param>
|
||||
Function_Signature(Ret (*f)(Param...) noexcept)->Function_Signature<Ret, Function_Params<Param...>, true>;
|
||||
template<typename Ret, typename... Param>
|
||||
Function_Signature(Ret (*f)(Param...) noexcept) -> Function_Signature<Ret, Function_Params<Param...>, true>;
|
||||
|
||||
// no reference specifier
|
||||
// no reference specifier
|
||||
|
||||
template<typename Ret, typename Class, typename... Param>
|
||||
Function_Signature(Ret (Class::*f)(Param...) volatile)->Function_Signature<Ret, Function_Params<volatile Class &, Param...>, false, true>;
|
||||
template<typename Ret, typename Class, typename... Param>
|
||||
Function_Signature(Ret (Class::*f)(Param...) volatile) -> Function_Signature<Ret, Function_Params<volatile Class &, Param...>, false, true>;
|
||||
|
||||
template<typename Ret, typename Class, typename... Param>
|
||||
Function_Signature(Ret (Class::*f)(Param...) volatile noexcept)->Function_Signature<Ret, Function_Params<volatile Class &, Param...>, true, true>;
|
||||
template<typename Ret, typename Class, typename... Param>
|
||||
Function_Signature(Ret (Class::*f)(Param...) volatile noexcept)
|
||||
-> Function_Signature<Ret, Function_Params<volatile Class &, Param...>, true, true>;
|
||||
|
||||
template<typename Ret, typename Class, typename... Param>
|
||||
Function_Signature(Ret (Class::*f)(Param...) volatile const)->Function_Signature<Ret, Function_Params<volatile const Class &, Param...>, false, true>;
|
||||
template<typename Ret, typename Class, typename... Param>
|
||||
Function_Signature(Ret (Class::*f)(Param...) volatile const)
|
||||
-> Function_Signature<Ret, Function_Params<volatile const Class &, Param...>, false, true>;
|
||||
|
||||
template<typename Ret, typename Class, typename... Param>
|
||||
Function_Signature(Ret (Class::*f)(Param...) volatile const noexcept)->Function_Signature<Ret, Function_Params<volatile const Class &, Param...>, true, true>;
|
||||
template<typename Ret, typename Class, typename... Param>
|
||||
Function_Signature(Ret (Class::*f)(Param...) volatile const noexcept)
|
||||
-> Function_Signature<Ret, Function_Params<volatile const Class &, Param...>, true, true>;
|
||||
|
||||
template<typename Ret, typename Class, typename... Param>
|
||||
Function_Signature(Ret (Class::*f)(Param...))->Function_Signature<Ret, Function_Params<Class &, Param...>, false, true>;
|
||||
template<typename Ret, typename Class, typename... Param>
|
||||
Function_Signature(Ret (Class::*f)(Param...)) -> Function_Signature<Ret, Function_Params<Class &, Param...>, false, true>;
|
||||
|
||||
template<typename Ret, typename Class, typename... Param>
|
||||
Function_Signature(Ret (Class::*f)(Param...) noexcept)->Function_Signature<Ret, Function_Params<Class &, Param...>, true, true>;
|
||||
template<typename Ret, typename Class, typename... Param>
|
||||
Function_Signature(Ret (Class::*f)(Param...) noexcept) -> Function_Signature<Ret, Function_Params<Class &, Param...>, true, true>;
|
||||
|
||||
template<typename Ret, typename Class, typename... Param>
|
||||
Function_Signature(Ret (Class::*f)(Param...) const)->Function_Signature<Ret, Function_Params<const Class &, Param...>, false, true>;
|
||||
template<typename Ret, typename Class, typename... Param>
|
||||
Function_Signature(Ret (Class::*f)(Param...) const) -> Function_Signature<Ret, Function_Params<const Class &, Param...>, false, true>;
|
||||
|
||||
template<typename Ret, typename Class, typename... Param>
|
||||
Function_Signature(Ret (Class::*f)(Param...) const noexcept)->Function_Signature<Ret, Function_Params<const Class &, Param...>, true, true>;
|
||||
template<typename Ret, typename Class, typename... Param>
|
||||
Function_Signature(Ret (Class::*f)(Param...) const noexcept) -> Function_Signature<Ret, Function_Params<const Class &, Param...>, true, true>;
|
||||
|
||||
// & reference specifier
|
||||
// & reference specifier
|
||||
|
||||
template<typename Ret, typename Class, typename... Param>
|
||||
Function_Signature(Ret (Class::*f)(Param...) volatile &)->Function_Signature<Ret, Function_Params<volatile Class &, Param...>, false, true>;
|
||||
template<typename Ret, typename Class, typename... Param>
|
||||
Function_Signature(Ret (Class::*f)(Param...) volatile &) -> Function_Signature<Ret, Function_Params<volatile Class &, Param...>, false, true>;
|
||||
|
||||
template<typename Ret, typename Class, typename... Param>
|
||||
Function_Signature(Ret (Class::*f)(Param...) volatile &noexcept)->Function_Signature<Ret, Function_Params<volatile Class &, Param...>, true, true>;
|
||||
template<typename Ret, typename Class, typename... Param>
|
||||
Function_Signature(Ret (Class::*f)(Param...) volatile &noexcept)
|
||||
-> Function_Signature<Ret, Function_Params<volatile Class &, Param...>, true, true>;
|
||||
|
||||
template<typename Ret, typename Class, typename... Param>
|
||||
Function_Signature(Ret (Class::*f)(Param...) volatile const &)->Function_Signature<Ret, Function_Params<volatile const Class &, Param...>, false, true>;
|
||||
template<typename Ret, typename Class, typename... Param>
|
||||
Function_Signature(Ret (Class::*f)(Param...) volatile const &)
|
||||
-> Function_Signature<Ret, Function_Params<volatile const Class &, Param...>, false, true>;
|
||||
|
||||
template<typename Ret, typename Class, typename... Param>
|
||||
Function_Signature(Ret (Class::*f)(Param...) volatile const &noexcept)->Function_Signature<Ret, Function_Params<volatile const Class &, Param...>, true, true>;
|
||||
template<typename Ret, typename Class, typename... Param>
|
||||
Function_Signature(Ret (Class::*f)(Param...) volatile const &noexcept)
|
||||
-> Function_Signature<Ret, Function_Params<volatile const Class &, Param...>, true, true>;
|
||||
|
||||
template<typename Ret, typename Class, typename... Param>
|
||||
Function_Signature(Ret (Class::*f)(Param...) &)->Function_Signature<Ret, Function_Params<Class &, Param...>, false, true>;
|
||||
template<typename Ret, typename Class, typename... Param>
|
||||
Function_Signature(Ret (Class::*f)(Param...) &) -> Function_Signature<Ret, Function_Params<Class &, Param...>, false, true>;
|
||||
|
||||
template<typename Ret, typename Class, typename... Param>
|
||||
Function_Signature(Ret (Class::*f)(Param...) & noexcept)->Function_Signature<Ret, Function_Params<Class &, Param...>, true, true>;
|
||||
template<typename Ret, typename Class, typename... Param>
|
||||
Function_Signature(Ret (Class::*f)(Param...) &noexcept) -> Function_Signature<Ret, Function_Params<Class &, Param...>, true, true>;
|
||||
|
||||
template<typename Ret, typename Class, typename... Param>
|
||||
Function_Signature(Ret (Class::*f)(Param...) const &)->Function_Signature<Ret, Function_Params<const Class &, Param...>, false, true>;
|
||||
template<typename Ret, typename Class, typename... Param>
|
||||
Function_Signature(Ret (Class::*f)(Param...) const &) -> Function_Signature<Ret, Function_Params<const Class &, Param...>, false, true>;
|
||||
|
||||
template<typename Ret, typename Class, typename... Param>
|
||||
Function_Signature(Ret (Class::*f)(Param...) const &noexcept)->Function_Signature<Ret, Function_Params<const Class &, Param...>, true, true>;
|
||||
template<typename Ret, typename Class, typename... Param>
|
||||
Function_Signature(Ret (Class::*f)(Param...) const &noexcept) -> Function_Signature<Ret, Function_Params<const Class &, Param...>, true, true>;
|
||||
|
||||
// && reference specifier
|
||||
// && reference specifier
|
||||
|
||||
template<typename Ret, typename Class, typename... Param>
|
||||
Function_Signature(Ret (Class::*f)(Param...) volatile &&)->Function_Signature<Ret, Function_Params<volatile Class &&, Param...>, false, true>;
|
||||
template<typename Ret, typename Class, typename... Param>
|
||||
Function_Signature(Ret (Class::*f)(Param...) volatile &&) -> Function_Signature<Ret, Function_Params<volatile Class &&, Param...>, false, true>;
|
||||
|
||||
template<typename Ret, typename Class, typename... Param>
|
||||
Function_Signature(Ret (Class::*f)(Param...) volatile &&noexcept)->Function_Signature<Ret, Function_Params<volatile Class &&, Param...>, true, true>;
|
||||
template<typename Ret, typename Class, typename... Param>
|
||||
Function_Signature(Ret (Class::*f)(Param...) volatile &&noexcept)
|
||||
-> Function_Signature<Ret, Function_Params<volatile Class &&, Param...>, true, true>;
|
||||
|
||||
template<typename Ret, typename Class, typename... Param>
|
||||
Function_Signature(Ret (Class::*f)(Param...) volatile const &&)->Function_Signature<Ret, Function_Params<volatile const Class &&, Param...>, false, true>;
|
||||
template<typename Ret, typename Class, typename... Param>
|
||||
Function_Signature(Ret (Class::*f)(Param...) volatile const &&)
|
||||
-> Function_Signature<Ret, Function_Params<volatile const Class &&, Param...>, false, true>;
|
||||
|
||||
template<typename Ret, typename Class, typename... Param>
|
||||
Function_Signature(Ret (Class::*f)(Param...) volatile const &&noexcept)->Function_Signature<Ret, Function_Params<volatile const Class &&, Param...>, true, true>;
|
||||
template<typename Ret, typename Class, typename... Param>
|
||||
Function_Signature(Ret (Class::*f)(Param...) volatile const &&noexcept)
|
||||
-> Function_Signature<Ret, Function_Params<volatile const Class &&, Param...>, true, true>;
|
||||
|
||||
template<typename Ret, typename Class, typename... Param>
|
||||
Function_Signature(Ret (Class::*f)(Param...) &&)->Function_Signature<Ret, Function_Params<Class &&, Param...>, false, true>;
|
||||
template<typename Ret, typename Class, typename... Param>
|
||||
Function_Signature(Ret (Class::*f)(Param...) &&) -> Function_Signature<Ret, Function_Params<Class &&, Param...>, false, true>;
|
||||
|
||||
template<typename Ret, typename Class, typename... Param>
|
||||
Function_Signature(Ret (Class::*f)(Param...) && noexcept)->Function_Signature<Ret, Function_Params<Class &&, Param...>, true, true>;
|
||||
template<typename Ret, typename Class, typename... Param>
|
||||
Function_Signature(Ret (Class::*f)(Param...) &&noexcept) -> Function_Signature<Ret, Function_Params<Class &&, Param...>, true, true>;
|
||||
|
||||
template<typename Ret, typename Class, typename... Param>
|
||||
Function_Signature(Ret (Class::*f)(Param...) const &&)->Function_Signature<Ret, Function_Params<const Class &&, Param...>, false, true>;
|
||||
template<typename Ret, typename Class, typename... Param>
|
||||
Function_Signature(Ret (Class::*f)(Param...) const &&) -> Function_Signature<Ret, Function_Params<const Class &&, Param...>, false, true>;
|
||||
|
||||
template<typename Ret, typename Class, typename... Param>
|
||||
Function_Signature(Ret (Class::*f)(Param...) const &&noexcept)->Function_Signature<Ret, Function_Params<const Class &&, Param...>, true, true>;
|
||||
template<typename Ret, typename Class, typename... Param>
|
||||
Function_Signature(Ret (Class::*f)(Param...) const &&noexcept)
|
||||
-> Function_Signature<Ret, Function_Params<const Class &&, Param...>, true, true>;
|
||||
|
||||
template<typename Ret, typename Class>
|
||||
Function_Signature(Ret Class::*f)->Function_Signature<Ret, Function_Params<Class &>, true, true, true>;
|
||||
template<typename Ret, typename Class>
|
||||
Function_Signature(Ret Class::*f) -> Function_Signature<Ret, Function_Params<Class &>, true, true, true>;
|
||||
|
||||
// primary template handles types that have no nested ::type member:
|
||||
template<class, class = std::void_t<>>
|
||||
struct has_call_operator : std::false_type
|
||||
{
|
||||
};
|
||||
// primary template handles types that have no nested ::type member:
|
||||
template<class, class = std::void_t<>>
|
||||
struct has_call_operator : std::false_type {
|
||||
};
|
||||
|
||||
// specialization recognizes types that do have a nested ::type member:
|
||||
template<class T>
|
||||
struct has_call_operator<T, std::void_t<decltype(&T::operator())>> : std::true_type
|
||||
{
|
||||
};
|
||||
// specialization recognizes types that do have a nested ::type member:
|
||||
template<class T>
|
||||
struct has_call_operator<T, std::void_t<decltype(&T::operator())>> : std::true_type {
|
||||
};
|
||||
|
||||
template<typename Func>
|
||||
auto function_signature(const Func &f)
|
||||
{
|
||||
template<typename Func>
|
||||
auto function_signature(const Func &f) {
|
||||
if constexpr (has_call_operator<Func>::value) {
|
||||
return Function_Signature<
|
||||
typename decltype(Function_Signature{ &std::decay_t<Func>::operator() })::Return_Type,
|
||||
typename decltype(Function_Signature{ &std::decay_t<Func>::operator() })::Param_Types,
|
||||
decltype(Function_Signature{ &std::decay_t<Func>::operator() })::is_noexcept,
|
||||
return Function_Signature<typename decltype(Function_Signature{&std::decay_t<Func>::operator()})::Return_Type,
|
||||
typename decltype(Function_Signature{&std::decay_t<Func>::operator()})::Param_Types,
|
||||
decltype(Function_Signature{&std::decay_t<Func>::operator()})::is_noexcept,
|
||||
false,
|
||||
false,
|
||||
true>{};
|
||||
} else {
|
||||
return Function_Signature{ f };
|
||||
return Function_Signature{f};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}// namespace chaiscript::dispatch::detail
|
||||
} // namespace chaiscript::dispatch::detail
|
||||
|
||||
#endif
|
||||
|
||||
@ -7,7 +7,6 @@
|
||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||
|
||||
|
||||
#ifndef CHAISCRIPT_HANDLE_RETURN_HPP_
|
||||
#define CHAISCRIPT_HANDLE_RETURN_HPP_
|
||||
|
||||
@ -19,254 +18,178 @@
|
||||
#include "boxed_value.hpp"
|
||||
|
||||
namespace chaiscript {
|
||||
class Boxed_Number;
|
||||
class Boxed_Number;
|
||||
} // namespace chaiscript
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
namespace dispatch
|
||||
{
|
||||
template<class T, class U> class Proxy_Function_Callable_Impl;
|
||||
template<class T> class Assignable_Proxy_Function_Impl;
|
||||
namespace chaiscript {
|
||||
namespace dispatch {
|
||||
template<class T, class U>
|
||||
class Proxy_Function_Callable_Impl;
|
||||
template<class T>
|
||||
class Assignable_Proxy_Function_Impl;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
namespace detail {
|
||||
/// Used internally for handling a return value from a Proxy_Function call
|
||||
template<typename Ret>
|
||||
struct Handle_Return
|
||||
{
|
||||
template<typename T,
|
||||
typename = typename std::enable_if_t<std::is_trivial_v<typename std::decay_t<T>>>>
|
||||
static Boxed_Value handle(T r)
|
||||
{
|
||||
struct Handle_Return {
|
||||
template<typename T, typename = typename std::enable_if_t<std::is_trivial_v<typename std::decay_t<T>>>>
|
||||
static Boxed_Value handle(T r) {
|
||||
return Boxed_Value(std::move(r), true);
|
||||
}
|
||||
|
||||
template<typename T,
|
||||
typename = typename std::enable_if_t<!(std::is_trivial_v<typename std::decay_t<T>>)>>
|
||||
static Boxed_Value handle(T &&r)
|
||||
{
|
||||
template<typename T, typename = typename std::enable_if_t<!(std::is_trivial_v<typename std::decay_t<T>>)>>
|
||||
static Boxed_Value handle(T &&r) {
|
||||
return Boxed_Value(std::make_shared<T>(std::forward<T>(r)), true);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Ret>
|
||||
struct Handle_Return<const std::function<Ret> &>
|
||||
{
|
||||
struct Handle_Return<const std::function<Ret> &> {
|
||||
static Boxed_Value handle(const std::function<Ret> &f) {
|
||||
return Boxed_Value(
|
||||
chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Proxy_Function_Callable_Impl<Ret, std::function<Ret>>>(f)
|
||||
);
|
||||
chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Proxy_Function_Callable_Impl<Ret, std::function<Ret>>>(f));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Ret>
|
||||
struct Handle_Return<std::function<Ret>> : Handle_Return<const std::function<Ret> &>
|
||||
{
|
||||
struct Handle_Return<std::function<Ret>> : Handle_Return<const std::function<Ret> &> {
|
||||
};
|
||||
|
||||
template<typename Ret>
|
||||
struct Handle_Return<const std::shared_ptr<std::function<Ret>>>
|
||||
{
|
||||
struct Handle_Return<const std::shared_ptr<std::function<Ret>>> {
|
||||
static Boxed_Value handle(const std::shared_ptr<std::function<Ret>> &f) {
|
||||
return Boxed_Value(
|
||||
chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Assignable_Proxy_Function_Impl<Ret>>(std::ref(*f),f)
|
||||
);
|
||||
chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Assignable_Proxy_Function_Impl<Ret>>(std::ref(*f), f));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Ret>
|
||||
struct Handle_Return<const std::shared_ptr<std::function<Ret>> &> : Handle_Return<const std::shared_ptr<std::function<Ret>>>
|
||||
{
|
||||
struct Handle_Return<const std::shared_ptr<std::function<Ret>> &> : Handle_Return<const std::shared_ptr<std::function<Ret>>> {
|
||||
};
|
||||
|
||||
template<typename Ret>
|
||||
struct Handle_Return<std::shared_ptr<std::function<Ret>>> : Handle_Return<const std::shared_ptr<std::function<Ret>>>
|
||||
{
|
||||
struct Handle_Return<std::shared_ptr<std::function<Ret>>> : Handle_Return<const std::shared_ptr<std::function<Ret>>> {
|
||||
};
|
||||
|
||||
template<typename Ret>
|
||||
struct Handle_Return<std::function<Ret> &>
|
||||
{
|
||||
struct Handle_Return<std::function<Ret> &> {
|
||||
static Boxed_Value handle(std::function<Ret> &f) {
|
||||
return Boxed_Value(
|
||||
chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Assignable_Proxy_Function_Impl<Ret>>(std::ref(f),
|
||||
std::shared_ptr<std::function<Ret>>())
|
||||
);
|
||||
return Boxed_Value(chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Assignable_Proxy_Function_Impl<Ret>>(
|
||||
std::ref(f), std::shared_ptr<std::function<Ret>>()));
|
||||
}
|
||||
|
||||
static Boxed_Value handle(const std::function<Ret> &f) {
|
||||
return Boxed_Value(
|
||||
chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Proxy_Function_Callable_Impl<Ret, std::function<Ret>>>(f)
|
||||
);
|
||||
chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Proxy_Function_Callable_Impl<Ret, std::function<Ret>>>(f));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Ret>
|
||||
struct Handle_Return<Ret *&>
|
||||
{
|
||||
static Boxed_Value handle(Ret *p)
|
||||
{
|
||||
return Boxed_Value(p, true);
|
||||
}
|
||||
struct Handle_Return<Ret *&> {
|
||||
static Boxed_Value handle(Ret *p) { return Boxed_Value(p, true); }
|
||||
};
|
||||
|
||||
template<typename Ret>
|
||||
struct Handle_Return<const Ret *&>
|
||||
{
|
||||
static Boxed_Value handle(const Ret *p)
|
||||
{
|
||||
return Boxed_Value(p, true);
|
||||
}
|
||||
struct Handle_Return<const Ret *&> {
|
||||
static Boxed_Value handle(const Ret *p) { return Boxed_Value(p, true); }
|
||||
};
|
||||
|
||||
template<typename Ret>
|
||||
struct Handle_Return<Ret *>
|
||||
{
|
||||
static Boxed_Value handle(Ret *p)
|
||||
{
|
||||
return Boxed_Value(p, true);
|
||||
}
|
||||
struct Handle_Return<Ret *> {
|
||||
static Boxed_Value handle(Ret *p) { return Boxed_Value(p, true); }
|
||||
};
|
||||
|
||||
template<typename Ret>
|
||||
struct Handle_Return<const Ret *>
|
||||
{
|
||||
static Boxed_Value handle(const Ret *p)
|
||||
{
|
||||
return Boxed_Value(p, true);
|
||||
}
|
||||
struct Handle_Return<const Ret *> {
|
||||
static Boxed_Value handle(const Ret *p) { return Boxed_Value(p, true); }
|
||||
};
|
||||
|
||||
template<typename Ret>
|
||||
struct Handle_Return<std::shared_ptr<Ret> &>
|
||||
{
|
||||
static Boxed_Value handle(const std::shared_ptr<Ret> &r)
|
||||
{
|
||||
return Boxed_Value(r, true);
|
||||
}
|
||||
struct Handle_Return<std::shared_ptr<Ret> &> {
|
||||
static Boxed_Value handle(const std::shared_ptr<Ret> &r) { return Boxed_Value(r, true); }
|
||||
};
|
||||
|
||||
template<typename Ret>
|
||||
struct Handle_Return<std::shared_ptr<Ret>> : Handle_Return<std::shared_ptr<Ret> &>
|
||||
{
|
||||
struct Handle_Return<std::shared_ptr<Ret>> : Handle_Return<std::shared_ptr<Ret> &> {
|
||||
};
|
||||
|
||||
template<typename Ret>
|
||||
struct Handle_Return<const std::shared_ptr<Ret> &> : Handle_Return<std::shared_ptr<Ret> &>
|
||||
{
|
||||
struct Handle_Return<const std::shared_ptr<Ret> &> : Handle_Return<std::shared_ptr<Ret> &> {
|
||||
};
|
||||
|
||||
|
||||
template<typename Ret>
|
||||
struct Handle_Return<std::unique_ptr<Ret>> : Handle_Return<std::unique_ptr<Ret> &>
|
||||
{
|
||||
static Boxed_Value handle(std::unique_ptr<Ret> &&r)
|
||||
{
|
||||
return Boxed_Value(std::move(r), true);
|
||||
}
|
||||
struct Handle_Return<std::unique_ptr<Ret>> : Handle_Return<std::unique_ptr<Ret> &> {
|
||||
static Boxed_Value handle(std::unique_ptr<Ret> &&r) { return Boxed_Value(std::move(r), true); }
|
||||
};
|
||||
|
||||
template<typename Ret, bool Ptr>
|
||||
struct Handle_Return_Ref
|
||||
{
|
||||
struct Handle_Return_Ref {
|
||||
template<typename T>
|
||||
static Boxed_Value handle(T &&r)
|
||||
{
|
||||
static Boxed_Value handle(T &&r) {
|
||||
return Boxed_Value(std::cref(r), true);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Ret>
|
||||
struct Handle_Return_Ref<Ret, true>
|
||||
{
|
||||
struct Handle_Return_Ref<Ret, true> {
|
||||
template<typename T>
|
||||
static Boxed_Value handle(T &&r)
|
||||
{
|
||||
static Boxed_Value handle(T &&r) {
|
||||
return Boxed_Value(typename std::remove_reference<decltype(r)>::type{r}, true);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Ret>
|
||||
struct Handle_Return<const Ret &> : Handle_Return_Ref<const Ret &, std::is_pointer<typename std::remove_reference<const Ret &>::type>::value>
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
|
||||
template<typename Ret>
|
||||
struct Handle_Return<const Ret>
|
||||
{
|
||||
static Boxed_Value handle(Ret r)
|
||||
{
|
||||
return Boxed_Value(std::move(r));
|
||||
}
|
||||
struct Handle_Return<const Ret &> : Handle_Return_Ref<const Ret &, std::is_pointer<typename std::remove_reference<const Ret &>::type>::value> {
|
||||
};
|
||||
|
||||
template<typename Ret>
|
||||
struct Handle_Return<Ret &>
|
||||
{
|
||||
static Boxed_Value handle(Ret &r)
|
||||
{
|
||||
return Boxed_Value(std::ref(r));
|
||||
}
|
||||
struct Handle_Return<const Ret> {
|
||||
static Boxed_Value handle(Ret r) { return Boxed_Value(std::move(r)); }
|
||||
};
|
||||
|
||||
template<typename Ret>
|
||||
struct Handle_Return<Ret &> {
|
||||
static Boxed_Value handle(Ret &r) { return Boxed_Value(std::ref(r)); }
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Handle_Return<Boxed_Value>
|
||||
{
|
||||
static Boxed_Value handle(const Boxed_Value &r) noexcept
|
||||
{
|
||||
return r;
|
||||
}
|
||||
struct Handle_Return<Boxed_Value> {
|
||||
static Boxed_Value handle(const Boxed_Value &r) noexcept { return r; }
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Handle_Return<const Boxed_Value> : Handle_Return<Boxed_Value>
|
||||
{
|
||||
struct Handle_Return<const Boxed_Value> : Handle_Return<Boxed_Value> {
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Handle_Return<Boxed_Value &> : Handle_Return<Boxed_Value>
|
||||
{
|
||||
struct Handle_Return<Boxed_Value &> : Handle_Return<Boxed_Value> {
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Handle_Return<const Boxed_Value &> : Handle_Return<Boxed_Value>
|
||||
{
|
||||
struct Handle_Return<const Boxed_Value &> : Handle_Return<Boxed_Value> {
|
||||
};
|
||||
|
||||
/**
|
||||
* Used internally for handling a return value from a Proxy_Function call
|
||||
*/
|
||||
template<>
|
||||
struct Handle_Return<Boxed_Number>
|
||||
{
|
||||
static Boxed_Value handle(const Boxed_Number &r) noexcept
|
||||
{
|
||||
return r.bv;
|
||||
}
|
||||
struct Handle_Return<Boxed_Number> {
|
||||
static Boxed_Value handle(const Boxed_Number &r) noexcept { return r.bv; }
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Handle_Return<const Boxed_Number> : Handle_Return<Boxed_Number>
|
||||
{
|
||||
struct Handle_Return<const Boxed_Number> : Handle_Return<Boxed_Number> {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Used internally for handling a return value from a Proxy_Function call
|
||||
*/
|
||||
template<>
|
||||
struct Handle_Return<void>
|
||||
{
|
||||
static Boxed_Value handle()
|
||||
{
|
||||
return void_var();
|
||||
}
|
||||
struct Handle_Return<void> {
|
||||
static Boxed_Value handle() { return void_var(); }
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace detail
|
||||
} // namespace dispatch
|
||||
} // namespace chaiscript
|
||||
|
||||
#endif
|
||||
|
||||
@ -7,218 +7,178 @@
|
||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||
|
||||
|
||||
#ifndef CHAISCRIPT_OPERATORS_HPP_
|
||||
#define CHAISCRIPT_OPERATORS_HPP_
|
||||
|
||||
#include "../chaiscript_defines.hpp"
|
||||
#include "../dispatchkit/dispatchkit.hpp"
|
||||
#include "register_function.hpp"
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
namespace bootstrap
|
||||
{
|
||||
namespace operators
|
||||
{
|
||||
namespace chaiscript::bootstrap::operators {
|
||||
template<typename T>
|
||||
void assign(Module& m)
|
||||
{
|
||||
m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs = rhs;}), "=");
|
||||
void assign(Module &m) {
|
||||
m.add(chaiscript::fun([](T &lhs, const T &rhs) -> T & { return lhs = rhs; }), "=");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void assign_bitwise_and(Module& m)
|
||||
{
|
||||
m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs &= rhs;}), "&=");
|
||||
void assign_bitwise_and(Module &m) {
|
||||
m.add(chaiscript::fun([](T &lhs, const T &rhs) -> T & { return lhs &= rhs; }), "&=");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void assign_xor(Module& m)
|
||||
{
|
||||
m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs ^= rhs;}), "^=");
|
||||
void assign_xor(Module &m) {
|
||||
m.add(chaiscript::fun([](T &lhs, const T &rhs) -> T & { return lhs ^= rhs; }), "^=");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void assign_bitwise_or(Module& m)
|
||||
{
|
||||
m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs |= rhs;}), "|=");
|
||||
void assign_bitwise_or(Module &m) {
|
||||
m.add(chaiscript::fun([](T &lhs, const T &rhs) -> T & { return lhs |= rhs; }), "|=");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void assign_difference(Module& m)
|
||||
{
|
||||
m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs -= rhs;}), "-=");
|
||||
void assign_difference(Module &m) {
|
||||
m.add(chaiscript::fun([](T &lhs, const T &rhs) -> T & { return lhs -= rhs; }), "-=");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void assign_left_shift(Module& m)
|
||||
{
|
||||
m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs <<= rhs;}), "<<=");
|
||||
void assign_left_shift(Module &m) {
|
||||
m.add(chaiscript::fun([](T &lhs, const T &rhs) -> T & { return lhs <<= rhs; }), "<<=");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void assign_product(Module& m)
|
||||
{
|
||||
m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs <<= rhs;}), "*=");
|
||||
void assign_product(Module &m) {
|
||||
m.add(chaiscript::fun([](T &lhs, const T &rhs) -> T & { return lhs <<= rhs; }), "*=");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void assign_quotient(Module& m)
|
||||
{
|
||||
m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs /= rhs;}), "/=");
|
||||
void assign_quotient(Module &m) {
|
||||
m.add(chaiscript::fun([](T &lhs, const T &rhs) -> T & { return lhs /= rhs; }), "/=");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void assign_remainder(Module& m)
|
||||
{
|
||||
m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs %= rhs;}), "%=");
|
||||
void assign_remainder(Module &m) {
|
||||
m.add(chaiscript::fun([](T &lhs, const T &rhs) -> T & { return lhs %= rhs; }), "%=");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void assign_right_shift(Module& m)
|
||||
{
|
||||
m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs >>= rhs;}), ">>=");
|
||||
void assign_right_shift(Module &m) {
|
||||
m.add(chaiscript::fun([](T &lhs, const T &rhs) -> T & { return lhs >>= rhs; }), ">>=");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void assign_sum(Module& m)
|
||||
{
|
||||
m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs += rhs;}), "+=");
|
||||
void assign_sum(Module &m) {
|
||||
m.add(chaiscript::fun([](T &lhs, const T &rhs) -> T & { return lhs += rhs; }), "+=");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void prefix_decrement(Module& m)
|
||||
{
|
||||
m.add(chaiscript::fun([](T &lhs)->T&{return --lhs;}), "--");
|
||||
void prefix_decrement(Module &m) {
|
||||
m.add(chaiscript::fun([](T &lhs) -> T & { return --lhs; }), "--");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void prefix_increment(Module& m)
|
||||
{
|
||||
m.add(chaiscript::fun([](T &lhs)->T&{return ++lhs;}), "++");
|
||||
void prefix_increment(Module &m) {
|
||||
m.add(chaiscript::fun([](T &lhs) -> T & { return ++lhs; }), "++");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void equal(Module& m)
|
||||
{
|
||||
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs==rhs;}), "==");
|
||||
void equal(Module &m) {
|
||||
m.add(chaiscript::fun([](const T &lhs, const T &rhs) { return lhs == rhs; }), "==");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void greater_than(Module& m)
|
||||
{
|
||||
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs>rhs;}), ">");
|
||||
void greater_than(Module &m) {
|
||||
m.add(chaiscript::fun([](const T &lhs, const T &rhs) { return lhs > rhs; }), ">");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void greater_than_equal(Module& m)
|
||||
{
|
||||
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs>=rhs;}), ">=");
|
||||
void greater_than_equal(Module &m) {
|
||||
m.add(chaiscript::fun([](const T &lhs, const T &rhs) { return lhs >= rhs; }), ">=");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void less_than(Module& m)
|
||||
{
|
||||
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs<rhs;}), "<");
|
||||
void less_than(Module &m) {
|
||||
m.add(chaiscript::fun([](const T &lhs, const T &rhs) { return lhs < rhs; }), "<");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void less_than_equal(Module& m)
|
||||
{
|
||||
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs<=rhs;}), "<=");
|
||||
void less_than_equal(Module &m) {
|
||||
m.add(chaiscript::fun([](const T &lhs, const T &rhs) { return lhs <= rhs; }), "<=");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void logical_compliment(Module& m)
|
||||
{
|
||||
m.add(chaiscript::fun([](const T &lhs){return !lhs;}), "!");
|
||||
void logical_compliment(Module &m) {
|
||||
m.add(chaiscript::fun([](const T &lhs) { return !lhs; }), "!");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void not_equal(Module& m)
|
||||
{
|
||||
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs!=rhs;}), "!=");
|
||||
void not_equal(Module &m) {
|
||||
m.add(chaiscript::fun([](const T &lhs, const T &rhs) { return lhs != rhs; }), "!=");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void addition(Module& m)
|
||||
{
|
||||
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs+rhs;}), "+");
|
||||
void addition(Module &m) {
|
||||
m.add(chaiscript::fun([](const T &lhs, const T &rhs) { return lhs + rhs; }), "+");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void unary_plus(Module& m)
|
||||
{
|
||||
m.add(chaiscript::fun([](const T &lhs){return +lhs;}), "+");
|
||||
void unary_plus(Module &m) {
|
||||
m.add(chaiscript::fun([](const T &lhs) { return +lhs; }), "+");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void subtraction(Module& m)
|
||||
{
|
||||
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs-rhs;}), "-");
|
||||
void subtraction(Module &m) {
|
||||
m.add(chaiscript::fun([](const T &lhs, const T &rhs) { return lhs - rhs; }), "-");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void unary_minus(Module& m)
|
||||
{
|
||||
m.add(chaiscript::fun([](const T &lhs){return -lhs;}), "-");
|
||||
void unary_minus(Module &m) {
|
||||
m.add(chaiscript::fun([](const T &lhs) { return -lhs; }), "-");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void bitwise_and(Module& m)
|
||||
{
|
||||
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs&rhs;}), "&");
|
||||
void bitwise_and(Module &m) {
|
||||
m.add(chaiscript::fun([](const T &lhs, const T &rhs) { return lhs & rhs; }), "&");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void bitwise_compliment(Module& m)
|
||||
{
|
||||
m.add(chaiscript::fun([](const T &lhs){return ~lhs;}), "~");
|
||||
void bitwise_compliment(Module &m) {
|
||||
m.add(chaiscript::fun([](const T &lhs) { return ~lhs; }), "~");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void bitwise_xor(Module& m)
|
||||
{
|
||||
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs^rhs;}), "^");
|
||||
void bitwise_xor(Module &m) {
|
||||
m.add(chaiscript::fun([](const T &lhs, const T &rhs) { return lhs ^ rhs; }), "^");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void bitwise_or(Module& m)
|
||||
{
|
||||
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs|rhs;}), "|");
|
||||
void bitwise_or(Module &m) {
|
||||
m.add(chaiscript::fun([](const T &lhs, const T &rhs) { return lhs | rhs; }), "|");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void division(Module& m)
|
||||
{
|
||||
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs/rhs;}), "/");
|
||||
void division(Module &m) {
|
||||
m.add(chaiscript::fun([](const T &lhs, const T &rhs) { return lhs / rhs; }), "/");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void left_shift(Module& m)
|
||||
{
|
||||
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs<<rhs;}), "<<");
|
||||
void left_shift(Module &m) {
|
||||
m.add(chaiscript::fun([](const T &lhs, const T &rhs) { return lhs << rhs; }), "<<");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void multiplication(Module& m)
|
||||
{
|
||||
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs*rhs;}), "*");
|
||||
void multiplication(Module &m) {
|
||||
m.add(chaiscript::fun([](const T &lhs, const T &rhs) { return lhs * rhs; }), "*");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void remainder(Module& m)
|
||||
{
|
||||
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs%rhs;}), "%");
|
||||
void remainder(Module &m) {
|
||||
m.add(chaiscript::fun([](const T &lhs, const T &rhs) { return lhs % rhs; }), "%");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void right_shift(Module& m)
|
||||
{
|
||||
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs>>rhs;}), ">>");
|
||||
void right_shift(Module &m) {
|
||||
m.add(chaiscript::fun([](const T &lhs, const T &rhs) { return lhs >> rhs; }), ">>");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace chaiscript::bootstrap::operators
|
||||
|
||||
#endif
|
||||
|
||||
@ -7,41 +7,31 @@
|
||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||
|
||||
|
||||
#ifndef CHAISCRIPT_PROXY_CONSTRUCTORS_HPP_
|
||||
#define CHAISCRIPT_PROXY_CONSTRUCTORS_HPP_
|
||||
|
||||
#include "proxy_functions.hpp"
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
namespace dispatch
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
template<typename Class, typename ... Params >
|
||||
Proxy_Function build_constructor_(Class (*)(Params...))
|
||||
{
|
||||
namespace chaiscript::dispatch::detail {
|
||||
template<typename Class, typename... Params>
|
||||
Proxy_Function build_constructor_(Class (*)(Params...)) {
|
||||
if constexpr (!std::is_copy_constructible_v<Class>) {
|
||||
auto call = [](auto && ... param) {
|
||||
return std::make_shared<Class>(std::forward<decltype(param)>(param)...);
|
||||
};
|
||||
auto call = [](auto &&...param) { return std::make_shared<Class>(std::forward<decltype(param)>(param)...); };
|
||||
|
||||
return Proxy_Function(
|
||||
chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Proxy_Function_Callable_Impl<std::shared_ptr<Class> (Params...), decltype(call)>>(call));
|
||||
chaiscript::make_shared<dispatch::Proxy_Function_Base,
|
||||
dispatch::Proxy_Function_Callable_Impl<std::shared_ptr<Class>(Params...), decltype(call)>>(call));
|
||||
} else if constexpr (true) {
|
||||
auto call = [](auto && ... param){
|
||||
return Class(std::forward<decltype(param)>(param)...);
|
||||
};
|
||||
auto call = [](auto &&...param) { return Class(std::forward<decltype(param)>(param)...); };
|
||||
|
||||
return Proxy_Function(
|
||||
chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Proxy_Function_Callable_Impl<Class (Params...), decltype(call)>>(call));
|
||||
}
|
||||
}
|
||||
chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Proxy_Function_Callable_Impl<Class(Params...), decltype(call)>>(
|
||||
call));
|
||||
}
|
||||
}
|
||||
} // namespace chaiscript::dispatch::detail
|
||||
|
||||
|
||||
namespace chaiscript {
|
||||
/// \brief Generates a constructor function for use with ChaiScript
|
||||
///
|
||||
/// \tparam T The signature of the constructor to generate. In the form of: ClassType (ParamType1, ParamType2, ...)
|
||||
@ -54,13 +44,10 @@ namespace chaiscript
|
||||
/// chai.add(constructor<MyClass (int, float)>(), "MyClass");
|
||||
/// \endcode
|
||||
template<typename T>
|
||||
Proxy_Function constructor()
|
||||
{
|
||||
Proxy_Function constructor() {
|
||||
T *f = nullptr;
|
||||
return (dispatch::detail::build_constructor_(f));
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace chaiscript
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -7,43 +7,39 @@
|
||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||
|
||||
|
||||
#ifndef CHAISCRIPT_PROXY_FUNCTIONS_DETAIL_HPP_
|
||||
#define CHAISCRIPT_PROXY_FUNCTIONS_DETAIL_HPP_
|
||||
|
||||
#include <array>
|
||||
#include <functional>
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
#include <array>
|
||||
|
||||
#include "../chaiscript_defines.hpp"
|
||||
#include "boxed_cast.hpp"
|
||||
#include "boxed_value.hpp"
|
||||
#include "function_params.hpp"
|
||||
#include "handle_return.hpp"
|
||||
#include "type_info.hpp"
|
||||
#include "function_params.hpp"
|
||||
|
||||
namespace chaiscript {
|
||||
class Type_Conversions_State;
|
||||
namespace exception {
|
||||
class bad_boxed_cast;
|
||||
} // namespace exception
|
||||
class Type_Conversions_State;
|
||||
namespace exception {
|
||||
class bad_boxed_cast;
|
||||
} // namespace exception
|
||||
} // namespace chaiscript
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
namespace exception
|
||||
{
|
||||
namespace chaiscript {
|
||||
namespace exception {
|
||||
/**
|
||||
* Exception thrown when there is a mismatch in number of
|
||||
* parameters during Proxy_Function execution
|
||||
*/
|
||||
struct arity_error : std::range_error
|
||||
{
|
||||
struct arity_error : std::range_error {
|
||||
arity_error(int t_got, int t_expected)
|
||||
: std::range_error("Function dispatch arity mismatch"),
|
||||
got(t_got), expected(t_expected)
|
||||
{
|
||||
: std::range_error("Function dispatch arity mismatch")
|
||||
, got(t_got)
|
||||
, expected(t_expected) {
|
||||
}
|
||||
|
||||
arity_error(const arity_error &) = default;
|
||||
@ -53,61 +49,52 @@ namespace chaiscript
|
||||
int got;
|
||||
int expected;
|
||||
};
|
||||
}
|
||||
} // namespace exception
|
||||
|
||||
namespace dispatch
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
namespace dispatch {
|
||||
namespace detail {
|
||||
/**
|
||||
* Used by Proxy_Function_Impl to return a list of all param types
|
||||
* it contains.
|
||||
*/
|
||||
template<typename Ret, typename ... Params>
|
||||
std::vector<Type_Info> build_param_type_list(Ret (*)(Params...))
|
||||
{
|
||||
template<typename Ret, typename... Params>
|
||||
std::vector<Type_Info> build_param_type_list(Ret (*)(Params...)) {
|
||||
/// \note somehow this is responsible for a large part of the code generation
|
||||
return { user_type<Ret>(), user_type<Params>()... };
|
||||
return {user_type<Ret>(), user_type<Params>()...};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Used by Proxy_Function_Impl to determine if it is equivalent to another
|
||||
* Proxy_Function_Impl object. This function is primarily used to prevent
|
||||
* registration of two functions with the exact same signatures
|
||||
*/
|
||||
template<typename Ret, typename ... Params>
|
||||
bool compare_types_cast(Ret (*)(Params...),
|
||||
const chaiscript::Function_Params ¶ms, const Type_Conversions_State &t_conversions) noexcept
|
||||
{
|
||||
template<typename Ret, typename... Params>
|
||||
bool compare_types_cast(Ret (*)(Params...), const chaiscript::Function_Params ¶ms, const Type_Conversions_State &t_conversions) noexcept {
|
||||
try {
|
||||
std::vector<Boxed_Value>::size_type i = 0;
|
||||
( boxed_cast<Params>(params[i++], &t_conversions), ... );
|
||||
(boxed_cast<Params>(params[i++], &t_conversions), ...);
|
||||
return true;
|
||||
} catch (const exception::bad_boxed_cast &) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<typename Callable, typename Ret, typename ... Params, size_t ... I>
|
||||
template<typename Callable, typename Ret, typename... Params, size_t... I>
|
||||
Ret call_func(Ret (*)(Params...),
|
||||
std::index_sequence<I...>, const Callable &f,
|
||||
std::index_sequence<I...>,
|
||||
const Callable &f,
|
||||
[[maybe_unused]] const chaiscript::Function_Params ¶ms,
|
||||
[[maybe_unused]] const Type_Conversions_State &t_conversions)
|
||||
{
|
||||
[[maybe_unused]] const Type_Conversions_State &t_conversions) {
|
||||
return f(boxed_cast<Params>(params[I], &t_conversions)...);
|
||||
}
|
||||
|
||||
|
||||
/// Used by Proxy_Function_Impl to perform typesafe execution of a function.
|
||||
/// The function attempts to unbox each parameter to the expected type.
|
||||
/// if any unboxing fails the execution of the function fails and
|
||||
/// the bad_boxed_cast is passed up to the caller.
|
||||
template<typename Callable, typename Ret, typename ... Params>
|
||||
Boxed_Value call_func(Ret (*sig)(Params...), const Callable &f,
|
||||
const chaiscript::Function_Params ¶ms, const Type_Conversions_State &t_conversions)
|
||||
{
|
||||
template<typename Callable, typename Ret, typename... Params>
|
||||
Boxed_Value
|
||||
call_func(Ret (*sig)(Params...), const Callable &f, const chaiscript::Function_Params ¶ms, const Type_Conversions_State &t_conversions) {
|
||||
if constexpr (std::is_same_v<Ret, void>) {
|
||||
call_func(sig, std::index_sequence_for<Params...>{}, f, params, t_conversions);
|
||||
return Handle_Return<void>::handle();
|
||||
@ -116,10 +103,9 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace detail
|
||||
} // namespace dispatch
|
||||
|
||||
} // namespace chaiscript
|
||||
|
||||
#endif
|
||||
|
||||
@ -7,63 +7,55 @@
|
||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||
|
||||
|
||||
#ifndef CHAISCRIPT_REGISTER_FUNCTION_HPP_
|
||||
#define CHAISCRIPT_REGISTER_FUNCTION_HPP_
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
#include "bind_first.hpp"
|
||||
#include "proxy_functions.hpp"
|
||||
#include "function_signature.hpp"
|
||||
#include "proxy_functions.hpp"
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
namespace dispatch::detail
|
||||
{
|
||||
template<typename Obj, typename Param1, typename ... Rest>
|
||||
Param1 get_first_param(Function_Params<Param1, Rest...>, Obj &&obj)
|
||||
{
|
||||
namespace chaiscript {
|
||||
namespace dispatch::detail {
|
||||
template<typename Obj, typename Param1, typename... Rest>
|
||||
Param1 get_first_param(Function_Params<Param1, Rest...>, Obj &&obj) {
|
||||
return static_cast<Param1>(std::forward<Obj>(obj));
|
||||
}
|
||||
|
||||
template<typename Func, bool Is_Noexcept, bool Is_Member, bool Is_MemberObject, bool Is_Object, typename Ret, typename ... Param>
|
||||
auto make_callable_impl(Func &&func, Function_Signature<Ret, Function_Params<Param...>, Is_Noexcept, Is_Member, Is_MemberObject, Is_Object>)
|
||||
{
|
||||
template<typename Func, bool Is_Noexcept, bool Is_Member, bool Is_MemberObject, bool Is_Object, typename Ret, typename... Param>
|
||||
auto make_callable_impl(Func &&func, Function_Signature<Ret, Function_Params<Param...>, Is_Noexcept, Is_Member, Is_MemberObject, Is_Object>) {
|
||||
if constexpr (Is_MemberObject) {
|
||||
// we now that the Param pack will have only one element, so we are safe expanding it here
|
||||
return Proxy_Function(chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Attribute_Access<Ret, std::decay_t<Param>...>>(std::forward<Func>(func)));
|
||||
return Proxy_Function(chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Attribute_Access<Ret, std::decay_t<Param>...>>(
|
||||
std::forward<Func>(func)));
|
||||
} else if constexpr (Is_Member) {
|
||||
// TODO some kind of bug is preventing forwarding of this noexcept for the lambda
|
||||
auto call = [func = std::forward<Func>(func)](auto && obj, auto && ... param) /* noexcept(Is_Noexcept) */ -> decltype(auto) {
|
||||
return (( get_first_param(Function_Params<Param...>{}, obj).*func )(std::forward<decltype(param)>(param)...));
|
||||
auto call = [func = std::forward<Func>(func)](auto &&obj, auto &&...param) /* noexcept(Is_Noexcept) */ -> decltype(auto) {
|
||||
return ((get_first_param(Function_Params<Param...>{}, obj).*func)(std::forward<decltype(param)>(param)...));
|
||||
};
|
||||
return Proxy_Function(
|
||||
chaiscript::make_shared<dispatch::Proxy_Function_Base,
|
||||
dispatch::Proxy_Function_Callable_Impl<Ret (Param...), decltype(call)>>(std::move(call))
|
||||
);
|
||||
chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Proxy_Function_Callable_Impl<Ret(Param...), decltype(call)>>(
|
||||
std::move(call)));
|
||||
} else {
|
||||
return Proxy_Function(
|
||||
chaiscript::make_shared<dispatch::Proxy_Function_Base,
|
||||
dispatch::Proxy_Function_Callable_Impl<Ret (Param...), std::decay_t<Func>>>(std::forward<Func>(func))
|
||||
);
|
||||
chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Proxy_Function_Callable_Impl<Ret(Param...), std::decay_t<Func>>>(
|
||||
std::forward<Func>(func)));
|
||||
}
|
||||
}
|
||||
|
||||
// this version peels off the function object itself from the function signature, when used
|
||||
// on a callable object
|
||||
template<typename Func, typename Ret, typename Object, typename ... Param, bool Is_Noexcept>
|
||||
auto make_callable(Func &&func, Function_Signature<Ret, Function_Params<Object, Param...>, Is_Noexcept, false, false, true>)
|
||||
{
|
||||
template<typename Func, typename Ret, typename Object, typename... Param, bool Is_Noexcept>
|
||||
auto make_callable(Func &&func, Function_Signature<Ret, Function_Params<Object, Param...>, Is_Noexcept, false, false, true>) {
|
||||
return make_callable_impl(std::forward<Func>(func), Function_Signature<Ret, Function_Params<Param...>, Is_Noexcept, false, false, true>{});
|
||||
}
|
||||
|
||||
template<typename Func, typename Ret, typename ... Param, bool Is_Noexcept, bool Is_Member, bool Is_MemberObject>
|
||||
auto make_callable(Func &&func, Function_Signature<Ret, Function_Params<Param...>, Is_Noexcept, Is_Member, Is_MemberObject, false> fs)
|
||||
{
|
||||
template<typename Func, typename Ret, typename... Param, bool Is_Noexcept, bool Is_Member, bool Is_MemberObject>
|
||||
auto make_callable(Func &&func, Function_Signature<Ret, Function_Params<Param...>, Is_Noexcept, Is_Member, Is_MemberObject, false> fs) {
|
||||
return make_callable_impl(std::forward<Func>(func), fs);
|
||||
}
|
||||
}
|
||||
} // namespace dispatch::detail
|
||||
|
||||
/// \brief Creates a new Proxy_Function object from a free function, member function or data member
|
||||
/// \param[in] t Function / member to expose
|
||||
@ -86,13 +78,10 @@ namespace chaiscript
|
||||
///
|
||||
/// \sa \ref adding_functions
|
||||
template<typename T>
|
||||
Proxy_Function fun(T &&t)
|
||||
{
|
||||
Proxy_Function fun(T &&t) {
|
||||
return dispatch::detail::make_callable(std::forward<T>(t), dispatch::detail::function_signature(t));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// \brief Creates a new Proxy_Function object from a free function, member function or data member and binds the first parameter of it
|
||||
/// \param[in] t Function / member to expose
|
||||
/// \param[in] q Value to bind to first parameter
|
||||
@ -112,15 +101,10 @@ namespace chaiscript
|
||||
///
|
||||
/// \sa \ref adding_functions
|
||||
template<typename T, typename Q>
|
||||
Proxy_Function fun(T &&t, const Q &q)
|
||||
{
|
||||
Proxy_Function fun(T &&t, const Q &q) {
|
||||
return fun(detail::bind_first(std::forward<T>(t), q));
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
} // namespace chaiscript
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@ -23,80 +23,70 @@
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#include <cstddef>
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
|
||||
template <std::size_t N, std::size_t alignment = alignof(std::max_align_t)>
|
||||
class arena
|
||||
{
|
||||
template<std::size_t N, std::size_t alignment = alignof(std::max_align_t)>
|
||||
class arena {
|
||||
alignas(alignment) char buf_[N];
|
||||
char* ptr_;
|
||||
char *ptr_;
|
||||
|
||||
public:
|
||||
~arena() {ptr_ = nullptr;}
|
||||
arena() noexcept : ptr_(buf_) {}
|
||||
arena(const arena&) = delete;
|
||||
arena& operator=(const arena&) = delete;
|
||||
~arena() { ptr_ = nullptr; }
|
||||
arena() noexcept
|
||||
: ptr_(buf_) {
|
||||
}
|
||||
arena(const arena &) = delete;
|
||||
arena &operator=(const arena &) = delete;
|
||||
|
||||
template <std::size_t ReqAlign> char* allocate(std::size_t n);
|
||||
void deallocate(char* p, std::size_t n) noexcept;
|
||||
template<std::size_t ReqAlign>
|
||||
char *allocate(std::size_t n);
|
||||
void deallocate(char *p, std::size_t n) noexcept;
|
||||
|
||||
static constexpr std::size_t size() noexcept {return N;}
|
||||
std::size_t used() const noexcept {return static_cast<std::size_t>(ptr_ - buf_);}
|
||||
void reset() noexcept {ptr_ = buf_;}
|
||||
static constexpr std::size_t size() noexcept { return N; }
|
||||
std::size_t used() const noexcept { return static_cast<std::size_t>(ptr_ - buf_); }
|
||||
void reset() noexcept { ptr_ = buf_; }
|
||||
|
||||
private:
|
||||
static
|
||||
std::size_t
|
||||
align_up(std::size_t n) noexcept
|
||||
{return (n + (alignment-1)) & ~(alignment-1);}
|
||||
static std::size_t align_up(std::size_t n) noexcept { return (n + (alignment - 1)) & ~(alignment - 1); }
|
||||
|
||||
bool
|
||||
pointer_in_buffer(char* p) noexcept
|
||||
{return buf_ <= p && p <= buf_ + N;}
|
||||
bool pointer_in_buffer(char *p) noexcept { return buf_ <= p && p <= buf_ + N; }
|
||||
};
|
||||
|
||||
template <std::size_t N, std::size_t alignment>
|
||||
template <std::size_t ReqAlign>
|
||||
char*
|
||||
arena<N, alignment>::allocate(std::size_t n)
|
||||
{
|
||||
template<std::size_t N, std::size_t alignment>
|
||||
template<std::size_t ReqAlign>
|
||||
char *arena<N, alignment>::allocate(std::size_t n) {
|
||||
static_assert(ReqAlign <= alignment, "alignment is too small for this arena");
|
||||
assert(pointer_in_buffer(ptr_) && "short_alloc has outlived arena");
|
||||
auto const aligned_n = align_up(n);
|
||||
if (static_cast<decltype(aligned_n)>(buf_ + N - ptr_) >= aligned_n)
|
||||
{
|
||||
char* r = ptr_;
|
||||
if (static_cast<decltype(aligned_n)>(buf_ + N - ptr_) >= aligned_n) {
|
||||
char *r = ptr_;
|
||||
ptr_ += aligned_n;
|
||||
return r;
|
||||
}
|
||||
|
||||
static_assert(alignment <= alignof(std::max_align_t), "you've chosen an "
|
||||
static_assert(alignment <= alignof(std::max_align_t),
|
||||
"you've chosen an "
|
||||
"alignment that is larger than alignof(std::max_align_t), and "
|
||||
"cannot be guaranteed by normal operator new");
|
||||
return static_cast<char*>(::operator new(n));
|
||||
return static_cast<char *>(::operator new(n));
|
||||
}
|
||||
|
||||
template <std::size_t N, std::size_t alignment>
|
||||
void
|
||||
arena<N, alignment>::deallocate(char* p, std::size_t n) noexcept
|
||||
{
|
||||
template<std::size_t N, std::size_t alignment>
|
||||
void arena<N, alignment>::deallocate(char *p, std::size_t n) noexcept {
|
||||
assert(pointer_in_buffer(ptr_) && "short_alloc has outlived arena");
|
||||
if (pointer_in_buffer(p))
|
||||
{
|
||||
if (pointer_in_buffer(p)) {
|
||||
n = align_up(n);
|
||||
if (p + n == ptr_) {
|
||||
ptr_ = p;
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
::operator delete(p);
|
||||
}
|
||||
}
|
||||
|
||||
template <class T, std::size_t N, std::size_t Align = alignof(std::max_align_t)>
|
||||
class short_alloc
|
||||
{
|
||||
template<class T, std::size_t N, std::size_t Align = alignof(std::max_align_t)>
|
||||
class short_alloc {
|
||||
public:
|
||||
using value_type = T;
|
||||
static auto constexpr alignment = Align;
|
||||
@ -104,56 +94,44 @@ public:
|
||||
using arena_type = arena<size, alignment>;
|
||||
|
||||
private:
|
||||
arena_type& a_;
|
||||
arena_type &a_;
|
||||
|
||||
public:
|
||||
short_alloc(const short_alloc&) = default;
|
||||
short_alloc& operator=(const short_alloc&) = delete;
|
||||
short_alloc(const short_alloc &) = default;
|
||||
short_alloc &operator=(const short_alloc &) = delete;
|
||||
|
||||
explicit short_alloc(arena_type& a) noexcept : a_(a)
|
||||
{
|
||||
static_assert(size % alignment == 0,
|
||||
"size N needs to be a multiple of alignment Align");
|
||||
explicit short_alloc(arena_type &a) noexcept
|
||||
: a_(a) {
|
||||
static_assert(size % alignment == 0, "size N needs to be a multiple of alignment Align");
|
||||
}
|
||||
template <class U>
|
||||
explicit short_alloc(const short_alloc<U, N, alignment>& a) noexcept
|
||||
: a_(a.a_) {}
|
||||
|
||||
template <class _Up> struct rebind {using other = short_alloc<_Up, N, alignment>;};
|
||||
|
||||
T* allocate(std::size_t n)
|
||||
{
|
||||
return reinterpret_cast<T*>(a_.template allocate<alignof(T)>(n*sizeof(T)));
|
||||
}
|
||||
void deallocate(T* p, std::size_t n) noexcept
|
||||
{
|
||||
a_.deallocate(reinterpret_cast<char*>(p), n*sizeof(T));
|
||||
template<class U>
|
||||
explicit short_alloc(const short_alloc<U, N, alignment> &a) noexcept
|
||||
: a_(a.a_) {
|
||||
}
|
||||
|
||||
template <class T1, std::size_t N1, std::size_t A1,
|
||||
class U, std::size_t M, std::size_t A2>
|
||||
friend
|
||||
bool
|
||||
operator==(const short_alloc<T1, N1, A1>& x, const short_alloc<U, M, A2>& y) noexcept;
|
||||
template<class _Up>
|
||||
struct rebind {
|
||||
using other = short_alloc<_Up, N, alignment>;
|
||||
};
|
||||
|
||||
template <class U, std::size_t M, std::size_t A> friend class short_alloc;
|
||||
T *allocate(std::size_t n) { return reinterpret_cast<T *>(a_.template allocate<alignof(T)>(n * sizeof(T))); }
|
||||
void deallocate(T *p, std::size_t n) noexcept { a_.deallocate(reinterpret_cast<char *>(p), n * sizeof(T)); }
|
||||
|
||||
template<class T1, std::size_t N1, std::size_t A1, class U, std::size_t M, std::size_t A2>
|
||||
friend bool operator==(const short_alloc<T1, N1, A1> &x, const short_alloc<U, M, A2> &y) noexcept;
|
||||
|
||||
template<class U, std::size_t M, std::size_t A>
|
||||
friend class short_alloc;
|
||||
};
|
||||
|
||||
template <class T, std::size_t N, std::size_t A1, class U, std::size_t M, std::size_t A2>
|
||||
inline
|
||||
bool
|
||||
operator==(const short_alloc<T, N, A1>& x, const short_alloc<U, M, A2>& y) noexcept
|
||||
{
|
||||
template<class T, std::size_t N, std::size_t A1, class U, std::size_t M, std::size_t A2>
|
||||
inline bool operator==(const short_alloc<T, N, A1> &x, const short_alloc<U, M, A2> &y) noexcept {
|
||||
return N == M && A1 == A2 && &x.a_ == &y.a_;
|
||||
}
|
||||
|
||||
template <class T, std::size_t N, std::size_t A1, class U, std::size_t M, std::size_t A2>
|
||||
inline
|
||||
bool
|
||||
operator!=(const short_alloc<T, N, A1>& x, const short_alloc<U, M, A2>& y) noexcept
|
||||
{
|
||||
template<class T, std::size_t N, std::size_t A1, class U, std::size_t M, std::size_t A2>
|
||||
inline bool operator!=(const short_alloc<T, N, A1> &x, const short_alloc<U, M, A2> &y) noexcept {
|
||||
return !(x == y);
|
||||
}
|
||||
|
||||
#endif // SHORT_ALLOC_HPP
|
||||
|
||||
|
||||
@ -7,10 +7,10 @@
|
||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||
|
||||
|
||||
#ifndef CHAISCRIPT_DYNAMIC_CAST_CONVERSION_HPP_
|
||||
#define CHAISCRIPT_DYNAMIC_CAST_CONVERSION_HPP_
|
||||
|
||||
#include <algorithm>
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
@ -26,37 +26,31 @@
|
||||
#include "boxed_value.hpp"
|
||||
#include "type_info.hpp"
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
namespace exception
|
||||
{
|
||||
namespace chaiscript {
|
||||
namespace exception {
|
||||
/// \brief Error thrown when there's a problem with type conversion
|
||||
class conversion_error: public bad_boxed_cast
|
||||
{
|
||||
class conversion_error : public bad_boxed_cast {
|
||||
public:
|
||||
conversion_error(const Type_Info t_to, const Type_Info t_from, const utility::Static_String what) noexcept
|
||||
: bad_boxed_cast(t_from, (*t_to.bare_type_info()), what), type_to(t_to) {}
|
||||
: bad_boxed_cast(t_from, (*t_to.bare_type_info()), what)
|
||||
, type_to(t_to) {
|
||||
}
|
||||
|
||||
Type_Info type_to;
|
||||
};
|
||||
|
||||
class bad_boxed_dynamic_cast : public bad_boxed_cast
|
||||
{
|
||||
class bad_boxed_dynamic_cast : public bad_boxed_cast {
|
||||
public:
|
||||
bad_boxed_dynamic_cast(const Type_Info &t_from, const std::type_info &t_to,
|
||||
const utility::Static_String &t_what) noexcept
|
||||
: bad_boxed_cast(t_from, t_to, t_what)
|
||||
{
|
||||
bad_boxed_dynamic_cast(const Type_Info &t_from, const std::type_info &t_to, const utility::Static_String &t_what) noexcept
|
||||
: bad_boxed_cast(t_from, t_to, t_what) {
|
||||
}
|
||||
|
||||
bad_boxed_dynamic_cast(const Type_Info &t_from, const std::type_info &t_to) noexcept
|
||||
: bad_boxed_cast(t_from, t_to)
|
||||
{
|
||||
: bad_boxed_cast(t_from, t_to) {
|
||||
}
|
||||
|
||||
explicit bad_boxed_dynamic_cast(const utility::Static_String &w) noexcept
|
||||
: bad_boxed_cast(w)
|
||||
{
|
||||
: bad_boxed_cast(w) {
|
||||
}
|
||||
|
||||
bad_boxed_dynamic_cast(const bad_boxed_dynamic_cast &) = default;
|
||||
@ -64,109 +58,78 @@ namespace chaiscript
|
||||
~bad_boxed_dynamic_cast() noexcept override = default;
|
||||
};
|
||||
|
||||
class bad_boxed_type_cast : public bad_boxed_cast
|
||||
{
|
||||
class bad_boxed_type_cast : public bad_boxed_cast {
|
||||
public:
|
||||
bad_boxed_type_cast(const Type_Info &t_from, const std::type_info &t_to,
|
||||
const utility::Static_String &t_what) noexcept
|
||||
: bad_boxed_cast(t_from, t_to, t_what)
|
||||
{
|
||||
bad_boxed_type_cast(const Type_Info &t_from, const std::type_info &t_to, const utility::Static_String &t_what) noexcept
|
||||
: bad_boxed_cast(t_from, t_to, t_what) {
|
||||
}
|
||||
|
||||
bad_boxed_type_cast(const Type_Info &t_from, const std::type_info &t_to) noexcept
|
||||
: bad_boxed_cast(t_from, t_to)
|
||||
{
|
||||
: bad_boxed_cast(t_from, t_to) {
|
||||
}
|
||||
|
||||
explicit bad_boxed_type_cast(const utility::Static_String &w) noexcept
|
||||
: bad_boxed_cast(w)
|
||||
{
|
||||
: bad_boxed_cast(w) {
|
||||
}
|
||||
|
||||
bad_boxed_type_cast(const bad_boxed_type_cast &) = default;
|
||||
|
||||
~bad_boxed_type_cast() noexcept override = default;
|
||||
};
|
||||
}
|
||||
} // namespace exception
|
||||
|
||||
|
||||
namespace detail
|
||||
{
|
||||
class Type_Conversion_Base
|
||||
{
|
||||
namespace detail {
|
||||
class Type_Conversion_Base {
|
||||
public:
|
||||
virtual Boxed_Value convert(const Boxed_Value &from) const = 0;
|
||||
virtual Boxed_Value convert_down(const Boxed_Value &to) const = 0;
|
||||
|
||||
const Type_Info &to() const noexcept
|
||||
{
|
||||
return m_to;
|
||||
}
|
||||
const Type_Info &from() const noexcept
|
||||
{
|
||||
return m_from;
|
||||
}
|
||||
const Type_Info &to() const noexcept { return m_to; }
|
||||
const Type_Info &from() const noexcept { return m_from; }
|
||||
|
||||
virtual bool bidir() const noexcept
|
||||
{
|
||||
return true;
|
||||
}
|
||||
virtual bool bidir() const noexcept { return true; }
|
||||
|
||||
virtual ~Type_Conversion_Base() = default;
|
||||
|
||||
protected:
|
||||
Type_Conversion_Base(Type_Info t_to, Type_Info t_from)
|
||||
: m_to(std::move(t_to)), m_from(std::move(t_from))
|
||||
{
|
||||
: m_to(std::move(t_to))
|
||||
, m_from(std::move(t_from)) {
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
const Type_Info m_to;
|
||||
const Type_Info m_from;
|
||||
|
||||
};
|
||||
|
||||
template<typename From, typename To>
|
||||
class Static_Caster
|
||||
{
|
||||
class Static_Caster {
|
||||
public:
|
||||
static Boxed_Value cast(const Boxed_Value &t_from)
|
||||
{
|
||||
|
||||
if (t_from.get_type_info().bare_equal(chaiscript::user_type<From>()))
|
||||
{
|
||||
if (t_from.is_pointer())
|
||||
{
|
||||
static Boxed_Value cast(const Boxed_Value &t_from) {
|
||||
if (t_from.get_type_info().bare_equal(chaiscript::user_type<From>())) {
|
||||
if (t_from.is_pointer()) {
|
||||
// Dynamic cast out the contained boxed value, which we know is the type we want
|
||||
if (t_from.is_const())
|
||||
{
|
||||
return Boxed_Value(
|
||||
[&](){
|
||||
if (auto data = std::static_pointer_cast<const To>(detail::Cast_Helper<std::shared_ptr<const From> >::cast(t_from, nullptr)))
|
||||
{
|
||||
if (t_from.is_const()) {
|
||||
return Boxed_Value([&]() {
|
||||
if (auto data
|
||||
= std::static_pointer_cast<const To>(detail::Cast_Helper<std::shared_ptr<const From>>::cast(t_from, nullptr))) {
|
||||
return data;
|
||||
} else {
|
||||
throw std::bad_cast();
|
||||
}
|
||||
}()
|
||||
);
|
||||
}());
|
||||
} else {
|
||||
return Boxed_Value(
|
||||
[&](){
|
||||
if (auto data = std::static_pointer_cast<To>(detail::Cast_Helper<std::shared_ptr<From> >::cast(t_from, nullptr)))
|
||||
{
|
||||
return Boxed_Value([&]() {
|
||||
if (auto data = std::static_pointer_cast<To>(detail::Cast_Helper<std::shared_ptr<From>>::cast(t_from, nullptr))) {
|
||||
return data;
|
||||
} else {
|
||||
throw std::bad_cast();
|
||||
}
|
||||
}()
|
||||
);
|
||||
}());
|
||||
}
|
||||
} else {
|
||||
// Pull the reference out of the contained boxed value, which we know is the type we want
|
||||
if (t_from.is_const())
|
||||
{
|
||||
if (t_from.is_const()) {
|
||||
const From &d = detail::Cast_Helper<const From &>::cast(t_from, nullptr);
|
||||
const To &data = static_cast<const To &>(d);
|
||||
return Boxed_Value(std::cref(data));
|
||||
@ -180,44 +143,33 @@ namespace chaiscript
|
||||
throw chaiscript::exception::bad_boxed_dynamic_cast(t_from.get_type_info(), typeid(To), "Unknown dynamic_cast_conversion");
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
template<typename From, typename To>
|
||||
class Dynamic_Caster
|
||||
{
|
||||
class Dynamic_Caster {
|
||||
public:
|
||||
static Boxed_Value cast(const Boxed_Value &t_from)
|
||||
{
|
||||
if (t_from.get_type_info().bare_equal(chaiscript::user_type<From>()))
|
||||
{
|
||||
if (t_from.is_pointer())
|
||||
{
|
||||
static Boxed_Value cast(const Boxed_Value &t_from) {
|
||||
if (t_from.get_type_info().bare_equal(chaiscript::user_type<From>())) {
|
||||
if (t_from.is_pointer()) {
|
||||
// Dynamic cast out the contained boxed value, which we know is the type we want
|
||||
if (t_from.is_const())
|
||||
{
|
||||
return Boxed_Value(
|
||||
[&](){
|
||||
if (auto data = std::dynamic_pointer_cast<const To>(detail::Cast_Helper<std::shared_ptr<const From> >::cast(t_from, nullptr)))
|
||||
{
|
||||
if (t_from.is_const()) {
|
||||
return Boxed_Value([&]() {
|
||||
if (auto data
|
||||
= std::dynamic_pointer_cast<const To>(detail::Cast_Helper<std::shared_ptr<const From>>::cast(t_from, nullptr))) {
|
||||
return data;
|
||||
} else {
|
||||
throw std::bad_cast();
|
||||
}
|
||||
}()
|
||||
);
|
||||
}());
|
||||
} else {
|
||||
return Boxed_Value(
|
||||
[&](){
|
||||
if (auto data = std::dynamic_pointer_cast<To>(detail::Cast_Helper<std::shared_ptr<From> >::cast(t_from, nullptr)))
|
||||
{
|
||||
return Boxed_Value([&]() {
|
||||
if (auto data = std::dynamic_pointer_cast<To>(detail::Cast_Helper<std::shared_ptr<From>>::cast(t_from, nullptr))) {
|
||||
return data;
|
||||
} else {
|
||||
#ifdef CHAISCRIPT_LIBCPP
|
||||
/// \todo fix this someday after libc++ is fixed.
|
||||
if (std::string(typeid(To).name()).find("Assignable_Proxy_Function") != std::string::npos) {
|
||||
auto from = detail::Cast_Helper<std::shared_ptr<From> >::cast(t_from, nullptr);
|
||||
auto from = detail::Cast_Helper<std::shared_ptr<From>>::cast(t_from, nullptr);
|
||||
if (std::string(typeid(*from).name()).find("Assignable_Proxy_Function_Impl") != std::string::npos) {
|
||||
return std::static_pointer_cast<To>(from);
|
||||
}
|
||||
@ -225,13 +177,11 @@ namespace chaiscript
|
||||
#endif
|
||||
throw std::bad_cast();
|
||||
}
|
||||
}()
|
||||
);
|
||||
}());
|
||||
}
|
||||
} else {
|
||||
// Pull the reference out of the contained boxed value, which we know is the type we want
|
||||
if (t_from.is_const())
|
||||
{
|
||||
if (t_from.is_const()) {
|
||||
const From &d = detail::Cast_Helper<const From &>::cast(t_from, nullptr);
|
||||
const To &data = dynamic_cast<const To &>(d);
|
||||
return Boxed_Value(std::cref(data));
|
||||
@ -245,113 +195,80 @@ namespace chaiscript
|
||||
throw chaiscript::exception::bad_boxed_dynamic_cast(t_from.get_type_info(), typeid(To), "Unknown dynamic_cast_conversion");
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
template<typename Base, typename Derived>
|
||||
class Dynamic_Conversion_Impl : public Type_Conversion_Base
|
||||
{
|
||||
class Dynamic_Conversion_Impl : public Type_Conversion_Base {
|
||||
public:
|
||||
Dynamic_Conversion_Impl()
|
||||
: Type_Conversion_Base(chaiscript::user_type<Base>(), chaiscript::user_type<Derived>())
|
||||
{
|
||||
: Type_Conversion_Base(chaiscript::user_type<Base>(), chaiscript::user_type<Derived>()) {
|
||||
}
|
||||
|
||||
Boxed_Value convert_down(const Boxed_Value &t_base) const override
|
||||
{
|
||||
return Dynamic_Caster<Base, Derived>::cast(t_base);
|
||||
}
|
||||
Boxed_Value convert_down(const Boxed_Value &t_base) const override { return Dynamic_Caster<Base, Derived>::cast(t_base); }
|
||||
|
||||
Boxed_Value convert(const Boxed_Value &t_derived) const override
|
||||
{
|
||||
return Static_Caster<Derived, Base>::cast(t_derived);
|
||||
}
|
||||
Boxed_Value convert(const Boxed_Value &t_derived) const override { return Static_Caster<Derived, Base>::cast(t_derived); }
|
||||
};
|
||||
|
||||
template<typename Base, typename Derived>
|
||||
class Static_Conversion_Impl : public Type_Conversion_Base
|
||||
{
|
||||
class Static_Conversion_Impl : public Type_Conversion_Base {
|
||||
public:
|
||||
Static_Conversion_Impl()
|
||||
: Type_Conversion_Base(chaiscript::user_type<Base>(), chaiscript::user_type<Derived>())
|
||||
{
|
||||
: Type_Conversion_Base(chaiscript::user_type<Base>(), chaiscript::user_type<Derived>()) {
|
||||
}
|
||||
|
||||
Boxed_Value convert_down(const Boxed_Value &t_base) const override
|
||||
{
|
||||
throw chaiscript::exception::bad_boxed_dynamic_cast(t_base.get_type_info(), typeid(Derived),
|
||||
Boxed_Value convert_down(const Boxed_Value &t_base) const override {
|
||||
throw chaiscript::exception::bad_boxed_dynamic_cast(t_base.get_type_info(),
|
||||
typeid(Derived),
|
||||
"Unable to cast down inheritance hierarchy with non-polymorphic types");
|
||||
}
|
||||
|
||||
bool bidir() const noexcept override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
bool bidir() const noexcept override { return false; }
|
||||
|
||||
Boxed_Value convert(const Boxed_Value &t_derived) const override
|
||||
{
|
||||
return Static_Caster<Derived, Base>::cast(t_derived);
|
||||
}
|
||||
Boxed_Value convert(const Boxed_Value &t_derived) const override { return Static_Caster<Derived, Base>::cast(t_derived); }
|
||||
};
|
||||
|
||||
|
||||
|
||||
template<typename Callable>
|
||||
class Type_Conversion_Impl : public Type_Conversion_Base
|
||||
{
|
||||
class Type_Conversion_Impl : public Type_Conversion_Base {
|
||||
public:
|
||||
Type_Conversion_Impl(Type_Info t_from, Type_Info t_to, Callable t_func)
|
||||
: Type_Conversion_Base(t_to, t_from),
|
||||
m_func(std::move(t_func))
|
||||
{
|
||||
: Type_Conversion_Base(t_to, t_from)
|
||||
, m_func(std::move(t_func)) {
|
||||
}
|
||||
|
||||
Boxed_Value convert_down(const Boxed_Value &) const override
|
||||
{
|
||||
Boxed_Value convert_down(const Boxed_Value &) const override {
|
||||
throw chaiscript::exception::bad_boxed_type_cast("No conversion exists");
|
||||
}
|
||||
|
||||
Boxed_Value convert(const Boxed_Value &t_from) const override
|
||||
{
|
||||
Boxed_Value convert(const Boxed_Value &t_from) const override {
|
||||
/// \todo better handling of errors from the conversion function
|
||||
return m_func(t_from);
|
||||
}
|
||||
|
||||
bool bidir() const noexcept override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool bidir() const noexcept override { return false; }
|
||||
|
||||
private:
|
||||
Callable m_func;
|
||||
};
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
class Type_Conversions
|
||||
{
|
||||
class Type_Conversions {
|
||||
public:
|
||||
struct Conversion_Saves
|
||||
{
|
||||
struct Conversion_Saves {
|
||||
bool enabled = false;
|
||||
std::vector<Boxed_Value> saves;
|
||||
};
|
||||
|
||||
struct Less_Than
|
||||
{
|
||||
bool operator()(const std::type_info *t_lhs, const std::type_info *t_rhs) const noexcept
|
||||
{
|
||||
struct Less_Than {
|
||||
bool operator()(const std::type_info *t_lhs, const std::type_info *t_rhs) const noexcept {
|
||||
return *t_lhs != *t_rhs && t_lhs->before(*t_rhs);
|
||||
}
|
||||
};
|
||||
|
||||
Type_Conversions()
|
||||
: m_mutex(),
|
||||
m_conversions(),
|
||||
m_convertableTypes(),
|
||||
m_num_types(0)
|
||||
{
|
||||
: m_mutex()
|
||||
, m_conversions()
|
||||
, m_convertableTypes()
|
||||
, m_num_types(0) {
|
||||
}
|
||||
|
||||
Type_Conversions(const Type_Conversions &t_other) = delete;
|
||||
@ -360,11 +277,9 @@ namespace chaiscript
|
||||
Type_Conversions &operator=(const Type_Conversions &) = delete;
|
||||
Type_Conversions &operator=(Type_Conversions &&) = delete;
|
||||
|
||||
const std::set<const std::type_info *, Less_Than> &thread_cache() const
|
||||
{
|
||||
const std::set<const std::type_info *, Less_Than> &thread_cache() const {
|
||||
auto &cache = *m_thread_cache;
|
||||
if (cache.size() != m_num_types)
|
||||
{
|
||||
if (cache.size() != m_num_types) {
|
||||
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||
cache = m_convertableTypes;
|
||||
}
|
||||
@ -372,13 +287,10 @@ namespace chaiscript
|
||||
return cache;
|
||||
}
|
||||
|
||||
|
||||
void add_conversion(const std::shared_ptr<detail::Type_Conversion_Base> &conversion)
|
||||
{
|
||||
void add_conversion(const std::shared_ptr<detail::Type_Conversion_Base> &conversion) {
|
||||
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||
if (find_bidir(conversion->to(), conversion->from()) != m_conversions.end()) {
|
||||
throw exception::conversion_error(conversion->to(), conversion->from(),
|
||||
"Trying to re-insert an existing conversion!");
|
||||
throw exception::conversion_error(conversion->to(), conversion->from(), "Trying to re-insert an existing conversion!");
|
||||
}
|
||||
m_conversions.insert(conversion);
|
||||
m_convertableTypes.insert({conversion->to().bare_type_info(), conversion->from().bare_type_info()});
|
||||
@ -386,23 +298,19 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool convertable_type() const noexcept
|
||||
{
|
||||
bool convertable_type() const noexcept {
|
||||
const auto type = user_type<T>().bare_type_info();
|
||||
return thread_cache().count(type) != 0;
|
||||
}
|
||||
|
||||
template<typename To, typename From>
|
||||
bool converts() const noexcept
|
||||
{
|
||||
bool converts() const noexcept {
|
||||
return converts(user_type<To>(), user_type<From>());
|
||||
}
|
||||
|
||||
bool converts(const Type_Info &to, const Type_Info &from) const noexcept
|
||||
{
|
||||
bool converts(const Type_Info &to, const Type_Info &from) const noexcept {
|
||||
const auto &types = thread_cache();
|
||||
if (types.count(to.bare_type_info()) != 0 && types.count(from.bare_type_info()) != 0)
|
||||
{
|
||||
if (types.count(to.bare_type_info()) != 0 && types.count(from.bare_type_info()) != 0) {
|
||||
return has_conversion(to, from);
|
||||
} else {
|
||||
return false;
|
||||
@ -410,23 +318,21 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
template<typename To>
|
||||
Boxed_Value boxed_type_conversion(Conversion_Saves &t_saves, const Boxed_Value &from) const
|
||||
{
|
||||
Boxed_Value boxed_type_conversion(Conversion_Saves &t_saves, const Boxed_Value &from) const {
|
||||
return boxed_type_conversion(user_type<To>(), t_saves, from);
|
||||
}
|
||||
|
||||
template<typename From>
|
||||
Boxed_Value boxed_type_down_conversion(Conversion_Saves &t_saves, const Boxed_Value &to) const
|
||||
{
|
||||
Boxed_Value boxed_type_down_conversion(Conversion_Saves &t_saves, const Boxed_Value &to) const {
|
||||
return boxed_type_down_conversion(user_type<From>(), t_saves, to);
|
||||
}
|
||||
|
||||
|
||||
Boxed_Value boxed_type_conversion(const Type_Info &to, Conversion_Saves &t_saves, const Boxed_Value &from) const
|
||||
{
|
||||
Boxed_Value boxed_type_conversion(const Type_Info &to, Conversion_Saves &t_saves, const Boxed_Value &from) const {
|
||||
try {
|
||||
Boxed_Value ret = get_conversion(to, from.get_type_info())->convert(from);
|
||||
if (t_saves.enabled) { t_saves.saves.push_back(ret); }
|
||||
if (t_saves.enabled) {
|
||||
t_saves.saves.push_back(ret);
|
||||
}
|
||||
return ret;
|
||||
} catch (const std::out_of_range &) {
|
||||
throw exception::bad_boxed_dynamic_cast(from.get_type_info(), *to.bare_type_info(), "No known conversion");
|
||||
@ -435,11 +341,12 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
Boxed_Value boxed_type_down_conversion(const Type_Info &from, Conversion_Saves &t_saves, const Boxed_Value &to) const
|
||||
{
|
||||
Boxed_Value boxed_type_down_conversion(const Type_Info &from, Conversion_Saves &t_saves, const Boxed_Value &to) const {
|
||||
try {
|
||||
Boxed_Value ret = get_conversion(to.get_type_info(), from)->convert_down(to);
|
||||
if (t_saves.enabled) { t_saves.saves.push_back(ret); }
|
||||
if (t_saves.enabled) {
|
||||
t_saves.saves.push_back(ret);
|
||||
}
|
||||
return ret;
|
||||
} catch (const std::out_of_range &) {
|
||||
throw exception::bad_boxed_dynamic_cast(to.get_type_info(), *from.bare_type_info(), "No known conversion");
|
||||
@ -448,75 +355,57 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
static void enable_conversion_saves(Conversion_Saves &t_saves, bool t_val)
|
||||
{
|
||||
t_saves.enabled = t_val;
|
||||
}
|
||||
static void enable_conversion_saves(Conversion_Saves &t_saves, bool t_val) { t_saves.enabled = t_val; }
|
||||
|
||||
std::vector<Boxed_Value> take_saves(Conversion_Saves &t_saves)
|
||||
{
|
||||
std::vector<Boxed_Value> take_saves(Conversion_Saves &t_saves) {
|
||||
std::vector<Boxed_Value> ret;
|
||||
std::swap(ret, t_saves.saves);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool has_conversion(const Type_Info &to, const Type_Info &from) const
|
||||
{
|
||||
bool has_conversion(const Type_Info &to, const Type_Info &from) const {
|
||||
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||
return find_bidir(to, from) != m_conversions.end();
|
||||
}
|
||||
|
||||
std::shared_ptr<detail::Type_Conversion_Base> get_conversion(const Type_Info &to, const Type_Info &from) const
|
||||
{
|
||||
std::shared_ptr<detail::Type_Conversion_Base> get_conversion(const Type_Info &to, const Type_Info &from) const {
|
||||
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||
|
||||
const auto itr = find(to, from);
|
||||
|
||||
if (itr != m_conversions.end())
|
||||
{
|
||||
if (itr != m_conversions.end()) {
|
||||
return *itr;
|
||||
} else {
|
||||
throw std::out_of_range(std::string("No such conversion exists from ") + from.bare_name() + " to " + to.bare_name());
|
||||
}
|
||||
}
|
||||
|
||||
Conversion_Saves &conversion_saves() const noexcept {
|
||||
return *m_conversion_saves;
|
||||
}
|
||||
Conversion_Saves &conversion_saves() const noexcept { return *m_conversion_saves; }
|
||||
|
||||
private:
|
||||
std::set<std::shared_ptr<detail::Type_Conversion_Base> >::const_iterator find_bidir(
|
||||
const Type_Info &to, const Type_Info &from) const
|
||||
{
|
||||
return std::find_if(m_conversions.begin(), m_conversions.end(),
|
||||
[&to, &from](const std::shared_ptr<detail::Type_Conversion_Base> &conversion) -> bool
|
||||
{
|
||||
std::set<std::shared_ptr<detail::Type_Conversion_Base>>::const_iterator find_bidir(const Type_Info &to, const Type_Info &from) const {
|
||||
return std::find_if(m_conversions.begin(),
|
||||
m_conversions.end(),
|
||||
[&to, &from](const std::shared_ptr<detail::Type_Conversion_Base> &conversion) -> bool {
|
||||
return (conversion->to().bare_equal(to) && conversion->from().bare_equal(from))
|
||||
|| (conversion->bidir() && conversion->from().bare_equal(to) && conversion->to().bare_equal(from));
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
std::set<std::shared_ptr<detail::Type_Conversion_Base> >::const_iterator find(
|
||||
const Type_Info &to, const Type_Info &from) const
|
||||
{
|
||||
return std::find_if(m_conversions.begin(), m_conversions.end(),
|
||||
[&to, &from](const std::shared_ptr<detail::Type_Conversion_Base> &conversion)
|
||||
{
|
||||
std::set<std::shared_ptr<detail::Type_Conversion_Base>>::const_iterator find(const Type_Info &to, const Type_Info &from) const {
|
||||
return std::find_if(m_conversions.begin(),
|
||||
m_conversions.end(),
|
||||
[&to, &from](const std::shared_ptr<detail::Type_Conversion_Base> &conversion) {
|
||||
return conversion->to().bare_equal(to) && conversion->from().bare_equal(from);
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
std::set<std::shared_ptr<detail::Type_Conversion_Base>> get_conversions() const
|
||||
{
|
||||
std::set<std::shared_ptr<detail::Type_Conversion_Base>> get_conversions() const {
|
||||
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||
|
||||
return m_conversions;
|
||||
}
|
||||
|
||||
|
||||
|
||||
mutable chaiscript::detail::threading::shared_mutex m_mutex;
|
||||
std::set<std::shared_ptr<detail::Type_Conversion_Base>> m_conversions;
|
||||
std::set<const std::type_info *, Less_Than> m_convertableTypes;
|
||||
@ -525,27 +414,18 @@ namespace chaiscript
|
||||
mutable chaiscript::detail::threading::Thread_Storage<Conversion_Saves> m_conversion_saves;
|
||||
};
|
||||
|
||||
class Type_Conversions_State
|
||||
{
|
||||
class Type_Conversions_State {
|
||||
public:
|
||||
Type_Conversions_State(const Type_Conversions &t_conversions,
|
||||
Type_Conversions::Conversion_Saves &t_saves)
|
||||
: m_conversions(t_conversions),
|
||||
m_saves(t_saves)
|
||||
{
|
||||
Type_Conversions_State(const Type_Conversions &t_conversions, Type_Conversions::Conversion_Saves &t_saves)
|
||||
: m_conversions(t_conversions)
|
||||
, m_saves(t_saves) {
|
||||
}
|
||||
|
||||
const Type_Conversions *operator->() const noexcept {
|
||||
return &m_conversions.get();
|
||||
}
|
||||
const Type_Conversions *operator->() const noexcept { return &m_conversions.get(); }
|
||||
|
||||
const Type_Conversions *get() const noexcept {
|
||||
return &m_conversions.get();
|
||||
}
|
||||
const Type_Conversions *get() const noexcept { return &m_conversions.get(); }
|
||||
|
||||
Type_Conversions::Conversion_Saves &saves() const noexcept {
|
||||
return m_saves;
|
||||
}
|
||||
Type_Conversions::Conversion_Saves &saves() const noexcept { return m_saves; }
|
||||
|
||||
private:
|
||||
std::reference_wrapper<const Type_Conversions> m_conversions;
|
||||
@ -576,53 +456,50 @@ namespace chaiscript
|
||||
/// \endcode
|
||||
///
|
||||
template<typename Base, typename Derived>
|
||||
Type_Conversion base_class()
|
||||
{
|
||||
//Can only be used with related polymorphic types
|
||||
//may be expanded some day to support conversions other than child -> parent
|
||||
static_assert(std::is_base_of<Base,Derived>::value, "Classes are not related by inheritance");
|
||||
Type_Conversion base_class() {
|
||||
// Can only be used with related polymorphic types
|
||||
// may be expanded some day to support conversions other than child -> parent
|
||||
static_assert(std::is_base_of<Base, Derived>::value, "Classes are not related by inheritance");
|
||||
|
||||
if constexpr(std::is_polymorphic<Base>::value && std::is_polymorphic<Derived>::value) {
|
||||
if constexpr (std::is_polymorphic<Base>::value && std::is_polymorphic<Derived>::value) {
|
||||
return chaiscript::make_shared<detail::Type_Conversion_Base, detail::Dynamic_Conversion_Impl<Base, Derived>>();
|
||||
} else {
|
||||
return chaiscript::make_shared<detail::Type_Conversion_Base, detail::Static_Conversion_Impl<Base, Derived>>();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<typename Callable>
|
||||
Type_Conversion type_conversion(const Type_Info &t_from, const Type_Info &t_to,
|
||||
const Callable &t_func)
|
||||
{
|
||||
Type_Conversion type_conversion(const Type_Info &t_from, const Type_Info &t_to, const Callable &t_func) {
|
||||
return chaiscript::make_shared<detail::Type_Conversion_Base, detail::Type_Conversion_Impl<Callable>>(t_from, t_to, t_func);
|
||||
}
|
||||
|
||||
template<typename From, typename To, typename Callable>
|
||||
Type_Conversion type_conversion(const Callable &t_function)
|
||||
{
|
||||
Type_Conversion type_conversion(const Callable &t_function) {
|
||||
auto func = [t_function](const Boxed_Value &t_bv) -> Boxed_Value {
|
||||
// not even attempting to call boxed_cast so that we don't get caught in some call recursion
|
||||
return chaiscript::Boxed_Value(t_function(detail::Cast_Helper<const From &>::cast(t_bv, nullptr)));
|
||||
};
|
||||
|
||||
return chaiscript::make_shared<detail::Type_Conversion_Base, detail::Type_Conversion_Impl<decltype(func)>>(user_type<From>(), user_type<To>(), func);
|
||||
return chaiscript::make_shared<detail::Type_Conversion_Base, detail::Type_Conversion_Impl<decltype(func)>>(user_type<From>(),
|
||||
user_type<To>(),
|
||||
func);
|
||||
}
|
||||
|
||||
template<typename From, typename To>
|
||||
Type_Conversion type_conversion()
|
||||
{
|
||||
Type_Conversion type_conversion() {
|
||||
static_assert(std::is_convertible<From, To>::value, "Types are not automatically convertible");
|
||||
auto func = [](const Boxed_Value &t_bv) -> Boxed_Value {
|
||||
// not even attempting to call boxed_cast so that we don't get caught in some call recursion
|
||||
return chaiscript::Boxed_Value(To(detail::Cast_Helper<From>::cast(t_bv, nullptr)));
|
||||
};
|
||||
|
||||
return chaiscript::make_shared<detail::Type_Conversion_Base, detail::Type_Conversion_Impl<decltype(func)>>(user_type<From>(), user_type<To>(), func);
|
||||
return chaiscript::make_shared<detail::Type_Conversion_Base, detail::Type_Conversion_Impl<decltype(func)>>(user_type<From>(),
|
||||
user_type<To>(),
|
||||
func);
|
||||
}
|
||||
|
||||
template<typename To>
|
||||
Type_Conversion vector_conversion()
|
||||
{
|
||||
Type_Conversion vector_conversion() {
|
||||
auto func = [](const Boxed_Value &t_bv) -> Boxed_Value {
|
||||
const std::vector<Boxed_Value> &from_vec = detail::Cast_Helper<const std::vector<Boxed_Value> &>::cast(t_bv, nullptr);
|
||||
|
||||
@ -635,14 +512,16 @@ namespace chaiscript
|
||||
return Boxed_Value(std::move(vec));
|
||||
};
|
||||
|
||||
return chaiscript::make_shared<detail::Type_Conversion_Base, detail::Type_Conversion_Impl<decltype(func)>>(user_type<std::vector<Boxed_Value>>(), user_type<To>(), func);
|
||||
return chaiscript::make_shared<detail::Type_Conversion_Base, detail::Type_Conversion_Impl<decltype(func)>>(user_type<std::vector<Boxed_Value>>(),
|
||||
user_type<To>(),
|
||||
func);
|
||||
}
|
||||
|
||||
template<typename To>
|
||||
Type_Conversion map_conversion()
|
||||
{
|
||||
Type_Conversion map_conversion() {
|
||||
auto func = [](const Boxed_Value &t_bv) -> Boxed_Value {
|
||||
const std::map<std::string, Boxed_Value> &from_map = detail::Cast_Helper<const std::map<std::string, Boxed_Value> &>::cast(t_bv, nullptr);
|
||||
const std::map<std::string, Boxed_Value> &from_map
|
||||
= detail::Cast_Helper<const std::map<std::string, Boxed_Value> &>::cast(t_bv, nullptr);
|
||||
|
||||
To map;
|
||||
for (const std::pair<const std::string, Boxed_Value> &p : from_map) {
|
||||
@ -652,9 +531,9 @@ namespace chaiscript
|
||||
return Boxed_Value(std::move(map));
|
||||
};
|
||||
|
||||
return chaiscript::make_shared<detail::Type_Conversion_Base, detail::Type_Conversion_Impl<decltype(func)>>(user_type<std::map<std::string, Boxed_Value>>(), user_type<To>(), func);
|
||||
return chaiscript::make_shared<detail::Type_Conversion_Base, detail::Type_Conversion_Impl<decltype(func)>>(
|
||||
user_type<std::map<std::string, Boxed_Value>>(), user_type<To>(), func);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace chaiscript
|
||||
|
||||
#endif
|
||||
|
||||
@ -7,81 +7,58 @@
|
||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||
|
||||
|
||||
#ifndef CHAISCRIPT_TYPE_INFO_HPP_
|
||||
#define CHAISCRIPT_TYPE_INFO_HPP_
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <typeinfo>
|
||||
#include <string>
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
namespace chaiscript {
|
||||
namespace detail {
|
||||
template<typename T>
|
||||
struct Bare_Type
|
||||
{
|
||||
struct Bare_Type {
|
||||
using type = typename std::remove_cv<typename std::remove_pointer<typename std::remove_reference<T>::type>::type>::type;
|
||||
};
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/// \brief Compile time deduced information about a type
|
||||
class Type_Info
|
||||
{
|
||||
class Type_Info {
|
||||
public:
|
||||
constexpr Type_Info(const bool t_is_const, const bool t_is_reference, const bool t_is_pointer, const bool t_is_void,
|
||||
const bool t_is_arithmetic, const std::type_info *t_ti, const std::type_info *t_bare_ti) noexcept
|
||||
: m_type_info(t_ti), m_bare_type_info(t_bare_ti),
|
||||
m_flags((static_cast<unsigned int>(t_is_const) << is_const_flag)
|
||||
+ (static_cast<unsigned int>(t_is_reference) << is_reference_flag)
|
||||
+ (static_cast<unsigned int>(t_is_pointer) << is_pointer_flag)
|
||||
+ (static_cast<unsigned int>(t_is_void) << is_void_flag)
|
||||
+ (static_cast<unsigned int>(t_is_arithmetic) << is_arithmetic_flag))
|
||||
{
|
||||
constexpr Type_Info(const bool t_is_const,
|
||||
const bool t_is_reference,
|
||||
const bool t_is_pointer,
|
||||
const bool t_is_void,
|
||||
const bool t_is_arithmetic,
|
||||
const std::type_info *t_ti,
|
||||
const std::type_info *t_bare_ti) noexcept
|
||||
: m_type_info(t_ti)
|
||||
, m_bare_type_info(t_bare_ti)
|
||||
, m_flags((static_cast<unsigned int>(t_is_const) << is_const_flag) + (static_cast<unsigned int>(t_is_reference) << is_reference_flag)
|
||||
+ (static_cast<unsigned int>(t_is_pointer) << is_pointer_flag) + (static_cast<unsigned int>(t_is_void) << is_void_flag)
|
||||
+ (static_cast<unsigned int>(t_is_arithmetic) << is_arithmetic_flag)) {
|
||||
}
|
||||
|
||||
constexpr Type_Info() noexcept = default;
|
||||
|
||||
bool operator<(const Type_Info &ti) const noexcept
|
||||
{
|
||||
return m_type_info->before(*ti.m_type_info);
|
||||
bool operator<(const Type_Info &ti) const noexcept { return m_type_info->before(*ti.m_type_info); }
|
||||
|
||||
constexpr bool operator!=(const Type_Info &ti) const noexcept { return !(operator==(ti)); }
|
||||
|
||||
constexpr bool operator!=(const std::type_info &ti) const noexcept { return !(operator==(ti)); }
|
||||
|
||||
constexpr bool operator==(const Type_Info &ti) const noexcept {
|
||||
return ti.m_type_info == m_type_info || *ti.m_type_info == *m_type_info;
|
||||
}
|
||||
|
||||
constexpr bool operator!=(const Type_Info &ti) const noexcept
|
||||
{
|
||||
return !(operator==(ti));
|
||||
constexpr bool operator==(const std::type_info &ti) const noexcept { return !is_undef() && (*m_type_info) == ti; }
|
||||
|
||||
constexpr bool bare_equal(const Type_Info &ti) const noexcept {
|
||||
return ti.m_bare_type_info == m_bare_type_info || *ti.m_bare_type_info == *m_bare_type_info;
|
||||
}
|
||||
|
||||
constexpr bool operator!=(const std::type_info &ti) const noexcept
|
||||
{
|
||||
return !(operator==(ti));
|
||||
}
|
||||
|
||||
constexpr bool operator==(const Type_Info &ti) const noexcept
|
||||
{
|
||||
return ti.m_type_info == m_type_info
|
||||
|| *ti.m_type_info == *m_type_info;
|
||||
}
|
||||
|
||||
constexpr bool operator==(const std::type_info &ti) const noexcept
|
||||
{
|
||||
return !is_undef() && (*m_type_info) == ti;
|
||||
}
|
||||
|
||||
constexpr bool bare_equal(const Type_Info &ti) const noexcept
|
||||
{
|
||||
return ti.m_bare_type_info == m_bare_type_info
|
||||
|| *ti.m_bare_type_info == *m_bare_type_info;
|
||||
}
|
||||
|
||||
constexpr bool bare_equal_type_info(const std::type_info &ti) const noexcept
|
||||
{
|
||||
return !is_undef() && (*m_bare_type_info) == ti;
|
||||
}
|
||||
constexpr bool bare_equal_type_info(const std::type_info &ti) const noexcept { return !is_undef() && (*m_bare_type_info) == ti; }
|
||||
|
||||
constexpr bool is_const() const noexcept { return (m_flags & (1 << is_const_flag)) != 0; }
|
||||
constexpr bool is_reference() const noexcept { return (m_flags & (1 << is_reference_flag)) != 0; }
|
||||
@ -90,33 +67,27 @@ namespace chaiscript
|
||||
constexpr bool is_undef() const noexcept { return (m_flags & (1 << is_undef_flag)) != 0; }
|
||||
constexpr bool is_pointer() const noexcept { return (m_flags & (1 << is_pointer_flag)) != 0; }
|
||||
|
||||
const char * name() const noexcept
|
||||
{
|
||||
if (!is_undef())
|
||||
{
|
||||
const char *name() const noexcept {
|
||||
if (!is_undef()) {
|
||||
return m_type_info->name();
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
const char * bare_name() const noexcept
|
||||
{
|
||||
if (!is_undef())
|
||||
{
|
||||
const char *bare_name() const noexcept {
|
||||
if (!is_undef()) {
|
||||
return m_bare_type_info->name();
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
constexpr const std::type_info *bare_type_info() const noexcept
|
||||
{
|
||||
return m_bare_type_info;
|
||||
}
|
||||
constexpr const std::type_info *bare_type_info() const noexcept { return m_bare_type_info; }
|
||||
|
||||
private:
|
||||
struct Unknown_Type {};
|
||||
struct Unknown_Type {
|
||||
};
|
||||
|
||||
const std::type_info *m_type_info = &typeid(Unknown_Type);
|
||||
const std::type_info *m_bare_type_info = &typeid(Unknown_Type);
|
||||
@ -129,16 +100,14 @@ namespace chaiscript
|
||||
unsigned int m_flags = (1 << is_undef_flag);
|
||||
};
|
||||
|
||||
namespace detail
|
||||
{
|
||||
namespace detail {
|
||||
/// Helper used to create a Type_Info object
|
||||
template<typename T>
|
||||
struct Get_Type_Info
|
||||
{
|
||||
constexpr static Type_Info get() noexcept
|
||||
{
|
||||
struct Get_Type_Info {
|
||||
constexpr static Type_Info get() noexcept {
|
||||
return Type_Info(std::is_const<typename std::remove_pointer<typename std::remove_reference<T>::type>::type>::value,
|
||||
std::is_reference<T>::value, std::is_pointer<T>::value,
|
||||
std::is_reference<T>::value,
|
||||
std::is_pointer<T>::value,
|
||||
std::is_void<T>::value,
|
||||
(std::is_arithmetic<T>::value || std::is_arithmetic<typename std::remove_reference<T>::type>::value)
|
||||
&& !std::is_same<typename std::remove_const<typename std::remove_reference<T>::type>::type, bool>::value,
|
||||
@ -148,63 +117,66 @@ namespace chaiscript
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct Get_Type_Info<std::shared_ptr<T> >
|
||||
{
|
||||
constexpr static Type_Info get() noexcept
|
||||
{
|
||||
return Type_Info(std::is_const<T>::value, std::is_reference<T>::value, std::is_pointer<T>::value,
|
||||
struct Get_Type_Info<std::shared_ptr<T>> {
|
||||
constexpr static Type_Info get() noexcept {
|
||||
return Type_Info(std::is_const<T>::value,
|
||||
std::is_reference<T>::value,
|
||||
std::is_pointer<T>::value,
|
||||
std::is_void<T>::value,
|
||||
std::is_arithmetic<T>::value && !std::is_same<typename std::remove_const<typename std::remove_reference<T>::type>::type, bool>::value,
|
||||
&typeid(std::shared_ptr<T> ),
|
||||
std::is_arithmetic<T>::value
|
||||
&& !std::is_same<typename std::remove_const<typename std::remove_reference<T>::type>::type, bool>::value,
|
||||
&typeid(std::shared_ptr<T>),
|
||||
&typeid(typename Bare_Type<T>::type));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct Get_Type_Info<std::shared_ptr<T> &> : Get_Type_Info<std::shared_ptr<T>>
|
||||
{
|
||||
struct Get_Type_Info<std::shared_ptr<T> &> : Get_Type_Info<std::shared_ptr<T>> {
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct Get_Type_Info<const std::shared_ptr<T> &>
|
||||
{
|
||||
constexpr static Type_Info get() noexcept
|
||||
{
|
||||
return Type_Info(std::is_const<T>::value, std::is_reference<T>::value, std::is_pointer<T>::value,
|
||||
struct Get_Type_Info<const std::shared_ptr<T> &> {
|
||||
constexpr static Type_Info get() noexcept {
|
||||
return Type_Info(std::is_const<T>::value,
|
||||
std::is_reference<T>::value,
|
||||
std::is_pointer<T>::value,
|
||||
std::is_void<T>::value,
|
||||
std::is_arithmetic<T>::value && !std::is_same<typename std::remove_const<typename std::remove_reference<T>::type>::type, bool>::value,
|
||||
std::is_arithmetic<T>::value
|
||||
&& !std::is_same<typename std::remove_const<typename std::remove_reference<T>::type>::type, bool>::value,
|
||||
&typeid(const std::shared_ptr<T> &),
|
||||
&typeid(typename Bare_Type<T>::type));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct Get_Type_Info<std::reference_wrapper<T> >
|
||||
{
|
||||
constexpr static Type_Info get() noexcept
|
||||
{
|
||||
return Type_Info(std::is_const<T>::value, std::is_reference<T>::value, std::is_pointer<T>::value,
|
||||
struct Get_Type_Info<std::reference_wrapper<T>> {
|
||||
constexpr static Type_Info get() noexcept {
|
||||
return Type_Info(std::is_const<T>::value,
|
||||
std::is_reference<T>::value,
|
||||
std::is_pointer<T>::value,
|
||||
std::is_void<T>::value,
|
||||
std::is_arithmetic<T>::value && !std::is_same<typename std::remove_const<typename std::remove_reference<T>::type>::type, bool>::value,
|
||||
&typeid(std::reference_wrapper<T> ),
|
||||
std::is_arithmetic<T>::value
|
||||
&& !std::is_same<typename std::remove_const<typename std::remove_reference<T>::type>::type, bool>::value,
|
||||
&typeid(std::reference_wrapper<T>),
|
||||
&typeid(typename Bare_Type<T>::type));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct Get_Type_Info<const std::reference_wrapper<T> &>
|
||||
{
|
||||
constexpr static Type_Info get() noexcept
|
||||
{
|
||||
return Type_Info(std::is_const<T>::value, std::is_reference<T>::value, std::is_pointer<T>::value,
|
||||
struct Get_Type_Info<const std::reference_wrapper<T> &> {
|
||||
constexpr static Type_Info get() noexcept {
|
||||
return Type_Info(std::is_const<T>::value,
|
||||
std::is_reference<T>::value,
|
||||
std::is_pointer<T>::value,
|
||||
std::is_void<T>::value,
|
||||
std::is_arithmetic<T>::value && !std::is_same<typename std::remove_const<typename std::remove_reference<T>::type>::type, bool>::value,
|
||||
std::is_arithmetic<T>::value
|
||||
&& !std::is_same<typename std::remove_const<typename std::remove_reference<T>::type>::type, bool>::value,
|
||||
&typeid(const std::reference_wrapper<T> &),
|
||||
&typeid(typename Bare_Type<T>::type));
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
/// \brief Creates a Type_Info object representing the type passed in
|
||||
/// \tparam T Type of object to get a Type_Info for, derived from the passed in parameter
|
||||
@ -216,12 +188,10 @@ namespace chaiscript
|
||||
/// chaiscript::Type_Info ti = chaiscript::user_type(i);
|
||||
/// \endcode
|
||||
template<typename T>
|
||||
constexpr Type_Info user_type(const T &/*t*/) noexcept
|
||||
{
|
||||
constexpr Type_Info user_type(const T & /*t*/) noexcept {
|
||||
return detail::Get_Type_Info<T>::get();
|
||||
}
|
||||
|
||||
|
||||
/// \brief Creates a Type_Info object representing the templated type
|
||||
/// \tparam T Type of object to get a Type_Info for
|
||||
/// \return Type_Info for T
|
||||
@ -231,12 +201,10 @@ namespace chaiscript
|
||||
/// chaiscript::Type_Info ti = chaiscript::user_type<int>();
|
||||
/// \endcode
|
||||
template<typename T>
|
||||
constexpr Type_Info user_type() noexcept
|
||||
{
|
||||
constexpr Type_Info user_type() noexcept {
|
||||
return detail::Get_Type_Info<T>::get();
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace chaiscript
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@ -7,7 +7,6 @@
|
||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||
|
||||
|
||||
#ifndef CHAISCRIPT_ALGEBRAIC_HPP_
|
||||
#define CHAISCRIPT_ALGEBRAIC_HPP_
|
||||
|
||||
@ -15,43 +14,51 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
|
||||
namespace chaiscript {
|
||||
struct Operators {
|
||||
enum class Opers
|
||||
{
|
||||
equals, less_than, greater_than, less_than_equal, greater_than_equal, not_equal,
|
||||
assign, pre_increment, pre_decrement, assign_product, assign_sum,
|
||||
assign_quotient, assign_difference,
|
||||
assign_bitwise_and, assign_bitwise_or, assign_shift_left, assign_shift_right,
|
||||
assign_remainder, assign_bitwise_xor,
|
||||
shift_left, shift_right, remainder, bitwise_and, bitwise_or, bitwise_xor, bitwise_complement,
|
||||
sum, quotient, product, difference, unary_plus, unary_minus,
|
||||
enum class Opers {
|
||||
equals,
|
||||
less_than,
|
||||
greater_than,
|
||||
less_than_equal,
|
||||
greater_than_equal,
|
||||
not_equal,
|
||||
assign,
|
||||
pre_increment,
|
||||
pre_decrement,
|
||||
assign_product,
|
||||
assign_sum,
|
||||
assign_quotient,
|
||||
assign_difference,
|
||||
assign_bitwise_and,
|
||||
assign_bitwise_or,
|
||||
assign_shift_left,
|
||||
assign_shift_right,
|
||||
assign_remainder,
|
||||
assign_bitwise_xor,
|
||||
shift_left,
|
||||
shift_right,
|
||||
remainder,
|
||||
bitwise_and,
|
||||
bitwise_or,
|
||||
bitwise_xor,
|
||||
bitwise_complement,
|
||||
sum,
|
||||
quotient,
|
||||
product,
|
||||
difference,
|
||||
unary_plus,
|
||||
unary_minus,
|
||||
invalid
|
||||
};
|
||||
|
||||
constexpr static const char *to_string(Opers t_oper) noexcept {
|
||||
constexpr const char *opers[] = {
|
||||
"",
|
||||
"==", "<", ">", "<=", ">=", "!=",
|
||||
"",
|
||||
"=", "++", "--", "*=", "+=",
|
||||
"/=", "-=",
|
||||
"",
|
||||
"&=", "|=", "<<=", ">>=",
|
||||
"%=", "^=",
|
||||
"",
|
||||
"<<", ">>", "%", "&", "|", "^", "~",
|
||||
"",
|
||||
"+", "/", "*", "-", "+", "-",
|
||||
""
|
||||
};
|
||||
constexpr const char *opers[]
|
||||
= {"", "==", "<", ">", "<=", ">=", "!=", "", "=", "++", "--", "*=", "+=", "/=", "-=", "", "&=", "|=", "<<=", ">>=", "%=", "^=", "", "<<", ">>", "%", "&", "|", "^", "~", "", "+", "/", "*", "-", "+", "-", ""};
|
||||
return opers[static_cast<int>(t_oper)];
|
||||
}
|
||||
|
||||
constexpr static Opers to_operator(std::string_view t_str, bool t_is_unary = false) noexcept
|
||||
{
|
||||
constexpr static Opers to_operator(std::string_view t_str, bool t_is_unary = false) noexcept {
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4307)
|
||||
@ -59,45 +66,102 @@ namespace chaiscript
|
||||
|
||||
const auto op_hash = utility::hash(t_str);
|
||||
switch (op_hash) {
|
||||
case utility::hash("=="): { return Opers::equals; }
|
||||
case utility::hash("<"): { return Opers::less_than; }
|
||||
case utility::hash(">"): { return Opers::greater_than; }
|
||||
case utility::hash("<="): { return Opers::less_than_equal; }
|
||||
case utility::hash(">="): { return Opers::greater_than_equal; }
|
||||
case utility::hash("!="): { return Opers::not_equal; }
|
||||
case utility::hash("="): { return Opers::assign; }
|
||||
case utility::hash("++"): { return Opers::pre_increment; }
|
||||
case utility::hash("--"): { return Opers::pre_decrement; }
|
||||
case utility::hash("*="): { return Opers::assign_product; }
|
||||
case utility::hash("+="): { return Opers::assign_sum; }
|
||||
case utility::hash("-="): { return Opers::assign_difference; }
|
||||
case utility::hash("&="): { return Opers::assign_bitwise_and; }
|
||||
case utility::hash("|="): { return Opers::assign_bitwise_or; }
|
||||
case utility::hash("<<="): { return Opers::assign_shift_left; }
|
||||
case utility::hash(">>="): { return Opers::assign_shift_right; }
|
||||
case utility::hash("%="): { return Opers::assign_remainder; }
|
||||
case utility::hash("^="): { return Opers::assign_bitwise_xor; }
|
||||
case utility::hash("<<"): { return Opers::shift_left; }
|
||||
case utility::hash(">>"): { return Opers::shift_right; }
|
||||
case utility::hash("%"): { return Opers::remainder; }
|
||||
case utility::hash("&"): { return Opers::bitwise_and; }
|
||||
case utility::hash("|"): { return Opers::bitwise_or; }
|
||||
case utility::hash("^"): { return Opers::bitwise_xor; }
|
||||
case utility::hash("~"): { return Opers::bitwise_complement; }
|
||||
case utility::hash("+"): { return t_is_unary ? Opers::unary_plus : Opers::sum; }
|
||||
case utility::hash("-"): { return t_is_unary ? Opers::unary_minus : Opers::difference; }
|
||||
case utility::hash("/"): { return Opers::quotient; }
|
||||
case utility::hash("*"): { return Opers::product; }
|
||||
default: { return Opers::invalid; }
|
||||
case utility::hash("=="): {
|
||||
return Opers::equals;
|
||||
}
|
||||
case utility::hash("<"): {
|
||||
return Opers::less_than;
|
||||
}
|
||||
case utility::hash(">"): {
|
||||
return Opers::greater_than;
|
||||
}
|
||||
case utility::hash("<="): {
|
||||
return Opers::less_than_equal;
|
||||
}
|
||||
case utility::hash(">="): {
|
||||
return Opers::greater_than_equal;
|
||||
}
|
||||
case utility::hash("!="): {
|
||||
return Opers::not_equal;
|
||||
}
|
||||
case utility::hash("="): {
|
||||
return Opers::assign;
|
||||
}
|
||||
case utility::hash("++"): {
|
||||
return Opers::pre_increment;
|
||||
}
|
||||
case utility::hash("--"): {
|
||||
return Opers::pre_decrement;
|
||||
}
|
||||
case utility::hash("*="): {
|
||||
return Opers::assign_product;
|
||||
}
|
||||
case utility::hash("+="): {
|
||||
return Opers::assign_sum;
|
||||
}
|
||||
case utility::hash("-="): {
|
||||
return Opers::assign_difference;
|
||||
}
|
||||
case utility::hash("&="): {
|
||||
return Opers::assign_bitwise_and;
|
||||
}
|
||||
case utility::hash("|="): {
|
||||
return Opers::assign_bitwise_or;
|
||||
}
|
||||
case utility::hash("<<="): {
|
||||
return Opers::assign_shift_left;
|
||||
}
|
||||
case utility::hash(">>="): {
|
||||
return Opers::assign_shift_right;
|
||||
}
|
||||
case utility::hash("%="): {
|
||||
return Opers::assign_remainder;
|
||||
}
|
||||
case utility::hash("^="): {
|
||||
return Opers::assign_bitwise_xor;
|
||||
}
|
||||
case utility::hash("<<"): {
|
||||
return Opers::shift_left;
|
||||
}
|
||||
case utility::hash(">>"): {
|
||||
return Opers::shift_right;
|
||||
}
|
||||
case utility::hash("%"): {
|
||||
return Opers::remainder;
|
||||
}
|
||||
case utility::hash("&"): {
|
||||
return Opers::bitwise_and;
|
||||
}
|
||||
case utility::hash("|"): {
|
||||
return Opers::bitwise_or;
|
||||
}
|
||||
case utility::hash("^"): {
|
||||
return Opers::bitwise_xor;
|
||||
}
|
||||
case utility::hash("~"): {
|
||||
return Opers::bitwise_complement;
|
||||
}
|
||||
case utility::hash("+"): {
|
||||
return t_is_unary ? Opers::unary_plus : Opers::sum;
|
||||
}
|
||||
case utility::hash("-"): {
|
||||
return t_is_unary ? Opers::unary_minus : Opers::difference;
|
||||
}
|
||||
case utility::hash("/"): {
|
||||
return Opers::quotient;
|
||||
}
|
||||
case utility::hash("*"): {
|
||||
return Opers::product;
|
||||
}
|
||||
default: {
|
||||
return Opers::invalid;
|
||||
}
|
||||
}
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
} // namespace chaiscript
|
||||
|
||||
#endif /* _CHAISCRIPT_ALGEBRAIC_HPP */
|
||||
|
||||
|
||||
@ -7,7 +7,6 @@
|
||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||
|
||||
|
||||
#ifndef CHAISCRIPT_COMMON_HPP_
|
||||
#define CHAISCRIPT_COMMON_HPP_
|
||||
|
||||
@ -26,53 +25,26 @@
|
||||
#include <unordered_set>
|
||||
|
||||
namespace chaiscript {
|
||||
struct AST_Node;
|
||||
struct AST_Node;
|
||||
} // namespace chaiscript
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
namespace chaiscript {
|
||||
struct Name_Validator {
|
||||
template<typename T>
|
||||
static bool is_reserved_word(const T &s) noexcept
|
||||
{
|
||||
const static std::unordered_set<std::uint32_t> words{
|
||||
utility::hash("def"),
|
||||
utility::hash("fun"),
|
||||
utility::hash("while"),
|
||||
utility::hash("for"),
|
||||
utility::hash("if"),
|
||||
utility::hash("else"),
|
||||
utility::hash("&&"),
|
||||
utility::hash("||"),
|
||||
utility::hash(","),
|
||||
utility::hash("auto"),
|
||||
utility::hash("return"),
|
||||
utility::hash("break"),
|
||||
utility::hash("true"),
|
||||
utility::hash("false"),
|
||||
utility::hash("class"),
|
||||
utility::hash("attr"),
|
||||
utility::hash("var"),
|
||||
utility::hash("global"),
|
||||
utility::hash("GLOBAL"),
|
||||
utility::hash("_"),
|
||||
utility::hash("__LINE__"),
|
||||
utility::hash("__FILE__"),
|
||||
utility::hash("__FUNC__"),
|
||||
utility::hash("__CLASS__")};
|
||||
static bool is_reserved_word(const T &s) noexcept {
|
||||
const static std::unordered_set<std::uint32_t>
|
||||
words{utility::hash("def"), utility::hash("fun"), utility::hash("while"), utility::hash("for"), utility::hash("if"), utility::hash("else"), utility::hash("&&"), utility::hash("||"), utility::hash(","), utility::hash("auto"), utility::hash("return"), utility::hash("break"), utility::hash("true"), utility::hash("false"), utility::hash("class"), utility::hash("attr"), utility::hash("var"), utility::hash("global"), utility::hash("GLOBAL"), utility::hash("_"), utility::hash("__LINE__"), utility::hash("__FILE__"), utility::hash("__FUNC__"), utility::hash("__CLASS__")};
|
||||
|
||||
return words.count(utility::hash(s)) == 1;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static bool valid_object_name(const T &name) noexcept
|
||||
{
|
||||
static bool valid_object_name(const T &name) noexcept {
|
||||
return name.find("::") == std::string::npos && !is_reserved_word(name);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static void validate_object_name(const T &name)
|
||||
{
|
||||
static void validate_object_name(const T &name) {
|
||||
if (is_reserved_word(name)) {
|
||||
throw exception::reserved_word_error(std::string(name));
|
||||
}
|
||||
@ -86,32 +58,78 @@ namespace chaiscript
|
||||
/// Signature of module entry point that all binary loadable modules must implement.
|
||||
using Create_Module_Func = ModulePtr (*)();
|
||||
|
||||
|
||||
/// Types of AST nodes available to the parser and eval
|
||||
enum class AST_Node_Type { Id, Fun_Call, Unused_Return_Fun_Call, Arg_List, Equation, Var_Decl, Assign_Decl,
|
||||
Array_Call, Dot_Access,
|
||||
Lambda, Block, Scopeless_Block, Def, While, If, For, Ranged_For, Inline_Array, Inline_Map, Return, File, Prefix, Break, Continue, Map_Pair, Value_Range,
|
||||
Inline_Range, Try, Catch, Finally, Method, Attr_Decl,
|
||||
Logical_And, Logical_Or, Reference, Switch, Case, Default, Noop, Class, Binary, Arg, Global_Decl, Constant, Compiled
|
||||
enum class AST_Node_Type {
|
||||
Id,
|
||||
Fun_Call,
|
||||
Unused_Return_Fun_Call,
|
||||
Arg_List,
|
||||
Equation,
|
||||
Var_Decl,
|
||||
Assign_Decl,
|
||||
Array_Call,
|
||||
Dot_Access,
|
||||
Lambda,
|
||||
Block,
|
||||
Scopeless_Block,
|
||||
Def,
|
||||
While,
|
||||
If,
|
||||
For,
|
||||
Ranged_For,
|
||||
Inline_Array,
|
||||
Inline_Map,
|
||||
Return,
|
||||
File,
|
||||
Prefix,
|
||||
Break,
|
||||
Continue,
|
||||
Map_Pair,
|
||||
Value_Range,
|
||||
Inline_Range,
|
||||
Try,
|
||||
Catch,
|
||||
Finally,
|
||||
Method,
|
||||
Attr_Decl,
|
||||
Logical_And,
|
||||
Logical_Or,
|
||||
Reference,
|
||||
Switch,
|
||||
Case,
|
||||
Default,
|
||||
Noop,
|
||||
Class,
|
||||
Binary,
|
||||
Arg,
|
||||
Global_Decl,
|
||||
Constant,
|
||||
Compiled
|
||||
};
|
||||
|
||||
enum class Operator_Precedence { Ternary_Cond, Logical_Or,
|
||||
Logical_And, Bitwise_Or, Bitwise_Xor, Bitwise_And,
|
||||
Equality, Comparison, Shift, Addition, Multiplication, Prefix };
|
||||
enum class Operator_Precedence {
|
||||
Ternary_Cond,
|
||||
Logical_Or,
|
||||
Logical_And,
|
||||
Bitwise_Or,
|
||||
Bitwise_Xor,
|
||||
Bitwise_And,
|
||||
Equality,
|
||||
Comparison,
|
||||
Shift,
|
||||
Addition,
|
||||
Multiplication,
|
||||
Prefix
|
||||
};
|
||||
|
||||
namespace
|
||||
{
|
||||
namespace {
|
||||
/// Helper lookup to get the name of each node type
|
||||
constexpr const char *ast_node_type_to_string(AST_Node_Type ast_node_type) noexcept {
|
||||
constexpr const char * const ast_node_types[] = { "Id", "Fun_Call", "Unused_Return_Fun_Call", "Arg_List", "Equation", "Var_Decl", "Assign_Decl",
|
||||
"Array_Call", "Dot_Access",
|
||||
"Lambda", "Block", "Scopeless_Block", "Def", "While", "If", "For", "Ranged_For", "Inline_Array", "Inline_Map", "Return", "File", "Prefix", "Break", "Continue", "Map_Pair", "Value_Range",
|
||||
"Inline_Range", "Try", "Catch", "Finally", "Method", "Attr_Decl",
|
||||
"Logical_And", "Logical_Or", "Reference", "Switch", "Case", "Default", "Noop", "Class", "Binary", "Arg", "Global_Decl", "Constant", "Compiled"};
|
||||
constexpr const char *const ast_node_types[] = {"Id", "Fun_Call", "Unused_Return_Fun_Call", "Arg_List", "Equation", "Var_Decl", "Assign_Decl", "Array_Call", "Dot_Access", "Lambda", "Block", "Scopeless_Block", "Def", "While", "If", "For", "Ranged_For", "Inline_Array", "Inline_Map", "Return", "File", "Prefix", "Break", "Continue", "Map_Pair", "Value_Range", "Inline_Range", "Try", "Catch", "Finally", "Method", "Attr_Decl", "Logical_And", "Logical_Or", "Reference", "Switch", "Case", "Default", "Noop", "Class", "Binary", "Arg", "Global_Decl", "Constant", "Compiled"};
|
||||
|
||||
return ast_node_types[static_cast<int>(ast_node_type)];
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
/// \brief Convenience type for file positions
|
||||
struct File_Position {
|
||||
@ -119,64 +137,57 @@ namespace chaiscript
|
||||
int column = 0;
|
||||
|
||||
constexpr File_Position(int t_file_line, int t_file_column) noexcept
|
||||
: line(t_file_line), column(t_file_column) { }
|
||||
: line(t_file_line)
|
||||
, column(t_file_column) {
|
||||
}
|
||||
|
||||
constexpr File_Position() noexcept = default;
|
||||
};
|
||||
|
||||
struct Parse_Location {
|
||||
Parse_Location(std::string t_fname="", const int t_start_line=0, const int t_start_col=0,
|
||||
const int t_end_line=0, const int t_end_col=0)
|
||||
: start(t_start_line, t_start_col),
|
||||
end(t_end_line, t_end_col),
|
||||
filename(std::make_shared<std::string>(std::move(t_fname)))
|
||||
{
|
||||
Parse_Location(std::string t_fname = "", const int t_start_line = 0, const int t_start_col = 0, const int t_end_line = 0, const int t_end_col = 0)
|
||||
: start(t_start_line, t_start_col)
|
||||
, end(t_end_line, t_end_col)
|
||||
, filename(std::make_shared<std::string>(std::move(t_fname))) {
|
||||
}
|
||||
|
||||
Parse_Location(std::shared_ptr<std::string> t_fname, const int t_start_line=0, const int t_start_col=0,
|
||||
const int t_end_line=0, const int t_end_col=0)
|
||||
: start(t_start_line, t_start_col),
|
||||
end(t_end_line, t_end_col),
|
||||
filename(std::move(t_fname))
|
||||
{
|
||||
Parse_Location(std::shared_ptr<std::string> t_fname,
|
||||
const int t_start_line = 0,
|
||||
const int t_start_col = 0,
|
||||
const int t_end_line = 0,
|
||||
const int t_end_col = 0)
|
||||
: start(t_start_line, t_start_col)
|
||||
, end(t_end_line, t_end_col)
|
||||
, filename(std::move(t_fname)) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
File_Position start;
|
||||
File_Position end;
|
||||
std::shared_ptr<std::string> filename;
|
||||
};
|
||||
|
||||
|
||||
/// \brief Typedef for pointers to AST_Node objects. Used in building of the AST_Node tree
|
||||
using AST_NodePtr = std::unique_ptr<AST_Node>;
|
||||
using AST_NodePtr_Const = std::unique_ptr<const AST_Node>;
|
||||
|
||||
struct AST_Node_Trace;
|
||||
|
||||
|
||||
/// \brief Classes which may be thrown during error cases when ChaiScript is executing.
|
||||
namespace exception
|
||||
{
|
||||
namespace exception {
|
||||
/// \brief Thrown if an error occurs while attempting to load a binary module
|
||||
struct load_module_error : std::runtime_error
|
||||
{
|
||||
struct load_module_error : std::runtime_error {
|
||||
explicit load_module_error(const std::string &t_reason)
|
||||
: std::runtime_error(t_reason)
|
||||
{
|
||||
: std::runtime_error(t_reason) {
|
||||
}
|
||||
|
||||
load_module_error(const std::string &t_name, const std::vector<load_module_error> &t_errors)
|
||||
: std::runtime_error(format_error(t_name, t_errors))
|
||||
{
|
||||
: std::runtime_error(format_error(t_name, t_errors)) {
|
||||
}
|
||||
|
||||
load_module_error(const load_module_error &) = default;
|
||||
~load_module_error() noexcept override = default;
|
||||
|
||||
static std::string format_error(const std::string &t_name, const std::vector<load_module_error> &t_errors)
|
||||
{
|
||||
static std::string format_error(const std::string &t_name, const std::vector<load_module_error> &t_errors) {
|
||||
std::stringstream ss;
|
||||
ss << "Error loading module '" << t_name << "'\n"
|
||||
<< " The following locations were searched:\n";
|
||||
@ -189,7 +200,6 @@ namespace chaiscript
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/// Errors generated during parsing or evaluation
|
||||
struct eval_error : std::runtime_error {
|
||||
std::string reason;
|
||||
@ -198,48 +208,55 @@ namespace chaiscript
|
||||
std::string detail;
|
||||
std::vector<AST_Node_Trace> call_stack;
|
||||
|
||||
eval_error(const std::string &t_why, const File_Position &t_where, const std::string &t_fname,
|
||||
const std::vector<Boxed_Value> &t_parameters, const std::vector<chaiscript::Const_Proxy_Function> &t_functions,
|
||||
eval_error(const std::string &t_why,
|
||||
const File_Position &t_where,
|
||||
const std::string &t_fname,
|
||||
const std::vector<Boxed_Value> &t_parameters,
|
||||
const std::vector<chaiscript::Const_Proxy_Function> &t_functions,
|
||||
bool t_dot_notation,
|
||||
const chaiscript::detail::Dispatch_Engine &t_ss) noexcept :
|
||||
std::runtime_error(format(t_why, t_where, t_fname, t_parameters, t_dot_notation, t_ss)),
|
||||
reason(t_why), start_position(t_where), filename(t_fname), detail(format_detail(t_functions, t_dot_notation, t_ss))
|
||||
{}
|
||||
const chaiscript::detail::Dispatch_Engine &t_ss) noexcept
|
||||
: std::runtime_error(format(t_why, t_where, t_fname, t_parameters, t_dot_notation, t_ss))
|
||||
, reason(t_why)
|
||||
, start_position(t_where)
|
||||
, filename(t_fname)
|
||||
, detail(format_detail(t_functions, t_dot_notation, t_ss)) {
|
||||
}
|
||||
|
||||
eval_error(const std::string &t_why,
|
||||
const std::vector<Boxed_Value> &t_parameters, const std::vector<chaiscript::Const_Proxy_Function> &t_functions,
|
||||
const std::vector<Boxed_Value> &t_parameters,
|
||||
const std::vector<chaiscript::Const_Proxy_Function> &t_functions,
|
||||
bool t_dot_notation,
|
||||
const chaiscript::detail::Dispatch_Engine &t_ss) noexcept :
|
||||
std::runtime_error(format(t_why, t_parameters, t_dot_notation, t_ss)),
|
||||
reason(t_why), detail(format_detail(t_functions, t_dot_notation, t_ss))
|
||||
{}
|
||||
const chaiscript::detail::Dispatch_Engine &t_ss) noexcept
|
||||
: std::runtime_error(format(t_why, t_parameters, t_dot_notation, t_ss))
|
||||
, reason(t_why)
|
||||
, detail(format_detail(t_functions, t_dot_notation, t_ss)) {
|
||||
}
|
||||
|
||||
|
||||
eval_error(const std::string &t_why, const File_Position &t_where, const std::string &t_fname) noexcept :
|
||||
std::runtime_error(format(t_why, t_where, t_fname)),
|
||||
reason(t_why), start_position(t_where), filename(t_fname)
|
||||
{}
|
||||
eval_error(const std::string &t_why, const File_Position &t_where, const std::string &t_fname) noexcept
|
||||
: std::runtime_error(format(t_why, t_where, t_fname))
|
||||
, reason(t_why)
|
||||
, start_position(t_where)
|
||||
, filename(t_fname) {
|
||||
}
|
||||
|
||||
explicit eval_error(const std::string &t_why) noexcept
|
||||
: std::runtime_error("Error: \"" + t_why + "\" "),
|
||||
reason(t_why)
|
||||
{}
|
||||
: std::runtime_error("Error: \"" + t_why + "\" ")
|
||||
, reason(t_why) {
|
||||
}
|
||||
|
||||
eval_error(const eval_error &) = default;
|
||||
|
||||
std::string pretty_print() const
|
||||
{
|
||||
std::string pretty_print() const {
|
||||
std::ostringstream ss;
|
||||
|
||||
ss << what();
|
||||
if (!call_stack.empty()) {
|
||||
ss << "during evaluation at (" << fname(call_stack[0]) << " " << startpos(call_stack[0]) << ")\n";
|
||||
ss << '\n' << detail << '\n';
|
||||
ss << '\n'
|
||||
<< detail << '\n';
|
||||
ss << " " << fname(call_stack[0]) << " (" << startpos(call_stack[0]) << ") '" << pretty(call_stack[0]) << "'";
|
||||
for (size_t j = 1; j < call_stack.size(); ++j) {
|
||||
if (id(call_stack[j]) != chaiscript::AST_Node_Type::Block
|
||||
&& id(call_stack[j]) != chaiscript::AST_Node_Type::File)
|
||||
{
|
||||
if (id(call_stack[j]) != chaiscript::AST_Node_Type::Block && id(call_stack[j]) != chaiscript::AST_Node_Type::File) {
|
||||
ss << '\n';
|
||||
ss << " from " << fname(call_stack[j]) << " (" << startpos(call_stack[j]) << ") '" << pretty(call_stack[j]) << "'";
|
||||
}
|
||||
@ -252,52 +269,39 @@ namespace chaiscript
|
||||
~eval_error() noexcept override = default;
|
||||
|
||||
private:
|
||||
|
||||
template<typename T>
|
||||
static AST_Node_Type id(const T& t) noexcept
|
||||
{
|
||||
static AST_Node_Type id(const T &t) noexcept {
|
||||
return t.identifier;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static std::string pretty(const T& t)
|
||||
{
|
||||
static std::string pretty(const T &t) {
|
||||
return t.pretty_print();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static const std::string &fname(const T& t) noexcept
|
||||
{
|
||||
static const std::string &fname(const T &t) noexcept {
|
||||
return t.filename();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static std::string startpos(const T& t)
|
||||
{
|
||||
static std::string startpos(const T &t) {
|
||||
std::ostringstream oss;
|
||||
oss << t.start().line << ", " << t.start().column;
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
static std::string format_why(const std::string &t_why)
|
||||
{
|
||||
return "Error: \"" + t_why + "\"";
|
||||
}
|
||||
static std::string format_why(const std::string &t_why) { return "Error: \"" + t_why + "\""; }
|
||||
|
||||
static std::string format_types(const Const_Proxy_Function &t_func,
|
||||
bool t_dot_notation,
|
||||
const chaiscript::detail::Dispatch_Engine &t_ss)
|
||||
{
|
||||
static std::string format_types(const Const_Proxy_Function &t_func, bool t_dot_notation, const chaiscript::detail::Dispatch_Engine &t_ss) {
|
||||
assert(t_func);
|
||||
int arity = t_func->get_arity();
|
||||
std::vector<Type_Info> types = t_func->get_param_types();
|
||||
|
||||
std::string retval;
|
||||
if (arity == -1)
|
||||
{
|
||||
if (arity == -1) {
|
||||
retval = "(...)";
|
||||
if (t_dot_notation)
|
||||
{
|
||||
if (t_dot_notation) {
|
||||
retval = "(Object)." + retval;
|
||||
}
|
||||
} else if (types.size() <= 1) {
|
||||
@ -308,18 +312,13 @@ namespace chaiscript
|
||||
|
||||
std::string paramstr;
|
||||
|
||||
for (size_t index = 1;
|
||||
index != types.size();
|
||||
++index)
|
||||
{
|
||||
paramstr += (types[index].is_const()?"const ":"");
|
||||
for (size_t index = 1; index != types.size(); ++index) {
|
||||
paramstr += (types[index].is_const() ? "const " : "");
|
||||
paramstr += t_ss.get_type_name(types[index]);
|
||||
|
||||
if (index == 1 && t_dot_notation)
|
||||
{
|
||||
if (index == 1 && t_dot_notation) {
|
||||
paramstr += ").(";
|
||||
if (types.size() == 2)
|
||||
{
|
||||
if (types.size() == 2) {
|
||||
paramstr += ", ";
|
||||
}
|
||||
} else {
|
||||
@ -333,19 +332,15 @@ namespace chaiscript
|
||||
retval = ss.str();
|
||||
}
|
||||
|
||||
|
||||
std::shared_ptr<const dispatch::Dynamic_Proxy_Function> dynfun
|
||||
= std::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(t_func);
|
||||
|
||||
if (dynfun && dynfun->has_parse_tree())
|
||||
{
|
||||
if (dynfun && dynfun->has_parse_tree()) {
|
||||
Proxy_Function f = dynfun->get_guard();
|
||||
|
||||
if (f)
|
||||
{
|
||||
if (f) {
|
||||
auto dynfunguard = std::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(f);
|
||||
if (dynfunguard && dynfunguard->has_parse_tree())
|
||||
{
|
||||
if (dynfunguard && dynfunguard->has_parse_tree()) {
|
||||
retval += " : " + format_guard(dynfunguard->get_parse_tree());
|
||||
}
|
||||
}
|
||||
@ -357,14 +352,12 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static std::string format_guard(const T &t)
|
||||
{
|
||||
static std::string format_guard(const T &t) {
|
||||
return t.pretty_print();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static std::string format_location(const T &t)
|
||||
{
|
||||
static std::string format_location(const T &t) {
|
||||
std::ostringstream oss;
|
||||
oss << "(" << t.filename() << " " << t.start().line << ", " << t.start().column << ")";
|
||||
return oss.str();
|
||||
@ -372,50 +365,37 @@ namespace chaiscript
|
||||
|
||||
static std::string format_detail(const std::vector<chaiscript::Const_Proxy_Function> &t_functions,
|
||||
bool t_dot_notation,
|
||||
const chaiscript::detail::Dispatch_Engine &t_ss)
|
||||
{
|
||||
const chaiscript::detail::Dispatch_Engine &t_ss) {
|
||||
std::stringstream ss;
|
||||
if (t_functions.size() == 1)
|
||||
{
|
||||
if (t_functions.size() == 1) {
|
||||
assert(t_functions[0]);
|
||||
ss << " Expected: " << format_types(t_functions[0], t_dot_notation, t_ss) << '\n';
|
||||
} else {
|
||||
ss << " " << t_functions.size() << " overloads available:\n";
|
||||
|
||||
for (const auto & t_function : t_functions)
|
||||
{
|
||||
for (const auto &t_function : t_functions) {
|
||||
ss << " " << format_types((t_function), t_dot_notation, t_ss) << '\n';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return ss.str();
|
||||
|
||||
}
|
||||
|
||||
static std::string format_parameters(const std::vector<Boxed_Value> &t_parameters,
|
||||
bool t_dot_notation,
|
||||
const chaiscript::detail::Dispatch_Engine &t_ss)
|
||||
{
|
||||
static std::string
|
||||
format_parameters(const std::vector<Boxed_Value> &t_parameters, bool t_dot_notation, const chaiscript::detail::Dispatch_Engine &t_ss) {
|
||||
std::stringstream ss;
|
||||
ss << "(";
|
||||
|
||||
if (!t_parameters.empty())
|
||||
{
|
||||
if (!t_parameters.empty()) {
|
||||
std::string paramstr;
|
||||
|
||||
for (auto itr = t_parameters.begin();
|
||||
itr != t_parameters.end();
|
||||
++itr)
|
||||
{
|
||||
paramstr += (itr->is_const()?"const ":"");
|
||||
for (auto itr = t_parameters.begin(); itr != t_parameters.end(); ++itr) {
|
||||
paramstr += (itr->is_const() ? "const " : "");
|
||||
paramstr += t_ss.type_name(*itr);
|
||||
|
||||
if (itr == t_parameters.begin() && t_dot_notation)
|
||||
{
|
||||
if (itr == t_parameters.begin() && t_dot_notation) {
|
||||
paramstr += ").(";
|
||||
if (t_parameters.size() == 1)
|
||||
{
|
||||
if (t_parameters.size() == 1) {
|
||||
paramstr += ", ";
|
||||
}
|
||||
} else {
|
||||
@ -430,12 +410,10 @@ namespace chaiscript
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
static std::string format_filename(const std::string &t_fname)
|
||||
{
|
||||
static std::string format_filename(const std::string &t_fname) {
|
||||
std::stringstream ss;
|
||||
|
||||
if (t_fname != "__EVAL__")
|
||||
{
|
||||
if (t_fname != "__EVAL__") {
|
||||
ss << "in '" << t_fname << "' ";
|
||||
} else {
|
||||
ss << "during evaluation ";
|
||||
@ -444,16 +422,18 @@ namespace chaiscript
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
static std::string format_location(const File_Position &t_where)
|
||||
{
|
||||
static std::string format_location(const File_Position &t_where) {
|
||||
std::stringstream ss;
|
||||
ss << "at (" << t_where.line << ", " << t_where.column << ")";
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
static std::string format(const std::string &t_why, const File_Position &t_where, const std::string &t_fname,
|
||||
const std::vector<Boxed_Value> &t_parameters, bool t_dot_notation, const chaiscript::detail::Dispatch_Engine &t_ss)
|
||||
{
|
||||
static std::string format(const std::string &t_why,
|
||||
const File_Position &t_where,
|
||||
const std::string &t_fname,
|
||||
const std::vector<Boxed_Value> &t_parameters,
|
||||
bool t_dot_notation,
|
||||
const chaiscript::detail::Dispatch_Engine &t_ss) {
|
||||
std::stringstream ss;
|
||||
|
||||
ss << format_why(t_why);
|
||||
@ -473,8 +453,7 @@ namespace chaiscript
|
||||
static std::string format(const std::string &t_why,
|
||||
const std::vector<Boxed_Value> &t_parameters,
|
||||
bool t_dot_notation,
|
||||
const chaiscript::detail::Dispatch_Engine &t_ss)
|
||||
{
|
||||
const chaiscript::detail::Dispatch_Engine &t_ss) {
|
||||
std::stringstream ss;
|
||||
|
||||
ss << format_why(t_why);
|
||||
@ -486,8 +465,7 @@ namespace chaiscript
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
static std::string format(const std::string &t_why, const File_Position &t_where, const std::string &t_fname)
|
||||
{
|
||||
static std::string format(const std::string &t_why, const File_Position &t_where, const std::string &t_fname) {
|
||||
std::stringstream ss;
|
||||
|
||||
ss << format_why(t_why);
|
||||
@ -502,13 +480,12 @@ namespace chaiscript
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/// Errors generated when loading a file
|
||||
struct file_not_found_error : std::runtime_error {
|
||||
explicit file_not_found_error(const std::string &t_filename)
|
||||
: std::runtime_error("File Not Found: " + t_filename),
|
||||
filename(t_filename)
|
||||
{ }
|
||||
: std::runtime_error("File Not Found: " + t_filename)
|
||||
, filename(t_filename) {
|
||||
}
|
||||
|
||||
file_not_found_error(const file_not_found_error &) = default;
|
||||
~file_not_found_error() noexcept override = default;
|
||||
@ -516,8 +493,7 @@ namespace chaiscript
|
||||
std::string filename;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
} // namespace exception
|
||||
|
||||
/// \brief Struct that doubles as both a parser ast_node and an AST node.
|
||||
struct AST_Node {
|
||||
@ -526,25 +502,18 @@ namespace chaiscript
|
||||
const std::string text;
|
||||
Parse_Location location;
|
||||
|
||||
const std::string &filename() const noexcept {
|
||||
return *location.filename;
|
||||
}
|
||||
const std::string &filename() const noexcept { return *location.filename; }
|
||||
|
||||
const File_Position &start() const noexcept {
|
||||
return location.start;
|
||||
}
|
||||
const File_Position &start() const noexcept { return location.start; }
|
||||
|
||||
const File_Position &end() const noexcept {
|
||||
return location.end;
|
||||
}
|
||||
const File_Position &end() const noexcept { return location.end; }
|
||||
|
||||
std::string pretty_print() const
|
||||
{
|
||||
std::string pretty_print() const {
|
||||
std::ostringstream oss;
|
||||
|
||||
oss << text;
|
||||
|
||||
for (auto & elem : get_children()) {
|
||||
for (auto &elem : get_children()) {
|
||||
oss << elem.get().pretty_print() << ' ';
|
||||
}
|
||||
|
||||
@ -554,99 +523,81 @@ namespace chaiscript
|
||||
virtual std::vector<std::reference_wrapper<AST_Node>> get_children() const = 0;
|
||||
virtual Boxed_Value eval(const chaiscript::detail::Dispatch_State &t_e) const = 0;
|
||||
|
||||
|
||||
/// Prints the contents of an AST node, including its children, recursively
|
||||
std::string to_string(const std::string &t_prepend = "") const {
|
||||
std::ostringstream oss;
|
||||
|
||||
oss << t_prepend << "(" << ast_node_type_to_string(this->identifier) << ") "
|
||||
<< this->text << " : " << this->location.start.line << ", " << this->location.start.column << '\n';
|
||||
oss << t_prepend << "(" << ast_node_type_to_string(this->identifier) << ") " << this->text << " : " << this->location.start.line
|
||||
<< ", " << this->location.start.column << '\n';
|
||||
|
||||
for (auto & elem : get_children()) {
|
||||
for (auto &elem : get_children()) {
|
||||
oss << elem.get().to_string(t_prepend + " ");
|
||||
}
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
|
||||
static bool get_bool_condition(const Boxed_Value &t_bv, const chaiscript::detail::Dispatch_State &t_ss) {
|
||||
try {
|
||||
return t_ss->boxed_cast<bool>(t_bv);
|
||||
}
|
||||
catch (const exception::bad_boxed_cast &) {
|
||||
} catch (const exception::bad_boxed_cast &) {
|
||||
throw exception::eval_error("Condition not boolean");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
virtual ~AST_Node() noexcept = default;
|
||||
AST_Node(AST_Node &&) = default;
|
||||
AST_Node &operator=(AST_Node &&) = delete;
|
||||
AST_Node(const AST_Node &) = delete;
|
||||
AST_Node& operator=(const AST_Node &) = delete;
|
||||
|
||||
AST_Node &operator=(const AST_Node &) = delete;
|
||||
|
||||
protected:
|
||||
AST_Node(std::string t_ast_node_text, AST_Node_Type t_id, Parse_Location t_loc)
|
||||
: identifier(t_id), text(std::move(t_ast_node_text)),
|
||||
location(std::move(t_loc))
|
||||
{
|
||||
: identifier(t_id)
|
||||
, text(std::move(t_ast_node_text))
|
||||
, location(std::move(t_loc)) {
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
struct AST_Node_Trace
|
||||
{
|
||||
struct AST_Node_Trace {
|
||||
const AST_Node_Type identifier;
|
||||
const std::string text;
|
||||
Parse_Location location;
|
||||
|
||||
const std::string &filename() const noexcept {
|
||||
return *location.filename;
|
||||
}
|
||||
const std::string &filename() const noexcept { return *location.filename; }
|
||||
|
||||
const File_Position &start() const noexcept {
|
||||
return location.start;
|
||||
}
|
||||
const File_Position &start() const noexcept { return location.start; }
|
||||
|
||||
const File_Position &end() const noexcept {
|
||||
return location.end;
|
||||
}
|
||||
const File_Position &end() const noexcept { return location.end; }
|
||||
|
||||
std::string pretty_print() const
|
||||
{
|
||||
std::string pretty_print() const {
|
||||
std::ostringstream oss;
|
||||
|
||||
oss << text;
|
||||
|
||||
for (const auto & elem : children) {
|
||||
for (const auto &elem : children) {
|
||||
oss << elem.pretty_print() << ' ';
|
||||
}
|
||||
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
std::vector<AST_Node_Trace> get_children(const AST_Node &node)
|
||||
{
|
||||
std::vector<AST_Node_Trace> get_children(const AST_Node &node) {
|
||||
const auto node_children = node.get_children();
|
||||
return std::vector<AST_Node_Trace>(node_children.begin(), node_children.end());
|
||||
}
|
||||
|
||||
AST_Node_Trace(const AST_Node &node)
|
||||
: identifier(node.identifier), text(node.text),
|
||||
location(node.location), children(get_children(node))
|
||||
{
|
||||
: identifier(node.identifier)
|
||||
, text(node.text)
|
||||
, location(node.location)
|
||||
, children(get_children(node)) {
|
||||
}
|
||||
|
||||
|
||||
std::vector<AST_Node_Trace> children;
|
||||
|
||||
};
|
||||
|
||||
namespace parser {
|
||||
class ChaiScript_Parser_Base
|
||||
{
|
||||
class ChaiScript_Parser_Base {
|
||||
public:
|
||||
virtual AST_NodePtr parse(const std::string &t_input, const std::string &t_fname) = 0;
|
||||
virtual void debug_print(const AST_Node &t, std::string prepend = "") const = 0;
|
||||
@ -658,116 +609,88 @@ namespace chaiscript
|
||||
ChaiScript_Parser_Base &operator=(const ChaiScript_Parser_Base &&) = delete;
|
||||
|
||||
template<typename T>
|
||||
T &get_tracer() noexcept
|
||||
{
|
||||
T &get_tracer() noexcept {
|
||||
// to do type check this somehow?
|
||||
return *static_cast<T*>(get_tracer_ptr());
|
||||
return *static_cast<T *>(get_tracer_ptr());
|
||||
}
|
||||
|
||||
protected:
|
||||
ChaiScript_Parser_Base(const ChaiScript_Parser_Base &) = default;
|
||||
};
|
||||
}
|
||||
} // namespace parser
|
||||
|
||||
namespace eval
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
namespace eval {
|
||||
namespace detail {
|
||||
/// Special type for returned values
|
||||
struct Return_Value {
|
||||
Boxed_Value retval;
|
||||
};
|
||||
|
||||
|
||||
/// Special type indicating a call to 'break'
|
||||
struct Break_Loop {
|
||||
};
|
||||
|
||||
|
||||
/// Special type indicating a call to 'continue'
|
||||
struct Continue_Loop {
|
||||
};
|
||||
|
||||
|
||||
/// Creates a new scope then pops it on destruction
|
||||
struct Scope_Push_Pop
|
||||
{
|
||||
struct Scope_Push_Pop {
|
||||
Scope_Push_Pop(Scope_Push_Pop &&) = default;
|
||||
Scope_Push_Pop& operator=(Scope_Push_Pop &&) = delete;
|
||||
Scope_Push_Pop &operator=(Scope_Push_Pop &&) = delete;
|
||||
Scope_Push_Pop(const Scope_Push_Pop &) = delete;
|
||||
Scope_Push_Pop& operator=(const Scope_Push_Pop &) = delete;
|
||||
Scope_Push_Pop &operator=(const Scope_Push_Pop &) = delete;
|
||||
|
||||
explicit Scope_Push_Pop(const chaiscript::detail::Dispatch_State &t_ds)
|
||||
: m_ds(t_ds)
|
||||
{
|
||||
: m_ds(t_ds) {
|
||||
m_ds->new_scope(m_ds.stack_holder());
|
||||
}
|
||||
|
||||
~Scope_Push_Pop()
|
||||
{
|
||||
m_ds->pop_scope(m_ds.stack_holder());
|
||||
}
|
||||
|
||||
~Scope_Push_Pop() { m_ds->pop_scope(m_ds.stack_holder()); }
|
||||
|
||||
private:
|
||||
const chaiscript::detail::Dispatch_State &m_ds;
|
||||
};
|
||||
|
||||
/// Creates a new function call and pops it on destruction
|
||||
struct Function_Push_Pop
|
||||
{
|
||||
struct Function_Push_Pop {
|
||||
Function_Push_Pop(Function_Push_Pop &&) = default;
|
||||
Function_Push_Pop& operator=(Function_Push_Pop &&) = delete;
|
||||
Function_Push_Pop &operator=(Function_Push_Pop &&) = delete;
|
||||
Function_Push_Pop(const Function_Push_Pop &) = delete;
|
||||
Function_Push_Pop& operator=(const Function_Push_Pop &) = delete;
|
||||
Function_Push_Pop &operator=(const Function_Push_Pop &) = delete;
|
||||
|
||||
explicit Function_Push_Pop(const chaiscript::detail::Dispatch_State &t_ds)
|
||||
: m_ds(t_ds)
|
||||
{
|
||||
: m_ds(t_ds) {
|
||||
m_ds->new_function_call(m_ds.stack_holder(), m_ds.conversion_saves());
|
||||
}
|
||||
|
||||
~Function_Push_Pop()
|
||||
{
|
||||
m_ds->pop_function_call(m_ds.stack_holder(), m_ds.conversion_saves());
|
||||
}
|
||||
|
||||
void save_params(const Function_Params &t_params)
|
||||
{
|
||||
m_ds->save_function_params(t_params);
|
||||
}
|
||||
~Function_Push_Pop() { m_ds->pop_function_call(m_ds.stack_holder(), m_ds.conversion_saves()); }
|
||||
|
||||
void save_params(const Function_Params &t_params) { m_ds->save_function_params(t_params); }
|
||||
|
||||
private:
|
||||
const chaiscript::detail::Dispatch_State &m_ds;
|
||||
};
|
||||
|
||||
/// Creates a new scope then pops it on destruction
|
||||
struct Stack_Push_Pop
|
||||
{
|
||||
struct Stack_Push_Pop {
|
||||
Stack_Push_Pop(Stack_Push_Pop &&) = default;
|
||||
Stack_Push_Pop& operator=(Stack_Push_Pop &&) = delete;
|
||||
Stack_Push_Pop &operator=(Stack_Push_Pop &&) = delete;
|
||||
Stack_Push_Pop(const Stack_Push_Pop &) = delete;
|
||||
Stack_Push_Pop& operator=(const Stack_Push_Pop &) = delete;
|
||||
Stack_Push_Pop &operator=(const Stack_Push_Pop &) = delete;
|
||||
|
||||
explicit Stack_Push_Pop(const chaiscript::detail::Dispatch_State &t_ds)
|
||||
: m_ds(t_ds)
|
||||
{
|
||||
: m_ds(t_ds) {
|
||||
m_ds->new_stack(m_ds.stack_holder());
|
||||
}
|
||||
|
||||
~Stack_Push_Pop()
|
||||
{
|
||||
m_ds->pop_stack(m_ds.stack_holder());
|
||||
}
|
||||
|
||||
~Stack_Push_Pop() { m_ds->pop_stack(m_ds.stack_holder()); }
|
||||
|
||||
private:
|
||||
const chaiscript::detail::Dispatch_State &m_ds;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace detail
|
||||
} // namespace eval
|
||||
} // namespace chaiscript
|
||||
|
||||
#endif /* _CHAISCRIPT_COMMON_HPP */
|
||||
|
||||
|
||||
@ -7,11 +7,11 @@
|
||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||
|
||||
|
||||
#ifndef CHAISCRIPT_ENGINE_HPP_
|
||||
#define CHAISCRIPT_ENGINE_HPP_
|
||||
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <exception>
|
||||
#include <fstream>
|
||||
#include <functional>
|
||||
@ -21,15 +21,15 @@
|
||||
#include <set>
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
#include <cstring>
|
||||
|
||||
#include "../chaiscript_defines.hpp"
|
||||
#include "../chaiscript_threading.hpp"
|
||||
#include "../dispatchkit/boxed_cast_helper.hpp"
|
||||
#include "../dispatchkit/boxed_value.hpp"
|
||||
#include "../dispatchkit/dispatchkit.hpp"
|
||||
#include "../dispatchkit/type_conversions.hpp"
|
||||
#include "../dispatchkit/proxy_functions.hpp"
|
||||
#include "../dispatchkit/register_function.hpp"
|
||||
#include "../dispatchkit/type_conversions.hpp"
|
||||
#include "chaiscript_common.hpp"
|
||||
|
||||
#if defined(__linux__) || defined(__unix__) || defined(__APPLE__) || defined(__HAIKU__)
|
||||
@ -50,23 +50,18 @@
|
||||
#include "chaiscript_unknown.hpp"
|
||||
#endif
|
||||
|
||||
|
||||
#include "../dispatchkit/exception_specification.hpp"
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
namespace chaiscript {
|
||||
/// Namespace alias to provide cleaner and more explicit syntax to users.
|
||||
using Namespace = dispatch::Dynamic_Object;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
namespace detail {
|
||||
using Loadable_Module_Ptr = std::shared_ptr<Loadable_Module>;
|
||||
}
|
||||
|
||||
|
||||
/// \brief The main object that the ChaiScript user will use.
|
||||
class ChaiScript_Basic {
|
||||
|
||||
mutable chaiscript::detail::threading::shared_mutex m_mutex;
|
||||
mutable chaiscript::detail::threading::recursive_mutex m_use_mutex;
|
||||
|
||||
@ -81,26 +76,21 @@ namespace chaiscript
|
||||
|
||||
chaiscript::detail::Dispatch_Engine m_engine;
|
||||
|
||||
std::map<std::string, std::function<Namespace&()>> m_namespace_generators;
|
||||
std::map<std::string, std::function<Namespace &()>> m_namespace_generators;
|
||||
|
||||
/// Evaluates the given string in by parsing it and running the results through the evaluator
|
||||
Boxed_Value do_eval(const std::string &t_input, const std::string &t_filename = "__EVAL__", bool /* t_internal*/ = false)
|
||||
{
|
||||
Boxed_Value do_eval(const std::string &t_input, const std::string &t_filename = "__EVAL__", bool /* t_internal*/ = false) {
|
||||
try {
|
||||
const auto p = m_parser->parse(t_input, t_filename);
|
||||
return p->eval(chaiscript::detail::Dispatch_State(m_engine));
|
||||
}
|
||||
catch (chaiscript::eval::detail::Return_Value &rv) {
|
||||
} catch (chaiscript::eval::detail::Return_Value &rv) {
|
||||
return rv.retval;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// Evaluates the given file and looks in the 'use' paths
|
||||
Boxed_Value internal_eval_file(const std::string &t_filename) {
|
||||
for (const auto &path : m_use_paths)
|
||||
{
|
||||
for (const auto &path : m_use_paths) {
|
||||
try {
|
||||
const auto appendedpath = path + t_filename;
|
||||
return do_eval(load_file(appendedpath), appendedpath, true);
|
||||
@ -113,11 +103,8 @@ namespace chaiscript
|
||||
|
||||
// failed to load by any name
|
||||
throw exception::file_not_found_error(t_filename);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// Evaluates the given string, used during eval() inside of a script
|
||||
Boxed_Value internal_eval(const std::string &t_e) {
|
||||
try {
|
||||
@ -128,81 +115,70 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
/// Returns the current evaluation m_engine
|
||||
chaiscript::detail::Dispatch_Engine &get_eval_engine() noexcept {
|
||||
return m_engine;
|
||||
}
|
||||
chaiscript::detail::Dispatch_Engine &get_eval_engine() noexcept { return m_engine; }
|
||||
|
||||
/// Builds all the requirements for ChaiScript, including its evaluator and a run of its prelude.
|
||||
void build_eval_system(const ModulePtr &t_lib, const std::vector<Options> &t_opts) {
|
||||
if (t_lib)
|
||||
{
|
||||
if (t_lib) {
|
||||
add(t_lib);
|
||||
}
|
||||
|
||||
m_engine.add(fun([this](){ m_engine.dump_system(); }), "dump_system");
|
||||
m_engine.add(fun([this](const Boxed_Value &t_bv){ m_engine.dump_object(t_bv); }), "dump_object");
|
||||
m_engine.add(fun([this](const Boxed_Value &t_bv, const std::string &t_type){ return m_engine.is_type(t_bv, t_type); }), "is_type");
|
||||
m_engine.add(fun([this](const Boxed_Value &t_bv){ return m_engine.type_name(t_bv); }), "type_name");
|
||||
m_engine.add(fun([this](const std::string &t_f){ return m_engine.function_exists(t_f); }), "function_exists");
|
||||
m_engine.add(fun([this](){ return m_engine.get_function_objects(); }), "get_functions");
|
||||
m_engine.add(fun([this](){ return m_engine.get_scripting_objects(); }), "get_objects");
|
||||
m_engine.add(fun([this]() { m_engine.dump_system(); }), "dump_system");
|
||||
m_engine.add(fun([this](const Boxed_Value &t_bv) { m_engine.dump_object(t_bv); }), "dump_object");
|
||||
m_engine.add(fun([this](const Boxed_Value &t_bv, const std::string &t_type) { return m_engine.is_type(t_bv, t_type); }), "is_type");
|
||||
m_engine.add(fun([this](const Boxed_Value &t_bv) { return m_engine.type_name(t_bv); }), "type_name");
|
||||
m_engine.add(fun([this](const std::string &t_f) { return m_engine.function_exists(t_f); }), "function_exists");
|
||||
m_engine.add(fun([this]() { return m_engine.get_function_objects(); }), "get_functions");
|
||||
m_engine.add(fun([this]() { return m_engine.get_scripting_objects(); }), "get_objects");
|
||||
|
||||
m_engine.add(
|
||||
dispatch::make_dynamic_proxy_function(
|
||||
[this](const Function_Params &t_params) {
|
||||
return m_engine.call_exists(t_params);
|
||||
})
|
||||
, "call_exists");
|
||||
m_engine.add(dispatch::make_dynamic_proxy_function([this](const Function_Params &t_params) { return m_engine.call_exists(t_params); }),
|
||||
"call_exists");
|
||||
|
||||
|
||||
m_engine.add(fun(
|
||||
[this](const dispatch::Proxy_Function_Base &t_fun, const std::vector<Boxed_Value> &t_params) -> Boxed_Value {
|
||||
m_engine.add(fun([this](const dispatch::Proxy_Function_Base &t_fun, const std::vector<Boxed_Value> &t_params) -> Boxed_Value {
|
||||
Type_Conversions_State s(this->m_engine.conversions(), this->m_engine.conversions().conversion_saves());
|
||||
return t_fun(Function_Params{t_params}, s);
|
||||
}), "call");
|
||||
}),
|
||||
"call");
|
||||
|
||||
m_engine.add(fun([this](const Type_Info &t_ti) { return m_engine.get_type_name(t_ti); }), "name");
|
||||
|
||||
m_engine.add(fun([this](const Type_Info &t_ti){ return m_engine.get_type_name(t_ti); }), "name");
|
||||
m_engine.add(fun([this](const std::string &t_type_name, bool t_throw) { return m_engine.get_type(t_type_name, t_throw); }), "type");
|
||||
m_engine.add(fun([this](const std::string &t_type_name) { return m_engine.get_type(t_type_name, true); }), "type");
|
||||
|
||||
m_engine.add(fun([this](const std::string &t_type_name, bool t_throw){ return m_engine.get_type(t_type_name, t_throw); }), "type");
|
||||
m_engine.add(fun([this](const std::string &t_type_name){ return m_engine.get_type(t_type_name, true); }), "type");
|
||||
|
||||
m_engine.add(fun(
|
||||
[this](const Type_Info &t_from, const Type_Info &t_to, const std::function<Boxed_Value (const Boxed_Value &)> &t_func) {
|
||||
m_engine.add(fun([this](const Type_Info &t_from, const Type_Info &t_to, const std::function<Boxed_Value(const Boxed_Value &)> &t_func) {
|
||||
m_engine.add(chaiscript::type_conversion(t_from, t_to, t_func));
|
||||
}
|
||||
), "add_type_conversion");
|
||||
|
||||
|
||||
}),
|
||||
"add_type_conversion");
|
||||
|
||||
if (std::find(t_opts.begin(), t_opts.end(), Options::No_Load_Modules) == t_opts.end()
|
||||
&& std::find(t_opts.begin(), t_opts.end(), Options::Load_Modules) != t_opts.end())
|
||||
{
|
||||
m_engine.add(fun([this](const std::string &t_module, const std::string &t_file){ load_module(t_module, t_file); }), "load_module");
|
||||
m_engine.add(fun([this](const std::string &t_module){ return load_module(t_module); }), "load_module");
|
||||
&& std::find(t_opts.begin(), t_opts.end(), Options::Load_Modules) != t_opts.end()) {
|
||||
m_engine.add(fun([this](const std::string &t_module, const std::string &t_file) { load_module(t_module, t_file); }), "load_module");
|
||||
m_engine.add(fun([this](const std::string &t_module) { return load_module(t_module); }), "load_module");
|
||||
}
|
||||
|
||||
if (std::find(t_opts.begin(), t_opts.end(), Options::No_External_Scripts) == t_opts.end()
|
||||
&& std::find(t_opts.begin(), t_opts.end(), Options::External_Scripts) != t_opts.end())
|
||||
{
|
||||
m_engine.add(fun([this](const std::string &t_file){ return use(t_file); }), "use");
|
||||
m_engine.add(fun([this](const std::string &t_file){ return internal_eval_file(t_file); }), "eval_file");
|
||||
&& std::find(t_opts.begin(), t_opts.end(), Options::External_Scripts) != t_opts.end()) {
|
||||
m_engine.add(fun([this](const std::string &t_file) { return use(t_file); }), "use");
|
||||
m_engine.add(fun([this](const std::string &t_file) { return internal_eval_file(t_file); }), "eval_file");
|
||||
}
|
||||
|
||||
m_engine.add(fun([this](const std::string &t_str){ return internal_eval(t_str); }), "eval");
|
||||
m_engine.add(fun([this](const AST_Node &t_ast){ return eval(t_ast); }), "eval");
|
||||
m_engine.add(fun([this](const std::string &t_str) { return internal_eval(t_str); }), "eval");
|
||||
m_engine.add(fun([this](const AST_Node &t_ast) { return eval(t_ast); }), "eval");
|
||||
|
||||
m_engine.add(fun([this](const std::string &t_str, const bool t_dump){ return parse(t_str, t_dump); }), "parse");
|
||||
m_engine.add(fun([this](const std::string &t_str){ return parse(t_str); }), "parse");
|
||||
m_engine.add(fun([this](const std::string &t_str, const bool t_dump) { return parse(t_str, t_dump); }), "parse");
|
||||
m_engine.add(fun([this](const std::string &t_str) { return parse(t_str); }), "parse");
|
||||
|
||||
|
||||
m_engine.add(fun([this](const Boxed_Value &t_bv, const std::string &t_name){ add_global_const(t_bv, t_name); }), "add_global_const");
|
||||
m_engine.add(fun([this](const Boxed_Value &t_bv, const std::string &t_name){ add_global(t_bv, t_name); }), "add_global");
|
||||
m_engine.add(fun([this](const Boxed_Value &t_bv, const std::string &t_name){ set_global(t_bv, t_name); }), "set_global");
|
||||
m_engine.add(fun([this](const Boxed_Value &t_bv, const std::string &t_name) { add_global_const(t_bv, t_name); }), "add_global_const");
|
||||
m_engine.add(fun([this](const Boxed_Value &t_bv, const std::string &t_name) { add_global(t_bv, t_name); }), "add_global");
|
||||
m_engine.add(fun([this](const Boxed_Value &t_bv, const std::string &t_name) { set_global(t_bv, t_name); }), "set_global");
|
||||
|
||||
// why this unused parameter to Namespace?
|
||||
m_engine.add(fun([this](const std::string& t_namespace_name) { register_namespace([] (Namespace& /*space*/) noexcept {}, t_namespace_name); import(t_namespace_name); }), "namespace");
|
||||
m_engine.add(fun([this](const std::string& t_namespace_name) { import(t_namespace_name); }), "import");
|
||||
m_engine.add(fun([this](const std::string &t_namespace_name) {
|
||||
register_namespace([](Namespace & /*space*/) noexcept {}, t_namespace_name);
|
||||
import(t_namespace_name);
|
||||
}),
|
||||
"namespace");
|
||||
m_engine.add(fun([this](const std::string &t_namespace_name) { import(t_namespace_name); }), "import");
|
||||
}
|
||||
|
||||
/// Skip BOM at the beginning of file
|
||||
@ -214,10 +190,7 @@ namespace chaiscript
|
||||
|
||||
infile.read(buffer, static_cast<std::streamsize>(bytes_needed));
|
||||
|
||||
if ((buffer[0] == '\xef')
|
||||
&& (buffer[1] == '\xbb')
|
||||
&& (buffer[2] == '\xbf')) {
|
||||
|
||||
if ((buffer[0] == '\xef') && (buffer[1] == '\xbb') && (buffer[2] == '\xbf')) {
|
||||
infile.seekg(3);
|
||||
return true;
|
||||
}
|
||||
@ -229,7 +202,7 @@ namespace chaiscript
|
||||
|
||||
/// Helper function for loading a file
|
||||
static std::string load_file(const std::string &t_filename) {
|
||||
std::ifstream infile(t_filename.c_str(), std::ios::in | std::ios::ate | std::ios::binary );
|
||||
std::ifstream infile(t_filename.c_str(), std::ios::in | std::ios::ate | std::ios::binary);
|
||||
|
||||
if (!infile.is_open()) {
|
||||
throw chaiscript::exception::file_not_found_error(t_filename);
|
||||
@ -241,12 +214,11 @@ namespace chaiscript
|
||||
assert(size >= 0);
|
||||
|
||||
if (skip_bom(infile)) {
|
||||
size-=3; // decrement the BOM size from file size, otherwise we'll get parsing errors
|
||||
assert(size >= 0); //and check if there's more text
|
||||
size -= 3; // decrement the BOM size from file size, otherwise we'll get parsing errors
|
||||
assert(size >= 0); // and check if there's more text
|
||||
}
|
||||
|
||||
if (size == std::streampos(0))
|
||||
{
|
||||
if (size == std::streampos(0)) {
|
||||
return std::string();
|
||||
} else {
|
||||
std::vector<char> v(static_cast<size_t>(size));
|
||||
@ -255,14 +227,15 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::string> ensure_minimum_path_vec(std::vector<std::string> paths)
|
||||
{
|
||||
if (paths.empty()) { return {""}; }
|
||||
else { return paths; }
|
||||
std::vector<std::string> ensure_minimum_path_vec(std::vector<std::string> paths) {
|
||||
if (paths.empty()) {
|
||||
return {""};
|
||||
} else {
|
||||
return paths;
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/// \brief Constructor for ChaiScript
|
||||
/// \param[in] t_lib Standard library to apply to this ChaiScript instance
|
||||
/// \param[in] t_modulepaths Vector of paths to search when attempting to load a binary module
|
||||
@ -272,42 +245,38 @@ namespace chaiscript
|
||||
std::vector<std::string> t_module_paths = {},
|
||||
std::vector<std::string> t_use_paths = {},
|
||||
const std::vector<chaiscript::Options> &t_opts = chaiscript::default_options())
|
||||
: m_module_paths(ensure_minimum_path_vec(std::move(t_module_paths))),
|
||||
m_use_paths(ensure_minimum_path_vec(std::move(t_use_paths))),
|
||||
m_parser(std::move(parser)),
|
||||
m_engine(*m_parser)
|
||||
{
|
||||
: m_module_paths(ensure_minimum_path_vec(std::move(t_module_paths)))
|
||||
, m_use_paths(ensure_minimum_path_vec(std::move(t_use_paths)))
|
||||
, m_parser(std::move(parser))
|
||||
, m_engine(*m_parser) {
|
||||
#if !defined(CHAISCRIPT_NO_DYNLOAD) && defined(_POSIX_VERSION) && !defined(__CYGWIN__)
|
||||
// If on Unix, add the path of the current executable to the module search path
|
||||
// as windows would do
|
||||
|
||||
union cast_union
|
||||
{
|
||||
Boxed_Value (ChaiScript_Basic::*in_ptr)(const std::string&);
|
||||
union cast_union {
|
||||
Boxed_Value (ChaiScript_Basic::*in_ptr)(const std::string &);
|
||||
void *out_ptr;
|
||||
};
|
||||
|
||||
Dl_info rInfo;
|
||||
memset( &rInfo, 0, sizeof(rInfo) );
|
||||
memset(&rInfo, 0, sizeof(rInfo));
|
||||
cast_union u;
|
||||
u.in_ptr = &ChaiScript_Basic::use;
|
||||
if ( (dladdr(static_cast<void*>(u.out_ptr), &rInfo) != 0) && (rInfo.dli_fname != nullptr) ) {
|
||||
if ((dladdr(static_cast<void *>(u.out_ptr), &rInfo) != 0) && (rInfo.dli_fname != nullptr)) {
|
||||
std::string dllpath(rInfo.dli_fname);
|
||||
const size_t lastslash = dllpath.rfind('/');
|
||||
if (lastslash != std::string::npos)
|
||||
{
|
||||
if (lastslash != std::string::npos) {
|
||||
dllpath.erase(lastslash);
|
||||
}
|
||||
|
||||
// Let's see if this is a link that we should expand
|
||||
std::vector<char> buf(2048);
|
||||
const auto pathlen = readlink(dllpath.c_str(), &buf.front(), buf.size());
|
||||
if (pathlen > 0 && static_cast<size_t>(pathlen) < buf.size())
|
||||
{
|
||||
if (pathlen > 0 && static_cast<size_t>(pathlen) < buf.size()) {
|
||||
dllpath = std::string(&buf.front(), static_cast<size_t>(pathlen));
|
||||
}
|
||||
|
||||
m_module_paths.insert(m_module_paths.begin(), dllpath+"/");
|
||||
m_module_paths.insert(m_module_paths.begin(), dllpath + "/");
|
||||
}
|
||||
#endif
|
||||
build_eval_system(t_lib, t_opts);
|
||||
@ -325,20 +294,18 @@ namespace chaiscript
|
||||
std::vector<std::string> t_module_paths = {},
|
||||
std::vector<std::string> t_use_paths = {},
|
||||
const std::vector<chaiscript::Options> &t_opts = chaiscript::default_options())
|
||||
: ChaiScript_Basic({}, std::move(parser), t_module_paths, t_use_paths, t_opts)
|
||||
{
|
||||
: ChaiScript_Basic({}, std::move(parser), t_module_paths, t_use_paths, t_opts) {
|
||||
try {
|
||||
// attempt to load the stdlib
|
||||
load_module("chaiscript_stdlib-" + Build_Info::version());
|
||||
} catch (const exception::load_module_error &t_err) {
|
||||
std::cout << "An error occured while trying to load the chaiscript standard library.\n"
|
||||
<< "\n"
|
||||
<< "You must either provide a standard library, or compile it in.\n"
|
||||
<< "For an example of compiling the standard library in,\n"
|
||||
<< "see: https://gist.github.com/lefticus/9456197\n"
|
||||
<< "Compiling the stdlib in is the recommended and MOST SUPPORTED method.\n"
|
||||
<< "\n"
|
||||
<< "\n"
|
||||
std::cout << "An error occurred while trying to load the chaiscript standard library.\n"
|
||||
"\n"
|
||||
"You must either provide a standard library, or compile it in.\n"
|
||||
"For an example of compiling the standard library in,\n"
|
||||
"see: https://gist.github.com/lefticus/9456197\n"
|
||||
"Compiling the stdlib in is the recommended and MOST SUPPORTED method.\n"
|
||||
"\n\n"
|
||||
<< t_err.what();
|
||||
throw;
|
||||
}
|
||||
@ -347,16 +314,15 @@ namespace chaiscript
|
||||
explicit ChaiScript_Basic(std::unique_ptr<parser::ChaiScript_Parser_Base> &&parser,
|
||||
std::vector<std::string> t_module_paths = {},
|
||||
std::vector<std::string> t_use_paths = {},
|
||||
const std::vector<chaiscript::Options> &t_opts = chaiscript::default_options()) = delete;
|
||||
const std::vector<chaiscript::Options> &t_opts = chaiscript::default_options())
|
||||
= delete;
|
||||
#endif
|
||||
|
||||
parser::ChaiScript_Parser_Base &get_parser() noexcept
|
||||
{
|
||||
parser::ChaiScript_Parser_Base &get_parser() noexcept {
|
||||
return *m_parser;
|
||||
}
|
||||
|
||||
const Boxed_Value eval(const AST_Node &t_ast)
|
||||
{
|
||||
const Boxed_Value eval(const AST_Node &t_ast) {
|
||||
try {
|
||||
return t_ast.eval(chaiscript::detail::Dispatch_State(m_engine));
|
||||
} catch (const exception::eval_error &t_ee) {
|
||||
@ -364,8 +330,7 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
AST_NodePtr parse(const std::string &t_input, const bool t_debug_print = false)
|
||||
{
|
||||
AST_NodePtr parse(const std::string &t_input, const bool t_debug_print = false) {
|
||||
auto ast = m_parser->parse(t_input, "PARSE");
|
||||
if (t_debug_print) {
|
||||
m_parser->debug_print(*ast);
|
||||
@ -373,38 +338,28 @@ namespace chaiscript
|
||||
return ast;
|
||||
}
|
||||
|
||||
|
||||
std::string get_type_name(const Type_Info &ti) const
|
||||
{
|
||||
return m_engine.get_type_name(ti);
|
||||
}
|
||||
std::string get_type_name(const Type_Info &ti) const { return m_engine.get_type_name(ti); }
|
||||
|
||||
template<typename T>
|
||||
std::string get_type_name() const
|
||||
{
|
||||
std::string get_type_name() const {
|
||||
return get_type_name(user_type<T>());
|
||||
}
|
||||
|
||||
|
||||
/// \brief Loads and parses a file. If the file is already open, it is not
|
||||
/// reloaded. The use paths specified at ChaiScript construction time are
|
||||
/// searched for the requested file.
|
||||
///
|
||||
/// \param[in] t_filename Filename to load and evaluate
|
||||
Boxed_Value use(const std::string &t_filename)
|
||||
{
|
||||
for (const auto &path : m_use_paths)
|
||||
{
|
||||
Boxed_Value use(const std::string &t_filename) {
|
||||
for (const auto &path : m_use_paths) {
|
||||
const auto appendedpath = path + t_filename;
|
||||
try {
|
||||
|
||||
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::recursive_mutex> l(m_use_mutex);
|
||||
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l2(m_mutex);
|
||||
|
||||
Boxed_Value retval;
|
||||
|
||||
if (m_used_files.count(appendedpath) == 0)
|
||||
{
|
||||
if (m_used_files.count(appendedpath) == 0) {
|
||||
l2.unlock();
|
||||
retval = eval_file(appendedpath);
|
||||
l2.lock();
|
||||
@ -430,8 +385,7 @@ namespace chaiscript
|
||||
/// \param[in] t_name Name of the value to add
|
||||
/// \throw chaiscript::exception::global_non_const If t_bv is not a constant object
|
||||
/// \sa Boxed_Value::is_const
|
||||
ChaiScript_Basic &add_global_const(const Boxed_Value &t_bv, const std::string &t_name)
|
||||
{
|
||||
ChaiScript_Basic &add_global_const(const Boxed_Value &t_bv, const std::string &t_name) {
|
||||
Name_Validator::validate_object_name(t_name);
|
||||
m_engine.add_global_const(t_bv, t_name);
|
||||
return *this;
|
||||
@ -442,15 +396,13 @@ namespace chaiscript
|
||||
/// \param[in] t_name Name of the value to add
|
||||
/// \warning The user is responsible for making sure the object is thread-safe if necessary
|
||||
/// ChaiScript is thread-safe but provides no threading locking mechanism to the script
|
||||
ChaiScript_Basic &add_global(const Boxed_Value &t_bv, const std::string &t_name)
|
||||
{
|
||||
ChaiScript_Basic &add_global(const Boxed_Value &t_bv, const std::string &t_name) {
|
||||
Name_Validator::validate_object_name(t_name);
|
||||
m_engine.add_global(t_bv, t_name);
|
||||
return *this;
|
||||
}
|
||||
|
||||
ChaiScript_Basic &set_global(const Boxed_Value &t_bv, const std::string &t_name)
|
||||
{
|
||||
ChaiScript_Basic &set_global(const Boxed_Value &t_bv, const std::string &t_name) {
|
||||
Name_Validator::validate_object_name(t_name);
|
||||
m_engine.set_global(t_bv, t_name);
|
||||
return *this;
|
||||
@ -461,8 +413,7 @@ namespace chaiscript
|
||||
/// are left out due to performance considerations involved in tracking the state
|
||||
/// \sa ChaiScript::get_state
|
||||
/// \sa ChaiScript::set_state
|
||||
struct State
|
||||
{
|
||||
struct State {
|
||||
std::set<std::string> used_files;
|
||||
chaiscript::detail::Dispatch_Engine::State engine_state;
|
||||
std::set<std::string> active_loaded_modules;
|
||||
@ -481,8 +432,7 @@ namespace chaiscript
|
||||
/// chaiscript::ChaiScript chai;
|
||||
/// chaiscript::ChaiScript::State s = chai.get_state(); // represents bootstrapped initial state
|
||||
/// \endcode
|
||||
State get_state() const
|
||||
{
|
||||
State get_state() const {
|
||||
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);
|
||||
|
||||
@ -507,8 +457,7 @@ namespace chaiscript
|
||||
/// chai.add(chaiscript::fun(&somefunction), "somefunction");
|
||||
/// chai.set_state(s); // restore initial state, which does not have the recently added "somefunction"
|
||||
/// \endcode
|
||||
void set_state(const State &t_state)
|
||||
{
|
||||
void set_state(const State &t_state) {
|
||||
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);
|
||||
|
||||
@ -518,20 +467,14 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
/// \returns All values in the local thread state, added through the add() function
|
||||
std::map<std::string, Boxed_Value> get_locals() const
|
||||
{
|
||||
return m_engine.get_locals();
|
||||
}
|
||||
std::map<std::string, Boxed_Value> get_locals() const { return m_engine.get_locals(); }
|
||||
|
||||
/// \brief Sets all of the locals for the current thread state.
|
||||
///
|
||||
/// \param[in] t_locals The map<name, value> set of variables to replace the current state with
|
||||
///
|
||||
/// Any existing locals are removed and the given set of variables is added
|
||||
void set_locals(const std::map<std::string, Boxed_Value> &t_locals)
|
||||
{
|
||||
m_engine.set_locals(t_locals);
|
||||
}
|
||||
void set_locals(const std::map<std::string, Boxed_Value> &t_locals) { m_engine.set_locals(t_locals); }
|
||||
|
||||
/// \brief Adds a type, function or object to ChaiScript. Objects are added to the local thread state.
|
||||
/// \param[in] t_t Item to add
|
||||
@ -549,8 +492,7 @@ namespace chaiscript
|
||||
///
|
||||
/// \sa \ref adding_items
|
||||
template<typename T>
|
||||
ChaiScript_Basic &add(const T &t_t, const std::string &t_name)
|
||||
{
|
||||
ChaiScript_Basic &add(const T &t_t, const std::string &t_name) {
|
||||
Name_Validator::validate_object_name(t_name);
|
||||
m_engine.add(t_t, t_name);
|
||||
return *this;
|
||||
@ -565,8 +507,7 @@ namespace chaiscript
|
||||
/// chaiscript::ChaiScript chai;
|
||||
/// chai.add(chaiscript::base_class<std::runtime_error, chaiscript::dispatch_error>());
|
||||
/// \endcode
|
||||
ChaiScript_Basic &add(const Type_Conversion &d)
|
||||
{
|
||||
ChaiScript_Basic &add(const Type_Conversion &d) {
|
||||
m_engine.add(d);
|
||||
return *this;
|
||||
}
|
||||
@ -574,8 +515,7 @@ namespace chaiscript
|
||||
/// \brief Adds all elements of a module to ChaiScript runtime
|
||||
/// \param[in] t_p The module to add.
|
||||
/// \sa chaiscript::Module
|
||||
ChaiScript_Basic &add(const ModulePtr &t_p)
|
||||
{
|
||||
ChaiScript_Basic &add(const ModulePtr &t_p) {
|
||||
t_p->apply(*this, this->get_eval_engine());
|
||||
return *this;
|
||||
}
|
||||
@ -592,16 +532,14 @@ namespace chaiscript
|
||||
/// (the symbol mentioned above), an exception is thrown.
|
||||
///
|
||||
/// \throw chaiscript::exception::load_module_error In the event that no matching module can be found.
|
||||
std::string load_module(const std::string &t_module_name)
|
||||
{
|
||||
std::string load_module(const std::string &t_module_name) {
|
||||
#ifdef CHAISCRIPT_NO_DYNLOAD
|
||||
throw chaiscript::exception::load_module_error("Loadable module support was disabled (CHAISCRIPT_NO_DYNLOAD)");
|
||||
#else
|
||||
std::vector<exception::load_module_error> errors;
|
||||
std::string version_stripped_name = t_module_name;
|
||||
size_t version_pos = version_stripped_name.find("-" + Build_Info::version());
|
||||
if (version_pos != std::string::npos)
|
||||
{
|
||||
if (version_pos != std::string::npos) {
|
||||
version_stripped_name.erase(version_pos);
|
||||
}
|
||||
|
||||
@ -609,12 +547,9 @@ namespace chaiscript
|
||||
|
||||
std::vector<std::string> postfixes{".dll", ".so", ".bundle", ""};
|
||||
|
||||
for (auto & elem : m_module_paths)
|
||||
{
|
||||
for (auto & prefix : prefixes)
|
||||
{
|
||||
for (auto & postfix : postfixes)
|
||||
{
|
||||
for (auto &elem : m_module_paths) {
|
||||
for (auto &prefix : prefixes) {
|
||||
for (auto &postfix : postfixes) {
|
||||
try {
|
||||
const auto name = elem + prefix + t_module_name + postfix;
|
||||
// std::cerr << "trying location: " << name << '\n';
|
||||
@ -640,12 +575,10 @@ namespace chaiscript
|
||||
/// \param[in] t_filename Ignore normal filename search process and use specific filename
|
||||
///
|
||||
/// \sa ChaiScript::load_module(const std::string &t_module_name)
|
||||
void load_module(const std::string &t_module_name, const std::string &t_filename)
|
||||
{
|
||||
void load_module(const std::string &t_module_name, const std::string &t_filename) {
|
||||
chaiscript::detail::threading::lock_guard<chaiscript::detail::threading::recursive_mutex> l(m_use_mutex);
|
||||
|
||||
if (m_loaded_modules.count(t_module_name) == 0)
|
||||
{
|
||||
if (m_loaded_modules.count(t_module_name) == 0) {
|
||||
detail::Loadable_Module_Ptr lm(new detail::Loadable_Module(t_module_name, t_filename));
|
||||
m_loaded_modules[t_module_name] = lm;
|
||||
m_active_loaded_modules.insert(t_module_name);
|
||||
@ -656,7 +589,6 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// \brief Evaluates a string. Equivalent to ChaiScript::eval.
|
||||
///
|
||||
/// \param[in] t_script Script to execute
|
||||
@ -665,8 +597,7 @@ namespace chaiscript
|
||||
/// \return result of the script execution
|
||||
///
|
||||
/// \throw chaiscript::exception::eval_error In the case that evaluation fails.
|
||||
Boxed_Value operator()(const std::string &t_script, const Exception_Handler &t_handler = Exception_Handler())
|
||||
{
|
||||
Boxed_Value operator()(const std::string &t_script, const Exception_Handler &t_handler = Exception_Handler()) {
|
||||
return eval(t_script, t_handler);
|
||||
}
|
||||
|
||||
@ -684,19 +615,16 @@ namespace chaiscript
|
||||
/// \throw chaiscript::exception::bad_boxed_cast In the case that evaluation succeeds but the result value cannot be converted
|
||||
/// to the requested type.
|
||||
template<typename T>
|
||||
T eval(const std::string &t_input, const Exception_Handler &t_handler = Exception_Handler(), const std::string &t_filename="__EVAL__")
|
||||
{
|
||||
T eval(const std::string &t_input, const Exception_Handler &t_handler = Exception_Handler(), const std::string &t_filename = "__EVAL__") {
|
||||
return m_engine.boxed_cast<T>(eval(t_input, t_handler, t_filename));
|
||||
}
|
||||
|
||||
/// \brief casts an object while applying any Dynamic_Conversion available
|
||||
template<typename Type>
|
||||
decltype(auto) boxed_cast(const Boxed_Value &bv) const
|
||||
{
|
||||
return(m_engine.boxed_cast<Type>(bv));
|
||||
decltype(auto) boxed_cast(const Boxed_Value &bv) const {
|
||||
return (m_engine.boxed_cast<Type>(bv));
|
||||
}
|
||||
|
||||
|
||||
/// \brief Evaluates a string.
|
||||
///
|
||||
/// \param[in] t_input Script to execute
|
||||
@ -707,8 +635,8 @@ namespace chaiscript
|
||||
/// \return result of the script execution
|
||||
///
|
||||
/// \throw exception::eval_error In the case that evaluation fails.
|
||||
Boxed_Value eval(const std::string &t_input, const Exception_Handler &t_handler = Exception_Handler(), const std::string &t_filename="__EVAL__")
|
||||
{
|
||||
Boxed_Value
|
||||
eval(const std::string &t_input, const Exception_Handler &t_handler = Exception_Handler(), const std::string &t_filename = "__EVAL__") {
|
||||
try {
|
||||
return do_eval(t_input, t_filename);
|
||||
} catch (Boxed_Value &bv) {
|
||||
@ -744,39 +672,35 @@ namespace chaiscript
|
||||
/// \brief Imports a namespace object into the global scope of this ChaiScript instance.
|
||||
/// \param[in] t_namespace_name Name of the namespace to import.
|
||||
/// \throw std::runtime_error In the case that the namespace name was never registered.
|
||||
void import(const std::string& t_namespace_name)
|
||||
{
|
||||
void import(const std::string &t_namespace_name) {
|
||||
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::recursive_mutex> l(m_use_mutex);
|
||||
|
||||
if (m_engine.get_scripting_objects().count(t_namespace_name)) {
|
||||
throw std::runtime_error("Namespace: " + t_namespace_name + " was already defined");
|
||||
}
|
||||
else if (m_namespace_generators.count(t_namespace_name)) {
|
||||
} else if (m_namespace_generators.count(t_namespace_name)) {
|
||||
m_engine.add_global(var(std::ref(m_namespace_generators[t_namespace_name]())), t_namespace_name);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
throw std::runtime_error("No registered namespace: " + t_namespace_name);
|
||||
}
|
||||
}
|
||||
|
||||
/// \brief Registers a namespace generator, which delays generation of the namespace until it is imported, saving memory if it is never used.
|
||||
/// \param[in] t_namespace_generator Namespace generator function.
|
||||
/// \param[in] t_namespace_name Name of the Namespace function being registered.
|
||||
/// \throw std::runtime_error In the case that the namespace name was already registered.
|
||||
void register_namespace(const std::function<void(Namespace&)>& t_namespace_generator, const std::string& t_namespace_name)
|
||||
{
|
||||
/// \brief Registers a namespace generator, which delays generation of the namespace until it is imported, saving memory if it is never
|
||||
/// used. \param[in] t_namespace_generator Namespace generator function. \param[in] t_namespace_name Name of the Namespace function
|
||||
/// being registered. \throw std::runtime_error In the case that the namespace name was already registered.
|
||||
void register_namespace(const std::function<void(Namespace &)> &t_namespace_generator, const std::string &t_namespace_name) {
|
||||
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::recursive_mutex> l(m_use_mutex);
|
||||
|
||||
if (!m_namespace_generators.count(t_namespace_name)) {
|
||||
// contain the namespace object memory within the m_namespace_generators map
|
||||
m_namespace_generators.emplace(std::make_pair(t_namespace_name, [=, space = Namespace()]() mutable -> Namespace& { t_namespace_generator(space); return space; }));
|
||||
}
|
||||
else {
|
||||
m_namespace_generators.emplace(std::make_pair(t_namespace_name, [=, space = Namespace()]() mutable -> Namespace & {
|
||||
t_namespace_generator(space);
|
||||
return space;
|
||||
}));
|
||||
} else {
|
||||
throw std::runtime_error("Namespace: " + t_namespace_name + " was already registered.");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace chaiscript
|
||||
#endif /* CHAISCRIPT_ENGINE_HPP_ */
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -9,22 +9,18 @@
|
||||
|
||||
#include "chaiscript_eval.hpp"
|
||||
|
||||
|
||||
namespace chaiscript {
|
||||
namespace optimizer {
|
||||
|
||||
template<typename ... T>
|
||||
struct Optimizer : T...
|
||||
{
|
||||
template<typename... T>
|
||||
struct Optimizer : T... {
|
||||
Optimizer() = default;
|
||||
explicit Optimizer(T ... t)
|
||||
: T(std::move(t))...
|
||||
{
|
||||
explicit Optimizer(T... t)
|
||||
: T(std::move(t))... {
|
||||
}
|
||||
|
||||
template<typename Tracer>
|
||||
auto optimize(eval::AST_Node_Impl_Ptr<Tracer> p) {
|
||||
( (p = static_cast<T&>(*this).optimize(std::move(p))), ... );
|
||||
((p = static_cast<T &>(*this).optimize(std::move(p))), ...);
|
||||
return p;
|
||||
}
|
||||
};
|
||||
@ -46,7 +42,6 @@ namespace chaiscript {
|
||||
return *node.children[offset];
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
if (node->identifier == AST_Node_Type::Compiled) {
|
||||
return dynamic_cast<const eval::Compiled_AST_Node<T>&>(*node).m_original_node->children[offset];
|
||||
@ -59,26 +54,23 @@ namespace chaiscript {
|
||||
template<typename T>
|
||||
auto child_count(const eval::AST_Node_Impl<T> &node) noexcept {
|
||||
if (node.identifier == AST_Node_Type::Compiled) {
|
||||
return dynamic_cast<const eval::Compiled_AST_Node<T>&>(node).m_original_node->children.size();
|
||||
return dynamic_cast<const eval::Compiled_AST_Node<T> &>(node).m_original_node->children.size();
|
||||
} else {
|
||||
return node.children.size();
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T, typename Callable>
|
||||
auto make_compiled_node(eval::AST_Node_Impl_Ptr<T> original_node, std::vector<eval::AST_Node_Impl_Ptr<T>> children, Callable callable)
|
||||
{
|
||||
return chaiscript::make_unique<eval::AST_Node_Impl<T>, eval::Compiled_AST_Node<T>>(std::move(original_node), std::move(children), std::move(callable));
|
||||
auto make_compiled_node(eval::AST_Node_Impl_Ptr<T> original_node, std::vector<eval::AST_Node_Impl_Ptr<T>> children, Callable callable) {
|
||||
return chaiscript::make_unique<eval::AST_Node_Impl<T>, eval::Compiled_AST_Node<T>>(std::move(original_node),
|
||||
std::move(children),
|
||||
std::move(callable));
|
||||
}
|
||||
|
||||
|
||||
struct Return {
|
||||
template<typename T>
|
||||
auto optimize(eval::AST_Node_Impl_Ptr<T> p)
|
||||
{
|
||||
if ( (p->identifier == AST_Node_Type::Def || p->identifier == AST_Node_Type::Lambda)
|
||||
&& !p->children.empty())
|
||||
{
|
||||
auto optimize(eval::AST_Node_Impl_Ptr<T> p) {
|
||||
if ((p->identifier == AST_Node_Type::Def || p->identifier == AST_Node_Type::Lambda) && !p->children.empty()) {
|
||||
auto &last_child = p->children.back();
|
||||
if (last_child->identifier == AST_Node_Type::Block) {
|
||||
auto &block_last_child = last_child->children.back();
|
||||
@ -95,9 +87,9 @@ namespace chaiscript {
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
bool contains_var_decl_in_scope(const eval::AST_Node_Impl<T> &node) noexcept
|
||||
{
|
||||
if (node.identifier == AST_Node_Type::Var_Decl || node.identifier == AST_Node_Type::Assign_Decl || node.identifier == AST_Node_Type::Reference) {
|
||||
bool contains_var_decl_in_scope(const eval::AST_Node_Impl<T> &node) noexcept {
|
||||
if (node.identifier == AST_Node_Type::Var_Decl || node.identifier == AST_Node_Type::Assign_Decl
|
||||
|| node.identifier == AST_Node_Type::Reference) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -105,10 +97,8 @@ namespace chaiscript {
|
||||
|
||||
for (size_t i = 0; i < num; ++i) {
|
||||
const auto &child = child_at(node, i);
|
||||
if (child.identifier != AST_Node_Type::Block
|
||||
&& child.identifier != AST_Node_Type::For
|
||||
&& child.identifier != AST_Node_Type::Ranged_For
|
||||
&& contains_var_decl_in_scope(child)) {
|
||||
if (child.identifier != AST_Node_Type::Block && child.identifier != AST_Node_Type::For
|
||||
&& child.identifier != AST_Node_Type::Ranged_For && contains_var_decl_in_scope(child)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -119,14 +109,13 @@ namespace chaiscript {
|
||||
struct Block {
|
||||
template<typename T>
|
||||
auto optimize(eval::AST_Node_Impl_Ptr<T> node) {
|
||||
if (node->identifier == AST_Node_Type::Block)
|
||||
{
|
||||
if (!contains_var_decl_in_scope(*node))
|
||||
{
|
||||
if (node->identifier == AST_Node_Type::Block) {
|
||||
if (!contains_var_decl_in_scope(*node)) {
|
||||
if (node->children.size() == 1) {
|
||||
return std::move(node->children[0]);
|
||||
} else {
|
||||
return chaiscript::make_unique<eval::AST_Node_Impl<T>, eval::Scopeless_Block_AST_Node<T>>(node->text, node->location,
|
||||
return chaiscript::make_unique<eval::AST_Node_Impl<T>, eval::Scopeless_Block_AST_Node<T>>(node->text,
|
||||
node->location,
|
||||
std::move(node->children));
|
||||
}
|
||||
}
|
||||
@ -139,16 +128,14 @@ namespace chaiscript {
|
||||
struct Dead_Code {
|
||||
template<typename T>
|
||||
auto optimize(eval::AST_Node_Impl_Ptr<T> node) {
|
||||
if (node->identifier == AST_Node_Type::Block)
|
||||
{
|
||||
if (node->identifier == AST_Node_Type::Block) {
|
||||
std::vector<size_t> keepers;
|
||||
const auto num_children = node->children.size();
|
||||
keepers.reserve(num_children);
|
||||
|
||||
for (size_t i = 0; i < num_children; ++i) {
|
||||
const auto &child = *node->children[i];
|
||||
if ( (child.identifier != AST_Node_Type::Id
|
||||
&& child.identifier != AST_Node_Type::Constant
|
||||
if ((child.identifier != AST_Node_Type::Id && child.identifier != AST_Node_Type::Constant
|
||||
&& child.identifier != AST_Node_Type::Noop)
|
||||
|| i == num_children - 1) {
|
||||
keepers.push_back(i);
|
||||
@ -158,10 +145,9 @@ namespace chaiscript {
|
||||
if (keepers.size() == num_children) {
|
||||
return node;
|
||||
} else {
|
||||
const auto new_children = [&](){
|
||||
const auto new_children = [&]() {
|
||||
std::vector<eval::AST_Node_Impl_Ptr<T>> retval;
|
||||
for (const auto x : keepers)
|
||||
{
|
||||
for (const auto x : keepers) {
|
||||
retval.push_back(std::move(node->children[x]));
|
||||
}
|
||||
return retval;
|
||||
@ -178,29 +164,25 @@ namespace chaiscript {
|
||||
struct Unused_Return {
|
||||
template<typename T>
|
||||
auto optimize(eval::AST_Node_Impl_Ptr<T> node) {
|
||||
if ((node->identifier == AST_Node_Type::Block
|
||||
|| node->identifier == AST_Node_Type::Scopeless_Block)
|
||||
&& !node->children.empty())
|
||||
{
|
||||
for (size_t i = 0; i < node->children.size()-1; ++i) {
|
||||
if ((node->identifier == AST_Node_Type::Block || node->identifier == AST_Node_Type::Scopeless_Block) && !node->children.empty()) {
|
||||
for (size_t i = 0; i < node->children.size() - 1; ++i) {
|
||||
auto child = node->children[i].get();
|
||||
if (child->identifier == AST_Node_Type::Fun_Call) {
|
||||
node->children[i] = chaiscript::make_unique<eval::AST_Node_Impl<T>, eval::Unused_Return_Fun_Call_AST_Node<T>>(child->text, child->location,
|
||||
node->children[i]
|
||||
= chaiscript::make_unique<eval::AST_Node_Impl<T>, eval::Unused_Return_Fun_Call_AST_Node<T>>(child->text,
|
||||
child->location,
|
||||
std::move(child->children));
|
||||
}
|
||||
}
|
||||
} else if ((node->identifier == AST_Node_Type::For
|
||||
|| node->identifier == AST_Node_Type::While)
|
||||
&& child_count(*node) > 0) {
|
||||
} else if ((node->identifier == AST_Node_Type::For || node->identifier == AST_Node_Type::While) && child_count(*node) > 0) {
|
||||
auto &child = child_at(*node, child_count(*node) - 1);
|
||||
if (child.identifier == AST_Node_Type::Block
|
||||
|| child.identifier == AST_Node_Type::Scopeless_Block)
|
||||
{
|
||||
if (child.identifier == AST_Node_Type::Block || child.identifier == AST_Node_Type::Scopeless_Block) {
|
||||
auto num_sub_children = child_count(child);
|
||||
for (size_t i = 0; i < num_sub_children; ++i) {
|
||||
auto &sub_child = child_at(child, i);
|
||||
if (sub_child.identifier == AST_Node_Type::Fun_Call) {
|
||||
child.children[i] = chaiscript::make_unique<eval::AST_Node_Impl<T>, eval::Unused_Return_Fun_Call_AST_Node<T>>(sub_child.text, sub_child.location, std::move(sub_child.children));
|
||||
child.children[i] = chaiscript::make_unique<eval::AST_Node_Impl<T>, eval::Unused_Return_Fun_Call_AST_Node<T>>(
|
||||
sub_child.text, sub_child.location, std::move(sub_child.children));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -212,31 +194,24 @@ namespace chaiscript {
|
||||
struct Assign_Decl {
|
||||
template<typename T>
|
||||
auto optimize(eval::AST_Node_Impl_Ptr<T> node) {
|
||||
if ((node->identifier == AST_Node_Type::Equation)
|
||||
&& node->text == "="
|
||||
&& node->children.size() == 2
|
||||
&& node->children[0]->identifier == AST_Node_Type::Var_Decl
|
||||
)
|
||||
{
|
||||
if ((node->identifier == AST_Node_Type::Equation) && node->text == "=" && node->children.size() == 2
|
||||
&& node->children[0]->identifier == AST_Node_Type::Var_Decl) {
|
||||
std::vector<eval::AST_Node_Impl_Ptr<T>> new_children;
|
||||
new_children.push_back(std::move(node->children[0]->children[0]));
|
||||
new_children.push_back(std::move(node->children[1]));
|
||||
return chaiscript::make_unique<eval::AST_Node_Impl<T>, eval::Assign_Decl_AST_Node<T>>(node->text,
|
||||
node->location, std::move(new_children) );
|
||||
node->location,
|
||||
std::move(new_children));
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct If {
|
||||
template<typename T>
|
||||
auto optimize(eval::AST_Node_Impl_Ptr<T> node) {
|
||||
if ((node->identifier == AST_Node_Type::If)
|
||||
&& node->children.size() >= 2
|
||||
&& node->children[0]->identifier == AST_Node_Type::Constant)
|
||||
{
|
||||
if ((node->identifier == AST_Node_Type::If) && node->children.size() >= 2 && node->children[0]->identifier == AST_Node_Type::Constant) {
|
||||
const auto condition = dynamic_cast<eval::Constant_AST_Node<T> *>(node->children[0].get())->m_value;
|
||||
if (condition.get_type_info().bare_equal_type_info(typeid(bool))) {
|
||||
if (boxed_cast<bool>(condition)) {
|
||||
@ -254,25 +229,21 @@ namespace chaiscript {
|
||||
struct Partial_Fold {
|
||||
template<typename T>
|
||||
auto optimize(eval::AST_Node_Impl_Ptr<T> node) {
|
||||
|
||||
// Fold right side
|
||||
if (node->identifier == AST_Node_Type::Binary
|
||||
&& node->children.size() == 2
|
||||
&& node->children[0]->identifier != AST_Node_Type::Constant
|
||||
&& node->children[1]->identifier == AST_Node_Type::Constant)
|
||||
{
|
||||
if (node->identifier == AST_Node_Type::Binary && node->children.size() == 2
|
||||
&& node->children[0]->identifier != AST_Node_Type::Constant && node->children[1]->identifier == AST_Node_Type::Constant) {
|
||||
try {
|
||||
const auto &oper = node->text;
|
||||
const auto parsed = Operators::to_operator(oper);
|
||||
if (parsed != Operators::Opers::invalid) {
|
||||
const auto rhs = dynamic_cast<eval::Constant_AST_Node<T> *>(node->children[1].get())->m_value;
|
||||
if (rhs.get_type_info().is_arithmetic()) {
|
||||
return chaiscript::make_unique<eval::AST_Node_Impl<T>, eval::Fold_Right_Binary_Operator_AST_Node<T>>(node->text, node->location,
|
||||
std::move(node->children), rhs);
|
||||
return chaiscript::make_unique<eval::AST_Node_Impl<T>, eval::Fold_Right_Binary_Operator_AST_Node<T>>(
|
||||
node->text, node->location, std::move(node->children), rhs);
|
||||
}
|
||||
}
|
||||
} catch (const std::exception &) {
|
||||
//failure to fold, that's OK
|
||||
// failure to fold, that's OK
|
||||
}
|
||||
}
|
||||
|
||||
@ -283,11 +254,7 @@ namespace chaiscript {
|
||||
struct Constant_Fold {
|
||||
template<typename T>
|
||||
auto optimize(eval::AST_Node_Impl_Ptr<T> node) {
|
||||
|
||||
if (node->identifier == AST_Node_Type::Prefix
|
||||
&& node->children.size() == 1
|
||||
&& node->children[0]->identifier == AST_Node_Type::Constant)
|
||||
{
|
||||
if (node->identifier == AST_Node_Type::Prefix && node->children.size() == 1 && node->children[0]->identifier == AST_Node_Type::Constant) {
|
||||
try {
|
||||
const auto &oper = node->text;
|
||||
const auto parsed = Operators::to_operator(oper, true);
|
||||
@ -296,38 +263,42 @@ namespace chaiscript {
|
||||
|
||||
if (parsed != Operators::Opers::invalid && parsed != Operators::Opers::bitwise_and && lhs.get_type_info().is_arithmetic()) {
|
||||
const auto val = Boxed_Number::do_oper(parsed, lhs);
|
||||
return chaiscript::make_unique<eval::AST_Node_Impl<T>, eval::Constant_AST_Node<T>>(std::move(match), node->location, std::move(val));
|
||||
return chaiscript::make_unique<eval::AST_Node_Impl<T>, eval::Constant_AST_Node<T>>(std::move(match),
|
||||
node->location,
|
||||
std::move(val));
|
||||
} else if (lhs.get_type_info().bare_equal_type_info(typeid(bool)) && oper == "!") {
|
||||
return chaiscript::make_unique<eval::AST_Node_Impl<T>, eval::Constant_AST_Node<T>>(std::move(match), node->location, Boxed_Value(!boxed_cast<bool>(lhs)));
|
||||
return chaiscript::make_unique<eval::AST_Node_Impl<T>, eval::Constant_AST_Node<T>>(std::move(match),
|
||||
node->location,
|
||||
Boxed_Value(!boxed_cast<bool>(lhs)));
|
||||
}
|
||||
} catch (const std::exception &) {
|
||||
//failure to fold, that's OK
|
||||
// failure to fold, that's OK
|
||||
}
|
||||
} else if ((node->identifier == AST_Node_Type::Logical_And || node->identifier == AST_Node_Type::Logical_Or)
|
||||
&& node->children.size() == 2
|
||||
&& node->children[0]->identifier == AST_Node_Type::Constant
|
||||
&& node->children[1]->identifier == AST_Node_Type::Constant)
|
||||
{
|
||||
&& node->children.size() == 2 && node->children[0]->identifier == AST_Node_Type::Constant
|
||||
&& node->children[1]->identifier == AST_Node_Type::Constant) {
|
||||
try {
|
||||
const auto lhs = dynamic_cast<const eval::Constant_AST_Node<T> &>(*node->children[0]).m_value;
|
||||
const auto rhs = dynamic_cast<const eval::Constant_AST_Node<T> &>(*node->children[1]).m_value;
|
||||
if (lhs.get_type_info().bare_equal_type_info(typeid(bool)) && rhs.get_type_info().bare_equal_type_info(typeid(bool))) {
|
||||
const auto match = node->children[0]->text + " " + node->text + " " + node->children[1]->text;
|
||||
const auto val = [lhs_val = boxed_cast<bool>(lhs), rhs_val = boxed_cast<bool>(rhs), id = node->identifier] {
|
||||
if (id == AST_Node_Type::Logical_And) { return Boxed_Value(lhs_val && rhs_val); }
|
||||
else { return Boxed_Value(lhs_val || rhs_val); }
|
||||
if (id == AST_Node_Type::Logical_And) {
|
||||
return Boxed_Value(lhs_val && rhs_val);
|
||||
} else {
|
||||
return Boxed_Value(lhs_val || rhs_val);
|
||||
}
|
||||
}();
|
||||
|
||||
return chaiscript::make_unique<eval::AST_Node_Impl<T>, eval::Constant_AST_Node<T>>(std::move(match), node->location, std::move(val));
|
||||
return chaiscript::make_unique<eval::AST_Node_Impl<T>, eval::Constant_AST_Node<T>>(std::move(match),
|
||||
node->location,
|
||||
std::move(val));
|
||||
}
|
||||
} catch (const std::exception &) {
|
||||
//failure to fold, that's OK
|
||||
// failure to fold, that's OK
|
||||
}
|
||||
} else if (node->identifier == AST_Node_Type::Binary
|
||||
&& node->children.size() == 2
|
||||
&& node->children[0]->identifier == AST_Node_Type::Constant
|
||||
&& node->children[1]->identifier == AST_Node_Type::Constant)
|
||||
{
|
||||
} else if (node->identifier == AST_Node_Type::Binary && node->children.size() == 2
|
||||
&& node->children[0]->identifier == AST_Node_Type::Constant && node->children[1]->identifier == AST_Node_Type::Constant) {
|
||||
try {
|
||||
const auto &oper = node->text;
|
||||
const auto parsed = Operators::to_operator(oper);
|
||||
@ -337,26 +308,26 @@ namespace chaiscript {
|
||||
if (lhs.get_type_info().is_arithmetic() && rhs.get_type_info().is_arithmetic()) {
|
||||
const auto val = Boxed_Number::do_oper(parsed, lhs, rhs);
|
||||
const auto match = node->children[0]->text + " " + oper + " " + node->children[1]->text;
|
||||
return chaiscript::make_unique<eval::AST_Node_Impl<T>, eval::Constant_AST_Node<T>>(std::move(match), node->location, std::move(val));
|
||||
return chaiscript::make_unique<eval::AST_Node_Impl<T>, eval::Constant_AST_Node<T>>(std::move(match),
|
||||
node->location,
|
||||
std::move(val));
|
||||
}
|
||||
}
|
||||
} catch (const std::exception &) {
|
||||
//failure to fold, that's OK
|
||||
// failure to fold, that's OK
|
||||
}
|
||||
} else if (node->identifier == AST_Node_Type::Fun_Call
|
||||
&& node->children.size() == 2
|
||||
&& node->children[0]->identifier == AST_Node_Type::Id
|
||||
&& node->children[1]->identifier == AST_Node_Type::Arg_List
|
||||
&& node->children[1]->children.size() == 1
|
||||
&& node->children[1]->children[0]->identifier == AST_Node_Type::Constant) {
|
||||
|
||||
} else if (node->identifier == AST_Node_Type::Fun_Call && node->children.size() == 2
|
||||
&& node->children[0]->identifier == AST_Node_Type::Id && node->children[1]->identifier == AST_Node_Type::Arg_List
|
||||
&& node->children[1]->children.size() == 1 && node->children[1]->children[0]->identifier == AST_Node_Type::Constant) {
|
||||
const auto arg = dynamic_cast<const eval::Constant_AST_Node<T> &>(*node->children[1]->children[0]).m_value;
|
||||
if (arg.get_type_info().is_arithmetic()) {
|
||||
const auto &fun_name = node->children[0]->text;
|
||||
|
||||
const auto make_constant = [&node, &fun_name](auto val){
|
||||
const auto make_constant = [&node, &fun_name](auto val) {
|
||||
const auto match = fun_name + "(" + node->children[1]->children[0]->text + ")";
|
||||
return chaiscript::make_unique<eval::AST_Node_Impl<T>, eval::Constant_AST_Node<T>>(std::move(match), node->location, const_var(val));
|
||||
return chaiscript::make_unique<eval::AST_Node_Impl<T>, eval::Constant_AST_Node<T>>(std::move(match),
|
||||
node->location,
|
||||
const_var(val));
|
||||
};
|
||||
|
||||
if (fun_name == "double") {
|
||||
@ -370,10 +341,7 @@ namespace chaiscript {
|
||||
} else if (fun_name == "size_t") {
|
||||
return make_constant(Boxed_Number(arg).get_as<size_t>());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return node;
|
||||
@ -383,7 +351,6 @@ namespace chaiscript {
|
||||
struct For_Loop {
|
||||
template<typename T>
|
||||
auto optimize(eval::AST_Node_Impl_Ptr<T> for_node) {
|
||||
|
||||
if (for_node->identifier != AST_Node_Type::For) {
|
||||
return for_node;
|
||||
}
|
||||
@ -392,30 +359,18 @@ namespace chaiscript {
|
||||
const auto &binary_node = child_at(*for_node, 1);
|
||||
const auto &prefix_node = child_at(*for_node, 2);
|
||||
|
||||
if (child_count(*for_node) == 4
|
||||
&& eq_node.identifier == AST_Node_Type::Assign_Decl
|
||||
&& child_count(eq_node) == 2
|
||||
&& child_at(eq_node, 0).identifier == AST_Node_Type::Id
|
||||
&& child_at(eq_node, 1).identifier == AST_Node_Type::Constant
|
||||
&& binary_node.identifier == AST_Node_Type::Binary
|
||||
&& binary_node.text == "<"
|
||||
&& child_count(binary_node) == 2
|
||||
&& child_at(binary_node, 0).identifier == AST_Node_Type::Id
|
||||
&& child_at(binary_node, 0).text == child_at(eq_node,0).text
|
||||
&& child_at(binary_node, 1).identifier == AST_Node_Type::Constant
|
||||
&& prefix_node.identifier == AST_Node_Type::Prefix
|
||||
&& prefix_node.text == "++"
|
||||
&& child_count(prefix_node) == 1
|
||||
&& child_at(prefix_node, 0).identifier == AST_Node_Type::Id
|
||||
&& child_at(prefix_node, 0).text == child_at(eq_node,0).text)
|
||||
{
|
||||
if (child_count(*for_node) == 4 && eq_node.identifier == AST_Node_Type::Assign_Decl && child_count(eq_node) == 2
|
||||
&& child_at(eq_node, 0).identifier == AST_Node_Type::Id && child_at(eq_node, 1).identifier == AST_Node_Type::Constant
|
||||
&& binary_node.identifier == AST_Node_Type::Binary && binary_node.text == "<" && child_count(binary_node) == 2
|
||||
&& child_at(binary_node, 0).identifier == AST_Node_Type::Id && child_at(binary_node, 0).text == child_at(eq_node, 0).text
|
||||
&& child_at(binary_node, 1).identifier == AST_Node_Type::Constant && prefix_node.identifier == AST_Node_Type::Prefix
|
||||
&& prefix_node.text == "++" && child_count(prefix_node) == 1 && child_at(prefix_node, 0).identifier == AST_Node_Type::Id
|
||||
&& child_at(prefix_node, 0).text == child_at(eq_node, 0).text) {
|
||||
const Boxed_Value &begin = dynamic_cast<const eval::Constant_AST_Node<T> &>(child_at(eq_node, 1)).m_value;
|
||||
const Boxed_Value &end = dynamic_cast<const eval::Constant_AST_Node<T> &>(child_at(binary_node, 1)).m_value;
|
||||
const std::string &id = child_at(prefix_node, 0).text;
|
||||
|
||||
if (begin.get_type_info().bare_equal(user_type<int>())
|
||||
&& end.get_type_info().bare_equal(user_type<int>())) {
|
||||
|
||||
if (begin.get_type_info().bare_equal(user_type<int>()) && end.get_type_info().bare_equal(user_type<int>())) {
|
||||
const auto start_int = boxed_cast<int>(begin);
|
||||
const auto end_int = boxed_cast<int>(end);
|
||||
|
||||
@ -426,8 +381,10 @@ namespace chaiscript {
|
||||
for_node->children.pop_back();
|
||||
body_vector.emplace_back(std::move(body_child));
|
||||
|
||||
return make_compiled_node(std::move(for_node), std::move(body_vector),
|
||||
[id, start_int, end_int](const std::vector<eval::AST_Node_Impl_Ptr<T>> &children, const chaiscript::detail::Dispatch_State &t_ss) {
|
||||
return make_compiled_node(std::move(for_node),
|
||||
std::move(body_vector),
|
||||
[id, start_int, end_int](const std::vector<eval::AST_Node_Impl_Ptr<T>> &children,
|
||||
const chaiscript::detail::Dispatch_State &t_ss) {
|
||||
assert(children.size() == 1);
|
||||
chaiscript::eval::detail::Scope_Push_Pop spp(t_ss);
|
||||
|
||||
@ -450,8 +407,7 @@ namespace chaiscript {
|
||||
}
|
||||
|
||||
return void_var();
|
||||
}
|
||||
);
|
||||
});
|
||||
} else {
|
||||
return for_node;
|
||||
}
|
||||
@ -461,12 +417,17 @@ namespace chaiscript {
|
||||
}
|
||||
};
|
||||
|
||||
using Optimizer_Default = Optimizer<optimizer::Partial_Fold, optimizer::Unused_Return, optimizer::Constant_Fold,
|
||||
optimizer::If, optimizer::Return, optimizer::Dead_Code, optimizer::Block, optimizer::For_Loop, optimizer::Assign_Decl>;
|
||||
|
||||
}
|
||||
}
|
||||
using Optimizer_Default = Optimizer<optimizer::Partial_Fold,
|
||||
optimizer::Unused_Return,
|
||||
optimizer::Constant_Fold,
|
||||
optimizer::If,
|
||||
optimizer::Return,
|
||||
optimizer::Dead_Code,
|
||||
optimizer::Block,
|
||||
optimizer::For_Loop,
|
||||
optimizer::Assign_Decl>;
|
||||
|
||||
} // namespace optimizer
|
||||
} // namespace chaiscript
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -7,19 +7,12 @@
|
||||
#ifndef CHAISCRIPT_POSIX_HPP_
|
||||
#define CHAISCRIPT_POSIX_HPP_
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
struct Loadable_Module
|
||||
{
|
||||
struct DLModule
|
||||
{
|
||||
namespace chaiscript::detail {
|
||||
struct Loadable_Module {
|
||||
struct DLModule {
|
||||
explicit DLModule(const std::string &t_filename)
|
||||
: m_data(dlopen(t_filename.c_str(), RTLD_NOW))
|
||||
{
|
||||
if (m_data == nullptr)
|
||||
{
|
||||
: m_data(dlopen(t_filename.c_str(), RTLD_NOW)) {
|
||||
if (m_data == nullptr) {
|
||||
throw chaiscript::exception::load_module_error(dlerror());
|
||||
}
|
||||
}
|
||||
@ -29,22 +22,16 @@ namespace chaiscript
|
||||
DLModule(const DLModule &) = delete;
|
||||
DLModule &operator=(const DLModule &) = delete;
|
||||
|
||||
~DLModule()
|
||||
{
|
||||
dlclose(m_data);
|
||||
}
|
||||
~DLModule() { dlclose(m_data); }
|
||||
|
||||
void *m_data;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct DLSym
|
||||
{
|
||||
struct DLSym {
|
||||
DLSym(DLModule &t_mod, const std::string &t_symbol)
|
||||
: m_symbol(reinterpret_cast<T>(dlsym(t_mod.m_data, t_symbol.c_str())))
|
||||
{
|
||||
if (!m_symbol)
|
||||
{
|
||||
: m_symbol(reinterpret_cast<T>(dlsym(t_mod.m_data, t_symbol.c_str()))) {
|
||||
if (!m_symbol) {
|
||||
throw chaiscript::exception::load_module_error(dlerror());
|
||||
}
|
||||
}
|
||||
@ -53,16 +40,14 @@ namespace chaiscript
|
||||
};
|
||||
|
||||
Loadable_Module(const std::string &t_module_name, const std::string &t_filename)
|
||||
: m_dlmodule(t_filename), m_func(m_dlmodule, "create_chaiscript_module_" + t_module_name),
|
||||
m_moduleptr(m_func.m_symbol())
|
||||
{
|
||||
: m_dlmodule(t_filename)
|
||||
, m_func(m_dlmodule, "create_chaiscript_module_" + t_module_name)
|
||||
, m_moduleptr(m_func.m_symbol()) {
|
||||
}
|
||||
|
||||
DLModule m_dlmodule;
|
||||
DLSym<Create_Module_Func> m_func;
|
||||
ModulePtr m_moduleptr;
|
||||
};
|
||||
}
|
||||
}
|
||||
} // namespace chaiscript::detail
|
||||
#endif
|
||||
|
||||
|
||||
@ -8,8 +8,9 @@
|
||||
#define CHAISCRIPT_PRELUDE_HPP_
|
||||
|
||||
namespace chaiscript {
|
||||
struct ChaiScript_Prelude {
|
||||
static std::string chaiscript_prelude() { return R"chaiscript(
|
||||
struct ChaiScript_Prelude {
|
||||
static std::string chaiscript_prelude() {
|
||||
return R"chaiscript(
|
||||
|
||||
def lt(l, r) {
|
||||
if (call_exists(`<`, l, r)) {
|
||||
@ -554,9 +555,8 @@ def find(container, value) {
|
||||
|
||||
|
||||
)chaiscript";
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
} // namespace chaiscript
|
||||
|
||||
#endif /* CHAISCRIPT_PRELUDE_HPP_ */
|
||||
|
||||
@ -2,26 +2,22 @@
|
||||
/// regarding the ChaiScript standard runtime library.
|
||||
|
||||
/// \brief Items in this namespace exist in the ChaiScript language runtime. They are not part of the C++ API
|
||||
namespace ChaiScript_Language
|
||||
{
|
||||
namespace ChaiScript_Language {
|
||||
/// \page LangStandardLibraryRef ChaiScript Language Standard Library Reference
|
||||
///
|
||||
/// ChaiScript, at its core, has some very functional programming-inspired habits. Few places show this off as clearly
|
||||
/// as the prelude, itself a name taken as a nod to the popular functional language Haskell. This prelude is available
|
||||
/// to all standard ChaiScript applications, and provides a simple foundation for using numbers, strings, and ranges
|
||||
/// (the general category of Range cs and their iteration).
|
||||
///
|
||||
|
||||
/// \page LangStandardLibraryRef ChaiScript Language Standard Library Reference
|
||||
///
|
||||
/// ChaiScript, at its core, has some very functional programming-inspired habits. Few places show this off as clearly
|
||||
/// as the prelude, itself a name taken as a nod to the popular functional language Haskell. This prelude is available
|
||||
/// to all standard ChaiScript applications, and provides a simple foundation for using numbers, strings, and ranges
|
||||
/// (the general category of Range cs and their iteration).
|
||||
///
|
||||
|
||||
|
||||
/// \brief Generic concept of a value in ChaiScript.
|
||||
///
|
||||
/// The Object type exists merely as a concept. All objects in ChaiScript support this concept
|
||||
/// and have the following methods available to them. All objects are stored internally as chaiscript::Boxed_Value types.
|
||||
///
|
||||
/// \sa chaiscript::Boxed_Value
|
||||
class Object
|
||||
{
|
||||
/// \brief Generic concept of a value in ChaiScript.
|
||||
///
|
||||
/// The Object type exists merely as a concept. All objects in ChaiScript support this concept
|
||||
/// and have the following methods available to them. All objects are stored internally as chaiscript::Boxed_Value types.
|
||||
///
|
||||
/// \sa chaiscript::Boxed_Value
|
||||
class Object {
|
||||
public:
|
||||
/// \brief Returns the Type_Info value for this Object
|
||||
Type_Info get_type_info() const;
|
||||
@ -51,42 +47,39 @@ class Object
|
||||
///
|
||||
/// \sa Type_Info::name();
|
||||
string type_name() const;
|
||||
};
|
||||
};
|
||||
|
||||
/// \brief Item returned from a Range object from a Map
|
||||
class Map_Pair
|
||||
{
|
||||
/// \brief Item returned from a Range object from a Map
|
||||
class Map_Pair {
|
||||
public:
|
||||
/// \brief Returns the key of the Map entry
|
||||
const string first();
|
||||
|
||||
/// \brief Returns the value Object of the Map entry
|
||||
Object second();
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/// \brief Maps strings to Objects
|
||||
///
|
||||
/// ChaiScript has a built in shortcut for generating Map objects:
|
||||
///
|
||||
/// Example:
|
||||
/// \code
|
||||
/// eval> var m = ["a":1, "b":2];
|
||||
/// [<a,1>, <b,2>]
|
||||
/// eval> m.count("a");
|
||||
/// 1
|
||||
/// eval> m.count("c");
|
||||
/// 0
|
||||
/// eval> m.size();
|
||||
/// 2
|
||||
/// \endcode
|
||||
///
|
||||
/// Implemented as std::map<Boxed_Value>
|
||||
///
|
||||
/// \sa Map_Pair
|
||||
/// \sa chaiscript::bootstrap::standard_library::map_type
|
||||
class Map
|
||||
{
|
||||
/// \brief Maps strings to Objects
|
||||
///
|
||||
/// ChaiScript has a built in shortcut for generating Map objects:
|
||||
///
|
||||
/// Example:
|
||||
/// \code
|
||||
/// eval> var m = ["a":1, "b":2];
|
||||
/// [<a,1>, <b,2>]
|
||||
/// eval> m.count("a");
|
||||
/// 1
|
||||
/// eval> m.count("c");
|
||||
/// 0
|
||||
/// eval> m.size();
|
||||
/// 2
|
||||
/// \endcode
|
||||
///
|
||||
/// Implemented as std::map<Boxed_Value>
|
||||
///
|
||||
/// \sa Map_Pair
|
||||
/// \sa chaiscript::bootstrap::standard_library::map_type
|
||||
class Map {
|
||||
public:
|
||||
/// \brief Returns an object that implements the Range concept for the Map_Pair's in this Map
|
||||
Range range();
|
||||
@ -108,64 +101,57 @@ class Map
|
||||
|
||||
/// \brief Returns true if the map contains no items
|
||||
bool empty() const;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
||||
/// \brief A concept implemented by string, Vector and Map. It is convertible to Range, default constructable and back_insertable
|
||||
class Container
|
||||
{
|
||||
/// \brief A concept implemented by string, Vector and Map. It is convertible to Range, default constructable and back_insertable
|
||||
class Container {
|
||||
public:
|
||||
void push_back(Object);
|
||||
Range range();
|
||||
Const_Range range() const;
|
||||
};
|
||||
};
|
||||
|
||||
/// \brief Converts o into a string.
|
||||
///
|
||||
/// \code
|
||||
/// eval> to_string(3).is_type("string") <br>
|
||||
/// true<br>
|
||||
/// \endcode
|
||||
string to_string(Object o);
|
||||
|
||||
/// \brief Converts o into a string.
|
||||
///
|
||||
/// \code
|
||||
/// eval> to_string(3).is_type("string") <br>
|
||||
/// true<br>
|
||||
/// \endcode
|
||||
string to_string(Object o);
|
||||
/// \brief Prints o to the terminal, without a trailing carriage return. Applies conversions to string automatically.
|
||||
/// \code
|
||||
/// eval> puts("hi, "); puts("there")
|
||||
/// hi, thereeval>
|
||||
/// \endcode
|
||||
/// \sa to_string
|
||||
/// \sa print
|
||||
void puts(Object o);
|
||||
|
||||
/// \brief Prints o to the terminal, with a trailing carriage return. Applies conversions to string automatically
|
||||
/// \code
|
||||
/// eval> print("hello")
|
||||
/// hello
|
||||
/// eval>
|
||||
/// \endcode
|
||||
/// \sa to_string
|
||||
/// \sa puts
|
||||
void print(Object o);
|
||||
|
||||
/// \brief Prints o to the terminal, without a trailing carriage return. Applies conversions to string automatically.
|
||||
/// \code
|
||||
/// eval> puts("hi, "); puts("there")
|
||||
/// hi, thereeval>
|
||||
/// \endcode
|
||||
/// \sa to_string
|
||||
/// \sa print
|
||||
void puts(Object o);
|
||||
|
||||
|
||||
/// \brief Prints o to the terminal, with a trailing carriage return. Applies conversions to string automatically
|
||||
/// \code
|
||||
/// eval> print("hello")
|
||||
/// hello
|
||||
/// eval>
|
||||
/// \endcode
|
||||
/// \sa to_string
|
||||
/// \sa puts
|
||||
void print(Object o);
|
||||
|
||||
/// \brief ChaiScript representation of std::string. It is an std::string but only some member are exposed to ChaiScript.
|
||||
///
|
||||
/// Because the ChaiScript string object is an std::string, it is directly convertible to and from std::string
|
||||
/// using the chaiscript::boxed_cast and chaiscript::var functions.
|
||||
///
|
||||
/// With the exception of string::trim, string::rtrim, string::ltrim, all members are direct pass-throughs to the
|
||||
/// std::string of the same name.
|
||||
///
|
||||
/// \note Object and function notations are equivalent in ChaiScript. This means that
|
||||
/// \c "bob".find("b") and \c find("bob", "b") are exactly the same. Most examples below follow the
|
||||
/// second formation of the function calls.
|
||||
/// \sa \ref keyworddef for extending existing C++ classes in ChaiScript
|
||||
/// \sa chaiscript::bootstrap::standard_library::string_type
|
||||
class string
|
||||
{
|
||||
/// \brief ChaiScript representation of std::string. It is an std::string but only some member are exposed to ChaiScript.
|
||||
///
|
||||
/// Because the ChaiScript string object is an std::string, it is directly convertible to and from std::string
|
||||
/// using the chaiscript::boxed_cast and chaiscript::var functions.
|
||||
///
|
||||
/// With the exception of string::trim, string::rtrim, string::ltrim, all members are direct pass-throughs to the
|
||||
/// std::string of the same name.
|
||||
///
|
||||
/// \note Object and function notations are equivalent in ChaiScript. This means that
|
||||
/// \c "bob".find("b") and \c find("bob", "b") are exactly the same. Most examples below follow the
|
||||
/// second formation of the function calls.
|
||||
/// \sa \ref keyworddef for extending existing C++ classes in ChaiScript
|
||||
/// \sa chaiscript::bootstrap::standard_library::string_type
|
||||
class string {
|
||||
public:
|
||||
/// \brief Finds the first instance of substr.
|
||||
/// \code
|
||||
@ -174,7 +160,6 @@ class string
|
||||
/// \endcode
|
||||
int find(string s) const;
|
||||
|
||||
|
||||
/// \brief Finds the last instance of substr.
|
||||
/// \code
|
||||
/// eval> rfind("abab", "ab")
|
||||
@ -281,16 +266,15 @@ class string
|
||||
|
||||
/// \brief Returns an object that implements the Const_Range concept for the characters of this string
|
||||
Const_Range range() const;
|
||||
};
|
||||
};
|
||||
|
||||
/// \brief A concept in ChaiScript that is implemented by \ref string, Vector and Map. It provides
|
||||
/// easy iteration over the elements in a container.
|
||||
///
|
||||
/// Implemented by the template chaiscript::bootstrap::standard_library::Bidir_Range
|
||||
///
|
||||
/// \sa Const_Range
|
||||
class Range
|
||||
{
|
||||
/// \brief A concept in ChaiScript that is implemented by \ref string, Vector and Map. It provides
|
||||
/// easy iteration over the elements in a container.
|
||||
///
|
||||
/// Implemented by the template chaiscript::bootstrap::standard_library::Bidir_Range
|
||||
///
|
||||
/// \sa Const_Range
|
||||
class Range {
|
||||
public:
|
||||
/// \brief Returns the last item of the range
|
||||
Object back();
|
||||
@ -311,17 +295,15 @@ class Range
|
||||
///
|
||||
/// \post front() returns the element at front() + 1;
|
||||
void pop_front();
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
/// \brief A concept in ChaiScript that is implemented by \ref string, Vector and Map. It provides
|
||||
/// easy iteration over the elements in a container. Contained values are const.
|
||||
///
|
||||
/// Implemented by the template chaiscript::bootstrap::standard_library::Const_Bidir_Range
|
||||
///
|
||||
/// \sa Range
|
||||
class Const_Range
|
||||
{
|
||||
/// \brief A concept in ChaiScript that is implemented by \ref string, Vector and Map. It provides
|
||||
/// easy iteration over the elements in a container. Contained values are const.
|
||||
///
|
||||
/// Implemented by the template chaiscript::bootstrap::standard_library::Const_Bidir_Range
|
||||
///
|
||||
/// \sa Range
|
||||
class Const_Range {
|
||||
public:
|
||||
/// \brief Returns the last item of the range
|
||||
const Object back();
|
||||
@ -342,28 +324,26 @@ class Const_Range
|
||||
///
|
||||
/// \post front() returns the element at front() + 1;
|
||||
void pop_front();
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
/// \brief A vector of Objects
|
||||
///
|
||||
/// ChaiScript includes a shortcut for creating a Vector of Objects
|
||||
///
|
||||
/// Example:
|
||||
/// \code
|
||||
/// eval> var v = [1,2,3,4]
|
||||
/// [1, 2, 3, 4]
|
||||
/// eval> v[0];
|
||||
/// 1
|
||||
/// eval> v.size();
|
||||
/// 4
|
||||
/// \endcode
|
||||
///
|
||||
/// Implemented with std::vector<chaiscript::Boxed_Value>
|
||||
///
|
||||
/// \sa chaiscript::bootstrap::standard_library::vector_type
|
||||
class Vector
|
||||
{
|
||||
/// \brief A vector of Objects
|
||||
///
|
||||
/// ChaiScript includes a shortcut for creating a Vector of Objects
|
||||
///
|
||||
/// Example:
|
||||
/// \code
|
||||
/// eval> var v = [1,2,3,4]
|
||||
/// [1, 2, 3, 4]
|
||||
/// eval> v[0];
|
||||
/// 1
|
||||
/// eval> v.size();
|
||||
/// 4
|
||||
/// \endcode
|
||||
///
|
||||
/// Implemented with std::vector<chaiscript::Boxed_Value>
|
||||
///
|
||||
/// \sa chaiscript::bootstrap::standard_library::vector_type
|
||||
class Vector {
|
||||
public:
|
||||
/// \brief returns the Object at the given index. Throws an exception if the index does not exist
|
||||
Object operator[](int t_index);
|
||||
@ -417,11 +397,9 @@ class Vector
|
||||
|
||||
/// \brief Returns the number of elements in the Vector
|
||||
int size() const;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
class Type_Info
|
||||
{
|
||||
class Type_Info {
|
||||
public:
|
||||
/// \brief Compares this Type_Info object with another one and returns true if the two types are the same
|
||||
/// after const, pointer, reference are removed.
|
||||
@ -450,32 +428,29 @@ class Type_Info
|
||||
|
||||
/// \brief Returns the ChaiScript registered name for the type if one exists.
|
||||
string name() const;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
||||
/// \brief Represents a function object in ChaiScript
|
||||
///
|
||||
/// A function object may be one function, such as:
|
||||
/// \code
|
||||
/// var f = fun(x) { return x; }
|
||||
/// \endcode
|
||||
///
|
||||
/// Or it may represent multiple functions
|
||||
/// \code
|
||||
/// var f2 = `-`; // represents the unary - as well as the set of binary - operators
|
||||
/// \endcode
|
||||
///
|
||||
/// Guarded function example
|
||||
/// \code
|
||||
/// def f3(x) : x > 2 {
|
||||
/// return x;
|
||||
/// }
|
||||
/// \endcode
|
||||
///
|
||||
/// Examples in the function definitions below will reference these examples
|
||||
class Function
|
||||
{
|
||||
/// \brief Represents a function object in ChaiScript
|
||||
///
|
||||
/// A function object may be one function, such as:
|
||||
/// \code
|
||||
/// var f = fun(x) { return x; }
|
||||
/// \endcode
|
||||
///
|
||||
/// Or it may represent multiple functions
|
||||
/// \code
|
||||
/// var f2 = `-`; // represents the unary - as well as the set of binary - operators
|
||||
/// \endcode
|
||||
///
|
||||
/// Guarded function example
|
||||
/// \code
|
||||
/// def f3(x) : x > 2 {
|
||||
/// return x;
|
||||
/// }
|
||||
/// \endcode
|
||||
///
|
||||
/// Examples in the function definitions below will reference these examples
|
||||
class Function {
|
||||
public:
|
||||
/// \brief Returns the annotation description of the function
|
||||
string get_annotation() const;
|
||||
@ -545,286 +520,264 @@ class Function
|
||||
/// 1
|
||||
/// \endcode
|
||||
Object call(Vector t_params) const;
|
||||
}
|
||||
}
|
||||
|
||||
/// \brief Returns the max of a or b. Requires that operator>(a, b) exists
|
||||
/// Equivalent to
|
||||
/// \code
|
||||
/// return a>b?a:b;
|
||||
/// \endcode
|
||||
///
|
||||
/// Example:
|
||||
/// \code
|
||||
/// eval> max(4, 10)
|
||||
/// 10
|
||||
/// \endcode
|
||||
Object
|
||||
max(Object a, Object b);
|
||||
|
||||
/// \brief Returns the min of a or b. Requires that operator<(a, b) exists
|
||||
///
|
||||
/// Equivalent to
|
||||
/// \code
|
||||
/// return a<b?a:b;
|
||||
/// \endcode
|
||||
///
|
||||
/// Example:
|
||||
/// \code
|
||||
/// eval> min(4, 10)
|
||||
/// 4
|
||||
/// \endcode
|
||||
Object min(Object a, Object b);
|
||||
|
||||
/// \brief Returns the max of a or b. Requires that operator>(a, b) exists
|
||||
/// Equivalent to
|
||||
/// \code
|
||||
/// return a>b?a:b;
|
||||
/// \endcode
|
||||
///
|
||||
/// Example:
|
||||
/// \code
|
||||
/// eval> max(4, 10)
|
||||
/// 10
|
||||
/// \endcode
|
||||
Object max(Object a, Object b);
|
||||
/// \brief Returns true if x is an even integer.
|
||||
///
|
||||
/// Will also work on any non-integer type for which an operator%(x, int) exists
|
||||
///
|
||||
/// Example:
|
||||
/// \code
|
||||
/// eval> even(4)
|
||||
/// true
|
||||
/// \endcode
|
||||
bool even(Object x);
|
||||
|
||||
/// \brief Returns the min of a or b. Requires that operator<(a, b) exists
|
||||
///
|
||||
/// Equivalent to
|
||||
/// \code
|
||||
/// return a<b?a:b;
|
||||
/// \endcode
|
||||
///
|
||||
/// Example:
|
||||
/// \code
|
||||
/// eval> min(4, 10)
|
||||
/// 4
|
||||
/// \endcode
|
||||
Object min(Object a, Object b);
|
||||
/// \brief Returns true if x is an odd integer.
|
||||
///
|
||||
/// Will also work on any non-integer type for which an operator%(x, int) exists
|
||||
///
|
||||
/// Example:
|
||||
/// \code
|
||||
/// eval> odd(4)
|
||||
/// false
|
||||
/// \endcode
|
||||
bool even(Object x);
|
||||
|
||||
/// \brief Returns true if x is an even integer.
|
||||
///
|
||||
/// Will also work on any non-integer type for which an operator%(x, int) exists
|
||||
///
|
||||
/// Example:
|
||||
/// \code
|
||||
/// eval> even(4)
|
||||
/// true
|
||||
/// \endcode
|
||||
bool even(Object x);
|
||||
/// \brief Applies the function f over each element in the Range c.
|
||||
///
|
||||
/// Example:
|
||||
/// \code
|
||||
/// eval> for_each([1, 2, 3], print)
|
||||
/// 1
|
||||
/// 2
|
||||
/// 3
|
||||
/// \endcode
|
||||
void for_each(Range c, Function f);
|
||||
|
||||
/// \brief Returns true if x is an odd integer.
|
||||
///
|
||||
/// Will also work on any non-integer type for which an operator%(x, int) exists
|
||||
///
|
||||
/// Example:
|
||||
/// \code
|
||||
/// eval> odd(4)
|
||||
/// false
|
||||
/// \endcode
|
||||
bool even(Object x);
|
||||
/// \brief Applies f over each element in the Range c, joining all the results.
|
||||
///
|
||||
/// Example:
|
||||
/// \code
|
||||
/// eval> map([1, 2, 3], odd)
|
||||
/// [true, false, true]
|
||||
/// \endcode
|
||||
Object map(Range c, Function f);
|
||||
|
||||
/// \brief Starts with the initial value and applies the function f to it and the first element of the Range c.
|
||||
/// The result is then applied to the second element, and so on until the elements are exhausted.
|
||||
///
|
||||
/// Example:
|
||||
/// \code
|
||||
/// eval> foldl([1, 2, 3, 4], `+`, 0)
|
||||
/// 10
|
||||
/// \endcode
|
||||
Object foldl(Range c, Function f, Object initial);
|
||||
|
||||
/// \brief Applies the function f over each element in the Range c.
|
||||
///
|
||||
/// Example:
|
||||
/// \code
|
||||
/// eval> for_each([1, 2, 3], print)
|
||||
/// 1
|
||||
/// 2
|
||||
/// 3
|
||||
/// \endcode
|
||||
void for_each(Range c, Function f);
|
||||
/// \brief Returns the sum total of the values in the Range c.
|
||||
///
|
||||
/// Example:
|
||||
/// \code
|
||||
/// eval> sum([1, 2, 3, 4])
|
||||
/// 10
|
||||
/// \endcode
|
||||
///
|
||||
/// Equivalent to:
|
||||
/// \code
|
||||
/// foldl(c, `+`, 0.0);
|
||||
/// \endcode
|
||||
Numeric sum(Range c);
|
||||
|
||||
/// \brief Returns the product of the value in the Range c.
|
||||
///
|
||||
/// Example:
|
||||
/// \code
|
||||
/// eval> product([1, 2, 3, 4])
|
||||
/// 24
|
||||
/// \endcode
|
||||
///
|
||||
/// Equivalent to:
|
||||
/// \code
|
||||
/// foldl(c, `*`, 1.0);
|
||||
/// \endcode
|
||||
Numeric product(Range c);
|
||||
|
||||
/// \brief Applies f over each element in the Range c, joining all the results.
|
||||
///
|
||||
/// Example:
|
||||
/// \code
|
||||
/// eval> map([1, 2, 3], odd)
|
||||
/// [true, false, true]
|
||||
/// \endcode
|
||||
Object map(Range c, Function f);
|
||||
/// \brief Takes num elements from the Range c, returning them.
|
||||
///
|
||||
/// Example:
|
||||
/// \code
|
||||
/// eval> take([1, 2, 3, 4], 2)
|
||||
/// [1, 2]
|
||||
/// \endcode
|
||||
///
|
||||
/// \returns A container of the same type that was passed in
|
||||
Object take(Range c, int num);
|
||||
|
||||
/// \brief Takes elements from the Range c that match function f, stopping at the first non-match, returning them as a new Vector.
|
||||
///
|
||||
/// Example:
|
||||
/// \code
|
||||
/// eval> take_while([1, 2, 3], odd)
|
||||
/// [1]
|
||||
/// \endcode
|
||||
///
|
||||
/// \returns A container of the same type that was passed in
|
||||
Object take_while(Range c, Function f);
|
||||
|
||||
/// \brief Starts with the initial value and applies the function f to it and the first element of the Range c.
|
||||
/// The result is then applied to the second element, and so on until the elements are exhausted.
|
||||
///
|
||||
/// Example:
|
||||
/// \code
|
||||
/// eval> foldl([1, 2, 3, 4], `+`, 0)
|
||||
/// 10
|
||||
/// \endcode
|
||||
Object foldl(Range c, Function f, Object initial);
|
||||
/// \brief Drops num elements from the Range c, returning the remainder.
|
||||
///
|
||||
/// Example:
|
||||
/// \code
|
||||
/// eval> drop([1, 2, 3, 4], 2)
|
||||
/// [3, 4]
|
||||
/// \endcode
|
||||
///
|
||||
/// \returns A container of the same type that was passed in
|
||||
Object drop(Range c, int num);
|
||||
|
||||
/// \brief Drops elements from the Range c that match f, stopping at the first non-match, returning the remainder.
|
||||
///
|
||||
/// Example:
|
||||
/// \code
|
||||
/// eval> drop_while([1, 2, 3], odd)
|
||||
/// [2, 3]
|
||||
/// \endcode
|
||||
Object drop_while(Range c, Function f);
|
||||
|
||||
/// \brief Returns the sum total of the values in the Range c.
|
||||
///
|
||||
/// Example:
|
||||
/// \code
|
||||
/// eval> sum([1, 2, 3, 4])
|
||||
/// 10
|
||||
/// \endcode
|
||||
///
|
||||
/// Equivalent to:
|
||||
/// \code
|
||||
/// foldl(c, `+`, 0.0);
|
||||
/// \endcode
|
||||
Numeric sum(Range c);
|
||||
/// \brief Similar to foldl, this takes the first two elements as its starting values for f. This assumes Range c has at least 2 elements.
|
||||
///
|
||||
/// Example:
|
||||
/// \code
|
||||
/// eval> reduce([1, 2, 3, 4], `+`)
|
||||
/// 10
|
||||
/// \endcode
|
||||
Object reduce(Range c, Function f);
|
||||
|
||||
/// \brief Takes elements from Container c that match function f, return them.
|
||||
///
|
||||
/// Example:
|
||||
/// \code
|
||||
/// eval> filter([1, 2, 3, 4], odd)
|
||||
/// [1, 3]
|
||||
/// \endcode
|
||||
Object filter(Container c, Function f);
|
||||
|
||||
/// \brief Returns the product of the value in the Range c.
|
||||
///
|
||||
/// Example:
|
||||
/// \code
|
||||
/// eval> product([1, 2, 3, 4])
|
||||
/// 24
|
||||
/// \endcode
|
||||
///
|
||||
/// Equivalent to:
|
||||
/// \code
|
||||
/// foldl(c, `*`, 1.0);
|
||||
/// \endcode
|
||||
Numeric product(Range c);
|
||||
/// \brief Joins the elements of the Range c into a string, delimiting each with the delim string.
|
||||
///
|
||||
/// Example:
|
||||
/// \code
|
||||
/// eval> join([1, 2, 3], "*")
|
||||
/// 1*2*3
|
||||
/// \endcode
|
||||
string join(Range c, string delim);
|
||||
|
||||
/// \brief Returns the contents of the Container c in reversed order.
|
||||
///
|
||||
/// Example:
|
||||
/// \code
|
||||
/// eval> reverse([1, 2, 3, 4, 5, 6, 7])
|
||||
/// [7, 6, 5, 4, 3, 2, 1]
|
||||
/// \endcode
|
||||
Container reverse(Container c);
|
||||
|
||||
/// \brief Takes num elements from the Range c, returning them.
|
||||
///
|
||||
/// Example:
|
||||
/// \code
|
||||
/// eval> take([1, 2, 3, 4], 2)
|
||||
/// [1, 2]
|
||||
/// \endcode
|
||||
///
|
||||
/// \returns A container of the same type that was passed in
|
||||
Object take(Range c, int num);
|
||||
/// \brief Generates a new Vector filled with values starting at x and ending with y.
|
||||
///
|
||||
/// Works on types supporting operator<=(x, y) and operator++(x)
|
||||
///
|
||||
/// Example:
|
||||
/// \code
|
||||
/// eval> generate_range(1, 10)
|
||||
/// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
|
||||
/// \endcode
|
||||
Vector generate_range(Object x, Object y);
|
||||
|
||||
/// \brief Returns a new Range with x and y concatenated.
|
||||
///
|
||||
/// Example:
|
||||
/// \code
|
||||
/// eval> concat([1, 2, 3], [4, 5, 6])
|
||||
/// [1, 2, 3, 4, 5, 6]
|
||||
/// \endcode
|
||||
Object concat(Range x, Range y);
|
||||
|
||||
/// \brief Takes elements from the Range c that match function f, stopping at the first non-match, returning them as a new Vector.
|
||||
///
|
||||
/// Example:
|
||||
/// \code
|
||||
/// eval> take_while([1, 2, 3], odd)
|
||||
/// [1]
|
||||
/// \endcode
|
||||
///
|
||||
/// \returns A container of the same type that was passed in
|
||||
Object take_while(Range c, Function f);
|
||||
/// \brief Returns a new Vector with x and y as its values.
|
||||
///
|
||||
/// Example:
|
||||
/// \code
|
||||
/// eval> collate(1, 2)
|
||||
/// [1, 2]
|
||||
/// \endcode
|
||||
Vector collate(Object x, Object y);
|
||||
|
||||
/// \brief Applies f to elements of x and y, returning a new Vector with the result of each application.
|
||||
///
|
||||
/// Example:
|
||||
/// \code
|
||||
/// eval> zip_with(`+`, [1, 2, 3], [4, 5, 6])
|
||||
/// [5, 7, 9]
|
||||
/// \endcode
|
||||
Vector zip_with(Function f, Range x, Range y);
|
||||
|
||||
/// \brief Drops num elements from the Range c, returning the remainder.
|
||||
///
|
||||
/// Example:
|
||||
/// \code
|
||||
/// eval> drop([1, 2, 3, 4], 2)
|
||||
/// [3, 4]
|
||||
/// \endcode
|
||||
///
|
||||
/// \returns A container of the same type that was passed in
|
||||
Object drop(Range c, int num);
|
||||
/// \brief Collates elements of x and y, returning a new Vector with the result.
|
||||
///
|
||||
/// Example:
|
||||
/// \code
|
||||
/// eval> zip([1, 2, 3], [4, 5, 6])
|
||||
/// [[1, 4], [2, 5], [3, 6]]
|
||||
/// \endcode
|
||||
Vector zip(Range x, Range y);
|
||||
|
||||
/// \brief returns true if there exists a call to the Function f that takes the given parameters
|
||||
///
|
||||
/// Example:
|
||||
/// \code
|
||||
/// eval> call_exists(`+`, 1, 2)
|
||||
/// true
|
||||
/// \endcode
|
||||
bool call_exists(Function f, ...);
|
||||
|
||||
/// \brief Drops elements from the Range c that match f, stopping at the first non-match, returning the remainder.
|
||||
///
|
||||
/// Example:
|
||||
/// \code
|
||||
/// eval> drop_while([1, 2, 3], odd)
|
||||
/// [2, 3]
|
||||
/// \endcode
|
||||
Object drop_while(Range c, Function f);
|
||||
/// \brief Reverses a Range object so that the elements are accessed in reverse
|
||||
Range retro(Range);
|
||||
|
||||
/// \brief Reverses a Const_Range object so that the elements are accessed in reverse
|
||||
Const_Range retro(Const_Range);
|
||||
|
||||
/// \brief Similar to foldl, this takes the first two elements as its starting values for f. This assumes Range c has at least 2 elements.
|
||||
///
|
||||
/// Example:
|
||||
/// \code
|
||||
/// eval> reduce([1, 2, 3, 4], `+`)
|
||||
/// 10
|
||||
/// \endcode
|
||||
Object reduce(Range c, Function f);
|
||||
|
||||
|
||||
/// \brief Takes elements from Container c that match function f, return them.
|
||||
///
|
||||
/// Example:
|
||||
/// \code
|
||||
/// eval> filter([1, 2, 3, 4], odd)
|
||||
/// [1, 3]
|
||||
/// \endcode
|
||||
Object filter(Container c, Function f);
|
||||
|
||||
|
||||
/// \brief Joins the elements of the Range c into a string, delimiting each with the delim string.
|
||||
///
|
||||
/// Example:
|
||||
/// \code
|
||||
/// eval> join([1, 2, 3], "*")
|
||||
/// 1*2*3
|
||||
/// \endcode
|
||||
string join(Range c, string delim);
|
||||
|
||||
|
||||
/// \brief Returns the contents of the Container c in reversed order.
|
||||
///
|
||||
/// Example:
|
||||
/// \code
|
||||
/// eval> reverse([1, 2, 3, 4, 5, 6, 7])
|
||||
/// [7, 6, 5, 4, 3, 2, 1]
|
||||
/// \endcode
|
||||
Container reverse(Container c);
|
||||
|
||||
|
||||
/// \brief Generates a new Vector filled with values starting at x and ending with y.
|
||||
///
|
||||
/// Works on types supporting operator<=(x, y) and operator++(x)
|
||||
///
|
||||
/// Example:
|
||||
/// \code
|
||||
/// eval> generate_range(1, 10)
|
||||
/// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
|
||||
/// \endcode
|
||||
Vector generate_range(Object x, Object y);
|
||||
|
||||
|
||||
/// \brief Returns a new Range with x and y concatenated.
|
||||
///
|
||||
/// Example:
|
||||
/// \code
|
||||
/// eval> concat([1, 2, 3], [4, 5, 6])
|
||||
/// [1, 2, 3, 4, 5, 6]
|
||||
/// \endcode
|
||||
Object concat(Range x, Range y);
|
||||
|
||||
|
||||
/// \brief Returns a new Vector with x and y as its values.
|
||||
///
|
||||
/// Example:
|
||||
/// \code
|
||||
/// eval> collate(1, 2)
|
||||
/// [1, 2]
|
||||
/// \endcode
|
||||
Vector collate(Object x, Object y);
|
||||
|
||||
|
||||
/// \brief Applies f to elements of x and y, returning a new Vector with the result of each application.
|
||||
///
|
||||
/// Example:
|
||||
/// \code
|
||||
/// eval> zip_with(`+`, [1, 2, 3], [4, 5, 6])
|
||||
/// [5, 7, 9]
|
||||
/// \endcode
|
||||
Vector zip_with(Function f, Range x, Range y);
|
||||
|
||||
|
||||
/// \brief Collates elements of x and y, returning a new Vector with the result.
|
||||
///
|
||||
/// Example:
|
||||
/// \code
|
||||
/// eval> zip([1, 2, 3], [4, 5, 6])
|
||||
/// [[1, 4], [2, 5], [3, 6]]
|
||||
/// \endcode
|
||||
Vector zip(Range x, Range y);
|
||||
|
||||
|
||||
/// \brief returns true if there exists a call to the Function f that takes the given parameters
|
||||
///
|
||||
/// Example:
|
||||
/// \code
|
||||
/// eval> call_exists(`+`, 1, 2)
|
||||
/// true
|
||||
/// \endcode
|
||||
bool call_exists(Function f, ...);
|
||||
|
||||
/// \brief Reverses a Range object so that the elements are accessed in reverse
|
||||
Range retro(Range);
|
||||
|
||||
/// \brief Reverses a Const_Range object so that the elements are accessed in reverse
|
||||
Const_Range retro(Const_Range);
|
||||
|
||||
|
||||
/// \brief Raises the given object as an exception. Any type of object can be thrown.
|
||||
///
|
||||
/// Example:
|
||||
/// \code
|
||||
/// eval> try { throw(1); } catch (e) { print("Exception caught: " + to_string(e)); }
|
||||
/// Exception caught: 1
|
||||
/// \endcode
|
||||
///
|
||||
/// \sa \ref keywordtry
|
||||
void throw(Object);
|
||||
}
|
||||
|
||||
/// \brief Raises the given object as an exception. Any type of object can be thrown.
|
||||
///
|
||||
/// Example:
|
||||
/// \code
|
||||
/// eval> try { throw(1); } catch (e) { print("Exception caught: " + to_string(e)); }
|
||||
/// Exception caught: 1
|
||||
/// \endcode
|
||||
///
|
||||
/// \sa \ref keywordtry
|
||||
void throw(Object);
|
||||
} // namespace ChaiScript_Language
|
||||
|
||||
@ -7,29 +7,22 @@
|
||||
#ifndef CHAISCRIPT_TRACER_HPP_
|
||||
#define CHAISCRIPT_TRACER_HPP_
|
||||
|
||||
namespace chaiscript {
|
||||
namespace eval {
|
||||
|
||||
|
||||
struct Noop_Tracer_Detail
|
||||
{
|
||||
namespace chaiscript::eval {
|
||||
struct Noop_Tracer_Detail {
|
||||
template<typename T>
|
||||
constexpr void trace(const chaiscript::detail::Dispatch_State &, const AST_Node_Impl<T> *) noexcept
|
||||
{
|
||||
constexpr void trace(const chaiscript::detail::Dispatch_State &, const AST_Node_Impl<T> *) noexcept {
|
||||
}
|
||||
};
|
||||
|
||||
template<typename ... T>
|
||||
struct Tracer : T...
|
||||
{
|
||||
template<typename... T>
|
||||
struct Tracer : T... {
|
||||
Tracer() = default;
|
||||
constexpr explicit Tracer(T ... t)
|
||||
: T(std::move(t))...
|
||||
{
|
||||
constexpr explicit Tracer(T... t)
|
||||
: T(std::move(t))... {
|
||||
}
|
||||
|
||||
void do_trace(const chaiscript::detail::Dispatch_State &ds, const AST_Node_Impl<Tracer<T...>> *node) {
|
||||
(static_cast<T&>(*this).trace(ds, node), ... );
|
||||
(static_cast<T &>(*this).trace(ds, node), ...);
|
||||
}
|
||||
|
||||
static void trace(const chaiscript::detail::Dispatch_State &ds, const AST_Node_Impl<Tracer<T...>> *node) {
|
||||
@ -39,8 +32,6 @@ namespace chaiscript {
|
||||
|
||||
using Noop_Tracer = Tracer<Noop_Tracer_Detail>;
|
||||
|
||||
}
|
||||
}
|
||||
} // namespace chaiscript::eval
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@ -7,15 +7,10 @@
|
||||
#ifndef CHAISCRIPT_UNKNOWN_HPP_
|
||||
#define CHAISCRIPT_UNKNOWN_HPP_
|
||||
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
struct Loadable_Module
|
||||
{
|
||||
Loadable_Module(const std::string &, const std::string &)
|
||||
{
|
||||
namespace chaiscript {
|
||||
namespace detail {
|
||||
struct Loadable_Module {
|
||||
Loadable_Module(const std::string &, const std::string &) {
|
||||
#ifdef CHAISCRIPT_NO_DYNLOAD
|
||||
throw chaiscript::exception::load_module_error("Loadable module support was disabled (CHAISCRIPT_NO_DYNLOAD)");
|
||||
#else
|
||||
@ -25,7 +20,6 @@ namespace chaiscript
|
||||
|
||||
ModulePtr m_moduleptr;
|
||||
};
|
||||
}
|
||||
}
|
||||
} // namespace detail
|
||||
} // namespace chaiscript
|
||||
#endif
|
||||
|
||||
|
||||
@ -17,41 +17,32 @@
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
struct Loadable_Module
|
||||
{
|
||||
namespace chaiscript {
|
||||
namespace detail {
|
||||
struct Loadable_Module {
|
||||
template<typename T>
|
||||
static std::wstring to_wstring(const T &t_str)
|
||||
{
|
||||
static std::wstring to_wstring(const T &t_str) {
|
||||
return std::wstring(t_str.begin(), t_str.end());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static std::string to_string(const T &t_str)
|
||||
{
|
||||
static std::string to_string(const T &t_str) {
|
||||
return std::string(t_str.begin(), t_str.end());
|
||||
}
|
||||
|
||||
#if defined(_UNICODE) || defined(UNICODE)
|
||||
template<typename T>
|
||||
static std::wstring to_proper_string(const T &t_str)
|
||||
{
|
||||
static std::wstring to_proper_string(const T &t_str) {
|
||||
return to_wstring(t_str);
|
||||
}
|
||||
#else
|
||||
template<typename T>
|
||||
static std::string to_proper_string(const T &t_str)
|
||||
{
|
||||
static std::string to_proper_string(const T &t_str) {
|
||||
return to_string(t_str);
|
||||
}
|
||||
#endif
|
||||
|
||||
static std::string get_error_message(DWORD t_err)
|
||||
{
|
||||
static std::string get_error_message(DWORD t_err) {
|
||||
using StringType = LPTSTR;
|
||||
|
||||
#if defined(_UNICODE) || defined(UNICODE)
|
||||
@ -61,16 +52,15 @@ namespace chaiscript
|
||||
#endif
|
||||
StringType lpMsgBuf = nullptr;
|
||||
|
||||
if (FormatMessage(
|
||||
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||
FORMAT_MESSAGE_FROM_SYSTEM |
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
nullptr,
|
||||
t_err,
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||
reinterpret_cast<StringType>(&lpMsgBuf),
|
||||
0, nullptr ) != 0 && lpMsgBuf)
|
||||
{
|
||||
0,
|
||||
nullptr)
|
||||
!= 0
|
||||
&& lpMsgBuf) {
|
||||
retval = lpMsgBuf;
|
||||
LocalFree(lpMsgBuf);
|
||||
}
|
||||
@ -78,13 +68,10 @@ namespace chaiscript
|
||||
return to_string(retval);
|
||||
}
|
||||
|
||||
struct DLModule
|
||||
{
|
||||
struct DLModule {
|
||||
explicit DLModule(const std::string &t_filename)
|
||||
: m_data(LoadLibrary(to_proper_string(t_filename).c_str()))
|
||||
{
|
||||
if (!m_data)
|
||||
{
|
||||
: m_data(LoadLibrary(to_proper_string(t_filename).c_str())) {
|
||||
if (!m_data) {
|
||||
throw chaiscript::exception::load_module_error(get_error_message(GetLastError()));
|
||||
}
|
||||
}
|
||||
@ -94,22 +81,16 @@ namespace chaiscript
|
||||
DLModule(const DLModule &) = delete;
|
||||
DLModule &operator=(const DLModule &) = delete;
|
||||
|
||||
~DLModule()
|
||||
{
|
||||
FreeLibrary(m_data);
|
||||
}
|
||||
~DLModule() { FreeLibrary(m_data); }
|
||||
|
||||
HMODULE m_data;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct DLSym
|
||||
{
|
||||
struct DLSym {
|
||||
DLSym(DLModule &t_mod, const std::string &t_symbol)
|
||||
: m_symbol(reinterpret_cast<T>(GetProcAddress(t_mod.m_data, t_symbol.c_str())))
|
||||
{
|
||||
if (!m_symbol)
|
||||
{
|
||||
: m_symbol(reinterpret_cast<T>(GetProcAddress(t_mod.m_data, t_symbol.c_str()))) {
|
||||
if (!m_symbol) {
|
||||
throw chaiscript::exception::load_module_error(get_error_message(GetLastError()));
|
||||
}
|
||||
}
|
||||
@ -118,16 +99,15 @@ namespace chaiscript
|
||||
};
|
||||
|
||||
Loadable_Module(const std::string &t_module_name, const std::string &t_filename)
|
||||
: m_dlmodule(t_filename), m_func(m_dlmodule, "create_chaiscript_module_" + t_module_name),
|
||||
m_moduleptr(m_func.m_symbol())
|
||||
{
|
||||
: m_dlmodule(t_filename)
|
||||
, m_func(m_dlmodule, "create_chaiscript_module_" + t_module_name)
|
||||
, m_moduleptr(m_func.m_symbol()) {
|
||||
}
|
||||
|
||||
DLModule m_dlmodule;
|
||||
DLSym<Create_Module_Func> m_func;
|
||||
ModulePtr m_moduleptr;
|
||||
};
|
||||
}
|
||||
}
|
||||
} // namespace detail
|
||||
} // namespace chaiscript
|
||||
#endif
|
||||
|
||||
|
||||
@ -7,19 +7,11 @@
|
||||
#ifndef CHAISCRIPT_UTILITY_FNV1A_HPP_
|
||||
#define CHAISCRIPT_UTILITY_FNV1A_HPP_
|
||||
|
||||
|
||||
#include <cstdint>
|
||||
#include "../chaiscript_defines.hpp"
|
||||
#include <cstdint>
|
||||
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
|
||||
|
||||
namespace utility
|
||||
{
|
||||
|
||||
|
||||
namespace chaiscript {
|
||||
namespace utility {
|
||||
static constexpr std::uint32_t fnv1a_32(const char *s, std::uint32_t h = 0x811c9dc5) {
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic push
|
||||
@ -30,7 +22,7 @@ namespace chaiscript
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4307)
|
||||
#endif
|
||||
return (*s == 0) ? h : fnv1a_32(s+1, ((h ^ (*s)) * 0x01000193));
|
||||
return (*s == 0) ? h : fnv1a_32(s + 1, ((h ^ (*s)) * 0x01000193));
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
@ -38,13 +30,9 @@ namespace chaiscript
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
} // namespace utility
|
||||
} // namespace chaiscript
|
||||
|
||||
#endif
|
||||
|
||||
@ -7,15 +7,11 @@
|
||||
#ifndef CHAISCRIPT_UTILITY_FNV1A_HPP_
|
||||
#define CHAISCRIPT_UTILITY_FNV1A_HPP_
|
||||
|
||||
|
||||
#include <cstdint>
|
||||
#include "../chaiscript_defines.hpp"
|
||||
#include <cstdint>
|
||||
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
namespace utility
|
||||
{
|
||||
namespace chaiscript {
|
||||
namespace utility {
|
||||
namespace fnv1a {
|
||||
template<typename Itr>
|
||||
static constexpr std::uint32_t hash(Itr begin, Itr end) noexcept {
|
||||
@ -43,13 +39,11 @@ namespace chaiscript
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
template<size_t N>
|
||||
static constexpr std::uint32_t hash(const char (&str)[N]) noexcept {
|
||||
return hash(std::begin(str), std::end(str)-1);
|
||||
return hash(std::begin(str), std::end(str) - 1);
|
||||
}
|
||||
|
||||
static constexpr std::uint32_t hash(std::string_view sv) noexcept {
|
||||
@ -59,7 +53,7 @@ namespace chaiscript
|
||||
static inline std::uint32_t hash(const std::string &s) noexcept {
|
||||
return hash(s.begin(), s.end());
|
||||
}
|
||||
}
|
||||
} // namespace fnv1a
|
||||
|
||||
namespace jenkins_one_at_a_time {
|
||||
template<typename Itr>
|
||||
@ -81,7 +75,7 @@ namespace chaiscript
|
||||
|
||||
template<size_t N>
|
||||
static constexpr std::uint32_t hash(const char (&str)[N]) noexcept {
|
||||
return hash(std::begin(str), std::end(str)-1);
|
||||
return hash(std::begin(str), std::end(str) - 1);
|
||||
}
|
||||
|
||||
static constexpr std::uint32_t hash(std::string_view sv) noexcept {
|
||||
@ -91,11 +85,10 @@ namespace chaiscript
|
||||
static inline std::uint32_t hash(const std::string &s) noexcept {
|
||||
return hash(s.begin(), s.end());
|
||||
}
|
||||
}
|
||||
} // namespace jenkins_one_at_a_time
|
||||
|
||||
using fnv1a::hash;
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace utility
|
||||
} // namespace chaiscript
|
||||
|
||||
#endif
|
||||
|
||||
@ -2,40 +2,32 @@
|
||||
// Released under the DWTFYW PL
|
||||
//
|
||||
|
||||
|
||||
|
||||
#ifndef SIMPLEJSON_HPP
|
||||
#define SIMPLEJSON_HPP
|
||||
|
||||
|
||||
#include <cstdint>
|
||||
#include <cmath>
|
||||
#include <cctype>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <type_traits>
|
||||
#include <initializer_list>
|
||||
#include <ostream>
|
||||
#include <iostream>
|
||||
#include <variant>
|
||||
#include "../chaiscript_defines.hpp"
|
||||
#include "quick_flat_map.hpp"
|
||||
#include <cctype>
|
||||
#include <cmath>
|
||||
#include <cstdint>
|
||||
#include <initializer_list>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <variant>
|
||||
#include <vector>
|
||||
|
||||
namespace json {
|
||||
using std::enable_if;
|
||||
using std::initializer_list;
|
||||
using std::is_convertible;
|
||||
using std::is_floating_point;
|
||||
using std::is_integral;
|
||||
using std::is_same;
|
||||
|
||||
using std::enable_if;
|
||||
using std::initializer_list;
|
||||
using std::is_same;
|
||||
using std::is_convertible;
|
||||
using std::is_integral;
|
||||
using std::is_floating_point;
|
||||
|
||||
|
||||
|
||||
|
||||
class JSON
|
||||
{
|
||||
class JSON {
|
||||
public:
|
||||
enum class Class {
|
||||
Null = 0,
|
||||
@ -48,26 +40,40 @@ class JSON
|
||||
};
|
||||
|
||||
private:
|
||||
using Data
|
||||
= std::variant<std::nullptr_t, chaiscript::utility::QuickFlatMap<std::string, JSON>, std::vector<JSON>, std::string, double, std::int64_t, bool>;
|
||||
|
||||
|
||||
using Data = std::variant<std::nullptr_t, chaiscript::utility::QuickFlatMap<std::string, JSON>, std::vector<JSON>, std::string, double, std::int64_t, bool>;
|
||||
|
||||
struct Internal
|
||||
{
|
||||
Internal(std::nullptr_t) : d(nullptr) { }
|
||||
Internal() : d(nullptr) { }
|
||||
Internal(Class c) : d(make_type(c)) { }
|
||||
template<typename T> Internal(T t) : d(std::move(t)) { }
|
||||
struct Internal {
|
||||
Internal(std::nullptr_t)
|
||||
: d(nullptr) {
|
||||
}
|
||||
Internal()
|
||||
: d(nullptr) {
|
||||
}
|
||||
Internal(Class c)
|
||||
: d(make_type(c)) {
|
||||
}
|
||||
template<typename T>
|
||||
Internal(T t)
|
||||
: d(std::move(t)) {
|
||||
}
|
||||
|
||||
static Data make_type(Class c) {
|
||||
switch (c) {
|
||||
case Class::Null: return nullptr;
|
||||
case Class::Object: return chaiscript::utility::QuickFlatMap<std::string, JSON>{};
|
||||
case Class::Array: return std::vector<JSON>{};
|
||||
case Class::String: return std::string{};
|
||||
case Class::Floating: return double{};
|
||||
case Class::Integral: return std::int64_t{};
|
||||
case Class::Boolean: return bool{};
|
||||
case Class::Null:
|
||||
return nullptr;
|
||||
case Class::Object:
|
||||
return chaiscript::utility::QuickFlatMap<std::string, JSON>{};
|
||||
case Class::Array:
|
||||
return std::vector<JSON>{};
|
||||
case Class::String:
|
||||
return std::string{};
|
||||
case Class::Floating:
|
||||
return double{};
|
||||
case Class::Integral:
|
||||
return std::int64_t{};
|
||||
case Class::Boolean:
|
||||
return bool{};
|
||||
}
|
||||
throw std::runtime_error("unknown type");
|
||||
}
|
||||
@ -78,14 +84,10 @@ class JSON
|
||||
}
|
||||
}
|
||||
|
||||
Class type() const noexcept {
|
||||
return Class(d.index());
|
||||
}
|
||||
|
||||
Class type() const noexcept { return Class(d.index()); }
|
||||
|
||||
template<auto ClassValue, typename Visitor, typename Or>
|
||||
decltype(auto) visit_or(Visitor &&visitor, Or &&other) const
|
||||
{
|
||||
decltype(auto) visit_or(Visitor &&visitor, Or &&other) const {
|
||||
if (type() == Class(ClassValue)) {
|
||||
return visitor(std::get<static_cast<std::size_t>(ClassValue)>(d));
|
||||
} else {
|
||||
@ -99,59 +101,35 @@ class JSON
|
||||
return (std::get<static_cast<std::size_t>(ClassValue)>(d));
|
||||
}
|
||||
|
||||
auto &Map() {
|
||||
return get_set_type<Class::Object>();
|
||||
}
|
||||
auto &Vector() {
|
||||
return get_set_type<Class::Array>();
|
||||
}
|
||||
auto &String() {
|
||||
return get_set_type<Class::String>();
|
||||
}
|
||||
auto &Int() {
|
||||
return get_set_type<Class::Integral>();
|
||||
}
|
||||
auto &Float() {
|
||||
return get_set_type<Class::Floating>();
|
||||
}
|
||||
auto &Bool() {
|
||||
return get_set_type<Class::Boolean>();
|
||||
}
|
||||
auto &Map() { return get_set_type<Class::Object>(); }
|
||||
auto &Vector() { return get_set_type<Class::Array>(); }
|
||||
auto &String() { return get_set_type<Class::String>(); }
|
||||
auto &Int() { return get_set_type<Class::Integral>(); }
|
||||
auto &Float() { return get_set_type<Class::Floating>(); }
|
||||
auto &Bool() { return get_set_type<Class::Boolean>(); }
|
||||
|
||||
auto Map() const noexcept {
|
||||
return std::get_if<static_cast<std::size_t>(Class::Object)>(&d);
|
||||
}
|
||||
auto Vector() const noexcept {
|
||||
return std::get_if<static_cast<std::size_t>(Class::Array)>(&d);
|
||||
}
|
||||
auto String() const noexcept {
|
||||
return std::get_if<static_cast<std::size_t>(Class::String)>(&d);
|
||||
}
|
||||
auto Int() const noexcept {
|
||||
return std::get_if<static_cast<std::size_t>(Class::Integral)>(&d);
|
||||
}
|
||||
auto Float() const noexcept {
|
||||
return std::get_if<static_cast<std::size_t>(Class::Floating)>(&d);
|
||||
}
|
||||
auto Bool() const noexcept {
|
||||
return std::get_if<static_cast<std::size_t>(Class::Boolean)>(&d);
|
||||
}
|
||||
auto Map() const noexcept { return std::get_if<static_cast<std::size_t>(Class::Object)>(&d); }
|
||||
auto Vector() const noexcept { return std::get_if<static_cast<std::size_t>(Class::Array)>(&d); }
|
||||
auto String() const noexcept { return std::get_if<static_cast<std::size_t>(Class::String)>(&d); }
|
||||
auto Int() const noexcept { return std::get_if<static_cast<std::size_t>(Class::Integral)>(&d); }
|
||||
auto Float() const noexcept { return std::get_if<static_cast<std::size_t>(Class::Floating)>(&d); }
|
||||
auto Bool() const noexcept { return std::get_if<static_cast<std::size_t>(Class::Boolean)>(&d); }
|
||||
|
||||
Data d;
|
||||
};
|
||||
|
||||
|
||||
Internal internal;
|
||||
|
||||
public:
|
||||
|
||||
template <typename Container>
|
||||
template<typename Container>
|
||||
class JSONWrapper {
|
||||
Container *object = nullptr;
|
||||
|
||||
public:
|
||||
JSONWrapper( Container *val ) : object( val ) {}
|
||||
JSONWrapper( std::nullptr_t ) {}
|
||||
JSONWrapper(Container *val)
|
||||
: object(val) {
|
||||
}
|
||||
JSONWrapper(std::nullptr_t) {}
|
||||
|
||||
typename Container::iterator begin() { return object ? object->begin() : typename Container::iterator(); }
|
||||
typename Container::iterator end() { return object ? object->end() : typename Container::iterator(); }
|
||||
@ -159,104 +137,96 @@ class JSON
|
||||
typename Container::const_iterator end() const { return object ? object->end() : typename Container::iterator(); }
|
||||
};
|
||||
|
||||
template <typename Container>
|
||||
template<typename Container>
|
||||
class JSONConstWrapper {
|
||||
const Container *object = nullptr;
|
||||
|
||||
public:
|
||||
JSONConstWrapper( const Container *val ) : object( val ) {}
|
||||
JSONConstWrapper( std::nullptr_t ) {}
|
||||
JSONConstWrapper(const Container *val)
|
||||
: object(val) {
|
||||
}
|
||||
JSONConstWrapper(std::nullptr_t) {}
|
||||
|
||||
typename Container::const_iterator begin() const noexcept { return object ? object->begin() : typename Container::const_iterator(); }
|
||||
typename Container::const_iterator begin() const noexcept {
|
||||
return object ? object->begin() : typename Container::const_iterator();
|
||||
}
|
||||
typename Container::const_iterator end() const noexcept { return object ? object->end() : typename Container::const_iterator(); }
|
||||
};
|
||||
|
||||
JSON() = default;
|
||||
JSON( std::nullptr_t ) {}
|
||||
JSON(std::nullptr_t) {}
|
||||
|
||||
explicit JSON(Class type)
|
||||
: internal(type)
|
||||
{
|
||||
: internal(type) {
|
||||
}
|
||||
|
||||
JSON( initializer_list<JSON> list )
|
||||
: internal(Class::Object)
|
||||
{
|
||||
for( auto i = list.begin(), e = list.end(); i != e; ++i, ++i ) {
|
||||
operator[]( i->to_string() ) = *std::next( i );
|
||||
JSON(initializer_list<JSON> list)
|
||||
: internal(Class::Object) {
|
||||
for (auto i = list.begin(), e = list.end(); i != e; ++i, ++i) {
|
||||
operator[](i->to_string()) = *std::next(i);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
explicit JSON( T b, typename enable_if<is_same<T,bool>::value>::type* = nullptr ) noexcept : internal( static_cast<bool>(b) ) {}
|
||||
|
||||
template <typename T>
|
||||
explicit JSON( T i, typename enable_if<is_integral<T>::value && !is_same<T,bool>::value>::type* = nullptr ) noexcept : internal( static_cast<std::int64_t>(i) ) {}
|
||||
|
||||
template <typename T>
|
||||
explicit JSON( T f, typename enable_if<is_floating_point<T>::value>::type* = nullptr ) noexcept : internal( static_cast<double>(f) ) {}
|
||||
|
||||
template <typename T>
|
||||
explicit JSON( T s, typename enable_if<is_convertible<T,std::string>::value>::type* = nullptr ) : internal( static_cast<std::string>(s) ) {}
|
||||
|
||||
|
||||
|
||||
static JSON Load( const std::string & );
|
||||
|
||||
JSON& operator[]( const std::string &key ) {
|
||||
return internal.Map().operator[]( key );
|
||||
template<typename T>
|
||||
explicit JSON(T b, typename enable_if<is_same<T, bool>::value>::type * = nullptr) noexcept
|
||||
: internal(static_cast<bool>(b)) {
|
||||
}
|
||||
|
||||
JSON& operator[]( const size_t index ) {
|
||||
template<typename T>
|
||||
explicit JSON(T i, typename enable_if<is_integral<T>::value && !is_same<T, bool>::value>::type * = nullptr) noexcept
|
||||
: internal(static_cast<std::int64_t>(i)) {
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
explicit JSON(T f, typename enable_if<is_floating_point<T>::value>::type * = nullptr) noexcept
|
||||
: internal(static_cast<double>(f)) {
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
explicit JSON(T s, typename enable_if<is_convertible<T, std::string>::value>::type * = nullptr)
|
||||
: internal(static_cast<std::string>(s)) {
|
||||
}
|
||||
|
||||
static JSON Load(const std::string &);
|
||||
|
||||
JSON &operator[](const std::string &key) { return internal.Map().operator[](key); }
|
||||
|
||||
JSON &operator[](const size_t index) {
|
||||
auto &vec = internal.Vector();
|
||||
if( index >= vec.size() ) {
|
||||
vec.resize( index + 1 );
|
||||
if (index >= vec.size()) {
|
||||
vec.resize(index + 1);
|
||||
}
|
||||
|
||||
return vec.operator[]( index );
|
||||
return vec.operator[](index);
|
||||
}
|
||||
|
||||
JSON &at(const std::string &key) { return operator[](key); }
|
||||
|
||||
JSON &at( const std::string &key ) {
|
||||
return operator[]( key );
|
||||
const JSON &at(const std::string &key) const {
|
||||
return internal.visit_or<Class::Object>([&](const auto &m) -> const JSON & { return m.at(key); },
|
||||
[]() -> const JSON & { throw std::range_error("Not an object, no keys"); });
|
||||
}
|
||||
|
||||
const JSON &at( const std::string &key ) const {
|
||||
return internal.visit_or<Class::Object>(
|
||||
[&](const auto &m)->const JSON &{ return m.at(key); },
|
||||
[]()->const JSON &{ throw std::range_error("Not an object, no keys"); }
|
||||
);
|
||||
}
|
||||
JSON &at(size_t index) { return operator[](index); }
|
||||
|
||||
JSON &at( size_t index ) {
|
||||
return operator[]( index );
|
||||
}
|
||||
|
||||
const JSON &at( size_t index ) const {
|
||||
return internal.visit_or<Class::Array>(
|
||||
[&](const auto &m)->const JSON&{ return m.at(index); },
|
||||
[]()->const JSON &{ throw std::range_error("Not an array, no indexes"); }
|
||||
);
|
||||
const JSON &at(size_t index) const {
|
||||
return internal.visit_or<Class::Array>([&](const auto &m) -> const JSON & { return m.at(index); },
|
||||
[]() -> const JSON & { throw std::range_error("Not an array, no indexes"); });
|
||||
}
|
||||
|
||||
auto length() const noexcept {
|
||||
return internal.visit_or<Class::Array>(
|
||||
[&](const auto &m){ return static_cast<int>(m.size()); },
|
||||
[](){ return -1; }
|
||||
);
|
||||
return internal.visit_or<Class::Array>([&](const auto &m) { return static_cast<int>(m.size()); }, []() { return -1; });
|
||||
}
|
||||
|
||||
bool has_key( const std::string &key ) const noexcept {
|
||||
return internal.visit_or<Class::Object>(
|
||||
[&](const auto &m){ return m.count(key) != 0; },
|
||||
[](){ return false; }
|
||||
);
|
||||
bool has_key(const std::string &key) const noexcept {
|
||||
return internal.visit_or<Class::Object>([&](const auto &m) { return m.count(key) != 0; }, []() { return false; });
|
||||
}
|
||||
|
||||
int size() const noexcept {
|
||||
if (auto m = internal.Map(); m != nullptr) {
|
||||
return static_cast<int>(m->size());
|
||||
} if (auto v = internal.Vector(); v != nullptr) {
|
||||
}
|
||||
if (auto v = internal.Vector(); v != nullptr) {
|
||||
return static_cast<int>(v->size());
|
||||
} else {
|
||||
return -1;
|
||||
@ -269,81 +239,70 @@ class JSON
|
||||
bool is_null() const noexcept { return internal.type() == Class::Null; }
|
||||
|
||||
std::string to_string() const noexcept {
|
||||
return internal.visit_or<Class::String>(
|
||||
[](const auto &o){ return o; },
|
||||
[](){ return std::string{}; }
|
||||
);
|
||||
return internal.visit_or<Class::String>([](const auto &o) { return o; }, []() { return std::string{}; });
|
||||
}
|
||||
double to_float() const noexcept {
|
||||
return internal.visit_or<Class::Floating>(
|
||||
[](const auto &o){ return o; },
|
||||
[](){ return double{}; }
|
||||
);
|
||||
return internal.visit_or<Class::Floating>([](const auto &o) { return o; }, []() { return double{}; });
|
||||
}
|
||||
std::int64_t to_int() const noexcept {
|
||||
return internal.visit_or<Class::Integral>(
|
||||
[](const auto &o){ return o; },
|
||||
[](){ return std::int64_t{}; }
|
||||
);
|
||||
return internal.visit_or<Class::Integral>([](const auto &o) { return o; }, []() { return std::int64_t{}; });
|
||||
}
|
||||
bool to_bool() const noexcept {
|
||||
return internal.visit_or<Class::Boolean>(
|
||||
[](const auto &o){ return o; },
|
||||
[](){ return false; }
|
||||
);
|
||||
return internal.visit_or<Class::Boolean>([](const auto &o) { return o; }, []() { return false; });
|
||||
}
|
||||
|
||||
JSONWrapper<chaiscript::utility::QuickFlatMap<std::string, JSON>> object_range() {
|
||||
return std::get_if<static_cast<std::size_t>(Class::Object)>(&internal.d);
|
||||
}
|
||||
|
||||
JSONWrapper<std::vector<JSON>> array_range() {
|
||||
return std::get_if<static_cast<std::size_t>(Class::Array)>(&internal.d);
|
||||
}
|
||||
JSONWrapper<std::vector<JSON>> array_range() { return std::get_if<static_cast<std::size_t>(Class::Array)>(&internal.d); }
|
||||
|
||||
JSONConstWrapper<chaiscript::utility::QuickFlatMap<std::string, JSON>> object_range() const {
|
||||
return std::get_if<static_cast<std::size_t>(Class::Object)>(&internal.d);
|
||||
}
|
||||
|
||||
JSONConstWrapper<std::vector<JSON>> array_range() const {
|
||||
return std::get_if<static_cast<std::size_t>(Class::Array)>(&internal.d);
|
||||
}
|
||||
JSONConstWrapper<std::vector<JSON>> array_range() const { return std::get_if<static_cast<std::size_t>(Class::Array)>(&internal.d); }
|
||||
|
||||
std::string dump( long depth = 1, std::string tab = " ") const {
|
||||
switch( internal.type() ) {
|
||||
std::string dump(long depth = 1, std::string tab = " ") const {
|
||||
switch (internal.type()) {
|
||||
case Class::Null:
|
||||
return "null";
|
||||
case Class::Object: {
|
||||
std::string pad = "";
|
||||
for( long i = 0; i < depth; ++i, pad += tab ) { }
|
||||
for (long i = 0; i < depth; ++i, pad += tab) {
|
||||
}
|
||||
|
||||
std::string s = "{\n";
|
||||
bool skip = true;
|
||||
for( auto &p : *internal.Map() ) {
|
||||
if( !skip ) { s += ",\n"; }
|
||||
s += ( pad + "\"" + json_escape(p.first) + "\" : " + p.second.dump( depth + 1, tab ) );
|
||||
for (auto &p : *internal.Map()) {
|
||||
if (!skip) {
|
||||
s += ",\n";
|
||||
}
|
||||
s += (pad + "\"" + json_escape(p.first) + "\" : " + p.second.dump(depth + 1, tab));
|
||||
skip = false;
|
||||
}
|
||||
s += ( "\n" + pad.erase( 0, 2 ) + "}" ) ;
|
||||
s += ("\n" + pad.erase(0, 2) + "}");
|
||||
return s;
|
||||
}
|
||||
case Class::Array: {
|
||||
std::string s = "[";
|
||||
bool skip = true;
|
||||
for( auto &p : *internal.Vector() ) {
|
||||
if( !skip ) { s += ", "; }
|
||||
s += p.dump( depth + 1, tab );
|
||||
for (auto &p : *internal.Vector()) {
|
||||
if (!skip) {
|
||||
s += ", ";
|
||||
}
|
||||
s += p.dump(depth + 1, tab);
|
||||
skip = false;
|
||||
}
|
||||
s += "]";
|
||||
return s;
|
||||
}
|
||||
case Class::String:
|
||||
return "\"" + json_escape( *internal.String() ) + "\"";
|
||||
return "\"" + json_escape(*internal.String()) + "\"";
|
||||
case Class::Floating:
|
||||
return std::to_string( *internal.Float() );
|
||||
return std::to_string(*internal.Float());
|
||||
case Class::Integral:
|
||||
return std::to_string( *internal.Int() );
|
||||
return std::to_string(*internal.Int());
|
||||
case Class::Boolean:
|
||||
return *internal.Bool() ? "true" : "false";
|
||||
}
|
||||
@ -351,35 +310,47 @@ class JSON
|
||||
throw std::runtime_error("Unhandled JSON type");
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
static std::string json_escape( const std::string &str ) {
|
||||
static std::string json_escape(const std::string &str) {
|
||||
std::string output;
|
||||
for(char i : str) {
|
||||
switch( i ) {
|
||||
case '\"': output += "\\\""; break;
|
||||
case '\\': output += "\\\\"; break;
|
||||
case '\b': output += "\\b"; break;
|
||||
case '\f': output += "\\f"; break;
|
||||
case '\n': output += "\\n"; break;
|
||||
case '\r': output += "\\r"; break;
|
||||
case '\t': output += "\\t"; break;
|
||||
default : output += i; break;
|
||||
for (char i : str) {
|
||||
switch (i) {
|
||||
case '\"':
|
||||
output += "\\\"";
|
||||
break;
|
||||
case '\\':
|
||||
output += "\\\\";
|
||||
break;
|
||||
case '\b':
|
||||
output += "\\b";
|
||||
break;
|
||||
case '\f':
|
||||
output += "\\f";
|
||||
break;
|
||||
case '\n':
|
||||
output += "\\n";
|
||||
break;
|
||||
case '\r':
|
||||
output += "\\r";
|
||||
break;
|
||||
case '\t':
|
||||
output += "\\t";
|
||||
break;
|
||||
default:
|
||||
output += i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
struct JSONParser {
|
||||
static bool isspace(const char c) noexcept
|
||||
{
|
||||
struct JSONParser {
|
||||
static bool isspace(const char c) noexcept {
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
// MSVC warns on these line in some circumstances
|
||||
// MSVC warns on these line in some circumstances
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 6330)
|
||||
#endif
|
||||
@ -387,41 +358,42 @@ struct JSONParser {
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void consume_ws( const std::string &str, size_t &offset ) {
|
||||
while( isspace( str.at(offset) ) && offset <= str.size() ) { ++offset; }
|
||||
static void consume_ws(const std::string &str, size_t &offset) {
|
||||
while (isspace(str.at(offset)) && offset <= str.size()) {
|
||||
++offset;
|
||||
}
|
||||
}
|
||||
|
||||
static JSON parse_object( const std::string &str, size_t &offset ) {
|
||||
JSON Object( JSON::Class::Object );
|
||||
static JSON parse_object(const std::string &str, size_t &offset) {
|
||||
JSON Object(JSON::Class::Object);
|
||||
|
||||
++offset;
|
||||
consume_ws( str, offset );
|
||||
if( str.at(offset) == '}' ) {
|
||||
++offset; return Object;
|
||||
consume_ws(str, offset);
|
||||
if (str.at(offset) == '}') {
|
||||
++offset;
|
||||
return Object;
|
||||
}
|
||||
|
||||
for (;offset<str.size();) {
|
||||
JSON Key = parse_next( str, offset );
|
||||
consume_ws( str, offset );
|
||||
if( str.at(offset) != ':' ) {
|
||||
for (; offset < str.size();) {
|
||||
JSON Key = parse_next(str, offset);
|
||||
consume_ws(str, offset);
|
||||
if (str.at(offset) != ':') {
|
||||
throw std::runtime_error(std::string("JSON ERROR: Object: Expected colon, found '") + str.at(offset) + "'\n");
|
||||
}
|
||||
consume_ws( str, ++offset );
|
||||
JSON Value = parse_next( str, offset );
|
||||
consume_ws(str, ++offset);
|
||||
JSON Value = parse_next(str, offset);
|
||||
Object[Key.to_string()] = Value;
|
||||
|
||||
consume_ws( str, offset );
|
||||
if( str.at(offset) == ',' ) {
|
||||
++offset; continue;
|
||||
}
|
||||
else if( str.at(offset) == '}' ) {
|
||||
++offset; break;
|
||||
}
|
||||
else {
|
||||
consume_ws(str, offset);
|
||||
if (str.at(offset) == ',') {
|
||||
++offset;
|
||||
continue;
|
||||
} else if (str.at(offset) == '}') {
|
||||
++offset;
|
||||
break;
|
||||
} else {
|
||||
throw std::runtime_error(std::string("JSON ERROR: Object: Expected comma, found '") + str.at(offset) + "'\n");
|
||||
}
|
||||
}
|
||||
@ -429,27 +401,28 @@ struct JSONParser {
|
||||
return Object;
|
||||
}
|
||||
|
||||
static JSON parse_array( const std::string &str, size_t &offset ) {
|
||||
JSON Array( JSON::Class::Array );
|
||||
static JSON parse_array(const std::string &str, size_t &offset) {
|
||||
JSON Array(JSON::Class::Array);
|
||||
size_t index = 0;
|
||||
|
||||
++offset;
|
||||
consume_ws( str, offset );
|
||||
if( str.at(offset) == ']' ) {
|
||||
++offset; return Array;
|
||||
consume_ws(str, offset);
|
||||
if (str.at(offset) == ']') {
|
||||
++offset;
|
||||
return Array;
|
||||
}
|
||||
|
||||
for (;offset < str.size();) {
|
||||
Array[index++] = parse_next( str, offset );
|
||||
consume_ws( str, offset );
|
||||
for (; offset < str.size();) {
|
||||
Array[index++] = parse_next(str, offset);
|
||||
consume_ws(str, offset);
|
||||
|
||||
if( str.at(offset) == ',' ) {
|
||||
++offset; continue;
|
||||
}
|
||||
else if( str.at(offset) == ']' ) {
|
||||
++offset; break;
|
||||
}
|
||||
else {
|
||||
if (str.at(offset) == ',') {
|
||||
++offset;
|
||||
continue;
|
||||
} else if (str.at(offset) == ']') {
|
||||
++offset;
|
||||
break;
|
||||
} else {
|
||||
throw std::runtime_error(std::string("JSON ERROR: Array: Expected ',' or ']', found '") + str.at(offset) + "'\n");
|
||||
}
|
||||
}
|
||||
@ -457,32 +430,51 @@ struct JSONParser {
|
||||
return Array;
|
||||
}
|
||||
|
||||
static JSON parse_string( const std::string &str, size_t &offset ) {
|
||||
static JSON parse_string(const std::string &str, size_t &offset) {
|
||||
std::string val;
|
||||
for( char c = str.at(++offset); c != '\"' ; c = str.at(++offset) ) {
|
||||
if( c == '\\' ) {
|
||||
switch( str.at(++offset) ) {
|
||||
case '\"': val += '\"'; break;
|
||||
case '\\': val += '\\'; break;
|
||||
case '/' : val += '/' ; break;
|
||||
case 'b' : val += '\b'; break;
|
||||
case 'f' : val += '\f'; break;
|
||||
case 'n' : val += '\n'; break;
|
||||
case 'r' : val += '\r'; break;
|
||||
case 't' : val += '\t'; break;
|
||||
case 'u' : {
|
||||
val += "\\u" ;
|
||||
for( size_t i = 1; i <= 4; ++i ) {
|
||||
c = str.at(offset+i);
|
||||
if( (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F') ) {
|
||||
for (char c = str.at(++offset); c != '\"'; c = str.at(++offset)) {
|
||||
if (c == '\\') {
|
||||
switch (str.at(++offset)) {
|
||||
case '\"':
|
||||
val += '\"';
|
||||
break;
|
||||
case '\\':
|
||||
val += '\\';
|
||||
break;
|
||||
case '/':
|
||||
val += '/';
|
||||
break;
|
||||
case 'b':
|
||||
val += '\b';
|
||||
break;
|
||||
case 'f':
|
||||
val += '\f';
|
||||
break;
|
||||
case 'n':
|
||||
val += '\n';
|
||||
break;
|
||||
case 'r':
|
||||
val += '\r';
|
||||
break;
|
||||
case 't':
|
||||
val += '\t';
|
||||
break;
|
||||
case 'u': {
|
||||
val += "\\u";
|
||||
for (size_t i = 1; i <= 4; ++i) {
|
||||
c = str.at(offset + i);
|
||||
if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')) {
|
||||
val += c;
|
||||
} else {
|
||||
throw std::runtime_error(std::string("JSON ERROR: String: Expected hex character in unicode escape, found '") + c + "'");
|
||||
throw std::runtime_error(
|
||||
std::string("JSON ERROR: String: Expected hex character in unicode escape, found '") + c + "'");
|
||||
}
|
||||
}
|
||||
offset += 4;
|
||||
} break;
|
||||
default : val += '\\'; break;
|
||||
default:
|
||||
val += '\\';
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
val += c;
|
||||
@ -492,113 +484,115 @@ struct JSONParser {
|
||||
return JSON(val);
|
||||
}
|
||||
|
||||
static JSON parse_number( const std::string &str, size_t &offset ) {
|
||||
static JSON parse_number(const std::string &str, size_t &offset) {
|
||||
std::string val, exp_str;
|
||||
char c = '\0';
|
||||
bool isDouble = false;
|
||||
bool isNegative = false;
|
||||
std::int64_t exp = 0;
|
||||
bool isExpNegative = false;
|
||||
if( offset < str.size() && str.at(offset) == '-' ) {
|
||||
if (offset < str.size() && str.at(offset) == '-') {
|
||||
isNegative = true;
|
||||
++offset;
|
||||
}
|
||||
for (; offset < str.size() ;) {
|
||||
for (; offset < str.size();) {
|
||||
c = str.at(offset++);
|
||||
if( c >= '0' && c <= '9' ) {
|
||||
if (c >= '0' && c <= '9') {
|
||||
val += c;
|
||||
} else if( c == '.' && !isDouble ) {
|
||||
} else if (c == '.' && !isDouble) {
|
||||
val += c;
|
||||
isDouble = true;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( offset < str.size() && (c == 'E' || c == 'e' )) {
|
||||
if (offset < str.size() && (c == 'E' || c == 'e')) {
|
||||
c = str.at(offset++);
|
||||
if( c == '-' ) {
|
||||
if (c == '-') {
|
||||
isExpNegative = true;
|
||||
} else if( c == '+' ) {
|
||||
} else if (c == '+') {
|
||||
// do nothing
|
||||
} else {
|
||||
--offset;
|
||||
}
|
||||
|
||||
for (; offset < str.size() ;) {
|
||||
for (; offset < str.size();) {
|
||||
c = str.at(offset++);
|
||||
if( c >= '0' && c <= '9' ) {
|
||||
if (c >= '0' && c <= '9') {
|
||||
exp_str += c;
|
||||
} else if( !isspace( c ) && c != ',' && c != ']' && c != '}' ) {
|
||||
} else if (!isspace(c) && c != ',' && c != ']' && c != '}') {
|
||||
throw std::runtime_error(std::string("JSON ERROR: Number: Expected a number for exponent, found '") + c + "'");
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
exp = chaiscript::parse_num<std::int64_t>( exp_str ) * (isExpNegative?-1:1);
|
||||
}
|
||||
else if( offset < str.size() && (!isspace( c ) && c != ',' && c != ']' && c != '}' )) {
|
||||
exp = chaiscript::parse_num<std::int64_t>(exp_str) * (isExpNegative ? -1 : 1);
|
||||
} else if (offset < str.size() && (!isspace(c) && c != ',' && c != ']' && c != '}')) {
|
||||
throw std::runtime_error(std::string("JSON ERROR: Number: unexpected character '") + c + "'");
|
||||
}
|
||||
--offset;
|
||||
|
||||
if( isDouble ) {
|
||||
return JSON((isNegative?-1:1) * chaiscript::parse_num<double>( val ) * std::pow( 10, exp ));
|
||||
if (isDouble) {
|
||||
return JSON((isNegative ? -1 : 1) * chaiscript::parse_num<double>(val) * std::pow(10, exp));
|
||||
} else {
|
||||
if( !exp_str.empty() ) {
|
||||
return JSON((isNegative?-1:1) * static_cast<double>(chaiscript::parse_num<std::int64_t>( val )) * std::pow( 10, exp ));
|
||||
if (!exp_str.empty()) {
|
||||
return JSON((isNegative ? -1 : 1) * static_cast<double>(chaiscript::parse_num<std::int64_t>(val)) * std::pow(10, exp));
|
||||
} else {
|
||||
return JSON((isNegative?-1:1) * chaiscript::parse_num<std::int64_t>( val ));
|
||||
return JSON((isNegative ? -1 : 1) * chaiscript::parse_num<std::int64_t>(val));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static JSON parse_bool( const std::string &str, size_t &offset ) {
|
||||
if( str.substr( offset, 4 ) == "true" ) {
|
||||
static JSON parse_bool(const std::string &str, size_t &offset) {
|
||||
if (str.substr(offset, 4) == "true") {
|
||||
offset += 4;
|
||||
return JSON(true);
|
||||
} else if( str.substr( offset, 5 ) == "false" ) {
|
||||
} else if (str.substr(offset, 5) == "false") {
|
||||
offset += 5;
|
||||
return JSON(false);
|
||||
} else {
|
||||
throw std::runtime_error(std::string("JSON ERROR: Bool: Expected 'true' or 'false', found '") + str.substr( offset, 5 ) + "'");
|
||||
throw std::runtime_error(std::string("JSON ERROR: Bool: Expected 'true' or 'false', found '") + str.substr(offset, 5) + "'");
|
||||
}
|
||||
}
|
||||
|
||||
static JSON parse_null( const std::string &str, size_t &offset ) {
|
||||
if( str.substr( offset, 4 ) != "null" ) {
|
||||
throw std::runtime_error(std::string("JSON ERROR: Null: Expected 'null', found '") + str.substr( offset, 4 ) + "'");
|
||||
static JSON parse_null(const std::string &str, size_t &offset) {
|
||||
if (str.substr(offset, 4) != "null") {
|
||||
throw std::runtime_error(std::string("JSON ERROR: Null: Expected 'null', found '") + str.substr(offset, 4) + "'");
|
||||
}
|
||||
offset += 4;
|
||||
return JSON();
|
||||
}
|
||||
|
||||
static JSON parse_next( const std::string &str, size_t &offset ) {
|
||||
static JSON parse_next(const std::string &str, size_t &offset) {
|
||||
char value;
|
||||
consume_ws( str, offset );
|
||||
consume_ws(str, offset);
|
||||
value = str.at(offset);
|
||||
switch( value ) {
|
||||
case '[' : return parse_array( str, offset );
|
||||
case '{' : return parse_object( str, offset );
|
||||
case '\"': return parse_string( str, offset );
|
||||
case 't' :
|
||||
case 'f' : return parse_bool( str, offset );
|
||||
case 'n' : return parse_null( str, offset );
|
||||
default : if( ( value <= '9' && value >= '0' ) || value == '-' ) {
|
||||
return parse_number( str, offset );
|
||||
switch (value) {
|
||||
case '[':
|
||||
return parse_array(str, offset);
|
||||
case '{':
|
||||
return parse_object(str, offset);
|
||||
case '\"':
|
||||
return parse_string(str, offset);
|
||||
case 't':
|
||||
case 'f':
|
||||
return parse_bool(str, offset);
|
||||
case 'n':
|
||||
return parse_null(str, offset);
|
||||
default:
|
||||
if ((value <= '9' && value >= '0') || value == '-') {
|
||||
return parse_number(str, offset);
|
||||
}
|
||||
}
|
||||
throw std::runtime_error(std::string("JSON ERROR: Parse: Unexpected starting character '") + value + "'");
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
inline JSON JSON::Load( const std::string &str ) {
|
||||
inline JSON JSON::Load(const std::string &str) {
|
||||
size_t offset = 0;
|
||||
return JSONParser::parse_next( str, offset );
|
||||
}
|
||||
return JSONParser::parse_next(str, offset);
|
||||
}
|
||||
|
||||
} // End Namespace json
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@ -3,46 +3,34 @@
|
||||
|
||||
#include "json.hpp"
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
class json_wrap
|
||||
{
|
||||
namespace chaiscript {
|
||||
class json_wrap {
|
||||
public:
|
||||
|
||||
static Module& library(Module& m)
|
||||
{
|
||||
|
||||
static Module &library(Module &m) {
|
||||
m.add(chaiscript::fun([](const std::string &t_str) { return from_json(t_str); }), "from_json");
|
||||
m.add(chaiscript::fun(&json_wrap::to_json), "to_json");
|
||||
|
||||
return m;
|
||||
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
static Boxed_Value from_json(const json::JSON &t_json)
|
||||
{
|
||||
switch( t_json.JSONType() ) {
|
||||
static Boxed_Value from_json(const json::JSON &t_json) {
|
||||
switch (t_json.JSONType()) {
|
||||
case json::JSON::Class::Null:
|
||||
return Boxed_Value();
|
||||
case json::JSON::Class::Object:
|
||||
{
|
||||
case json::JSON::Class::Object: {
|
||||
std::map<std::string, Boxed_Value> m;
|
||||
|
||||
for (const auto &p : t_json.object_range())
|
||||
{
|
||||
for (const auto &p : t_json.object_range()) {
|
||||
m.insert(std::make_pair(p.first, from_json(p.second)));
|
||||
}
|
||||
|
||||
return Boxed_Value(m);
|
||||
}
|
||||
case json::JSON::Class::Array:
|
||||
{
|
||||
case json::JSON::Class::Array: {
|
||||
std::vector<Boxed_Value> vec;
|
||||
|
||||
for (const auto &p : t_json.array_range())
|
||||
{
|
||||
for (const auto &p : t_json.array_range()) {
|
||||
vec.emplace_back(from_json(p));
|
||||
}
|
||||
|
||||
@ -61,28 +49,22 @@ namespace chaiscript
|
||||
throw std::runtime_error("Unknown JSON type");
|
||||
}
|
||||
|
||||
static Boxed_Value from_json(const std::string &t_json)
|
||||
{
|
||||
static Boxed_Value from_json(const std::string &t_json) {
|
||||
try {
|
||||
return from_json( json::JSON::Load(t_json) );
|
||||
} catch (const std::out_of_range& ) {
|
||||
return from_json(json::JSON::Load(t_json));
|
||||
} catch (const std::out_of_range &) {
|
||||
throw std::runtime_error("Unparsed JSON input");
|
||||
}
|
||||
}
|
||||
|
||||
static std::string to_json(const Boxed_Value &t_bv)
|
||||
{
|
||||
return to_json_object(t_bv).dump();
|
||||
}
|
||||
static std::string to_json(const Boxed_Value &t_bv) { return to_json_object(t_bv).dump(); }
|
||||
|
||||
static json::JSON to_json_object(const Boxed_Value &t_bv)
|
||||
{
|
||||
static json::JSON to_json_object(const Boxed_Value &t_bv) {
|
||||
try {
|
||||
const std::map<std::string, Boxed_Value> m = chaiscript::boxed_cast<const std::map<std::string, Boxed_Value> &>(t_bv);
|
||||
|
||||
json::JSON obj(json::JSON::Class::Object);
|
||||
for (const auto &o : m)
|
||||
{
|
||||
for (const auto &o : m) {
|
||||
obj[o.first] = to_json_object(o.second);
|
||||
}
|
||||
return obj;
|
||||
@ -94,8 +76,7 @@ namespace chaiscript
|
||||
const std::vector<Boxed_Value> v = chaiscript::boxed_cast<const std::vector<Boxed_Value> &>(t_bv);
|
||||
|
||||
json::JSON obj(json::JSON::Class::Array);
|
||||
for (size_t i = 0; i < v.size(); ++i)
|
||||
{
|
||||
for (size_t i = 0; i < v.size(); ++i) {
|
||||
obj[i] = to_json_object(v[i]);
|
||||
}
|
||||
return obj;
|
||||
@ -103,11 +84,9 @@ namespace chaiscript
|
||||
// not a vector
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
Boxed_Number bn(t_bv);
|
||||
if (Boxed_Number::is_floating_point(t_bv))
|
||||
{
|
||||
if (Boxed_Number::is_floating_point(t_bv)) {
|
||||
return json::JSON(bn.get_as<double>());
|
||||
} else {
|
||||
return json::JSON(bn.get_as<std::int64_t>());
|
||||
@ -128,13 +107,11 @@ namespace chaiscript
|
||||
// not a string
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
const chaiscript::dispatch::Dynamic_Object &o = boxed_cast<const dispatch::Dynamic_Object &>(t_bv);
|
||||
|
||||
json::JSON obj(json::JSON::Class::Object);
|
||||
for (const auto &attr : o.get_attrs())
|
||||
{
|
||||
for (const auto &attr : o.get_attrs()) {
|
||||
obj[attr.first] = to_json_object(attr.second);
|
||||
}
|
||||
return obj;
|
||||
@ -142,15 +119,13 @@ namespace chaiscript
|
||||
// not a dynamic object
|
||||
}
|
||||
|
||||
if (t_bv.is_null()) return json::JSON(); // a null value
|
||||
if (t_bv.is_null())
|
||||
return json::JSON(); // a null value
|
||||
|
||||
throw std::runtime_error("Unknown object type to convert to JSON");
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
} // namespace chaiscript
|
||||
|
||||
#endif
|
||||
|
||||
@ -2,10 +2,8 @@
|
||||
#define CHAISCRIPT_UTILITY_QUICK_FLAT_MAP_HPP
|
||||
|
||||
namespace chaiscript::utility {
|
||||
|
||||
template<typename Key, typename Value, typename Comparator=std::equal_to<>>
|
||||
struct QuickFlatMap
|
||||
{
|
||||
template<typename Key, typename Value, typename Comparator = std::equal_to<>>
|
||||
struct QuickFlatMap {
|
||||
Comparator comparator;
|
||||
|
||||
template<typename Lookup>
|
||||
@ -28,35 +26,19 @@ namespace chaiscript::utility {
|
||||
}
|
||||
}
|
||||
|
||||
auto size() const noexcept {
|
||||
return data.size();
|
||||
}
|
||||
auto size() const noexcept { return data.size(); }
|
||||
|
||||
auto begin() const noexcept {
|
||||
return data.begin();
|
||||
}
|
||||
auto begin() const noexcept { return data.begin(); }
|
||||
|
||||
auto end() const noexcept {
|
||||
return data.end();
|
||||
}
|
||||
auto end() const noexcept { return data.end(); }
|
||||
|
||||
auto begin() noexcept { return data.begin(); }
|
||||
|
||||
auto begin() noexcept {
|
||||
return data.begin();
|
||||
}
|
||||
auto end() noexcept { return data.end(); }
|
||||
|
||||
auto end() noexcept {
|
||||
return data.end();
|
||||
}
|
||||
|
||||
auto &back() noexcept {
|
||||
return data.back();
|
||||
}
|
||||
|
||||
const auto &back() const noexcept {
|
||||
return data.back();
|
||||
}
|
||||
auto &back() noexcept { return data.back(); }
|
||||
|
||||
const auto &back() const noexcept { return data.back(); }
|
||||
|
||||
Value &operator[](const Key &s) {
|
||||
const auto itr = find(s);
|
||||
@ -68,24 +50,14 @@ namespace chaiscript::utility {
|
||||
}
|
||||
}
|
||||
|
||||
Value &at_index(const std::size_t idx) noexcept
|
||||
{
|
||||
return data[idx].second;
|
||||
}
|
||||
Value &at_index(const std::size_t idx) noexcept { return data[idx].second; }
|
||||
|
||||
const Value &at_index(const std::size_t idx) const noexcept
|
||||
{
|
||||
return data[idx].second;
|
||||
}
|
||||
const Value &at_index(const std::size_t idx) const noexcept { return data[idx].second; }
|
||||
|
||||
bool empty() const noexcept
|
||||
{
|
||||
return data.empty();
|
||||
}
|
||||
bool empty() const noexcept { return data.empty(); }
|
||||
|
||||
template<typename Itr>
|
||||
void assign(Itr begin, Itr end)
|
||||
{
|
||||
void assign(Itr begin, Itr end) {
|
||||
data.assign(begin, end);
|
||||
}
|
||||
|
||||
@ -98,10 +70,8 @@ namespace chaiscript::utility {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<typename M>
|
||||
auto insert_or_assign(Key &&key, M &&m)
|
||||
{
|
||||
auto insert_or_assign(Key &&key, M &&m) {
|
||||
if (auto itr = find(key); itr != data.end()) {
|
||||
*itr = std::forward<M>(m);
|
||||
return std::pair{itr, false};
|
||||
@ -111,10 +81,8 @@ namespace chaiscript::utility {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<typename M>
|
||||
auto insert_or_assign(const Key &key, M &&m)
|
||||
{
|
||||
auto insert_or_assign(const Key &key, M &&m) {
|
||||
if (auto itr = find(key); itr != data.end()) {
|
||||
itr->second = std::forward<M>(m);
|
||||
return std::pair{itr, false};
|
||||
@ -135,7 +103,7 @@ namespace chaiscript::utility {
|
||||
|
||||
template<typename Lookup>
|
||||
size_t count(const Lookup &s) const noexcept {
|
||||
return (find(s) != data.end())?1:0;
|
||||
return (find(s) != data.end()) ? 1 : 0;
|
||||
}
|
||||
|
||||
std::vector<std::pair<Key, Value>> data;
|
||||
@ -144,8 +112,7 @@ namespace chaiscript::utility {
|
||||
using iterator = typename decltype(data)::iterator;
|
||||
using const_iterator = typename decltype(data)::const_iterator;
|
||||
|
||||
std::pair<iterator,bool> insert( value_type&& value )
|
||||
{
|
||||
std::pair<iterator, bool> insert(value_type &&value) {
|
||||
if (const auto itr = find(value.first); itr != data.end()) {
|
||||
return std::pair{itr, false};
|
||||
} else {
|
||||
@ -159,11 +126,8 @@ namespace chaiscript::utility {
|
||||
data.reserve(data.size() + 2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace chaiscript::utility
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@ -7,47 +7,36 @@
|
||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||
|
||||
|
||||
#ifndef CHAISCRIPT_STACK_VECTOR_HPP_
|
||||
#define CHAISCRIPT_STACK_VECTOR_HPP_
|
||||
|
||||
#include <cstdint>
|
||||
#include <type_traits>
|
||||
#include <string>
|
||||
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
template<typename T, std::size_t MaxSize>
|
||||
struct Stack_Vector
|
||||
{
|
||||
struct Stack_Vector {
|
||||
constexpr static auto aligned_size = sizeof(T) + (sizeof(T) & std::alignment_of_v<T>) > 0 ? std::alignment_of_v<T> : 0;
|
||||
|
||||
alignas(std::alignment_of_v<T>) char data[aligned_size * MaxSize];
|
||||
|
||||
[[nodiscard]] T & operator[](const std::size_t idx) noexcept {
|
||||
return *reinterpret_cast<T*>(&data + aligned_size * idx);
|
||||
[[nodiscard]] T &operator[](const std::size_t idx) noexcept { return *reinterpret_cast<T *>(&data + aligned_size * idx); }
|
||||
|
||||
[[nodiscard]] const T &operator[](const std::size_t idx) const noexcept {
|
||||
return *reinterpret_cast<const T *>(&data + aligned_size * idx);
|
||||
}
|
||||
|
||||
[[nodiscard]] const T & operator[](const std::size_t idx) const noexcept {
|
||||
return *reinterpret_cast<const T*>(&data + aligned_size * idx);
|
||||
}
|
||||
|
||||
template<typename ... Param>
|
||||
T& emplace_back(Param && ... param) {
|
||||
auto *p = new(&(*this)[m_size++]) T(std::forward<Param>(param)...);
|
||||
template<typename... Param>
|
||||
T &emplace_back(Param &&...param) {
|
||||
auto *p = new (&(*this)[m_size++]) T(std::forward<Param>(param)...);
|
||||
return *p;
|
||||
};
|
||||
|
||||
auto size() const noexcept {
|
||||
return m_size;
|
||||
};
|
||||
auto size() const noexcept { return m_size; };
|
||||
|
||||
void pop_back() noexcept(std::is_nothrow_destructible_v<T>) {
|
||||
(*this)[--m_size].~T();
|
||||
}
|
||||
void pop_back() noexcept(std::is_nothrow_destructible_v<T>) { (*this)[--m_size].~T(); }
|
||||
|
||||
~Stack_Vector() noexcept(std::is_nothrow_destructible_v<T>)
|
||||
{
|
||||
~Stack_Vector() noexcept(std::is_nothrow_destructible_v<T>) {
|
||||
auto loc = m_size - 1;
|
||||
for (std::size_t pos = 0; pos < m_size; ++pos) {
|
||||
(*this)[loc--].~T();
|
||||
@ -55,9 +44,6 @@ struct Stack_Vector
|
||||
}
|
||||
|
||||
std::size_t m_size{0};
|
||||
|
||||
};
|
||||
|
||||
#endif CHAISCRIPT_STACK_VECTOR_HPP_
|
||||
|
||||
|
||||
|
||||
@ -7,59 +7,48 @@
|
||||
#ifndef CHAISCRIPT_UTILITY_STATIC_STRING_HPP_
|
||||
#define CHAISCRIPT_UTILITY_STATIC_STRING_HPP_
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
namespace utility
|
||||
{
|
||||
|
||||
struct Static_String
|
||||
{
|
||||
namespace chaiscript::utility {
|
||||
struct Static_String {
|
||||
template<size_t N>
|
||||
constexpr Static_String(const char (&str)[N]) noexcept
|
||||
: m_size(N-1), data(&str[0])
|
||||
{
|
||||
: m_size(N - 1)
|
||||
, data(&str[0]) {
|
||||
}
|
||||
|
||||
constexpr size_t size() const noexcept {
|
||||
return m_size;
|
||||
}
|
||||
constexpr size_t size() const noexcept { return m_size; }
|
||||
|
||||
constexpr const char *c_str() const noexcept {
|
||||
return data;
|
||||
}
|
||||
constexpr const char *c_str() const noexcept { return data; }
|
||||
|
||||
constexpr auto begin() const noexcept {
|
||||
return data;
|
||||
}
|
||||
constexpr auto begin() const noexcept { return data; }
|
||||
|
||||
constexpr auto end() const noexcept {
|
||||
return data + m_size;
|
||||
}
|
||||
constexpr auto end() const noexcept { return data + m_size; }
|
||||
|
||||
constexpr bool operator==(std::string_view other) const noexcept {
|
||||
//return std::string_view(data, m_size) == other;
|
||||
// return std::string_view(data, m_size) == other;
|
||||
auto b1 = begin();
|
||||
const auto e1 = end();
|
||||
auto b2 = other.begin();
|
||||
const auto e2 = other.end();
|
||||
|
||||
if (e1 - b1 != e2 - b2) { return false; }
|
||||
if (e1 - b1 != e2 - b2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
while (b1 != e1) {
|
||||
if (*b1 != *b2) { return false; }
|
||||
++b1; ++b2;
|
||||
if (*b1 != *b2) {
|
||||
return false;
|
||||
}
|
||||
++b1;
|
||||
++b2;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool operator==(const std::string &t_str) const noexcept {
|
||||
return std::equal(begin(), end(), std::cbegin(t_str), std::cend(t_str));
|
||||
}
|
||||
bool operator==(const std::string &t_str) const noexcept { return std::equal(begin(), end(), std::cbegin(t_str), std::cend(t_str)); }
|
||||
|
||||
const size_t m_size;
|
||||
const char *data = nullptr;
|
||||
};
|
||||
}
|
||||
}
|
||||
} // namespace chaiscript::utility
|
||||
|
||||
#endif
|
||||
|
||||
@ -7,7 +7,6 @@
|
||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||
|
||||
|
||||
#ifndef CHAISCRIPT_UTILITY_UTILITY_HPP_
|
||||
#define CHAISCRIPT_UTILITY_UTILITY_HPP_
|
||||
|
||||
@ -16,16 +15,11 @@
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "../language/chaiscript_common.hpp"
|
||||
#include "../dispatchkit/register_function.hpp"
|
||||
#include "../dispatchkit/operators.hpp"
|
||||
#include "../dispatchkit/register_function.hpp"
|
||||
#include "../language/chaiscript_common.hpp"
|
||||
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
namespace utility
|
||||
{
|
||||
|
||||
namespace chaiscript::utility {
|
||||
/// Single step command for registering a class with ChaiScript
|
||||
///
|
||||
/// \param[in,out] t_module Model to add class to
|
||||
@ -53,17 +47,14 @@ namespace chaiscript
|
||||
void add_class(ModuleType &t_module,
|
||||
const std::string &t_class_name,
|
||||
const std::vector<chaiscript::Proxy_Function> &t_constructors,
|
||||
const std::vector<std::pair<chaiscript::Proxy_Function, std::string>> &t_funcs)
|
||||
{
|
||||
const std::vector<std::pair<chaiscript::Proxy_Function, std::string>> &t_funcs) {
|
||||
t_module.add(chaiscript::user_type<Class>(), t_class_name);
|
||||
|
||||
for(const chaiscript::Proxy_Function &ctor: t_constructors)
|
||||
{
|
||||
for (const chaiscript::Proxy_Function &ctor : t_constructors) {
|
||||
t_module.add(ctor, t_class_name);
|
||||
}
|
||||
|
||||
for(const auto &fun: t_funcs)
|
||||
{
|
||||
for (const auto &fun : t_funcs) {
|
||||
t_module.add(fun.first, fun.second);
|
||||
}
|
||||
}
|
||||
@ -72,13 +63,11 @@ namespace chaiscript
|
||||
typename std::enable_if<std::is_enum<Enum>::value, void>::type
|
||||
add_class(ModuleType &t_module,
|
||||
const std::string &t_class_name,
|
||||
const std::vector<std::pair<typename std::underlying_type<Enum>::type, std::string>> &t_constants
|
||||
)
|
||||
{
|
||||
const std::vector<std::pair<typename std::underlying_type<Enum>::type, std::string>> &t_constants) {
|
||||
t_module.add(chaiscript::user_type<Enum>(), t_class_name);
|
||||
|
||||
t_module.add(chaiscript::constructor<Enum ()>(), t_class_name);
|
||||
t_module.add(chaiscript::constructor<Enum (const Enum &)>(), t_class_name);
|
||||
t_module.add(chaiscript::constructor<Enum()>(), t_class_name);
|
||||
t_module.add(chaiscript::constructor<Enum(const Enum &)>(), t_class_name);
|
||||
|
||||
using namespace chaiscript::bootstrap::operators;
|
||||
equal<Enum>(t_module);
|
||||
@ -88,19 +77,14 @@ namespace chaiscript
|
||||
t_module.add(chaiscript::fun([](const Enum &e, const int &i) { return e == i; }), "==");
|
||||
t_module.add(chaiscript::fun([](const int &i, const Enum &e) { return i == e; }), "==");
|
||||
|
||||
for (const auto &constant : t_constants)
|
||||
{
|
||||
for (const auto &constant : t_constants) {
|
||||
t_module.add_global_const(chaiscript::const_var(Enum(constant.first)), constant.second);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename EnumClass, typename ModuleType>
|
||||
typename std::enable_if<std::is_enum<EnumClass>::value, void>::type
|
||||
add_class(ModuleType &t_module,
|
||||
const std::string &t_class_name,
|
||||
const std::vector<std::pair<EnumClass, std::string>> &t_constants
|
||||
)
|
||||
{
|
||||
add_class(ModuleType &t_module, const std::string &t_class_name, const std::vector<std::pair<EnumClass, std::string>> &t_constants) {
|
||||
t_module.add(chaiscript::user_type<EnumClass>(), t_class_name);
|
||||
|
||||
t_module.add(chaiscript::constructor<EnumClass()>(), t_class_name);
|
||||
@ -111,13 +95,10 @@ namespace chaiscript
|
||||
not_equal<EnumClass>(t_module);
|
||||
assign<EnumClass>(t_module);
|
||||
|
||||
for (const auto &constant : t_constants)
|
||||
{
|
||||
for (const auto &constant : t_constants) {
|
||||
t_module.add_global_const(chaiscript::const_var(EnumClass(constant.first)), constant.second);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace chaiscript::utility
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@ -5,8 +5,7 @@ double f(const std::string &, double, bool) noexcept {
|
||||
return .0;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
int main() {
|
||||
chaiscript::ChaiScript chai;
|
||||
|
||||
chai.add(chaiscript::fun(&f), "f");
|
||||
@ -16,5 +15,4 @@ int main()
|
||||
f("str", 1.2, false);
|
||||
}
|
||||
)");
|
||||
|
||||
}
|
||||
|
||||
@ -5,16 +5,14 @@ double f(const std::string &, double, bool) noexcept {
|
||||
return .0;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
int main() {
|
||||
chaiscript::ChaiScript chai;
|
||||
|
||||
chai.add(chaiscript::fun(&f), "f");
|
||||
|
||||
const auto f = chai.eval<std::function<void ()>>(R"(fun(){ f("str", 1.2, false); })");
|
||||
const auto f = chai.eval<std::function<void()>>(R"(fun(){ f("str", 1.2, false); })");
|
||||
|
||||
for (int i = 0; i < 100000; ++i) {
|
||||
f();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,52 +1,45 @@
|
||||
#include <chaiscript/chaiscript.hpp>
|
||||
|
||||
class Entity
|
||||
{
|
||||
public:
|
||||
class Entity {
|
||||
public:
|
||||
int width;
|
||||
int height;
|
||||
int x;
|
||||
int y;
|
||||
std::string name;
|
||||
|
||||
std::function<void (Entity &)> updater;
|
||||
std::function<void(Entity &)> updater;
|
||||
|
||||
Entity(const int t_width, const int t_height, const int t_x, const int t_y, std::string t_name)
|
||||
: width(t_width), height(t_height), x(t_x), y(t_y), name(std::move(t_name))
|
||||
{
|
||||
: width(t_width)
|
||||
, height(t_height)
|
||||
, x(t_x)
|
||||
, y(t_y)
|
||||
, name(std::move(t_name)) {
|
||||
}
|
||||
};
|
||||
|
||||
class Factory
|
||||
{
|
||||
public:
|
||||
class Factory {
|
||||
public:
|
||||
// we may as well pass the parameters for the entity to the factory method, this does the initialization
|
||||
// in one step.
|
||||
Entity *make_entity(const int width, const int height, const int x, const int y, const std::string &name)
|
||||
{
|
||||
Entity *make_entity(const int width, const int height, const int x, const int y, const std::string &name) {
|
||||
auto entity = entities.insert({name, Entity{width, height, x, y, name}});
|
||||
return &(entity.first->second);
|
||||
}
|
||||
|
||||
Entity *get_entity(const std::string &name)
|
||||
{
|
||||
return &entities.at(name);
|
||||
}
|
||||
|
||||
Entity *get_entity(const std::string &name) { return &entities.at(name); }
|
||||
|
||||
// loop over all entities and all their updater function (if it exists)
|
||||
void update_entities()
|
||||
{
|
||||
for (auto &entity : entities)
|
||||
{
|
||||
void update_entities() {
|
||||
for (auto &entity : entities) {
|
||||
if (entity.second.updater) {
|
||||
entity.second.updater(entity.second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
private:
|
||||
// we cannot store the entities in a std::vector if we want to return a pointer to them,
|
||||
// because a vector automatically resizing itself can invalidate the pointer that was returned.
|
||||
// using a map guarantees that the memory assigned to the entity will never change, plus
|
||||
@ -54,8 +47,7 @@ class Factory
|
||||
std::map<std::string, Entity> entities;
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
int main() {
|
||||
chaiscript::ChaiScript chai;
|
||||
|
||||
chai.add(chaiscript::fun(&Entity::width), "width");
|
||||
@ -71,7 +63,6 @@ int main()
|
||||
chai.add(chaiscript::fun(&Factory::update_entities), "update_entities");
|
||||
chai.add(chaiscript::user_type<Factory>(), "Factory"); // this isn't strictly necessary but makes error messages nicer
|
||||
|
||||
|
||||
Factory f;
|
||||
chai.add(chaiscript::var(&f), "f");
|
||||
|
||||
@ -92,11 +83,5 @@ int main()
|
||||
print(f.get_entity("entity3").x == 20) // this one has no updater, so it stays the same
|
||||
)"";
|
||||
|
||||
|
||||
chai.eval(script);
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -7,7 +7,6 @@
|
||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include <list>
|
||||
#include <regex>
|
||||
@ -19,14 +18,15 @@
|
||||
#include <chaiscript/chaiscript.hpp>
|
||||
|
||||
#ifdef READLINE_AVAILABLE
|
||||
#include <readline/readline.h>
|
||||
#include <readline/history.h>
|
||||
#include <readline/readline.h>
|
||||
#else
|
||||
|
||||
char *mystrdup(const char *s) {
|
||||
size_t len = strlen(s); // Space for length plus nul
|
||||
char *d = static_cast<char*>(malloc(len + 1));
|
||||
if (d == nullptr) return nullptr; // No memory
|
||||
char *d = static_cast<char *>(malloc(len + 1));
|
||||
if (d == nullptr)
|
||||
return nullptr; // No memory
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
strcpy_s(d, len + 1, s); // Copy the characters
|
||||
#else
|
||||
@ -36,26 +36,20 @@ char *mystrdup(const char *s) {
|
||||
return d; // Return the new string
|
||||
}
|
||||
|
||||
char* readline(const char* p)
|
||||
{
|
||||
char *readline(const char *p) {
|
||||
std::string retval;
|
||||
std::cout << p;
|
||||
std::getline(std::cin, retval);
|
||||
return std::cin.eof() ? nullptr : mystrdup(retval.c_str());
|
||||
}
|
||||
|
||||
|
||||
void add_history(const char*){}
|
||||
void using_history(){}
|
||||
void add_history(const char *) {}
|
||||
void using_history() {}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
void *cast_module_symbol(std::vector<std::string>(*t_path)())
|
||||
{
|
||||
union cast_union
|
||||
{
|
||||
std::vector<std::string>(*in_ptr)();
|
||||
void *cast_module_symbol(std::vector<std::string> (*t_path)()) {
|
||||
union cast_union {
|
||||
std::vector<std::string> (*in_ptr)();
|
||||
void *out_ptr;
|
||||
};
|
||||
|
||||
@ -64,8 +58,7 @@ void *cast_module_symbol(std::vector<std::string>(*t_path)())
|
||||
return c.out_ptr;
|
||||
}
|
||||
|
||||
std::vector<std::string> default_search_paths()
|
||||
{
|
||||
std::vector<std::string> default_search_paths() {
|
||||
std::vector<std::string> paths;
|
||||
|
||||
#ifndef CHAISCRIPT_NO_DYNLOAD
|
||||
@ -77,14 +70,12 @@ std::vector<std::string> default_search_paths()
|
||||
|
||||
size_t lastslash = exepath.rfind('\\');
|
||||
size_t secondtolastslash = exepath.rfind('\\', lastslash - 1);
|
||||
if (lastslash != std::string::npos)
|
||||
{
|
||||
if (lastslash != std::string::npos) {
|
||||
paths.push_back(exepath.substr(0, lastslash));
|
||||
}
|
||||
|
||||
if (secondtolastslash != std::string::npos)
|
||||
{
|
||||
return{ exepath.substr(0, secondtolastslash) + "\\lib\\chaiscript\\" };
|
||||
if (secondtolastslash != std::string::npos) {
|
||||
return {exepath.substr(0, secondtolastslash) + "\\lib\\chaiscript\\"};
|
||||
}
|
||||
#else
|
||||
|
||||
@ -93,29 +84,23 @@ std::vector<std::string> default_search_paths()
|
||||
std::vector<char> buf(2048);
|
||||
ssize_t size = -1;
|
||||
|
||||
if ((size = readlink("/proc/self/exe", &buf.front(), buf.size())) > 0)
|
||||
{
|
||||
if ((size = readlink("/proc/self/exe", &buf.front(), buf.size())) > 0) {
|
||||
exepath = std::string(&buf.front(), static_cast<size_t>(size));
|
||||
}
|
||||
|
||||
if (exepath.empty())
|
||||
{
|
||||
if ((size = readlink("/proc/curproc/file", &buf.front(), buf.size())) > 0)
|
||||
{
|
||||
if (exepath.empty()) {
|
||||
if ((size = readlink("/proc/curproc/file", &buf.front(), buf.size())) > 0) {
|
||||
exepath = std::string(&buf.front(), static_cast<size_t>(size));
|
||||
}
|
||||
}
|
||||
|
||||
if (exepath.empty())
|
||||
{
|
||||
if ((size = readlink("/proc/self/path/a.out", &buf.front(), buf.size())) > 0)
|
||||
{
|
||||
if (exepath.empty()) {
|
||||
if ((size = readlink("/proc/self/path/a.out", &buf.front(), buf.size())) > 0) {
|
||||
exepath = std::string(&buf.front(), static_cast<size_t>(size));
|
||||
}
|
||||
}
|
||||
|
||||
if (exepath.empty())
|
||||
{
|
||||
if (exepath.empty()) {
|
||||
Dl_info rInfo;
|
||||
memset(&rInfo, 0, sizeof(rInfo));
|
||||
if (!dladdr(cast_module_symbol(&default_search_paths), &rInfo) || !rInfo.dli_fname) {
|
||||
@ -128,13 +113,11 @@ std::vector<std::string> default_search_paths()
|
||||
size_t lastslash = exepath.rfind('/');
|
||||
|
||||
size_t secondtolastslash = exepath.rfind('/', lastslash - 1);
|
||||
if (lastslash != std::string::npos)
|
||||
{
|
||||
if (lastslash != std::string::npos) {
|
||||
paths.push_back(exepath.substr(0, lastslash));
|
||||
}
|
||||
|
||||
if (secondtolastslash != std::string::npos)
|
||||
{
|
||||
if (secondtolastslash != std::string::npos) {
|
||||
paths.push_back(exepath.substr(0, secondtolastslash) + "/lib/chaiscript/");
|
||||
}
|
||||
#endif
|
||||
@ -149,8 +132,7 @@ void help(int n) {
|
||||
std::cout << "Additionally, you can inspect the runtime system using:\n";
|
||||
std::cout << " dump_system() - outputs all functions registered to the system\n";
|
||||
std::cout << " dump_object(x) - dumps information about the given symbol\n";
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
std::cout << "usage : chai [option]+\n";
|
||||
std::cout << "option:\n";
|
||||
std::cout << " -h | --help\n";
|
||||
@ -162,29 +144,24 @@ void help(int n) {
|
||||
}
|
||||
}
|
||||
|
||||
std::string helloWorld(const std::string &t_name)
|
||||
{
|
||||
std::string helloWorld(const std::string &t_name) {
|
||||
return "Hello " + t_name + "!";
|
||||
}
|
||||
|
||||
bool throws_exception(const std::function<void()> &f)
|
||||
{
|
||||
bool throws_exception(const std::function<void()> &f) {
|
||||
try {
|
||||
f();
|
||||
}
|
||||
catch (...) {
|
||||
} catch (...) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
chaiscript::exception::eval_error get_eval_error(const std::function<void()> &f)
|
||||
{
|
||||
chaiscript::exception::eval_error get_eval_error(const std::function<void()> &f) {
|
||||
try {
|
||||
f();
|
||||
}
|
||||
catch (const chaiscript::exception::eval_error &e) {
|
||||
} catch (const chaiscript::exception::eval_error &e) {
|
||||
return e;
|
||||
}
|
||||
|
||||
@ -200,13 +177,11 @@ std::string get_next_command() {
|
||||
|
||||
std::string val(input_raw);
|
||||
size_t pos = val.find_first_not_of("\t \n");
|
||||
if (pos != std::string::npos)
|
||||
{
|
||||
if (pos != std::string::npos) {
|
||||
val.erase(0, pos);
|
||||
}
|
||||
pos = val.find_last_not_of("\t \n");
|
||||
if (pos != std::string::npos)
|
||||
{
|
||||
if (pos != std::string::npos) {
|
||||
val.erase(pos + 1, std::string::npos);
|
||||
}
|
||||
|
||||
@ -215,11 +190,7 @@ std::string get_next_command() {
|
||||
::free(input_raw);
|
||||
}
|
||||
}
|
||||
if (retval == "quit"
|
||||
|| retval == "exit"
|
||||
|| retval == "help"
|
||||
|| retval == "version")
|
||||
{
|
||||
if (retval == "quit" || retval == "exit" || retval == "help" || retval == "version") {
|
||||
retval += "(0)";
|
||||
}
|
||||
return retval;
|
||||
@ -231,8 +202,7 @@ void myexit(int return_val) {
|
||||
exit(return_val);
|
||||
}
|
||||
|
||||
void interactive(chaiscript::ChaiScript& chai)
|
||||
{
|
||||
void interactive(chaiscript::ChaiScript &chai) {
|
||||
using_history();
|
||||
|
||||
for (;;) {
|
||||
@ -241,32 +211,28 @@ void interactive(chaiscript::ChaiScript& chai)
|
||||
// evaluate input
|
||||
chaiscript::Boxed_Value val = chai.eval(input);
|
||||
|
||||
//Then, we try to print the result of the evaluation to the user
|
||||
// Then, we try to print the result of the evaluation to the user
|
||||
if (!val.get_type_info().bare_equal(chaiscript::user_type<void>())) {
|
||||
try {
|
||||
std::cout << chai.eval<std::function<std::string(const chaiscript::Boxed_Value &bv)> >("to_string")(val) << '\n';
|
||||
std::cout << chai.eval<std::function<std::string(const chaiscript::Boxed_Value &bv)>>("to_string")(val) << '\n';
|
||||
} catch (...) {
|
||||
} // If we can't, do nothing
|
||||
}
|
||||
catch (...) {} //If we can't, do nothing
|
||||
}
|
||||
}
|
||||
catch (const chaiscript::exception::eval_error &ee) {
|
||||
} catch (const chaiscript::exception::eval_error &ee) {
|
||||
std::cout << ee.what();
|
||||
if (ee.call_stack.size() > 0) {
|
||||
std::cout << "during evaluation at (" << ee.call_stack[0].start().line << ", " << ee.call_stack[0].start().column << ")";
|
||||
}
|
||||
std::cout << '\n';
|
||||
}
|
||||
catch (const std::exception &e) {
|
||||
} catch (const std::exception &e) {
|
||||
std::cout << e.what();
|
||||
std::cout << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
|
||||
// Disable deprecation warning for getenv call.
|
||||
int main(int argc, char *argv[]) {
|
||||
// Disable deprecation warning for getenv call.
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4996)
|
||||
@ -281,8 +247,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
std::vector<std::string> usepaths;
|
||||
usepaths.push_back("");
|
||||
if (usepath)
|
||||
{
|
||||
if (usepath) {
|
||||
usepaths.push_back(usepath);
|
||||
}
|
||||
|
||||
@ -290,12 +255,11 @@ int main(int argc, char *argv[])
|
||||
std::vector<std::string> searchpaths = default_search_paths();
|
||||
modulepaths.insert(modulepaths.end(), searchpaths.begin(), searchpaths.end());
|
||||
modulepaths.push_back("");
|
||||
if (modulepath)
|
||||
{
|
||||
if (modulepath) {
|
||||
modulepaths.push_back(modulepath);
|
||||
}
|
||||
|
||||
//chaiscript::ChaiScript chai(modulepaths, usepaths);
|
||||
// chaiscript::ChaiScript chai(modulepaths, usepaths);
|
||||
chaiscript::ChaiScript chai(usepaths);
|
||||
|
||||
chai.add(chaiscript::fun(&myexit), "exit");
|
||||
@ -308,8 +272,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
clock_t begin = clock();
|
||||
|
||||
for (int i = 0; i < 1000; i++)
|
||||
{
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
std::string str = helloWorld("Bob12345");
|
||||
fwrite(str.c_str(), 1, str.size(), stdout);
|
||||
}
|
||||
@ -317,17 +280,17 @@ int main(int argc, char *argv[])
|
||||
clock_t end = clock();
|
||||
double elapsed_secs = double(end - begin) / CLOCKS_PER_SEC;
|
||||
|
||||
//begin = clock();
|
||||
// begin = clock();
|
||||
|
||||
////for (int i = 0; i < 1000; i++)
|
||||
////{
|
||||
//// chai.eval("puts(helloWorld(\"Bob12345\"));");
|
||||
////}
|
||||
//chai.eval_file("E:\\C++\\ChaiScript - 5.4.0\\samples\forx.chai");
|
||||
// chai.eval_file("E:\\C++\\ChaiScript - 5.4.0\\samples\forx.chai");
|
||||
|
||||
//end = clock();
|
||||
//elapsed_secs = double(end - begin) / CLOCKS_PER_SEC;
|
||||
//printf("**MyProgram::time= %lf\n", elapsed_secs);
|
||||
// end = clock();
|
||||
// elapsed_secs = double(end - begin) / CLOCKS_PER_SEC;
|
||||
// printf("**MyProgram::time= %lf\n", elapsed_secs);
|
||||
|
||||
for (int i = 0; i < argc; ++i) {
|
||||
if (i == 0 && argc > 1) {
|
||||
@ -337,49 +300,47 @@ int main(int argc, char *argv[])
|
||||
std::string arg(i ? argv[i] : "--interactive");
|
||||
|
||||
enum {
|
||||
eInteractive
|
||||
, eCommand
|
||||
, eFile
|
||||
} mode = eCommand;
|
||||
eInteractive,
|
||||
eCommand,
|
||||
eFile
|
||||
} mode
|
||||
= eCommand;
|
||||
|
||||
if (arg == "-c" || arg == "--command") {
|
||||
if ((i + 1) >= argc) {
|
||||
std::cout << "insufficient input following " << arg << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
arg = argv[++i];
|
||||
}
|
||||
}
|
||||
else if (arg == "-" || arg == "--stdin") {
|
||||
} else if (arg == "-" || arg == "--stdin") {
|
||||
arg = "";
|
||||
std::string line;
|
||||
while (std::getline(std::cin, line)) {
|
||||
arg += line + '\n';
|
||||
}
|
||||
}
|
||||
else if (arg == "-v" || arg == "--version") {
|
||||
} else if (arg == "-v" || arg == "--version") {
|
||||
arg = "version()";
|
||||
}
|
||||
else if (arg == "-h" || arg == "--help") {
|
||||
} else if (arg == "-h" || arg == "--help") {
|
||||
arg = "help(-1)";
|
||||
}
|
||||
else if (arg == "-i" || arg == "--interactive") {
|
||||
} else if (arg == "-i" || arg == "--interactive") {
|
||||
mode = eInteractive;
|
||||
}
|
||||
else if (arg.find('-') == 0) {
|
||||
} else if (arg.find('-') == 0) {
|
||||
std::cout << "unrecognised argument " << arg << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
mode = eFile;
|
||||
}
|
||||
|
||||
chaiscript::Boxed_Value val;
|
||||
try {
|
||||
switch (mode) {
|
||||
case eInteractive: interactive(chai); break;
|
||||
case eCommand: val = chai.eval(arg); break;
|
||||
case eInteractive:
|
||||
interactive(chai);
|
||||
break;
|
||||
case eCommand:
|
||||
val = chai.eval(arg);
|
||||
break;
|
||||
case eFile: {
|
||||
begin = clock();
|
||||
|
||||
@ -391,15 +352,12 @@ int main(int argc, char *argv[])
|
||||
printf("**ChaiScript::time= %.10f\n", elapsed_secs1);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
catch (const chaiscript::exception::eval_error &ee) {
|
||||
} catch (const chaiscript::exception::eval_error &ee) {
|
||||
std::cout << ee.pretty_print();
|
||||
std::cout << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
catch (std::exception &e) {
|
||||
} catch (std::exception &e) {
|
||||
std::cout << e.what() << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
@ -407,4 +365,3 @@ int main(int argc, char *argv[])
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
@ -1,79 +1,66 @@
|
||||
#include <chaiscript/chaiscript.hpp>
|
||||
|
||||
class BaseClass
|
||||
{
|
||||
public:
|
||||
BaseClass()
|
||||
{
|
||||
}
|
||||
class BaseClass {
|
||||
public:
|
||||
BaseClass() = default;
|
||||
|
||||
BaseClass(const BaseClass &) = default;
|
||||
|
||||
virtual ~BaseClass() {}
|
||||
virtual ~BaseClass() = default;
|
||||
|
||||
virtual std::string doSomething(float, double) const = 0;
|
||||
|
||||
|
||||
void setValue(const std::string &t_val) {
|
||||
if (validateValue(t_val))
|
||||
{
|
||||
if (validateValue(t_val)) {
|
||||
m_value = t_val;
|
||||
}
|
||||
}
|
||||
|
||||
std::string getValue() const {
|
||||
return m_value;
|
||||
}
|
||||
std::string getValue() const { return m_value; }
|
||||
|
||||
protected:
|
||||
protected:
|
||||
virtual bool validateValue(const std::string &t_val) = 0;
|
||||
|
||||
private:
|
||||
private:
|
||||
std::string m_value;
|
||||
};
|
||||
|
||||
class ChaiScriptDerived : public BaseClass
|
||||
{
|
||||
public:
|
||||
ChaiScriptDerived(const std::vector<chaiscript::Boxed_Value> &t_funcs)
|
||||
{
|
||||
class ChaiScriptDerived : public BaseClass {
|
||||
public:
|
||||
ChaiScriptDerived(const std::vector<chaiscript::Boxed_Value> &t_funcs) {
|
||||
// using the range-checked .at() methods to give us an exception
|
||||
// instead of a crash if the user passed in too-few params
|
||||
tie(t_funcs.at(0), m_doSomethingImpl);
|
||||
tie(t_funcs.at(1), m_validateValueImpl);
|
||||
}
|
||||
|
||||
std::string doSomething(float f, double d) const override
|
||||
{
|
||||
std::string doSomething(float f, double d) const override {
|
||||
assert(m_doSomethingImpl);
|
||||
return m_doSomethingImpl(*this, f, d);
|
||||
}
|
||||
|
||||
protected:
|
||||
bool validateValue(const std::string &t_val) override
|
||||
{
|
||||
protected:
|
||||
bool validateValue(const std::string &t_val) override {
|
||||
assert(m_validateValueImpl);
|
||||
return m_validateValueImpl(*this, t_val);
|
||||
}
|
||||
|
||||
private:
|
||||
private:
|
||||
template<typename Param>
|
||||
void tie(const chaiscript::Boxed_Value &t_func, Param &t_param)
|
||||
{
|
||||
void tie(const chaiscript::Boxed_Value &t_func, Param &t_param) {
|
||||
t_param = chaiscript::boxed_cast<Param>(t_func);
|
||||
}
|
||||
|
||||
std::function<std::string (const ChaiScriptDerived&, float, double)> m_doSomethingImpl;
|
||||
std::function<bool (ChaiScriptDerived&, const std::string &t_val)> m_validateValueImpl;
|
||||
std::function<std::string(const ChaiScriptDerived &, float, double)> m_doSomethingImpl;
|
||||
std::function<bool(ChaiScriptDerived &, const std::string &t_val)> m_validateValueImpl;
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
int main() {
|
||||
chaiscript::ChaiScript chai;
|
||||
chai.add(chaiscript::fun(&BaseClass::doSomething), "doSomething");
|
||||
chai.add(chaiscript::fun(&BaseClass::setValue), "setValue");
|
||||
chai.add(chaiscript::fun(&BaseClass::getValue), "getValue");
|
||||
chai.add(chaiscript::constructor<ChaiScriptDerived (const std::vector<chaiscript::Boxed_Value> &)>(), "ChaiScriptDerived");
|
||||
chai.add(chaiscript::constructor<ChaiScriptDerived(const std::vector<chaiscript::Boxed_Value> &)>(), "ChaiScriptDerived");
|
||||
chai.add(chaiscript::base_class<BaseClass, ChaiScriptDerived>());
|
||||
chai.add(chaiscript::user_type<BaseClass>(), "BaseClass");
|
||||
chai.add(chaiscript::user_type<ChaiScriptDerived>(), "ChaiScriptDerived");
|
||||
@ -106,7 +93,7 @@ int main()
|
||||
|
||||
chai.eval(script);
|
||||
|
||||
BaseClass &myderived = chai.eval<ChaiScriptDerived&>("myderived");
|
||||
BaseClass &myderived = chai.eval<ChaiScriptDerived &>("myderived");
|
||||
|
||||
// at this point in the code myderived is both a ChaiScript variable and a C++ variable. In both cases
|
||||
// it is a derivation of BaseClass, and the implementation is provided via ChaiScript functors
|
||||
@ -121,7 +108,6 @@ int main()
|
||||
myderived.setValue("12345");
|
||||
assert(myderived.getValue() == "1234");
|
||||
|
||||
|
||||
chai.eval(R"(myderived.setValue("new"))"); // set the value via chaiscript
|
||||
assert(myderived.getValue() == "new");
|
||||
|
||||
@ -131,5 +117,3 @@ int main()
|
||||
|
||||
// The whole process is fully orthogonal
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -3,12 +3,10 @@
|
||||
#include <chaiscript/chaiscript.hpp>
|
||||
|
||||
#ifdef READLINE_AVAILABLE
|
||||
#include <readline/readline.h>
|
||||
#include <readline/history.h>
|
||||
#include <readline/readline.h>
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
std::string get_next_command() {
|
||||
#ifdef READLINE_AVAILABLE
|
||||
char *input_raw;
|
||||
@ -23,42 +21,32 @@ std::string get_next_command() {
|
||||
#endif
|
||||
}
|
||||
|
||||
void function(void)
|
||||
{
|
||||
void function(void) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
class test
|
||||
{
|
||||
class test {
|
||||
chaiscript::ChaiScript chai;
|
||||
chaiscript::ChaiScript::State backupState = chai.get_state();
|
||||
|
||||
public:
|
||||
void ResetState()
|
||||
{
|
||||
public:
|
||||
void ResetState() {
|
||||
chai.set_state(backupState);
|
||||
chai.add(chaiscript::fun(&function),"Whatever()");
|
||||
chai.add(chaiscript::fun(&function), "Whatever()");
|
||||
}
|
||||
|
||||
void RunFile(std::string sFile)
|
||||
{
|
||||
void RunFile(std::string sFile) {
|
||||
try {
|
||||
chaiscript::Boxed_Value val = chai.eval_file(sFile);
|
||||
}
|
||||
catch (std::exception &e) {
|
||||
} catch (std::exception &e) {
|
||||
std::cout << e.what() << '\n';
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
int main(int /*argc*/, char * /*argv*/[]) {
|
||||
|
||||
test myChai;
|
||||
|
||||
|
||||
std::string command = "";
|
||||
|
||||
//
|
||||
@ -70,12 +58,11 @@ int main(int /*argc*/, char * /*argv*/[]) {
|
||||
// scenario3 - RunFile gets in changing intervals: memory usage goes up and down, but never as
|
||||
// low as in case 1 scenario3 :
|
||||
|
||||
while(command != "quit")
|
||||
{
|
||||
for(int i = 1; i < 200; i++)
|
||||
while (command != "quit") {
|
||||
for (int i = 1; i < 200; i++)
|
||||
myChai.ResetState();
|
||||
|
||||
if(command == "runfile")
|
||||
if (command == "runfile")
|
||||
myChai.RunFile("Test.chai");
|
||||
|
||||
command = get_next_command();
|
||||
|
||||
@ -2,14 +2,11 @@
|
||||
#include <chaiscript/dispatchkit/bootstrap_stl.hpp>
|
||||
#include <chaiscript/dispatchkit/function_call.hpp>
|
||||
|
||||
int main( int /*argc*/ , char * /*argv*/[] )
|
||||
{
|
||||
int main(int /*argc*/, char * /*argv*/[]) {
|
||||
chaiscript::ChaiScript ch;
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
static const char script[ ] =
|
||||
try {
|
||||
static const char script[] =
|
||||
R""(
|
||||
|
||||
class Rectangle
|
||||
@ -21,12 +18,9 @@ int main( int /*argc*/ , char * /*argv*/[] )
|
||||
|
||||
)"";
|
||||
|
||||
|
||||
ch.eval( script );
|
||||
}
|
||||
catch ( const std::exception &e )
|
||||
{
|
||||
printf( " >>> Exception thrown: %s \n" , e.what( ) );
|
||||
ch.eval(script);
|
||||
} catch (const std::exception &e) {
|
||||
printf(" >>> Exception thrown: %s \n", e.what());
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
|
||||
#include <chaiscript/chaiscript_stdlib.hpp>
|
||||
|
||||
|
||||
// MSVC doesn't like that we are using C++ return types from our C declared module
|
||||
// but this is the best way to do it for cross platform compatibility
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
@ -14,13 +13,10 @@
|
||||
#pragma clang diagnostic ignored "-Wreturn-type-c-linkage"
|
||||
#endif
|
||||
|
||||
|
||||
CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_chaiscript_stdlib()
|
||||
{
|
||||
CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_chaiscript_stdlib() {
|
||||
return chaiscript::Std_Lib::library();
|
||||
}
|
||||
|
||||
|
||||
#ifdef __llvm__
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
@ -7,7 +7,6 @@
|
||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include <list>
|
||||
#include <regex>
|
||||
@ -16,49 +15,45 @@
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#endif
|
||||
|
||||
#include <chaiscript/chaiscript.hpp>
|
||||
#include "../static_libs/chaiscript_parser.hpp"
|
||||
#include "../static_libs/chaiscript_stdlib.hpp"
|
||||
#include <chaiscript/chaiscript.hpp>
|
||||
|
||||
#include "sha3.h"
|
||||
|
||||
#ifdef READLINE_AVAILABLE
|
||||
#include <readline/readline.h>
|
||||
#include <readline/history.h>
|
||||
#include <readline/readline.h>
|
||||
#else
|
||||
|
||||
char *mystrdup (const char *s) {
|
||||
char *mystrdup(const char *s) {
|
||||
size_t len = strlen(s); // Space for length plus nul
|
||||
char *d = static_cast<char*>(malloc (len+1));
|
||||
if (d == nullptr) { return nullptr; } // No memory
|
||||
char *d = static_cast<char *>(malloc(len + 1));
|
||||
if (d == nullptr) {
|
||||
return nullptr;
|
||||
} // No memory
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
strcpy_s(d, len+1, s); // Copy the characters
|
||||
strcpy_s(d, len + 1, s); // Copy the characters
|
||||
#else
|
||||
strncpy(d,s,len); // Copy the characters
|
||||
strncpy(d, s, len); // Copy the characters
|
||||
#endif
|
||||
d[len] = '\0';
|
||||
return d; // Return the new string
|
||||
}
|
||||
|
||||
char* readline(const char* p)
|
||||
{
|
||||
char *readline(const char *p) {
|
||||
std::string retval;
|
||||
std::cout << p ;
|
||||
std::cout << p;
|
||||
std::getline(std::cin, retval);
|
||||
return std::cin.eof() ? nullptr : mystrdup(retval.c_str());
|
||||
}
|
||||
|
||||
|
||||
void add_history(const char* /*unused*/){}
|
||||
void using_history(){}
|
||||
void add_history(const char * /*unused*/) {}
|
||||
void using_history() {}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
void *cast_module_symbol(std::vector<std::string> (*t_path)())
|
||||
{
|
||||
union cast_union
|
||||
{
|
||||
void *cast_module_symbol(std::vector<std::string> (*t_path)()) {
|
||||
union cast_union {
|
||||
std::vector<std::string> (*in_ptr)();
|
||||
void *out_ptr;
|
||||
};
|
||||
@ -68,26 +63,23 @@ void *cast_module_symbol(std::vector<std::string> (*t_path)())
|
||||
return c.out_ptr;
|
||||
}
|
||||
|
||||
std::vector<std::string> default_search_paths()
|
||||
{
|
||||
std::vector<std::string> default_search_paths() {
|
||||
std::vector<std::string> paths;
|
||||
|
||||
#ifndef CHAISCRIPT_NO_DYNLOAD
|
||||
#ifdef CHAISCRIPT_WINDOWS // force no unicode
|
||||
CHAR path[4096];
|
||||
int size = GetModuleFileNameA(nullptr, path, sizeof(path)-1);
|
||||
int size = GetModuleFileNameA(nullptr, path, sizeof(path) - 1);
|
||||
|
||||
std::string exepath(path, size);
|
||||
|
||||
size_t lastslash = exepath.rfind('\\');
|
||||
size_t secondtolastslash = exepath.rfind('\\', lastslash - 1);
|
||||
if (lastslash != std::string::npos)
|
||||
{
|
||||
if (lastslash != std::string::npos) {
|
||||
paths.push_back(exepath.substr(0, lastslash));
|
||||
}
|
||||
|
||||
if (secondtolastslash != std::string::npos)
|
||||
{
|
||||
if (secondtolastslash != std::string::npos) {
|
||||
return {exepath.substr(0, secondtolastslash) + "\\lib\\chaiscript\\"};
|
||||
}
|
||||
#else
|
||||
@ -97,32 +89,26 @@ std::vector<std::string> default_search_paths()
|
||||
std::vector<char> buf(2048);
|
||||
ssize_t size = -1;
|
||||
|
||||
if ((size = readlink("/proc/self/exe", &buf.front(), buf.size())) >= 0)
|
||||
{
|
||||
if ((size = readlink("/proc/self/exe", &buf.front(), buf.size())) >= 0) {
|
||||
exepath = std::string(&buf.front(), static_cast<size_t>(size));
|
||||
}
|
||||
|
||||
if (exepath.empty())
|
||||
{
|
||||
if ((size = readlink("/proc/curproc/file", &buf.front(), buf.size())) >= 0)
|
||||
{
|
||||
if (exepath.empty()) {
|
||||
if ((size = readlink("/proc/curproc/file", &buf.front(), buf.size())) >= 0) {
|
||||
exepath = std::string(&buf.front(), static_cast<size_t>(size));
|
||||
}
|
||||
}
|
||||
|
||||
if (exepath.empty())
|
||||
{
|
||||
if ((size = readlink("/proc/self/path/a.out", &buf.front(), buf.size())) >= 0)
|
||||
{
|
||||
if (exepath.empty()) {
|
||||
if ((size = readlink("/proc/self/path/a.out", &buf.front(), buf.size())) >= 0) {
|
||||
exepath = std::string(&buf.front(), static_cast<size_t>(size));
|
||||
}
|
||||
}
|
||||
|
||||
if (exepath.empty())
|
||||
{
|
||||
if (exepath.empty()) {
|
||||
Dl_info rInfo;
|
||||
memset( &rInfo, 0, sizeof(rInfo) );
|
||||
if ( dladdr(cast_module_symbol(&default_search_paths), &rInfo) == 0 || rInfo.dli_fname == nullptr ) {
|
||||
memset(&rInfo, 0, sizeof(rInfo));
|
||||
if (dladdr(cast_module_symbol(&default_search_paths), &rInfo) == 0 || rInfo.dli_fname == nullptr) {
|
||||
return paths;
|
||||
}
|
||||
|
||||
@ -132,13 +118,11 @@ std::vector<std::string> default_search_paths()
|
||||
size_t lastslash = exepath.rfind('/');
|
||||
|
||||
size_t secondtolastslash = exepath.rfind('/', lastslash - 1);
|
||||
if (lastslash != std::string::npos)
|
||||
{
|
||||
paths.push_back(exepath.substr(0, lastslash+1));
|
||||
if (lastslash != std::string::npos) {
|
||||
paths.push_back(exepath.substr(0, lastslash + 1));
|
||||
}
|
||||
|
||||
if (secondtolastslash != std::string::npos)
|
||||
{
|
||||
if (secondtolastslash != std::string::npos) {
|
||||
paths.push_back(exepath.substr(0, secondtolastslash) + "/lib/chaiscript/");
|
||||
}
|
||||
#endif
|
||||
@ -148,7 +132,7 @@ std::vector<std::string> default_search_paths()
|
||||
}
|
||||
|
||||
void help(int n) {
|
||||
if ( n >= 0 ) {
|
||||
if (n >= 0) {
|
||||
std::cout << "ChaiScript evaluator. To evaluate an expression, type it and press <enter>.\n";
|
||||
std::cout << "Additionally, you can inspect the runtime system using:\n";
|
||||
std::cout << " dump_system() - outputs all functions registered to the system\n";
|
||||
@ -165,8 +149,7 @@ void help(int n) {
|
||||
}
|
||||
}
|
||||
|
||||
bool throws_exception(const std::function<void ()> &f)
|
||||
{
|
||||
bool throws_exception(const std::function<void()> &f) {
|
||||
try {
|
||||
f();
|
||||
} catch (...) {
|
||||
@ -176,8 +159,7 @@ bool throws_exception(const std::function<void ()> &f)
|
||||
return false;
|
||||
}
|
||||
|
||||
chaiscript::exception::eval_error get_eval_error(const std::function<void ()> &f)
|
||||
{
|
||||
chaiscript::exception::eval_error get_eval_error(const std::function<void()> &f) {
|
||||
try {
|
||||
f();
|
||||
} catch (const chaiscript::exception::eval_error &e) {
|
||||
@ -189,21 +171,19 @@ chaiscript::exception::eval_error get_eval_error(const std::function<void ()> &f
|
||||
|
||||
std::string get_next_command() {
|
||||
std::string retval("quit");
|
||||
if ( ! std::cin.eof() ) {
|
||||
if (!std::cin.eof()) {
|
||||
char *input_raw = readline("eval> ");
|
||||
if ( input_raw != nullptr ) {
|
||||
if (input_raw != nullptr) {
|
||||
add_history(input_raw);
|
||||
|
||||
std::string val(input_raw);
|
||||
size_t pos = val.find_first_not_of("\t \n");
|
||||
if (pos != std::string::npos)
|
||||
{
|
||||
if (pos != std::string::npos) {
|
||||
val.erase(0, pos);
|
||||
}
|
||||
pos = val.find_last_not_of("\t \n");
|
||||
if (pos != std::string::npos)
|
||||
{
|
||||
val.erase(pos+1, std::string::npos);
|
||||
if (pos != std::string::npos) {
|
||||
val.erase(pos + 1, std::string::npos);
|
||||
}
|
||||
|
||||
retval = val;
|
||||
@ -211,11 +191,7 @@ std::string get_next_command() {
|
||||
::free(input_raw);
|
||||
}
|
||||
}
|
||||
if( retval == "quit"
|
||||
|| retval == "exit"
|
||||
|| retval == "help"
|
||||
|| retval == "version")
|
||||
{
|
||||
if (retval == "quit" || retval == "exit" || retval == "help" || retval == "version") {
|
||||
retval += "(0)";
|
||||
}
|
||||
return retval;
|
||||
@ -227,8 +203,7 @@ void myexit(int return_val) {
|
||||
exit(return_val);
|
||||
}
|
||||
|
||||
void interactive(chaiscript::ChaiScript_Basic& chai)
|
||||
{
|
||||
void interactive(chaiscript::ChaiScript_Basic &chai) {
|
||||
using_history();
|
||||
|
||||
for (;;) {
|
||||
@ -237,30 +212,27 @@ void interactive(chaiscript::ChaiScript_Basic& chai)
|
||||
// evaluate input
|
||||
chaiscript::Boxed_Value val = chai.eval(input);
|
||||
|
||||
//Then, we try to print the result of the evaluation to the user
|
||||
// Then, we try to print the result of the evaluation to the user
|
||||
if (!val.get_type_info().bare_equal(chaiscript::user_type<void>())) {
|
||||
try {
|
||||
std::cout << chai.eval<std::function<std::string (const chaiscript::Boxed_Value &bv)> >("to_string")(val) << '\n';
|
||||
std::cout << chai.eval<std::function<std::string(const chaiscript::Boxed_Value &bv)>>("to_string")(val) << '\n';
|
||||
} catch (...) {
|
||||
} // If we can't, do nothing
|
||||
}
|
||||
catch (...) {} //If we can't, do nothing
|
||||
}
|
||||
}
|
||||
catch (const chaiscript::exception::eval_error &ee) {
|
||||
} catch (const chaiscript::exception::eval_error &ee) {
|
||||
std::cout << ee.what();
|
||||
if ( !ee.call_stack.empty() ) {
|
||||
if (!ee.call_stack.empty()) {
|
||||
std::cout << "during evaluation at (" << ee.call_stack[0].start().line << ", " << ee.call_stack[0].start().column << ")";
|
||||
}
|
||||
std::cout << '\n';
|
||||
}
|
||||
catch (const std::exception &e) {
|
||||
} catch (const std::exception &e) {
|
||||
std::cout << e.what();
|
||||
std::cout << '\n';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
double now()
|
||||
{
|
||||
double now() {
|
||||
using namespace std::chrono;
|
||||
auto now = high_resolution_clock::now();
|
||||
return duration_cast<duration<double>>(now.time_since_epoch()).count();
|
||||
@ -269,7 +241,7 @@ double now()
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||
chaiscript::ChaiScript chai;
|
||||
|
||||
chai.eval( R"chaiscript(
|
||||
chai.eval(R"chaiscript(
|
||||
def assert_equal(x, y)
|
||||
{
|
||||
if (x == y)
|
||||
@ -339,7 +311,8 @@ def assert_throws(desc, x)
|
||||
std::ofstream ofs("BOXED_VALUE/" + sha);
|
||||
ofs << input;
|
||||
} catch (const chaiscript::exception::load_module_error &e) {
|
||||
std::cout << "Unhandled module load error\n" << e.what() << '\n';
|
||||
std::cout << "Unhandled module load error\n"
|
||||
<< e.what() << '\n';
|
||||
} catch (const std::exception &) {
|
||||
std::ofstream ofs("STD_EXCEPTION/" + sha);
|
||||
ofs << input;
|
||||
@ -350,5 +323,3 @@ def assert_throws(desc, x)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
203
src/main.cpp
203
src/main.cpp
@ -7,7 +7,6 @@
|
||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include <list>
|
||||
#include <regex>
|
||||
@ -16,48 +15,43 @@
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#endif
|
||||
|
||||
#include <chaiscript/chaiscript_basic.hpp>
|
||||
#include "../static_libs/chaiscript_parser.hpp"
|
||||
#include "../static_libs/chaiscript_stdlib.hpp"
|
||||
|
||||
#include <chaiscript/chaiscript_basic.hpp>
|
||||
|
||||
#ifdef READLINE_AVAILABLE
|
||||
#include <readline/readline.h>
|
||||
#include <readline/history.h>
|
||||
#include <readline/readline.h>
|
||||
#else
|
||||
|
||||
char *mystrdup (const char *s) {
|
||||
char *mystrdup(const char *s) {
|
||||
size_t len = strlen(s); // Space for length plus nul
|
||||
char *d = static_cast<char*>(malloc (len+1));
|
||||
if (d == nullptr) { return nullptr; } // No memory
|
||||
char *d = static_cast<char *>(malloc(len + 1));
|
||||
if (d == nullptr) {
|
||||
return nullptr;
|
||||
} // No memory
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
strcpy_s(d, len+1, s); // Copy the characters
|
||||
strcpy_s(d, len + 1, s); // Copy the characters
|
||||
#else
|
||||
strncpy(d,s,len); // Copy the characters
|
||||
strncpy(d, s, len); // Copy the characters
|
||||
#endif
|
||||
d[len] = '\0';
|
||||
return d; // Return the new string
|
||||
}
|
||||
|
||||
char* readline(const char* p)
|
||||
{
|
||||
char *readline(const char *p) {
|
||||
std::string retval;
|
||||
std::cout << p ;
|
||||
std::cout << p;
|
||||
std::getline(std::cin, retval);
|
||||
return std::cin.eof() ? nullptr : mystrdup(retval.c_str());
|
||||
}
|
||||
|
||||
|
||||
void add_history(const char* /*unused*/){}
|
||||
void using_history(){}
|
||||
void add_history(const char * /*unused*/) {}
|
||||
void using_history() {}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
void *cast_module_symbol(std::vector<std::string> (*t_path)())
|
||||
{
|
||||
union cast_union
|
||||
{
|
||||
void *cast_module_symbol(std::vector<std::string> (*t_path)()) {
|
||||
union cast_union {
|
||||
std::vector<std::string> (*in_ptr)();
|
||||
void *out_ptr;
|
||||
};
|
||||
@ -67,26 +61,23 @@ void *cast_module_symbol(std::vector<std::string> (*t_path)())
|
||||
return c.out_ptr;
|
||||
}
|
||||
|
||||
std::vector<std::string> default_search_paths()
|
||||
{
|
||||
std::vector<std::string> default_search_paths() {
|
||||
std::vector<std::string> paths;
|
||||
|
||||
#ifndef CHAISCRIPT_NO_DYNLOAD
|
||||
#ifdef CHAISCRIPT_WINDOWS // force no unicode
|
||||
CHAR path[4096];
|
||||
int size = GetModuleFileNameA(nullptr, path, sizeof(path)-1);
|
||||
int size = GetModuleFileNameA(nullptr, path, sizeof(path) - 1);
|
||||
|
||||
std::string exepath(path, size);
|
||||
|
||||
size_t lastslash = exepath.rfind('\\');
|
||||
size_t secondtolastslash = exepath.rfind('\\', lastslash - 1);
|
||||
if (lastslash != std::string::npos)
|
||||
{
|
||||
if (lastslash != std::string::npos) {
|
||||
paths.push_back(exepath.substr(0, lastslash));
|
||||
}
|
||||
|
||||
if (secondtolastslash != std::string::npos)
|
||||
{
|
||||
if (secondtolastslash != std::string::npos) {
|
||||
return {exepath.substr(0, secondtolastslash) + "\\lib\\chaiscript\\"};
|
||||
}
|
||||
#else
|
||||
@ -96,32 +87,26 @@ std::vector<std::string> default_search_paths()
|
||||
std::vector<char> buf(2048);
|
||||
ssize_t size = -1;
|
||||
|
||||
if ((size = readlink("/proc/self/exe", &buf.front(), buf.size())) >= 0)
|
||||
{
|
||||
if ((size = readlink("/proc/self/exe", &buf.front(), buf.size())) >= 0) {
|
||||
exepath = std::string(&buf.front(), static_cast<size_t>(size));
|
||||
}
|
||||
|
||||
if (exepath.empty())
|
||||
{
|
||||
if ((size = readlink("/proc/curproc/file", &buf.front(), buf.size())) >= 0)
|
||||
{
|
||||
if (exepath.empty()) {
|
||||
if ((size = readlink("/proc/curproc/file", &buf.front(), buf.size())) >= 0) {
|
||||
exepath = std::string(&buf.front(), static_cast<size_t>(size));
|
||||
}
|
||||
}
|
||||
|
||||
if (exepath.empty())
|
||||
{
|
||||
if ((size = readlink("/proc/self/path/a.out", &buf.front(), buf.size())) >= 0)
|
||||
{
|
||||
if (exepath.empty()) {
|
||||
if ((size = readlink("/proc/self/path/a.out", &buf.front(), buf.size())) >= 0) {
|
||||
exepath = std::string(&buf.front(), static_cast<size_t>(size));
|
||||
}
|
||||
}
|
||||
|
||||
if (exepath.empty())
|
||||
{
|
||||
if (exepath.empty()) {
|
||||
Dl_info rInfo;
|
||||
memset( &rInfo, 0, sizeof(rInfo) );
|
||||
if ( dladdr(cast_module_symbol(&default_search_paths), &rInfo) == 0 || rInfo.dli_fname == nullptr ) {
|
||||
memset(&rInfo, 0, sizeof(rInfo));
|
||||
if (dladdr(cast_module_symbol(&default_search_paths), &rInfo) == 0 || rInfo.dli_fname == nullptr) {
|
||||
return paths;
|
||||
}
|
||||
|
||||
@ -131,13 +116,11 @@ std::vector<std::string> default_search_paths()
|
||||
size_t lastslash = exepath.rfind('/');
|
||||
|
||||
size_t secondtolastslash = exepath.rfind('/', lastslash - 1);
|
||||
if (lastslash != std::string::npos)
|
||||
{
|
||||
paths.push_back(exepath.substr(0, lastslash+1));
|
||||
if (lastslash != std::string::npos) {
|
||||
paths.push_back(exepath.substr(0, lastslash + 1));
|
||||
}
|
||||
|
||||
if (secondtolastslash != std::string::npos)
|
||||
{
|
||||
if (secondtolastslash != std::string::npos) {
|
||||
paths.push_back(exepath.substr(0, secondtolastslash) + "/lib/chaiscript/");
|
||||
}
|
||||
#endif
|
||||
@ -147,7 +130,7 @@ std::vector<std::string> default_search_paths()
|
||||
}
|
||||
|
||||
void help(int n) {
|
||||
if ( n >= 0 ) {
|
||||
if (n >= 0) {
|
||||
std::cout << "ChaiScript evaluator. To evaluate an expression, type it and press <enter>.\n";
|
||||
std::cout << "Additionally, you can inspect the runtime system using:\n";
|
||||
std::cout << " dump_system() - outputs all functions registered to the system\n";
|
||||
@ -164,8 +147,7 @@ void help(int n) {
|
||||
}
|
||||
}
|
||||
|
||||
std::string throws_exception(const std::function<void ()> &f)
|
||||
{
|
||||
std::string throws_exception(const std::function<void()> &f) {
|
||||
try {
|
||||
f();
|
||||
} catch (const std::exception &e) {
|
||||
@ -175,8 +157,7 @@ std::string throws_exception(const std::function<void ()> &f)
|
||||
return "";
|
||||
}
|
||||
|
||||
chaiscript::exception::eval_error get_eval_error(const std::function<void ()> &f)
|
||||
{
|
||||
chaiscript::exception::eval_error get_eval_error(const std::function<void()> &f) {
|
||||
try {
|
||||
f();
|
||||
} catch (const chaiscript::exception::eval_error &e) {
|
||||
@ -188,21 +169,19 @@ chaiscript::exception::eval_error get_eval_error(const std::function<void ()> &f
|
||||
|
||||
std::string get_next_command() {
|
||||
std::string retval("quit");
|
||||
if ( ! std::cin.eof() ) {
|
||||
if (!std::cin.eof()) {
|
||||
char *input_raw = readline("eval> ");
|
||||
if ( input_raw != nullptr ) {
|
||||
if (input_raw != nullptr) {
|
||||
add_history(input_raw);
|
||||
|
||||
std::string val(input_raw);
|
||||
size_t pos = val.find_first_not_of("\t \n");
|
||||
if (pos != std::string::npos)
|
||||
{
|
||||
if (pos != std::string::npos) {
|
||||
val.erase(0, pos);
|
||||
}
|
||||
pos = val.find_last_not_of("\t \n");
|
||||
if (pos != std::string::npos)
|
||||
{
|
||||
val.erase(pos+1, std::string::npos);
|
||||
if (pos != std::string::npos) {
|
||||
val.erase(pos + 1, std::string::npos);
|
||||
}
|
||||
|
||||
retval = val;
|
||||
@ -210,11 +189,7 @@ std::string get_next_command() {
|
||||
::free(input_raw);
|
||||
}
|
||||
}
|
||||
if( retval == "quit"
|
||||
|| retval == "exit"
|
||||
|| retval == "help"
|
||||
|| retval == "version")
|
||||
{
|
||||
if (retval == "quit" || retval == "exit" || retval == "help" || retval == "version") {
|
||||
retval += "(0)";
|
||||
}
|
||||
return retval;
|
||||
@ -226,8 +201,7 @@ void myexit(int return_val) {
|
||||
exit(return_val);
|
||||
}
|
||||
|
||||
void interactive(chaiscript::ChaiScript_Basic& chai)
|
||||
{
|
||||
void interactive(chaiscript::ChaiScript_Basic &chai) {
|
||||
using_history();
|
||||
|
||||
for (;;) {
|
||||
@ -236,39 +210,34 @@ void interactive(chaiscript::ChaiScript_Basic& chai)
|
||||
// evaluate input
|
||||
chaiscript::Boxed_Value val = chai.eval(input);
|
||||
|
||||
//Then, we try to print the result of the evaluation to the user
|
||||
// Then, we try to print the result of the evaluation to the user
|
||||
if (!val.get_type_info().bare_equal(chaiscript::user_type<void>())) {
|
||||
try {
|
||||
std::cout << chai.eval<std::function<std::string (const chaiscript::Boxed_Value &bv)> >("to_string")(val) << '\n';
|
||||
std::cout << chai.eval<std::function<std::string(const chaiscript::Boxed_Value &bv)>>("to_string")(val) << '\n';
|
||||
} catch (...) {
|
||||
} // If we can't, do nothing
|
||||
}
|
||||
catch (...) {} //If we can't, do nothing
|
||||
}
|
||||
}
|
||||
catch (const chaiscript::exception::eval_error &ee) {
|
||||
} catch (const chaiscript::exception::eval_error &ee) {
|
||||
std::cout << ee.what();
|
||||
if ( !ee.call_stack.empty() ) {
|
||||
if (!ee.call_stack.empty()) {
|
||||
std::cout << "during evaluation at (" << ee.call_stack[0].start().line << ", " << ee.call_stack[0].start().column << ")";
|
||||
}
|
||||
std::cout << '\n';
|
||||
}
|
||||
catch (const std::exception &e) {
|
||||
} catch (const std::exception &e) {
|
||||
std::cout << e.what();
|
||||
std::cout << '\n';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
double now()
|
||||
{
|
||||
double now() {
|
||||
using namespace std::chrono;
|
||||
auto now = high_resolution_clock::now();
|
||||
return duration_cast<duration<double>>(now.time_since_epoch()).count();
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
|
||||
// Disable deprecation warning for getenv call.
|
||||
int main(int argc, char *argv[]) {
|
||||
// Disable deprecation warning for getenv call.
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4996)
|
||||
@ -283,8 +252,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
std::vector<std::string> usepaths;
|
||||
usepaths.emplace_back("");
|
||||
if (usepath != nullptr)
|
||||
{
|
||||
if (usepath != nullptr) {
|
||||
usepaths.emplace_back(usepath);
|
||||
}
|
||||
|
||||
@ -292,12 +260,11 @@ int main(int argc, char *argv[])
|
||||
std::vector<std::string> searchpaths = default_search_paths();
|
||||
modulepaths.insert(modulepaths.end(), searchpaths.begin(), searchpaths.end());
|
||||
modulepaths.emplace_back("");
|
||||
if (modulepath != nullptr)
|
||||
{
|
||||
if (modulepath != nullptr) {
|
||||
modulepaths.emplace_back(modulepath);
|
||||
}
|
||||
|
||||
chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser(),modulepaths,usepaths);
|
||||
chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(), create_chaiscript_parser(), modulepaths, usepaths);
|
||||
|
||||
chai.add(chaiscript::fun(&myexit), "exit");
|
||||
chai.add(chaiscript::fun(&myexit), "quit");
|
||||
@ -311,46 +278,48 @@ int main(int argc, char *argv[])
|
||||
bool any_exception_ok = false;
|
||||
|
||||
for (int i = 0; i < argc; ++i) {
|
||||
if ( i == 0 && argc > 1 ) {
|
||||
if (i == 0 && argc > 1) {
|
||||
++i;
|
||||
}
|
||||
|
||||
std::string arg( i != 0 ? argv[i] : "--interactive" );
|
||||
std::string arg(i != 0 ? argv[i] : "--interactive");
|
||||
|
||||
enum { eInteractive
|
||||
, eCommand
|
||||
, eFile
|
||||
} mode = eCommand ;
|
||||
enum {
|
||||
eInteractive,
|
||||
eCommand,
|
||||
eFile
|
||||
} mode
|
||||
= eCommand;
|
||||
|
||||
if ( arg == "-c" || arg == "--command" ) {
|
||||
if ( (i+1) >= argc ) {
|
||||
if (arg == "-c" || arg == "--command") {
|
||||
if ((i + 1) >= argc) {
|
||||
std::cout << "insufficient input following " << arg << '\n';
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
arg = argv[++i];
|
||||
|
||||
} else if ( arg == "-" || arg == "--stdin" ) {
|
||||
arg = "" ;
|
||||
} else if (arg == "-" || arg == "--stdin") {
|
||||
arg = "";
|
||||
std::string line;
|
||||
while ( std::getline(std::cin, line) ) {
|
||||
arg += line + '\n' ;
|
||||
while (std::getline(std::cin, line)) {
|
||||
arg += line + '\n';
|
||||
}
|
||||
} else if ( arg == "-v" || arg == "--version" ) {
|
||||
arg = "print(version())" ;
|
||||
} else if ( arg == "-h" || arg == "--help" ) {
|
||||
} else if (arg == "-v" || arg == "--version") {
|
||||
arg = "print(version())";
|
||||
} else if (arg == "-h" || arg == "--help") {
|
||||
arg = "help(-1)";
|
||||
} else if ( arg == "-e" || arg == "--evalerrorok" ) {
|
||||
} else if (arg == "-e" || arg == "--evalerrorok") {
|
||||
eval_error_ok = true;
|
||||
continue;
|
||||
} else if ( arg == "--exception" ) {
|
||||
} else if (arg == "--exception") {
|
||||
boxed_exception_ok = true;
|
||||
continue;
|
||||
} else if ( arg == "--any-exception" ) {
|
||||
} else if (arg == "--any-exception") {
|
||||
any_exception_ok = true;
|
||||
continue;
|
||||
} else if ( arg == "-i" || arg == "--interactive" ) {
|
||||
mode = eInteractive ;
|
||||
} else if ( arg.find('-') == 0 ) {
|
||||
} else if (arg == "-i" || arg == "--interactive") {
|
||||
mode = eInteractive;
|
||||
} else if (arg.find('-') == 0) {
|
||||
std::cout << "unrecognised argument " << arg << '\n';
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
@ -358,7 +327,7 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
try {
|
||||
switch ( mode ) {
|
||||
switch (mode) {
|
||||
case eInteractive:
|
||||
interactive(chai);
|
||||
break;
|
||||
@ -368,32 +337,28 @@ int main(int argc, char *argv[])
|
||||
case eFile:
|
||||
chai.eval_file(arg);
|
||||
}
|
||||
}
|
||||
catch (const chaiscript::exception::eval_error &ee) {
|
||||
} catch (const chaiscript::exception::eval_error &ee) {
|
||||
std::cout << ee.pretty_print();
|
||||
std::cout << '\n';
|
||||
|
||||
if (!eval_error_ok) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
catch (const chaiscript::Boxed_Value &e) {
|
||||
} catch (const chaiscript::Boxed_Value &e) {
|
||||
std::cout << "Unhandled exception thrown of type " << e.get_type_info().name() << '\n';
|
||||
|
||||
if (!boxed_exception_ok) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
catch (const chaiscript::exception::load_module_error &e) {
|
||||
std::cout << "Unhandled module load error\n" << e.what() << '\n';
|
||||
}
|
||||
catch (std::exception &e) {
|
||||
} catch (const chaiscript::exception::load_module_error &e) {
|
||||
std::cout << "Unhandled module load error\n"
|
||||
<< e.what() << '\n';
|
||||
} catch (std::exception &e) {
|
||||
std::cout << "Unhandled standard exception: " << e.what() << '\n';
|
||||
if (!any_exception_ok) {
|
||||
throw;
|
||||
}
|
||||
}
|
||||
catch (...) {
|
||||
} catch (...) {
|
||||
std::cout << "Unhandled unknown exception" << '\n';
|
||||
if (!any_exception_ok) {
|
||||
throw;
|
||||
|
||||
@ -4,67 +4,52 @@
|
||||
// and Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
|
||||
// NOT TO BE USED AS A SOURCE OF BEST PRACTICES
|
||||
// FOR CHAISCRIPT
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include <ctime>
|
||||
#include <iostream>
|
||||
|
||||
#include <chaiscript/chaiscript.hpp>
|
||||
#include <chaiscript/dispatchkit/bootstrap_stl.hpp>
|
||||
#include <chaiscript/dispatchkit/function_call.hpp>
|
||||
|
||||
void log(const std::string &msg)
|
||||
{
|
||||
void log(const std::string &msg) {
|
||||
std::cout << "[" << time(nullptr) << "] " << msg << '\n';
|
||||
}
|
||||
|
||||
void log(const std::string &module, const std::string &msg)
|
||||
{
|
||||
void log(const std::string &module, const std::string &msg) {
|
||||
std::cout << "[" << time(nullptr) << "] <" << module << "> " << msg << '\n';
|
||||
}
|
||||
|
||||
void bound_log(const std::string &msg)
|
||||
{
|
||||
void bound_log(const std::string &msg) {
|
||||
log(msg);
|
||||
}
|
||||
|
||||
void hello_world(const chaiscript::Boxed_Value & /*o*/)
|
||||
{
|
||||
void hello_world(const chaiscript::Boxed_Value & /*o*/) {
|
||||
std::cout << "Hello World\n";
|
||||
}
|
||||
|
||||
void hello_constructor(const chaiscript::Boxed_Value & /*o*/)
|
||||
{
|
||||
void hello_constructor(const chaiscript::Boxed_Value & /*o*/) {
|
||||
std::cout << "Hello Constructor\n";
|
||||
}
|
||||
|
||||
struct System {
|
||||
std::map<std::string, std::function<std::string(const std::string &)>> m_callbacks;
|
||||
|
||||
struct System
|
||||
{
|
||||
std::map<std::string, std::function<std::string (const std::string &) > > m_callbacks;
|
||||
|
||||
void add_callback(const std::string &t_name,
|
||||
const std::function<std::string (const std::string &)> &t_func)
|
||||
{
|
||||
void add_callback(const std::string &t_name, const std::function<std::string(const std::string &)> &t_func) {
|
||||
m_callbacks[t_name] = t_func;
|
||||
}
|
||||
|
||||
|
||||
void do_callbacks(const std::string &inp)
|
||||
{
|
||||
void do_callbacks(const std::string &inp) {
|
||||
log("Running Callbacks: " + inp);
|
||||
for (auto & m_callback : m_callbacks)
|
||||
{
|
||||
for (auto &m_callback : m_callbacks) {
|
||||
log("Callback: " + m_callback.first, m_callback.second(inp));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void take_shared_ptr(const std::shared_ptr<const std::string> &p)
|
||||
{
|
||||
void take_shared_ptr(const std::shared_ptr<const std::string> &p) {
|
||||
std::cout << *p << '\n';
|
||||
}
|
||||
|
||||
@ -73,15 +58,14 @@ int main(int /*argc*/, char * /*argv*/[]) {
|
||||
|
||||
ChaiScript chai;
|
||||
|
||||
|
||||
//Create a new system object and share it with the chaiscript engine
|
||||
// Create a new system object and share it with the chaiscript engine
|
||||
System system;
|
||||
chai.add_global(var(&system), "system");
|
||||
|
||||
//Add a bound callback method
|
||||
// Add a bound callback method
|
||||
chai.add(fun(&System::add_callback, std::ref(system)), "add_callback_bound");
|
||||
|
||||
//Register the two methods of the System structure.
|
||||
// Register the two methods of the System structure.
|
||||
chai.add(fun(&System::add_callback), "add_callback");
|
||||
chai.add(fun(&System::do_callbacks), "do_callbacks");
|
||||
|
||||
@ -111,29 +95,26 @@ int main(int /*argc*/, char * /*argv*/[]) {
|
||||
// A shortcut to using eval is just to use the chai operator()
|
||||
chai(R"(log("Test Module", "Test Message");)");
|
||||
|
||||
//Finally, it is possible to register a lambda as a system function, in this
|
||||
//way, we can, for instance add a bound member function to the system
|
||||
chai.add(fun([&system](){ return system.do_callbacks("Bound Test"); }), "do_callbacks");
|
||||
// Finally, it is possible to register a lambda as a system function, in this
|
||||
// way, we can, for instance add a bound member function to the system
|
||||
chai.add(fun([&system]() { return system.do_callbacks("Bound Test"); }), "do_callbacks");
|
||||
|
||||
//Call bound version of do_callbacks
|
||||
// Call bound version of do_callbacks
|
||||
chai("do_callbacks()");
|
||||
|
||||
std::function<void ()> caller = chai.eval<std::function<void ()> >(
|
||||
R"(fun() { system.do_callbacks("From Functor"); })"
|
||||
);
|
||||
std::function<void()> caller = chai.eval<std::function<void()>>(R"(fun() { system.do_callbacks("From Functor"); })");
|
||||
caller();
|
||||
|
||||
|
||||
//If we would like a type-safe return value from all call, we can use
|
||||
//the templated version of eval:
|
||||
// If we would like a type-safe return value from all call, we can use
|
||||
// the templated version of eval:
|
||||
int i = chai.eval<int>("5+5");
|
||||
|
||||
std::cout << "5+5: " << i << '\n';
|
||||
|
||||
//Add a new variable
|
||||
// Add a new variable
|
||||
chai("var scripti = 15");
|
||||
|
||||
//We can even get a handle to the variables in the system
|
||||
// We can even get a handle to the variables in the system
|
||||
int &scripti = chai.eval<int &>("scripti");
|
||||
|
||||
std::cout << "scripti: " << scripti << '\n';
|
||||
@ -141,10 +122,10 @@ int main(int /*argc*/, char * /*argv*/[]) {
|
||||
std::cout << "scripti (updated): " << scripti << '\n';
|
||||
chai(R"(print("Scripti from chai: " + to_string(scripti)))");
|
||||
|
||||
//To do: Add examples of handling Boxed_Values directly when needed
|
||||
// To do: Add examples of handling Boxed_Values directly when needed
|
||||
|
||||
//Creating a functor on the stack and using it immediately
|
||||
int x = chai.eval<std::function<int (int, int)> >("fun (x, y) { return x + y; }")(5, 6);
|
||||
// Creating a functor on the stack and using it immediately
|
||||
int x = chai.eval<std::function<int(int, int)>>("fun (x, y) { return x + y; }")(5, 6);
|
||||
|
||||
std::stringstream ss;
|
||||
ss << x;
|
||||
@ -158,25 +139,23 @@ int main(int /*argc*/, char * /*argv*/[]) {
|
||||
chai("def getvar() { return constvar; }");
|
||||
chai("print( getvar() )");
|
||||
|
||||
|
||||
//Ability to create our own container types when needed. std::vector and std::map are
|
||||
//mostly supported currently
|
||||
//chai.add(bootstrap::standard_library::vector_type<std::vector<int> >("IntVector"));
|
||||
|
||||
// Ability to create our own container types when needed. std::vector and std::map are
|
||||
// mostly supported currently
|
||||
// chai.add(bootstrap::standard_library::vector_type<std::vector<int> >("IntVector"));
|
||||
|
||||
// Test ability to register a function that excepts a shared_ptr version of a type
|
||||
chai(R"(take_shared_ptr("Hello World as a shared_ptr");)");
|
||||
|
||||
chai.add(fun(&bound_log, std::string("Msg")), "BoundFun");
|
||||
|
||||
//Dynamic objects test
|
||||
// Dynamic objects test
|
||||
chai.add(chaiscript::Proxy_Function(new dispatch::detail::Dynamic_Object_Function("TestType", fun(&hello_world))), "hello_world");
|
||||
chai.add(chaiscript::Proxy_Function(new dispatch::detail::Dynamic_Object_Constructor("TestType", fun(&hello_constructor))), "TestType");
|
||||
// chai.add(fun(std::function<Boxed_Value (dispatch::Dynamic_Object &)>(std::bind(&dispatch::detail::Dynamic_Object_Attribute::func, "TestType", "attr", std::placeholders::_1))), "attr");
|
||||
// chai.add(fun(std::function<Boxed_Value (dispatch::Dynamic_Object &)>(std::bind(&dispatch::detail::Dynamic_Object_Attribute::func,
|
||||
// "TestType", "attr", std::placeholders::_1))), "attr");
|
||||
|
||||
chai.eval("var x = TestType()");
|
||||
// chai.eval("x.attr = \"hi\"");
|
||||
// chai.eval("print(x.attr)");
|
||||
// chai.eval("x.attr = \"hi\"");
|
||||
// chai.eval("print(x.attr)");
|
||||
chai.eval("x.hello_world()");
|
||||
}
|
||||
|
||||
|
||||
206
src/sha3.cpp
206
src/sha3.cpp
@ -11,19 +11,15 @@
|
||||
#include <endian.h>
|
||||
#endif
|
||||
|
||||
|
||||
/// same as reset()
|
||||
SHA3::SHA3(Bits bits)
|
||||
: m_blockSize(200 - 2 * (bits / 8)),
|
||||
m_bits(bits)
|
||||
{
|
||||
: m_blockSize(200 - 2 * (bits / 8))
|
||||
, m_bits(bits) {
|
||||
reset();
|
||||
}
|
||||
|
||||
|
||||
/// restart
|
||||
void SHA3::reset()
|
||||
{
|
||||
void SHA3::reset() {
|
||||
for (size_t i = 0; i < StateSize; i++)
|
||||
m_hash[i] = 0;
|
||||
|
||||
@ -31,32 +27,19 @@ void SHA3::reset()
|
||||
m_bufferSize = 0;
|
||||
}
|
||||
|
||||
|
||||
/// constants and local helper functions
|
||||
namespace
|
||||
{
|
||||
namespace {
|
||||
const unsigned int Rounds = 24;
|
||||
const uint64_t XorMasks[Rounds] =
|
||||
{
|
||||
0x0000000000000001ULL, 0x0000000000008082ULL, 0x800000000000808aULL,
|
||||
0x8000000080008000ULL, 0x000000000000808bULL, 0x0000000080000001ULL,
|
||||
0x8000000080008081ULL, 0x8000000000008009ULL, 0x000000000000008aULL,
|
||||
0x0000000000000088ULL, 0x0000000080008009ULL, 0x000000008000000aULL,
|
||||
0x000000008000808bULL, 0x800000000000008bULL, 0x8000000000008089ULL,
|
||||
0x8000000000008003ULL, 0x8000000000008002ULL, 0x8000000000000080ULL,
|
||||
0x000000000000800aULL, 0x800000008000000aULL, 0x8000000080008081ULL,
|
||||
0x8000000000008080ULL, 0x0000000080000001ULL, 0x8000000080008008ULL
|
||||
};
|
||||
const uint64_t XorMasks[Rounds]
|
||||
= {0x0000000000000001ULL, 0x0000000000008082ULL, 0x800000000000808aULL, 0x8000000080008000ULL, 0x000000000000808bULL, 0x0000000080000001ULL, 0x8000000080008081ULL, 0x8000000000008009ULL, 0x000000000000008aULL, 0x0000000000000088ULL, 0x0000000080008009ULL, 0x000000008000000aULL, 0x000000008000808bULL, 0x800000000000008bULL, 0x8000000000008089ULL, 0x8000000000008003ULL, 0x8000000000008002ULL, 0x8000000000000080ULL, 0x000000000000800aULL, 0x800000008000000aULL, 0x8000000080008081ULL, 0x8000000000008080ULL, 0x0000000080000001ULL, 0x8000000080008008ULL};
|
||||
|
||||
/// rotate left and wrap around to the right
|
||||
inline uint64_t rotateLeft(uint64_t x, uint8_t numBits)
|
||||
{
|
||||
inline uint64_t rotateLeft(uint64_t x, uint8_t numBits) {
|
||||
return (x << numBits) | (x >> (64 - numBits));
|
||||
}
|
||||
|
||||
/// convert litte vs big endian
|
||||
inline uint64_t swap(uint64_t x)
|
||||
{
|
||||
inline uint64_t swap(uint64_t x) {
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
return __builtin_bswap64(x);
|
||||
#endif
|
||||
@ -64,54 +47,42 @@ namespace
|
||||
return _byteswap_uint64(x);
|
||||
#endif
|
||||
|
||||
return (x >> 56) |
|
||||
((x >> 40) & 0x000000000000FF00ULL) |
|
||||
((x >> 24) & 0x0000000000FF0000ULL) |
|
||||
((x >> 8) & 0x00000000FF000000ULL) |
|
||||
((x << 8) & 0x000000FF00000000ULL) |
|
||||
((x << 24) & 0x0000FF0000000000ULL) |
|
||||
((x << 40) & 0x00FF000000000000ULL) |
|
||||
(x << 56);
|
||||
return (x >> 56) | ((x >> 40) & 0x000000000000FF00ULL) | ((x >> 24) & 0x0000000000FF0000ULL) | ((x >> 8) & 0x00000000FF000000ULL)
|
||||
| ((x << 8) & 0x000000FF00000000ULL) | ((x << 24) & 0x0000FF0000000000ULL) | ((x << 40) & 0x00FF000000000000ULL) | (x << 56);
|
||||
}
|
||||
|
||||
|
||||
/// return x % 5 for 0 <= x <= 9
|
||||
unsigned int mod5(unsigned int x)
|
||||
{
|
||||
unsigned int mod5(unsigned int x) {
|
||||
if (x < 5)
|
||||
return x;
|
||||
|
||||
return x - 5;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
/// process a full block
|
||||
void SHA3::processBlock(const void* data)
|
||||
{
|
||||
void SHA3::processBlock(const void *data) {
|
||||
#if defined(__BYTE_ORDER) && (__BYTE_ORDER != 0) && (__BYTE_ORDER == __BIG_ENDIAN)
|
||||
#define LITTLEENDIAN(x) swap(x)
|
||||
#else
|
||||
#define LITTLEENDIAN(x) (x)
|
||||
#endif
|
||||
|
||||
const uint64_t* data64 = (const uint64_t*) data;
|
||||
const uint64_t *data64 = (const uint64_t *)data;
|
||||
// mix data into state
|
||||
for (unsigned int i = 0; i < m_blockSize / 8; i++)
|
||||
m_hash[i] ^= LITTLEENDIAN(data64[i]);
|
||||
|
||||
// re-compute state
|
||||
for (unsigned int round = 0; round < Rounds; round++)
|
||||
{
|
||||
for (unsigned int round = 0; round < Rounds; round++) {
|
||||
// Theta
|
||||
uint64_t coefficients[5];
|
||||
for (unsigned int i = 0; i < 5; i++)
|
||||
coefficients[i] = m_hash[i] ^ m_hash[i + 5] ^ m_hash[i + 10] ^ m_hash[i + 15] ^ m_hash[i + 20];
|
||||
|
||||
for (unsigned int i = 0; i < 5; i++)
|
||||
{
|
||||
for (unsigned int i = 0; i < 5; i++) {
|
||||
uint64_t one = coefficients[mod5(i + 4)] ^ rotateLeft(coefficients[mod5(i + 1)], 1);
|
||||
m_hash[i ] ^= one;
|
||||
m_hash[i] ^= one;
|
||||
m_hash[i + 5] ^= one;
|
||||
m_hash[i + 10] ^= one;
|
||||
m_hash[i + 15] ^= one;
|
||||
@ -123,34 +94,79 @@ void SHA3::processBlock(const void* data)
|
||||
|
||||
// Rho Pi
|
||||
uint64_t last = m_hash[1];
|
||||
one = m_hash[10]; m_hash[10] = rotateLeft(last, 1); last = one;
|
||||
one = m_hash[ 7]; m_hash[ 7] = rotateLeft(last, 3); last = one;
|
||||
one = m_hash[11]; m_hash[11] = rotateLeft(last, 6); last = one;
|
||||
one = m_hash[17]; m_hash[17] = rotateLeft(last, 10); last = one;
|
||||
one = m_hash[18]; m_hash[18] = rotateLeft(last, 15); last = one;
|
||||
one = m_hash[ 3]; m_hash[ 3] = rotateLeft(last, 21); last = one;
|
||||
one = m_hash[ 5]; m_hash[ 5] = rotateLeft(last, 28); last = one;
|
||||
one = m_hash[16]; m_hash[16] = rotateLeft(last, 36); last = one;
|
||||
one = m_hash[ 8]; m_hash[ 8] = rotateLeft(last, 45); last = one;
|
||||
one = m_hash[21]; m_hash[21] = rotateLeft(last, 55); last = one;
|
||||
one = m_hash[24]; m_hash[24] = rotateLeft(last, 2); last = one;
|
||||
one = m_hash[ 4]; m_hash[ 4] = rotateLeft(last, 14); last = one;
|
||||
one = m_hash[15]; m_hash[15] = rotateLeft(last, 27); last = one;
|
||||
one = m_hash[23]; m_hash[23] = rotateLeft(last, 41); last = one;
|
||||
one = m_hash[19]; m_hash[19] = rotateLeft(last, 56); last = one;
|
||||
one = m_hash[13]; m_hash[13] = rotateLeft(last, 8); last = one;
|
||||
one = m_hash[12]; m_hash[12] = rotateLeft(last, 25); last = one;
|
||||
one = m_hash[ 2]; m_hash[ 2] = rotateLeft(last, 43); last = one;
|
||||
one = m_hash[20]; m_hash[20] = rotateLeft(last, 62); last = one;
|
||||
one = m_hash[14]; m_hash[14] = rotateLeft(last, 18); last = one;
|
||||
one = m_hash[22]; m_hash[22] = rotateLeft(last, 39); last = one;
|
||||
one = m_hash[ 9]; m_hash[ 9] = rotateLeft(last, 61); last = one;
|
||||
one = m_hash[ 6]; m_hash[ 6] = rotateLeft(last, 20); last = one;
|
||||
m_hash[ 1] = rotateLeft(last, 44);
|
||||
one = m_hash[10];
|
||||
m_hash[10] = rotateLeft(last, 1);
|
||||
last = one;
|
||||
one = m_hash[7];
|
||||
m_hash[7] = rotateLeft(last, 3);
|
||||
last = one;
|
||||
one = m_hash[11];
|
||||
m_hash[11] = rotateLeft(last, 6);
|
||||
last = one;
|
||||
one = m_hash[17];
|
||||
m_hash[17] = rotateLeft(last, 10);
|
||||
last = one;
|
||||
one = m_hash[18];
|
||||
m_hash[18] = rotateLeft(last, 15);
|
||||
last = one;
|
||||
one = m_hash[3];
|
||||
m_hash[3] = rotateLeft(last, 21);
|
||||
last = one;
|
||||
one = m_hash[5];
|
||||
m_hash[5] = rotateLeft(last, 28);
|
||||
last = one;
|
||||
one = m_hash[16];
|
||||
m_hash[16] = rotateLeft(last, 36);
|
||||
last = one;
|
||||
one = m_hash[8];
|
||||
m_hash[8] = rotateLeft(last, 45);
|
||||
last = one;
|
||||
one = m_hash[21];
|
||||
m_hash[21] = rotateLeft(last, 55);
|
||||
last = one;
|
||||
one = m_hash[24];
|
||||
m_hash[24] = rotateLeft(last, 2);
|
||||
last = one;
|
||||
one = m_hash[4];
|
||||
m_hash[4] = rotateLeft(last, 14);
|
||||
last = one;
|
||||
one = m_hash[15];
|
||||
m_hash[15] = rotateLeft(last, 27);
|
||||
last = one;
|
||||
one = m_hash[23];
|
||||
m_hash[23] = rotateLeft(last, 41);
|
||||
last = one;
|
||||
one = m_hash[19];
|
||||
m_hash[19] = rotateLeft(last, 56);
|
||||
last = one;
|
||||
one = m_hash[13];
|
||||
m_hash[13] = rotateLeft(last, 8);
|
||||
last = one;
|
||||
one = m_hash[12];
|
||||
m_hash[12] = rotateLeft(last, 25);
|
||||
last = one;
|
||||
one = m_hash[2];
|
||||
m_hash[2] = rotateLeft(last, 43);
|
||||
last = one;
|
||||
one = m_hash[20];
|
||||
m_hash[20] = rotateLeft(last, 62);
|
||||
last = one;
|
||||
one = m_hash[14];
|
||||
m_hash[14] = rotateLeft(last, 18);
|
||||
last = one;
|
||||
one = m_hash[22];
|
||||
m_hash[22] = rotateLeft(last, 39);
|
||||
last = one;
|
||||
one = m_hash[9];
|
||||
m_hash[9] = rotateLeft(last, 61);
|
||||
last = one;
|
||||
one = m_hash[6];
|
||||
m_hash[6] = rotateLeft(last, 20);
|
||||
last = one;
|
||||
m_hash[1] = rotateLeft(last, 44);
|
||||
|
||||
// Chi
|
||||
for (unsigned int j = 0; j < 25; j += 5)
|
||||
{
|
||||
for (unsigned int j = 0; j < 25; j += 5) {
|
||||
// temporaries
|
||||
uint64_t one = m_hash[j];
|
||||
uint64_t two = m_hash[j + 1];
|
||||
@ -167,26 +183,21 @@ void SHA3::processBlock(const void* data)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// add arbitrary number of bytes
|
||||
void SHA3::add(const void* data, size_t numBytes)
|
||||
{
|
||||
const uint8_t* current = (const uint8_t*) data;
|
||||
void SHA3::add(const void *data, size_t numBytes) {
|
||||
const uint8_t *current = (const uint8_t *)data;
|
||||
|
||||
// copy data to buffer
|
||||
if (m_bufferSize > 0)
|
||||
{
|
||||
while (numBytes > 0 && m_bufferSize < m_blockSize)
|
||||
{
|
||||
if (m_bufferSize > 0) {
|
||||
while (numBytes > 0 && m_bufferSize < m_blockSize) {
|
||||
m_buffer[m_bufferSize++] = *current++;
|
||||
numBytes--;
|
||||
}
|
||||
}
|
||||
|
||||
// full buffer
|
||||
if (m_bufferSize == m_blockSize)
|
||||
{
|
||||
processBlock((void*)m_buffer);
|
||||
if (m_bufferSize == m_blockSize) {
|
||||
processBlock((void *)m_buffer);
|
||||
m_numBytes += m_blockSize;
|
||||
m_bufferSize = 0;
|
||||
}
|
||||
@ -196,8 +207,7 @@ void SHA3::add(const void* data, size_t numBytes)
|
||||
return;
|
||||
|
||||
// process full blocks
|
||||
while (numBytes >= m_blockSize)
|
||||
{
|
||||
while (numBytes >= m_blockSize) {
|
||||
processBlock(current);
|
||||
current += m_blockSize;
|
||||
m_numBytes += m_blockSize;
|
||||
@ -205,17 +215,14 @@ void SHA3::add(const void* data, size_t numBytes)
|
||||
}
|
||||
|
||||
// keep remaining bytes in buffer
|
||||
while (numBytes > 0)
|
||||
{
|
||||
while (numBytes > 0) {
|
||||
m_buffer[m_bufferSize++] = *current++;
|
||||
numBytes--;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// process everything left in the internal buffer
|
||||
void SHA3::processBuffer()
|
||||
{
|
||||
void SHA3::processBuffer() {
|
||||
// add padding
|
||||
size_t offset = m_bufferSize;
|
||||
// add a "1" byte
|
||||
@ -230,10 +237,8 @@ void SHA3::processBuffer()
|
||||
processBlock(m_buffer);
|
||||
}
|
||||
|
||||
|
||||
/// return latest hash as 16 hex characters
|
||||
std::string SHA3::getHash()
|
||||
{
|
||||
std::string SHA3::getHash() {
|
||||
// process remaining bytes
|
||||
processBuffer();
|
||||
|
||||
@ -249,7 +254,7 @@ std::string SHA3::getHash()
|
||||
for (unsigned int j = 0; j < 8; j++) // 64 bits => 8 bytes
|
||||
{
|
||||
// convert a byte to hex
|
||||
unsigned char oneByte = (unsigned char) (m_hash[i] >> (8 * j));
|
||||
unsigned char oneByte = (unsigned char)(m_hash[i] >> (8 * j));
|
||||
result += dec2hex[oneByte >> 4];
|
||||
result += dec2hex[oneByte & 15];
|
||||
}
|
||||
@ -257,10 +262,9 @@ std::string SHA3::getHash()
|
||||
// SHA3-224's last entry in m_hash provides only 32 bits instead of 64 bits
|
||||
unsigned int remainder = m_bits - hashLength * 64;
|
||||
unsigned int processed = 0;
|
||||
while (processed < remainder)
|
||||
{
|
||||
while (processed < remainder) {
|
||||
// convert a byte to hex
|
||||
unsigned char oneByte = (unsigned char) (m_hash[hashLength] >> processed);
|
||||
unsigned char oneByte = (unsigned char)(m_hash[hashLength] >> processed);
|
||||
result += dec2hex[oneByte >> 4];
|
||||
result += dec2hex[oneByte & 15];
|
||||
|
||||
@ -270,19 +274,15 @@ std::string SHA3::getHash()
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/// compute SHA3 of a memory block
|
||||
std::string SHA3::operator()(const void* data, size_t numBytes)
|
||||
{
|
||||
std::string SHA3::operator()(const void *data, size_t numBytes) {
|
||||
reset();
|
||||
add(data, numBytes);
|
||||
return getHash();
|
||||
}
|
||||
|
||||
|
||||
/// compute SHA3 of a string, excluding final zero
|
||||
std::string SHA3::operator()(const std::string& text)
|
||||
{
|
||||
std::string SHA3::operator()(const std::string &text) {
|
||||
reset();
|
||||
add(text.c_str(), text.size());
|
||||
return getHash();
|
||||
|
||||
@ -7,7 +7,6 @@
|
||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||
|
||||
|
||||
#include <chaiscript/chaiscript_basic.hpp>
|
||||
#include <chaiscript/dispatchkit/bootstrap_stl.hpp>
|
||||
#include <list>
|
||||
@ -25,11 +24,10 @@
|
||||
#pragma clang diagnostic ignored "-Wreturn-type-c-linkage"
|
||||
#endif
|
||||
|
||||
CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_stl_extra()
|
||||
{
|
||||
CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_stl_extra() {
|
||||
auto module = std::make_shared<chaiscript::Module>();
|
||||
chaiscript::bootstrap::standard_library::list_type<std::list<chaiscript::Boxed_Value> >("List", *module);
|
||||
chaiscript::bootstrap::standard_library::vector_type<std::vector<uint16_t> >("u16vector", *module);
|
||||
chaiscript::bootstrap::standard_library::list_type<std::list<chaiscript::Boxed_Value>>("List", *module);
|
||||
chaiscript::bootstrap::standard_library::vector_type<std::vector<uint16_t>>("u16vector", *module);
|
||||
module->add(chaiscript::vector_conversion<std::vector<uint16_t>>());
|
||||
return module;
|
||||
}
|
||||
|
||||
@ -3,28 +3,38 @@
|
||||
#include <chaiscript/dispatchkit/bootstrap.hpp>
|
||||
#include <string>
|
||||
|
||||
|
||||
|
||||
class TestBaseType
|
||||
{
|
||||
public:
|
||||
TestBaseType() : val(10), const_val(15), mdarray{} { }
|
||||
TestBaseType(int) : val(10), const_val(15), mdarray{} { }
|
||||
TestBaseType(int *) : val(10), const_val(15), mdarray{} { }
|
||||
class TestBaseType {
|
||||
public:
|
||||
TestBaseType()
|
||||
: val(10)
|
||||
, const_val(15)
|
||||
, mdarray{} {
|
||||
}
|
||||
TestBaseType(int)
|
||||
: val(10)
|
||||
, const_val(15)
|
||||
, mdarray{} {
|
||||
}
|
||||
TestBaseType(int *)
|
||||
: val(10)
|
||||
, const_val(15)
|
||||
, mdarray{} {
|
||||
}
|
||||
|
||||
TestBaseType(const TestBaseType &other)
|
||||
: val(other.val), const_val(other.const_val), const_val_ptr(&const_val),
|
||||
func_member(other.func_member)
|
||||
{
|
||||
: val(other.val)
|
||||
, const_val(other.const_val)
|
||||
, const_val_ptr(&const_val)
|
||||
, func_member(other.func_member) {
|
||||
}
|
||||
|
||||
TestBaseType(TestBaseType &&other)
|
||||
: val(other.val), const_val(other.const_val), const_val_ptr(&const_val),
|
||||
func_member(std::move(other.func_member))
|
||||
{
|
||||
: val(other.val)
|
||||
, const_val(other.const_val)
|
||||
, const_val_ptr(&const_val)
|
||||
, func_member(std::move(other.func_member)) {
|
||||
}
|
||||
|
||||
|
||||
TestBaseType &operator=(TestBaseType &&) = delete;
|
||||
TestBaseType &operator=(const TestBaseType &) = delete;
|
||||
|
||||
@ -39,102 +49,75 @@ class TestBaseType
|
||||
const int const_val;
|
||||
const int *const_val_ptr = &const_val;
|
||||
|
||||
const int *get_const_val_ptr() {
|
||||
return const_val_ptr;
|
||||
}
|
||||
const int *get_const_val_ptr() { return const_val_ptr; }
|
||||
|
||||
int mdarray[2][3][5];
|
||||
std::function<int (int)> func_member;
|
||||
|
||||
void set_string_val(std::string &t_str)
|
||||
{
|
||||
t_str = "42";
|
||||
}
|
||||
std::function<int(int)> func_member;
|
||||
|
||||
void set_string_val(std::string &t_str) { t_str = "42"; }
|
||||
};
|
||||
|
||||
class Type2
|
||||
{
|
||||
public:
|
||||
class Type2 {
|
||||
public:
|
||||
Type2(TestBaseType t_bt)
|
||||
: m_bt(std::move(t_bt)),
|
||||
m_str("Hello World")
|
||||
{
|
||||
: m_bt(std::move(t_bt))
|
||||
, m_str("Hello World") {
|
||||
}
|
||||
|
||||
int get_val() const
|
||||
{
|
||||
return m_bt.val;
|
||||
}
|
||||
int get_val() const { return m_bt.val; }
|
||||
|
||||
const char *get_str() const { return m_str.c_str(); }
|
||||
|
||||
const char *get_str() const
|
||||
{
|
||||
return m_str.c_str();
|
||||
}
|
||||
|
||||
private:
|
||||
private:
|
||||
TestBaseType m_bt;
|
||||
std::string m_str;
|
||||
};
|
||||
|
||||
enum TestEnum
|
||||
{
|
||||
enum TestEnum {
|
||||
TestValue1 = 1
|
||||
};
|
||||
|
||||
int to_int(TestEnum t)
|
||||
{
|
||||
int to_int(TestEnum t) {
|
||||
return t;
|
||||
}
|
||||
|
||||
class TestDerivedType : public TestBaseType
|
||||
{
|
||||
public:
|
||||
class TestDerivedType : public TestBaseType {
|
||||
public:
|
||||
int func() override { return 1; }
|
||||
int derived_only_func() { return 19; }
|
||||
|
||||
};
|
||||
|
||||
class TestMoreDerivedType : public TestDerivedType
|
||||
{
|
||||
public:
|
||||
class TestMoreDerivedType : public TestDerivedType {
|
||||
public:
|
||||
};
|
||||
|
||||
std::shared_ptr<TestBaseType> derived_type_factory()
|
||||
{
|
||||
std::shared_ptr<TestBaseType> derived_type_factory() {
|
||||
return std::make_shared<TestDerivedType>();
|
||||
}
|
||||
|
||||
std::shared_ptr<TestBaseType> more_derived_type_factory()
|
||||
{
|
||||
std::shared_ptr<TestBaseType> more_derived_type_factory() {
|
||||
return std::make_shared<TestMoreDerivedType>();
|
||||
}
|
||||
|
||||
std::shared_ptr<TestBaseType> null_factory()
|
||||
{
|
||||
std::shared_ptr<TestBaseType> null_factory() {
|
||||
return std::shared_ptr<TestBaseType>();
|
||||
}
|
||||
|
||||
void update_shared_ptr(std::shared_ptr<TestBaseType> &ptr)
|
||||
{
|
||||
void update_shared_ptr(std::shared_ptr<TestBaseType> &ptr) {
|
||||
ptr = std::make_shared<TestDerivedType>();
|
||||
}
|
||||
|
||||
void nullify_shared_ptr(std::shared_ptr<TestBaseType> &ptr)
|
||||
{
|
||||
void nullify_shared_ptr(std::shared_ptr<TestBaseType> &ptr) {
|
||||
ptr = nullptr;
|
||||
}
|
||||
|
||||
std::string hello_world()
|
||||
{
|
||||
std::string hello_world() {
|
||||
return "Hello World";
|
||||
}
|
||||
|
||||
static int global_i = 1;
|
||||
|
||||
int *get_new_int()
|
||||
{
|
||||
int *get_new_int() {
|
||||
return &global_i;
|
||||
}
|
||||
|
||||
@ -150,8 +133,7 @@ int *get_new_int()
|
||||
#pragma clang diagnostic ignored "-Wreturn-type-c-linkage"
|
||||
#endif
|
||||
|
||||
CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_test_module()
|
||||
{
|
||||
CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_test_module() {
|
||||
chaiscript::ModulePtr m(new chaiscript::Module());
|
||||
|
||||
m->add(chaiscript::fun(hello_world), "hello_world");
|
||||
@ -161,16 +143,16 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_test_mo
|
||||
m->add(chaiscript::user_type<TestMoreDerivedType>(), "TestMoreDerivedType");
|
||||
m->add(chaiscript::user_type<Type2>(), "Type2");
|
||||
|
||||
m->add(chaiscript::constructor<TestBaseType ()>(), "TestBaseType");
|
||||
// m->add(chaiscript::constructor<TestBaseType (int)>(), "TestBaseType");
|
||||
m->add(chaiscript::constructor<TestBaseType (const TestBaseType &)>(), "TestBaseType");
|
||||
m->add(chaiscript::constructor<TestBaseType (int *)>(), "TestBaseType");
|
||||
m->add(chaiscript::constructor<TestBaseType()>(), "TestBaseType");
|
||||
// m->add(chaiscript::constructor<TestBaseType (int)>(), "TestBaseType");
|
||||
m->add(chaiscript::constructor<TestBaseType(const TestBaseType &)>(), "TestBaseType");
|
||||
m->add(chaiscript::constructor<TestBaseType(int *)>(), "TestBaseType");
|
||||
|
||||
m->add(chaiscript::constructor<TestDerivedType ()>(), "TestDerivedType");
|
||||
m->add(chaiscript::constructor<TestDerivedType (const TestDerivedType &)>(), "TestDerivedType");
|
||||
m->add(chaiscript::constructor<TestDerivedType()>(), "TestDerivedType");
|
||||
m->add(chaiscript::constructor<TestDerivedType(const TestDerivedType &)>(), "TestDerivedType");
|
||||
|
||||
m->add(chaiscript::constructor<TestMoreDerivedType ()>(), "TestMoreDerivedType");
|
||||
m->add(chaiscript::constructor<TestMoreDerivedType (const TestMoreDerivedType &)>(), "TestMoreDerivedType");
|
||||
m->add(chaiscript::constructor<TestMoreDerivedType()>(), "TestMoreDerivedType");
|
||||
m->add(chaiscript::constructor<TestMoreDerivedType(const TestMoreDerivedType &)>(), "TestMoreDerivedType");
|
||||
|
||||
/// \todo automatic chaining of base classes?
|
||||
m->add(chaiscript::base_class<TestBaseType, TestDerivedType>());
|
||||
@ -202,7 +184,6 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_test_mo
|
||||
m->add(chaiscript::fun(&TestBaseType::func_member), "func_member");
|
||||
m->add(chaiscript::fun(&get_new_int), "get_new_int");
|
||||
|
||||
|
||||
m->add_global_const(chaiscript::const_var(TestValue1), "TestValue1");
|
||||
|
||||
m->add(chaiscript::user_type<TestEnum>(), "TestEnum");
|
||||
@ -215,16 +196,14 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_test_mo
|
||||
m->add(chaiscript::fun(&Type2::get_val), "get_val");
|
||||
m->add(chaiscript::fun(&Type2::get_str), "get_str");
|
||||
m->add(chaiscript::type_conversion<const char *, std::string>());
|
||||
m->add(chaiscript::constructor<Type2 (const TestBaseType &)>(), "Type2");
|
||||
m->add(chaiscript::constructor<Type2(const TestBaseType &)>(), "Type2");
|
||||
|
||||
m->add(chaiscript::fun(&update_shared_ptr), "update_shared_ptr");
|
||||
m->add(chaiscript::fun(&nullify_shared_ptr), "nullify_shared_ptr");
|
||||
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
#ifdef __llvm__
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
@ -1,8 +1,6 @@
|
||||
#include "../include/chaiscript/language/chaiscript_parser.hpp"
|
||||
#include "chaiscript_parser.hpp"
|
||||
|
||||
std::unique_ptr<chaiscript::parser::ChaiScript_Parser_Base> create_chaiscript_parser()
|
||||
{
|
||||
std::unique_ptr<chaiscript::parser::ChaiScript_Parser_Base> create_chaiscript_parser() {
|
||||
return std::make_unique<chaiscript::parser::ChaiScript_Parser<chaiscript::eval::Noop_Tracer, chaiscript::optimizer::Optimizer_Default>>();
|
||||
}
|
||||
|
||||
|
||||
@ -2,11 +2,13 @@
|
||||
#ifndef CHAISCRIPT_PARSER_LIB
|
||||
#define CHAISCRIPT_PARSER_LIB
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace chaiscript {
|
||||
namespace parser {
|
||||
class ChaiScript_Parser_Base;
|
||||
}
|
||||
}
|
||||
} // namespace chaiscript
|
||||
|
||||
std::unique_ptr<chaiscript::parser::ChaiScript_Parser_Base> create_chaiscript_parser();
|
||||
|
||||
|
||||
@ -1,8 +1,6 @@
|
||||
#include "../include/chaiscript/chaiscript_stdlib.hpp"
|
||||
#include "chaiscript_stdlib.hpp"
|
||||
|
||||
std::shared_ptr<chaiscript::Module> create_chaiscript_stdlib()
|
||||
{
|
||||
std::shared_ptr<chaiscript::Module> create_chaiscript_stdlib() {
|
||||
return chaiscript::Std_Lib::library();
|
||||
}
|
||||
|
||||
|
||||
@ -1,15 +1,13 @@
|
||||
#include <chaiscript/utility/utility.hpp>
|
||||
|
||||
|
||||
using namespace chaiscript;
|
||||
|
||||
|
||||
template<typename T>
|
||||
void use(T){}
|
||||
void use(T) {
|
||||
}
|
||||
|
||||
template<typename To>
|
||||
bool run_test_type_conversion(const Boxed_Value &bv, bool expectedpass)
|
||||
{
|
||||
bool run_test_type_conversion(const Boxed_Value &bv, bool expectedpass) {
|
||||
try {
|
||||
To ret = chaiscript::boxed_cast<To>(bv);
|
||||
use(ret);
|
||||
@ -31,17 +29,14 @@ bool run_test_type_conversion(const Boxed_Value &bv, bool expectedpass)
|
||||
}
|
||||
|
||||
template<typename To>
|
||||
bool test_type_conversion(const Boxed_Value &bv, bool expectedpass)
|
||||
{
|
||||
bool test_type_conversion(const Boxed_Value &bv, bool expectedpass) {
|
||||
bool ret = run_test_type_conversion<To>(bv, expectedpass);
|
||||
|
||||
if (!ret)
|
||||
{
|
||||
std::cerr << "Error with type conversion test. From: "
|
||||
<< (bv.is_const()?(std::string("const ")):(std::string())) << bv.get_type_info().name()
|
||||
<< " To: "
|
||||
<< (std::is_const<To>::value?(std::string("const ")):(std::string())) << typeid(To).name()
|
||||
<< " test was expected to " << ((expectedpass)?(std::string("succeed")):(std::string("fail"))) << " but did not\n";
|
||||
if (!ret) {
|
||||
std::cerr << "Error with type conversion test. From: " << (bv.is_const() ? "const " : "")
|
||||
<< bv.get_type_info().name() << " To: " << (std::is_const<To>::value ? "const " : "")
|
||||
<< typeid(To).name() << " test was expected to " << (expectedpass ? "succeed" : "fail")
|
||||
<< " but did not\n";
|
||||
}
|
||||
|
||||
return ret;
|
||||
@ -49,13 +44,32 @@ bool test_type_conversion(const Boxed_Value &bv, bool expectedpass)
|
||||
|
||||
template<typename Type>
|
||||
bool do_test(const Boxed_Value &bv,
|
||||
bool T, bool ConstT, bool TRef, bool ConstTRef, bool TPtr,
|
||||
bool ConstTPtr, bool TPtrConst, bool ConstTPtrConst, bool SharedPtrT, bool SharedConstPtrT,
|
||||
bool SharedPtrTRef, bool ConstSharedPtrT, bool ConstSharedConstPtrT, bool ConstSharedPtrTRef, bool ConstSharedPtrTConstRef,
|
||||
bool WrappedRef, bool WrappedConstRef, bool ConstWrappedRef, bool ConstWrappedConstRef, bool ConstWrappedRefRef,
|
||||
bool ConstWrappedConstRefRef, bool Number, bool ConstNumber, bool ConstNumberRef, bool TPtrConstRef,
|
||||
bool ConstTPtrConstRef)
|
||||
{
|
||||
bool T,
|
||||
bool ConstT,
|
||||
bool TRef,
|
||||
bool ConstTRef,
|
||||
bool TPtr,
|
||||
bool ConstTPtr,
|
||||
bool TPtrConst,
|
||||
bool ConstTPtrConst,
|
||||
bool SharedPtrT,
|
||||
bool SharedConstPtrT,
|
||||
bool SharedPtrTRef,
|
||||
bool ConstSharedPtrT,
|
||||
bool ConstSharedConstPtrT,
|
||||
bool ConstSharedPtrTRef,
|
||||
bool ConstSharedPtrTConstRef,
|
||||
bool WrappedRef,
|
||||
bool WrappedConstRef,
|
||||
bool ConstWrappedRef,
|
||||
bool ConstWrappedConstRef,
|
||||
bool ConstWrappedRefRef,
|
||||
bool ConstWrappedConstRefRef,
|
||||
bool Number,
|
||||
bool ConstNumber,
|
||||
bool ConstNumberRef,
|
||||
bool TPtrConstRef,
|
||||
bool ConstTPtrConstRef) {
|
||||
bool passed = true;
|
||||
passed &= test_type_conversion<Type>(bv, T);
|
||||
passed &= test_type_conversion<const Type>(bv, ConstT);
|
||||
@ -63,22 +77,22 @@ bool do_test(const Boxed_Value &bv,
|
||||
passed &= test_type_conversion<const Type &>(bv, ConstTRef);
|
||||
passed &= test_type_conversion<Type *>(bv, TPtr);
|
||||
passed &= test_type_conversion<const Type *>(bv, ConstTPtr);
|
||||
passed &= test_type_conversion<Type * const>(bv, TPtrConst);
|
||||
passed &= test_type_conversion<const Type * const>(bv, ConstTPtrConst);
|
||||
passed &= test_type_conversion<std::shared_ptr<Type> >(bv, SharedPtrT);
|
||||
passed &= test_type_conversion<std::shared_ptr<const Type> >(bv, SharedConstPtrT);
|
||||
passed &= test_type_conversion<Type *const>(bv, TPtrConst);
|
||||
passed &= test_type_conversion<const Type *const>(bv, ConstTPtrConst);
|
||||
passed &= test_type_conversion<std::shared_ptr<Type>>(bv, SharedPtrT);
|
||||
passed &= test_type_conversion<std::shared_ptr<const Type>>(bv, SharedConstPtrT);
|
||||
passed &= test_type_conversion<std::shared_ptr<Type> &>(bv, SharedPtrTRef);
|
||||
//passed &= test_type_conversion<std::shared_ptr<const Type> &>(bv, false);
|
||||
passed &= test_type_conversion<const std::shared_ptr<Type> >(bv, ConstSharedPtrT);
|
||||
passed &= test_type_conversion<const std::shared_ptr<const Type> >(bv, ConstSharedConstPtrT);
|
||||
// passed &= test_type_conversion<std::shared_ptr<const Type> &>(bv, false);
|
||||
passed &= test_type_conversion<const std::shared_ptr<Type>>(bv, ConstSharedPtrT);
|
||||
passed &= test_type_conversion<const std::shared_ptr<const Type>>(bv, ConstSharedConstPtrT);
|
||||
passed &= test_type_conversion<const std::shared_ptr<Type> &>(bv, ConstSharedPtrTRef);
|
||||
passed &= test_type_conversion<const std::shared_ptr<const Type> &>(bv, ConstSharedPtrTConstRef);
|
||||
passed &= test_type_conversion<std::reference_wrapper<Type> >(bv, WrappedRef);
|
||||
passed &= test_type_conversion<std::reference_wrapper<const Type> >(bv, WrappedConstRef);
|
||||
passed &= test_type_conversion<std::reference_wrapper<Type>>(bv, WrappedRef);
|
||||
passed &= test_type_conversion<std::reference_wrapper<const Type>>(bv, WrappedConstRef);
|
||||
passed &= test_type_conversion<std::reference_wrapper<Type> &>(bv, false);
|
||||
passed &= test_type_conversion<std::reference_wrapper<const Type> &>(bv, false);
|
||||
passed &= test_type_conversion<const std::reference_wrapper<Type> >(bv, ConstWrappedRef);
|
||||
passed &= test_type_conversion<const std::reference_wrapper<const Type> >(bv, ConstWrappedConstRef);
|
||||
passed &= test_type_conversion<const std::reference_wrapper<Type>>(bv, ConstWrappedRef);
|
||||
passed &= test_type_conversion<const std::reference_wrapper<const Type>>(bv, ConstWrappedConstRef);
|
||||
passed &= test_type_conversion<const std::reference_wrapper<Type> &>(bv, ConstWrappedRefRef);
|
||||
passed &= test_type_conversion<const std::reference_wrapper<const Type> &>(bv, ConstWrappedConstRefRef);
|
||||
passed &= test_type_conversion<Boxed_Number>(bv, Number);
|
||||
@ -87,12 +101,12 @@ bool do_test(const Boxed_Value &bv,
|
||||
passed &= test_type_conversion<const Boxed_Number &>(bv, ConstNumberRef);
|
||||
passed &= test_type_conversion<Boxed_Number *>(bv, false);
|
||||
passed &= test_type_conversion<const Boxed_Number *>(bv, false);
|
||||
passed &= test_type_conversion<Boxed_Number * const>(bv, false);
|
||||
passed &= test_type_conversion<Boxed_Number *const>(bv, false);
|
||||
passed &= test_type_conversion<const Boxed_Number *const>(bv, false);
|
||||
passed &= test_type_conversion<Type *&>(bv, false);
|
||||
passed &= test_type_conversion<const Type *&>(bv, false);
|
||||
passed &= test_type_conversion<Type * const&>(bv, TPtrConstRef);
|
||||
passed &= test_type_conversion<const Type * const&>(bv, ConstTPtrConstRef);
|
||||
passed &= test_type_conversion<Type *const &>(bv, TPtrConstRef);
|
||||
passed &= test_type_conversion<const Type *const &>(bv, ConstTPtrConstRef);
|
||||
passed &= test_type_conversion<Boxed_Value>(bv, true);
|
||||
passed &= test_type_conversion<const Boxed_Value>(bv, true);
|
||||
passed &= test_type_conversion<const Boxed_Value &>(bv, true);
|
||||
@ -102,134 +116,506 @@ bool do_test(const Boxed_Value &bv,
|
||||
|
||||
/** Tests intended for built int types **/
|
||||
template<typename T>
|
||||
bool built_in_type_test(const T &initial, bool ispod)
|
||||
{
|
||||
bool built_in_type_test(const T &initial, bool ispod) {
|
||||
bool passed = true;
|
||||
|
||||
/** value tests **/
|
||||
T i = T(initial);
|
||||
passed &= do_test<T>(var(i), true, true, true, true, true,
|
||||
true, true, true, true, true,
|
||||
true, true, true, true, true, true,
|
||||
true, true, true, true, true,
|
||||
ispod, ispod, ispod, true, true);
|
||||
passed &= do_test<T>(var(i),
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
ispod,
|
||||
ispod,
|
||||
ispod,
|
||||
true,
|
||||
true);
|
||||
|
||||
passed &= do_test<T>(const_var(i), true, true, false, true, false,
|
||||
true, false, true, false, true,
|
||||
false, false, true, false, true, false,
|
||||
true, false, true, false, true,
|
||||
ispod, ispod, ispod, false, true);
|
||||
passed &= do_test<T>(const_var(i),
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
ispod,
|
||||
ispod,
|
||||
ispod,
|
||||
false,
|
||||
true);
|
||||
|
||||
passed &= do_test<T>(var(&i), true, true, true, true, true,
|
||||
true, true, true, false, false,
|
||||
false, false, false, false, false, true,
|
||||
true, true, true, true, true,
|
||||
ispod, ispod, ispod, true, true);
|
||||
passed &= do_test<T>(var(&i),
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
ispod,
|
||||
ispod,
|
||||
ispod,
|
||||
true,
|
||||
true);
|
||||
|
||||
passed &= do_test<T>(const_var(&i), true, true, false, true, false,
|
||||
true, false, true, false, false,
|
||||
false, false, false, false, false, false,
|
||||
true, false, true, false, true,
|
||||
ispod, ispod, ispod, false, true);
|
||||
passed &= do_test<T>(const_var(&i),
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
ispod,
|
||||
ispod,
|
||||
ispod,
|
||||
false,
|
||||
true);
|
||||
|
||||
passed &= do_test<T>(var(std::ref(i)), true, true, true, true, true,
|
||||
true, true, true, false, false,
|
||||
false, false, false, false, false, true,
|
||||
true, true, true, true, true,
|
||||
ispod, ispod, ispod, true, true);
|
||||
passed &= do_test<T>(var(std::ref(i)),
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
ispod,
|
||||
ispod,
|
||||
ispod,
|
||||
true,
|
||||
true);
|
||||
|
||||
passed &= do_test<T>(var(std::cref(i)), true, true, false, true, false,
|
||||
true, false, true, false, false,
|
||||
false, false, false, false, false, false,
|
||||
true, false, true, false, true,
|
||||
ispod, ispod, ispod, false, true);
|
||||
passed &= do_test<T>(var(std::cref(i)),
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
ispod,
|
||||
ispod,
|
||||
ispod,
|
||||
false,
|
||||
true);
|
||||
|
||||
/** Const Reference Variable tests */
|
||||
|
||||
// This reference will be copied on input, which is expected
|
||||
const T &ir = i;
|
||||
|
||||
passed &= do_test<T>(var(i), true, true, true, true, true,
|
||||
true, true, true, true, true,
|
||||
true, true, true, true, true, true,
|
||||
true, true, true, true, true,
|
||||
ispod, ispod, ispod, true, true);
|
||||
passed &= do_test<T>(var(i),
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
ispod,
|
||||
ispod,
|
||||
ispod,
|
||||
true,
|
||||
true);
|
||||
|
||||
// But a pointer or reference to it should be necessarily const
|
||||
passed &= do_test<T>(var(&ir), true, true, false, true, false,
|
||||
true, false, true, false, false,
|
||||
false, false, false, false, false, false,
|
||||
true, false, true, false, true,
|
||||
ispod, ispod, ispod, false, true);
|
||||
passed &= do_test<T>(var(&ir),
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
ispod,
|
||||
ispod,
|
||||
ispod,
|
||||
false,
|
||||
true);
|
||||
|
||||
passed &= do_test<T>(var(std::ref(ir)), true, true, false, true, false,
|
||||
true, false, true, false, false,
|
||||
false, false, false, false, false, false,
|
||||
true, false, true, false, true,
|
||||
ispod, ispod, ispod, false, true);
|
||||
passed &= do_test<T>(var(std::ref(ir)),
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
ispod,
|
||||
ispod,
|
||||
ispod,
|
||||
false,
|
||||
true);
|
||||
|
||||
// Make sure const of const works too
|
||||
passed &= do_test<T>(const_var(&ir), true, true, false, true, false,
|
||||
true, false, true, false, false,
|
||||
false, false, false, false, false, false,
|
||||
true, false, true, false, true,
|
||||
ispod, ispod, ispod, false, true);
|
||||
passed &= do_test<T>(const_var(&ir),
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
ispod,
|
||||
ispod,
|
||||
ispod,
|
||||
false,
|
||||
true);
|
||||
|
||||
passed &= do_test<T>(const_var(std::ref(ir)), true, true, false, true, false,
|
||||
true, false, true, false, false,
|
||||
false, false, false, false, false, false,
|
||||
true, false, true, false, true,
|
||||
ispod, ispod, ispod, false, true);
|
||||
passed &= do_test<T>(const_var(std::ref(ir)),
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
ispod,
|
||||
ispod,
|
||||
ispod,
|
||||
false,
|
||||
true);
|
||||
|
||||
/** Const Reference Variable tests */
|
||||
|
||||
// This will always be seen as a const
|
||||
const T*cip = &i;
|
||||
passed &= do_test<T>(var(cip), true, true, false, true, false,
|
||||
true, false, true, false, false,
|
||||
false, false, false, false, false, false,
|
||||
true, false, true, false, true,
|
||||
ispod, ispod, ispod, false, true);
|
||||
const T *cip = &i;
|
||||
passed &= do_test<T>(var(cip),
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
ispod,
|
||||
ispod,
|
||||
ispod,
|
||||
false,
|
||||
true);
|
||||
|
||||
// make sure const of const works
|
||||
passed &= do_test<T>(const_var(cip), true, true, false, true, false,
|
||||
true, false, true, false, false,
|
||||
false, false, false, false, false, false,
|
||||
true, false, true, false, true,
|
||||
ispod, ispod, ispod, false, true);
|
||||
passed &= do_test<T>(const_var(cip),
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
ispod,
|
||||
ispod,
|
||||
ispod,
|
||||
false,
|
||||
true);
|
||||
|
||||
/** shared_ptr tests **/
|
||||
|
||||
auto ip = std::make_shared<T>(initial);
|
||||
|
||||
passed &= do_test<T>(var(ip), true, true, true, true, true,
|
||||
true, true, true, true, true,
|
||||
true, true, true, true, true, true,
|
||||
true, true, true, true, true,
|
||||
ispod, ispod, ispod, true, true);
|
||||
passed &= do_test<T>(var(ip),
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
ispod,
|
||||
ispod,
|
||||
ispod,
|
||||
true,
|
||||
true);
|
||||
|
||||
passed &= do_test<T>(const_var(ip), true, true, false, true, false,
|
||||
true, false, true, false, true,
|
||||
false, false, true, false, true, false,
|
||||
true, false, true, false, true,
|
||||
ispod, ispod, ispod, false, true);
|
||||
passed &= do_test<T>(const_var(ip),
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
ispod,
|
||||
ispod,
|
||||
ispod,
|
||||
false,
|
||||
true);
|
||||
|
||||
/** const shared_ptr tests **/
|
||||
auto ipc = std::make_shared<const T>(T(initial));
|
||||
|
||||
passed &= do_test<T>(var(ipc), true, true, false, true, false,
|
||||
true, false, true, false, true,
|
||||
false, false, true, false, true, false,
|
||||
true, false, true, false, true,
|
||||
ispod, ispod, ispod, false, true);
|
||||
passed &= do_test<T>(var(ipc),
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
ispod,
|
||||
ispod,
|
||||
ispod,
|
||||
false,
|
||||
true);
|
||||
|
||||
// const of this should be the same, making sure it compiles
|
||||
passed &= do_test<T>(const_var(ipc), true, true, false, true, false,
|
||||
true, false, true, false, true,
|
||||
false, false, true, false, true, false,
|
||||
true, false, true, false, true,
|
||||
ispod, ispod, ispod, false, true);
|
||||
|
||||
passed &= do_test<T>(const_var(ipc),
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
ispod,
|
||||
ispod,
|
||||
ispod,
|
||||
false,
|
||||
true);
|
||||
|
||||
/** Double ptr tests **/
|
||||
|
||||
@ -241,15 +627,13 @@ bool built_in_type_test(const T &initial, bool ispod)
|
||||
false, true, false, true, false,
|
||||
true, false, true, false, true,
|
||||
ispod, ispod, ispod, false, true);
|
||||
*/
|
||||
*/
|
||||
|
||||
return passed;
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
bool pointer_test(const T& default_value, const T& new_value)
|
||||
{
|
||||
bool pointer_test(const T &default_value, const T &new_value) {
|
||||
T *p = new T(default_value);
|
||||
|
||||
// we store a pointer to a pointer, so we can get a pointer to a pointer
|
||||
@ -257,14 +641,13 @@ bool pointer_test(const T& default_value, const T& new_value)
|
||||
T **result = boxed_cast<T **>(var(&p));
|
||||
*(*result) = new_value;
|
||||
|
||||
|
||||
if (p != (*result) ) {
|
||||
if (p != (*result)) {
|
||||
std::cerr << "Pointer passed in different than one returned\n";
|
||||
delete p;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (*p != *(*result) ) {
|
||||
if (*p != *(*result)) {
|
||||
std::cerr << "Somehow dereferenced pointer values are not the same?\n";
|
||||
delete p;
|
||||
return false;
|
||||
@ -283,9 +666,7 @@ bool pointer_test(const T& default_value, const T& new_value)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
int main() {
|
||||
bool passed = true;
|
||||
|
||||
/*
|
||||
|
||||
@ -1,21 +1,16 @@
|
||||
#include <chaiscript/chaiscript_basic.hpp>
|
||||
#include "../static_libs/chaiscript_parser.hpp"
|
||||
#include "../static_libs/chaiscript_stdlib.hpp"
|
||||
#include <chaiscript/chaiscript_basic.hpp>
|
||||
|
||||
|
||||
extern "C"
|
||||
{
|
||||
int do_something(int i)
|
||||
{
|
||||
extern "C" {
|
||||
int do_something(int i) {
|
||||
return i % 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser());
|
||||
int main() {
|
||||
chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(), create_chaiscript_parser());
|
||||
chai.add(chaiscript::fun(&do_something), "do_something");
|
||||
|
||||
return chai.eval<int>("do_something(101)") == 101 % 2?EXIT_SUCCESS:EXIT_FAILURE;
|
||||
|
||||
return chai.eval<int>("do_something(101)") == 101 % 2 ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||
}
|
||||
|
||||
12140
unittests/catch.hpp
12140
unittests/catch.hpp
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,7 +1,6 @@
|
||||
#include <chaiscript/chaiscript_basic.hpp>
|
||||
#include "../static_libs/chaiscript_parser.hpp"
|
||||
#include "../static_libs/chaiscript_stdlib.hpp"
|
||||
|
||||
#include <chaiscript/chaiscript_basic.hpp>
|
||||
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
// ignore errors about negative unsigned integer literals
|
||||
@ -9,20 +8,18 @@
|
||||
#pragma warning(disable : 4146)
|
||||
#endif
|
||||
|
||||
|
||||
#define TEST_LITERAL(v) test_literal(v, #v)
|
||||
#define TEST_LITERAL_SIGNED(v) test_literal(v, #v, true)
|
||||
|
||||
template<typename T>
|
||||
bool test_literal(T val, const std::string &str, bool use_boxed_number = false)
|
||||
{
|
||||
bool test_literal(T val, const std::string &str, bool use_boxed_number = false) {
|
||||
std::cout << '(' << str << ") Comparing : C++ '" << val;
|
||||
chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser());
|
||||
chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(), create_chaiscript_parser());
|
||||
|
||||
// Note, after applying the `-` it's possible that chaiscript has internally converted
|
||||
// between two equivalently sized types (ie, unsigned long and unsigned long long on a 64bit system)
|
||||
// so we're going to allow some leeway with the signed tests
|
||||
T val2 = [&](){
|
||||
T val2 = [&]() {
|
||||
if (!use_boxed_number) {
|
||||
return chai.eval<T>(str);
|
||||
}
|
||||
@ -33,79 +30,29 @@ bool test_literal(T val, const std::string &str, bool use_boxed_number = false)
|
||||
return val == val2;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
if(
|
||||
TEST_LITERAL(0xF)
|
||||
&& TEST_LITERAL(0xFF)
|
||||
&& TEST_LITERAL(0xFFF)
|
||||
&& TEST_LITERAL(0xFFFF)
|
||||
&& TEST_LITERAL(0xFFFFF)
|
||||
&& TEST_LITERAL(0xFFFFFF)
|
||||
&& TEST_LITERAL(0xFFFFFFF)
|
||||
&& TEST_LITERAL(0xFFFFFFFF)
|
||||
&& TEST_LITERAL(0xFFFFFFFFF)
|
||||
&& TEST_LITERAL(0xFFFFFFFFFF)
|
||||
&& TEST_LITERAL(0xFFFFFFFFFFF)
|
||||
&& TEST_LITERAL(0xFFFFFFFFFFFF)
|
||||
&& TEST_LITERAL(0xFFFFFFFFFFFFF)
|
||||
&& TEST_LITERAL(0xFFFFFFFFFFFFFF)
|
||||
&& TEST_LITERAL(0xFFFFFFFFFFFFFFF)
|
||||
&& TEST_LITERAL(0xFFFFFFFFFFFFFFFF)
|
||||
int main() {
|
||||
if (TEST_LITERAL(0xF) && TEST_LITERAL(0xFF) && TEST_LITERAL(0xFFF) && TEST_LITERAL(0xFFFF) && TEST_LITERAL(0xFFFFF)
|
||||
&& TEST_LITERAL(0xFFFFFF) && TEST_LITERAL(0xFFFFFFF) && TEST_LITERAL(0xFFFFFFFF) && TEST_LITERAL(0xFFFFFFFFF)
|
||||
&& TEST_LITERAL(0xFFFFFFFFFF) && TEST_LITERAL(0xFFFFFFFFFFF) && TEST_LITERAL(0xFFFFFFFFFFFF) && TEST_LITERAL(0xFFFFFFFFFFFFF)
|
||||
&& TEST_LITERAL(0xFFFFFFFFFFFFFF) && TEST_LITERAL(0xFFFFFFFFFFFFFFF) && TEST_LITERAL(0xFFFFFFFFFFFFFFFF)
|
||||
|
||||
&& TEST_LITERAL(01) && TEST_LITERAL(017) && TEST_LITERAL(0177) && TEST_LITERAL(01777) && TEST_LITERAL(017777)
|
||||
&& TEST_LITERAL(0177777) && TEST_LITERAL(01777777) && TEST_LITERAL(017777777) && TEST_LITERAL(0177777777)
|
||||
&& TEST_LITERAL(01777777777) && TEST_LITERAL(017777777777) && TEST_LITERAL(0177777777777) && TEST_LITERAL(01777777777777)
|
||||
&& TEST_LITERAL(017777777777777) && TEST_LITERAL(0177777777777777) && TEST_LITERAL(01777777777777777)
|
||||
&& TEST_LITERAL(017777777777777777) && TEST_LITERAL(0177777777777777777) && TEST_LITERAL(01777777777777777777)
|
||||
&& TEST_LITERAL(017777777777777777777) && TEST_LITERAL(0177777777777777777777) && TEST_LITERAL(01777777777777777777777)
|
||||
|
||||
&& TEST_LITERAL(01)
|
||||
&& TEST_LITERAL(017)
|
||||
&& TEST_LITERAL(0177)
|
||||
&& TEST_LITERAL(01777)
|
||||
&& TEST_LITERAL(017777)
|
||||
&& TEST_LITERAL(0177777)
|
||||
&& TEST_LITERAL(01777777)
|
||||
&& TEST_LITERAL(017777777)
|
||||
&& TEST_LITERAL(0177777777)
|
||||
&& TEST_LITERAL(01777777777)
|
||||
&& TEST_LITERAL(017777777777)
|
||||
&& TEST_LITERAL(0177777777777)
|
||||
&& TEST_LITERAL(01777777777777)
|
||||
&& TEST_LITERAL(017777777777777)
|
||||
&& TEST_LITERAL(0177777777777777)
|
||||
&& TEST_LITERAL(01777777777777777)
|
||||
&& TEST_LITERAL(017777777777777777)
|
||||
&& TEST_LITERAL(0177777777777777777)
|
||||
&& TEST_LITERAL(01777777777777777777)
|
||||
&& TEST_LITERAL(017777777777777777777)
|
||||
&& TEST_LITERAL(0177777777777777777777)
|
||||
&& TEST_LITERAL(01777777777777777777777)
|
||||
&& TEST_LITERAL(1) && TEST_LITERAL(17) && TEST_LITERAL(177) && TEST_LITERAL(1777) && TEST_LITERAL(17777) && TEST_LITERAL(177777)
|
||||
&& TEST_LITERAL(1777777) && TEST_LITERAL(17777777) && TEST_LITERAL(177777777) && TEST_LITERAL(1777777777)
|
||||
&& TEST_LITERAL(17777777777) && TEST_LITERAL(177777777777) && TEST_LITERAL(1777777777777) && TEST_LITERAL(17777777777777)
|
||||
&& TEST_LITERAL(177777777777777) && TEST_LITERAL(1777777777777777) && TEST_LITERAL(17777777777777777)
|
||||
&& TEST_LITERAL(177777777777777777) && TEST_LITERAL(1777777777777777777)
|
||||
|
||||
&& TEST_LITERAL(1)
|
||||
&& TEST_LITERAL(17)
|
||||
&& TEST_LITERAL(177)
|
||||
&& TEST_LITERAL(1777)
|
||||
&& TEST_LITERAL(17777)
|
||||
&& TEST_LITERAL(177777)
|
||||
&& TEST_LITERAL(1777777)
|
||||
&& TEST_LITERAL(17777777)
|
||||
&& TEST_LITERAL(177777777)
|
||||
&& TEST_LITERAL(1777777777)
|
||||
&& TEST_LITERAL(17777777777)
|
||||
&& TEST_LITERAL(177777777777)
|
||||
&& TEST_LITERAL(1777777777777)
|
||||
&& TEST_LITERAL(17777777777777)
|
||||
&& TEST_LITERAL(177777777777777)
|
||||
&& TEST_LITERAL(1777777777777777)
|
||||
&& TEST_LITERAL(17777777777777777)
|
||||
&& TEST_LITERAL(177777777777777777)
|
||||
&& TEST_LITERAL(1777777777777777777)
|
||||
|
||||
&& test_literal(0xF, "0b1111")
|
||||
&& test_literal(0xFF, "0b11111111")
|
||||
&& test_literal(0xFFF, "0b111111111111")
|
||||
&& test_literal(0xFFFF, "0b1111111111111111")
|
||||
&& test_literal(0xFFFFF, "0b11111111111111111111")
|
||||
&& test_literal(0xFFFFFF, "0b111111111111111111111111")
|
||||
&& test_literal(0xFFFFFFF, "0b1111111111111111111111111111")
|
||||
&& test_literal(0xFFFFFFFF, "0b11111111111111111111111111111111")
|
||||
&& test_literal(0xFFFFFFFFF, "0b111111111111111111111111111111111111")
|
||||
&& test_literal(0xF, "0b1111") && test_literal(0xFF, "0b11111111") && test_literal(0xFFF, "0b111111111111")
|
||||
&& test_literal(0xFFFF, "0b1111111111111111") && test_literal(0xFFFFF, "0b11111111111111111111")
|
||||
&& test_literal(0xFFFFFF, "0b111111111111111111111111") && test_literal(0xFFFFFFF, "0b1111111111111111111111111111")
|
||||
&& test_literal(0xFFFFFFFF, "0b11111111111111111111111111111111") && test_literal(0xFFFFFFFFF, "0b111111111111111111111111111111111111")
|
||||
&& test_literal(0xFFFFFFFFFF, "0b1111111111111111111111111111111111111111")
|
||||
&& test_literal(0xFFFFFFFFFFF, "0b11111111111111111111111111111111111111111111")
|
||||
&& test_literal(0xFFFFFFFFFFFF, "0b111111111111111111111111111111111111111111111111")
|
||||
@ -114,15 +61,10 @@ int main()
|
||||
&& test_literal(0xFFFFFFFFFFFFFFF, "0b111111111111111111111111111111111111111111111111111111111111")
|
||||
&& test_literal(0xFFFFFFFFFFFFFFFF, "0b1111111111111111111111111111111111111111111111111111111111111111")
|
||||
|
||||
&& test_literal(0x7, "0b111")
|
||||
&& test_literal(0x7F, "0b1111111")
|
||||
&& test_literal(0x7FF, "0b11111111111")
|
||||
&& test_literal(0x7FFF, "0b111111111111111")
|
||||
&& test_literal(0x7FFFF, "0b1111111111111111111")
|
||||
&& test_literal(0x7FFFFF, "0b11111111111111111111111")
|
||||
&& test_literal(0x7FFFFFF, "0b111111111111111111111111111")
|
||||
&& test_literal(0x7FFFFFFF, "0b1111111111111111111111111111111")
|
||||
&& test_literal(0x7FFFFFFFF, "0b11111111111111111111111111111111111")
|
||||
&& test_literal(0x7, "0b111") && test_literal(0x7F, "0b1111111") && test_literal(0x7FF, "0b11111111111")
|
||||
&& test_literal(0x7FFF, "0b111111111111111") && test_literal(0x7FFFF, "0b1111111111111111111")
|
||||
&& test_literal(0x7FFFFF, "0b11111111111111111111111") && test_literal(0x7FFFFFF, "0b111111111111111111111111111")
|
||||
&& test_literal(0x7FFFFFFF, "0b1111111111111111111111111111111") && test_literal(0x7FFFFFFFF, "0b11111111111111111111111111111111111")
|
||||
&& test_literal(0x7FFFFFFFFF, "0b111111111111111111111111111111111111111")
|
||||
&& test_literal(0x7FFFFFFFFFF, "0b1111111111111111111111111111111111111111111")
|
||||
&& test_literal(0x7FFFFFFFFFFF, "0b11111111111111111111111111111111111111111111111")
|
||||
@ -131,152 +73,82 @@ int main()
|
||||
&& test_literal(0x7FFFFFFFFFFFFFF, "0b11111111111111111111111111111111111111111111111111111111111")
|
||||
&& test_literal(0x7FFFFFFFFFFFFFFF, "0b111111111111111111111111111111111111111111111111111111111111111")
|
||||
|
||||
&& TEST_LITERAL_SIGNED(-0xF) && TEST_LITERAL_SIGNED(-0xFF) && TEST_LITERAL_SIGNED(-0xFFF) && TEST_LITERAL_SIGNED(-0xFFFF)
|
||||
&& TEST_LITERAL_SIGNED(-0xFFFFF) && TEST_LITERAL_SIGNED(-0xFFFFFF) && TEST_LITERAL_SIGNED(-0xFFFFFFF)
|
||||
&& TEST_LITERAL_SIGNED(-0xFFFFFFFF) && TEST_LITERAL_SIGNED(-0xFFFFFFFFF) && TEST_LITERAL_SIGNED(-0xFFFFFFFFFF)
|
||||
&& TEST_LITERAL_SIGNED(-0xFFFFFFFFFFF) && TEST_LITERAL_SIGNED(-0xFFFFFFFFFFFF) && TEST_LITERAL_SIGNED(-0xFFFFFFFFFFFFF)
|
||||
&& TEST_LITERAL_SIGNED(-0xFFFFFFFFFFFFFF) && TEST_LITERAL_SIGNED(-0xFFFFFFFFFFFFFFF) && TEST_LITERAL_SIGNED(-0xFFFFFFFFFFFFFFFF)
|
||||
|
||||
&& TEST_LITERAL_SIGNED(-0xF)
|
||||
&& TEST_LITERAL_SIGNED(-0xFF)
|
||||
&& TEST_LITERAL_SIGNED(-0xFFF)
|
||||
&& TEST_LITERAL_SIGNED(-0xFFFF)
|
||||
&& TEST_LITERAL_SIGNED(-0xFFFFF)
|
||||
&& TEST_LITERAL_SIGNED(-0xFFFFFF)
|
||||
&& TEST_LITERAL_SIGNED(-0xFFFFFFF)
|
||||
&& TEST_LITERAL_SIGNED(-0xFFFFFFFF)
|
||||
&& TEST_LITERAL_SIGNED(-0xFFFFFFFFF)
|
||||
&& TEST_LITERAL_SIGNED(-0xFFFFFFFFFF)
|
||||
&& TEST_LITERAL_SIGNED(-0xFFFFFFFFFFF)
|
||||
&& TEST_LITERAL_SIGNED(-0xFFFFFFFFFFFF)
|
||||
&& TEST_LITERAL_SIGNED(-0xFFFFFFFFFFFFF)
|
||||
&& TEST_LITERAL_SIGNED(-0xFFFFFFFFFFFFFF)
|
||||
&& TEST_LITERAL_SIGNED(-0xFFFFFFFFFFFFFFF)
|
||||
&& TEST_LITERAL_SIGNED(-0xFFFFFFFFFFFFFFFF)
|
||||
&& TEST_LITERAL_SIGNED(-01) && TEST_LITERAL_SIGNED(-017) && TEST_LITERAL_SIGNED(-0177) && TEST_LITERAL_SIGNED(-01777)
|
||||
&& TEST_LITERAL_SIGNED(-017777) && TEST_LITERAL_SIGNED(-0177777) && TEST_LITERAL_SIGNED(-01777777) && TEST_LITERAL_SIGNED(-017777777)
|
||||
&& TEST_LITERAL_SIGNED(-0177777777) && TEST_LITERAL_SIGNED(-01777777777) && TEST_LITERAL_SIGNED(-017777777777)
|
||||
&& TEST_LITERAL_SIGNED(-0177777777777) && TEST_LITERAL_SIGNED(-01777777777777) && TEST_LITERAL_SIGNED(-017777777777777)
|
||||
&& TEST_LITERAL_SIGNED(-0177777777777777) && TEST_LITERAL_SIGNED(-01777777777777777) && TEST_LITERAL_SIGNED(-017777777777777777)
|
||||
&& TEST_LITERAL_SIGNED(-0177777777777777777) && TEST_LITERAL_SIGNED(-01777777777777777777) && TEST_LITERAL_SIGNED(-017777777777777777777)
|
||||
&& TEST_LITERAL_SIGNED(-0177777777777777777777) && TEST_LITERAL_SIGNED(-01777777777777777777777)
|
||||
|
||||
|
||||
&& TEST_LITERAL_SIGNED(-01)
|
||||
&& TEST_LITERAL_SIGNED(-017)
|
||||
&& TEST_LITERAL_SIGNED(-0177)
|
||||
&& TEST_LITERAL_SIGNED(-01777)
|
||||
&& TEST_LITERAL_SIGNED(-017777)
|
||||
&& TEST_LITERAL_SIGNED(-0177777)
|
||||
&& TEST_LITERAL_SIGNED(-01777777)
|
||||
&& TEST_LITERAL_SIGNED(-017777777)
|
||||
&& TEST_LITERAL_SIGNED(-0177777777)
|
||||
&& TEST_LITERAL_SIGNED(-01777777777)
|
||||
&& TEST_LITERAL_SIGNED(-017777777777)
|
||||
&& TEST_LITERAL_SIGNED(-0177777777777)
|
||||
&& TEST_LITERAL_SIGNED(-01777777777777)
|
||||
&& TEST_LITERAL_SIGNED(-017777777777777)
|
||||
&& TEST_LITERAL_SIGNED(-0177777777777777)
|
||||
&& TEST_LITERAL_SIGNED(-01777777777777777)
|
||||
&& TEST_LITERAL_SIGNED(-017777777777777777)
|
||||
&& TEST_LITERAL_SIGNED(-0177777777777777777)
|
||||
&& TEST_LITERAL_SIGNED(-01777777777777777777)
|
||||
&& TEST_LITERAL_SIGNED(-017777777777777777777)
|
||||
&& TEST_LITERAL_SIGNED(-0177777777777777777777)
|
||||
&& TEST_LITERAL_SIGNED(-01777777777777777777777)
|
||||
|
||||
&& TEST_LITERAL_SIGNED(-1)
|
||||
&& TEST_LITERAL_SIGNED(-17)
|
||||
&& TEST_LITERAL_SIGNED(-177)
|
||||
&& TEST_LITERAL_SIGNED(-1777)
|
||||
&& TEST_LITERAL_SIGNED(-17777)
|
||||
&& TEST_LITERAL_SIGNED(-177777)
|
||||
&& TEST_LITERAL_SIGNED(-1777777)
|
||||
&& TEST_LITERAL_SIGNED(-17777777)
|
||||
&& TEST_LITERAL_SIGNED(-177777777)
|
||||
&& TEST_LITERAL_SIGNED(-1777777777)
|
||||
&& TEST_LITERAL_SIGNED(-17777777777)
|
||||
&& TEST_LITERAL_SIGNED(-177777777777)
|
||||
&& TEST_LITERAL_SIGNED(-1777777777777)
|
||||
&& TEST_LITERAL_SIGNED(-17777777777777)
|
||||
&& TEST_LITERAL_SIGNED(-177777777777777)
|
||||
&& TEST_LITERAL_SIGNED(-1777777777777777)
|
||||
&& TEST_LITERAL_SIGNED(-17777777777777777)
|
||||
&& TEST_LITERAL_SIGNED(-1) && TEST_LITERAL_SIGNED(-17) && TEST_LITERAL_SIGNED(-177) && TEST_LITERAL_SIGNED(-1777)
|
||||
&& TEST_LITERAL_SIGNED(-17777) && TEST_LITERAL_SIGNED(-177777) && TEST_LITERAL_SIGNED(-1777777) && TEST_LITERAL_SIGNED(-17777777)
|
||||
&& TEST_LITERAL_SIGNED(-177777777) && TEST_LITERAL_SIGNED(-1777777777) && TEST_LITERAL_SIGNED(-17777777777)
|
||||
&& TEST_LITERAL_SIGNED(-177777777777) && TEST_LITERAL_SIGNED(-1777777777777) && TEST_LITERAL_SIGNED(-17777777777777)
|
||||
&& TEST_LITERAL_SIGNED(-177777777777777) && TEST_LITERAL_SIGNED(-1777777777777777) && TEST_LITERAL_SIGNED(-17777777777777777)
|
||||
&& TEST_LITERAL_SIGNED(-177777777777777777)
|
||||
&& TEST_LITERAL_SIGNED(-1777777777777777777)
|
||||
|
||||
// Test 8/16/24/32 bit boundaries for various types
|
||||
|
||||
&& TEST_LITERAL(255)
|
||||
&& TEST_LITERAL(65535)
|
||||
&& TEST_LITERAL(255) && TEST_LITERAL(65535)
|
||||
&& TEST_LITERAL(16777215)
|
||||
#ifndef CHAISCRIPT_MSVC
|
||||
// bug in cl.exe causes this to be incorrectly parsed as an unsigned
|
||||
&& TEST_LITERAL(4294967295)
|
||||
#endif
|
||||
|
||||
&& TEST_LITERAL_SIGNED(-255)
|
||||
&& TEST_LITERAL_SIGNED(-65535)
|
||||
&& TEST_LITERAL_SIGNED(-255) && TEST_LITERAL_SIGNED(-65535)
|
||||
&& TEST_LITERAL_SIGNED(-16777215)
|
||||
#ifndef CHAISCRIPT_MSVC
|
||||
// bug in cl.exe causes this to be incorrectly parsed as an unsigned
|
||||
&& TEST_LITERAL_SIGNED(-4294967295)
|
||||
#endif
|
||||
|
||||
&& TEST_LITERAL(255u)
|
||||
&& TEST_LITERAL(65535u)
|
||||
&& TEST_LITERAL(16777215u)
|
||||
&& TEST_LITERAL(4294967295u)
|
||||
&& TEST_LITERAL(255u) && TEST_LITERAL(65535u) && TEST_LITERAL(16777215u) && TEST_LITERAL(4294967295u)
|
||||
|
||||
&& TEST_LITERAL_SIGNED(-255u)
|
||||
&& TEST_LITERAL_SIGNED(-65535u)
|
||||
&& TEST_LITERAL_SIGNED(-16777215u)
|
||||
&& TEST_LITERAL_SIGNED(-4294967295u)
|
||||
&& TEST_LITERAL_SIGNED(-255u) && TEST_LITERAL_SIGNED(-65535u) && TEST_LITERAL_SIGNED(-16777215u) && TEST_LITERAL_SIGNED(-4294967295u)
|
||||
|
||||
&& TEST_LITERAL(255l)
|
||||
&& TEST_LITERAL(65535l)
|
||||
&& TEST_LITERAL(255l) && TEST_LITERAL(65535l)
|
||||
&& TEST_LITERAL(16777215l)
|
||||
#ifndef CHAISCRIPT_MSVC
|
||||
// bug in cl.exe causes this to be incorrectly parsed as an unsigned
|
||||
&& TEST_LITERAL(4294967295l)
|
||||
#endif
|
||||
|
||||
&& TEST_LITERAL_SIGNED(-255l)
|
||||
&& TEST_LITERAL_SIGNED(-65535l)
|
||||
&& TEST_LITERAL_SIGNED(-255l) && TEST_LITERAL_SIGNED(-65535l)
|
||||
&& TEST_LITERAL_SIGNED(-16777215l)
|
||||
#ifndef CHAISCRIPT_MSVC
|
||||
// bug in cl.exe causes this to be incorrectly parsed as an unsigned
|
||||
&& TEST_LITERAL_SIGNED(-4294967295l)
|
||||
#endif
|
||||
|
||||
&& TEST_LITERAL(255ul)
|
||||
&& TEST_LITERAL(65535ul)
|
||||
&& TEST_LITERAL(16777215ul)
|
||||
&& TEST_LITERAL(4294967295ul)
|
||||
&& TEST_LITERAL(255ul) && TEST_LITERAL(65535ul) && TEST_LITERAL(16777215ul) && TEST_LITERAL(4294967295ul)
|
||||
|
||||
&& TEST_LITERAL_SIGNED(-255ul)
|
||||
&& TEST_LITERAL_SIGNED(-65535ul)
|
||||
&& TEST_LITERAL_SIGNED(-16777215ul)
|
||||
&& TEST_LITERAL_SIGNED(-4294967295ul)
|
||||
&& TEST_LITERAL_SIGNED(-255ul) && TEST_LITERAL_SIGNED(-65535ul) && TEST_LITERAL_SIGNED(-16777215ul) && TEST_LITERAL_SIGNED(-4294967295ul)
|
||||
|
||||
&& TEST_LITERAL(255ull)
|
||||
&& TEST_LITERAL(65535ull)
|
||||
&& TEST_LITERAL(16777215ull)
|
||||
&& TEST_LITERAL(4294967295ull)
|
||||
&& TEST_LITERAL(255ull) && TEST_LITERAL(65535ull) && TEST_LITERAL(16777215ull) && TEST_LITERAL(4294967295ull)
|
||||
|
||||
&& TEST_LITERAL_SIGNED(-255ull)
|
||||
&& TEST_LITERAL_SIGNED(-65535ull)
|
||||
&& TEST_LITERAL_SIGNED(-16777215ull)
|
||||
&& TEST_LITERAL_SIGNED(-255ull) && TEST_LITERAL_SIGNED(-65535ull) && TEST_LITERAL_SIGNED(-16777215ull)
|
||||
&& TEST_LITERAL_SIGNED(-4294967295ull)
|
||||
|
||||
&& TEST_LITERAL(255ll)
|
||||
&& TEST_LITERAL(65535ll)
|
||||
&& TEST_LITERAL(16777215ll)
|
||||
&& TEST_LITERAL(4294967295ll)
|
||||
&& TEST_LITERAL(255ll) && TEST_LITERAL(65535ll) && TEST_LITERAL(16777215ll) && TEST_LITERAL(4294967295ll)
|
||||
|
||||
&& TEST_LITERAL_SIGNED(-255ll)
|
||||
&& TEST_LITERAL_SIGNED(-65535ll)
|
||||
&& TEST_LITERAL_SIGNED(-16777215ll)
|
||||
&& TEST_LITERAL_SIGNED(-4294967295ll)
|
||||
&& TEST_LITERAL_SIGNED(-255ll) && TEST_LITERAL_SIGNED(-65535ll) && TEST_LITERAL_SIGNED(-16777215ll) && TEST_LITERAL_SIGNED(-4294967295ll)
|
||||
|
||||
|
||||
)
|
||||
{
|
||||
) {
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
@ -4,13 +4,11 @@
|
||||
#include <chaiscript/language/chaiscript_parser.hpp>
|
||||
|
||||
Multi_Test_Chai::Multi_Test_Chai()
|
||||
: m_chai(new chaiscript::ChaiScript_Basic(chaiscript::Std_Lib::library(),
|
||||
std::make_unique<chaiscript::parser::ChaiScript_Parser<chaiscript::eval::Noop_Tracer, chaiscript::optimizer::Optimizer_Default>>()))
|
||||
{
|
||||
: m_chai(new chaiscript::ChaiScript_Basic(
|
||||
chaiscript::Std_Lib::library(),
|
||||
std::make_unique<chaiscript::parser::ChaiScript_Parser<chaiscript::eval::Noop_Tracer, chaiscript::optimizer::Optimizer_Default>>())) {
|
||||
}
|
||||
|
||||
|
||||
std::shared_ptr<chaiscript::ChaiScript_Basic> Multi_Test_Chai::get_chai()
|
||||
{
|
||||
std::shared_ptr<chaiscript::ChaiScript_Basic> Multi_Test_Chai::get_chai() {
|
||||
return m_chai;
|
||||
}
|
||||
|
||||
@ -1,14 +1,11 @@
|
||||
#include <chaiscript/chaiscript_basic.hpp>
|
||||
|
||||
class Multi_Test_Chai
|
||||
{
|
||||
public:
|
||||
class Multi_Test_Chai {
|
||||
public:
|
||||
Multi_Test_Chai();
|
||||
|
||||
std::shared_ptr<chaiscript::ChaiScript_Basic> get_chai();
|
||||
|
||||
private:
|
||||
private:
|
||||
std::shared_ptr<chaiscript::ChaiScript_Basic> m_chai;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -3,8 +3,7 @@
|
||||
|
||||
#include <chaiscript/chaiscript_basic.hpp>
|
||||
|
||||
int main()
|
||||
{
|
||||
int main() {
|
||||
Multi_Test_Chai chaitest;
|
||||
Multi_Test_Module chaimodule;
|
||||
|
||||
|
||||
@ -4,13 +4,11 @@
|
||||
|
||||
Multi_Test_Module::Multi_Test_Module() noexcept = default;
|
||||
|
||||
int Multi_Test_Module::get_module_value()
|
||||
{
|
||||
int Multi_Test_Module::get_module_value() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
chaiscript::ModulePtr Multi_Test_Module::get_module()
|
||||
{
|
||||
chaiscript::ModulePtr Multi_Test_Module::get_module() {
|
||||
chaiscript::ModulePtr module(new chaiscript::Module());
|
||||
|
||||
module->add(chaiscript::fun(&Multi_Test_Module::get_module_value), "get_module_value");
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
#include <chaiscript/chaiscript_basic.hpp>
|
||||
|
||||
class Multi_Test_Module
|
||||
{
|
||||
public:
|
||||
class Multi_Test_Module {
|
||||
public:
|
||||
static int get_module_value();
|
||||
|
||||
Multi_Test_Module() noexcept;
|
||||
|
||||
@ -8,20 +8,17 @@
|
||||
#include <chaiscript/chaiscript_basic.hpp>
|
||||
#include <chaiscript/language/chaiscript_parser.hpp>
|
||||
|
||||
int expected_value(int num_iters)
|
||||
{
|
||||
int expected_value(int num_iters) {
|
||||
int i = 0;
|
||||
for (int k = 0; k<num_iters * 10; ++k)
|
||||
{
|
||||
for (int k = 0; k < num_iters * 10; ++k) {
|
||||
i += k;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
void do_work(chaiscript::ChaiScript_Basic &c, const size_t id)
|
||||
{
|
||||
try{
|
||||
void do_work(chaiscript::ChaiScript_Basic &c, const size_t id) {
|
||||
try {
|
||||
std::stringstream ss;
|
||||
ss << "MyVar" << rand();
|
||||
c.add(chaiscript::var(5), ss.str());
|
||||
@ -34,9 +31,8 @@ void do_work(chaiscript::ChaiScript_Basic &c, const size_t id)
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
// Disable deprecation warning for getenv call.
|
||||
int main() {
|
||||
// Disable deprecation warning for getenv call.
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
#ifdef max // Why Microsoft? why?
|
||||
#undef max
|
||||
@ -54,19 +50,17 @@ int main()
|
||||
|
||||
std::vector<std::string> usepaths;
|
||||
usepaths.emplace_back("");
|
||||
if (usepath)
|
||||
{
|
||||
if (usepath) {
|
||||
usepaths.emplace_back(usepath);
|
||||
}
|
||||
|
||||
std::vector<std::string> modulepaths;
|
||||
|
||||
#ifdef CHAISCRIPT_NO_DYNLOAD
|
||||
chaiscript::ChaiScript chai(/* unused */modulepaths, usepaths);
|
||||
chaiscript::ChaiScript chai(/* unused */ modulepaths, usepaths);
|
||||
#else
|
||||
modulepaths.emplace_back("");
|
||||
if (modulepath)
|
||||
{
|
||||
if (modulepath) {
|
||||
modulepaths.emplace_back(modulepath);
|
||||
}
|
||||
|
||||
@ -74,43 +68,36 @@ int main()
|
||||
// to make sure it continues to work
|
||||
chaiscript::ChaiScript_Basic chai(
|
||||
std::make_unique<chaiscript::parser::ChaiScript_Parser<chaiscript::eval::Noop_Tracer, chaiscript::optimizer::Optimizer_Default>>(),
|
||||
modulepaths,usepaths);
|
||||
modulepaths,
|
||||
usepaths);
|
||||
#endif
|
||||
|
||||
std::vector<std::shared_ptr<std::thread> > threads;
|
||||
std::vector<std::shared_ptr<std::thread>> threads;
|
||||
|
||||
// Ensure at least two, but say only 7 on an 8 core processor
|
||||
size_t num_threads = static_cast<size_t>(std::max(static_cast<int>(std::thread::hardware_concurrency()) - 1, 2));
|
||||
|
||||
std::cout << "Num threads: " << num_threads << '\n';
|
||||
|
||||
for (size_t i = 0; i < num_threads; ++i)
|
||||
{
|
||||
for (size_t i = 0; i < num_threads; ++i) {
|
||||
threads.push_back(std::make_shared<std::thread>(do_work, std::ref(chai), i));
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < num_threads; ++i)
|
||||
{
|
||||
for (size_t i = 0; i < num_threads; ++i) {
|
||||
threads[i]->join();
|
||||
}
|
||||
|
||||
|
||||
|
||||
for (size_t i = 0; i < num_threads; ++i)
|
||||
{
|
||||
for (size_t i = 0; i < num_threads; ++i) {
|
||||
std::stringstream ss;
|
||||
ss << i;
|
||||
if (chai.eval<int>("getvalue(" + ss.str() + ")") != expected_value(4000))
|
||||
{
|
||||
if (chai.eval<int>("getvalue(" + ss.str() + ")") != expected_value(4000)) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (chai.eval<int>("getid(" + ss.str() + ")") != static_cast<int>(i))
|
||||
{
|
||||
if (chai.eval<int>("getid(" + ss.str() + ")") != static_cast<int>(i)) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
@ -11,25 +11,18 @@
|
||||
#pragma GCC diagnostic ignored "-Wparentheses"
|
||||
#endif
|
||||
|
||||
|
||||
#include <chaiscript/chaiscript_defines.hpp>
|
||||
#include <chaiscript/dispatchkit/type_info.hpp>
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
|
||||
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#define CATCH_CONFIG_MAIN
|
||||
|
||||
#include "catch.hpp"
|
||||
|
||||
|
||||
TEST_CASE("Type_Info objects generate expected results")
|
||||
{
|
||||
const auto test_type = [](const chaiscript::Type_Info &ti, bool t_is_const, bool t_is_pointer, bool t_is_reference, bool t_is_void,
|
||||
bool t_is_undef, bool t_is_arithmetic)
|
||||
{
|
||||
TEST_CASE("Type_Info objects generate expected results") {
|
||||
const auto test_type
|
||||
= [](const chaiscript::Type_Info &ti, bool t_is_const, bool t_is_pointer, bool t_is_reference, bool t_is_void, bool t_is_undef, bool t_is_arithmetic) {
|
||||
CHECK(ti.is_const() == t_is_const);
|
||||
CHECK(ti.is_pointer() == t_is_pointer);
|
||||
CHECK(ti.is_reference() == t_is_reference);
|
||||
@ -49,6 +42,3 @@ TEST_CASE("Type_Info objects generate expected results")
|
||||
|
||||
std::cout << "Size of Type_Info " << sizeof(chaiscript::Type_Info) << '\n';
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user