mirror of
https://github.com/ChaiScript/ChaiScript.git
synced 2025-12-06 08:46:53 +08:00
change .clang-format and reformat code with clang-format 11
I initially tried to use the existing .clang-format file, but it does not match the code style (at least with clang-format 11) and the formatting is not consistent across files. Therefore, I decided to rewrite the .clang-format with some personal preferences. Used command find . -iname "*.hpp" -o -iname "*.cpp" | xargs clang-format -i -style=file
This commit is contained in:
parent
6491b80496
commit
cff6a0aced
131
.clang-format
131
.clang-format
@ -1,98 +1,33 @@
|
|||||||
AccessModifierOffset: -2
|
# clang-format: 11
|
||||||
AlignAfterOpenBracket: DontAlign
|
AccessModifierOffset: -2
|
||||||
AlignConsecutiveAssignments: false
|
AlignAfterOpenBracket: Align
|
||||||
AlignConsecutiveDeclarations: false
|
AlignConsecutiveBitFields: false
|
||||||
AlignEscapedNewlines: Left
|
AllowShortBlocksOnASingleLine: false
|
||||||
AlignOperands: true
|
AllowShortFunctionsOnASingleLine: Inline
|
||||||
AlignTrailingComments: false
|
AllowShortLambdasOnASingleLine: All
|
||||||
AllowAllParametersOfDeclarationOnNextLine: false
|
AlwaysBreakTemplateDeclarations: true
|
||||||
AllowShortBlocksOnASingleLine: true
|
BasedOnStyle: WebKit
|
||||||
AllowShortCaseLabelsOnASingleLine: false
|
BinPackArguments: true
|
||||||
AllowShortFunctionsOnASingleLine: All
|
BinPackParameters: true
|
||||||
AllowShortIfStatementsOnASingleLine: true
|
BreakBeforeBraces: Attach
|
||||||
AllowShortLoopsOnASingleLine: true
|
ColumnLimit: 0
|
||||||
AlwaysBreakAfterDefinitionReturnType: None
|
Cpp11BracedListStyle: true
|
||||||
AlwaysBreakAfterReturnType: None
|
FixNamespaceComments: true
|
||||||
AlwaysBreakBeforeMultilineStrings: true
|
IncludeBlocks: Preserve
|
||||||
AlwaysBreakTemplateDeclarations: false
|
IndentCaseLabels: true
|
||||||
BinPackArguments: false
|
IndentPPDirectives: None
|
||||||
BinPackParameters: false
|
IndentWidth: 2
|
||||||
BraceWrapping:
|
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||||
AfterClass: true
|
NamespaceIndentation: All
|
||||||
AfterControlStatement: false
|
PenaltyBreakBeforeFirstCallParameter: 200
|
||||||
AfterEnum: false
|
PenaltyBreakComment: 5
|
||||||
AfterFunction: true
|
PenaltyBreakFirstLessLess: 50
|
||||||
AfterNamespace: false
|
PenaltyExcessCharacter: 4
|
||||||
AfterObjCDeclaration: false
|
PointerAlignment: Right
|
||||||
AfterStruct: true
|
SortIncludes: true
|
||||||
AfterUnion: false
|
SpaceAfterTemplateKeyword: false
|
||||||
BeforeCatch: false
|
SpaceBeforeCpp11BracedList: false
|
||||||
BeforeElse: false
|
SpaceInEmptyBlock: false
|
||||||
IndentBraces: false
|
Standard: Latest
|
||||||
SplitEmptyFunction: false
|
TabWidth: 2
|
||||||
SplitEmptyNamespace: true
|
UseTab: Never
|
||||||
SplitEmptyRecord: true
|
|
||||||
BreakAfterJavaFieldAnnotations: true
|
|
||||||
BreakBeforeBinaryOperators: NonAssignment
|
|
||||||
BreakBeforeBraces: Custom
|
|
||||||
BreakBeforeInheritanceComma: true
|
|
||||||
BreakBeforeTernaryOperators: true
|
|
||||||
BreakConstructorInitializers: BeforeColon
|
|
||||||
BreakConstructorInitializersBeforeComma: false
|
|
||||||
BreakStringLiterals: true
|
|
||||||
ColumnLimit: 0
|
|
||||||
CommentPragmas: '^ IWYU pragma:'
|
|
||||||
CompactNamespaces: false
|
|
||||||
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
|
||||||
ConstructorInitializerIndentWidth: 2
|
|
||||||
ContinuationIndentWidth: 2
|
|
||||||
Cpp11BracedListStyle: false
|
|
||||||
DerivePointerAlignment: true
|
|
||||||
DisableFormat: false
|
|
||||||
ExperimentalAutoDetectBinPacking: 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
|
|
||||||
IndentWidth: 2
|
|
||||||
IndentWrappedFunctionNames: true
|
|
||||||
JavaScriptQuotes: Leave
|
|
||||||
JavaScriptWrapImports: true
|
|
||||||
KeepEmptyLinesAtTheStartOfBlocks: true
|
|
||||||
Language: Cpp
|
|
||||||
MacroBlockBegin: ''
|
|
||||||
MacroBlockEnd: ''
|
|
||||||
MaxEmptyLinesToKeep: 2
|
|
||||||
NamespaceIndentation: Inner
|
|
||||||
ObjCBlockIndentWidth: 7
|
|
||||||
ObjCSpaceAfterProperty: true
|
|
||||||
ObjCSpaceBeforeProtocolList: false
|
|
||||||
PointerAlignment: Right
|
|
||||||
ReflowComments: true
|
|
||||||
SortIncludes: false
|
|
||||||
SortUsingDeclarations: false
|
|
||||||
SpaceAfterCStyleCast: false
|
|
||||||
SpaceAfterTemplateKeyword: false
|
|
||||||
SpaceBeforeAssignmentOperators: true
|
|
||||||
SpaceBeforeParens: ControlStatements
|
|
||||||
SpaceInEmptyParentheses: false
|
|
||||||
SpacesBeforeTrailingComments: 0
|
|
||||||
SpacesInAngles: false
|
|
||||||
SpacesInCStyleCastParentheses: false
|
|
||||||
SpacesInContainerLiterals: true
|
|
||||||
SpacesInParentheses: false
|
|
||||||
SpacesInSquareBrackets: false
|
|
||||||
Standard: Cpp11
|
|
||||||
TabWidth: 8
|
|
||||||
UseTab: Never
|
|
||||||
|
|
||||||
@ -7,25 +7,23 @@
|
|||||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
// 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
|
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||||
|
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_HPP_
|
#ifndef CHAISCRIPT_HPP_
|
||||||
#define CHAISCRIPT_HPP_
|
#define CHAISCRIPT_HPP_
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @mainpage
|
/// @mainpage
|
||||||
/// [ChaiScript](http://www.chaiscript.com") is a scripting language designed specifically for integration with C++. It provides
|
/// [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.
|
/// seamless integration with C++ on all levels, including shared_ptr objects, functors and exceptions.
|
||||||
///
|
///
|
||||||
/// The parts of the ChaiScript API that the average user will be concerned with are contained in the
|
/// The parts of the ChaiScript API that the average user will be concerned with are contained in the
|
||||||
/// chaiscript namespace and the chaiscript::ChaiScript class.
|
/// chaiscript namespace and the chaiscript::ChaiScript class.
|
||||||
///
|
///
|
||||||
/// The end user parts of the API are extremely simple both in size and ease of use.
|
/// 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").
|
||||||
///
|
///
|
||||||
/// ------------------------------------------------------------
|
/// ------------------------------------------------------------
|
||||||
///
|
///
|
||||||
/// @sa chaiscript
|
/// @sa chaiscript
|
||||||
/// @sa chaiscript::ChaiScript
|
/// @sa chaiscript::ChaiScript
|
||||||
/// @sa ChaiScript_Language for Built in Functions
|
/// @sa ChaiScript_Language for Built in Functions
|
||||||
@ -51,16 +49,16 @@
|
|||||||
/// - @ref functionobjects
|
/// - @ref functionobjects
|
||||||
/// - @ref threading
|
/// - @ref threading
|
||||||
/// - @ref exceptions
|
/// - @ref exceptions
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
/// @subsection basics Basics
|
/// @subsection basics Basics
|
||||||
///
|
///
|
||||||
/// Basic simple example:
|
/// Basic simple example:
|
||||||
///
|
///
|
||||||
/// ~~~~~~~{.cpp}
|
/// ~~~~~~~{.cpp}
|
||||||
/// //main.cpp
|
/// //main.cpp
|
||||||
/// #include <chaiscript/chaiscript.hpp>
|
/// #include <chaiscript/chaiscript.hpp>
|
||||||
///
|
///
|
||||||
/// double function(int i, double j)
|
/// double function(int i, double j)
|
||||||
/// {
|
/// {
|
||||||
/// return i * j;
|
/// return i * j;
|
||||||
@ -72,7 +70,7 @@
|
|||||||
/// chai.add(chaiscript::fun(&function), "function");
|
/// chai.add(chaiscript::fun(&function), "function");
|
||||||
///
|
///
|
||||||
/// double d = chai.eval<double>("function(3, 4.75);");
|
/// double d = chai.eval<double>("function(3, 4.75);");
|
||||||
/// }
|
/// }
|
||||||
/// ~~~~~~~
|
/// ~~~~~~~
|
||||||
///
|
///
|
||||||
/// ------------------------------------------------------
|
/// ------------------------------------------------------
|
||||||
@ -81,14 +79,14 @@
|
|||||||
///
|
///
|
||||||
/// ChaiScript is a header only library with only one dependency: The
|
/// ChaiScript is a header only library with only one dependency: The
|
||||||
/// operating system provided dynamic library loader, which has to be specified on some platforms.
|
/// operating system provided dynamic library loader, which has to be specified on some platforms.
|
||||||
///
|
///
|
||||||
/// @subsubsection compilinggcc Compiling with GCC
|
/// @subsubsection compilinggcc Compiling with GCC
|
||||||
///
|
///
|
||||||
/// To compile the above application on a Unix like operating system (MacOS, Linux) with GCC you need to link
|
/// To compile the above application on a Unix like operating system (MacOS, Linux) with GCC you need to link
|
||||||
/// the dynamic loader. For example:
|
/// the dynamic loader. For example:
|
||||||
///
|
///
|
||||||
/// ~~~~~~~~
|
/// ~~~~~~~~
|
||||||
/// gcc main.cpp -I/path/to/chaiscript/headers -ldl
|
/// gcc main.cpp -I/path/to/chaiscript/headers -ldl
|
||||||
/// ~~~~~~~~
|
/// ~~~~~~~~
|
||||||
///
|
///
|
||||||
/// Alternatively, you may compile without threading support.
|
/// Alternatively, you may compile without threading support.
|
||||||
@ -111,11 +109,11 @@
|
|||||||
/// chaiscript::ChaiScript chai;
|
/// chaiscript::ChaiScript chai;
|
||||||
/// chai("print(@"hello world@")");
|
/// chai("print(@"hello world@")");
|
||||||
/// ~~~~~~~~
|
/// ~~~~~~~~
|
||||||
///
|
///
|
||||||
/// @sa chaiscript::ChaiScript::operator()(const std::string &)
|
/// @sa chaiscript::ChaiScript::operator()(const std::string &)
|
||||||
///
|
///
|
||||||
/// @subsubsection evalmethod Method 'eval'
|
/// @subsubsection evalmethod Method 'eval'
|
||||||
///
|
///
|
||||||
/// The eval method is somewhat more verbose and can be used to get type safely return values
|
/// The eval method is somewhat more verbose and can be used to get type safely return values
|
||||||
/// from the script.
|
/// from the script.
|
||||||
///
|
///
|
||||||
@ -129,15 +127,15 @@
|
|||||||
/// @sa chaiscript::ChaiScript::eval
|
/// @sa chaiscript::ChaiScript::eval
|
||||||
///
|
///
|
||||||
/// @subsubsection evalfilemethod Method 'eval_file'
|
/// @subsubsection evalfilemethod Method 'eval_file'
|
||||||
///
|
///
|
||||||
/// The 'eval_file' method loads a file from disk and executes the script in it
|
/// The 'eval_file' method loads a file from disk and executes the script in it
|
||||||
///
|
///
|
||||||
/// ~~~~~~~~{.cpp}
|
/// ~~~~~~~~{.cpp}
|
||||||
/// chaiscript::ChaiScript chai;
|
/// chaiscript::ChaiScript chai;
|
||||||
/// chai.eval_file("myfile.chai");
|
/// chai.eval_file("myfile.chai");
|
||||||
/// std::string result = chai.eval_file<std::string>("myfile.chai") // extract the last value returned from the file
|
/// std::string result = chai.eval_file<std::string>("myfile.chai") // extract the last value returned from the file
|
||||||
/// ~~~~~~~~
|
/// ~~~~~~~~
|
||||||
///
|
///
|
||||||
/// @sa chaiscript::ChaiScript::eval_file
|
/// @sa chaiscript::ChaiScript::eval_file
|
||||||
///
|
///
|
||||||
/// --------------------------------------------------
|
/// --------------------------------------------------
|
||||||
@ -149,10 +147,10 @@
|
|||||||
/// @subsubsection adding_objects Adding Objects
|
/// @subsubsection adding_objects Adding Objects
|
||||||
///
|
///
|
||||||
/// Named objects can be created with the chaiscript::var function. Note: adding a object
|
/// Named objects can be created with the chaiscript::var function. Note: adding a object
|
||||||
/// adds it to the current thread scope, not to a global scope. If you have multiple
|
/// adds it to the current thread scope, not to a global scope. If you have multiple
|
||||||
/// threads that need to access the same variables you will need to add them
|
/// threads that need to access the same variables you will need to add them
|
||||||
/// separately for each thread, from the thread itself.
|
/// separately for each thread, from the thread itself.
|
||||||
///
|
///
|
||||||
/// ~~~~~~~~~{.cpp}
|
/// ~~~~~~~~~{.cpp}
|
||||||
/// using namespace chaiscript;
|
/// using namespace chaiscript;
|
||||||
/// ChaiScript chai;
|
/// ChaiScript chai;
|
||||||
@ -167,23 +165,23 @@
|
|||||||
/// chai.add(const_var(i), "i");
|
/// chai.add(const_var(i), "i");
|
||||||
/// chai("i = 5"); // exception throw, cannot assign const var
|
/// chai("i = 5"); // exception throw, cannot assign const var
|
||||||
/// ~~~~~~~~~
|
/// ~~~~~~~~~
|
||||||
///
|
///
|
||||||
/// Named variables can only be accessed from the context they are created in.
|
/// Named variables can only be accessed from the context they are created in.
|
||||||
/// If you want a global variable, it must be const, and created with the
|
/// If you want a global variable, it must be const, and created with the
|
||||||
/// chaiscript::ChaiScript::add_global_const function.
|
/// chaiscript::ChaiScript::add_global_const function.
|
||||||
///
|
///
|
||||||
/// ~~~~~~~~~{.cpp}
|
/// ~~~~~~~~~{.cpp}
|
||||||
/// chai.add_global_const(const_var(i), "i");
|
/// chai.add_global_const(const_var(i), "i");
|
||||||
/// chai("def somefun() { print(i); }; somefun();");
|
/// chai("def somefun() { print(i); }; somefun();");
|
||||||
/// ~~~~~~~~~
|
/// ~~~~~~~~~
|
||||||
///
|
///
|
||||||
/// @subsubsection adding_functions Adding Functions
|
/// @subsubsection adding_functions Adding Functions
|
||||||
///
|
///
|
||||||
/// Functions, methods and members are all added using the same function: chaiscript::fun.
|
/// Functions, methods and members are all added using the same function: chaiscript::fun.
|
||||||
///
|
///
|
||||||
/// ~~~~~~~~~{.cpp}
|
/// ~~~~~~~~~{.cpp}
|
||||||
/// using namespace chaiscript;
|
/// using namespace chaiscript;
|
||||||
///
|
///
|
||||||
/// class MyClass {
|
/// class MyClass {
|
||||||
/// public:
|
/// public:
|
||||||
/// int memberdata;
|
/// int memberdata;
|
||||||
@ -193,7 +191,7 @@
|
|||||||
/// void overloadedmethod();
|
/// void overloadedmethod();
|
||||||
/// void overloadedmethod(const std::string &);
|
/// void overloadedmethod(const std::string &);
|
||||||
/// };
|
/// };
|
||||||
///
|
///
|
||||||
/// ChaiScript chai;
|
/// ChaiScript chai;
|
||||||
/// chai.add(fun(&MyClass::memberdata), "memberdata");
|
/// chai.add(fun(&MyClass::memberdata), "memberdata");
|
||||||
/// chai.add(fun(&MyClass::method), "method");
|
/// chai.add(fun(&MyClass::method), "method");
|
||||||
@ -208,7 +206,7 @@
|
|||||||
/// ~~~~~~~~~
|
/// ~~~~~~~~~
|
||||||
///
|
///
|
||||||
/// There are also shortcuts built into chaiscript::fun for binding up to the first two parameters of the function.
|
/// There are also shortcuts built into chaiscript::fun for binding up to the first two parameters of the function.
|
||||||
///
|
///
|
||||||
/// ~~~~~~~~~{.cpp}
|
/// ~~~~~~~~~{.cpp}
|
||||||
/// MyClass obj;
|
/// MyClass obj;
|
||||||
/// chai.add(fun(&MyClass::method, &obj), "method");
|
/// chai.add(fun(&MyClass::method, &obj), "method");
|
||||||
@ -220,7 +218,7 @@
|
|||||||
/// @subsubsection addingtypeinfo Adding Type Info
|
/// @subsubsection addingtypeinfo Adding Type Info
|
||||||
///
|
///
|
||||||
/// ChaiScript will automatically support any type implicitly provided to it in the form
|
/// ChaiScript will automatically support any type implicitly provided to it in the form
|
||||||
/// of objects and function parameters / return types. However, it can be nice to let ChaiScript
|
/// of objects and function parameters / return types. However, it can be nice to let ChaiScript
|
||||||
/// know more details about the types you are giving it. For instance, the "clone" functionality
|
/// know more details about the types you are giving it. For instance, the "clone" functionality
|
||||||
/// cannot work unless there is a copy constructor registered and the name of the type is known
|
/// cannot work unless there is a copy constructor registered and the name of the type is known
|
||||||
/// (so that ChaiScript can look up the copy constructor).
|
/// (so that ChaiScript can look up the copy constructor).
|
||||||
@ -232,23 +230,23 @@
|
|||||||
/// ~~~~~~~~
|
/// ~~~~~~~~
|
||||||
///
|
///
|
||||||
/// @subsubsection adding_modules Adding Modules
|
/// @subsubsection adding_modules Adding Modules
|
||||||
///
|
///
|
||||||
/// Modules are holders for collections of ChaiScript registrations.
|
/// Modules are holders for collections of ChaiScript registrations.
|
||||||
///
|
///
|
||||||
/// ~~~~~~~~{.cpp}
|
/// ~~~~~~~~{.cpp}
|
||||||
/// ModulePtr module = get_sum_module();
|
/// ModulePtr module = get_sum_module();
|
||||||
/// chai.add(module);
|
/// chai.add(module);
|
||||||
/// ~~~~~~~~
|
/// ~~~~~~~~
|
||||||
///
|
///
|
||||||
/// @sa chaiscript::Module
|
/// @sa chaiscript::Module
|
||||||
///
|
///
|
||||||
/// -----------------------------------------------------------------------
|
/// -----------------------------------------------------------------------
|
||||||
///
|
///
|
||||||
/// @subsection operatoroverloading Operator Overloading
|
/// @subsection operatoroverloading Operator Overloading
|
||||||
///
|
///
|
||||||
/// Operators are just like any other function in ChaiScript, to overload an operator, simply register it.
|
/// Operators are just like any other function in ChaiScript, to overload an operator, simply register it.
|
||||||
///
|
///
|
||||||
/// ~~~~~~~~{.cpp}
|
/// ~~~~~~~~{.cpp}
|
||||||
/// class MyClass {
|
/// class MyClass {
|
||||||
/// MyClass operator+(const MyClass &) const;
|
/// MyClass operator+(const MyClass &) const;
|
||||||
/// };
|
/// };
|
||||||
@ -270,7 +268,7 @@
|
|||||||
/// -----------------------------------------------------------------------
|
/// -----------------------------------------------------------------------
|
||||||
///
|
///
|
||||||
/// @subsection add_class Class Helper Utility
|
/// @subsection add_class Class Helper Utility
|
||||||
///
|
///
|
||||||
/// Much of the work of adding new classes to ChaiScript can be reduced with the help
|
/// Much of the work of adding new classes to ChaiScript can be reduced with the help
|
||||||
/// of the add_class helper utility.
|
/// of the add_class helper utility.
|
||||||
///
|
///
|
||||||
@ -295,8 +293,8 @@
|
|||||||
/// constructor<Test(const Test &)>() },
|
/// constructor<Test(const Test &)>() },
|
||||||
/// { {fun(&Test::function), "function"},
|
/// { {fun(&Test::function), "function"},
|
||||||
/// {fun(&Test::function2), "function2"},
|
/// {fun(&Test::function2), "function2"},
|
||||||
/// {fun(&Test::function2), "function3"}
|
/// {fun(&Test::function2), "function3"}
|
||||||
/// {fun(static_cast<std::string Test::*(double)>(&Test::functionOverload)), "functionOverload"}
|
/// {fun(static_cast<std::string Test::*(double)>(&Test::functionOverload)), "functionOverload"}
|
||||||
/// {fun(static_cast<std::string Test::*(int)>(&Test::functionOverload)), "functionOverload"} }
|
/// {fun(static_cast<std::string Test::*(int)>(&Test::functionOverload)), "functionOverload"} }
|
||||||
/// );
|
/// );
|
||||||
///
|
///
|
||||||
@ -305,7 +303,7 @@
|
|||||||
/// chai.add(m);
|
/// chai.add(m);
|
||||||
/// }
|
/// }
|
||||||
/// ~~~~~~~~
|
/// ~~~~~~~~
|
||||||
///
|
///
|
||||||
/// @sa @ref adding_modules
|
/// @sa @ref adding_modules
|
||||||
///
|
///
|
||||||
/// -----------------------------------------------------------------------
|
/// -----------------------------------------------------------------------
|
||||||
@ -315,8 +313,8 @@
|
|||||||
/// As much as possible, ChaiScript attempts to convert between &, *, const &, const *, std::shared_ptr<T>,
|
/// 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.
|
/// 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).
|
/// 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
|
||||||
/// Const may be added, but never removed.
|
/// 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.
|
/// The take away is that you can pretty much expect function calls to Just Work when you need them to.
|
||||||
///
|
///
|
||||||
@ -359,16 +357,16 @@
|
|||||||
/// chai("fun8(i)");
|
/// chai("fun8(i)");
|
||||||
/// chai("fun9(i)");
|
/// chai("fun9(i)");
|
||||||
/// chai("fun10(i)");
|
/// chai("fun10(i)");
|
||||||
/// }
|
/// }
|
||||||
/// ~~~~~~~~
|
/// ~~~~~~~~
|
||||||
///
|
///
|
||||||
/// See the unit test unittests/boxed_cast_test.cpp for a complete breakdown of the automatic casts that
|
/// See the unit test unittests/boxed_cast_test.cpp for a complete breakdown of the automatic casts that
|
||||||
/// available and tested.
|
/// available and tested.
|
||||||
///
|
///
|
||||||
/// -----------------------------------------------------------------------
|
/// -----------------------------------------------------------------------
|
||||||
///
|
///
|
||||||
/// @subsection baseclasses Base Classes
|
/// @subsection baseclasses Base Classes
|
||||||
///
|
///
|
||||||
/// ChaiScript supports handling of passing a derived class object to a function expecting a base class object.
|
/// ChaiScript supports handling of passing a derived class object to a function expecting a base class object.
|
||||||
/// For the process to work, the base/derived relationship must be registered with the engine.
|
/// For the process to work, the base/derived relationship must be registered with the engine.
|
||||||
///
|
///
|
||||||
@ -387,7 +385,7 @@
|
|||||||
/// chai("myfunction(d)");
|
/// chai("myfunction(d)");
|
||||||
/// }
|
/// }
|
||||||
/// ~~~~~~~~
|
/// ~~~~~~~~
|
||||||
///
|
///
|
||||||
/// -----------------------------------------------------------------------
|
/// -----------------------------------------------------------------------
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
@ -401,7 +399,7 @@
|
|||||||
/// {
|
/// {
|
||||||
/// t_func("bob");
|
/// t_func("bob");
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// int main()
|
/// int main()
|
||||||
/// {
|
/// {
|
||||||
/// chaiscript::ChaiScript chai;
|
/// chaiscript::ChaiScript chai;
|
||||||
@ -413,16 +411,16 @@
|
|||||||
/// f(); // call the ChaiScript function dump_system, from C++
|
/// f(); // call the ChaiScript function dump_system, from C++
|
||||||
/// }
|
/// }
|
||||||
/// ~~~~~~~~
|
/// ~~~~~~~~
|
||||||
///
|
///
|
||||||
/// -----------------------------------------------------------------------
|
/// -----------------------------------------------------------------------
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
/// @subsection threading Threading
|
/// @subsection threading Threading
|
||||||
///
|
///
|
||||||
/// Thread safety is automatically handled within the ChaiScript system. Objects can be added
|
/// Thread safety is automatically handled within the ChaiScript system. Objects can be added
|
||||||
/// and scripts executed from multiple threads. For each thread that executes scripts, a new
|
/// and scripts executed from multiple threads. For each thread that executes scripts, a new
|
||||||
/// context is created and managed by the engine.
|
/// context is created and managed by the engine.
|
||||||
///
|
///
|
||||||
/// Thread safety can be disabled by defining CHAISCRIPT_NO_THREADS when using the library.
|
/// Thread safety can be disabled by defining CHAISCRIPT_NO_THREADS when using the library.
|
||||||
///
|
///
|
||||||
/// Disabling thread safety increases performance in many cases.
|
/// Disabling thread safety increases performance in many cases.
|
||||||
@ -431,10 +429,10 @@
|
|||||||
///
|
///
|
||||||
///
|
///
|
||||||
/// @subsection exceptions Exception Handling
|
/// @subsection exceptions Exception Handling
|
||||||
///
|
///
|
||||||
/// @subsubsection exceptionsbasics Exception Handling Basics
|
/// @subsubsection exceptionsbasics Exception Handling Basics
|
||||||
///
|
///
|
||||||
/// Exceptions can be thrown in ChaiScript and caught in C++ or thrown in C++ and caught in
|
/// Exceptions can be thrown in ChaiScript and caught in C++ or thrown in C++ and caught in
|
||||||
/// ChaiScript.
|
/// ChaiScript.
|
||||||
///
|
///
|
||||||
/// ~~~~~~~~{.cpp}
|
/// ~~~~~~~~{.cpp}
|
||||||
@ -442,14 +440,14 @@
|
|||||||
/// {
|
/// {
|
||||||
/// throw std::runtime_error("err");
|
/// throw std::runtime_error("err");
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// int main()
|
/// int main()
|
||||||
/// {
|
/// {
|
||||||
/// // Throw in C++, catch in ChaiScript
|
/// // Throw in C++, catch in ChaiScript
|
||||||
/// chaiscript::ChaiScript chai;
|
/// chaiscript::ChaiScript chai;
|
||||||
/// chai.add(chaiscript::fun(&throwexception), "throwexception");
|
/// chai.add(chaiscript::fun(&throwexception), "throwexception");
|
||||||
/// chai("try { throwexception(); } catch (e) { print(e.what()); }"); // prints "err"
|
/// chai("try { throwexception(); } catch (e) { print(e.what()); }"); // prints "err"
|
||||||
///
|
///
|
||||||
/// // Throw in ChaiScript, catch in C++
|
/// // Throw in ChaiScript, catch in C++
|
||||||
/// try {
|
/// try {
|
||||||
/// chai("throw(1)");
|
/// chai("throw(1)");
|
||||||
@ -459,18 +457,19 @@
|
|||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
/// ~~~~~~~~
|
/// ~~~~~~~~
|
||||||
///
|
///
|
||||||
/// @subsubsection exceptionsautomatic Exception Handling Automatic Unboxing
|
/// @subsubsection exceptionsautomatic Exception Handling Automatic Unboxing
|
||||||
///
|
///
|
||||||
/// As an alternative to the manual unboxing of exceptions shown above, exception specifications allow the user to tell
|
/// As an alternative to the manual unboxing of exceptions shown above, exception specifications allow the user to tell
|
||||||
/// ChaiScript what possible exceptions are expected from the script being executed.
|
/// ChaiScript what possible exceptions are expected from the script being executed.
|
||||||
///
|
///
|
||||||
/// Example:
|
/// Example:
|
||||||
/// ~~~~~~~~{.cpp}
|
/// ~~~~~~~~{.cpp}
|
||||||
/// chaiscript::ChaiScript chai;
|
/// chaiscript::ChaiScript chai;
|
||||||
///
|
///
|
||||||
/// try {
|
/// 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 (const double e) {
|
||||||
/// } catch (int) {
|
/// } catch (int) {
|
||||||
/// } catch (float) {
|
/// } catch (float) {
|
||||||
@ -480,11 +479,9 @@
|
|||||||
/// }
|
/// }
|
||||||
/// ~~~~~~~~
|
/// ~~~~~~~~
|
||||||
///
|
///
|
||||||
/// @sa chaiscript::Exception_Handler for details on automatic exception unboxing
|
/// @sa chaiscript::Exception_Handler for details on automatic exception unboxing
|
||||||
/// @sa chaiscript::exception_specification
|
/// @sa chaiscript::exception_specification
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @page LangObjectSystemRef ChaiScript Language Object Model Reference
|
/// @page LangObjectSystemRef ChaiScript Language Object Model Reference
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
@ -495,7 +492,7 @@
|
|||||||
/// attr Rectangle::width
|
/// attr Rectangle::width
|
||||||
/// def Rectangle::Rectangle() { this.height = 10; this.width = 20 }
|
/// def Rectangle::Rectangle() { this.height = 10; this.width = 20 }
|
||||||
/// def Rectangle::area() { this.height * this.width }
|
/// def Rectangle::area() { this.height * this.width }
|
||||||
///
|
///
|
||||||
/// var rect = Rectangle()
|
/// var rect = Rectangle()
|
||||||
/// rect.height = 30
|
/// rect.height = 30
|
||||||
/// print(rect.area())
|
/// print(rect.area())
|
||||||
@ -521,7 +518,7 @@
|
|||||||
|
|
||||||
/// @page LangInPlaceRef ChaiScript Language In-Place Creation Reference
|
/// @page LangInPlaceRef ChaiScript Language In-Place Creation Reference
|
||||||
/// @section inplacevector Vector
|
/// @section inplacevector Vector
|
||||||
///
|
///
|
||||||
/// ~~~~~~~~~
|
/// ~~~~~~~~~
|
||||||
/// In-place Vector ::= "[" [expression ("," expression)*] "]"
|
/// In-place Vector ::= "[" [expression ("," expression)*] "]"
|
||||||
/// ~~~~~~~~~
|
/// ~~~~~~~~~
|
||||||
@ -541,9 +538,9 @@
|
|||||||
/// ~~~~~~~~
|
/// ~~~~~~~~
|
||||||
|
|
||||||
/// @page LangGettingStarted ChaiScript Language Getting Started
|
/// @page LangGettingStarted ChaiScript Language Getting Started
|
||||||
///
|
///
|
||||||
/// ChaiScript is a simple language that should feel familiar to anyone who knows
|
/// ChaiScript is a simple language that should feel familiar to anyone who knows
|
||||||
/// C++ or ECMAScript (JavaScript).
|
/// C++ or ECMAScript (JavaScript).
|
||||||
///
|
///
|
||||||
/// -----------------------------------------------------------------------
|
/// -----------------------------------------------------------------------
|
||||||
///
|
///
|
||||||
@ -575,10 +572,10 @@
|
|||||||
/// @section chaiscriptifs Conditionals
|
/// @section chaiscriptifs Conditionals
|
||||||
///
|
///
|
||||||
/// If statements work as expected
|
/// If statements work as expected
|
||||||
///
|
///
|
||||||
/// ~~~~~~~~
|
/// ~~~~~~~~
|
||||||
/// var b = true;
|
/// var b = true;
|
||||||
///
|
///
|
||||||
/// if (b) {
|
/// if (b) {
|
||||||
/// // do something
|
/// // do something
|
||||||
/// } else if (c < 10) {
|
/// } else if (c < 10) {
|
||||||
@ -593,9 +590,9 @@
|
|||||||
/// -----------------------------------------------------------------------
|
/// -----------------------------------------------------------------------
|
||||||
///
|
///
|
||||||
/// @section chaiscriptfunctions Functions
|
/// @section chaiscriptfunctions Functions
|
||||||
///
|
///
|
||||||
/// Functions are defined with the def keyword
|
/// Functions are defined with the def keyword
|
||||||
///
|
///
|
||||||
/// ~~~~~~~~
|
/// ~~~~~~~~
|
||||||
/// def myfun(x) { print(x); }
|
/// def myfun(x) { print(x); }
|
||||||
///
|
///
|
||||||
@ -612,7 +609,7 @@
|
|||||||
/// eval> myfun2(12)
|
/// eval> myfun2(12)
|
||||||
/// 10 or greater
|
/// 10 or greater
|
||||||
/// ~~~~~~~~
|
/// ~~~~~~~~
|
||||||
///
|
///
|
||||||
/// @sa @ref keyworddef
|
/// @sa @ref keyworddef
|
||||||
/// @sa @ref keywordattr
|
/// @sa @ref keywordattr
|
||||||
/// @sa @ref LangObjectSystemRef
|
/// @sa @ref LangObjectSystemRef
|
||||||
@ -620,7 +617,7 @@
|
|||||||
/// -----------------------------------------------------------------------
|
/// -----------------------------------------------------------------------
|
||||||
///
|
///
|
||||||
/// @section chaiscriptfunctionobjects Function Objects
|
/// @section chaiscriptfunctionobjects Function Objects
|
||||||
///
|
///
|
||||||
/// Functions are first class types in ChaiScript and can be used as variables.
|
/// Functions are first class types in ChaiScript and can be used as variables.
|
||||||
///
|
///
|
||||||
/// ~~~~~~~~
|
/// ~~~~~~~~
|
||||||
@ -628,8 +625,8 @@
|
|||||||
/// eval> p(1);
|
/// eval> p(1);
|
||||||
/// 1
|
/// 1
|
||||||
/// ~~~~~~~~
|
/// ~~~~~~~~
|
||||||
///
|
///
|
||||||
/// They can also be passed to functions.
|
/// They can also be passed to functions.
|
||||||
///
|
///
|
||||||
/// ~~~~~~~~
|
/// ~~~~~~~~
|
||||||
/// eval> def callfunc(f, lhs, rhs) { return f(lhs, rhs); }
|
/// eval> def callfunc(f, lhs, rhs) { return f(lhs, rhs); }
|
||||||
@ -639,7 +636,7 @@
|
|||||||
/// ~~~~~~~~
|
/// ~~~~~~~~
|
||||||
///
|
///
|
||||||
/// Operators can also be treated as functions by using the back tick operator. Building on the above example:
|
/// Operators can also be treated as functions by using the back tick operator. Building on the above example:
|
||||||
///
|
///
|
||||||
/// ~~~~~~~~
|
/// ~~~~~~~~
|
||||||
/// eval> callfunc(`+`, 1, 4);
|
/// eval> callfunc(`+`, 1, 4);
|
||||||
/// 5
|
/// 5
|
||||||
@ -652,7 +649,6 @@
|
|||||||
/// @sa @ref LangKeywordRef
|
/// @sa @ref LangKeywordRef
|
||||||
/// @sa ChaiScript_Language for Built in Functions
|
/// @sa ChaiScript_Language for Built in Functions
|
||||||
|
|
||||||
|
|
||||||
/// @page LangKeywordRef ChaiScript Language Keyword Reference
|
/// @page LangKeywordRef ChaiScript Language Keyword Reference
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
@ -660,8 +656,8 @@
|
|||||||
///
|
///
|
||||||
/// @section keywordattr attr
|
/// @section keywordattr attr
|
||||||
/// Defines a ChaiScript object attribute
|
/// Defines a ChaiScript object attribute
|
||||||
///
|
///
|
||||||
/// ~~~~~~~~
|
/// ~~~~~~~~
|
||||||
/// Attribute Definition ::= "attr" class_name "::" attribute_name
|
/// Attribute Definition ::= "attr" class_name "::" attribute_name
|
||||||
/// ~~~~~~~~
|
/// ~~~~~~~~
|
||||||
///
|
///
|
||||||
@ -690,7 +686,7 @@
|
|||||||
/// ~~~~~~~~
|
/// ~~~~~~~~
|
||||||
///
|
///
|
||||||
/// @sa @ref keywordfor
|
/// @sa @ref keywordfor
|
||||||
/// @sa @ref keywordwhile
|
/// @sa @ref keywordwhile
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
/// -----------------------------------------------------------------------
|
/// -----------------------------------------------------------------------
|
||||||
@ -702,7 +698,7 @@
|
|||||||
/// Function Definition ::= "def" identifier "(" [[type] arg ("," [type] arg)*] ")" [":" guard] block
|
/// Function Definition ::= "def" identifier "(" [[type] arg ("," [type] arg)*] ")" [":" guard] block
|
||||||
/// Method Definition ::= "def" class_name "::" method_name "(" [[type] arg ("," [type] arg)*] ")" [":" guard] block
|
/// Method Definition ::= "def" class_name "::" method_name "(" [[type] arg ("," [type] arg)*] ")" [":" guard] block
|
||||||
/// ~~~~~~~~
|
/// ~~~~~~~~
|
||||||
///
|
///
|
||||||
/// identifier: name of function. Required.
|
/// identifier: name of function. Required.
|
||||||
/// args: comma-delimited list of parameter names with optional type specifiers. Optional.
|
/// args: comma-delimited list of parameter names with optional type specifiers. Optional.
|
||||||
/// guards: guarding statement that act as a prerequisite for the function. Optional.
|
/// guards: guarding statement that act as a prerequisite for the function. Optional.
|
||||||
@ -722,7 +718,7 @@
|
|||||||
/// -----------------------------------------------------------------------
|
/// -----------------------------------------------------------------------
|
||||||
///
|
///
|
||||||
/// @section keywordelse else
|
/// @section keywordelse else
|
||||||
/// @sa @ref keywordif
|
/// @sa @ref keywordif
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
/// -----------------------------------------------------------------------
|
/// -----------------------------------------------------------------------
|
||||||
@ -762,7 +758,7 @@
|
|||||||
/// Else If Block ::= "else if" "(" condition ")" block
|
/// Else If Block ::= "else if" "(" condition ")" block
|
||||||
/// Else Block ::= "else" block
|
/// Else Block ::= "else" block
|
||||||
/// ~~~~~~~~
|
/// ~~~~~~~~
|
||||||
///
|
///
|
||||||
/// _Example_
|
/// _Example_
|
||||||
///
|
///
|
||||||
/// ~~~~~~~~
|
/// ~~~~~~~~
|
||||||
@ -780,8 +776,8 @@
|
|||||||
///
|
///
|
||||||
/// @section keywordtry try
|
/// @section keywordtry try
|
||||||
/// ~~~~~~~~
|
/// ~~~~~~~~
|
||||||
/// Try Block ::= "try" block
|
/// Try Block ::= "try" block
|
||||||
/// ("catch" ["(" [type] variable ")"] [":" guards] block)+
|
/// ("catch" ["(" [type] variable ")"] [":" guards] block)+
|
||||||
/// ["finally" block]
|
/// ["finally" block]
|
||||||
/// ~~~~~~~~
|
/// ~~~~~~~~
|
||||||
///
|
///
|
||||||
@ -791,7 +787,7 @@
|
|||||||
/// -----------------------------------------------------------------------
|
/// -----------------------------------------------------------------------
|
||||||
///
|
///
|
||||||
/// @section keywordwhile while
|
/// @section keywordwhile while
|
||||||
///
|
///
|
||||||
/// Begins a conditional block of code that loops 0 or more times, as long as the condition is true
|
/// Begins a conditional block of code that loops 0 or more times, as long as the condition is true
|
||||||
///
|
///
|
||||||
/// ~~~~~~~~
|
/// ~~~~~~~~
|
||||||
@ -804,7 +800,7 @@
|
|||||||
/// -----------------------------------------------------------------------
|
/// -----------------------------------------------------------------------
|
||||||
///
|
///
|
||||||
/// @section keywordvar var
|
/// @section keywordvar var
|
||||||
///
|
///
|
||||||
/// Defines a variable
|
/// Defines a variable
|
||||||
///
|
///
|
||||||
/// ~~~~~~~~
|
/// ~~~~~~~~
|
||||||
@ -813,7 +809,6 @@
|
|||||||
///
|
///
|
||||||
/// Synonym for @ref keywordauto
|
/// Synonym for @ref keywordauto
|
||||||
|
|
||||||
|
|
||||||
/// @namespace chaiscript
|
/// @namespace chaiscript
|
||||||
/// @brief Namespace chaiscript contains every API call that the average user will be concerned with.
|
/// @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.
|
/// @brief Classes and functions reserved for internal use. Items in this namespace are not supported.
|
||||||
|
|
||||||
#include "chaiscript_basic.hpp"
|
#include "chaiscript_basic.hpp"
|
||||||
#include "language/chaiscript_parser.hpp"
|
|
||||||
#include "chaiscript_stdlib.hpp"
|
#include "chaiscript_stdlib.hpp"
|
||||||
|
#include "language/chaiscript_parser.hpp"
|
||||||
|
|
||||||
|
namespace chaiscript {
|
||||||
namespace chaiscript
|
class ChaiScript : public ChaiScript_Basic {
|
||||||
{
|
public:
|
||||||
class ChaiScript : public ChaiScript_Basic
|
ChaiScript(std::vector<std::string> t_modulepaths = {},
|
||||||
{
|
std::vector<std::string> t_usepaths = {},
|
||||||
public:
|
std::vector<Options> t_opts = chaiscript::default_options())
|
||||||
ChaiScript(std::vector<std::string> t_modulepaths = {},
|
: ChaiScript_Basic(chaiscript::Std_Lib::library(),
|
||||||
std::vector<std::string> t_usepaths = {},
|
std::make_unique<parser::ChaiScript_Parser<eval::Noop_Tracer, optimizer::Optimizer_Default>>(),
|
||||||
std::vector<Options> t_opts = chaiscript::default_options())
|
std::move(t_modulepaths),
|
||||||
: ChaiScript_Basic(
|
std::move(t_usepaths),
|
||||||
chaiscript::Std_Lib::library(),
|
std::move(t_opts)) {
|
||||||
std::make_unique<parser::ChaiScript_Parser<eval::Noop_Tracer, optimizer::Optimizer_Default>>(),
|
}
|
||||||
std::move(t_modulepaths), std::move(t_usepaths), std::move(t_opts))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
} // namespace chaiscript
|
||||||
|
|
||||||
#endif /* CHAISCRIPT_HPP_ */
|
#endif /* CHAISCRIPT_HPP_ */
|
||||||
|
|||||||
@ -9,13 +9,13 @@
|
|||||||
|
|
||||||
#include "chaiscript_defines.hpp"
|
#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/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_engine.hpp"
|
||||||
|
#include "language/chaiscript_eval.hpp"
|
||||||
|
|
||||||
// This file includes all of the basic requirements for ChaiScript,
|
// This file includes all of the basic requirements for ChaiScript,
|
||||||
// to use, you might do something like:
|
// 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
|
// If you want a fully packaged ready to go ChaiScript, use chaiscript.hpp
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* CHAISCRIPT_BASIC_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__
|
#define CHAISCRIPT_COMPILER_VERSION __VERSION__
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#if defined( _LIBCPP_VERSION )
|
#if defined(_LIBCPP_VERSION)
|
||||||
#define CHAISCRIPT_LIBCPP
|
#define CHAISCRIPT_LIBCPP
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -49,16 +49,14 @@ static_assert(_MSC_FULL_VER >= 190024210, "Visual C++ 2015 Update 3 or later req
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#if defined(__llvm__)
|
#if defined(__llvm__)
|
||||||
#define CHAISCRIPT_CLANG
|
#define CHAISCRIPT_CLANG
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CHAISCRIPT_HAS_DECLSPEC
|
||||||
#ifdef CHAISCRIPT_HAS_DECLSPEC
|
|
||||||
#define CHAISCRIPT_MODULE_EXPORT extern "C" __declspec(dllexport)
|
#define CHAISCRIPT_MODULE_EXPORT extern "C" __declspec(dllexport)
|
||||||
#else
|
#else
|
||||||
#define CHAISCRIPT_MODULE_EXPORT extern "C"
|
#define CHAISCRIPT_MODULE_EXPORT extern "C"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(CHAISCRIPT_MSVC) || (defined(__GNUC__) && __GNUC__ >= 5) || defined(CHAISCRIPT_CLANG)
|
#if defined(CHAISCRIPT_MSVC) || (defined(__GNUC__) && __GNUC__ >= 5) || defined(CHAISCRIPT_CLANG)
|
||||||
@ -71,9 +69,9 @@ static_assert(_MSC_FULL_VER >= 190024210, "Visual C++ 2015 Update 3 or later req
|
|||||||
#define CHAISCRIPT_DEBUG false
|
#define CHAISCRIPT_DEBUG false
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <cmath>
|
|
||||||
|
|
||||||
namespace chaiscript {
|
namespace chaiscript {
|
||||||
constexpr static const int version_major = 7;
|
constexpr static const int version_major = 7;
|
||||||
@ -84,166 +82,129 @@ namespace chaiscript {
|
|||||||
constexpr static const char *compiler_name = CHAISCRIPT_COMPILER_NAME;
|
constexpr static const char *compiler_name = CHAISCRIPT_COMPILER_NAME;
|
||||||
constexpr static const bool debug_build = CHAISCRIPT_DEBUG;
|
constexpr static const bool debug_build = CHAISCRIPT_DEBUG;
|
||||||
|
|
||||||
template<typename B, typename D, typename ...Arg>
|
template<typename B, typename D, typename... Arg>
|
||||||
inline std::shared_ptr<B> make_shared(Arg && ... arg)
|
inline std::shared_ptr<B> make_shared(Arg &&...arg) {
|
||||||
{
|
|
||||||
#ifdef CHAISCRIPT_USE_STD_MAKE_SHARED
|
#ifdef CHAISCRIPT_USE_STD_MAKE_SHARED
|
||||||
return std::make_shared<D>(std::forward<Arg>(arg)...);
|
return std::make_shared<D>(std::forward<Arg>(arg)...);
|
||||||
#else
|
#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
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename B, typename D, typename ...Arg>
|
template<typename B, typename D, typename... Arg>
|
||||||
inline std::unique_ptr<B> make_unique(Arg && ... arg)
|
inline std::unique_ptr<B> make_unique(Arg &&...arg) {
|
||||||
{
|
|
||||||
#ifdef CHAISCRIPT_USE_STD_MAKE_SHARED
|
#ifdef CHAISCRIPT_USE_STD_MAKE_SHARED
|
||||||
return std::make_unique<D>(std::forward<Arg>(arg)...);
|
return std::make_unique<D>(std::forward<Arg>(arg)...);
|
||||||
#else
|
#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
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Build_Info {
|
struct Build_Info {
|
||||||
[[nodiscard]] constexpr static int version_major() noexcept
|
[[nodiscard]] constexpr static int version_major() noexcept { return chaiscript::version_major; }
|
||||||
{
|
|
||||||
return chaiscript::version_major;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] constexpr static int version_minor() noexcept
|
[[nodiscard]] constexpr static int version_minor() noexcept { return chaiscript::version_minor; }
|
||||||
{
|
|
||||||
return chaiscript::version_minor;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] constexpr static int version_patch() noexcept
|
[[nodiscard]] constexpr static int version_patch() noexcept { return chaiscript::version_patch; }
|
||||||
{
|
|
||||||
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());
|
return std::to_string(version_major()) + '.' + std::to_string(version_minor()) + '.' + std::to_string(version_patch());
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] static std::string compiler_id()
|
[[nodiscard]] static std::string compiler_id() { return compiler_name() + '-' + compiler_version(); }
|
||||||
{
|
|
||||||
return compiler_name() + '-' + compiler_version();
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] static std::string build_id()
|
[[nodiscard]] static std::string build_id() { return compiler_id() + (debug_build() ? "-Debug" : "-Release"); }
|
||||||
{
|
|
||||||
return compiler_id() + (debug_build()?"-Debug":"-Release");
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] static std::string compiler_version()
|
[[nodiscard]] static std::string compiler_version() { return chaiscript::compiler_version; }
|
||||||
{
|
|
||||||
return chaiscript::compiler_version;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] static std::string compiler_name()
|
[[nodiscard]] static std::string compiler_name() { return chaiscript::compiler_name; }
|
||||||
{
|
|
||||||
return chaiscript::compiler_name;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] constexpr static bool debug_build() noexcept
|
[[nodiscard]] constexpr static bool debug_build() noexcept { return chaiscript::debug_build; }
|
||||||
{
|
|
||||||
return chaiscript::debug_build;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
template<typename T>
|
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;
|
||||||
T t = 0;
|
for (const auto c : t_str) {
|
||||||
for (const auto c : t_str) {
|
if (c < '0' || c > '9') {
|
||||||
if (c < '0' || c > '9') {
|
return t;
|
||||||
return t;
|
|
||||||
}
|
|
||||||
t *= 10;
|
|
||||||
t += c - '0';
|
|
||||||
}
|
}
|
||||||
return t;
|
t *= 10;
|
||||||
|
t += c - '0';
|
||||||
}
|
}
|
||||||
|
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 {
|
||||||
|
T t = 0;
|
||||||
|
T base{};
|
||||||
|
T decimal_place = 0;
|
||||||
|
int exponent = 0;
|
||||||
|
|
||||||
template<typename T>
|
for (const auto c : t_str) {
|
||||||
[[nodiscard]] auto parse_num(const std::string_view t_str) -> typename std::enable_if<!std::is_integral<T>::value, T>::type
|
switch (c) {
|
||||||
{
|
case '.':
|
||||||
T t = 0;
|
decimal_place = 10;
|
||||||
T base{};
|
break;
|
||||||
T decimal_place = 0;
|
case 'e':
|
||||||
int exponent = 0;
|
case 'E':
|
||||||
|
exponent = 1;
|
||||||
for (const auto c : t_str) {
|
decimal_place = 0;
|
||||||
switch (c)
|
base = t;
|
||||||
{
|
t = 0;
|
||||||
case '.':
|
break;
|
||||||
decimal_place = 10;
|
case '-':
|
||||||
break;
|
exponent = -1;
|
||||||
case 'e':
|
break;
|
||||||
case 'E':
|
case '+':
|
||||||
exponent = 1;
|
break;
|
||||||
decimal_place = 0;
|
case '0':
|
||||||
base = t;
|
case '1':
|
||||||
t = 0;
|
case '2':
|
||||||
break;
|
case '3':
|
||||||
case '-':
|
case '4':
|
||||||
exponent = -1;
|
case '5':
|
||||||
break;
|
case '6':
|
||||||
case '+':
|
case '7':
|
||||||
break;
|
case '8':
|
||||||
case '0':
|
case '9':
|
||||||
case '1':
|
if (decimal_place < 10) {
|
||||||
case '2':
|
t *= 10;
|
||||||
case '3':
|
t += static_cast<T>(c - '0');
|
||||||
case '4':
|
} else {
|
||||||
case '5':
|
t += static_cast<T>(c - '0') / decimal_place;
|
||||||
case '6':
|
decimal_place *= 10;
|
||||||
case '7':
|
|
||||||
case '8':
|
|
||||||
case '9':
|
|
||||||
if (decimal_place < 10) {
|
|
||||||
t *= 10;
|
|
||||||
t += static_cast<T>(c - '0');
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
t += static_cast<T>(c - '0') / decimal_place;
|
|
||||||
decimal_place *= 10;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
break;
|
||||||
return exponent ? base * std::pow(T(10), t * static_cast<T>(exponent)) : t;
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return exponent ? base * std::pow(T(10), t * static_cast<T>(exponent)) : t;
|
||||||
|
}
|
||||||
|
|
||||||
struct str_equal {
|
struct str_equal {
|
||||||
[[nodiscard]] bool operator()(const std::string &t_lhs, const std::string &t_rhs) const noexcept {
|
[[nodiscard]] bool operator()(const std::string &t_lhs, const std::string &t_rhs) const noexcept { return t_lhs == t_rhs; }
|
||||||
return t_lhs == t_rhs;
|
|
||||||
}
|
|
||||||
template<typename LHS, typename RHS>
|
template<typename LHS, typename RHS>
|
||||||
[[nodiscard]] constexpr bool operator()(const LHS &t_lhs, const RHS &t_rhs) const noexcept {
|
[[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());
|
return std::equal(t_lhs.begin(), t_lhs.end(), t_rhs.begin(), t_rhs.end());
|
||||||
}
|
}
|
||||||
struct is_transparent{};
|
struct is_transparent {
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
struct str_less {
|
struct str_less {
|
||||||
[[nodiscard]] bool operator()(const std::string &t_lhs, const std::string &t_rhs) const noexcept {
|
[[nodiscard]] bool operator()(const std::string &t_lhs, const std::string &t_rhs) const noexcept { return t_lhs < t_rhs; }
|
||||||
return t_lhs < t_rhs;
|
|
||||||
}
|
|
||||||
template<typename LHS, typename RHS>
|
template<typename LHS, typename RHS>
|
||||||
[[nodiscard]] constexpr bool operator()(const LHS &t_lhs, const RHS &t_rhs) const noexcept {
|
[[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());
|
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,
|
No_Load_Modules,
|
||||||
Load_Modules,
|
Load_Modules,
|
||||||
No_External_Scripts,
|
No_External_Scripts,
|
||||||
@ -251,44 +212,33 @@ namespace chaiscript {
|
|||||||
};
|
};
|
||||||
|
|
||||||
template<typename From, typename To>
|
template<typename From, typename To>
|
||||||
struct is_nothrow_forward_constructible
|
struct is_nothrow_forward_constructible : std::bool_constant<noexcept(To{std::declval<From>()})> {
|
||||||
: std::bool_constant<noexcept(To{std::declval<From>()})>
|
|
||||||
{
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template< class From, class To >
|
template<class From, class To>
|
||||||
static inline constexpr bool is_nothrow_forward_constructible_v
|
static inline constexpr bool is_nothrow_forward_constructible_v = is_nothrow_forward_constructible<From, To>::value;
|
||||||
= is_nothrow_forward_constructible<From, To>::value;
|
|
||||||
|
|
||||||
template<typename Container, typename ... T>
|
template<typename Container, typename... T>
|
||||||
[[nodiscard]] constexpr auto make_container(T && ... t)
|
[[nodiscard]] constexpr auto make_container(T &&...t) {
|
||||||
{
|
|
||||||
Container c;
|
Container c;
|
||||||
c.reserve(sizeof...(t));
|
c.reserve(sizeof...(t));
|
||||||
(c.push_back(std::forward<T>(t)), ...);
|
(c.push_back(std::forward<T>(t)), ...);
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename... T>
|
||||||
template<typename ... T>
|
[[nodiscard]] auto make_vector(T &&...t) -> std::vector<std::common_type_t<std::decay_t<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>...>>;
|
||||||
{
|
|
||||||
using container_type =
|
|
||||||
std::vector<std::common_type_t<std::decay_t<T>...>>;
|
|
||||||
|
|
||||||
return make_container<container_type>(std::forward<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
|
#ifdef CHAISCRIPT_NO_DYNLOAD
|
||||||
return {Options::No_Load_Modules, Options::External_Scripts};
|
return {Options::No_Load_Modules, Options::External_Scripts};
|
||||||
#else
|
#else
|
||||||
return {Options::Load_Modules, Options::External_Scripts};
|
return {Options::Load_Modules, Options::External_Scripts};
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
} // namespace chaiscript
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@ -19,53 +19,48 @@
|
|||||||
#include "dispatchkit/function_call.hpp"
|
#include "dispatchkit/function_call.hpp"
|
||||||
|
|
||||||
//#include "dispatchkit/dispatchkit.hpp"
|
//#include "dispatchkit/dispatchkit.hpp"
|
||||||
#include "dispatchkit/operators.hpp"
|
|
||||||
#include "dispatchkit/bootstrap.hpp"
|
#include "dispatchkit/bootstrap.hpp"
|
||||||
#include "dispatchkit/bootstrap_stl.hpp"
|
#include "dispatchkit/bootstrap_stl.hpp"
|
||||||
|
#include "dispatchkit/operators.hpp"
|
||||||
//#include "dispatchkit/boxed_value.hpp"
|
//#include "dispatchkit/boxed_value.hpp"
|
||||||
#include "language/chaiscript_prelude.hpp"
|
|
||||||
#include "dispatchkit/register_function.hpp"
|
#include "dispatchkit/register_function.hpp"
|
||||||
|
#include "language/chaiscript_prelude.hpp"
|
||||||
#include "utility/json_wrap.hpp"
|
#include "utility/json_wrap.hpp"
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_NO_THREADS
|
#ifndef CHAISCRIPT_NO_THREADS
|
||||||
#include <future>
|
#include <future>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/// @file
|
/// @file
|
||||||
///
|
///
|
||||||
/// This file generates the standard library that normal ChaiScript usage requires.
|
/// This file generates the standard library that normal ChaiScript usage requires.
|
||||||
|
|
||||||
namespace chaiscript
|
namespace chaiscript {
|
||||||
{
|
class Std_Lib {
|
||||||
class Std_Lib
|
public:
|
||||||
{
|
[[nodiscard]] static ModulePtr library() {
|
||||||
public:
|
auto lib = std::make_shared<Module>();
|
||||||
|
bootstrap::Bootstrap::bootstrap(*lib);
|
||||||
|
|
||||||
[[nodiscard]] static ModulePtr library()
|
bootstrap::standard_library::vector_type<std::vector<Boxed_Value>>("Vector", *lib);
|
||||||
{
|
bootstrap::standard_library::string_type<std::string>("string", *lib);
|
||||||
auto lib = std::make_shared<Module>();
|
bootstrap::standard_library::map_type<std::map<std::string, Boxed_Value>>("Map", *lib);
|
||||||
bootstrap::Bootstrap::bootstrap(*lib);
|
bootstrap::standard_library::pair_type<std::pair<Boxed_Value, Boxed_Value>>("Pair", *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);
|
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_NO_THREADS
|
#ifndef CHAISCRIPT_NO_THREADS
|
||||||
bootstrap::standard_library::future_type<std::future<chaiscript::Boxed_Value>>("future", *lib);
|
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
|
#endif
|
||||||
|
|
||||||
json_wrap::library(*lib);
|
json_wrap::library(*lib);
|
||||||
|
|
||||||
lib->eval(ChaiScript_Prelude::chaiscript_prelude() /*, "standard prelude"*/ );
|
lib->eval(ChaiScript_Prelude::chaiscript_prelude() /*, "standard prelude"*/);
|
||||||
|
|
||||||
return lib;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
return lib;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
} // namespace chaiscript
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@ -7,20 +7,18 @@
|
|||||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
// 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
|
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||||
|
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_THREADING_HPP_
|
#ifndef CHAISCRIPT_THREADING_HPP_
|
||||||
#define CHAISCRIPT_THREADING_HPP_
|
#define CHAISCRIPT_THREADING_HPP_
|
||||||
|
|
||||||
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_NO_THREADS
|
#ifndef CHAISCRIPT_NO_THREADS
|
||||||
#include <thread>
|
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <shared_mutex>
|
#include <shared_mutex>
|
||||||
|
#include <thread>
|
||||||
#else
|
#else
|
||||||
#ifndef CHAISCRIPT_NO_THREADS_WARNING
|
#ifndef CHAISCRIPT_NO_THREADS_WARNING
|
||||||
#pragma message ("ChaiScript is compiling without thread safety.")
|
#pragma message("ChaiScript is compiling without thread safety.")
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -34,143 +32,102 @@
|
|||||||
/// It also has the side effect that the chaiscript::ChaiScript object may not be accessed from more than
|
/// It also has the side effect that the chaiscript::ChaiScript object may not be accessed from more than
|
||||||
/// one thread simultaneously.
|
/// one thread simultaneously.
|
||||||
|
|
||||||
namespace chaiscript
|
/// 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.
|
||||||
namespace detail
|
/// This allows us to avoid \#ifdef code in the sections that need thread safety.
|
||||||
{
|
namespace chaiscript::detail::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 threading
|
|
||||||
{
|
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_NO_THREADS
|
#ifndef CHAISCRIPT_NO_THREADS
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
using unique_lock = std::unique_lock<T>;
|
using unique_lock = std::unique_lock<T>;
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
using shared_lock = std::shared_lock<T>;
|
using shared_lock = std::shared_lock<T>;
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
using lock_guard = std::lock_guard<T>;
|
using lock_guard = std::lock_guard<T>;
|
||||||
|
|
||||||
|
using std::shared_mutex;
|
||||||
|
|
||||||
using std::shared_mutex;
|
using std::mutex;
|
||||||
|
|
||||||
using std::mutex;
|
using std::recursive_mutex;
|
||||||
|
|
||||||
using std::recursive_mutex;
|
/// 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 {
|
||||||
|
public:
|
||||||
|
Thread_Storage() = default;
|
||||||
|
Thread_Storage(const Thread_Storage &) = delete;
|
||||||
|
Thread_Storage(Thread_Storage &&) = delete;
|
||||||
|
Thread_Storage &operator=(const Thread_Storage &) = delete;
|
||||||
|
Thread_Storage &operator=(Thread_Storage &&) = delete;
|
||||||
|
|
||||||
/// Typesafe thread specific storage. If threading is enabled, this class uses a mutex protected map. If
|
~Thread_Storage() { t().erase(this); }
|
||||||
/// 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
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Thread_Storage() = default;
|
|
||||||
Thread_Storage(const Thread_Storage &) = delete;
|
|
||||||
Thread_Storage(Thread_Storage &&) = delete;
|
|
||||||
Thread_Storage &operator=(const Thread_Storage &) = delete;
|
|
||||||
Thread_Storage &operator=(Thread_Storage &&) = delete;
|
|
||||||
|
|
||||||
~Thread_Storage()
|
inline const T *operator->() const noexcept { return &(t()[this]); }
|
||||||
{
|
|
||||||
t().erase(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const T *operator->() const noexcept
|
inline const T &operator*() const noexcept { return t()[this]; }
|
||||||
{
|
|
||||||
return &(t()[this]);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const T &operator*() const noexcept
|
inline T *operator->() noexcept { return &(t()[this]); }
|
||||||
{
|
|
||||||
return t()[this];
|
|
||||||
}
|
|
||||||
|
|
||||||
inline T *operator->() noexcept
|
inline T &operator*() noexcept { return t()[this]; }
|
||||||
{
|
|
||||||
return &(t()[this]);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline T &operator*() noexcept
|
void *m_key;
|
||||||
{
|
|
||||||
return t()[this];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
private:
|
||||||
void *m_key;
|
/// todo: is it valid to make this noexcept? The allocation could fail, but if it
|
||||||
|
/// does there is no possible way to recover
|
||||||
private:
|
static std::unordered_map<const void *, T> &t() noexcept {
|
||||||
/// todo: is it valid to make this noexcept? The allocation could fail, but if it
|
static thread_local std::unordered_map<const void *, T> my_t;
|
||||||
/// does there is no possible way to recover
|
return my_t;
|
||||||
static std::unordered_map<const void*, T> &t() noexcept
|
}
|
||||||
{
|
};
|
||||||
static thread_local std::unordered_map<const void *, T> my_t;
|
|
||||||
return my_t;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#else // threading disabled
|
#else // threading disabled
|
||||||
template<typename T>
|
template<typename T>
|
||||||
class unique_lock
|
class unique_lock {
|
||||||
{
|
public:
|
||||||
public:
|
constexpr explicit unique_lock(T &) noexcept {}
|
||||||
constexpr explicit unique_lock(T &) noexcept {}
|
constexpr void lock() noexcept {}
|
||||||
constexpr void lock() noexcept {}
|
constexpr void unlock() noexcept {}
|
||||||
constexpr void unlock() noexcept {}
|
};
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
class shared_lock
|
class shared_lock {
|
||||||
{
|
public:
|
||||||
public:
|
constexpr explicit shared_lock(T &) noexcept {}
|
||||||
constexpr explicit shared_lock(T &) noexcept {}
|
constexpr void lock() noexcept {}
|
||||||
constexpr void lock() noexcept {}
|
constexpr void unlock() noexcept {}
|
||||||
constexpr void unlock() noexcept {}
|
};
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
class lock_guard
|
class lock_guard {
|
||||||
{
|
public:
|
||||||
public:
|
constexpr explicit lock_guard(T &) noexcept {}
|
||||||
constexpr explicit lock_guard(T &) noexcept {}
|
};
|
||||||
};
|
|
||||||
|
|
||||||
class shared_mutex { };
|
class shared_mutex {
|
||||||
|
};
|
||||||
|
|
||||||
class recursive_mutex {};
|
class recursive_mutex {
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
class Thread_Storage {
|
||||||
|
public:
|
||||||
|
constexpr explicit Thread_Storage() noexcept {}
|
||||||
|
|
||||||
template<typename T>
|
constexpr inline T *operator->() const noexcept { return &obj; }
|
||||||
class Thread_Storage
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
constexpr explicit Thread_Storage() noexcept
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr inline T *operator->() const noexcept
|
constexpr inline T &operator*() const noexcept { return obj; }
|
||||||
{
|
|
||||||
return &obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr inline T &operator*() const noexcept
|
private:
|
||||||
{
|
mutable T obj;
|
||||||
return obj;
|
};
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
mutable T obj;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
}
|
} // namespace chaiscript::detail::threading
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@ -11,139 +11,105 @@
|
|||||||
|
|
||||||
namespace chaiscript {
|
namespace chaiscript {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
namespace exception
|
namespace exception {
|
||||||
{
|
|
||||||
/// \brief Thrown in the event that an Any cannot be cast to the desired type
|
/// \brief Thrown in the event that an Any cannot be cast to the desired type
|
||||||
///
|
///
|
||||||
/// It is used internally during function dispatch.
|
/// It is used internally during function dispatch.
|
||||||
///
|
///
|
||||||
/// \sa chaiscript::detail::Any
|
/// \sa chaiscript::detail::Any
|
||||||
class bad_any_cast : public std::bad_cast
|
class bad_any_cast : public std::bad_cast {
|
||||||
{
|
public:
|
||||||
public:
|
/// \brief Description of what error occurred
|
||||||
/// \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 {
|
class Any {
|
||||||
private:
|
private:
|
||||||
struct Data
|
struct Data {
|
||||||
{
|
constexpr explicit Data(const std::type_info &t_type) noexcept
|
||||||
constexpr explicit Data(const std::type_info &t_type) noexcept
|
: m_type(t_type) {
|
||||||
: m_type(t_type)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
Data &operator=(const Data &) = delete;
|
|
||||||
|
|
||||||
virtual ~Data() noexcept = default;
|
|
||||||
|
|
||||||
virtual void *data() noexcept = 0;
|
|
||||||
|
|
||||||
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
|
|
||||||
{
|
|
||||||
explicit Data_Impl(T t_type)
|
|
||||||
: Data(typeid(T)),
|
|
||||||
m_data(std::move(t_type))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void *data() noexcept override
|
|
||||||
{
|
|
||||||
return &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;
|
|
||||||
|
|
||||||
T m_data;
|
|
||||||
};
|
|
||||||
|
|
||||||
std::unique_ptr<Data> m_data;
|
|
||||||
|
|
||||||
public:
|
|
||||||
// construct/copy/destruct
|
|
||||||
constexpr Any() noexcept = default;
|
|
||||||
Any(Any &&) noexcept = default;
|
|
||||||
Any &operator=(Any &&t_any) = default;
|
|
||||||
|
|
||||||
Any(const Any &t_any)
|
|
||||||
: m_data(t_any.empty() ? nullptr : t_any.m_data->clone())
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename ValueType,
|
Data &operator=(const Data &) = delete;
|
||||||
typename = std::enable_if_t<!std::is_same_v<Any, std::decay_t<ValueType>>>>
|
|
||||||
explicit Any(ValueType &&t_value)
|
virtual ~Data() noexcept = default;
|
||||||
: m_data(std::make_unique<Data_Impl<std::decay_t<ValueType>>>(std::forward<ValueType>(t_value)))
|
|
||||||
{
|
virtual void *data() noexcept = 0;
|
||||||
|
|
||||||
|
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 {
|
||||||
|
explicit Data_Impl(T t_type)
|
||||||
|
: Data(typeid(T))
|
||||||
|
, m_data(std::move(t_type)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void *data() noexcept override { return &m_data; }
|
||||||
|
|
||||||
Any & operator=(const Any &t_any)
|
std::unique_ptr<Data> clone() const override { return std::make_unique<Data_Impl<T>>(m_data); }
|
||||||
{
|
|
||||||
Any copy(t_any);
|
Data_Impl &operator=(const Data_Impl &) = delete;
|
||||||
swap(copy);
|
|
||||||
return *this;
|
T m_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::unique_ptr<Data> m_data;
|
||||||
|
|
||||||
|
public:
|
||||||
|
// construct/copy/destruct
|
||||||
|
constexpr Any() noexcept = default;
|
||||||
|
Any(Any &&) noexcept = default;
|
||||||
|
Any &operator=(Any &&t_any) = default;
|
||||||
|
|
||||||
|
Any(const Any &t_any)
|
||||||
|
: 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>>>>
|
||||||
|
explicit Any(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 copy(t_any);
|
||||||
|
swap(copy);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ToType>
|
||||||
|
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();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
template<typename ToType>
|
// modifiers
|
||||||
ToType &cast() const
|
Any &swap(Any &t_other) {
|
||||||
{
|
std::swap(t_other.m_data, m_data);
|
||||||
if (m_data && typeid(ToType) == m_data->type())
|
return *this;
|
||||||
{
|
}
|
||||||
return *static_cast<ToType *>(m_data->data());
|
|
||||||
} else {
|
|
||||||
throw chaiscript::detail::exception::bad_any_cast();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// queries
|
||||||
|
bool empty() const noexcept { return !static_cast<bool>(m_data); }
|
||||||
|
|
||||||
// modifiers
|
const std::type_info &type() const noexcept {
|
||||||
Any & swap(Any &t_other)
|
if (m_data) {
|
||||||
{
|
return m_data->type();
|
||||||
std::swap(t_other.m_data, m_data);
|
} else {
|
||||||
return *this;
|
return typeid(void);
|
||||||
}
|
|
||||||
|
|
||||||
// queries
|
|
||||||
bool empty() const noexcept
|
|
||||||
{
|
|
||||||
return !static_cast<bool>(m_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::type_info & type() const noexcept
|
|
||||||
{
|
|
||||||
if (m_data) {
|
|
||||||
return m_data->type();
|
|
||||||
} else {
|
|
||||||
return typeid(void);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
} // namespace detail
|
||||||
}
|
} // namespace chaiscript
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -7,7 +7,6 @@
|
|||||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
// 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
|
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||||
|
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_BAD_BOXED_CAST_HPP_
|
#ifndef CHAISCRIPT_BAD_BOXED_CAST_HPP_
|
||||||
#define CHAISCRIPT_BAD_BOXED_CAST_HPP_
|
#define CHAISCRIPT_BAD_BOXED_CAST_HPP_
|
||||||
|
|
||||||
@ -19,56 +18,47 @@
|
|||||||
#include "type_info.hpp"
|
#include "type_info.hpp"
|
||||||
|
|
||||||
namespace chaiscript {
|
namespace chaiscript {
|
||||||
class Type_Info;
|
class Type_Info;
|
||||||
} // namespace chaiscript
|
} // namespace chaiscript
|
||||||
|
|
||||||
namespace chaiscript
|
namespace chaiscript {
|
||||||
{
|
namespace exception {
|
||||||
namespace exception
|
|
||||||
{
|
|
||||||
/// \brief Thrown in the event that a Boxed_Value cannot be cast to the desired type
|
/// \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.
|
/// It is used internally during function dispatch and may be used by the end user.
|
||||||
///
|
///
|
||||||
/// \sa chaiscript::boxed_cast
|
/// \sa chaiscript::boxed_cast
|
||||||
class bad_boxed_cast : public std::bad_cast
|
class bad_boxed_cast : public std::bad_cast {
|
||||||
{
|
public:
|
||||||
public:
|
bad_boxed_cast(Type_Info t_from, const std::type_info &t_to, utility::Static_String t_what) noexcept
|
||||||
bad_boxed_cast(Type_Info t_from, const std::type_info &t_to,
|
: from(t_from)
|
||||||
utility::Static_String t_what) noexcept
|
, to(&t_to)
|
||||||
: from(t_from), to(&t_to), m_what(std::move(t_what))
|
, m_what(std::move(t_what)) {
|
||||||
{
|
}
|
||||||
}
|
|
||||||
|
|
||||||
bad_boxed_cast(Type_Info t_from, const std::type_info &t_to) noexcept
|
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
|
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(const bad_boxed_cast &) noexcept = default;
|
||||||
~bad_boxed_cast() noexcept override = default;
|
~bad_boxed_cast() noexcept override = default;
|
||||||
|
|
||||||
/// \brief Description of what error occurred
|
/// \brief Description of what error occurred
|
||||||
const char * what() const noexcept override
|
const char *what() const noexcept override { return m_what.c_str(); }
|
||||||
{
|
|
||||||
return m_what.c_str();
|
|
||||||
}
|
|
||||||
|
|
||||||
Type_Info from; ///< Type_Info contained in the Boxed_Value
|
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
|
const std::type_info *to = nullptr; ///< std::type_info of the desired (but failed) result type
|
||||||
|
|
||||||
private:
|
private:
|
||||||
utility::Static_String m_what;
|
utility::Static_String m_what;
|
||||||
};
|
};
|
||||||
}
|
} // namespace exception
|
||||||
}
|
} // namespace chaiscript
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@ -7,79 +7,54 @@
|
|||||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
// 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
|
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||||
|
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_BIND_FIRST_HPP_
|
#ifndef CHAISCRIPT_BIND_FIRST_HPP_
|
||||||
#define CHAISCRIPT_BIND_FIRST_HPP_
|
#define CHAISCRIPT_BIND_FIRST_HPP_
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
namespace chaiscript
|
namespace chaiscript {
|
||||||
{
|
namespace detail {
|
||||||
namespace detail
|
template<typename T>
|
||||||
{
|
constexpr T *get_pointer(T *t) noexcept {
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
constexpr T* get_pointer(T *t) noexcept
|
T *get_pointer(const std::reference_wrapper<T> &t) noexcept {
|
||||||
{
|
return &t.get();
|
||||||
return t;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename O, typename Ret, typename P1, typename... Param>
|
||||||
T* get_pointer(const std::reference_wrapper<T> &t) noexcept
|
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)...); };
|
||||||
return &t.get();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
template<typename O, typename Ret, typename P1, typename ... Param>
|
template<typename O, typename Ret, typename Class, typename... Param>
|
||||||
constexpr auto bind_first(Ret (*f)(P1, Param...), O&& o)
|
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)...); };
|
||||||
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>
|
template<typename O, typename Ret, typename Class, typename... Param>
|
||||||
constexpr auto bind_first(Ret (Class::*f)(Param...), O&& o)
|
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)...); };
|
||||||
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>
|
template<typename O, typename Ret, typename P1, typename... Param>
|
||||||
constexpr auto bind_first(Ret (Class::*f)(Param...) const, O&& o)
|
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)...); };
|
||||||
return [f, o = std::forward<O>(o)](Param...param) -> Ret {
|
}
|
||||||
return (get_pointer(o)->*f)(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) {
|
||||||
template<typename O, typename Ret, typename P1, typename ... Param>
|
return [fo, o = std::forward<O>(o), f](Param... param) -> Ret { return (fo.*f)(o, std::forward<Param>(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>
|
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());
|
||||||
return bind_first(f, std::forward<O>(o), &F::operator());
|
}
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
} // namespace chaiscript
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -7,381 +7,327 @@
|
|||||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
// 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
|
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||||
|
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_BOOTSTRAP_HPP_
|
#ifndef CHAISCRIPT_BOOTSTRAP_HPP_
|
||||||
#define CHAISCRIPT_BOOTSTRAP_HPP_
|
#define CHAISCRIPT_BOOTSTRAP_HPP_
|
||||||
|
|
||||||
#include "../utility/utility.hpp"
|
#include "../utility/utility.hpp"
|
||||||
#include "register_function.hpp"
|
#include "register_function.hpp"
|
||||||
|
|
||||||
namespace chaiscript
|
/// \brief Classes and functions useful for bootstrapping of ChaiScript and adding of new types
|
||||||
{
|
namespace chaiscript::bootstrap {
|
||||||
/// \brief Classes and functions useful for bootstrapping of ChaiScript and adding of new types
|
template<typename T, typename = typename std::enable_if<std::is_array<T>::value>::type>
|
||||||
namespace bootstrap
|
void array(const std::string &type, Module &m) {
|
||||||
{
|
using ReturnType = typename std::remove_extent<T>::type;
|
||||||
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(user_type<T>(), type);
|
||||||
m.add(fun(
|
m.add(fun([](T &t, size_t index) -> ReturnType & {
|
||||||
[](T& t, size_t index)->ReturnType &{
|
constexpr const auto extent = std::extent<T>::value;
|
||||||
constexpr const auto extent = std::extent<T>::value;
|
if (extent > 0 && index >= extent) {
|
||||||
if (extent > 0 && index >= extent) {
|
throw std::range_error("Array index out of range. Received: " + std::to_string(index) + " expected < "
|
||||||
throw std::range_error("Array index out of range. Received: " + std::to_string(index) + " expected < " + std::to_string(extent));
|
+ std::to_string(extent));
|
||||||
} else {
|
} else {
|
||||||
return t[index];
|
return t[index];
|
||||||
}
|
}
|
||||||
}
|
}),
|
||||||
), "[]"
|
"[]");
|
||||||
);
|
|
||||||
|
|
||||||
m.add(fun(
|
m.add(fun([](const T &t, size_t index) -> const ReturnType & {
|
||||||
[](const T &t, size_t index)->const ReturnType &{
|
constexpr const auto extent = std::extent<T>::value;
|
||||||
constexpr const auto extent = std::extent<T>::value;
|
if (extent > 0 && index >= extent) {
|
||||||
if (extent > 0 && index >= extent) {
|
throw std::range_error("Array index out of range. Received: " + std::to_string(index) + " expected < "
|
||||||
throw std::range_error("Array index out of range. Received: " + std::to_string(index) + " expected < " + std::to_string(extent));
|
+ std::to_string(extent));
|
||||||
} else {
|
} else {
|
||||||
return t[index];
|
return t[index];
|
||||||
}
|
}
|
||||||
}
|
}),
|
||||||
), "[]"
|
"[]");
|
||||||
);
|
|
||||||
|
|
||||||
m.add(fun(
|
m.add(fun([](const T &) { return std::extent<T>::value; }), "size");
|
||||||
[](const T &) {
|
}
|
||||||
return std::extent<T>::value;
|
|
||||||
}), "size");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// \brief Adds a copy constructor for the given type to the given Model
|
/// \brief Adds a copy constructor for the given type to the given Model
|
||||||
/// \param[in] type The name of the type. The copy constructor will be named "type".
|
/// \param[in] type The name of the type. The copy constructor will be named "type".
|
||||||
/// \param[in,out] m The Module to add the copy constructor to
|
/// \param[in,out] m The Module to add the copy constructor to
|
||||||
/// \tparam T The type to add a copy constructor for
|
/// \tparam T The type to add a copy constructor for
|
||||||
/// \returns The passed in Module
|
/// \returns The passed in Module
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void copy_constructor(const std::string &type, Module& m)
|
void copy_constructor(const std::string &type, Module &m) {
|
||||||
{
|
m.add(constructor<T(const T &)>(), type);
|
||||||
m.add(constructor<T (const T &)>(), type);
|
}
|
||||||
|
|
||||||
|
/// \brief Add all comparison operators for the templated type. Used during bootstrap, also available to users.
|
||||||
|
/// \tparam T Type to create comparison operators for
|
||||||
|
/// \param[in,out] m module to add comparison operators to
|
||||||
|
/// \returns the passed in Module.
|
||||||
|
template<typename T>
|
||||||
|
void opers_comparison(Module &m) {
|
||||||
|
operators::equal<T>(m);
|
||||||
|
operators::greater_than<T>(m);
|
||||||
|
operators::greater_than_equal<T>(m);
|
||||||
|
operators::less_than<T>(m);
|
||||||
|
operators::less_than_equal<T>(m);
|
||||||
|
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
|
||||||
|
/// \tparam T Type to generate basic constructors for
|
||||||
|
/// \returns The passed in Module
|
||||||
|
/// \sa copy_constructor
|
||||||
|
/// \sa constructor
|
||||||
|
template<typename T>
|
||||||
|
void basic_constructors(const std::string &type, Module &m) {
|
||||||
|
m.add(constructor<T()>(), type);
|
||||||
|
copy_constructor<T>(type, m);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \brief Adds a constructor for a POD type
|
||||||
|
/// \tparam T The type to add the constructor for
|
||||||
|
/// \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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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) {
|
||||||
|
std::stringstream ss(i);
|
||||||
|
Input t;
|
||||||
|
ss >> t;
|
||||||
|
return t;
|
||||||
|
} else {
|
||||||
|
throw std::runtime_error("Parsing of wide characters is not yet supported");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// \brief Add all comparison operators for the templated type. Used during bootstrap, also available to users.
|
/// Add all common functions for a POD type. All operators, and
|
||||||
/// \tparam T Type to create comparison operators for
|
/// common conversions
|
||||||
/// \param[in,out] m module to add comparison operators to
|
template<typename T>
|
||||||
/// \returns the passed in Module.
|
void bootstrap_pod_type(const std::string &name, Module &m) {
|
||||||
template<typename T>
|
m.add(user_type<T>(), name);
|
||||||
void opers_comparison(Module& m)
|
m.add(constructor<T()>(), name);
|
||||||
{
|
construct_pod<T>(name, m);
|
||||||
operators::equal<T>(m);
|
|
||||||
operators::greater_than<T>(m);
|
m.add(fun(&parse_string<T>), "to_" + name);
|
||||||
operators::greater_than_equal<T>(m);
|
m.add(fun([](const T t) { return t; }), "to_" + name);
|
||||||
operators::less_than<T>(m);
|
}
|
||||||
operators::less_than_equal<T>(m);
|
|
||||||
operators::not_equal<T>(m);
|
/// "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) {
|
||||||
|
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) {
|
||||||
|
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()))) {
|
||||||
|
lhs.assign(Boxed_Value(rhs));
|
||||||
|
return lhs;
|
||||||
|
} else {
|
||||||
|
throw exception::bad_boxed_cast("type mismatch in pointer assignment");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Class consisting of only static functions. All default bootstrapping occurs
|
||||||
|
/// from this class.
|
||||||
/// \brief Adds default and copy constructors for the given type
|
class Bootstrap {
|
||||||
/// \param[in] type The name of the type to add the constructors for.
|
private:
|
||||||
/// \param[in,out] m The Module to add the basic constructors to
|
/// Function allowing for assignment of an unknown type to any other value
|
||||||
/// \tparam T Type to generate basic constructors for
|
static Boxed_Value unknown_assign(Boxed_Value lhs, Boxed_Value rhs) {
|
||||||
/// \returns The passed in Module
|
if (lhs.is_undef()) {
|
||||||
/// \sa copy_constructor
|
return (lhs.assign(rhs));
|
||||||
/// \sa constructor
|
|
||||||
template<typename T>
|
|
||||||
void basic_constructors(const std::string &type, Module& m)
|
|
||||||
{
|
|
||||||
m.add(constructor<T ()>(), type);
|
|
||||||
copy_constructor<T>(type, m);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// \brief Adds a constructor for a POD type
|
|
||||||
/// \tparam T The type to add the constructor for
|
|
||||||
/// \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);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// 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) {
|
|
||||||
std::stringstream ss(i);
|
|
||||||
Input t;
|
|
||||||
ss >> t;
|
|
||||||
return t;
|
|
||||||
} else {
|
} else {
|
||||||
throw std::runtime_error("Parsing of wide characters is not yet supported");
|
throw exception::bad_boxed_cast("boxed_value has a set type already");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add all common functions for a POD type. All operators, and
|
static void print(const std::string &s) noexcept { fwrite(s.c_str(), 1, s.size(), stdout); }
|
||||||
/// common conversions
|
|
||||||
template<typename T>
|
|
||||||
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);
|
static void println(const std::string &s) noexcept { puts(s.c_str()); }
|
||||||
m.add(fun([](const T t){ return t; }), "to_" + name);
|
|
||||||
|
/// Add all arithmetic operators for PODs
|
||||||
|
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), ">");
|
||||||
|
m.add(fun(&Boxed_Number::greater_than_equal), ">=");
|
||||||
|
m.add(fun(&Boxed_Number::less_than_equal), "<=");
|
||||||
|
m.add(fun(&Boxed_Number::not_equal), "!=");
|
||||||
|
|
||||||
|
m.add(fun(&Boxed_Number::pre_decrement), "--");
|
||||||
|
m.add(fun(&Boxed_Number::pre_increment), "++");
|
||||||
|
m.add(fun(&Boxed_Number::sum), "+");
|
||||||
|
m.add(fun(&Boxed_Number::unary_plus), "+");
|
||||||
|
m.add(fun(&Boxed_Number::unary_minus), "-");
|
||||||
|
m.add(fun(&Boxed_Number::difference), "-");
|
||||||
|
m.add(fun(&Boxed_Number::assign_bitwise_and), "&=");
|
||||||
|
m.add(fun(&Boxed_Number::assign), "=");
|
||||||
|
m.add(fun(&Boxed_Number::assign_bitwise_or), "|=");
|
||||||
|
m.add(fun(&Boxed_Number::assign_bitwise_xor), "^=");
|
||||||
|
m.add(fun(&Boxed_Number::assign_remainder), "%=");
|
||||||
|
m.add(fun(&Boxed_Number::assign_shift_left), "<<=");
|
||||||
|
m.add(fun(&Boxed_Number::assign_shift_right), ">>=");
|
||||||
|
m.add(fun(&Boxed_Number::bitwise_and), "&");
|
||||||
|
m.add(fun(&Boxed_Number::bitwise_complement), "~");
|
||||||
|
m.add(fun(&Boxed_Number::bitwise_xor), "^");
|
||||||
|
m.add(fun(&Boxed_Number::bitwise_or), "|");
|
||||||
|
m.add(fun(&Boxed_Number::assign_product), "*=");
|
||||||
|
m.add(fun(&Boxed_Number::assign_quotient), "/=");
|
||||||
|
m.add(fun(&Boxed_Number::assign_sum), "+=");
|
||||||
|
m.add(fun(&Boxed_Number::assign_difference), "-=");
|
||||||
|
m.add(fun(&Boxed_Number::quotient), "/");
|
||||||
|
m.add(fun(&Boxed_Number::shift_left), "<<");
|
||||||
|
m.add(fun(&Boxed_Number::product), "*");
|
||||||
|
m.add(fun(&Boxed_Number::remainder), "%");
|
||||||
|
m.add(fun(&Boxed_Number::shift_right), ">>");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 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) {
|
||||||
|
if (params.empty()) {
|
||||||
|
throw exception::arity_error(0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
/// "clone" function for a shared_ptr type. This is used in the case
|
Const_Proxy_Function f = boxed_cast<Const_Proxy_Function>(params[0]);
|
||||||
/// 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
|
if (f->get_arity() != -1 && size_t(f->get_arity()) != params.size() - 1) {
|
||||||
/// for handling of Proxy_Function object (that is,
|
throw exception::arity_error(static_cast<int>(params.size()), f->get_arity());
|
||||||
/// function variables.
|
}
|
||||||
template<typename Type>
|
|
||||||
auto shared_ptr_clone(const std::shared_ptr<Type> &p)
|
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 p;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Specific version of shared_ptr_clone just for Proxy_Functions
|
static bool has_guard(const Const_Proxy_Function &t_pf) noexcept {
|
||||||
template<typename Type>
|
auto pf = std::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(t_pf);
|
||||||
std::shared_ptr<std::remove_const_t<Type>> shared_ptr_unconst_clone(const std::shared_ptr<std::add_const_t<Type>> &p)
|
return pf && pf->has_guard();
|
||||||
{
|
|
||||||
return std::const_pointer_cast<typename std::remove_const<Type>::type>(p);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
/// Assignment function for shared_ptr objects, does not perform a copy of the
|
if (pf && pf->get_guard()) {
|
||||||
/// object pointed to, instead maintains the shared_ptr concept.
|
return pf->get_guard();
|
||||||
/// 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())))
|
|
||||||
{
|
|
||||||
lhs.assign(Boxed_Value(rhs));
|
|
||||||
return lhs;
|
|
||||||
} else {
|
} else {
|
||||||
throw exception::bad_boxed_cast("type mismatch in pointer assignment");
|
throw std::runtime_error("Function does not have a guard");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Class consisting of only static functions. All default bootstrapping occurs
|
template<typename FunctionType>
|
||||||
/// from this class.
|
static std::vector<Boxed_Value> do_return_boxed_value_vector(FunctionType f, const dispatch::Proxy_Function_Base *b) {
|
||||||
class Bootstrap
|
auto v = (b->*f)();
|
||||||
{
|
|
||||||
private:
|
std::vector<Boxed_Value> vbv;
|
||||||
/// Function allowing for assignment of an unknown type to any other value
|
|
||||||
static Boxed_Value unknown_assign(Boxed_Value lhs, Boxed_Value rhs)
|
for (const auto &o : v) {
|
||||||
{
|
vbv.push_back(const_var(o));
|
||||||
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
|
return vbv;
|
||||||
{
|
}
|
||||||
fwrite(s.c_str(), 1, s.size(), stdout);
|
|
||||||
|
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) {
|
||||||
|
const auto pf = std::dynamic_pointer_cast<const chaiscript::dispatch::Dynamic_Proxy_Function>(t_pf);
|
||||||
|
if (pf) {
|
||||||
|
return pf->get_parse_tree();
|
||||||
|
} else {
|
||||||
|
throw std::runtime_error("Function does not have a parse tree");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void println(const std::string &s) noexcept
|
template<typename Function>
|
||||||
{
|
static auto return_boxed_value_vector(const Function &f) {
|
||||||
puts(s.c_str());
|
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) {
|
||||||
|
m.add(user_type<void>(), "void");
|
||||||
|
m.add(user_type<bool>(), "bool");
|
||||||
|
m.add(user_type<Boxed_Value>(), "Object");
|
||||||
|
m.add(user_type<Boxed_Number>(), "Number");
|
||||||
|
m.add(user_type<Proxy_Function>(), "Function");
|
||||||
|
m.add(user_type<dispatch::Assignable_Proxy_Function>(), "Assignable_Function");
|
||||||
|
m.add(user_type<std::exception>(), "exception");
|
||||||
|
|
||||||
/// Add all arithmetic operators for PODs
|
m.add(fun(&dispatch::Proxy_Function_Base::get_arity), "get_arity");
|
||||||
static void opers_arithmetic_pod(Module& m)
|
m.add(fun(&dispatch::Proxy_Function_Base::operator==), "==");
|
||||||
{
|
|
||||||
m.add(fun(&Boxed_Number::equals), "==");
|
|
||||||
m.add(fun(&Boxed_Number::less_than), "<");
|
|
||||||
m.add(fun(&Boxed_Number::greater_than), ">");
|
|
||||||
m.add(fun(&Boxed_Number::greater_than_equal), ">=");
|
|
||||||
m.add(fun(&Boxed_Number::less_than_equal), "<=");
|
|
||||||
m.add(fun(&Boxed_Number::not_equal), "!=");
|
|
||||||
|
|
||||||
m.add(fun(&Boxed_Number::pre_decrement), "--");
|
m.add(fun(return_boxed_value_vector(&dispatch::Proxy_Function_Base::get_param_types)), "get_param_types");
|
||||||
m.add(fun(&Boxed_Number::pre_increment), "++");
|
m.add(fun(return_boxed_value_vector(&dispatch::Proxy_Function_Base::get_contained_functions)), "get_contained_functions");
|
||||||
m.add(fun(&Boxed_Number::sum), "+");
|
|
||||||
m.add(fun(&Boxed_Number::unary_plus), "+");
|
|
||||||
m.add(fun(&Boxed_Number::unary_minus), "-");
|
|
||||||
m.add(fun(&Boxed_Number::difference), "-");
|
|
||||||
m.add(fun(&Boxed_Number::assign_bitwise_and), "&=");
|
|
||||||
m.add(fun(&Boxed_Number::assign), "=");
|
|
||||||
m.add(fun(&Boxed_Number::assign_bitwise_or), "|=");
|
|
||||||
m.add(fun(&Boxed_Number::assign_bitwise_xor), "^=");
|
|
||||||
m.add(fun(&Boxed_Number::assign_remainder), "%=");
|
|
||||||
m.add(fun(&Boxed_Number::assign_shift_left), "<<=");
|
|
||||||
m.add(fun(&Boxed_Number::assign_shift_right), ">>=");
|
|
||||||
m.add(fun(&Boxed_Number::bitwise_and), "&");
|
|
||||||
m.add(fun(&Boxed_Number::bitwise_complement), "~");
|
|
||||||
m.add(fun(&Boxed_Number::bitwise_xor), "^");
|
|
||||||
m.add(fun(&Boxed_Number::bitwise_or), "|");
|
|
||||||
m.add(fun(&Boxed_Number::assign_product), "*=");
|
|
||||||
m.add(fun(&Boxed_Number::assign_quotient), "/=");
|
|
||||||
m.add(fun(&Boxed_Number::assign_sum), "+=");
|
|
||||||
m.add(fun(&Boxed_Number::assign_difference), "-=");
|
|
||||||
m.add(fun(&Boxed_Number::quotient), "/");
|
|
||||||
m.add(fun(&Boxed_Number::shift_left), "<<");
|
|
||||||
m.add(fun(&Boxed_Number::product), "*");
|
|
||||||
m.add(fun(&Boxed_Number::remainder), "%");
|
|
||||||
m.add(fun(&Boxed_Number::shift_right), ">>");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create a bound function object. The first param is the function to bind
|
m.add(fun([](const std::exception &e) { return std::string(e.what()); }), "what");
|
||||||
/// the remaining parameters are the args to bind into the result
|
|
||||||
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]);
|
m.add(user_type<std::out_of_range>(), "out_of_range");
|
||||||
|
m.add(user_type<std::logic_error>(), "logic_error");
|
||||||
|
m.add(chaiscript::base_class<std::exception, std::logic_error>());
|
||||||
|
m.add(chaiscript::base_class<std::logic_error, std::out_of_range>());
|
||||||
|
m.add(chaiscript::base_class<std::exception, std::out_of_range>());
|
||||||
|
|
||||||
if (f->get_arity() != -1 && size_t(f->get_arity()) != params.size() - 1)
|
m.add(user_type<std::runtime_error>(), "runtime_error");
|
||||||
{
|
m.add(chaiscript::base_class<std::exception, std::runtime_error>());
|
||||||
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),
|
m.add(constructor<std::runtime_error(const std::string &)>(), "runtime_error");
|
||||||
std::vector<Boxed_Value>(params.begin() + 1, params.end()))));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
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(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");
|
||||||
|
|
||||||
static bool has_guard(const Const_Proxy_Function &t_pf) noexcept
|
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)),
|
||||||
auto pf = std::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(t_pf);
|
"get_attr");
|
||||||
return pf && pf->has_guard();
|
|
||||||
}
|
|
||||||
|
|
||||||
static Const_Proxy_Function get_guard(const Const_Proxy_Function &t_pf)
|
m.add(fun(static_cast<Boxed_Value &(dispatch::Dynamic_Object::*)(const std::string &)>(&dispatch::Dynamic_Object::method_missing)),
|
||||||
{
|
"method_missing");
|
||||||
const auto pf = std::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(t_pf);
|
m.add(fun(static_cast<const Boxed_Value &(dispatch::Dynamic_Object::*)(const std::string &) const>(
|
||||||
if (pf && pf->get_guard())
|
&dispatch::Dynamic_Object::method_missing)),
|
||||||
{
|
"method_missing");
|
||||||
return pf->get_guard();
|
|
||||||
} else {
|
|
||||||
throw std::runtime_error("Function does not have a guard");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename FunctionType>
|
m.add(fun(static_cast<Boxed_Value &(dispatch::Dynamic_Object::*)(const std::string &)>(&dispatch::Dynamic_Object::get_attr)), "[]");
|
||||||
static std::vector<Boxed_Value> do_return_boxed_value_vector(FunctionType f,
|
m.add(fun(static_cast<const Boxed_Value &(dispatch::Dynamic_Object::*)(const std::string &) const>(&dispatch::Dynamic_Object::get_attr)),
|
||||||
const dispatch::Proxy_Function_Base *b)
|
"[]");
|
||||||
{
|
|
||||||
auto v = (b->*f)();
|
|
||||||
|
|
||||||
std::vector<Boxed_Value> vbv;
|
|
||||||
|
|
||||||
for (const auto &o: v)
|
m.eval(R"chaiscript(
|
||||||
{
|
def Dynamic_Object::clone() {
|
||||||
vbv.push_back(const_var(o));
|
auto &new_o = Dynamic_Object(this.get_type_name());
|
||||||
}
|
for_each(this.get_attrs(), fun[new_o](x) { new_o.get_attr(x.first) = x.second; } );
|
||||||
|
new_o;
|
||||||
return vbv;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
const auto pf = std::dynamic_pointer_cast<const chaiscript::dispatch::Dynamic_Proxy_Function>(t_pf);
|
|
||||||
if (pf)
|
|
||||||
{
|
|
||||||
return pf->get_parse_tree();
|
|
||||||
} else {
|
|
||||||
throw std::runtime_error("Function does not have a parse tree");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
m.add(user_type<void>(), "void");
|
|
||||||
m.add(user_type<bool>(), "bool");
|
|
||||||
m.add(user_type<Boxed_Value>(), "Object");
|
|
||||||
m.add(user_type<Boxed_Number>(), "Number");
|
|
||||||
m.add(user_type<Proxy_Function>(), "Function");
|
|
||||||
m.add(user_type<dispatch::Assignable_Proxy_Function>(), "Assignable_Function");
|
|
||||||
m.add(user_type<std::exception>(), "exception");
|
|
||||||
|
|
||||||
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(user_type<std::out_of_range>(), "out_of_range");
|
|
||||||
m.add(user_type<std::logic_error>(), "logic_error");
|
|
||||||
m.add(chaiscript::base_class<std::exception, std::logic_error>());
|
|
||||||
m.add(chaiscript::base_class<std::logic_error, std::out_of_range>());
|
|
||||||
m.add(chaiscript::base_class<std::exception, std::out_of_range>());
|
|
||||||
|
|
||||||
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(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(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::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.eval(R"chaiscript(
|
|
||||||
def Dynamic_Object::clone() {
|
|
||||||
auto &new_o = Dynamic_Object(this.get_type_name());
|
|
||||||
for_each(this.get_attrs(), fun[new_o](x) { new_o.get_attr(x.first) = x.second; } );
|
|
||||||
new_o;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def `=`(Dynamic_Object lhs, Dynamic_Object rhs) : lhs.get_type_name() == rhs.get_type_name()
|
def `=`(Dynamic_Object lhs, Dynamic_Object rhs) : lhs.get_type_name() == rhs.get_type_name()
|
||||||
{
|
{
|
||||||
for_each(rhs.get_attrs(), fun[lhs](x) { lhs.get_attr(x.first) = clone(x.second); } );
|
for_each(rhs.get_attrs(), fun[lhs](x) { lhs.get_attr(x.first) = clone(x.second); } );
|
||||||
}
|
}
|
||||||
|
|
||||||
def `!=`(Dynamic_Object lhs, Dynamic_Object rhs) : lhs.get_type_name() == rhs.get_type_name()
|
def `!=`(Dynamic_Object lhs, Dynamic_Object rhs) : lhs.get_type_name() == rhs.get_type_name()
|
||||||
@ -409,173 +355,157 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
)chaiscript");
|
)chaiscript");
|
||||||
|
|
||||||
m.add(fun(&has_guard), "has_guard");
|
m.add(fun(&has_guard), "has_guard");
|
||||||
m.add(fun(&get_guard), "get_guard");
|
m.add(fun(&get_guard), "get_guard");
|
||||||
|
|
||||||
m.add(fun(&Boxed_Value::is_undef), "is_var_undef");
|
m.add(fun(&Boxed_Value::is_undef), "is_var_undef");
|
||||||
m.add(fun(&Boxed_Value::is_null), "is_var_null");
|
m.add(fun(&Boxed_Value::is_null), "is_var_null");
|
||||||
m.add(fun(&Boxed_Value::is_const), "is_var_const");
|
m.add(fun(&Boxed_Value::is_const), "is_var_const");
|
||||||
m.add(fun(&Boxed_Value::is_ref), "is_var_reference");
|
m.add(fun(&Boxed_Value::is_ref), "is_var_reference");
|
||||||
m.add(fun(&Boxed_Value::is_pointer), "is_var_pointer");
|
m.add(fun(&Boxed_Value::is_pointer), "is_var_pointer");
|
||||||
m.add(fun(&Boxed_Value::is_return_value), "is_var_return_value");
|
m.add(fun(&Boxed_Value::is_return_value), "is_var_return_value");
|
||||||
m.add(fun(&Boxed_Value::reset_return_value), "reset_var_return_value");
|
m.add(fun(&Boxed_Value::reset_return_value), "reset_var_return_value");
|
||||||
m.add(fun(&Boxed_Value::is_type), "is_type");
|
m.add(fun(&Boxed_Value::is_type), "is_type");
|
||||||
m.add(fun(&Boxed_Value::get_attr), "get_var_attr");
|
m.add(fun(&Boxed_Value::get_attr), "get_var_attr");
|
||||||
m.add(fun(&Boxed_Value::copy_attrs), "copy_var_attrs");
|
m.add(fun(&Boxed_Value::copy_attrs), "copy_var_attrs");
|
||||||
m.add(fun(&Boxed_Value::clone_attrs), "clone_var_attrs");
|
m.add(fun(&Boxed_Value::clone_attrs), "clone_var_attrs");
|
||||||
|
|
||||||
m.add(fun(&Boxed_Value::get_type_info), "get_type_info");
|
m.add(fun(&Boxed_Value::get_type_info), "get_type_info");
|
||||||
m.add(user_type<Type_Info>(), "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);
|
||||||
|
|
||||||
operators::equal<Type_Info>(m);
|
m.add(fun(&Type_Info::is_const), "is_type_const");
|
||||||
|
m.add(fun(&Type_Info::is_reference), "is_type_reference");
|
||||||
|
m.add(fun(&Type_Info::is_void), "is_type_void");
|
||||||
|
m.add(fun(&Type_Info::is_undef), "is_type_undef");
|
||||||
|
m.add(fun(&Type_Info::is_pointer), "is_type_pointer");
|
||||||
|
m.add(fun(&Type_Info::is_arithmetic), "is_type_arithmetic");
|
||||||
|
m.add(fun(&Type_Info::name), "cpp_name");
|
||||||
|
m.add(fun(&Type_Info::bare_name), "cpp_bare_name");
|
||||||
|
m.add(fun(&Type_Info::bare_equal), "bare_equal");
|
||||||
|
|
||||||
m.add(fun(&Type_Info::is_const), "is_type_const");
|
basic_constructors<bool>("bool", m);
|
||||||
m.add(fun(&Type_Info::is_reference), "is_type_reference");
|
operators::assign<bool>(m);
|
||||||
m.add(fun(&Type_Info::is_void), "is_type_void");
|
operators::equal<bool>(m);
|
||||||
m.add(fun(&Type_Info::is_undef), "is_type_undef");
|
operators::not_equal<bool>(m);
|
||||||
m.add(fun(&Type_Info::is_pointer), "is_type_pointer");
|
|
||||||
m.add(fun(&Type_Info::is_arithmetic), "is_type_arithmetic");
|
|
||||||
m.add(fun(&Type_Info::name), "cpp_name");
|
|
||||||
m.add(fun(&Type_Info::bare_name), "cpp_bare_name");
|
|
||||||
m.add(fun(&Type_Info::bare_equal), "bare_equal");
|
|
||||||
|
|
||||||
|
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(&unknown_assign), "=");
|
||||||
|
m.add(fun([](const Boxed_Value &bv) { throw bv; }), "throw");
|
||||||
|
|
||||||
basic_constructors<bool>("bool", m);
|
m.add(fun([](const char c) { return std::string(1, c); }), "to_string");
|
||||||
operators::assign<bool>(m);
|
m.add(fun(&Boxed_Number::to_string), "to_string");
|
||||||
operators::equal<bool>(m);
|
|
||||||
operators::not_equal<bool>(m);
|
|
||||||
|
|
||||||
m.add(fun([](const std::string &s) { return s; }), "to_string");
|
bootstrap_pod_type<double>("double", m);
|
||||||
m.add(fun([](const bool b) { return std::string(b?"true":"false"); }), "to_string");
|
bootstrap_pod_type<long double>("long_double", m);
|
||||||
m.add(fun(&unknown_assign), "=");
|
bootstrap_pod_type<float>("float", m);
|
||||||
m.add(fun([](const Boxed_Value &bv) { throw bv; }), "throw");
|
bootstrap_pod_type<int>("int", m);
|
||||||
|
bootstrap_pod_type<long>("long", m);
|
||||||
|
bootstrap_pod_type<unsigned int>("unsigned_int", m);
|
||||||
|
bootstrap_pod_type<unsigned long>("unsigned_long", m);
|
||||||
|
bootstrap_pod_type<long long>("long_long", m);
|
||||||
|
bootstrap_pod_type<unsigned long long>("unsigned_long_long", m);
|
||||||
|
bootstrap_pod_type<size_t>("size_t", m);
|
||||||
|
bootstrap_pod_type<char>("char", m);
|
||||||
|
bootstrap_pod_type<wchar_t>("wchar_t", m);
|
||||||
|
bootstrap_pod_type<char16_t>("char16_t", m);
|
||||||
|
bootstrap_pod_type<char32_t>("char32_t", m);
|
||||||
|
bootstrap_pod_type<std::int8_t>("int8_t", m);
|
||||||
|
bootstrap_pod_type<std::int16_t>("int16_t", m);
|
||||||
|
bootstrap_pod_type<std::int32_t>("int32_t", m);
|
||||||
|
bootstrap_pod_type<std::int64_t>("int64_t", m);
|
||||||
|
bootstrap_pod_type<std::uint8_t>("uint8_t", m);
|
||||||
|
bootstrap_pod_type<std::uint16_t>("uint16_t", m);
|
||||||
|
bootstrap_pod_type<std::uint32_t>("uint32_t", m);
|
||||||
|
bootstrap_pod_type<std::uint64_t>("uint64_t", m);
|
||||||
|
|
||||||
m.add(fun([](const char c) { return std::string(1, c); }), "to_string");
|
operators::logical_compliment<bool>(m);
|
||||||
m.add(fun(&Boxed_Number::to_string), "to_string");
|
|
||||||
|
|
||||||
|
opers_arithmetic_pod(m);
|
||||||
|
|
||||||
bootstrap_pod_type<double>("double", m);
|
m.add(fun(&Build_Info::version_major), "version_major");
|
||||||
bootstrap_pod_type<long double>("long_double", m);
|
m.add(fun(&Build_Info::version_minor), "version_minor");
|
||||||
bootstrap_pod_type<float>("float", m);
|
m.add(fun(&Build_Info::version_patch), "version_patch");
|
||||||
bootstrap_pod_type<int>("int", m);
|
m.add(fun(&Build_Info::version), "version");
|
||||||
bootstrap_pod_type<long>("long", m);
|
m.add(fun(&Build_Info::compiler_version), "compiler_version");
|
||||||
bootstrap_pod_type<unsigned int>("unsigned_int", m);
|
m.add(fun(&Build_Info::compiler_name), "compiler_name");
|
||||||
bootstrap_pod_type<unsigned long>("unsigned_long", m);
|
m.add(fun(&Build_Info::compiler_id), "compiler_id");
|
||||||
bootstrap_pod_type<long long>("long_long", m);
|
m.add(fun(&Build_Info::debug_build), "debug_build");
|
||||||
bootstrap_pod_type<unsigned long long>("unsigned_long_long", m);
|
|
||||||
bootstrap_pod_type<size_t>("size_t", m);
|
|
||||||
bootstrap_pod_type<char>("char", m);
|
|
||||||
bootstrap_pod_type<wchar_t>("wchar_t", m);
|
|
||||||
bootstrap_pod_type<char16_t>("char16_t", m);
|
|
||||||
bootstrap_pod_type<char32_t>("char32_t", m);
|
|
||||||
bootstrap_pod_type<std::int8_t>("int8_t", m);
|
|
||||||
bootstrap_pod_type<std::int16_t>("int16_t", m);
|
|
||||||
bootstrap_pod_type<std::int32_t>("int32_t", m);
|
|
||||||
bootstrap_pod_type<std::int64_t>("int64_t", m);
|
|
||||||
bootstrap_pod_type<std::uint8_t>("uint8_t", m);
|
|
||||||
bootstrap_pod_type<std::uint16_t>("uint16_t", m);
|
|
||||||
bootstrap_pod_type<std::uint32_t>("uint32_t", m);
|
|
||||||
bootstrap_pod_type<std::uint64_t>("uint64_t", m);
|
|
||||||
|
|
||||||
|
m.add(fun(&print), "print_string");
|
||||||
|
m.add(fun(&println), "println_string");
|
||||||
|
|
||||||
operators::logical_compliment<bool>(m);
|
m.add(dispatch::make_dynamic_proxy_function(&bind_function), "bind");
|
||||||
|
|
||||||
opers_arithmetic_pod(m);
|
m.add(fun(&shared_ptr_unconst_clone<dispatch::Proxy_Function_Base>), "clone");
|
||||||
|
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) {
|
||||||
|
t_lhs.assign(t_rhs);
|
||||||
|
}),
|
||||||
|
"=");
|
||||||
|
|
||||||
|
m.add(fun(&Boxed_Value::type_match), "type_match");
|
||||||
|
|
||||||
m.add(fun(&Build_Info::version_major), "version_major");
|
m.add(chaiscript::fun(&has_parse_tree), "has_parse_tree");
|
||||||
m.add(fun(&Build_Info::version_minor), "version_minor");
|
m.add(chaiscript::fun(&get_parse_tree), "get_parse_tree");
|
||||||
m.add(fun(&Build_Info::version_patch), "version_patch");
|
|
||||||
m.add(fun(&Build_Info::version), "version");
|
|
||||||
m.add(fun(&Build_Info::compiler_version), "compiler_version");
|
|
||||||
m.add(fun(&Build_Info::compiler_name), "compiler_name");
|
|
||||||
m.add(fun(&Build_Info::compiler_id), "compiler_id");
|
|
||||||
m.add(fun(&Build_Info::debug_build), "debug_build");
|
|
||||||
|
|
||||||
|
m.add(chaiscript::base_class<std::runtime_error, chaiscript::exception::eval_error>());
|
||||||
|
m.add(chaiscript::base_class<std::exception, chaiscript::exception::eval_error>());
|
||||||
|
|
||||||
m.add(fun(&print), "print_string");
|
m.add(chaiscript::user_type<chaiscript::exception::arithmetic_error>(), "arithmetic_error");
|
||||||
m.add(fun(&println), "println_string");
|
m.add(chaiscript::base_class<std::runtime_error, chaiscript::exception::arithmetic_error>());
|
||||||
|
m.add(chaiscript::base_class<std::exception, chaiscript::exception::arithmetic_error>());
|
||||||
|
|
||||||
m.add(dispatch::make_dynamic_proxy_function(&bind_function), "bind");
|
// chaiscript::bootstrap::standard_library::vector_type<std::vector<std::shared_ptr<chaiscript::AST_Node> >
|
||||||
|
// >("AST_NodeVector", m);
|
||||||
|
|
||||||
m.add(fun(&shared_ptr_unconst_clone<dispatch::Proxy_Function_Base>), "clone");
|
chaiscript::utility::add_class<chaiscript::exception::eval_error>(m,
|
||||||
m.add(fun(&ptr_assign<std::remove_const<dispatch::Proxy_Function_Base>::type>), "=");
|
"eval_error",
|
||||||
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>());
|
{{fun(&chaiscript::exception::eval_error::reason), "reason"},
|
||||||
m.add(fun(
|
{fun(&chaiscript::exception::eval_error::pretty_print), "pretty_print"},
|
||||||
[](dispatch::Assignable_Proxy_Function &t_lhs, const std::shared_ptr<const dispatch::Proxy_Function_Base> &t_rhs) {
|
{fun([](const chaiscript::exception::eval_error &t_eval_error) {
|
||||||
t_lhs.assign(t_rhs);
|
std::vector<Boxed_Value> retval;
|
||||||
}
|
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"}});
|
||||||
|
|
||||||
m.add(fun(&Boxed_Value::type_match), "type_match");
|
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"}});
|
||||||
|
|
||||||
|
chaiscript::utility::add_class<AST_Node>(m,
|
||||||
m.add(chaiscript::fun(&has_parse_tree), "has_parse_tree");
|
"AST_Node",
|
||||||
m.add(chaiscript::fun(&get_parse_tree), "get_parse_tree");
|
{},
|
||||||
|
{{fun(&AST_Node::text), "text"},
|
||||||
m.add(chaiscript::base_class<std::runtime_error, chaiscript::exception::eval_error>());
|
{fun(&AST_Node::identifier), "identifier"},
|
||||||
m.add(chaiscript::base_class<std::exception, chaiscript::exception::eval_error>());
|
{fun(&AST_Node::filename), "filename"},
|
||||||
|
{fun(&AST_Node::start), "start"},
|
||||||
m.add(chaiscript::user_type<chaiscript::exception::arithmetic_error>(), "arithmetic_error");
|
{fun(&AST_Node::end), "end"},
|
||||||
m.add(chaiscript::base_class<std::runtime_error, chaiscript::exception::arithmetic_error>());
|
{fun(&AST_Node::to_string), "to_string"},
|
||||||
m.add(chaiscript::base_class<std::exception, chaiscript::exception::arithmetic_error>());
|
{fun([](const chaiscript::AST_Node &t_node) -> std::vector<Boxed_Value> {
|
||||||
|
std::vector<Boxed_Value> retval;
|
||||||
|
const auto children = t_node.get_children();
|
||||||
// chaiscript::bootstrap::standard_library::vector_type<std::vector<std::shared_ptr<chaiscript::AST_Node> > >("AST_NodeVector", m);
|
std::transform(children.begin(),
|
||||||
|
children.end(),
|
||||||
|
std::back_inserter(retval),
|
||||||
chaiscript::utility::add_class<chaiscript::exception::eval_error>(m,
|
&chaiscript::var<const std::reference_wrapper<chaiscript::AST_Node> &>);
|
||||||
"eval_error",
|
return retval;
|
||||||
{ },
|
}),
|
||||||
{ {fun(&chaiscript::exception::eval_error::reason), "reason"},
|
"children"}});
|
||||||
{fun(&chaiscript::exception::eval_error::pretty_print), "pretty_print"},
|
}
|
||||||
{fun([](const chaiscript::exception::eval_error &t_eval_error) {
|
};
|
||||||
std::vector<Boxed_Value> retval;
|
} // namespace chaiscript::bootstrap
|
||||||
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"} }
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
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"} }
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
chaiscript::utility::add_class<AST_Node>(m,
|
|
||||||
"AST_Node",
|
|
||||||
{ },
|
|
||||||
{ {fun(&AST_Node::text), "text"},
|
|
||||||
{fun(&AST_Node::identifier), "identifier"},
|
|
||||||
{fun(&AST_Node::filename), "filename"},
|
|
||||||
{fun(&AST_Node::start), "start"},
|
|
||||||
{fun(&AST_Node::end), "end"},
|
|
||||||
{fun(&AST_Node::to_string), "to_string"},
|
|
||||||
{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::back_inserter(retval),
|
|
||||||
&chaiscript::var<const std::reference_wrapper<chaiscript::AST_Node> &>);
|
|
||||||
return retval;
|
|
||||||
}), "children"}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@ -7,13 +7,11 @@
|
|||||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
// 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
|
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||||
|
|
||||||
|
|
||||||
/// \file
|
/// \file
|
||||||
/// This file contains utility functions for registration of STL container
|
/// This file contains utility functions for registration of STL container
|
||||||
/// classes. The methodology used is based on the SGI STL concepts.
|
/// classes. The methodology used is based on the SGI STL concepts.
|
||||||
/// http://www.sgi.com/tech/stl/table_of_contents.html
|
/// http://www.sgi.com/tech/stl/table_of_contents.html
|
||||||
|
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_BOOTSTRAP_STL_HPP_
|
#ifndef CHAISCRIPT_BOOTSTRAP_STL_HPP_
|
||||||
#define CHAISCRIPT_BOOTSTRAP_STL_HPP_
|
#define CHAISCRIPT_BOOTSTRAP_STL_HPP_
|
||||||
|
|
||||||
@ -31,412 +29,353 @@
|
|||||||
#include "register_function.hpp"
|
#include "register_function.hpp"
|
||||||
#include "type_info.hpp"
|
#include "type_info.hpp"
|
||||||
|
|
||||||
namespace chaiscript
|
namespace chaiscript::bootstrap::standard_library {
|
||||||
{
|
/// Bidir_Range, based on the D concept of ranges.
|
||||||
namespace bootstrap
|
/// \todo Update the Range code to base its capabilities on
|
||||||
{
|
/// the user_typetraits of the iterator passed in
|
||||||
namespace standard_library
|
template<typename Container, typename IterType>
|
||||||
{
|
struct Bidir_Range {
|
||||||
|
using container_type = Container;
|
||||||
|
|
||||||
/// Bidir_Range, based on the D concept of ranges.
|
constexpr Bidir_Range(Container &c)
|
||||||
/// \todo Update the Range code to base its capabilities on
|
: m_begin(c.begin())
|
||||||
/// the user_typetraits of the iterator passed in
|
, m_end(c.end()) {
|
||||||
template<typename Container, typename IterType>
|
}
|
||||||
struct Bidir_Range
|
|
||||||
{
|
|
||||||
using container_type = Container;
|
|
||||||
|
|
||||||
constexpr Bidir_Range(Container &c)
|
constexpr bool empty() const noexcept { return m_begin == m_end; }
|
||||||
: m_begin(c.begin()), m_end(c.end())
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr bool empty() const noexcept
|
constexpr void pop_front() {
|
||||||
{
|
if (empty()) {
|
||||||
return m_begin == m_end;
|
throw std::range_error("Range empty");
|
||||||
}
|
}
|
||||||
|
++m_begin;
|
||||||
|
}
|
||||||
|
|
||||||
constexpr void pop_front()
|
constexpr void pop_back() {
|
||||||
{
|
if (empty()) {
|
||||||
if (empty())
|
throw std::range_error("Range empty");
|
||||||
{
|
}
|
||||||
throw std::range_error("Range empty");
|
--m_end;
|
||||||
}
|
}
|
||||||
++m_begin;
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr void pop_back()
|
constexpr decltype(auto) front() const {
|
||||||
{
|
if (empty()) {
|
||||||
if (empty())
|
throw std::range_error("Range empty");
|
||||||
{
|
}
|
||||||
throw std::range_error("Range empty");
|
return (*m_begin);
|
||||||
}
|
}
|
||||||
--m_end;
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr decltype(auto) front() const
|
constexpr decltype(auto) back() const {
|
||||||
{
|
if (empty()) {
|
||||||
if (empty())
|
throw std::range_error("Range empty");
|
||||||
{
|
}
|
||||||
throw std::range_error("Range empty");
|
auto pos = m_end;
|
||||||
}
|
--pos;
|
||||||
return (*m_begin);
|
return (*(pos));
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr decltype(auto) back() const
|
IterType m_begin;
|
||||||
{
|
IterType m_end;
|
||||||
if (empty())
|
};
|
||||||
{
|
|
||||||
throw std::range_error("Range empty");
|
|
||||||
}
|
|
||||||
auto pos = m_end;
|
|
||||||
--pos;
|
|
||||||
return (*(pos));
|
|
||||||
}
|
|
||||||
|
|
||||||
IterType m_begin;
|
namespace detail {
|
||||||
IterType m_end;
|
template<typename T>
|
||||||
};
|
size_t count(const T &t_target, const typename T::key_type &t_key) {
|
||||||
|
return t_target.count(t_key);
|
||||||
|
}
|
||||||
|
|
||||||
namespace detail {
|
template<typename T>
|
||||||
|
void insert(T &t_target, const T &t_other) {
|
||||||
|
t_target.insert(t_other.begin(), t_other.end());
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
size_t count(const T &t_target, const typename T::key_type &t_key)
|
void insert_ref(T &t_target, const typename T::value_type &t_val) {
|
||||||
{
|
t_target.insert(t_val);
|
||||||
return t_target.count(t_key);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
/// Add Bidir_Range support for the given ContainerType
|
||||||
void insert(T &t_target, const T &t_other)
|
template<typename Bidir_Type>
|
||||||
{
|
void input_range_type_impl(const std::string &type, Module &m) {
|
||||||
t_target.insert(t_other.begin(), t_other.end());
|
m.add(user_type<Bidir_Type>(), type + "_Range");
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
copy_constructor<Bidir_Type>(type + "_Range", m);
|
||||||
void insert_ref(T &t_target, const typename T::value_type &t_val)
|
|
||||||
{
|
|
||||||
t_target.insert(t_val);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
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");
|
||||||
|
m.add(fun(&Bidir_Type::front), "front");
|
||||||
|
m.add(fun(&Bidir_Type::pop_back), "pop_back");
|
||||||
|
m.add(fun(&Bidir_Type::back), "back");
|
||||||
|
}
|
||||||
|
|
||||||
/// Add Bidir_Range support for the given ContainerType
|
/// Algorithm for inserting at a specific position into a container
|
||||||
template<typename Bidir_Type>
|
template<typename Type>
|
||||||
void input_range_type_impl(const std::string &type, Module& m)
|
void insert_at(Type &container, int pos, const typename Type::value_type &v) {
|
||||||
{
|
auto itr = container.begin();
|
||||||
m.add(user_type<Bidir_Type>(), type + "_Range");
|
auto end = container.end();
|
||||||
|
|
||||||
copy_constructor<Bidir_Type>(type + "_Range", m);
|
if (pos < 0 || std::distance(itr, end) < pos) {
|
||||||
|
throw std::range_error("Cannot insert past end of range");
|
||||||
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");
|
|
||||||
m.add(fun(&Bidir_Type::front), "front");
|
|
||||||
m.add(fun(&Bidir_Type::pop_back), "pop_back");
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
auto itr = container.begin();
|
|
||||||
auto end = container.end();
|
|
||||||
|
|
||||||
if (pos < 0 || std::distance(itr, end) < pos)
|
|
||||||
{
|
|
||||||
throw std::range_error("Cannot insert past end of range");
|
|
||||||
}
|
|
||||||
|
|
||||||
std::advance(itr, pos);
|
|
||||||
container.insert(itr, v);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// Algorithm for erasing a specific position from a container
|
|
||||||
template<typename Type>
|
|
||||||
void erase_at(Type &container, int pos)
|
|
||||||
{
|
|
||||||
auto itr = container.begin();
|
|
||||||
auto end = container.end();
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename ContainerType>
|
std::advance(itr, pos);
|
||||||
void input_range_type(const std::string &type, Module& m)
|
container.insert(itr, v);
|
||||||
{
|
}
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/// Algorithm for erasing a specific position from a container
|
||||||
|
template<typename Type>
|
||||||
|
void erase_at(Type &container, int pos) {
|
||||||
|
auto itr = container.begin();
|
||||||
|
auto end = container.end();
|
||||||
|
|
||||||
/// Add random_access_container concept to the given ContainerType
|
if (pos < 0 || std::distance(itr, end) < (pos - 1)) {
|
||||||
/// http://www.sgi.com/tech/stl/RandomAccessContainer.html
|
throw std::range_error("Cannot erase past end of range");
|
||||||
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 {
|
|
||||||
/// \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(
|
std::advance(itr, pos);
|
||||||
fun(
|
container.erase(itr);
|
||||||
[](const ContainerType &c, int index) -> typename ContainerType::const_reference {
|
}
|
||||||
/// \todo we are preferring to keep the key as 'int' to avoid runtime conversions
|
} // namespace detail
|
||||||
/// during dispatch. reevaluate
|
|
||||||
return c.at(static_cast<typename ContainerType::size_type>(index));
|
|
||||||
}), "[]");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
/// Add assignable concept to the given ContainerType
|
/// Add random_access_container concept to the given ContainerType
|
||||||
/// http://www.sgi.com/tech/stl/Assignable.html
|
/// http://www.sgi.com/tech/stl/RandomAccessContainer.html
|
||||||
template<typename ContainerType>
|
template<typename ContainerType>
|
||||||
void assignable_type(const std::string &type, Module& m)
|
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,
|
||||||
copy_constructor<ContainerType>(type, m);
|
// to throw an exception in an out of bounds condition.
|
||||||
operators::assign<ContainerType>(m);
|
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));
|
||||||
|
}),
|
||||||
|
"[]");
|
||||||
|
|
||||||
/// Add container resize concept to the given ContainerType
|
m.add(fun([](const ContainerType &c, int index) -> typename ContainerType::const_reference {
|
||||||
/// http://www.cplusplus.com/reference/stl/
|
/// \todo we are preferring to keep the key as 'int' to avoid runtime conversions
|
||||||
template<typename ContainerType>
|
/// during dispatch. reevaluate
|
||||||
void resizable_type(const std::string &/*type*/, Module& m)
|
return c.at(static_cast<typename ContainerType::size_type>(index));
|
||||||
{
|
}),
|
||||||
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
|
/// Add assignable concept to the given ContainerType
|
||||||
/// http://www.cplusplus.com/reference/stl/
|
/// http://www.sgi.com/tech/stl/Assignable.html
|
||||||
template<typename ContainerType>
|
template<typename ContainerType>
|
||||||
void reservable_type(const std::string &/*type*/, Module& m)
|
void assignable_type(const std::string &type, Module &m) {
|
||||||
{
|
copy_constructor<ContainerType>(type, m);
|
||||||
m.add(fun([](ContainerType *a, typename ContainerType::size_type n) { return a->reserve(n); } ), "reserve");
|
operators::assign<ContainerType>(m);
|
||||||
m.add(fun([](const ContainerType *a) { return a->capacity(); } ), "capacity");
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// Add container concept to the given ContainerType
|
/// Add container resize concept to the given ContainerType
|
||||||
/// http://www.sgi.com/tech/stl/Container.html
|
/// http://www.cplusplus.com/reference/stl/
|
||||||
template<typename ContainerType>
|
template<typename ContainerType>
|
||||||
void container_type(const std::string &/*type*/, Module& m)
|
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) {
|
||||||
m.add(fun([](const ContainerType *a) { return a->size(); } ), "size");
|
return a->resize(n, val);
|
||||||
m.add(fun([](const ContainerType *a) { return a->empty(); } ), "empty");
|
}),
|
||||||
m.add(fun([](ContainerType *a) { a->clear(); } ), "clear");
|
"resize");
|
||||||
}
|
m.add(fun([](ContainerType *a, typename ContainerType::size_type n) { return a->resize(n); }), "resize");
|
||||||
|
}
|
||||||
|
|
||||||
/// Add default constructable concept to the given Type
|
/// Add container reserve concept to the given ContainerType
|
||||||
/// http://www.sgi.com/tech/stl/DefaultConstructible.html
|
/// http://www.cplusplus.com/reference/stl/
|
||||||
template<typename Type>
|
template<typename ContainerType>
|
||||||
void default_constructible_type(const std::string &type, Module& m)
|
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(constructor<Type ()>(), type);
|
m.add(fun([](const ContainerType *a) { return a->capacity(); }), "capacity");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add sequence concept to the given ContainerType
|
/// Add container concept to the given ContainerType
|
||||||
/// http://www.sgi.com/tech/stl/Sequence.html
|
/// http://www.sgi.com/tech/stl/Container.html
|
||||||
template<typename ContainerType>
|
template<typename ContainerType>
|
||||||
void sequence_type(const std::string &/*type*/, Module& m)
|
void container_type(const std::string & /*type*/, Module &m) {
|
||||||
{
|
m.add(fun([](const ContainerType *a) { return a->size(); }), "size");
|
||||||
m.add(fun(&detail::insert_at<ContainerType>),
|
m.add(fun([](const ContainerType *a) { return a->empty(); }), "empty");
|
||||||
[]()->std::string{
|
m.add(fun([](ContainerType *a) { a->clear(); }), "clear");
|
||||||
if (typeid(typename ContainerType::value_type) == typeid(Boxed_Value)) {
|
}
|
||||||
return "insert_ref_at";
|
|
||||||
} else {
|
|
||||||
return "insert_at";
|
|
||||||
}
|
|
||||||
}());
|
|
||||||
|
|
||||||
m.add(fun(&detail::erase_at<ContainerType>), "erase_at");
|
/// 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);
|
||||||
|
}
|
||||||
|
|
||||||
/// Add back insertion sequence concept to the given ContainerType
|
/// Add sequence concept to the given ContainerType
|
||||||
/// http://www.sgi.com/tech/stl/BackInsertionSequence.html
|
/// http://www.sgi.com/tech/stl/Sequence.html
|
||||||
template<typename ContainerType>
|
template<typename ContainerType>
|
||||||
void back_insertion_sequence_type(const std::string &type, Module& m)
|
void sequence_type(const std::string & /*type*/, Module &m) {
|
||||||
{
|
m.add(fun(&detail::insert_at<ContainerType>), []() -> std::string {
|
||||||
m.add(fun([](ContainerType &container)->decltype(auto){
|
if (typeid(typename ContainerType::value_type) == typeid(Boxed_Value)) {
|
||||||
if (container.empty()) {
|
return "insert_ref_at";
|
||||||
throw std::range_error("Container empty");
|
} else {
|
||||||
} else {
|
return "insert_at";
|
||||||
return (container.back());
|
}
|
||||||
}
|
}());
|
||||||
}
|
|
||||||
)
|
|
||||||
, "back");
|
|
||||||
m.add(fun([](const ContainerType &container)->decltype(auto){
|
|
||||||
if (container.empty()) {
|
|
||||||
throw std::range_error("Container empty");
|
|
||||||
} else {
|
|
||||||
return (container.back());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
, "back");
|
|
||||||
|
|
||||||
|
m.add(fun(&detail::erase_at<ContainerType>), "erase_at");
|
||||||
|
}
|
||||||
|
|
||||||
using push_back = void (ContainerType::*)(const typename ContainerType::value_type &);
|
/// Add back insertion sequence concept to the given ContainerType
|
||||||
m.add(fun(static_cast<push_back>(&ContainerType::push_back)),
|
/// http://www.sgi.com/tech/stl/BackInsertionSequence.html
|
||||||
[&]()->std::string{
|
template<typename ContainerType>
|
||||||
if (typeid(typename ContainerType::value_type) == typeid(Boxed_Value)) {
|
void back_insertion_sequence_type(const std::string &type, Module &m) {
|
||||||
m.eval(
|
m.add(fun([](ContainerType &container) -> decltype(auto) {
|
||||||
"# Pushes the second value onto the container while making a clone of the value\n"
|
if (container.empty()) {
|
||||||
"def push_back(" + type + " container, x)\n"
|
throw std::range_error("Container empty");
|
||||||
"{ \n"
|
} else {
|
||||||
" if (x.is_var_return_value()) {\n"
|
return (container.back());
|
||||||
" x.reset_var_return_value() \n"
|
}
|
||||||
" container.push_back_ref(x) \n"
|
}),
|
||||||
" } else { \n"
|
"back");
|
||||||
" container.push_back_ref(clone(x)); \n"
|
m.add(fun([](const ContainerType &container) -> decltype(auto) {
|
||||||
" }\n"
|
if (container.empty()) {
|
||||||
"} \n"
|
throw std::range_error("Container empty");
|
||||||
);
|
} else {
|
||||||
|
return (container.back());
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
"back");
|
||||||
|
|
||||||
return "push_back_ref";
|
using push_back = void (ContainerType::*)(const typename ContainerType::value_type &);
|
||||||
} else {
|
m.add(fun(static_cast<push_back>(&ContainerType::push_back)), [&]() -> std::string {
|
||||||
return "push_back";
|
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"
|
||||||
|
"{ \n"
|
||||||
|
" if (x.is_var_return_value()) {\n"
|
||||||
|
" x.reset_var_return_value() \n"
|
||||||
|
" container.push_back_ref(x) \n"
|
||||||
|
" } else { \n"
|
||||||
|
" container.push_back_ref(clone(x)); \n"
|
||||||
|
" }\n"
|
||||||
|
"} \n");
|
||||||
|
|
||||||
m.add(fun(&ContainerType::pop_back), "pop_back");
|
return "push_back_ref";
|
||||||
}
|
} else {
|
||||||
|
return "push_back";
|
||||||
|
}
|
||||||
|
}());
|
||||||
|
|
||||||
|
m.add(fun(&ContainerType::pop_back), "pop_back");
|
||||||
|
}
|
||||||
|
|
||||||
/// Front insertion sequence
|
/// Front insertion sequence
|
||||||
/// http://www.sgi.com/tech/stl/FrontInsertionSequence.html
|
/// http://www.sgi.com/tech/stl/FrontInsertionSequence.html
|
||||||
template<typename ContainerType>
|
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 push_ptr = void (ContainerType::*)(typename ContainerType::const_reference);
|
using pop_ptr = void (ContainerType::*)();
|
||||||
using pop_ptr = void (ContainerType::*)();
|
|
||||||
|
|
||||||
m.add(fun([](ContainerType &container)->decltype(auto){
|
m.add(fun([](ContainerType &container) -> decltype(auto) {
|
||||||
if (container.empty()) {
|
if (container.empty()) {
|
||||||
throw std::range_error("Container empty");
|
throw std::range_error("Container empty");
|
||||||
} else {
|
} else {
|
||||||
return (container.front());
|
return (container.front());
|
||||||
}
|
}
|
||||||
}
|
}),
|
||||||
)
|
"front");
|
||||||
, "front");
|
|
||||||
|
|
||||||
m.add(fun([](const ContainerType &container)->decltype(auto){
|
m.add(fun([](const ContainerType &container) -> decltype(auto) {
|
||||||
if (container.empty()) {
|
if (container.empty()) {
|
||||||
throw std::range_error("Container empty");
|
throw std::range_error("Container empty");
|
||||||
} else {
|
} else {
|
||||||
return (container.front());
|
return (container.front());
|
||||||
}
|
}
|
||||||
}
|
}),
|
||||||
)
|
"front");
|
||||||
, "front");
|
|
||||||
|
|
||||||
|
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"
|
||||||
|
"{ \n"
|
||||||
|
" if (x.is_var_return_value()) {\n"
|
||||||
|
" x.reset_var_return_value() \n"
|
||||||
|
" container.push_front_ref(x) \n"
|
||||||
|
" } else { \n"
|
||||||
|
" container.push_front_ref(clone(x)); \n"
|
||||||
|
" }\n"
|
||||||
|
"} \n");
|
||||||
|
return "push_front_ref";
|
||||||
|
} else {
|
||||||
|
return "push_front";
|
||||||
|
}
|
||||||
|
}());
|
||||||
|
|
||||||
m.add(fun(static_cast<push_ptr>(&ContainerType::push_front)),
|
m.add(fun(static_cast<pop_ptr>(&ContainerType::pop_front)), "pop_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"
|
|
||||||
"{ \n"
|
|
||||||
" if (x.is_var_return_value()) {\n"
|
|
||||||
" x.reset_var_return_value() \n"
|
|
||||||
" container.push_front_ref(x) \n"
|
|
||||||
" } else { \n"
|
|
||||||
" container.push_front_ref(clone(x)); \n"
|
|
||||||
" }\n"
|
|
||||||
"} \n"
|
|
||||||
);
|
|
||||||
return "push_front_ref";
|
|
||||||
} else {
|
|
||||||
return "push_front";
|
|
||||||
}
|
|
||||||
}());
|
|
||||||
|
|
||||||
m.add(fun(static_cast<pop_ptr>(&ContainerType::pop_front)), "pop_front");
|
/// bootstrap a given PairType
|
||||||
}
|
/// http://www.sgi.com/tech/stl/pair.html
|
||||||
|
template<typename PairType>
|
||||||
|
void pair_type(const std::string &type, Module &m) {
|
||||||
|
m.add(user_type<PairType>(), type);
|
||||||
|
|
||||||
/// bootstrap a given PairType
|
m.add(fun(&PairType::first), "first");
|
||||||
/// http://www.sgi.com/tech/stl/pair.html
|
m.add(fun(&PairType::second), "second");
|
||||||
template<typename PairType>
|
|
||||||
void pair_type(const std::string &type, Module& m)
|
|
||||||
{
|
|
||||||
m.add(user_type<PairType>(), type);
|
|
||||||
|
|
||||||
m.add(fun(&PairType::first), "first");
|
basic_constructors<PairType>(type, m);
|
||||||
m.add(fun(&PairType::second), "second");
|
m.add(constructor<PairType(const typename PairType::first_type &, const typename PairType::second_type &)>(), type);
|
||||||
|
}
|
||||||
|
|
||||||
basic_constructors<PairType>(type, m);
|
/// Add pair associative container concept to the given ContainerType
|
||||||
m.add(constructor<PairType (const typename PairType::first_type &, const typename PairType::second_type &)>(), type);
|
/// http://www.sgi.com/tech/stl/PairAssociativeContainer.html
|
||||||
}
|
|
||||||
|
|
||||||
|
template<typename ContainerType>
|
||||||
|
void pair_associative_container_type(const std::string &type, Module &m) {
|
||||||
|
pair_type<typename ContainerType::value_type>(type + "_Pair", m);
|
||||||
|
}
|
||||||
|
|
||||||
/// Add pair associative container concept to the given ContainerType
|
/// Add unique associative container concept to the given ContainerType
|
||||||
/// http://www.sgi.com/tech/stl/PairAssociativeContainer.html
|
/// http://www.sgi.com/tech/stl/UniqueAssociativeContainer.html
|
||||||
|
template<typename ContainerType>
|
||||||
|
void unique_associative_container_type(const std::string & /*type*/, Module &m) {
|
||||||
|
m.add(fun(detail::count<ContainerType>), "count");
|
||||||
|
|
||||||
template<typename ContainerType>
|
using erase_ptr = size_t (ContainerType::*)(const typename ContainerType::key_type &);
|
||||||
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
|
m.add(fun(static_cast<erase_ptr>(&ContainerType::erase)), "erase");
|
||||||
/// http://www.sgi.com/tech/stl/UniqueAssociativeContainer.html
|
|
||||||
template<typename ContainerType>
|
|
||||||
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 &);
|
m.add(fun(&detail::insert<ContainerType>), "insert");
|
||||||
|
|
||||||
m.add(fun(static_cast<erase_ptr>(&ContainerType::erase)), "erase");
|
m.add(fun(&detail::insert_ref<ContainerType>), []() -> std::string {
|
||||||
|
if (typeid(typename ContainerType::mapped_type) == typeid(Boxed_Value)) {
|
||||||
|
return "insert_ref";
|
||||||
|
} else {
|
||||||
|
return "insert";
|
||||||
|
}
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
|
||||||
m.add(fun(&detail::insert<ContainerType>), "insert");
|
/// Add a MapType container
|
||||||
|
/// http://www.sgi.com/tech/stl/Map.html
|
||||||
|
template<typename MapType>
|
||||||
|
void map_type(const std::string &type, Module &m) {
|
||||||
|
m.add(user_type<MapType>(), type);
|
||||||
|
|
||||||
m.add(fun(&detail::insert_ref<ContainerType>),
|
using elem_access = typename MapType::mapped_type &(MapType::*)(const typename MapType::key_type &);
|
||||||
[]()->std::string{
|
using const_elem_access = const typename MapType::mapped_type &(MapType::*)(const typename MapType::key_type &) const;
|
||||||
if (typeid(typename ContainerType::mapped_type) == typeid(Boxed_Value)) {
|
|
||||||
return "insert_ref";
|
|
||||||
} else {
|
|
||||||
return "insert";
|
|
||||||
}
|
|
||||||
}());
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Add a MapType container
|
m.add(fun(static_cast<elem_access>(&MapType::operator[])), "[]");
|
||||||
/// http://www.sgi.com/tech/stl/Map.html
|
|
||||||
template<typename MapType>
|
|
||||||
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 &);
|
m.add(fun(static_cast<elem_access>(&MapType::at)), "at");
|
||||||
using const_elem_access = const typename MapType::mapped_type &(MapType::*)(const typename MapType::key_type &) const;
|
m.add(fun(static_cast<const_elem_access>(&MapType::at)), "at");
|
||||||
|
|
||||||
m.add(fun(static_cast<elem_access>(&MapType::operator[])), "[]");
|
if (typeid(MapType) == typeid(std::map<std::string, Boxed_Value>)) {
|
||||||
|
m.eval(R"(
|
||||||
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>))
|
|
||||||
{
|
|
||||||
m.eval(R"(
|
|
||||||
def Map::`==`(Map rhs) {
|
def Map::`==`(Map rhs) {
|
||||||
if ( rhs.size() != this.size() ) {
|
if ( rhs.size() != this.size() ) {
|
||||||
return false;
|
return false;
|
||||||
@ -454,77 +393,68 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
true;
|
true;
|
||||||
}
|
}
|
||||||
} )"
|
} )");
|
||||||
);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
container_type<MapType>(type, m);
|
container_type<MapType>(type, m);
|
||||||
default_constructible_type<MapType>(type, m);
|
default_constructible_type<MapType>(type, m);
|
||||||
assignable_type<MapType>(type, m);
|
assignable_type<MapType>(type, m);
|
||||||
unique_associative_container_type<MapType>(type, m);
|
unique_associative_container_type<MapType>(type, m);
|
||||||
pair_associative_container_type<MapType>(type, m);
|
pair_associative_container_type<MapType>(type, m);
|
||||||
input_range_type<MapType>(type, m);
|
input_range_type<MapType>(type, m);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// http://www.sgi.com/tech/stl/List.html
|
/// http://www.sgi.com/tech/stl/List.html
|
||||||
template<typename ListType>
|
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);
|
||||||
m.add(user_type<ListType>(), type);
|
|
||||||
|
|
||||||
front_insertion_sequence_type<ListType>(type, m);
|
front_insertion_sequence_type<ListType>(type, m);
|
||||||
back_insertion_sequence_type<ListType>(type, m);
|
back_insertion_sequence_type<ListType>(type, m);
|
||||||
sequence_type<ListType>(type, m);
|
sequence_type<ListType>(type, m);
|
||||||
resizable_type<ListType>(type, m);
|
resizable_type<ListType>(type, m);
|
||||||
container_type<ListType>(type, m);
|
container_type<ListType>(type, m);
|
||||||
default_constructible_type<ListType>(type, m);
|
default_constructible_type<ListType>(type, m);
|
||||||
assignable_type<ListType>(type, m);
|
assignable_type<ListType>(type, m);
|
||||||
input_range_type<ListType>(type, m);
|
input_range_type<ListType>(type, m);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a vector type with associated concepts
|
/// Create a vector type with associated concepts
|
||||||
/// http://www.sgi.com/tech/stl/Vector.html
|
/// http://www.sgi.com/tech/stl/Vector.html
|
||||||
template<typename VectorType>
|
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(user_type<VectorType>(), type);
|
|
||||||
|
|
||||||
m.add(fun([](VectorType &container)->decltype(auto){
|
m.add(fun([](VectorType &container) -> decltype(auto) {
|
||||||
if (container.empty()) {
|
if (container.empty()) {
|
||||||
throw std::range_error("Container empty");
|
throw std::range_error("Container empty");
|
||||||
} else {
|
} else {
|
||||||
return (container.front());
|
return (container.front());
|
||||||
}
|
}
|
||||||
}
|
}),
|
||||||
)
|
"front");
|
||||||
, "front");
|
|
||||||
|
|
||||||
m.add(fun([](const VectorType &container)->decltype(auto){
|
m.add(fun([](const VectorType &container) -> decltype(auto) {
|
||||||
if (container.empty()) {
|
if (container.empty()) {
|
||||||
throw std::range_error("Container empty");
|
throw std::range_error("Container empty");
|
||||||
} else {
|
} else {
|
||||||
return (container.front());
|
return (container.front());
|
||||||
}
|
}
|
||||||
}
|
}),
|
||||||
)
|
"front");
|
||||||
, "front");
|
|
||||||
|
|
||||||
|
back_insertion_sequence_type<VectorType>(type, m);
|
||||||
|
sequence_type<VectorType>(type, m);
|
||||||
|
random_access_container_type<VectorType>(type, m);
|
||||||
|
resizable_type<VectorType>(type, m);
|
||||||
|
reservable_type<VectorType>(type, m);
|
||||||
|
container_type<VectorType>(type, m);
|
||||||
|
default_constructible_type<VectorType>(type, m);
|
||||||
|
assignable_type<VectorType>(type, m);
|
||||||
|
input_range_type<VectorType>(type, m);
|
||||||
|
|
||||||
|
if (typeid(VectorType) == typeid(std::vector<Boxed_Value>)) {
|
||||||
|
m.eval(R"(
|
||||||
back_insertion_sequence_type<VectorType>(type, m);
|
|
||||||
sequence_type<VectorType>(type, m);
|
|
||||||
random_access_container_type<VectorType>(type, m);
|
|
||||||
resizable_type<VectorType>(type, m);
|
|
||||||
reservable_type<VectorType>(type, m);
|
|
||||||
container_type<VectorType>(type, m);
|
|
||||||
default_constructible_type<VectorType>(type, m);
|
|
||||||
assignable_type<VectorType>(type, m);
|
|
||||||
input_range_type<VectorType>(type, m);
|
|
||||||
|
|
||||||
if (typeid(VectorType) == typeid(std::vector<Boxed_Value>))
|
|
||||||
{
|
|
||||||
m.eval(R"(
|
|
||||||
def Vector::`==`(Vector rhs) {
|
def Vector::`==`(Vector rhs) {
|
||||||
if ( rhs.size() != this.size() ) {
|
if ( rhs.size() != this.size() ) {
|
||||||
return false;
|
return false;
|
||||||
@ -542,73 +472,62 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
true;
|
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)
|
|
||||||
{
|
|
||||||
m.add(user_type<String>(), type);
|
|
||||||
operators::addition<String>(m);
|
|
||||||
operators::assign_sum<String>(m);
|
|
||||||
opers_comparison<String>(m);
|
|
||||||
random_access_container_type<String>(type, m);
|
|
||||||
sequence_type<String>(type, m);
|
|
||||||
default_constructible_type<String>(type, m);
|
|
||||||
// container_type<String>(type, m);
|
|
||||||
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{
|
|
||||||
if (typeid(typename String::value_type) == typeid(Boxed_Value)) {
|
|
||||||
return "push_back_ref";
|
|
||||||
} else {
|
|
||||||
return "push_back";
|
|
||||||
}
|
|
||||||
}());
|
|
||||||
|
|
||||||
|
|
||||||
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) { 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");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// Add a MapType container
|
|
||||||
/// http://www.sgi.com/tech/stl/Map.html
|
|
||||||
template<typename FutureType>
|
|
||||||
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");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
/// 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) {
|
||||||
|
m.add(user_type<String>(), type);
|
||||||
|
operators::addition<String>(m);
|
||||||
|
operators::assign_sum<String>(m);
|
||||||
|
opers_comparison<String>(m);
|
||||||
|
random_access_container_type<String>(type, m);
|
||||||
|
sequence_type<String>(type, m);
|
||||||
|
default_constructible_type<String>(type, m);
|
||||||
|
// container_type<String>(type, m);
|
||||||
|
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 {
|
||||||
|
if (typeid(typename String::value_type) == typeid(Boxed_Value)) {
|
||||||
|
return "push_back_ref";
|
||||||
|
} else {
|
||||||
|
return "push_back";
|
||||||
|
}
|
||||||
|
}());
|
||||||
|
|
||||||
|
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) { 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");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Add a MapType container
|
||||||
|
/// http://www.sgi.com/tech/stl/Map.html
|
||||||
|
template<typename FutureType>
|
||||||
|
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
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -7,7 +7,6 @@
|
|||||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
// 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
|
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||||
|
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_BOXED_CAST_HPP_
|
#ifndef CHAISCRIPT_BOXED_CAST_HPP_
|
||||||
#define CHAISCRIPT_BOXED_CAST_HPP_
|
#define CHAISCRIPT_BOXED_CAST_HPP_
|
||||||
|
|
||||||
@ -19,23 +18,19 @@
|
|||||||
#include "type_info.hpp"
|
#include "type_info.hpp"
|
||||||
|
|
||||||
namespace chaiscript {
|
namespace chaiscript {
|
||||||
class Type_Conversions;
|
class Type_Conversions;
|
||||||
namespace detail {
|
}
|
||||||
namespace exception {
|
namespace chaiscript::detail::exception {
|
||||||
class bad_any_cast;
|
class bad_any_cast;
|
||||||
} // namespace exception
|
} // namespace chaiscript::detail::exception
|
||||||
} // namespace detail
|
|
||||||
} // namespace chaiscript
|
|
||||||
|
|
||||||
namespace chaiscript
|
namespace chaiscript {
|
||||||
{
|
|
||||||
|
|
||||||
/// \brief Function for extracting a value stored in a Boxed_Value object
|
/// \brief Function for extracting a value stored in a Boxed_Value object
|
||||||
/// \tparam Type The type to extract from the Boxed_Value
|
/// \tparam Type The type to extract from the Boxed_Value
|
||||||
/// \param[in] bv The Boxed_Value to extract a typed value from
|
/// \param[in] bv The Boxed_Value to extract a typed value from
|
||||||
/// \returns Type equivalent to the requested type
|
/// \returns Type equivalent to the requested type
|
||||||
/// \throws exception::bad_boxed_cast If the requested conversion is not possible
|
/// \throws exception::bad_boxed_cast If the requested conversion is not possible
|
||||||
///
|
///
|
||||||
/// boxed_cast will attempt to make conversions between value, &, *, std::shared_ptr, std::reference_wrapper,
|
/// boxed_cast will attempt to make conversions between value, &, *, std::shared_ptr, std::reference_wrapper,
|
||||||
/// and std::function (const and non-const) where possible. boxed_cast is used internally during function
|
/// and std::function (const and non-const) where possible. boxed_cast is used internally during function
|
||||||
/// dispatch. This means that all of these conversions will be attempted automatically for you during
|
/// dispatch. This means that all of these conversions will be attempted automatically for you during
|
||||||
@ -67,47 +62,41 @@ namespace chaiscript
|
|||||||
/// std::function conversion example
|
/// std::function conversion example
|
||||||
/// \code
|
/// \code
|
||||||
/// chaiscript::ChaiScript chai;
|
/// chaiscript::ChaiScript chai;
|
||||||
/// Boxed_Value bv = chai.eval("`+`"); // Get the functor for the + operator which is built in
|
/// Boxed_Value bv = chai.eval("`+`"); // Get the functor for the + operator which is built in
|
||||||
/// std::function<int (int, int)> f = chaiscript::boxed_cast<std::function<int (int, int)> >(bv);
|
/// std::function<int (int, int)> f = chaiscript::boxed_cast<std::function<int (int, int)> >(bv);
|
||||||
/// int i = f(2,3);
|
/// int i = f(2,3);
|
||||||
/// assert(i == 5);
|
/// assert(i == 5);
|
||||||
/// \endcode
|
/// \endcode
|
||||||
template<typename Type>
|
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>())) {
|
if (!t_conversions || bv.get_type_info().bare_equal(user_type<Type>()) || (t_conversions && !(*t_conversions)->convertable_type<Type>())) {
|
||||||
try {
|
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 &) {
|
} 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 {
|
try {
|
||||||
// We will not catch any bad_boxed_dynamic_cast that is thrown, let the user get it
|
// 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
|
// 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 (...) {
|
} catch (...) {
|
||||||
try {
|
try {
|
||||||
// try going the other way
|
// 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 &) {
|
} catch (const chaiscript::detail::exception::bad_any_cast &) {
|
||||||
throw exception::bad_boxed_cast(bv.get_type_info(), typeid(Type));
|
throw exception::bad_boxed_cast(bv.get_type_info(), typeid(Type));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// If it's not convertable, just throw the error, don't waste the time on the
|
// If it's not convertable, just throw the error, don't waste the time on the
|
||||||
// attempted dynamic_cast
|
// attempted dynamic_cast
|
||||||
throw exception::bad_boxed_cast(bv.get_type_info(), typeid(Type));
|
throw exception::bad_boxed_cast(bv.get_type_info(), typeid(Type));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
} // namespace chaiscript
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@ -7,7 +7,6 @@
|
|||||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
// 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
|
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||||
|
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_BOXED_CAST_HELPER_HPP_
|
#ifndef CHAISCRIPT_BOXED_CAST_HELPER_HPP_
|
||||||
#define CHAISCRIPT_BOXED_CAST_HELPER_HPP_
|
#define CHAISCRIPT_BOXED_CAST_HELPER_HPP_
|
||||||
|
|
||||||
@ -17,21 +16,19 @@
|
|||||||
#include "boxed_value.hpp"
|
#include "boxed_value.hpp"
|
||||||
#include "type_info.hpp"
|
#include "type_info.hpp"
|
||||||
|
|
||||||
|
namespace chaiscript {
|
||||||
namespace chaiscript
|
|
||||||
{
|
|
||||||
class Type_Conversions_State;
|
class Type_Conversions_State;
|
||||||
|
|
||||||
namespace detail
|
namespace detail {
|
||||||
{
|
|
||||||
// Cast_Helper_Inner helper classes
|
// Cast_Helper_Inner helper classes
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
constexpr T* throw_if_null(T *t)
|
constexpr T *throw_if_null(T *t) {
|
||||||
{
|
if (t) {
|
||||||
if (t) { return t; }
|
return t;
|
||||||
throw std::runtime_error("Attempted to dereference null Boxed_Value");
|
|
||||||
}
|
}
|
||||||
|
throw std::runtime_error("Attempted to dereference null Boxed_Value");
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static const T *verify_type_no_throw(const Boxed_Value &ob, const std::type_info &ti, const T *ptr) {
|
static const T *verify_type_no_throw(const Boxed_Value &ob, const std::type_info &ti, const T *ptr) {
|
||||||
@ -51,7 +48,6 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static const T *verify_type(const Boxed_Value &ob, const std::type_info &ti, const T *ptr) {
|
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)) {
|
if (ob.get_type_info().bare_equal_type_info(ti)) {
|
||||||
@ -72,252 +68,193 @@ namespace chaiscript
|
|||||||
|
|
||||||
/// Generic Cast_Helper_Inner, for casting to any type
|
/// Generic Cast_Helper_Inner, for casting to any type
|
||||||
template<typename Result>
|
template<typename Result>
|
||||||
struct Cast_Helper_Inner
|
struct Cast_Helper_Inner {
|
||||||
{
|
static Result cast(const Boxed_Value &ob, const Type_Conversions_State *) {
|
||||||
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()));
|
||||||
{
|
}
|
||||||
return *static_cast<const Result *>(verify_type(ob, typeid(Result), ob.get_const_ptr()));
|
};
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename Result>
|
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
|
/// Cast_Helper_Inner for casting to a const * type
|
||||||
template<typename Result>
|
template<typename Result>
|
||||||
struct Cast_Helper_Inner<const Result *>
|
struct Cast_Helper_Inner<const Result *> {
|
||||||
{
|
static const Result *cast(const Boxed_Value &ob, const Type_Conversions_State *) {
|
||||||
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()));
|
||||||
{
|
}
|
||||||
return static_cast<const Result *>(verify_type_no_throw(ob, typeid(Result), ob.get_const_ptr()));
|
};
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Cast_Helper_Inner for casting to a * type
|
/// Cast_Helper_Inner for casting to a * type
|
||||||
template<typename Result>
|
template<typename Result>
|
||||||
struct Cast_Helper_Inner<Result *>
|
struct Cast_Helper_Inner<Result *> {
|
||||||
{
|
static Result *cast(const Boxed_Value &ob, const Type_Conversions_State *) {
|
||||||
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()));
|
||||||
{
|
}
|
||||||
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 *>
|
|
||||||
{
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Result>
|
template<typename Result>
|
||||||
struct Cast_Helper_Inner<const Result * const &> : public Cast_Helper_Inner<const 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 *> {
|
||||||
|
};
|
||||||
|
|
||||||
/// Cast_Helper_Inner for casting to a & type
|
/// Cast_Helper_Inner for casting to a & type
|
||||||
template<typename Result>
|
template<typename Result>
|
||||||
struct Cast_Helper_Inner<const Result &>
|
struct Cast_Helper_Inner<const Result &> {
|
||||||
{
|
static const Result &cast(const Boxed_Value &ob, const Type_Conversions_State *) {
|
||||||
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()));
|
||||||
{
|
}
|
||||||
return *static_cast<const Result *>(verify_type(ob, typeid(Result), ob.get_const_ptr()));
|
};
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// Cast_Helper_Inner for casting to a & type
|
/// Cast_Helper_Inner for casting to a & type
|
||||||
template<typename Result>
|
template<typename Result>
|
||||||
struct Cast_Helper_Inner<Result &>
|
struct Cast_Helper_Inner<Result &> {
|
||||||
{
|
static Result &cast(const Boxed_Value &ob, const Type_Conversions_State *) {
|
||||||
static Result& cast(const Boxed_Value &ob, const Type_Conversions_State *)
|
return *static_cast<Result *>(verify_type(ob, typeid(Result), ob.get_ptr()));
|
||||||
{
|
}
|
||||||
return *static_cast<Result *>(verify_type(ob, typeid(Result), ob.get_ptr()));
|
};
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Cast_Helper_Inner for casting to a && type
|
/// Cast_Helper_Inner for casting to a && type
|
||||||
template<typename Result>
|
template<typename Result>
|
||||||
struct Cast_Helper_Inner<Result &&>
|
struct Cast_Helper_Inner<Result &&> {
|
||||||
{
|
static Result &&cast(const Boxed_Value &ob, const Type_Conversions_State *) {
|
||||||
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())));
|
||||||
{
|
}
|
||||||
return std::move(*static_cast<Result *>(verify_type(ob, typeid(Result), ob.get_ptr())));
|
};
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Cast_Helper_Inner for casting to a std::unique_ptr<> && type
|
/// 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
|
/// \todo Fix the fact that this has to be in a shared_ptr for now
|
||||||
template<typename Result>
|
template<typename Result>
|
||||||
struct Cast_Helper_Inner<std::unique_ptr<Result> &&>
|
struct Cast_Helper_Inner<std::unique_ptr<Result> &&> {
|
||||||
{
|
static std::unique_ptr<Result> &&cast(const Boxed_Value &ob, const Type_Conversions_State *) {
|
||||||
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>>>()));
|
||||||
{
|
}
|
||||||
return std::move(*(ob.get().cast<std::shared_ptr<std::unique_ptr<Result>>>()));
|
};
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Cast_Helper_Inner for casting to a std::unique_ptr<> & type
|
/// 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
|
/// \todo Fix the fact that this has to be in a shared_ptr for now
|
||||||
template<typename Result>
|
template<typename Result>
|
||||||
struct Cast_Helper_Inner<std::unique_ptr<Result> &>
|
struct Cast_Helper_Inner<std::unique_ptr<Result> &> {
|
||||||
{
|
static std::unique_ptr<Result> &cast(const Boxed_Value &ob, const Type_Conversions_State *) {
|
||||||
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>>>());
|
||||||
{
|
}
|
||||||
return *(ob.get().cast<std::shared_ptr<std::unique_ptr<Result>>>());
|
};
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Cast_Helper_Inner for casting to a std::unique_ptr<> & type
|
/// 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
|
/// \todo Fix the fact that this has to be in a shared_ptr for now
|
||||||
template<typename Result>
|
template<typename Result>
|
||||||
struct Cast_Helper_Inner<const std::unique_ptr<Result> &>
|
struct Cast_Helper_Inner<const std::unique_ptr<Result> &> {
|
||||||
{
|
static std::unique_ptr<Result> &cast(const Boxed_Value &ob, const Type_Conversions_State *) {
|
||||||
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>>>());
|
||||||
{
|
}
|
||||||
return *(ob.get().cast<std::shared_ptr<std::unique_ptr<Result>>>());
|
};
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/// Cast_Helper_Inner for casting to a std::shared_ptr<> type
|
/// Cast_Helper_Inner for casting to a std::shared_ptr<> type
|
||||||
template<typename Result>
|
template<typename Result>
|
||||||
struct Cast_Helper_Inner<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>>(); }
|
||||||
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
|
/// Cast_Helper_Inner for casting to a std::shared_ptr<const> type
|
||||||
template<typename Result>
|
template<typename Result>
|
||||||
struct Cast_Helper_Inner<std::shared_ptr<const Result> >
|
struct Cast_Helper_Inner<std::shared_ptr<const Result>> {
|
||||||
{
|
static auto cast(const Boxed_Value &ob, const Type_Conversions_State *) {
|
||||||
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>>());
|
||||||
if (!ob.get_type_info().is_const())
|
} else {
|
||||||
{
|
return ob.get().cast<std::shared_ptr<const Result>>();
|
||||||
return std::const_pointer_cast<const Result>(ob.get().cast<std::shared_ptr<Result> >());
|
|
||||||
} else {
|
|
||||||
return ob.get().cast<std::shared_ptr<const Result> >();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/// Cast_Helper_Inner for casting to a const std::shared_ptr<> & type
|
/// Cast_Helper_Inner for casting to a const std::shared_ptr<> & type
|
||||||
template<typename 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>
|
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>
|
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_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 *) {
|
||||||
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);
|
||||||
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
|
/// Cast_Helper_Inner for casting to a const std::shared_ptr<const> & type
|
||||||
template<typename 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>> {
|
||||||
{
|
};
|
||||||
};
|
|
||||||
|
|
||||||
template<typename 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
|
/// Cast_Helper_Inner for casting to a Boxed_Value type
|
||||||
template<>
|
template<>
|
||||||
struct Cast_Helper_Inner<Boxed_Value>
|
struct Cast_Helper_Inner<Boxed_Value> {
|
||||||
{
|
static Boxed_Value cast(const Boxed_Value &ob, const Type_Conversions_State *) { return ob; }
|
||||||
static Boxed_Value cast(const Boxed_Value &ob, const Type_Conversions_State *)
|
};
|
||||||
{
|
|
||||||
return ob;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Cast_Helper_Inner for casting to a Boxed_Value & type
|
/// Cast_Helper_Inner for casting to a Boxed_Value & type
|
||||||
template<>
|
template<>
|
||||||
struct Cast_Helper_Inner<Boxed_Value &>
|
struct Cast_Helper_Inner<Boxed_Value &> {
|
||||||
{
|
static std::reference_wrapper<Boxed_Value> cast(const Boxed_Value &ob, const Type_Conversions_State *) {
|
||||||
static std::reference_wrapper<Boxed_Value> cast(const Boxed_Value &ob, const Type_Conversions_State *)
|
return std::ref(const_cast<Boxed_Value &>(ob));
|
||||||
{
|
}
|
||||||
return std::ref(const_cast<Boxed_Value &>(ob));
|
};
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/// Cast_Helper_Inner for casting to a const Boxed_Value & type
|
/// Cast_Helper_Inner for casting to a const Boxed_Value & type
|
||||||
template<>
|
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<>
|
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
|
/// Cast_Helper_Inner for casting to a std::reference_wrapper type
|
||||||
template<typename Result>
|
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>
|
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>
|
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>
|
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>
|
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>
|
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
|
/// The exposed Cast_Helper object that by default just calls the Cast_Helper_Inner
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct Cast_Helper
|
struct Cast_Helper {
|
||||||
{
|
static decltype(auto) cast(const Boxed_Value &ob, const Type_Conversions_State *t_conversions) {
|
||||||
static decltype(auto) cast(const Boxed_Value &ob, const Type_Conversions_State *t_conversions)
|
return (Cast_Helper_Inner<T>::cast(ob, t_conversions));
|
||||||
{
|
}
|
||||||
return(Cast_Helper_Inner<T>::cast(ob, t_conversions));
|
};
|
||||||
}
|
} // namespace detail
|
||||||
};
|
|
||||||
}
|
} // namespace chaiscript
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#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.
|
// 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
|
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||||
|
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_BOXED_VALUE_HPP_
|
#ifndef CHAISCRIPT_BOXED_VALUE_HPP_
|
||||||
#define CHAISCRIPT_BOXED_VALUE_HPP_
|
#define CHAISCRIPT_BOXED_VALUE_HPP_
|
||||||
|
|
||||||
@ -19,357 +18,238 @@
|
|||||||
#include "any.hpp"
|
#include "any.hpp"
|
||||||
#include "type_info.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
|
/// \brief A wrapper for holding any valid C++ type. All types in ChaiScript are Boxed_Value objects
|
||||||
/// \sa chaiscript::boxed_cast
|
/// \sa chaiscript::boxed_cast
|
||||||
class Boxed_Value
|
class Boxed_Value {
|
||||||
{
|
public:
|
||||||
public:
|
/// used for explicitly creating a "void" object
|
||||||
/// used for explicitly creating a "void" object
|
struct Void_Type {
|
||||||
struct Void_Type
|
};
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// structure which holds the internal state of a Boxed_Value
|
/// 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
|
/// \todo Get rid of Any and merge it with this, reducing an allocation in the process
|
||||||
struct Data
|
struct Data {
|
||||||
{
|
Data(const Type_Info &ti, chaiscript::detail::Any to, bool is_ref, const void *t_void_ptr, bool t_return_value)
|
||||||
Data(const Type_Info &ti,
|
: m_type_info(ti)
|
||||||
chaiscript::detail::Any to,
|
, m_obj(std::move(to))
|
||||||
bool is_ref,
|
, m_data_ptr(ti.is_const() ? nullptr : const_cast<void *>(t_void_ptr))
|
||||||
const void *t_void_ptr,
|
, m_const_data_ptr(t_void_ptr)
|
||||||
bool t_return_value)
|
, m_is_ref(is_ref)
|
||||||
: 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_return_value(t_return_value) {
|
||||||
m_is_ref(is_ref), m_return_value(t_return_value)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
Data &operator=(const Data &rhs)
|
|
||||||
{
|
|
||||||
m_type_info = rhs.m_type_info;
|
|
||||||
m_obj = rhs.m_obj;
|
|
||||||
m_is_ref = rhs.m_is_ref;
|
|
||||||
m_data_ptr = rhs.m_data_ptr;
|
|
||||||
m_const_data_ptr = rhs.m_const_data_ptr;
|
|
||||||
m_return_value = rhs.m_return_value;
|
|
||||||
|
|
||||||
if (rhs.m_attrs)
|
|
||||||
{
|
|
||||||
m_attrs = std::make_unique<std::map<std::string, std::shared_ptr<Data>>>(*rhs.m_attrs);
|
|
||||||
}
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Data(const Data &) = delete;
|
|
||||||
|
|
||||||
Data(Data &&) = default;
|
|
||||||
Data &operator=(Data &&rhs) = default;
|
|
||||||
|
|
||||||
|
|
||||||
Type_Info m_type_info;
|
|
||||||
chaiscript::detail::Any m_obj;
|
|
||||||
void *m_data_ptr;
|
|
||||||
const void *m_const_data_ptr;
|
|
||||||
std::unique_ptr<std::map<std::string, std::shared_ptr<Data>>> m_attrs;
|
|
||||||
bool m_is_ref;
|
|
||||||
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)
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
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
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
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
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
return get(std::cref(*t), t_return_value);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
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
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
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(),
|
|
||||||
chaiscript::detail::Any(std::make_shared<std::unique_ptr<T>>(std::move(obj))),
|
|
||||||
true,
|
|
||||||
ptr,
|
|
||||||
t_return_value
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
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
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
|
||||||
/// Basic Boxed_Value constructor
|
|
||||||
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))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 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;
|
|
||||||
|
|
||||||
void swap(Boxed_Value &rhs) noexcept
|
|
||||||
{
|
|
||||||
std::swap(m_data, rhs.m_data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Copy the values stored in rhs.m_data to m_data.
|
Data &operator=(const Data &rhs) {
|
||||||
/// m_data pointers are not shared in this case
|
m_type_info = rhs.m_type_info;
|
||||||
Boxed_Value assign(const Boxed_Value &rhs) noexcept
|
m_obj = rhs.m_obj;
|
||||||
{
|
m_is_ref = rhs.m_is_ref;
|
||||||
(*m_data) = (*rhs.m_data);
|
m_data_ptr = rhs.m_data_ptr;
|
||||||
|
m_const_data_ptr = rhs.m_const_data_ptr;
|
||||||
|
m_return_value = rhs.m_return_value;
|
||||||
|
|
||||||
|
if (rhs.m_attrs) {
|
||||||
|
m_attrs = std::make_unique<std::map<std::string, std::shared_ptr<Data>>>(*rhs.m_attrs);
|
||||||
|
}
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Type_Info &get_type_info() const noexcept
|
Data(const Data &) = delete;
|
||||||
{
|
|
||||||
return m_data->m_type_info;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// return true if the object is uninitialized
|
Data(Data &&) = default;
|
||||||
bool is_undef() const noexcept
|
Data &operator=(Data &&rhs) = default;
|
||||||
{
|
|
||||||
return m_data->m_type_info.is_undef();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_const() const noexcept
|
Type_Info m_type_info;
|
||||||
{
|
chaiscript::detail::Any m_obj;
|
||||||
return m_data->m_type_info.is_const();
|
void *m_data_ptr;
|
||||||
}
|
const void *m_const_data_ptr;
|
||||||
|
std::unique_ptr<std::map<std::string, std::shared_ptr<Data>>> m_attrs;
|
||||||
|
bool m_is_ref;
|
||||||
|
bool m_return_value;
|
||||||
|
};
|
||||||
|
|
||||||
bool is_type(const Type_Info &ti) const noexcept
|
struct Object_Data {
|
||||||
{
|
static auto get(Boxed_Value::Void_Type, bool t_return_value) {
|
||||||
return m_data->m_type_info.bare_equal(ti);
|
return std::make_shared<Data>(detail::Get_Type_Info<void>::get(), chaiscript::detail::Any(), false, nullptr, t_return_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
auto pointer_sentinel(std::shared_ptr<T> &ptr) const noexcept
|
static auto get(const std::shared_ptr<T> *obj, bool t_return_value) {
|
||||||
{
|
return get(*obj, t_return_value);
|
||||||
struct Sentinel {
|
|
||||||
Sentinel(std::shared_ptr<T> &t_ptr, Data &data)
|
|
||||||
: m_ptr(t_ptr), m_data(data)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
~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(Sentinel &&s) = default;
|
|
||||||
|
|
||||||
operator std::shared_ptr<T>&() const noexcept
|
|
||||||
{
|
|
||||||
return m_ptr.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
Sentinel &operator=(const Sentinel &) = delete;
|
|
||||||
Sentinel(Sentinel&) = delete;
|
|
||||||
|
|
||||||
std::reference_wrapper<std::shared_ptr<T>> m_ptr;
|
|
||||||
std::reference_wrapper<Data> m_data;
|
|
||||||
};
|
|
||||||
|
|
||||||
return Sentinel(ptr, *(m_data.get()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_null() const noexcept
|
template<typename T>
|
||||||
{
|
static auto get(const std::shared_ptr<T> &obj, bool t_return_value) {
|
||||||
return (m_data->m_data_ptr == nullptr && m_data->m_const_data_ptr == nullptr);
|
return std::make_shared<Data>(detail::Get_Type_Info<T>::get(), chaiscript::detail::Any(obj), false, obj.get(), t_return_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
const chaiscript::detail::Any & get() const noexcept
|
template<typename T>
|
||||||
{
|
static auto get(std::shared_ptr<T> &&obj, bool t_return_value) {
|
||||||
return m_data->m_obj;
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_ref() const noexcept
|
template<typename T>
|
||||||
{
|
static auto get(T *t, bool t_return_value) {
|
||||||
return m_data->m_is_ref;
|
return get(std::ref(*t), t_return_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_return_value() const noexcept
|
template<typename T>
|
||||||
{
|
static auto get(const T *t, bool t_return_value) {
|
||||||
return m_data->m_return_value;
|
return get(std::cref(*t), t_return_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void reset_return_value() const noexcept
|
template<typename T>
|
||||||
{
|
static auto get(std::reference_wrapper<T> obj, bool t_return_value) {
|
||||||
m_data->m_return_value = false;
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_pointer() const noexcept
|
template<typename T>
|
||||||
{
|
static auto get(std::unique_ptr<T> &&obj, bool t_return_value) {
|
||||||
return !is_ref();
|
auto ptr = obj.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);
|
||||||
}
|
}
|
||||||
|
|
||||||
void *get_ptr() const noexcept
|
template<typename T>
|
||||||
{
|
static auto get(T t, bool t_return_value) {
|
||||||
return m_data->m_data_ptr;
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
const void *get_const_ptr() const noexcept
|
static std::shared_ptr<Data> get() { return std::make_shared<Data>(Type_Info(), chaiscript::detail::Any(), false, nullptr, false); }
|
||||||
{
|
};
|
||||||
return m_data->m_const_data_ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
Boxed_Value get_attr(const std::string &t_name)
|
public:
|
||||||
{
|
/// Basic Boxed_Value constructor
|
||||||
if (!m_data->m_attrs)
|
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->m_attrs = std::make_unique<std::map<std::string, std::shared_ptr<Data>>>();
|
: 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;
|
||||||
|
|
||||||
|
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 {
|
||||||
|
(*m_data) = (*rhs.m_data);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
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_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 {
|
||||||
|
struct Sentinel {
|
||||||
|
Sentinel(std::shared_ptr<T> &t_ptr, Data &data)
|
||||||
|
: m_ptr(t_ptr)
|
||||||
|
, m_data(data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto &attr = (*m_data->m_attrs)[t_name];
|
~Sentinel() {
|
||||||
if (attr) {
|
// save new pointer data
|
||||||
return Boxed_Value(attr, Internal_Construction());
|
const auto ptr_ = m_ptr.get().get();
|
||||||
} else {
|
m_data.get().m_data_ptr = ptr_;
|
||||||
Boxed_Value bv; //default construct a new one
|
m_data.get().m_const_data_ptr = ptr_;
|
||||||
attr = bv.m_data;
|
|
||||||
return bv;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Sentinel &operator=(Sentinel &&s) = default;
|
||||||
|
Sentinel(Sentinel &&s) = default;
|
||||||
|
|
||||||
|
operator std::shared_ptr<T> &() const noexcept { return m_ptr.get(); }
|
||||||
|
|
||||||
|
Sentinel &operator=(const Sentinel &) = delete;
|
||||||
|
Sentinel(Sentinel &) = delete;
|
||||||
|
|
||||||
|
std::reference_wrapper<std::shared_ptr<T>> m_ptr;
|
||||||
|
std::reference_wrapper<Data> m_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
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); }
|
||||||
|
|
||||||
|
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_return_value() const noexcept { return m_data->m_return_value; }
|
||||||
|
|
||||||
|
void reset_return_value() const noexcept { m_data->m_return_value = false; }
|
||||||
|
|
||||||
|
bool is_pointer() const noexcept { return !is_ref(); }
|
||||||
|
|
||||||
|
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; }
|
||||||
|
|
||||||
|
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>>>();
|
||||||
}
|
}
|
||||||
|
|
||||||
Boxed_Value ©_attrs(const Boxed_Value &t_obj)
|
auto &attr = (*m_data->m_attrs)[t_name];
|
||||||
{
|
if (attr) {
|
||||||
if (t_obj.m_data->m_attrs)
|
return Boxed_Value(attr, Internal_Construction());
|
||||||
{
|
} else {
|
||||||
m_data->m_attrs = std::make_unique<std::map<std::string, std::shared_ptr<Data>>>(*t_obj.m_data->m_attrs);
|
Boxed_Value bv; // default construct a new one
|
||||||
}
|
attr = bv.m_data;
|
||||||
return *this;
|
return bv;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Boxed_Value &clone_attrs(const Boxed_Value &t_obj)
|
Boxed_Value ©_attrs(const Boxed_Value &t_obj) {
|
||||||
{
|
if (t_obj.m_data->m_attrs) {
|
||||||
copy_attrs(t_obj);
|
m_data->m_attrs = std::make_unique<std::map<std::string, std::shared_ptr<Data>>>(*t_obj.m_data->m_attrs);
|
||||||
reset_return_value();
|
|
||||||
return *this;
|
|
||||||
}
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
/// \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
|
static bool type_match(const Boxed_Value &l, const Boxed_Value &r) noexcept { return l.get_type_info() == r.get_type_info(); }
|
||||||
{
|
|
||||||
return l.get_type_info() == r.get_type_info();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// necessary to avoid hitting the templated && constructor of Boxed_Value
|
// 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)
|
Boxed_Value(std::shared_ptr<Data> t_data, Internal_Construction)
|
||||||
: m_data(std::move(t_data)) {
|
: m_data(std::move(t_data)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<Data> m_data = Object_Data::get();
|
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.
|
/// a copy is not made.
|
||||||
/// @param t The value to box
|
/// @param t The value to box
|
||||||
///
|
///
|
||||||
@ -384,21 +264,19 @@ namespace chaiscript
|
|||||||
///
|
///
|
||||||
/// @sa @ref adding_objects
|
/// @sa @ref adding_objects
|
||||||
template<typename T>
|
template<typename T>
|
||||||
Boxed_Value var(T &&t)
|
Boxed_Value var(T &&t) {
|
||||||
{
|
return Boxed_Value(std::forward<T>(t));
|
||||||
return Boxed_Value(std::forward<T>(t));
|
}
|
||||||
}
|
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
/// \brief Takes a value, copies it and returns a Boxed_Value object that is immutable
|
/// \brief Takes a value, copies it and returns a Boxed_Value object that is immutable
|
||||||
/// \param[in] t Value to copy and make const
|
/// \param[in] t Value to copy and make const
|
||||||
/// \returns Immutable Boxed_Value
|
/// \returns Immutable Boxed_Value
|
||||||
/// \sa Boxed_Value::is_const
|
/// \sa Boxed_Value::is_const
|
||||||
template<typename T>
|
template<typename T>
|
||||||
Boxed_Value const_var_impl(const T &t)
|
Boxed_Value const_var_impl(const T &t) {
|
||||||
{
|
return Boxed_Value(std::make_shared<typename std::add_const<T>::type>(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.
|
/// \brief Takes a pointer to a value, adds const to the pointed to type and returns an immutable Boxed_Value.
|
||||||
/// Does not copy the pointed to value.
|
/// Does not copy the pointed to value.
|
||||||
@ -406,10 +284,9 @@ namespace chaiscript
|
|||||||
/// \returns Immutable Boxed_Value
|
/// \returns Immutable Boxed_Value
|
||||||
/// \sa Boxed_Value::is_const
|
/// \sa Boxed_Value::is_const
|
||||||
template<typename T>
|
template<typename T>
|
||||||
Boxed_Value const_var_impl(T *t)
|
Boxed_Value const_var_impl(T *t) {
|
||||||
{
|
return Boxed_Value(const_cast<typename std::add_const<T>::type *>(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.
|
/// \brief Takes a std::shared_ptr to a value, adds const to the pointed to type and returns an immutable Boxed_Value.
|
||||||
/// Does not copy the pointed to value.
|
/// Does not copy the pointed to value.
|
||||||
@ -417,10 +294,9 @@ namespace chaiscript
|
|||||||
/// \returns Immutable Boxed_Value
|
/// \returns Immutable Boxed_Value
|
||||||
/// \sa Boxed_Value::is_const
|
/// \sa Boxed_Value::is_const
|
||||||
template<typename T>
|
template<typename T>
|
||||||
Boxed_Value const_var_impl(const std::shared_ptr<T> &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));
|
||||||
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.
|
/// \brief Takes a std::reference_wrapper value, adds const to the referenced type and returns an immutable Boxed_Value.
|
||||||
/// Does not copy the referenced value.
|
/// Does not copy the referenced value.
|
||||||
@ -428,11 +304,10 @@ namespace chaiscript
|
|||||||
/// \returns Immutable Boxed_Value
|
/// \returns Immutable Boxed_Value
|
||||||
/// \sa Boxed_Value::is_const
|
/// \sa Boxed_Value::is_const
|
||||||
template<typename T>
|
template<typename T>
|
||||||
Boxed_Value const_var_impl(const std::reference_wrapper<T> &t)
|
Boxed_Value const_var_impl(const std::reference_wrapper<T> &t) {
|
||||||
{
|
return Boxed_Value(std::cref(t.get()));
|
||||||
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
|
/// \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.
|
/// the value is not copied. If it is an object type, it is copied.
|
||||||
@ -454,14 +329,13 @@ namespace chaiscript
|
|||||||
/// chai.add(chaiscript::const_var(Red), "Red");
|
/// chai.add(chaiscript::const_var(Red), "Red");
|
||||||
/// chai.add(chaiscript::const_var(Green), "Green");
|
/// chai.add(chaiscript::const_var(Green), "Green");
|
||||||
/// \endcode
|
/// \endcode
|
||||||
///
|
///
|
||||||
/// \todo support C++11 strongly typed enums
|
/// \todo support C++11 strongly typed enums
|
||||||
/// \sa \ref adding_objects
|
/// \sa \ref adding_objects
|
||||||
template<typename T>
|
template<typename T>
|
||||||
Boxed_Value const_var(const T &t)
|
Boxed_Value const_var(const T &t) {
|
||||||
{
|
return detail::const_var_impl(t);
|
||||||
return detail::const_var_impl(t);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
inline Boxed_Value void_var() {
|
inline Boxed_Value void_var() {
|
||||||
static const auto v = Boxed_Value(Boxed_Value::Void_Type());
|
static const auto v = Boxed_Value(Boxed_Value::Void_Type());
|
||||||
@ -479,7 +353,6 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
} // namespace chaiscript
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@ -12,49 +12,50 @@
|
|||||||
namespace chaiscript {
|
namespace chaiscript {
|
||||||
namespace dispatch {
|
namespace dispatch {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
template<typename Class, typename... Param>
|
||||||
template<typename Class, typename ... Param>
|
struct Constructor {
|
||||||
struct Constructor
|
template<typename... Inner>
|
||||||
{
|
std::shared_ptr<Class> operator()(Inner &&...inner) const {
|
||||||
template<typename ... Inner>
|
|
||||||
std::shared_ptr<Class> operator()(Inner&& ... inner) const {
|
|
||||||
return std::make_shared<Class>(std::forward<Inner>(inner)...);
|
return std::make_shared<Class>(std::forward<Inner>(inner)...);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Ret, typename Class, typename ... Param>
|
template<typename Ret, typename Class, typename... Param>
|
||||||
struct Const_Caller
|
struct Const_Caller {
|
||||||
{
|
explicit Const_Caller(Ret (Class::*t_func)(Param...) const)
|
||||||
explicit Const_Caller(Ret (Class::*t_func)(Param...) const) : m_func(t_func) {}
|
: m_func(t_func) {
|
||||||
|
}
|
||||||
|
|
||||||
template<typename ... Inner>
|
template<typename... Inner>
|
||||||
Ret operator()(const Class &o, Inner&& ... inner) const {
|
Ret operator()(const Class &o, Inner &&...inner) const {
|
||||||
return (o.*m_func)(std::forward<Inner>(inner)...);
|
return (o.*m_func)(std::forward<Inner>(inner)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ret (Class::*m_func)(Param...) const;
|
Ret (Class::*m_func)(Param...) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Ret, typename ... Param>
|
template<typename Ret, typename... Param>
|
||||||
struct Fun_Caller
|
struct Fun_Caller {
|
||||||
{
|
explicit Fun_Caller(Ret (*t_func)(Param...))
|
||||||
explicit Fun_Caller(Ret( * t_func)(Param...) ) : m_func(t_func) {}
|
: m_func(t_func) {
|
||||||
|
}
|
||||||
|
|
||||||
template<typename ... Inner>
|
template<typename... Inner>
|
||||||
Ret operator()(Inner&& ... inner) const {
|
Ret operator()(Inner &&...inner) const {
|
||||||
return (m_func)(std::forward<Inner>(inner)...);
|
return (m_func)(std::forward<Inner>(inner)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ret(*m_func)(Param...);
|
Ret (*m_func)(Param...);
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Ret, typename Class, typename ... Param>
|
template<typename Ret, typename Class, typename... Param>
|
||||||
struct Caller
|
struct Caller {
|
||||||
{
|
explicit Caller(Ret (Class::*t_func)(Param...))
|
||||||
explicit Caller(Ret (Class::*t_func)(Param...)) : m_func(t_func) {}
|
: m_func(t_func) {
|
||||||
|
}
|
||||||
|
|
||||||
template<typename ... Inner>
|
template<typename... Inner>
|
||||||
Ret operator()(Class &o, Inner&& ... inner) const {
|
Ret operator()(Class &o, Inner &&...inner) const {
|
||||||
return (o.*m_func)(std::forward<Inner>(inner)...);
|
return (o.*m_func)(std::forward<Inner>(inner)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,46 +63,37 @@ namespace chaiscript {
|
|||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct Arity
|
struct Arity {
|
||||||
{
|
};
|
||||||
};
|
|
||||||
|
|
||||||
template<typename Ret, typename ... Params>
|
|
||||||
struct Arity<Ret (Params...)>
|
|
||||||
{
|
|
||||||
static const size_t arity = sizeof...(Params);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
template<typename Ret, typename... Params>
|
||||||
|
struct Arity<Ret(Params...)> {
|
||||||
|
static const size_t arity = sizeof...(Params);
|
||||||
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct Function_Signature
|
struct Function_Signature {
|
||||||
{
|
};
|
||||||
};
|
|
||||||
|
|
||||||
template<typename Ret, typename ... Params>
|
template<typename Ret, typename... Params>
|
||||||
struct Function_Signature<Ret (Params...)>
|
struct Function_Signature<Ret(Params...)> {
|
||||||
{
|
using Return_Type = Ret;
|
||||||
using Return_Type = Ret;
|
using Signature = Ret()(Params...);
|
||||||
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 Ret, typename T, typename... Params>
|
||||||
|
struct Function_Signature<Ret (T::*)(Params...) const> {
|
||||||
|
using Return_Type = Ret;
|
||||||
|
using Signature = Ret()(Params...);
|
||||||
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct Callable_Traits
|
struct Callable_Traits {
|
||||||
{
|
using Signature = typename Function_Signature<decltype(&T::operator())>::Signature;
|
||||||
using Signature = typename Function_Signature<decltype(&T::operator())>::Signature;
|
using Return_Type = typename Function_Signature<decltype(&T::operator())>::Return_Type;
|
||||||
using Return_Type = typename Function_Signature<decltype(&T::operator())>::Return_Type;
|
};
|
||||||
};
|
} // namespace detail
|
||||||
}
|
} // namespace dispatch
|
||||||
}
|
} // namespace chaiscript
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#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.
|
// 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
|
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||||
|
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_DYNAMIC_OBJECT_HPP_
|
#ifndef CHAISCRIPT_DYNAMIC_OBJECT_HPP_
|
||||||
#define CHAISCRIPT_DYNAMIC_OBJECT_HPP_
|
#define CHAISCRIPT_DYNAMIC_OBJECT_HPP_
|
||||||
|
|
||||||
@ -18,21 +17,17 @@
|
|||||||
#include "boxed_value.hpp"
|
#include "boxed_value.hpp"
|
||||||
|
|
||||||
namespace chaiscript {
|
namespace chaiscript {
|
||||||
class Type_Conversions;
|
class Type_Conversions;
|
||||||
namespace dispatch {
|
namespace dispatch {
|
||||||
class Proxy_Function_Base;
|
class Proxy_Function_Base;
|
||||||
} // namespace dispatch
|
} // namespace dispatch
|
||||||
} // namespace chaiscript
|
} // namespace chaiscript
|
||||||
|
|
||||||
namespace chaiscript
|
namespace chaiscript {
|
||||||
{
|
namespace dispatch {
|
||||||
namespace dispatch
|
|
||||||
{
|
|
||||||
struct option_explicit_set : std::runtime_error {
|
struct option_explicit_set : std::runtime_error {
|
||||||
explicit option_explicit_set(const std::string &t_param_name)
|
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;
|
option_explicit_set(const option_explicit_set &) = default;
|
||||||
@ -40,92 +35,64 @@ namespace chaiscript
|
|||||||
~option_explicit_set() noexcept override = default;
|
~option_explicit_set() noexcept override = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Dynamic_Object
|
class Dynamic_Object {
|
||||||
{
|
public:
|
||||||
public:
|
explicit Dynamic_Object(std::string t_type_name)
|
||||||
explicit Dynamic_Object(std::string t_type_name)
|
: m_type_name(std::move(t_type_name))
|
||||||
: m_type_name(std::move(t_type_name)), m_option_explicit(false)
|
, m_option_explicit(false) {
|
||||||
{
|
}
|
||||||
|
|
||||||
|
Dynamic_Object() = default;
|
||||||
|
|
||||||
|
bool is_explicit() const noexcept { return m_option_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 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); }
|
||||||
|
|
||||||
|
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()) {
|
||||||
|
return a->second;
|
||||||
|
} else {
|
||||||
|
throw std::range_error("Attr not found '" + t_attr_name + "' and cannot be added to const obj");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 &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);
|
||||||
}
|
}
|
||||||
|
|
||||||
Dynamic_Object() = default;
|
return get_attr(t_method_name);
|
||||||
|
}
|
||||||
|
|
||||||
bool is_explicit() const noexcept
|
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()) {
|
||||||
return m_option_explicit;
|
throw option_explicit_set(t_method_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_explicit(const bool t_explicit) noexcept
|
return get_attr(t_method_name);
|
||||||
{
|
}
|
||||||
m_option_explicit = t_explicit;
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::string &get_type_name() const noexcept
|
std::map<std::string, Boxed_Value> get_attrs() const { return m_attrs; }
|
||||||
{
|
|
||||||
return m_type_name;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Boxed_Value &operator[](const std::string &t_attr_name) const
|
private:
|
||||||
{
|
const std::string m_type_name = "";
|
||||||
return get_attr(t_attr_name);
|
bool m_option_explicit = false;
|
||||||
}
|
|
||||||
|
|
||||||
Boxed_Value &operator[](const std::string &t_attr_name)
|
std::map<std::string, Boxed_Value> m_attrs;
|
||||||
{
|
|
||||||
return get_attr(t_attr_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
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()) {
|
|
||||||
return a->second;
|
|
||||||
} else {
|
|
||||||
throw std::range_error("Attr not found '" + t_attr_name + "' and cannot be added to const obj");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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 &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);
|
|
||||||
}
|
|
||||||
|
|
||||||
return get_attr(t_method_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
return get_attr(t_method_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::map<std::string, Boxed_Value> get_attrs() const
|
|
||||||
{
|
|
||||||
return m_attrs;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
const std::string m_type_name = "";
|
|
||||||
bool m_option_explicit = false;
|
|
||||||
|
|
||||||
std::map<std::string, Boxed_Value> m_attrs;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
} // namespace dispatch
|
||||||
}
|
} // namespace chaiscript
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@ -19,219 +19,185 @@
|
|||||||
#include "boxed_cast.hpp"
|
#include "boxed_cast.hpp"
|
||||||
#include "boxed_cast_helper.hpp"
|
#include "boxed_cast_helper.hpp"
|
||||||
#include "boxed_value.hpp"
|
#include "boxed_value.hpp"
|
||||||
|
#include "dynamic_object.hpp"
|
||||||
#include "proxy_functions.hpp"
|
#include "proxy_functions.hpp"
|
||||||
#include "type_info.hpp"
|
#include "type_info.hpp"
|
||||||
#include "dynamic_object.hpp"
|
|
||||||
|
|
||||||
namespace chaiscript {
|
namespace chaiscript {
|
||||||
class Type_Conversions;
|
class Type_Conversions;
|
||||||
namespace dispatch {
|
namespace dispatch {
|
||||||
class Proxy_Function_Base;
|
class Proxy_Function_Base;
|
||||||
} // namespace dispatch
|
} // namespace dispatch
|
||||||
} // namespace chaiscript
|
} // namespace chaiscript
|
||||||
|
|
||||||
namespace chaiscript
|
namespace chaiscript {
|
||||||
{
|
namespace dispatch {
|
||||||
namespace dispatch
|
namespace detail {
|
||||||
{
|
|
||||||
namespace detail
|
|
||||||
{
|
|
||||||
/// A Proxy_Function implementation designed for calling a function
|
/// A Proxy_Function implementation designed for calling a function
|
||||||
/// that is automatically guarded based on the first param based on the
|
/// that is automatically guarded based on the first param based on the
|
||||||
/// param's type name
|
/// param's type name
|
||||||
class Dynamic_Object_Function final : public Proxy_Function_Base
|
class Dynamic_Object_Function final : public Proxy_Function_Base {
|
||||||
{
|
public:
|
||||||
public:
|
Dynamic_Object_Function(std::string t_type_name, const Proxy_Function &t_func, bool t_is_attribute = false)
|
||||||
Dynamic_Object_Function(
|
: Proxy_Function_Base(t_func->get_param_types(), t_func->get_arity())
|
||||||
std::string t_type_name,
|
, m_type_name(std::move(t_type_name))
|
||||||
const Proxy_Function &t_func,
|
, m_func(t_func)
|
||||||
bool t_is_attribute = false)
|
, m_doti(user_type<Dynamic_Object>())
|
||||||
: Proxy_Function_Base(t_func->get_param_types(), t_func->get_arity()),
|
, m_is_attribute(t_is_attribute) {
|
||||||
m_type_name(std::move(t_type_name)), m_func(t_func), m_doti(user_type<Dynamic_Object>()),
|
assert((t_func->get_arity() > 0 || t_func->get_arity() < 0)
|
||||||
m_is_attribute(t_is_attribute)
|
&& "Programming error, Dynamic_Object_Function must have at least one parameter (this)");
|
||||||
{
|
}
|
||||||
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)
|
||||||
|
&& "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)) {
|
||||||
|
return df->m_type_name == m_type_name && (*df->m_func) == (*m_func);
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Dynamic_Object_Function(
|
bool is_attribute_function() const noexcept override { return m_is_attribute; }
|
||||||
std::string t_type_name,
|
|
||||||
const Proxy_Function &t_func,
|
bool call_match(const chaiscript::Function_Params &vals, const Type_Conversions_State &t_conversions) const noexcept override {
|
||||||
const Type_Info &t_ti,
|
if (dynamic_object_typename_match(vals, m_type_name, m_ti, t_conversions)) {
|
||||||
bool t_is_attribute = false)
|
return m_func->call_match(vals, t_conversions);
|
||||||
: Proxy_Function_Base(build_param_types(t_func->get_param_types(), t_ti), t_func->get_arity()),
|
} else {
|
||||||
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>()),
|
return false;
|
||||||
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)");
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<Const_Proxy_Function> get_contained_functions() const override { return {m_func}; }
|
||||||
|
|
||||||
Dynamic_Object_Function &operator=(const Dynamic_Object_Function) = delete;
|
protected:
|
||||||
Dynamic_Object_Function(Dynamic_Object_Function &) = delete;
|
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 operator==(const Proxy_Function_Base &f) 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);
|
||||||
if (const auto *df = dynamic_cast<const Dynamic_Object_Function *>(&f))
|
}
|
||||||
{
|
|
||||||
return df->m_type_name == m_type_name && (*df->m_func) == (*m_func);
|
private:
|
||||||
|
static std::vector<Type_Info> build_param_types(const std::vector<Type_Info> &t_inner_types, const Type_Info &t_objectti) {
|
||||||
|
std::vector<Type_Info> types(t_inner_types);
|
||||||
|
|
||||||
|
assert(types.size() > 1);
|
||||||
|
// assert(types[1].bare_equal(user_type<Boxed_Value>()));
|
||||||
|
types[1] = t_objectti;
|
||||||
|
return types;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool dynamic_object_typename_match(const Boxed_Value &bv,
|
||||||
|
const std::string &name,
|
||||||
|
const std::unique_ptr<Type_Info> &ti,
|
||||||
|
const Type_Conversions_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;
|
||||||
|
} catch (const std::bad_cast &) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (ti) {
|
||||||
|
return bv.get_type_info().bare_equal(*ti);
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool is_attribute_function() const noexcept override { return m_is_attribute; }
|
bool dynamic_object_typename_match(const chaiscript::Function_Params &bvs,
|
||||||
|
const std::string &name,
|
||||||
bool call_match(const chaiscript::Function_Params &vals, const Type_Conversions_State &t_conversions) const noexcept override
|
const std::unique_ptr<Type_Info> &ti,
|
||||||
{
|
const Type_Conversions_State &t_conversions) const noexcept {
|
||||||
if (dynamic_object_typename_match(vals, m_type_name, m_ti, t_conversions))
|
if (!bvs.empty()) {
|
||||||
{
|
return dynamic_object_typename_match(bvs[0], name, ti, t_conversions);
|
||||||
return m_func->call_match(vals, t_conversions);
|
} else {
|
||||||
} else {
|
return false;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<Const_Proxy_Function> get_contained_functions() const override
|
std::string m_type_name;
|
||||||
{
|
Proxy_Function m_func;
|
||||||
return {m_func};
|
std::unique_ptr<Type_Info> m_ti;
|
||||||
}
|
const Type_Info m_doti;
|
||||||
|
const bool m_is_attribute;
|
||||||
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))
|
|
||||||
{
|
|
||||||
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
|
|
||||||
{
|
|
||||||
return dynamic_object_typename_match(bv, m_type_name, m_ti, t_conversions);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
static std::vector<Type_Info> build_param_types(
|
|
||||||
const std::vector<Type_Info> &t_inner_types, const Type_Info& t_objectti)
|
|
||||||
{
|
|
||||||
std::vector<Type_Info> types(t_inner_types);
|
|
||||||
|
|
||||||
assert(types.size() > 1);
|
|
||||||
//assert(types[1].bare_equal(user_type<Boxed_Value>()));
|
|
||||||
types[1] = t_objectti;
|
|
||||||
return types;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool dynamic_object_typename_match(const Boxed_Value &bv, const std::string &name,
|
|
||||||
const std::unique_ptr<Type_Info> &ti, const Type_Conversions_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;
|
|
||||||
} catch (const std::bad_cast &) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (ti)
|
|
||||||
{
|
|
||||||
return bv.get_type_info().bare_equal(*ti);
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
bool dynamic_object_typename_match(const 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string m_type_name;
|
|
||||||
Proxy_Function m_func;
|
|
||||||
std::unique_ptr<Type_Info> m_ti;
|
|
||||||
const Type_Info m_doti;
|
|
||||||
const bool m_is_attribute;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A Proxy_Function implementation designed for creating a new
|
* A Proxy_Function implementation designed for creating a new
|
||||||
* Dynamic_Object
|
* Dynamic_Object
|
||||||
* that is automatically guarded based on the first param based on the
|
* that is automatically guarded based on the first param based on the
|
||||||
* param's type name
|
* param's type name
|
||||||
*/
|
*/
|
||||||
class Dynamic_Object_Constructor final : public Proxy_Function_Base
|
class Dynamic_Object_Constructor final : public Proxy_Function_Base {
|
||||||
{
|
public:
|
||||||
public:
|
Dynamic_Object_Constructor(std::string t_type_name, const Proxy_Function &t_func)
|
||||||
Dynamic_Object_Constructor(
|
: Proxy_Function_Base(build_type_list(t_func->get_param_types()), t_func->get_arity() - 1)
|
||||||
std::string t_type_name,
|
, m_type_name(std::move(t_type_name))
|
||||||
const Proxy_Function &t_func)
|
, m_func(t_func) {
|
||||||
: Proxy_Function_Base(build_type_list(t_func->get_param_types()), t_func->get_arity() - 1),
|
assert((t_func->get_arity() > 0 || t_func->get_arity() < 0)
|
||||||
m_type_name(std::move(t_type_name)), m_func(t_func)
|
&& "Programming error, Dynamic_Object_Function must have at least one parameter (this)");
|
||||||
{
|
}
|
||||||
assert( (t_func->get_arity() > 0 || t_func->get_arity() < 0)
|
|
||||||
&& "Programming error, Dynamic_Object_Function must have at least one parameter (this)");
|
static std::vector<Type_Info> build_type_list(const std::vector<Type_Info> &tl) {
|
||||||
|
auto begin = tl.begin();
|
||||||
|
auto end = tl.end();
|
||||||
|
|
||||||
|
if (begin != end) {
|
||||||
|
++begin;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::vector<Type_Info> build_type_list(const std::vector<Type_Info> &tl)
|
return std::vector<Type_Info>(begin, end);
|
||||||
{
|
}
|
||||||
auto begin = tl.begin();
|
|
||||||
auto end = tl.end();
|
|
||||||
|
|
||||||
if (begin != end)
|
bool operator==(const Proxy_Function_Base &f) const noexcept override {
|
||||||
{
|
const Dynamic_Object_Constructor *dc = dynamic_cast<const Dynamic_Object_Constructor *>(&f);
|
||||||
++begin;
|
return (dc != nullptr) && dc->m_type_name == m_type_name && (*dc->m_func) == (*m_func);
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::vector<Type_Info>(begin, end);
|
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());
|
||||||
|
|
||||||
bool operator==(const Proxy_Function_Base &f) const noexcept override
|
return m_func->call_match(chaiscript::Function_Params{new_vals}, t_conversions);
|
||||||
{
|
}
|
||||||
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
|
protected:
|
||||||
{
|
Boxed_Value do_call(const chaiscript::Function_Params ¶ms, const Type_Conversions_State &t_conversions) const override {
|
||||||
std::vector<Boxed_Value> new_vals{Boxed_Value(Dynamic_Object(m_type_name))};
|
auto bv = Boxed_Value(Dynamic_Object(m_type_name), true);
|
||||||
new_vals.insert(new_vals.end(), vals.begin(), vals.end());
|
std::vector<Boxed_Value> new_params{bv};
|
||||||
|
new_params.insert(new_params.end(), params.begin(), params.end());
|
||||||
|
|
||||||
return m_func->call_match(chaiscript::Function_Params{new_vals}, t_conversions);
|
(*m_func)(chaiscript::Function_Params{new_params}, t_conversions);
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
return bv;
|
||||||
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());
|
|
||||||
|
|
||||||
(*m_func)(chaiscript::Function_Params{new_params}, t_conversions);
|
|
||||||
|
|
||||||
return bv;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
const std::string m_type_name;
|
|
||||||
const Proxy_Function m_func;
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
const std::string m_type_name;
|
||||||
|
const Proxy_Function m_func;
|
||||||
};
|
};
|
||||||
}
|
} // namespace detail
|
||||||
}
|
} // namespace dispatch
|
||||||
}
|
} // namespace chaiscript
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@ -7,7 +7,6 @@
|
|||||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
// 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
|
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||||
|
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_EXCEPTION_SPECIFICATION_HPP_
|
#ifndef CHAISCRIPT_EXCEPTION_SPECIFICATION_HPP_
|
||||||
#define CHAISCRIPT_EXCEPTION_SPECIFICATION_HPP_
|
#define CHAISCRIPT_EXCEPTION_SPECIFICATION_HPP_
|
||||||
|
|
||||||
@ -17,39 +16,28 @@
|
|||||||
#include "boxed_cast.hpp"
|
#include "boxed_cast.hpp"
|
||||||
|
|
||||||
namespace chaiscript {
|
namespace chaiscript {
|
||||||
class Boxed_Value;
|
namespace detail {
|
||||||
namespace exception {
|
struct Exception_Handler_Base {
|
||||||
class bad_boxed_cast;
|
|
||||||
} // namespace exception
|
|
||||||
} // namespace chaiscript
|
|
||||||
|
|
||||||
namespace chaiscript
|
|
||||||
{
|
|
||||||
namespace detail
|
|
||||||
{
|
|
||||||
struct Exception_Handler_Base
|
|
||||||
{
|
|
||||||
virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine) = 0;
|
virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine) = 0;
|
||||||
|
|
||||||
virtual ~Exception_Handler_Base() = default;
|
virtual ~Exception_Handler_Base() = default;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static void throw_type(const Boxed_Value &bv, const Dispatch_Engine &t_engine)
|
static void throw_type(const Boxed_Value &bv, const Dispatch_Engine &t_engine) {
|
||||||
{
|
try {
|
||||||
try { T t = t_engine.boxed_cast<T>(bv); throw t; } catch (const chaiscript::exception::bad_boxed_cast &) {}
|
T t = t_engine.boxed_cast<T>(bv);
|
||||||
|
throw t;
|
||||||
|
} catch (const chaiscript::exception::bad_boxed_cast &) {
|
||||||
}
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename ... T>
|
template<typename... T>
|
||||||
struct Exception_Handler_Impl : Exception_Handler_Base
|
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), ...); }
|
||||||
void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine) override
|
};
|
||||||
{
|
} // namespace detail
|
||||||
(throw_type<T>(bv, t_engine), ...);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// \brief Used in the automatic unboxing of exceptions thrown during script evaluation
|
/// \brief Used in the automatic unboxing of exceptions thrown during script evaluation
|
||||||
///
|
///
|
||||||
@ -61,7 +49,8 @@ namespace chaiscript
|
|||||||
/// chaiscript::ChaiScript chai;
|
/// chaiscript::ChaiScript chai;
|
||||||
///
|
///
|
||||||
/// try {
|
/// 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 (const double e) {
|
||||||
/// } catch (int) {
|
/// } catch (int) {
|
||||||
/// } catch (float) {
|
/// } catch (float) {
|
||||||
@ -86,7 +75,7 @@ namespace chaiscript
|
|||||||
///
|
///
|
||||||
/// Similarly, if you are using the ChaiScript::eval form that unboxes the return value, then chaiscript::exception::bad_boxed_cast
|
/// Similarly, if you are using the ChaiScript::eval form that unboxes the return value, then chaiscript::exception::bad_boxed_cast
|
||||||
/// should be handled as well.
|
/// should be handled as well.
|
||||||
///
|
///
|
||||||
/// \code
|
/// \code
|
||||||
/// try {
|
/// try {
|
||||||
/// chai.eval<int>("1.0", chaiscript::exception_specification<const std::exception &>());
|
/// chai.eval<int>("1.0", chaiscript::exception_specification<const std::exception &>());
|
||||||
@ -105,13 +94,10 @@ namespace chaiscript
|
|||||||
|
|
||||||
/// \brief creates a chaiscript::Exception_Handler which handles one type of exception unboxing
|
/// \brief creates a chaiscript::Exception_Handler which handles one type of exception unboxing
|
||||||
/// \sa \ref exceptions
|
/// \sa \ref exceptions
|
||||||
template<typename ... T>
|
template<typename... T>
|
||||||
Exception_Handler exception_specification()
|
Exception_Handler exception_specification() {
|
||||||
{
|
|
||||||
return std::make_shared<detail::Exception_Handler_Impl<T...>>();
|
return std::make_shared<detail::Exception_Handler_Impl<T...>>();
|
||||||
}
|
}
|
||||||
}
|
} // namespace chaiscript
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@ -7,7 +7,6 @@
|
|||||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
// 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
|
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||||
|
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_FUNCTION_CALL_HPP_
|
#ifndef CHAISCRIPT_FUNCTION_CALL_HPP_
|
||||||
#define CHAISCRIPT_FUNCTION_CALL_HPP_
|
#define CHAISCRIPT_FUNCTION_CALL_HPP_
|
||||||
|
|
||||||
@ -20,25 +19,22 @@
|
|||||||
#include "proxy_functions.hpp"
|
#include "proxy_functions.hpp"
|
||||||
|
|
||||||
namespace chaiscript {
|
namespace chaiscript {
|
||||||
class Boxed_Value;
|
class Boxed_Value;
|
||||||
class Type_Conversions_State;
|
class Type_Conversions_State;
|
||||||
namespace detail {
|
namespace detail {
|
||||||
template <typename T> struct Cast_Helper;
|
template<typename T>
|
||||||
} // namespace detail
|
struct Cast_Helper;
|
||||||
} // namespace chaiscript
|
} // namespace detail
|
||||||
|
} // namespace chaiscript
|
||||||
|
|
||||||
namespace chaiscript
|
namespace chaiscript {
|
||||||
{
|
namespace dispatch {
|
||||||
namespace dispatch
|
namespace detail {
|
||||||
{
|
template<typename Ret, typename... Param>
|
||||||
namespace detail
|
constexpr auto arity(Ret (*)(Param...)) noexcept {
|
||||||
{
|
|
||||||
template<typename Ret, typename ... Param>
|
|
||||||
constexpr auto arity(Ret (*)(Param...)) noexcept
|
|
||||||
{
|
|
||||||
return sizeof...(Param);
|
return sizeof...(Param);
|
||||||
}
|
}
|
||||||
}
|
} // namespace detail
|
||||||
|
|
||||||
/// Build a function caller that knows how to dispatch on a set of functions
|
/// Build a function caller that knows how to dispatch on a set of functions
|
||||||
/// example:
|
/// example:
|
||||||
@ -47,21 +43,19 @@ namespace chaiscript
|
|||||||
/// \returns A std::function object for dispatching
|
/// \returns A std::function object for dispatching
|
||||||
/// \param[in] funcs the set of functions to dispatch on.
|
/// \param[in] funcs the set of functions to dispatch on.
|
||||||
template<typename FunctionType>
|
template<typename FunctionType>
|
||||||
std::function<FunctionType> functor(const std::vector<Const_Proxy_Function> &funcs, const Type_Conversions_State *t_conversions)
|
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) {
|
||||||
const bool has_arity_match = std::any_of(funcs.begin(), funcs.end(),
|
return f->get_arity() == -1 || size_t(f->get_arity()) == detail::arity(static_cast<FunctionType *>(nullptr));
|
||||||
[](const Const_Proxy_Function &f) {
|
});
|
||||||
return f->get_arity() == -1 || size_t(f->get_arity()) == detail::arity(static_cast<FunctionType *>(nullptr));
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!has_arity_match) {
|
if (!has_arity_match) {
|
||||||
throw exception::bad_boxed_cast(user_type<Const_Proxy_Function>(), typeid(std::function<FunctionType>));
|
throw exception::bad_boxed_cast(user_type<Const_Proxy_Function>(), typeid(std::function<FunctionType>));
|
||||||
}
|
|
||||||
|
|
||||||
FunctionType *p=nullptr;
|
|
||||||
return detail::build_function_caller_helper(p, funcs, t_conversions);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FunctionType *p = nullptr;
|
||||||
|
return detail::build_function_caller_helper(p, funcs, t_conversions);
|
||||||
|
}
|
||||||
|
|
||||||
/// Build a function caller for a particular Proxy_Function object
|
/// Build a function caller for a particular Proxy_Function object
|
||||||
/// useful in the case that a function is being pass out from scripting back
|
/// useful in the case that a function is being pass out from scripting back
|
||||||
/// into code
|
/// into code
|
||||||
@ -74,67 +68,55 @@ namespace chaiscript
|
|||||||
/// \returns A std::function object for dispatching
|
/// \returns A std::function object for dispatching
|
||||||
/// \param[in] func A function to execute.
|
/// \param[in] func A function to execute.
|
||||||
template<typename FunctionType>
|
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);
|
||||||
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
|
/// Helper for automatically unboxing a Boxed_Value that contains a function object
|
||||||
/// and creating a typesafe C++ function caller from it.
|
/// and creating a typesafe C++ function caller from it.
|
||||||
template<typename FunctionType>
|
template<typename FunctionType>
|
||||||
std::function<FunctionType> functor(const Boxed_Value &bv, const Type_Conversions_State *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);
|
||||||
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 &
|
/// Cast helper to handle automatic casting to const std::function &
|
||||||
template<typename Signature>
|
template<typename Signature>
|
||||||
struct Cast_Helper<const std::function<Signature> &>
|
struct Cast_Helper<const std::function<Signature> &> {
|
||||||
{
|
static std::function<Signature> cast(const Boxed_Value &ob, const Type_Conversions_State *t_conversions) {
|
||||||
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);
|
||||||
if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>()))
|
} else {
|
||||||
{
|
return Cast_Helper_Inner<const std::function<Signature> &>::cast(ob, t_conversions);
|
||||||
return dispatch::functor<Signature>(ob, t_conversions);
|
|
||||||
} else {
|
|
||||||
return Cast_Helper_Inner<const std::function<Signature> &>::cast(ob, t_conversions);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/// Cast helper to handle automatic casting to std::function
|
/// Cast helper to handle automatic casting to std::function
|
||||||
template<typename Signature>
|
template<typename Signature>
|
||||||
struct Cast_Helper<std::function<Signature> >
|
struct Cast_Helper<std::function<Signature>> {
|
||||||
{
|
static std::function<Signature> cast(const Boxed_Value &ob, const Type_Conversions_State *t_conversions) {
|
||||||
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);
|
||||||
if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>()))
|
} else {
|
||||||
{
|
return Cast_Helper_Inner<std::function<Signature>>::cast(ob, t_conversions);
|
||||||
return dispatch::functor<Signature>(ob, t_conversions);
|
|
||||||
} else {
|
|
||||||
return Cast_Helper_Inner<std::function<Signature> >::cast(ob, t_conversions);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/// Cast helper to handle automatic casting to const std::function
|
/// Cast helper to handle automatic casting to const std::function
|
||||||
template<typename Signature>
|
template<typename Signature>
|
||||||
struct Cast_Helper<const std::function<Signature> >
|
struct Cast_Helper<const std::function<Signature>> {
|
||||||
{
|
static std::function<Signature> cast(const Boxed_Value &ob, const Type_Conversions_State *t_conversions) {
|
||||||
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);
|
||||||
if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>()))
|
} else {
|
||||||
{
|
return Cast_Helper_Inner<const std::function<Signature>>::cast(ob, t_conversions);
|
||||||
return dispatch::functor<Signature>(ob, t_conversions);
|
|
||||||
} else {
|
|
||||||
return Cast_Helper_Inner<const std::function<Signature> >::cast(ob, t_conversions);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
}
|
};
|
||||||
}
|
} // namespace detail
|
||||||
|
} // namespace chaiscript
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@ -7,7 +7,6 @@
|
|||||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
// 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
|
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||||
|
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_FUNCTION_CALL_DETAIL_HPP_
|
#ifndef CHAISCRIPT_FUNCTION_CALL_DETAIL_HPP_
|
||||||
#define CHAISCRIPT_FUNCTION_CALL_DETAIL_HPP_
|
#define CHAISCRIPT_FUNCTION_CALL_DETAIL_HPP_
|
||||||
|
|
||||||
@ -20,96 +19,79 @@
|
|||||||
#include "boxed_cast.hpp"
|
#include "boxed_cast.hpp"
|
||||||
#include "boxed_number.hpp"
|
#include "boxed_number.hpp"
|
||||||
#include "boxed_value.hpp"
|
#include "boxed_value.hpp"
|
||||||
#include "type_conversions.hpp"
|
|
||||||
#include "proxy_functions.hpp"
|
#include "proxy_functions.hpp"
|
||||||
|
#include "type_conversions.hpp"
|
||||||
|
|
||||||
namespace chaiscript
|
namespace chaiscript::dispatch::detail {
|
||||||
{
|
/// used internally for unwrapping a function call's types
|
||||||
namespace dispatch
|
template<typename Ret, typename... Param>
|
||||||
{
|
struct Build_Function_Caller_Helper {
|
||||||
namespace detail
|
Build_Function_Caller_Helper(std::vector<Const_Proxy_Function> t_funcs, const Type_Conversions *t_conversions)
|
||||||
{
|
: m_funcs(std::move(t_funcs))
|
||||||
/// used internally for unwrapping a function call's types
|
, m_conversions(t_conversions) {
|
||||||
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)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
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>) {
|
|
||||||
dispatch::dispatch(m_funcs, params, t_state);
|
|
||||||
} else {
|
|
||||||
return boxed_cast<Ret>(dispatch::dispatch(m_funcs, params, t_state), &t_state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename ... P>
|
|
||||||
Ret operator()(P&& ... param)
|
|
||||||
{
|
|
||||||
std::array<Boxed_Value, sizeof...(P)> params{box<P>(std::forward<P>(param))...};
|
|
||||||
|
|
||||||
if (m_conversions) {
|
|
||||||
Type_Conversions_State state(*m_conversions, m_conversions->conversion_saves());
|
|
||||||
return call(chaiscript::Function_Params{params}, state);
|
|
||||||
} else {
|
|
||||||
Type_Conversions conv;
|
|
||||||
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>>) {
|
|
||||||
return std::forward<Q>(q);
|
|
||||||
} else if constexpr (std::is_reference_v<P>) {
|
|
||||||
return Boxed_Value(std::ref(std::forward<Q>(q)));
|
|
||||||
} else {
|
|
||||||
return Boxed_Value(std::forward<Q>(q));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
if (funcs.size() == 1)
|
|
||||||
{
|
|
||||||
std::shared_ptr<const Proxy_Function_Impl<Ret (Params...)>> pfi =
|
|
||||||
std::dynamic_pointer_cast<const Proxy_Function_Impl<Ret (Params...)> >
|
|
||||||
(funcs[0]);
|
|
||||||
|
|
||||||
if (pfi)
|
|
||||||
{
|
|
||||||
return pfi->internal_function();
|
|
||||||
}
|
|
||||||
// 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));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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>) {
|
||||||
|
dispatch::dispatch(m_funcs, params, t_state);
|
||||||
|
} else {
|
||||||
|
return boxed_cast<Ret>(dispatch::dispatch(m_funcs, params, t_state), &t_state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename... P>
|
||||||
|
Ret operator()(P &&...param) {
|
||||||
|
std::array<Boxed_Value, sizeof...(P)> params{box<P>(std::forward<P>(param))...};
|
||||||
|
|
||||||
|
if (m_conversions) {
|
||||||
|
Type_Conversions_State state(*m_conversions, m_conversions->conversion_saves());
|
||||||
|
return call(chaiscript::Function_Params{params}, state);
|
||||||
|
} else {
|
||||||
|
Type_Conversions conv;
|
||||||
|
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>>) {
|
||||||
|
return std::forward<Q>(q);
|
||||||
|
} else if constexpr (std::is_reference_v<P>) {
|
||||||
|
return Boxed_Value(std::ref(std::forward<Q>(q)));
|
||||||
|
} else {
|
||||||
|
return Boxed_Value(std::forward<Q>(q));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
/*
|
||||||
|
if (funcs.size() == 1)
|
||||||
|
{
|
||||||
|
std::shared_ptr<const Proxy_Function_Impl<Ret (Params...)>> pfi =
|
||||||
|
std::dynamic_pointer_cast<const Proxy_Function_Impl<Ret (Params...)> >
|
||||||
|
(funcs[0]);
|
||||||
|
|
||||||
|
if (pfi)
|
||||||
|
{
|
||||||
|
return pfi->internal_function();
|
||||||
|
}
|
||||||
|
// 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));
|
||||||
}
|
}
|
||||||
}
|
} // namespace chaiscript::dispatch::detail
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@ -7,79 +7,61 @@
|
|||||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
// 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
|
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||||
|
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_FUNCTION_PARAMS_HPP
|
#ifndef CHAISCRIPT_FUNCTION_PARAMS_HPP
|
||||||
#define CHAISCRIPT_FUNCTION_PARAMS_HPP
|
#define CHAISCRIPT_FUNCTION_PARAMS_HPP
|
||||||
|
|
||||||
|
|
||||||
#include "boxed_value.hpp"
|
#include "boxed_value.hpp"
|
||||||
|
|
||||||
namespace chaiscript {
|
namespace chaiscript {
|
||||||
|
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) {
|
||||||
|
}
|
||||||
|
|
||||||
class Function_Params
|
explicit Function_Params(const Boxed_Value &bv)
|
||||||
{
|
: m_begin(&bv)
|
||||||
public:
|
, m_end(m_begin + 1) {
|
||||||
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)
|
explicit Function_Params(const std::vector<Boxed_Value> &vec)
|
||||||
: m_begin(&bv), m_end(m_begin + 1)
|
: m_begin(vec.empty() ? nullptr : &vec.front())
|
||||||
{
|
, m_end(vec.empty() ? nullptr : &vec.front() + vec.size()) {
|
||||||
}
|
}
|
||||||
|
|
||||||
explicit Function_Params(const std::vector<Boxed_Value> &vec)
|
template<size_t Size>
|
||||||
: m_begin(vec.empty() ? nullptr : &vec.front()), m_end(vec.empty() ? nullptr : &vec.front() + vec.size())
|
constexpr explicit Function_Params(const std::array<Boxed_Value, Size> &a)
|
||||||
{
|
: m_begin(&a.front())
|
||||||
}
|
, m_end(&a.front() + Size) {
|
||||||
|
}
|
||||||
|
|
||||||
template<size_t Size>
|
[[nodiscard]] constexpr const Boxed_Value &operator[](const std::size_t t_i) const noexcept { return m_begin[t_i]; }
|
||||||
constexpr explicit Function_Params(const std::array<Boxed_Value, Size> &a)
|
|
||||||
: m_begin(&a.front()), m_end(&a.front() + Size)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] constexpr const Boxed_Value &operator[](const std::size_t t_i) const noexcept {
|
[[nodiscard]] constexpr const Boxed_Value *begin() const noexcept { return m_begin; }
|
||||||
return m_begin[t_i];
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] constexpr const Boxed_Value *begin() const noexcept {
|
[[nodiscard]] constexpr const Boxed_Value &front() const noexcept { return *m_begin; }
|
||||||
return m_begin;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] constexpr const Boxed_Value &front() const noexcept {
|
[[nodiscard]] constexpr const Boxed_Value *end() const noexcept { return m_end; }
|
||||||
return *m_begin;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] constexpr const Boxed_Value *end() const noexcept {
|
[[nodiscard]] constexpr std::size_t size() const noexcept { return std::size_t(m_end - m_begin); }
|
||||||
return m_end;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] constexpr std::size_t size() const noexcept {
|
[[nodiscard]] std::vector<Boxed_Value> to_vector() const { return std::vector<Boxed_Value>{m_begin, m_end}; }
|
||||||
return std::size_t(m_end - m_begin);
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] std::vector<Boxed_Value> to_vector() const {
|
[[nodiscard]] constexpr bool empty() const noexcept { return m_begin == m_end; }
|
||||||
return std::vector<Boxed_Value>{m_begin, m_end};
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] constexpr bool empty() const noexcept {
|
private:
|
||||||
return m_begin == m_end;
|
const Boxed_Value *m_begin = nullptr;
|
||||||
}
|
const Boxed_Value *m_end = nullptr;
|
||||||
|
|
||||||
private:
|
|
||||||
const Boxed_Value *m_begin = nullptr;
|
|
||||||
const Boxed_Value *m_end = nullptr;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Constructor specialization for array of size 0
|
// Constructor specialization for array of size 0
|
||||||
template<>
|
template<>
|
||||||
constexpr Function_Params::Function_Params(const std::array<Boxed_Value, size_t{0}> & /* a */)
|
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
|
#endif
|
||||||
|
|||||||
@ -4,142 +4,146 @@
|
|||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
namespace chaiscript::dispatch::detail {
|
namespace chaiscript::dispatch::detail {
|
||||||
|
template<typename... Param>
|
||||||
|
struct Function_Params {
|
||||||
|
};
|
||||||
|
|
||||||
template<typename... Param>
|
template<typename Ret, typename Params, bool IsNoExcept = false, bool IsMember = false, bool IsMemberObject = false, bool IsObject = false>
|
||||||
struct Function_Params
|
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() noexcept = default;
|
||||||
|
};
|
||||||
|
|
||||||
template<typename Ret, typename Params, bool IsNoExcept = false, bool IsMember = false, bool IsMemberObject = false, bool IsObject = false>
|
// Free functions
|
||||||
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() noexcept = default;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Free functions
|
template<typename Ret, typename... Param>
|
||||||
|
Function_Signature(Ret (*f)(Param...)) -> Function_Signature<Ret, Function_Params<Param...>>;
|
||||||
|
|
||||||
template<typename Ret, typename... Param>
|
template<typename Ret, typename... Param>
|
||||||
Function_Signature(Ret (*f)(Param...))->Function_Signature<Ret, Function_Params<Param...>>;
|
Function_Signature(Ret (*f)(Param...) noexcept) -> Function_Signature<Ret, Function_Params<Param...>, true>;
|
||||||
|
|
||||||
template<typename Ret, typename... Param>
|
// no reference specifier
|
||||||
Function_Signature(Ret (*f)(Param...) noexcept)->Function_Signature<Ret, Function_Params<Param...>, true>;
|
|
||||||
|
|
||||||
// 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>
|
template<typename Ret, typename Class, typename... Param>
|
||||||
Function_Signature(Ret (Class::*f)(Param...) volatile)->Function_Signature<Ret, Function_Params<volatile Class &, Param...>, false, true>;
|
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>
|
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>;
|
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>
|
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>;
|
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>
|
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>;
|
Function_Signature(Ret (Class::*f)(Param...)) -> Function_Signature<Ret, Function_Params<Class &, Param...>, false, true>;
|
||||||
|
|
||||||
template<typename Ret, typename Class, typename... Param>
|
template<typename Ret, typename Class, typename... Param>
|
||||||
Function_Signature(Ret (Class::*f)(Param...))->Function_Signature<Ret, Function_Params<Class &, Param...>, false, true>;
|
Function_Signature(Ret (Class::*f)(Param...) noexcept) -> Function_Signature<Ret, Function_Params<Class &, Param...>, true, true>;
|
||||||
|
|
||||||
template<typename Ret, typename Class, typename... Param>
|
template<typename Ret, typename Class, typename... Param>
|
||||||
Function_Signature(Ret (Class::*f)(Param...) noexcept)->Function_Signature<Ret, Function_Params<Class &, Param...>, true, true>;
|
Function_Signature(Ret (Class::*f)(Param...) const) -> Function_Signature<Ret, Function_Params<const Class &, Param...>, false, true>;
|
||||||
|
|
||||||
template<typename Ret, typename Class, typename... Param>
|
template<typename Ret, typename Class, typename... Param>
|
||||||
Function_Signature(Ret (Class::*f)(Param...) const)->Function_Signature<Ret, Function_Params<const Class &, Param...>, false, true>;
|
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>
|
// & reference specifier
|
||||||
Function_Signature(Ret (Class::*f)(Param...) const noexcept)->Function_Signature<Ret, Function_Params<const Class &, Param...>, true, true>;
|
|
||||||
|
|
||||||
// & 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>
|
template<typename Ret, typename Class, typename... Param>
|
||||||
Function_Signature(Ret (Class::*f)(Param...) volatile &)->Function_Signature<Ret, Function_Params<volatile Class &, Param...>, false, true>;
|
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>
|
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>;
|
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>
|
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>;
|
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>
|
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>;
|
Function_Signature(Ret (Class::*f)(Param...) &) -> Function_Signature<Ret, Function_Params<Class &, Param...>, false, true>;
|
||||||
|
|
||||||
template<typename Ret, typename Class, typename... Param>
|
template<typename Ret, typename Class, typename... Param>
|
||||||
Function_Signature(Ret (Class::*f)(Param...) &)->Function_Signature<Ret, Function_Params<Class &, Param...>, false, true>;
|
Function_Signature(Ret (Class::*f)(Param...) &noexcept) -> Function_Signature<Ret, Function_Params<Class &, Param...>, true, true>;
|
||||||
|
|
||||||
template<typename Ret, typename Class, typename... Param>
|
template<typename Ret, typename Class, typename... Param>
|
||||||
Function_Signature(Ret (Class::*f)(Param...) & noexcept)->Function_Signature<Ret, Function_Params<Class &, Param...>, true, true>;
|
Function_Signature(Ret (Class::*f)(Param...) const &) -> Function_Signature<Ret, Function_Params<const Class &, Param...>, false, true>;
|
||||||
|
|
||||||
template<typename Ret, typename Class, typename... Param>
|
template<typename Ret, typename Class, typename... Param>
|
||||||
Function_Signature(Ret (Class::*f)(Param...) const &)->Function_Signature<Ret, Function_Params<const Class &, Param...>, false, true>;
|
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>
|
// && reference specifier
|
||||||
Function_Signature(Ret (Class::*f)(Param...) const &noexcept)->Function_Signature<Ret, Function_Params<const Class &, Param...>, true, true>;
|
|
||||||
|
|
||||||
// && 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>
|
template<typename Ret, typename Class, typename... Param>
|
||||||
Function_Signature(Ret (Class::*f)(Param...) volatile &&)->Function_Signature<Ret, Function_Params<volatile Class &&, Param...>, false, true>;
|
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>
|
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>;
|
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>
|
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>;
|
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>
|
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>;
|
Function_Signature(Ret (Class::*f)(Param...) &&) -> Function_Signature<Ret, Function_Params<Class &&, Param...>, false, true>;
|
||||||
|
|
||||||
template<typename Ret, typename Class, typename... Param>
|
template<typename Ret, typename Class, typename... Param>
|
||||||
Function_Signature(Ret (Class::*f)(Param...) &&)->Function_Signature<Ret, Function_Params<Class &&, Param...>, false, true>;
|
Function_Signature(Ret (Class::*f)(Param...) &&noexcept) -> Function_Signature<Ret, Function_Params<Class &&, Param...>, true, true>;
|
||||||
|
|
||||||
template<typename Ret, typename Class, typename... Param>
|
template<typename Ret, typename Class, typename... Param>
|
||||||
Function_Signature(Ret (Class::*f)(Param...) && noexcept)->Function_Signature<Ret, Function_Params<Class &&, Param...>, true, true>;
|
Function_Signature(Ret (Class::*f)(Param...) const &&) -> Function_Signature<Ret, Function_Params<const Class &&, Param...>, false, true>;
|
||||||
|
|
||||||
template<typename Ret, typename Class, typename... Param>
|
template<typename Ret, typename Class, typename... Param>
|
||||||
Function_Signature(Ret (Class::*f)(Param...) const &&)->Function_Signature<Ret, Function_Params<const Class &&, Param...>, false, true>;
|
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>
|
template<typename Ret, typename Class>
|
||||||
Function_Signature(Ret (Class::*f)(Param...) const &&noexcept)->Function_Signature<Ret, Function_Params<const Class &&, Param...>, true, true>;
|
Function_Signature(Ret Class::*f) -> Function_Signature<Ret, Function_Params<Class &>, true, true, true>;
|
||||||
|
|
||||||
template<typename Ret, typename Class>
|
// primary template handles types that have no nested ::type member:
|
||||||
Function_Signature(Ret Class::*f)->Function_Signature<Ret, Function_Params<Class &>, true, true, true>;
|
template<class, class = std::void_t<>>
|
||||||
|
struct has_call_operator : std::false_type {
|
||||||
|
};
|
||||||
|
|
||||||
// primary template handles types that have no nested ::type member:
|
// specialization recognizes types that do have a nested ::type member:
|
||||||
template<class, class = std::void_t<>>
|
template<class T>
|
||||||
struct has_call_operator : std::false_type
|
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<typename Func>
|
||||||
template<class T>
|
auto function_signature(const Func &f) {
|
||||||
struct has_call_operator<T, std::void_t<decltype(&T::operator())>> : std::true_type
|
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,
|
||||||
template<typename Func>
|
false,
|
||||||
auto function_signature(const Func &f)
|
false,
|
||||||
{
|
true>{};
|
||||||
if constexpr (has_call_operator<Func>::value) {
|
} else {
|
||||||
return Function_Signature<
|
return Function_Signature{f};
|
||||||
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 };
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
}// namespace chaiscript::dispatch::detail
|
} // namespace chaiscript::dispatch::detail
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -7,7 +7,6 @@
|
|||||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
// 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
|
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||||
|
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_HANDLE_RETURN_HPP_
|
#ifndef CHAISCRIPT_HANDLE_RETURN_HPP_
|
||||||
#define CHAISCRIPT_HANDLE_RETURN_HPP_
|
#define CHAISCRIPT_HANDLE_RETURN_HPP_
|
||||||
|
|
||||||
@ -19,254 +18,178 @@
|
|||||||
#include "boxed_value.hpp"
|
#include "boxed_value.hpp"
|
||||||
|
|
||||||
namespace chaiscript {
|
namespace chaiscript {
|
||||||
class Boxed_Number;
|
class Boxed_Number;
|
||||||
} // namespace chaiscript
|
} // namespace chaiscript
|
||||||
|
|
||||||
namespace chaiscript
|
namespace chaiscript {
|
||||||
{
|
namespace dispatch {
|
||||||
namespace dispatch
|
template<class T, class U>
|
||||||
{
|
class Proxy_Function_Callable_Impl;
|
||||||
template<class T, class U> class Proxy_Function_Callable_Impl;
|
template<class T>
|
||||||
template<class T> class Assignable_Proxy_Function_Impl;
|
class Assignable_Proxy_Function_Impl;
|
||||||
|
|
||||||
namespace detail
|
namespace detail {
|
||||||
{
|
|
||||||
/// Used internally for handling a return value from a Proxy_Function call
|
/// Used internally for handling a return value from a Proxy_Function call
|
||||||
template<typename Ret>
|
template<typename Ret>
|
||||||
struct Handle_Return
|
struct Handle_Return {
|
||||||
{
|
template<typename T, typename = typename std::enable_if_t<std::is_trivial_v<typename std::decay_t<T>>>>
|
||||||
template<typename T,
|
static Boxed_Value handle(T r) {
|
||||||
typename = typename std::enable_if_t<std::is_trivial_v<typename std::decay_t<T>>>>
|
return Boxed_Value(std::move(r), true);
|
||||||
static Boxed_Value handle(T r)
|
}
|
||||||
{
|
|
||||||
return Boxed_Value(std::move(r), true);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T,
|
template<typename T, typename = typename std::enable_if_t<!(std::is_trivial_v<typename std::decay_t<T>>)>>
|
||||||
typename = typename std::enable_if_t<!(std::is_trivial_v<typename std::decay_t<T>>)>>
|
static Boxed_Value handle(T &&r) {
|
||||||
static Boxed_Value handle(T &&r)
|
return Boxed_Value(std::make_shared<T>(std::forward<T>(r)), true);
|
||||||
{
|
}
|
||||||
return Boxed_Value(std::make_shared<T>(std::forward<T>(r)), true);
|
};
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename Ret>
|
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) {
|
||||||
static Boxed_Value handle(const std::function<Ret> &f) {
|
return Boxed_Value(
|
||||||
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>
|
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>
|
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) {
|
||||||
static Boxed_Value handle(const std::shared_ptr<std::function<Ret>> &f) {
|
return Boxed_Value(
|
||||||
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>
|
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>
|
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>
|
template<typename Ret>
|
||||||
struct Handle_Return<std::function<Ret> &>
|
struct Handle_Return<std::function<Ret> &> {
|
||||||
{
|
static Boxed_Value handle(std::function<Ret> &f) {
|
||||||
static Boxed_Value handle(std::function<Ret> &f) {
|
return Boxed_Value(chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Assignable_Proxy_Function_Impl<Ret>>(
|
||||||
return Boxed_Value(
|
std::ref(f), std::shared_ptr<std::function<Ret>>()));
|
||||||
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) {
|
static Boxed_Value handle(const std::function<Ret> &f) {
|
||||||
return Boxed_Value(
|
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>
|
template<typename Ret>
|
||||||
struct Handle_Return<Ret *&>
|
struct Handle_Return<Ret *&> {
|
||||||
{
|
static Boxed_Value handle(Ret *p) { return Boxed_Value(p, true); }
|
||||||
static Boxed_Value handle(Ret *p)
|
};
|
||||||
{
|
|
||||||
return Boxed_Value(p, true);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename Ret>
|
template<typename Ret>
|
||||||
struct Handle_Return<const Ret *&>
|
struct Handle_Return<const Ret *&> {
|
||||||
{
|
static Boxed_Value handle(const Ret *p) { return Boxed_Value(p, true); }
|
||||||
static Boxed_Value handle(const Ret *p)
|
};
|
||||||
{
|
|
||||||
return Boxed_Value(p, true);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename Ret>
|
template<typename Ret>
|
||||||
struct Handle_Return<Ret *>
|
struct Handle_Return<Ret *> {
|
||||||
{
|
static Boxed_Value handle(Ret *p) { return Boxed_Value(p, true); }
|
||||||
static Boxed_Value handle(Ret *p)
|
};
|
||||||
{
|
|
||||||
return Boxed_Value(p, true);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename Ret>
|
template<typename Ret>
|
||||||
struct Handle_Return<const Ret *>
|
struct Handle_Return<const Ret *> {
|
||||||
{
|
static Boxed_Value handle(const Ret *p) { return Boxed_Value(p, true); }
|
||||||
static Boxed_Value handle(const Ret *p)
|
};
|
||||||
{
|
|
||||||
return Boxed_Value(p, true);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename Ret>
|
template<typename Ret>
|
||||||
struct Handle_Return<std::shared_ptr<Ret> &>
|
struct Handle_Return<std::shared_ptr<Ret> &> {
|
||||||
{
|
static Boxed_Value handle(const std::shared_ptr<Ret> &r) { return Boxed_Value(r, true); }
|
||||||
static Boxed_Value handle(const std::shared_ptr<Ret> &r)
|
};
|
||||||
{
|
|
||||||
return Boxed_Value(r, true);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename Ret>
|
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>
|
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>
|
template<typename Ret>
|
||||||
struct Handle_Return<std::unique_ptr<Ret>> : Handle_Return<std::unique_ptr<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); }
|
||||||
static Boxed_Value handle(std::unique_ptr<Ret> &&r)
|
};
|
||||||
{
|
|
||||||
return Boxed_Value(std::move(r), true);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename Ret, bool Ptr>
|
template<typename Ret, bool Ptr>
|
||||||
struct Handle_Return_Ref
|
struct Handle_Return_Ref {
|
||||||
{
|
template<typename T>
|
||||||
template<typename T>
|
static Boxed_Value handle(T &&r) {
|
||||||
static Boxed_Value handle(T &&r)
|
return Boxed_Value(std::cref(r), true);
|
||||||
{
|
}
|
||||||
return Boxed_Value(std::cref(r), true);
|
};
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename Ret>
|
template<typename Ret>
|
||||||
struct Handle_Return_Ref<Ret, true>
|
struct Handle_Return_Ref<Ret, true> {
|
||||||
{
|
template<typename T>
|
||||||
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);
|
||||||
{
|
}
|
||||||
return Boxed_Value(typename std::remove_reference<decltype(r)>::type{r}, true);
|
};
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename Ret>
|
template<typename Ret>
|
||||||
struct Handle_Return<const Ret &> : Handle_Return_Ref<const Ret &, std::is_pointer<typename std::remove_reference<const Ret &>::type>::value>
|
struct Handle_Return<const Ret &> : Handle_Return_Ref<const Ret &, std::is_pointer<typename std::remove_reference<const Ret &>::type>::value> {
|
||||||
{
|
};
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
template<typename Ret>
|
template<typename Ret>
|
||||||
struct Handle_Return<const Ret>
|
struct Handle_Return<const Ret> {
|
||||||
{
|
static Boxed_Value handle(Ret r) { return Boxed_Value(std::move(r)); }
|
||||||
static Boxed_Value handle(Ret r)
|
};
|
||||||
{
|
|
||||||
return Boxed_Value(std::move(r));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename Ret>
|
template<typename Ret>
|
||||||
struct Handle_Return<Ret &>
|
struct Handle_Return<Ret &> {
|
||||||
{
|
static Boxed_Value handle(Ret &r) { return Boxed_Value(std::ref(r)); }
|
||||||
static Boxed_Value handle(Ret &r)
|
};
|
||||||
{
|
|
||||||
return Boxed_Value(std::ref(r));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct Handle_Return<Boxed_Value>
|
struct Handle_Return<Boxed_Value> {
|
||||||
{
|
static Boxed_Value handle(const Boxed_Value &r) noexcept { return r; }
|
||||||
static Boxed_Value handle(const Boxed_Value &r) noexcept
|
};
|
||||||
{
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct Handle_Return<const Boxed_Value> : Handle_Return<Boxed_Value>
|
struct Handle_Return<const Boxed_Value> : Handle_Return<Boxed_Value> {
|
||||||
{
|
};
|
||||||
};
|
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct Handle_Return<Boxed_Value &> : Handle_Return<Boxed_Value>
|
struct Handle_Return<Boxed_Value &> : Handle_Return<Boxed_Value> {
|
||||||
{
|
};
|
||||||
};
|
|
||||||
|
|
||||||
template<>
|
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
|
* Used internally for handling a return value from a Proxy_Function call
|
||||||
*/
|
*/
|
||||||
template<>
|
template<>
|
||||||
struct Handle_Return<Boxed_Number>
|
struct Handle_Return<Boxed_Number> {
|
||||||
{
|
static Boxed_Value handle(const Boxed_Number &r) noexcept { return r.bv; }
|
||||||
static Boxed_Value handle(const Boxed_Number &r) noexcept
|
};
|
||||||
{
|
|
||||||
return r.bv;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<>
|
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
|
* Used internally for handling a return value from a Proxy_Function call
|
||||||
*/
|
*/
|
||||||
template<>
|
template<>
|
||||||
struct Handle_Return<void>
|
struct Handle_Return<void> {
|
||||||
{
|
static Boxed_Value handle() { return void_var(); }
|
||||||
static Boxed_Value handle()
|
};
|
||||||
{
|
} // namespace detail
|
||||||
return void_var();
|
} // namespace dispatch
|
||||||
}
|
} // namespace chaiscript
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -7,218 +7,178 @@
|
|||||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
// 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
|
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||||
|
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_OPERATORS_HPP_
|
#ifndef CHAISCRIPT_OPERATORS_HPP_
|
||||||
#define CHAISCRIPT_OPERATORS_HPP_
|
#define CHAISCRIPT_OPERATORS_HPP_
|
||||||
|
|
||||||
#include "../chaiscript_defines.hpp"
|
#include "../chaiscript_defines.hpp"
|
||||||
|
#include "../dispatchkit/dispatchkit.hpp"
|
||||||
#include "register_function.hpp"
|
#include "register_function.hpp"
|
||||||
|
|
||||||
namespace chaiscript
|
namespace chaiscript::bootstrap::operators {
|
||||||
{
|
template<typename T>
|
||||||
namespace bootstrap
|
void assign(Module &m) {
|
||||||
{
|
m.add(chaiscript::fun([](T &lhs, const T &rhs) -> T & { return lhs = rhs; }), "=");
|
||||||
namespace operators
|
|
||||||
{
|
|
||||||
template<typename T>
|
|
||||||
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;}), "&=");
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
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;}), "|=");
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
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;}), "<<=");
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
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;}), "/=");
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
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;}), ">>=");
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
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;}), "--");
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
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;}), "==");
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
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;}), ">=");
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
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;}), "<=");
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
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;}), "!=");
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
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;}), "+");
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
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;}), "-");
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
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;}), "~");
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
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;}), "|");
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
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;}), "<<");
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
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;}), "%");
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
void right_shift(Module& m)
|
|
||||||
{
|
|
||||||
m.add(chaiscript::fun([](const T &lhs, const T &rhs){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; }), "&=");
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
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; }), "|=");
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
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; }), "<<=");
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
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; }), "/=");
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
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; }), ">>=");
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
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; }), "--");
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
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; }), "==");
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
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; }), ">=");
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
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; }), "<=");
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
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; }), "!=");
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
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; }), "+");
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
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; }), "-");
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
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; }), "~");
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
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; }), "|");
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
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; }), "<<");
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
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; }), "%");
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void right_shift(Module &m) {
|
||||||
|
m.add(chaiscript::fun([](const T &lhs, const T &rhs) { return lhs >> rhs; }), ">>");
|
||||||
|
}
|
||||||
|
} // namespace chaiscript::bootstrap::operators
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -7,45 +7,35 @@
|
|||||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
// 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
|
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||||
|
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_PROXY_CONSTRUCTORS_HPP_
|
#ifndef CHAISCRIPT_PROXY_CONSTRUCTORS_HPP_
|
||||||
#define CHAISCRIPT_PROXY_CONSTRUCTORS_HPP_
|
#define CHAISCRIPT_PROXY_CONSTRUCTORS_HPP_
|
||||||
|
|
||||||
#include "proxy_functions.hpp"
|
#include "proxy_functions.hpp"
|
||||||
|
|
||||||
namespace chaiscript
|
namespace chaiscript::dispatch::detail {
|
||||||
{
|
template<typename Class, typename... Params>
|
||||||
namespace dispatch
|
Proxy_Function build_constructor_(Class (*)(Params...)) {
|
||||||
{
|
if constexpr (!std::is_copy_constructible_v<Class>) {
|
||||||
namespace detail
|
auto call = [](auto &&...param) { return std::make_shared<Class>(std::forward<decltype(param)>(param)...); };
|
||||||
{
|
|
||||||
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)...);
|
|
||||||
};
|
|
||||||
|
|
||||||
return Proxy_Function(
|
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,
|
||||||
} else if constexpr (true) {
|
dispatch::Proxy_Function_Callable_Impl<std::shared_ptr<Class>(Params...), decltype(call)>>(call));
|
||||||
auto call = [](auto && ... param){
|
} else if constexpr (true) {
|
||||||
return Class(std::forward<decltype(param)>(param)...);
|
auto call = [](auto &&...param) { return Class(std::forward<decltype(param)>(param)...); };
|
||||||
};
|
|
||||||
|
|
||||||
return Proxy_Function(
|
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
|
/// \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, ...)
|
/// \tparam T The signature of the constructor to generate. In the form of: ClassType (ParamType1, ParamType2, ...)
|
||||||
///
|
///
|
||||||
/// Example:
|
/// Example:
|
||||||
/// \code
|
/// \code
|
||||||
/// chaiscript::ChaiScript chai;
|
/// chaiscript::ChaiScript chai;
|
||||||
@ -54,13 +44,10 @@ namespace chaiscript
|
|||||||
/// chai.add(constructor<MyClass (int, float)>(), "MyClass");
|
/// chai.add(constructor<MyClass (int, float)>(), "MyClass");
|
||||||
/// \endcode
|
/// \endcode
|
||||||
template<typename T>
|
template<typename T>
|
||||||
Proxy_Function constructor()
|
Proxy_Function constructor() {
|
||||||
{
|
T *f = nullptr;
|
||||||
T *f = nullptr;
|
return (dispatch::detail::build_constructor_(f));
|
||||||
return (dispatch::detail::build_constructor_(f));
|
}
|
||||||
}
|
} // namespace chaiscript
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#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.
|
// 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
|
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||||
|
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_PROXY_FUNCTIONS_DETAIL_HPP_
|
#ifndef CHAISCRIPT_PROXY_FUNCTIONS_DETAIL_HPP_
|
||||||
#define CHAISCRIPT_PROXY_FUNCTIONS_DETAIL_HPP_
|
#define CHAISCRIPT_PROXY_FUNCTIONS_DETAIL_HPP_
|
||||||
|
|
||||||
|
#include <array>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <array>
|
|
||||||
|
|
||||||
#include "../chaiscript_defines.hpp"
|
#include "../chaiscript_defines.hpp"
|
||||||
#include "boxed_cast.hpp"
|
#include "boxed_cast.hpp"
|
||||||
#include "boxed_value.hpp"
|
#include "boxed_value.hpp"
|
||||||
|
#include "function_params.hpp"
|
||||||
#include "handle_return.hpp"
|
#include "handle_return.hpp"
|
||||||
#include "type_info.hpp"
|
#include "type_info.hpp"
|
||||||
#include "function_params.hpp"
|
|
||||||
|
|
||||||
namespace chaiscript {
|
namespace chaiscript {
|
||||||
class Type_Conversions_State;
|
class Type_Conversions_State;
|
||||||
namespace exception {
|
namespace exception {
|
||||||
class bad_boxed_cast;
|
class bad_boxed_cast;
|
||||||
} // namespace exception
|
} // namespace exception
|
||||||
} // namespace chaiscript
|
} // namespace chaiscript
|
||||||
|
|
||||||
namespace chaiscript
|
namespace chaiscript {
|
||||||
{
|
namespace exception {
|
||||||
namespace exception
|
|
||||||
{
|
|
||||||
/**
|
/**
|
||||||
* Exception thrown when there is a mismatch in number of
|
* Exception thrown when there is a mismatch in number of
|
||||||
* parameters during Proxy_Function execution
|
* 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)
|
arity_error(int t_got, int t_expected)
|
||||||
: std::range_error("Function dispatch arity mismatch"),
|
: std::range_error("Function dispatch arity mismatch")
|
||||||
got(t_got), expected(t_expected)
|
, got(t_got)
|
||||||
{
|
, expected(t_expected) {
|
||||||
}
|
}
|
||||||
|
|
||||||
arity_error(const arity_error &) = default;
|
arity_error(const arity_error &) = default;
|
||||||
@ -53,73 +49,63 @@ namespace chaiscript
|
|||||||
int got;
|
int got;
|
||||||
int expected;
|
int expected;
|
||||||
};
|
};
|
||||||
}
|
} // namespace exception
|
||||||
|
|
||||||
namespace dispatch
|
namespace dispatch {
|
||||||
{
|
namespace detail {
|
||||||
namespace detail
|
|
||||||
{
|
|
||||||
/**
|
/**
|
||||||
* Used by Proxy_Function_Impl to return a list of all param types
|
* Used by Proxy_Function_Impl to return a list of all param types
|
||||||
* it contains.
|
* it contains.
|
||||||
*/
|
*/
|
||||||
template<typename Ret, typename ... Params>
|
template<typename Ret, typename... Params>
|
||||||
std::vector<Type_Info> build_param_type_list(Ret (*)(Params...))
|
std::vector<Type_Info> build_param_type_list(Ret (*)(Params...)) {
|
||||||
{
|
/// \note somehow this is responsible for a large part of the code generation
|
||||||
/// \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
|
* Used by Proxy_Function_Impl to determine if it is equivalent to another
|
||||||
* Proxy_Function_Impl object. This function is primarily used to prevent
|
* Proxy_Function_Impl object. This function is primarily used to prevent
|
||||||
* registration of two functions with the exact same signatures
|
* registration of two functions with the exact same signatures
|
||||||
*/
|
*/
|
||||||
template<typename Ret, typename ... Params>
|
template<typename Ret, typename... Params>
|
||||||
bool compare_types_cast(Ret (*)(Params...),
|
bool compare_types_cast(Ret (*)(Params...), const chaiscript::Function_Params ¶ms, const Type_Conversions_State &t_conversions) noexcept {
|
||||||
const chaiscript::Function_Params ¶ms, const Type_Conversions_State &t_conversions) noexcept
|
try {
|
||||||
{
|
std::vector<Boxed_Value>::size_type i = 0;
|
||||||
try {
|
(boxed_cast<Params>(params[i++], &t_conversions), ...);
|
||||||
std::vector<Boxed_Value>::size_type i = 0;
|
return true;
|
||||||
( boxed_cast<Params>(params[i++], &t_conversions), ... );
|
} catch (const exception::bad_boxed_cast &) {
|
||||||
return true;
|
return false;
|
||||||
} catch (const exception::bad_boxed_cast &) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<typename Callable, typename Ret, typename ... Params, size_t ... I>
|
|
||||||
Ret call_func(Ret (*)(Params...),
|
|
||||||
std::index_sequence<I...>, const Callable &f,
|
|
||||||
[[maybe_unused]] const chaiscript::Function_Params ¶ms,
|
|
||||||
[[maybe_unused]] const Type_Conversions_State &t_conversions)
|
|
||||||
{
|
|
||||||
return f(boxed_cast<Params>(params[I], &t_conversions)...);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Callable, typename Ret, typename... Params, size_t... I>
|
||||||
|
Ret call_func(Ret (*)(Params...),
|
||||||
|
std::index_sequence<I...>,
|
||||||
|
const Callable &f,
|
||||||
|
[[maybe_unused]] const chaiscript::Function_Params ¶ms,
|
||||||
|
[[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.
|
/// Used by Proxy_Function_Impl to perform typesafe execution of a function.
|
||||||
/// The function attempts to unbox each parameter to the expected type.
|
/// The function attempts to unbox each parameter to the expected type.
|
||||||
/// if any unboxing fails the execution of the function fails and
|
/// if any unboxing fails the execution of the function fails and
|
||||||
/// the bad_boxed_cast is passed up to the caller.
|
/// the bad_boxed_cast is passed up to the caller.
|
||||||
template<typename Callable, typename Ret, typename ... Params>
|
template<typename Callable, typename Ret, typename... Params>
|
||||||
Boxed_Value call_func(Ret (*sig)(Params...), const Callable &f,
|
Boxed_Value
|
||||||
const chaiscript::Function_Params ¶ms, const Type_Conversions_State &t_conversions)
|
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>) {
|
||||||
if constexpr (std::is_same_v<Ret, void>) {
|
call_func(sig, std::index_sequence_for<Params...>{}, f, params, t_conversions);
|
||||||
call_func(sig, std::index_sequence_for<Params...>{}, f, params, t_conversions);
|
return Handle_Return<void>::handle();
|
||||||
return Handle_Return<void>::handle();
|
} else {
|
||||||
} else {
|
return Handle_Return<Ret>::handle(call_func(sig, std::index_sequence_for<Params...>{}, f, params, t_conversions));
|
||||||
return Handle_Return<Ret>::handle(call_func(sig, std::index_sequence_for<Params...>{}, f, params, t_conversions));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
} // namespace detail
|
||||||
}
|
} // namespace dispatch
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
} // namespace chaiscript
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -7,63 +7,55 @@
|
|||||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
// 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
|
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||||
|
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_REGISTER_FUNCTION_HPP_
|
#ifndef CHAISCRIPT_REGISTER_FUNCTION_HPP_
|
||||||
#define CHAISCRIPT_REGISTER_FUNCTION_HPP_
|
#define CHAISCRIPT_REGISTER_FUNCTION_HPP_
|
||||||
|
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
#include "bind_first.hpp"
|
#include "bind_first.hpp"
|
||||||
#include "proxy_functions.hpp"
|
|
||||||
#include "function_signature.hpp"
|
#include "function_signature.hpp"
|
||||||
|
#include "proxy_functions.hpp"
|
||||||
|
|
||||||
namespace chaiscript
|
namespace chaiscript {
|
||||||
{
|
namespace dispatch::detail {
|
||||||
namespace dispatch::detail
|
template<typename Obj, typename Param1, typename... Rest>
|
||||||
{
|
Param1 get_first_param(Function_Params<Param1, Rest...>, Obj &&obj) {
|
||||||
template<typename Obj, typename Param1, typename ... Rest>
|
return static_cast<Param1>(std::forward<Obj>(obj));
|
||||||
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>
|
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>)
|
auto make_callable_impl(Func &&func, Function_Signature<Ret, Function_Params<Param...>, Is_Noexcept, Is_Member, Is_MemberObject, Is_Object>) {
|
||||||
{
|
if constexpr (Is_MemberObject) {
|
||||||
if constexpr (Is_MemberObject) {
|
// we now that the Param pack will have only one element, so we are safe expanding it here
|
||||||
// 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>...>>(
|
||||||
return Proxy_Function(chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Attribute_Access<Ret, std::decay_t<Param>...>>(std::forward<Func>(func)));
|
std::forward<Func>(func)));
|
||||||
} else if constexpr (Is_Member) {
|
} else if constexpr (Is_Member) {
|
||||||
// TODO some kind of bug is preventing forwarding of this noexcept for the lambda
|
// 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) {
|
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 ((get_first_param(Function_Params<Param...>{}, obj).*func)(std::forward<decltype(param)>(param)...));
|
||||||
};
|
};
|
||||||
return Proxy_Function(
|
return Proxy_Function(
|
||||||
chaiscript::make_shared<dispatch::Proxy_Function_Base,
|
chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Proxy_Function_Callable_Impl<Ret(Param...), decltype(call)>>(
|
||||||
dispatch::Proxy_Function_Callable_Impl<Ret (Param...), decltype(call)>>(std::move(call))
|
std::move(call)));
|
||||||
);
|
} else {
|
||||||
} else {
|
return Proxy_Function(
|
||||||
return Proxy_Function(
|
chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Proxy_Function_Callable_Impl<Ret(Param...), std::decay_t<Func>>>(
|
||||||
chaiscript::make_shared<dispatch::Proxy_Function_Base,
|
std::forward<Func>(func)));
|
||||||
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
|
// this version peels off the function object itself from the function signature, when used
|
||||||
// on a callable object
|
// on a callable object
|
||||||
template<typename Func, typename Ret, typename Object, typename ... Param, bool Is_Noexcept>
|
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>)
|
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>{});
|
||||||
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>
|
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)
|
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);
|
||||||
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
|
/// \brief Creates a new Proxy_Function object from a free function, member function or data member
|
||||||
/// \param[in] t Function / member to expose
|
/// \param[in] t Function / member to expose
|
||||||
@ -77,22 +69,19 @@ namespace chaiscript
|
|||||||
/// void memberfunction();
|
/// void memberfunction();
|
||||||
/// int memberdata;
|
/// int memberdata;
|
||||||
/// };
|
/// };
|
||||||
///
|
///
|
||||||
/// chaiscript::ChaiScript chai;
|
/// chaiscript::ChaiScript chai;
|
||||||
/// chai.add(fun(&myfunction), "myfunction");
|
/// chai.add(fun(&myfunction), "myfunction");
|
||||||
/// chai.add(fun(&MyClass::memberfunction), "memberfunction");
|
/// chai.add(fun(&MyClass::memberfunction), "memberfunction");
|
||||||
/// chai.add(fun(&MyClass::memberdata), "memberdata");
|
/// chai.add(fun(&MyClass::memberdata), "memberdata");
|
||||||
/// \endcode
|
/// \endcode
|
||||||
///
|
///
|
||||||
/// \sa \ref adding_functions
|
/// \sa \ref adding_functions
|
||||||
template<typename T>
|
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));
|
||||||
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
|
/// \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] t Function / member to expose
|
||||||
/// \param[in] q Value to bind to first parameter
|
/// \param[in] q Value to bind to first parameter
|
||||||
@ -103,24 +92,19 @@ namespace chaiscript
|
|||||||
/// {
|
/// {
|
||||||
/// void memberfunction(int);
|
/// void memberfunction(int);
|
||||||
/// };
|
/// };
|
||||||
///
|
///
|
||||||
/// MyClass obj;
|
/// MyClass obj;
|
||||||
/// chaiscript::ChaiScript chai;
|
/// chaiscript::ChaiScript chai;
|
||||||
/// // Add function taking only one argument, an int, and permanently bound to "obj"
|
/// // Add function taking only one argument, an int, and permanently bound to "obj"
|
||||||
/// chai.add(fun(&MyClass::memberfunction, std::ref(obj)), "memberfunction");
|
/// chai.add(fun(&MyClass::memberfunction, std::ref(obj)), "memberfunction");
|
||||||
/// \endcode
|
/// \endcode
|
||||||
///
|
///
|
||||||
/// \sa \ref adding_functions
|
/// \sa \ref adding_functions
|
||||||
template<typename T, typename Q>
|
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));
|
||||||
return fun(detail::bind_first(std::forward<T>(t), q));
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
} // namespace chaiscript
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@ -2,19 +2,19 @@
|
|||||||
#define SHORT_ALLOC_H
|
#define SHORT_ALLOC_H
|
||||||
|
|
||||||
// The MIT License (MIT)
|
// The MIT License (MIT)
|
||||||
//
|
//
|
||||||
// Copyright (c) 2015 Howard Hinnant
|
// Copyright (c) 2015 Howard Hinnant
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
// in the Software without restriction, including without limitation the rights
|
// in the Software without restriction, including without limitation the rights
|
||||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
// copies of the Software, and to permit persons to whom the Software is
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
// furnished to do so, subject to the following conditions:
|
// furnished to do so, subject to the following conditions:
|
||||||
//
|
//
|
||||||
// The above copyright notice and this permission notice shall be included in all
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
// copies or substantial portions of the Software.
|
// copies or substantial portions of the Software.
|
||||||
//
|
//
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
@ -23,137 +23,115 @@
|
|||||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
// SOFTWARE.
|
// SOFTWARE.
|
||||||
|
|
||||||
#include <cstddef>
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
template <std::size_t N, std::size_t alignment = alignof(std::max_align_t)>
|
template<std::size_t N, std::size_t alignment = alignof(std::max_align_t)>
|
||||||
class arena
|
class arena {
|
||||||
{
|
alignas(alignment) char buf_[N];
|
||||||
alignas(alignment) char buf_[N];
|
char *ptr_;
|
||||||
char* ptr_;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
~arena() {ptr_ = nullptr;}
|
~arena() { ptr_ = nullptr; }
|
||||||
arena() noexcept : ptr_(buf_) {}
|
arena() noexcept
|
||||||
arena(const arena&) = delete;
|
: ptr_(buf_) {
|
||||||
arena& operator=(const arena&) = delete;
|
}
|
||||||
|
arena(const arena &) = delete;
|
||||||
|
arena &operator=(const arena &) = delete;
|
||||||
|
|
||||||
template <std::size_t ReqAlign> char* allocate(std::size_t n);
|
template<std::size_t ReqAlign>
|
||||||
void deallocate(char* p, std::size_t n) noexcept;
|
char *allocate(std::size_t n);
|
||||||
|
void deallocate(char *p, std::size_t n) noexcept;
|
||||||
|
|
||||||
static constexpr std::size_t size() noexcept {return N;}
|
static constexpr std::size_t size() noexcept { return N; }
|
||||||
std::size_t used() const noexcept {return static_cast<std::size_t>(ptr_ - buf_);}
|
std::size_t used() const noexcept { return static_cast<std::size_t>(ptr_ - buf_); }
|
||||||
void reset() noexcept {ptr_ = buf_;}
|
void reset() noexcept { ptr_ = buf_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static
|
static std::size_t align_up(std::size_t n) noexcept { return (n + (alignment - 1)) & ~(alignment - 1); }
|
||||||
std::size_t
|
|
||||||
align_up(std::size_t n) noexcept
|
|
||||||
{return (n + (alignment-1)) & ~(alignment-1);}
|
|
||||||
|
|
||||||
bool
|
bool pointer_in_buffer(char *p) noexcept { return buf_ <= p && p <= buf_ + N; }
|
||||||
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 N, std::size_t alignment>
|
||||||
template <std::size_t ReqAlign>
|
template<std::size_t ReqAlign>
|
||||||
char*
|
char *arena<N, alignment>::allocate(std::size_t n) {
|
||||||
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");
|
||||||
static_assert(ReqAlign <= alignment, "alignment is too small for this arena");
|
auto const aligned_n = align_up(n);
|
||||||
assert(pointer_in_buffer(ptr_) && "short_alloc has outlived arena");
|
if (static_cast<decltype(aligned_n)>(buf_ + N - ptr_) >= aligned_n) {
|
||||||
auto const aligned_n = align_up(n);
|
char *r = ptr_;
|
||||||
if (static_cast<decltype(aligned_n)>(buf_ + N - ptr_) >= aligned_n)
|
ptr_ += aligned_n;
|
||||||
{
|
return r;
|
||||||
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),
|
||||||
"alignment that is larger than alignof(std::max_align_t), and "
|
"you've chosen an "
|
||||||
"cannot be guaranteed by normal operator new");
|
"alignment that is larger than alignof(std::max_align_t), and "
|
||||||
return static_cast<char*>(::operator new(n));
|
"cannot be guaranteed by normal operator new");
|
||||||
|
return static_cast<char *>(::operator new(n));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <std::size_t N, std::size_t alignment>
|
template<std::size_t N, std::size_t alignment>
|
||||||
void
|
void arena<N, alignment>::deallocate(char *p, std::size_t n) noexcept {
|
||||||
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)) {
|
||||||
assert(pointer_in_buffer(ptr_) && "short_alloc has outlived arena");
|
n = align_up(n);
|
||||||
if (pointer_in_buffer(p))
|
if (p + n == ptr_) {
|
||||||
{
|
ptr_ = p;
|
||||||
n = align_up(n);
|
|
||||||
if (p + n == ptr_) {
|
|
||||||
ptr_ = p;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
::operator delete(p);
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
::operator delete(p);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T, std::size_t N, std::size_t Align = alignof(std::max_align_t)>
|
template<class T, std::size_t N, std::size_t Align = alignof(std::max_align_t)>
|
||||||
class short_alloc
|
class short_alloc {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
using value_type = T;
|
using value_type = T;
|
||||||
static auto constexpr alignment = Align;
|
static auto constexpr alignment = Align;
|
||||||
static auto constexpr size = N;
|
static auto constexpr size = N;
|
||||||
using arena_type = arena<size, alignment>;
|
using arena_type = arena<size, alignment>;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
arena_type& a_;
|
arena_type &a_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
short_alloc(const short_alloc&) = default;
|
short_alloc(const short_alloc &) = default;
|
||||||
short_alloc& operator=(const short_alloc&) = delete;
|
short_alloc &operator=(const short_alloc &) = delete;
|
||||||
|
|
||||||
explicit short_alloc(arena_type& a) noexcept : a_(a)
|
explicit short_alloc(arena_type &a) noexcept
|
||||||
{
|
: a_(a) {
|
||||||
static_assert(size % alignment == 0,
|
static_assert(size % alignment == 0, "size N needs to be a multiple of alignment Align");
|
||||||
"size N needs to be a multiple of alignment Align");
|
}
|
||||||
}
|
template<class U>
|
||||||
template <class U>
|
explicit short_alloc(const short_alloc<U, N, alignment> &a) noexcept
|
||||||
explicit short_alloc(const short_alloc<U, N, alignment>& a) noexcept
|
: a_(a.a_) {
|
||||||
: a_(a.a_) {}
|
}
|
||||||
|
|
||||||
template <class _Up> struct rebind {using other = short_alloc<_Up, N, alignment>;};
|
template<class _Up>
|
||||||
|
struct rebind {
|
||||||
|
using other = short_alloc<_Up, N, alignment>;
|
||||||
|
};
|
||||||
|
|
||||||
T* allocate(std::size_t n)
|
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)); }
|
||||||
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,
|
template<class T1, std::size_t N1, std::size_t A1, class U, std::size_t M, std::size_t A2>
|
||||||
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;
|
||||||
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 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>
|
template<class T, std::size_t N, std::size_t A1, class U, std::size_t M, std::size_t A2>
|
||||||
inline
|
inline bool operator==(const short_alloc<T, N, A1> &x, const short_alloc<U, M, A2> &y) noexcept {
|
||||||
bool
|
return N == M && A1 == A2 && &x.a_ == &y.a_;
|
||||||
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>
|
template<class T, std::size_t N, std::size_t A1, class U, std::size_t M, std::size_t A2>
|
||||||
inline
|
inline bool operator!=(const short_alloc<T, N, A1> &x, const short_alloc<U, M, A2> &y) noexcept {
|
||||||
bool
|
return !(x == y);
|
||||||
operator!=(const short_alloc<T, N, A1>& x, const short_alloc<U, M, A2>& y) noexcept
|
|
||||||
{
|
|
||||||
return !(x == y);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // SHORT_ALLOC_HPP
|
#endif // SHORT_ALLOC_HPP
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -7,236 +7,204 @@
|
|||||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
// 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
|
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||||
|
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_TYPE_INFO_HPP_
|
#ifndef CHAISCRIPT_TYPE_INFO_HPP_
|
||||||
#define CHAISCRIPT_TYPE_INFO_HPP_
|
#define CHAISCRIPT_TYPE_INFO_HPP_
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <typeinfo>
|
#include <typeinfo>
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace chaiscript
|
namespace chaiscript {
|
||||||
{
|
namespace detail {
|
||||||
|
|
||||||
namespace detail
|
|
||||||
{
|
|
||||||
template<typename T>
|
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;
|
||||||
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
|
/// \brief Compile time deduced information about a type
|
||||||
class Type_Info
|
class Type_Info {
|
||||||
{
|
public:
|
||||||
public:
|
constexpr Type_Info(const bool t_is_const,
|
||||||
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_reference,
|
||||||
const bool t_is_arithmetic, const std::type_info *t_ti, const std::type_info *t_bare_ti) noexcept
|
const bool t_is_pointer,
|
||||||
: m_type_info(t_ti), m_bare_type_info(t_bare_ti),
|
const bool t_is_void,
|
||||||
m_flags((static_cast<unsigned int>(t_is_const) << is_const_flag)
|
const bool t_is_arithmetic,
|
||||||
+ (static_cast<unsigned int>(t_is_reference) << is_reference_flag)
|
const std::type_info *t_ti,
|
||||||
+ (static_cast<unsigned int>(t_is_pointer) << is_pointer_flag)
|
const std::type_info *t_bare_ti) noexcept
|
||||||
+ (static_cast<unsigned int>(t_is_void) << is_void_flag)
|
: m_type_info(t_ti)
|
||||||
+ (static_cast<unsigned int>(t_is_arithmetic) << is_arithmetic_flag))
|
, 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); }
|
||||||
|
|
||||||
|
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 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 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; }
|
||||||
|
constexpr bool is_void() const noexcept { return (m_flags & (1 << is_void_flag)) != 0; }
|
||||||
|
constexpr bool is_arithmetic() const noexcept { return (m_flags & (1 << is_arithmetic_flag)) != 0; }
|
||||||
|
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()) {
|
||||||
|
return m_type_info->name();
|
||||||
|
} else {
|
||||||
|
return "";
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
constexpr Type_Info() noexcept = default;
|
const char *bare_name() const noexcept {
|
||||||
|
if (!is_undef()) {
|
||||||
bool operator<(const Type_Info &ti) const noexcept
|
return m_bare_type_info->name();
|
||||||
{
|
} else {
|
||||||
return m_type_info->before(*ti.m_type_info);
|
return "";
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
constexpr bool operator!=(const Type_Info &ti) const noexcept
|
constexpr const std::type_info *bare_type_info() const noexcept { return m_bare_type_info; }
|
||||||
{
|
|
||||||
return !(operator==(ti));
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr bool operator!=(const std::type_info &ti) const noexcept
|
private:
|
||||||
{
|
struct Unknown_Type {
|
||||||
return !(operator==(ti));
|
};
|
||||||
}
|
|
||||||
|
|
||||||
constexpr bool operator==(const Type_Info &ti) const noexcept
|
const std::type_info *m_type_info = &typeid(Unknown_Type);
|
||||||
{
|
const std::type_info *m_bare_type_info = &typeid(Unknown_Type);
|
||||||
return ti.m_type_info == m_type_info
|
static const int is_const_flag = 0;
|
||||||
|| *ti.m_type_info == *m_type_info;
|
static const int is_reference_flag = 1;
|
||||||
}
|
static const int is_pointer_flag = 2;
|
||||||
|
static const int is_void_flag = 3;
|
||||||
constexpr bool operator==(const std::type_info &ti) const noexcept
|
static const int is_arithmetic_flag = 4;
|
||||||
{
|
static const int is_undef_flag = 5;
|
||||||
return !is_undef() && (*m_type_info) == ti;
|
unsigned int m_flags = (1 << is_undef_flag);
|
||||||
}
|
|
||||||
|
|
||||||
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 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; }
|
|
||||||
constexpr bool is_void() const noexcept { return (m_flags & (1 << is_void_flag)) != 0; }
|
|
||||||
constexpr bool is_arithmetic() const noexcept { return (m_flags & (1 << is_arithmetic_flag)) != 0; }
|
|
||||||
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())
|
|
||||||
{
|
|
||||||
return m_type_info->name();
|
|
||||||
} else {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
struct Unknown_Type {};
|
|
||||||
|
|
||||||
const std::type_info *m_type_info = &typeid(Unknown_Type);
|
|
||||||
const std::type_info *m_bare_type_info = &typeid(Unknown_Type);
|
|
||||||
static const int is_const_flag = 0;
|
|
||||||
static const int is_reference_flag = 1;
|
|
||||||
static const int is_pointer_flag = 2;
|
|
||||||
static const int is_void_flag = 3;
|
|
||||||
static const int is_arithmetic_flag = 4;
|
|
||||||
static const int is_undef_flag = 5;
|
|
||||||
unsigned int m_flags = (1 << is_undef_flag);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace detail
|
namespace detail {
|
||||||
{
|
|
||||||
/// Helper used to create a Type_Info object
|
/// Helper used to create a Type_Info object
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct Get_Type_Info
|
struct Get_Type_Info {
|
||||||
{
|
constexpr static Type_Info get() noexcept {
|
||||||
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,
|
||||||
return Type_Info(std::is_const<typename std::remove_pointer<typename std::remove_reference<T>::type>::type>::value,
|
std::is_pointer<T>::value,
|
||||||
std::is_reference<T>::value, std::is_pointer<T>::value,
|
std::is_void<T>::value,
|
||||||
std::is_void<T>::value,
|
(std::is_arithmetic<T>::value || std::is_arithmetic<typename std::remove_reference<T>::type>::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,
|
||||||
&& !std::is_same<typename std::remove_const<typename std::remove_reference<T>::type>::type, bool>::value,
|
&typeid(T),
|
||||||
&typeid(T),
|
&typeid(typename Bare_Type<T>::type));
|
||||||
&typeid(typename Bare_Type<T>::type));
|
}
|
||||||
}
|
};
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct Get_Type_Info<std::shared_ptr<T> >
|
struct Get_Type_Info<std::shared_ptr<T>> {
|
||||||
{
|
constexpr static Type_Info get() noexcept {
|
||||||
constexpr static Type_Info get() noexcept
|
return Type_Info(std::is_const<T>::value,
|
||||||
{
|
std::is_reference<T>::value,
|
||||||
return Type_Info(std::is_const<T>::value, std::is_reference<T>::value, std::is_pointer<T>::value,
|
std::is_pointer<T>::value,
|
||||||
std::is_void<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
|
||||||
&typeid(std::shared_ptr<T> ),
|
&& !std::is_same<typename std::remove_const<typename std::remove_reference<T>::type>::type, bool>::value,
|
||||||
&typeid(typename Bare_Type<T>::type));
|
&typeid(std::shared_ptr<T>),
|
||||||
}
|
&typeid(typename Bare_Type<T>::type));
|
||||||
};
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template<typename T>
|
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>
|
template<typename T>
|
||||||
struct Get_Type_Info<const std::shared_ptr<T> &>
|
struct Get_Type_Info<const std::shared_ptr<T> &> {
|
||||||
{
|
constexpr static Type_Info get() noexcept {
|
||||||
constexpr static Type_Info get() noexcept
|
return Type_Info(std::is_const<T>::value,
|
||||||
{
|
std::is_reference<T>::value,
|
||||||
return Type_Info(std::is_const<T>::value, std::is_reference<T>::value, std::is_pointer<T>::value,
|
std::is_pointer<T>::value,
|
||||||
std::is_void<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
|
||||||
&typeid(const std::shared_ptr<T> &),
|
&& !std::is_same<typename std::remove_const<typename std::remove_reference<T>::type>::type, bool>::value,
|
||||||
&typeid(typename Bare_Type<T>::type));
|
&typeid(const std::shared_ptr<T> &),
|
||||||
}
|
&typeid(typename Bare_Type<T>::type));
|
||||||
};
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct Get_Type_Info<std::reference_wrapper<T> >
|
struct Get_Type_Info<std::reference_wrapper<T>> {
|
||||||
{
|
constexpr static Type_Info get() noexcept {
|
||||||
constexpr static Type_Info get() noexcept
|
return Type_Info(std::is_const<T>::value,
|
||||||
{
|
std::is_reference<T>::value,
|
||||||
return Type_Info(std::is_const<T>::value, std::is_reference<T>::value, std::is_pointer<T>::value,
|
std::is_pointer<T>::value,
|
||||||
std::is_void<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
|
||||||
&typeid(std::reference_wrapper<T> ),
|
&& !std::is_same<typename std::remove_const<typename std::remove_reference<T>::type>::type, bool>::value,
|
||||||
&typeid(typename Bare_Type<T>::type));
|
&typeid(std::reference_wrapper<T>),
|
||||||
}
|
&typeid(typename Bare_Type<T>::type));
|
||||||
};
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct Get_Type_Info<const std::reference_wrapper<T> &>
|
struct Get_Type_Info<const std::reference_wrapper<T> &> {
|
||||||
{
|
constexpr static Type_Info get() noexcept {
|
||||||
constexpr static Type_Info get() noexcept
|
return Type_Info(std::is_const<T>::value,
|
||||||
{
|
std::is_reference<T>::value,
|
||||||
return Type_Info(std::is_const<T>::value, std::is_reference<T>::value, std::is_pointer<T>::value,
|
std::is_pointer<T>::value,
|
||||||
std::is_void<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
|
||||||
&typeid(const std::reference_wrapper<T> &),
|
&& !std::is_same<typename std::remove_const<typename std::remove_reference<T>::type>::type, bool>::value,
|
||||||
&typeid(typename Bare_Type<T>::type));
|
&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
|
/// \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
|
/// \tparam T Type of object to get a Type_Info for, derived from the passed in parameter
|
||||||
/// \return Type_Info for T
|
/// \return Type_Info for T
|
||||||
///
|
///
|
||||||
/// \b Example:
|
/// \b Example:
|
||||||
/// \code
|
/// \code
|
||||||
/// int i;
|
/// int i;
|
||||||
/// chaiscript::Type_Info ti = chaiscript::user_type(i);
|
/// chaiscript::Type_Info ti = chaiscript::user_type(i);
|
||||||
/// \endcode
|
/// \endcode
|
||||||
template<typename T>
|
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();
|
return detail::Get_Type_Info<T>::get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// \brief Creates a Type_Info object representing the templated type
|
/// \brief Creates a Type_Info object representing the templated type
|
||||||
/// \tparam T Type of object to get a Type_Info for
|
/// \tparam T Type of object to get a Type_Info for
|
||||||
/// \return Type_Info for T
|
/// \return Type_Info for T
|
||||||
///
|
///
|
||||||
/// \b Example:
|
/// \b Example:
|
||||||
/// \code
|
/// \code
|
||||||
/// chaiscript::Type_Info ti = chaiscript::user_type<int>();
|
/// chaiscript::Type_Info ti = chaiscript::user_type<int>();
|
||||||
/// \endcode
|
/// \endcode
|
||||||
template<typename T>
|
template<typename T>
|
||||||
constexpr Type_Info user_type() noexcept
|
constexpr Type_Info user_type() noexcept {
|
||||||
{
|
|
||||||
return detail::Get_Type_Info<T>::get();
|
return detail::Get_Type_Info<T>::get();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
} // namespace chaiscript
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@ -7,7 +7,6 @@
|
|||||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
// 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
|
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||||
|
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_ALGEBRAIC_HPP_
|
#ifndef CHAISCRIPT_ALGEBRAIC_HPP_
|
||||||
#define CHAISCRIPT_ALGEBRAIC_HPP_
|
#define CHAISCRIPT_ALGEBRAIC_HPP_
|
||||||
|
|
||||||
@ -15,43 +14,51 @@
|
|||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace chaiscript
|
namespace chaiscript {
|
||||||
{
|
|
||||||
|
|
||||||
struct Operators {
|
struct Operators {
|
||||||
enum class Opers
|
enum class Opers {
|
||||||
{
|
equals,
|
||||||
equals, less_than, greater_than, less_than_equal, greater_than_equal, not_equal,
|
less_than,
|
||||||
assign, pre_increment, pre_decrement, assign_product, assign_sum,
|
greater_than,
|
||||||
assign_quotient, assign_difference,
|
less_than_equal,
|
||||||
assign_bitwise_and, assign_bitwise_or, assign_shift_left, assign_shift_right,
|
greater_than_equal,
|
||||||
assign_remainder, assign_bitwise_xor,
|
not_equal,
|
||||||
shift_left, shift_right, remainder, bitwise_and, bitwise_or, bitwise_xor, bitwise_complement,
|
assign,
|
||||||
sum, quotient, product, difference, unary_plus, unary_minus,
|
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
|
invalid
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr static const char *to_string(Opers t_oper) noexcept {
|
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)];
|
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
|
#ifdef CHAISCRIPT_MSVC
|
||||||
#pragma warning(push)
|
#pragma warning(push)
|
||||||
#pragma warning(disable : 4307)
|
#pragma warning(disable : 4307)
|
||||||
@ -59,45 +66,102 @@ namespace chaiscript
|
|||||||
|
|
||||||
const auto op_hash = utility::hash(t_str);
|
const auto op_hash = utility::hash(t_str);
|
||||||
switch (op_hash) {
|
switch (op_hash) {
|
||||||
case utility::hash("=="): { return Opers::equals; }
|
case utility::hash("=="): {
|
||||||
case utility::hash("<"): { return Opers::less_than; }
|
return Opers::equals;
|
||||||
case utility::hash(">"): { return Opers::greater_than; }
|
}
|
||||||
case utility::hash("<="): { return Opers::less_than_equal; }
|
case utility::hash("<"): {
|
||||||
case utility::hash(">="): { return Opers::greater_than_equal; }
|
return Opers::less_than;
|
||||||
case utility::hash("!="): { return Opers::not_equal; }
|
}
|
||||||
case utility::hash("="): { return Opers::assign; }
|
case utility::hash(">"): {
|
||||||
case utility::hash("++"): { return Opers::pre_increment; }
|
return Opers::greater_than;
|
||||||
case utility::hash("--"): { return Opers::pre_decrement; }
|
}
|
||||||
case utility::hash("*="): { return Opers::assign_product; }
|
case utility::hash("<="): {
|
||||||
case utility::hash("+="): { return Opers::assign_sum; }
|
return Opers::less_than_equal;
|
||||||
case utility::hash("-="): { return Opers::assign_difference; }
|
}
|
||||||
case utility::hash("&="): { return Opers::assign_bitwise_and; }
|
case utility::hash(">="): {
|
||||||
case utility::hash("|="): { return Opers::assign_bitwise_or; }
|
return Opers::greater_than_equal;
|
||||||
case utility::hash("<<="): { return Opers::assign_shift_left; }
|
}
|
||||||
case utility::hash(">>="): { return Opers::assign_shift_right; }
|
case utility::hash("!="): {
|
||||||
case utility::hash("%="): { return Opers::assign_remainder; }
|
return Opers::not_equal;
|
||||||
case utility::hash("^="): { return Opers::assign_bitwise_xor; }
|
}
|
||||||
case utility::hash("<<"): { return Opers::shift_left; }
|
case utility::hash("="): {
|
||||||
case utility::hash(">>"): { return Opers::shift_right; }
|
return Opers::assign;
|
||||||
case utility::hash("%"): { return Opers::remainder; }
|
}
|
||||||
case utility::hash("&"): { return Opers::bitwise_and; }
|
case utility::hash("++"): {
|
||||||
case utility::hash("|"): { return Opers::bitwise_or; }
|
return Opers::pre_increment;
|
||||||
case utility::hash("^"): { return Opers::bitwise_xor; }
|
}
|
||||||
case utility::hash("~"): { return Opers::bitwise_complement; }
|
case utility::hash("--"): {
|
||||||
case utility::hash("+"): { return t_is_unary ? Opers::unary_plus : Opers::sum; }
|
return Opers::pre_decrement;
|
||||||
case utility::hash("-"): { return t_is_unary ? Opers::unary_minus : Opers::difference; }
|
}
|
||||||
case utility::hash("/"): { return Opers::quotient; }
|
case utility::hash("*="): {
|
||||||
case utility::hash("*"): { return Opers::product; }
|
return Opers::assign_product;
|
||||||
default: { return Opers::invalid; }
|
}
|
||||||
|
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
|
#ifdef CHAISCRIPT_MSVC
|
||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
} // namespace chaiscript
|
||||||
|
|
||||||
#endif /* _CHAISCRIPT_ALGEBRAIC_HPP */
|
#endif /* _CHAISCRIPT_ALGEBRAIC_HPP */
|
||||||
|
|
||||||
|
|||||||
@ -7,7 +7,6 @@
|
|||||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
// 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
|
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||||
|
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_COMMON_HPP_
|
#ifndef CHAISCRIPT_COMMON_HPP_
|
||||||
#define CHAISCRIPT_COMMON_HPP_
|
#define CHAISCRIPT_COMMON_HPP_
|
||||||
|
|
||||||
@ -26,53 +25,26 @@
|
|||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
|
||||||
namespace chaiscript {
|
namespace chaiscript {
|
||||||
struct AST_Node;
|
struct AST_Node;
|
||||||
} // namespace chaiscript
|
} // namespace chaiscript
|
||||||
|
|
||||||
namespace chaiscript
|
namespace chaiscript {
|
||||||
{
|
|
||||||
struct Name_Validator {
|
struct Name_Validator {
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static bool is_reserved_word(const T &s) noexcept
|
static bool is_reserved_word(const T &s) noexcept {
|
||||||
{
|
const static std::unordered_set<std::uint32_t>
|
||||||
const static std::unordered_set<std::uint32_t> words{
|
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__")};
|
||||||
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;
|
return words.count(utility::hash(s)) == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
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);
|
return name.find("::") == std::string::npos && !is_reserved_word(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static void validate_object_name(const T &name)
|
static void validate_object_name(const T &name) {
|
||||||
{
|
|
||||||
if (is_reserved_word(name)) {
|
if (is_reserved_word(name)) {
|
||||||
throw exception::reserved_word_error(std::string(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.
|
/// Signature of module entry point that all binary loadable modules must implement.
|
||||||
using Create_Module_Func = ModulePtr (*)();
|
using Create_Module_Func = ModulePtr (*)();
|
||||||
|
|
||||||
|
|
||||||
/// Types of AST nodes available to the parser and eval
|
/// 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,
|
enum class AST_Node_Type {
|
||||||
Array_Call, Dot_Access,
|
Id,
|
||||||
Lambda, Block, Scopeless_Block, Def, While, If, For, Ranged_For, Inline_Array, Inline_Map, Return, File, Prefix, Break, Continue, Map_Pair, Value_Range,
|
Fun_Call,
|
||||||
Inline_Range, Try, Catch, Finally, Method, Attr_Decl,
|
Unused_Return_Fun_Call,
|
||||||
Logical_And, Logical_Or, Reference, Switch, Case, Default, Noop, Class, Binary, Arg, Global_Decl, Constant, Compiled
|
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,
|
enum class Operator_Precedence {
|
||||||
Logical_And, Bitwise_Or, Bitwise_Xor, Bitwise_And,
|
Ternary_Cond,
|
||||||
Equality, Comparison, Shift, Addition, Multiplication, Prefix };
|
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
|
/// 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 *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",
|
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"};
|
||||||
"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)];
|
return ast_node_types[static_cast<int>(ast_node_type)];
|
||||||
}
|
}
|
||||||
}
|
} // namespace
|
||||||
|
|
||||||
/// \brief Convenience type for file positions
|
/// \brief Convenience type for file positions
|
||||||
struct File_Position {
|
struct File_Position {
|
||||||
@ -119,64 +137,57 @@ namespace chaiscript
|
|||||||
int column = 0;
|
int column = 0;
|
||||||
|
|
||||||
constexpr File_Position(int t_file_line, int t_file_column) noexcept
|
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;
|
constexpr File_Position() noexcept = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Parse_Location {
|
struct Parse_Location {
|
||||||
Parse_Location(std::string t_fname="", const int t_start_line=0, const int t_start_col=0,
|
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)
|
||||||
const int t_end_line=0, const int t_end_col=0)
|
: start(t_start_line, t_start_col)
|
||||||
: start(t_start_line, t_start_col),
|
, end(t_end_line, t_end_col)
|
||||||
end(t_end_line, t_end_col),
|
, filename(std::make_shared<std::string>(std::move(t_fname))) {
|
||||||
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,
|
Parse_Location(std::shared_ptr<std::string> t_fname,
|
||||||
const int t_end_line=0, const int t_end_col=0)
|
const int t_start_line = 0,
|
||||||
: start(t_start_line, t_start_col),
|
const int t_start_col = 0,
|
||||||
end(t_end_line, t_end_col),
|
const int t_end_line = 0,
|
||||||
filename(std::move(t_fname))
|
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 start;
|
||||||
File_Position end;
|
File_Position end;
|
||||||
std::shared_ptr<std::string> filename;
|
std::shared_ptr<std::string> filename;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/// \brief Typedef for pointers to AST_Node objects. Used in building of the AST_Node tree
|
/// \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 = std::unique_ptr<AST_Node>;
|
||||||
using AST_NodePtr_Const = std::unique_ptr<const AST_Node>;
|
using AST_NodePtr_Const = std::unique_ptr<const AST_Node>;
|
||||||
|
|
||||||
struct AST_Node_Trace;
|
struct AST_Node_Trace;
|
||||||
|
|
||||||
|
|
||||||
/// \brief Classes which may be thrown during error cases when ChaiScript is executing.
|
/// \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
|
/// \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)
|
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)
|
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(const load_module_error &) = default;
|
||||||
~load_module_error() noexcept override = 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;
|
std::stringstream ss;
|
||||||
ss << "Error loading module '" << t_name << "'\n"
|
ss << "Error loading module '" << t_name << "'\n"
|
||||||
<< " The following locations were searched:\n";
|
<< " The following locations were searched:\n";
|
||||||
@ -189,7 +200,6 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/// Errors generated during parsing or evaluation
|
/// Errors generated during parsing or evaluation
|
||||||
struct eval_error : std::runtime_error {
|
struct eval_error : std::runtime_error {
|
||||||
std::string reason;
|
std::string reason;
|
||||||
@ -198,48 +208,55 @@ namespace chaiscript
|
|||||||
std::string detail;
|
std::string detail;
|
||||||
std::vector<AST_Node_Trace> call_stack;
|
std::vector<AST_Node_Trace> call_stack;
|
||||||
|
|
||||||
eval_error(const std::string &t_why, const File_Position &t_where, const std::string &t_fname,
|
eval_error(const std::string &t_why,
|
||||||
const std::vector<Boxed_Value> &t_parameters, const std::vector<chaiscript::Const_Proxy_Function> &t_functions,
|
const File_Position &t_where,
|
||||||
bool t_dot_notation,
|
const std::string &t_fname,
|
||||||
const chaiscript::detail::Dispatch_Engine &t_ss) noexcept :
|
const std::vector<Boxed_Value> &t_parameters,
|
||||||
std::runtime_error(format(t_why, t_where, t_fname, t_parameters, t_dot_notation, t_ss)),
|
const std::vector<chaiscript::Const_Proxy_Function> &t_functions,
|
||||||
reason(t_why), start_position(t_where), filename(t_fname), detail(format_detail(t_functions, t_dot_notation, t_ss))
|
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)) {
|
||||||
|
}
|
||||||
|
|
||||||
eval_error(const std::string &t_why,
|
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,
|
||||||
bool t_dot_notation,
|
const std::vector<chaiscript::Const_Proxy_Function> &t_functions,
|
||||||
const chaiscript::detail::Dispatch_Engine &t_ss) noexcept :
|
bool t_dot_notation,
|
||||||
std::runtime_error(format(t_why, t_parameters, t_dot_notation, t_ss)),
|
const chaiscript::detail::Dispatch_Engine &t_ss) noexcept
|
||||||
reason(t_why), detail(format_detail(t_functions, t_dot_notation, t_ss))
|
: 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
|
||||||
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))
|
||||||
std::runtime_error(format(t_why, t_where, t_fname)),
|
, reason(t_why)
|
||||||
reason(t_why), start_position(t_where), filename(t_fname)
|
, start_position(t_where)
|
||||||
{}
|
, filename(t_fname) {
|
||||||
|
}
|
||||||
|
|
||||||
explicit eval_error(const std::string &t_why) noexcept
|
explicit eval_error(const std::string &t_why) noexcept
|
||||||
: std::runtime_error("Error: \"" + t_why + "\" "),
|
: std::runtime_error("Error: \"" + t_why + "\" ")
|
||||||
reason(t_why)
|
, reason(t_why) {
|
||||||
{}
|
}
|
||||||
|
|
||||||
eval_error(const eval_error &) = default;
|
eval_error(const eval_error &) = default;
|
||||||
|
|
||||||
std::string pretty_print() const
|
std::string pretty_print() const {
|
||||||
{
|
|
||||||
std::ostringstream ss;
|
std::ostringstream ss;
|
||||||
|
|
||||||
ss << what();
|
ss << what();
|
||||||
if (!call_stack.empty()) {
|
if (!call_stack.empty()) {
|
||||||
ss << "during evaluation at (" << fname(call_stack[0]) << " " << startpos(call_stack[0]) << ")\n";
|
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]) << "'";
|
ss << " " << fname(call_stack[0]) << " (" << startpos(call_stack[0]) << ") '" << pretty(call_stack[0]) << "'";
|
||||||
for (size_t j = 1; j < call_stack.size(); ++j) {
|
for (size_t j = 1; j < call_stack.size(); ++j) {
|
||||||
if (id(call_stack[j]) != chaiscript::AST_Node_Type::Block
|
if (id(call_stack[j]) != chaiscript::AST_Node_Type::Block && id(call_stack[j]) != chaiscript::AST_Node_Type::File) {
|
||||||
&& id(call_stack[j]) != chaiscript::AST_Node_Type::File)
|
|
||||||
{
|
|
||||||
ss << '\n';
|
ss << '\n';
|
||||||
ss << " from " << fname(call_stack[j]) << " (" << startpos(call_stack[j]) << ") '" << pretty(call_stack[j]) << "'";
|
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;
|
~eval_error() noexcept override = default;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static AST_Node_Type id(const T& t) noexcept
|
static AST_Node_Type id(const T &t) noexcept {
|
||||||
{
|
return t.identifier;
|
||||||
return t.identifier;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
static std::string pretty(const T& t)
|
|
||||||
{
|
|
||||||
return t.pretty_print();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
static const std::string &fname(const T& t) noexcept
|
|
||||||
{
|
|
||||||
return t.filename();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename 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_types(const Const_Proxy_Function &t_func,
|
template<typename T>
|
||||||
bool t_dot_notation,
|
static std::string pretty(const T &t) {
|
||||||
const chaiscript::detail::Dispatch_Engine &t_ss)
|
return t.pretty_print();
|
||||||
{
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
static const std::string &fname(const T &t) noexcept {
|
||||||
|
return t.filename();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename 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_types(const Const_Proxy_Function &t_func, bool t_dot_notation, const chaiscript::detail::Dispatch_Engine &t_ss) {
|
||||||
assert(t_func);
|
assert(t_func);
|
||||||
int arity = t_func->get_arity();
|
int arity = t_func->get_arity();
|
||||||
std::vector<Type_Info> types = t_func->get_param_types();
|
std::vector<Type_Info> types = t_func->get_param_types();
|
||||||
|
|
||||||
std::string retval;
|
std::string retval;
|
||||||
if (arity == -1)
|
if (arity == -1) {
|
||||||
{
|
|
||||||
retval = "(...)";
|
retval = "(...)";
|
||||||
if (t_dot_notation)
|
if (t_dot_notation) {
|
||||||
{
|
|
||||||
retval = "(Object)." + retval;
|
retval = "(Object)." + retval;
|
||||||
}
|
}
|
||||||
} else if (types.size() <= 1) {
|
} else if (types.size() <= 1) {
|
||||||
@ -308,18 +312,13 @@ namespace chaiscript
|
|||||||
|
|
||||||
std::string paramstr;
|
std::string paramstr;
|
||||||
|
|
||||||
for (size_t index = 1;
|
for (size_t index = 1; index != types.size(); ++index) {
|
||||||
index != types.size();
|
paramstr += (types[index].is_const() ? "const " : "");
|
||||||
++index)
|
|
||||||
{
|
|
||||||
paramstr += (types[index].is_const()?"const ":"");
|
|
||||||
paramstr += t_ss.get_type_name(types[index]);
|
paramstr += t_ss.get_type_name(types[index]);
|
||||||
|
|
||||||
if (index == 1 && t_dot_notation)
|
if (index == 1 && t_dot_notation) {
|
||||||
{
|
|
||||||
paramstr += ").(";
|
paramstr += ").(";
|
||||||
if (types.size() == 2)
|
if (types.size() == 2) {
|
||||||
{
|
|
||||||
paramstr += ", ";
|
paramstr += ", ";
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -333,19 +332,15 @@ namespace chaiscript
|
|||||||
retval = ss.str();
|
retval = ss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<const dispatch::Dynamic_Proxy_Function> dynfun
|
||||||
|
= std::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(t_func);
|
||||||
|
|
||||||
std::shared_ptr<const dispatch::Dynamic_Proxy_Function> dynfun
|
if (dynfun && dynfun->has_parse_tree()) {
|
||||||
= std::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(t_func);
|
|
||||||
|
|
||||||
if (dynfun && dynfun->has_parse_tree())
|
|
||||||
{
|
|
||||||
Proxy_Function f = dynfun->get_guard();
|
Proxy_Function f = dynfun->get_guard();
|
||||||
|
|
||||||
if (f)
|
if (f) {
|
||||||
{
|
|
||||||
auto dynfunguard = std::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(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());
|
retval += " : " + format_guard(dynfunguard->get_parse_tree());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -357,65 +352,50 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static std::string format_guard(const T &t)
|
static std::string format_guard(const T &t) {
|
||||||
{
|
return t.pretty_print();
|
||||||
return t.pretty_print();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static std::string format_location(const T &t)
|
static std::string format_location(const T &t) {
|
||||||
{
|
std::ostringstream oss;
|
||||||
std::ostringstream oss;
|
oss << "(" << t.filename() << " " << t.start().line << ", " << t.start().column << ")";
|
||||||
oss << "(" << t.filename() << " " << t.start().line << ", " << t.start().column << ")";
|
return oss.str();
|
||||||
return oss.str();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
static std::string format_detail(const std::vector<chaiscript::Const_Proxy_Function> &t_functions,
|
static std::string format_detail(const std::vector<chaiscript::Const_Proxy_Function> &t_functions,
|
||||||
bool t_dot_notation,
|
bool t_dot_notation,
|
||||||
const chaiscript::detail::Dispatch_Engine &t_ss)
|
const chaiscript::detail::Dispatch_Engine &t_ss) {
|
||||||
{
|
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
if (t_functions.size() == 1)
|
if (t_functions.size() == 1) {
|
||||||
{
|
|
||||||
assert(t_functions[0]);
|
assert(t_functions[0]);
|
||||||
ss << " Expected: " << format_types(t_functions[0], t_dot_notation, t_ss) << '\n';
|
ss << " Expected: " << format_types(t_functions[0], t_dot_notation, t_ss) << '\n';
|
||||||
} else {
|
} else {
|
||||||
ss << " " << t_functions.size() << " overloads available:\n";
|
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';
|
ss << " " << format_types((t_function), t_dot_notation, t_ss) << '\n';
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ss.str();
|
return ss.str();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string format_parameters(const std::vector<Boxed_Value> &t_parameters,
|
static std::string
|
||||||
bool t_dot_notation,
|
format_parameters(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;
|
std::stringstream ss;
|
||||||
ss << "(";
|
ss << "(";
|
||||||
|
|
||||||
if (!t_parameters.empty())
|
if (!t_parameters.empty()) {
|
||||||
{
|
|
||||||
std::string paramstr;
|
std::string paramstr;
|
||||||
|
|
||||||
for (auto itr = t_parameters.begin();
|
for (auto itr = t_parameters.begin(); itr != t_parameters.end(); ++itr) {
|
||||||
itr != t_parameters.end();
|
paramstr += (itr->is_const() ? "const " : "");
|
||||||
++itr)
|
|
||||||
{
|
|
||||||
paramstr += (itr->is_const()?"const ":"");
|
|
||||||
paramstr += t_ss.type_name(*itr);
|
paramstr += t_ss.type_name(*itr);
|
||||||
|
|
||||||
if (itr == t_parameters.begin() && t_dot_notation)
|
if (itr == t_parameters.begin() && t_dot_notation) {
|
||||||
{
|
|
||||||
paramstr += ").(";
|
paramstr += ").(";
|
||||||
if (t_parameters.size() == 1)
|
if (t_parameters.size() == 1) {
|
||||||
{
|
|
||||||
paramstr += ", ";
|
paramstr += ", ";
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -430,12 +410,10 @@ namespace chaiscript
|
|||||||
return ss.str();
|
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;
|
std::stringstream ss;
|
||||||
|
|
||||||
if (t_fname != "__EVAL__")
|
if (t_fname != "__EVAL__") {
|
||||||
{
|
|
||||||
ss << "in '" << t_fname << "' ";
|
ss << "in '" << t_fname << "' ";
|
||||||
} else {
|
} else {
|
||||||
ss << "during evaluation ";
|
ss << "during evaluation ";
|
||||||
@ -444,16 +422,18 @@ namespace chaiscript
|
|||||||
return ss.str();
|
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;
|
std::stringstream ss;
|
||||||
ss << "at (" << t_where.line << ", " << t_where.column << ")";
|
ss << "at (" << t_where.line << ", " << t_where.column << ")";
|
||||||
return ss.str();
|
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 std::vector<Boxed_Value> &t_parameters, bool t_dot_notation, const chaiscript::detail::Dispatch_Engine &t_ss)
|
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;
|
std::stringstream ss;
|
||||||
|
|
||||||
ss << format_why(t_why);
|
ss << format_why(t_why);
|
||||||
@ -470,11 +450,10 @@ namespace chaiscript
|
|||||||
return ss.str();
|
return ss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string format(const std::string &t_why,
|
static std::string format(const std::string &t_why,
|
||||||
const std::vector<Boxed_Value> &t_parameters,
|
const std::vector<Boxed_Value> &t_parameters,
|
||||||
bool t_dot_notation,
|
bool t_dot_notation,
|
||||||
const chaiscript::detail::Dispatch_Engine &t_ss)
|
const chaiscript::detail::Dispatch_Engine &t_ss) {
|
||||||
{
|
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
|
|
||||||
ss << format_why(t_why);
|
ss << format_why(t_why);
|
||||||
@ -486,8 +465,7 @@ namespace chaiscript
|
|||||||
return ss.str();
|
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;
|
std::stringstream ss;
|
||||||
|
|
||||||
ss << format_why(t_why);
|
ss << format_why(t_why);
|
||||||
@ -502,13 +480,12 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/// Errors generated when loading a file
|
/// Errors generated when loading a file
|
||||||
struct file_not_found_error : std::runtime_error {
|
struct file_not_found_error : std::runtime_error {
|
||||||
explicit file_not_found_error(const std::string &t_filename)
|
explicit file_not_found_error(const std::string &t_filename)
|
||||||
: std::runtime_error("File Not Found: " + t_filename),
|
: std::runtime_error("File Not Found: " + t_filename)
|
||||||
filename(t_filename)
|
, filename(t_filename) {
|
||||||
{ }
|
}
|
||||||
|
|
||||||
file_not_found_error(const file_not_found_error &) = default;
|
file_not_found_error(const file_not_found_error &) = default;
|
||||||
~file_not_found_error() noexcept override = default;
|
~file_not_found_error() noexcept override = default;
|
||||||
@ -516,258 +493,204 @@ namespace chaiscript
|
|||||||
std::string filename;
|
std::string filename;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
} // namespace exception
|
||||||
|
|
||||||
|
|
||||||
/// \brief Struct that doubles as both a parser ast_node and an AST node.
|
/// \brief Struct that doubles as both a parser ast_node and an AST node.
|
||||||
struct AST_Node {
|
struct AST_Node {
|
||||||
public:
|
public:
|
||||||
const AST_Node_Type identifier;
|
|
||||||
const std::string text;
|
|
||||||
Parse_Location location;
|
|
||||||
|
|
||||||
const std::string &filename() const noexcept {
|
|
||||||
return *location.filename;
|
|
||||||
}
|
|
||||||
|
|
||||||
const File_Position &start() const noexcept {
|
|
||||||
return location.start;
|
|
||||||
}
|
|
||||||
|
|
||||||
const File_Position &end() const noexcept {
|
|
||||||
return location.end;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string pretty_print() const
|
|
||||||
{
|
|
||||||
std::ostringstream oss;
|
|
||||||
|
|
||||||
oss << text;
|
|
||||||
|
|
||||||
for (auto & elem : get_children()) {
|
|
||||||
oss << elem.get().pretty_print() << ' ';
|
|
||||||
}
|
|
||||||
|
|
||||||
return oss.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
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';
|
|
||||||
|
|
||||||
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 &) {
|
|
||||||
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;
|
|
||||||
|
|
||||||
|
|
||||||
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))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
struct AST_Node_Trace
|
|
||||||
{
|
|
||||||
const AST_Node_Type identifier;
|
const AST_Node_Type identifier;
|
||||||
const std::string text;
|
const std::string text;
|
||||||
Parse_Location location;
|
Parse_Location location;
|
||||||
|
|
||||||
const std::string &filename() const noexcept {
|
const std::string &filename() const noexcept { return *location.filename; }
|
||||||
return *location.filename;
|
|
||||||
}
|
|
||||||
|
|
||||||
const File_Position &start() const noexcept {
|
const File_Position &start() const noexcept { return location.start; }
|
||||||
return location.start;
|
|
||||||
}
|
|
||||||
|
|
||||||
const File_Position &end() const noexcept {
|
const File_Position &end() const noexcept { return location.end; }
|
||||||
return location.end;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string pretty_print() const
|
std::string pretty_print() const {
|
||||||
{
|
|
||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
|
|
||||||
oss << text;
|
oss << text;
|
||||||
|
|
||||||
for (const auto & elem : children) {
|
for (auto &elem : get_children()) {
|
||||||
|
oss << elem.get().pretty_print() << ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
return oss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
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';
|
||||||
|
|
||||||
|
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 &) {
|
||||||
|
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;
|
||||||
|
|
||||||
|
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)) {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
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 File_Position &start() const noexcept { return location.start; }
|
||||||
|
|
||||||
|
const File_Position &end() const noexcept { return location.end; }
|
||||||
|
|
||||||
|
std::string pretty_print() const {
|
||||||
|
std::ostringstream oss;
|
||||||
|
|
||||||
|
oss << text;
|
||||||
|
|
||||||
|
for (const auto &elem : children) {
|
||||||
oss << elem.pretty_print() << ' ';
|
oss << elem.pretty_print() << ' ';
|
||||||
}
|
}
|
||||||
|
|
||||||
return oss.str();
|
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();
|
const auto node_children = node.get_children();
|
||||||
return std::vector<AST_Node_Trace>(node_children.begin(), node_children.end());
|
return std::vector<AST_Node_Trace>(node_children.begin(), node_children.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
AST_Node_Trace(const AST_Node &node)
|
AST_Node_Trace(const AST_Node &node)
|
||||||
: identifier(node.identifier), text(node.text),
|
: identifier(node.identifier)
|
||||||
location(node.location), children(get_children(node))
|
, text(node.text)
|
||||||
{
|
, location(node.location)
|
||||||
|
, children(get_children(node)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::vector<AST_Node_Trace> children;
|
std::vector<AST_Node_Trace> children;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace parser {
|
namespace parser {
|
||||||
class ChaiScript_Parser_Base
|
class ChaiScript_Parser_Base {
|
||||||
{
|
public:
|
||||||
public:
|
virtual AST_NodePtr parse(const std::string &t_input, const std::string &t_fname) = 0;
|
||||||
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;
|
||||||
virtual void debug_print(const AST_Node &t, std::string prepend = "") const = 0;
|
virtual void *get_tracer_ptr() = 0;
|
||||||
virtual void *get_tracer_ptr() = 0;
|
virtual ~ChaiScript_Parser_Base() = default;
|
||||||
virtual ~ChaiScript_Parser_Base() = default;
|
ChaiScript_Parser_Base() = default;
|
||||||
ChaiScript_Parser_Base() = default;
|
ChaiScript_Parser_Base(ChaiScript_Parser_Base &&) = default;
|
||||||
ChaiScript_Parser_Base(ChaiScript_Parser_Base &&) = default;
|
ChaiScript_Parser_Base &operator=(ChaiScript_Parser_Base &&) = delete;
|
||||||
ChaiScript_Parser_Base &operator=(ChaiScript_Parser_Base &&) = delete;
|
ChaiScript_Parser_Base &operator=(const ChaiScript_Parser_Base &&) = delete;
|
||||||
ChaiScript_Parser_Base &operator=(const ChaiScript_Parser_Base &&) = delete;
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T &get_tracer() noexcept
|
T &get_tracer() noexcept {
|
||||||
{
|
// to do type check this somehow?
|
||||||
// to do type check this somehow?
|
return *static_cast<T *>(get_tracer_ptr());
|
||||||
return *static_cast<T*>(get_tracer_ptr());
|
}
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
ChaiScript_Parser_Base(const ChaiScript_Parser_Base &) = default;
|
ChaiScript_Parser_Base(const ChaiScript_Parser_Base &) = default;
|
||||||
};
|
};
|
||||||
}
|
} // namespace parser
|
||||||
|
|
||||||
namespace eval
|
namespace eval {
|
||||||
{
|
namespace detail {
|
||||||
namespace detail
|
|
||||||
{
|
|
||||||
/// Special type for returned values
|
/// Special type for returned values
|
||||||
struct Return_Value {
|
struct Return_Value {
|
||||||
Boxed_Value retval;
|
Boxed_Value retval;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/// Special type indicating a call to 'break'
|
/// Special type indicating a call to 'break'
|
||||||
struct Break_Loop {
|
struct Break_Loop {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/// Special type indicating a call to 'continue'
|
/// Special type indicating a call to 'continue'
|
||||||
struct Continue_Loop {
|
struct Continue_Loop {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/// Creates a new scope then pops it on destruction
|
/// 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(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(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)
|
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());
|
m_ds->new_scope(m_ds.stack_holder());
|
||||||
}
|
}
|
||||||
|
|
||||||
~Scope_Push_Pop()
|
~Scope_Push_Pop() { m_ds->pop_scope(m_ds.stack_holder()); }
|
||||||
{
|
|
||||||
m_ds->pop_scope(m_ds.stack_holder());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
private:
|
||||||
private:
|
const chaiscript::detail::Dispatch_State &m_ds;
|
||||||
const chaiscript::detail::Dispatch_State &m_ds;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Creates a new function call and pops it on destruction
|
/// 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(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(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)
|
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());
|
m_ds->new_function_call(m_ds.stack_holder(), m_ds.conversion_saves());
|
||||||
}
|
}
|
||||||
|
|
||||||
~Function_Push_Pop()
|
~Function_Push_Pop() { m_ds->pop_function_call(m_ds.stack_holder(), m_ds.conversion_saves()); }
|
||||||
{
|
|
||||||
m_ds->pop_function_call(m_ds.stack_holder(), m_ds.conversion_saves());
|
|
||||||
}
|
|
||||||
|
|
||||||
void save_params(const Function_Params &t_params)
|
void save_params(const Function_Params &t_params) { m_ds->save_function_params(t_params); }
|
||||||
{
|
|
||||||
m_ds->save_function_params(t_params);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
private:
|
||||||
private:
|
const chaiscript::detail::Dispatch_State &m_ds;
|
||||||
const chaiscript::detail::Dispatch_State &m_ds;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Creates a new scope then pops it on destruction
|
/// 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(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(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)
|
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());
|
m_ds->new_stack(m_ds.stack_holder());
|
||||||
}
|
}
|
||||||
|
|
||||||
~Stack_Push_Pop()
|
~Stack_Push_Pop() { m_ds->pop_stack(m_ds.stack_holder()); }
|
||||||
{
|
|
||||||
m_ds->pop_stack(m_ds.stack_holder());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
private:
|
||||||
private:
|
const chaiscript::detail::Dispatch_State &m_ds;
|
||||||
const chaiscript::detail::Dispatch_State &m_ds;
|
|
||||||
};
|
};
|
||||||
}
|
} // namespace detail
|
||||||
}
|
} // namespace eval
|
||||||
}
|
} // namespace chaiscript
|
||||||
|
|
||||||
#endif /* _CHAISCRIPT_COMMON_HPP */
|
#endif /* _CHAISCRIPT_COMMON_HPP */
|
||||||
|
|
||||||
|
|||||||
@ -7,11 +7,11 @@
|
|||||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
// 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
|
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||||
|
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_ENGINE_HPP_
|
#ifndef CHAISCRIPT_ENGINE_HPP_
|
||||||
#define CHAISCRIPT_ENGINE_HPP_
|
#define CHAISCRIPT_ENGINE_HPP_
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
#include <cstring>
|
||||||
#include <exception>
|
#include <exception>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
@ -21,15 +21,15 @@
|
|||||||
#include <set>
|
#include <set>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <cstring>
|
|
||||||
|
|
||||||
#include "../chaiscript_defines.hpp"
|
#include "../chaiscript_defines.hpp"
|
||||||
#include "../chaiscript_threading.hpp"
|
#include "../chaiscript_threading.hpp"
|
||||||
#include "../dispatchkit/boxed_cast_helper.hpp"
|
#include "../dispatchkit/boxed_cast_helper.hpp"
|
||||||
#include "../dispatchkit/boxed_value.hpp"
|
#include "../dispatchkit/boxed_value.hpp"
|
||||||
#include "../dispatchkit/dispatchkit.hpp"
|
#include "../dispatchkit/dispatchkit.hpp"
|
||||||
#include "../dispatchkit/type_conversions.hpp"
|
|
||||||
#include "../dispatchkit/proxy_functions.hpp"
|
#include "../dispatchkit/proxy_functions.hpp"
|
||||||
|
#include "../dispatchkit/register_function.hpp"
|
||||||
|
#include "../dispatchkit/type_conversions.hpp"
|
||||||
#include "chaiscript_common.hpp"
|
#include "chaiscript_common.hpp"
|
||||||
|
|
||||||
#if defined(__linux__) || defined(__unix__) || defined(__APPLE__) || defined(__HAIKU__)
|
#if defined(__linux__) || defined(__unix__) || defined(__APPLE__) || defined(__HAIKU__)
|
||||||
@ -50,23 +50,18 @@
|
|||||||
#include "chaiscript_unknown.hpp"
|
#include "chaiscript_unknown.hpp"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#include "../dispatchkit/exception_specification.hpp"
|
#include "../dispatchkit/exception_specification.hpp"
|
||||||
|
|
||||||
namespace chaiscript
|
namespace chaiscript {
|
||||||
{
|
/// Namespace alias to provide cleaner and more explicit syntax to users.
|
||||||
/// Namespace alias to provide cleaner and more explicit syntax to users.
|
using Namespace = dispatch::Dynamic_Object;
|
||||||
using Namespace = dispatch::Dynamic_Object;
|
|
||||||
|
|
||||||
namespace detail
|
namespace detail {
|
||||||
{
|
|
||||||
using Loadable_Module_Ptr = std::shared_ptr<Loadable_Module>;
|
using Loadable_Module_Ptr = std::shared_ptr<Loadable_Module>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// \brief The main object that the ChaiScript user will use.
|
/// \brief The main object that the ChaiScript user will use.
|
||||||
class ChaiScript_Basic {
|
class ChaiScript_Basic {
|
||||||
|
|
||||||
mutable chaiscript::detail::threading::shared_mutex m_mutex;
|
mutable chaiscript::detail::threading::shared_mutex m_mutex;
|
||||||
mutable chaiscript::detail::threading::recursive_mutex m_use_mutex;
|
mutable chaiscript::detail::threading::recursive_mutex m_use_mutex;
|
||||||
|
|
||||||
@ -81,26 +76,21 @@ namespace chaiscript
|
|||||||
|
|
||||||
chaiscript::detail::Dispatch_Engine m_engine;
|
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
|
/// 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 {
|
try {
|
||||||
const auto p = m_parser->parse(t_input, t_filename);
|
const auto p = m_parser->parse(t_input, t_filename);
|
||||||
return p->eval(chaiscript::detail::Dispatch_State(m_engine));
|
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;
|
return rv.retval;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// Evaluates the given file and looks in the 'use' paths
|
/// Evaluates the given file and looks in the 'use' paths
|
||||||
Boxed_Value internal_eval_file(const std::string &t_filename) {
|
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 {
|
try {
|
||||||
const auto appendedpath = path + t_filename;
|
const auto appendedpath = path + t_filename;
|
||||||
return do_eval(load_file(appendedpath), appendedpath, true);
|
return do_eval(load_file(appendedpath), appendedpath, true);
|
||||||
@ -113,11 +103,8 @@ namespace chaiscript
|
|||||||
|
|
||||||
// failed to load by any name
|
// failed to load by any name
|
||||||
throw exception::file_not_found_error(t_filename);
|
throw exception::file_not_found_error(t_filename);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// Evaluates the given string, used during eval() inside of a script
|
/// Evaluates the given string, used during eval() inside of a script
|
||||||
Boxed_Value internal_eval(const std::string &t_e) {
|
Boxed_Value internal_eval(const std::string &t_e) {
|
||||||
try {
|
try {
|
||||||
@ -128,108 +115,94 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the current evaluation m_engine
|
/// Returns the current evaluation m_engine
|
||||||
chaiscript::detail::Dispatch_Engine &get_eval_engine() noexcept {
|
chaiscript::detail::Dispatch_Engine &get_eval_engine() noexcept { return m_engine; }
|
||||||
return m_engine;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Builds all the requirements for ChaiScript, including its evaluator and a run of its prelude.
|
/// 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) {
|
void build_eval_system(const ModulePtr &t_lib, const std::vector<Options> &t_opts) {
|
||||||
if (t_lib)
|
if (t_lib) {
|
||||||
{
|
|
||||||
add(t_lib);
|
add(t_lib);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_engine.add(fun([this](){ m_engine.dump_system(); }), "dump_system");
|
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) { 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, 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 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](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_function_objects(); }), "get_functions");
|
||||||
m_engine.add(fun([this](){ return m_engine.get_scripting_objects(); }), "get_objects");
|
m_engine.add(fun([this]() { return m_engine.get_scripting_objects(); }), "get_objects");
|
||||||
|
|
||||||
m_engine.add(
|
m_engine.add(dispatch::make_dynamic_proxy_function([this](const Function_Params &t_params) { return m_engine.call_exists(t_params); }),
|
||||||
dispatch::make_dynamic_proxy_function(
|
"call_exists");
|
||||||
[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 {
|
||||||
|
Type_Conversions_State s(this->m_engine.conversions(), this->m_engine.conversions().conversion_saves());
|
||||||
|
return t_fun(Function_Params{t_params}, s);
|
||||||
|
}),
|
||||||
|
"call");
|
||||||
|
|
||||||
m_engine.add(fun(
|
m_engine.add(fun([this](const Type_Info &t_ti) { return m_engine.get_type_name(t_ti); }), "name");
|
||||||
[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");
|
|
||||||
|
|
||||||
|
|
||||||
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 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");
|
|
||||||
|
|
||||||
|
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(chaiscript::type_conversion(t_from, t_to, t_func));
|
||||||
|
}),
|
||||||
|
"add_type_conversion");
|
||||||
|
|
||||||
if (std::find(t_opts.begin(), t_opts.end(), Options::No_Load_Modules) == t_opts.end()
|
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())
|
&& 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, 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");
|
||||||
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()
|
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())
|
&& 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 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_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 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 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, 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) { 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_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){ 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){ set_global(t_bv, t_name); }), "set_global");
|
|
||||||
|
|
||||||
// why this unused parameter to Namespace?
|
// 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) {
|
||||||
m_engine.add(fun([this](const std::string& t_namespace_name) { import(t_namespace_name); }), "import");
|
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
|
/// Skip BOM at the beginning of file
|
||||||
static bool skip_bom(std::ifstream &infile) {
|
static bool skip_bom(std::ifstream &infile) {
|
||||||
size_t bytes_needed = 3;
|
size_t bytes_needed = 3;
|
||||||
char buffer[3];
|
char buffer[3];
|
||||||
|
|
||||||
memset(buffer, '\0', bytes_needed);
|
memset(buffer, '\0', bytes_needed);
|
||||||
|
|
||||||
infile.read(buffer, static_cast<std::streamsize>(bytes_needed));
|
infile.read(buffer, static_cast<std::streamsize>(bytes_needed));
|
||||||
|
|
||||||
if ((buffer[0] == '\xef')
|
if ((buffer[0] == '\xef') && (buffer[1] == '\xbb') && (buffer[2] == '\xbf')) {
|
||||||
&& (buffer[1] == '\xbb')
|
infile.seekg(3);
|
||||||
&& (buffer[2] == '\xbf')) {
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
infile.seekg(3);
|
infile.seekg(0);
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
infile.seekg(0);
|
return false;
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Helper function for loading a file
|
/// Helper function for loading a file
|
||||||
static std::string load_file(const std::string &t_filename) {
|
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()) {
|
if (!infile.is_open()) {
|
||||||
throw chaiscript::exception::file_not_found_error(t_filename);
|
throw chaiscript::exception::file_not_found_error(t_filename);
|
||||||
@ -241,12 +214,11 @@ namespace chaiscript
|
|||||||
assert(size >= 0);
|
assert(size >= 0);
|
||||||
|
|
||||||
if (skip_bom(infile)) {
|
if (skip_bom(infile)) {
|
||||||
size-=3; // decrement the BOM size from file size, otherwise we'll get parsing errors
|
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
|
assert(size >= 0); // and check if there's more text
|
||||||
}
|
}
|
||||||
|
|
||||||
if (size == std::streampos(0))
|
if (size == std::streampos(0)) {
|
||||||
{
|
|
||||||
return std::string();
|
return std::string();
|
||||||
} else {
|
} else {
|
||||||
std::vector<char> v(static_cast<size_t>(size));
|
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)
|
std::vector<std::string> ensure_minimum_path_vec(std::vector<std::string> paths) {
|
||||||
{
|
if (paths.empty()) {
|
||||||
if (paths.empty()) { return {""}; }
|
return {""};
|
||||||
else { return paths; }
|
} else {
|
||||||
|
return paths;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/// \brief Constructor for ChaiScript
|
/// \brief Constructor for ChaiScript
|
||||||
/// \param[in] t_lib Standard library to apply to this ChaiScript instance
|
/// \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
|
/// \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_module_paths = {},
|
||||||
std::vector<std::string> t_use_paths = {},
|
std::vector<std::string> t_use_paths = {},
|
||||||
const std::vector<chaiscript::Options> &t_opts = chaiscript::default_options())
|
const std::vector<chaiscript::Options> &t_opts = chaiscript::default_options())
|
||||||
: m_module_paths(ensure_minimum_path_vec(std::move(t_module_paths))),
|
: 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_use_paths(ensure_minimum_path_vec(std::move(t_use_paths)))
|
||||||
m_parser(std::move(parser)),
|
, m_parser(std::move(parser))
|
||||||
m_engine(*m_parser)
|
, m_engine(*m_parser) {
|
||||||
{
|
|
||||||
#if !defined(CHAISCRIPT_NO_DYNLOAD) && defined(_POSIX_VERSION) && !defined(__CYGWIN__)
|
#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
|
// If on Unix, add the path of the current executable to the module search path
|
||||||
// as windows would do
|
// as windows would do
|
||||||
|
|
||||||
union cast_union
|
union cast_union {
|
||||||
{
|
Boxed_Value (ChaiScript_Basic::*in_ptr)(const std::string &);
|
||||||
Boxed_Value (ChaiScript_Basic::*in_ptr)(const std::string&);
|
|
||||||
void *out_ptr;
|
void *out_ptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
Dl_info rInfo;
|
Dl_info rInfo;
|
||||||
memset( &rInfo, 0, sizeof(rInfo) );
|
memset(&rInfo, 0, sizeof(rInfo));
|
||||||
cast_union u;
|
cast_union u;
|
||||||
u.in_ptr = &ChaiScript_Basic::use;
|
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);
|
std::string dllpath(rInfo.dli_fname);
|
||||||
const size_t lastslash = dllpath.rfind('/');
|
const size_t lastslash = dllpath.rfind('/');
|
||||||
if (lastslash != std::string::npos)
|
if (lastslash != std::string::npos) {
|
||||||
{
|
|
||||||
dllpath.erase(lastslash);
|
dllpath.erase(lastslash);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Let's see if this is a link that we should expand
|
// Let's see if this is a link that we should expand
|
||||||
std::vector<char> buf(2048);
|
std::vector<char> buf(2048);
|
||||||
const auto pathlen = readlink(dllpath.c_str(), &buf.front(), buf.size());
|
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));
|
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
|
#endif
|
||||||
build_eval_system(t_lib, t_opts);
|
build_eval_system(t_lib, t_opts);
|
||||||
@ -315,30 +284,28 @@ namespace chaiscript
|
|||||||
|
|
||||||
#ifndef CHAISCRIPT_NO_DYNLOAD
|
#ifndef CHAISCRIPT_NO_DYNLOAD
|
||||||
/// \brief Constructor for ChaiScript.
|
/// \brief Constructor for ChaiScript.
|
||||||
///
|
///
|
||||||
/// This version of the ChaiScript constructor attempts to find the stdlib module to load
|
/// This version of the ChaiScript constructor attempts to find the stdlib module to load
|
||||||
/// at runtime generates an error if it cannot be found.
|
/// at runtime generates an error if it cannot be found.
|
||||||
///
|
///
|
||||||
/// \param[in] t_modulepaths Vector of paths to search when attempting to load a binary module
|
/// \param[in] t_modulepaths Vector of paths to search when attempting to load a binary module
|
||||||
/// \param[in] t_usepaths Vector of paths to search when attempting to "use" an included ChaiScript file
|
/// \param[in] t_usepaths Vector of paths to search when attempting to "use" an included ChaiScript file
|
||||||
explicit ChaiScript_Basic(std::unique_ptr<parser::ChaiScript_Parser_Base> &&parser,
|
explicit ChaiScript_Basic(std::unique_ptr<parser::ChaiScript_Parser_Base> &&parser,
|
||||||
std::vector<std::string> t_module_paths = {},
|
std::vector<std::string> t_module_paths = {},
|
||||||
std::vector<std::string> t_use_paths = {},
|
std::vector<std::string> t_use_paths = {},
|
||||||
const std::vector<chaiscript::Options> &t_opts = chaiscript::default_options())
|
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 {
|
try {
|
||||||
// attempt to load the stdlib
|
// attempt to load the stdlib
|
||||||
load_module("chaiscript_stdlib-" + Build_Info::version());
|
load_module("chaiscript_stdlib-" + Build_Info::version());
|
||||||
} catch (const exception::load_module_error &t_err) {
|
} catch (const exception::load_module_error &t_err) {
|
||||||
std::cout << "An error occured while trying to load the chaiscript standard library.\n"
|
std::cout << "An error occurred while trying to load the chaiscript standard library.\n"
|
||||||
<< "\n"
|
"\n"
|
||||||
<< "You must either provide a standard library, or compile it in.\n"
|
"You must either provide a standard library, or compile it in.\n"
|
||||||
<< "For an example of compiling the standard library in,\n"
|
"For an example of compiling the standard library in,\n"
|
||||||
<< "see: https://gist.github.com/lefticus/9456197\n"
|
"see: https://gist.github.com/lefticus/9456197\n"
|
||||||
<< "Compiling the stdlib in is the recommended and MOST SUPPORTED method.\n"
|
"Compiling the stdlib in is the recommended and MOST SUPPORTED method.\n"
|
||||||
<< "\n"
|
"\n\n"
|
||||||
<< "\n"
|
|
||||||
<< t_err.what();
|
<< t_err.what();
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
@ -347,16 +314,15 @@ namespace chaiscript
|
|||||||
explicit ChaiScript_Basic(std::unique_ptr<parser::ChaiScript_Parser_Base> &&parser,
|
explicit ChaiScript_Basic(std::unique_ptr<parser::ChaiScript_Parser_Base> &&parser,
|
||||||
std::vector<std::string> t_module_paths = {},
|
std::vector<std::string> t_module_paths = {},
|
||||||
std::vector<std::string> t_use_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
|
#endif
|
||||||
|
|
||||||
parser::ChaiScript_Parser_Base &get_parser() noexcept
|
parser::ChaiScript_Parser_Base &get_parser() noexcept {
|
||||||
{
|
|
||||||
return *m_parser;
|
return *m_parser;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Boxed_Value eval(const AST_Node &t_ast)
|
const Boxed_Value eval(const AST_Node &t_ast) {
|
||||||
{
|
|
||||||
try {
|
try {
|
||||||
return t_ast.eval(chaiscript::detail::Dispatch_State(m_engine));
|
return t_ast.eval(chaiscript::detail::Dispatch_State(m_engine));
|
||||||
} catch (const exception::eval_error &t_ee) {
|
} 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");
|
auto ast = m_parser->parse(t_input, "PARSE");
|
||||||
if (t_debug_print) {
|
if (t_debug_print) {
|
||||||
m_parser->debug_print(*ast);
|
m_parser->debug_print(*ast);
|
||||||
@ -373,38 +338,28 @@ namespace chaiscript
|
|||||||
return ast;
|
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>
|
template<typename T>
|
||||||
std::string get_type_name() const
|
std::string get_type_name() const {
|
||||||
{
|
|
||||||
return get_type_name(user_type<T>());
|
return get_type_name(user_type<T>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// \brief Loads and parses a file. If the file is already open, it is not
|
/// \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
|
/// reloaded. The use paths specified at ChaiScript construction time are
|
||||||
/// searched for the requested file.
|
/// searched for the requested file.
|
||||||
///
|
///
|
||||||
/// \param[in] t_filename Filename to load and evaluate
|
/// \param[in] t_filename Filename to load and evaluate
|
||||||
Boxed_Value use(const std::string &t_filename)
|
Boxed_Value use(const std::string &t_filename) {
|
||||||
{
|
for (const auto &path : m_use_paths) {
|
||||||
for (const auto &path : m_use_paths)
|
|
||||||
{
|
|
||||||
const auto appendedpath = path + t_filename;
|
const auto appendedpath = path + t_filename;
|
||||||
try {
|
try {
|
||||||
|
|
||||||
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::recursive_mutex> l(m_use_mutex);
|
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);
|
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l2(m_mutex);
|
||||||
|
|
||||||
Boxed_Value retval;
|
Boxed_Value retval;
|
||||||
|
|
||||||
if (m_used_files.count(appendedpath) == 0)
|
if (m_used_files.count(appendedpath) == 0) {
|
||||||
{
|
|
||||||
l2.unlock();
|
l2.unlock();
|
||||||
retval = eval_file(appendedpath);
|
retval = eval_file(appendedpath);
|
||||||
l2.lock();
|
l2.lock();
|
||||||
@ -430,8 +385,7 @@ namespace chaiscript
|
|||||||
/// \param[in] t_name Name of the value to add
|
/// \param[in] t_name Name of the value to add
|
||||||
/// \throw chaiscript::exception::global_non_const If t_bv is not a constant object
|
/// \throw chaiscript::exception::global_non_const If t_bv is not a constant object
|
||||||
/// \sa Boxed_Value::is_const
|
/// \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);
|
Name_Validator::validate_object_name(t_name);
|
||||||
m_engine.add_global_const(t_bv, t_name);
|
m_engine.add_global_const(t_bv, t_name);
|
||||||
return *this;
|
return *this;
|
||||||
@ -442,15 +396,13 @@ namespace chaiscript
|
|||||||
/// \param[in] t_name Name of the value to add
|
/// \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
|
/// \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 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);
|
Name_Validator::validate_object_name(t_name);
|
||||||
m_engine.add_global(t_bv, t_name);
|
m_engine.add_global(t_bv, t_name);
|
||||||
return *this;
|
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);
|
Name_Validator::validate_object_name(t_name);
|
||||||
m_engine.set_global(t_bv, t_name);
|
m_engine.set_global(t_bv, t_name);
|
||||||
return *this;
|
return *this;
|
||||||
@ -461,8 +413,7 @@ namespace chaiscript
|
|||||||
/// are left out due to performance considerations involved in tracking the state
|
/// are left out due to performance considerations involved in tracking the state
|
||||||
/// \sa ChaiScript::get_state
|
/// \sa ChaiScript::get_state
|
||||||
/// \sa ChaiScript::set_state
|
/// \sa ChaiScript::set_state
|
||||||
struct State
|
struct State {
|
||||||
{
|
|
||||||
std::set<std::string> used_files;
|
std::set<std::string> used_files;
|
||||||
chaiscript::detail::Dispatch_Engine::State engine_state;
|
chaiscript::detail::Dispatch_Engine::State engine_state;
|
||||||
std::set<std::string> active_loaded_modules;
|
std::set<std::string> active_loaded_modules;
|
||||||
@ -481,8 +432,7 @@ namespace chaiscript
|
|||||||
/// chaiscript::ChaiScript chai;
|
/// chaiscript::ChaiScript chai;
|
||||||
/// chaiscript::ChaiScript::State s = chai.get_state(); // represents bootstrapped initial state
|
/// chaiscript::ChaiScript::State s = chai.get_state(); // represents bootstrapped initial state
|
||||||
/// \endcode
|
/// \endcode
|
||||||
State get_state() const
|
State get_state() const {
|
||||||
{
|
|
||||||
chaiscript::detail::threading::lock_guard<chaiscript::detail::threading::recursive_mutex> l(m_use_mutex);
|
chaiscript::detail::threading::lock_guard<chaiscript::detail::threading::recursive_mutex> l(m_use_mutex);
|
||||||
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l2(m_mutex);
|
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l2(m_mutex);
|
||||||
|
|
||||||
@ -507,8 +457,7 @@ namespace chaiscript
|
|||||||
/// chai.add(chaiscript::fun(&somefunction), "somefunction");
|
/// chai.add(chaiscript::fun(&somefunction), "somefunction");
|
||||||
/// chai.set_state(s); // restore initial state, which does not have the recently added "somefunction"
|
/// chai.set_state(s); // restore initial state, which does not have the recently added "somefunction"
|
||||||
/// \endcode
|
/// \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::lock_guard<chaiscript::detail::threading::recursive_mutex> l(m_use_mutex);
|
||||||
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l2(m_mutex);
|
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l2(m_mutex);
|
||||||
|
|
||||||
@ -518,26 +467,20 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// \returns All values in the local thread state, added through the add() function
|
/// \returns All values in the local thread state, added through the add() function
|
||||||
std::map<std::string, Boxed_Value> get_locals() const
|
std::map<std::string, Boxed_Value> get_locals() const { return m_engine.get_locals(); }
|
||||||
{
|
|
||||||
return m_engine.get_locals();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// \brief Sets all of the locals for the current thread state.
|
/// \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
|
/// \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
|
/// 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)
|
void set_locals(const std::map<std::string, Boxed_Value> &t_locals) { m_engine.set_locals(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.
|
/// \brief Adds a type, function or object to ChaiScript. Objects are added to the local thread state.
|
||||||
/// \param[in] t_t Item to add
|
/// \param[in] t_t Item to add
|
||||||
/// \param[in] t_name Name of item to add
|
/// \param[in] t_name Name of item to add
|
||||||
/// \returns Reference to current ChaiScript object
|
/// \returns Reference to current ChaiScript object
|
||||||
///
|
///
|
||||||
/// \b Examples:
|
/// \b Examples:
|
||||||
/// \code
|
/// \code
|
||||||
/// chaiscript::ChaiScript chai;
|
/// chaiscript::ChaiScript chai;
|
||||||
@ -549,8 +492,7 @@ namespace chaiscript
|
|||||||
///
|
///
|
||||||
/// \sa \ref adding_items
|
/// \sa \ref adding_items
|
||||||
template<typename T>
|
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);
|
Name_Validator::validate_object_name(t_name);
|
||||||
m_engine.add(t_t, t_name);
|
m_engine.add(t_t, t_name);
|
||||||
return *this;
|
return *this;
|
||||||
@ -558,15 +500,14 @@ namespace chaiscript
|
|||||||
|
|
||||||
/// \brief Add a new conversion for upcasting to a base class
|
/// \brief Add a new conversion for upcasting to a base class
|
||||||
/// \sa chaiscript::base_class
|
/// \sa chaiscript::base_class
|
||||||
/// \param[in] d Base class / parent class
|
/// \param[in] d Base class / parent class
|
||||||
///
|
///
|
||||||
/// \b Example:
|
/// \b Example:
|
||||||
/// \code
|
/// \code
|
||||||
/// chaiscript::ChaiScript chai;
|
/// chaiscript::ChaiScript chai;
|
||||||
/// chai.add(chaiscript::base_class<std::runtime_error, chaiscript::dispatch_error>());
|
/// chai.add(chaiscript::base_class<std::runtime_error, chaiscript::dispatch_error>());
|
||||||
/// \endcode
|
/// \endcode
|
||||||
ChaiScript_Basic &add(const Type_Conversion &d)
|
ChaiScript_Basic &add(const Type_Conversion &d) {
|
||||||
{
|
|
||||||
m_engine.add(d);
|
m_engine.add(d);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@ -574,8 +515,7 @@ namespace chaiscript
|
|||||||
/// \brief Adds all elements of a module to ChaiScript runtime
|
/// \brief Adds all elements of a module to ChaiScript runtime
|
||||||
/// \param[in] t_p The module to add.
|
/// \param[in] t_p The module to add.
|
||||||
/// \sa chaiscript::Module
|
/// \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());
|
t_p->apply(*this, this->get_eval_engine());
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@ -588,20 +528,18 @@ namespace chaiscript
|
|||||||
/// and with standard prefixes and postfixes: ("lib"|"")\<t_module_name\>(".dll"|".so"|".bundle"|"").
|
/// and with standard prefixes and postfixes: ("lib"|"")\<t_module_name\>(".dll"|".so"|".bundle"|"").
|
||||||
///
|
///
|
||||||
/// Once the file is located, the system looks for the symbol "create_chaiscript_module_\<t_module_name\>".
|
/// Once the file is located, the system looks for the symbol "create_chaiscript_module_\<t_module_name\>".
|
||||||
/// If no file can be found matching the search criteria and containing the appropriate entry point
|
/// If no file can be found matching the search criteria and containing the appropriate entry point
|
||||||
/// (the symbol mentioned above), an exception is thrown.
|
/// (the symbol mentioned above), an exception is thrown.
|
||||||
///
|
///
|
||||||
/// \throw chaiscript::exception::load_module_error In the event that no matching module can be found.
|
/// \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
|
#ifdef CHAISCRIPT_NO_DYNLOAD
|
||||||
throw chaiscript::exception::load_module_error("Loadable module support was disabled (CHAISCRIPT_NO_DYNLOAD)");
|
throw chaiscript::exception::load_module_error("Loadable module support was disabled (CHAISCRIPT_NO_DYNLOAD)");
|
||||||
#else
|
#else
|
||||||
std::vector<exception::load_module_error> errors;
|
std::vector<exception::load_module_error> errors;
|
||||||
std::string version_stripped_name = t_module_name;
|
std::string version_stripped_name = t_module_name;
|
||||||
size_t version_pos = version_stripped_name.find("-" + Build_Info::version());
|
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);
|
version_stripped_name.erase(version_pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -609,12 +547,9 @@ namespace chaiscript
|
|||||||
|
|
||||||
std::vector<std::string> postfixes{".dll", ".so", ".bundle", ""};
|
std::vector<std::string> postfixes{".dll", ".so", ".bundle", ""};
|
||||||
|
|
||||||
for (auto & elem : m_module_paths)
|
for (auto &elem : m_module_paths) {
|
||||||
{
|
for (auto &prefix : prefixes) {
|
||||||
for (auto & prefix : prefixes)
|
for (auto &postfix : postfixes) {
|
||||||
{
|
|
||||||
for (auto & postfix : postfixes)
|
|
||||||
{
|
|
||||||
try {
|
try {
|
||||||
const auto name = elem + prefix + t_module_name + postfix;
|
const auto name = elem + prefix + t_module_name + postfix;
|
||||||
// std::cerr << "trying location: " << name << '\n';
|
// 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
|
/// \param[in] t_filename Ignore normal filename search process and use specific filename
|
||||||
///
|
///
|
||||||
/// \sa ChaiScript::load_module(const std::string &t_module_name)
|
/// \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);
|
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));
|
detail::Loadable_Module_Ptr lm(new detail::Loadable_Module(t_module_name, t_filename));
|
||||||
m_loaded_modules[t_module_name] = lm;
|
m_loaded_modules[t_module_name] = lm;
|
||||||
m_active_loaded_modules.insert(t_module_name);
|
m_active_loaded_modules.insert(t_module_name);
|
||||||
@ -653,20 +586,18 @@ namespace chaiscript
|
|||||||
} else if (m_active_loaded_modules.count(t_module_name) == 0) {
|
} else if (m_active_loaded_modules.count(t_module_name) == 0) {
|
||||||
m_active_loaded_modules.insert(t_module_name);
|
m_active_loaded_modules.insert(t_module_name);
|
||||||
add(m_loaded_modules[t_module_name]->m_moduleptr);
|
add(m_loaded_modules[t_module_name]->m_moduleptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// \brief Evaluates a string. Equivalent to ChaiScript::eval.
|
/// \brief Evaluates a string. Equivalent to ChaiScript::eval.
|
||||||
///
|
///
|
||||||
/// \param[in] t_script Script to execute
|
/// \param[in] t_script Script to execute
|
||||||
/// \param[in] t_handler Optional Exception_Handler used for automatic unboxing of script thrown exceptions
|
/// \param[in] t_handler Optional Exception_Handler used for automatic unboxing of script thrown exceptions
|
||||||
///
|
///
|
||||||
/// \return result of the script execution
|
/// \return result of the script execution
|
||||||
///
|
///
|
||||||
/// \throw chaiscript::exception::eval_error In the case that evaluation fails.
|
/// \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);
|
return eval(t_script, t_handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -679,23 +610,20 @@ namespace chaiscript
|
|||||||
/// in special cases where you are loading a file internally instead of using eval_file
|
/// in special cases where you are loading a file internally instead of using eval_file
|
||||||
///
|
///
|
||||||
/// \return result of the script execution
|
/// \return result of the script execution
|
||||||
///
|
///
|
||||||
/// \throw chaiscript::exception::eval_error In the case that evaluation fails.
|
/// \throw chaiscript::exception::eval_error In the case that evaluation fails.
|
||||||
/// \throw chaiscript::exception::bad_boxed_cast In the case that evaluation succeeds but the result value cannot be converted
|
/// \throw chaiscript::exception::bad_boxed_cast In the case that evaluation succeeds but the result value cannot be converted
|
||||||
/// to the requested type.
|
/// to the requested type.
|
||||||
template<typename T>
|
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));
|
return m_engine.boxed_cast<T>(eval(t_input, t_handler, t_filename));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief casts an object while applying any Dynamic_Conversion available
|
/// \brief casts an object while applying any Dynamic_Conversion available
|
||||||
template<typename Type>
|
template<typename Type>
|
||||||
decltype(auto) boxed_cast(const Boxed_Value &bv) const
|
decltype(auto) boxed_cast(const Boxed_Value &bv) const {
|
||||||
{
|
return (m_engine.boxed_cast<Type>(bv));
|
||||||
return(m_engine.boxed_cast<Type>(bv));
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// \brief Evaluates a string.
|
/// \brief Evaluates a string.
|
||||||
///
|
///
|
||||||
@ -705,10 +633,10 @@ namespace chaiscript
|
|||||||
/// in special cases where you are loading a file internally instead of using eval_file
|
/// in special cases where you are loading a file internally instead of using eval_file
|
||||||
///
|
///
|
||||||
/// \return result of the script execution
|
/// \return result of the script execution
|
||||||
///
|
///
|
||||||
/// \throw exception::eval_error In the case that evaluation fails.
|
/// \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 {
|
try {
|
||||||
return do_eval(t_input, t_filename);
|
return do_eval(t_input, t_filename);
|
||||||
} catch (Boxed_Value &bv) {
|
} catch (Boxed_Value &bv) {
|
||||||
@ -744,39 +672,35 @@ namespace chaiscript
|
|||||||
/// \brief Imports a namespace object into the global scope of this ChaiScript instance.
|
/// \brief Imports a namespace object into the global scope of this ChaiScript instance.
|
||||||
/// \param[in] t_namespace_name Name of the namespace to import.
|
/// \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.
|
/// \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);
|
||||||
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::recursive_mutex> l(m_use_mutex);
|
|
||||||
|
|
||||||
if (m_engine.get_scripting_objects().count(t_namespace_name)) {
|
if (m_engine.get_scripting_objects().count(t_namespace_name)) {
|
||||||
throw std::runtime_error("Namespace: " + t_namespace_name + " was already defined");
|
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);
|
||||||
m_engine.add_global(var(std::ref(m_namespace_generators[t_namespace_name]())), t_namespace_name);
|
} else {
|
||||||
}
|
throw std::runtime_error("No registered namespace: " + t_namespace_name);
|
||||||
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.
|
/// \brief Registers a namespace generator, which delays generation of the namespace until it is imported, saving memory if it is never
|
||||||
/// \param[in] t_namespace_generator Namespace generator function.
|
/// used. \param[in] t_namespace_generator Namespace generator function. \param[in] t_namespace_name Name of the Namespace function
|
||||||
/// \param[in] t_namespace_name Name of the Namespace function being registered.
|
/// being registered. \throw std::runtime_error In the case that the namespace name was already 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) {
|
||||||
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);
|
||||||
{
|
|
||||||
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::recursive_mutex> l(m_use_mutex);
|
|
||||||
|
|
||||||
if (!m_namespace_generators.count(t_namespace_name)) {
|
if (!m_namespace_generators.count(t_namespace_name)) {
|
||||||
// contain the namespace object memory within the m_namespace_generators map
|
// 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; }));
|
m_namespace_generators.emplace(std::make_pair(t_namespace_name, [=, space = Namespace()]() mutable -> Namespace & {
|
||||||
}
|
t_namespace_generator(space);
|
||||||
else {
|
return space;
|
||||||
throw std::runtime_error("Namespace: " + t_namespace_name + " was already registered.");
|
}));
|
||||||
}
|
} else {
|
||||||
|
throw std::runtime_error("Namespace: " + t_namespace_name + " was already registered.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
} // namespace chaiscript
|
||||||
#endif /* CHAISCRIPT_ENGINE_HPP_ */
|
#endif /* CHAISCRIPT_ENGINE_HPP_ */
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -9,76 +9,68 @@
|
|||||||
|
|
||||||
#include "chaiscript_eval.hpp"
|
#include "chaiscript_eval.hpp"
|
||||||
|
|
||||||
|
|
||||||
namespace chaiscript {
|
namespace chaiscript {
|
||||||
namespace optimizer {
|
namespace optimizer {
|
||||||
|
template<typename... T>
|
||||||
template<typename ... T>
|
struct Optimizer : T... {
|
||||||
struct Optimizer : T...
|
|
||||||
{
|
|
||||||
Optimizer() = default;
|
Optimizer() = default;
|
||||||
explicit Optimizer(T ... t)
|
explicit Optimizer(T... t)
|
||||||
: T(std::move(t))...
|
: T(std::move(t))... {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Tracer>
|
template<typename Tracer>
|
||||||
auto optimize(eval::AST_Node_Impl_Ptr<Tracer> p) {
|
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;
|
return p;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
eval::AST_Node_Impl<T> &child_at(eval::AST_Node_Impl<T> &node, const size_t offset) noexcept {
|
eval::AST_Node_Impl<T> &child_at(eval::AST_Node_Impl<T> &node, const size_t offset) noexcept {
|
||||||
if (node.children[offset]->identifier == AST_Node_Type::Compiled) {
|
if (node.children[offset]->identifier == AST_Node_Type::Compiled) {
|
||||||
return *(dynamic_cast<eval::Compiled_AST_Node<T> &>(*node.children[offset]).m_original_node);
|
return *(dynamic_cast<eval::Compiled_AST_Node<T> &>(*node.children[offset]).m_original_node);
|
||||||
} else {
|
} else {
|
||||||
return *node.children[offset];
|
return *node.children[offset];
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
const eval::AST_Node_Impl<T> &child_at(const eval::AST_Node_Impl<T> &node, const size_t offset) noexcept {
|
const eval::AST_Node_Impl<T> &child_at(const eval::AST_Node_Impl<T> &node, const size_t offset) noexcept {
|
||||||
if (node.children[offset]->identifier == AST_Node_Type::Compiled) {
|
if (node.children[offset]->identifier == AST_Node_Type::Compiled) {
|
||||||
return *(dynamic_cast<const eval::Compiled_AST_Node<T> &>(*node.children[offset]).m_original_node);
|
return *(dynamic_cast<const eval::Compiled_AST_Node<T> &>(*node.children[offset]).m_original_node);
|
||||||
} else {
|
} else {
|
||||||
return *node.children[offset];
|
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];
|
|
||||||
} else {
|
|
||||||
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];
|
||||||
|
} else {
|
||||||
|
return node->children[offset];
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
auto child_count(const eval::AST_Node_Impl<T> &node) noexcept {
|
auto child_count(const eval::AST_Node_Impl<T> &node) noexcept {
|
||||||
if (node.identifier == AST_Node_Type::Compiled) {
|
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 {
|
} else {
|
||||||
return node.children.size();
|
return node.children.size();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T, typename Callable>
|
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)
|
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),
|
||||||
return chaiscript::make_unique<eval::AST_Node_Impl<T>, eval::Compiled_AST_Node<T>>(std::move(original_node), std::move(children), std::move(callable));
|
std::move(children),
|
||||||
}
|
std::move(callable));
|
||||||
|
}
|
||||||
|
|
||||||
struct Return {
|
struct Return {
|
||||||
template<typename T>
|
template<typename T>
|
||||||
auto optimize(eval::AST_Node_Impl_Ptr<T> p)
|
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()) {
|
||||||
if ( (p->identifier == AST_Node_Type::Def || p->identifier == AST_Node_Type::Lambda)
|
|
||||||
&& !p->children.empty())
|
|
||||||
{
|
|
||||||
auto &last_child = p->children.back();
|
auto &last_child = p->children.back();
|
||||||
if (last_child->identifier == AST_Node_Type::Block) {
|
if (last_child->identifier == AST_Node_Type::Block) {
|
||||||
auto &block_last_child = last_child->children.back();
|
auto &block_last_child = last_child->children.back();
|
||||||
@ -95,9 +87,9 @@ namespace chaiscript {
|
|||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
bool contains_var_decl_in_scope(const eval::AST_Node_Impl<T> &node) noexcept
|
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
|
||||||
if (node.identifier == AST_Node_Type::Var_Decl || node.identifier == AST_Node_Type::Assign_Decl || node.identifier == AST_Node_Type::Reference) {
|
|| node.identifier == AST_Node_Type::Reference) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,10 +97,8 @@ namespace chaiscript {
|
|||||||
|
|
||||||
for (size_t i = 0; i < num; ++i) {
|
for (size_t i = 0; i < num; ++i) {
|
||||||
const auto &child = child_at(node, i);
|
const auto &child = child_at(node, i);
|
||||||
if (child.identifier != AST_Node_Type::Block
|
if (child.identifier != AST_Node_Type::Block && child.identifier != AST_Node_Type::For
|
||||||
&& child.identifier != AST_Node_Type::For
|
&& child.identifier != AST_Node_Type::Ranged_For && contains_var_decl_in_scope(child)) {
|
||||||
&& child.identifier != AST_Node_Type::Ranged_For
|
|
||||||
&& contains_var_decl_in_scope(child)) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -119,15 +109,14 @@ namespace chaiscript {
|
|||||||
struct Block {
|
struct Block {
|
||||||
template<typename T>
|
template<typename T>
|
||||||
auto optimize(eval::AST_Node_Impl_Ptr<T> node) {
|
auto optimize(eval::AST_Node_Impl_Ptr<T> node) {
|
||||||
if (node->identifier == AST_Node_Type::Block)
|
if (node->identifier == AST_Node_Type::Block) {
|
||||||
{
|
if (!contains_var_decl_in_scope(*node)) {
|
||||||
if (!contains_var_decl_in_scope(*node))
|
|
||||||
{
|
|
||||||
if (node->children.size() == 1) {
|
if (node->children.size() == 1) {
|
||||||
return std::move(node->children[0]);
|
return std::move(node->children[0]);
|
||||||
} else {
|
} 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,
|
||||||
std::move(node->children));
|
node->location,
|
||||||
|
std::move(node->children));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -138,105 +127,91 @@ namespace chaiscript {
|
|||||||
|
|
||||||
struct Dead_Code {
|
struct Dead_Code {
|
||||||
template<typename T>
|
template<typename T>
|
||||||
auto optimize(eval::AST_Node_Impl_Ptr<T> node) {
|
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;
|
||||||
std::vector<size_t> keepers;
|
const auto num_children = node->children.size();
|
||||||
const auto num_children = node->children.size();
|
keepers.reserve(num_children);
|
||||||
keepers.reserve(num_children);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < num_children; ++i) {
|
for (size_t i = 0; i < num_children; ++i) {
|
||||||
const auto &child = *node->children[i];
|
const auto &child = *node->children[i];
|
||||||
if ( (child.identifier != AST_Node_Type::Id
|
if ((child.identifier != AST_Node_Type::Id && child.identifier != AST_Node_Type::Constant
|
||||||
&& child.identifier != AST_Node_Type::Constant
|
&& child.identifier != AST_Node_Type::Noop)
|
||||||
&& child.identifier != AST_Node_Type::Noop)
|
|| i == num_children - 1) {
|
||||||
|| i == num_children - 1) {
|
keepers.push_back(i);
|
||||||
keepers.push_back(i);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (keepers.size() == num_children) {
|
|
||||||
return node;
|
|
||||||
} else {
|
|
||||||
const auto new_children = [&](){
|
|
||||||
std::vector<eval::AST_Node_Impl_Ptr<T>> retval;
|
|
||||||
for (const auto x : keepers)
|
|
||||||
{
|
|
||||||
retval.push_back(std::move(node->children[x]));
|
|
||||||
}
|
|
||||||
return retval;
|
|
||||||
};
|
|
||||||
|
|
||||||
return chaiscript::make_unique<eval::AST_Node_Impl<T>, eval::Block_AST_Node<T>>(node->text, node->location, new_children());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return node;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (keepers.size() == num_children) {
|
||||||
|
return node;
|
||||||
|
} else {
|
||||||
|
const auto new_children = [&]() {
|
||||||
|
std::vector<eval::AST_Node_Impl_Ptr<T>> retval;
|
||||||
|
for (const auto x : keepers) {
|
||||||
|
retval.push_back(std::move(node->children[x]));
|
||||||
|
}
|
||||||
|
return retval;
|
||||||
|
};
|
||||||
|
|
||||||
|
return chaiscript::make_unique<eval::AST_Node_Impl<T>, eval::Block_AST_Node<T>>(node->text, node->location, new_children());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return node;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Unused_Return {
|
struct Unused_Return {
|
||||||
template<typename T>
|
template<typename T>
|
||||||
auto optimize(eval::AST_Node_Impl_Ptr<T> node) {
|
auto optimize(eval::AST_Node_Impl_Ptr<T> node) {
|
||||||
if ((node->identifier == AST_Node_Type::Block
|
if ((node->identifier == AST_Node_Type::Block || node->identifier == AST_Node_Type::Scopeless_Block) && !node->children.empty()) {
|
||||||
|| node->identifier == AST_Node_Type::Scopeless_Block)
|
for (size_t i = 0; i < node->children.size() - 1; ++i) {
|
||||||
&& !node->children.empty())
|
auto child = node->children[i].get();
|
||||||
{
|
if (child->identifier == AST_Node_Type::Fun_Call) {
|
||||||
for (size_t i = 0; i < node->children.size()-1; ++i) {
|
node->children[i]
|
||||||
auto child = node->children[i].get();
|
= chaiscript::make_unique<eval::AST_Node_Impl<T>, eval::Unused_Return_Fun_Call_AST_Node<T>>(child->text,
|
||||||
if (child->identifier == AST_Node_Type::Fun_Call) {
|
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));
|
||||||
std::move(child->children));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else if ((node->identifier == AST_Node_Type::For
|
}
|
||||||
|| node->identifier == AST_Node_Type::While)
|
} else if ((node->identifier == AST_Node_Type::For || node->identifier == AST_Node_Type::While) && child_count(*node) > 0) {
|
||||||
&& child_count(*node) > 0) {
|
auto &child = child_at(*node, child_count(*node) - 1);
|
||||||
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
|
auto num_sub_children = child_count(child);
|
||||||
|| child.identifier == AST_Node_Type::Scopeless_Block)
|
for (size_t i = 0; i < num_sub_children; ++i) {
|
||||||
{
|
auto &sub_child = child_at(child, i);
|
||||||
auto num_sub_children = child_count(child);
|
if (sub_child.identifier == AST_Node_Type::Fun_Call) {
|
||||||
for (size_t i = 0; i < num_sub_children; ++i) {
|
child.children[i] = chaiscript::make_unique<eval::AST_Node_Impl<T>, eval::Unused_Return_Fun_Call_AST_Node<T>>(
|
||||||
auto &sub_child = child_at(child, i);
|
sub_child.text, sub_child.location, std::move(sub_child.children));
|
||||||
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));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return node;
|
|
||||||
}
|
}
|
||||||
|
return node;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Assign_Decl {
|
struct Assign_Decl {
|
||||||
template<typename T>
|
template<typename T>
|
||||||
auto optimize(eval::AST_Node_Impl_Ptr<T> node) {
|
auto optimize(eval::AST_Node_Impl_Ptr<T> node) {
|
||||||
if ((node->identifier == AST_Node_Type::Equation)
|
if ((node->identifier == AST_Node_Type::Equation) && node->text == "=" && node->children.size() == 2
|
||||||
&& node->text == "="
|
&& node->children[0]->identifier == AST_Node_Type::Var_Decl) {
|
||||||
&& node->children.size() == 2
|
|
||||||
&& node->children[0]->identifier == AST_Node_Type::Var_Decl
|
|
||||||
)
|
|
||||||
{
|
|
||||||
std::vector<eval::AST_Node_Impl_Ptr<T>> new_children;
|
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[0]->children[0]));
|
||||||
new_children.push_back(std::move(node->children[1]));
|
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,
|
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;
|
return node;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
struct If {
|
struct If {
|
||||||
template<typename T>
|
template<typename T>
|
||||||
auto optimize(eval::AST_Node_Impl_Ptr<T> node) {
|
auto optimize(eval::AST_Node_Impl_Ptr<T> node) {
|
||||||
if ((node->identifier == AST_Node_Type::If)
|
if ((node->identifier == AST_Node_Type::If) && node->children.size() >= 2 && node->children[0]->identifier == AST_Node_Type::Constant) {
|
||||||
&& 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;
|
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 (condition.get_type_info().bare_equal_type_info(typeid(bool))) {
|
||||||
if (boxed_cast<bool>(condition)) {
|
if (boxed_cast<bool>(condition)) {
|
||||||
@ -254,25 +229,21 @@ namespace chaiscript {
|
|||||||
struct Partial_Fold {
|
struct Partial_Fold {
|
||||||
template<typename T>
|
template<typename T>
|
||||||
auto optimize(eval::AST_Node_Impl_Ptr<T> node) {
|
auto optimize(eval::AST_Node_Impl_Ptr<T> node) {
|
||||||
|
|
||||||
// Fold right side
|
// Fold right side
|
||||||
if (node->identifier == AST_Node_Type::Binary
|
if (node->identifier == AST_Node_Type::Binary && node->children.size() == 2
|
||||||
&& node->children.size() == 2
|
&& node->children[0]->identifier != AST_Node_Type::Constant && node->children[1]->identifier == AST_Node_Type::Constant) {
|
||||||
&& node->children[0]->identifier != AST_Node_Type::Constant
|
|
||||||
&& node->children[1]->identifier == AST_Node_Type::Constant)
|
|
||||||
{
|
|
||||||
try {
|
try {
|
||||||
const auto &oper = node->text;
|
const auto &oper = node->text;
|
||||||
const auto parsed = Operators::to_operator(oper);
|
const auto parsed = Operators::to_operator(oper);
|
||||||
if (parsed != Operators::Opers::invalid) {
|
if (parsed != Operators::Opers::invalid) {
|
||||||
const auto rhs = dynamic_cast<eval::Constant_AST_Node<T> *>(node->children[1].get())->m_value;
|
const auto rhs = dynamic_cast<eval::Constant_AST_Node<T> *>(node->children[1].get())->m_value;
|
||||||
if (rhs.get_type_info().is_arithmetic()) {
|
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,
|
return chaiscript::make_unique<eval::AST_Node_Impl<T>, eval::Fold_Right_Binary_Operator_AST_Node<T>>(
|
||||||
std::move(node->children), rhs);
|
node->text, node->location, std::move(node->children), rhs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (const std::exception &) {
|
} 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 {
|
struct Constant_Fold {
|
||||||
template<typename T>
|
template<typename T>
|
||||||
auto optimize(eval::AST_Node_Impl_Ptr<T> node) {
|
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 {
|
try {
|
||||||
const auto &oper = node->text;
|
const auto &oper = node->text;
|
||||||
const auto parsed = Operators::to_operator(oper, true);
|
const auto parsed = Operators::to_operator(oper, true);
|
||||||
@ -295,39 +262,43 @@ namespace chaiscript {
|
|||||||
const auto match = oper + node->children[0]->text;
|
const auto match = oper + node->children[0]->text;
|
||||||
|
|
||||||
if (parsed != Operators::Opers::invalid && parsed != Operators::Opers::bitwise_and && lhs.get_type_info().is_arithmetic()) {
|
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);
|
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 == "!") {
|
} 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 &) {
|
} 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)
|
} else if ((node->identifier == AST_Node_Type::Logical_And || node->identifier == AST_Node_Type::Logical_Or)
|
||||||
&& node->children.size() == 2
|
&& node->children.size() == 2 && node->children[0]->identifier == AST_Node_Type::Constant
|
||||||
&& node->children[0]->identifier == AST_Node_Type::Constant
|
&& node->children[1]->identifier == AST_Node_Type::Constant) {
|
||||||
&& node->children[1]->identifier == AST_Node_Type::Constant)
|
|
||||||
{
|
|
||||||
try {
|
try {
|
||||||
const auto lhs = dynamic_cast<const eval::Constant_AST_Node<T> &>(*node->children[0]).m_value;
|
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;
|
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))) {
|
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 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] {
|
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); }
|
if (id == AST_Node_Type::Logical_And) {
|
||||||
else { return Boxed_Value(lhs_val || rhs_val); }
|
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 &) {
|
} catch (const std::exception &) {
|
||||||
//failure to fold, that's OK
|
// failure to fold, that's OK
|
||||||
}
|
}
|
||||||
} else if (node->identifier == AST_Node_Type::Binary
|
} else if (node->identifier == AST_Node_Type::Binary && node->children.size() == 2
|
||||||
&& node->children.size() == 2
|
&& node->children[0]->identifier == AST_Node_Type::Constant && node->children[1]->identifier == AST_Node_Type::Constant) {
|
||||||
&& node->children[0]->identifier == AST_Node_Type::Constant
|
|
||||||
&& node->children[1]->identifier == AST_Node_Type::Constant)
|
|
||||||
{
|
|
||||||
try {
|
try {
|
||||||
const auto &oper = node->text;
|
const auto &oper = node->text;
|
||||||
const auto parsed = Operators::to_operator(oper);
|
const auto parsed = Operators::to_operator(oper);
|
||||||
@ -335,28 +306,28 @@ namespace chaiscript {
|
|||||||
const auto lhs = dynamic_cast<const eval::Constant_AST_Node<T> &>(*node->children[0]).m_value;
|
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;
|
const auto rhs = dynamic_cast<const eval::Constant_AST_Node<T> &>(*node->children[1]).m_value;
|
||||||
if (lhs.get_type_info().is_arithmetic() && rhs.get_type_info().is_arithmetic()) {
|
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 val = Boxed_Number::do_oper(parsed, lhs, rhs);
|
||||||
const auto match = node->children[0]->text + " " + oper + " " + node->children[1]->text;
|
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 &) {
|
} 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
|
} else if (node->identifier == AST_Node_Type::Fun_Call && node->children.size() == 2
|
||||||
&& node->children.size() == 2
|
&& node->children[0]->identifier == AST_Node_Type::Id && node->children[1]->identifier == AST_Node_Type::Arg_List
|
||||||
&& node->children[0]->identifier == AST_Node_Type::Id
|
&& node->children[1]->children.size() == 1 && node->children[1]->children[0]->identifier == AST_Node_Type::Constant) {
|
||||||
&& 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;
|
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()) {
|
if (arg.get_type_info().is_arithmetic()) {
|
||||||
const auto &fun_name = node->children[0]->text;
|
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 + ")";
|
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") {
|
if (fun_name == "double") {
|
||||||
@ -370,10 +341,7 @@ namespace chaiscript {
|
|||||||
} else if (fun_name == "size_t") {
|
} else if (fun_name == "size_t") {
|
||||||
return make_constant(Boxed_Number(arg).get_as<size_t>());
|
return make_constant(Boxed_Number(arg).get_as<size_t>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
@ -383,7 +351,6 @@ namespace chaiscript {
|
|||||||
struct For_Loop {
|
struct For_Loop {
|
||||||
template<typename T>
|
template<typename T>
|
||||||
auto optimize(eval::AST_Node_Impl_Ptr<T> for_node) {
|
auto optimize(eval::AST_Node_Impl_Ptr<T> for_node) {
|
||||||
|
|
||||||
if (for_node->identifier != AST_Node_Type::For) {
|
if (for_node->identifier != AST_Node_Type::For) {
|
||||||
return for_node;
|
return for_node;
|
||||||
}
|
}
|
||||||
@ -392,66 +359,55 @@ namespace chaiscript {
|
|||||||
const auto &binary_node = child_at(*for_node, 1);
|
const auto &binary_node = child_at(*for_node, 1);
|
||||||
const auto &prefix_node = child_at(*for_node, 2);
|
const auto &prefix_node = child_at(*for_node, 2);
|
||||||
|
|
||||||
if (child_count(*for_node) == 4
|
if (child_count(*for_node) == 4 && eq_node.identifier == AST_Node_Type::Assign_Decl && child_count(eq_node) == 2
|
||||||
&& eq_node.identifier == AST_Node_Type::Assign_Decl
|
&& child_at(eq_node, 0).identifier == AST_Node_Type::Id && child_at(eq_node, 1).identifier == AST_Node_Type::Constant
|
||||||
&& child_count(eq_node) == 2
|
&& binary_node.identifier == AST_Node_Type::Binary && binary_node.text == "<" && child_count(binary_node) == 2
|
||||||
&& child_at(eq_node, 0).identifier == AST_Node_Type::Id
|
&& child_at(binary_node, 0).identifier == AST_Node_Type::Id && child_at(binary_node, 0).text == child_at(eq_node, 0).text
|
||||||
&& child_at(eq_node, 1).identifier == AST_Node_Type::Constant
|
&& child_at(binary_node, 1).identifier == AST_Node_Type::Constant && prefix_node.identifier == AST_Node_Type::Prefix
|
||||||
&& binary_node.identifier == AST_Node_Type::Binary
|
&& prefix_node.text == "++" && child_count(prefix_node) == 1 && child_at(prefix_node, 0).identifier == AST_Node_Type::Id
|
||||||
&& binary_node.text == "<"
|
&& child_at(prefix_node, 0).text == child_at(eq_node, 0).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 &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 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;
|
const std::string &id = child_at(prefix_node, 0).text;
|
||||||
|
|
||||||
if (begin.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>())) {
|
||||||
&& end.get_type_info().bare_equal(user_type<int>())) {
|
|
||||||
|
|
||||||
const auto start_int = boxed_cast<int>(begin);
|
const auto start_int = boxed_cast<int>(begin);
|
||||||
const auto end_int = boxed_cast<int>(end);
|
const auto end_int = boxed_cast<int>(end);
|
||||||
|
|
||||||
// note that we are moving the last element out, then popping the empty shared_ptr
|
// note that we are moving the last element out, then popping the empty shared_ptr
|
||||||
// from the vector
|
// from the vector
|
||||||
std::vector<eval::AST_Node_Impl_Ptr<T>> body_vector;
|
std::vector<eval::AST_Node_Impl_Ptr<T>> body_vector;
|
||||||
auto body_child = std::move(for_node->children[3]);
|
auto body_child = std::move(for_node->children[3]);
|
||||||
for_node->children.pop_back();
|
for_node->children.pop_back();
|
||||||
body_vector.emplace_back(std::move(body_child));
|
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) {
|
|
||||||
assert(children.size() == 1);
|
|
||||||
chaiscript::eval::detail::Scope_Push_Pop spp(t_ss);
|
|
||||||
|
|
||||||
int i = start_int;
|
return make_compiled_node(std::move(for_node),
|
||||||
t_ss.add_object(id, var(&i));
|
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);
|
||||||
|
|
||||||
try {
|
int i = start_int;
|
||||||
for (; i < end_int; ++i) {
|
t_ss.add_object(id, var(&i));
|
||||||
try {
|
|
||||||
// Body of Loop
|
|
||||||
children[0]->eval(t_ss);
|
|
||||||
} catch (eval::detail::Continue_Loop &) {
|
|
||||||
// we got a continue exception, which means all of the remaining
|
|
||||||
// loop implementation is skipped and we just need to continue to
|
|
||||||
// the next iteration step
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (eval::detail::Break_Loop &) {
|
|
||||||
// loop broken
|
|
||||||
}
|
|
||||||
|
|
||||||
return void_var();
|
try {
|
||||||
}
|
for (; i < end_int; ++i) {
|
||||||
);
|
try {
|
||||||
|
// Body of Loop
|
||||||
|
children[0]->eval(t_ss);
|
||||||
|
} catch (eval::detail::Continue_Loop &) {
|
||||||
|
// we got a continue exception, which means all of the remaining
|
||||||
|
// loop implementation is skipped and we just need to continue to
|
||||||
|
// the next iteration step
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (eval::detail::Break_Loop &) {
|
||||||
|
// loop broken
|
||||||
|
}
|
||||||
|
|
||||||
|
return void_var();
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
return for_node;
|
return for_node;
|
||||||
}
|
}
|
||||||
@ -461,12 +417,17 @@ namespace chaiscript {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
using Optimizer_Default = Optimizer<optimizer::Partial_Fold, optimizer::Unused_Return, optimizer::Constant_Fold,
|
using Optimizer_Default = Optimizer<optimizer::Partial_Fold,
|
||||||
optimizer::If, optimizer::Return, optimizer::Dead_Code, optimizer::Block, optimizer::For_Loop, optimizer::Assign_Decl>;
|
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
|
#endif
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -7,62 +7,47 @@
|
|||||||
#ifndef CHAISCRIPT_POSIX_HPP_
|
#ifndef CHAISCRIPT_POSIX_HPP_
|
||||||
#define CHAISCRIPT_POSIX_HPP_
|
#define CHAISCRIPT_POSIX_HPP_
|
||||||
|
|
||||||
namespace chaiscript
|
namespace chaiscript::detail {
|
||||||
{
|
struct Loadable_Module {
|
||||||
namespace detail
|
struct DLModule {
|
||||||
{
|
explicit DLModule(const std::string &t_filename)
|
||||||
struct Loadable_Module
|
: m_data(dlopen(t_filename.c_str(), RTLD_NOW)) {
|
||||||
{
|
if (m_data == nullptr) {
|
||||||
struct DLModule
|
throw chaiscript::exception::load_module_error(dlerror());
|
||||||
{
|
|
||||||
explicit DLModule(const std::string &t_filename)
|
|
||||||
: m_data(dlopen(t_filename.c_str(), RTLD_NOW))
|
|
||||||
{
|
|
||||||
if (m_data == nullptr)
|
|
||||||
{
|
|
||||||
throw chaiscript::exception::load_module_error(dlerror());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DLModule(DLModule &&) = default;
|
|
||||||
DLModule &operator=(DLModule &&) = default;
|
|
||||||
DLModule(const DLModule &) = delete;
|
|
||||||
DLModule &operator=(const DLModule &) = delete;
|
|
||||||
|
|
||||||
~DLModule()
|
|
||||||
{
|
|
||||||
dlclose(m_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
void *m_data;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
throw chaiscript::exception::load_module_error(dlerror());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
T m_symbol;
|
|
||||||
};
|
|
||||||
|
|
||||||
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())
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DLModule m_dlmodule;
|
DLModule(DLModule &&) = default;
|
||||||
DLSym<Create_Module_Func> m_func;
|
DLModule &operator=(DLModule &&) = default;
|
||||||
ModulePtr m_moduleptr;
|
DLModule(const DLModule &) = delete;
|
||||||
};
|
DLModule &operator=(const DLModule &) = delete;
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
~DLModule() { dlclose(m_data); }
|
||||||
|
|
||||||
|
void *m_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
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) {
|
||||||
|
throw chaiscript::exception::load_module_error(dlerror());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
T m_symbol;
|
||||||
|
};
|
||||||
|
|
||||||
|
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()) {
|
||||||
|
}
|
||||||
|
|
||||||
|
DLModule m_dlmodule;
|
||||||
|
DLSym<Create_Module_Func> m_func;
|
||||||
|
ModulePtr m_moduleptr;
|
||||||
|
};
|
||||||
|
} // namespace chaiscript::detail
|
||||||
|
#endif
|
||||||
|
|||||||
@ -8,8 +8,9 @@
|
|||||||
#define CHAISCRIPT_PRELUDE_HPP_
|
#define CHAISCRIPT_PRELUDE_HPP_
|
||||||
|
|
||||||
namespace chaiscript {
|
namespace chaiscript {
|
||||||
struct ChaiScript_Prelude {
|
struct ChaiScript_Prelude {
|
||||||
static std::string chaiscript_prelude() { return R"chaiscript(
|
static std::string chaiscript_prelude() {
|
||||||
|
return R"chaiscript(
|
||||||
|
|
||||||
def lt(l, r) {
|
def lt(l, r) {
|
||||||
if (call_exists(`<`, l, r)) {
|
if (call_exists(`<`, l, r)) {
|
||||||
@ -554,9 +555,8 @@ def find(container, value) {
|
|||||||
|
|
||||||
|
|
||||||
)chaiscript";
|
)chaiscript";
|
||||||
}
|
}
|
||||||
|
};
|
||||||
};
|
} // namespace chaiscript
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* CHAISCRIPT_PRELUDE_HPP_ */
|
#endif /* CHAISCRIPT_PRELUDE_HPP_ */
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -7,40 +7,31 @@
|
|||||||
#ifndef CHAISCRIPT_TRACER_HPP_
|
#ifndef CHAISCRIPT_TRACER_HPP_
|
||||||
#define CHAISCRIPT_TRACER_HPP_
|
#define CHAISCRIPT_TRACER_HPP_
|
||||||
|
|
||||||
namespace chaiscript {
|
namespace chaiscript::eval {
|
||||||
namespace eval {
|
struct Noop_Tracer_Detail {
|
||||||
|
template<typename T>
|
||||||
|
constexpr void trace(const chaiscript::detail::Dispatch_State &, const AST_Node_Impl<T> *) noexcept {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename... T>
|
||||||
|
struct Tracer : T... {
|
||||||
|
Tracer() = default;
|
||||||
|
constexpr explicit Tracer(T... t)
|
||||||
|
: T(std::move(t))... {
|
||||||
|
}
|
||||||
|
|
||||||
struct Noop_Tracer_Detail
|
void do_trace(const chaiscript::detail::Dispatch_State &ds, const AST_Node_Impl<Tracer<T...>> *node) {
|
||||||
{
|
(static_cast<T &>(*this).trace(ds, node), ...);
|
||||||
template<typename T>
|
}
|
||||||
constexpr void trace(const chaiscript::detail::Dispatch_State &, const AST_Node_Impl<T> *) noexcept
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename ... T>
|
static void trace(const chaiscript::detail::Dispatch_State &ds, const AST_Node_Impl<Tracer<T...>> *node) {
|
||||||
struct Tracer : T...
|
ds->get_parser().get_tracer<Tracer<T...>>().do_trace(ds, node);
|
||||||
{
|
}
|
||||||
Tracer() = default;
|
};
|
||||||
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) {
|
using Noop_Tracer = Tracer<Noop_Tracer_Detail>;
|
||||||
(static_cast<T&>(*this).trace(ds, node), ... );
|
|
||||||
}
|
|
||||||
|
|
||||||
static void trace(const chaiscript::detail::Dispatch_State &ds, const AST_Node_Impl<Tracer<T...>> *node) {
|
} // namespace chaiscript::eval
|
||||||
ds->get_parser().get_tracer<Tracer<T...>>().do_trace(ds, node);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
using Noop_Tracer = Tracer<Noop_Tracer_Detail>;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@ -7,15 +7,10 @@
|
|||||||
#ifndef CHAISCRIPT_UNKNOWN_HPP_
|
#ifndef CHAISCRIPT_UNKNOWN_HPP_
|
||||||
#define CHAISCRIPT_UNKNOWN_HPP_
|
#define CHAISCRIPT_UNKNOWN_HPP_
|
||||||
|
|
||||||
|
namespace chaiscript {
|
||||||
namespace chaiscript
|
namespace detail {
|
||||||
{
|
struct Loadable_Module {
|
||||||
namespace detail
|
Loadable_Module(const std::string &, const std::string &) {
|
||||||
{
|
|
||||||
struct Loadable_Module
|
|
||||||
{
|
|
||||||
Loadable_Module(const std::string &, const std::string &)
|
|
||||||
{
|
|
||||||
#ifdef CHAISCRIPT_NO_DYNLOAD
|
#ifdef CHAISCRIPT_NO_DYNLOAD
|
||||||
throw chaiscript::exception::load_module_error("Loadable module support was disabled (CHAISCRIPT_NO_DYNLOAD)");
|
throw chaiscript::exception::load_module_error("Loadable module support was disabled (CHAISCRIPT_NO_DYNLOAD)");
|
||||||
#else
|
#else
|
||||||
@ -25,7 +20,6 @@ namespace chaiscript
|
|||||||
|
|
||||||
ModulePtr m_moduleptr;
|
ModulePtr m_moduleptr;
|
||||||
};
|
};
|
||||||
}
|
} // namespace detail
|
||||||
}
|
} // namespace chaiscript
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@ -17,41 +17,32 @@
|
|||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
namespace chaiscript {
|
||||||
namespace chaiscript
|
namespace detail {
|
||||||
{
|
struct Loadable_Module {
|
||||||
namespace detail
|
|
||||||
{
|
|
||||||
struct Loadable_Module
|
|
||||||
{
|
|
||||||
template<typename T>
|
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());
|
||||||
return std::wstring(t_str.begin(), t_str.end());
|
}
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
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());
|
||||||
return std::string(t_str.begin(), t_str.end());
|
}
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(_UNICODE) || defined(UNICODE)
|
#if defined(_UNICODE) || defined(UNICODE)
|
||||||
template<typename T>
|
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);
|
||||||
return to_wstring(t_str);
|
}
|
||||||
}
|
|
||||||
#else
|
#else
|
||||||
template<typename T>
|
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);
|
||||||
return to_string(t_str);
|
}
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static std::string get_error_message(DWORD t_err)
|
static std::string get_error_message(DWORD t_err) {
|
||||||
{
|
|
||||||
using StringType = LPTSTR;
|
using StringType = LPTSTR;
|
||||||
|
|
||||||
#if defined(_UNICODE) || defined(UNICODE)
|
#if defined(_UNICODE) || defined(UNICODE)
|
||||||
@ -61,16 +52,15 @@ namespace chaiscript
|
|||||||
#endif
|
#endif
|
||||||
StringType lpMsgBuf = nullptr;
|
StringType lpMsgBuf = nullptr;
|
||||||
|
|
||||||
if (FormatMessage(
|
if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||||
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
nullptr,
|
||||||
FORMAT_MESSAGE_FROM_SYSTEM |
|
t_err,
|
||||||
FORMAT_MESSAGE_IGNORE_INSERTS,
|
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||||
nullptr,
|
reinterpret_cast<StringType>(&lpMsgBuf),
|
||||||
t_err,
|
0,
|
||||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
nullptr)
|
||||||
reinterpret_cast<StringType>(&lpMsgBuf),
|
!= 0
|
||||||
0, nullptr ) != 0 && lpMsgBuf)
|
&& lpMsgBuf) {
|
||||||
{
|
|
||||||
retval = lpMsgBuf;
|
retval = lpMsgBuf;
|
||||||
LocalFree(lpMsgBuf);
|
LocalFree(lpMsgBuf);
|
||||||
}
|
}
|
||||||
@ -78,13 +68,10 @@ namespace chaiscript
|
|||||||
return to_string(retval);
|
return to_string(retval);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct DLModule
|
struct DLModule {
|
||||||
{
|
|
||||||
explicit DLModule(const std::string &t_filename)
|
explicit DLModule(const std::string &t_filename)
|
||||||
: m_data(LoadLibrary(to_proper_string(t_filename).c_str()))
|
: m_data(LoadLibrary(to_proper_string(t_filename).c_str())) {
|
||||||
{
|
if (!m_data) {
|
||||||
if (!m_data)
|
|
||||||
{
|
|
||||||
throw chaiscript::exception::load_module_error(get_error_message(GetLastError()));
|
throw chaiscript::exception::load_module_error(get_error_message(GetLastError()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -94,40 +81,33 @@ namespace chaiscript
|
|||||||
DLModule(const DLModule &) = delete;
|
DLModule(const DLModule &) = delete;
|
||||||
DLModule &operator=(const DLModule &) = delete;
|
DLModule &operator=(const DLModule &) = delete;
|
||||||
|
|
||||||
~DLModule()
|
~DLModule() { FreeLibrary(m_data); }
|
||||||
{
|
|
||||||
FreeLibrary(m_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
HMODULE m_data;
|
HMODULE m_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct DLSym
|
struct DLSym {
|
||||||
{
|
DLSym(DLModule &t_mod, const std::string &t_symbol)
|
||||||
DLSym(DLModule &t_mod, const std::string &t_symbol)
|
: m_symbol(reinterpret_cast<T>(GetProcAddress(t_mod.m_data, t_symbol.c_str()))) {
|
||||||
: 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()));
|
||||||
if (!m_symbol)
|
|
||||||
{
|
|
||||||
throw chaiscript::exception::load_module_error(get_error_message(GetLastError()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
T m_symbol;
|
T m_symbol;
|
||||||
};
|
};
|
||||||
|
|
||||||
Loadable_Module(const std::string &t_module_name, const std::string &t_filename)
|
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_dlmodule(t_filename)
|
||||||
m_moduleptr(m_func.m_symbol())
|
, m_func(m_dlmodule, "create_chaiscript_module_" + t_module_name)
|
||||||
{
|
, m_moduleptr(m_func.m_symbol()) {
|
||||||
}
|
}
|
||||||
|
|
||||||
DLModule m_dlmodule;
|
DLModule m_dlmodule;
|
||||||
DLSym<Create_Module_Func> m_func;
|
DLSym<Create_Module_Func> m_func;
|
||||||
ModulePtr m_moduleptr;
|
ModulePtr m_moduleptr;
|
||||||
};
|
};
|
||||||
}
|
} // namespace detail
|
||||||
}
|
} // namespace chaiscript
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@ -7,19 +7,11 @@
|
|||||||
#ifndef CHAISCRIPT_UTILITY_FNV1A_HPP_
|
#ifndef CHAISCRIPT_UTILITY_FNV1A_HPP_
|
||||||
#define CHAISCRIPT_UTILITY_FNV1A_HPP_
|
#define CHAISCRIPT_UTILITY_FNV1A_HPP_
|
||||||
|
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
#include "../chaiscript_defines.hpp"
|
#include "../chaiscript_defines.hpp"
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
namespace chaiscript {
|
||||||
namespace chaiscript
|
namespace utility {
|
||||||
{
|
|
||||||
|
|
||||||
|
|
||||||
namespace utility
|
|
||||||
{
|
|
||||||
|
|
||||||
|
|
||||||
static constexpr std::uint32_t fnv1a_32(const char *s, std::uint32_t h = 0x811c9dc5) {
|
static constexpr std::uint32_t fnv1a_32(const char *s, std::uint32_t h = 0x811c9dc5) {
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
#pragma GCC diagnostic push
|
#pragma GCC diagnostic push
|
||||||
@ -30,7 +22,7 @@ namespace chaiscript
|
|||||||
#pragma warning(push)
|
#pragma warning(push)
|
||||||
#pragma warning(disable : 4307)
|
#pragma warning(disable : 4307)
|
||||||
#endif
|
#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
|
#ifdef CHAISCRIPT_MSVC
|
||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
#endif
|
#endif
|
||||||
@ -38,13 +30,9 @@ namespace chaiscript
|
|||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
#pragma GCC diagnostic pop
|
#pragma GCC diagnostic pop
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace utility
|
||||||
}
|
} // namespace chaiscript
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -7,18 +7,14 @@
|
|||||||
#ifndef CHAISCRIPT_UTILITY_FNV1A_HPP_
|
#ifndef CHAISCRIPT_UTILITY_FNV1A_HPP_
|
||||||
#define CHAISCRIPT_UTILITY_FNV1A_HPP_
|
#define CHAISCRIPT_UTILITY_FNV1A_HPP_
|
||||||
|
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
#include "../chaiscript_defines.hpp"
|
#include "../chaiscript_defines.hpp"
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
namespace chaiscript {
|
||||||
namespace chaiscript
|
namespace utility {
|
||||||
{
|
|
||||||
namespace utility
|
|
||||||
{
|
|
||||||
namespace fnv1a {
|
namespace fnv1a {
|
||||||
template<typename Itr>
|
template<typename Itr>
|
||||||
static constexpr std::uint32_t hash(Itr begin, Itr end) noexcept {
|
static constexpr std::uint32_t hash(Itr begin, Itr end) noexcept {
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
#pragma GCC diagnostic push
|
#pragma GCC diagnostic push
|
||||||
#pragma GCC diagnostic ignored "-Wsign-conversion"
|
#pragma GCC diagnostic ignored "-Wsign-conversion"
|
||||||
@ -28,13 +24,13 @@ namespace chaiscript
|
|||||||
#pragma warning(push)
|
#pragma warning(push)
|
||||||
#pragma warning(disable : 4307)
|
#pragma warning(disable : 4307)
|
||||||
#endif
|
#endif
|
||||||
std::uint32_t h = 0x811c9dc5;
|
std::uint32_t h = 0x811c9dc5;
|
||||||
|
|
||||||
while (begin != end) {
|
while (begin != end) {
|
||||||
h = (h ^ (*begin)) * 0x01000193;
|
h = (h ^ (*begin)) * 0x01000193;
|
||||||
++begin;
|
++begin;
|
||||||
}
|
}
|
||||||
return h;
|
return h;
|
||||||
|
|
||||||
#ifdef CHAISCRIPT_MSVC
|
#ifdef CHAISCRIPT_MSVC
|
||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
@ -43,14 +39,12 @@ namespace chaiscript
|
|||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
#pragma GCC diagnostic pop
|
#pragma GCC diagnostic pop
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<size_t N>
|
template<size_t N>
|
||||||
static constexpr std::uint32_t hash(const char (&str)[N]) noexcept {
|
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 {
|
static constexpr std::uint32_t hash(std::string_view sv) noexcept {
|
||||||
return hash(sv.begin(), sv.end());
|
return hash(sv.begin(), sv.end());
|
||||||
@ -59,30 +53,30 @@ namespace chaiscript
|
|||||||
static inline std::uint32_t hash(const std::string &s) noexcept {
|
static inline std::uint32_t hash(const std::string &s) noexcept {
|
||||||
return hash(s.begin(), s.end());
|
return hash(s.begin(), s.end());
|
||||||
}
|
}
|
||||||
}
|
} // namespace fnv1a
|
||||||
|
|
||||||
namespace jenkins_one_at_a_time {
|
namespace jenkins_one_at_a_time {
|
||||||
template<typename Itr>
|
template<typename Itr>
|
||||||
static constexpr std::uint32_t hash(Itr begin, Itr end) noexcept {
|
static constexpr std::uint32_t hash(Itr begin, Itr end) noexcept {
|
||||||
std::uint32_t hash = 0;
|
std::uint32_t hash = 0;
|
||||||
|
|
||||||
while (begin != end) {
|
while (begin != end) {
|
||||||
hash += std::uint32_t(*begin);
|
hash += std::uint32_t(*begin);
|
||||||
hash += hash << 10;
|
hash += hash << 10;
|
||||||
hash ^= hash >> 6;
|
hash ^= hash >> 6;
|
||||||
++begin;
|
++begin;
|
||||||
}
|
|
||||||
|
|
||||||
hash += hash << 3;
|
|
||||||
hash ^= hash >> 11;
|
|
||||||
hash += hash << 15;
|
|
||||||
return hash;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hash += hash << 3;
|
||||||
|
hash ^= hash >> 11;
|
||||||
|
hash += hash << 15;
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
template<size_t N>
|
template<size_t N>
|
||||||
static constexpr std::uint32_t hash(const char (&str)[N]) noexcept {
|
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 {
|
static constexpr std::uint32_t hash(std::string_view sv) noexcept {
|
||||||
return hash(sv.begin(), sv.end());
|
return hash(sv.begin(), sv.end());
|
||||||
@ -91,11 +85,10 @@ namespace chaiscript
|
|||||||
static inline std::uint32_t hash(const std::string &s) noexcept {
|
static inline std::uint32_t hash(const std::string &s) noexcept {
|
||||||
return hash(s.begin(), s.end());
|
return hash(s.begin(), s.end());
|
||||||
}
|
}
|
||||||
}
|
} // namespace jenkins_one_at_a_time
|
||||||
|
|
||||||
using fnv1a::hash;
|
using fnv1a::hash;
|
||||||
}
|
} // namespace utility
|
||||||
|
} // namespace chaiscript
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -3,154 +3,129 @@
|
|||||||
|
|
||||||
#include "json.hpp"
|
#include "json.hpp"
|
||||||
|
|
||||||
namespace chaiscript
|
namespace chaiscript {
|
||||||
{
|
class json_wrap {
|
||||||
class json_wrap
|
public:
|
||||||
{
|
static Module &library(Module &m) {
|
||||||
public:
|
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");
|
||||||
|
|
||||||
static Module& library(Module& m)
|
return m;
|
||||||
{
|
}
|
||||||
|
|
||||||
m.add(chaiscript::fun([](const std::string &t_str) { return from_json(t_str); }), "from_json");
|
private:
|
||||||
m.add(chaiscript::fun(&json_wrap::to_json), "to_json");
|
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: {
|
||||||
|
std::map<std::string, Boxed_Value> m;
|
||||||
|
|
||||||
return m;
|
for (const auto &p : t_json.object_range()) {
|
||||||
|
m.insert(std::make_pair(p.first, from_json(p.second)));
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
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:
|
|
||||||
{
|
|
||||||
std::map<std::string, Boxed_Value> m;
|
|
||||||
|
|
||||||
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:
|
|
||||||
{
|
|
||||||
std::vector<Boxed_Value> vec;
|
|
||||||
|
|
||||||
for (const auto &p : t_json.array_range())
|
|
||||||
{
|
|
||||||
vec.emplace_back(from_json(p));
|
|
||||||
}
|
|
||||||
|
|
||||||
return Boxed_Value(vec);
|
|
||||||
}
|
|
||||||
case json::JSON::Class::String:
|
|
||||||
return Boxed_Value(t_json.to_string());
|
|
||||||
case json::JSON::Class::Floating:
|
|
||||||
return Boxed_Value(t_json.to_float());
|
|
||||||
case json::JSON::Class::Integral:
|
|
||||||
return Boxed_Value(t_json.to_int());
|
|
||||||
case json::JSON::Class::Boolean:
|
|
||||||
return Boxed_Value(t_json.to_bool());
|
|
||||||
}
|
|
||||||
|
|
||||||
throw std::runtime_error("Unknown JSON type");
|
|
||||||
}
|
|
||||||
|
|
||||||
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& ) {
|
|
||||||
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 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)
|
|
||||||
{
|
|
||||||
obj[o.first] = to_json_object(o.second);
|
|
||||||
}
|
}
|
||||||
return obj;
|
|
||||||
} catch (const chaiscript::exception::bad_boxed_cast &) {
|
return Boxed_Value(m);
|
||||||
// not a map
|
|
||||||
}
|
}
|
||||||
|
case json::JSON::Class::Array: {
|
||||||
|
std::vector<Boxed_Value> vec;
|
||||||
|
|
||||||
try {
|
for (const auto &p : t_json.array_range()) {
|
||||||
const std::vector<Boxed_Value> v = chaiscript::boxed_cast<const std::vector<Boxed_Value> &>(t_bv);
|
vec.emplace_back(from_json(p));
|
||||||
|
|
||||||
json::JSON obj(json::JSON::Class::Array);
|
|
||||||
for (size_t i = 0; i < v.size(); ++i)
|
|
||||||
{
|
|
||||||
obj[i] = to_json_object(v[i]);
|
|
||||||
}
|
}
|
||||||
return obj;
|
|
||||||
} catch (const chaiscript::exception::bad_boxed_cast &) {
|
return Boxed_Value(vec);
|
||||||
// not a vector
|
|
||||||
}
|
}
|
||||||
|
case json::JSON::Class::String:
|
||||||
|
return Boxed_Value(t_json.to_string());
|
||||||
try {
|
case json::JSON::Class::Floating:
|
||||||
Boxed_Number bn(t_bv);
|
return Boxed_Value(t_json.to_float());
|
||||||
if (Boxed_Number::is_floating_point(t_bv))
|
case json::JSON::Class::Integral:
|
||||||
{
|
return Boxed_Value(t_json.to_int());
|
||||||
return json::JSON(bn.get_as<double>());
|
case json::JSON::Class::Boolean:
|
||||||
} else {
|
return Boxed_Value(t_json.to_bool());
|
||||||
return json::JSON(bn.get_as<std::int64_t>());
|
|
||||||
}
|
|
||||||
} catch (const chaiscript::detail::exception::bad_any_cast &) {
|
|
||||||
// not a number
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
return json::JSON(boxed_cast<bool>(t_bv));
|
|
||||||
} catch (const chaiscript::exception::bad_boxed_cast &) {
|
|
||||||
// not a bool
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
return json::JSON(boxed_cast<std::string>(t_bv));
|
|
||||||
} catch (const chaiscript::exception::bad_boxed_cast &) {
|
|
||||||
// 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())
|
|
||||||
{
|
|
||||||
obj[attr.first] = to_json_object(attr.second);
|
|
||||||
}
|
|
||||||
return obj;
|
|
||||||
} catch (const chaiscript::exception::bad_boxed_cast &) {
|
|
||||||
// not a dynamic object
|
|
||||||
}
|
|
||||||
|
|
||||||
if (t_bv.is_null()) return json::JSON(); // a null value
|
|
||||||
|
|
||||||
throw std::runtime_error("Unknown object type to convert to JSON");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
throw std::runtime_error("Unknown JSON type");
|
||||||
|
}
|
||||||
|
|
||||||
|
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 &) {
|
||||||
|
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 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) {
|
||||||
|
obj[o.first] = to_json_object(o.second);
|
||||||
|
}
|
||||||
|
return obj;
|
||||||
|
} catch (const chaiscript::exception::bad_boxed_cast &) {
|
||||||
|
// not a map
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
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) {
|
||||||
|
obj[i] = to_json_object(v[i]);
|
||||||
|
}
|
||||||
|
return obj;
|
||||||
|
} catch (const chaiscript::exception::bad_boxed_cast &) {
|
||||||
|
// not a vector
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
Boxed_Number bn(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>());
|
||||||
|
}
|
||||||
|
} catch (const chaiscript::detail::exception::bad_any_cast &) {
|
||||||
|
// not a number
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return json::JSON(boxed_cast<bool>(t_bv));
|
||||||
|
} catch (const chaiscript::exception::bad_boxed_cast &) {
|
||||||
|
// not a bool
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return json::JSON(boxed_cast<std::string>(t_bv));
|
||||||
|
} catch (const chaiscript::exception::bad_boxed_cast &) {
|
||||||
|
// 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()) {
|
||||||
|
obj[attr.first] = to_json_object(attr.second);
|
||||||
|
}
|
||||||
|
return obj;
|
||||||
|
} catch (const chaiscript::exception::bad_boxed_cast &) {
|
||||||
|
// not a dynamic object
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
#endif
|
||||||
|
|||||||
@ -2,10 +2,8 @@
|
|||||||
#define CHAISCRIPT_UTILITY_QUICK_FLAT_MAP_HPP
|
#define CHAISCRIPT_UTILITY_QUICK_FLAT_MAP_HPP
|
||||||
|
|
||||||
namespace chaiscript::utility {
|
namespace chaiscript::utility {
|
||||||
|
template<typename Key, typename Value, typename Comparator = std::equal_to<>>
|
||||||
template<typename Key, typename Value, typename Comparator=std::equal_to<>>
|
struct QuickFlatMap {
|
||||||
struct QuickFlatMap
|
|
||||||
{
|
|
||||||
Comparator comparator;
|
Comparator comparator;
|
||||||
|
|
||||||
template<typename Lookup>
|
template<typename Lookup>
|
||||||
@ -28,35 +26,19 @@ namespace chaiscript::utility {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto size() const noexcept {
|
auto size() const noexcept { return data.size(); }
|
||||||
return data.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
auto begin() const noexcept {
|
auto begin() const noexcept { return data.begin(); }
|
||||||
return data.begin();
|
|
||||||
}
|
|
||||||
|
|
||||||
auto end() const noexcept {
|
auto end() const noexcept { return data.end(); }
|
||||||
return data.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
auto begin() noexcept { return data.begin(); }
|
||||||
|
|
||||||
auto begin() noexcept {
|
auto end() noexcept { return data.end(); }
|
||||||
return data.begin();
|
|
||||||
}
|
|
||||||
|
|
||||||
auto end() noexcept {
|
auto &back() noexcept { return data.back(); }
|
||||||
return data.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
auto &back() noexcept {
|
|
||||||
return data.back();
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto &back() const noexcept {
|
|
||||||
return data.back();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
const auto &back() const noexcept { return data.back(); }
|
||||||
|
|
||||||
Value &operator[](const Key &s) {
|
Value &operator[](const Key &s) {
|
||||||
const auto itr = find(s);
|
const auto itr = find(s);
|
||||||
@ -68,24 +50,14 @@ namespace chaiscript::utility {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Value &at_index(const std::size_t idx) noexcept
|
Value &at_index(const std::size_t idx) noexcept { return data[idx].second; }
|
||||||
{
|
|
||||||
return data[idx].second;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Value &at_index(const std::size_t idx) const noexcept
|
const Value &at_index(const std::size_t idx) const noexcept { return data[idx].second; }
|
||||||
{
|
|
||||||
return data[idx].second;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool empty() const noexcept
|
bool empty() const noexcept { return data.empty(); }
|
||||||
{
|
|
||||||
return data.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Itr>
|
template<typename Itr>
|
||||||
void assign(Itr begin, Itr end)
|
void assign(Itr begin, Itr end) {
|
||||||
{
|
|
||||||
data.assign(begin, end);
|
data.assign(begin, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -98,10 +70,8 @@ namespace chaiscript::utility {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<typename M>
|
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()) {
|
if (auto itr = find(key); itr != data.end()) {
|
||||||
*itr = std::forward<M>(m);
|
*itr = std::forward<M>(m);
|
||||||
return std::pair{itr, false};
|
return std::pair{itr, false};
|
||||||
@ -111,10 +81,8 @@ namespace chaiscript::utility {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<typename M>
|
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()) {
|
if (auto itr = find(key); itr != data.end()) {
|
||||||
itr->second = std::forward<M>(m);
|
itr->second = std::forward<M>(m);
|
||||||
return std::pair{itr, false};
|
return std::pair{itr, false};
|
||||||
@ -135,7 +103,7 @@ namespace chaiscript::utility {
|
|||||||
|
|
||||||
template<typename Lookup>
|
template<typename Lookup>
|
||||||
size_t count(const Lookup &s) const noexcept {
|
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;
|
std::vector<std::pair<Key, Value>> data;
|
||||||
@ -144,8 +112,7 @@ namespace chaiscript::utility {
|
|||||||
using iterator = typename decltype(data)::iterator;
|
using iterator = typename decltype(data)::iterator;
|
||||||
using const_iterator = typename decltype(data)::const_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()) {
|
if (const auto itr = find(value.first); itr != data.end()) {
|
||||||
return std::pair{itr, false};
|
return std::pair{itr, false};
|
||||||
} else {
|
} else {
|
||||||
@ -159,11 +126,8 @@ namespace chaiscript::utility {
|
|||||||
data.reserve(data.size() + 2);
|
data.reserve(data.size() + 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
} // namespace chaiscript::utility
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@ -7,47 +7,36 @@
|
|||||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
// 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
|
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||||
|
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_STACK_VECTOR_HPP_
|
#ifndef CHAISCRIPT_STACK_VECTOR_HPP_
|
||||||
#define CHAISCRIPT_STACK_VECTOR_HPP_
|
#define CHAISCRIPT_STACK_VECTOR_HPP_
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <type_traits>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
|
||||||
template<typename T, std::size_t MaxSize>
|
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;
|
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];
|
alignas(std::alignment_of_v<T>) char data[aligned_size * MaxSize];
|
||||||
|
|
||||||
[[nodiscard]] T & operator[](const std::size_t idx) noexcept {
|
[[nodiscard]] T &operator[](const std::size_t idx) noexcept { return *reinterpret_cast<T *>(&data + aligned_size * idx); }
|
||||||
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 {
|
template<typename... Param>
|
||||||
return *reinterpret_cast<const T*>(&data + aligned_size * idx);
|
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;
|
return *p;
|
||||||
};
|
};
|
||||||
|
|
||||||
auto size() const noexcept {
|
auto size() const noexcept { return m_size; };
|
||||||
return m_size;
|
|
||||||
};
|
|
||||||
|
|
||||||
void pop_back() noexcept(std::is_nothrow_destructible_v<T>) {
|
void pop_back() noexcept(std::is_nothrow_destructible_v<T>) { (*this)[--m_size].~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;
|
auto loc = m_size - 1;
|
||||||
for (std::size_t pos = 0; pos < m_size; ++pos) {
|
for (std::size_t pos = 0; pos < m_size; ++pos) {
|
||||||
(*this)[loc--].~T();
|
(*this)[loc--].~T();
|
||||||
@ -55,9 +44,6 @@ struct Stack_Vector
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::size_t m_size{0};
|
std::size_t m_size{0};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif CHAISCRIPT_STACK_VECTOR_HPP_
|
#endif CHAISCRIPT_STACK_VECTOR_HPP_
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -7,59 +7,48 @@
|
|||||||
#ifndef CHAISCRIPT_UTILITY_STATIC_STRING_HPP_
|
#ifndef CHAISCRIPT_UTILITY_STATIC_STRING_HPP_
|
||||||
#define CHAISCRIPT_UTILITY_STATIC_STRING_HPP_
|
#define CHAISCRIPT_UTILITY_STATIC_STRING_HPP_
|
||||||
|
|
||||||
namespace chaiscript
|
namespace chaiscript::utility {
|
||||||
{
|
struct Static_String {
|
||||||
namespace utility
|
template<size_t N>
|
||||||
{
|
constexpr Static_String(const char (&str)[N]) noexcept
|
||||||
|
: m_size(N - 1)
|
||||||
|
, data(&str[0]) {
|
||||||
|
}
|
||||||
|
|
||||||
struct Static_String
|
constexpr size_t size() const noexcept { return m_size; }
|
||||||
{
|
|
||||||
template<size_t N>
|
constexpr const char *c_str() const noexcept { return data; }
|
||||||
constexpr Static_String(const char (&str)[N]) noexcept
|
|
||||||
: m_size(N-1), data(&str[0])
|
constexpr auto begin() const noexcept { return data; }
|
||||||
{
|
|
||||||
|
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;
|
||||||
|
auto b1 = begin();
|
||||||
|
const auto e1 = end();
|
||||||
|
auto b2 = other.begin();
|
||||||
|
const auto e2 = other.end();
|
||||||
|
|
||||||
|
if (e1 - b1 != e2 - b2) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (b1 != e1) {
|
||||||
|
if (*b1 != *b2) {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
++b1;
|
||||||
constexpr size_t size() const noexcept {
|
++b2;
|
||||||
return m_size;
|
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
constexpr const char *c_str() const noexcept {
|
bool operator==(const std::string &t_str) const noexcept { return std::equal(begin(), end(), std::cbegin(t_str), std::cend(t_str)); }
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr auto begin() const noexcept {
|
const size_t m_size;
|
||||||
return data;
|
const char *data = nullptr;
|
||||||
}
|
};
|
||||||
|
} // namespace chaiscript::utility
|
||||||
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;
|
|
||||||
auto b1 = begin();
|
|
||||||
const auto e1 = end();
|
|
||||||
auto b2 = other.begin();
|
|
||||||
const auto e2 = other.end();
|
|
||||||
|
|
||||||
if (e1 - b1 != e2 - b2) { return false; }
|
|
||||||
|
|
||||||
while (b1 != e1) {
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
|
|
||||||
const size_t m_size;
|
|
||||||
const char *data = nullptr;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -7,7 +7,6 @@
|
|||||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
// 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
|
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||||
|
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_UTILITY_UTILITY_HPP_
|
#ifndef CHAISCRIPT_UTILITY_UTILITY_HPP_
|
||||||
#define CHAISCRIPT_UTILITY_UTILITY_HPP_
|
#define CHAISCRIPT_UTILITY_UTILITY_HPP_
|
||||||
|
|
||||||
@ -16,108 +15,90 @@
|
|||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "../language/chaiscript_common.hpp"
|
|
||||||
#include "../dispatchkit/register_function.hpp"
|
|
||||||
#include "../dispatchkit/operators.hpp"
|
#include "../dispatchkit/operators.hpp"
|
||||||
|
#include "../dispatchkit/register_function.hpp"
|
||||||
|
#include "../language/chaiscript_common.hpp"
|
||||||
|
|
||||||
|
namespace chaiscript::utility {
|
||||||
|
/// Single step command for registering a class with ChaiScript
|
||||||
|
///
|
||||||
|
/// \param[in,out] t_module Model to add class to
|
||||||
|
/// \param[in] t_class_name Name of the class being registered
|
||||||
|
/// \param[in] t_constructors Vector of constructors to add
|
||||||
|
/// \param[in] t_funcs Vector of methods to add
|
||||||
|
///
|
||||||
|
/// \example Adding a basic class to ChaiScript in one step
|
||||||
|
///
|
||||||
|
/// \code
|
||||||
|
/// chaiscript::utility::add_class<test>(*m,
|
||||||
|
/// "test",
|
||||||
|
/// { constructor<test ()>(),
|
||||||
|
/// constructor<test (const test &)>() },
|
||||||
|
/// { {fun(&test::function), "function"},
|
||||||
|
/// {fun(&test::function2), "function2"},
|
||||||
|
/// {fun(&test::function3), "function3"},
|
||||||
|
/// {fun(static_cast<std::string(test::*)(double)>(&test::function_overload)), "function_overload" },
|
||||||
|
/// {fun(static_cast<std::string(test::*)(int)>(&test::function_overload)), "function_overload" },
|
||||||
|
/// {fun(static_cast<test & (test::*)(const test &)>(&test::operator=)), "=" }
|
||||||
|
/// }
|
||||||
|
/// );
|
||||||
|
///
|
||||||
|
template<typename Class, typename ModuleType>
|
||||||
|
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) {
|
||||||
|
t_module.add(chaiscript::user_type<Class>(), t_class_name);
|
||||||
|
|
||||||
namespace chaiscript
|
for (const chaiscript::Proxy_Function &ctor : t_constructors) {
|
||||||
{
|
t_module.add(ctor, t_class_name);
|
||||||
namespace utility
|
}
|
||||||
{
|
|
||||||
|
|
||||||
/// Single step command for registering a class with ChaiScript
|
for (const auto &fun : t_funcs) {
|
||||||
///
|
t_module.add(fun.first, fun.second);
|
||||||
/// \param[in,out] t_module Model to add class to
|
}
|
||||||
/// \param[in] t_class_name Name of the class being registered
|
|
||||||
/// \param[in] t_constructors Vector of constructors to add
|
|
||||||
/// \param[in] t_funcs Vector of methods to add
|
|
||||||
///
|
|
||||||
/// \example Adding a basic class to ChaiScript in one step
|
|
||||||
///
|
|
||||||
/// \code
|
|
||||||
/// chaiscript::utility::add_class<test>(*m,
|
|
||||||
/// "test",
|
|
||||||
/// { constructor<test ()>(),
|
|
||||||
/// constructor<test (const test &)>() },
|
|
||||||
/// { {fun(&test::function), "function"},
|
|
||||||
/// {fun(&test::function2), "function2"},
|
|
||||||
/// {fun(&test::function3), "function3"},
|
|
||||||
/// {fun(static_cast<std::string(test::*)(double)>(&test::function_overload)), "function_overload" },
|
|
||||||
/// {fun(static_cast<std::string(test::*)(int)>(&test::function_overload)), "function_overload" },
|
|
||||||
/// {fun(static_cast<test & (test::*)(const test &)>(&test::operator=)), "=" }
|
|
||||||
/// }
|
|
||||||
/// );
|
|
||||||
///
|
|
||||||
template<typename Class, typename ModuleType>
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
t_module.add(chaiscript::user_type<Class>(), t_class_name);
|
|
||||||
|
|
||||||
for(const chaiscript::Proxy_Function &ctor: t_constructors)
|
|
||||||
{
|
|
||||||
t_module.add(ctor, t_class_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
for(const auto &fun: t_funcs)
|
|
||||||
{
|
|
||||||
t_module.add(fun.first, fun.second);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Enum, typename ModuleType>
|
|
||||||
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
|
|
||||||
)
|
|
||||||
{
|
|
||||||
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);
|
|
||||||
|
|
||||||
using namespace chaiscript::bootstrap::operators;
|
|
||||||
equal<Enum>(t_module);
|
|
||||||
not_equal<Enum>(t_module);
|
|
||||||
assign<Enum>(t_module);
|
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
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
|
|
||||||
)
|
|
||||||
{
|
|
||||||
t_module.add(chaiscript::user_type<EnumClass>(), t_class_name);
|
|
||||||
|
|
||||||
t_module.add(chaiscript::constructor<EnumClass()>(), t_class_name);
|
|
||||||
t_module.add(chaiscript::constructor<EnumClass(const EnumClass &)>(), t_class_name);
|
|
||||||
|
|
||||||
using namespace chaiscript::bootstrap::operators;
|
|
||||||
equal<EnumClass>(t_module);
|
|
||||||
not_equal<EnumClass>(t_module);
|
|
||||||
assign<EnumClass>(t_module);
|
|
||||||
|
|
||||||
for (const auto &constant : t_constants)
|
|
||||||
{
|
|
||||||
t_module.add_global_const(chaiscript::const_var(EnumClass(constant.first)), constant.second);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
template<typename Enum, typename ModuleType>
|
||||||
|
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) {
|
||||||
|
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);
|
||||||
|
|
||||||
|
using namespace chaiscript::bootstrap::operators;
|
||||||
|
equal<Enum>(t_module);
|
||||||
|
not_equal<Enum>(t_module);
|
||||||
|
assign<Enum>(t_module);
|
||||||
|
|
||||||
|
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) {
|
||||||
|
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) {
|
||||||
|
t_module.add(chaiscript::user_type<EnumClass>(), t_class_name);
|
||||||
|
|
||||||
|
t_module.add(chaiscript::constructor<EnumClass()>(), t_class_name);
|
||||||
|
t_module.add(chaiscript::constructor<EnumClass(const EnumClass &)>(), t_class_name);
|
||||||
|
|
||||||
|
using namespace chaiscript::bootstrap::operators;
|
||||||
|
equal<EnumClass>(t_module);
|
||||||
|
not_equal<EnumClass>(t_module);
|
||||||
|
assign<EnumClass>(t_module);
|
||||||
|
|
||||||
|
for (const auto &constant : t_constants) {
|
||||||
|
t_module.add_global_const(chaiscript::const_var(EnumClass(constant.first)), constant.second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace chaiscript::utility
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@ -5,8 +5,7 @@ double f(const std::string &, double, bool) noexcept {
|
|||||||
return .0;
|
return .0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main()
|
int main() {
|
||||||
{
|
|
||||||
chaiscript::ChaiScript chai;
|
chaiscript::ChaiScript chai;
|
||||||
|
|
||||||
chai.add(chaiscript::fun(&f), "f");
|
chai.add(chaiscript::fun(&f), "f");
|
||||||
@ -16,5 +15,4 @@ int main()
|
|||||||
f("str", 1.2, false);
|
f("str", 1.2, false);
|
||||||
}
|
}
|
||||||
)");
|
)");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,16 +5,14 @@ double f(const std::string &, double, bool) noexcept {
|
|||||||
return .0;
|
return .0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main()
|
int main() {
|
||||||
{
|
|
||||||
chaiscript::ChaiScript chai;
|
chaiscript::ChaiScript chai;
|
||||||
|
|
||||||
chai.add(chaiscript::fun(&f), "f");
|
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) {
|
for (int i = 0; i < 100000; ++i) {
|
||||||
f();
|
f();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,61 +1,53 @@
|
|||||||
#include <chaiscript/chaiscript.hpp>
|
#include <chaiscript/chaiscript.hpp>
|
||||||
|
|
||||||
class Entity
|
class Entity {
|
||||||
{
|
public:
|
||||||
public:
|
int width;
|
||||||
int width;
|
int height;
|
||||||
int height;
|
int x;
|
||||||
int x;
|
int y;
|
||||||
int y;
|
std::string name;
|
||||||
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)
|
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
|
class Factory {
|
||||||
{
|
public:
|
||||||
public:
|
// we may as well pass the parameters for the entity to the factory method, this does the initialization
|
||||||
// we may as well pass the parameters for the entity to the factory method, this does the initialization
|
// in one step.
|
||||||
// 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);
|
||||||
auto entity = entities.insert({name, Entity{width, height, x, y, name}});
|
}
|
||||||
return &(entity.first->second);
|
|
||||||
}
|
|
||||||
|
|
||||||
Entity *get_entity(const std::string &name)
|
Entity *get_entity(const std::string &name) { return &entities.at(name); }
|
||||||
{
|
|
||||||
return &entities.at(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// loop over all entities and all their updater function (if it exists)
|
||||||
// loop over all entities and all their updater function (if it exists)
|
void update_entities() {
|
||||||
void update_entities()
|
for (auto &entity : entities) {
|
||||||
{
|
if (entity.second.updater) {
|
||||||
for (auto &entity : entities)
|
entity.second.updater(entity.second);
|
||||||
{
|
|
||||||
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,
|
||||||
// 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.
|
||||||
// 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
|
||||||
// using a map guarantees that the memory assigned to the entity will never change, plus
|
// lets us easily look up an entity by name
|
||||||
// lets us easily look up an entity by name
|
std::map<std::string, Entity> entities;
|
||||||
std::map<std::string, Entity> entities;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
int main()
|
int main() {
|
||||||
{
|
|
||||||
chaiscript::ChaiScript chai;
|
chaiscript::ChaiScript chai;
|
||||||
|
|
||||||
chai.add(chaiscript::fun(&Entity::width), "width");
|
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::fun(&Factory::update_entities), "update_entities");
|
||||||
chai.add(chaiscript::user_type<Factory>(), "Factory"); // this isn't strictly necessary but makes error messages nicer
|
chai.add(chaiscript::user_type<Factory>(), "Factory"); // this isn't strictly necessary but makes error messages nicer
|
||||||
|
|
||||||
|
|
||||||
Factory f;
|
Factory f;
|
||||||
chai.add(chaiscript::var(&f), "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
|
print(f.get_entity("entity3").x == 20) // this one has no updater, so it stays the same
|
||||||
)"";
|
)"";
|
||||||
|
|
||||||
|
|
||||||
chai.eval(script);
|
chai.eval(script);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -7,7 +7,6 @@
|
|||||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
// 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
|
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||||
|
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <regex>
|
#include <regex>
|
||||||
@ -19,43 +18,38 @@
|
|||||||
#include <chaiscript/chaiscript.hpp>
|
#include <chaiscript/chaiscript.hpp>
|
||||||
|
|
||||||
#ifdef READLINE_AVAILABLE
|
#ifdef READLINE_AVAILABLE
|
||||||
#include <readline/readline.h>
|
|
||||||
#include <readline/history.h>
|
#include <readline/history.h>
|
||||||
|
#include <readline/readline.h>
|
||||||
#else
|
#else
|
||||||
|
|
||||||
char *mystrdup(const char *s) {
|
char *mystrdup(const char *s) {
|
||||||
size_t len = strlen(s); // Space for length plus nul
|
size_t len = strlen(s); // Space for length plus nul
|
||||||
char *d = static_cast<char*>(malloc(len + 1));
|
char *d = static_cast<char *>(malloc(len + 1));
|
||||||
if (d == nullptr) return nullptr; // No memory
|
if (d == nullptr)
|
||||||
|
return nullptr; // No memory
|
||||||
#ifdef CHAISCRIPT_MSVC
|
#ifdef CHAISCRIPT_MSVC
|
||||||
strcpy_s(d, len + 1, s); // Copy the characters
|
strcpy_s(d, len + 1, s); // Copy the characters
|
||||||
#else
|
#else
|
||||||
strncpy(d, s, len); // Copy the characters
|
strncpy(d, s, len); // Copy the characters
|
||||||
#endif
|
#endif
|
||||||
d[len] = '\0';
|
d[len] = '\0';
|
||||||
return d; // Return the new string
|
return d; // Return the new string
|
||||||
}
|
}
|
||||||
|
|
||||||
char* readline(const char* p)
|
char *readline(const char *p) {
|
||||||
{
|
|
||||||
std::string retval;
|
std::string retval;
|
||||||
std::cout << p;
|
std::cout << p;
|
||||||
std::getline(std::cin, retval);
|
std::getline(std::cin, retval);
|
||||||
return std::cin.eof() ? nullptr : mystrdup(retval.c_str());
|
return std::cin.eof() ? nullptr : mystrdup(retval.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void add_history(const char *) {}
|
||||||
void add_history(const char*){}
|
void using_history() {}
|
||||||
void using_history(){}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void *cast_module_symbol(std::vector<std::string> (*t_path)()) {
|
||||||
|
union cast_union {
|
||||||
void *cast_module_symbol(std::vector<std::string>(*t_path)())
|
std::vector<std::string> (*in_ptr)();
|
||||||
{
|
|
||||||
union cast_union
|
|
||||||
{
|
|
||||||
std::vector<std::string>(*in_ptr)();
|
|
||||||
void *out_ptr;
|
void *out_ptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -64,12 +58,11 @@ void *cast_module_symbol(std::vector<std::string>(*t_path)())
|
|||||||
return c.out_ptr;
|
return c.out_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> default_search_paths()
|
std::vector<std::string> default_search_paths() {
|
||||||
{
|
|
||||||
std::vector<std::string> paths;
|
std::vector<std::string> paths;
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_NO_DYNLOAD
|
#ifndef CHAISCRIPT_NO_DYNLOAD
|
||||||
#ifdef CHAISCRIPT_WINDOWS // force no unicode
|
#ifdef CHAISCRIPT_WINDOWS // force no unicode
|
||||||
CHAR path[4096];
|
CHAR path[4096];
|
||||||
int size = GetModuleFileNameA(0, path, sizeof(path) - 1);
|
int size = GetModuleFileNameA(0, path, sizeof(path) - 1);
|
||||||
|
|
||||||
@ -77,14 +70,12 @@ std::vector<std::string> default_search_paths()
|
|||||||
|
|
||||||
size_t lastslash = exepath.rfind('\\');
|
size_t lastslash = exepath.rfind('\\');
|
||||||
size_t secondtolastslash = exepath.rfind('\\', lastslash - 1);
|
size_t secondtolastslash = exepath.rfind('\\', lastslash - 1);
|
||||||
if (lastslash != std::string::npos)
|
if (lastslash != std::string::npos) {
|
||||||
{
|
|
||||||
paths.push_back(exepath.substr(0, lastslash));
|
paths.push_back(exepath.substr(0, lastslash));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (secondtolastslash != std::string::npos)
|
if (secondtolastslash != std::string::npos) {
|
||||||
{
|
return {exepath.substr(0, secondtolastslash) + "\\lib\\chaiscript\\"};
|
||||||
return{ exepath.substr(0, secondtolastslash) + "\\lib\\chaiscript\\" };
|
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
|
||||||
@ -93,29 +84,23 @@ std::vector<std::string> default_search_paths()
|
|||||||
std::vector<char> buf(2048);
|
std::vector<char> buf(2048);
|
||||||
ssize_t size = -1;
|
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));
|
exepath = std::string(&buf.front(), static_cast<size_t>(size));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (exepath.empty())
|
if (exepath.empty()) {
|
||||||
{
|
if ((size = readlink("/proc/curproc/file", &buf.front(), buf.size())) > 0) {
|
||||||
if ((size = readlink("/proc/curproc/file", &buf.front(), buf.size())) > 0)
|
|
||||||
{
|
|
||||||
exepath = std::string(&buf.front(), static_cast<size_t>(size));
|
exepath = std::string(&buf.front(), static_cast<size_t>(size));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (exepath.empty())
|
if (exepath.empty()) {
|
||||||
{
|
if ((size = readlink("/proc/self/path/a.out", &buf.front(), buf.size())) > 0) {
|
||||||
if ((size = readlink("/proc/self/path/a.out", &buf.front(), buf.size())) > 0)
|
|
||||||
{
|
|
||||||
exepath = std::string(&buf.front(), static_cast<size_t>(size));
|
exepath = std::string(&buf.front(), static_cast<size_t>(size));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (exepath.empty())
|
if (exepath.empty()) {
|
||||||
{
|
|
||||||
Dl_info rInfo;
|
Dl_info rInfo;
|
||||||
memset(&rInfo, 0, sizeof(rInfo));
|
memset(&rInfo, 0, sizeof(rInfo));
|
||||||
if (!dladdr(cast_module_symbol(&default_search_paths), &rInfo) || !rInfo.dli_fname) {
|
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 lastslash = exepath.rfind('/');
|
||||||
|
|
||||||
size_t secondtolastslash = exepath.rfind('/', lastslash - 1);
|
size_t secondtolastslash = exepath.rfind('/', lastslash - 1);
|
||||||
if (lastslash != std::string::npos)
|
if (lastslash != std::string::npos) {
|
||||||
{
|
|
||||||
paths.push_back(exepath.substr(0, lastslash));
|
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/");
|
paths.push_back(exepath.substr(0, secondtolastslash) + "/lib/chaiscript/");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -149,8 +132,7 @@ void help(int n) {
|
|||||||
std::cout << "Additionally, you can inspect the runtime system using:\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_system() - outputs all functions registered to the system\n";
|
||||||
std::cout << " dump_object(x) - dumps information about the given symbol\n";
|
std::cout << " dump_object(x) - dumps information about the given symbol\n";
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
std::cout << "usage : chai [option]+\n";
|
std::cout << "usage : chai [option]+\n";
|
||||||
std::cout << "option:\n";
|
std::cout << "option:\n";
|
||||||
std::cout << " -h | --help\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 + "!";
|
return "Hello " + t_name + "!";
|
||||||
}
|
}
|
||||||
|
|
||||||
bool throws_exception(const std::function<void()> &f)
|
bool throws_exception(const std::function<void()> &f) {
|
||||||
{
|
|
||||||
try {
|
try {
|
||||||
f();
|
f();
|
||||||
}
|
} catch (...) {
|
||||||
catch (...) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
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 {
|
try {
|
||||||
f();
|
f();
|
||||||
}
|
} catch (const chaiscript::exception::eval_error &e) {
|
||||||
catch (const chaiscript::exception::eval_error &e) {
|
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -200,13 +177,11 @@ std::string get_next_command() {
|
|||||||
|
|
||||||
std::string val(input_raw);
|
std::string val(input_raw);
|
||||||
size_t pos = val.find_first_not_of("\t \n");
|
size_t pos = val.find_first_not_of("\t \n");
|
||||||
if (pos != std::string::npos)
|
if (pos != std::string::npos) {
|
||||||
{
|
|
||||||
val.erase(0, pos);
|
val.erase(0, pos);
|
||||||
}
|
}
|
||||||
pos = val.find_last_not_of("\t \n");
|
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);
|
val.erase(pos + 1, std::string::npos);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -215,11 +190,7 @@ std::string get_next_command() {
|
|||||||
::free(input_raw);
|
::free(input_raw);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (retval == "quit"
|
if (retval == "quit" || retval == "exit" || retval == "help" || retval == "version") {
|
||||||
|| retval == "exit"
|
|
||||||
|| retval == "help"
|
|
||||||
|| retval == "version")
|
|
||||||
{
|
|
||||||
retval += "(0)";
|
retval += "(0)";
|
||||||
}
|
}
|
||||||
return retval;
|
return retval;
|
||||||
@ -231,8 +202,7 @@ void myexit(int return_val) {
|
|||||||
exit(return_val);
|
exit(return_val);
|
||||||
}
|
}
|
||||||
|
|
||||||
void interactive(chaiscript::ChaiScript& chai)
|
void interactive(chaiscript::ChaiScript &chai) {
|
||||||
{
|
|
||||||
using_history();
|
using_history();
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
@ -241,32 +211,28 @@ void interactive(chaiscript::ChaiScript& chai)
|
|||||||
// evaluate input
|
// evaluate input
|
||||||
chaiscript::Boxed_Value val = chai.eval(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>())) {
|
if (!val.get_type_info().bare_equal(chaiscript::user_type<void>())) {
|
||||||
try {
|
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 (...) {
|
||||||
catch (...) {} //If we can't, do nothing
|
} // If we can't, do nothing
|
||||||
}
|
}
|
||||||
}
|
} catch (const chaiscript::exception::eval_error &ee) {
|
||||||
catch (const chaiscript::exception::eval_error &ee) {
|
|
||||||
std::cout << ee.what();
|
std::cout << ee.what();
|
||||||
if (ee.call_stack.size() > 0) {
|
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 << "during evaluation at (" << ee.call_stack[0].start().line << ", " << ee.call_stack[0].start().column << ")";
|
||||||
}
|
}
|
||||||
std::cout << '\n';
|
std::cout << '\n';
|
||||||
}
|
} catch (const std::exception &e) {
|
||||||
catch (const std::exception &e) {
|
|
||||||
std::cout << e.what();
|
std::cout << e.what();
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[]) {
|
||||||
{
|
// Disable deprecation warning for getenv call.
|
||||||
|
|
||||||
// Disable deprecation warning for getenv call.
|
|
||||||
#ifdef CHAISCRIPT_MSVC
|
#ifdef CHAISCRIPT_MSVC
|
||||||
#pragma warning(push)
|
#pragma warning(push)
|
||||||
#pragma warning(disable : 4996)
|
#pragma warning(disable : 4996)
|
||||||
@ -281,8 +247,7 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
std::vector<std::string> usepaths;
|
std::vector<std::string> usepaths;
|
||||||
usepaths.push_back("");
|
usepaths.push_back("");
|
||||||
if (usepath)
|
if (usepath) {
|
||||||
{
|
|
||||||
usepaths.push_back(usepath);
|
usepaths.push_back(usepath);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -290,12 +255,11 @@ int main(int argc, char *argv[])
|
|||||||
std::vector<std::string> searchpaths = default_search_paths();
|
std::vector<std::string> searchpaths = default_search_paths();
|
||||||
modulepaths.insert(modulepaths.end(), searchpaths.begin(), searchpaths.end());
|
modulepaths.insert(modulepaths.end(), searchpaths.begin(), searchpaths.end());
|
||||||
modulepaths.push_back("");
|
modulepaths.push_back("");
|
||||||
if (modulepath)
|
if (modulepath) {
|
||||||
{
|
|
||||||
modulepaths.push_back(modulepath);
|
modulepaths.push_back(modulepath);
|
||||||
}
|
}
|
||||||
|
|
||||||
//chaiscript::ChaiScript chai(modulepaths, usepaths);
|
// chaiscript::ChaiScript chai(modulepaths, usepaths);
|
||||||
chaiscript::ChaiScript chai(usepaths);
|
chaiscript::ChaiScript chai(usepaths);
|
||||||
|
|
||||||
chai.add(chaiscript::fun(&myexit), "exit");
|
chai.add(chaiscript::fun(&myexit), "exit");
|
||||||
@ -308,8 +272,7 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
clock_t begin = clock();
|
clock_t begin = clock();
|
||||||
|
|
||||||
for (int i = 0; i < 1000; i++)
|
for (int i = 0; i < 1000; i++) {
|
||||||
{
|
|
||||||
std::string str = helloWorld("Bob12345");
|
std::string str = helloWorld("Bob12345");
|
||||||
fwrite(str.c_str(), 1, str.size(), stdout);
|
fwrite(str.c_str(), 1, str.size(), stdout);
|
||||||
}
|
}
|
||||||
@ -317,17 +280,17 @@ int main(int argc, char *argv[])
|
|||||||
clock_t end = clock();
|
clock_t end = clock();
|
||||||
double elapsed_secs = double(end - begin) / CLOCKS_PER_SEC;
|
double elapsed_secs = double(end - begin) / CLOCKS_PER_SEC;
|
||||||
|
|
||||||
//begin = clock();
|
// begin = clock();
|
||||||
|
|
||||||
////for (int i = 0; i < 1000; i++)
|
////for (int i = 0; i < 1000; i++)
|
||||||
////{
|
////{
|
||||||
//// chai.eval("puts(helloWorld(\"Bob12345\"));");
|
//// 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();
|
// end = clock();
|
||||||
//elapsed_secs = double(end - begin) / CLOCKS_PER_SEC;
|
// elapsed_secs = double(end - begin) / CLOCKS_PER_SEC;
|
||||||
//printf("**MyProgram::time= %lf\n", elapsed_secs);
|
// printf("**MyProgram::time= %lf\n", elapsed_secs);
|
||||||
|
|
||||||
for (int i = 0; i < argc; ++i) {
|
for (int i = 0; i < argc; ++i) {
|
||||||
if (i == 0 && argc > 1) {
|
if (i == 0 && argc > 1) {
|
||||||
@ -337,69 +300,64 @@ int main(int argc, char *argv[])
|
|||||||
std::string arg(i ? argv[i] : "--interactive");
|
std::string arg(i ? argv[i] : "--interactive");
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
eInteractive
|
eInteractive,
|
||||||
, eCommand
|
eCommand,
|
||||||
, eFile
|
eFile
|
||||||
} mode = eCommand;
|
} mode
|
||||||
|
= eCommand;
|
||||||
|
|
||||||
if (arg == "-c" || arg == "--command") {
|
if (arg == "-c" || arg == "--command") {
|
||||||
if ((i + 1) >= argc) {
|
if ((i + 1) >= argc) {
|
||||||
std::cout << "insufficient input following " << arg << std::endl;
|
std::cout << "insufficient input following " << arg << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
arg = argv[++i];
|
arg = argv[++i];
|
||||||
}
|
}
|
||||||
}
|
} else if (arg == "-" || arg == "--stdin") {
|
||||||
else if (arg == "-" || arg == "--stdin") {
|
|
||||||
arg = "";
|
arg = "";
|
||||||
std::string line;
|
std::string line;
|
||||||
while (std::getline(std::cin, line)) {
|
while (std::getline(std::cin, line)) {
|
||||||
arg += line + '\n';
|
arg += line + '\n';
|
||||||
}
|
}
|
||||||
}
|
} else if (arg == "-v" || arg == "--version") {
|
||||||
else if (arg == "-v" || arg == "--version") {
|
|
||||||
arg = "version()";
|
arg = "version()";
|
||||||
}
|
} else if (arg == "-h" || arg == "--help") {
|
||||||
else if (arg == "-h" || arg == "--help") {
|
|
||||||
arg = "help(-1)";
|
arg = "help(-1)";
|
||||||
}
|
} else if (arg == "-i" || arg == "--interactive") {
|
||||||
else if (arg == "-i" || arg == "--interactive") {
|
|
||||||
mode = eInteractive;
|
mode = eInteractive;
|
||||||
}
|
} else if (arg.find('-') == 0) {
|
||||||
else if (arg.find('-') == 0) {
|
|
||||||
std::cout << "unrecognised argument " << arg << std::endl;
|
std::cout << "unrecognised argument " << arg << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
mode = eFile;
|
mode = eFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
chaiscript::Boxed_Value val;
|
chaiscript::Boxed_Value val;
|
||||||
try {
|
try {
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case eInteractive: interactive(chai); break;
|
case eInteractive:
|
||||||
case eCommand: val = chai.eval(arg); break;
|
interactive(chai);
|
||||||
|
break;
|
||||||
|
case eCommand:
|
||||||
|
val = chai.eval(arg);
|
||||||
|
break;
|
||||||
case eFile: {
|
case eFile: {
|
||||||
begin = clock();
|
begin = clock();
|
||||||
|
|
||||||
val = chai.eval_file(arg);
|
val = chai.eval_file(arg);
|
||||||
|
|
||||||
end = clock();
|
|
||||||
double elapsed_secs1 = double(end - begin) / CLOCKS_PER_SEC;
|
|
||||||
printf("**C++::time= %.10f\n", elapsed_secs);
|
|
||||||
printf("**ChaiScript::time= %.10f\n", elapsed_secs1);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
end = clock();
|
||||||
|
double elapsed_secs1 = double(end - begin) / CLOCKS_PER_SEC;
|
||||||
|
printf("**C++::time= %.10f\n", elapsed_secs);
|
||||||
|
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 << ee.pretty_print();
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
} catch (std::exception &e) {
|
||||||
catch (std::exception &e) {
|
|
||||||
std::cout << e.what() << std::endl;
|
std::cout << e.what() << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
@ -407,4 +365,3 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,79 +1,66 @@
|
|||||||
#include <chaiscript/chaiscript.hpp>
|
#include <chaiscript/chaiscript.hpp>
|
||||||
|
|
||||||
class BaseClass
|
class BaseClass {
|
||||||
{
|
public:
|
||||||
public:
|
BaseClass() = default;
|
||||||
BaseClass()
|
|
||||||
{
|
BaseClass(const BaseClass &) = default;
|
||||||
|
|
||||||
|
virtual ~BaseClass() = default;
|
||||||
|
|
||||||
|
virtual std::string doSomething(float, double) const = 0;
|
||||||
|
|
||||||
|
void setValue(const std::string &t_val) {
|
||||||
|
if (validateValue(t_val)) {
|
||||||
|
m_value = t_val;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
BaseClass(const BaseClass &) = default;
|
std::string getValue() const { return m_value; }
|
||||||
|
|
||||||
virtual ~BaseClass() {}
|
protected:
|
||||||
|
virtual bool validateValue(const std::string &t_val) = 0;
|
||||||
|
|
||||||
virtual std::string doSomething(float, double) const = 0;
|
private:
|
||||||
|
std::string m_value;
|
||||||
|
|
||||||
void setValue(const std::string &t_val) {
|
|
||||||
if (validateValue(t_val))
|
|
||||||
{
|
|
||||||
m_value = t_val;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string getValue() const {
|
|
||||||
return m_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual bool validateValue(const std::string &t_val) = 0;
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::string m_value;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class ChaiScriptDerived : public BaseClass
|
class ChaiScriptDerived : public BaseClass {
|
||||||
{
|
public:
|
||||||
public:
|
ChaiScriptDerived(const std::vector<chaiscript::Boxed_Value> &t_funcs) {
|
||||||
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
|
||||||
// using the range-checked .at() methods to give us an exception
|
tie(t_funcs.at(0), m_doSomethingImpl);
|
||||||
// instead of a crash if the user passed in too-few params
|
tie(t_funcs.at(1), m_validateValueImpl);
|
||||||
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);
|
||||||
assert(m_doSomethingImpl);
|
return m_doSomethingImpl(*this, f, d);
|
||||||
return m_doSomethingImpl(*this, f, d);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool validateValue(const std::string &t_val) override
|
bool validateValue(const std::string &t_val) override {
|
||||||
{
|
assert(m_validateValueImpl);
|
||||||
assert(m_validateValueImpl);
|
return m_validateValueImpl(*this, t_val);
|
||||||
return m_validateValueImpl(*this, t_val);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template<typename Param>
|
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);
|
||||||
t_param = chaiscript::boxed_cast<Param>(t_func);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
std::function<std::string (const ChaiScriptDerived&, float, double)> m_doSomethingImpl;
|
std::function<std::string(const ChaiScriptDerived &, float, double)> m_doSomethingImpl;
|
||||||
std::function<bool (ChaiScriptDerived&, const std::string &t_val)> m_validateValueImpl;
|
std::function<bool(ChaiScriptDerived &, const std::string &t_val)> m_validateValueImpl;
|
||||||
};
|
};
|
||||||
|
|
||||||
int main()
|
int main() {
|
||||||
{
|
|
||||||
chaiscript::ChaiScript chai;
|
chaiscript::ChaiScript chai;
|
||||||
chai.add(chaiscript::fun(&BaseClass::doSomething), "doSomething");
|
chai.add(chaiscript::fun(&BaseClass::doSomething), "doSomething");
|
||||||
chai.add(chaiscript::fun(&BaseClass::setValue), "setValue");
|
chai.add(chaiscript::fun(&BaseClass::setValue), "setValue");
|
||||||
chai.add(chaiscript::fun(&BaseClass::getValue), "getValue");
|
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::base_class<BaseClass, ChaiScriptDerived>());
|
||||||
chai.add(chaiscript::user_type<BaseClass>(), "BaseClass");
|
chai.add(chaiscript::user_type<BaseClass>(), "BaseClass");
|
||||||
chai.add(chaiscript::user_type<ChaiScriptDerived>(), "ChaiScriptDerived");
|
chai.add(chaiscript::user_type<ChaiScriptDerived>(), "ChaiScriptDerived");
|
||||||
@ -105,8 +92,8 @@ int main()
|
|||||||
)"";
|
)"";
|
||||||
|
|
||||||
chai.eval(script);
|
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
|
// 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
|
// it is a derivation of BaseClass, and the implementation is provided via ChaiScript functors
|
||||||
@ -121,7 +108,6 @@ int main()
|
|||||||
myderived.setValue("12345");
|
myderived.setValue("12345");
|
||||||
assert(myderived.getValue() == "1234");
|
assert(myderived.getValue() == "1234");
|
||||||
|
|
||||||
|
|
||||||
chai.eval(R"(myderived.setValue("new"))"); // set the value via chaiscript
|
chai.eval(R"(myderived.setValue("new"))"); // set the value via chaiscript
|
||||||
assert(myderived.getValue() == "new");
|
assert(myderived.getValue() == "new");
|
||||||
|
|
||||||
@ -131,5 +117,3 @@ int main()
|
|||||||
|
|
||||||
// The whole process is fully orthogonal
|
// The whole process is fully orthogonal
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -3,12 +3,10 @@
|
|||||||
#include <chaiscript/chaiscript.hpp>
|
#include <chaiscript/chaiscript.hpp>
|
||||||
|
|
||||||
#ifdef READLINE_AVAILABLE
|
#ifdef READLINE_AVAILABLE
|
||||||
#include <readline/readline.h>
|
|
||||||
#include <readline/history.h>
|
#include <readline/history.h>
|
||||||
|
#include <readline/readline.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
std::string get_next_command() {
|
std::string get_next_command() {
|
||||||
#ifdef READLINE_AVAILABLE
|
#ifdef READLINE_AVAILABLE
|
||||||
char *input_raw;
|
char *input_raw;
|
||||||
@ -23,42 +21,32 @@ std::string get_next_command() {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void function(void)
|
void function(void) {
|
||||||
{
|
|
||||||
// do nothing
|
// do nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
class test
|
class test {
|
||||||
{
|
|
||||||
chaiscript::ChaiScript chai;
|
chaiscript::ChaiScript chai;
|
||||||
chaiscript::ChaiScript::State backupState = chai.get_state();
|
chaiscript::ChaiScript::State backupState = chai.get_state();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void ResetState()
|
void ResetState() {
|
||||||
{
|
|
||||||
chai.set_state(backupState);
|
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 {
|
try {
|
||||||
chaiscript::Boxed_Value val = chai.eval_file(sFile);
|
chaiscript::Boxed_Value val = chai.eval_file(sFile);
|
||||||
}
|
} catch (std::exception &e) {
|
||||||
catch (std::exception &e) {
|
|
||||||
std::cout << e.what() << '\n';
|
std::cout << e.what() << '\n';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int main(int /*argc*/, char * /*argv*/[]) {
|
int main(int /*argc*/, char * /*argv*/[]) {
|
||||||
|
|
||||||
test myChai;
|
test myChai;
|
||||||
|
|
||||||
|
|
||||||
std::string command = "";
|
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
|
// scenario3 - RunFile gets in changing intervals: memory usage goes up and down, but never as
|
||||||
// low as in case 1 scenario3 :
|
// low as in case 1 scenario3 :
|
||||||
|
|
||||||
while(command != "quit")
|
while (command != "quit") {
|
||||||
{
|
for (int i = 1; i < 200; i++)
|
||||||
for(int i = 1; i < 200; i++)
|
|
||||||
myChai.ResetState();
|
myChai.ResetState();
|
||||||
|
|
||||||
if(command == "runfile")
|
if (command == "runfile")
|
||||||
myChai.RunFile("Test.chai");
|
myChai.RunFile("Test.chai");
|
||||||
|
|
||||||
command = get_next_command();
|
command = get_next_command();
|
||||||
|
|||||||
@ -2,15 +2,12 @@
|
|||||||
#include <chaiscript/dispatchkit/bootstrap_stl.hpp>
|
#include <chaiscript/dispatchkit/bootstrap_stl.hpp>
|
||||||
#include <chaiscript/dispatchkit/function_call.hpp>
|
#include <chaiscript/dispatchkit/function_call.hpp>
|
||||||
|
|
||||||
int main( int /*argc*/ , char * /*argv*/[] )
|
int main(int /*argc*/, char * /*argv*/[]) {
|
||||||
{
|
|
||||||
chaiscript::ChaiScript ch;
|
chaiscript::ChaiScript ch;
|
||||||
|
|
||||||
|
try {
|
||||||
try
|
static const char script[] =
|
||||||
{
|
R""(
|
||||||
static const char script[ ] =
|
|
||||||
R""(
|
|
||||||
|
|
||||||
class Rectangle
|
class Rectangle
|
||||||
{
|
{
|
||||||
@ -21,12 +18,9 @@ int main( int /*argc*/ , char * /*argv*/[] )
|
|||||||
|
|
||||||
)"";
|
)"";
|
||||||
|
|
||||||
|
ch.eval(script);
|
||||||
ch.eval( script );
|
} catch (const std::exception &e) {
|
||||||
}
|
printf(" >>> Exception thrown: %s \n", e.what());
|
||||||
catch ( const std::exception &e )
|
|
||||||
{
|
|
||||||
printf( " >>> Exception thrown: %s \n" , e.what( ) );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
|
|
||||||
#include <chaiscript/chaiscript_stdlib.hpp>
|
#include <chaiscript/chaiscript_stdlib.hpp>
|
||||||
|
|
||||||
|
|
||||||
// MSVC doesn't like that we are using C++ return types from our C declared module
|
// MSVC doesn't like that we are using C++ return types from our C declared module
|
||||||
// but this is the best way to do it for cross platform compatibility
|
// but this is the best way to do it for cross platform compatibility
|
||||||
#ifdef CHAISCRIPT_MSVC
|
#ifdef CHAISCRIPT_MSVC
|
||||||
@ -14,13 +13,10 @@
|
|||||||
#pragma clang diagnostic ignored "-Wreturn-type-c-linkage"
|
#pragma clang diagnostic ignored "-Wreturn-type-c-linkage"
|
||||||
#endif
|
#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();
|
return chaiscript::Std_Lib::library();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef __llvm__
|
#ifdef __llvm__
|
||||||
#pragma clang diagnostic pop
|
#pragma clang diagnostic pop
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -7,7 +7,6 @@
|
|||||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
// 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
|
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||||
|
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <regex>
|
#include <regex>
|
||||||
@ -16,49 +15,45 @@
|
|||||||
#define _CRT_SECURE_NO_WARNINGS
|
#define _CRT_SECURE_NO_WARNINGS
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <chaiscript/chaiscript.hpp>
|
|
||||||
#include "../static_libs/chaiscript_parser.hpp"
|
#include "../static_libs/chaiscript_parser.hpp"
|
||||||
#include "../static_libs/chaiscript_stdlib.hpp"
|
#include "../static_libs/chaiscript_stdlib.hpp"
|
||||||
|
#include <chaiscript/chaiscript.hpp>
|
||||||
|
|
||||||
#include "sha3.h"
|
#include "sha3.h"
|
||||||
|
|
||||||
#ifdef READLINE_AVAILABLE
|
#ifdef READLINE_AVAILABLE
|
||||||
#include <readline/readline.h>
|
|
||||||
#include <readline/history.h>
|
#include <readline/history.h>
|
||||||
|
#include <readline/readline.h>
|
||||||
#else
|
#else
|
||||||
|
|
||||||
char *mystrdup (const char *s) {
|
char *mystrdup(const char *s) {
|
||||||
size_t len = strlen(s); // Space for length plus nul
|
size_t len = strlen(s); // Space for length plus nul
|
||||||
char *d = static_cast<char*>(malloc (len+1));
|
char *d = static_cast<char *>(malloc(len + 1));
|
||||||
if (d == nullptr) { return nullptr; } // No memory
|
if (d == nullptr) {
|
||||||
|
return nullptr;
|
||||||
|
} // No memory
|
||||||
#ifdef CHAISCRIPT_MSVC
|
#ifdef CHAISCRIPT_MSVC
|
||||||
strcpy_s(d, len+1, s); // Copy the characters
|
strcpy_s(d, len + 1, s); // Copy the characters
|
||||||
#else
|
#else
|
||||||
strncpy(d,s,len); // Copy the characters
|
strncpy(d, s, len); // Copy the characters
|
||||||
#endif
|
#endif
|
||||||
d[len] = '\0';
|
d[len] = '\0';
|
||||||
return d; // Return the new string
|
return d; // Return the new string
|
||||||
}
|
}
|
||||||
|
|
||||||
char* readline(const char* p)
|
char *readline(const char *p) {
|
||||||
{
|
|
||||||
std::string retval;
|
std::string retval;
|
||||||
std::cout << p ;
|
std::cout << p;
|
||||||
std::getline(std::cin, retval);
|
std::getline(std::cin, retval);
|
||||||
return std::cin.eof() ? nullptr : mystrdup(retval.c_str());
|
return std::cin.eof() ? nullptr : mystrdup(retval.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void add_history(const char * /*unused*/) {}
|
||||||
void add_history(const char* /*unused*/){}
|
void using_history() {}
|
||||||
void using_history(){}
|
|
||||||
#endif
|
#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)();
|
std::vector<std::string> (*in_ptr)();
|
||||||
void *out_ptr;
|
void *out_ptr;
|
||||||
};
|
};
|
||||||
@ -68,26 +63,23 @@ void *cast_module_symbol(std::vector<std::string> (*t_path)())
|
|||||||
return c.out_ptr;
|
return c.out_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> default_search_paths()
|
std::vector<std::string> default_search_paths() {
|
||||||
{
|
|
||||||
std::vector<std::string> paths;
|
std::vector<std::string> paths;
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_NO_DYNLOAD
|
#ifndef CHAISCRIPT_NO_DYNLOAD
|
||||||
#ifdef CHAISCRIPT_WINDOWS // force no unicode
|
#ifdef CHAISCRIPT_WINDOWS // force no unicode
|
||||||
CHAR path[4096];
|
CHAR path[4096];
|
||||||
int size = GetModuleFileNameA(nullptr, path, sizeof(path)-1);
|
int size = GetModuleFileNameA(nullptr, path, sizeof(path) - 1);
|
||||||
|
|
||||||
std::string exepath(path, size);
|
std::string exepath(path, size);
|
||||||
|
|
||||||
size_t lastslash = exepath.rfind('\\');
|
size_t lastslash = exepath.rfind('\\');
|
||||||
size_t secondtolastslash = exepath.rfind('\\', lastslash - 1);
|
size_t secondtolastslash = exepath.rfind('\\', lastslash - 1);
|
||||||
if (lastslash != std::string::npos)
|
if (lastslash != std::string::npos) {
|
||||||
{
|
|
||||||
paths.push_back(exepath.substr(0, lastslash));
|
paths.push_back(exepath.substr(0, lastslash));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (secondtolastslash != std::string::npos)
|
if (secondtolastslash != std::string::npos) {
|
||||||
{
|
|
||||||
return {exepath.substr(0, secondtolastslash) + "\\lib\\chaiscript\\"};
|
return {exepath.substr(0, secondtolastslash) + "\\lib\\chaiscript\\"};
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
@ -97,32 +89,26 @@ std::vector<std::string> default_search_paths()
|
|||||||
std::vector<char> buf(2048);
|
std::vector<char> buf(2048);
|
||||||
ssize_t size = -1;
|
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));
|
exepath = std::string(&buf.front(), static_cast<size_t>(size));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (exepath.empty())
|
if (exepath.empty()) {
|
||||||
{
|
if ((size = readlink("/proc/curproc/file", &buf.front(), buf.size())) >= 0) {
|
||||||
if ((size = readlink("/proc/curproc/file", &buf.front(), buf.size())) >= 0)
|
|
||||||
{
|
|
||||||
exepath = std::string(&buf.front(), static_cast<size_t>(size));
|
exepath = std::string(&buf.front(), static_cast<size_t>(size));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (exepath.empty())
|
if (exepath.empty()) {
|
||||||
{
|
if ((size = readlink("/proc/self/path/a.out", &buf.front(), buf.size())) >= 0) {
|
||||||
if ((size = readlink("/proc/self/path/a.out", &buf.front(), buf.size())) >= 0)
|
|
||||||
{
|
|
||||||
exepath = std::string(&buf.front(), static_cast<size_t>(size));
|
exepath = std::string(&buf.front(), static_cast<size_t>(size));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (exepath.empty())
|
if (exepath.empty()) {
|
||||||
{
|
|
||||||
Dl_info rInfo;
|
Dl_info rInfo;
|
||||||
memset( &rInfo, 0, sizeof(rInfo) );
|
memset(&rInfo, 0, sizeof(rInfo));
|
||||||
if ( dladdr(cast_module_symbol(&default_search_paths), &rInfo) == 0 || rInfo.dli_fname == nullptr ) {
|
if (dladdr(cast_module_symbol(&default_search_paths), &rInfo) == 0 || rInfo.dli_fname == nullptr) {
|
||||||
return paths;
|
return paths;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -132,13 +118,11 @@ std::vector<std::string> default_search_paths()
|
|||||||
size_t lastslash = exepath.rfind('/');
|
size_t lastslash = exepath.rfind('/');
|
||||||
|
|
||||||
size_t secondtolastslash = exepath.rfind('/', lastslash - 1);
|
size_t secondtolastslash = exepath.rfind('/', lastslash - 1);
|
||||||
if (lastslash != std::string::npos)
|
if (lastslash != std::string::npos) {
|
||||||
{
|
paths.push_back(exepath.substr(0, lastslash + 1));
|
||||||
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/");
|
paths.push_back(exepath.substr(0, secondtolastslash) + "/lib/chaiscript/");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -148,25 +132,24 @@ std::vector<std::string> default_search_paths()
|
|||||||
}
|
}
|
||||||
|
|
||||||
void help(int n) {
|
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 << "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 << "Additionally, you can inspect the runtime system using:\n";
|
||||||
std::cout << " dump_system() - outputs all functions registered to the system\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";
|
std::cout << " dump_object(x) - dumps information about the given symbol\n";
|
||||||
} else {
|
} else {
|
||||||
std::cout << "usage : chai [option]+\n";
|
std::cout << "usage : chai [option]+\n";
|
||||||
std::cout << "option:" << '\n';
|
std::cout << "option:" << '\n';
|
||||||
std::cout << " -h | --help" << '\n';
|
std::cout << " -h | --help" << '\n';
|
||||||
std::cout << " -i | --interactive" << '\n';
|
std::cout << " -i | --interactive" << '\n';
|
||||||
std::cout << " -c | --command cmd" << '\n';
|
std::cout << " -c | --command cmd" << '\n';
|
||||||
std::cout << " -v | --version" << '\n';
|
std::cout << " -v | --version" << '\n';
|
||||||
std::cout << " - --stdin" << '\n';
|
std::cout << " - --stdin" << '\n';
|
||||||
std::cout << " filepath" << '\n';
|
std::cout << " filepath" << '\n';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool throws_exception(const std::function<void ()> &f)
|
bool throws_exception(const std::function<void()> &f) {
|
||||||
{
|
|
||||||
try {
|
try {
|
||||||
f();
|
f();
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
@ -176,8 +159,7 @@ bool throws_exception(const std::function<void ()> &f)
|
|||||||
return false;
|
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 {
|
try {
|
||||||
f();
|
f();
|
||||||
} catch (const chaiscript::exception::eval_error &e) {
|
} 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 get_next_command() {
|
||||||
std::string retval("quit");
|
std::string retval("quit");
|
||||||
if ( ! std::cin.eof() ) {
|
if (!std::cin.eof()) {
|
||||||
char *input_raw = readline("eval> ");
|
char *input_raw = readline("eval> ");
|
||||||
if ( input_raw != nullptr ) {
|
if (input_raw != nullptr) {
|
||||||
add_history(input_raw);
|
add_history(input_raw);
|
||||||
|
|
||||||
std::string val(input_raw);
|
std::string val(input_raw);
|
||||||
size_t pos = val.find_first_not_of("\t \n");
|
size_t pos = val.find_first_not_of("\t \n");
|
||||||
if (pos != std::string::npos)
|
if (pos != std::string::npos) {
|
||||||
{
|
|
||||||
val.erase(0, pos);
|
val.erase(0, pos);
|
||||||
}
|
}
|
||||||
pos = val.find_last_not_of("\t \n");
|
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);
|
||||||
val.erase(pos+1, std::string::npos);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
retval = val;
|
retval = val;
|
||||||
@ -211,11 +191,7 @@ std::string get_next_command() {
|
|||||||
::free(input_raw);
|
::free(input_raw);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if( retval == "quit"
|
if (retval == "quit" || retval == "exit" || retval == "help" || retval == "version") {
|
||||||
|| retval == "exit"
|
|
||||||
|| retval == "help"
|
|
||||||
|| retval == "version")
|
|
||||||
{
|
|
||||||
retval += "(0)";
|
retval += "(0)";
|
||||||
}
|
}
|
||||||
return retval;
|
return retval;
|
||||||
@ -227,8 +203,7 @@ void myexit(int return_val) {
|
|||||||
exit(return_val);
|
exit(return_val);
|
||||||
}
|
}
|
||||||
|
|
||||||
void interactive(chaiscript::ChaiScript_Basic& chai)
|
void interactive(chaiscript::ChaiScript_Basic &chai) {
|
||||||
{
|
|
||||||
using_history();
|
using_history();
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
@ -237,30 +212,27 @@ void interactive(chaiscript::ChaiScript_Basic& chai)
|
|||||||
// evaluate input
|
// evaluate input
|
||||||
chaiscript::Boxed_Value val = chai.eval(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>())) {
|
if (!val.get_type_info().bare_equal(chaiscript::user_type<void>())) {
|
||||||
try {
|
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 (...) {
|
||||||
catch (...) {} //If we can't, do nothing
|
} // If we can't, do nothing
|
||||||
}
|
}
|
||||||
}
|
} catch (const chaiscript::exception::eval_error &ee) {
|
||||||
catch (const chaiscript::exception::eval_error &ee) {
|
|
||||||
std::cout << ee.what();
|
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 << "during evaluation at (" << ee.call_stack[0].start().line << ", " << ee.call_stack[0].start().column << ")";
|
||||||
}
|
}
|
||||||
std::cout << '\n';
|
std::cout << '\n';
|
||||||
}
|
} catch (const std::exception &e) {
|
||||||
catch (const std::exception &e) {
|
|
||||||
std::cout << e.what();
|
std::cout << e.what();
|
||||||
std::cout << '\n';
|
std::cout << '\n';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
double now()
|
double now() {
|
||||||
{
|
|
||||||
using namespace std::chrono;
|
using namespace std::chrono;
|
||||||
auto now = high_resolution_clock::now();
|
auto now = high_resolution_clock::now();
|
||||||
return duration_cast<duration<double>>(now.time_since_epoch()).count();
|
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) {
|
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||||
chaiscript::ChaiScript chai;
|
chaiscript::ChaiScript chai;
|
||||||
|
|
||||||
chai.eval( R"chaiscript(
|
chai.eval(R"chaiscript(
|
||||||
def assert_equal(x, y)
|
def assert_equal(x, y)
|
||||||
{
|
{
|
||||||
if (x == y)
|
if (x == y)
|
||||||
@ -339,7 +311,8 @@ def assert_throws(desc, x)
|
|||||||
std::ofstream ofs("BOXED_VALUE/" + sha);
|
std::ofstream ofs("BOXED_VALUE/" + sha);
|
||||||
ofs << input;
|
ofs << input;
|
||||||
} catch (const chaiscript::exception::load_module_error &e) {
|
} 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 &) {
|
} catch (const std::exception &) {
|
||||||
std::ofstream ofs("STD_EXCEPTION/" + sha);
|
std::ofstream ofs("STD_EXCEPTION/" + sha);
|
||||||
ofs << input;
|
ofs << input;
|
||||||
@ -350,5 +323,3 @@ def assert_throws(desc, x)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
229
src/main.cpp
229
src/main.cpp
@ -7,7 +7,6 @@
|
|||||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
// 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
|
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||||
|
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <regex>
|
#include <regex>
|
||||||
@ -16,48 +15,43 @@
|
|||||||
#define _CRT_SECURE_NO_WARNINGS
|
#define _CRT_SECURE_NO_WARNINGS
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <chaiscript/chaiscript_basic.hpp>
|
|
||||||
#include "../static_libs/chaiscript_parser.hpp"
|
#include "../static_libs/chaiscript_parser.hpp"
|
||||||
#include "../static_libs/chaiscript_stdlib.hpp"
|
#include "../static_libs/chaiscript_stdlib.hpp"
|
||||||
|
#include <chaiscript/chaiscript_basic.hpp>
|
||||||
|
|
||||||
#ifdef READLINE_AVAILABLE
|
#ifdef READLINE_AVAILABLE
|
||||||
#include <readline/readline.h>
|
|
||||||
#include <readline/history.h>
|
#include <readline/history.h>
|
||||||
|
#include <readline/readline.h>
|
||||||
#else
|
#else
|
||||||
|
|
||||||
char *mystrdup (const char *s) {
|
char *mystrdup(const char *s) {
|
||||||
size_t len = strlen(s); // Space for length plus nul
|
size_t len = strlen(s); // Space for length plus nul
|
||||||
char *d = static_cast<char*>(malloc (len+1));
|
char *d = static_cast<char *>(malloc(len + 1));
|
||||||
if (d == nullptr) { return nullptr; } // No memory
|
if (d == nullptr) {
|
||||||
|
return nullptr;
|
||||||
|
} // No memory
|
||||||
#ifdef CHAISCRIPT_MSVC
|
#ifdef CHAISCRIPT_MSVC
|
||||||
strcpy_s(d, len+1, s); // Copy the characters
|
strcpy_s(d, len + 1, s); // Copy the characters
|
||||||
#else
|
#else
|
||||||
strncpy(d,s,len); // Copy the characters
|
strncpy(d, s, len); // Copy the characters
|
||||||
#endif
|
#endif
|
||||||
d[len] = '\0';
|
d[len] = '\0';
|
||||||
return d; // Return the new string
|
return d; // Return the new string
|
||||||
}
|
}
|
||||||
|
|
||||||
char* readline(const char* p)
|
char *readline(const char *p) {
|
||||||
{
|
|
||||||
std::string retval;
|
std::string retval;
|
||||||
std::cout << p ;
|
std::cout << p;
|
||||||
std::getline(std::cin, retval);
|
std::getline(std::cin, retval);
|
||||||
return std::cin.eof() ? nullptr : mystrdup(retval.c_str());
|
return std::cin.eof() ? nullptr : mystrdup(retval.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void add_history(const char * /*unused*/) {}
|
||||||
void add_history(const char* /*unused*/){}
|
void using_history() {}
|
||||||
void using_history(){}
|
|
||||||
#endif
|
#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)();
|
std::vector<std::string> (*in_ptr)();
|
||||||
void *out_ptr;
|
void *out_ptr;
|
||||||
};
|
};
|
||||||
@ -67,26 +61,23 @@ void *cast_module_symbol(std::vector<std::string> (*t_path)())
|
|||||||
return c.out_ptr;
|
return c.out_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> default_search_paths()
|
std::vector<std::string> default_search_paths() {
|
||||||
{
|
|
||||||
std::vector<std::string> paths;
|
std::vector<std::string> paths;
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_NO_DYNLOAD
|
#ifndef CHAISCRIPT_NO_DYNLOAD
|
||||||
#ifdef CHAISCRIPT_WINDOWS // force no unicode
|
#ifdef CHAISCRIPT_WINDOWS // force no unicode
|
||||||
CHAR path[4096];
|
CHAR path[4096];
|
||||||
int size = GetModuleFileNameA(nullptr, path, sizeof(path)-1);
|
int size = GetModuleFileNameA(nullptr, path, sizeof(path) - 1);
|
||||||
|
|
||||||
std::string exepath(path, size);
|
std::string exepath(path, size);
|
||||||
|
|
||||||
size_t lastslash = exepath.rfind('\\');
|
size_t lastslash = exepath.rfind('\\');
|
||||||
size_t secondtolastslash = exepath.rfind('\\', lastslash - 1);
|
size_t secondtolastslash = exepath.rfind('\\', lastslash - 1);
|
||||||
if (lastslash != std::string::npos)
|
if (lastslash != std::string::npos) {
|
||||||
{
|
|
||||||
paths.push_back(exepath.substr(0, lastslash));
|
paths.push_back(exepath.substr(0, lastslash));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (secondtolastslash != std::string::npos)
|
if (secondtolastslash != std::string::npos) {
|
||||||
{
|
|
||||||
return {exepath.substr(0, secondtolastslash) + "\\lib\\chaiscript\\"};
|
return {exepath.substr(0, secondtolastslash) + "\\lib\\chaiscript\\"};
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
@ -96,32 +87,26 @@ std::vector<std::string> default_search_paths()
|
|||||||
std::vector<char> buf(2048);
|
std::vector<char> buf(2048);
|
||||||
ssize_t size = -1;
|
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));
|
exepath = std::string(&buf.front(), static_cast<size_t>(size));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (exepath.empty())
|
if (exepath.empty()) {
|
||||||
{
|
if ((size = readlink("/proc/curproc/file", &buf.front(), buf.size())) >= 0) {
|
||||||
if ((size = readlink("/proc/curproc/file", &buf.front(), buf.size())) >= 0)
|
|
||||||
{
|
|
||||||
exepath = std::string(&buf.front(), static_cast<size_t>(size));
|
exepath = std::string(&buf.front(), static_cast<size_t>(size));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (exepath.empty())
|
if (exepath.empty()) {
|
||||||
{
|
if ((size = readlink("/proc/self/path/a.out", &buf.front(), buf.size())) >= 0) {
|
||||||
if ((size = readlink("/proc/self/path/a.out", &buf.front(), buf.size())) >= 0)
|
|
||||||
{
|
|
||||||
exepath = std::string(&buf.front(), static_cast<size_t>(size));
|
exepath = std::string(&buf.front(), static_cast<size_t>(size));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (exepath.empty())
|
if (exepath.empty()) {
|
||||||
{
|
|
||||||
Dl_info rInfo;
|
Dl_info rInfo;
|
||||||
memset( &rInfo, 0, sizeof(rInfo) );
|
memset(&rInfo, 0, sizeof(rInfo));
|
||||||
if ( dladdr(cast_module_symbol(&default_search_paths), &rInfo) == 0 || rInfo.dli_fname == nullptr ) {
|
if (dladdr(cast_module_symbol(&default_search_paths), &rInfo) == 0 || rInfo.dli_fname == nullptr) {
|
||||||
return paths;
|
return paths;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -131,13 +116,11 @@ std::vector<std::string> default_search_paths()
|
|||||||
size_t lastslash = exepath.rfind('/');
|
size_t lastslash = exepath.rfind('/');
|
||||||
|
|
||||||
size_t secondtolastslash = exepath.rfind('/', lastslash - 1);
|
size_t secondtolastslash = exepath.rfind('/', lastslash - 1);
|
||||||
if (lastslash != std::string::npos)
|
if (lastslash != std::string::npos) {
|
||||||
{
|
paths.push_back(exepath.substr(0, lastslash + 1));
|
||||||
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/");
|
paths.push_back(exepath.substr(0, secondtolastslash) + "/lib/chaiscript/");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -147,25 +130,24 @@ std::vector<std::string> default_search_paths()
|
|||||||
}
|
}
|
||||||
|
|
||||||
void help(int n) {
|
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 << "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 << "Additionally, you can inspect the runtime system using:\n";
|
||||||
std::cout << " dump_system() - outputs all functions registered to the system\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";
|
std::cout << " dump_object(x) - dumps information about the given symbol\n";
|
||||||
} else {
|
} else {
|
||||||
std::cout << "usage : chai [option]+\n";
|
std::cout << "usage : chai [option]+\n";
|
||||||
std::cout << "option:" << '\n';
|
std::cout << "option:" << '\n';
|
||||||
std::cout << " -h | --help" << '\n';
|
std::cout << " -h | --help" << '\n';
|
||||||
std::cout << " -i | --interactive" << '\n';
|
std::cout << " -i | --interactive" << '\n';
|
||||||
std::cout << " -c | --command cmd" << '\n';
|
std::cout << " -c | --command cmd" << '\n';
|
||||||
std::cout << " -v | --version" << '\n';
|
std::cout << " -v | --version" << '\n';
|
||||||
std::cout << " - --stdin" << '\n';
|
std::cout << " - --stdin" << '\n';
|
||||||
std::cout << " filepath" << '\n';
|
std::cout << " filepath" << '\n';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string throws_exception(const std::function<void ()> &f)
|
std::string throws_exception(const std::function<void()> &f) {
|
||||||
{
|
|
||||||
try {
|
try {
|
||||||
f();
|
f();
|
||||||
} catch (const std::exception &e) {
|
} catch (const std::exception &e) {
|
||||||
@ -175,8 +157,7 @@ std::string throws_exception(const std::function<void ()> &f)
|
|||||||
return "";
|
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 {
|
try {
|
||||||
f();
|
f();
|
||||||
} catch (const chaiscript::exception::eval_error &e) {
|
} 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 get_next_command() {
|
||||||
std::string retval("quit");
|
std::string retval("quit");
|
||||||
if ( ! std::cin.eof() ) {
|
if (!std::cin.eof()) {
|
||||||
char *input_raw = readline("eval> ");
|
char *input_raw = readline("eval> ");
|
||||||
if ( input_raw != nullptr ) {
|
if (input_raw != nullptr) {
|
||||||
add_history(input_raw);
|
add_history(input_raw);
|
||||||
|
|
||||||
std::string val(input_raw);
|
std::string val(input_raw);
|
||||||
size_t pos = val.find_first_not_of("\t \n");
|
size_t pos = val.find_first_not_of("\t \n");
|
||||||
if (pos != std::string::npos)
|
if (pos != std::string::npos) {
|
||||||
{
|
|
||||||
val.erase(0, pos);
|
val.erase(0, pos);
|
||||||
}
|
}
|
||||||
pos = val.find_last_not_of("\t \n");
|
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);
|
||||||
val.erase(pos+1, std::string::npos);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
retval = val;
|
retval = val;
|
||||||
@ -210,11 +189,7 @@ std::string get_next_command() {
|
|||||||
::free(input_raw);
|
::free(input_raw);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if( retval == "quit"
|
if (retval == "quit" || retval == "exit" || retval == "help" || retval == "version") {
|
||||||
|| retval == "exit"
|
|
||||||
|| retval == "help"
|
|
||||||
|| retval == "version")
|
|
||||||
{
|
|
||||||
retval += "(0)";
|
retval += "(0)";
|
||||||
}
|
}
|
||||||
return retval;
|
return retval;
|
||||||
@ -226,8 +201,7 @@ void myexit(int return_val) {
|
|||||||
exit(return_val);
|
exit(return_val);
|
||||||
}
|
}
|
||||||
|
|
||||||
void interactive(chaiscript::ChaiScript_Basic& chai)
|
void interactive(chaiscript::ChaiScript_Basic &chai) {
|
||||||
{
|
|
||||||
using_history();
|
using_history();
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
@ -236,39 +210,34 @@ void interactive(chaiscript::ChaiScript_Basic& chai)
|
|||||||
// evaluate input
|
// evaluate input
|
||||||
chaiscript::Boxed_Value val = chai.eval(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>())) {
|
if (!val.get_type_info().bare_equal(chaiscript::user_type<void>())) {
|
||||||
try {
|
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 (...) {
|
||||||
catch (...) {} //If we can't, do nothing
|
} // If we can't, do nothing
|
||||||
}
|
}
|
||||||
}
|
} catch (const chaiscript::exception::eval_error &ee) {
|
||||||
catch (const chaiscript::exception::eval_error &ee) {
|
|
||||||
std::cout << ee.what();
|
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 << "during evaluation at (" << ee.call_stack[0].start().line << ", " << ee.call_stack[0].start().column << ")";
|
||||||
}
|
}
|
||||||
std::cout << '\n';
|
std::cout << '\n';
|
||||||
}
|
} catch (const std::exception &e) {
|
||||||
catch (const std::exception &e) {
|
|
||||||
std::cout << e.what();
|
std::cout << e.what();
|
||||||
std::cout << '\n';
|
std::cout << '\n';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
double now()
|
double now() {
|
||||||
{
|
|
||||||
using namespace std::chrono;
|
using namespace std::chrono;
|
||||||
auto now = high_resolution_clock::now();
|
auto now = high_resolution_clock::now();
|
||||||
return duration_cast<duration<double>>(now.time_since_epoch()).count();
|
return duration_cast<duration<double>>(now.time_since_epoch()).count();
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[]) {
|
||||||
{
|
// Disable deprecation warning for getenv call.
|
||||||
|
|
||||||
// Disable deprecation warning for getenv call.
|
|
||||||
#ifdef CHAISCRIPT_MSVC
|
#ifdef CHAISCRIPT_MSVC
|
||||||
#pragma warning(push)
|
#pragma warning(push)
|
||||||
#pragma warning(disable : 4996)
|
#pragma warning(disable : 4996)
|
||||||
@ -283,8 +252,7 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
std::vector<std::string> usepaths;
|
std::vector<std::string> usepaths;
|
||||||
usepaths.emplace_back("");
|
usepaths.emplace_back("");
|
||||||
if (usepath != nullptr)
|
if (usepath != nullptr) {
|
||||||
{
|
|
||||||
usepaths.emplace_back(usepath);
|
usepaths.emplace_back(usepath);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -292,12 +260,11 @@ int main(int argc, char *argv[])
|
|||||||
std::vector<std::string> searchpaths = default_search_paths();
|
std::vector<std::string> searchpaths = default_search_paths();
|
||||||
modulepaths.insert(modulepaths.end(), searchpaths.begin(), searchpaths.end());
|
modulepaths.insert(modulepaths.end(), searchpaths.begin(), searchpaths.end());
|
||||||
modulepaths.emplace_back("");
|
modulepaths.emplace_back("");
|
||||||
if (modulepath != nullptr)
|
if (modulepath != nullptr) {
|
||||||
{
|
|
||||||
modulepaths.emplace_back(modulepath);
|
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), "exit");
|
||||||
chai.add(chaiscript::fun(&myexit), "quit");
|
chai.add(chaiscript::fun(&myexit), "quit");
|
||||||
@ -311,46 +278,48 @@ int main(int argc, char *argv[])
|
|||||||
bool any_exception_ok = false;
|
bool any_exception_ok = false;
|
||||||
|
|
||||||
for (int i = 0; i < argc; ++i) {
|
for (int i = 0; i < argc; ++i) {
|
||||||
if ( i == 0 && argc > 1 ) {
|
if (i == 0 && argc > 1) {
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string arg( i != 0 ? argv[i] : "--interactive" );
|
std::string arg(i != 0 ? argv[i] : "--interactive");
|
||||||
|
|
||||||
enum { eInteractive
|
enum {
|
||||||
, eCommand
|
eInteractive,
|
||||||
, eFile
|
eCommand,
|
||||||
} mode = eCommand ;
|
eFile
|
||||||
|
} mode
|
||||||
|
= eCommand;
|
||||||
|
|
||||||
if ( arg == "-c" || arg == "--command" ) {
|
if (arg == "-c" || arg == "--command") {
|
||||||
if ( (i+1) >= argc ) {
|
if ((i + 1) >= argc) {
|
||||||
std::cout << "insufficient input following " << arg << '\n';
|
std::cout << "insufficient input following " << arg << '\n';
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
|
||||||
arg = argv[++i];
|
|
||||||
|
|
||||||
} else if ( arg == "-" || arg == "--stdin" ) {
|
|
||||||
arg = "" ;
|
|
||||||
std::string line;
|
|
||||||
while ( std::getline(std::cin, line) ) {
|
|
||||||
arg += line + '\n' ;
|
|
||||||
}
|
}
|
||||||
} else if ( arg == "-v" || arg == "--version" ) {
|
arg = argv[++i];
|
||||||
arg = "print(version())" ;
|
|
||||||
} else if ( arg == "-h" || arg == "--help" ) {
|
} else if (arg == "-" || arg == "--stdin") {
|
||||||
|
arg = "";
|
||||||
|
std::string line;
|
||||||
|
while (std::getline(std::cin, line)) {
|
||||||
|
arg += line + '\n';
|
||||||
|
}
|
||||||
|
} else if (arg == "-v" || arg == "--version") {
|
||||||
|
arg = "print(version())";
|
||||||
|
} else if (arg == "-h" || arg == "--help") {
|
||||||
arg = "help(-1)";
|
arg = "help(-1)";
|
||||||
} else if ( arg == "-e" || arg == "--evalerrorok" ) {
|
} else if (arg == "-e" || arg == "--evalerrorok") {
|
||||||
eval_error_ok = true;
|
eval_error_ok = true;
|
||||||
continue;
|
continue;
|
||||||
} else if ( arg == "--exception" ) {
|
} else if (arg == "--exception") {
|
||||||
boxed_exception_ok = true;
|
boxed_exception_ok = true;
|
||||||
continue;
|
continue;
|
||||||
} else if ( arg == "--any-exception" ) {
|
} else if (arg == "--any-exception") {
|
||||||
any_exception_ok = true;
|
any_exception_ok = true;
|
||||||
continue;
|
continue;
|
||||||
} else if ( arg == "-i" || arg == "--interactive" ) {
|
} else if (arg == "-i" || arg == "--interactive") {
|
||||||
mode = eInteractive ;
|
mode = eInteractive;
|
||||||
} else if ( arg.find('-') == 0 ) {
|
} else if (arg.find('-') == 0) {
|
||||||
std::cout << "unrecognised argument " << arg << '\n';
|
std::cout << "unrecognised argument " << arg << '\n';
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
} else {
|
} else {
|
||||||
@ -358,7 +327,7 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
switch ( mode ) {
|
switch (mode) {
|
||||||
case eInteractive:
|
case eInteractive:
|
||||||
interactive(chai);
|
interactive(chai);
|
||||||
break;
|
break;
|
||||||
@ -368,32 +337,28 @@ int main(int argc, char *argv[])
|
|||||||
case eFile:
|
case eFile:
|
||||||
chai.eval_file(arg);
|
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 << ee.pretty_print();
|
||||||
std::cout << '\n';
|
std::cout << '\n';
|
||||||
|
|
||||||
if (!eval_error_ok) {
|
if (!eval_error_ok) {
|
||||||
return EXIT_FAILURE;
|
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';
|
std::cout << "Unhandled exception thrown of type " << e.get_type_info().name() << '\n';
|
||||||
|
|
||||||
if (!boxed_exception_ok) {
|
if (!boxed_exception_ok) {
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
} catch (const chaiscript::exception::load_module_error &e) {
|
||||||
catch (const chaiscript::exception::load_module_error &e) {
|
std::cout << "Unhandled module load error\n"
|
||||||
std::cout << "Unhandled module load error\n" << e.what() << '\n';
|
<< e.what() << '\n';
|
||||||
}
|
} catch (std::exception &e) {
|
||||||
catch (std::exception &e) {
|
|
||||||
std::cout << "Unhandled standard exception: " << e.what() << '\n';
|
std::cout << "Unhandled standard exception: " << e.what() << '\n';
|
||||||
if (!any_exception_ok) {
|
if (!any_exception_ok) {
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
}
|
} catch (...) {
|
||||||
catch (...) {
|
|
||||||
std::cout << "Unhandled unknown exception" << '\n';
|
std::cout << "Unhandled unknown exception" << '\n';
|
||||||
if (!any_exception_ok) {
|
if (!any_exception_ok) {
|
||||||
throw;
|
throw;
|
||||||
|
|||||||
@ -4,67 +4,52 @@
|
|||||||
// and Jason Turner (jason@emptycrate.com)
|
// and Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
|
// NOT TO BE USED AS A SOURCE OF BEST PRACTICES
|
||||||
// NOT TO BE USED AS A SOURCE OF BEST PRACTICES
|
|
||||||
// FOR CHAISCRIPT
|
// FOR CHAISCRIPT
|
||||||
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
#include <chaiscript/chaiscript.hpp>
|
#include <chaiscript/chaiscript.hpp>
|
||||||
#include <chaiscript/dispatchkit/bootstrap_stl.hpp>
|
#include <chaiscript/dispatchkit/bootstrap_stl.hpp>
|
||||||
#include <chaiscript/dispatchkit/function_call.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';
|
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';
|
std::cout << "[" << time(nullptr) << "] <" << module << "> " << msg << '\n';
|
||||||
}
|
}
|
||||||
|
|
||||||
void bound_log(const std::string &msg)
|
void bound_log(const std::string &msg) {
|
||||||
{
|
|
||||||
log(msg);
|
log(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void hello_world(const chaiscript::Boxed_Value & /*o*/)
|
void hello_world(const chaiscript::Boxed_Value & /*o*/) {
|
||||||
{
|
|
||||||
std::cout << "Hello World\n";
|
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";
|
std::cout << "Hello Constructor\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct System {
|
||||||
|
std::map<std::string, std::function<std::string(const std::string &)>> m_callbacks;
|
||||||
|
|
||||||
struct System
|
void add_callback(const std::string &t_name, const std::function<std::string(const std::string &)> &t_func) {
|
||||||
{
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
m_callbacks[t_name] = 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);
|
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));
|
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';
|
std::cout << *p << '\n';
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,27 +57,26 @@ int main(int /*argc*/, char * /*argv*/[]) {
|
|||||||
using namespace chaiscript;
|
using namespace chaiscript;
|
||||||
|
|
||||||
ChaiScript chai;
|
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;
|
System system;
|
||||||
chai.add_global(var(&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");
|
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::add_callback), "add_callback");
|
||||||
chai.add(fun(&System::do_callbacks), "do_callbacks");
|
chai.add(fun(&System::do_callbacks), "do_callbacks");
|
||||||
|
|
||||||
chai.add(fun(&take_shared_ptr), "take_shared_ptr");
|
chai.add(fun(&take_shared_ptr), "take_shared_ptr");
|
||||||
|
|
||||||
// Let's use chaiscript to add a new lambda callback to our system.
|
// Let's use chaiscript to add a new lambda callback to our system.
|
||||||
// The function "{ 'Callback1' + x }" is created in chaiscript and passed into our C++ application
|
// The function "{ 'Callback1' + x }" is created in chaiscript and passed into our C++ application
|
||||||
// in the "add_callback" function of struct System the chaiscript function is converted into a
|
// in the "add_callback" function of struct System the chaiscript function is converted into a
|
||||||
// std::function, so it can be handled and called easily and type-safely
|
// std::function, so it can be handled and called easily and type-safely
|
||||||
chai.eval(R"(system.add_callback("#1", fun(x) { "Callback1 " + x });)");
|
chai.eval(R"(system.add_callback("#1", fun(x) { "Callback1 " + x });)");
|
||||||
|
|
||||||
// Because we are sharing the "system" object with the chaiscript engine we have equal
|
// Because we are sharing the "system" object with the chaiscript engine we have equal
|
||||||
// access to it both from within chaiscript and from C++ code
|
// access to it both from within chaiscript and from C++ code
|
||||||
system.do_callbacks("TestString");
|
system.do_callbacks("TestString");
|
||||||
@ -111,29 +95,26 @@ int main(int /*argc*/, char * /*argv*/[]) {
|
|||||||
// A shortcut to using eval is just to use the chai operator()
|
// A shortcut to using eval is just to use the chai operator()
|
||||||
chai(R"(log("Test Module", "Test Message");)");
|
chai(R"(log("Test Module", "Test Message");)");
|
||||||
|
|
||||||
//Finally, it is possible to register a lambda as a system function, in this
|
// 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
|
// 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");
|
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()");
|
chai("do_callbacks()");
|
||||||
|
|
||||||
std::function<void ()> caller = chai.eval<std::function<void ()> >(
|
std::function<void()> caller = chai.eval<std::function<void()>>(R"(fun() { system.do_callbacks("From Functor"); })");
|
||||||
R"(fun() { system.do_callbacks("From Functor"); })"
|
|
||||||
);
|
|
||||||
caller();
|
caller();
|
||||||
|
|
||||||
|
// If we would like a type-safe return value from all call, we can use
|
||||||
//If we would like a type-safe return value from all call, we can use
|
// the templated version of eval:
|
||||||
//the templated version of eval:
|
|
||||||
int i = chai.eval<int>("5+5");
|
int i = chai.eval<int>("5+5");
|
||||||
|
|
||||||
std::cout << "5+5: " << i << '\n';
|
std::cout << "5+5: " << i << '\n';
|
||||||
|
|
||||||
//Add a new variable
|
// Add a new variable
|
||||||
chai("var scripti = 15");
|
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");
|
int &scripti = chai.eval<int &>("scripti");
|
||||||
|
|
||||||
std::cout << "scripti: " << scripti << '\n';
|
std::cout << "scripti: " << scripti << '\n';
|
||||||
@ -141,10 +122,10 @@ int main(int /*argc*/, char * /*argv*/[]) {
|
|||||||
std::cout << "scripti (updated): " << scripti << '\n';
|
std::cout << "scripti (updated): " << scripti << '\n';
|
||||||
chai(R"(print("Scripti from chai: " + to_string(scripti)))");
|
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
|
// 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);
|
int x = chai.eval<std::function<int(int, int)>>("fun (x, y) { return x + y; }")(5, 6);
|
||||||
|
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << x;
|
ss << x;
|
||||||
@ -158,25 +139,23 @@ int main(int /*argc*/, char * /*argv*/[]) {
|
|||||||
chai("def getvar() { return constvar; }");
|
chai("def getvar() { return constvar; }");
|
||||||
chai("print( getvar() )");
|
chai("print( getvar() )");
|
||||||
|
|
||||||
|
// Ability to create our own container types when needed. std::vector and std::map are
|
||||||
//Ability to create our own container types when needed. std::vector and std::map are
|
// mostly supported currently
|
||||||
//mostly supported currently
|
// chai.add(bootstrap::standard_library::vector_type<std::vector<int> >("IntVector"));
|
||||||
//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
|
// 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(R"(take_shared_ptr("Hello World as a shared_ptr");)");
|
||||||
|
|
||||||
chai.add(fun(&bound_log, std::string("Msg")), "BoundFun");
|
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_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(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("var x = TestType()");
|
||||||
// chai.eval("x.attr = \"hi\"");
|
// chai.eval("x.attr = \"hi\"");
|
||||||
// chai.eval("print(x.attr)");
|
// chai.eval("print(x.attr)");
|
||||||
chai.eval("x.hello_world()");
|
chai.eval("x.hello_world()");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
222
src/sha3.cpp
222
src/sha3.cpp
@ -11,52 +11,35 @@
|
|||||||
#include <endian.h>
|
#include <endian.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/// same as reset()
|
/// same as reset()
|
||||||
SHA3::SHA3(Bits bits)
|
SHA3::SHA3(Bits bits)
|
||||||
: m_blockSize(200 - 2 * (bits / 8)),
|
: m_blockSize(200 - 2 * (bits / 8))
|
||||||
m_bits(bits)
|
, m_bits(bits) {
|
||||||
{
|
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// restart
|
/// restart
|
||||||
void SHA3::reset()
|
void SHA3::reset() {
|
||||||
{
|
|
||||||
for (size_t i = 0; i < StateSize; i++)
|
for (size_t i = 0; i < StateSize; i++)
|
||||||
m_hash[i] = 0;
|
m_hash[i] = 0;
|
||||||
|
|
||||||
m_numBytes = 0;
|
m_numBytes = 0;
|
||||||
m_bufferSize = 0;
|
m_bufferSize = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// constants and local helper functions
|
/// constants and local helper functions
|
||||||
namespace
|
namespace {
|
||||||
{
|
|
||||||
const unsigned int Rounds = 24;
|
const unsigned int Rounds = 24;
|
||||||
const uint64_t XorMasks[Rounds] =
|
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};
|
||||||
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
|
/// 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));
|
return (x << numBits) | (x >> (64 - numBits));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// convert litte vs big endian
|
/// convert litte vs big endian
|
||||||
inline uint64_t swap(uint64_t x)
|
inline uint64_t swap(uint64_t x) {
|
||||||
{
|
|
||||||
#if defined(__GNUC__) || defined(__clang__)
|
#if defined(__GNUC__) || defined(__clang__)
|
||||||
return __builtin_bswap64(x);
|
return __builtin_bswap64(x);
|
||||||
#endif
|
#endif
|
||||||
@ -64,55 +47,43 @@ namespace
|
|||||||
return _byteswap_uint64(x);
|
return _byteswap_uint64(x);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return (x >> 56) |
|
return (x >> 56) | ((x >> 40) & 0x000000000000FF00ULL) | ((x >> 24) & 0x0000000000FF0000ULL) | ((x >> 8) & 0x00000000FF000000ULL)
|
||||||
((x >> 40) & 0x000000000000FF00ULL) |
|
| ((x << 8) & 0x000000FF00000000ULL) | ((x << 24) & 0x0000FF0000000000ULL) | ((x << 40) & 0x00FF000000000000ULL) | (x << 56);
|
||||||
((x >> 24) & 0x0000000000FF0000ULL) |
|
|
||||||
((x >> 8) & 0x00000000FF000000ULL) |
|
|
||||||
((x << 8) & 0x000000FF00000000ULL) |
|
|
||||||
((x << 24) & 0x0000FF0000000000ULL) |
|
|
||||||
((x << 40) & 0x00FF000000000000ULL) |
|
|
||||||
(x << 56);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// return x % 5 for 0 <= x <= 9
|
/// return x % 5 for 0 <= x <= 9
|
||||||
unsigned int mod5(unsigned int x)
|
unsigned int mod5(unsigned int x) {
|
||||||
{
|
|
||||||
if (x < 5)
|
if (x < 5)
|
||||||
return x;
|
return x;
|
||||||
|
|
||||||
return x - 5;
|
return x - 5;
|
||||||
}
|
}
|
||||||
}
|
} // namespace
|
||||||
|
|
||||||
|
|
||||||
/// process a full block
|
/// 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)
|
#if defined(__BYTE_ORDER) && (__BYTE_ORDER != 0) && (__BYTE_ORDER == __BIG_ENDIAN)
|
||||||
#define LITTLEENDIAN(x) swap(x)
|
#define LITTLEENDIAN(x) swap(x)
|
||||||
#else
|
#else
|
||||||
#define LITTLEENDIAN(x) (x)
|
#define LITTLEENDIAN(x) (x)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const uint64_t* data64 = (const uint64_t*) data;
|
const uint64_t *data64 = (const uint64_t *)data;
|
||||||
// mix data into state
|
// mix data into state
|
||||||
for (unsigned int i = 0; i < m_blockSize / 8; i++)
|
for (unsigned int i = 0; i < m_blockSize / 8; i++)
|
||||||
m_hash[i] ^= LITTLEENDIAN(data64[i]);
|
m_hash[i] ^= LITTLEENDIAN(data64[i]);
|
||||||
|
|
||||||
// re-compute state
|
// re-compute state
|
||||||
for (unsigned int round = 0; round < Rounds; round++)
|
for (unsigned int round = 0; round < Rounds; round++) {
|
||||||
{
|
|
||||||
// Theta
|
// Theta
|
||||||
uint64_t coefficients[5];
|
uint64_t coefficients[5];
|
||||||
for (unsigned int i = 0; i < 5; i++)
|
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];
|
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);
|
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 + 5] ^= one;
|
||||||
m_hash[i + 10] ^= one;
|
m_hash[i + 10] ^= one;
|
||||||
m_hash[i + 15] ^= one;
|
m_hash[i + 15] ^= one;
|
||||||
m_hash[i + 20] ^= one;
|
m_hash[i + 20] ^= one;
|
||||||
@ -123,43 +94,88 @@ void SHA3::processBlock(const void* data)
|
|||||||
|
|
||||||
// Rho Pi
|
// Rho Pi
|
||||||
uint64_t last = m_hash[1];
|
uint64_t last = m_hash[1];
|
||||||
one = m_hash[10]; m_hash[10] = rotateLeft(last, 1); last = one;
|
one = m_hash[10];
|
||||||
one = m_hash[ 7]; m_hash[ 7] = rotateLeft(last, 3); last = one;
|
m_hash[10] = rotateLeft(last, 1);
|
||||||
one = m_hash[11]; m_hash[11] = rotateLeft(last, 6); last = one;
|
last = one;
|
||||||
one = m_hash[17]; m_hash[17] = rotateLeft(last, 10); last = one;
|
one = m_hash[7];
|
||||||
one = m_hash[18]; m_hash[18] = rotateLeft(last, 15); last = one;
|
m_hash[7] = rotateLeft(last, 3);
|
||||||
one = m_hash[ 3]; m_hash[ 3] = rotateLeft(last, 21); last = one;
|
last = one;
|
||||||
one = m_hash[ 5]; m_hash[ 5] = rotateLeft(last, 28); last = one;
|
one = m_hash[11];
|
||||||
one = m_hash[16]; m_hash[16] = rotateLeft(last, 36); last = one;
|
m_hash[11] = rotateLeft(last, 6);
|
||||||
one = m_hash[ 8]; m_hash[ 8] = rotateLeft(last, 45); last = one;
|
last = one;
|
||||||
one = m_hash[21]; m_hash[21] = rotateLeft(last, 55); last = one;
|
one = m_hash[17];
|
||||||
one = m_hash[24]; m_hash[24] = rotateLeft(last, 2); last = one;
|
m_hash[17] = rotateLeft(last, 10);
|
||||||
one = m_hash[ 4]; m_hash[ 4] = rotateLeft(last, 14); last = one;
|
last = one;
|
||||||
one = m_hash[15]; m_hash[15] = rotateLeft(last, 27); last = one;
|
one = m_hash[18];
|
||||||
one = m_hash[23]; m_hash[23] = rotateLeft(last, 41); last = one;
|
m_hash[18] = rotateLeft(last, 15);
|
||||||
one = m_hash[19]; m_hash[19] = rotateLeft(last, 56); last = one;
|
last = one;
|
||||||
one = m_hash[13]; m_hash[13] = rotateLeft(last, 8); last = one;
|
one = m_hash[3];
|
||||||
one = m_hash[12]; m_hash[12] = rotateLeft(last, 25); last = one;
|
m_hash[3] = rotateLeft(last, 21);
|
||||||
one = m_hash[ 2]; m_hash[ 2] = rotateLeft(last, 43); last = one;
|
last = one;
|
||||||
one = m_hash[20]; m_hash[20] = rotateLeft(last, 62); last = one;
|
one = m_hash[5];
|
||||||
one = m_hash[14]; m_hash[14] = rotateLeft(last, 18); last = one;
|
m_hash[5] = rotateLeft(last, 28);
|
||||||
one = m_hash[22]; m_hash[22] = rotateLeft(last, 39); last = one;
|
last = one;
|
||||||
one = m_hash[ 9]; m_hash[ 9] = rotateLeft(last, 61); last = one;
|
one = m_hash[16];
|
||||||
one = m_hash[ 6]; m_hash[ 6] = rotateLeft(last, 20); last = one;
|
m_hash[16] = rotateLeft(last, 36);
|
||||||
m_hash[ 1] = rotateLeft(last, 44);
|
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
|
// Chi
|
||||||
for (unsigned int j = 0; j < 25; j += 5)
|
for (unsigned int j = 0; j < 25; j += 5) {
|
||||||
{
|
|
||||||
// temporaries
|
// temporaries
|
||||||
uint64_t one = m_hash[j];
|
uint64_t one = m_hash[j];
|
||||||
uint64_t two = m_hash[j + 1];
|
uint64_t two = m_hash[j + 1];
|
||||||
|
|
||||||
m_hash[j] ^= m_hash[j + 2] & ~two;
|
m_hash[j] ^= m_hash[j + 2] & ~two;
|
||||||
m_hash[j + 1] ^= m_hash[j + 3] & ~m_hash[j + 2];
|
m_hash[j + 1] ^= m_hash[j + 3] & ~m_hash[j + 2];
|
||||||
m_hash[j + 2] ^= m_hash[j + 4] & ~m_hash[j + 3];
|
m_hash[j + 2] ^= m_hash[j + 4] & ~m_hash[j + 3];
|
||||||
m_hash[j + 3] ^= one & ~m_hash[j + 4];
|
m_hash[j + 3] ^= one & ~m_hash[j + 4];
|
||||||
m_hash[j + 4] ^= two & ~one;
|
m_hash[j + 4] ^= two & ~one;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Iota
|
// Iota
|
||||||
@ -167,27 +183,22 @@ void SHA3::processBlock(const void* data)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// add arbitrary number of bytes
|
/// add arbitrary number of bytes
|
||||||
void SHA3::add(const void* data, size_t numBytes)
|
void SHA3::add(const void *data, size_t numBytes) {
|
||||||
{
|
const uint8_t *current = (const uint8_t *)data;
|
||||||
const uint8_t* current = (const uint8_t*) data;
|
|
||||||
|
|
||||||
// copy data to buffer
|
// copy data to buffer
|
||||||
if (m_bufferSize > 0)
|
if (m_bufferSize > 0) {
|
||||||
{
|
while (numBytes > 0 && m_bufferSize < m_blockSize) {
|
||||||
while (numBytes > 0 && m_bufferSize < m_blockSize)
|
|
||||||
{
|
|
||||||
m_buffer[m_bufferSize++] = *current++;
|
m_buffer[m_bufferSize++] = *current++;
|
||||||
numBytes--;
|
numBytes--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// full buffer
|
// full buffer
|
||||||
if (m_bufferSize == m_blockSize)
|
if (m_bufferSize == m_blockSize) {
|
||||||
{
|
processBlock((void *)m_buffer);
|
||||||
processBlock((void*)m_buffer);
|
m_numBytes += m_blockSize;
|
||||||
m_numBytes += m_blockSize;
|
|
||||||
m_bufferSize = 0;
|
m_bufferSize = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -196,26 +207,22 @@ void SHA3::add(const void* data, size_t numBytes)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// process full blocks
|
// process full blocks
|
||||||
while (numBytes >= m_blockSize)
|
while (numBytes >= m_blockSize) {
|
||||||
{
|
|
||||||
processBlock(current);
|
processBlock(current);
|
||||||
current += m_blockSize;
|
current += m_blockSize;
|
||||||
m_numBytes += m_blockSize;
|
m_numBytes += m_blockSize;
|
||||||
numBytes -= m_blockSize;
|
numBytes -= m_blockSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
// keep remaining bytes in buffer
|
// keep remaining bytes in buffer
|
||||||
while (numBytes > 0)
|
while (numBytes > 0) {
|
||||||
{
|
|
||||||
m_buffer[m_bufferSize++] = *current++;
|
m_buffer[m_bufferSize++] = *current++;
|
||||||
numBytes--;
|
numBytes--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// process everything left in the internal buffer
|
/// process everything left in the internal buffer
|
||||||
void SHA3::processBuffer()
|
void SHA3::processBuffer() {
|
||||||
{
|
|
||||||
// add padding
|
// add padding
|
||||||
size_t offset = m_bufferSize;
|
size_t offset = m_bufferSize;
|
||||||
// add a "1" byte
|
// add a "1" byte
|
||||||
@ -230,10 +237,8 @@ void SHA3::processBuffer()
|
|||||||
processBlock(m_buffer);
|
processBlock(m_buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// return latest hash as 16 hex characters
|
/// return latest hash as 16 hex characters
|
||||||
std::string SHA3::getHash()
|
std::string SHA3::getHash() {
|
||||||
{
|
|
||||||
// process remaining bytes
|
// process remaining bytes
|
||||||
processBuffer();
|
processBuffer();
|
||||||
|
|
||||||
@ -249,7 +254,7 @@ std::string SHA3::getHash()
|
|||||||
for (unsigned int j = 0; j < 8; j++) // 64 bits => 8 bytes
|
for (unsigned int j = 0; j < 8; j++) // 64 bits => 8 bytes
|
||||||
{
|
{
|
||||||
// convert a byte to hex
|
// 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 >> 4];
|
||||||
result += dec2hex[oneByte & 15];
|
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
|
// 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 remainder = m_bits - hashLength * 64;
|
||||||
unsigned int processed = 0;
|
unsigned int processed = 0;
|
||||||
while (processed < remainder)
|
while (processed < remainder) {
|
||||||
{
|
|
||||||
// convert a byte to hex
|
// 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 >> 4];
|
||||||
result += dec2hex[oneByte & 15];
|
result += dec2hex[oneByte & 15];
|
||||||
|
|
||||||
@ -270,19 +274,15 @@ std::string SHA3::getHash()
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// compute SHA3 of a memory block
|
/// 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();
|
reset();
|
||||||
add(data, numBytes);
|
add(data, numBytes);
|
||||||
return getHash();
|
return getHash();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// compute SHA3 of a string, excluding final zero
|
/// 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();
|
reset();
|
||||||
add(text.c_str(), text.size());
|
add(text.c_str(), text.size());
|
||||||
return getHash();
|
return getHash();
|
||||||
|
|||||||
@ -7,7 +7,6 @@
|
|||||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
// 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
|
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||||
|
|
||||||
|
|
||||||
#include <chaiscript/chaiscript_basic.hpp>
|
#include <chaiscript/chaiscript_basic.hpp>
|
||||||
#include <chaiscript/dispatchkit/bootstrap_stl.hpp>
|
#include <chaiscript/dispatchkit/bootstrap_stl.hpp>
|
||||||
#include <list>
|
#include <list>
|
||||||
@ -25,11 +24,10 @@
|
|||||||
#pragma clang diagnostic ignored "-Wreturn-type-c-linkage"
|
#pragma clang diagnostic ignored "-Wreturn-type-c-linkage"
|
||||||
#endif
|
#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>();
|
auto module = std::make_shared<chaiscript::Module>();
|
||||||
chaiscript::bootstrap::standard_library::list_type<std::list<chaiscript::Boxed_Value> >("List", *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::vector_type<std::vector<uint16_t>>("u16vector", *module);
|
||||||
module->add(chaiscript::vector_conversion<std::vector<uint16_t>>());
|
module->add(chaiscript::vector_conversion<std::vector<uint16_t>>());
|
||||||
return module;
|
return module;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,138 +3,121 @@
|
|||||||
#include <chaiscript/dispatchkit/bootstrap.hpp>
|
#include <chaiscript/dispatchkit/bootstrap.hpp>
|
||||||
#include <string>
|
#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{} {
|
||||||
|
}
|
||||||
|
|
||||||
|
TestBaseType(const TestBaseType &other)
|
||||||
|
: val(other.val)
|
||||||
|
, const_val(other.const_val)
|
||||||
|
, const_val_ptr(&const_val)
|
||||||
|
, func_member(other.func_member) {
|
||||||
|
}
|
||||||
|
|
||||||
class TestBaseType
|
TestBaseType(TestBaseType &&other)
|
||||||
{
|
: val(other.val)
|
||||||
public:
|
, const_val(other.const_val)
|
||||||
TestBaseType() : val(10), const_val(15), mdarray{} { }
|
, const_val_ptr(&const_val)
|
||||||
TestBaseType(int) : val(10), const_val(15), mdarray{} { }
|
, func_member(std::move(other.func_member)) {
|
||||||
TestBaseType(int *) : val(10), const_val(15), mdarray{} { }
|
}
|
||||||
|
|
||||||
TestBaseType(const TestBaseType &other)
|
TestBaseType &operator=(TestBaseType &&) = delete;
|
||||||
: val(other.val), const_val(other.const_val), const_val_ptr(&const_val),
|
TestBaseType &operator=(const TestBaseType &) = delete;
|
||||||
func_member(other.func_member)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
TestBaseType(TestBaseType &&other)
|
virtual ~TestBaseType() = default;
|
||||||
: val(other.val), const_val(other.const_val), const_val_ptr(&const_val),
|
virtual int func() { return 0; }
|
||||||
func_member(std::move(other.func_member))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
int base_only_func() { return -9; }
|
||||||
|
|
||||||
TestBaseType &operator=(TestBaseType &&) = delete;
|
const TestBaseType &constMe() const { return *this; }
|
||||||
TestBaseType &operator=(const TestBaseType &) = delete;
|
|
||||||
|
|
||||||
virtual ~TestBaseType() = default;
|
int val;
|
||||||
virtual int func() { return 0; }
|
const int const_val;
|
||||||
|
const int *const_val_ptr = &const_val;
|
||||||
|
|
||||||
int base_only_func() { return -9; }
|
const int *get_const_val_ptr() { return const_val_ptr; }
|
||||||
|
|
||||||
const TestBaseType &constMe() const { return *this; }
|
int mdarray[2][3][5];
|
||||||
|
std::function<int(int)> func_member;
|
||||||
int val;
|
|
||||||
const int const_val;
|
|
||||||
const int *const_val_ptr = &const_val;
|
|
||||||
|
|
||||||
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";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
void set_string_val(std::string &t_str) { t_str = "42"; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class Type2
|
class Type2 {
|
||||||
{
|
public:
|
||||||
public:
|
Type2(TestBaseType t_bt)
|
||||||
Type2(TestBaseType t_bt)
|
: m_bt(std::move(t_bt))
|
||||||
: m_bt(std::move(t_bt)),
|
, m_str("Hello World") {
|
||||||
m_str("Hello World")
|
}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
int get_val() const
|
int get_val() const { return m_bt.val; }
|
||||||
{
|
|
||||||
return m_bt.val;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
const char *get_str() const { return m_str.c_str(); }
|
||||||
|
|
||||||
const char *get_str() const
|
private:
|
||||||
{
|
TestBaseType m_bt;
|
||||||
return m_str.c_str();
|
std::string m_str;
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
TestBaseType m_bt;
|
|
||||||
std::string m_str;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum TestEnum
|
enum TestEnum {
|
||||||
{
|
|
||||||
TestValue1 = 1
|
TestValue1 = 1
|
||||||
};
|
};
|
||||||
|
|
||||||
int to_int(TestEnum t)
|
int to_int(TestEnum t) {
|
||||||
{
|
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
class TestDerivedType : public TestBaseType
|
class TestDerivedType : public TestBaseType {
|
||||||
{
|
public:
|
||||||
public:
|
int func() override { return 1; }
|
||||||
int func() override { return 1; }
|
int derived_only_func() { return 19; }
|
||||||
int derived_only_func() { return 19; }
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class TestMoreDerivedType : public TestDerivedType
|
class TestMoreDerivedType : public TestDerivedType {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
};
|
};
|
||||||
|
|
||||||
std::shared_ptr<TestBaseType> derived_type_factory()
|
std::shared_ptr<TestBaseType> derived_type_factory() {
|
||||||
{
|
|
||||||
return std::make_shared<TestDerivedType>();
|
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>();
|
return std::make_shared<TestMoreDerivedType>();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<TestBaseType> null_factory()
|
std::shared_ptr<TestBaseType> null_factory() {
|
||||||
{
|
|
||||||
return std::shared_ptr<TestBaseType>();
|
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>();
|
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;
|
ptr = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string hello_world()
|
std::string hello_world() {
|
||||||
{
|
|
||||||
return "Hello World";
|
return "Hello World";
|
||||||
}
|
}
|
||||||
|
|
||||||
static int global_i = 1;
|
static int global_i = 1;
|
||||||
|
|
||||||
int *get_new_int()
|
int *get_new_int() {
|
||||||
{
|
|
||||||
return &global_i;
|
return &global_i;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,8 +133,7 @@ int *get_new_int()
|
|||||||
#pragma clang diagnostic ignored "-Wreturn-type-c-linkage"
|
#pragma clang diagnostic ignored "-Wreturn-type-c-linkage"
|
||||||
#endif
|
#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());
|
chaiscript::ModulePtr m(new chaiscript::Module());
|
||||||
|
|
||||||
m->add(chaiscript::fun(hello_world), "hello_world");
|
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<TestMoreDerivedType>(), "TestMoreDerivedType");
|
||||||
m->add(chaiscript::user_type<Type2>(), "Type2");
|
m->add(chaiscript::user_type<Type2>(), "Type2");
|
||||||
|
|
||||||
m->add(chaiscript::constructor<TestBaseType ()>(), "TestBaseType");
|
m->add(chaiscript::constructor<TestBaseType()>(), "TestBaseType");
|
||||||
// m->add(chaiscript::constructor<TestBaseType (int)>(), "TestBaseType");
|
// m->add(chaiscript::constructor<TestBaseType (int)>(), "TestBaseType");
|
||||||
m->add(chaiscript::constructor<TestBaseType (const TestBaseType &)>(), "TestBaseType");
|
m->add(chaiscript::constructor<TestBaseType(const TestBaseType &)>(), "TestBaseType");
|
||||||
m->add(chaiscript::constructor<TestBaseType (int *)>(), "TestBaseType");
|
m->add(chaiscript::constructor<TestBaseType(int *)>(), "TestBaseType");
|
||||||
|
|
||||||
m->add(chaiscript::constructor<TestDerivedType ()>(), "TestDerivedType");
|
m->add(chaiscript::constructor<TestDerivedType()>(), "TestDerivedType");
|
||||||
m->add(chaiscript::constructor<TestDerivedType (const TestDerivedType &)>(), "TestDerivedType");
|
m->add(chaiscript::constructor<TestDerivedType(const TestDerivedType &)>(), "TestDerivedType");
|
||||||
|
|
||||||
m->add(chaiscript::constructor<TestMoreDerivedType ()>(), "TestMoreDerivedType");
|
m->add(chaiscript::constructor<TestMoreDerivedType()>(), "TestMoreDerivedType");
|
||||||
m->add(chaiscript::constructor<TestMoreDerivedType (const TestMoreDerivedType &)>(), "TestMoreDerivedType");
|
m->add(chaiscript::constructor<TestMoreDerivedType(const TestMoreDerivedType &)>(), "TestMoreDerivedType");
|
||||||
|
|
||||||
/// \todo automatic chaining of base classes?
|
/// \todo automatic chaining of base classes?
|
||||||
m->add(chaiscript::base_class<TestBaseType, TestDerivedType>());
|
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(&TestBaseType::func_member), "func_member");
|
||||||
m->add(chaiscript::fun(&get_new_int), "get_new_int");
|
m->add(chaiscript::fun(&get_new_int), "get_new_int");
|
||||||
|
|
||||||
|
|
||||||
m->add_global_const(chaiscript::const_var(TestValue1), "TestValue1");
|
m->add_global_const(chaiscript::const_var(TestValue1), "TestValue1");
|
||||||
|
|
||||||
m->add(chaiscript::user_type<TestEnum>(), "TestEnum");
|
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_val), "get_val");
|
||||||
m->add(chaiscript::fun(&Type2::get_str), "get_str");
|
m->add(chaiscript::fun(&Type2::get_str), "get_str");
|
||||||
m->add(chaiscript::type_conversion<const char *, std::string>());
|
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(&update_shared_ptr), "update_shared_ptr");
|
||||||
m->add(chaiscript::fun(&nullify_shared_ptr), "nullify_shared_ptr");
|
m->add(chaiscript::fun(&nullify_shared_ptr), "nullify_shared_ptr");
|
||||||
|
|
||||||
|
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef __llvm__
|
#ifdef __llvm__
|
||||||
#pragma clang diagnostic pop
|
#pragma clang diagnostic pop
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -1,8 +1,6 @@
|
|||||||
#include "../include/chaiscript/language/chaiscript_parser.hpp"
|
#include "../include/chaiscript/language/chaiscript_parser.hpp"
|
||||||
#include "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>>();
|
return std::make_unique<chaiscript::parser::ChaiScript_Parser<chaiscript::eval::Noop_Tracer, chaiscript::optimizer::Optimizer_Default>>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -2,11 +2,13 @@
|
|||||||
#ifndef CHAISCRIPT_PARSER_LIB
|
#ifndef CHAISCRIPT_PARSER_LIB
|
||||||
#define CHAISCRIPT_PARSER_LIB
|
#define CHAISCRIPT_PARSER_LIB
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
namespace chaiscript {
|
namespace chaiscript {
|
||||||
namespace parser {
|
namespace parser {
|
||||||
class ChaiScript_Parser_Base;
|
class ChaiScript_Parser_Base;
|
||||||
}
|
}
|
||||||
}
|
} // namespace chaiscript
|
||||||
|
|
||||||
std::unique_ptr<chaiscript::parser::ChaiScript_Parser_Base> create_chaiscript_parser();
|
std::unique_ptr<chaiscript::parser::ChaiScript_Parser_Base> create_chaiscript_parser();
|
||||||
|
|
||||||
|
|||||||
@ -1,8 +1,6 @@
|
|||||||
#include "../include/chaiscript/chaiscript_stdlib.hpp"
|
#include "../include/chaiscript/chaiscript_stdlib.hpp"
|
||||||
#include "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();
|
return chaiscript::Std_Lib::library();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,15 +1,13 @@
|
|||||||
#include <chaiscript/utility/utility.hpp>
|
#include <chaiscript/utility/utility.hpp>
|
||||||
|
|
||||||
|
|
||||||
using namespace chaiscript;
|
using namespace chaiscript;
|
||||||
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void use(T){}
|
void use(T) {
|
||||||
|
}
|
||||||
|
|
||||||
template<typename To>
|
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 {
|
try {
|
||||||
To ret = chaiscript::boxed_cast<To>(bv);
|
To ret = chaiscript::boxed_cast<To>(bv);
|
||||||
use(ret);
|
use(ret);
|
||||||
@ -26,36 +24,52 @@ bool run_test_type_conversion(const Boxed_Value &bv, bool expectedpass)
|
|||||||
std::cerr << "Unexpected unknown exception when attempting cast_conversion.\n";
|
std::cerr << "Unexpected unknown exception when attempting cast_conversion.\n";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return expectedpass;
|
return expectedpass;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename To>
|
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);
|
bool ret = run_test_type_conversion<To>(bv, expectedpass);
|
||||||
|
|
||||||
if (!ret)
|
if (!ret) {
|
||||||
{
|
std::cerr << "Error with type conversion test. From: " << (bv.is_const() ? "const " : "")
|
||||||
std::cerr << "Error with type conversion test. From: "
|
<< bv.get_type_info().name() << " To: " << (std::is_const<To>::value ? "const " : "")
|
||||||
<< (bv.is_const()?(std::string("const ")):(std::string())) << bv.get_type_info().name()
|
<< typeid(To).name() << " test was expected to " << (expectedpass ? "succeed" : "fail")
|
||||||
<< " To: "
|
<< " but did not\n";
|
||||||
<< (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";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Type>
|
template<typename Type>
|
||||||
bool do_test(const Boxed_Value &bv,
|
bool do_test(const Boxed_Value &bv,
|
||||||
bool T, bool ConstT, bool TRef, bool ConstTRef, bool TPtr,
|
bool T,
|
||||||
bool ConstTPtr, bool TPtrConst, bool ConstTPtrConst, bool SharedPtrT, bool SharedConstPtrT,
|
bool ConstT,
|
||||||
bool SharedPtrTRef, bool ConstSharedPtrT, bool ConstSharedConstPtrT, bool ConstSharedPtrTRef, bool ConstSharedPtrTConstRef,
|
bool TRef,
|
||||||
bool WrappedRef, bool WrappedConstRef, bool ConstWrappedRef, bool ConstWrappedConstRef, bool ConstWrappedRefRef,
|
bool ConstTRef,
|
||||||
bool ConstWrappedConstRefRef, bool Number, bool ConstNumber, bool ConstNumberRef, bool TPtrConstRef,
|
bool TPtr,
|
||||||
bool ConstTPtrConstRef)
|
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;
|
bool passed = true;
|
||||||
passed &= test_type_conversion<Type>(bv, T);
|
passed &= test_type_conversion<Type>(bv, T);
|
||||||
passed &= test_type_conversion<const Type>(bv, ConstT);
|
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<const Type &>(bv, ConstTRef);
|
||||||
passed &= test_type_conversion<Type *>(bv, TPtr);
|
passed &= test_type_conversion<Type *>(bv, TPtr);
|
||||||
passed &= test_type_conversion<const Type *>(bv, ConstTPtr);
|
passed &= test_type_conversion<const Type *>(bv, ConstTPtr);
|
||||||
passed &= test_type_conversion<Type * const>(bv, TPtrConst);
|
passed &= test_type_conversion<Type *const>(bv, TPtrConst);
|
||||||
passed &= test_type_conversion<const Type * const>(bv, ConstTPtrConst);
|
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<Type>>(bv, SharedPtrT);
|
||||||
passed &= test_type_conversion<std::shared_ptr<const Type> >(bv, SharedConstPtrT);
|
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<Type> &>(bv, SharedPtrTRef);
|
||||||
//passed &= test_type_conversion<std::shared_ptr<const Type> &>(bv, false);
|
// 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<Type>>(bv, ConstSharedPtrT);
|
||||||
passed &= test_type_conversion<const std::shared_ptr<const Type> >(bv, ConstSharedConstPtrT);
|
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<Type> &>(bv, ConstSharedPtrTRef);
|
||||||
passed &= test_type_conversion<const std::shared_ptr<const Type> &>(bv, ConstSharedPtrTConstRef);
|
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<Type>>(bv, WrappedRef);
|
||||||
passed &= test_type_conversion<std::reference_wrapper<const Type> >(bv, WrappedConstRef);
|
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<Type> &>(bv, false);
|
||||||
passed &= test_type_conversion<std::reference_wrapper<const 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<Type>>(bv, ConstWrappedRef);
|
||||||
passed &= test_type_conversion<const std::reference_wrapper<const Type> >(bv, ConstWrappedConstRef);
|
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<Type> &>(bv, ConstWrappedRefRef);
|
||||||
passed &= test_type_conversion<const std::reference_wrapper<const Type> &>(bv, ConstWrappedConstRefRef);
|
passed &= test_type_conversion<const std::reference_wrapper<const Type> &>(bv, ConstWrappedConstRefRef);
|
||||||
passed &= test_type_conversion<Boxed_Number>(bv, Number);
|
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<const Boxed_Number &>(bv, ConstNumberRef);
|
||||||
passed &= test_type_conversion<Boxed_Number *>(bv, false);
|
passed &= test_type_conversion<Boxed_Number *>(bv, false);
|
||||||
passed &= test_type_conversion<const 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<const Boxed_Number *const>(bv, false);
|
||||||
passed &= test_type_conversion<Type *&>(bv, false);
|
passed &= test_type_conversion<Type *&>(bv, false);
|
||||||
passed &= test_type_conversion<const Type *&>(bv, false);
|
passed &= test_type_conversion<const Type *&>(bv, false);
|
||||||
passed &= test_type_conversion<Type * const&>(bv, TPtrConstRef);
|
passed &= test_type_conversion<Type *const &>(bv, TPtrConstRef);
|
||||||
passed &= test_type_conversion<const Type * const&>(bv, ConstTPtrConstRef);
|
passed &= test_type_conversion<const Type *const &>(bv, ConstTPtrConstRef);
|
||||||
passed &= test_type_conversion<Boxed_Value>(bv, true);
|
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);
|
||||||
passed &= test_type_conversion<const Boxed_Value &>(bv, true);
|
passed &= test_type_conversion<const Boxed_Value &>(bv, true);
|
||||||
@ -102,154 +116,524 @@ bool do_test(const Boxed_Value &bv,
|
|||||||
|
|
||||||
/** Tests intended for built int types **/
|
/** Tests intended for built int types **/
|
||||||
template<typename T>
|
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;
|
bool passed = true;
|
||||||
|
|
||||||
/** value tests **/
|
/** value tests **/
|
||||||
T i = T(initial);
|
T i = T(initial);
|
||||||
passed &= do_test<T>(var(i), true, true, true, 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,
|
||||||
ispod, ispod, ispod, 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,
|
passed &= do_test<T>(const_var(i),
|
||||||
true, false, true, false, true,
|
true,
|
||||||
false, false, true, false, true, false,
|
true,
|
||||||
true, false, true, false, true,
|
false,
|
||||||
ispod, ispod, ispod, false, true);
|
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,
|
passed &= do_test<T>(var(&i),
|
||||||
true, true, true, false, false,
|
true,
|
||||||
false, false, false, false, false, true,
|
true,
|
||||||
true, true, true, true, true,
|
true,
|
||||||
ispod, ispod, ispod, 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,
|
passed &= do_test<T>(const_var(&i),
|
||||||
true, false, true, false, false,
|
true,
|
||||||
false, false, false, false, false, false,
|
true,
|
||||||
true, false, true, false, true,
|
false,
|
||||||
ispod, ispod, ispod, false, true);
|
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,
|
passed &= do_test<T>(var(std::ref(i)),
|
||||||
true, true, true, false, false,
|
true,
|
||||||
false, false, false, false, false, true,
|
true,
|
||||||
true, true, true, true, true,
|
true,
|
||||||
ispod, ispod, ispod, 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,
|
passed &= do_test<T>(var(std::cref(i)),
|
||||||
true, false, true, false, false,
|
true,
|
||||||
false, false, false, false, false, false,
|
true,
|
||||||
true, false, true, false, true,
|
false,
|
||||||
ispod, ispod, ispod, false, true);
|
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 */
|
/** Const Reference Variable tests */
|
||||||
|
|
||||||
// This reference will be copied on input, which is expected
|
// This reference will be copied on input, which is expected
|
||||||
const T &ir = i;
|
const T &ir = i;
|
||||||
|
|
||||||
passed &= do_test<T>(var(i), true, true, true, 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,
|
||||||
ispod, ispod, ispod, 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
|
// But a pointer or reference to it should be necessarily const
|
||||||
passed &= do_test<T>(var(&ir), true, true, false, true, false,
|
passed &= do_test<T>(var(&ir),
|
||||||
true, false, true, false, false,
|
true,
|
||||||
false, false, false, false, false, false,
|
true,
|
||||||
true, false, true, false, true,
|
false,
|
||||||
ispod, ispod, ispod, false, true);
|
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,
|
passed &= do_test<T>(var(std::ref(ir)),
|
||||||
true, false, true, false, false,
|
true,
|
||||||
false, false, false, false, false, false,
|
true,
|
||||||
true, false, true, false, true,
|
false,
|
||||||
ispod, ispod, ispod, false, true);
|
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
|
// Make sure const of const works too
|
||||||
passed &= do_test<T>(const_var(&ir), true, true, false, true, false,
|
passed &= do_test<T>(const_var(&ir),
|
||||||
true, false, true, false, false,
|
true,
|
||||||
false, false, false, false, false, false,
|
true,
|
||||||
true, false, true, false, true,
|
false,
|
||||||
ispod, ispod, ispod, false, true);
|
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,
|
passed &= do_test<T>(const_var(std::ref(ir)),
|
||||||
true, false, true, false, false,
|
true,
|
||||||
false, false, false, false, false, false,
|
true,
|
||||||
true, false, true, false, true,
|
false,
|
||||||
ispod, ispod, ispod, false, true);
|
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 */
|
/** Const Reference Variable tests */
|
||||||
|
|
||||||
// This will always be seen as a const
|
// This will always be seen as a const
|
||||||
const T*cip = &i;
|
const T *cip = &i;
|
||||||
passed &= do_test<T>(var(cip), true, true, false, true, false,
|
passed &= do_test<T>(var(cip),
|
||||||
true, false, true, false, false,
|
true,
|
||||||
false, false, false, false, false, false,
|
true,
|
||||||
true, false, true, false, true,
|
false,
|
||||||
ispod, ispod, ispod, false, true);
|
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
|
// make sure const of const works
|
||||||
passed &= do_test<T>(const_var(cip), true, true, false, true, false,
|
passed &= do_test<T>(const_var(cip),
|
||||||
true, false, true, false, false,
|
true,
|
||||||
false, false, false, false, false, false,
|
true,
|
||||||
true, false, true, false, true,
|
false,
|
||||||
ispod, ispod, ispod, false, true);
|
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 **/
|
/** shared_ptr tests **/
|
||||||
|
|
||||||
auto ip = std::make_shared<T>(initial);
|
auto ip = std::make_shared<T>(initial);
|
||||||
|
|
||||||
passed &= do_test<T>(var(ip), true, true, true, 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,
|
||||||
ispod, ispod, ispod, 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,
|
passed &= do_test<T>(const_var(ip),
|
||||||
true, false, true, false, true,
|
true,
|
||||||
false, false, true, false, true, false,
|
true,
|
||||||
true, false, true, false, true,
|
false,
|
||||||
ispod, ispod, ispod, false, true);
|
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 **/
|
/** const shared_ptr tests **/
|
||||||
auto ipc = std::make_shared<const T>(T(initial));
|
auto ipc = std::make_shared<const T>(T(initial));
|
||||||
|
|
||||||
passed &= do_test<T>(var(ipc), true, true, false, true, false,
|
passed &= do_test<T>(var(ipc),
|
||||||
true, false, true, false, true,
|
true,
|
||||||
false, false, true, false, true, false,
|
true,
|
||||||
true, false, true, false, true,
|
false,
|
||||||
ispod, ispod, ispod, false, true);
|
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
|
// const of this should be the same, making sure it compiles
|
||||||
passed &= do_test<T>(const_var(ipc), true, true, false, true, false,
|
passed &= do_test<T>(const_var(ipc),
|
||||||
true, false, true, false, true,
|
true,
|
||||||
false, false, true, false, true, false,
|
true,
|
||||||
true, false, true, false, true,
|
false,
|
||||||
ispod, ispod, ispod, false, true);
|
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 **/
|
/** Double ptr tests **/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
T **doublep;
|
T **doublep;
|
||||||
|
|
||||||
passed &= do_test<T*>(var(doublep), true, true, false, true, false,
|
passed &= do_test<T*>(var(doublep), true, true, false, true, false,
|
||||||
true, false, true, false, true,
|
true, false, true, false, true,
|
||||||
false, true, false, true, false,
|
false, true, false, true, false,
|
||||||
true, false, true, false, true,
|
true, false, true, false, true,
|
||||||
ispod, ispod, ispod, false, true);
|
ispod, ispod, ispod, false, true);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
return passed;
|
return passed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<typename T>
|
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);
|
T *p = new T(default_value);
|
||||||
|
|
||||||
// we store a pointer to a pointer, so we can get a pointer to a pointer
|
// 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));
|
T **result = boxed_cast<T **>(var(&p));
|
||||||
*(*result) = new_value;
|
*(*result) = new_value;
|
||||||
|
|
||||||
|
if (p != (*result)) {
|
||||||
if (p != (*result) ) {
|
|
||||||
std::cerr << "Pointer passed in different than one returned\n";
|
std::cerr << "Pointer passed in different than one returned\n";
|
||||||
delete p;
|
delete p;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*p != *(*result) ) {
|
if (*p != *(*result)) {
|
||||||
std::cerr << "Somehow dereferenced pointer values are not the same?\n";
|
std::cerr << "Somehow dereferenced pointer values are not the same?\n";
|
||||||
delete p;
|
delete p;
|
||||||
return false;
|
return false;
|
||||||
@ -283,18 +666,16 @@ bool pointer_test(const T& default_value, const T& new_value)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
int main()
|
|
||||||
{
|
|
||||||
bool passed = true;
|
bool passed = true;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
bool T, bool ConstT, bool TRef, bool ConstTRef, bool TPtr,
|
bool T, bool ConstT, bool TRef, bool ConstTRef, bool TPtr,
|
||||||
bool ConstTPtr, bool TPtrConst, bool ConstTPtrConst, bool SharedPtrT, bool SharedConstPtrT,
|
bool ConstTPtr, bool TPtrConst, bool ConstTPtrConst, bool SharedPtrT, bool SharedConstPtrT,
|
||||||
bool ConstSharedPtrT, bool ConstSharedConstPtrT, bool ConstSharedPtrTRef, bool ConstSharedPtrTConstRef, bool WrappedRef,
|
bool ConstSharedPtrT, bool ConstSharedConstPtrT, bool ConstSharedPtrTRef, bool ConstSharedPtrTConstRef, bool WrappedRef,
|
||||||
bool WrappedConstRef, bool ConstWrappedRef, bool ConstWrappedConstRef, bool ConstWrappedRefRef, bool ConstWrappedConstRefRef,
|
bool WrappedConstRef, bool ConstWrappedRef, bool ConstWrappedConstRef, bool ConstWrappedRefRef, bool ConstWrappedConstRefRef,
|
||||||
bool Number, bool ConstNumber, bool ConstNumberRef
|
bool Number, bool ConstNumber, bool ConstNumberRef
|
||||||
*/
|
*/
|
||||||
|
|
||||||
passed &= built_in_type_test<int>(5, true);
|
passed &= built_in_type_test<int>(5, true);
|
||||||
passed &= built_in_type_test<double>(1.1, true);
|
passed &= built_in_type_test<double>(1.1, true);
|
||||||
@ -303,8 +684,8 @@ int main()
|
|||||||
passed &= built_in_type_test<int64_t>('a', true);
|
passed &= built_in_type_test<int64_t>('a', true);
|
||||||
passed &= built_in_type_test<bool>(false, false);
|
passed &= built_in_type_test<bool>(false, false);
|
||||||
passed &= built_in_type_test<std::string>("Hello World", false);
|
passed &= built_in_type_test<std::string>("Hello World", false);
|
||||||
|
|
||||||
// storing a pointer
|
// storing a pointer
|
||||||
passed &= pointer_test<int>(1, 0);
|
passed &= pointer_test<int>(1, 0);
|
||||||
|
|
||||||
if (passed) {
|
if (passed) {
|
||||||
|
|||||||
@ -1,21 +1,16 @@
|
|||||||
#include <chaiscript/chaiscript_basic.hpp>
|
|
||||||
#include "../static_libs/chaiscript_parser.hpp"
|
#include "../static_libs/chaiscript_parser.hpp"
|
||||||
#include "../static_libs/chaiscript_stdlib.hpp"
|
#include "../static_libs/chaiscript_stdlib.hpp"
|
||||||
|
#include <chaiscript/chaiscript_basic.hpp>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
extern "C"
|
int do_something(int i) {
|
||||||
{
|
return i % 2;
|
||||||
int do_something(int i)
|
}
|
||||||
{
|
|
||||||
return i % 2;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int main()
|
int main() {
|
||||||
{
|
chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(), create_chaiscript_parser());
|
||||||
chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser());
|
|
||||||
chai.add(chaiscript::fun(&do_something), "do_something");
|
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;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
25714
unittests/catch.hpp
25714
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_parser.hpp"
|
||||||
#include "../static_libs/chaiscript_stdlib.hpp"
|
#include "../static_libs/chaiscript_stdlib.hpp"
|
||||||
|
#include <chaiscript/chaiscript_basic.hpp>
|
||||||
|
|
||||||
#ifdef CHAISCRIPT_MSVC
|
#ifdef CHAISCRIPT_MSVC
|
||||||
// ignore errors about negative unsigned integer literals
|
// ignore errors about negative unsigned integer literals
|
||||||
@ -9,20 +8,18 @@
|
|||||||
#pragma warning(disable : 4146)
|
#pragma warning(disable : 4146)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#define TEST_LITERAL(v) test_literal(v, #v)
|
#define TEST_LITERAL(v) test_literal(v, #v)
|
||||||
#define TEST_LITERAL_SIGNED(v) test_literal(v, #v, true)
|
#define TEST_LITERAL_SIGNED(v) test_literal(v, #v, true)
|
||||||
|
|
||||||
template<typename T>
|
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;
|
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
|
// 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)
|
// 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
|
// so we're going to allow some leeway with the signed tests
|
||||||
T val2 = [&](){
|
T val2 = [&]() {
|
||||||
if (!use_boxed_number) {
|
if (!use_boxed_number) {
|
||||||
return chai.eval<T>(str);
|
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;
|
return val == val2;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main()
|
int main() {
|
||||||
{
|
if (TEST_LITERAL(0xF) && TEST_LITERAL(0xFF) && TEST_LITERAL(0xFFF) && TEST_LITERAL(0xFFFF) && TEST_LITERAL(0xFFFFF)
|
||||||
if(
|
&& TEST_LITERAL(0xFFFFFF) && TEST_LITERAL(0xFFFFFFF) && TEST_LITERAL(0xFFFFFFFF) && TEST_LITERAL(0xFFFFFFFFF)
|
||||||
TEST_LITERAL(0xF)
|
&& TEST_LITERAL(0xFFFFFFFFFF) && TEST_LITERAL(0xFFFFFFFFFFF) && TEST_LITERAL(0xFFFFFFFFFFFF) && TEST_LITERAL(0xFFFFFFFFFFFFF)
|
||||||
&& TEST_LITERAL(0xFF)
|
&& TEST_LITERAL(0xFFFFFFFFFFFFFF) && TEST_LITERAL(0xFFFFFFFFFFFFFFF) && TEST_LITERAL(0xFFFFFFFFFFFFFFFF)
|
||||||
&& 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(1) && TEST_LITERAL(17) && TEST_LITERAL(177) && TEST_LITERAL(1777) && TEST_LITERAL(17777) && TEST_LITERAL(177777)
|
||||||
&& TEST_LITERAL(017)
|
&& TEST_LITERAL(1777777) && TEST_LITERAL(17777777) && TEST_LITERAL(177777777) && TEST_LITERAL(1777777777)
|
||||||
&& TEST_LITERAL(0177)
|
&& TEST_LITERAL(17777777777) && TEST_LITERAL(177777777777) && TEST_LITERAL(1777777777777) && TEST_LITERAL(17777777777777)
|
||||||
&& TEST_LITERAL(01777)
|
&& TEST_LITERAL(177777777777777) && TEST_LITERAL(1777777777777777) && TEST_LITERAL(17777777777777777)
|
||||||
&& TEST_LITERAL(017777)
|
&& TEST_LITERAL(177777777777777777) && TEST_LITERAL(1777777777777777777)
|
||||||
&& 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(0xF, "0b1111") && test_literal(0xFF, "0b11111111") && test_literal(0xFFF, "0b111111111111")
|
||||||
&& TEST_LITERAL(17)
|
&& test_literal(0xFFFF, "0b1111111111111111") && test_literal(0xFFFFF, "0b11111111111111111111")
|
||||||
&& TEST_LITERAL(177)
|
&& test_literal(0xFFFFFF, "0b111111111111111111111111") && test_literal(0xFFFFFFF, "0b1111111111111111111111111111")
|
||||||
&& TEST_LITERAL(1777)
|
&& test_literal(0xFFFFFFFF, "0b11111111111111111111111111111111") && test_literal(0xFFFFFFFFF, "0b111111111111111111111111111111111111")
|
||||||
&& 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(0xFFFFFFFFFF, "0b1111111111111111111111111111111111111111")
|
&& test_literal(0xFFFFFFFFFF, "0b1111111111111111111111111111111111111111")
|
||||||
&& test_literal(0xFFFFFFFFFFF, "0b11111111111111111111111111111111111111111111")
|
&& test_literal(0xFFFFFFFFFFF, "0b11111111111111111111111111111111111111111111")
|
||||||
&& test_literal(0xFFFFFFFFFFFF, "0b111111111111111111111111111111111111111111111111")
|
&& test_literal(0xFFFFFFFFFFFF, "0b111111111111111111111111111111111111111111111111")
|
||||||
@ -114,15 +61,10 @@ int main()
|
|||||||
&& test_literal(0xFFFFFFFFFFFFFFF, "0b111111111111111111111111111111111111111111111111111111111111")
|
&& test_literal(0xFFFFFFFFFFFFFFF, "0b111111111111111111111111111111111111111111111111111111111111")
|
||||||
&& test_literal(0xFFFFFFFFFFFFFFFF, "0b1111111111111111111111111111111111111111111111111111111111111111")
|
&& test_literal(0xFFFFFFFFFFFFFFFF, "0b1111111111111111111111111111111111111111111111111111111111111111")
|
||||||
|
|
||||||
&& test_literal(0x7, "0b111")
|
&& test_literal(0x7, "0b111") && test_literal(0x7F, "0b1111111") && test_literal(0x7FF, "0b11111111111")
|
||||||
&& test_literal(0x7F, "0b1111111")
|
&& test_literal(0x7FFF, "0b111111111111111") && test_literal(0x7FFFF, "0b1111111111111111111")
|
||||||
&& test_literal(0x7FF, "0b11111111111")
|
&& test_literal(0x7FFFFF, "0b11111111111111111111111") && test_literal(0x7FFFFFF, "0b111111111111111111111111111")
|
||||||
&& test_literal(0x7FFF, "0b111111111111111")
|
&& test_literal(0x7FFFFFFF, "0b1111111111111111111111111111111") && test_literal(0x7FFFFFFFF, "0b11111111111111111111111111111111111")
|
||||||
&& 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(0x7FFFFFFFFF, "0b111111111111111111111111111111111111111")
|
||||||
&& test_literal(0x7FFFFFFFFFF, "0b1111111111111111111111111111111111111111111")
|
&& test_literal(0x7FFFFFFFFFF, "0b1111111111111111111111111111111111111111111")
|
||||||
&& test_literal(0x7FFFFFFFFFFF, "0b11111111111111111111111111111111111111111111111")
|
&& test_literal(0x7FFFFFFFFFFF, "0b11111111111111111111111111111111111111111111111")
|
||||||
@ -131,152 +73,82 @@ int main()
|
|||||||
&& test_literal(0x7FFFFFFFFFFFFFF, "0b11111111111111111111111111111111111111111111111111111111111")
|
&& test_literal(0x7FFFFFFFFFFFFFF, "0b11111111111111111111111111111111111111111111111111111111111")
|
||||||
&& test_literal(0x7FFFFFFFFFFFFFFF, "0b111111111111111111111111111111111111111111111111111111111111111")
|
&& 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(-01) && TEST_LITERAL_SIGNED(-017) && TEST_LITERAL_SIGNED(-0177) && TEST_LITERAL_SIGNED(-01777)
|
||||||
&& TEST_LITERAL_SIGNED(-0xFF)
|
&& TEST_LITERAL_SIGNED(-017777) && TEST_LITERAL_SIGNED(-0177777) && TEST_LITERAL_SIGNED(-01777777) && TEST_LITERAL_SIGNED(-017777777)
|
||||||
&& TEST_LITERAL_SIGNED(-0xFFF)
|
&& TEST_LITERAL_SIGNED(-0177777777) && TEST_LITERAL_SIGNED(-01777777777) && TEST_LITERAL_SIGNED(-017777777777)
|
||||||
&& TEST_LITERAL_SIGNED(-0xFFFF)
|
&& TEST_LITERAL_SIGNED(-0177777777777) && TEST_LITERAL_SIGNED(-01777777777777) && TEST_LITERAL_SIGNED(-017777777777777)
|
||||||
&& TEST_LITERAL_SIGNED(-0xFFFFF)
|
&& TEST_LITERAL_SIGNED(-0177777777777777) && TEST_LITERAL_SIGNED(-01777777777777777) && TEST_LITERAL_SIGNED(-017777777777777777)
|
||||||
&& TEST_LITERAL_SIGNED(-0xFFFFFF)
|
&& TEST_LITERAL_SIGNED(-0177777777777777777) && TEST_LITERAL_SIGNED(-01777777777777777777) && TEST_LITERAL_SIGNED(-017777777777777777777)
|
||||||
&& TEST_LITERAL_SIGNED(-0xFFFFFFF)
|
&& TEST_LITERAL_SIGNED(-0177777777777777777777) && TEST_LITERAL_SIGNED(-01777777777777777777777)
|
||||||
&& 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(-1) && TEST_LITERAL_SIGNED(-17) && TEST_LITERAL_SIGNED(-177) && TEST_LITERAL_SIGNED(-1777)
|
||||||
&& TEST_LITERAL_SIGNED(-01)
|
&& TEST_LITERAL_SIGNED(-17777) && TEST_LITERAL_SIGNED(-177777) && TEST_LITERAL_SIGNED(-1777777) && TEST_LITERAL_SIGNED(-17777777)
|
||||||
&& TEST_LITERAL_SIGNED(-017)
|
&& TEST_LITERAL_SIGNED(-177777777) && TEST_LITERAL_SIGNED(-1777777777) && TEST_LITERAL_SIGNED(-17777777777)
|
||||||
&& TEST_LITERAL_SIGNED(-0177)
|
&& TEST_LITERAL_SIGNED(-177777777777) && TEST_LITERAL_SIGNED(-1777777777777) && TEST_LITERAL_SIGNED(-17777777777777)
|
||||||
&& TEST_LITERAL_SIGNED(-01777)
|
&& TEST_LITERAL_SIGNED(-177777777777777) && TEST_LITERAL_SIGNED(-1777777777777777) && TEST_LITERAL_SIGNED(-17777777777777777)
|
||||||
&& 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(-177777777777777777)
|
&& TEST_LITERAL_SIGNED(-177777777777777777)
|
||||||
&& TEST_LITERAL_SIGNED(-1777777777777777777)
|
&& TEST_LITERAL_SIGNED(-1777777777777777777)
|
||||||
|
|
||||||
// Test 8/16/24/32 bit boundaries for various types
|
// Test 8/16/24/32 bit boundaries for various types
|
||||||
|
|
||||||
&& TEST_LITERAL(255)
|
&& TEST_LITERAL(255) && TEST_LITERAL(65535)
|
||||||
&& TEST_LITERAL(65535)
|
|
||||||
&& TEST_LITERAL(16777215)
|
&& TEST_LITERAL(16777215)
|
||||||
#ifndef CHAISCRIPT_MSVC
|
#ifndef CHAISCRIPT_MSVC
|
||||||
// bug in cl.exe causes this to be incorrectly parsed as an unsigned
|
// bug in cl.exe causes this to be incorrectly parsed as an unsigned
|
||||||
&& TEST_LITERAL(4294967295)
|
&& TEST_LITERAL(4294967295)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
&& TEST_LITERAL_SIGNED(-255)
|
&& TEST_LITERAL_SIGNED(-255) && TEST_LITERAL_SIGNED(-65535)
|
||||||
&& TEST_LITERAL_SIGNED(-65535)
|
|
||||||
&& TEST_LITERAL_SIGNED(-16777215)
|
&& TEST_LITERAL_SIGNED(-16777215)
|
||||||
#ifndef CHAISCRIPT_MSVC
|
#ifndef CHAISCRIPT_MSVC
|
||||||
// bug in cl.exe causes this to be incorrectly parsed as an unsigned
|
// bug in cl.exe causes this to be incorrectly parsed as an unsigned
|
||||||
&& TEST_LITERAL_SIGNED(-4294967295)
|
&& TEST_LITERAL_SIGNED(-4294967295)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
&& TEST_LITERAL(255u)
|
&& TEST_LITERAL(255u) && TEST_LITERAL(65535u) && TEST_LITERAL(16777215u) && TEST_LITERAL(4294967295u)
|
||||||
&& TEST_LITERAL(65535u)
|
|
||||||
&& TEST_LITERAL(16777215u)
|
|
||||||
&& TEST_LITERAL(4294967295u)
|
|
||||||
|
|
||||||
&& TEST_LITERAL_SIGNED(-255u)
|
&& TEST_LITERAL_SIGNED(-255u) && TEST_LITERAL_SIGNED(-65535u) && TEST_LITERAL_SIGNED(-16777215u) && TEST_LITERAL_SIGNED(-4294967295u)
|
||||||
&& TEST_LITERAL_SIGNED(-65535u)
|
|
||||||
&& TEST_LITERAL_SIGNED(-16777215u)
|
|
||||||
&& TEST_LITERAL_SIGNED(-4294967295u)
|
|
||||||
|
|
||||||
&& TEST_LITERAL(255l)
|
&& TEST_LITERAL(255l) && TEST_LITERAL(65535l)
|
||||||
&& TEST_LITERAL(65535l)
|
|
||||||
&& TEST_LITERAL(16777215l)
|
&& TEST_LITERAL(16777215l)
|
||||||
#ifndef CHAISCRIPT_MSVC
|
#ifndef CHAISCRIPT_MSVC
|
||||||
// bug in cl.exe causes this to be incorrectly parsed as an unsigned
|
// bug in cl.exe causes this to be incorrectly parsed as an unsigned
|
||||||
&& TEST_LITERAL(4294967295l)
|
&& TEST_LITERAL(4294967295l)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
&& TEST_LITERAL_SIGNED(-255l)
|
&& TEST_LITERAL_SIGNED(-255l) && TEST_LITERAL_SIGNED(-65535l)
|
||||||
&& TEST_LITERAL_SIGNED(-65535l)
|
|
||||||
&& TEST_LITERAL_SIGNED(-16777215l)
|
&& TEST_LITERAL_SIGNED(-16777215l)
|
||||||
#ifndef CHAISCRIPT_MSVC
|
#ifndef CHAISCRIPT_MSVC
|
||||||
// bug in cl.exe causes this to be incorrectly parsed as an unsigned
|
// bug in cl.exe causes this to be incorrectly parsed as an unsigned
|
||||||
&& TEST_LITERAL_SIGNED(-4294967295l)
|
&& TEST_LITERAL_SIGNED(-4294967295l)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
&& TEST_LITERAL(255ul)
|
&& TEST_LITERAL(255ul) && TEST_LITERAL(65535ul) && TEST_LITERAL(16777215ul) && TEST_LITERAL(4294967295ul)
|
||||||
&& TEST_LITERAL(65535ul)
|
|
||||||
&& TEST_LITERAL(16777215ul)
|
|
||||||
&& TEST_LITERAL(4294967295ul)
|
|
||||||
|
|
||||||
&& TEST_LITERAL_SIGNED(-255ul)
|
&& TEST_LITERAL_SIGNED(-255ul) && TEST_LITERAL_SIGNED(-65535ul) && TEST_LITERAL_SIGNED(-16777215ul) && TEST_LITERAL_SIGNED(-4294967295ul)
|
||||||
&& TEST_LITERAL_SIGNED(-65535ul)
|
|
||||||
&& TEST_LITERAL_SIGNED(-16777215ul)
|
|
||||||
&& TEST_LITERAL_SIGNED(-4294967295ul)
|
|
||||||
|
|
||||||
&& TEST_LITERAL(255ull)
|
&& TEST_LITERAL(255ull) && TEST_LITERAL(65535ull) && TEST_LITERAL(16777215ull) && TEST_LITERAL(4294967295ull)
|
||||||
&& TEST_LITERAL(65535ull)
|
|
||||||
&& TEST_LITERAL(16777215ull)
|
|
||||||
&& TEST_LITERAL(4294967295ull)
|
|
||||||
|
|
||||||
&& TEST_LITERAL_SIGNED(-255ull)
|
&& TEST_LITERAL_SIGNED(-255ull) && TEST_LITERAL_SIGNED(-65535ull) && TEST_LITERAL_SIGNED(-16777215ull)
|
||||||
&& TEST_LITERAL_SIGNED(-65535ull)
|
|
||||||
&& TEST_LITERAL_SIGNED(-16777215ull)
|
|
||||||
&& TEST_LITERAL_SIGNED(-4294967295ull)
|
&& TEST_LITERAL_SIGNED(-4294967295ull)
|
||||||
|
|
||||||
&& TEST_LITERAL(255ll)
|
&& TEST_LITERAL(255ll) && TEST_LITERAL(65535ll) && TEST_LITERAL(16777215ll) && TEST_LITERAL(4294967295ll)
|
||||||
&& TEST_LITERAL(65535ll)
|
|
||||||
&& TEST_LITERAL(16777215ll)
|
|
||||||
&& TEST_LITERAL(4294967295ll)
|
|
||||||
|
|
||||||
&& TEST_LITERAL_SIGNED(-255ll)
|
&& TEST_LITERAL_SIGNED(-255ll) && TEST_LITERAL_SIGNED(-65535ll) && TEST_LITERAL_SIGNED(-16777215ll) && TEST_LITERAL_SIGNED(-4294967295ll)
|
||||||
&& TEST_LITERAL_SIGNED(-65535ll)
|
|
||||||
&& TEST_LITERAL_SIGNED(-16777215ll)
|
|
||||||
&& TEST_LITERAL_SIGNED(-4294967295ll)
|
|
||||||
|
|
||||||
|
) {
|
||||||
)
|
|
||||||
{
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef CHAISCRIPT_MSVC
|
#ifdef CHAISCRIPT_MSVC
|
||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -4,13 +4,11 @@
|
|||||||
#include <chaiscript/language/chaiscript_parser.hpp>
|
#include <chaiscript/language/chaiscript_parser.hpp>
|
||||||
|
|
||||||
Multi_Test_Chai::Multi_Test_Chai()
|
Multi_Test_Chai::Multi_Test_Chai()
|
||||||
: m_chai(new chaiscript::ChaiScript_Basic(chaiscript::Std_Lib::library(),
|
: m_chai(new chaiscript::ChaiScript_Basic(
|
||||||
std::make_unique<chaiscript::parser::ChaiScript_Parser<chaiscript::eval::Noop_Tracer, chaiscript::optimizer::Optimizer_Default>>()))
|
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;
|
return m_chai;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,14 +1,11 @@
|
|||||||
#include <chaiscript/chaiscript_basic.hpp>
|
#include <chaiscript/chaiscript_basic.hpp>
|
||||||
|
|
||||||
class Multi_Test_Chai
|
class Multi_Test_Chai {
|
||||||
{
|
public:
|
||||||
public:
|
Multi_Test_Chai();
|
||||||
Multi_Test_Chai();
|
|
||||||
|
|
||||||
std::shared_ptr<chaiscript::ChaiScript_Basic> get_chai();
|
std::shared_ptr<chaiscript::ChaiScript_Basic> get_chai();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<chaiscript::ChaiScript_Basic> m_chai;
|
std::shared_ptr<chaiscript::ChaiScript_Basic> m_chai;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -3,8 +3,7 @@
|
|||||||
|
|
||||||
#include <chaiscript/chaiscript_basic.hpp>
|
#include <chaiscript/chaiscript_basic.hpp>
|
||||||
|
|
||||||
int main()
|
int main() {
|
||||||
{
|
|
||||||
Multi_Test_Chai chaitest;
|
Multi_Test_Chai chaitest;
|
||||||
Multi_Test_Module chaimodule;
|
Multi_Test_Module chaimodule;
|
||||||
|
|
||||||
|
|||||||
@ -4,13 +4,11 @@
|
|||||||
|
|
||||||
Multi_Test_Module::Multi_Test_Module() noexcept = default;
|
Multi_Test_Module::Multi_Test_Module() noexcept = default;
|
||||||
|
|
||||||
int Multi_Test_Module::get_module_value()
|
int Multi_Test_Module::get_module_value() {
|
||||||
{
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
chaiscript::ModulePtr Multi_Test_Module::get_module()
|
chaiscript::ModulePtr Multi_Test_Module::get_module() {
|
||||||
{
|
|
||||||
chaiscript::ModulePtr module(new chaiscript::Module());
|
chaiscript::ModulePtr module(new chaiscript::Module());
|
||||||
|
|
||||||
module->add(chaiscript::fun(&Multi_Test_Module::get_module_value), "get_module_value");
|
module->add(chaiscript::fun(&Multi_Test_Module::get_module_value), "get_module_value");
|
||||||
|
|||||||
@ -1,11 +1,10 @@
|
|||||||
#include <chaiscript/chaiscript_basic.hpp>
|
#include <chaiscript/chaiscript_basic.hpp>
|
||||||
|
|
||||||
class Multi_Test_Module
|
class Multi_Test_Module {
|
||||||
{
|
public:
|
||||||
public:
|
static int get_module_value();
|
||||||
static int get_module_value();
|
|
||||||
|
|
||||||
Multi_Test_Module() noexcept;
|
Multi_Test_Module() noexcept;
|
||||||
|
|
||||||
chaiscript::ModulePtr get_module();
|
chaiscript::ModulePtr get_module();
|
||||||
};
|
};
|
||||||
|
|||||||
@ -8,20 +8,17 @@
|
|||||||
#include <chaiscript/chaiscript_basic.hpp>
|
#include <chaiscript/chaiscript_basic.hpp>
|
||||||
#include <chaiscript/language/chaiscript_parser.hpp>
|
#include <chaiscript/language/chaiscript_parser.hpp>
|
||||||
|
|
||||||
int expected_value(int num_iters)
|
int expected_value(int num_iters) {
|
||||||
{
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (int k = 0; k<num_iters * 10; ++k)
|
for (int k = 0; k < num_iters * 10; ++k) {
|
||||||
{
|
|
||||||
i += k;
|
i += k;
|
||||||
}
|
}
|
||||||
|
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
void do_work(chaiscript::ChaiScript_Basic &c, const size_t id)
|
void do_work(chaiscript::ChaiScript_Basic &c, const size_t id) {
|
||||||
{
|
try {
|
||||||
try{
|
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << "MyVar" << rand();
|
ss << "MyVar" << rand();
|
||||||
c.add(chaiscript::var(5), ss.str());
|
c.add(chaiscript::var(5), ss.str());
|
||||||
@ -34,9 +31,8 @@ void do_work(chaiscript::ChaiScript_Basic &c, const size_t id)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int main()
|
int main() {
|
||||||
{
|
// Disable deprecation warning for getenv call.
|
||||||
// Disable deprecation warning for getenv call.
|
|
||||||
#ifdef CHAISCRIPT_MSVC
|
#ifdef CHAISCRIPT_MSVC
|
||||||
#ifdef max // Why Microsoft? why?
|
#ifdef max // Why Microsoft? why?
|
||||||
#undef max
|
#undef max
|
||||||
@ -54,63 +50,54 @@ int main()
|
|||||||
|
|
||||||
std::vector<std::string> usepaths;
|
std::vector<std::string> usepaths;
|
||||||
usepaths.emplace_back("");
|
usepaths.emplace_back("");
|
||||||
if (usepath)
|
if (usepath) {
|
||||||
{
|
|
||||||
usepaths.emplace_back(usepath);
|
usepaths.emplace_back(usepath);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> modulepaths;
|
std::vector<std::string> modulepaths;
|
||||||
|
|
||||||
#ifdef CHAISCRIPT_NO_DYNLOAD
|
#ifdef CHAISCRIPT_NO_DYNLOAD
|
||||||
chaiscript::ChaiScript chai(/* unused */modulepaths, usepaths);
|
chaiscript::ChaiScript chai(/* unused */ modulepaths, usepaths);
|
||||||
#else
|
#else
|
||||||
modulepaths.emplace_back("");
|
modulepaths.emplace_back("");
|
||||||
if (modulepath)
|
if (modulepath) {
|
||||||
{
|
|
||||||
modulepaths.emplace_back(modulepath);
|
modulepaths.emplace_back(modulepath);
|
||||||
}
|
}
|
||||||
|
|
||||||
// For this test we are going to load the dynamic stdlib
|
// For this test we are going to load the dynamic stdlib
|
||||||
// to make sure it continues to work
|
// to make sure it continues to work
|
||||||
chaiscript::ChaiScript_Basic chai(
|
chaiscript::ChaiScript_Basic chai(
|
||||||
std::make_unique<chaiscript::parser::ChaiScript_Parser<chaiscript::eval::Noop_Tracer, chaiscript::optimizer::Optimizer_Default>>(),
|
std::make_unique<chaiscript::parser::ChaiScript_Parser<chaiscript::eval::Noop_Tracer, chaiscript::optimizer::Optimizer_Default>>(),
|
||||||
modulepaths,usepaths);
|
modulepaths,
|
||||||
|
usepaths);
|
||||||
#endif
|
#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
|
// 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));
|
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';
|
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));
|
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();
|
threads[i]->join();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < num_threads; ++i) {
|
||||||
|
|
||||||
for (size_t i = 0; i < num_threads; ++i)
|
|
||||||
{
|
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << i;
|
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;
|
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_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -11,34 +11,27 @@
|
|||||||
#pragma GCC diagnostic ignored "-Wparentheses"
|
#pragma GCC diagnostic ignored "-Wparentheses"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#include <chaiscript/chaiscript_defines.hpp>
|
#include <chaiscript/chaiscript_defines.hpp>
|
||||||
#include <chaiscript/dispatchkit/type_info.hpp>
|
#include <chaiscript/dispatchkit/type_info.hpp>
|
||||||
#include <iostream>
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define CATCH_CONFIG_MAIN
|
#define CATCH_CONFIG_MAIN
|
||||||
|
|
||||||
#include "catch.hpp"
|
#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) {
|
||||||
|
CHECK(ti.is_const() == t_is_const);
|
||||||
|
CHECK(ti.is_pointer() == t_is_pointer);
|
||||||
|
CHECK(ti.is_reference() == t_is_reference);
|
||||||
|
CHECK(ti.is_void() == t_is_void);
|
||||||
|
CHECK(ti.is_undef() == t_is_undef);
|
||||||
|
CHECK(ti.is_arithmetic() == t_is_arithmetic);
|
||||||
|
};
|
||||||
|
|
||||||
TEST_CASE("Type_Info objects generate expected results")
|
SECTION("void") { test_type(chaiscript::user_type<void>(), false, false, false, true, false, false); }
|
||||||
{
|
|
||||||
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);
|
|
||||||
CHECK(ti.is_void() == t_is_void);
|
|
||||||
CHECK(ti.is_undef() == t_is_undef);
|
|
||||||
CHECK(ti.is_arithmetic() == t_is_arithmetic);
|
|
||||||
};
|
|
||||||
|
|
||||||
SECTION("void") { test_type(chaiscript::user_type<void>(), false, false, false, true, false, false); }
|
|
||||||
SECTION("const int") { test_type(chaiscript::user_type<const int>(), true, false, false, false, false, true); }
|
SECTION("const int") { test_type(chaiscript::user_type<const int>(), true, false, false, false, false, true); }
|
||||||
SECTION("const int &") { test_type(chaiscript::user_type<const int &>(), true, false, true, false, false, true); }
|
SECTION("const int &") { test_type(chaiscript::user_type<const int &>(), true, false, true, false, false, true); }
|
||||||
SECTION("int") { test_type(chaiscript::user_type<int>(), false, false, false, false, false, true); }
|
SECTION("int") { test_type(chaiscript::user_type<int>(), false, false, false, false, false, true); }
|
||||||
@ -49,6 +42,3 @@ TEST_CASE("Type_Info objects generate expected results")
|
|||||||
|
|
||||||
std::cout << "Size of Type_Info " << sizeof(chaiscript::Type_Info) << '\n';
|
std::cout << "Size of Type_Info " << sizeof(chaiscript::Type_Info) << '\n';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user