Compare commits

..

227 Commits

Author SHA1 Message Date
Jason Turner
1cd9a9098c Update gcc flags for MacOS to ignore sign comparison warnings 2011-06-18 07:34:55 -06:00
Jason Turner
5ff14a54db Commented out code removal 2011-06-16 10:42:26 -06:00
Jason Turner
28e3d442e2 Update version number to 3.1.0 for next release 2011-06-16 10:19:54 -06:00
Jason Turner
bb0edcb62a Add exception_specification and unittests for it. #6 2011-06-16 10:14:52 -06:00
Jonathan Turner
9a015a5c49 Fix typo in unit test and add string literal access 2011-06-13 18:14:41 -07:00
Jonathan Turner
9d20f60903 Update license year 2011-06-13 07:45:11 -07:00
Jonathan Turner
5426496b4f Fix parsing of member access and function calls 2011-06-13 07:43:51 -07:00
Jason Turner
9e9fb3ad7d Fix one more documentation error 2011-06-10 16:42:38 -06:00
Jason Turner
8cc3651c76 Correct copyright date 2011-06-10 16:41:00 -06:00
Jason Turner
4d879afca7 Documentation updates 2011-06-10 16:38:20 -06:00
Jason Turner
afae221cb3 Add tests for more complex uses of the index operator 2011-06-10 11:18:58 -06:00
Jason Turner
b064bb61e9 Finish renaming and cleaning up of Boxed_Number type for dump_system() output 2011-06-10 10:12:09 -06:00
Jason Turner
7a9baeb350 Rename of numeric to number 2011-06-08 13:53:55 -06:00
Jason Turner
6d4041b2a1 Added profile for mathy functions.x 2011-06-07 14:59:43 -06:00
Jason Turner
1932cbfbbc Eliminate duplicate code and reduce Boxed_Value copies necessary 2011-06-04 12:31:33 -06:00
Jonathan Turner
8fecf5c145 Merge branch 'master' of github.com:ChaiScript/ChaiScript 2011-06-04 11:02:07 -07:00
Jonathan Turner
6131a9c4c1 Moved common operators into their own AST nodes and removed the operator child. 2011-06-04 11:01:35 -07:00
Jason Turner
881d569d8e Remove unnecessary loop from Binary_Operator 2011-06-04 10:34:15 -06:00
Jonathan Turner
6c18c197c6 Fixed operator parsing to return trees instead of flat representations. Fixed evaluator to not loop over equations. 2011-06-04 09:15:19 -07:00
Jason Turner
f47ec0d522 Merge pull request #7 from lefticus/master
Merge Number Performance Updates
2011-06-03 17:52:04 -07:00
Jason Turner
4053196188 Reduce creation of new Boxed_Value containers when returning the same value that was passed in 2011-06-04 04:26:06 +08:00
Jason Turner
5b40a85024 Add direct access to Boxed_Value data * for high performance operations 2011-06-04 04:26:00 +08:00
Jason Turner
36faba8ed3 Bypass dispatch during numeric operations. 2x speedup 2011-06-04 04:25:54 +08:00
Jason Turner
7d022c4f0d Add is_prime profile script 2011-06-04 04:25:47 +08:00
Jason Turner
b933bb6c50 Begin move of Operators code out a level so that it can be used before dispatch 2011-06-04 04:25:42 +08:00
Jason Turner
92bfcfdcf3 Wrap up new Boxed_Numeric support 2011-06-04 04:25:36 +08:00
Jason Turner
3b754cfec4 Further simplification and refinement of enhanced Algebraic types support 2011-06-04 04:25:30 +08:00
Jason Turner
3689c01e4b Significant reduction in templates instantiated by grouping of operators - smaller code and compile time 2011-06-04 04:25:24 +08:00
Jason Turner
4b90fbd07a wrap up support for all built in C++ Arithmetic types 2011-06-04 04:25:18 +08:00
Jason Turner
1a225dca67 Progress towards eliminating arithmetic operators on a per-type basis 2011-06-04 04:25:12 +08:00
Jason Turner
226666c2bb Rename Boxed_POD_Value to Boxed_Numeric, which is more correct. 2011-06-04 04:24:57 +08:00
Jason Turner
d4ef226911 Reduce creation of new Boxed_Value containers when returning the same value that was passed in 2011-06-03 13:48:32 -06:00
Jason Turner
6491262491 Add direct access to Boxed_Value data * for high performance operations 2011-06-03 12:41:38 -06:00
Jason Turner
2c4d69bfc0 Bypass dispatch during numeric operations. 2x speedup 2011-06-01 22:12:50 -06:00
Jason Turner
f423969a8e Add is_prime profile script 2011-05-31 08:09:30 -06:00
Jason Turner
36cd4c370a Begin move of Operators code out a level so that it can be used before dispatch 2011-05-31 07:42:30 -06:00
Jason Turner
85f69782b2 Wrap up new Boxed_Numeric support 2011-05-30 19:38:04 -06:00
Jason Turner
1f130c0891 Further simplification and refinement of enhanced Algebraic types support 2011-05-29 17:33:45 -06:00
Jason Turner
fdd1b40a9f Significant reduction in templates instantiated by grouping of operators - smaller code and compile time 2011-05-29 09:14:48 -06:00
Jason Turner
6993d58fdc wrap up support for all built in C++ Arithmetic types 2011-05-28 23:48:17 -06:00
Jason Turner
1845114d36 Progress towards eliminating arithmetic operators on a per-type basis 2011-05-26 05:58:19 -06:00
Jason Turner
bba1ffde38 Rename Boxed_POD_Value to Boxed_Numeric, which is more correct. 2011-05-24 12:39:39 -06:00
Jason Turner
18d4984258 Final tweaks to packaging for 3.0.0 2011-05-23 08:16:24 -06:00
Jason Turner
845eb394ac Correct installation of pkgconfig file 2011-05-23 07:58:05 -06:00
Jason Turner
66b2adba5c Final tweaks to release 3.0.0 docs 2011-05-23 07:07:27 -06:00
Jason Turner
02db23e9e2 Minor doc tweaks 2011-05-23 06:55:31 -06:00
Jason Turner
fbef83ecb7 Final documentation for release 3.0.0 completed 2011-05-22 23:29:55 -06:00
Jason Turner
88fbf41091 Getting started document updates 2011-05-22 21:43:58 -06:00
Jason Turner
897385953c More documentation updates and additions to getting started guide 2011-05-22 12:08:24 -06:00
Jason Turner
319f9e4de9 Fix issues with trim() and with unit tests relying on certain line endings. 2011-05-20 16:01:50 -06:00
Jason Turner
2786156086 Finalize documentation for 3.0.0 release and update version number in CMakeLists.txt 2011-05-20 13:44:34 -06:00
Jason Turner
e5f9dbb93b Fix failing unit tests related to recent renaming of function to Function 2011-04-26 10:17:24 -06:00
Jason Turner
61b8481514 Further documentation of the prelude / standard library. 2011-04-25 20:24:31 -06:00
Jason Turner
8a0ef143c9 C++ API documentation is complete. ChaiScript keyword and language documentation about 75% complete (mostly ported from website.) 2011-04-17 09:29:34 -06:00
Jason Turner
f1918f147d More documentation updates. 2011-04-04 07:08:28 -06:00
Jason Turner
0d238b1617 Documentation updates and namespace reorg for docs. 2011-04-02 20:52:49 -06:00
Jason Turner
d22a77503c Fix build errors and warnings for VS2010 2011-04-02 11:21:11 -06:00
Jason Turner
8dec35ba19 Merge branch '2011-03-15-DocumentationUpdates'
Conflicts:
	include/chaiscript/language/chaiscript_engine.hpp
2011-03-29 20:24:17 -06:00
Jason Turner
a91c66d286 Couple of include guard cleanups 2011-03-29 09:28:35 -06:00
Jason Turner
8ecd3a084b Add simple efficencies for static ids 2011-03-28 19:50:41 -06:00
Jason Turner
79e8af4f6e Enhance eval error stack reporting
Use OOP to avoid code duplication for eval error tracking. This results
in much more robust stack error reporting and 400 LOC less.
2011-03-27 21:03:24 -06:00
Jason Turner
de5822873b Use RAII for scope management
Possibly fixes a few bugs where scope pops where missed.
2011-03-27 10:03:37 -06:00
Jason Turner
d6b8e32373 Allow for parse time evaluation of const values.
The goal is to allow for more evaluation at parse time, in general, to
increase eval time performance.

 - Make AST_Node non-constructable except by derived classes.
 - Make data in AST_Node const (as much as possible).
 - Replace reflection "text = " with replace_child() (where the
   replacement must be with a new parse tree).
 - Evaluate floats, strings, ints, chars at parse time to avoid repeat
   evaluations (~10% speed up in loops in -O3)
2011-03-27 08:17:04 -06:00
Jason Turner
bbe89e61bc elimination of unused / outdated code and documentation cleanups. 2011-03-26 22:42:11 -06:00
Jason Turner
87c29ebc91 Ensure that non-shared_ptr, non-boxed_value, non-reference return types
are treated as const.
2011-03-26 09:03:36 -06:00
Jason Turner
92c836c58a Simplify mutex code by providing stubs that are do nothing during
CHAISCRIPT_NO_THREADS builds.
2011-03-25 22:49:17 -06:00
Jason Turner
58e5df0a9a Even more reorganization of namespaces to help with documentation and
clarity.
2011-03-25 15:42:18 -06:00
Jason Turner
854737ea25 Fix compile time error for non-posix, non-win32 platforms. 2011-03-25 10:43:17 -06:00
Jason Turner
8bd512a0af Merge branch '2011-03-15-DocumentationUpdates' of https://github.com/ChaiScript/ChaiScript into 2011-03-15-DocumentationUpdates 2011-03-24 09:28:11 -06:00
Jason Turner
deb4cb036f Hide Bare_Type in detail namespace 2011-03-24 09:26:41 -06:00
Jason Turner
cd8bead54a Further namespace reorganization and cleanup to limit to the user the
most important aspect of the API and make documenation easier.
2011-03-24 09:23:05 -06:00
Jason Turner
637164e457 Move around some namespaces for documentation purposes.
Fix problems with building on clang 2.8.
Remove unneeded function for get_engine() and fix functor<> calls that take a Boxed_Value
2011-03-15 17:35:14 -06:00
Jason Turner
9dd9ffec46 Update copyright information for 2011 2011-03-15 09:42:33 -06:00
Jason Turner
ac0688a8d7 Fix warnings in memory_leak_test 2011-03-14 12:07:08 -06:00
Jason Turner
e3feb05e05 Merge branch 'master' of https://github.com/ChaiScript/ChaiScript 2011-03-14 09:12:01 -06:00
Jason Turner
2ce55d81b3 Fix bug in installation of some files 2011-03-13 19:24:42 -06:00
Jason Turner
4e06478fb8 Amp up the warnings used in g++ and fix associated errors 2011-03-12 11:27:53 -07:00
Jason Turner
46a669dab1 Fix problem with method specifiers for bad_dynamic_boxed_cast exception. Add support for operators to Utility.hpp 2011-03-11 17:56:46 -07:00
Jason Turner
d9a92a5148 Add std::exception as a base clase off std::runtime_error and provide unit test for it. 2011-03-09 21:41:32 -07:00
Jason Turner
f6b6936348 Normalize on include guard style, removing __ reserved words 2011-03-08 14:06:09 -07:00
Jason Turner
0b97fcb4df Add better namespaces to make documentation easier to handle 2011-03-05 22:50:38 -07:00
Jason Turner
eee5c19b6e Begin support for Doxygen and building Chaiscript version number into
the code.
2011-03-03 22:43:01 -07:00
Jason Turner
5cc4a758ab Make scoping more explicit during initialization of alphabet 2011-02-21 19:25:22 -07:00
Jason Turner
7c2550ba74 Modify alphabet to m_alphabet to match rest of coding style 2011-02-21 19:17:36 -07:00
Jason Turner
41d7842963 Move from hand rolled trim function to boost::trim function 2011-02-21 19:02:30 -07:00
Jason Turner
13b35f2f47 Better localize MSVC specific code. Remove deprecated / gratuitous use
of "static". Clean up code for readability and effeciencies in C++.
2011-02-21 18:56:04 -07:00
clanmills
18c6ed71f0 Add code to compile _strdup on non-Microsoft platforms (builds on Windows with DevStudio and Cygwin). 2011-02-16 23:24:51 -08:00
clanmills
7ac22c7072 Tweaking the --help output 2011-02-16 11:00:18 -08:00
Robin Mills
c9c4f1add7 Tweak to --stdin line end handling. 2011-02-16 10:13:12 -08:00
clanmills
65d054b36e Three lots of changes:
1) Changes post code review by Jason
2) Fixing bug in end of line processing on Windows with cr-lf
3) Adding command-line options to chai
2011-02-16 08:21:19 -08:00
clanmills
894063261e Changes to parser. 2011-02-14 10:33:40 -08:00
Jason Turner
80f576a2f3 Reflection and introspection updates for task #85 2010-12-29 17:58:56 +00:00
Jason Turner
0a2b5d7a40 Find, test and fix an issue related to function argument type reporting when discussing dynamic object functions (ie, def int::somefunc() {} ) 2010-12-24 22:26:14 +00:00
Jason Turner
660e978da3 Implement test for function ordering for dispatch. Catch bug for "const" characterization of function parameters. Add test for type characterizations. 2010-12-13 03:32:47 +00:00
Jason Turner
e90d49bb9d Function ordering is working properly now, just need to add a unit test for it. 2010-12-11 22:38:08 +00:00
Jason Turner
13f53839c9 Check in of function ordering. Breaks function assignment test - need to understand why still. 2010-12-11 21:01:18 +00:00
Jason Turner
65edf30ef0 Fix regression in parsing of empty file. Visible in windows debug mode, but probably affects all platforms. 2010-11-15 22:45:57 +00:00
Jason Turner
7ef1b81504 Simplify how functions are stored and passed. This is the first step in allowing us to sort functions so that dispatches are attempted in an organized order (as opposed to just the order they were added in).
Should have resulted in a speed imrovement too - fewer string copies during dispatch.
2010-11-15 05:52:48 +00:00
Jason Turner
3aee589274 Remove unused variable 2010-11-15 00:01:33 +00:00
Jason Turner
97081b1f33 Remove vestiges of object caching from dispatch kit 2010-11-14 22:28:05 +00:00
Jason Turner
a758c86ba5 Add automatic unwrapping of Proxy_Function_Impl contained boost::function during functor() construction if possible.
Task #110
2010-11-14 01:17:56 +00:00
Jason Turner
5f661fad20 Get rid of a C++ conversion and make it a static_cast 2010-11-12 23:19:30 +00:00
Jason Turner
811764e048 Object lifetime specificity test added. 2010-11-11 15:58:51 +00:00
Jason Turner
0f9b1aaf92 Make extra modules (stl, reflection) into compile time options. Task #118 2010-11-11 04:36:43 +00:00
Jason Turner
912379d58c Fix some compile warnings 2010-11-09 21:06:50 +00:00
Jason Turner
91c05f0e73 Apply patch (and rearrange a directory) from emarcotte for pkgconfig support 2010-11-08 13:47:41 +00:00
Jason Turner
906140ec78 Find and fix bug in handling of bound function types_infos and arity.
Remote outdated samples. Move working samples into samples folder and make part of build process. Make building of samples optional.
Closing #107
2010-11-08 05:22:15 +00:00
Jason Turner
e75a354a04 Apply some module and parameter variable naming standards. Remove ChaiScript template where it was no longer necessary. 2010-11-06 05:20:41 +00:00
Jason Turner
36173d277d Closing issue #99 : shared const char * memory issues. Also, clean up some file loading overhead (did not seem to have an performance impact). 2010-11-05 22:01:39 +00:00
Jason Turner
e1e48d732f Wrap up of clean up of warnings in 64bit visual studio 2010-11-05 04:05:02 +00:00
Jason Turner
6e18aa3dcd Further VS 64bit warning fixes. 2010-11-05 02:43:52 +00:00
Jason Turner
6a18862c79 Fix some of the 64bit VS warnings. 2010-11-05 02:22:38 +00:00
Jason Turner
b3dafa385e Add bigobj compile flag for 64bit windows builds. 2010-11-05 01:58:48 +00:00
Jason Turner
70cc1111f3 Regression - fix VisualStudio builds 2010-10-23 16:25:16 +00:00
Jason Turner
2d353cb189 Fix oddity found while testing on msys with G++ 4.5.0 2010-10-23 15:59:39 +00:00
Jason Turner
67bad374a9 Get mutlifile compilation working again and add a test for it 2010-10-22 21:30:58 +00:00
Jason Turner
bff5b8bce0 Add some quick comments 2010-10-14 14:36:32 +00:00
Jason Turner
2cdfac4e47 Add function meta data functions, plus related tests, and some various cleanups for how functions are constructed internally 2010-10-14 14:33:17 +00:00
Jason Turner
0caa782437 Basic unit tests for casting to **. Storing of (double) pointer types is probably not something we will make an effort to support 100%.
Also, tests of all types that are supported.
2010-10-11 03:45:45 +00:00
Jason Turner
caa67e811c Add boost::ref and boost::cref tests for inputs 2010-10-08 18:48:10 +00:00
Jason Turner
c1318eb8b4 Fix llvm (probably affecting gcc too, MSVC is too lax onthe use of "typename") 2010-10-08 18:42:59 +00:00
Jason Turner
3f87210dc5 Several tests and fixes related to type conversions added. Still more to go. 2010-10-08 15:18:58 +00:00
Jason Turner
c3da778103 Preliminary boxed_cast_test added. This test is meant to test all possible boxed_cast conversions that are available. Currently... some basic ones are failing. 2010-10-08 03:07:26 +00:00
Jonathan Turner
5a92146d28 Fix to disallow mixing inline map and array elements 2010-10-02 23:39:17 +00:00
Jason Turner
3ab91356e5 Make inline maps const. Add test for malformed inline map that causes crash 2010-10-02 22:50:09 +00:00
Jason Turner
fa2a7045a7 Make inplace vector construction result in const temp return. Also clean up construction of vectors in code 2010-10-02 22:19:51 +00:00
Jason Turner
512d6b342d Support for const ranges working 2010-10-02 21:56:33 +00:00
Jason Turner
4ab29013ec Add currently failing test for const range support 2010-10-02 21:31:18 +00:00
Jason Turner
3ae748c026 Add "Pair" unit test. It was the basis for failures with Dynamic_Object on MSVC2010 2010-10-02 21:28:13 +00:00
Jason Turner
d8c979b204 Fix for unexpected new base class to std::pair in VS2010. All tests now pass in VS2010 2010-10-02 20:38:46 +00:00
Jason Turner
74e719c053 Add object dependency tracking to make sure that during nested function calls all returned values are not prematurely destructed.
All tests pass on vc2008 now.
2010-10-02 13:26:06 +00:00
Jason Turner
43dbd8ac78 Rip out object caching. With this removed it becomes that much more critical that we fix the scoping issue with references returned from temporaries. 2010-10-01 02:25:29 +00:00
Jason Turner
7b77af3736 Remove commented out code and make variable declarations/scopes consistent with the rest of the C++ codebase 2010-09-30 19:16:03 +00:00
Jason Turner
8b35434e6f rip out a couple hundred lines of code with inheritance 2010-09-30 18:17:32 +00:00
Jason Turner
1e867f5760 Fix broken gcc build introduced during vc2010 fixes 2010-09-30 16:34:27 +00:00
Jason Turner
670eb0692b Visual studio warning reduction and compile fixes for vs2010. Warning suppression on vs2005. Fixes to get cmake working with boost autolinking. Update to support boost 1.44 2010-09-30 14:33:12 +00:00
Jason Turner
4b9d2d130f Add comment about clang work around 2010-09-20 12:57:33 +00:00
Jason Turner
30affb8855 Correct assertion that was causing clang (and any other debug build) to fail tests 2010-09-20 12:47:25 +00:00
Jason Turner
22c2be835a Get chaiscript compiling with LLVM/clang. Resulting code crashes, however. 2010-09-20 03:24:48 +00:00
Jason Turner
a39d70dbca Rip out caching in dispatch kit to get a more clean view of the performance world 2010-09-19 23:24:52 +00:00
Jason Turner
10986c159f Add support for automatic conversion between chaiscript functions and boost::function. Might merit some look to see how much overhead this adds. 2010-09-13 14:24:12 +00:00
Jonathan Turner
cfa42158af Clean up reflection a bit, and how we do pretty printing of ast nodes. Registered new internal_to_string in reflection module so that we
can have automatic pretty printing of ast nodes during repl eval.
2010-08-30 13:37:50 +00:00
Jonathan Turner
054179ead3 Commenting out of previous node value caching scheme. This allows us to profile later, without having these smaller optimizations
clutter up the flow.  This also allows us to pass the reflection test.
2010-08-29 21:33:11 +00:00
Jonathan Turner
8a6a46d0d3 Fix to the method/array dispatch issue 2010-08-29 19:49:57 +00:00
Jason Turner
efae821996 Add some unit tests for reflection and recently discovered array lookup returned from a method problem 2010-08-28 22:55:43 +00:00
Jason Turner
31feab6053 Fix to parsing of single-line comments where the comment at the end of a line was merging statements separated by a single line comment 2010-08-28 22:14:09 +00:00
Jason Turner
7ef12f634d Register AST_Node and Parser, overloaded eval for AST_Node and some const correctness fixes 2010-08-28 21:48:30 +00:00
Jonathan Turner
c6452c4bd6 Rename of Token to AST_Node to be more correct 2010-08-28 18:38:01 +00:00
Jason Turner
71de169e09 Stub out the reflection module 2010-08-28 18:29:38 +00:00
Jason Turner
329244759f Fix warnings discovered on macos 2010-08-28 17:58:02 +00:00
Jonathan Turner
c5f20ea158 A little cleanup of logical and/or since those are now separate evals. 2010-08-19 14:42:18 +00:00
Jonathan Turner
58c62f6333 More refactoring of parser to use the token children types directly instead of using a giant switch statement during build_match. 2010-08-15 02:04:35 +00:00
Jonathan Turner
7f037b26d4 Updated email addresses in copyright information. 2010-08-10 05:24:07 +00:00
Jonathan Turner
b1e357423f Move structure to being inheritance-based in preparation for reflection infrastructure. This technique relies on the vtable's dynamic dispatch for correct evaluation, and removes the giant switch eval style of previous revisions. 2010-08-08 17:18:32 +00:00
Jason Turner
3a904d9f74 Drastically reduce the number of exceptions thrown at runtime (cannot completely eliminate them all, it's the nature of doing what we are doing with making a runtime interface to a compiled system like we are).
profile.chai should see something like a reduction from 35,000 exceptions to about 100.
2010-08-07 19:27:15 +00:00
Jonathan Turner
d838f7a6d4 Renaming of helper function char_between. Adding help to check for hitting the end of input. 2010-08-07 02:18:51 +00:00
Jonathan Turner
556e7ad916 Cleaned up the formatting a bit. Switched parser over to using charBetween, which significantly improves
readability of the early parsing rules.
2010-08-06 11:17:53 +00:00
Jason Turner
21253043d1 Add option for "light" testing, which greatly reduces compile times 2010-08-05 13:44:23 +00:00
Jason Turner
f215cae866 Add string.c_str() and string.data() methods. 2010-08-05 13:38:11 +00:00
Jason Turner
ea93903884 Fix build problem that was causing chaiscript_no_threads to still link with boost_thread 2010-08-04 19:17:33 +00:00
Jason Turner
f03189c168 Quiet down some irrelevant warnings in MSVC2008, make dynamic_cast conversions work in msvc across modules by applying a kludge that will probably not work long term, but does work now. This may mean that chaiscript needs to move to being a library? 2010-08-03 17:21:51 +00:00
Jason Turner
a122403c20 Fix problem with functor<>() not casting to the proper type and add unit test for this case 2010-08-03 15:19:20 +00:00
Jason Turner
e1fbf54e40 Make disabling of thread support a configuration time option. This mainly exists for testing purposes. 2010-08-03 03:09:49 +00:00
Jason Turner
2b80ca8cc5 Add missing inheritance unit test 2010-08-03 01:18:15 +00:00
Jason Turner
f4e4f92dae Move type registration into module code, and fix problems with unloading of modules and type conversions registered inside of a module.
We have to allow the same type registration more than once now, just in case several different modules register the same conversion.
2010-08-03 01:17:38 +00:00
Jason Turner
4358564065 Make sure the same base/derived relationship is never registered more than once 2010-08-02 18:18:39 +00:00
Jason Turner
a463ee5ff2 Clean up key used in the thread global object cache, to make sure proper type comparisons are done in the corner cases found in the main boxed_cast<> code a while back 2010-08-02 17:51:30 +00:00
Jason Turner
cd015a8437 Thread safety for dynamic conversions / registration of new inheritance relationship 2010-08-02 17:01:38 +00:00
Jason Turner
8be4aa08db Reduce runtime calls into the new dynamic cast system by first making sure the type is polymorphic.
Cleanup some std::cout calls
2010-08-02 02:30:41 +00:00
Jason Turner
edee892cad Initial check in of support for upcasting during function invocation. No examples or tests are checked in yet. Some reorg was necessary to get things compiling in the right order. Is not currently thread safe and probably does not work properly across module boundaries 2010-08-02 01:38:25 +00:00
Jason Turner
b971ee44ad Make warnings stricter on windows and clean up all legit warnings in our code. 2010-07-30 18:06:17 +00:00
Jason Turner
b9ae4cd528 Make warnings more strict and fix one warning caught by gcc 2010-07-30 16:25:58 +00:00
Jason Turner
4ec21ff552 Add test of dynamic object attribute access shared between c++ and chaiscript 2010-07-25 19:56:19 +00:00
Jason Turner
f5f99961c1 Make sure that stack is properly initialized on a per-thread basis. Fixes #95wq 2010-07-23 20:00:17 +00:00
Jason Turner
f7086c10ec Roll back changes from last 2 checkins - user defined type conversions are going to be too slow and too hard to keep track of. Need more portable / generic approach to solving the actual problem - the ability to deal with inhertance properly 2010-07-23 14:55:32 +00:00
Jason Turner
3d19138c95 Minor reorg of type conversion code to support move to using it in dispatch 2010-07-18 01:52:07 +00:00
Jason Turner
35ac7342b6 Stub in of support for type conversions. Not yet fully implemented. 2010-07-17 21:49:27 +00:00
Jason Turner
3f9b5081c6 Add macro for helping with registering classes with ChaiScript, plus unit test for it 2010-07-17 01:01:21 +00:00
Jason Turner
799b3ef388 Update copyright for 2010 2010-05-15 22:48:54 +00:00
Jason Turner
fe6694297f Set version number to 2.3.3 2010-05-15 22:39:28 +00:00
Jason Turner
e77ec4b16a Clean up the vim syntax a bit, add escape characters and incorporate changes from bram 2010-04-01 19:01:18 +00:00
Jason Turner
f070575205 Cleanups of vim files to get them ready for submission 2010-03-31 20:11:19 +00:00
Jason Turner
43d0d6199a Clean up use recognition of backtick operator functions, add support for .. range operator 2010-03-31 01:01:45 +00:00
Jason Turner
65c5178549 Update copyright/version info for geshi filter 2010-03-31 00:23:02 +00:00
Jason Turner
c928e2992b Fix readline support for the eval 2010-03-30 18:40:55 +00:00
Jason Turner
7fef086cab Add geshi syntax highlighting (updated and cleaned up from the version that was hosted at chaiscript.com) 2010-03-30 16:50:18 +00:00
Jason Turner
791fd242e7 Add "throw" built in function to vim syntax highlighting 2010-03-30 16:38:20 +00:00
Jason Turner
e81b71ccc7 Add missing README for vim highlighting 2010-03-30 16:21:35 +00:00
Jason Turner
ef7a785214 Initial check-in of vim syntax highlighting 2010-03-30 16:21:06 +00:00
Jason Turner
f431d479fc Add support for using cmake to build RPMs 2010-03-30 02:01:59 +00:00
Jason Turner
e11eca406d Get cpack working for source and deb distribtions. Still need to check nsis and rpm 2010-03-29 15:32:20 +00:00
Jason Turner
7efb65a5c2 Move to using cmake for VisualStudio 2010-03-28 13:31:19 +00:00
Jason Turner
39339d769a Get the rest of the unit tests passing. Note: ChaiScript now requires CMake 2.8, which is almost a year old, so this is fair, but for the meantime we will have to either get it from backports in ubuntu or from cmake.org 2010-03-19 00:50:36 +00:00
Jason Turner
7ac9ea7249 Add the ability to specify "load_module" and "use" search paths. The capability is primitive and it is currently used by chaiscript_eval to set a single path from environment variables 2010-03-18 22:53:52 +00:00
Jason Turner
7080f5d681 Use ctest to run unit tests. run "make test" to run them. Note, anything "use"ing another file or loading a module will fail. Need to come up with some cross platform mechanism for specifying include dirs to solve this. Current thought: using environment variables "CHAI_USE_PATH" and "CHAI_MODULE_PATH" 2010-03-16 04:07:38 +00:00
Jason Turner
22d994009e Add missing unit_test.inc file 2010-03-14 14:54:00 +00:00
Jason Turner
567f911093 Move to a more standardized unit testing design which relies less on OS support and can soon be moved to a ctest implementation 2010-03-14 05:19:24 +00:00
Jason Turner
5c98a5d6e7 Add sync_cache to set_state code to fix logic flaw in resetting of state and memory leak. #92 2010-03-09 02:09:05 +00:00
Jason Turner
856b682e72 Testing of memberscope so we can close #91 2010-03-09 01:39:54 +00:00
Jason Turner
faaa964565 No longer allow a local variable to be used as a function during dot notation sugar lookup. It's far less confusing this way 2010-01-27 03:54:42 +00:00
Jason Turner
d8213a4206 Convert from #warning to #pragma message for notification of thread safety being disabled, so support more compilers portably 2010-01-19 01:54:00 +00:00
Jason Turner
3a4421a57c Fix empty array unit test by reimplementing the node->children.size() test erroneously removed in r466 2010-01-07 01:47:04 +00:00
Jonathan Turner
31fec2202c Add the answer to the unittest I added earlier 2010-01-06 19:42:09 +00:00
Jonathan Turner
13178e55e1 Add unit test that dies after r465 2010-01-06 19:39:04 +00:00
Jason Turner
968da650b2 Clean up leaking #define's for iterations (n, m) that could mess up subsequently included files such as boost/signals2.hpp 2010-01-03 15:48:17 +00:00
Jason Turner
fb5ba0be26 Remove std::swap implementation that was not supported for multiple file compilation. 2010-01-03 15:03:26 +00:00
Jason Turner
39a2c39d90 Minor fixes to example.cpp to avoid exceptions 2009-12-30 15:29:36 +00:00
Jason Turner
70047424f9 Get compiling with Visual Studio 10 beta 2. Had to work around issues with conflicts between boost::function and VisualStudio's std::tr1::mem_fn (http://social.msdn.microsoft.com/Forums/en/vcprerelease/thread/e04d93ed-d686-4ef6-9939-26e34c0955eb). Also had to work around non-standard overloaded std member functions in std::map (http://msdn.microsoft.com/en-us/library/fe72hft9(VS.100).aspx)
Strongly consider rolling this back when the issues are resolved between microsoft and boost. Also, needs to be tested across all platforms.
2009-12-28 17:16:03 +00:00
Jason Turner
2805af1ed2 move from std::numeric_limits::min() to boost::integer_traits::const_min - avoids runtime overhead of the function call. 2009-12-11 15:35:59 +00:00
Jonathan Turner
e5a29ede5f Added 0b1010 binary format. Fixed hex and octal to allow negative ints 2009-12-11 14:46:12 +00:00
Jason Turner
0c0df2c982 VS 2008 related corrections. 2009-12-08 15:57:31 +00:00
Jason Turner
4457df9ff5 Fix NO_THREADS related issues 2009-12-06 05:12:02 +00:00
Jason Turner
e601de9d18 Reduce use of Param_List_Builder by providing call_function implementations for 0,1,2 arity 2009-12-06 01:31:58 +00:00
Jason Turner
37b2ac2056 Implement proper swap for Boxed_Value 2009-12-05 19:30:09 +00:00
Jason Turner
645cdddd70 Small but measurable eval performance increase (in optimized builds) by managing the number of Boxed_Values copies and assignments 2009-12-05 18:54:55 +00:00
Jonathan Turner
ac8462fb67 Fix up some broken sample files 2009-12-02 14:29:42 +00:00
Jason Turner
636c55493c Smartly size the integer returned from a Boxed_POD_Value operation to return an "int" if the resulting value is small enough 2009-12-01 03:52:57 +00:00
Jason Turner
e2a2c14c0d Eliminate use of size_t in stl related wrappings 2009-12-01 02:56:02 +00:00
Jonathan Turner
c418644a5b Fix for single-line comments stopping at semicolon. 2009-11-27 22:52:55 +00:00
Jason Turner
fbf8f53e04 Add Type_Info type and add *_type objects at time of type registration. 2009-11-21 22:47:44 +00:00
Jason Turner
a0c6366479 Added introspecition/classification of types 2009-11-21 06:39:35 +00:00
Jason Turner
15ffbd200a Fixed unittests broken by last checkin 2009-11-21 06:39:11 +00:00
Jason Turner
1c6b2725b3 Provide some hints for dispatches with lhs (first param) that is const 2009-11-21 06:02:17 +00:00
Jason Turner
95c124ca35 Support better tracking of loaded modules for saving and setting of state 2009-11-21 05:28:00 +00:00
Jason Turner
1bd73884b2 Add documentation to the set_state get_state functions 2009-11-18 05:05:40 +00:00
Jason Turner
d3e4af433e Add support for saving/restoring of chaiscript engine state. 2009-11-18 04:43:08 +00:00
Jason Turner
9f65303370 Handle case of const & return values (should probably be investigated a bit more) 2009-11-18 04:42:43 +00:00
327 changed files with 14669 additions and 8079 deletions

View File

@@ -1,45 +1,216 @@
cmake_minimum_required(VERSION 2.6)
cmake_minimum_required(VERSION 2.8)
project(chaiscript)
option(MULTITHREAD_SUPPORT_ENABLED "Multithreaded Support Enabled" TRUE)
option(BUILD_MODULES "Build Extra Modules (stl, reflection)" TRUE)
option(BUILD_SAMPLES "Build Samples Folder" FALSE)
list(APPEND CPACK_SOURCE_IGNORE_FILES "${CMAKE_CURRENT_BINARY_DIR}")
list(APPEND CPACK_SOURCE_IGNORE_FILES "\\\\.svn")
list(APPEND CPACK_SOURCE_IGNORE_FILES "\\\\.git")
list(APPEND CPACK_SOURCE_IGNORE_FILES ".swp")
list(APPEND CPACK_SOURCE_IGNORE_FILES ".*~")
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/license.txt")
set(CPACK_RESOURCE_FILE_README "${CMAKE_CURRENT_SOURCE_DIR}/readme.txt")
set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/description.txt")
set(CPACK_PACKAGE_VERSION_MAJOR 3)
set(CPACK_PACKAGE_VERSION_MINOR 1)
set(CPACK_PACKAGE_VERSION_PATCH 0)
set(CPACK_PACKAGE_EXECUTABLES "chai;ChaiScript Eval")
set(CPACK_PACKAGE_VENDOR "ChaiScript.com")
set(CPACK_PACKAGE_CONTACT "contact@chaiscript.com")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "An embedded scripting language for C++")
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libboost-dev (>=1.36.0)")
set(CPACK_DEBIAN_PACKAGE_SECTION "devel")
set(CPACK_DEBIAN_PACKAGE_PRIORITY "optional")
set(CPACK_RPM_PACKAGE_LICENSE "BSD")
set(CPACK_RPM_PACKAGE_GROUP "Programming")
set(CPACK_RPM_PACKAGE_REQUIRES "boost-devel >= 1.36.0, boost-thread >= 1.36.0")
set(CHAI_VERSION ${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH})
configure_file(Doxyfile.in ${CMAKE_BINARY_DIR}/Doxyfile)
include(CTest)
include(CPack)
FIND_LIBRARY(READLINE_LIBRARY NAMES readline PATH /usr/lib /usr/local/lib /opt/local/lib)
enable_testing()
MESSAGE(STATUS "Detecting readline support")
if (READLINE_LIBRARY)
MESSAGE(STATUS "Found: ${READLINE_LIBRARY}")
SET (READLINE_LIB readline)
SET (READLINE_FLAG " -DREADLINE_AVAILABLE")
ADD_DEFINITIONS(/DREADLINE_AVAILABLE)
else(READLINE_LIBRARY)
MESSAGE(STATUS "Not Found")
SET (READLINE_LIB )
SET (READLINE_FLAG )
endif(READLINE_LIBRARY)
SET (CMAKE_C_FLAGS_REL " -Wall -O3 ${READLINE_FLAG}")
SET (CMAKE_CXX_FLAGS_REL " -Wall -O3 ${READLINE_FLAG}")
IF(MSVC)
ADD_DEFINITIONS(/W4)
IF(CMAKE_CL_64)
ADD_DEFINITIONS(/bigobj)
ENDIF()
ELSE()
ADD_DEFINITIONS(-Wall -Wextra -Wshadow)
SET (CMAKE_C_FLAGS " -Wall -ggdb ${READLINE_FLAG}")
SET (CMAKE_CXX_FLAGS " -Wall -ggdb ${READLINE_FLAG}")
IF (APPLE)
# -Wno-missing-field-initializers is for boost on macos
ADD_DEFINITIONS(-Wno-missing-field-initializers -Wno-sign-compare)
ENDIF()
ENDIF()
include_directories(include)
find_package(Boost 1.36.0 COMPONENTS thread)
SET(Boost_ADDITIONAL_VERSIONS "1.44" "1.44.0" "1.43" "1.43.0" "1.42" "1.42.0" "1.41")
SET(Boost_USE_MULTITHREADED ON)
if (Boost_FOUND)
include_directories(${Boost_INCLUDE_DIRS})
add_executable(chaiscript_eval src/main.cpp)
#add_executable(dispatchkit_test contrib/test/dispatchkit_test.cpp)
target_link_libraries(chaiscript_eval dl ${Boost_LIBRARIES} ${READLINE_LIB})
if (MULTITHREAD_SUPPORT_ENABLED)
find_package(Boost 1.36.0 COMPONENTS thread)
add_library(test MODULE src/test_module.cpp)
target_link_libraries(test ${Boost_LIBRARIES})
if (Boost_FOUND)
link_directories( ${Boost_LIBRARY_DIRS} )
else()
message(FATAL_ERROR "Can not find Boost")
endif(Boost_FOUND)
else()
ADD_DEFINITIONS(-DCHAISCRIPT_NO_THREADS)
endif()
add_library(stl_extra MODULE src/stl_extra.cpp)
target_link_libraries(stl_extra ${Boost_LIBRARIES})
if (CMAKE_HOST_UNIX)
SET(DYNAMIC_LOADER "dl")
endif(CMAKE_HOST_UNIX)
install(TARGETS chaiscript_eval DESTINATION ${CMAKE_CURRENT_SOURCE_DIR}/bin)
if (MSVC)
# Boost on MSVC does automatic linking
SET(LIBS ${DYNAMIC_LOADER} ${READLINE_LIB})
else()
SET(LIBS ${DYNAMIC_LOADER} ${Boost_LIBRARIES} ${READLINE_LIB})
endif()
if (CMAKE_COMPILER_2005)
# vs2005 is a bit too loud about possible loss of data warnings
# ADD_DEFINITIONS(/wd4244)
endif()
include_directories(${Boost_INCLUDE_DIRS})
include_directories(${Boost_INCLUDE_DIR})
add_executable(chai src/main.cpp)
target_link_libraries(chai ${LIBS})
if (BUILD_SAMPLES)
add_executable(example samples/example.cpp)
target_link_libraries(example ${LIBS})
add_executable(memory_leak_test samples/memory_leak_test.cpp)
target_link_libraries(memory_leak_test ${LIBS})
endif()
if (BUILD_MODULES)
add_library(stl_extra MODULE src/stl_extra.cpp)
target_link_libraries(stl_extra ${LIBS})
add_library(reflection MODULE src/reflection.cpp)
target_link_libraries(reflection ${LIBS})
set(MODULES stl_extra reflection)
endif()
file(GLOB UNIT_TESTS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/unittests/ ${CMAKE_CURRENT_SOURCE_DIR}/unittests/*.chai)
list(SORT UNIT_TESTS)
IF(BUILD_TESTING)
option(UNIT_TEST_LIGHT "Unit tests light (expect module loading failures)" FALSE)
foreach(filename ${UNIT_TESTS})
message(STATUS "Adding test ${filename}")
add_test(${filename} chai ${CMAKE_CURRENT_SOURCE_DIR}/unittests/unit_test.inc ${CMAKE_CURRENT_SOURCE_DIR}/unittests/${filename})
endforeach(filename)
SET_PROPERTY(TEST ${UNIT_TESTS}
PROPERTY ENVIRONMENT
"CHAI_USE_PATH=${CMAKE_CURRENT_SOURCE_DIR}/unittests/"
"CHAI_MODULE_PATH=${CMAKE_CURRENT_BINARY_DIR}/"
)
IF (NOT UNIT_TEST_LIGHT)
add_executable(utility_test unittests/utility_test.cpp)
target_link_libraries(utility_test ${LIBS})
add_test(NAME Utility_Test COMMAND utility_test)
add_executable(dynamic_object_test unittests/dynamic_object_test.cpp)
target_link_libraries(dynamic_object_test ${LIBS})
add_test(NAME Dynamic_Object_Test COMMAND dynamic_object_test)
add_executable(functor_creation_test unittests/functor_creation_test.cpp)
target_link_libraries(functor_creation_test ${LIBS})
add_test(NAME Functor_Creation_Test COMMAND functor_creation_test)
add_executable(functor_cast_test unittests/functor_cast_test.cpp)
target_link_libraries(functor_cast_test ${LIBS})
add_test(NAME Functor_Cast_Test COMMAND functor_cast_test)
add_executable(boxed_cast_test unittests/boxed_cast_test.cpp)
target_link_libraries(boxed_cast_test ${LIBS})
add_test(NAME Boxed_Cast_Test COMMAND boxed_cast_test)
add_executable(object_lifetime_test unittests/object_lifetime_test.cpp)
target_link_libraries(object_lifetime_test ${LIBS})
add_test(NAME Object_Lifetime_Test COMMAND object_lifetime_test)
add_executable(function_ordering_test unittests/function_ordering_test.cpp)
target_link_libraries(function_ordering_test ${LIBS})
add_test(NAME Function_Ordering_Test COMMAND function_ordering_test)
add_executable(type_info_test unittests/type_info_test.cpp)
target_link_libraries(type_info_test ${LIBS})
add_test(NAME Type_Info_Test COMMAND type_info_test)
add_executable(eval_catch_exception_test unittests/eval_catch_exception_test.cpp)
target_link_libraries(eval_catch_exception_test ${LIBS})
add_test(NAME Eval_Catch_Exception_Test COMMAND eval_catch_exception_test)
add_executable(multifile_test unittests/multifile_test_main.cpp unittests/multifile_test_chai.cpp
unittests/multifile_test_module.cpp)
target_link_libraries(multifile_test ${LIBS})
add_test(NAME MultiFile_Test COMMAND multifile_test)
add_library(test_module MODULE src/test_module.cpp)
target_link_libraries(test_module ${LIBS})
install(TARGETS test_module RUNTIME DESTINATION bin LIBRARY DESTINATION lib/chaiscript)
ENDIF()
ENDIF(BUILD_TESTING)
install(TARGETS chai ${MODULES} RUNTIME DESTINATION bin LIBRARY DESTINATION lib/chaiscript )
install(DIRECTORY include/chaiscript DESTINATION include
PATTERN "*.hpp"
PATTERN "*/.svn*" EXCLUDE
PATTERN "*/.git*" EXCLUDE
PATTERN "*~" EXCLUDE)
install(DIRECTORY unittests DESTINATION share/chaiscript
PATTERN "*.chai"
PATTERN "*.inc"
PATTERN "*/.svn*" EXCLUDE
PATTERN "*/.git*" EXCLUDE
PATTERN "*~" EXCLUDE)
install(DIRECTORY samples DESTINATION share/chaiscript
PATTERN "*.chai"
PATTERN "*/.svn*" EXCLUDE
PATTERN "*/.git*" EXCLUDE
PATTERN "*~" EXCLUDE)
else(Boost_FOUND)
message(FATAL_ERROR "Can not find Boost")
endif(Boost_FOUND)
configure_file(contrib/pkgconfig/chaiscript.pc.in lib/pkgconfig/chaiscript.pc @ONLY)
install(FILES "${chaiscript_BINARY_DIR}/lib/pkgconfig/chaiscript.pc"
DESTINATION lib/pkgconfig)

1661
Doxyfile.in Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1 +0,0 @@
This is a placeholder

View File

@@ -1,8 +0,0 @@
#!/bin/bash
cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo .
make install
INCLUDED_FILES="include/chaiscript/*.hpp include/chaiscript/dispatchkit/*.hpp include/chaiscript/language/*.hpp bin/chaiscript_eval"
zip -r chaiscript-1.0.zip $INCLUDED_FILES

View File

@@ -0,0 +1,25 @@
def isprime(n)
{
for (var i = 2; i < n; ++i)
{
if (n % i == 0) {return false}
}
return true
}
def primes(n)
{
var count = 0
for (var i = 2; i <= n; ++i)
{
if (isprime(i)) {++count}
}
return count
}
var N = 5000
print("primes: " + primes(N).to_string())

View File

@@ -0,0 +1,9 @@
var something = 0;
for (var i = 1; i < 10000; ++i)
{
something += int(3 % 2 * 4 + 2 / 16.0 - 100 + (10 ^ 19) / 64 + (3 & 12) - (4 | 14)) % i;
}
print(something);

View File

@@ -0,0 +1,136 @@
<?php
/*************************************************************************************
* chaiscript.php
* --------------
* Author: Jason Turner & Jonathan Turner (based on JavaScript by Ben Keen (ben.keen@gmail.com))
* Copyright: (c) 2010 Jason Turner (jason@emptycrate.com) (c) 2009 Jonathan Turner
* (c) 2004 Ben Keen (ben.keen@gmail.com), Nigel McNie (http://qbnz.com/highlighter)
* Release Version: 1.0
* Date Started: 2009/07/03
*
* ChaiScript language file for GeSHi.
*
* CHANGES
* -------
* 2009/07/03 (1.0.0)
* - First Release
* 2010/03/30 (1.1.0)
* - Updated to include more language features and remove left over pieces from JavaScript
*
*************************************************************************************
*
* This file is part of GeSHi.
*
* GeSHi is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* GeSHi is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GeSHi; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
************************************************************************************/
$language_data = array (
'LANG_NAME' => 'Chaiscript',
'COMMENT_SINGLE' => array(1 => '//'),
'COMMENT_MULTI' => array('/*' => '*/'),
//Regular Expressions
'COMMENT_REGEXP' => array(2 => "/(?<=[\\s^])s\\/(?:\\\\.|(?!\n)[^\\/\\\\])+\\/(?:\\\\.|(?!\n)[^\\/\\\\])+\\/[gimsu]*(?=[\\s$\\.\\;])|(?<=[\\s^(=])m?\\/(?:\\\\.|(?!\n)[^\\/\\\\])+\\/[gimsu]*(?=[\\s$\\.\\,\\;\\)])/iU"),
'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
'QUOTEMARKS' => array("'", '"'),
'ESCAPE_CHAR' => '\\',
'KEYWORDS' => array(
1 => array(
'break', 'else', 'else if', 'eval', 'for', 'if', 'return', 'while', 'try', 'catch', 'finally',
),
2 => array(
'def', 'false', 'fun', 'true', 'var', 'attr',
),
3 => array(
// built in functions
'throw',
)
),
'SYMBOLS' => array(
'(', ')', '[', ']', '{', '}',
'+', '-', '*', '/', '%',
'!', '@', '&', '|', '^',
'<', '>', '=',
',', ';', '?', ':'
),
'CASE_SENSITIVE' => array(
GESHI_COMMENTS => false,
1 => false,
2 => false,
3 => false
),
'STYLES' => array(
'KEYWORDS' => array(
1 => 'color: #000066; font-weight: bold;',
2 => 'color: #003366; font-weight: bold;',
3 => 'color: #000066;'
),
'COMMENTS' => array(
1 => 'color: #006600; font-style: italic;',
2 => 'color: #009966; font-style: italic;',
'MULTI' => 'color: #006600; font-style: italic;'
),
'ESCAPE_CHAR' => array(
0 => 'color: #000099; font-weight: bold;'
),
'BRACKETS' => array(
0 => 'color: #009900;'
),
'STRINGS' => array(
0 => 'color: #3366CC;'
),
'NUMBERS' => array(
0 => 'color: #CC0000;'
),
'METHODS' => array(
1 => 'color: #660066;'
),
'SYMBOLS' => array(
0 => 'color: #339933;'
),
'REGEXPS' => array(
),
'SCRIPT' => array(
0 => '',
1 => '',
2 => '',
3 => ''
)
),
'URLS' => array(
1 => '',
2 => '',
3 => ''
),
'OOLANG' => true,
'OBJECT_SPLITTERS' => array(
1 => '.'
),
'REGEXPS' => array(
),
'STRICT_MODE_APPLIES' => GESHI_MAYBE,
'SCRIPT_DELIMITERS' => array(
0 => array(
),
1 => array(
)
),
'HIGHLIGHT_STRICT_BLOCK' => array(
0 => true,
1 => true
)
);
?>

View File

@@ -0,0 +1,12 @@
prefix=@CMAKE_INSTALL_PREFIX@
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=${prefix}/include
Name: chaiscript
Description: ChaiScript is a scripting language that easily embeds into your existing C++ applications. It's built to be flexible and dynamic, yet still maintain the type-safety you expect as a C++ user. It can natively use classes, methods, and attributes, even if the class inherits functionality from a parent class.
Version: @CPACK_PACKAGE_VERSION_MAJOR@.@CPACK_PACKAGE_VERSION_MINOR@.@CPACK_PACKAGE_VERSION_PATCH@
Requires:
Conflicts:
Libs:
Cflags: -I${includedir}

View File

@@ -1,69 +0,0 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009, Jonathan Turner (jturner@minnow-lang.org)
// and Jason Turner (lefticus@gmail.com)
// http://www.chaiscript.com
#include <iostream>
#include "function_call.hpp"
#include "chaiscript.hpp"
#include <boost/function.hpp>
struct Callback_Handler
{
typedef std::vector<std::pair<boost::function<std::string ()>,
boost::function<double (int)> > > Callbacks;
Callbacks m_callbacks;
void add_callbacks(boost::shared_ptr<dispatchkit::Proxy_Function> t_name,
boost::shared_ptr<dispatchkit::Proxy_Function> t_value)
{
m_callbacks.push_back(
std::make_pair(dispatchkit::build_function_caller<std::string ()>(t_name),
dispatchkit::build_function_caller<double (int)>(t_value)
)
);
}
void do_callbacks()
{
int i=1;
for (Callbacks::iterator itr = m_callbacks.begin();
itr != m_callbacks.end();
++itr)
{
std::cout << "Name: " << itr->first() << " = " << itr->second(i) << std::endl;
++i;
}
}
};
int main(int argc, char *argv[]) {
chaiscript::ChaiScript_Engine chai;
Callback_Handler cb_handler;
chai.get_eval_engine().add_object("cb_handler", boost::ref(cb_handler));
dispatchkit::register_function(chai.get_eval_engine(), &Callback_Handler::add_callbacks, "add_callbacks");
for (int i = 1; i < argc; ++i) {
try {
dispatchkit::Boxed_Value val = chai.evaluate_file(argv[i]);
}
catch (std::exception &e) {
std::cerr << "Could not open: " << argv[i] << std::endl;
exit(1);
}
}
cb_handler.do_callbacks();
boost::function<std::string (const std::string&, const std::string &)> f =
dispatchkit::build_functor<std::string (const std::string &, const std::string &)>
(chai, "function(x, y) { return x + y }");
std::cout << "Functor call: " << f("Hello", " World") << std::endl;
}

View File

@@ -1,212 +0,0 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009, Jonathan Turner (jturner@minnow-lang.org)
// and Jason Turner (lefticus@gmail.com)
// http://www.chaiscript.com
#include <iostream>
#include <string>
#include <vector>
#include <boost/shared_ptr.hpp>
#include <boost/function.hpp>
#include <chaiscript/dispatchkit/dispatchkit.hpp>
#include <chaiscript/dispatchkit/bootstrap.hpp>
#include <chaiscript/dispatchkit/bootstrap_stl.hpp>
#include <chaiscript/dispatchkit/function_call.hpp>
using namespace dispatchkit;
struct Test
{
Test(const std::string &s)
: number(-25), message(s)
{
std::cout << "Test class constructed with value: " << s << std::endl;
}
void show_message()
{
std::cout << "Constructed Message: " << message << std::endl;
}
std::string &get_message()
{
return message;
}
int number;
std::string message;
};
Boxed_Value named_func_call(Dispatch_Engine &ss,
const std::string &nametocall, const std::vector<Boxed_Value> &params)
{
if (params.size() == 2)
{
return dispatch(ss.get_function(nametocall), params);
} else {
throw std::runtime_error("Invalid num params");
}
}
// A function that takes a dynamic list of params
// and calls a bunch of conversion functions on them and
// returns the result as a boxed_value
Boxed_Value dynamic_function(Dispatch_Engine &ss, const std::string &name,
const std::vector<Boxed_Value> &params)
{
if (name == "concat_string")
{
Boxed_Value result;
//Return a void if there is nothing in the array
if (params.size() == 0)
{
return result;
} else {
//else, prepopulate the result with a string conversion of the first
//param
result =
dispatch(ss.get_function("to_string"), Param_List_Builder() << params[0]);
}
//Then, loop over all remaining params, converting them to strings and adding
//them to the result. This example maybe bette served with a string += operator
//implementation, but it works.
for (size_t i = 1; i < params.size(); ++i)
{
result =
dispatch(ss.get_function("+"), Param_List_Builder() << result <<
dispatch(ss.get_function("to_string"), Param_List_Builder() << params[i]));
}
return result;
} else {
throw std::runtime_error("Unknown function call");
}
}
void test(const std::string &p)
{
std::cout << "Test: " << p << std::endl;
}
//Test main
int main()
{
Dispatch_Engine ss;
Bootstrap::bootstrap(ss);
bootstrap_vector<std::vector<int> >(ss, "VectorInt");
dump_system(ss);
//Calling a function by name and allowing the built in dispatch mechanism to
//choose the most appropriate version of the function
Boxed_Value addresult = dispatch(ss.get_function("+"), Param_List_Builder() << double(5.1) << double(10.3));
//Using the cast to unbox the resultant value and output it
std::cout << boxed_cast<double>(addresult) << std::endl;
//Using the Boxed_Value as input to another function, again with automatic dispatch.
//This time we will not bother saving the result and will instead send it straight out
std::cout << boxed_cast<double>(
dispatch(ss.get_function("*"), Param_List_Builder() << 2 << addresult)
) << std::endl;
//Register a new function, this one with typing for us, so we don't have to ubox anything
//right here
//Now we have a print method, let's try to print out the earlier example:
//so, we dispatch the to_string and pass its result as a param to "print"
//In this example we don't bother with temporaries and we don't have to know
//anything about types
dispatch(ss.get_function("print_string"),
Param_List_Builder() << dispatch(ss.get_function("to_string"), Param_List_Builder() << addresult));
// Now we are going to register a new dynamic function,
// when this function is called the objects are not unboxed, but passed
// in in their boxed state
ss.register_function(boost::shared_ptr<Proxy_Function>(new Dynamic_Proxy_Function(boost::bind(&dynamic_function, boost::ref(ss), "concat_string", _1))), "concat_string");
// Call our newly defined dynamic function with 10 parameters, then send
// its output to the "print" function
dispatch(ss.get_function("print_string"),
Param_List_Builder() << dispatch(ss.get_function("concat_string"),
Param_List_Builder() << std::string("\n\t") << std::string("The Value Was: ")
<< double(42.5) << std::string(".")
<< '\n'
<< '\t' << std::string("The old value was: ")
<< addresult << '.' << '\n' ));
//Register some local methods of the "Test" class
ss.register_function(build_constructor<Test, const std::string &>(), "Test");
register_function(ss, &Test::get_message, "get_message");
register_function(ss, &Test::show_message, "show_message");
register_member(ss, &Test::number, "number");
//Create a new object using the "Test" constructor, passing the param "Yo".
//Then, add the new object to the system with the name "testobj2"
ss.add_object("testobj2",
dispatch(ss.get_function("Test"), Param_List_Builder() << std::string("Yo")));
// Look up and store a reference to our new object
std::vector<Boxed_Value> sos;
sos.push_back(ss.get_object("testobj2"));
//Build a bound function proxy for calling the script handled function
boost::function<void (Test &)> show_message =
build_function_caller<void (Test &)>(ss.get_function("show_message"));
Test &t = boxed_cast<Test &>(ss.get_object("testobj2"));
//Print the message the object was created with
show_message(t);
//Now, get a reference to the object's stored message
Boxed_Value stringref = dispatch(ss.get_function("get_message"), sos);
//Unbox it using boxed_cast
std::string &sr = boxed_cast<std::string &>(stringref);
//Update the value of the reference
sr = "Bob Updated The message";
//Now, get a reference to the object's stored number
Boxed_Value numberref= dispatch(ss.get_function("number"), sos);
//Unbox it using boxed_cast
int &ir = boxed_cast<int &>(numberref);
std::cout << "Number: " << ir << std::endl;
//Now, prove that the reference was successfully acquired
//and we are able to peek into the boxed types
show_message(t);
// Finally, we are going to register some named function aliases, for
// the fun of it
ss.register_function(boost::shared_ptr<Proxy_Function>(
new Dynamic_Proxy_Function(boost::bind(&named_func_call, boost::ref(ss), "+", _1))), "add");
//Call our newly named "add" function (which in turn dispatches +)
std::cout << "Result of add function: " <<
boxed_cast<int>(dispatch(ss.get_function("add"), Param_List_Builder() << 5 << 2))
<< std::endl;
ss.set_object("myfunc", boost::shared_ptr<Proxy_Function>(new Proxy_Function_Impl<boost::function<void (const std::string &)> >(&test)));
dispatch(ss.get_function("myfunc"), Param_List_Builder() << std::string("hello function variable"));
}

View File

@@ -1,23 +0,0 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009, Jonathan Turner (jturner@minnow-lang.org)
// and Jason Turner (lefticus@gmail.com)
// http://www.chaiscript.com
#include "dispatchkit.hpp"
#include "bootstrap.hpp"
#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE boxedcpp_unittests
#include <boost/test/unit_test.hpp>
BOOST_AUTO_TEST_CASE( add_operators )
{
using namespace dispatchkit;
Dispatch_Engine ss;
Bootstrap::bootstrap(ss);
dump_system(ss);
BOOST_CHECK_EQUAL(boxed_cast<int>(dispatch(ss.get_function("+"), Param_List_Builder() << double(5.1) << double(10.3))), 15.4);
}

View File

@@ -1,148 +0,0 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009, Jonathan Turner (jturner@minnow-lang.org)
// and Jason Turner (lefticus@gmail.com)
// http://www.chaiscript.com
#include <iostream>
#include "chaiscript.hpp"
#include "function_call.hpp"
#include <boost/function.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/regex.hpp>
std::string load_text_file(const std::string &filename)
{
std::ifstream infile(filename.c_str());
std::string str;
std::string result;
while (std::getline(infile, str))
{
result += str + "\n";
}
return result;
}
std::vector<dispatchkit::Boxed_Value> regex_search(const std::string &str, const std::string &regex)
{
boost::smatch matches;
boost::regex_search(str, matches, boost::regex(regex));
std::vector<dispatchkit::Boxed_Value> results;
for (unsigned int i = 0; i < matches.size(); ++i)
{
results.push_back(dispatchkit::Boxed_Value(std::string(matches.str(i))));
}
return results;
}
struct Sensor_Manager
{
struct Sensor
{
int milliseconds;
dispatchkit::Boxed_Value state_object;
boost::function<double (dispatchkit::Boxed_Value)> sensor;
boost::posix_time::ptime next_run;
Sensor(int t_milliseconds, dispatchkit::Boxed_Value t_state_object,
boost::function<double (dispatchkit::Boxed_Value)> t_sensor)
: milliseconds(t_milliseconds), state_object(t_state_object), sensor(t_sensor),
next_run(boost::posix_time::microsec_clock::universal_time()
+ boost::posix_time::milliseconds(milliseconds))
{
}
std::pair<boost::posix_time::ptime, double> get_value()
{
next_run = boost::posix_time::microsec_clock::universal_time()
+ boost::posix_time::milliseconds(milliseconds);
return std::make_pair(boost::posix_time::microsec_clock::universal_time(),
sensor(state_object));
}
};
std::map<std::string, Sensor> m_sensors;
//sensor_manager.add_sensor("CPU", 1000, global_state, function(state) { update_state(state); state["CPU"]; } )
void add_sensor(const std::string &t_name, int t_milliseconds, dispatchkit::Boxed_Value t_state_object,
boost::shared_ptr<dispatchkit::Proxy_Function> t_func)
{
m_sensors.insert(
std::make_pair(t_name,
Sensor(t_milliseconds, t_state_object,
dispatchkit::build_function_caller<double (dispatchkit::Boxed_Value)>(t_func)
)
)
);
}
std::vector<std::pair<std::string, double> > run_sensors()
{
std::vector<std::pair<std::string, double> > results;
boost::posix_time::ptime t(boost::posix_time::microsec_clock::universal_time());
for (std::map<std::string, Sensor>::iterator itr = m_sensors.begin();
itr != m_sensors.end();
++itr)
{
if (itr->second.next_run <= t)
{
results.push_back(std::make_pair(itr->first, itr->second.get_value().second));
}
}
return results;
}
};
int main(int argc, char *argv[]) {
chaiscript::ChaiScript_Engine chai;
Sensor_Manager sensor_manager;
chai.get_eval_engine().add_object("sensor_manager", boost::ref(sensor_manager));
dispatchkit::register_function(chai.get_eval_engine(), &Sensor_Manager::add_sensor, "add_sensor");
dispatchkit::register_function(chai.get_eval_engine(), &regex_search, "regex_search");
dispatchkit::register_function(chai.get_eval_engine(), &load_text_file, "load_text_file");
for (int i = 1; i < argc; ++i) {
try {
chai.evaluate_file(argv[i]);
}
catch (std::exception &e) {
std::cerr << "Could not open: " << argv[i] << std::endl;
exit(1);
}
}
while (true)
{
usleep(1000);
std::vector<std::pair<std::string, double> > sensor_data = sensor_manager.run_sensors();
for (std::vector<std::pair<std::string, double> >::iterator itr = sensor_data.begin();
itr != sensor_data.end();
++itr)
{
std::cout << "Sensor: " << itr->first << " value: " << itr->second << std::endl;
}
}
}

7
contrib/vim/README.txt Normal file
View File

@@ -0,0 +1,7 @@
Install ftdetect, indent and syntax subdirectories to:
~/.vim/
See the vim documentation on this:
http://vimdoc.sourceforge.net/htmldoc/syntax.html#mysyntaxfile

View File

@@ -0,0 +1,2 @@
au BufRead,BufNewFile *.chai set filetype=chaiscript

View File

@@ -0,0 +1,50 @@
" Vim indent file
" Language: ChaiScript
" Maintainer: Jason Turner <lefticus 'at' gmail com>
" Only load this indent file when no other was loaded.
if exists("b:did_indent")
finish
endif
let b:did_indent = 1
setlocal indentexpr=GetChaiScriptIndent()
setlocal autoindent
" Only define the function once.
if exists("*GetChaiScriptIndent")
finish
endif
function! GetChaiScriptIndent()
" Find a non-blank line above the current line.
let lnum = prevnonblank(v:lnum - 1)
" Hit the start of the file, use zero indent.
if lnum == 0
return 0
endif
" Add a 'shiftwidth' after lines that start a block:
" lines containing a {
let ind = indent(lnum)
let flag = 0
let prevline = getline(lnum)
if prevline =~ '^.*{.*'
let ind = ind + &shiftwidth
let flag = 1
endif
" Subtract a 'shiftwidth' after lines containing a { followed by a }
" to keep it balanced
if flag == 1 && prevline =~ '.*{.*}.*'
let ind = ind - &shiftwidth
endif
" Subtract a 'shiftwidth' on lines ending with }
if getline(v:lnum) =~ '^\s*\%(}\)'
let ind = ind - &shiftwidth
endif
return ind
endfunction

View File

@@ -0,0 +1,94 @@
" Vim syntax file
" Language: ChaiScript
" Maintainer: Jason Turner <lefticus 'at' gmail com>
" Quit when a (custom) syntax file was already loaded
if exists("b:current_syntax")
finish
end
syn case match
" syncing method
syn sync fromstart
" Strings
syn region chaiscriptString start=+"+ end=+"+ skip=+\\\\\|\\"+ contains=chaiscriptSpecial,chaiscriptEval,@Spell
" Escape characters
syn match chaiscriptSpecial contained "\\[\\abfnrtv\'\"]\|\\\d\{,3}"
" String evals
syn region chaiscriptEval contained start="${" end="}"
" integer number
syn match chaiscriptNumber "\<\d\+\>"
" floating point number, with dot, optional exponent
syn match chaiscriptFloat "\<\d\+\.\d*\%(e[-+]\=\d\+\)\=\>"
" floating point number, starting with a dot, optional exponent
syn match chaiscriptFloat "\.\d\+\%(e[-+]\=\d\+\)\=\>"
" floating point number, without dot, with exponent
syn match chaiscriptFloat "\<\d\+e[-+]\=\d\+\>"
" Hex strings
syn match chaiscriptNumber "\<0x\x\+\>"
" Binary strings
syn match chaiscriptNumber "\<0b[01]\+\>"
" Various language features
syn keyword chaiscriptCond if else
syn keyword chaiscriptRepeat while for do
syn keyword chaiscriptStatement break continue return
syn keyword chaiscriptExceptions try catch throw
"Keyword
syn keyword chaiscriptKeyword def true false attr
"Built in types
syn keyword chaiscriptType fun var
"Built in funcs, keep it simple
syn keyword chaiscriptFunc eval throw
"Let's treat all backtick operator function lookups as built in too
syn region chaiscriptFunc matchgroup=chaiscriptFunc start="`" end="`"
" Account for the "[1..10]" syntax, treating it as an operator
" Intentionally leaving out all of the normal, well known operators
syn match chaiscriptOperator "\.\."
" Guard seperator as an operator
syn match chaiscriptOperator ":"
" Comments
syn match chaiscriptComment "//.*$" contains=@Spell
syn region chaiscriptComment matchgroup=chaiscriptComment start="/\*" end="\*/" contains=@Spell
hi def link chaiscriptExceptions Exception
hi def link chaiscriptKeyword Keyword
hi def link chaiscriptStatement Statement
hi def link chaiscriptRepeat Repeat
hi def link chaiscriptString String
hi def link chaiscriptNumber Number
hi def link chaiscriptFloat Float
hi def link chaiscriptOperator Operator
hi def link chaiscriptConstant Constant
hi def link chaiscriptCond Conditional
hi def link chaiscriptFunction Function
hi def link chaiscriptComment Comment
hi def link chaiscriptTodo Todo
hi def link chaiscriptError Error
hi def link chaiscriptSpecial SpecialChar
hi def link chaiscriptFunc Identifier
hi def link chaiscriptType Type
hi def link chaiscriptEval Special
let b:current_syntax = "chaiscript"
" vim: nowrap sw=2 sts=2 ts=8 noet

1
description.txt Normal file
View File

@@ -0,0 +1 @@
ChaiScript is a header-only C++ embedded scripting language loosely based on ECMA script. It is designed for ease of use and tight integration with C++. See http://www.chaiscript.com for more details.

View File

@@ -1,27 +1,754 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009, Jonathan Turner (jturner@minnow-lang.org)
// and Jason Turner (lefticus@gmail.com)
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_HPP_
#define CHAISCRIPT_HPP_
#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/function.hpp>
#include <stdexcept>
#include <iostream>
#include <map>
#include <fstream>
#include <boost/shared_ptr.hpp>
/// \mainpage
/// <a href="http://www.chaiscript.com">ChaiScript</a> 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.
///
/// 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.
///
/// 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 <a href="http://www.github.com/ChaiScript/ChaiScript">github</a>.
///
/// <hr>
///
/// \sa chaiscript
/// \sa chaiscript::ChaiScript
/// \sa ChaiScript_Language for Built in Functions
/// \sa \ref LangGettingStarted
/// \sa \ref LangKeywordRef
/// \sa \ref LangInPlaceRef
/// \sa \ref LangObjectSystemRef
/// \sa http://www.chaiscript.com
/// \sa http://www.github.com/ChaiScript/ChaiScript
///
/// <hr>
///
/// \section gettingstarted API Getting Started
///
/// \li \ref basics
/// \li \ref compiling
/// \li \ref eval
/// \li \ref addingitems
/// \li \ref operatoroverloading
/// \li \ref helpermacro
/// \li \ref pointerconversions
/// \li \ref baseclasses
/// \li \ref functionobjects
/// \li \ref threading
/// \li \ref exceptions
///
///
/// \subsection basics Basics
///
/// Basic simple example:
///
/// \code
/// //main.cpp
/// #include <chaiscript/chaiscript.hpp>
///
/// double function(int i, double j)
/// {
/// return i * j;
/// }
///
/// int main()
/// {
/// chaiscript::ChaiScript chai;
/// chai.add(&function, "function");
///
/// double d = chai.eval<double>("function(3, 4.75);");
/// }
/// \endcode
///
/// <hr>
/// \subsection compiling Compiling ChaiScript Applications
///
/// ChaiScript is a header only library with only two dependecies. boost::threads (optional) and the
/// operating system provided dynamic library loader, which has to be specified on some platforms.
///
/// \subsubsection compilinggcc Compiling with GCC
///
/// To compile the above application on a Unix like operating system (MacOS, Linux) with GCC you need to link
/// both boost::threads and the dynamic loader. For example:
///
/// \code
/// gcc main.cpp -I/path/to/chaiscript/headers -ldl -lboost_threads
/// \endcode
///
/// Alternatively, you may compile without threading support.
///
/// \code
/// gcc main.cpp -I/path/to/chaiscript/headers -ldl -DCHAISCRIPT_NO_THREADS
/// \endcode
///
/// <hr>
/// \subsection eval Evaluating Scripts
///
/// Scripts can be evaluated with the () operator, eval method or eval_file method.
///
/// \subsubsection parenoperator () Operator
///
/// operator() can be used as a handy shortcut for evaluating ChaiScript snippets.
/// \code
/// chaiscript::ChaiScript chai;
/// chai("print(\"hello world\")");
/// \endcode
///
/// \sa chaiscript::ChaiScript::operator()(const std::string &)
///
/// \subsubsection evalmethod Method 'eval'
///
/// The eval method is somewhat more verbose and can be used to get typesafely return values
/// from the script.
///
/// \code
/// chaiscript::ChaiScript chai;
/// chai.eval("callsomefunc()");
/// int result = chai.eval<int>("1 + 3");
/// // result now equals 4
/// \endcode
///
/// \sa chaiscript::ChaiScript::eval
///
/// \subsubsection evalfilemethod Method 'eval_file'
///
/// The 'eval_file' method loads a file from disk and executes the script in it
///
/// \code
/// chaiscript::ChaiScript chai;
/// chai.eval_file("myfile.chai");
/// std::string result = chai.eval_file<std::string>("myfile.chai") // extract the last value returned from the file
/// \endcode
///
/// \sa chaiscript::ChaiScript::eval_file
///
/// <hr>
/// \subsection addingitems Adding Items to ChaiScript
///
/// ChaiScript supports 4 basic things that can be added: objects, functions, type infos and Modules
///
/// \subsubsection addingobjects Adding Objects
///
/// Named objects can be created with the chaiscript::var function.
///
/// \code
/// using namespace chaiscript;
/// ChaiScript chai;
/// int i = 5;
/// chai.add(var(i), "i");
/// chai("print(i)");
/// \endcode
///
/// Immutable objects can be created with the chaiscript::const_var function.
///
/// \code
/// chai.add(const_var(i), "i");
/// chai("i = 5"); // exception throw, cannot assign const var
/// \endcode
///
/// 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
/// chaiscript::ChaiScript::add_global_const function.
///
/// \code
/// chai.add_global_const(const_var(i), "i");
/// chai("def somefun() { print(i); }; sumfun();");
/// \endcode
///
/// \subsubsection addingfunctions Adding Functions
///
/// Functions, methods and members are all added using the same function: chaiscript::fun.
///
/// \code
/// using namespace chaiscript;
///
/// class MyClass {
/// public:
/// int memberdata;
/// void method();
/// void method2(int);
/// static void staticmethod();
/// void overloadedmethod();
/// void overloadedmethod(const std::string &);
/// };
///
/// ChaiScript chai;
/// chai.add(fun(&MyClass::memberdata), "memberdata");
/// chai.add(fun(&MyClass::method), "method");
/// chai.add(fun(&MyClass::staticmethod), "staticmethod");
/// \endcode
///
/// Overloaded methods will need some help, to hint the compiler as to which overload you want:
///
/// \code
/// chai.add(fun<void (MyClass::*)()>(&MyClass::overloadedmethod), "overloadedmethod"));
/// chai.add(fun<void (MyClass::*)(const std::string &)>(&MyClass::overloadedmethod, "overloadedmethod"));
/// \endcode
///
/// There are also shortcuts built into chaiscript::fun for binding up to the first two parameters of the function.
///
/// \code
/// MyClass obj;
/// chai.add(fun(&MyClass::method, &obj), "method");
/// chai("method()"); // equiv to obj.method()
/// chai.add(fun(&MyClass::method2, &obj, 3), "method2");
/// chai("method2()"); // equiv to obj.method2(3)
/// \endcode
///
/// \subsubsection addingtypeinfo Adding Type Info
///
/// 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
/// 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
/// (so that ChaiScript can look up the copy constructor).
///
/// Continuing with the example "MyClass" from above:
///
/// \code
/// chai.add(user_type<MyClass>(), "MyClass");
/// \endcode
///
/// \subsubsection addingmodules Adding Modules
///
/// Modules are holders for collections of ChaiScript registrations.
///
/// \code
/// ModulePtr module = get_sum_module();
/// chai.add(module);
/// \endcode
///
/// \sa chaiscript::Module
///
/// <hr>
/// \subsection operatoroverloading Operator Overloading
///
/// Operators are just like any other function in ChaiScript, to overload an operator, simply register it.
///
/// \code
/// class MyClass {
/// MyClass operator+(const MyClass &) const;
/// };
///
/// chai.add(fun(&MyClass::operator+), "+");
///
/// std::string append_string_int(const std::string &t_lhs, int t_rhs)
/// {
/// return t_lhs + boost::lexical_cast<std::string>(t_rhs);
/// }
///
/// chai.add(fun(append_string_int), "+");
/// \endcode
///
/// \sa \ref addingfunctions
///
/// <hr>
/// \subsection helpermacro Class Helper Macro
///
/// Much of the work of adding new classes to ChaiScript can be reduced with the help
/// of the CHAISCRIPT_CLASS helper macro.
///
/// \code
/// class Test
/// {
/// public:
/// void function() {}
/// std::string function2() { return "Function2"; }
/// void function3() {}
/// std::string functionOverload(double) { return "double"; }
/// std::string functionOverload(int) { return "int"; }
/// };
///
/// int main()
/// {
///
/// chaiscript::ModulePtr m = chaiscript::ModulePtr(new chaiscript::Module());
///
/// CHAISCRIPT_CLASS( m,
/// Test,
/// (Test ())
/// (Test (const Test &)),
/// ((function))
/// ((function2))
/// ((function3))
/// ((functionOverload)(std::string (Test::*)(double)))
/// ((functionOverload)(std::string (Test::*)(int)))
/// ((operator=))
/// );
///
/// chaiscript::ChaiScript chai;
/// chai.add(m);
/// }
/// \endcode
///
/// \sa \ref addingmodules
///
/// <hr>
/// \subsection pointerconversions Pointer / Object Conversions
///
/// As much as possible, ChaiScript attempts to convert between &, *, const &, const *, boost::shared_ptr<T>,
/// boost::shared_ptr<const T>, boost::reference_wrapper<T>, boost::reference_wrapper<const T> and value types automatically.
///
/// If a chaiscript::var object was created in C++ from a pointer, it cannot be convered to a shared_ptr (this would add invalid reference counting).
/// Const may be added, but never removed.
///
/// The take away is that you can pretty much expect function calls to Just Work when you need them to.
///
/// \code
/// void fun1(const int *);
/// void fun2(int *);
/// void fun3(int);
/// void fun4(int &);
/// void fun5(const int &);
/// void fun5(boost::shared_ptr<int>);
/// void fun6(boost::shared_ptr<const int>);
/// void fun7(const boost::shared_ptr<int> &);
/// void fun8(const boost::shared_ptr<const int> &);
/// void fun9(boost::reference_wrapper<int>);
/// void fun10(boost::reference_wrapper<const int>);
///
/// int main()
/// {
/// using namespace chaiscript
/// chaiscript::ChaiScript chai;
/// chai.add(fun(fun1), "fun1");
/// chai.add(fun(fun2), "fun2");
/// chai.add(fun(fun3), "fun3");
/// chai.add(fun(fun4), "fun4");
/// chai.add(fun(fun5), "fun5");
/// chai.add(fun(fun6), "fun6");
/// chai.add(fun(fun7), "fun7");
/// chai.add(fun(fun8), "fun8");
/// chai.add(fun(fun9), "fun9");
/// chai.add(fun(fun10), "fun10");
///
/// chai("var i = 10;");
/// chai("fun1(i)");
/// chai("fun2(i)");
/// chai("fun3(i)");
/// chai("fun4(i)");
/// chai("fun5(i)");
/// chai("fun6(i)");
/// chai("fun7(i)");
/// chai("fun8(i)");
/// chai("fun9(i)");
/// chai("fun10(i)");
/// }
/// \endcode
///
/// See the unit test unittests/boxed_cast_test.cpp for a complete breakdown of the automatic casts that
/// available and tested.
///
/// <hr>
/// \subsection baseclasses Base Classes
///
/// 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.
///
/// \code
/// class Base {};
/// class Derived : public Base {};
/// void myfunction(Base *b);
///
/// int main()
/// {
/// chaiscript::ChaiScript chai;
/// chai.add(chaiscript::base_class<Base, Derived>());
/// Derived d;
/// chai.add(chaiscript::var(&d), "d");
/// chai.add(chaiscript::fun(&myfunction), "myfunction");
/// chai("myfunction(d)");
/// }
/// \endcode
///
/// <hr>
///
/// \subsection functionobjects Function Objects
///
/// Functions are first class objects in Chaiscript and ChaiScript supports automatic conversion
/// between ChaiScript functions and boost::function objects.
///
/// \code
/// void callafunc(const boost::function<void (const std::string &)> &t_func)
/// {
/// t_func("bob");
/// }
///
/// int main()
/// {
/// chaiscript::ChaiScript chai;
/// chai.add(chaiscript::fun(&callafunc), "callafunc");
/// chai("callafunc(fun(x) { print(x); })"); // pass a lambda function to the registered function
/// // which expects a typed boost::function
///
/// boost::function<void ()> f = chai.eval<boost::function<void ()> >("dump_system");
/// f(); // call the ChaiScript function dump_system, from C++
/// }
/// \endcode
///
/// <hr>
///
/// \subsection threading Threading
///
/// 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
/// context is created and managed by the engine.
///
/// Thread safety can be disabled by defining CHAISCRIPT_NO_THREADS when using the library.
///
/// Disabling thread safety increases performance and removes the requirement for boost_threads.
///
/// <hr>
///
/// \subsection exceptions Exception Handling
///
/// \subsubsection exceptionsbasics Exception Handling Basics
///
/// Exceptions can be thrown in ChaiScript and caught in C++ or thrown in C++ and caught in
/// ChaiScript.
///
/// \code
/// void throwexception()
/// {
/// throw std::runtime_error("err");
/// }
///
/// int main()
/// {
/// // Throw in C++, catch in ChaiScript
/// chaiscript::ChaiScript chai;
/// chai.add(chaiscript::fun(&throwexception), "throwexception");
/// chai("try { throwexception(); } catch (e) { print(e.what()); }"); // prints "err"
///
/// // Throw in ChaiScript, catch in C++
/// try {
/// chai("throw(1)");
/// } catch (chaiscript::Boxed_Value bv) {
/// int i = chaiscript::boxed_cast<int>(bv);
/// // i == 1
/// }
/// }
/// \endcode
///
/// \subsubsection exceptionsautomatic Exception Handling Automatic Unboxing
///
/// 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.
///
/// Example:
/// \code
/// chaiscript::ChaiScript chai;
///
/// try {
/// chai.eval("throw(runtime_error(\"error\"))", chaiscript::exception_specification<int, double, float, const std::string &, const std::exception &>());
/// } catch (const double e) {
/// } catch (int) {
/// } catch (float) {
/// } catch (const std::string &) {
/// } catch (const std::exception &e) {
/// // This is the one what will be called in the specific throw() above
/// }
/// \endcode
///
/// \sa chaiscript::Exception_Handler for details on automatic exception unboxing
/// \sa chaiscript::exception_specification
/// \page LangObjectSystemRef ChaiScript Language Object Model Reference
///
///
/// ChaiScript has an object system built in, for types defined within the ChaiScript system.
///
/// \code
/// attr Rectangle::height
/// attr Rectangle::width
/// def Rectangle::Rectangle() { this.height = 10; this.width = 20 }
/// def Rectangle::area() { this.height * this.width }
///
/// var rect = Rectangle()
/// rect.height = 30
/// print(rect.area())
/// \endcode
///
/// \sa \ref keywordattr
/// \sa \ref keyworddef
/// \page LangInPlaceRef ChaiScript Language In-Place Creation Reference
/// \section inplacevector Vector
///
/// \code
/// In-place Vector ::= "[" [expression ("," expression)*] "]"
/// \endcode
///
/// \section inplacerangedvector Ranged Vector
///
/// \code
/// In-place Ranged Vector ::= "[" value ".." value "]"
/// \endcode
///
/// Creates a vector over a range (eg. 1..10)
///
/// \section inplacemap Map
///
/// \code
/// In-place Map ::= "[" (string ":" expression)+ "]"
/// \endcode
/// \page LangGettingStarted ChaiScript Language Getting Started
///
/// ChaiScript is a simple language that should feel familiar to anyone who knows
/// C++ or ECMAScript (JavaScript).
///
/// <hr>
/// \section chaiscriptloops Loops
///
/// Common looping constructs exist in ChaiScript
///
/// \code
/// var i = 0;
/// while (i < 10)
/// {
/// // do something
/// ++i;
/// }
/// \endcode
///
/// \code
/// for (var i = 0; i < 10; ++i)
/// {
/// // do something
/// }
/// \endcode
///
/// \sa \ref keywordfor
/// \sa \ref keywordwhile
///
/// <hr>
/// \section chaiscriptifs Conditionals
///
/// If statements work as expected
///
/// \code
/// var b = true;
///
/// if (b) {
/// // do something
/// } else if (c < 10) {
/// // do something else
/// } else {
/// // or do this
/// }
/// \endcode
///
/// \sa \ref keywordif
///
/// <hr>
/// \section chaiscriptfunctions Functions
///
/// Functions are defined with the def keyword
///
/// \code
/// def myfun(x) { print(x); }
///
/// myfun(10);
/// \endcode
///
/// Functions may have "guards" which determine if which is called.
///
/// \code
/// eval> def myfun2(x) : x < 10 { print("less than 10"); }
/// eval> def myfun2(x) : x >= 10 { print("10 or greater"); }
/// eval> myfun2(5)
/// less than 10
/// eval> myfun2(12)
/// 10 or greater
/// \endcode
///
/// \sa \ref keyworddef
/// \sa \ref keywordattr
/// \sa \ref LangObjectSystemRef
///
/// <hr>
/// \section chaiscriptfunctionobjects Function Objects
///
/// Functions are first class types in ChaiScript and can be used as variables.
///
/// \code
/// eval> var p = print;
/// eval> p(1);
/// 1
/// \endcode
///
/// They can also be passed to functions.
///
/// \code
/// eval> def callfunc(f, lhs, rhs) { return f(lhs, rhs); }
/// eval> def dosomething(lhs, rhs) { print("lhs: ${lhs}, rhs: ${rhs}"); }
/// eval> callfunc(dosomething, 1, 2);
/// lhs: 1, rhs: 2
/// \endcode
///
/// Operators can also be treated as functions by using the back tick operator. Building on the above example:
///
/// \code
/// eval> callfunc(`+`, 1, 4);
/// 5
/// eval> callfunc(`*`, 3, 2);
/// 6
/// \endcode
///
/// <hr>
/// \sa \ref LangKeywordRef
/// \sa ChaiScript_Language for Built in Functions
/// \page LangKeywordRef ChaiScript Language Keyword Reference
///
///
/// <hr>
/// \section keywordattr attr
/// Defines a ChaiScript object attribute
///
/// \code
/// Attribute Definition ::= "attr" class_name "::" attribute_name
/// \endcode
///
/// \sa \ref LangObjectSystemRef
///
/// <hr>
/// \section keywordbreak break
/// Stops execution of a looping block.
///
/// \code
/// Break Statement ::= "break"
/// \endcode
///
/// \sa \ref keywordfor
/// \sa \ref keywordwhile
///
///
/// <hr>
/// \section keyworddef def
/// Begins a function or method definition
///
/// \code
/// Function Definition ::= [annotation + CR/LF] "def" identifier "(" [arg ("," arg)*] ")" [":" guard] block
/// Method Definition ::= [annotation + CR/LF] "def" class_name "::" method_name "(" [arg ("," arg)*] ")" [":" guard] block
/// \endcode
///
/// annotation: meta-annotation on function, currently used as documentation. Optional.
/// identifier: name of function. Required.
/// args: comma-delimited list of parameter names. Optional.
/// guards: guarding statement that act as a prerequisite for the function. Optional.
/// { }: scoped block as function body. Required.
///
/// Functions return values in one of two ways:
///
/// By using an explicit return call, optionally passing the value to be returned.
/// By implicitly returning the value of the last expression (if it is not a while or for loop).
///
/// Method definitions for known types extend those types with new methods. This includes C++ and ChaiScript defined types.
/// Method definitions for unknown types implicitly define the named type.
///
/// \sa \ref LangObjectSystemRef
///
///
/// <hr>
/// \section keywordelse else
/// \sa \ref keywordif
///
///
/// <hr>
/// \section keywordfor for
/// \code
/// For Block ::= "for" "(" [initial] ";" stop_condition ";" loop_expression ")" block
/// \endcode
/// This loop can be broken using the \ref keywordbreak command.
///
///
/// <hr>
/// \section keywordfun fun
/// Begins an anonymous function declaration (sometimes called a lambda).
///
/// \code
/// Lambda ::= "fun" "(" [variable] ("," variable)* ")" block
/// \endcode
///
/// \b Examples:
///
/// \code
/// // Generate an anonymous function object that adds 2 to its parameter
/// var f = fun(x) { x + 2; }
/// \endcode
///
/// \sa \ref keyworddef for more details on ChaiScript functions
///
///
/// <hr>
/// \section keywordif if
/// Begins a conditional block of code that only executes if the condition evaluates as true.
/// \code
/// If Block ::= "if" "(" condition ")" block
/// Else If Block ::= "else if" "(" condition ")" block
/// Else Block ::= "else" block
/// \endcode
/// \b Example:
/// \code
/// if (true) {
/// // do something
/// } else if (false) {
/// // do something else
/// } else {
/// // otherwise do this
/// }
/// \endcode
///
///
/// <hr>
/// \section keywordtry try
/// \code
/// Try Block ::= "try" block
/// ("catch" ["(" variable ")"] [":" guards] block)+
/// ["finally" block]
/// \endcode
///
/// \sa ChaiScript_Language::throw
///
/// <hr>
/// \section keywordwhile while
///
/// Begins a conditional block of code that loops 0 or more times, as long as the condition is true
///
/// \code
/// While Block ::= "while" "(" condition ")" block
/// \endcode
/// This loop can be broken using the \ref keywordbreak command.
/// \namespace chaiscript
/// \brief Namespace chaiscript contains every API call that the average user will be concerned with.
/// \namespace chaiscript::detail
/// \brief Classes and functions reserved for internal use. Items in this namespace are not supported.
#include "dispatchkit/dispatchkit.hpp"
#include "dispatchkit/bootstrap.hpp"
#include "dispatchkit/bootstrap_stl.hpp"
#include "dispatchkit/function_call.hpp"
#include "dispatchkit/dynamic_object.hpp"
#include "dispatchkit/boxed_number.hpp"
#ifdef BOOST_HAS_DECLSPEC
#define CHAISCRIPT_MODULE_EXPORT extern "C" __declspec(dllexport)

View File

@@ -1,69 +1,122 @@
#ifndef __chaiscript_threading_hpp__
#define __chaiscript_threading_hpp__
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_THREADING_HPP_
#define CHAISCRIPT_THREADING_HPP_
#ifndef CHAISCRIPT_NO_THREADS
#include <boost/thread.hpp>
#else
#warning "ChaiScript is compiling without thread safety."
#pragma message ("ChaiScript is compiling without thread safety.")
#endif
/// \file
///
/// This file contains code necessary for thread support in ChaiScript.
/// If the compiler definition CHAISCRIPT_NO_THREADS is defined then thread safety
/// is disabled in ChaiScript. This has the result that some code is faster, because mutex locks are not required.
/// It also has the side effect that the chaiscript::ChaiScript object may not be accessed from more than
/// one thread simultaneously.
namespace chaiscript
{
namespace threading
namespace detail
{
/// If threading is enabled, then this namespace contains boost::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
using boost::unique_lock;
using boost::shared_lock;
using boost::lock_guard;
using boost::shared_mutex;
using boost::recursive_mutex;
template<typename T>
class Thread_Storage
{
public:
~Thread_Storage()
{
m_thread_storage.reset();
}
inline T *operator->() const
{
if (!m_thread_storage.get())
/// Typesafe thread specific storage. If threading is enabled, this class uses boost::thread_specific_ptr<T>. 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()
{
m_thread_storage.reset(new T());
m_thread_storage.reset();
}
return m_thread_storage.get();
}
inline T *operator->() const
{
if (!m_thread_storage.get())
{
m_thread_storage.reset(new T());
}
inline T &operator*() const
{
return *(this->operator->());
}
return m_thread_storage.get();
}
private:
mutable boost::thread_specific_ptr<T> m_thread_storage;
};
inline T &operator*() const
{
return *(this->operator->());
}
private:
mutable boost::thread_specific_ptr<T> m_thread_storage;
};
#else
template<typename T>
class Thread_Storage
template<typename T>
class unique_lock
{
public:
inline T *operator->() const
{
return &obj;
}
inline T &operator*() const
{
return obj;
}
private:
mutable T obj;
unique_lock(T &) {}
};
#endif
template<typename T>
class shared_lock
{
public:
shared_lock(T &) {}
void unlock() {}
};
template<typename T>
class lock_guard
{
public:
lock_guard(T &) {}
};
class shared_mutex { };
class recursive_mutex {};
template<typename T>
class Thread_Storage
{
public:
inline T *operator->() const
{
return &obj;
}
inline T &operator*() const
{
return obj;
}
private:
mutable T obj;
};
#endif
}
}
}

View File

@@ -0,0 +1,60 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_BAD_BOXED_CAST_HPP_
#define CHAISCRIPT_BAD_BOXED_CAST_HPP_
#include "type_info.hpp"
namespace chaiscript
{
namespace exception
{
/// \brief Thrown in the event that a Boxed_Value cannot be cast to the desired type
///
/// It is used internally during function dispatch and may be used by the end user.
///
/// \sa chaiscript::boxed_cast
class bad_boxed_cast : public std::bad_cast
{
public:
bad_boxed_cast(const Type_Info &t_from, const std::type_info &t_to,
const std::string &t_what) throw()
: from(t_from), to(&t_to), m_what(t_what)
{
}
bad_boxed_cast(const Type_Info &t_from, const std::type_info &t_to) throw()
: from(t_from), to(&t_to), m_what("Cannot perform boxed_cast")
{
}
bad_boxed_cast(const std::string &t_what) throw()
: m_what(t_what)
{
}
virtual ~bad_boxed_cast() throw() {}
/// \brief Description of what error occured
virtual const char * what() const throw()
{
return m_what.c_str();
}
Type_Info from; ///< Type_Info contained in the Boxed_Value
const std::type_info *to; ///< std::type_info of the desired (but failed) result type
private:
std::string m_what;
};
}
}
#endif

View File

@@ -1,7 +1,7 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009, Jonathan Turner (jturner@minnow-lang.org)
// and Jason Turner (lefticus@gmail.com)
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#include <boost/preprocessor.hpp>
@@ -10,8 +10,8 @@
#define param(z,n,text) BOOST_PP_CAT(text, BOOST_PP_INC(n))
#ifndef BOOST_PP_IS_ITERATING
#ifndef __bind_first_hpp__
#define __bind_first_hpp__
#ifndef CHAISCRIPT_BIND_FIRST_HPP_
#define CHAISCRIPT_BIND_FIRST_HPP_
#include <boost/function.hpp>
#include <boost/bind.hpp>
@@ -30,36 +30,64 @@
namespace chaiscript
{
template<typename Ret, typename O, typename Class BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param) >
boost::function<Ret (BOOST_PP_ENUM_PARAMS(n, Param))>
namespace detail
{
/// \brief Helper function for binding the first parameter of a class method pointer. Used in chaiscript::fun overloads
/// that take 1 or 2 parameters to pre-bind to the function.
///
/// \param[in] f method pointer to bind
/// \param[in] o object to bind as first parameter
/// \returns a new boost::function object with one fewer parameters than the function passed in.
template<typename Ret, typename O, typename Class BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param) >
boost::function<Ret (BOOST_PP_ENUM_PARAMS(n, Param))>
bind_first(Ret (Class::*f)(BOOST_PP_ENUM_PARAMS(n, Param)), const O &o)
{
return boost::bind(f, o BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM(n, param, _));
return boost::bind(boost::mem_fn(f), o BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM(n, param, _));
}
template<typename Ret, typename O, typename Class BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param) >
boost::function<Ret (BOOST_PP_ENUM_PARAMS(n, Param))>
bind_first(Ret (Class::*f)(BOOST_PP_ENUM_PARAMS(n, Param))const, const O &o)
/// \brief Helper function for binding the first parameter of a const class method pointer. Used in chaiscript::fun overloads
/// that take 1 or 2 parameters to pre-bind to the function.
///
/// \param[in] f method pointer to bind
/// \param[in] o object to bind as first parameter
/// \returns a new boost::function object with one fewer parameters than the function passed in.
template<typename Ret, typename O, typename Class BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param) >
boost::function<Ret (BOOST_PP_ENUM_PARAMS(n, Param))>
bind_first(Ret (Class::*f)(BOOST_PP_ENUM_PARAMS(n, Param)) const, const O &o)
{
return boost::bind(f, o BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM(n, param, _));
return boost::bind(boost::mem_fn(f), o BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM(n, param, _));
}
template<typename Ret,typename O BOOST_PP_COMMA_IF(m) BOOST_PP_ENUM_PARAMS(m, typename Param) >
boost::function<Ret (BOOST_PP_ENUM(n, param, Param))>
/// \brief Helper function for binding the first parameter of a function pointer. Used in chaiscript::fun overloads
/// that take 1 or 2 parameters to pre-bind to the function.
///
/// \param[in] f method pointer to bind
/// \param[in] o object to bind as first parameter
/// \returns a new boost::function object with one fewer parameters than the function passed in.
template<typename Ret,typename O BOOST_PP_COMMA_IF(m) BOOST_PP_ENUM_PARAMS(m, typename Param) >
boost::function<Ret (BOOST_PP_ENUM(n, param, Param))>
bind_first(Ret (*f)(BOOST_PP_ENUM_PARAMS(m, Param)), const O &o)
{
return boost::bind(f, o BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM(n, param, _));
}
template<typename Ret,typename O BOOST_PP_COMMA_IF(m) BOOST_PP_ENUM_PARAMS(m, typename Param) >
boost::function<Ret (BOOST_PP_ENUM(n, param, Param))>
/// \brief Helper function for binding the first parameter of a boost::function object. Used in chaiscript::fun overloads
/// that take 1 or 2 parameters to pre-bind to the function.
///
/// \param[in] f method pointer to bind
/// \param[in] o object to bind as first parameter
/// \returns a new boost::function object with one fewer parameters than the function passed in.
template<typename Ret,typename O BOOST_PP_COMMA_IF(m) BOOST_PP_ENUM_PARAMS(m, typename Param) >
boost::function<Ret (BOOST_PP_ENUM(n, param, Param))>
bind_first(const boost::function<Ret (BOOST_PP_ENUM_PARAMS(m, Param))> &f, const O &o)
{
return boost::bind(f, o BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM(n, param, _));
}
}
}
#undef n
#undef m
#endif

View File

@@ -1,168 +1,56 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009, Jonathan Turner (jturner@minnow-lang.org)
// and Jason Turner (lefticus@gmail.com)
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef __bootstrap_hpp
#define __bootstrap_hpp__
#ifndef CHAISCRIPT_BOOTSTRAP_HPP_
#define CHAISCRIPT_BOOTSTRAP_HPP_
#include "dispatchkit.hpp"
#include "dynamic_object.hpp"
#include "register_function.hpp"
#include "operators.hpp"
#include "boxed_number.hpp"
#include <boost/function_types/result_type.hpp>
namespace chaiscript
{
/// \brief Classes and functions useful for bootstrapping of ChaiScript and adding of new types
namespace bootstrap
{
namespace detail
{
/* Special helpers for generating generic "POD" type operators
* The POD operators are needed for general support of C++ POD
* types without iterating out all possible combinations of operators
* (<, >, +, +=, *=, \=, -, <=, >=, ==) and types
* (char, uint8_t, int8_t, uint16_t, int16_t...)
*/
/// \brief Constructs a new POD value object from a Boxed_Number
/// \param[in] v Boxed_Number to copy into the new object
/// \returns The newly created object.
template<typename P1>
P1 &assign_pod(P1 &p1, Boxed_POD_Value v)
boost::shared_ptr<P1> construct_pod(Boxed_Number v)
{
if (v.m_isfloat)
{
return (p1 = P1(v.d));
} else {
return (p1 = P1(v.i));
}
boost::shared_ptr<P1> p(new P1());
Boxed_Value bv(p);
Boxed_Number nb(bv);
nb = v;
return p;
}
template<typename P1>
P1 construct_pod(Boxed_POD_Value v)
{
if (v.m_isfloat)
{
return P1(v.d);
} else {
return P1(v.i);
}
}
template<typename P1>
P1 &assign_bitwise_and_pod(P1 &p1, Boxed_POD_Value r)
{
if (!r.m_isfloat)
{
return p1 &= P1(r.i);
}
throw bad_boxed_cast("&= only valid for integer types");
}
template<typename P1>
P1 &assign_xor_pod(P1 &p1, Boxed_POD_Value r)
{
if (!r.m_isfloat)
{
return p1 ^= P1(r.i);
}
throw bad_boxed_cast("^= only valid for integer types");
}
template<typename P1>
P1 &assign_bitwise_or_pod(P1 &p1, Boxed_POD_Value r)
{
if (!r.m_isfloat)
{
return p1 |= P1(r.i);
}
throw bad_boxed_cast("&= only valid for integer types");
}
template<typename P1>
P1 &assign_difference_pod(P1 &p1, Boxed_POD_Value r)
{
if (r.m_isfloat)
{
return p1 -= P1(r.d);
} else {
return p1 -= P1(r.i);
}
}
template<typename P1>
P1 &assign_left_shift_pod(P1 &p1, Boxed_POD_Value r)
{
if (!r.m_isfloat)
{
return p1 <<= P1(r.i);
}
throw bad_boxed_cast("<<= only valid for integer types");
}
template<typename P1>
P1 &assign_product_pod(P1 &p1, Boxed_POD_Value r)
{
if (r.m_isfloat)
{
return p1 *= P1(r.d);
} else {
return p1 *= P1(r.i);
}
}
template<typename P1>
P1 &assign_quotient_pod(P1 &p1, Boxed_POD_Value r)
{
if (r.m_isfloat)
{
return p1 /= P1(r.d);
} else {
return p1 /= P1(r.i);
}
}
template<typename P1>
P1 &assign_remainder_pod(P1 &p1, Boxed_POD_Value r)
{
if (!r.m_isfloat)
{
return p1 %= P1(r.i);
}
throw bad_boxed_cast("%= only valid for integer types");
}
template<typename P1>
P1 &assign_right_shift_pod(P1 &p1, Boxed_POD_Value r)
{
if (!r.m_isfloat)
{
return p1 >>= P1(r.i);
}
throw bad_boxed_cast(">>= only valid for integer types");
}
template<typename P1>
P1 &assign_sum_pod(P1 &p1, Boxed_POD_Value r)
{
if (r.m_isfloat)
{
return p1 += P1(r.d);
} else {
return p1 += P1(r.i);
}
}
}
/// \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,out] m The Module to add the copy constructor to
/// \tparam T The type to add a copy constructor for
/// \returns The passed in ModulePtr, or the newly constructed one if the default param is used
template<typename T>
ModulePtr copy_constructor(const std::string &type, ModulePtr m = ModulePtr(new Module()))
{
m->add(constructor<T (const T &)>(), type);
return m;
}
/// \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 ModulePtr or the newly constructed one if the default params are used.
template<typename T>
ModulePtr opers_comparison(ModulePtr m = ModulePtr(new Module()))
{
@@ -175,68 +63,15 @@ namespace chaiscript
return m;
}
template<typename T>
ModulePtr opers_integer_arithmetic(ModulePtr m = ModulePtr(new Module()))
{
operators::assign_bitwise_and<T>(m);
operators::assign_xor<T>(m);
operators::assign_bitwise_or<T>(m);
operators::assign_difference<T>(m);
operators::assign_left_shift<T>(m);
operators::assign_product<T>(m);
operators::assign_quotient<T>(m);
operators::assign_remainder<T>(m);
operators::assign_right_shift<T>(m);
operators::assign_sum<T>(m);
operators::prefix_decrement<T>(m);
operators::prefix_increment<T>(m);
operators::addition<T>(m);
operators::unary_plus<T>(m);
operators::subtraction<T>(m);
operators::unary_minus<T>(m);
operators::bitwise_and<T>(m);
operators::bitwise_compliment<T>(m);
operators::bitwise_xor<T>(m);
operators::bitwise_or<T>(m);
operators::division<T>(m);
operators::left_shift<T>(m);
operators::multiplication<T>(m);
operators::remainder<T>(m);
operators::right_shift<T>(m);
return m;
}
template<typename T>
ModulePtr opers_float_arithmetic(ModulePtr m = ModulePtr(new Module()))
{
operators::assign_difference<T>(m);
operators::assign_product<T>(m);
operators::assign_quotient<T>(m);
operators::assign_sum<T>(m);
operators::addition<T>(m);
operators::unary_plus<T>(m);
operators::subtraction<T>(m);
operators::unary_minus<T>(m);
operators::division<T>(m);
operators::multiplication<T>(m);
return m;
}
/**
* Add a copy constructor for type T
*/
template<typename T>
ModulePtr copy_constructor(const std::string &type, ModulePtr m = ModulePtr(new Module()))
{
m->add(constructor<T (const T &)>(), type);
return m;
}
/**
* Add default and copy constructors for type T
*/
/// \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 ModulePtr, or the newly constructed one if the default param is used
/// \sa copy_constructor
/// \sa constructor
template<typename T>
ModulePtr basic_constructors(const std::string &type, ModulePtr m = ModulePtr(new Module()))
{
@@ -245,9 +80,10 @@ namespace chaiscript
return m;
}
/**
* Add POD type constructor for type T. ie: T = type(POD)
*/
/// \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>
ModulePtr construct_pod(const std::string &type, ModulePtr m = ModulePtr(new Module()))
{
@@ -255,16 +91,6 @@ namespace chaiscript
return m;
}
/**
* add user defined single parameter constructor for type T.
* T = type(const U &)
*/
template<typename T, typename U>
ModulePtr constructor_overload(const std::string &type, ModulePtr m = ModulePtr(new Module()))
{
m->add(constructor<T (const U &)>(), type);
return m;
}
/**
* to_string function for internal use. Uses ostream operator<<
@@ -287,15 +113,6 @@ namespace chaiscript
}
/**
* Add assignment operator for T = POD.
*/
template<typename T>
ModulePtr oper_assign_pod(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&detail::assign_pod<T>), "=");
return m;
}
/**
* Add all common functions for a POD type. All operators, and
@@ -305,52 +122,14 @@ namespace chaiscript
ModulePtr bootstrap_pod_type(const std::string &name, ModulePtr m = ModulePtr(new Module()))
{
m->add(user_type<T>(), name);
basic_constructors<T>(name, m);
operators::assign<T>(m);
oper_assign_pod<T>(m);
m->add(constructor<T ()>(), name);
construct_pod<T>(name, m);
m->add(fun(&detail::assign_sum_pod<T>), "+=");
m->add(fun(&detail::assign_difference_pod<T>), "-=");
m->add(fun(&detail::assign_product_pod<T>), "*=");
m->add(fun(&detail::assign_quotient_pod<T>), "/=");
m->add(fun(&to_string<T>), "to_string");
m->add(fun(&parse_string<T>), "to_" + name);
return m;
}
/**
* Add all common functions for a POD type. All operators, and
* common conversions
*/
template<typename T>
ModulePtr bootstrap_integer_type(const std::string &name, ModulePtr m = ModulePtr(new Module()))
{
bootstrap_pod_type<T>(name, m);
m->add(fun(&detail::assign_bitwise_and_pod<T>), "&=");
m->add(fun(&detail::assign_xor_pod<T>), "^=");
m->add(fun(&detail::assign_bitwise_or_pod<T>), "|=");
m->add(fun(&detail::assign_left_shift_pod<T>), "<<=");
m->add(fun(&detail::assign_remainder_pod<T>), "%=");
m->add(fun(&detail::assign_right_shift_pod<T>), ">>=");
opers_integer_arithmetic<T>(m);
return m;
}
/**
* Add all common functions for a POD type. All operators, and
* common conversions
*/
template<typename T>
ModulePtr bootstrap_float_type(const std::string &name, ModulePtr m = ModulePtr(new Module()))
{
bootstrap_pod_type<T>(name, m);
opers_float_arithmetic<T>(m);
return m;
}
/**
* "clone" function for a shared_ptr type. This is used in the case
@@ -383,7 +162,7 @@ namespace chaiscript
* Similar to shared_ptr_clone. Used for Proxy_Function.
*/
template<typename Type>
Boxed_Value ptr_assign(Boxed_Value lhs, const boost::shared_ptr<typename boost::add_const<Type>::type> &rhs)
Boxed_Value ptr_assign(Boxed_Value lhs, const boost::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())))
@@ -391,7 +170,7 @@ namespace chaiscript
lhs.assign(Boxed_Value(rhs));
return lhs;
} else {
throw bad_boxed_cast("type mismatch in pointer assignment");
throw exception::bad_boxed_cast("type mismatch in pointer assignment");
}
}
@@ -411,7 +190,7 @@ namespace chaiscript
{
return (lhs.assign(rhs));
} else {
throw bad_boxed_cast("boxed_value has a set type already");
throw exception::bad_boxed_cast("boxed_value has a set type already");
}
}
@@ -425,22 +204,48 @@ namespace chaiscript
std::cout << s << std::endl;
}
/**
* Add all arithmetic operators for PODs
*/
static void opers_arithmetic_pod(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&operators::addition<Boxed_Value, Boxed_POD_Value, Boxed_POD_Value>), "+");
m->add(fun(&operators::subtraction<Boxed_Value, Boxed_POD_Value, Boxed_POD_Value>), "-");
m->add(fun(&operators::bitwise_and<Boxed_Value, Boxed_POD_Value, Boxed_POD_Value>), "&");
m->add(fun(&operators::bitwise_xor<Boxed_Value, Boxed_POD_Value, Boxed_POD_Value>), "^");
m->add(fun(&operators::bitwise_or<Boxed_Value, Boxed_POD_Value, Boxed_POD_Value>), "|");
m->add(fun(&operators::division<Boxed_Value, Boxed_POD_Value, Boxed_POD_Value>), "/");
m->add(fun(&operators::left_shift<Boxed_Value, Boxed_POD_Value, Boxed_POD_Value>), "<<");
m->add(fun(&operators::multiplication<Boxed_Value, Boxed_POD_Value, Boxed_POD_Value>), "*");
m->add(fun(&operators::remainder<Boxed_Value, Boxed_POD_Value, Boxed_POD_Value>), "%");
m->add(fun(&operators::right_shift<Boxed_Value, Boxed_POD_Value, Boxed_POD_Value>), ">>");
}
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
@@ -451,12 +256,12 @@ namespace chaiscript
{
if (params.size() < 2)
{
throw arity_error(params.size(), 2);
throw exception::arity_error(static_cast<int>(params.size()), 2);
}
Const_Proxy_Function f = boxed_cast<Const_Proxy_Function>(params[0]);
return Boxed_Value(Const_Proxy_Function(new Bound_Function(f,
return Boxed_Value(Const_Proxy_Function(new dispatch::Bound_Function(f,
std::vector<Boxed_Value>(params.begin() + 1, params.end()))));
}
@@ -468,7 +273,7 @@ namespace chaiscript
{
if (params.size() < 1)
{
throw arity_error(params.size(), 1);
throw exception::arity_error(static_cast<int>(params.size()), 1);
}
Const_Proxy_Function f = boxed_cast<Const_Proxy_Function>(params[0]);
@@ -476,11 +281,38 @@ namespace chaiscript
return Boxed_Value(f->call_match(std::vector<Boxed_Value>(params.begin() + 1, params.end())));
}
static bool has_guard(const Const_Proxy_Function &t_pf)
{
boost::shared_ptr<const dispatch::Dynamic_Proxy_Function> pf = boost::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(t_pf);
if (pf)
{
return pf->get_guard();
} else {
return false;
}
}
static Const_Proxy_Function get_guard(const Const_Proxy_Function &t_pf)
{
boost::shared_ptr<const dispatch::Dynamic_Proxy_Function> pf = boost::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(t_pf);
if (pf)
{
if (pf->get_guard())
{
return pf->get_guard();
} else {
throw std::runtime_error("Function does not have a guard");
}
} else {
throw std::runtime_error("Function does not have a guard");
}
}
static void throw_exception(const Boxed_Value &bv) {
throw bv;
}
static boost::shared_ptr<Dispatch_Engine> bootstrap2(boost::shared_ptr<Dispatch_Engine> e = boost::shared_ptr<Dispatch_Engine> (new Dispatch_Engine()))
static boost::shared_ptr<chaiscript::detail::Dispatch_Engine> bootstrap2(boost::shared_ptr<chaiscript::detail::Dispatch_Engine> e = boost::shared_ptr<chaiscript::detail::Dispatch_Engine> (new chaiscript::detail::Dispatch_Engine()))
{
e->add(user_type<void>(), "void");
return e;
@@ -504,35 +336,100 @@ namespace chaiscript
}
}
template<typename FunctionType>
static std::vector<Boxed_Value> do_return_boxed_value_vector(FunctionType f,
const dispatch::Proxy_Function_Base *b)
{
typedef typename boost::function_types::result_type<FunctionType>::type Vector;
Vector v = (b->*f)();
std::vector<Boxed_Value> vbv;
for (typename Vector::const_iterator itr = v.begin();
itr != v.end();
++itr)
{
vbv.push_back(const_var(*itr));
}
return vbv;
}
template<typename Function>
static boost::function<std::vector<Boxed_Value> (const dispatch::Proxy_Function_Base*)> return_boxed_value_vector(const Function &f)
{
return boost::bind(&do_return_boxed_value_vector<Function>, f, _1);
}
public:
/**
* perform all common bootstrap functions for std::string, void and POD types
*/
/// \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 ModulePtr, or newly created one if default argument is used
static ModulePtr bootstrap(ModulePtr m = ModulePtr(new Module()))
{
m->add(user_type<void>(), "void");
m->add(user_type<bool>(), "bool");
m->add(user_type<Boxed_Value>(), "Object");
m->add(user_type<Boxed_POD_Value>(), "PODObject");
m->add(user_type<Proxy_Function>(), "function");
m->add(user_type<Boxed_Number>(), "Number");
m->add(user_type<Proxy_Function>(), "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::annotation), "get_annotation");
m->add(fun(&dispatch::Proxy_Function_Base::operator()), "call");
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(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(fun(boost::function<std::string (const std::runtime_error &)>(&what)), "what");
m->add(user_type<Dynamic_Object>(), "Dynamic_Object");
m->add(constructor<Dynamic_Object (const std::string &)>(), "Dynamic_Object");
m->add(fun(&Dynamic_Object::get_type_name), "get_type_name");
m->add(fun(&Dynamic_Object::get_attrs), "get_attrs");
m->add(fun(&Dynamic_Object::get_attr), "get_attr");
m->add(user_type<dispatch::Dynamic_Object>(), "Dynamic_Object");
m->add(constructor<dispatch::Dynamic_Object (const std::string &)>(), "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::get_attr), "get_attr");
m->eval("def Dynamic_Object::clone() { var new_o := Dynamic_Object(this.get_type_name()); for_each(this.get_attrs(), bind(fun(new_o, x) { new_o.get_attr(x.first) = x.second; }, new_o, _) ); return new_o; }");
m->add(fun(&Boxed_Value::is_undef), "is_undef");
m->add(fun(&Boxed_Value::is_null), "is_null");
m->add(fun(&has_guard), "has_guard");
m->add(fun(&get_guard), "get_guard");
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_const), "is_var_const");
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_type), "is_type");
m->add(fun(&Boxed_Value::get_type_info), "get_type_info");
m->add(user_type<Type_Info>(), "Type_Info");
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::name), "cpp_name");
m->add(fun(&Type_Info::bare_name), "cpp_bare_name");
m->add(fun(&Type_Info::bare_equal), "bare_equal");
typedef bool (Type_Info::*typeinfocompare)(const Type_Info &) const;
m->add(fun(typeinfocompare(&Type_Info::operator==)), "==");
m->add(fun(&Type_Info::bare_equal), "bare_equal");
basic_constructors<bool>("bool", m);
operators::assign<bool>(m);
operators::equal<bool>(m);
m->add(fun(&to_string<const std::string &>), "internal_to_string");
m->add(fun(&Bootstrap::bool_to_string), "internal_to_string");
@@ -540,28 +437,39 @@ namespace chaiscript
m->add(fun(&throw_exception), "throw");
m->add(fun(&what), "what");
bootstrap_float_type<double>("double", m);
bootstrap_integer_type<int>("int", m);
bootstrap_integer_type<size_t>("size_t", m);
bootstrap_integer_type<char>("char", m);
bootstrap_integer_type<boost::int64_t>("int64_t", m);
bootstrap_pod_type<double>("double", m);
bootstrap_pod_type<long double>("long_double", m);
bootstrap_pod_type<float>("float", m);
bootstrap_pod_type<int>("int", m);
bootstrap_pod_type<unsigned int>("unsigned_int", m);
bootstrap_pod_type<unsigned long>("unsigned_long", m);
bootstrap_pod_type<size_t>("size_t", m);
bootstrap_pod_type<char>("char", m);
bootstrap_pod_type<boost::int8_t>("int8_t", m);
bootstrap_pod_type<boost::int16_t>("int16_t", m);
bootstrap_pod_type<boost::int32_t>("int32_t", m);
bootstrap_pod_type<boost::int64_t>("int64_t", m);
bootstrap_pod_type<boost::uint8_t>("uint8_t", m);
bootstrap_pod_type<boost::uint16_t>("uint16_t", m);
bootstrap_pod_type<boost::uint32_t>("uint32_t", m);
bootstrap_pod_type<boost::uint64_t>("uint64_t", m);
operators::logical_compliment<bool>(m);
opers_comparison<Boxed_POD_Value>(m);
opers_arithmetic_pod(m);
m->add(fun(&print), "print_string");
m->add(fun(&println), "println_string");
m->add(Proxy_Function(new Dynamic_Proxy_Function(boost::bind(&bind_function, _1))),
m->add(Proxy_Function(new dispatch::Dynamic_Proxy_Function(boost::bind(&bind_function, _1))),
"bind");
m->add(fun(&shared_ptr_unconst_clone<Proxy_Function_Base>), "clone");
m->add(fun(&ptr_assign<Proxy_Function_Base>), "=");
m->add(fun(&shared_ptr_unconst_clone<dispatch::Proxy_Function_Base>), "clone");
m->add(fun(&ptr_assign<boost::remove_const<dispatch::Proxy_Function_Base>::type>), "=");
m->add(fun(&ptr_assign<boost::add_const<dispatch::Proxy_Function_Base>::type>), "=");
m->add(Proxy_Function(new Dynamic_Proxy_Function(boost::bind(&call_exists, _1))),
m->add(Proxy_Function(new dispatch::Dynamic_Proxy_Function(boost::bind(&call_exists, _1))),
"call_exists");
m->add(fun(&type_match), "type_match");

View File

@@ -1,428 +1,536 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009, Jonathan Turner (jturner@minnow-lang.org)
// and Jason Turner (lefticus@gmail.com)
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
/**
* This file contains utility functions for registration of STL container
* classes. The methodology used is based on the SGI STL concepts.
* http://www.sgi.com/tech/stl/table_of_contents.html
*/
* \file
* This file contains utility functions for registration of STL container
* classes. The methodology used is based on the SGI STL concepts.
* http://www.sgi.com/tech/stl/table_of_contents.html
*/
#ifndef __bootstrap_stl_hpp__
#define __bootstrap_stl_hpp__
#ifndef CHAISCRIPT_BOOTSTRAP_STL_HPP_
#define CHAISCRIPT_BOOTSTRAP_STL_HPP_
#include "dispatchkit.hpp"
#include "register_function.hpp"
namespace chaiscript
{
namespace bootstrap
{
/**
* Bidir_Range, based on the D concept of ranges.
* \todo Update the Range code to base its capabilities on
* the user_typetraits of the iterator passed in
*/
template<typename Container>
struct Bidir_Range
namespace standard_library
{
typedef typename std::iterator_traits<typename Container::iterator>::reference reference_type;
Bidir_Range(Container &c)
: m_begin(c.begin()), m_end(c.end())
{
}
bool empty() const
{
return m_begin == m_end;
}
void pop_front()
{
if (empty())
/**
* Bidir_Range, based on the D concept of ranges.
* \todo Update the Range code to base its capabilities on
* the user_typetraits of the iterator passed in
*/
template<typename Container>
struct Bidir_Range
{
throw std::range_error("Range empty");
}
++m_begin;
}
typedef Container container_type;
typedef typename std::iterator_traits<typename Container::iterator>::reference reference_type;
void pop_back()
{
if (empty())
Bidir_Range(Container &c)
: m_begin(c.begin()), m_end(c.end())
{
}
bool empty() const
{
return m_begin == m_end;
}
void pop_front()
{
if (empty())
{
throw std::range_error("Range empty");
}
++m_begin;
}
void pop_back()
{
if (empty())
{
throw std::range_error("Range empty");
}
--m_end;
}
reference_type front() const
{
if (empty())
{
throw std::range_error("Range empty");
}
return *m_begin;
}
reference_type back() const
{
if (empty())
{
throw std::range_error("Range empty");
}
typename Container::iterator pos = m_end;
--pos;
return *(pos);
}
typename Container::iterator m_begin;
typename Container::iterator m_end;
};
template<typename Container>
struct Const_Bidir_Range
{
throw std::range_error("Range empty");
}
--m_end;
typedef const Container container_type;
typedef typename std::iterator_traits<typename Container::const_iterator>::reference const_reference_type;
Const_Bidir_Range(const Container &c)
: m_begin(c.begin()), m_end(c.end())
{
}
bool empty() const
{
return m_begin == m_end;
}
void pop_front()
{
if (empty())
{
throw std::range_error("Range empty");
}
++m_begin;
}
void pop_back()
{
if (empty())
{
throw std::range_error("Range empty");
}
--m_end;
}
const_reference_type front() const
{
if (empty())
{
throw std::range_error("Range empty");
}
return *m_begin;
}
const_reference_type back() const
{
if (empty())
{
throw std::range_error("Range empty");
}
typename Container::const_iterator pos = m_end;
--pos;
return *(pos);
}
typename Container::const_iterator m_begin;
typename Container::const_iterator m_end;
};
namespace detail {
/**
* Add Bidir_Range support for the given ContainerType
*/
template<typename Bidir_Type>
ModulePtr input_range_type_impl(const std::string &type, ModulePtr m = ModulePtr(new Module()))
{
m->add(user_type<Bidir_Type>(), type + "_Range");
copy_constructor<Bidir_Type>(type + "_Range", m);
m->add(constructor<Bidir_Type (typename Bidir_Type::container_type &)>(), "range");
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");
return m;
}
/**
* 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)
{
typename Type::iterator itr = container.begin();
typename Type::iterator 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)
{
typename Type::iterator itr = container.begin();
typename Type::iterator 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);
}
}
reference_type front() const
{
if (empty())
template<typename ContainerType>
ModulePtr input_range_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
{
throw std::range_error("Range empty");
detail::input_range_type_impl<Bidir_Range<ContainerType> >(type,m);
detail::input_range_type_impl<Const_Bidir_Range<ContainerType> >("Const_" + type, m);
return m;
}
return *m_begin;
}
reference_type back() const
{
if (empty())
/**
* Add random_access_container concept to the given ContainerType
* http://www.sgi.com/tech/stl/RandomAccessContainer.html
*/
template<typename ContainerType>
ModulePtr random_access_container_type(const std::string &/*type*/, ModulePtr m = ModulePtr(new Module()))
{
throw std::range_error("Range empty");
typedef typename ContainerType::reference(ContainerType::*indexoper)(size_t);
typedef typename ContainerType::const_reference(ContainerType::*constindexoper)(size_t) const;
//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(boost::function<typename ContainerType::reference (ContainerType *, int)>
(boost::mem_fn(static_cast<indexoper>(&ContainerType::at)))), "[]");
m->add(
fun(boost::function<typename ContainerType::const_reference (const ContainerType *, int)>
(boost::mem_fn(static_cast<constindexoper>(&ContainerType::at)))), "[]");
return m;
}
typename Container::iterator pos = m_end;
--pos;
return *(pos);
}
typename Container::iterator m_begin;
typename Container::iterator m_end;
};
/**
* Add assignable concept to the given ContainerType
* http://www.sgi.com/tech/stl/Assignable.html
*/
template<typename ContainerType>
ModulePtr assignable_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
{
basic_constructors<ContainerType>(type, m);
operators::assign<ContainerType>(m);
return m;
}
template<typename Range>
struct Retro
{
Retro(const Range &r)
: m_r(r)
{}
/**
* Add container concept to the given ContainerType
* http://www.sgi.com/tech/stl/Container.html
*/
template<typename ContainerType>
ModulePtr container_type(const std::string &/*type*/, ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(boost::function<int (const ContainerType *)>(boost::mem_fn(&ContainerType::size))), "size");
m->add(fun<bool (ContainerType::*)() const>(&ContainerType::empty), "empty");
m->add(fun<void (ContainerType::*)()>(&ContainerType::clear), "clear");
bool empty() { return m_r.empty(); }
void pop_front() { m_r.pop_back(); }
void pop_back() { m_r.pop_front(); }
typename Range::reference_type front() { return m_r.back(); }
typename Range::reference_type back() { return m_r.front(); }
return m;
}
private:
Range m_r;
};
/**
* Add default constructable concept to the given Type
* http://www.sgi.com/tech/stl/DefaultConstructible.html
*/
template<typename Type>
ModulePtr default_constructible_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
{
m->add(constructor<Type ()>(), type);
return m;
}
/**
* Add Bidir_Range support for the given ContainerType
*/
template<typename ContainerType>
ModulePtr input_range_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
{
m->add(user_type<Bidir_Range<ContainerType> >(), type + "_Range");
copy_constructor<Bidir_Range<ContainerType> >(type + "_Range", m);
/**
* Add sequence concept to the given ContainerType
* http://www.sgi.com/tech/stl/Sequence.html
*/
template<typename ContainerType>
ModulePtr sequence_type(const std::string &/*type*/, ModulePtr m = ModulePtr(new Module()))
{
std::string insert_name;
if (typeid(typename ContainerType::value_type) == typeid(Boxed_Value))
{
insert_name = "insert_ref_at";
} else {
insert_name = "insert_at";
}
m->add(constructor<Bidir_Range<ContainerType> (ContainerType &)>(), "range");
m->add(fun(&detail::insert_at<ContainerType>), insert_name);
m->add(fun(&detail::erase_at<ContainerType>), "erase_at");
m->add(fun(&Bidir_Range<ContainerType>::empty), "empty");
m->add(fun(&Bidir_Range<ContainerType>::pop_front), "pop_front");
m->add(fun(&Bidir_Range<ContainerType>::front), "front");
m->add(fun(&Bidir_Range<ContainerType>::pop_back), "pop_back");
m->add(fun(&Bidir_Range<ContainerType>::back), "back");
return m;
}
return m;
}
/**
* Add back insertion sequence concept to the given ContainerType
* http://www.sgi.com/tech/stl/BackInsertionSequence.html
*/
template<typename ContainerType>
ModulePtr back_insertion_sequence_type(const std::string &/*type*/, ModulePtr m = ModulePtr(new Module()))
{
typedef typename ContainerType::reference (ContainerType::*backptr)();
/**
* Add random_access_container concept to the given ContainerType
* http://www.sgi.com/tech/stl/RandomAccessContainer.html
*/
template<typename ContainerType>
ModulePtr random_access_container_type(const std::string &/*type*/, ModulePtr m = ModulePtr(new Module()))
{
typedef typename ContainerType::reference(ContainerType::*indexoper)(size_t);
m->add(fun(static_cast<backptr>(&ContainerType::back)), "back");
//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(boost::function<typename ContainerType::reference (ContainerType *, int)>(static_cast<indexoper>(&ContainerType::at))), "[]");
std::string push_back_name;
if (typeid(typename ContainerType::value_type) == typeid(Boxed_Value))
{
push_back_name = "push_back_ref";
} else {
push_back_name = "push_back";
}
return m;
}
/**
* Add assignable concept to the given ContainerType
* http://www.sgi.com/tech/stl/Assignable.html
*/
template<typename ContainerType>
ModulePtr assignable_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
{
basic_constructors<ContainerType>(type, m);
operators::assign<ContainerType>(m);
return m;
}
/**
* Add container concept to the given ContainerType
* http://www.sgi.com/tech/stl/Container.html
*/
template<typename ContainerType>
ModulePtr container_type(const std::string &/*type*/, ModulePtr m = ModulePtr(new Module()))
{
m->add(fun<size_t (ContainerType::*)() const>(&ContainerType::size), "size");
m->add(fun<bool (ContainerType::*)() const>(&ContainerType::empty), "empty");
m->add(fun<void (ContainerType::*)()>(&ContainerType::clear), "clear");
return m;
}
/**
* Add default constructable concept to the given Type
* http://www.sgi.com/tech/stl/DefaultConstructible.html
*/
template<typename Type>
ModulePtr default_constructible_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
{
m->add(constructor<Type ()>(), type);
return m;
}
/**
* 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)
{
typename Type::iterator itr = container.begin();
typename Type::iterator 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)
{
typename Type::iterator itr = container.begin();
typename Type::iterator 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);
}
/**
* Add sequence concept to the given ContainerType
* http://www.sgi.com/tech/stl/Sequence.html
*/
template<typename ContainerType>
ModulePtr sequence_type(const std::string &/*type*/, ModulePtr m = ModulePtr(new Module()))
{
std::string insert_name;
if (typeid(typename ContainerType::value_type) == typeid(Boxed_Value))
{
insert_name = "insert_ref_at";
} else {
insert_name = "insert_at";
}
m->add(fun(&insert_at<ContainerType>), insert_name);
m->add(fun(&erase_at<ContainerType>), "erase_at");
return m;
}
/**
* Add back insertion sequence concept to the given ContainerType
* http://www.sgi.com/tech/stl/BackInsertionSequence.html
*/
template<typename ContainerType>
ModulePtr back_insertion_sequence_type(const std::string &/*type*/, ModulePtr m = ModulePtr(new Module()))
{
typedef typename ContainerType::reference (ContainerType::*backptr)();
m->add(fun(static_cast<backptr>(&ContainerType::back)), "back");
std::string push_back_name;
if (typeid(typename ContainerType::value_type) == typeid(Boxed_Value))
{
push_back_name = "push_back_ref";
} else {
push_back_name = "push_back";
}
m->add(fun(&ContainerType::push_back), push_back_name);
m->add(fun(&ContainerType::pop_back), "pop_back");
return m;
}
typedef void (ContainerType::*pushback)(const typename ContainerType::value_type &);
m->add(fun(static_cast<pushback>(&ContainerType::push_back)), push_back_name);
m->add(fun(&ContainerType::pop_back), "pop_back");
return m;
}
/**
*Front insertion sequence
*http://www.sgi.com/tech/stl/FrontInsertionSequence.html
*/
template<typename ContainerType>
ModulePtr front_insertion_sequence_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
{
typedef typename ContainerType::reference (ContainerType::*frontptr)();
/**
*Front insertion sequence
*http://www.sgi.com/tech/stl/FrontInsertionSequence.html
*/
template<typename ContainerType>
ModulePtr front_insertion_sequence_type(const std::string &, ModulePtr m = ModulePtr(new Module()))
{
typedef typename ContainerType::reference (ContainerType::*frontptr)();
typedef void (ContainerType::*pushptr)(typename ContainerType::const_reference);
typedef void (ContainerType::*popptr)();
m->add(fun(static_cast<frontptr>(&ContainerType::front)), "front");
m->add(fun(static_cast<frontptr>(&ContainerType::front)), "front");
std::string push_front_name;
if (typeid(typename ContainerType::value_type) == typeid(Boxed_Value))
{
push_front_name = "push_front_ref";
} else {
push_front_name = "push_front";
}
m->add(fun(&ContainerType::push_front), push_front_name);
m->add(fun(&ContainerType::pop_front), "pop_front");
return m;
}
std::string push_front_name;
if (typeid(typename ContainerType::value_type) == typeid(Boxed_Value))
{
push_front_name = "push_front_ref";
} else {
push_front_name = "push_front";
}
/**
* bootstrap a given PairType
* http://www.sgi.com/tech/stl/pair.html
*/
template<typename PairType>
ModulePtr pair_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
{
m->add(user_type<PairType>(), type);
m->add(fun(static_cast<pushptr>(&ContainerType::push_front)), push_front_name);
m->add(fun(static_cast<popptr>(&ContainerType::pop_front)), "pop_front");
return m;
}
m->add(fun(&PairType::first), "first");
m->add(fun(&PairType::second), "second");
basic_constructors<PairType>(type, m);
m->add(constructor<PairType (const typename PairType::first_type &, const typename PairType::second_type &)>(), type);
return m;
}
/**
* bootstrap a given PairType
* http://www.sgi.com/tech/stl/pair.html
*/
template<typename PairType>
ModulePtr pair_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
{
m->add(user_type<PairType>(), type);
/**
* Add pair associative container concept to the given ContainerType
* http://www.sgi.com/tech/stl/PairAssociativeContainer.html
*/
template<typename ContainerType>
ModulePtr pair_associative_container_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
{
pair_type<typename ContainerType::value_type>(type + "_Pair", m);
typename PairType::first_type PairType::* f = &PairType::first;
typename PairType::second_type PairType::* s = &PairType::second;
return m;
}
m->add(fun(f), "first");
m->add(fun(s), "second");
/**
* Add unique associative container concept to the given ContainerType
* http://www.sgi.com/tech/stl/UniqueAssociativeContainer.html
*/
template<typename ContainerType>
ModulePtr unique_associative_container_type(const std::string &/*type*/, ModulePtr m = ModulePtr(new Module()))
{
m->add(fun<size_t (ContainerType::*)(const typename ContainerType::key_type &) const>(&ContainerType::count), "count");
basic_constructors<PairType>(type, m);
m->add(constructor<PairType (const typename PairType::first_type &, const typename PairType::second_type &)>(), type);
return m;
}
/**
* Add a MapType container
* http://www.sgi.com/tech/stl/Map.html
*/
template<typename MapType>
ModulePtr map_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
{
m->add(user_type<MapType>(), type);
m->add(fun(&MapType::operator[]), "[]");
container_type<MapType>(type, m);
assignable_type<MapType>(type, m);
unique_associative_container_type<MapType>(type, m);
pair_associative_container_type<MapType>(type, m);
input_range_type<MapType>(type, m);
return m;
}
/**
* hopefully working List type
* http://www.sgi.com/tech/stl/List.html
*/
template<typename ListType>
ModulePtr list_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
{
m->add(user_type<ListType>(), type);
front_insertion_sequence_type<ListType>(type, m);
back_insertion_sequence_type<ListType>(type, m);
sequence_type<ListType>(type, m);
container_type<ListType>(type, m);
default_constructible_type<ListType>(type, m);
assignable_type<ListType>(type, m);
input_range_type<ListType>(type, m);
return m;
}
/**
* Create a vector type with associated concepts
* http://www.sgi.com/tech/stl/Vector.html
*/
template<typename VectorType>
ModulePtr vector_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
{
m->add(user_type<VectorType>(), type);
back_insertion_sequence_type<VectorType>(type, m);
sequence_type<VectorType>(type, m);
random_access_container_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);
return m;
}
return m;
}
/**
* Add a String container
* http://www.sgi.com/tech/stl/basic_string.html
*/
template<typename String>
ModulePtr string_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
{
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);
/**
* Add pair associative container concept to the given ContainerType
* http://www.sgi.com/tech/stl/PairAssociativeContainer.html
*/
template<typename ContainerType>
ModulePtr pair_associative_container_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
{
pair_type<typename ContainerType::value_type>(type + "_Pair", m);
//Special case: add push_back to string (which doesn't support other back_insertion operations
std::string push_back_name;
if (typeid(typename String::value_type) == typeid(Boxed_Value))
{
push_back_name = "push_back_ref";
} else {
push_back_name = "push_back";
}
m->add(fun(&String::push_back), push_back_name);
return m;
}
typedef typename String::size_type (String::*find_func)(const String &, typename String::size_type) const;
m->add(fun(static_cast<find_func>(&String::find)), "find");
m->add(fun(static_cast<find_func>(&String::rfind)), "rfind");
m->add(fun(static_cast<find_func>(&String::find_first_of)), "find_first_of");
m->add(fun(static_cast<find_func>(&String::find_last_of)), "find_last_of");
m->add(fun(static_cast<find_func>(&String::find_first_not_of)), "find_first_not_of");
m->add(fun(static_cast<find_func>(&String::find_last_not_of)), "find_last_not_of");
/**
* Add unique associative container concept to the given ContainerType
* http://www.sgi.com/tech/stl/UniqueAssociativeContainer.html
*/
template<typename ContainerType>
ModulePtr unique_associative_container_type(const std::string &/*type*/, ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(boost::function<int (const ContainerType *, const typename ContainerType::key_type &)>(boost::mem_fn(&ContainerType::count))), "count");
return m;
return m;
}
/**
* Add a MapType container
* http://www.sgi.com/tech/stl/Map.html
*/
template<typename MapType>
ModulePtr map_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
{
m->add(user_type<MapType>(), type);
typedef typename MapType::mapped_type &(MapType::*elemaccess)(const typename MapType::key_type &);
m->add(fun(static_cast<elemaccess>(&MapType::operator[])), "[]");
container_type<MapType>(type, m);
assignable_type<MapType>(type, m);
unique_associative_container_type<MapType>(type, m);
pair_associative_container_type<MapType>(type, m);
input_range_type<MapType>(type, m);
return m;
}
/**
* hopefully working List type
* http://www.sgi.com/tech/stl/List.html
*/
template<typename ListType>
ModulePtr list_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
{
m->add(user_type<ListType>(), type);
front_insertion_sequence_type<ListType>(type, m);
back_insertion_sequence_type<ListType>(type, m);
sequence_type<ListType>(type, m);
container_type<ListType>(type, m);
default_constructible_type<ListType>(type, m);
assignable_type<ListType>(type, m);
input_range_type<ListType>(type, m);
return m;
}
/**
* Create a vector type with associated concepts
* http://www.sgi.com/tech/stl/Vector.html
*/
template<typename VectorType>
ModulePtr vector_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
{
m->add(user_type<VectorType>(), type);
typedef typename VectorType::reference (VectorType::*frontptr)();
m->add(fun(static_cast<frontptr>(&VectorType::front)), "front");
back_insertion_sequence_type<VectorType>(type, m);
sequence_type<VectorType>(type, m);
random_access_container_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("def Vector::`==`(rhs) : type_match(rhs, this) { \
if ( rhs.size() != this.size() ) { \
return false; \
} else { \
var r1 = range(this); \
var r2 = range(rhs); \
while (!r1.empty()) \
{ \
if (!eq(r1.front(), r2.front())) \
{ \
return false; \
} \
r1.pop_front(); \
r2.pop_front(); \
} \
return true; \
} \
}");
}
return m;
}
/**
* Add a String container
* http://www.sgi.com/tech/stl/basic_string.html
*/
template<typename String>
ModulePtr string_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
{
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
std::string push_back_name;
if (typeid(typename String::value_type) == typeid(Boxed_Value))
{
push_back_name = "push_back_ref";
} else {
push_back_name = "push_back";
}
m->add(fun(&String::push_back), push_back_name);
typedef typename String::size_type (String::*find_func_ptr)(const String &, typename String::size_type) const;
typedef boost::function<int (const String *, const String &, int)> find_func;
m->add(fun(find_func(boost::mem_fn(static_cast<find_func_ptr>(&String::find)))), "find");
m->add(fun(find_func(boost::mem_fn(static_cast<find_func_ptr>(&String::rfind)))), "rfind");
m->add(fun(find_func(boost::mem_fn(static_cast<find_func_ptr>(&String::find_first_of)))), "find_first_of");
m->add(fun(find_func(boost::mem_fn(static_cast<find_func_ptr>(&String::find_last_of)))), "find_last_of");
m->add(fun(find_func(boost::mem_fn(static_cast<find_func_ptr>(&String::find_first_not_of)))), "find_first_not_of");
m->add(fun(find_func(boost::mem_fn(static_cast<find_func_ptr>(&String::find_last_not_of)))), "find_last_not_of");
m->add(fun(&String::c_str), "c_str");
m->add(fun(&String::data), "data");
return m;
}
}
}
}
#endif

View File

@@ -0,0 +1,112 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef __boxed_cast_hpp__
#define __boxed_cast_hpp__
#include "type_info.hpp"
#include "boxed_value.hpp"
#include "boxed_cast_helper.hpp"
#include "dynamic_cast_conversion.hpp"
#include "../chaiscript_threading.hpp"
#include <boost/shared_ptr.hpp>
#include <boost/any.hpp>
#include <boost/function.hpp>
#include <boost/ref.hpp>
#include <boost/cstdint.hpp>
#include <boost/type_traits/add_const.hpp>
#include <boost/type_traits/is_polymorphic.hpp>
#include <boost/integer_traits.hpp>
namespace chaiscript
{
/// \brief Function for extracting a value stored in a Boxed_Value object
/// \tparam Type The type to extract from the Boxed_Value
/// \param[in] bv The Boxed_Value to extract a typed value from
/// \returns Type equivalent to the requested type
/// \throws exception::bad_boxed_cast If the requested conversion is not possible
///
/// boxed_cast will attempt to make conversions between value, &, *, boost::shared_ptr, boost::reference_wrapper,
/// and boost::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
/// ChaiScript function calls.
///
/// \li non-const values can be extracted as const or non-const
/// \li const values can be extracted only as const
/// \li Boxed_Value constructed from pointer or boost::reference_wrapper can be extracted as reference,
/// pointer or value types
/// \li Boxed_Value constructed from boost::shared_ptr or value types can be extracted as reference,
/// pointer, value, or boost::shared_ptr types
///
/// Conversions to boost::function objects are attempted as well
///
/// Example:
/// \code
/// // All of the following should succeed
/// chaiscript::Boxed_Value bv(1);
/// boost::shared_ptr<int> spi = chaiscript::boxed_cast<boost::shared_ptr<int> >(bv);
/// int i = chaiscript::boxed_cast<int>(bv);
/// int *ip = chaiscript::boxed_cast<int *>(bv);
/// int &ir = chaiscript::boxed_cast<int &>(bv);
/// boost::shared_ptr<const int> cspi = chaiscript::boxed_cast<boost::shared_ptr<const int> >(bv);
/// const int ci = chaiscript::boxed_cast<const int>(bv);
/// const int *cip = chaiscript::boxed_cast<const int *>(bv);
/// const int &cir = chaiscript::boxed_cast<const int &>(bv);
/// \endcode
///
/// boost::function conversion example
/// \code
/// chaiscript::ChaiScript chai;
/// Boxed_Value bv = chai.eval("`+`"); // Get the functor for the + operator which is built in
/// boost::function<int (int, int)> f = chaiscript::boxed_cast<boost::function<int (int, int)> >(bv);
/// int i = f(2,3);
/// assert(i == 5);
/// \endcode
template<typename Type>
typename detail::Cast_Helper<Type>::Result_Type boxed_cast(const Boxed_Value &bv)
{
try {
return detail::Cast_Helper<Type>::cast(bv);
} catch (const boost::bad_any_cast &) {
#ifdef BOOST_MSVC
//Thank you MSVC, yes we know that a constant value is being used in the if
// statment in THIS VERSION of the template instantiation
#pragma warning(push)
#pragma warning(disable : 4127)
#endif
if (boost::is_polymorphic<typename detail::Stripped_Type<Type>::type>::value)
{
try {
// We will not catch any bad_boxed_dynamic_cast that is thrown, let the user get it
// either way, we are not responsible if it doesn't work
return detail::Cast_Helper<Type>::cast(detail::boxed_dynamic_cast<Type>(bv));
} catch (const boost::bad_any_cast &) {
throw exception::bad_boxed_cast(bv.get_type_info(), typeid(Type));
}
} else {
// If it's not polymorphic, just throw the error, don't waste the time on the
// attempted dynamic_cast
throw exception::bad_boxed_cast(bv.get_type_info(), typeid(Type));
}
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif
}
}
}
#endif

View File

@@ -0,0 +1,273 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_BOXED_CAST_HELPER_HPP_
#define CHAISCRIPT_BOXED_CAST_HELPER_HPP_
#include "type_info.hpp"
#include "boxed_value.hpp"
#include <boost/shared_ptr.hpp>
#include <boost/any.hpp>
#include <boost/ref.hpp>
#include <boost/type_traits/add_const.hpp>
namespace chaiscript
{
namespace detail
{
// Cast_Helper_Inner helper classes
/**
* Generic Cast_Helper_Inner, for casting to any type
*/
template<typename Result>
struct Cast_Helper_Inner
{
typedef typename boost::reference_wrapper<typename boost::add_const<Result>::type > Result_Type;
static Result_Type cast(const Boxed_Value &ob)
{
if (ob.is_ref())
{
if (!ob.get_type_info().is_const())
{
return boost::cref((boost::any_cast<boost::reference_wrapper<Result> >(ob.get())).get());
} else {
return boost::any_cast<boost::reference_wrapper<const Result> >(ob.get());
}
} else {
if (!ob.get_type_info().is_const())
{
return boost::cref(*(boost::any_cast<boost::shared_ptr<Result> >(ob.get())));
} else {
return boost::cref(*(boost::any_cast<boost::shared_ptr<const Result> >(ob.get())));
}
}
}
};
template<typename Result>
struct Cast_Helper_Inner<const Result> : Cast_Helper_Inner<Result>
{
};
/**
* Cast_Helper_Inner for casting to a const & type
*/
template<typename Result>
struct Cast_Helper_Inner<const Result &> : Cast_Helper_Inner<Result>
{
};
/**
* Cast_Helper_Inner for casting to a const * type
*/
template<typename Result>
struct Cast_Helper_Inner<const Result *>
{
typedef const Result * Result_Type;
static Result_Type cast(const Boxed_Value &ob)
{
if (ob.is_ref())
{
if (!ob.get_type_info().is_const())
{
return (boost::any_cast<boost::reference_wrapper<Result> >(ob.get())).get_pointer();
} else {
return (boost::any_cast<boost::reference_wrapper<const Result> >(ob.get())).get_pointer();
}
} else {
if (!ob.get_type_info().is_const())
{
return (boost::any_cast<boost::shared_ptr<Result> >(ob.get())).get();
} else {
return (boost::any_cast<boost::shared_ptr<const Result> >(ob.get())).get();
}
}
}
};
/**
* Cast_Helper_Inner for casting to a * type
*/
template<typename Result>
struct Cast_Helper_Inner<Result *>
{
typedef Result * Result_Type;
static Result_Type cast(const Boxed_Value &ob)
{
if (ob.is_ref())
{
return (boost::any_cast<boost::reference_wrapper<Result> >(ob.get())).get_pointer();
} else {
return (boost::any_cast<boost::shared_ptr<Result> >(ob.get())).get();
}
}
};
/**
* Cast_Helper_Inner for casting to a & type
*/
template<typename Result>
struct Cast_Helper_Inner<Result &>
{
typedef typename boost::reference_wrapper<Result> Result_Type;
static Result_Type cast(const Boxed_Value &ob)
{
if (ob.is_ref())
{
return boost::any_cast<boost::reference_wrapper<Result> >(ob.get());
} else {
return boost::ref(*(boost::any_cast<boost::shared_ptr<Result> >(ob.get())));
}
}
};
/**
* Cast_Helper_Inner for casting to a boost::shared_ptr<> type
*/
template<typename Result>
struct Cast_Helper_Inner<typename boost::shared_ptr<Result> >
{
typedef typename boost::shared_ptr<Result> Result_Type;
static Result_Type cast(const Boxed_Value &ob)
{
return boost::any_cast<boost::shared_ptr<Result> >(ob.get());
}
};
/**
* Cast_Helper_Inner for casting to a boost::shared_ptr<const> type
*/
template<typename Result>
struct Cast_Helper_Inner<typename boost::shared_ptr<const Result> >
{
typedef typename boost::shared_ptr<const Result> Result_Type;
static Result_Type cast(const Boxed_Value &ob)
{
if (!ob.get_type_info().is_const())
{
return boost::const_pointer_cast<const Result>(boost::any_cast<boost::shared_ptr<Result> >(ob.get()));
} else {
return boost::any_cast<boost::shared_ptr<const Result> >(ob.get());
}
}
};
/**
* Cast_Helper_Inner for casting to a const boost::shared_ptr<> & type
*/
template<typename Result>
struct Cast_Helper_Inner<const boost::shared_ptr<Result> > : Cast_Helper_Inner<boost::shared_ptr<Result> >
{
};
template<typename Result>
struct Cast_Helper_Inner<const boost::shared_ptr<Result> &> : Cast_Helper_Inner<boost::shared_ptr<Result> >
{
};
/**
* Cast_Helper_Inner for casting to a const boost::shared_ptr<const> & type
*/
template<typename Result>
struct Cast_Helper_Inner<const boost::shared_ptr<const Result> > : Cast_Helper_Inner<boost::shared_ptr<const Result> >
{
};
template<typename Result>
struct Cast_Helper_Inner<const boost::shared_ptr<const Result> &> : Cast_Helper_Inner<boost::shared_ptr<const Result> >
{
};
/**
* Cast_Helper_Inner for casting to a Boxed_Value type
*/
template<>
struct Cast_Helper_Inner<Boxed_Value>
{
typedef const Boxed_Value & Result_Type;
static Result_Type cast(const Boxed_Value &ob)
{
return ob;
}
};
/**
* Cast_Helper_Inner for casting to a const Boxed_Value & type
*/
template<>
struct Cast_Helper_Inner<const Boxed_Value> : Cast_Helper_Inner<Boxed_Value>
{
};
template<>
struct Cast_Helper_Inner<const Boxed_Value &> : Cast_Helper_Inner<Boxed_Value>
{
};
/**
* Cast_Helper_Inner for casting to a boost::reference_wrapper type
*/
template<typename Result>
struct Cast_Helper_Inner<boost::reference_wrapper<Result> > : Cast_Helper_Inner<Result &>
{
};
template<typename Result>
struct Cast_Helper_Inner<const boost::reference_wrapper<Result> > : Cast_Helper_Inner<Result &>
{
};
template<typename Result>
struct Cast_Helper_Inner<const boost::reference_wrapper<Result> &> : Cast_Helper_Inner<Result &>
{
};
template<typename Result>
struct Cast_Helper_Inner<boost::reference_wrapper<const Result> > : Cast_Helper_Inner<const Result &>
{
};
template<typename Result>
struct Cast_Helper_Inner<const boost::reference_wrapper<const Result> > : Cast_Helper_Inner<const Result &>
{
};
template<typename Result>
struct Cast_Helper_Inner<const boost::reference_wrapper<const Result> & > : Cast_Helper_Inner<const Result &>
{
};
/**
* The exposed Cast_Helper object that by default just calls the Cast_Helper_Inner
*/
template<typename T>
struct Cast_Helper
{
typedef typename Cast_Helper_Inner<T>::Result_Type Result_Type;
static Result_Type cast(const Boxed_Value &ob)
{
return Cast_Helper_Inner<T>::cast(ob);
}
};
}
}
#endif

View File

@@ -0,0 +1,689 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_BOXED_NUMERIC_HPP_
#define CHAISCRIPT_BOXED_NUMERIC_HPP_
#include "boxed_value.hpp"
#include "../language/chaiscript_algebraic.hpp"
#include <boost/cstdint.hpp>
namespace chaiscript
{
/// \brief Represents any numeric type, generically. Used internally for generic operations between POD values
class Boxed_Number
{
private:
struct boolean
{
#pragma GCC diagnostic ignored "-Wsign-compare"
template<typename T, typename U>
static Boxed_Value go(Operators::Opers t_oper, const T &t, const U &u, const Boxed_Value &)
{
switch (t_oper)
{
case Operators::equals:
return const_var(t == u);
case Operators::less_than:
return const_var(t < u);
case Operators::greater_than:
return const_var(t > u);
case Operators::less_than_equal:
return const_var(t <= u);
case Operators::greater_than_equal:
return const_var(t >= u);
case Operators::not_equal:
return const_var(t != u);
default:
throw boost::bad_any_cast();
}
throw boost::bad_any_cast();
}
};
struct binary
{
template<typename T, typename U>
static Boxed_Value go(Operators::Opers t_oper, T &t, const U &u, const Boxed_Value &t_lhs)
{
switch (t_oper)
{
case Operators::assign:
t = u;
break;
case Operators::pre_increment:
++t;
break;
case Operators::pre_decrement:
--t;
break;
case Operators::assign_product:
t *= u;
break;
case Operators::assign_sum:
t += u;
break;
case Operators::assign_quotient:
t /= u;
break;
case Operators::assign_difference:
t -= u;
break;
default:
throw boost::bad_any_cast();
}
return t_lhs;
}
};
struct binary_int
{
template<typename T, typename U>
static Boxed_Value go(Operators::Opers t_oper, T &t, const U &u, const Boxed_Value &t_lhs)
{
switch (t_oper)
{
case Operators::assign_bitwise_and:
t &= u;
break;
case Operators::assign_bitwise_or:
t |= u;
break;
case Operators::assign_shift_left:
t <<= u;
break;
case Operators::assign_shift_right:
t >>= u;
break;
case Operators::assign_remainder:
t %= u;
break;
case Operators::assign_bitwise_xor:
t ^= u;
break;
default:
throw boost::bad_any_cast();
}
return t_lhs;
}
};
struct const_binary_int
{
template<typename T, typename U>
static Boxed_Value go(Operators::Opers t_oper, const T &t, const U &u, const Boxed_Value &)
{
switch (t_oper)
{
case Operators::shift_left:
return const_var(t << u);
case Operators::shift_right:
return const_var(t >> u);
case Operators::remainder:
return const_var(t % u);
case Operators::bitwise_and:
return const_var(t & u);
case Operators::bitwise_or:
return const_var(t | u);
case Operators::bitwise_xor:
return const_var(t ^ u);
case Operators::bitwise_complement:
return const_var(~t);
default:
throw boost::bad_any_cast();
}
throw boost::bad_any_cast();
}
};
struct const_binary
{
template<typename T, typename U>
static Boxed_Value go(Operators::Opers t_oper, const T &t, const U &u, const Boxed_Value &)
{
switch (t_oper)
{
case Operators::sum:
return const_var(t + u);
case Operators::quotient:
return const_var(t / u);
case Operators::product:
return const_var(t * u);
case Operators::difference:
return const_var(t - u);
case Operators::unary_minus:
return const_var(-t);
case Operators::unary_plus:
return const_var(+t);
default:
throw boost::bad_any_cast();
}
throw boost::bad_any_cast();
}
};
template<typename LHS, typename RHS, bool Float>
struct Go
{
static Boxed_Value go(Operators::Opers t_oper, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs)
{
if (t_oper > Operators::boolean_flag && t_oper < Operators::non_const_flag)
{
return boolean::go<LHS, RHS>(t_oper, *static_cast<const LHS *>(t_lhs.get_const_ptr()), *static_cast<const RHS *>(t_rhs.get_const_ptr()), t_lhs);
} else if (t_oper > Operators::non_const_flag && t_oper < Operators::non_const_int_flag && !t_lhs.is_const()) {
return binary::go<LHS, RHS>(t_oper, *static_cast<LHS *>(t_lhs.get_ptr()), *static_cast<const RHS *>(t_rhs.get_const_ptr()), t_lhs);
} else if (t_oper > Operators::non_const_int_flag && t_oper < Operators::const_int_flag && !t_lhs.is_const()) {
return binary_int::go<LHS, RHS>(t_oper, *static_cast<LHS *>(t_lhs.get_ptr()), *static_cast<const RHS *>(t_rhs.get_const_ptr()), t_lhs);
} else if (t_oper > Operators::const_int_flag && t_oper < Operators::const_flag) {
return const_binary_int::go<LHS, RHS>(t_oper, *static_cast<const LHS *>(t_lhs.get_const_ptr()), *static_cast<const RHS *>(t_rhs.get_const_ptr()), t_lhs);
} else if (t_oper > Operators::const_flag) {
return const_binary::go<LHS, RHS>(t_oper, *static_cast<const LHS *>(t_lhs.get_const_ptr()), *static_cast<const RHS *>(t_rhs.get_const_ptr()), t_lhs);
} else {
throw boost::bad_any_cast();
}
}
};
template<typename LHS, typename RHS>
struct Go<LHS, RHS, true>
{
static Boxed_Value go(Operators::Opers t_oper, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs)
{
if (t_oper > Operators::boolean_flag && t_oper < Operators::non_const_flag)
{
return boolean::go<LHS, RHS>(t_oper, *static_cast<const LHS *>(t_lhs.get_const_ptr()), *static_cast<const RHS *>(t_rhs.get_const_ptr()), t_lhs);
} else if (t_oper > Operators::non_const_flag && t_oper < Operators::non_const_int_flag && !t_lhs.is_const()) {
return binary::go<LHS, RHS>(t_oper, *static_cast<LHS *>(t_lhs.get_ptr()), *static_cast<const RHS *>(t_rhs.get_const_ptr()), t_lhs);
} else if (t_oper > Operators::non_const_int_flag && t_oper < Operators::const_int_flag) {
throw boost::bad_any_cast();
} else if (t_oper > Operators::const_int_flag && t_oper < Operators::const_flag) {
throw boost::bad_any_cast();
} else if (t_oper > Operators::const_flag) {
return const_binary::go<LHS, RHS>(t_oper, *static_cast<const LHS *>(t_lhs.get_const_ptr()), *static_cast<const RHS *>(t_rhs.get_const_ptr()), t_lhs);
} else {
throw boost::bad_any_cast();
}
}
};
template<typename LHS, bool Float>
static Boxed_Value oper_rhs(Operators::Opers t_oper, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs)
{
const Type_Info &inp_ = t_rhs.get_type_info();
if (inp_ == typeid(int)) {
return Go<LHS, int, Float>::go(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(double)) {
return Go<LHS, double, true>::go(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(float)) {
return Go<LHS, float, true>::go(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(long double)) {
return Go<LHS, long double, true>::go(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(char)) {
return Go<LHS, char, Float>::go(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(unsigned int)) {
return Go<LHS, unsigned int, Float>::go(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(long)) {
return Go<LHS, long, Float>::go(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(unsigned long)) {
return Go<LHS, unsigned long, Float>::go(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(boost::int8_t)) {
return Go<LHS, boost::int8_t, Float>::go(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(boost::int16_t)) {
return Go<LHS, boost::int16_t, Float>::go(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(boost::int32_t)) {
return Go<LHS, boost::int32_t, Float>::go(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(boost::int64_t)) {
return Go<LHS, boost::int64_t, Float>::go(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(boost::uint8_t)) {
return Go<LHS, boost::uint8_t, Float>::go(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(boost::uint16_t)) {
return Go<LHS, boost::uint16_t, Float>::go(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(boost::uint32_t)) {
return Go<LHS, boost::uint32_t, Float>::go(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(boost::uint64_t)) {
return Go<LHS, boost::uint64_t, Float>::go(t_oper, t_lhs, t_rhs);
} else {
throw boost::bad_any_cast();
}
}
static Boxed_Value oper(Operators::Opers t_oper, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs)
{
const Type_Info &inp_ = t_lhs.get_type_info();
if (inp_ == typeid(int)) {
return oper_rhs<int, false>(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(double)) {
return oper_rhs<double, true>(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(long double)) {
return oper_rhs<long double, true>(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(float)) {
return oper_rhs<float, true>(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(char)) {
return oper_rhs<char, false>(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(unsigned int)) {
return oper_rhs<unsigned int, false>(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(long)) {
return oper_rhs<long, false>(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(unsigned long)) {
return oper_rhs<unsigned long, false>(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(boost::int8_t)) {
return oper_rhs<boost::int8_t, false>(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(boost::int16_t)) {
return oper_rhs<boost::int32_t, false>(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(boost::int32_t)) {
return oper_rhs<boost::int32_t, false>(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(boost::int64_t)) {
return oper_rhs<boost::int64_t, false>(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(boost::uint8_t)) {
return oper_rhs<boost::uint8_t, false>(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(boost::uint16_t)) {
return oper_rhs<boost::uint16_t, false>(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(boost::uint32_t)) {
return oper_rhs<boost::uint32_t, false>(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(boost::uint64_t)) {
return oper_rhs<boost::uint64_t, false>(t_oper, t_lhs, t_rhs);
} else {
throw boost::bad_any_cast();
}
}
public:
Boxed_Number(const Boxed_Value &v)
: bv(v)
{
const Type_Info &inp_ = v.get_type_info();
if (inp_ == typeid(bool))
{
throw boost::bad_any_cast();
}
if (!inp_.is_arithmetic())
{
throw boost::bad_any_cast();
}
}
bool operator==(const Boxed_Number &t_rhs) const
{
return boxed_cast<bool>(oper(Operators::equals, this->bv, t_rhs.bv));
}
bool operator<(const Boxed_Number &t_rhs) const
{
return boxed_cast<bool>(oper(Operators::less_than, this->bv, t_rhs.bv));
}
bool operator>(const Boxed_Number &t_rhs) const
{
return boxed_cast<bool>(oper(Operators::greater_than, this->bv, t_rhs.bv));
}
bool operator>=(const Boxed_Number &t_rhs) const
{
return boxed_cast<bool>(oper(Operators::greater_than_equal, this->bv, t_rhs.bv));
}
bool operator<=(const Boxed_Number &t_rhs) const
{
return boxed_cast<bool>(oper(Operators::less_than_equal, this->bv, t_rhs.bv));
}
bool operator!=(const Boxed_Number &t_rhs) const
{
return boxed_cast<bool>(oper(Operators::not_equal, this->bv, t_rhs.bv));
}
Boxed_Number operator--()
{
return oper(Operators::pre_decrement, this->bv, var(0));
}
Boxed_Number operator++()
{
return oper(Operators::pre_increment, this->bv, var(0));
}
Boxed_Number operator+(const Boxed_Number &t_rhs) const
{
return oper(Operators::sum, this->bv, t_rhs.bv);
}
Boxed_Number operator+() const
{
return oper(Operators::unary_plus, this->bv, Boxed_Value(0));
}
Boxed_Number operator-() const
{
return oper(Operators::unary_minus, this->bv, Boxed_Value(0));
}
Boxed_Number operator-(const Boxed_Number &t_rhs) const
{
return oper(Operators::difference, this->bv, t_rhs.bv);
}
Boxed_Number operator&=(const Boxed_Number &t_rhs)
{
return oper(Operators::assign_bitwise_and, this->bv, t_rhs.bv);
}
Boxed_Number operator=(const Boxed_Number &t_rhs) const
{
return oper(Operators::assign, this->bv, t_rhs.bv);
}
Boxed_Number operator|=(const Boxed_Number &t_rhs)
{
return oper(Operators::assign_bitwise_or, this->bv, t_rhs.bv);
}
Boxed_Number operator^=(const Boxed_Number &t_rhs)
{
return oper(Operators::assign_bitwise_xor, this->bv, t_rhs.bv);
}
Boxed_Number operator%=(const Boxed_Number &t_rhs)
{
return oper(Operators::assign_remainder, this->bv, t_rhs.bv);
}
Boxed_Number operator<<=(const Boxed_Number &t_rhs)
{
return oper(Operators::assign_shift_left, this->bv, t_rhs.bv);
}
Boxed_Number operator>>=(const Boxed_Number &t_rhs)
{
return oper(Operators::assign_shift_right, this->bv, t_rhs.bv);
}
Boxed_Number operator&(const Boxed_Number &t_rhs) const
{
return oper(Operators::bitwise_and, this->bv, t_rhs.bv);
}
Boxed_Number operator~() const
{
return oper(Operators::bitwise_complement, this->bv, Boxed_Value(0));
}
Boxed_Number operator^(const Boxed_Number &t_rhs) const
{
return oper(Operators::bitwise_xor, this->bv, t_rhs.bv);
}
Boxed_Number operator|(const Boxed_Number &t_rhs) const
{
return oper(Operators::bitwise_or, this->bv, t_rhs.bv);
}
Boxed_Number operator*=(const Boxed_Number &t_rhs)
{
return oper(Operators::assign_product, this->bv, t_rhs.bv);
}
Boxed_Number operator/=(const Boxed_Number &t_rhs)
{
return oper(Operators::assign_quotient, this->bv, t_rhs.bv);
}
Boxed_Number operator+=(const Boxed_Number &t_rhs)
{
return oper(Operators::assign_sum, this->bv, t_rhs.bv);
}
Boxed_Number operator-=(const Boxed_Number &t_rhs)
{
return oper(Operators::assign_difference, this->bv, t_rhs.bv);
}
Boxed_Number operator/(const Boxed_Number &t_rhs) const
{
return oper(Operators::quotient, this->bv, t_rhs.bv);
}
Boxed_Number operator<<(const Boxed_Number &t_rhs) const
{
return oper(Operators::shift_left, this->bv, t_rhs.bv);
}
Boxed_Number operator*(const Boxed_Number &t_rhs) const
{
return oper(Operators::product, this->bv, t_rhs.bv);
}
Boxed_Number operator%(const Boxed_Number &t_rhs) const
{
return oper(Operators::remainder, this->bv, t_rhs.bv);
}
Boxed_Number operator>>(const Boxed_Number &t_rhs) const
{
return oper(Operators::shift_right, this->bv, t_rhs.bv);
}
static bool equals(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
{
return boxed_cast<bool>(oper(Operators::equals, t_lhs.bv, t_rhs.bv));
}
static bool less_than(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
{
return boxed_cast<bool>(oper(Operators::less_than, t_lhs.bv, t_rhs.bv));
}
static bool greater_than(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
{
return boxed_cast<bool>(oper(Operators::greater_than, t_lhs.bv, t_rhs.bv));
}
static bool greater_than_equal(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
{
return boxed_cast<bool>(oper(Operators::greater_than_equal, t_lhs.bv, t_rhs.bv));
}
static bool less_than_equal(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
{
return boxed_cast<bool>(oper(Operators::less_than_equal, t_lhs.bv, t_rhs.bv));
}
static bool not_equal(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
{
return boxed_cast<bool>(oper(Operators::not_equal, t_lhs.bv, t_rhs.bv));
}
static Boxed_Number pre_decrement(Boxed_Number t_lhs)
{
return oper(Operators::pre_decrement, t_lhs.bv, var(0));
}
static Boxed_Number pre_increment(Boxed_Number t_lhs)
{
return oper(Operators::pre_increment, t_lhs.bv, var(0));
}
static const Boxed_Number sum(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::sum, t_lhs.bv, t_rhs.bv);
}
static const Boxed_Number unary_plus(const Boxed_Number &t_lhs)
{
return oper(Operators::unary_plus, t_lhs.bv, Boxed_Value(0));
}
static const Boxed_Number unary_minus(const Boxed_Number &t_lhs)
{
return oper(Operators::unary_minus, t_lhs.bv, Boxed_Value(0));
}
static const Boxed_Number difference(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::difference, t_lhs.bv, t_rhs.bv);
}
static Boxed_Number assign_bitwise_and(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::assign_bitwise_and, t_lhs.bv, t_rhs.bv);
}
static Boxed_Number assign(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::assign, t_lhs.bv, t_rhs.bv);
}
static Boxed_Number assign_bitwise_or(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::assign_bitwise_or, t_lhs.bv, t_rhs.bv);
}
static Boxed_Number assign_bitwise_xor(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::assign_bitwise_xor, t_lhs.bv, t_rhs.bv);
}
static Boxed_Number assign_remainder(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::assign_remainder, t_lhs.bv, t_rhs.bv);
}
static Boxed_Number assign_shift_left(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::assign_shift_left, t_lhs.bv, t_rhs.bv);
}
static Boxed_Number assign_shift_right(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::assign_shift_right, t_lhs.bv, t_rhs.bv);
}
static const Boxed_Number bitwise_and(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::bitwise_and, t_lhs.bv, t_rhs.bv);
}
static const Boxed_Number bitwise_complement(const Boxed_Number &t_lhs)
{
return oper(Operators::bitwise_complement, t_lhs.bv, Boxed_Value(0));
}
static const Boxed_Number bitwise_xor(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::bitwise_xor, t_lhs.bv, t_rhs.bv);
}
static const Boxed_Number bitwise_or(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::bitwise_or, t_lhs.bv, t_rhs.bv);
}
static Boxed_Number assign_product(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::assign_product, t_lhs.bv, t_rhs.bv);
}
static Boxed_Number assign_quotient(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::assign_quotient, t_lhs.bv, t_rhs.bv);
}
static Boxed_Number assign_sum(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::assign_sum, t_lhs.bv, t_rhs.bv);
}
static Boxed_Number assign_difference(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::assign_difference, t_lhs.bv, t_rhs.bv);
}
static const Boxed_Number quotient(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::quotient, t_lhs.bv, t_rhs.bv);
}
static const Boxed_Number shift_left(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::shift_left, t_lhs.bv, t_rhs.bv);
}
static const Boxed_Number product(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::product, t_lhs.bv, t_rhs.bv);
}
static const Boxed_Number remainder(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::remainder, t_lhs.bv, t_rhs.bv);
}
static const Boxed_Number shift_right(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::shift_right, t_lhs.bv, t_rhs.bv);
}
static Boxed_Value do_oper(Operators::Opers t_oper, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs)
{
return oper(t_oper, t_lhs, t_rhs);
}
static Boxed_Value do_oper(Operators::Opers t_oper, const Boxed_Value &t_lhs)
{
return oper(t_oper, t_lhs, const_var(0));
}
Boxed_Value bv;
};
namespace detail
{
/**
* Cast_Helper for converting from Boxed_Value to Boxed_Number
*/
template<>
struct Cast_Helper<Boxed_Number>
{
typedef Boxed_Number Result_Type;
static Result_Type cast(const Boxed_Value &ob)
{
return Boxed_Number(ob);
}
};
/**
* Cast_Helper for converting from Boxed_Value to Boxed_Number
*/
template<>
struct Cast_Helper<const Boxed_Number &> : Cast_Helper<Boxed_Number>
{
};
/**
* Cast_Helper for converting from Boxed_Value to Boxed_Number
*/
template<>
struct Cast_Helper<const Boxed_Number> : Cast_Helper<Boxed_Number>
{
};
}
}
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,287 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_DYNAMIC_CAST_CONVERSION_HPP_
#define CHAISCRIPT_DYNAMIC_CAST_CONVERSION_HPP_
#include "type_info.hpp"
#include "boxed_value.hpp"
#include "boxed_cast_helper.hpp"
#include "bad_boxed_cast.hpp"
#include <boost/static_assert.hpp>
#include <boost/type_traits/is_polymorphic.hpp>
#include <boost/type_traits/is_base_of.hpp>
namespace chaiscript
{
namespace exception
{
class bad_boxed_dynamic_cast : public bad_boxed_cast
{
public:
bad_boxed_dynamic_cast(const Type_Info &t_from, const std::type_info &t_to,
const std::string &t_what) throw()
: bad_boxed_cast(t_from, t_to, t_what)
{
}
bad_boxed_dynamic_cast(const Type_Info &t_from, const std::type_info &t_to) throw()
: bad_boxed_cast(t_from, t_to)
{
}
bad_boxed_dynamic_cast(const std::string &w) throw()
: bad_boxed_cast(w)
{
}
virtual ~bad_boxed_dynamic_cast() throw() {}
};
}
namespace detail
{
class Dynamic_Conversion
{
public:
virtual Boxed_Value convert(const Boxed_Value &derived) = 0;
const Type_Info &base()
{
return m_base;
}
const Type_Info &derived()
{
return m_derived;
}
protected:
Dynamic_Conversion(const Type_Info &t_base, const Type_Info &t_derived)
: m_base(t_base), m_derived(t_derived)
{
}
private:
Type_Info m_base;
Type_Info m_derived;
};
template<typename Base, typename Derived>
class Dynamic_Conversion_Impl : public Dynamic_Conversion
{
public:
Dynamic_Conversion_Impl()
: Dynamic_Conversion(user_type<Base>(), user_type<Derived>())
{
}
virtual Boxed_Value convert(const Boxed_Value &t_derived)
{
if (t_derived.get_type_info().bare_equal(user_type<Derived>()))
{
if (t_derived.is_pointer())
{
// Dynamic cast out the contained boxed value, which we know is the type we want
if (t_derived.is_const())
{
boost::shared_ptr<const Base> data
= boost::dynamic_pointer_cast<const Base>(detail::Cast_Helper<boost::shared_ptr<const Derived> >::cast(t_derived));
if (!data)
{
throw std::bad_cast();
}
return Boxed_Value(data);
} else {
boost::shared_ptr<Base> data
= boost::dynamic_pointer_cast<Base>(detail::Cast_Helper<boost::shared_ptr<Derived> >::cast(t_derived));
if (!data)
{
throw std::bad_cast();
}
return Boxed_Value(data);
}
} else {
// Pull the reference out of the contained boxed value, which we know is the type we want
if (t_derived.is_const())
{
const Derived &d = detail::Cast_Helper<const Derived &>::cast(t_derived);
const Base &data = dynamic_cast<const Base &>(d);
return Boxed_Value(boost::cref(data));
} else {
Derived &d = detail::Cast_Helper<Derived &>::cast(t_derived);
Base &data = dynamic_cast<Base &>(d);
return Boxed_Value(boost::ref(data));
}
}
} else {
throw exception::bad_boxed_dynamic_cast(t_derived.get_type_info(), typeid(Base), "Unknown dynamic_cast_conversion");
}
}
};
class Dynamic_Conversions
{
public:
static inline Dynamic_Conversions &get()
{
static Dynamic_Conversions obj;
return obj;
}
template<typename Base, typename Derived>
static boost::shared_ptr<Dynamic_Conversion> create()
{
boost::shared_ptr<Dynamic_Conversion> conversion(new Dynamic_Conversion_Impl<Base, Derived>());
/// \todo this is a hack and a kludge. The idea is to make sure that
/// the conversion is registered both in the module's notion of the static conversion object
/// and in the global notion of the static conversion object
/// someday this will almost certainly have to change. Maybe it is time for ChaiScript
/// to become a library?
Dynamic_Conversions::get().add_conversion(conversion);
return conversion;
}
template<typename InItr>
void cleanup(InItr begin, const InItr &end)
{
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
while (begin != end)
{
if (begin->unique())
{
m_conversions.erase(begin->get());
}
++begin;
}
}
void add_conversion(const boost::shared_ptr<Dynamic_Conversion> &conversion)
{
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
m_conversions.insert(conversion.get());
}
bool has_conversion(const Type_Info &base, const Type_Info &derived) const
{
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
return find(base, derived) != m_conversions.end();
}
Dynamic_Conversion *get_conversion(const Type_Info &base, const Type_Info &derived) const
{
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
std::set<Dynamic_Conversion *>::const_iterator itr =
find(base, derived);
if (itr != m_conversions.end())
{
return *itr;
} else {
throw std::out_of_range("No such conversion exists from " + derived.bare_name() + " to " + base.bare_name());
}
}
private:
Dynamic_Conversions() {}
std::set<Dynamic_Conversion *>::const_iterator find(
const Type_Info &base, const Type_Info &derived) const
{
for (std::set<Dynamic_Conversion *>::const_iterator itr = m_conversions.begin();
itr != m_conversions.end();
++itr)
{
if ((*itr)->base().bare_equal(base) && (*itr)->derived().bare_equal(derived))
{
return itr;
}
}
return m_conversions.end();
}
mutable chaiscript::detail::threading::shared_mutex m_mutex;
std::set<Dynamic_Conversion *> m_conversions;
};
}
typedef boost::shared_ptr<chaiscript::detail::Dynamic_Conversion> Dynamic_Cast_Conversion;
/// \brief Used to register a base / parent class relationship with ChaiScript. Necessary if you
/// want automatic conversions up your inheritance hierarchy.
///
/// Create a new base class registration for applying to a module or to the chaiscript engine
/// Currently, due to limitations in module loading on Windows, and for the sake of portability,
/// if you have a type that is introduced in a loadable module and is used by multiple modules
/// (through a tertiary dll that is shared between the modules, static linking the new type
/// into both loadable modules would not be portable), you need to register the base type
/// relationship in all modules that use the newly added type in a polymorphic way.
///
/// Example:
/// \code
/// class Base
/// {};
/// class Derived : public Base
/// {};
///
/// chaiscript::ChaiScript chai;
/// chai.add(chaiscript::base_class<Base, Derived>());
/// \endcode
///
/// \todo Move share static type registration code into a mechanism that allows it to be properly
/// shared by all modules
template<typename Base, typename Derived>
Dynamic_Cast_Conversion base_class()
{
//Can only be used with related polymorphic types
//may be expanded some day to support conversions other than child -> parent
BOOST_STATIC_ASSERT((boost::is_base_of<Base,Derived>::value));
BOOST_STATIC_ASSERT(boost::is_polymorphic<Base>::value);
BOOST_STATIC_ASSERT(boost::is_polymorphic<Derived>::value);
return detail::Dynamic_Conversions::create<Base, Derived>();
}
namespace detail
{
template<typename Base, typename Derived>
bool dynamic_cast_converts()
{
return dynamic_cast_converts(user_type<Base>(), user_type<Derived>());
}
static bool dynamic_cast_converts(const Type_Info &base, const Type_Info &derived)
{
return detail::Dynamic_Conversions::get().has_conversion(base, derived);
}
template<typename Base>
Boxed_Value boxed_dynamic_cast(const Boxed_Value &derived)
{
try {
return detail::Dynamic_Conversions::get().get_conversion(user_type<Base>(), derived.get_type_info())->convert(derived);
} catch (const std::out_of_range &) {
throw exception::bad_boxed_dynamic_cast(derived.get_type_info(), typeid(Base), "No known conversion");
} catch (const std::bad_cast &) {
throw exception::bad_boxed_dynamic_cast(derived.get_type_info(), typeid(Base), "Unable to perform dynamic_cast operation");
}
}
}
}
#endif

View File

@@ -1,226 +1,284 @@
#ifndef __DYNAMIC_OBJECT_HPP__
#define __DYNAMIC_OBJECT_HPP__
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_DYNAMIC_OBJECT_HPP_
#define CHAISCRIPT_DYNAMIC_OBJECT_HPP_
#include <boost/optional.hpp>
namespace chaiscript
{
class Dynamic_Object
namespace dispatch
{
public:
Dynamic_Object(const std::string &t_type_name)
: m_type_name(t_type_name)
{
}
std::string get_type_name() const
{
return m_type_name;
}
Boxed_Value get_attr(const std::string &t_attr_name)
{
return m_attrs[t_attr_name];
}
std::map<std::string, Boxed_Value> get_attrs()
{
return m_attrs;
}
private:
std::string m_type_name;
std::map<std::string, Boxed_Value> m_attrs;
};
struct Dynamic_Object_Attribute
{
static Boxed_Value func(const std::string &t_type_name, const std::string &t_attr_name,
Dynamic_Object &t_do)
class Dynamic_Object
{
if (t_do.get_type_name() != t_type_name)
{
throw bad_boxed_cast("Dynamic object type mismatch");
}
return t_do.get_attr(t_attr_name);
}
};
/**
* A Proxy_Function implementation designed for calling a function
* that is automatically guarded based on the first param based on the
* param's type name
*/
class Dynamic_Object_Function : public Proxy_Function_Base
{
public:
Dynamic_Object_Function(
const std::string &t_type_name,
const Proxy_Function &t_func,
const boost::optional<Type_Info> &t_ti = boost::optional<Type_Info>())
: Proxy_Function_Base(t_func->get_param_types()),
m_type_name(t_type_name), m_func(t_func), m_ti(t_ti)
{
assert( (t_func->get_arity() > 0 || t_func->get_arity() < 0)
&& "Programming error, Dynamic_Object_Function must have at least one parameter (this)");
}
virtual ~Dynamic_Object_Function() {}
virtual bool operator==(const Proxy_Function_Base &f) const
{
try
public:
Dynamic_Object(const std::string &t_type_name)
: m_type_name(t_type_name)
{
const Dynamic_Object_Function &df = dynamic_cast<const Dynamic_Object_Function &>(f);
return df.m_type_name == m_type_name && (*df.m_func) == (*m_func);
} catch (const std::bad_cast &) {
return false;
}
}
virtual bool call_match(const std::vector<Boxed_Value> &vals) const
{
if (dynamic_object_typename_match(vals, m_type_name, m_ti))
std::string get_type_name() const
{
return m_func->call_match(vals);
} else {
return false;
return m_type_name;
}
}
virtual Boxed_Value operator()(const std::vector<Boxed_Value> &params) const
{
if (dynamic_object_typename_match(params, m_type_name, m_ti))
Boxed_Value get_attr(const std::string &t_attr_name)
{
return (*m_func)(params);
} else {
throw guard_error();
}
}
return m_attrs[t_attr_name];
}
virtual int get_arity() const
{
return m_func->get_arity();
}
virtual std::string annotation() const
{
return m_func->annotation();
}
private:
static bool dynamic_object_typename_match(const std::vector<Boxed_Value> &bvs, const std::string &name,
const boost::optional<Type_Info> &ti)
{
if (bvs.size() > 0)
std::map<std::string, Boxed_Value> get_attrs()
{
try {
const Dynamic_Object &d = boxed_cast<const Dynamic_Object &>(bvs[0]);
return name == "Dynamic_Object" || d.get_type_name() == name;
} catch (const std::bad_cast &) {
if (ti)
return m_attrs;
}
private:
std::string m_type_name;
std::map<std::string, Boxed_Value> m_attrs;
};
namespace detail
{
struct Dynamic_Object_Attribute
{
static Boxed_Value func(const std::string &t_type_name, const std::string &t_attr_name,
Dynamic_Object &t_do)
{
if (t_do.get_type_name() != t_type_name)
{
throw exception::bad_boxed_cast("Dynamic object type mismatch");
}
return t_do.get_attr(t_attr_name);
}
};
/**
* A Proxy_Function implementation designed for calling a function
* that is automatically guarded based on the first param based on the
* param's type name
*/
class Dynamic_Object_Function : public Proxy_Function_Base
{
public:
Dynamic_Object_Function(
const std::string &t_type_name,
const Proxy_Function &t_func,
const boost::optional<Type_Info> &t_ti = boost::optional<Type_Info>())
: Proxy_Function_Base(build_param_types(t_func->get_param_types(), t_ti)),
m_type_name(t_type_name), m_func(t_func), m_ti(t_ti)
{
assert( (t_func->get_arity() > 0 || t_func->get_arity() < 0)
&& "Programming error, Dynamic_Object_Function must have at least one parameter (this)");
}
virtual ~Dynamic_Object_Function() {}
virtual bool operator==(const Proxy_Function_Base &f) const
{
const Dynamic_Object_Function *df = dynamic_cast<const Dynamic_Object_Function *>(&f);
if (df)
{
return bvs[0].get_type_info().bare_equal(*ti);
return df->m_type_name == m_type_name && (*df->m_func) == (*m_func);
} else {
return false;
}
}
} else {
return false;
}
}
std::string m_type_name;
Proxy_Function m_func;
boost::optional<Type_Info> m_ti;
virtual bool call_match(const std::vector<Boxed_Value> &vals) const
{
if (dynamic_object_typename_match(vals, m_type_name, m_ti))
{
return m_func->call_match(vals);
} else {
return false;
}
}
};
virtual std::vector<Const_Proxy_Function> get_contained_functions() const
{
std::vector<Const_Proxy_Function> fs;
fs.push_back(m_func);
return fs;
}
/**
* A Proxy_Function implementation designed for creating a new
* Dynamic_Object
* that is automatically guarded based on the first param based on the
* param's type name
*/
class Dynamic_Object_Constructor : public Proxy_Function_Base
{
public:
Dynamic_Object_Constructor(
const std::string &t_type_name,
const Proxy_Function &t_func)
: Proxy_Function_Base(build_type_list(t_func->get_param_types())),
m_type_name(t_type_name), m_func(t_func)
virtual int get_arity() const
{
return m_func->get_arity();
}
virtual std::string annotation() const
{
return m_func->annotation();
}
protected:
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params) const
{
if (dynamic_object_typename_match(params, m_type_name, m_ti))
{
return (*m_func)(params);
} else {
throw exception::guard_error();
}
}
virtual bool compare_first_type(const Boxed_Value &bv) const
{
return dynamic_object_typename_match(bv, m_type_name, m_ti);
}
private:
static std::vector<Type_Info> build_param_types(
const std::vector<Type_Info> &t_inner_types, boost::optional<Type_Info> t_objectti)
{
if (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;
} else {
return t_inner_types;
}
}
static bool dynamic_object_typename_match(const Boxed_Value &bv, const std::string &name,
const boost::optional<Type_Info> &ti)
{
static Type_Info doti = user_type<Dynamic_Object>();
if (bv.get_type_info().bare_equal(doti))
{
try {
const Dynamic_Object &d = boxed_cast<const Dynamic_Object &>(bv);
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;
}
}
}
static bool dynamic_object_typename_match(const std::vector<Boxed_Value> &bvs, const std::string &name,
const boost::optional<Type_Info> &ti)
{
if (bvs.size() > 0)
{
return dynamic_object_typename_match(bvs[0], name, ti);
} else {
return false;
}
}
std::string m_type_name;
Proxy_Function m_func;
boost::optional<Type_Info> m_ti;
};
/**
* A Proxy_Function implementation designed for creating a new
* Dynamic_Object
* that is automatically guarded based on the first param based on the
* param's type name
*/
class Dynamic_Object_Constructor : public Proxy_Function_Base
{
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)
{
std::vector<Type_Info>::const_iterator begin = tl.begin();
std::vector<Type_Info>::const_iterator end = tl.end();
if (begin != end)
public:
Dynamic_Object_Constructor(
const std::string &t_type_name,
const Proxy_Function &t_func)
: Proxy_Function_Base(build_type_list(t_func->get_param_types())),
m_type_name(t_type_name), m_func(t_func)
{
++begin;
assert( (t_func->get_arity() > 0 || t_func->get_arity() < 0)
&& "Programming error, Dynamic_Object_Function must have at least one parameter (this)");
}
return std::vector<Type_Info>(begin, end);
}
static std::vector<Type_Info> build_type_list(const std::vector<Type_Info> &tl)
{
std::vector<Type_Info>::const_iterator begin = tl.begin();
std::vector<Type_Info>::const_iterator end = tl.end();
virtual ~Dynamic_Object_Constructor() {}
if (begin != end)
{
++begin;
}
virtual bool operator==(const Proxy_Function_Base &f) const
{
try
{
const Dynamic_Object_Constructor &dc = dynamic_cast<const Dynamic_Object_Constructor&>(f);
return dc.m_type_name == m_type_name && (*dc.m_func) == (*m_func);
} catch (const std::bad_cast &) {
return false;
}
}
return std::vector<Type_Info>(begin, end);
}
virtual bool call_match(const std::vector<Boxed_Value> &vals) const
{
std::vector<Boxed_Value> new_vals;
new_vals.push_back(Boxed_Value(Dynamic_Object(m_type_name)));
new_vals.insert(new_vals.end(), vals.begin(), vals.end());
virtual ~Dynamic_Object_Constructor() {}
return m_func->call_match(new_vals);
}
virtual bool operator==(const Proxy_Function_Base &f) const
{
const Dynamic_Object_Constructor *dc = dynamic_cast<const Dynamic_Object_Constructor*>(&f);
if (dc)
{
return dc->m_type_name == m_type_name && (*dc->m_func) == (*m_func);
} else {
return false;
}
}
virtual Boxed_Value operator()(const std::vector<Boxed_Value> &params) const
{
std::vector<Boxed_Value> new_params;
chaiscript::Boxed_Value bv = var(Dynamic_Object(m_type_name));
new_params.push_back(bv);
new_params.insert(new_params.end(), params.begin(), params.end());
virtual bool call_match(const std::vector<Boxed_Value> &vals) const
{
std::vector<Boxed_Value> new_vals;
new_vals.push_back(Boxed_Value(Dynamic_Object(m_type_name)));
new_vals.insert(new_vals.end(), vals.begin(), vals.end());
(*m_func)(new_params);
return m_func->call_match(new_vals);
}
return bv;
}
virtual int get_arity() const
{
// "this" is not considered part of the arity
return m_func->get_arity() - 1;
}
virtual int get_arity() const
{
// "this" is not considered part of the arity
return m_func->get_arity() - 1;
}
virtual std::string annotation() const
{
return m_func->annotation();
}
virtual std::string annotation() const
{
return m_func->annotation();
}
private:
std::string m_type_name;
Proxy_Function m_func;
protected:
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params) const
{
std::vector<Boxed_Value> new_params;
chaiscript::Boxed_Value bv = var(Dynamic_Object(m_type_name));
new_params.push_back(bv);
new_params.insert(new_params.end(), params.begin(), params.end());
};
(*m_func)(new_params);
return bv;
}
private:
std::string m_type_name;
Proxy_Function m_func;
};
}
}
}
#endif

View File

@@ -0,0 +1,176 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_EXCEPTION_SPECIFICATION_HPP_
#define CHAISCRIPT_EXCEPTION_SPECIFICATION_HPP_
#include "boxed_cast.hpp"
namespace chaiscript
{
namespace detail
{
struct Exception_Handler_Base
{
virtual void handle(const Boxed_Value &bv) = 0;
protected:
template<typename T>
void throw_type(const Boxed_Value &bv)
{
try { T t = boxed_cast<T>(bv); throw t; } catch (const exception::bad_boxed_cast &) {}
}
};
template<typename T1>
struct Exception_Handler_Impl1 : Exception_Handler_Base
{
virtual void handle(const Boxed_Value &bv)
{
throw_type<T1>(bv);
}
};
template<typename T1, typename T2>
struct Exception_Handler_Impl2 : Exception_Handler_Base
{
virtual void handle(const Boxed_Value &bv)
{
throw_type<T1>(bv);
throw_type<T2>(bv);
}
};
template<typename T1, typename T2, typename T3>
struct Exception_Handler_Impl3 : Exception_Handler_Base
{
virtual void handle(const Boxed_Value &bv)
{
throw_type<T1>(bv);
throw_type<T2>(bv);
throw_type<T3>(bv);
}
};
template<typename T1, typename T2, typename T3, typename T4>
struct Exception_Handler_Impl4 : Exception_Handler_Base
{
virtual void handle(const Boxed_Value &bv)
{
throw_type<T1>(bv);
throw_type<T2>(bv);
throw_type<T3>(bv);
throw_type<T4>(bv);
}
};
template<typename T1, typename T2, typename T3, typename T4, typename T5>
struct Exception_Handler_Impl5 : Exception_Handler_Base
{
virtual void handle(const Boxed_Value &bv)
{
throw_type<T1>(bv);
throw_type<T2>(bv);
throw_type<T3>(bv);
throw_type<T4>(bv);
throw_type<T5>(bv);
}
};
}
/// \brief Used in the automatic unboxing of exceptions thrown during script evaluation
///
/// Exception specifications allow the user to tell ChaiScript what possible exceptions are expected from the script
/// being executed. Exception_Handler objects are created with the chaiscript::exception_specification() function.
///
/// Example:
/// \code
/// chaiscript::ChaiScript chai;
///
/// try {
/// chai.eval("throw(runtime_error(\"error\"))", chaiscript::exception_specification<int, double, float, const std::string &, const std::exception &>());
/// } catch (const double e) {
/// } catch (int) {
/// } catch (float) {
/// } catch (const std::string &) {
/// } catch (const std::exception &e) {
/// // This is the one what will be called in the specific throw() above
/// }
/// \endcode
///
/// It is recommended that if catching the generic \c std::exception& type that you specifically catch
/// the chaiscript::exception::eval_error type, so that there is no confusion.
///
/// \code
/// try {
/// chai.eval("throw(runtime_error(\"error\"))", chaiscript::exception_specification<const std::exception &>());
/// } catch (const chaiscript::exception::eval_error &) {
/// // Error in script parsing / execution
/// } catch (const std::exception &e) {
/// // Error explicitly thrown from script
/// }
/// \endcode
///
/// 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.
///
/// \code
/// try {
/// chai.eval<int>("1.0", chaiscript::exception_specification<const std::exception &>());
/// } catch (const chaiscript::exception::eval_error &) {
/// // Error in script parsing / execution
/// } catch (const chaiscript::exception::bad_boxed_cast &) {
/// // Error unboxing return value
/// } catch (const std::exception &e) {
/// // Error explicitly thrown from script
/// }
/// \endcode
///
/// \sa chaiscript::exception_specification for creation of chaiscript::Exception_Handler objects
/// \sa \ref exceptions
typedef boost::shared_ptr<detail::Exception_Handler_Base> Exception_Handler;
/// \brief creates a chaiscript::Exception_Handler which handles one type of exception unboxing
/// \sa \ref exceptions
template<typename T1>
Exception_Handler exception_specification()
{
return Exception_Handler(new detail::Exception_Handler_Impl1<T1>());
}
/// \brief creates a chaiscript::Exception_Handler which handles two types of exception unboxing
/// \sa \ref exceptions
template<typename T1, typename T2>
Exception_Handler exception_specification()
{
return Exception_Handler(new detail::Exception_Handler_Impl2<T1, T2>());
}
/// \brief creates a chaiscript::Exception_Handler which handles three types of exception unboxing
/// \sa \ref exceptions
template<typename T1, typename T2, typename T3>
Exception_Handler exception_specification()
{
return Exception_Handler(new detail::Exception_Handler_Impl3<T1, T2, T3>());
}
/// \brief creates a chaiscript::Exception_Handler which handles four types of exception unboxing
/// \sa \ref exceptions
template<typename T1, typename T2, typename T3, typename T4>
Exception_Handler exception_specification()
{
return Exception_Handler(new detail::Exception_Handler_Impl4<T1, T2, T3, T4>());
}
/// \brief creates a chaiscript::Exception_Handler which handles five types of exception unboxing
/// \sa \ref exceptions
template<typename T1, typename T2, typename T3, typename T4, typename T5>
Exception_Handler exception_specification()
{
return Exception_Handler(new detail::Exception_Handler_Impl5<T1, T2, T3, T4, T5>());
}
}
#endif

View File

@@ -1,11 +1,11 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009, Jonathan Turner (jturner@minnow-lang.org)
// and Jason Turner (lefticus@gmail.com)
// Copyright 2009-2010, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef __function_call_hpp__
#define __function_call_hpp__
#ifndef CHAISCRIPT_FUNCTION_CALL_HPP_
#define CHAISCRIPT_FUNCTION_CALL_HPP_
#include <boost/shared_ptr.hpp>
#include <boost/bind.hpp>
@@ -15,57 +15,121 @@
#include "proxy_functions.hpp"
#include "function_call_detail.hpp"
#include <iostream>
namespace chaiscript
{
/**
* Build a function caller that knows how to dispatch on a set of functions
* example:
* boost::function<void (int)> f =
* build_function_caller(dispatchkit.get_function("print"));
* \returns A boost::function object for dispatching
* \param[in] funcs the set of functions to dispatch on.
*/
template<typename FunctionType>
boost::function<FunctionType>
functor(const std::vector<std::pair<std::string, Proxy_Function > > &funcs)
namespace dispatch
{
/**
* Build a function caller that knows how to dispatch on a set of functions
* example:
* boost::function<void (int)> f =
* build_function_caller(dispatchkit.get_function("print"));
* \returns A boost::function object for dispatching
* \param[in] funcs the set of functions to dispatch on.
*/
template<typename FunctionType>
boost::function<FunctionType>
functor(const std::vector<Const_Proxy_Function> &funcs)
{
FunctionType *p=0;
return detail::build_function_caller_helper(p, funcs);
}
/**
* Build a function caller for a particular Proxy_Function object
* useful in the case that a function is being pass out from scripting back
* into code
* example:
* void my_function(Proxy_Function f)
* {
* boost::function<void (int)> local_f =
* build_function_caller(f);
* }
* \returns A boost::function object for dispatching
* \param[in] func A function to execute.
*/
template<typename FunctionType>
boost::function<FunctionType>
functor(Proxy_Function func)
/**
* Build a function caller for a particular Proxy_Function object
* useful in the case that a function is being pass out from scripting back
* into code
* example:
* void my_function(Proxy_Function f)
* {
* boost::function<void (int)> local_f =
* build_function_caller(f);
* }
* \returns A boost::function object for dispatching
* \param[in] func A function to execute.
*/
template<typename FunctionType>
boost::function<FunctionType>
functor(Const_Proxy_Function func)
{
std::vector<std::pair<std::string, Proxy_Function > > funcs;
funcs.push_back(std::make_pair(std::string(), func));
std::vector<Const_Proxy_Function> funcs;
funcs.push_back(func);
return functor<FunctionType>(funcs);
}
/**
* Helper for automatically unboxing a Boxed_Value that contains a function object
* and creating a typesafe C++ function caller from it.
*/
template<typename FunctionType>
boost::function<FunctionType>
/**
* Helper for automatically unboxing a Boxed_Value that contains a function object
* and creating a typesafe C++ function caller from it.
*/
template<typename FunctionType>
boost::function<FunctionType>
functor(const Boxed_Value &bv)
{
return functor<FunctionType>(boxed_cast<Proxy_Function >(bv));
return functor<FunctionType>(boxed_cast<Const_Proxy_Function >(bv));
}
}
namespace detail{
/**
* Cast helper to handle automatic casting to const boost::function &
*/
template<typename Signature>
struct Cast_Helper<const boost::function<Signature> &>
{
typedef boost::function<Signature> Result_Type;
static Result_Type cast(const Boxed_Value &ob)
{
if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>()))
{
return dispatch::functor<Signature>(ob);
} else {
return Cast_Helper_Inner<const boost::function<Signature> &>::cast(ob);
}
}
};
/**
* Cast helper to handle automatic casting to boost::function
*/
template<typename Signature>
struct Cast_Helper<boost::function<Signature> >
{
typedef boost::function<Signature> Result_Type;
static Result_Type cast(const Boxed_Value &ob)
{
if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>()))
{
return dispatch::functor<Signature>(ob);
} else {
return Cast_Helper_Inner<boost::function<Signature> >::cast(ob);
}
}
};
/**
* Cast helper to handle automatic casting to const boost::function
*/
template<typename Signature>
struct Cast_Helper<const boost::function<Signature> >
{
typedef boost::function<Signature> Result_Type;
static Result_Type cast(const Boxed_Value &ob)
{
if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>()))
{
return dispatch::functor<Signature>(ob);
} else {
return Cast_Helper_Inner<const boost::function<Signature> >::cast(ob);
}
}
};
}
}
#endif

View File

@@ -1,18 +1,18 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009, Jonathan Turner (jturner@minnow-lang.org)
// and Jason Turner (lefticus@gmail.com)
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#include <boost/preprocessor.hpp>
#define addparam(z,n,text) params.push_back(boost::is_reference<Param ## n>::value?Boxed_Value(boost::ref(BOOST_PP_CAT(p, n))):Boxed_Value(BOOST_PP_CAT(p, n) ));
#define addparam(z,n,text) params.push_back((boost::is_reference<Param ## n>::value&&!(boost::is_same<chaiscript::Boxed_Value, typename boost::remove_const<typename boost::remove_reference<Param ## n>::type>::type>::value))?Boxed_Value(boost::ref(BOOST_PP_CAT(p, n))):Boxed_Value(BOOST_PP_CAT(p, n) ));
#define curry(z,n,text) BOOST_PP_CAT(_, BOOST_PP_INC(n))
#ifndef BOOST_PP_IS_ITERATING
#ifndef __function_call_detail_hpp__
#define __function_call_detail_hpp__
#ifndef CHAISCRIPT_FUNCTION_CALL_DETAIL_HPP_
#define CHAISCRIPT_FUNCTION_CALL_DETAIL_HPP_
#include <boost/shared_ptr.hpp>
#include <boost/bind.hpp>
@@ -23,34 +23,38 @@
namespace chaiscript
{
namespace detail
namespace dispatch
{
/**
* Internal helper class for handling the return
* value of a build_function_caller
*/
template<typename Ret>
struct Function_Caller_Ret
{
static Ret call(const std::vector<std::pair<std::string, Proxy_Function > > &t_funcs,
const std::vector<Boxed_Value> &params)
{
return boxed_cast<Ret>(dispatch(t_funcs, params));
}
};
namespace detail
{
/**
* Specialization for void return types
*/
template<>
struct Function_Caller_Ret<void>
{
static void call(const std::vector<std::pair<std::string, Proxy_Function > > &t_funcs,
const std::vector<Boxed_Value> &params)
/**
* Internal helper class for handling the return
* value of a build_function_caller
*/
template<typename Ret>
struct Function_Caller_Ret
{
dispatch(t_funcs, params);
}
};
static Ret call(const std::vector<Const_Proxy_Function> &t_funcs,
const std::vector<Boxed_Value> &params)
{
return boxed_cast<Ret>(dispatch::dispatch(t_funcs, params));
}
};
/**
* Specialization for void return types
*/
template<>
struct Function_Caller_Ret<void>
{
static void call(const std::vector<Const_Proxy_Function> &t_funcs,
const std::vector<Boxed_Value> &params)
{
dispatch::dispatch(t_funcs, params);
}
};
}
}
}
@@ -64,35 +68,52 @@ namespace chaiscript
namespace chaiscript
{
namespace detail
namespace dispatch
{
/**
* used internally for unwrapping a function call's types
*/
template<typename Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param) >
Ret function_caller(const std::vector<std::pair<std::string, Proxy_Function > > &funcs
BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_BINARY_PARAMS(n, Param, p) )
{
std::vector<Boxed_Value> params;
namespace detail
{
/**
* used internally for unwrapping a function call's types
*/
template<typename Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param) >
Ret function_caller(const std::vector<Const_Proxy_Function> &funcs
BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_BINARY_PARAMS(n, Param, p) )
{
std::vector<Boxed_Value> params;
BOOST_PP_REPEAT(n, addparam, ~)
BOOST_PP_REPEAT(n, addparam, ~)
return Function_Caller_Ret<Ret>::call(funcs, params);
}
return Function_Caller_Ret<Ret>::call(funcs, params);
}
/**
* used internally for unwrapping a function call's types
*/
template<typename Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param) >
boost::function<Ret (BOOST_PP_ENUM_PARAMS(n, Param)) >
build_function_caller_helper(Ret (BOOST_PP_ENUM_PARAMS(n, Param)), const std::vector<std::pair<std::string, Proxy_Function> > &funcs)
{
return boost::bind(&function_caller<Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, Param)>, funcs
BOOST_PP_ENUM_TRAILING(n, curry, ~));
}
/**
* used internally for unwrapping a function call's types
*/
template<typename Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param) >
boost::function<Ret (BOOST_PP_ENUM_PARAMS(n, Param)) >
build_function_caller_helper(Ret (BOOST_PP_ENUM_PARAMS(n, Param)), const std::vector<Const_Proxy_Function> &funcs)
{
if (funcs.size() == 1)
{
boost::shared_ptr<const Proxy_Function_Impl<Ret (BOOST_PP_ENUM_PARAMS(n, Param))> > pfi =
boost::dynamic_pointer_cast<const Proxy_Function_Impl<Ret (BOOST_PP_ENUM_PARAMS(n, Param))> >
(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 boost::bind(&function_caller<Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, Param)>, funcs
BOOST_PP_ENUM_TRAILING(n, curry, ~));
}
}
}
}
#undef n
#endif

View File

@@ -1,13 +1,14 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009, Jonathan Turner (jturner@minnow-lang.org)
// and Jason Turner (lefticus@gmail.com)
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef __handle_return_hpp__
#define __handle_return_hpp__
#ifndef CHAISCRIPT_HANDLE_RETURN_HPP_
#define CHAISCRIPT_HANDLE_RETURN_HPP_
#include "boxed_value.hpp"
#include "boxed_number.hpp"
#include "type_info.hpp"
#include <string>
#include <boost/function.hpp>
@@ -17,96 +18,162 @@
namespace chaiscript
{
/**
* Used internally for handling a return value from a Proxy_Function call
*/
template<typename Ret>
struct Handle_Return
namespace dispatch
{
namespace detail
{
static Boxed_Value handle(const Ret &r)
{
return Boxed_Value(r);
}
};
/**
* Used internally for handling a return value from a Proxy_Function call
*/
template<typename Ret>
struct Handle_Return
{
static Boxed_Value handle(const Ret &r)
{
return const_var(r);
}
};
template<typename Ret>
struct Handle_Return<boost::shared_ptr<Ret> &>
{
static Boxed_Value handle(const boost::shared_ptr<Ret> &r)
{
return Boxed_Value(r);
}
};
template<typename Ret>
struct Handle_Return<boost::shared_ptr<Ret> &>
{
static Boxed_Value handle(const boost::shared_ptr<Ret> &r)
{
return Boxed_Value(r);
}
};
template<typename Ret>
struct Handle_Return<const boost::shared_ptr<Ret> &>
{
static Boxed_Value handle(const boost::shared_ptr<Ret> &r)
{
return Boxed_Value(r);
}
};
template<typename Ret>
struct Handle_Return<boost::shared_ptr<Ret> >
{
static Boxed_Value handle(const boost::shared_ptr<Ret> &r)
{
return Boxed_Value(r);
}
};
/**
* Used internally for handling a return value from a Proxy_Function call
*/
template<typename Ret>
struct Handle_Return<Ret &>
{
static Boxed_Value handle(Ret &r)
{
return Boxed_Value(boost::ref(r));
}
};
template<typename Ret>
struct Handle_Return<const boost::shared_ptr<Ret> &>
{
static Boxed_Value handle(const boost::shared_ptr<Ret> &r)
{
return Boxed_Value(r);
}
};
/**
* Used internally for handling a return value from a Proxy_Function call
*/
template<>
struct Handle_Return<Boxed_Value>
{
static Boxed_Value handle(const Boxed_Value &r)
{
return r;
}
};
/**
* Used internally for handling a return value from a Proxy_Function call
*/
template<>
struct Handle_Return<Boxed_Value &>
{
static Boxed_Value handle(const Boxed_Value &r)
{
return r;
}
};
/**
* Used internally for handling a return value from a Proxy_Function call
*/
template<>
struct Handle_Return<const Boxed_Value &>
{
static Boxed_Value handle(const Boxed_Value &r)
{
return r;
}
};
template<typename Ret>
struct Handle_Return<const Ret &>
{
static Boxed_Value handle(const Ret &r)
{
return Boxed_Value(boost::cref(r));
}
};
/**
* Used internally for handling a return value from a Proxy_Function call
*/
template<>
struct Handle_Return<void>
{
static Boxed_Value handle()
{
return Boxed_Value(Boxed_Value::Void_Type());
}
};
/**
* Used internally for handling a return value from a Proxy_Function call
*/
template<typename Ret>
struct Handle_Return<Ret &>
{
static Boxed_Value handle(Ret &r)
{
return Boxed_Value(boost::ref(r));
}
static Boxed_Value handle(const Ret &r)
{
return Boxed_Value(boost::cref(r));
}
};
/**
* Used internally for handling a return value from a Proxy_Function call
*/
template<>
struct Handle_Return<Boxed_Value>
{
static Boxed_Value handle(const Boxed_Value &r)
{
return r;
}
};
/**
* Used internally for handling a return value from a Proxy_Function call
*/
template<>
struct Handle_Return<const Boxed_Value>
{
static Boxed_Value handle(const Boxed_Value &r)
{
return r;
}
};
/**
* Used internally for handling a return value from a Proxy_Function call
*/
template<>
struct Handle_Return<Boxed_Value &>
{
static Boxed_Value handle(const Boxed_Value &r)
{
return r;
}
};
/**
* Used internally for handling a return value from a Proxy_Function call
*/
template<>
struct Handle_Return<const Boxed_Value &>
{
static Boxed_Value handle(const Boxed_Value &r)
{
return r;
}
};
/**
* Used internally for handling a return value from a Proxy_Function call
*/
template<>
struct Handle_Return<Boxed_Number>
{
static Boxed_Value handle(const Boxed_Number &r)
{
return r.bv;
}
};
/**
* Used internally for handling a return value from a Proxy_Function call
*/
template<>
struct Handle_Return<const Boxed_Number>
{
static Boxed_Value handle(const Boxed_Number &r)
{
return r.bv;
}
};
/**
* Used internally for handling a return value from a Proxy_Function call
*/
template<>
struct Handle_Return<void>
{
static Boxed_Value handle()
{
return Boxed_Value(Boxed_Value::Void_Type());
}
};
}
}
}
#endif

View File

@@ -1,441 +1,457 @@
#ifndef __CHAISCRIPT_OPERATORS_HPP__
#define __CHAISCRIPT_OPERATORS_HPP__
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_OPERATORS_HPP_
#define CHAISCRIPT_OPERATORS_HPP_
namespace chaiscript
{
namespace operators
namespace bootstrap
{
template<typename Ret, typename L, typename R>
Ret assign(L l, R r)
{
return (l = r);
}
template<typename Ret, typename L, typename R>
Ret assign_bitwise_and(L l, R r)
{
return (l &= r);
}
template<typename Ret, typename L, typename R>
Ret assign_xor(L l, R r)
{
return (l ^= r);
}
template<typename Ret, typename L, typename R>
Ret assign_bitwise_or(L l, R r)
{
return (l |= r);
}
template<typename Ret, typename L, typename R>
Ret assign_difference(L l, R r)
{
return (l -= r);
}
template<typename Ret, typename L, typename R>
Ret assign_left_shift(L l, R r)
{
return (l <<= r);
}
template<typename Ret, typename L, typename R>
Ret assign_product(L l, R r)
{
return (l *= r);
}
template<typename Ret, typename L, typename R>
Ret assign_quotient(L l, R r)
{
return (l /= r);
}
template<typename Ret, typename L, typename R>
Ret assign_remainder(L l, R r)
{
return (l %= r);
}
template<typename Ret, typename L, typename R>
Ret assign_right_shift(L l, R r)
{
return (l >>= r);
}
template<typename Ret, typename L, typename R>
Ret assign_sum(L l, R r)
{
return (l += r);
}
template<typename Ret, typename L>
Ret prefix_decrement(L l)
{
return (--l);
}
template<typename Ret, typename L>
Ret prefix_increment(L l)
{
return (++l);
}
template<typename Ret, typename L, typename R>
Ret equal(L l, R r)
{
return (l == r);
}
template<typename Ret, typename L, typename R>
Ret greater_than(L l, R r)
{
return (l > r);
}
template<typename Ret, typename L, typename R>
Ret greater_than_equal(L l, R r)
{
return (l >= r);
}
template<typename Ret, typename L, typename R>
Ret less_than(L l, R r)
{
return (l < r);
}
template<typename Ret, typename L, typename R>
Ret less_than_equal(L l, R r)
{
return (l <= r);
}
template<typename Ret, typename L>
Ret logical_compliment(L l)
{
return (!l);
}
template<typename Ret, typename L, typename R>
Ret not_equal(L l, R r)
{
return (l != r);
}
template<typename Ret, typename L, typename R>
Ret addition(L l, R r)
{
return (l + r);
}
template<typename Ret, typename L>
Ret unary_plus(L l)
{
return (+l);
}
template<typename Ret, typename L, typename R>
Ret subtraction(L l, R r)
{
return (l - r);
}
template<typename Ret, typename L>
Ret unary_minus(L l)
{
return (-l);
}
template<typename Ret, typename L, typename R>
Ret bitwise_and(L l, R r)
{
return (l & r);
}
template<typename Ret, typename L>
Ret bitwise_compliment(L l)
{
return (~l);
}
template<typename Ret, typename L, typename R>
Ret bitwise_xor(L l, R r)
{
return (l ^ r);
}
template<typename Ret, typename L, typename R>
Ret bitwise_or(L l, R r)
{
return (l | r);
}
template<typename Ret, typename L, typename R>
Ret division(L l, R r)
{
return (l / r);
}
template<typename Ret, typename L, typename R>
Ret left_shift(L l, R r)
{
return l << r;
}
template<typename Ret, typename L, typename R>
Ret multiplication(L l, R r)
{
return l * r;
}
template<typename Ret, typename L, typename R>
Ret remainder(L l, R r)
{
return (l % r);
}
template<typename Ret, typename L, typename R>
Ret right_shift(L l, R r)
{
return (l >> r);
}
template<typename T>
ModulePtr assign(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&assign<T &, T &, const T&>), "=");
return m;
}
template<typename T>
ModulePtr assign_bitwise_and(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&assign_bitwise_and<T &, T &, const T&>), "&=");
return m;
}
template<typename T>
ModulePtr assign_xor(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&assign_xor<T &, T &, const T&>), "^=");
return m;
}
template<typename T>
ModulePtr assign_bitwise_or(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&assign_bitwise_or<T &, T &, const T&>), "|=");
return m;
}
template<typename T>
ModulePtr assign_difference(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&assign_difference<T &, T &, const T&>), "-=");
return m;
}
template<typename T>
ModulePtr assign_left_shift(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&assign_left_shift<T &, T &, const T&>), "<<=");
return m;
}
template<typename T>
ModulePtr assign_product(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&assign_product<T &, T &, const T&>), "*=");
return m;
}
template<typename T>
ModulePtr assign_quotient(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&assign_quotient<T &, T &, const T&>), "/=");
return m;
}
template<typename T>
ModulePtr assign_remainder(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&assign_remainder<T &, T &, const T&>), "%=");
return m;
}
template<typename T>
ModulePtr assign_right_shift(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&assign_right_shift<T &, T &, const T&>), ">>=");
return m;
}
template<typename T>
ModulePtr assign_sum(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&assign_sum<T &, T &, const T&>), "+=");
return m;
}
template<typename T>
ModulePtr prefix_decrement(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&prefix_decrement<T &, T &>), "--");
return m;
}
template<typename T>
ModulePtr prefix_increment(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&prefix_increment<T &, T &>), "++");
return m;
}
template<typename T>
ModulePtr equal(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&equal<bool, const T&, const T&>), "==");
return m;
}
template<typename T>
ModulePtr greater_than(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&greater_than<bool, const T&, const T&>), ">");
return m;
}
template<typename T>
ModulePtr greater_than_equal(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&greater_than_equal<bool, const T&, const T&>), ">=");
return m;
}
template<typename T>
ModulePtr less_than(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&less_than<bool, const T&, const T&>), "<");
return m;
}
template<typename T>
ModulePtr less_than_equal(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&less_than_equal<bool, const T&, const T&>), "<=");
return m;
}
template<typename T>
ModulePtr logical_compliment(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&logical_compliment<bool, const T &>), "!");
return m;
}
template<typename T>
ModulePtr not_equal(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&not_equal<bool, const T &, const T &>), "!=");
return m;
}
template<typename T>
ModulePtr addition(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&addition<T, const T &, const T &>), "+");
return m;
}
template<typename T>
ModulePtr unary_plus(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&unary_plus<T, const T &>), "+");
return m;
}
template<typename T>
ModulePtr subtraction(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&subtraction<T, const T &, const T &>), "-");
return m;
}
template<typename T>
ModulePtr unary_minus(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&unary_minus<T, const T &>), "-");
return m;
}
template<typename T>
ModulePtr bitwise_and(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&bitwise_and<T, const T &, const T &>), "&");
return m;
}
template<typename T>
ModulePtr bitwise_compliment(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&bitwise_compliment<T, const T &>), "~");
return m;
}
template<typename T>
ModulePtr bitwise_xor(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&bitwise_xor<T, const T &, const T &>), "^");
return m;
}
template<typename T>
ModulePtr bitwise_or(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&bitwise_or<T, const T &, const T &>), "|");
return m;
}
template<typename T>
ModulePtr division(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&division<T, const T &, const T &>), "/");
return m;
}
template<typename T>
ModulePtr left_shift(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&left_shift<T, const T &, const T &>), "<<");
return m;
}
template<typename T>
ModulePtr multiplication(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&multiplication<T, const T &, const T &>), "*");
return m;
}
template<typename T>
ModulePtr remainder(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&remainder<T, const T &, const T &>), "%");
return m;
}
template<typename T>
ModulePtr right_shift(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&right_shift<T, const T &, const T &>), ">>");
return m;
}
namespace operators
{
template<typename Ret, typename L, typename R>
Ret assign(L l, R r)
{
return (l = r);
}
template<typename Ret, typename L, typename R>
Ret assign_bitwise_and(L l, R r)
{
return (l &= r);
}
template<typename Ret, typename L, typename R>
Ret assign_xor(L l, R r)
{
return (l ^= r);
}
template<typename Ret, typename L, typename R>
Ret assign_bitwise_or(L l, R r)
{
return (l |= r);
}
template<typename Ret, typename L, typename R>
Ret assign_difference(L l, R r)
{
return (l -= r);
}
template<typename Ret, typename L, typename R>
Ret assign_left_shift(L l, R r)
{
return (l <<= r);
}
template<typename Ret, typename L, typename R>
Ret assign_product(L l, R r)
{
return (l *= r);
}
template<typename Ret, typename L, typename R>
Ret assign_quotient(L l, R r)
{
return (l /= r);
}
template<typename Ret, typename L, typename R>
Ret assign_remainder(L l, R r)
{
return (l %= r);
}
template<typename Ret, typename L, typename R>
Ret assign_right_shift(L l, R r)
{
return (l >>= r);
}
template<typename Ret, typename L, typename R>
Ret assign_sum(L l, R r)
{
return (l += r);
}
template<typename Ret, typename L>
Ret prefix_decrement(L l)
{
return (--l);
}
template<typename Ret, typename L>
Ret prefix_increment(L l)
{
return (++l);
}
template<typename Ret, typename L, typename R>
Ret equal(L l, R r)
{
return (l == r);
}
template<typename Ret, typename L, typename R>
Ret greater_than(L l, R r)
{
return (l > r);
}
template<typename Ret, typename L, typename R>
Ret greater_than_equal(L l, R r)
{
return (l >= r);
}
template<typename Ret, typename L, typename R>
Ret less_than(L l, R r)
{
return (l < r);
}
template<typename Ret, typename L, typename R>
Ret less_than_equal(L l, R r)
{
return (l <= r);
}
template<typename Ret, typename L>
Ret logical_compliment(L l)
{
return (!l);
}
template<typename Ret, typename L, typename R>
Ret not_equal(L l, R r)
{
return (l != r);
}
template<typename Ret, typename L, typename R>
Ret addition(L l, R r)
{
return (l + r);
}
template<typename Ret, typename L>
Ret unary_plus(L l)
{
return (+l);
}
template<typename Ret, typename L, typename R>
Ret subtraction(L l, R r)
{
return (l - r);
}
template<typename Ret, typename L>
Ret unary_minus(L l)
{
#ifdef BOOST_MSVC
#pragma warning(push)
#pragma warning(disable : 4146)
return (-l);
#pragma warning(pop)
#else
return (-l);
#endif
}
template<typename Ret, typename L, typename R>
Ret bitwise_and(L l, R r)
{
return (l & r);
}
template<typename Ret, typename L>
Ret bitwise_compliment(L l)
{
return (~l);
}
template<typename Ret, typename L, typename R>
Ret bitwise_xor(L l, R r)
{
return (l ^ r);
}
template<typename Ret, typename L, typename R>
Ret bitwise_or(L l, R r)
{
return (l | r);
}
template<typename Ret, typename L, typename R>
Ret division(L l, R r)
{
return (l / r);
}
template<typename Ret, typename L, typename R>
Ret left_shift(L l, R r)
{
return l << r;
}
template<typename Ret, typename L, typename R>
Ret multiplication(L l, R r)
{
return l * r;
}
template<typename Ret, typename L, typename R>
Ret remainder(L l, R r)
{
return (l % r);
}
template<typename Ret, typename L, typename R>
Ret right_shift(L l, R r)
{
return (l >> r);
}
template<typename T>
ModulePtr assign(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&assign<T &, T &, const T&>), "=");
return m;
}
template<typename T>
ModulePtr assign_bitwise_and(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&assign_bitwise_and<T &, T &, const T&>), "&=");
return m;
}
template<typename T>
ModulePtr assign_xor(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&assign_xor<T &, T &, const T&>), "^=");
return m;
}
template<typename T>
ModulePtr assign_bitwise_or(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&assign_bitwise_or<T &, T &, const T&>), "|=");
return m;
}
template<typename T>
ModulePtr assign_difference(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&assign_difference<T &, T &, const T&>), "-=");
return m;
}
template<typename T>
ModulePtr assign_left_shift(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&assign_left_shift<T &, T &, const T&>), "<<=");
return m;
}
template<typename T>
ModulePtr assign_product(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&assign_product<T &, T &, const T&>), "*=");
return m;
}
template<typename T>
ModulePtr assign_quotient(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&assign_quotient<T &, T &, const T&>), "/=");
return m;
}
template<typename T>
ModulePtr assign_remainder(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&assign_remainder<T &, T &, const T&>), "%=");
return m;
}
template<typename T>
ModulePtr assign_right_shift(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&assign_right_shift<T &, T &, const T&>), ">>=");
return m;
}
template<typename T>
ModulePtr assign_sum(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&assign_sum<T &, T &, const T&>), "+=");
return m;
}
template<typename T>
ModulePtr prefix_decrement(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&prefix_decrement<T &, T &>), "--");
return m;
}
template<typename T>
ModulePtr prefix_increment(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&prefix_increment<T &, T &>), "++");
return m;
}
template<typename T>
ModulePtr equal(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&equal<bool, const T&, const T&>), "==");
return m;
}
template<typename T>
ModulePtr greater_than(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&greater_than<bool, const T&, const T&>), ">");
return m;
}
template<typename T>
ModulePtr greater_than_equal(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&greater_than_equal<bool, const T&, const T&>), ">=");
return m;
}
template<typename T>
ModulePtr less_than(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&less_than<bool, const T&, const T&>), "<");
return m;
}
template<typename T>
ModulePtr less_than_equal(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&less_than_equal<bool, const T&, const T&>), "<=");
return m;
}
template<typename T>
ModulePtr logical_compliment(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&logical_compliment<bool, const T &>), "!");
return m;
}
template<typename T>
ModulePtr not_equal(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&not_equal<bool, const T &, const T &>), "!=");
return m;
}
template<typename T>
ModulePtr addition(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&addition<T, const T &, const T &>), "+");
return m;
}
template<typename T>
ModulePtr unary_plus(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&unary_plus<T, const T &>), "+");
return m;
}
template<typename T>
ModulePtr subtraction(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&subtraction<T, const T &, const T &>), "-");
return m;
}
template<typename T>
ModulePtr unary_minus(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&unary_minus<T, const T &>), "-");
return m;
}
template<typename T>
ModulePtr bitwise_and(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&bitwise_and<T, const T &, const T &>), "&");
return m;
}
template<typename T>
ModulePtr bitwise_compliment(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&bitwise_compliment<T, const T &>), "~");
return m;
}
template<typename T>
ModulePtr bitwise_xor(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&bitwise_xor<T, const T &, const T &>), "^");
return m;
}
template<typename T>
ModulePtr bitwise_or(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&bitwise_or<T, const T &, const T &>), "|");
return m;
}
template<typename T>
ModulePtr division(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&division<T, const T &, const T &>), "/");
return m;
}
template<typename T>
ModulePtr left_shift(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&left_shift<T, const T &, const T &>), "<<");
return m;
}
template<typename T>
ModulePtr multiplication(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&multiplication<T, const T &, const T &>), "*");
return m;
}
template<typename T>
ModulePtr remainder(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&remainder<T, const T &, const T &>), "%");
return m;
}
template<typename T>
ModulePtr right_shift(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&right_shift<T, const T &, const T &>), ">>");
return m;
}
}
}
}

View File

@@ -1,14 +1,14 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009, Jonathan Turner (jturner@minnow-lang.org)
// and Jason Turner (lefticus@gmail.com)
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#include <boost/preprocessor.hpp>
#ifndef BOOST_PP_IS_ITERATING
#ifndef __proxy_constructors_hpp__
#define __proxy_constructors_hpp__
#ifndef CHAISCRIPT_PROXY_CONSTRUCTORS_HPP_
#define CHAISCRIPT_PROXY_CONSTRUCTORS_HPP_
#include <boost/shared_ptr.hpp>
#include <boost/bind.hpp>
@@ -22,11 +22,22 @@
namespace chaiscript
{
/// \brief Generates a constructor function for use with ChaiScript
///
/// \tparam T The signature of the constructor to generate. In the form of: ClassType (ParamType1, ParamType2, ...)
///
/// Example:
/// \code
/// chaiscript::ChaiScript chai;
/// // Create a new function that creates a MyClass object using the (int, float) constructor
/// // and call that function "MyClass" so that it appears as a normal constructor to the user.
/// chai.add(constructor<MyClass (int, float)>(), "MyClass");
/// \endcode
template<typename T>
Proxy_Function constructor()
{
T *f = 0;
return (detail::build_constructor_(f));
return (dispatch::detail::build_constructor_(f));
}
}
@@ -35,32 +46,36 @@ namespace chaiscript
namespace chaiscript
{
namespace detail
namespace dispatch
{
/**
* A constructor function, used for creating a new object
* of a given type with a given set of params
*/
template<typename Class BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param) >
boost::shared_ptr<Class> constructor_( BOOST_PP_ENUM_BINARY_PARAMS(n, Param, p) )
{
return boost::shared_ptr<Class>(new Class( BOOST_PP_ENUM_PARAMS(n, p) ));
}
namespace detail
{
/**
* A constructor function, used for creating a new object
* of a given type with a given set of params
*/
template<typename Class BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param) >
boost::shared_ptr<Class> constructor_( BOOST_PP_ENUM_BINARY_PARAMS(n, Param, p) )
{
return boost::shared_ptr<Class>(new Class( BOOST_PP_ENUM_PARAMS(n, p) ));
}
/**
* Helper function for build a constructor function
* example:
* dispatchengine.register_function(build_constructor<MyClass, int, const std::string&>, "MyClass");
* \todo See if it is possible to make this not be a variadic function
*/
template<typename Class BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param) >
Proxy_Function build_constructor_(Class (*)(BOOST_PP_ENUM_PARAMS(n, Param)))
{
typedef boost::shared_ptr<Class> (sig)(BOOST_PP_ENUM_PARAMS(n, Param));
return Proxy_Function(new Proxy_Function_Impl<sig>(boost::function<sig>(&(constructor_<Class BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, Param)>))));
}
/**
* Helper function for build a constructor function
* example:
* dispatchengine.register_function(build_constructor<MyClass, int, const std::string&>, "MyClass");
* \todo See if it is possible to make this not be a variadic function
*/
template<typename Class BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param) >
Proxy_Function build_constructor_(Class (*)(BOOST_PP_ENUM_PARAMS(n, Param)))
{
typedef boost::shared_ptr<Class> (sig)(BOOST_PP_ENUM_PARAMS(n, Param));
return Proxy_Function(new Proxy_Function_Impl<sig>(boost::function<sig>(&(constructor_<Class BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, Param)>))));
}
}
}
}
#undef n
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,20 +1,21 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009, Jonathan Turner (jturner@minnow-lang.org)
// and Jason Turner (lefticus@gmail.com)
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#include <boost/preprocessor.hpp>
#define gettypeinfo(z,n,text) ti.push_back(detail::Get_Type_Info<Param ## n>::get());
#define gettypeinfo(z,n,text) ti.push_back(chaiscript::detail::Get_Type_Info<Param ## n>::get());
#define casthelper(z,n,text) BOOST_PP_COMMA_IF(n) chaiscript::boxed_cast< Param ## n >(params[n])
#define trycast(z,n,text) chaiscript::boxed_cast<Param ## n>(params[n]);
#ifndef BOOST_PP_IS_ITERATING
#ifndef __proxy_functions_detail_hpp__
#define __proxy_functions_detail_hpp__
#ifndef CHAISCRIPT_PROXY_FUNCTIONS_DETAIL_HPP_
#define CHAISCRIPT_PROXY_FUNCTIONS_DETAIL_HPP_
#include "boxed_value.hpp"
#include "boxed_cast.hpp"
#include "type_info.hpp"
#include "handle_return.hpp"
#include <string>
@@ -27,43 +28,27 @@
namespace chaiscript
{
/**
* Exception thrown when there is a mismatch in number of
* parameters during Proxy_Function execution
*/
struct arity_error : std::range_error
namespace exception
{
arity_error(int t_got, int t_expected)
: std::range_error("Function dispatch arity mismatch"),
got(t_got), expected(t_expected)
/**
* Exception thrown when there is a mismatch in number of
* parameters during Proxy_Function execution
*/
struct arity_error : std::range_error
{
}
virtual ~arity_error() throw() {}
int got;
int expected;
};
template<typename Ret>
struct Do_Call
{
template<typename Fun>
static Boxed_Value go(const boost::function<Fun> &fun, const std::vector<Boxed_Value> &params)
arity_error(int t_got, int t_expected)
: std::range_error("Function dispatch arity mismatch"),
got(t_got), expected(t_expected)
{
return Handle_Return<Ret>::handle(call_func(fun, params));
}
};
template<>
struct Do_Call<void>
{
template<typename Fun>
static Boxed_Value go(const boost::function<Fun> &fun, const std::vector<Boxed_Value> &params)
{
call_func(fun, params);
return Handle_Return<void>::handle();
};
virtual ~arity_error() throw() {}
int got;
int expected;
};
}
}
#define BOOST_PP_ITERATION_LIMITS ( 0, 10 )
@@ -77,57 +62,99 @@ namespace chaiscript
namespace chaiscript
{
/**
* Used by Proxy_Function_Impl to return a list of all param types
* it contains.
*/
template<typename Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param) >
std::vector<Type_Info> build_param_type_list(Ret (*)(BOOST_PP_ENUM_PARAMS(n, Param)))
namespace dispatch
{
namespace detail
{
std::vector<Type_Info> ti;
ti.push_back(detail::Get_Type_Info<Ret>::get());
/**
* Used by Proxy_Function_Impl to return a list of all param types
* it contains.
*/
template<typename Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param) >
std::vector<Type_Info> build_param_type_list(Ret (*)(BOOST_PP_ENUM_PARAMS(n, Param)))
{
std::vector<Type_Info> ti;
ti.push_back(chaiscript::detail::Get_Type_Info<Ret>::get());
BOOST_PP_REPEAT(n, gettypeinfo, ~)
BOOST_PP_REPEAT(n, gettypeinfo, ~)
return ti;
return ti;
}
/**
* Used by Proxy_Function_Impl to perform typesafe execution of a function.
* The function attempts to unbox each paramter to the expected type.
* if any unboxing fails the execution of the function fails and
* the bad_boxed_cast is passed up to the caller.
*/
template<typename Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param)>
Ret call_func(const boost::function<Ret (BOOST_PP_ENUM_PARAMS(n, Param))> &f,
const std::vector<Boxed_Value> &params)
{
if (params.size() != n)
{
throw exception::arity_error(static_cast<int>(params.size()), n);
} else {
return f(BOOST_PP_REPEAT(n, casthelper, ~));
}
}
/**
* Used by Proxy_Function_Impl to determine if it is equivalent to another
* Proxy_Function_Impl object. This function is primarly used to prevent
* registration of two functions with the exact same signatures
*/
template<typename Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param)>
bool compare_types_cast(Ret (*)(BOOST_PP_ENUM_PARAMS(n, Param)),
const std::vector<Boxed_Value> & BOOST_PP_IF(n, params, ))
{
try {
BOOST_PP_REPEAT(n, trycast, ~);
} catch (const exception::bad_boxed_cast &) {
return false;
}
return true;
}
}
}
}
/**
* Used by Proxy_Function_Impl to perform typesafe execution of a function.
* The function attempts to unbox each paramter to the expected type.
* if any unboxing fails the execution of the function fails and
* the bad_boxed_cast is passed up to the caller.
*/
template<typename Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param)>
Ret call_func(const boost::function<Ret (BOOST_PP_ENUM_PARAMS(n, Param))> &f,
const std::vector<Boxed_Value> &params)
#undef n
#endif
#ifndef BOOST_PP_IS_ITERATING
namespace chaiscript
{
namespace dispatch
{
namespace detail
{
if (params.size() != n)
template<typename Ret>
struct Do_Call
{
throw arity_error(params.size(), n);
} else {
return f(BOOST_PP_REPEAT(n, casthelper, ~));
}
template<typename Fun>
static Boxed_Value go(const boost::function<Fun> &fun, const std::vector<Boxed_Value> &params)
{
return Handle_Return<Ret>::handle(call_func(fun, params));
}
};
template<>
struct Do_Call<void>
{
template<typename Fun>
static Boxed_Value go(const boost::function<Fun> &fun, const std::vector<Boxed_Value> &params)
{
call_func(fun, params);
return Handle_Return<void>::handle();
}
};
}
/**
* Used by Proxy_Function_Impl to determine if it is equivalent to another
* Proxy_Function_Impl object. This function is primarly used to prevent
* registration of two functions with the exact same signatures
*/
template<typename Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param)>
bool compare_types_cast(Ret (*)(BOOST_PP_ENUM_PARAMS(n, Param)),
const std::vector<Boxed_Value> & BOOST_PP_IF(n, params, ))
{
try {
BOOST_PP_REPEAT(n, trycast, ~);
} catch (const bad_boxed_cast &) {
return false;
}
return true;
}
}
}
#endif

View File

@@ -1,11 +1,11 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009, Jonathan Turner (jturner@minnow-lang.org)
// and Jason Turner (lefticus@gmail.com)
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef __register_function_hpp__
#define __register_function_hpp__
#ifndef CHAISCRIPT_REGISTER_FUNCTION_HPP_
#define CHAISCRIPT_REGISTER_FUNCTION_HPP_
#include "dispatchkit.hpp"
#include "bind_first.hpp"
@@ -14,60 +14,148 @@
#include <boost/function_types/components.hpp>
#include <boost/function_types/function_type.hpp>
#include <boost/function_types/is_member_object_pointer.hpp>
#include <boost/function_types/is_member_function_pointer.hpp>
namespace chaiscript
{
namespace detail
namespace dispatch
{
template<bool Object>
struct Fun_Helper
{
template<typename T>
static Proxy_Function go(T t)
namespace detail
{
template<bool Object, bool MemFn>
struct Fun_Helper
{
return Proxy_Function(
new Proxy_Function_Impl<
template<typename T>
static Proxy_Function go(T t)
{
return Proxy_Function(
new Proxy_Function_Impl<
typename boost::function_types::function_type<boost::function_types::components<T> >::type> (
boost::function<
typename boost::function_types::function_type<boost::function_types::components<T> >::type
>(t)));
}
};
typename boost::function_types::function_type<boost::function_types::components<T> >::type
>(t)));
}
};
template<>
struct Fun_Helper<true>
{
template<typename T, typename Class>
static Proxy_Function go(T Class::* m)
{
return Proxy_Function(new Attribute_Access<T, Class>(m));
}
};
template<>
struct Fun_Helper<false, true>
{
template<typename T>
static Proxy_Function go(T t)
{
return Proxy_Function(
new Proxy_Function_Impl<
typename boost::function_types::function_type<boost::function_types::components<T> >::type> (
boost::function<
typename boost::function_types::function_type<boost::function_types::components<T> >::type
>(boost::mem_fn(t))));
}
};
template<>
struct Fun_Helper<true, false>
{
template<typename T, typename Class>
static Proxy_Function go(T Class::* m)
{
return Proxy_Function(new Attribute_Access<T, Class>(m));
}
};
}
}
/// \brief Creates a new Proxy_Function object from a boost::function object
/// \param[in] f boost::function to expose to ChaiScript
///
/// \b Example:
/// \code
/// boost::function<int (char, float, std::string)> f = get_some_function();
/// chaiscript::ChaiScript chai;
/// chai.add(fun(f), "some_function");
/// \endcode
///
/// \sa \ref addingfunctions
template<typename T>
Proxy_Function fun(const boost::function<T> &f)
{
return Proxy_Function(new Proxy_Function_Impl<T>(f));
return Proxy_Function(new dispatch::Proxy_Function_Impl<T>(f));
}
/// \brief Creates a new Proxy_Function object from a free function, member function or data member
/// \param[in] t Function / member to expose
///
/// \b Example:
/// \code
/// int myfunction(const std::string &);
/// class MyClass
/// {
/// public:
/// void memberfunction();
/// int memberdata;
/// };
///
/// chaiscript::ChaiScript chai;
/// chai.add(fun(&myfunction), "myfunction");
/// chai.add(fun(&MyClass::memberfunction), "memberfunction");
/// chai.add(fun(&MyClass::memberdata), "memberdata");
/// \endcode
///
/// \sa \ref addingfunctions
template<typename T>
Proxy_Function fun(T t)
{
return detail::Fun_Helper<boost::function_types::is_member_object_pointer<T>::value>::go(t);
return dispatch::detail::Fun_Helper<boost::function_types::is_member_object_pointer<T>::value, boost::function_types::is_member_function_pointer<T>::value>::go(t);
}
/// \brief Creates a new Proxy_Function object from a free function, member function or data member and binds the first parameter of it
/// \param[in] t Function / member to expose
/// \param[in] q Value to bind to first parameter
///
/// \b Example:
/// \code
/// struct MyClass
/// {
/// void memberfunction(int);
/// };
///
/// MyClass obj;
/// chaiscript::ChaiScript chai;
/// // Add function taking only one argument, an int, and permanently bound to "obj"
/// chai.add(fun(&MyClass::memberfunction, boost::ref(obj)), "memberfunction");
/// \endcode
///
/// \sa \ref addingfunctions
template<typename T, typename Q>
Proxy_Function fun(T t, const Q &q)
{
return fun(bind_first(t, q));
return fun(detail::bind_first(t, q));
}
/// \brief Creates a new Proxy_Function object from a free function or member function and binds the first and second parameters of it
/// \param[in] t Function / member to expose
/// \param[in] q Value to bind to first parameter
/// \param[in] r Value to bind to second parameter
///
/// \b Example:
/// \code
/// struct MyClass
/// {
/// void memberfunction(int);
/// };
///
/// MyClass obj;
/// chaiscript::ChaiScript chai;
/// // Add function taking only no arguments, and permanently bound to "obj" and "1"
/// // memberfunction() will be equivalent to obj.memberfunction(1)
/// chai.add(fun(&MyClass::memberfunction, boost::ref(obj), 1), "memberfunction");
/// \endcode
///
/// \sa \ref addingfunctions
template<typename T, typename Q, typename R>
Proxy_Function fun(T t, const Q &q, const R &r)
{
return fun(bind_first(bind_first(t, q), r));
return fun(detail::bind_first(detail::bind_first(t, q), r));
}
}

View File

@@ -1,16 +1,21 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009, Jonathan Turner (jturner@minnow-lang.org)
// and Jason Turner (lefticus@gmail.com)
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef __type_info_hpp__
#define __type_info_hpp__
#ifndef CHAISCRIPT_TYPE_INFO_HPP_
#define CHAISCRIPT_TYPE_INFO_HPP_
#include <string>
#include <typeinfo>
#include <boost/shared_ptr.hpp>
#include <boost/type_traits/is_const.hpp>
#include <boost/type_traits/is_void.hpp>
#include <boost/type_traits/is_reference.hpp>
#include <boost/type_traits/is_pointer.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/is_arithmetic.hpp>
#include <boost/type_traits/remove_const.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/type_traits/remove_pointer.hpp>
@@ -18,16 +23,24 @@
namespace chaiscript
{
/**
* compile time deduced information about a type
*/
namespace detail
{
template<typename T>
struct Bare_Type
{
typedef typename boost::remove_const<typename boost::remove_pointer<typename boost::remove_reference<T>::type>::type>::type type;
};
}
/// \brief Compile time deduced information about a type
class Type_Info
{
public:
Type_Info(bool t_is_const, bool t_is_reference, bool t_is_pointer, bool t_is_void,
const std::type_info *t_ti, const std::type_info *t_bareti)
bool t_is_arithmetic, const std::type_info *t_ti, const std::type_info *t_bareti)
: m_is_const(t_is_const), m_is_reference(t_is_reference), m_is_pointer(t_is_pointer),
m_is_void(t_is_void),
m_is_void(t_is_void), m_is_arithmetic(t_is_arithmetic),
m_type_info(t_ti), m_bare_type_info(t_bareti),
m_is_undef(false)
{
@@ -35,7 +48,7 @@ namespace chaiscript
Type_Info()
: m_is_const(false), m_is_reference(false), m_is_pointer(false),
m_is_void(false), m_type_info(0), m_bare_type_info(0),
m_is_void(false), m_is_arithmetic(false), m_type_info(0), m_bare_type_info(0),
m_is_undef(true)
{
}
@@ -43,7 +56,8 @@ namespace chaiscript
Type_Info(const Type_Info &ti)
: m_is_const(ti.m_is_const), m_is_reference(ti.m_is_reference),
m_is_pointer(ti.m_is_pointer),
m_is_void(ti.m_is_void), m_type_info(ti.m_type_info),
m_is_void(ti.m_is_void), m_is_arithmetic(ti.m_is_arithmetic),
m_type_info(ti.m_type_info),
m_bare_type_info(ti.m_bare_type_info),
m_is_undef(ti.m_is_undef)
{
@@ -55,6 +69,7 @@ namespace chaiscript
m_is_reference = ti.m_is_reference;
m_is_pointer = ti.m_is_pointer;
m_is_void = ti.m_is_void;
m_is_arithmetic = ti.m_is_arithmetic;
m_type_info = ti.m_type_info;
m_bare_type_info = ti.m_bare_type_info;
m_is_undef = ti.m_is_undef;
@@ -86,7 +101,19 @@ namespace chaiscript
bool is_const() const { return m_is_const; }
bool is_reference() const { return m_is_reference; }
bool is_void() const { return m_is_void; }
bool is_arithmetic() const { return m_is_arithmetic; }
bool is_undef() const { return m_is_undef || m_bare_type_info == 0; }
bool is_pointer() const { return m_is_pointer; }
std::string name() const
{
if (m_type_info)
{
return m_type_info->name();
} else {
return "";
}
}
std::string bare_name() const
{
@@ -103,6 +130,7 @@ namespace chaiscript
bool m_is_reference;
bool m_is_pointer;
bool m_is_void;
bool m_is_arithmetic;
const std::type_info *m_type_info;
const std::type_info *m_bare_type_info;
bool m_is_undef;
@@ -116,59 +144,109 @@ namespace chaiscript
template<typename T>
struct Get_Type_Info
{
typedef T type;
static Type_Info get()
{
return Type_Info(boost::is_const<T>::value, boost::is_reference<T>::value, boost::is_pointer<T>::value,
return Type_Info(boost::is_const<typename boost::remove_pointer<typename boost::remove_reference<T>::type>::type>::value, boost::is_reference<T>::value, boost::is_pointer<T>::value,
boost::is_void<T>::value,
boost::is_arithmetic<T>::value && !boost::is_same<typename boost::remove_const<T>::type, bool>::value,
&typeid(T),
&typeid(typename boost::remove_const<typename boost::remove_pointer<typename boost::remove_reference<T>::type>::type>::type));
&typeid(typename Bare_Type<T>::type));
}
};
template<typename T>
struct Get_Type_Info<boost::shared_ptr<T> >
{
typedef T type;
static Type_Info get()
{
return Type_Info(boost::is_const<T>::value, boost::is_reference<T>::value, boost::is_pointer<T>::value,
boost::is_void<T>::value,
boost::is_arithmetic<T>::value && !boost::is_same<typename boost::remove_const<T>::type, bool>::value,
&typeid(boost::shared_ptr<T> ),
&typeid(typename boost::remove_const<typename boost::remove_pointer<typename boost::remove_reference<T>::type>::type>::type));
&typeid(typename Bare_Type<T>::type));
}
};
template<typename T>
struct Get_Type_Info<const boost::shared_ptr<T> &>
{
typedef T type;
static Type_Info get()
{
return Type_Info(boost::is_const<T>::value, boost::is_reference<T>::value, boost::is_pointer<T>::value,
boost::is_void<T>::value,
boost::is_arithmetic<T>::value && !boost::is_same<typename boost::remove_const<T>::type, bool>::value,
&typeid(const boost::shared_ptr<T> &),
&typeid(typename boost::remove_const<typename boost::remove_pointer<typename boost::remove_reference<T>::type>::type>::type));
&typeid(typename Bare_Type<T>::type));
}
};
template<typename T>
struct Get_Type_Info<boost::reference_wrapper<T> >
{
typedef T type;
static Type_Info get()
{
return Type_Info(boost::is_const<T>::value, boost::is_reference<T>::value, boost::is_pointer<T>::value,
boost::is_void<T>::value,
boost::is_arithmetic<T>::value && !boost::is_same<typename boost::remove_const<T>::type, bool>::value,
&typeid(boost::reference_wrapper<T> ),
&typeid(typename boost::remove_const<typename boost::remove_pointer<typename boost::remove_reference<T>::type>::type>::type));
&typeid(typename Bare_Type<T>::type));
}
};
template<typename T>
struct Get_Type_Info<const boost::reference_wrapper<T> &>
{
typedef T type;
static Type_Info get()
{
return Type_Info(boost::is_const<T>::value, boost::is_reference<T>::value, boost::is_pointer<T>::value,
boost::is_void<T>::value,
boost::is_arithmetic<T>::value && !boost::is_same<typename boost::remove_const<T>::type, bool>::value,
&typeid(const boost::reference_wrapper<T> &),
&typeid(typename Bare_Type<T>::type));
}
};
template<typename T>
struct Stripped_Type
{
typedef typename Bare_Type<typename detail::Get_Type_Info<T>::type>::type type;
};
}
/// \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
/// \return Type_Info for T
///
/// \b Example:
/// \code
/// int i;
/// chaiscript::Type_Info ti = chaiscript::user_type(i);
/// \endcode
template<typename T>
Type_Info user_type(T)
Type_Info user_type(const T &/*t*/)
{
return detail::Get_Type_Info<T>::get();
}
/// \brief Creates a Type_Info object representing the templated type
/// \tparam T Type of object to get a Type_Info for
/// \return Type_Info for T
///
/// \b Example:
/// \code
/// chaiscript::Type_Info ti = chaiscript::user_type<int>();
/// \endcode
template<typename T>
Type_Info user_type()
{

View File

@@ -0,0 +1,131 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_ALGEBRAIC_HPP_
#define CHAISCRIPT_ALGEBRAIC_HPP_
#include <chaiscript/dispatchkit/dispatchkit.hpp>
#include <boost/enable_shared_from_this.hpp>
namespace chaiscript
{
struct Operators {
enum Opers
{
boolean_flag,
equals, less_than, greater_than, less_than_equal, greater_than_equal, not_equal,
non_const_flag,
assign, pre_increment, pre_decrement, assign_product, assign_sum,
assign_quotient, assign_difference,
non_const_int_flag,
assign_bitwise_and, assign_bitwise_or, assign_shift_left, assign_shift_right,
assign_remainder, assign_bitwise_xor,
const_int_flag,
shift_left, shift_right, remainder, bitwise_and, bitwise_or, bitwise_xor, bitwise_complement,
const_flag,
sum, quotient, product, difference, unary_plus, unary_minus,
invalid
};
static const char *to_string(Opers t_oper) {
const char *opers[] = {
"",
"==", "<", ">", "<=", ">=", "!=",
"",
"=", "++", "--", "*=", "+=",
"/=", "-=",
"",
"&=", "|=", "<<=", ">>=",
"%=", "^=",
"",
"<<", ">>", "%", "&", "|", "^", "~",
"",
"+", "/", "*", "-", "+", "-",
""
};
return opers[t_oper];
}
static Opers to_operator(const std::string &t_str, bool t_is_unary = false)
{
if (t_str == "==")
{
return equals;
} else if (t_str == "<") {
return less_than;
} else if (t_str == ">") {
return greater_than;
} else if (t_str == "<=") {
return less_than_equal;
} else if (t_str == ">=") {
return greater_than_equal;
} else if (t_str == "!=") {
return not_equal;
} else if (t_str == "=") {
return assign;
} else if (t_str == "++") {
return pre_increment;
} else if (t_str == "--") {
return pre_decrement;
} else if (t_str == "*=") {
return assign_product;
} else if (t_str == "+=") {
return assign_sum;
} else if (t_str == "-=") {
return assign_difference;
} else if (t_str == "&=") {
return assign_bitwise_and;
} else if (t_str == "|=") {
return assign_bitwise_or;
} else if (t_str == "<<=") {
return assign_shift_left;
} else if (t_str == ">>=") {
return assign_shift_right;
} else if (t_str == "%=") {
return assign_remainder;
} else if (t_str == "^=") {
return assign_bitwise_xor;
} else if (t_str == "<<") {
return shift_left;
} else if (t_str == ">>") {
return shift_right;
} else if (t_str == "%") {
return remainder;
} else if (t_str == "&") {
return bitwise_and;
} else if (t_str == "|") {
return bitwise_or;
} else if (t_str == "^") {
return bitwise_xor;
} else if (t_str == "~") {
return bitwise_complement;
} else if (t_str == "+") {
if (t_is_unary) {
return unary_plus;
} else {
return sum;
}
} else if (t_str == "-") {
if (t_is_unary) {
return unary_minus;
} else {
return difference;
}
} else if (t_str == "/") {
return quotient;
} else if (t_str == "*") {
return product;
} else {
return invalid;
}
}
};
}
#endif /* _CHAISCRIPT_ALGEBRAIC_HPP */

View File

@@ -1,136 +1,220 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009, Jonathan Turner (jturner@minnow-lang.org)
// and Jason Turner (lefticus@gmail.com)
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef _CHAISCRIPT_COMMON_HPP
#define _CHAISCRIPT_COMMON_HPP
#ifndef CHAISCRIPT_COMMON_HPP_
#define CHAISCRIPT_COMMON_HPP_
#ifdef BOOST_HAS_DECLSPEC
#define CHAISCRIPT_MODULE_EXPORT extern "C" __declspec(dllexport)
#else
#define CHAISCRIPT_MODULE_EXPORT extern "C"
#endif
#include <chaiscript/dispatchkit/dispatchkit.hpp>
#include <boost/enable_shared_from_this.hpp>
namespace chaiscript
{
typedef ModulePtr (*Create_Module_Func)();
/// Signature of module entry point that all binary loadable modules must implement.
typedef ModulePtr (*Create_Module_Func)();
/// Types of AST nodes available to the parser and eval
class AST_Node_Type {
public:
enum Type { Error, Int, Float, Id, Char, Str, Eol, Fun_Call, Inplace_Fun_Call, Arg_List, Variable, Equation, Var_Decl,
Comparison, Addition, Subtraction, Multiplication, Division, Modulus, Array_Call, Dot_Access, Quoted_String, Single_Quoted_String,
Lambda, Block, Def, While, If, For, Inline_Array, Inline_Map, Return, File, Prefix, Break, Map_Pair, Value_Range,
Inline_Range, Annotation, Try, Catch, Finally, Method, Attr_Decl, Shift, Equality, Bitwise_And, Bitwise_Xor, Bitwise_Or,
Logical_And, Logical_Or
};
};
namespace
{
/**
* Types of AST nodes available to the parser and eval
* Helper lookup to get the name of each node type
*/
class Token_Type { public: enum Type { Error, Int, Float, Id, Char, Str, Eol, Fun_Call, Inplace_Fun_Call, Arg_List, Variable, Equation, Var_Decl,
Comparison, Additive, Multiplicative, Array_Call, Dot_Access, Quoted_String, Single_Quoted_String,
Lambda, Block, Def, While, If, For, Inline_Array, Inline_Map, Return, File, Prefix, Break, Map_Pair, Value_Range,
Inline_Range, Annotation, Try, Catch, Finally, Method, Attr_Decl, Shift, Equality, Bitwise_And, Bitwise_Xor, Bitwise_Or,
Logical_And, Logical_Or}; };
const char *ast_node_type_to_string(int ast_node_type) {
const char *ast_node_types[] = { "Internal Parser Error", "Int", "Float", "Id", "Char", "Str", "Eol", "Fun_Call", "Inplace_Fun_Call", "Arg_List", "Variable", "Equation", "Var_Decl",
"Comparison", "Addition", "Subtraction", "Multiplication", "Division", "Modulus", "Array_Call", "Dot_Access", "Quoted_String", "Single_Quoted_String",
"Lambda", "Block", "Def", "While", "If", "For", "Inline_Array", "Inline_Map", "Return", "File", "Prefix", "Break", "Map_Pair", "Value_Range",
"Inline_Range", "Annotation", "Try", "Catch", "Finally", "Method", "Attr_Decl", "Shift", "Equality", "Bitwise_And", "Bitwise_Xor", "Bitwise_Or",
"Logical_And", "Logical_Or"};
namespace
{
/**
* Helper lookup to get the name of each node type
*/
const char *token_type_to_string(int tokentype) {
const char *token_types[] = { "Internal Parser Error", "Int", "Float", "Id", "Char", "Str", "Eol", "Fun_Call", "Inplace_Fun_Call", "Arg_List", "Variable", "Equation", "Var_Decl",
"Comparison", "Additive", "Multiplicative", "Array_Call", "Dot_Access", "Quoted_String", "Single_Quoted_String",
"Lambda", "Block", "Def", "While", "If", "For", "Inline_Array", "Inline_Map", "Return", "File", "Prefix", "Break", "Map_Pair", "Value_Range",
"Inline_Range", "Annotation", "Try", "Catch", "Finally", "Method", "Attr_Decl", "Shift", "Equality", "Bitwise_And", "Bitwise_Xor", "Bitwise_Or",
"Logical_And", "Logical_Or"};
return token_types[tokentype];
}
return ast_node_types[ast_node_type];
}
}
/**
* Convenience type for file positions
*/
struct File_Position {
int line;
int column;
/// \brief Convenience type for file positions
struct File_Position {
int line;
int column;
File_Position(int file_line, int file_column)
: line(file_line), column(file_column) { }
File_Position(int t_file_line, int t_file_column)
: line(t_file_line), column(t_file_column) { }
File_Position() : line(0), column(0) { }
};
File_Position() : line(0), column(0) { }
};
typedef boost::shared_ptr<struct Token> TokenPtr;
/// \brief Typedef for pointers to AST_Node objects. Used in building of the AST_Node tree
typedef boost::shared_ptr<struct AST_Node> AST_NodePtr;
/**
* The struct that doubles as both a parser token and an AST node
*/
struct Token {
std::string text;
int identifier;
const char *filename;
File_Position start, end;
bool is_cached;
Boxed_Value cached_value;
std::vector<TokenPtr> children;
TokenPtr annotation;
Token(const std::string &token_text, int id, const char *fname) :
text(token_text), identifier(id), filename(fname), is_cached(false) { }
Token(const std::string &token_text, int id, const char *fname, int start_line, int start_col, int end_line, int end_col) :
text(token_text), identifier(id), filename(fname), is_cached(false) {
start.line = start_line;
start.column = start_col;
end.line = end_line;
end.column = end_col;
}
};
/// \brief Classes which may be thrown during error cases when ChaiScript is executing.
namespace exception
{
/**
* Errors generated during parsing or evaluation
*/
struct Eval_Error : public std::runtime_error {
std::string reason;
File_Position start_position;
File_Position end_position;
const char *filename;
struct eval_error : public std::runtime_error {
std::string reason;
File_Position start_position;
File_Position end_position;
std::string filename;
std::vector<AST_NodePtr> call_stack;
Eval_Error(const std::string &why, const File_Position &where, const char *fname) :
std::runtime_error("Error: \"" + why + "\" " +
(std::string(fname) != "__EVAL__" ? ("in '" + std::string(fname) + "' ") : "during evaluation ") +
+ "at (" + boost::lexical_cast<std::string>(where.line) + ", " +
boost::lexical_cast<std::string>(where.column) + ")"),
reason(why), start_position(where), end_position(where), filename(fname)
eval_error(const std::string &t_why, const File_Position &t_where, const std::string &t_fname) throw() :
std::runtime_error("Error: \"" + t_why + "\" " +
(t_fname != "__EVAL__" ? ("in '" + t_fname + "' ") : "during evaluation ") +
+ "at (" + boost::lexical_cast<std::string>(t_where.line) + ", " +
boost::lexical_cast<std::string>(t_where.column) + ")"),
reason(t_why), start_position(t_where), end_position(t_where), filename(t_fname)
{ }
Eval_Error(const std::string &why, const TokenPtr &where)
: std::runtime_error("Error: \"" + why + "\" " +
(std::string(where->filename) != "__EVAL__" ? ("in '" + std::string(where->filename) + "' ") : "during evaluation ") +
"at (" + boost::lexical_cast<std::string>(where->start.line) + ", " +
boost::lexical_cast<std::string>(where->start.column) + ")"),
reason(why), start_position(where->start), end_position(where->end), filename(where->filename) {
eval_error(const std::string &t_why) throw()
: std::runtime_error("Error: \"" + t_why + "\" "),
reason(t_why)
{}
virtual ~eval_error() throw() {}
};
/**
* Errors generated when loading a file
*/
struct file_not_found_error : public std::runtime_error {
file_not_found_error(const std::string &t_filename) throw()
: std::runtime_error("File Not Found: " + t_filename)
{ }
virtual ~file_not_found_error() throw() {}
};
}
/// \brief Struct that doubles as both a parser ast_node and an AST node.
struct AST_Node : boost::enable_shared_from_this<AST_Node> {
public:
const std::string text;
const int identifier;
boost::shared_ptr<const std::string> filename;
File_Position start, end;
std::vector<AST_NodePtr> children;
AST_NodePtr annotation;
/**
* Prints the contents of an AST node, including its children, recursively
*/
std::string to_string(std::string t_prepend = "") {
std::ostringstream oss;
oss << t_prepend << "(" << ast_node_type_to_string(this->identifier) << ") "
<< this->text << " : " << this->start.line << ", " << this->start.column << std::endl;
for (unsigned int j = 0; j < this->children.size(); ++j) {
oss << this->children[j]->to_string(t_prepend + " ");
}
return oss.str();
}
std::string internal_to_string() {
return to_string();
}
Boxed_Value eval(chaiscript::detail::Dispatch_Engine &t_e)
{
try {
return eval_internal(t_e);
} catch (exception::eval_error &ee) {
ee.call_stack.push_back(shared_from_this());
throw ee;
}
}
void replace_child(const AST_NodePtr &t_child, const AST_NodePtr &t_new_child)
{
std::replace(children.begin(), children.end(), t_child, t_new_child);
}
protected:
AST_Node(const std::string &t_ast_node_text, int t_id, const boost::shared_ptr<std::string> &t_fname,
int t_start_line, int t_start_col, int t_end_line, int t_end_col) :
text(t_ast_node_text), identifier(t_id), filename(t_fname),
start(t_start_line, t_start_col), end(t_end_line, t_end_col)
{
}
AST_Node(const std::string &t_ast_node_text, int t_id, const boost::shared_ptr<std::string> &t_fname) :
text(t_ast_node_text), identifier(t_id), filename(t_fname) {}
virtual ~AST_Node() {}
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &)
{
throw std::runtime_error("Undispatched ast_node (internal error)");
}
private:
// Copy and assignment explicitly unimplemented
AST_Node(const AST_Node &);
AST_Node& operator=(const AST_Node &);
};
namespace eval
{
namespace detail
{
/**
* Special type for returned values
*/
struct Return_Value {
Boxed_Value retval;
Return_Value(const Boxed_Value &t_return_value) : retval(t_return_value) { }
};
/**
* Special type indicating a call to 'break'
*/
struct Break_Loop {
Break_Loop() { }
};
/// Creates a new scope then pops it on destruction
struct Scope_Push_Pop
{
Scope_Push_Pop(chaiscript::detail::Dispatch_Engine &t_de)
: m_de(t_de)
{
m_de.new_scope();
}
virtual ~Eval_Error() throw() {}
};
~Scope_Push_Pop()
{
m_de.pop_scope();
}
/**
* Special type for returned values
*/
struct Return_Value {
Boxed_Value retval;
TokenPtr location;
Return_Value(const Boxed_Value &return_value, const TokenPtr where) : retval(return_value), location(where) { }
};
private:
// explicitly unimplemented copy and assignment
Scope_Push_Pop(const Scope_Push_Pop &);
Scope_Push_Pop& operator=(const Scope_Push_Pop &);
/**
* Special type indicating a call to 'break'
*/
struct Break_Loop {
TokenPtr location;
Break_Loop(const TokenPtr where) : location(where) { }
};
chaiscript::detail::Dispatch_Engine &m_de;
};
}
}
}
#endif /* _CHAISCRIPT_COMMON_HPP */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,7 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009, Jonathan Turner (jturner@minnow-lang.org)
// and Jason Turner (lefticus@gmail.com)
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_PRELUDE_HPP_
@@ -131,11 +131,11 @@ def product(container) { foldl(container, `*`, 1.0) } \n\
# Returns a new container with the elements of the first value concatenated with the elements of the second value\n\
def concat(x, y) : call_exists(clone, x) { \n\
var retval = x; \n\
var len = y.size(); \n\
var i = 0; \n\
while (i < len) { \n\
retval.push_back(y[i]); \n\
++i; \n\
var inserter = back_inserter(retval); \n\
var range = range(y); \n\
while (!range.empty()) { \n\
inserter(range.front()); \n\
range.pop_front(); \n\
} \n\
retval; \n\
} \n\
@@ -282,38 +282,38 @@ def zip(x, y) { \n\
}\n\
# Returns the position of the second value string in the first value string\n\
def string::find(substr) : is_type(substr, "string") { \n\
int(find(this, substr, size_t(0))); \n\
int(find(this, substr, 0)); \n\
} \n\
# Returns the position of last match of the second value string in the first value string\n\
def string::rfind(substr) : is_type(substr, "string") { \n\
int(rfind(this, substr, size_t(-1))); \n\
int(rfind(this, substr, -1)); \n\
} \n\
# Returns the position of the first match of elements in the second value string in the first value string\n\
def string::find_first_of(list) : is_type(list, "string") { \n\
int(find_first_of(this, list, size_t(0))); \n\
int(find_first_of(this, list, 0)); \n\
} \n\
# Returns the position of the last match of elements in the second value string in the first value string\n\
def string::find_last_of(list) : is_type(list, "string") { \n\
int(find_last_of(this, list, size_t(-1))); \n\
int(find_last_of(this, list, -1)); \n\
} \n\
# Returns the position of the first non-matching element in the second value string in the first value string\n\
def string::find_first_not_of(list) : is_type(list, "string") { \n\
int(find_first_not_of(this, list, size_t(0))); \n\
int(find_first_not_of(this, list, 0)); \n\
} \n\
# Returns the position of the last non-matching element in the second value string in the first value string\n\
def string::find_last_not_of(list) : is_type(list, "string") { \n\
int(find_last_not_of(this, list, size_t(-1))); \n\
int(find_last_not_of(this, list, -1)); \n\
} \n\
def string::ltrim() { \n\
drop_while(this, fun(x) { x == ' ' || x == '\t' }); \n\
drop_while(this, fun(x) { x == ' ' || x == '\t' || x == '\r' || x == '\n'}); \n\
} \n\
def string::rtrim() { \n\
reverse(drop_while(reverse(this), fun(x) { x == ' ' || x == '\t' })); \n\
reverse(drop_while(reverse(this), fun(x) { x == ' ' || x == '\t' || x == '\r' || x == '\n'})); \n\
} \n\
def string::trim() { \n\
ltrim(rtrim(this)); \n\
} \n\
def find(container, value, compare_func) : call_exists(range, container) && is_type(compare_func, "function") { \n\
def find(container, value, compare_func) : call_exists(range, container) && is_type(compare_func, "Function") { \n\
var range = range(container); \n\
while (!range.empty()) { \n\
if (compare_func(range.front(), value)) { \n\

View File

@@ -0,0 +1,830 @@
/// This file is not technically part of the ChaiScript API. It is used solely for generating Doxygen docs
/// regarding the ChaiScript standard runtime library.
/// \brief Items in this namespace exist in the ChaiScript language runtime. They are not part of the C++ API
namespace ChaiScript_Language
{
/// \page LangStandardLibraryRef ChaiScript Language Standard Libary Reference
///
/// ChaiScript, at its core, has some very functional programming-inspired habits. Few places show this off as clearly
/// as the prelude, itself a name taken as a nod to the popular functional language Haskell. This prelude is available
/// to all standard ChaiScript applications, and provides a simple foundation for using numbers, strings, and ranges
/// (the general category of Range cs and their iteration).
///
/// \brief Generic concept of a value in ChaiScript.
///
/// The Object type exists merely as a concept. All objects in ChaiScript support this concept
/// and have the following methods available to them. All objects are stored internally as chaiscript::Boxed_Value types.
///
/// \sa chaiscript::Boxed_Value
class Object
{
public:
/// \brief Returns the Type_Info value for this Object
Type_Info get_type_info() const;
/// \brief Returns true if the Object is of the named type
bool is_type(string) const;
/// \brief Returns true if the Object is of the Type_Info passed in
bool is_type(Type_Info) const;
/// \brief Returns true if the Object is immutable
bool is_var_const() const;
/// \brief Returns true if the Object is a pointer and the pointer is null
bool is_var_null() const;
/// \brief Returns true if the Object is stored as a pointer
bool is_var_pointer() const;
/// \brief Returns true if the Object is stored as a reference
bool is_var_reference() const;
/// \brief Returns true if the Object does not contain a value is is undefined.
bool is_var_undef() const;
/// \brief Returns the registered name of the type of the object.
///
/// \sa Type_Info::name();
string type_name() const;
};
/// \brief Item returned from a Range object from a Map
class Map_Pair
{
public:
/// \brief Returns the key of the Map entry
const string first();
/// \brief Returns the value Object of the Map entry
Object second();
};
/// \brief Maps strings to Objects
///
/// ChaiScript has a built in shortcut for generating Map objects:
///
/// Example:
/// \code
/// eval> var m = ["a":1, "b":2];
/// [<a,1>, <b,2>]
/// eval> m.count("a");
/// 1
/// eval> m.count("c");
/// 0
/// eval> m.size();
/// 2
/// \endcode
///
/// Implemented as std::map<Boxed_Value>
///
/// \sa Map_Pair
/// \sa chaiscript::bootstrap::standard_library::map_type
class Map
{
public:
/// \brief Returns an object that implements the Range concept for the Map_Pair's in this Map
Range range();
/// \brief Returns an object that implements the Const_Range concept for the Map_Pair's in this Map
Const_Range range() const;
/// \brief Returns the number of elements in the Map
int size() const;
/// \brief Returns the item at the given key, creating an undefined Object if the key does not yet exist in the map
Object operator[](string);
/// \brief Clears the map of all items
void clear();
/// \brief Returns the number of items in the Map with the given key. Returns 0 or 1 since this is not an std::multimap.
int count(string) const;
/// \brief Returns true if the map contains no items
bool empty() const;
};
/// \brief A concept implemented by string, Vector and Map. It is convertable to Range, default constructable and back_insertable
class Container
{
public:
void push_back(Object);
Range range();
Const_Range range() const;
};
/// \brief Converts o into a string.
///
/// \code
/// eval> to_string(3).is_type("string") <br>
/// true<br>
/// \endcode
string to_string(Object o);
/// \brief Prints o to the terminal, without a trailing carriage return. Applies conversions to string automatically.
/// \code
/// eval> puts("hi, "); puts("there")
/// hi, thereeval>
/// \endcode
/// \sa to_string
/// \sa print
void puts(Object o);
/// \brief Prints o to the terminal, with a trailing carriage return. Applies conversions to string automatically
/// \code
/// eval> print("hello")
/// hello
/// eval>
/// \endcode
/// \sa to_string
/// \sa puts
void print(Object o);
/// \brief ChaiScript representation of std::string. It is an std::string but only some member are exposed to ChaiScript.
///
/// Because the ChaiScript string object is an std::string, it is directly convertable to and from std::string
/// using the chaiscript::boxed_cast and chaiscript::var functions.
///
/// With the exception of string::trim, string::rtrim, string::ltrim, all members are direct passthroughs to the
/// std::string of the same name.
///
/// \note Object and function notations are equivalent in ChaiScript. This means that
/// \c "bob".find("b") and \c find("bob", "b") are exactly the same. Most examples below follow the
/// second formation of the function calls.
/// \sa \ref keyworddef for extending existing C++ classes in ChaiScript
/// \sa chaiscript::bootstrap::standard_library::string_type
class string
{
public:
/// \brief Finds the first instance of substr.
/// \code
/// eval> find("abab", "ab")
/// 0
/// \endcode
int find(string s) const;
/// \brief Finds the last instance of substr.
/// \code
/// eval> rfind("abab", "ab")
/// 2
/// \endcode
int rfind(string s) const;
/// \brief Finds the first of characters in list in the string.
///
/// \code
/// eval> find_first_of("abab", "bec")
/// 1
/// \endcode
int find_first_of(string list) const;
/// \brief Finds the last of characters in list in the string.
///
/// \code
/// eval> find_last_of("abab", "bec")
/// 3
/// \endcode
int find_last_of(string list) const;
/// \brief Finds the first non-matching character to list in the str string.
///
/// \code
/// eval> find_first_not_of("abcd", "fec")
/// 0
/// \endcode
int find_first_not_of(string list) const;
/// \brief Finds the last non-matching character to list in the list string.
///
/// \code
/// eval> find_last_not_of("abcd", "fec")
/// 3
/// \endcode
int find_last_not_of(string list) const;
/// \brief Removes whitespace from the front of the string, returning a new string
///
/// \note This function is implemented as a ChaiScript function using the def member function notation.
///
/// \code
/// eval> ltrim(" bob")
/// bob
/// \endcode
///
/// \sa \ref keyworddef
string lstrim() const;
/// \brief Removes whitespace from the back of the string, returning a new string
///
/// \note This function is implemented as a ChaiScript function using the def member function notation.
///
/// \code
/// eval> rtrim("bob ") + "|"
/// bob|
/// \endcode
///
/// \sa \ref keyworddef
string rtrim() const;
/// \brief Removes whitespace from the front and back of the string, returning a new string
///
/// \note This function is implemented as a ChaiScript function using the def member function notation.
///
/// \code
/// eval> trim(" bob ") + "|"
/// bob|
/// \endcode
///
/// Equivalent to rtrim(ltrim(" bob "));
///
/// \sa \ref keyworddef
string trim() const;
/// \brief Returns the character at the given index in the string, const version
const char &operator[](int t_index) const;
/// \brief Returns the character at the given index in the string
char &operator[](int t_index);
/// \brief Returns underlying const char * for C api compatibility
const char *c_str() const;
/// \brief Returns a pointer to the raw data in the string
const char *data() const;
/// \brief Resets the string to empty
void clear();
/// \brief Returns true if the string is empty
bool empty() const;
/// \brief Returns the size of the string in bytes.
///
/// This function normally returns size_t in C++. In ChaiScript the return value is cast to int
/// for ease of use.
int size() const;
/// \brief Returns an object that implements the Range concept for the characters of this string
Range range();
/// \brief Returns an object that implements the Const_Range concept for the characters of this string
Const_Range range() const;
};
/// \brief A concept in ChaiScript that is implemented by \ref string, Vector and Map. It provides
/// easy iteration over the elements in a container.
///
/// Implemented by the template chaiscript::bootstrap::standard_library::Bidir_Range
///
/// \sa Const_Range
class Range
{
public:
/// \brief Returns the last item of the range
Object back();
/// \brief Returns true if the front and back pointers have passed each other, if no items
/// are left in the Range
bool empty() const;
/// \brief Returns the first item of the range
Object front();
/// \brief Moves the back pointer back one.
///
/// \post back() returns the element at back() - 1;
void pop_back();
/// \brief Moves the front pointer forward one
///
/// \post front() returne the element at front() + 1;
void pop_front();
};
/// \brief A concept in ChaiScript that is implemented by \ref string, Vector and Map. It provides
/// easy iteration over the elements in a container. Contained values are const.
///
/// Implemented by the template chaiscript::bootstrap::standard_library::Const_Bidir_Range
///
/// \sa Range
class Const_Range
{
public:
/// \brief Returns the last item of the range
const Object back();
/// \brief Returns true if the front and back pointers have passed each other, if no items
/// are left in the Range
bool empty() const;
/// \brief Returns the first item of the range
const Object front();
/// \brief Moves the back pointer back one.
///
/// \post back() returns the element at back() - 1;
void pop_back();
/// \brief Moves the front pointer forward one
///
/// \post front() returne the element at front() + 1;
void pop_front();
};
/// \brief A vector of Objects
///
/// ChaiScript includes a shortcut for creating a Vector of Objects
///
/// Example:
/// \code
/// eval> var v = [1,2,3,4]
/// [1, 2, 3, 4]
/// eval> v[0];
/// 1
/// eval> v.size();
/// 4
/// \endcode
///
/// Implemented with std::vector<chaiscript::Boxed_Value>
///
/// \sa chaiscript::bootstrap::standard_library::vector_type
class Vector
{
public:
/// \brief returns the Object at the given index. Throws an exception if the index does not exist
Object operator[](int t_index);
/// \brief returns a const Object at the given index. Throws an exception if the index does not exist.
const Object operator[](int t_index) const;
/// \brief returns the last item in the Vector
Object back();
/// \brief Clears the Vector of all items
void clear();
/// \brief Returns true if the Vector is contains 0 items
bool empty();
/// \brief Erases the element at the given index
void erase_at(int t_index);
/// \brief Returns the first item in the Vector
Object front();
/// \brief Inserts a new item in the Vector at the given index. The item is not cloned on insert
///
/// \sa insert_ref
void insert_ref_at(int, Object);
/// \brief Inserts a new item in the Vector at the given index. The item is cloned on insert
///
/// \sa insert_ref
void insert_at(int, Object);
/// \brief Removes the last item from the Vector
void pop_back();
/// \brief Adds an item to the end of the Vector. The item is not cloned.
///
/// \sa push_back
void push_back_ref(Object);
/// \brief Adds an item to the end of the Vector. The item is cloned.
///
/// \sa push_back_ref
void push_back(Object);
/// \brief Returns a Range object for the entire vector
Range range();
/// \brief Returns a Const_Range object for the entire vector
Const_Range range() const;
/// \brief Returns the number of elements in the Vector
int size() const;
};
class Type_Info
{
public:
/// \brief Compares this Type_Info object with another one and returns true if the two types are the same
/// after const, pointer, reference are removed.
bool bare_equal(Type_Info t_ti) const;
/// \brief Returns the mangled C++ name for the type given by the compiler after const, pointer, reference is removed.
string cpp_bare_name() const;
/// \brief Returns the mangled C++ name for the type given by the compiler.
string cpp_name() const;
/// \brief Returns true if the type is const
bool is_type_const() const;
/// \brief Returns true if the type is a pointer
bool is_type_pointer() const;
/// \brief Returns true if the type is a reference
bool is_type_reference() const;
/// \brief Returns true if the type is undefined
bool is_type_undef() const;
/// \brief Returns true if the type is "void"
bool is_type_void() const;
/// \brief Returns the ChaiScript registered name for the type if one exists.
string name() const;
};
/// \brief Represents a function object in ChaiScript
///
/// A function object may be one function, such as:
/// \code
/// var f = fun(x) { return x; }
/// \endcode
///
/// Or it may represent multiple functions
/// \code
/// var f2 = `-`; // represents the unary - as well as the set of binary - operators
/// \endcode
///
/// Guarded function example
/// \code
/// def f3(x) : x > 2 {
/// return x;
/// }
/// \endcode
///
/// Examples in the function definitions below will reference these examples
class Function
{
public:
/// \brief Returns the annotation description of the function
string get_annotation() const;
/// \brief Returns the arity of the function, -1 if the function takes a variable number of parameters
///
/// Example:
/// \code
/// eval> f.get_arity()
/// 1
/// eval> f2.get_arity()
/// -1
/// \endcode
int get_arity() const;
/// \brief Returns a vector of the contained functions
///
/// Example:
/// \code
/// eval> f.get_contained_functions().size()
/// 0
/// eval> f2.get_contained_functions().size()
/// 11
/// eval> var v = f2.get_contained_functions();
/// v[0].get_arity()
/// 2
/// \endcode
Vector get_contained_functions() const;
/// \brief Returns a vector of the contained functions
///
/// Example:
/// \code
/// eval> f.get_guard() // Throws exception
/// Function does not have a guard
/// eval> f3.get_guard().get_arity()
/// 1
/// \endcode
Function get_guard() const;
/// \brief Returns a vector of Type_Info objects that represent the param types for this function.
/// The first value in the list is the return type.
///
/// If this function is a conglomeration of several functions (get_contained_values().size() > 0)
/// then the function returns as many Type_Info objects as it can. If the functions contained all have
/// the same arity, then it represents the arity. If they have different arities, it returns only
/// one value - the return type.
///
/// For each parameter that is the same type, the type is returned. If the types are different
/// then a Type_Info for Object is returned.
///
/// Example:
/// \code
/// eval> f2.get_param_types().size(); // Returns a Type_Info for Object for the return type
/// 1
/// \endcode
Vector get_param_types() const;
/// \brief Returns true if the function has a guard to it. Always returns falls for a conglomerate function
bool has_guard() const;
/// \brief Calls the function with the given set of parameters and returns the value;
///
/// Example:
/// \code
/// eval> `-`.call([2,1]);
/// 1
/// \endcode
Object call(Vector t_params) const;
}
/// \brief Returns the max of a or b. Requires that operator>(a, b) exists
/// Equivalent to
/// \code
/// return a>b?a:b;
/// \endcode
///
/// Example:
/// \code
/// eval> max(4, 10)
/// 10
/// \endcode
Object max(Object a, Object b);
/// \brief Returns the min of a or b. Requires that operator<(a, b) exists
///
/// Equivalent to
/// \code
/// return a<b?a:b;
/// \endcode
///
/// Example:
/// \code
/// eval> min(4, 10)
/// 4
/// \endcode
Object min(Object a, Object b);
/// \brief Returns true if x is an even integer.
///
/// Will also work on any non-integer type for which an operator%(x, int) exists
///
/// Example:
/// \code
/// eval> even(4)
/// true
/// \endcode
bool even(Object x);
/// \brief Returns true if x is an odd integer.
///
/// Will also work on any non-integer type for which an operator%(x, int) exists
///
/// Example:
/// \code
/// eval> odd(4)
/// false
/// \endcode
bool even(Object x);
/// \brief Applies the function f over each element in the Range c.
///
/// Example:
/// \code
/// eval> for_each([1, 2, 3], print)
/// 1
/// 2
/// 3
/// \endcode
void for_each(Range c, Function f);
/// \brief Applies f over each element in the Range c, joining all the results.
///
/// Example:
/// \code
/// eval> map([1, 2, 3], odd)
/// [true, false, true]
/// \endcode
Object map(Range c, Function f);
/// \brief Starts with the initial value and applies the function f to it and the first element of the Range c.
/// The result is then applied to the second element, and so on until the elements are exhausted.
///
/// Example:
/// \code
/// eval> foldl([1, 2, 3, 4], `+`, 0)
/// 10
/// \endcode
Object foldl(Range c, Function f, Object initial);
/// \brief Returns the sum total of the values in the Range c.
///
/// Example:
/// \code
/// eval> sum([1, 2, 3, 4])
/// 10
/// \endcode
///
/// Equivalent to:
/// \code
/// foldl(c, `+`, 0.0);
/// \endcode
Numeric sum(Range c);
/// \brief Returns the product of the value in the Range c.
///
/// Example:
/// \code
/// eval> product([1, 2, 3, 4])
/// 24
/// \endcode
///
/// Equivalent to:
/// \code
/// foldl(c, `*`, 1.0);
/// \endcode
Numeric product(Range c);
/// \brief Takes num elements from the Range c, returning them.
///
/// Example:
/// \code
/// eval> take([1, 2, 3, 4], 2)
/// [1, 2]
/// \endcode
///
/// \returns A container of the same type that was passed in
Object take(Range c, int num);
/// \brief Takes elements from the Range c that match function f, stopping at the first non-match, returning them as a new Vector.
///
/// Example:
/// \code
/// eval> take_while([1, 2, 3], odd)
/// [1]
/// \endcode
///
/// \returns A container of the same type that was passed in
Object take_while(Range c, Function f);
/// \brief Drops num elements from the Range c, returning the remainder.
///
/// Example:
/// \code
/// eval> drop([1, 2, 3, 4], 2)
/// [3, 4]
/// \endcode
///
/// \returns A container of the same type that was passed in
Object drop(Range c, int num);
/// \brief Drops elements from the Range c that match f, stopping at the first non-match, returning the remainder.
///
/// Example:
/// \code
/// eval> drop_while([1, 2, 3], odd)
/// [2, 3]
/// \endcode
Object drop_while(Range c, Function f);
/// \brief Similar to foldl, this takes the first two elements as its starting values for f. This assumes Range c has at least 2 elements.
///
/// Example:
/// \code
/// eval> reduce([1, 2, 3, 4], `+`)
/// 10
/// \endcode
Object reduce(Range c, Function f);
/// \brief Takes elements from Range c that match function f, return them.
///
/// Example:
/// \code
/// eval> filter([1, 2, 3, 4], odd)
/// [1, 3]
/// \endcode
Object filter(Range c, Function f);
/// \brief Joins the elements of the Range c into a string, delimiting each with the delim string.
///
/// Example:
/// \code
/// eval> join([1, 2, 3], "*")
/// 1*2*3
/// \endcode
string join(Range c, string delim);
/// \brief Returns the contents of the Container c in reversed order.
///
/// Example:
/// \code
/// eval> reverse([1, 2, 3, 4, 5, 6, 7])
/// [7, 6, 5, 4, 3, 2, 1]
/// \endcode
Container reverse(Container c);
/// \brief Generates a new Vector filled with values starting at x and ending with y.
///
/// Works on types supporting operator<=(x, y) and operator++(x)
///
/// Example:
/// \code
/// eval> generate_range(1, 10)
/// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
/// \endcode
Vector generate_range(Object x, Object y);
/// \brief Returns a new Range with x and y concatenated.
///
/// Example:
/// \code
/// eval> concat([1, 2, 3], [4, 5, 6])
/// [1, 2, 3, 4, 5, 6]
/// \endcode
Object concat(Range x, Range y);
/// \brief Returns a new Vector with x and y as its values.
///
/// Example:
/// \code
/// eval> collate(1, 2)
/// [1, 2]
/// \endcode
Vector collate(Object x, Object y);
/// \brief Applies f to elements of x and y, returning a new Vector with the result of each application.
///
/// Example:
/// \code
/// eval> zip_with(`+`, [1, 2, 3], [4, 5, 6])
/// [5, 7, 9]
/// \endcode
Vector zip_with(Function f, Range x, Range y);
/// \brief Collates elements of x and y, returning a new Vector with the result.
///
/// Example:
/// \code
/// eval> zip([1, 2, 3], [4, 5, 6])
/// [[1, 4], [2, 5], [3, 6]]
/// \endcode
Vector zip(Range x, Range y);
/// \brief returns true if there exists a call to the Function f that takes the given parameters
///
/// Example:
/// \code
/// eval> call_exists(`+`, 1, 2)
/// true
/// \endcode
bool call_exists(Function f, ...);
/// \brief Reverses a Range object so that the elements are accessed in reverse
Range retro(Range);
/// \brief Reverses a Const_Range object so that the elements are accessed in reverse
Const_Range retro(Const_Range);
/// \brief Raises the given object as an exception. Any type of object can be thrown.
///
/// Example:
/// \code
/// eval> try { throw(1); } catch (e) { print("Exception caught: " + to_string(e)); }
/// Exception caught: 1
/// \endcode
///
/// \sa \ref keywordtry
void throw(Object);
}

View File

@@ -0,0 +1,89 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_UTILITY_UTILITY_HPP_
#define CHAISCRIPT_UTILITY_UTILITY_HPP_
#include "../chaiscript.hpp"
#include <boost/preprocessor.hpp>
#include <string>
#define CHAISCRIPT_MODULE(_info) BOOST_PP_SEQ_ELEM(0, _info)
#define CHAISCRIPT_CLASS_ELEM(_info) BOOST_PP_SEQ_ELEM(1, _info)
#define CHAISCRIPT_METHOD(_info, _method) & CHAISCRIPT_CLASS_ELEM(_info) :: BOOST_PP_SEQ_ELEM(0, _method)
#define CHAISCRIPT_METHOD_NAME(_info, _method) \
BOOST_PP_SEQ_ELEM(3, _info) (BOOST_PP_STRINGIZE(BOOST_PP_SEQ_ELEM(0, _method ) ) )
#define CHAISCRIPT_CLASS_NAME(_info) \
BOOST_PP_SEQ_ELEM(2, _info) (BOOST_PP_STRINGIZE(CHAISCRIPT_CLASS_ELEM(_info) ) )
#define CHAISCRIPT_METHOD_SIGNATURE_PART(_r, _info, _i, _method_part) \
BOOST_PP_EXPR_IF(BOOST_PP_EQUAL(_i, 1), < _method_part > )
#define CHAISCRIPT_METHOD_SIGNATURE(_info, _method) \
BOOST_PP_SEQ_FOR_EACH_I(CHAISCRIPT_METHOD_SIGNATURE_PART, _info, _method)
#define CHAISCRIPT_CLASS_CONSTRUCTOR(_r, _info, _constructor) \
CHAISCRIPT_MODULE(_info) ->add BOOST_PP_LPAREN() chaiscript::constructor<_constructor>() BOOST_PP_COMMA() CHAISCRIPT_CLASS_NAME(_info) BOOST_PP_RPAREN() ;
#define CHAISCRIPT_CLASS_METHOD(_r, _info, _method) \
CHAISCRIPT_MODULE(_info) ->add BOOST_PP_LPAREN() chaiscript::fun CHAISCRIPT_METHOD_SIGNATURE(_info, _method) \
BOOST_PP_LPAREN() CHAISCRIPT_METHOD(_info, _method) BOOST_PP_RPAREN() BOOST_PP_COMMA() CHAISCRIPT_METHOD_NAME(_info, _method)BOOST_PP_RPAREN() ;
#define CHAISCRIPT_CLASS_CONSTRUCTORS(_info, _constructors) \
BOOST_PP_SEQ_FOR_EACH(CHAISCRIPT_CLASS_CONSTRUCTOR, _info, _constructors)
#define CHAISCRIPT_CLASS_METHODS(_info, _methods) \
BOOST_PP_SEQ_FOR_EACH(CHAISCRIPT_CLASS_METHOD, _info, _methods)
#define CHAISCRIPT_CLASS_EX(_module, _class_name, _class_name_translator, _method_name_translator, _constructors, _methods) \
{ \
_module->add(chaiscript::user_type<_class_name>(), _class_name_translator (BOOST_PP_STRINGIZE(_class_name))); \
CHAISCRIPT_CLASS_CONSTRUCTORS((_module)(_class_name)(_class_name_translator), _constructors) \
CHAISCRIPT_CLASS_METHODS((_module)(_class_name)(_class_name_translator)(_method_name_translator), _methods) \
}
#define CHAISCRIPT_CLASS(_module, _class_name, _constructors, _methods) \
CHAISCRIPT_CLASS_EX(_module, _class_name, chaiscript::utility::class_name_translator, \
chaiscript::utility::method_name_translator, _constructors, _methods)
namespace chaiscript
{
/// \brief Classes and functions which provide general utility to the end user.
namespace utility
{
inline std::string class_name_translator(const std::string &t_name)
{
size_t colon = t_name.rfind("::");
if (colon != std::string::npos)
{
return t_name.substr(colon+2, std::string::npos);
} else {
return t_name;
}
}
inline std::string method_name_translator(const std::string &t_name)
{
size_t namestart = t_name.rfind("operator");
namestart = (namestart == std::string::npos)?0:namestart+strlen("operator");
if (namestart == 0)
{
namestart = t_name.rfind("::");
namestart = (namestart == std::string::npos)?0:namestart+strlen("::");
}
return t_name.substr(namestart, std::string::npos);
}
}
}
#endif

View File

@@ -1,4 +1,4 @@
Copyright 2009 Jason and Jonathan Turner. All Rights Reserved.
Copyright 2009-2011 Jason Turner and Jonathan Turner. All Rights Reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:

View File

@@ -1,197 +0,0 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="chai-example"
ProjectGUID="{CE422E94-B360-4588-8C65-6A9BE80798F9}"
RootNamespace="chaiexample"
Keyword="Win32Proj"
TargetFrameworkVersion="196613"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
InheritedPropertySheets="..\chaiscript\Boost.vsprops"
CharacterSet="0"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="&quot;$(ProjectDir)\..\..\include&quot;"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="1"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
InheritedPropertySheets="..\chaiscript\Boost.vsprops"
CharacterSet="0"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
EnableIntrinsicFunctions="true"
AdditionalIncludeDirectories="&quot;$(ProjectDir)\..\..\include&quot;"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath="..\..\src\example.cpp"
>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
</Filter>
<Filter
Name="Resource Files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@@ -1,19 +0,0 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioPropertySheet
ProjectType="Visual C++"
Version="8.00"
Name="Boost"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="&quot;C:\boost\include\boost-1_38&quot;"
/>
<Tool
Name="VCLibrarianTool"
AdditionalLibraryDirectories="C:\Programming\Boost\lib"
/>
<Tool
Name="VCLinkerTool"
AdditionalLibraryDirectories="C:\Boost\lib;C:\Programming\Boost\lib"
/>
</VisualStudioPropertySheet>

View File

@@ -1,32 +0,0 @@

Microsoft Visual Studio Solution File, Format Version 10.00
# Visual C++ Express 2008
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "chaiscript", "chaiscript.vcproj", "{46FD9DC7-2DA9-4C17-ADE4-E3A18C46E87B}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "chai-example", "..\chai-example\chai-example.vcproj", "{CE422E94-B360-4588-8C65-6A9BE80798F9}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_module", "..\test_module\test_module.vcproj", "{775EDCC2-102F-4E75-A860-9AF398D04145}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{46FD9DC7-2DA9-4C17-ADE4-E3A18C46E87B}.Debug|Win32.ActiveCfg = Debug|Win32
{46FD9DC7-2DA9-4C17-ADE4-E3A18C46E87B}.Debug|Win32.Build.0 = Debug|Win32
{46FD9DC7-2DA9-4C17-ADE4-E3A18C46E87B}.Release|Win32.ActiveCfg = Release|Win32
{46FD9DC7-2DA9-4C17-ADE4-E3A18C46E87B}.Release|Win32.Build.0 = Release|Win32
{CE422E94-B360-4588-8C65-6A9BE80798F9}.Debug|Win32.ActiveCfg = Debug|Win32
{CE422E94-B360-4588-8C65-6A9BE80798F9}.Debug|Win32.Build.0 = Debug|Win32
{CE422E94-B360-4588-8C65-6A9BE80798F9}.Release|Win32.ActiveCfg = Release|Win32
{CE422E94-B360-4588-8C65-6A9BE80798F9}.Release|Win32.Build.0 = Release|Win32
{775EDCC2-102F-4E75-A860-9AF398D04145}.Debug|Win32.ActiveCfg = Debug|Win32
{775EDCC2-102F-4E75-A860-9AF398D04145}.Debug|Win32.Build.0 = Debug|Win32
{775EDCC2-102F-4E75-A860-9AF398D04145}.Release|Win32.ActiveCfg = Release|Win32
{775EDCC2-102F-4E75-A860-9AF398D04145}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@@ -1,286 +0,0 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="chaiscript"
ProjectGUID="{46FD9DC7-2DA9-4C17-ADE4-E3A18C46E87B}"
RootNamespace="chaiscript"
Keyword="Win32Proj"
TargetFrameworkVersion="196613"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
InheritedPropertySheets=".\Boost.vsprops"
UseOfMFC="2"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
UseUnicodeResponseFiles="false"
Optimization="0"
AdditionalIncludeDirectories="&quot;$(ProjectDir)\..\..\include&quot;"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
DisableLanguageExtensions="false"
TreatWChar_tAsBuiltInType="false"
UsePrecompiledHeader="0"
WarningLevel="4"
DebugInformationFormat="4"
CompileAs="2"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="1"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
InheritedPropertySheets=".\Boost.vsprops"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="3"
EnableIntrinsicFunctions="true"
AdditionalIncludeDirectories="&quot;$(ProjectDir)\..\..\include&quot;"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
WarningLevel="4"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath="..\..\src\main.cpp"
>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
<File
RelativePath="..\..\include\chaiscript\dispatchkit\bind_first.hpp"
>
</File>
<File
RelativePath="..\..\include\chaiscript\dispatchkit\bootstrap.hpp"
>
</File>
<File
RelativePath="..\..\include\chaiscript\dispatchkit\bootstrap_stl.hpp"
>
</File>
<File
RelativePath="..\..\include\chaiscript\dispatchkit\boxed_value.hpp"
>
</File>
<File
RelativePath="..\..\include\chaiscript\chaiscript.hpp"
>
</File>
<File
RelativePath="..\..\include\chaiscript\language\chaiscript_engine.hpp"
>
</File>
<File
RelativePath="..\..\include\chaiscript\language\chaiscript_eval.hpp"
>
</File>
<File
RelativePath="..\..\include\chaiscript\language\chaiscript_parser.hpp"
>
</File>
<File
RelativePath="..\..\include\chaiscript\language\chaiscript_prelude.hpp"
>
</File>
<File
RelativePath="..\..\include\chaiscript\chaiscript_threading.hpp"
>
</File>
<File
RelativePath="..\..\include\chaiscript\dispatchkit\dispatchkit.hpp"
>
</File>
<File
RelativePath="..\..\include\chaiscript\dispatchkit\dynamic_object.hpp"
>
</File>
<File
RelativePath="..\..\include\chaiscript\dispatchkit\function_call.hpp"
>
</File>
<File
RelativePath="..\..\include\chaiscript\dispatchkit\function_call_detail.hpp"
>
</File>
<File
RelativePath="..\..\include\chaiscript\dispatchkit\handle_return.hpp"
>
</File>
<File
RelativePath="..\..\include\chaiscript\dispatchkit\operators.hpp"
>
</File>
<File
RelativePath="..\..\include\chaiscript\dispatchkit\proxy_constructors.hpp"
>
</File>
<File
RelativePath="..\..\include\chaiscript\dispatchkit\proxy_functions.hpp"
>
</File>
<File
RelativePath="..\..\include\chaiscript\dispatchkit\proxy_functions_detail.hpp"
>
</File>
<File
RelativePath="..\..\include\chaiscript\dispatchkit\register_function.hpp"
>
</File>
<File
RelativePath="..\..\include\chaiscript\dispatchkit\type_info.hpp"
>
</File>
</Filter>
<Filter
Name="Resource Files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@@ -1,198 +0,0 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="test_module"
ProjectGUID="{775EDCC2-102F-4E75-A860-9AF398D04145}"
RootNamespace="test_module"
Keyword="Win32Proj"
TargetFrameworkVersion="196613"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="2"
InheritedPropertySheets="..\chaiscript\Boost.vsprops"
UseOfMFC="0"
CharacterSet="0"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="&quot;$(ProjectDir)\..\..\include&quot;"
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;TEST_MODULE_EXPORTS"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="2"
InheritedPropertySheets="..\chaiscript\Boost.vsprops"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
EnableIntrinsicFunctions="true"
AdditionalIncludeDirectories="&quot;$(ProjectDir)\..\..\include&quot;"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;TEST_MODULE_EXPORTS"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="2"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath="..\..\src\test_module.cpp"
>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
</Filter>
<Filter
Name="Resource Files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@@ -1,11 +1,11 @@
ChaiScript v1.0
ChaiScript
http://www.chaiscript.com
(c) 2009 Jason Turner and Jonathan Turner
(c) 2009-2011 Jason Turner and Jonathan Turner
Release under the BSD license, see "license.txt" for details.
[Introduction]
ChaiScript is one of the first (and perhaps only) embedded scripting language designed from the ground up to directly target C++. Being a native C++ application, it has some advantages over existing embedded scripting languages:
ChaiScript is one of the only embedded scripting language designed from the ground up to directly target C++ and take advantage of modern C++ development techniques, working with the developer like he expects it to work. Being a native C++ application, it has some advantages over existing embedded scripting languages:
1) It uses a header-only approach, which makes it easy to integrate with existing projects.
2) It maintains type safety between your C++ application and the user scripts.
@@ -19,13 +19,13 @@ ChaiScript requires a recent version of Boost (http://www.boost.org) to build.
* Add the ChaiScript include directory to your project's header search path
* Add "#include <chaiscript/chaiscript.hpp> to your source file
* Instantiate the ChaiScript engine in your application. For example, create a new engine with the name 'chai' like so: "chaiscript::ChaiScript_Engine chai"
* Instantiate the ChaiScript engine in your application. For example, create a new engine with the name 'chai' like so: "chaiscript::ChaiScript chai"
Once instantiated, the engine is ready to start running ChaiScript source. You have two main options for processing ChaiScript source: a line at a time using "chai.evaluate_string(string)" and a file at a time using "chai.evaluate_file(fname)"
To make functions in your C++ code visible to scripts, they must be registered with the scripting engine. To do so, call register_function:
To make functions in your C++ code visible to scripts, they must be registered with the scripting engine. To do so, call add:
dispatchkit::register_function(chai.get_eval_engine(), &my_function, "my_function_name");
chai.add(chaiscript::fun(&my_function), "my_function_name");
Once registered the function will be visible to scripts as "my_function_name"
@@ -33,4 +33,23 @@ Once registered the function will be visible to scripts as "my_function_name"
ChaiScript is similar to ECMAScript (aka JavaScript(tm)), but with some modifications to make it easier to use. For usage examples see the "samples" directory, and for more in-depth look at the language, the unit tests in the "unittests" directory cover the most ground.
For example of how to register parts of your C++ application, see "example.cpp" in the "src" directory.
For examples of how to register parts of your C++ application, see "example.cpp" in the "src" directory. Example.cpp is verbose and shows every possible way of working with the library. For further documentation generate the doxygen documentation in the build folder or see the website http://www.chaiscript.com.
The shortest complete example possible follows:
/// main.cpp
#include <chaiscript/chaiscript.hpp>
double function(int i, double j)
{
return i * j;
}
int main()
{
chaiscript::ChaiScript chai;
chai.add(chaiscript::fun(&function), "function");
double d = chai.eval<double>("function(3, 4.75);");
}

26
releasenotes.txt Normal file
View File

@@ -0,0 +1,26 @@
Changes since 2.3.3
* Code simplifications
* Fully integrate documentation with source code in doxygen style comments
* Unit tests increased from 114 to 137
* Automatic conversion between boost::function objects and ChaiScript functions
* Many bug fixes
* Minor performance improvements
* Namespace reorganization to make end user code more accessible
* clang support
* VisualStudio 2010 Support
* Support for C++ base classes and automatic upcasting
* Remove __ reserved identifiers
* Better code organization to reduce #ifdefs
* clanmills: command line options for chai eval
* clanmills: parser cleanups and code reduction
* Function introspection and reflection
* Correct function dispatch order to account for base classes and provide a defined order of dispatch
* Predictable object lifetime that emulates C++ stack lifetime
* emarcotte: pkgconfig support
* standardize on method/member naming and indentation
* 64bit Visual Studio support
* Better support for const objects
* Drastic reduction of runtime exceptions - making debug builds orders of magnitude faster
* Support for platforms with no loadable module support
* Add helper macro for registering class

View File

@@ -1,26 +0,0 @@
#!/bin/bash
successes=0
failures=0
echo -n "Running unit tests"
for file in unittests/*.chai
do
tstname=${file%.*}
tst="$tstname.txt"
LD_LIBRARY_PATH=. ./chaiscript_eval $file > /tmp/tstout.txt
diff $tst /tmp/tstout.txt
if [ "$?" -eq "0" ]
then
echo -n "."
successes=$((successes+1))
else
echo "[from failed test $file]"
failures=$((failures+1))
fi
done
echo ""
total=$((successes+failures))
echo "$successes out of $total succeeded"

View File

@@ -1,27 +0,0 @@
#!/bin/bash
successes=0
failures=0
echo -n "Running unit tests"
for file in unittests/*.chai
do
tstname=${file%.*}
tst="$tstname.txt"
./chaiscript_eval $file > /tmp/tstout.txt
cat $tst > /tmp/tstmaster.txt
awk 'sub("$", "\r")' $tst > /tmp/tstmaster.txt
diff /tmp/tstmaster.txt /tmp/tstout.txt
if [ "$?" -eq "0" ]
then
echo -n "."
successes=$((successes+1))
else
echo "[from failed test $file]"
failures=$((failures+1))
fi
done
echo ""
total=$((successes+failures))
echo "$successes out of $total succeeded"

View File

@@ -1,22 +0,0 @@
def add(x, y)
{
return x + y;
}
var b = bind(add, 2, _);
var c = bind(b, 3);
print(b(4));
print(c());
def concat(a,b,c,d)
{
return to_string(a) + to_string(b) + to_string(c) + to_string(d);
}
var d = bind(concat, _, " Hello ", _, " World ");
print(d(1, 3));
//This checks to make sure arity is handled correctly:
//print(d(1, 3, 4));

View File

@@ -1,3 +1,2 @@
var i = 1
var j = eval("5 + 4")
print(j)

View File

@@ -1,7 +1,7 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009, Jonathan Turner (jturner@minnow-lang.org)
// and Jason Turner (lefticus@gmail.com)
// Copyright 2009-2010, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#include <iostream>
@@ -27,12 +27,12 @@ void bound_log(const std::string &msg)
log(msg);
}
void hello_world(const chaiscript::Boxed_Value &o)
void hello_world(const chaiscript::Boxed_Value & /*o*/)
{
std::cout << "Hello World" << std::endl;
}
void hello_constructor(const chaiscript::Boxed_Value &o)
void hello_constructor(const chaiscript::Boxed_Value & /*o*/)
{
std::cout << "Hello Constructor" << std::endl;
}
@@ -45,7 +45,7 @@ struct System
void add_callback(const std::string &t_name,
const chaiscript::Proxy_Function &t_func)
{
m_callbacks[t_name] = chaiscript::functor<std::string (const std::string &)>(t_func);
m_callbacks[t_name] = chaiscript::dispatch::functor<std::string (const std::string &)>(t_func);
}
@@ -66,7 +66,7 @@ void take_shared_ptr(const boost::shared_ptr<const std::string> &p)
std::cout << *p << std::endl;
}
int main(int argc, char *argv[]) {
int main(int /*argc*/, char * /*argv*/[]) {
using namespace chaiscript;
ChaiScript chai;
@@ -115,7 +115,7 @@ int main(int argc, char *argv[]) {
//Call bound version of do_callbacks
chai("do_callbacks()");
boost::function<void ()> caller = chai.functor<void ()>("fun() { system.do_callbacks(\"From Functor\"); }");
boost::function<void ()> caller = chai.eval<boost::function<void ()> >("fun() { system.do_callbacks(\"From Functor\"); }");
caller();
@@ -139,12 +139,12 @@ int main(int argc, char *argv[]) {
//To do: Add examples of handling Boxed_Values directly when needed
//Creating a functor on the stack and using it immediatly
int x = chai.functor<int (int, int)>("fun (x, y) { return x + y; }")(5, 6);
int x = chai.eval<boost::function<int (int, int)> >("fun (x, y) { return x + y; }")(5, 6);
log("Functor test output", boost::lexical_cast<std::string>(x));
chai.add(var(boost::shared_ptr<int>()), "nullvar");
chai("print(\"This should be true.\"); print(nullvar.is_null())");
chai("print(\"This should be true.\"); print(nullvar.is_var_null())");
// test the global const action
chai.add_global_const(const_var(1), "constvar");
@@ -154,7 +154,7 @@ int main(int argc, char *argv[]) {
//Ability to create our own container types when needed. std::vector and std::map are
//mostly supported currently
chai.add(bootstrap::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
@@ -163,13 +163,13 @@ int main(int argc, char *argv[]) {
chai.add(fun(&bound_log, std::string("Msg")), "BoundFun");
//Dynamic objects test
chai.add(chaiscript::Proxy_Function(new Dynamic_Object_Function("TestType", fun(&hello_world))), "hello_world");
chai.add(chaiscript::Proxy_Function(new Dynamic_Object_Constructor("TestType", fun(&hello_constructor))), "TestType");
chai.add(fun(boost::function<Boxed_Value (Dynamic_Object &)>(boost::bind(&Dynamic_Object_Attribute::func, "TestType", "attr", _1))), "attr");
chai.add(chaiscript::Proxy_Function(new dispatch::detail::Dynamic_Object_Function("TestType", fun(&hello_world))), "hello_world");
chai.add(chaiscript::Proxy_Function(new dispatch::detail::Dynamic_Object_Constructor("TestType", fun(&hello_constructor))), "TestType");
chai.add(fun(boost::function<Boxed_Value (dispatch::Dynamic_Object &)>(boost::bind(&dispatch::detail::Dynamic_Object_Attribute::func, "TestType", "attr", _1))), "attr");
chai.eval("var x = TestType()");
chai.eval("x.attr = \"hi\"");
chai.eval("print(x.attr)");
// chai.eval("x.attr = \"hi\"");
// chai.eval("print(x.attr)");
chai.eval("x.hello_world()");
}

View File

@@ -2,11 +2,11 @@ for (var i = 0; i < 10; ++i) {
print(i)
}
for (i = 10; i >= 0; i -= 2) {
for (var i = 10; i >= 0; i -= 2) {
print(i)
}
i = 0
var i = 0
for (; i < 5; ++i) {
print(i)

View File

@@ -0,0 +1,88 @@
#include <iostream>
#include "chaiscript/chaiscript.hpp"
#ifdef READLINE_AVAILABLE
#include <readline/readline.h>
#include <readline/history.h>
#endif
using namespace chaiscript;
std::string get_next_command() {
#ifdef READLINE_AVAILABLE
char *input_raw;
input_raw = readline("eval> ");
add_history(input_raw);
return std::string(input_raw);
#else
std::string retval;
std::cout << "eval> ";
std::getline(std::cin, retval);
return retval;
#endif
}
void fuction(void)
{
// do nothing
}
class test
{
ChaiScript chai;
ChaiScript::State backupState;
public:
test()
{
backupState = chai.get_state();
}
~test(){}
void ResetState()
{
chai.set_state(backupState);
chai.add(fun(&fuction),"Whatever()");
}
void RunFile(std::string sFile)
{
try {
chaiscript::Boxed_Value val = chai.eval_file(sFile);
}
catch (std::exception &e) {
std::cout << e.what() << std::endl;
}
}
};
int main(int /*argc*/, char * /*argv*/[]) {
test myChai;
std::string command = "";
//
// this loop increases memoryusage, if RunFile is not called (just hittin enter)
// as soon RunFile gets called, memory will be freed.
//
// scenario1 - RunFile gets called every Loop: memoryusage does not change
// scenario2 - RunFile gets never called (just hitting enter): memoryusage increases every loop
// scenario3 - RunFile gets in changing intervals: memoryusage goes up and down, but never as
// low as in case 1 scenario3 :
while(command != "quit")
{
for(int i = 1; i < 200; i++)
myChai.ResetState();
if(command == "runfile")
myChai.RunFile("Test.chai");
command = get_next_command();
}
}

View File

@@ -1,70 +0,0 @@
def initialize_cpu_sensor(state, cpuname, sensor_manager)
{
state[cpuname] = 0.0;
state[cpuname + ".user"] = 0.0;
state[cpuname + ".nice"] = 0.0;
state[cpuname + ".system"] = 0.0;
state[cpuname + ".idle"] = 0.0;
state[cpuname + ".iowait"] = 0.0;
state[cpuname + ".irq"] = 0.0;
state[cpuname + ".softirq"] = 0.0;
}
def update_cpu_state(state, statfile, cpuname)
{
var regex = cpuname + "\\s+([0-9]+)\\s+([0-9]+)\\s+([0-9]+)\\s+([0-9]+)\\s+([0-9]+)\\s+([0-9]+)\\s+([0-9]+)";
var strs = regex_search(statfile, regex);
var user = to_double(strs[1]);
var nice = to_double(strs[2]);
var system = to_double(strs[3]);
var idle = to_double(strs[4]);
var iowait = to_double(strs[5]);
var irq = to_double(strs[6]);
var softirq = to_double(strs[7]);
var userd = user - state[cpuname + ".user"];
var niced = nice - state[cpuname + ".nice"];
var systemd = system - state[cpuname + ".system"];
var idled = idle - state[cpuname + ".idle"];
var iowaitd = iowait - state[cpuname + ".iowait"];
var irqd = irq - state[cpuname + ".irq"];
var softirqd = softirq - state[cpuname + ".softirq"];
var totalticks = userd + niced + systemd + idled + iowaitd + irqd + softirqd;
state[cpuname] = (totalticks - idled) / totalticks
state[cpuname + ".user"] = user;
state[cpuname + ".nice"] = nice;
state[cpuname + ".system"] = system;
state[cpuname + ".idle"] = idle;
state[cpuname + ".iowait"] = iowait;
state[cpuname + ".irq"] = irq;
state[cpuname + ".softirq"] = softirq;
}
# annotation
def update_state(state)
{
var file = load_text_file("/proc/stat");
update_cpu_state(state, file, "cpu");
update_cpu_state(state, file, "cpu0");
update_cpu_state(state, file, "cpu1");
}
//dump_system()
var global_state = Map()
initialize_cpu_sensor(global_state, "cpu", sensor_manager);
initialize_cpu_sensor(global_state, "cpu0", sensor_manager);
initialize_cpu_sensor(global_state, "cpu1", sensor_manager);
sensor_manager.add_sensor("cpu", 500, global_state, fun(state) { update_state(state); state["cpu"]; } )
sensor_manager.add_sensor("cpu0", 500, global_state, fun(state) { state["cpu0"]; } )
sensor_manager.add_sensor("cpu1", 500, global_state, fun(state) { state["cpu1"]; } )

View File

@@ -1,93 +1,243 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009, Jonathan Turner (jturner@minnow-lang.org)
// and Jason Turner (lefticus@gmail.com)
// Copyright 2009-2010, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#include <iostream>
#include <list>
#include <boost/algorithm/string/trim.hpp>
#define _CRT_SECURE_NO_WARNINGS
#include <chaiscript/chaiscript.hpp>
#ifdef READLINE_AVAILABLE
#include <readline/readline.h>
#include <readline/history.h>
#else
char* readline(const char* p)
{
std::string retval;
std::cout << p ;
std::getline(std::cin, retval);
#ifdef BOOST_MSVC
return std::cin.eof() ? NULL : _strdup(retval.c_str());
#else
return std::cin.eof() ? NULL : strdup(retval.c_str());
#endif
}
void add_history(const char*){}
void using_history(){}
#endif
#include <chaiscript/chaiscript.hpp>
void print_help() {
void help(int n) {
if ( n >= 0 ) {
std::cout << "ChaiScript evaluator. To evaluate an expression, type it and press <enter>." << std::endl;
std::cout << "Additionally, you can inspect the runtime system using:" << std::endl;
std::cout << " dump_system() - outputs all functions registered to the system" << std::endl;
std::cout << " dump_object(x) - dumps information about the given symbol" << std::endl;
} else {
std::cout << "usage : chai [option]+" << std::endl;
std::cout << "option:" << std::endl;
std::cout << " -h | --help" << std::endl;
std::cout << " -i | --interactive" << std::endl;
std::cout << " -c | --command cmd" << std::endl;
std::cout << " -v | --version" << std::endl;
std::cout << " - --stdin" << std::endl;
std::cout << " filepath" << std::endl;
}
}
void version(int){
std::cout << "chai: compiled " << __TIME__ << " " << __DATE__ << std::endl;
}
bool throws_exception(const boost::function<void ()> &f)
{
try {
f();
} catch (...) {
return true;
}
return false;
}
chaiscript::exception::eval_error get_eval_error(const boost::function<void ()> &f)
{
try {
f();
} catch (const chaiscript::exception::eval_error &e) {
return e;
}
throw std::runtime_error("no exception throw");
}
std::string get_next_command() {
#ifdef READLINE_AVAILABLE
char *input_raw;
input_raw = readline("eval> ");
add_history(input_raw);
return std::string(input_raw);
#else
std::string retval;
std::cout << "eval> ";
std::getline(std::cin, retval);
return retval;
#endif
std::string retval("quit");
if ( ! std::cin.eof() ) {
char *input_raw = readline("eval> ");
if ( input_raw ) {
add_history(input_raw);
retval = boost::trim_copy_if(std::string(input_raw),boost::is_any_of(" \t"));
::free(input_raw);
}
}
if( retval == "quit"
|| retval == "exit"
|| retval == "help"
|| retval == "version")
{
retval += "(0)";
}
return retval;
}
int main(int argc, char *argv[]) {
std::string input;
chaiscript::ChaiScript chai;
if (argc < 2) {
//std::cout << "eval> ";
//std::getline(std::cin, input);
#ifdef READLINE_AVAILABLE
using_history();
#endif
input = get_next_command();
while (input != "quit") {
chaiscript::Boxed_Value val;
if (input == "help") {
print_help();
}
else {
try {
//First, we evaluate it
val = chai.eval(input);
//Then, we try to print the result of the evaluation to the user
if (!val.get_type_info().bare_equal(chaiscript::user_type<void>())) {
try {
chaiscript::dispatch(chai.get_eval_engine().get_function("print"), chaiscript::Param_List_Builder() << val);
}
catch (...) {
//If we can't, do nothing
}
}
}
catch (std::exception &e) {
std::cout << e.what() << std::endl;
}
}
input = get_next_command();
}
}
else {
for (int i = 1; i < argc; ++i) {
std::string filename(argv[i]);
try {
chaiscript::Boxed_Value val = chai.eval_file(argv[i]);
}
catch (std::exception &e) {
std::cout << e.what() << std::endl;
}
}
}
// We have to wrap exit with our own because Clang has a hard time with
// function pointers to functions with special attributes (system exit being marked NORETURN)
void myexit(int return_val) {
exit(return_val);
}
void interactive(chaiscript::ChaiScript& chai)
{
using_history();
for (;;) {
std::string input = get_next_command();
try {
// evaluate input
chaiscript::Boxed_Value val = chai.eval(input);
//Then, we try to print the result of the evaluation to the user
if (!val.get_type_info().bare_equal(chaiscript::user_type<void>())) {
try {
std::cout << chai.eval<boost::function<std::string (const chaiscript::Boxed_Value &bv)> >("to_string")(val) << std::endl;
}
catch (...) {} //If we can't, do nothing
}
}
catch (const chaiscript::exception::eval_error &ee) {
std::cout << ee.what();
if (ee.call_stack.size() > 0) {
std::cout << "during evaluation at (" << ee.call_stack[0]->start.line << ", " << ee.call_stack[0]->start.column << ")";
}
std::cout << std::endl;
}
catch (const std::exception &e) {
std::cout << e.what();
std::cout << std::endl;
}
}
}
int main(int argc, char *argv[])
{
std::vector<std::string> usepaths;
std::vector<std::string> modulepaths;
// Disable deprecation warning for getenv call.
#ifdef BOOST_MSVC
#pragma warning(push)
#pragma warning(disable : 4996)
#endif
const char *usepath = getenv("CHAI_USE_PATH");
const char *modulepath = getenv("CHAI_MODULE_PATH");
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif
usepaths.push_back("");
if (usepath)
{
usepaths.push_back(usepath);
}
modulepaths.push_back("");
if (modulepath)
{
modulepaths.push_back(modulepath);
}
chaiscript::ChaiScript chai(modulepaths,usepaths);
chai.add(chaiscript::fun(&myexit), "exit");
chai.add(chaiscript::fun(&myexit), "quit");
chai.add(chaiscript::fun(&help), "help");
chai.add(chaiscript::fun(&version), "version");
chai.add(chaiscript::fun(&throws_exception), "throws_exception");
chai.add(chaiscript::fun(&get_eval_error), "get_eval_error");
for (int i = 0; i < argc; ++i) {
if ( i == 0 && argc > 1 ) {
++i;
}
std::string arg( i ? argv[i] : "--interactive" );
enum { eInteractive
, eCommand
, eFile
} mode = eCommand ;
if ( arg == "-c" || arg == "--command" ) {
if ( (i+1) >= argc ) {
std::cout << "insufficient input following " << arg << std::endl;
return EXIT_FAILURE;
} else {
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 = "version(0)" ;
} else if ( arg == "-h" || arg == "--help" ) {
arg = "help(-1)";
} else if ( arg == "-i" || arg == "--interactive" ) {
mode = eInteractive ;
} else if ( arg.find('-') == 0 ) {
std::cout << "unrecognised argument " << arg << std::endl;
return EXIT_FAILURE;
} else {
mode = eFile;
}
chaiscript::Boxed_Value val ;
try {
switch ( mode ) {
case eInteractive : interactive(chai); break;
case eCommand : val = chai.eval(arg); break;
case eFile : val = chai.eval_file(arg); break;
}
}
catch (const chaiscript::exception::eval_error &ee) {
std::cout << ee.what();
if (ee.call_stack.size() > 0) {
std::cout << "during evaluation at (" << *(ee.call_stack[0]->filename) << " " << ee.call_stack[0]->start.line << ", " << ee.call_stack[0]->start.column << ")";
for (size_t j = 1; j < ee.call_stack.size(); ++j) {
if (ee.call_stack[j]->identifier != chaiscript::AST_Node_Type::Block
&& ee.call_stack[j]->identifier != chaiscript::AST_Node_Type::File)
{
std::cout << std::endl;
std::cout << " from " << *(ee.call_stack[j]->filename) << " (" << ee.call_stack[j]->start.line << ", " << ee.call_stack[j]->start.column << ")";
}
}
}
std::cout << std::endl;
return EXIT_FAILURE;
}
catch (std::exception &e) {
std::cout << e.what() << std::endl;
return EXIT_FAILURE;
}
}
return EXIT_SUCCESS;
}

View File

@@ -1,7 +1,7 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009, Jonathan Turner (jturner@minnow-lang.org)
// and Jason Turner (lefticus@gmail.com)
// Copyright 2009-2010, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#include <iostream>
@@ -13,7 +13,9 @@
void do_work(chaiscript::ChaiScript &c)
{
// c("use(\"work.chai\"); do_chai_work(num_iterations);");
// c("use(\"work.chai\"); do_chai_work(num_iterations);");
std::string name = "MyVar" + boost::lexical_cast<std::string>(rand());
c.add(chaiscript::var(5), name);
c("use(\"work.chai\"); do_chai_work(10000);");
}

97
src/reflection.cpp Normal file
View File

@@ -0,0 +1,97 @@
#include <chaiscript/chaiscript.hpp>
#include <chaiscript/utility/utility.hpp>
#include <string>
// MSVC doesn't like that we are using C++ return types from our C declared module
// but this is the best way to do it for cross platform compatibility
#ifdef BOOST_MSVC
#pragma warning(push)
#pragma warning(disable : 4190)
#endif
bool has_parse_tree(const chaiscript::Const_Proxy_Function &t_pf)
{
boost::shared_ptr<const chaiscript::dispatch::Dynamic_Proxy_Function> pf
= boost::dynamic_pointer_cast<const chaiscript::dispatch::Dynamic_Proxy_Function>(t_pf);
if (pf)
{
return pf->get_parse_tree();
} else {
return false;
}
}
chaiscript::AST_NodePtr get_parse_tree(const chaiscript::Const_Proxy_Function &t_pf)
{
boost::shared_ptr<const chaiscript::dispatch::Dynamic_Proxy_Function> pf
= boost::dynamic_pointer_cast<const chaiscript::dispatch::Dynamic_Proxy_Function>(t_pf);
if (pf)
{
if (pf->get_parse_tree())
{
return pf->get_parse_tree();
} else {
throw std::runtime_error("Function does not have a parse tree");
}
} else {
throw std::runtime_error("Function does not have a parse tree");
}
}
CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_reflection()
{
chaiscript::ModulePtr m(new chaiscript::Module());
m->add(chaiscript::fun(&has_parse_tree), "has_parse_tree");
m->add(chaiscript::fun(&get_parse_tree), "get_parse_tree");
chaiscript::bootstrap::standard_library::vector_type<std::vector<boost::shared_ptr<chaiscript::AST_Node> > >("AST_NodeVector", m);
CHAISCRIPT_CLASS( m,
chaiscript::exception::eval_error,
,
((reason))
((call_stack))
);
CHAISCRIPT_CLASS( m,
chaiscript::File_Position,
(chaiscript::File_Position())
(chaiscript::File_Position(int,int)),
((line))
((column))
);
CHAISCRIPT_CLASS( m,
chaiscript::AST_Node,
,
((text))
((identifier))
((filename))
((start))
((end))
((internal_to_string))
((children))
((replace_child))
);
CHAISCRIPT_CLASS( m,
chaiscript::parser::ChaiScript_Parser,
(chaiscript::parser::ChaiScript_Parser ()),
((parse))
((ast))
);
return m;
}
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif

View File

@@ -1,9 +1,21 @@
#include <chaiscript/chaiscript.hpp>
#include <list>
#include <string>
// MSVC doesn't like that we are using C++ return types from our C declared module
// but this is the best way to do it for cross platform compatibility
#ifdef BOOST_MSVC
#pragma warning(push)
#pragma warning(disable : 4190)
#endif
CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_stl_extra()
{
return chaiscript::bootstrap::list_type<std::list<chaiscript::Boxed_Value> >("List");
return chaiscript::bootstrap::standard_library::list_type<std::list<chaiscript::Boxed_Value> >("List");
}
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif

View File

@@ -2,15 +2,60 @@
#include <chaiscript/chaiscript.hpp>
#include <string>
class TestBaseType
{
public:
TestBaseType() {}
TestBaseType(int) {}
virtual ~TestBaseType() {}
virtual int func() { return 0; }
};
class TestDerivedType : public TestBaseType
{
public:
virtual ~TestDerivedType() {}
virtual int func() { return 1; }
};
std::string hello_world()
{
return "Hello World";
}
CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_test()
// MSVC doesn't like that we are using C++ return types from our C declared module
// but this is the best way to do it for cross platform compatibility
#ifdef BOOST_MSVC
#pragma warning(push)
#pragma warning(disable : 4190)
#endif
CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_test_module()
{
chaiscript::ModulePtr m(new chaiscript::Module());
m->add(chaiscript::fun(hello_world), "hello_world");
m->add(chaiscript::user_type<TestBaseType>(), "TestBaseType");
m->add(chaiscript::user_type<TestDerivedType>(), "TestDerivedType");
m->add(chaiscript::constructor<TestBaseType ()>(), "TestBaseType");
// m->add(chaiscript::constructor<TestBaseType (int)>(), "TestBaseType");
m->add(chaiscript::constructor<TestBaseType (const TestBaseType &)>(), "TestBaseType");
m->add(chaiscript::constructor<TestDerivedType ()>(), "TestDerivedType");
m->add(chaiscript::constructor<TestDerivedType (const TestDerivedType &)>(), "TestDerivedType");
m->add(chaiscript::base_class<TestBaseType, TestDerivedType>());
m->add(chaiscript::fun(&TestBaseType::func), "func");
return m;
}
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif

View File

@@ -0,0 +1,2 @@
assert_throws("Mismatched types in equation, lhs is const.", fun() { 1 = 2 } );
assert_throws("Mismatched types in equation, lhs is const.", fun() { 1 + 2 = 2 } );

View File

@@ -1,2 +1,2 @@
var prod = bind(foldl, _, `*`, 1.0)
print(prod([3, 4, 5]))
assert_equal(60, prod([3, 4, 5]))

View File

@@ -1 +0,0 @@
60

34
unittests/bind2.chai Normal file
View File

@@ -0,0 +1,34 @@
def add(x, y)
{
return x + y;
}
assert_equal(2, add.get_arity());
var b = bind(add, 2, _);
assert_equal(1, b.get_arity());
var c = bind(b, 3);
assert_equal(0, c.get_arity());
assert_equal(6, b(4));
assert_equal(5, c());
def concat2(a,b,c,d)
{
return to_string(a) + to_string(b) + to_string(c) + to_string(d);
}
var d = bind(concat2, _, " Hello ", _, " World");
assert_equal(2, d.get_arity());
assert_equal("1 Hello 3 World", d(1,3));
var e = bind(`<`, _, 5);
var types = e.get_param_types();
assert_equal(2, types.size());
assert_equal(true, types[0].bare_equal(bool_type));

View File

@@ -1 +0,0 @@
hello

View File

@@ -1 +1 @@
print(!true)
assert_equal(false, !true)

View File

@@ -1 +0,0 @@
false

View File

@@ -0,0 +1,319 @@
#include <chaiscript/utility/utility.hpp>
using namespace chaiscript;
template<typename T>
void use(T){}
template<typename To>
bool run_test_type_conversion(const Boxed_Value &bv, bool expectedpass)
{
try {
To ret = chaiscript::boxed_cast<To>(bv);
use(ret);
} catch (const chaiscript::exception::bad_boxed_cast &/*e*/) {
if (expectedpass) {
// std::cerr << "Failure in run_test_type_conversion: " << e.what() << std::endl;
return false;
} else {
return true;
}
} catch (const std::exception &e) {
std::cerr << "Unexpected standard exception when attempting cast_conversion: " << e.what() << std::endl;
return false;
} catch (...) {
std::cerr << "Unexpected unknown exception when attempting cast_conversion." << std::endl;
return false;
}
if (expectedpass)
{
return true;
} else {
return false;
}
}
template<typename To>
bool test_type_conversion(const Boxed_Value &bv, bool expectedpass)
{
bool ret = run_test_type_conversion<To>(bv, expectedpass);
if (!ret)
{
std::cerr << "Error with type conversion test. From: "
<< (bv.is_const()?(std::string("const ")):(std::string())) << bv.get_type_info().name()
<< " To: "
<< (boost::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" << std::endl;
}
return ret;
}
template<typename Type>
bool do_test(const Boxed_Value &bv, bool T, bool ConstT, bool TRef, bool ConstTRef, bool TPtr, bool ConstTPtr, bool TPtrConst,
bool ConstTPtrConst, bool SharedPtrT, bool SharedConstPtrT,
bool ConstSharedPtrT, bool ConstSharedConstPtrT, bool ConstSharedPtrTRef, bool ConstSharedPtrTConstRef,
bool BoostRef, bool BoostConstRef, bool ConstBoostRef, bool ConstBoostConstRef,
bool ConstBoostRefRef, bool ConstBoostConstRefRef, bool Number,
bool ConstNumber, bool ConstNumberRef, bool TPtrConstRef, bool ConstTPtrConstRef)
{
bool passed = true;
passed &= test_type_conversion<Type>(bv, T);
passed &= test_type_conversion<const Type>(bv, ConstT);
passed &= test_type_conversion<Type &>(bv, TRef);
passed &= test_type_conversion<const Type &>(bv, ConstTRef);
passed &= test_type_conversion<Type *>(bv, TPtr);
passed &= test_type_conversion<const Type *>(bv, ConstTPtr);
passed &= test_type_conversion<Type * const>(bv, TPtrConst);
passed &= test_type_conversion<const Type * const>(bv, ConstTPtrConst);
passed &= test_type_conversion<boost::shared_ptr<Type> >(bv, SharedPtrT);
passed &= test_type_conversion<boost::shared_ptr<const Type> >(bv, SharedConstPtrT);
passed &= test_type_conversion<boost::shared_ptr<Type> &>(bv, false);
passed &= test_type_conversion<boost::shared_ptr<const Type> &>(bv, false);
passed &= test_type_conversion<const boost::shared_ptr<Type> >(bv, ConstSharedPtrT);
passed &= test_type_conversion<const boost::shared_ptr<const Type> >(bv, ConstSharedConstPtrT);
passed &= test_type_conversion<const boost::shared_ptr<Type> &>(bv, ConstSharedPtrTRef);
passed &= test_type_conversion<const boost::shared_ptr<const Type> &>(bv, ConstSharedPtrTConstRef);
passed &= test_type_conversion<boost::reference_wrapper<Type> >(bv, BoostRef);
passed &= test_type_conversion<boost::reference_wrapper<const Type> >(bv, BoostConstRef);
passed &= test_type_conversion<boost::reference_wrapper<Type> &>(bv, false);
passed &= test_type_conversion<boost::reference_wrapper<const Type> &>(bv, false);
passed &= test_type_conversion<const boost::reference_wrapper<Type> >(bv, ConstBoostRef);
passed &= test_type_conversion<const boost::reference_wrapper<const Type> >(bv, ConstBoostConstRef);
passed &= test_type_conversion<const boost::reference_wrapper<Type> &>(bv, ConstBoostRefRef);
passed &= test_type_conversion<const boost::reference_wrapper<const Type> &>(bv, ConstBoostConstRefRef);
passed &= test_type_conversion<Boxed_Number>(bv, Number);
passed &= test_type_conversion<const Boxed_Number>(bv, ConstNumber);
passed &= test_type_conversion<Boxed_Number &>(bv, false);
passed &= test_type_conversion<const Boxed_Number &>(bv, ConstNumberRef);
passed &= test_type_conversion<Boxed_Number *>(bv, false);
passed &= test_type_conversion<const Boxed_Number *>(bv, false);
passed &= test_type_conversion<Boxed_Number * const>(bv, false);
passed &= test_type_conversion<const Boxed_Number *const>(bv, false);
passed &= test_type_conversion<Type *&>(bv, false);
passed &= test_type_conversion<const Type *&>(bv, false);
passed &= test_type_conversion<Type * const&>(bv, TPtrConstRef);
passed &= test_type_conversion<const Type * const&>(bv, ConstTPtrConstRef);
passed &= test_type_conversion<Boxed_Value>(bv, true);
passed &= test_type_conversion<const Boxed_Value>(bv, true);
passed &= test_type_conversion<const Boxed_Value &>(bv, true);
return passed;
}
/** Tests intended for built int types **/
template<typename T>
bool built_in_type_test(const T &initial, bool ispod)
{
bool passed = true;
/** value tests **/
T i = T(initial);
passed &= do_test<T>(var(i), true, true, true, true, true,
true, true, true, true, true,
true, true, true, true, true,
true, true, true, true, true,
ispod && true, ispod && true, ispod && true, true, true);
passed &= do_test<T>(const_var(i), true, true, false, true, false,
true, false, true, false, true,
false, true, false, true, false,
true, false, true, false, true,
ispod && true, ispod && true, ispod && true, false, true);
passed &= do_test<T>(var(&i), true, true, true, true, true,
true, true, true, false, false,
false, false, false, false, true,
true, true, true, true, true,
ispod && true, ispod && true, ispod && true, true, true);
passed &= do_test<T>(const_var(&i), true, true, false, true, false,
true, false, true, false, false,
false, false, false, false, false,
true, false, true, false, true,
ispod && true, ispod && true, ispod && true, ispod && false, true);
passed &= do_test<T>(var(boost::ref(i)), true, true, true, true, true,
true, true, true, false, false,
false, false, false, false, true,
true, true, true, true, true,
ispod && true, ispod && true, ispod && true, true, true);
passed &= do_test<T>(var(boost::cref(i)), true, true, false, true, false,
true, false, true, false, false,
false, false, false, false, false,
true, false, true, false, true,
ispod && true, ispod && true, ispod && true, false, true);
/** Const Reference Variable tests */
// This reference will be copied on input, which is expected
const T &ir = i;
passed &= do_test<T>(var(i), true, true, true, true, true,
true, true, true, true, true,
true, true, true, true, true,
true, true, true, true, true,
ispod && true, ispod && true, ispod && true, true, true);
// But a pointer or reference to it should be necessarily const
passed &= do_test<T>(var(&ir), true, true, false, true, false,
true, false, true, false, false,
false, false, false, false, false,
true, false, true, false, true,
ispod && true, ispod && true, ispod && true, false, true);
passed &= do_test<T>(var(boost::ref(ir)), true, true, false, true, false,
true, false, true, false, false,
false, false, false, false, false,
true, false, true, false, true,
ispod && true, ispod && true, ispod && true, false, true);
// Make sure const of const works too
passed &= do_test<T>(const_var(&ir), true, true, false, true, false,
true, false, true, false, false,
false, false, false, false, false,
true, false, true, false, true,
ispod && true, ispod && true, ispod && true, false, true);
passed &= do_test<T>(const_var(boost::ref(ir)), true, true, false, true, false,
true, false, true, false, false,
false, false, false, false, false,
true, false, true, false, true,
ispod && true, ispod && true, ispod && true, false, true);
/** Const Reference Variable tests */
// This will always be seen as a const
const T*cip = &i;
passed &= do_test<T>(var(cip), true, true, false, true, false,
true, false, true, false, false,
false, false, false, false, false,
true, false, true, false, true,
ispod && true, ispod && true, ispod && true, false, true);
// make sure const of const works
passed &= do_test<T>(const_var(cip), true, true, false, true, false,
true, false, true, false, false,
false, false, false, false, false,
true, false, true, false, true,
ispod && true, ispod && true, ispod && true, false, true);
/** shared_ptr tests **/
boost::shared_ptr<T> ip(new T(initial));
passed &= do_test<T>(var(ip), true, true, true, true, true,
true, true, true, true, true,
true, true, true, true, true,
true, true, true, true, true,
ispod && true, ispod && true, ispod && true, true, true);
passed &= do_test<T>(const_var(ip), true, true, false, true, false,
true, false, true, false, true,
false, true, false, true, false,
true, false, true, false, true,
ispod && true, ispod && true, ispod && true, false, true);
/** const shared_ptr tests **/
boost::shared_ptr<const T> ipc(new T(initial));
passed &= do_test<T>(var(ipc), true, true, false, true, false,
true, false, true, false, true,
false, true, false, true, false,
true, false, true, false, true,
ispod && true, ispod && true, ispod && true, false, true);
// const of this should be the same, making sure it compiles
passed &= do_test<T>(const_var(ipc), true, true, false, true, false,
true, false, true, false, true,
false, true, false, true, false,
true, false, true, false, true,
ispod && true, ispod && true, ispod && true, false, true);
/** Double ptr tests **/
/*
T **doublep;
passed &= do_test<T*>(var(doublep), true, true, false, true, false,
true, false, true, false, true,
false, true, false, true, false,
true, false, true, false, true,
ispod && true, ispod && true, ispod && true, false, true);
*/
return passed;
}
template<typename T>
bool pointer_test(const T& default_value, const T& new_value)
{
T *p = new T(default_value);
// we store a pointer to a pointer, so we can get a pointer to a pointer
try {
T **result = boxed_cast<T **>(var(&p));
*(*result) = new_value;
if (p != (*result) ) {
std::cerr << "Pointer passed in different than one returned" << std::endl;
return false;
}
if (*p != *(*result) ) {
std::cerr << "Somehow dereferenced pointer values are not the same?" << std::endl;
return false;
}
return true;
} catch (const exception::bad_boxed_cast &) {
std::cerr << "Bad boxed cast performing ** to ** test" << std::endl;
return false;
} catch (...) {
std::cerr << "Unknown exception performing ** to ** test" << std::endl;
return false;
}
}
int main()
{
bool passed = true;
/*
bool T, bool ConstT, bool TRef, bool ConstTRef, bool TPtr,
bool ConstTPtr, bool TPtrConst, bool ConstTPtrConst, bool SharedPtrT, bool SharedConstPtrT,
bool ConstSharedPtrT, bool ConstSharedConstPtrT, bool ConstSharedPtrTRef, bool ConstSharedPtrTConstRef, bool BoostRef,
bool BoostConstRef, bool ConstBoostRef, bool ConstBoostConstRef, bool ConstBoostRefRef, bool ConstBoostConstRefRef,
bool Number, bool ConstNumber, bool ConstNumberRef
*/
passed &= built_in_type_test<int>(5, true);
passed &= built_in_type_test<double>(1.1, true);
passed &= built_in_type_test<char>('a', true);
passed &= built_in_type_test<uint8_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<std::string>("Hello World", false);
// storing a pointer
passed &= pointer_test<int>(1, 0);
if (passed)
{
return EXIT_SUCCESS;
} else {
return EXIT_FAILURE;
}
}

View File

@@ -4,4 +4,4 @@ while (i < 10) {
break
}
}
print(i)
assert_equal(5, i);

View File

@@ -1 +0,0 @@
5

View File

@@ -1 +1 @@
print('b')
assert_equal("b", to_string('b'))

View File

@@ -1 +0,0 @@
b

View File

@@ -0,0 +1,7 @@
assert_equal(true, 1.is_var_const());
assert_equal(false, 1.is_var_reference());
assert_equal(true, 1.is_var_pointer());
assert_equal(false, 1.is_var_null());
assert_equal(false, 1.is_var_undef());
var i;
assert_equal(true, i.is_var_undef());

View File

@@ -1 +1,3 @@
print(collate(1, 2))
var v = collate(1, 2)
assert_equal(1, v[0])
assert_equal(2, v[1])

View File

@@ -1 +0,0 @@
[1, 2]

View File

@@ -1 +1 @@
print(1 > 2)
assert_equal(false, 1 > 2);

View File

@@ -1 +0,0 @@
false

View File

@@ -1 +1 @@
print(1 < 2)
assert_equal(true, 1 < 2)

View File

@@ -1 +0,0 @@
true

View File

@@ -1 +1,5 @@
print(concat([1, 2], [3, 4]))
var v = concat([1, 2], [3, 4]);
assert_equal(4, v.size());
assert_equal(1, v[0]);
assert_equal(4, v[3]);

View File

@@ -1 +0,0 @@
[1, 2, 3, 4]

View File

@@ -0,0 +1,4 @@
//If the following succeeds, the test passes
"Hello World".for_each(fun(x) { print(x) } )

View File

@@ -1 +1 @@
print(3.5.to_string() + "bob")
assert_equal("3.5bob", 3.5.to_string() + "bob");

View File

@@ -1 +0,0 @@
3.5bob

View File

@@ -1 +1 @@
print(3.to_string + "bob")
assert_equal("3bob", 3.to_string + "bob")

View File

@@ -1 +0,0 @@
3bob

View File

@@ -1 +1 @@
print("3.5".to_double() + 3.3)
assert_equal(6.8, "3.5".to_double() + 3.3)

View File

@@ -1 +0,0 @@
6.7999999999999998

View File

@@ -1 +1 @@
print("4".to_int() + 4)
assert_equal(8, "4".to_int() + 4)

View File

@@ -1 +0,0 @@
8

View File

@@ -0,0 +1,11 @@
var a = [1,2,3, [4,5,6] ]
assert_equal(a[3][0], 4)
def Test::Test() { this.a = [1,2,3]; }
attr Test::a;
var t = Test();
assert_equal(t.a[0], 1)

Some files were not shown because too many files have changed in this diff Show More