Compare commits
153 Commits
Release-1.
...
Release-2.
Author | SHA1 | Date | |
---|---|---|---|
![]() |
799b3ef388 | ||
![]() |
fe6694297f | ||
![]() |
e77ec4b16a | ||
![]() |
f070575205 | ||
![]() |
43d0d6199a | ||
![]() |
65c5178549 | ||
![]() |
c928e2992b | ||
![]() |
7fef086cab | ||
![]() |
791fd242e7 | ||
![]() |
e81b71ccc7 | ||
![]() |
ef7a785214 | ||
![]() |
f431d479fc | ||
![]() |
e11eca406d | ||
![]() |
7efb65a5c2 | ||
![]() |
39339d769a | ||
![]() |
7ac9ea7249 | ||
![]() |
7080f5d681 | ||
![]() |
22d994009e | ||
![]() |
567f911093 | ||
![]() |
5c98a5d6e7 | ||
![]() |
856b682e72 | ||
![]() |
faaa964565 | ||
![]() |
d8213a4206 | ||
![]() |
3a4421a57c | ||
![]() |
31fec2202c | ||
![]() |
13178e55e1 | ||
![]() |
968da650b2 | ||
![]() |
fb5ba0be26 | ||
![]() |
39a2c39d90 | ||
![]() |
70047424f9 | ||
![]() |
2805af1ed2 | ||
![]() |
e5a29ede5f | ||
![]() |
0c0df2c982 | ||
![]() |
4457df9ff5 | ||
![]() |
e601de9d18 | ||
![]() |
37b2ac2056 | ||
![]() |
645cdddd70 | ||
![]() |
ac8462fb67 | ||
![]() |
636c55493c | ||
![]() |
e2a2c14c0d | ||
![]() |
c418644a5b | ||
![]() |
fbf8f53e04 | ||
![]() |
a0c6366479 | ||
![]() |
15ffbd200a | ||
![]() |
1c6b2725b3 | ||
![]() |
95c124ca35 | ||
![]() |
1bd73884b2 | ||
![]() |
d3e4af433e | ||
![]() |
9f65303370 | ||
![]() |
391eaa9e11 | ||
![]() |
ed11f48847 | ||
![]() |
9dddb49850 | ||
![]() |
cca477dae6 | ||
![]() |
07352a16a3 | ||
![]() |
e14931f389 | ||
![]() |
f4a680a582 | ||
![]() |
e6c6223c5b | ||
![]() |
cbc61d898c | ||
![]() |
3a37ceedb7 | ||
![]() |
1bc968e788 | ||
![]() |
fe5a935abd | ||
![]() |
4e5c972e66 | ||
![]() |
d946cb7e9d | ||
![]() |
18bfead387 | ||
![]() |
4c015d7e44 | ||
![]() |
1122f2c818 | ||
![]() |
d2d752ecd4 | ||
![]() |
a18c701866 | ||
![]() |
9871604a48 | ||
![]() |
b1d12fdc91 | ||
![]() |
24e717d532 | ||
![]() |
1568fedebd | ||
![]() |
c88578d537 | ||
![]() |
9827345213 | ||
![]() |
c51d14fb13 | ||
![]() |
480761c1f7 | ||
![]() |
12e909d9aa | ||
![]() |
b1e892487f | ||
![]() |
720eabcb16 | ||
![]() |
1fde71f3f4 | ||
![]() |
90f8b77171 | ||
![]() |
315d7521a7 | ||
![]() |
ff177b5eaf | ||
![]() |
46fd7e9a58 | ||
![]() |
edd274ccce | ||
![]() |
a5b2ec3006 | ||
![]() |
cd3c0d4fd7 | ||
![]() |
3bdd79a3fd | ||
![]() |
b04e01cda7 | ||
![]() |
bad5384c96 | ||
![]() |
443902f787 | ||
![]() |
d3cdd6959d | ||
![]() |
9762e15460 | ||
![]() |
33897e2c0f | ||
![]() |
9528e44b88 | ||
![]() |
03746e7606 | ||
![]() |
50eace16da | ||
![]() |
8241e46680 | ||
![]() |
160f64e9c2 | ||
![]() |
593c6c68ee | ||
![]() |
991753a492 | ||
![]() |
7cdd772f2b | ||
![]() |
c5f837fd19 | ||
![]() |
7c244d25b5 | ||
![]() |
18fc4d419f | ||
![]() |
813fa055a3 | ||
![]() |
6a47846b84 | ||
![]() |
b0041217b0 | ||
![]() |
fedcd28ecc | ||
![]() |
b17c6b9748 | ||
![]() |
204d379176 | ||
![]() |
a754ce9eb6 | ||
![]() |
99b5f46a9e | ||
![]() |
394d8c3bf6 | ||
![]() |
4bdbcf30ff | ||
![]() |
63de0fd33c | ||
![]() |
0fbb7c44bd | ||
![]() |
5092713876 | ||
![]() |
f369afed77 | ||
![]() |
f23f0edc70 | ||
![]() |
daee00da95 | ||
![]() |
e2cdac0406 | ||
![]() |
cc44ec99ba | ||
![]() |
1bf3b1ed37 | ||
![]() |
f7b530ebae | ||
![]() |
b185e2e792 | ||
![]() |
73ec2abd43 | ||
![]() |
cfee4c6bc1 | ||
![]() |
2d4b9c0d93 | ||
![]() |
f522d3697c | ||
![]() |
48e96b2f3b | ||
![]() |
798908f127 | ||
![]() |
7e3127549f | ||
![]() |
4713325877 | ||
![]() |
7cc6a3cab9 | ||
![]() |
cba5731576 | ||
![]() |
b3656c95f5 | ||
![]() |
e9539dfee2 | ||
![]() |
4b40812e26 | ||
![]() |
ef8cd1f591 | ||
![]() |
46cdb89921 | ||
![]() |
3094ff6e3b | ||
![]() |
4d42d6ff33 | ||
![]() |
a427d2c1a9 | ||
![]() |
efb7a8d453 | ||
![]() |
6c4872eae9 | ||
![]() |
ff639a267d | ||
![]() |
94e4b671f3 | ||
![]() |
096c8aab50 | ||
![]() |
89186a86c8 | ||
![]() |
c8c1c65e8c | ||
![]() |
c5e1d5fa20 | ||
![]() |
91011695f0 |
118
CMakeLists.txt
118
CMakeLists.txt
@@ -1,25 +1,113 @@
|
||||
cmake_minimum_required(VERSION 2.6)
|
||||
cmake_minimum_required(VERSION 2.8)
|
||||
|
||||
project(chaiscript)
|
||||
|
||||
SET (CMAKE_BUILD_TYPE gdb)
|
||||
SET (CMAKE_C_FLAGS_GDB " -Wall -ggdb")
|
||||
SET (CMAKE_CXX_FLAGS_GDB " -Wall -ggdb")
|
||||
list(APPEND CPACK_SOURCE_IGNORE_FILES "${CMAKE_CURRENT_BINARY_DIR}")
|
||||
list(APPEND CPACK_SOURCE_IGNORE_FILES "\\\\.svn")
|
||||
list(APPEND CPACK_SOURCE_IGNORE_FILES ".swp")
|
||||
list(APPEND CPACK_SOURCE_IGNORE_FILES ".*~")
|
||||
|
||||
#SET (CMAKE_BUILD_TYPE rel)
|
||||
#SET (CMAKE_C_FLAGS_REL " -Wall -O3")
|
||||
#SET (CMAKE_CXX_FLAGS_REL " -Wall -O3")
|
||||
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 2)
|
||||
set(CPACK_PACKAGE_VERSION_MINOR 3)
|
||||
set(CPACK_PACKAGE_VERSION_PATCH 3)
|
||||
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")
|
||||
|
||||
|
||||
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)
|
||||
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}")
|
||||
|
||||
#SET (CMAKE_C_FLAGS " -Wall -ggdb ${READLINE_FLAG}")
|
||||
#SET (CMAKE_CXX_FLAGS " -Wall -ggdb ${READLINE_FLAG}")
|
||||
|
||||
include_directories(include)
|
||||
|
||||
find_package(Boost 1.36.0)
|
||||
SET(Boost_ADDITIONAL_VERSIONS "1.43" "1.43.0" "1.42" "1.42.0" "1.41")
|
||||
SET(Boost_USE_MULTITHREADED ON)
|
||||
|
||||
find_package(Boost 1.36.0 COMPONENTS thread)
|
||||
|
||||
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 ${Boost_LIBRARIES})
|
||||
install(TARGETS chaiscript_eval DESTINATION ${CMAKE_CURRENT_SOURCE_DIR}/bin)
|
||||
else(Boost_FOUND)
|
||||
message(FATAL_ERROR "Can not find Boost")
|
||||
link_directories( ${Boost_LIBRARY_DIRS} )
|
||||
else()
|
||||
message(FATAL_ERROR "Can not find Boost")
|
||||
endif(Boost_FOUND)
|
||||
|
||||
if (CMAKE_HOST_UNIX)
|
||||
SET(DYNAMIC_LOADER "dl")
|
||||
endif(CMAKE_HOST_UNIX)
|
||||
|
||||
|
||||
include_directories(${Boost_INCLUDE_DIRS})
|
||||
add_executable(chai src/main.cpp)
|
||||
#add_executable(dispatchkit_test contrib/test/dispatchkit_test.cpp)
|
||||
target_link_libraries(chai ${DYNAMIC_LOADER} ${Boost_LIBRARIES} ${READLINE_LIB})
|
||||
|
||||
add_library(test_module MODULE src/test_module.cpp)
|
||||
target_link_libraries(test_module ${Boost_LIBRARIES})
|
||||
|
||||
add_library(stl_extra MODULE src/stl_extra.cpp)
|
||||
target_link_libraries(stl_extra ${Boost_LIBRARIES})
|
||||
|
||||
file(GLOB UNIT_TESTS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/unittests/ ${CMAKE_CURRENT_SOURCE_DIR}/unittests/*.chai)
|
||||
|
||||
IF(BUILD_TESTING)
|
||||
|
||||
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}/"
|
||||
)
|
||||
ENDIF(BUILD_TESTING)
|
||||
|
||||
install(TARGETS chai stl_extra test_module RUNTIME DESTINATION bin LIBRARY DESTINATION lib/chaiscript )
|
||||
install(DIRECTORY include/chaiscript DESTINATION include
|
||||
PATTERN "*.hpp"
|
||||
PATTERN "*/.svn*" EXCLUDE)
|
||||
install(DIRECTORY unittests DESTINATION share/chaiscript
|
||||
PATTERN "*.chai"
|
||||
PATTERN "*.inc"
|
||||
PATTERN "*/.svn*" EXCLUDE)
|
||||
install(DIRECTORY samples DESTINATION share/chaiscript
|
||||
PATTERN "*.chai"
|
||||
PATTERN "*/.svn*" EXCLUDE)
|
||||
|
||||
|
||||
|
@@ -1 +0,0 @@
|
||||
This is a placeholder
|
@@ -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
|
43
contrib/codeanalysis/analyzedata.sh
Executable file
43
contrib/codeanalysis/analyzedata.sh
Executable file
@@ -0,0 +1,43 @@
|
||||
|
||||
function analyze_data
|
||||
{
|
||||
echo -n "$1," >> $2
|
||||
awk 'END {printf "%s,", $1}' r$1-codesize.out >> $2
|
||||
awk '{printf "%s,", $1}' r$1-numunittests.out >> $2
|
||||
awk 'END {printf "%s,", $1}' r$1-unittestsoutput.out >> $2
|
||||
|
||||
awk '{printf "%s,", $1}' r$1-debugbinarysize.out >> $2
|
||||
awk 'NR>1{exit} 1 {printf "%s,", $2}' r$1-debugbuildtime.out >> $2
|
||||
awk 'NR>1{exit} 1 {printf "%s,", $2}' r$1-debugprofiletime.out >> $2
|
||||
|
||||
awk '{printf "%s,", $1}' r$1-releasebinarysize.out >> $2
|
||||
awk 'NR>1{exit} 1 {printf "%s,", $2}' r$1-releasebuildtime.out >> $2
|
||||
awk 'NR>1{exit} 1 {printf "%s,", $2}' r$1-releasemodulesbuildtime.out >> $2
|
||||
awk 'NR>1{exit} 1 {printf "%s,", $2}' r$1-releaseprofiletime.out >> $2
|
||||
awk 'NR>1{exit} 1 {printf "%s,", $2}' r$1-releaseunittestruntime.out >> $2
|
||||
|
||||
if [ -x r$1-threadfreebinarysize.out ]
|
||||
then
|
||||
awk '{printf "%s,", $1}' r$1-threadfreebinarysize.out >> $2
|
||||
awk 'NR>1{exit} 1 {printf "%s,", $2}' r$1-threadfreeprofiletime.out >> $2
|
||||
|
||||
awk 'NR>1{exit} 1 {printf "%s,", $2}' r$1-1threadruntime.out >> $2
|
||||
awk 'NR>1{exit} 1 {printf "%s,", $2}' r$1-2threadruntime.out >> $2
|
||||
awk 'NR>1{exit} 1 {printf "%s,", $2}' r$1-4threadruntime.out >> $2
|
||||
awk 'NR>1{exit} 1 {printf "%s,", $2}' r$1-8threadruntime.out >> $2
|
||||
else
|
||||
echo -n ",,,,,," >> $2
|
||||
fi
|
||||
|
||||
awk -F "\n" 'NR>1{exit} 1 {printf "\"%s\"\n", $1}' r$1-revisionlog.out >> $2
|
||||
}
|
||||
|
||||
|
||||
filename=output-$1-$2.csv
|
||||
|
||||
echo "Revision, LOC, Num Unit Tests, Successful Unit Tests, Debug Binary Size, Debug Build Time, Debug Profile Time, Release Binary Size, Release Core Build Time, Release Modules Build Time, Release Profile Time, Release Unit Tests Time, Threadless Binary Size, Threadless Profile Time, 1 Thread Profile Time, 2 Threads Profile Time, 4 Threads Profile Time, 8 Threads Profile Time, Revision Log" > $filename
|
||||
|
||||
for i in `seq $1 $2`
|
||||
do
|
||||
analyze_data $i $filename
|
||||
done
|
81
contrib/codeanalysis/codeanalysis.sh
Executable file
81
contrib/codeanalysis/codeanalysis.sh
Executable file
@@ -0,0 +1,81 @@
|
||||
|
||||
function run_test
|
||||
{
|
||||
echo "****Getting r$1 from SVN"
|
||||
svn export --quiet -r$1 http://chaiscript.googlecode.com/svn/trunk chaiscript-r$1
|
||||
|
||||
pushd chaiscript-r$1
|
||||
|
||||
echo "****Getting svn revision log"
|
||||
svn propget svn:log --revprop -r$1 http://chaiscript.googlecode.com/svn/trunk > ../r$1-revisionlog.out
|
||||
|
||||
echo "****Editing CMakeLists.txt to allow for build type switching"
|
||||
# Clean up CMakeLists.txt so that we can set the build type at configure time
|
||||
sed -i -e "s/SET (CMAKE_BUILD_TYPE.*//" CMakeLists.txt
|
||||
|
||||
echo "****Compiling Debug Build"
|
||||
cmake -D CMAKE_BUILD_TYPE=Debug CMakeLists.txt
|
||||
/usr/bin/time -p make chaiscript_eval 2> ../r$1-debugbuildtime.out
|
||||
|
||||
echo "****Analyzing Debug Build"
|
||||
/usr/bin/time -p ./chaiscript_eval ../profile.chai 2>../r$1-debugprofiletime.out
|
||||
ls -s --block-size=1 ./chaiscript_eval > ../r$1-debugbinarysize.out
|
||||
|
||||
make clean
|
||||
|
||||
echo "****Compiling Release Build"
|
||||
cmake -D CMAKE_BUILD_TYPE=Release CMakeLists.txt
|
||||
/usr/bin/time -p make chaiscript_eval 2> ../r$1-releasebuildtime.out
|
||||
|
||||
echo "****Analyzing Release Build"
|
||||
/usr/bin/time -p ./chaiscript_eval ../profile.chai 2>../r$1-releaseprofiletime.out
|
||||
ls -s --block-size=1 ./chaiscript_eval > ../r$1-releasebinarysize.out
|
||||
|
||||
echo "****Analyzing Code Size"
|
||||
find ./include -name "*.hpp" | xargs wc > ../r$1-codesize.out
|
||||
|
||||
echo "****Building Remaining Modules"
|
||||
/usr/bin/time -p make 2> ../r$1-releasemodulesbuildtime.out
|
||||
|
||||
echo "****Running unit tests"
|
||||
/usr/bin/time -p ./run_unit_tests.sh 2> ../r$1-releaseunittestruntime.out > ../r$1-unittestsoutput.out
|
||||
|
||||
echo "****Counting number of unit tests"
|
||||
find unittests/ -name "*.chai" | wc | awk '{print $1}' > ../r$1-numunittests.out
|
||||
|
||||
|
||||
echo "****Running multithreaded tests"
|
||||
if [ -e src/multithreaded.cpp ]
|
||||
then
|
||||
# Run multithreaded tests
|
||||
echo "****Building multithreaded test"
|
||||
pushd src
|
||||
g++ multithreaded.cpp -lboost_thread-mt -ldl -omultithreaded -I../include -O3
|
||||
echo "****Testing 1 thread runtime"
|
||||
/usr/bin/time -p ./multithreaded 1 2> ../../r$1-1threadruntime.out
|
||||
echo "****Testing 2 thread runtime"
|
||||
/usr/bin/time -p ./multithreaded 1 1 2> ../../r$1-2threadruntime.out
|
||||
echo "****Testing 4 thread runtime"
|
||||
/usr/bin/time -p ./multithreaded 1 1 1 1 2> ../../r$1-4threadruntime.out
|
||||
echo "****Testing 8 thread runtime"
|
||||
/usr/bin/time -p ./multithreaded 1 1 1 1 1 1 1 1 2> ../../r$1-8threadruntime.out
|
||||
|
||||
|
||||
echo "****Compiling thread-free version"
|
||||
g++ main.cpp -ldl -othreadfree -I../include -O3 -DCHAISCRIPT_NO_THREADS
|
||||
echo "****Analyzing thread-free version"
|
||||
/usr/bin/time -p ./threadfree ../../profile.chai 2>../../r$1-threadfreeprofiletime.out
|
||||
ls -s --block-size=1 ./threadfree > ../../r$1-threadfreebinarysize.out
|
||||
|
||||
popd
|
||||
else
|
||||
echo "Multithreaded test non-existent"
|
||||
fi
|
||||
|
||||
popd
|
||||
}
|
||||
|
||||
for i in `seq $1 $2`
|
||||
do
|
||||
run_test $i
|
||||
done
|
15
contrib/codeanalysis/profile.chai
Normal file
15
contrib/codeanalysis/profile.chai
Normal file
@@ -0,0 +1,15 @@
|
||||
var total = 0
|
||||
|
||||
for (var i = 0.0; i < 10000.0; i += 0.1) {
|
||||
total += int(double(i) + int(10));
|
||||
if (i < 9000.0)
|
||||
{
|
||||
total += double(11);
|
||||
if (i > double(4000.0))
|
||||
{
|
||||
total += double(10);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
print(total)
|
136
contrib/geshi/chaiscript.php
Normal file
136
contrib/geshi/chaiscript.php
Normal 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 (lefticus@gmail.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
|
||||
)
|
||||
);
|
||||
|
||||
?>
|
7
contrib/vim/README.txt
Normal file
7
contrib/vim/README.txt
Normal 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
|
2
contrib/vim/ftdetect/chaiscript.vim
Normal file
2
contrib/vim/ftdetect/chaiscript.vim
Normal file
@@ -0,0 +1,2 @@
|
||||
au BufRead,BufNewFile *.chai set filetype=chaiscript
|
||||
|
50
contrib/vim/indent/chaiscript.vim
Normal file
50
contrib/vim/indent/chaiscript.vim
Normal 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
|
94
contrib/vim/syntax/chaiscript.vim
Normal file
94
contrib/vim/syntax/chaiscript.vim
Normal 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
1
description.txt
Normal 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.
|
@@ -1,6 +1,6 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009, Jonathan Turner (jturner@minnow-lang.org)
|
||||
// Copyright 2009-2010, Jonathan Turner (jturner@minnow-lang.org)
|
||||
// and Jason Turner (lefticus@gmail.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
@@ -21,114 +21,13 @@
|
||||
#include "dispatchkit/bootstrap.hpp"
|
||||
#include "dispatchkit/bootstrap_stl.hpp"
|
||||
#include "dispatchkit/function_call.hpp"
|
||||
namespace chaiscript
|
||||
{
|
||||
/**
|
||||
* Types of AST nodes available to the parser and eval
|
||||
*/
|
||||
class Token_Type { public: enum Type { Error, Int, Float, Id, Char, Str, Eol, Fun_Call, Arg_List, Variable, Equation, Var_Decl,
|
||||
Expression, Comparison, Additive, Multiplicative, Negate, Not, 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 }; };
|
||||
#include "dispatchkit/dynamic_object.hpp"
|
||||
|
||||
/**
|
||||
* 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", "Arg_List", "Variable", "Equation", "Var_Decl",
|
||||
"Expression", "Comparison", "Additive", "Multiplicative", "Negate", "Not", "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"};
|
||||
|
||||
return token_types[tokentype];
|
||||
}
|
||||
|
||||
/**
|
||||
* 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() : line(0), column(0) { }
|
||||
};
|
||||
|
||||
typedef boost::shared_ptr<struct Token> TokenPtr;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
std::vector<TokenPtr> children;
|
||||
TokenPtr annotation;
|
||||
|
||||
Token(const std::string &token_text, int id, const char *fname) : text(token_text), identifier(id), filename(fname) { }
|
||||
|
||||
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) {
|
||||
|
||||
start.line = start_line;
|
||||
start.column = start_col;
|
||||
end.line = end_line;
|
||||
end.column = end_col;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
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 &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) {
|
||||
}
|
||||
|
||||
virtual ~Eval_Error() throw() {}
|
||||
};
|
||||
|
||||
/**
|
||||
* 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) { }
|
||||
};
|
||||
|
||||
/**
|
||||
* Special type indicating a call to 'break'
|
||||
*/
|
||||
struct Break_Loop {
|
||||
TokenPtr location;
|
||||
|
||||
Break_Loop(const TokenPtr where) : location(where) { }
|
||||
};
|
||||
}
|
||||
#ifdef BOOST_HAS_DECLSPEC
|
||||
#define CHAISCRIPT_MODULE_EXPORT extern "C" __declspec(dllexport)
|
||||
#else
|
||||
#define CHAISCRIPT_MODULE_EXPORT extern "C"
|
||||
#endif
|
||||
|
||||
#include "language/chaiscript_eval.hpp"
|
||||
#include "language/chaiscript_engine.hpp"
|
||||
|
73
include/chaiscript/chaiscript_threading.hpp
Normal file
73
include/chaiscript/chaiscript_threading.hpp
Normal file
@@ -0,0 +1,73 @@
|
||||
#ifndef __chaiscript_threading_hpp__
|
||||
#define __chaiscript_threading_hpp__
|
||||
|
||||
#ifndef CHAISCRIPT_NO_THREADS
|
||||
#include <boost/thread.hpp>
|
||||
#else
|
||||
#pragma message ("ChaiScript is compiling without thread safety.")
|
||||
#endif
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
namespace threading
|
||||
{
|
||||
|
||||
#ifndef CHAISCRIPT_NO_THREADS
|
||||
|
||||
template<typename T>
|
||||
class Thread_Storage
|
||||
{
|
||||
public:
|
||||
~Thread_Storage()
|
||||
{
|
||||
m_thread_storage.reset();
|
||||
}
|
||||
|
||||
inline T *operator->() const
|
||||
{
|
||||
if (!m_thread_storage.get())
|
||||
{
|
||||
m_thread_storage.reset(new T());
|
||||
}
|
||||
|
||||
return m_thread_storage.get();
|
||||
}
|
||||
|
||||
inline T &operator*() const
|
||||
{
|
||||
return *(this->operator->());
|
||||
}
|
||||
|
||||
private:
|
||||
mutable boost::thread_specific_ptr<T> m_thread_storage;
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
template<typename T>
|
||||
class Thread_Storage
|
||||
{
|
||||
public:
|
||||
inline T *operator->() const
|
||||
{
|
||||
return &obj;
|
||||
}
|
||||
|
||||
inline T &operator*() const
|
||||
{
|
||||
return obj;
|
||||
}
|
||||
|
||||
private:
|
||||
mutable T obj;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
66
include/chaiscript/dispatchkit/bind_first.hpp
Normal file
66
include/chaiscript/dispatchkit/bind_first.hpp
Normal file
@@ -0,0 +1,66 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2010, Jonathan Turner (jturner@minnow-lang.org)
|
||||
// and Jason Turner (lefticus@gmail.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#include <boost/preprocessor.hpp>
|
||||
#include <boost/preprocessor/arithmetic/inc.hpp>
|
||||
|
||||
#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__
|
||||
|
||||
#include <boost/function.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/ref.hpp>
|
||||
|
||||
#define BOOST_PP_ITERATION_LIMITS ( 0, 8 )
|
||||
#define BOOST_PP_FILENAME_1 <chaiscript/dispatchkit/bind_first.hpp>
|
||||
|
||||
#include BOOST_PP_ITERATE()
|
||||
|
||||
|
||||
# endif
|
||||
#else
|
||||
# define n BOOST_PP_ITERATION()
|
||||
# define m BOOST_PP_INC(n)
|
||||
|
||||
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))>
|
||||
bind_first(Ret (Class::*f)(BOOST_PP_ENUM_PARAMS(n, Param)), const O &o)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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))>
|
||||
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))>
|
||||
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
|
@@ -1,6 +1,6 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009, Jonathan Turner (jturner@minnow-lang.org)
|
||||
// Copyright 2009-2010, Jonathan Turner (jturner@minnow-lang.org)
|
||||
// and Jason Turner (lefticus@gmail.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
@@ -8,7 +8,9 @@
|
||||
#define __bootstrap_hpp__
|
||||
|
||||
#include "dispatchkit.hpp"
|
||||
#include "dynamic_object.hpp"
|
||||
#include "register_function.hpp"
|
||||
#include "operators.hpp"
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
@@ -16,129 +18,6 @@ namespace chaiscript
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
/**
|
||||
* Set of helper functions for common operators
|
||||
*/
|
||||
template<typename Ret, typename P1, typename P2>
|
||||
Ret add(P1 p1, P2 p2)
|
||||
{
|
||||
return p1 + p2;
|
||||
}
|
||||
|
||||
template<typename Ret, typename P1, typename P2>
|
||||
Ret subtract(P1 p1, P2 p2)
|
||||
{
|
||||
return p1 - p2;
|
||||
}
|
||||
|
||||
template<typename Ret, typename P1, typename P2>
|
||||
Ret divide(P1 p1, P2 p2)
|
||||
{
|
||||
return p1 / p2;
|
||||
}
|
||||
|
||||
template<typename Ret, typename P1, typename P2>
|
||||
Ret multiply(P1 p1, P2 p2)
|
||||
{
|
||||
return p1 * p2;
|
||||
}
|
||||
|
||||
template<typename Ret, typename P1, typename P2>
|
||||
Ret modulus(P1 p1, P2 p2)
|
||||
{
|
||||
return p1 % p2;
|
||||
}
|
||||
|
||||
template<typename P1, typename P2>
|
||||
P1 &assign(P1 &p1, const P2 &p2)
|
||||
{
|
||||
return (p1 = p2);
|
||||
}
|
||||
|
||||
template<typename P1, typename P2>
|
||||
bool equals(P1 p1, P2 p2)
|
||||
{
|
||||
return p1 == p2;
|
||||
}
|
||||
|
||||
template<typename P1, typename P2>
|
||||
bool not_equals(P1 p1, P2 p2)
|
||||
{
|
||||
return p1 != p2;
|
||||
}
|
||||
|
||||
|
||||
template<typename P1, typename P2>
|
||||
bool less_than(P1 p1, P2 p2)
|
||||
{
|
||||
return p1 < p2;
|
||||
}
|
||||
|
||||
template<typename P1, typename P2>
|
||||
bool greater_than(P1 p1, P2 p2)
|
||||
{
|
||||
return p1 > p2;
|
||||
}
|
||||
|
||||
template<typename P1, typename P2>
|
||||
bool less_than_equals(P1 p1, P2 p2)
|
||||
{
|
||||
return p1 <= p2;
|
||||
}
|
||||
|
||||
template<typename P1, typename P2>
|
||||
bool greater_than_equals(P1 p1, P2 p2)
|
||||
{
|
||||
return p1 >= p2;
|
||||
}
|
||||
|
||||
template<typename P1, typename P2>
|
||||
P1 ×equal(P1 &p1, const P2 &p2)
|
||||
{
|
||||
return (p1 *= p2);
|
||||
}
|
||||
|
||||
template<typename P1, typename P2>
|
||||
P1 ÷sequal(P1 &p1, const P2 &p2)
|
||||
{
|
||||
return (p1 /= p2);
|
||||
}
|
||||
|
||||
template<typename P1, typename P2>
|
||||
P1 &addsequal(P1 &p1, const P2 &p2)
|
||||
{
|
||||
return (p1 += p2);
|
||||
}
|
||||
|
||||
template<typename P1, typename P2>
|
||||
P1 &subtractsequal(P1 &p1, const P2 &p2)
|
||||
{
|
||||
return (p1 -= p2);
|
||||
}
|
||||
|
||||
template<typename P1>
|
||||
P1 &prefixincrement(P1 &p1)
|
||||
{
|
||||
return (++p1);
|
||||
}
|
||||
|
||||
template<typename P1>
|
||||
P1 &prefixdecrement(P1 &p1)
|
||||
{
|
||||
return (--p1);
|
||||
}
|
||||
|
||||
template<typename P1>
|
||||
P1 &prefixnegate(P1 &p1)
|
||||
{
|
||||
return (p1);
|
||||
}
|
||||
|
||||
template<typename P1>
|
||||
P1 &prefixnot(P1 &p1)
|
||||
{
|
||||
return (p1);
|
||||
}
|
||||
|
||||
/* Special helpers for generating generic "POD" type operators
|
||||
* The POD operators are needed for general support of C++ POD
|
||||
@@ -149,6 +28,7 @@ namespace chaiscript
|
||||
template<typename P1>
|
||||
P1 &assign_pod(P1 &p1, Boxed_POD_Value v)
|
||||
{
|
||||
|
||||
if (v.m_isfloat)
|
||||
{
|
||||
return (p1 = P1(v.d));
|
||||
@@ -169,7 +49,63 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
template<typename P1>
|
||||
P1 ×equal_pod(P1 &p1, Boxed_POD_Value r)
|
||||
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)
|
||||
{
|
||||
@@ -180,7 +116,7 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
template<typename P1>
|
||||
P1 ÷sequal_pod(P1 &p1, Boxed_POD_Value r)
|
||||
P1 &assign_quotient_pod(P1 &p1, Boxed_POD_Value r)
|
||||
{
|
||||
if (r.m_isfloat)
|
||||
{
|
||||
@@ -191,7 +127,31 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
template<typename P1>
|
||||
P1 &addsequal_pod(P1 &p1, Boxed_POD_Value r)
|
||||
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)
|
||||
{
|
||||
@@ -201,223 +161,66 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
template<typename P1>
|
||||
P1 &subtractsequal_pod(P1 &p1, Boxed_POD_Value r)
|
||||
{
|
||||
if (r.m_isfloat)
|
||||
{
|
||||
return p1 -= P1(r.d);
|
||||
} else {
|
||||
return p1 -= P1(r.i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add canonical form of "=" for type T
|
||||
*/
|
||||
template<typename T>
|
||||
ModulePtr oper_equals(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&detail::equals<const T&, const T&>), "=");
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add canonical form of "+" for type T
|
||||
*/
|
||||
template<typename T>
|
||||
ModulePtr oper_add(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&detail::add<T, const T&, const T&>), "+");
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add canonical form of "+=" for type T
|
||||
*/
|
||||
template<typename T>
|
||||
ModulePtr oper_add_equals(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&detail::addsequal<T, T>), "+=");
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add canonical form of "-" for type T
|
||||
*/
|
||||
template<typename T>
|
||||
ModulePtr oper_subtract(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&detail::subtract<T, const T&, const T&>), "-");
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add canonical form of "/" for type T
|
||||
*/
|
||||
template<typename T>
|
||||
ModulePtr oper_divide(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&detail::divide<T, const T&, const T&>), "/");
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add canonical form of "*" for type T
|
||||
*/
|
||||
template<typename T>
|
||||
ModulePtr oper_multiply(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&detail::multiply<T, const T&, const T&>), "*");
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add canonical form of "!=" for type T
|
||||
*/
|
||||
template<typename T>
|
||||
ModulePtr oper_not_equals(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&detail::not_equals<const T&, const T&>), "!=");
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add user defined assignment operator for T = U
|
||||
*/
|
||||
template<typename T, typename U>
|
||||
ModulePtr oper_assign_overload(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&detail::assign<T,U>), "=");
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add canonical form of "=" for type T
|
||||
*/
|
||||
template<typename T>
|
||||
ModulePtr oper_assign(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&detail::assign<T,T>), "=");
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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 canonical form of "<" for type T
|
||||
*/
|
||||
template<typename T>
|
||||
ModulePtr oper_less_than(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&detail::less_than<const T&, const T&>), "<");
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add canonical form of ">" for type T
|
||||
*/
|
||||
template<typename T>
|
||||
ModulePtr oper_greater_than(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&detail::greater_than<const T&, const T&>), ">");
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add canonical form of "<=" for type T
|
||||
*/
|
||||
template<typename T>
|
||||
ModulePtr oper_less_than_equals(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&detail::less_than_equals<const T&, const T&>), "<=");
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add canonical form of ">=" for type T
|
||||
*/
|
||||
template<typename T>
|
||||
ModulePtr oper_greater_than_equals(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&detail::greater_than_equals<const T&, const T&>), ">=");
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add user defined comparison operators for T and R.
|
||||
* Examples: T < R, T == R, etc.
|
||||
*/
|
||||
template<typename T, typename R>
|
||||
ModulePtr opers_comparison_overload(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&detail::equals<const T&, const R&>), "==");
|
||||
m->add(fun(&detail::not_equals<const T&, const R&>), "!=");
|
||||
m->add(fun(&detail::less_than<const T&, const R&>), "<");
|
||||
m->add(fun(&detail::greater_than<const T&, const R&>), ">");
|
||||
m->add(fun(&detail::less_than_equals<const T&, const R&>), "<=");
|
||||
m->add(fun(&detail::greater_than_equals<const T&, const R&>), ">=");
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add canonical forms of all comparison operators for type T
|
||||
*/
|
||||
template<typename T>
|
||||
ModulePtr opers_comparison(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
opers_comparison_overload<T, T>(m);
|
||||
operators::equal<T>(m);
|
||||
operators::greater_than<T>(m);
|
||||
operators::greater_than_equal<T>(m);
|
||||
operators::less_than<T>(m);
|
||||
operators::less_than_equal<T>(m);
|
||||
operators::not_equal<T>(m);
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add all arithmetic operators that return a type of Ret, taking
|
||||
* a lhs of T and a rhs of R, when possible.
|
||||
* examples: Ret = T + R;
|
||||
* ++T
|
||||
* T *= R;
|
||||
*/
|
||||
template<typename Ret, typename T, typename R>
|
||||
ModulePtr opers_arithmetic_overload(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&detail::add<Ret, T, R>), "+");
|
||||
m->add(fun(&detail::subtract<Ret, T, R>), "-");
|
||||
m->add(fun(&detail::divide<Ret, T, R>), "/");
|
||||
m->add(fun(&detail::multiply<Ret, T, R>), "*");
|
||||
m->add(fun(&detail::timesequal<T, R>), "*=");
|
||||
m->add(fun(&detail::dividesequal<T, R>), "/=");
|
||||
m->add(fun(&detail::subtractsequal<T, R>), "-=");
|
||||
m->add(fun(&detail::addsequal<T, R>), "+=");
|
||||
m->add(fun(&detail::prefixincrement<T>), "++");
|
||||
m->add(fun(&detail::prefixdecrement<T>), "--");
|
||||
m->add(fun(&detail::prefixnegate<T>), "-");
|
||||
m->add(fun(&detail::prefixnot<T>), "!");
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add arithmetic assign operators for POD types:
|
||||
* example: POD *= T, POD /= T
|
||||
*/
|
||||
template<typename T>
|
||||
ModulePtr opers_arithmetic_modify_pod(ModulePtr m = ModulePtr(new Module()))
|
||||
ModulePtr opers_integer_arithmetic(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&detail::timesequal_pod<T>), "*=");
|
||||
m->add(fun(&detail::dividesequal_pod<T>), "/=");
|
||||
m->add(fun(&detail::subtractsequal_pod<T>), "-=");
|
||||
m->add(fun(&detail::addsequal_pod<T>), "+=");
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -463,16 +266,6 @@ namespace chaiscript
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add canonical forms of all arithmetic operators for type T
|
||||
*/
|
||||
template<typename T>
|
||||
ModulePtr opers_arithmetic(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
opers_arithmetic_overload<T, T, T>(m);
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* to_string function for internal use. Uses ostream operator<<
|
||||
*/
|
||||
@@ -482,18 +275,6 @@ namespace chaiscript
|
||||
return boost::lexical_cast<std::string>(i);
|
||||
}
|
||||
|
||||
/**
|
||||
* Boolean specialization of internal to_string function
|
||||
*/
|
||||
template<> std::string to_string(bool b)
|
||||
{
|
||||
if (b)
|
||||
{
|
||||
return "true";
|
||||
} else {
|
||||
return "false";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal function for converting from a string to a value
|
||||
@@ -505,6 +286,17 @@ namespace chaiscript
|
||||
return boost::lexical_cast<Input>(i);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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
|
||||
* common conversions
|
||||
@@ -514,16 +306,52 @@ namespace chaiscript
|
||||
{
|
||||
m->add(user_type<T>(), name);
|
||||
basic_constructors<T>(name, m);
|
||||
oper_assign<T>(m);
|
||||
operators::assign<T>(m);
|
||||
oper_assign_pod<T>(m);
|
||||
construct_pod<T>(name, m);
|
||||
opers_arithmetic<T>(m);
|
||||
opers_arithmetic_modify_pod<T>(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
|
||||
* where you do not want to make a deep copy of an object during cloning
|
||||
@@ -532,22 +360,39 @@ namespace chaiscript
|
||||
* function variables.
|
||||
*/
|
||||
template<typename Type>
|
||||
boost::shared_ptr<Type> shared_ptr_clone(boost::shared_ptr<Type> f)
|
||||
boost::shared_ptr<Type> shared_ptr_clone(const boost::shared_ptr<Type> &p)
|
||||
{
|
||||
return f;
|
||||
return p;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specific version of shared_ptr_clone just for Proxy_Functions
|
||||
*/
|
||||
template<typename Type>
|
||||
boost::shared_ptr<typename boost::remove_const<Type>::type>
|
||||
shared_ptr_unconst_clone(const boost::shared_ptr<typename boost::add_const<Type>::type> &p)
|
||||
{
|
||||
return boost::const_pointer_cast<typename boost::remove_const<Type>::type>(p);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Assignment function for shared_ptr objects, does not perform a copy of the
|
||||
* object pointed to, instead maintains the shared_ptr concept.
|
||||
* Similar to shared_ptr_clone. Used for Proxy_Function.
|
||||
*/
|
||||
template<typename Type>
|
||||
Boxed_Value ptr_assign(Boxed_Value lhs, boost::shared_ptr<Type> rhs)
|
||||
Boxed_Value ptr_assign(Boxed_Value lhs, const boost::shared_ptr<typename boost::add_const<Type>::type> &rhs)
|
||||
{
|
||||
lhs.assign(Boxed_Value(rhs));
|
||||
|
||||
return lhs;
|
||||
if (lhs.is_undef()
|
||||
|| (!lhs.get_type_info().is_const() && lhs.get_type_info().bare_equal(chaiscript::detail::Get_Type_Info<Type>::get())))
|
||||
{
|
||||
lhs.assign(Boxed_Value(rhs));
|
||||
return lhs;
|
||||
} else {
|
||||
throw bad_boxed_cast("type mismatch in pointer assignment");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -562,7 +407,7 @@ namespace chaiscript
|
||||
*/
|
||||
static Boxed_Value unknown_assign(Boxed_Value lhs, Boxed_Value rhs)
|
||||
{
|
||||
if (lhs.is_unknown())
|
||||
if (lhs.is_undef())
|
||||
{
|
||||
return (lhs.assign(rhs));
|
||||
} else {
|
||||
@@ -580,28 +425,21 @@ namespace chaiscript
|
||||
std::cout << s << std::endl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add all comparison operators for POD types
|
||||
*/
|
||||
static void opers_comparison_pod(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&detail::equals<Boxed_POD_Value, Boxed_POD_Value>), "==");
|
||||
m->add(fun(&detail::not_equals<Boxed_POD_Value, Boxed_POD_Value>), "!=");
|
||||
m->add(fun(&detail::less_than<Boxed_POD_Value, Boxed_POD_Value>), "<");
|
||||
m->add(fun(&detail::greater_than<Boxed_POD_Value, Boxed_POD_Value>), ">");
|
||||
m->add(fun(&detail::less_than_equals<Boxed_POD_Value, Boxed_POD_Value>), "<=");
|
||||
m->add(fun(&detail::greater_than_equals<Boxed_POD_Value, Boxed_POD_Value>), ">=");
|
||||
}
|
||||
|
||||
/**
|
||||
* Add all arithmetic operators for PODs
|
||||
*/
|
||||
static void opers_arithmetic_pod(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&detail::add<Boxed_Value, Boxed_POD_Value, Boxed_POD_Value>), "+");
|
||||
m->add(fun(&detail::subtract<Boxed_Value, Boxed_POD_Value, Boxed_POD_Value>), "-");
|
||||
m->add(fun(&detail::divide<Boxed_Value, Boxed_POD_Value, Boxed_POD_Value>), "/");
|
||||
m->add(fun(&detail::multiply<Boxed_Value, Boxed_POD_Value, Boxed_POD_Value>), "*");
|
||||
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>), ">>");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -616,9 +454,9 @@ namespace chaiscript
|
||||
throw arity_error(params.size(), 2);
|
||||
}
|
||||
|
||||
Proxy_Function f = boxed_cast<Proxy_Function >(params[0]);
|
||||
Const_Proxy_Function f = boxed_cast<Const_Proxy_Function>(params[0]);
|
||||
|
||||
return Boxed_Value(Proxy_Function(new Bound_Function(f,
|
||||
return Boxed_Value(Const_Proxy_Function(new Bound_Function(f,
|
||||
std::vector<Boxed_Value>(params.begin() + 1, params.end()))));
|
||||
}
|
||||
|
||||
@@ -633,17 +471,39 @@ namespace chaiscript
|
||||
throw arity_error(params.size(), 1);
|
||||
}
|
||||
|
||||
Proxy_Function f = boxed_cast<Proxy_Function >(params[0]);
|
||||
Const_Proxy_Function f = boxed_cast<Const_Proxy_Function>(params[0]);
|
||||
|
||||
return Boxed_Value(f->call_match(std::vector<Boxed_Value>(params.begin() + 1, params.end())));
|
||||
}
|
||||
|
||||
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()))
|
||||
{
|
||||
e->add(user_type<void>(), "void");
|
||||
return e;
|
||||
}
|
||||
|
||||
static std::string what(const std::exception &e)
|
||||
{
|
||||
return e.what();
|
||||
}
|
||||
|
||||
/**
|
||||
* Boolean specialization of internal to_string function
|
||||
*/
|
||||
static std::string bool_to_string(bool b)
|
||||
{
|
||||
if (b)
|
||||
{
|
||||
return "true";
|
||||
} else {
|
||||
return "false";
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* perform all common bootstrap functions for std::string, void and POD types
|
||||
@@ -655,25 +515,62 @@ namespace chaiscript
|
||||
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<std::exception>(), "exception");
|
||||
|
||||
m->add(user_type<std::runtime_error>(), "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->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_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");
|
||||
|
||||
|
||||
basic_constructors<bool>("bool", m);
|
||||
oper_assign<std::string>(m);
|
||||
oper_assign<bool>(m);
|
||||
operators::assign<bool>(m);
|
||||
|
||||
m->add(fun(&to_string<const std::string &>), "internal_to_string");
|
||||
m->add(fun(&to_string<bool>), "internal_to_string");
|
||||
m->add(fun(&Bootstrap::bool_to_string), "internal_to_string");
|
||||
m->add(fun(&unknown_assign), "=");
|
||||
m->add(fun(&throw_exception), "throw");
|
||||
m->add(fun(&what), "what");
|
||||
|
||||
bootstrap_pod_type<double>("double", m);
|
||||
bootstrap_pod_type<int>("int", m);
|
||||
bootstrap_pod_type<size_t>("size_t", m);
|
||||
bootstrap_pod_type<char>("char", m);
|
||||
bootstrap_pod_type<boost::int64_t>("int64_t", m);
|
||||
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);
|
||||
|
||||
opers_comparison_pod(m);
|
||||
operators::logical_compliment<bool>(m);
|
||||
|
||||
opers_comparison<Boxed_POD_Value>(m);
|
||||
opers_arithmetic_pod(m);
|
||||
|
||||
m->add(fun(&detail::modulus<int, int, int>), "%");
|
||||
|
||||
m->add(fun(&print), "print_string");
|
||||
m->add(fun(&println), "println_string");
|
||||
@@ -681,7 +578,7 @@ namespace chaiscript
|
||||
m->add(Proxy_Function(new Dynamic_Proxy_Function(boost::bind(&bind_function, _1))),
|
||||
"bind");
|
||||
|
||||
m->add(fun(&shared_ptr_clone<Proxy_Function_Base>), "clone");
|
||||
m->add(fun(&shared_ptr_unconst_clone<Proxy_Function_Base>), "clone");
|
||||
m->add(fun(&ptr_assign<Proxy_Function_Base>), "=");
|
||||
|
||||
m->add(Proxy_Function(new Dynamic_Proxy_Function(boost::bind(&call_exists, _1))),
|
||||
|
@@ -1,6 +1,6 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009, Jonathan Turner (jturner@minnow-lang.org)
|
||||
// Copyright 2009-2010, Jonathan Turner (jturner@minnow-lang.org)
|
||||
// and Jason Turner (lefticus@gmail.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
@@ -36,16 +36,6 @@ namespace chaiscript
|
||||
{
|
||||
}
|
||||
|
||||
Bidir_Range(typename Container::iterator itr)
|
||||
: m_begin(itr), m_end(itr)
|
||||
{
|
||||
}
|
||||
|
||||
Bidir_Range(const std::pair<typename Container::iterator, typename Container::iterator> &t_p)
|
||||
: m_begin(t_p.first), m_end(t_p.second)
|
||||
{
|
||||
}
|
||||
|
||||
bool empty() const
|
||||
{
|
||||
return m_begin == m_end;
|
||||
@@ -118,20 +108,10 @@ namespace chaiscript
|
||||
ModulePtr input_range_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(user_type<Bidir_Range<ContainerType> >(), type + "_Range");
|
||||
m->add(user_type<Retro<Bidir_Range<ContainerType> > >(), type + "_Retro_Range");
|
||||
m->add(user_type<typename ContainerType::iterator>(), type+"_Iterator");
|
||||
|
||||
copy_constructor<Bidir_Range<ContainerType> >(type + "_Range", m);
|
||||
copy_constructor<Retro<Bidir_Range<ContainerType> > >(type + "_Retro_Range", m);
|
||||
|
||||
m->add(constructor<Bidir_Range<ContainerType> (ContainerType &)>(), "range");
|
||||
m->add(constructor<Bidir_Range<ContainerType> (typename ContainerType::iterator)>(), "range");
|
||||
|
||||
typedef std::pair<typename ContainerType::iterator, typename ContainerType::iterator> ItrPair;
|
||||
|
||||
m->add(constructor<Bidir_Range<ContainerType> (const ItrPair &)>(), "range");
|
||||
|
||||
m->add(user_type<ItrPair>(), type+"_Iterator_Pair");
|
||||
|
||||
m->add(fun(&Bidir_Range<ContainerType>::empty), "empty");
|
||||
m->add(fun(&Bidir_Range<ContainerType>::pop_front), "pop_front");
|
||||
@@ -139,45 +119,22 @@ namespace chaiscript
|
||||
m->add(fun(&Bidir_Range<ContainerType>::pop_back), "pop_back");
|
||||
m->add(fun(&Bidir_Range<ContainerType>::back), "back");
|
||||
|
||||
m->add(fun(&Retro<Bidir_Range<ContainerType> >::empty), "empty");
|
||||
m->add(fun(&Retro<Bidir_Range<ContainerType> >::pop_front), "pop_front");
|
||||
m->add(fun(&Retro<Bidir_Range<ContainerType> >::front), "front");
|
||||
m->add(fun(&Retro<Bidir_Range<ContainerType> >::pop_back), "pop_back");
|
||||
m->add(fun(&Retro<Bidir_Range<ContainerType> >::back), "back");
|
||||
|
||||
m->add(constructor<Retro<Bidir_Range<ContainerType> > (const Bidir_Range<ContainerType> &)>(), "retro");
|
||||
|
||||
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add reversible_container concept to the given ContainerType
|
||||
* http://www.sgi.com/tech/stl/ReversibleContainer.html
|
||||
*/
|
||||
template<typename ContainerType>
|
||||
ModulePtr reversible_container_type(const std::string &, ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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()))
|
||||
ModulePtr random_access_container_type(const std::string &/*type*/, ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
reversible_container_type<ContainerType>(type, m);
|
||||
typedef typename ContainerType::reference(ContainerType::*indexoper)(size_t);
|
||||
|
||||
//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)>(indexoper(&ContainerType::at))), "[]");
|
||||
m->add(
|
||||
fun(boost::function<typename ContainerType::reference (ContainerType *, int)>(indexoper(&ContainerType::operator[]))), "at");
|
||||
fun(boost::function<typename ContainerType::reference (ContainerType *, int)>(boost::mem_fn(static_cast<indexoper>(&ContainerType::at)))), "[]");
|
||||
|
||||
return m;
|
||||
}
|
||||
@@ -190,7 +147,7 @@ namespace chaiscript
|
||||
ModulePtr assignable_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
basic_constructors<ContainerType>(type, m);
|
||||
oper_assign<ContainerType>(m);
|
||||
operators::assign<ContainerType>(m);
|
||||
return m;
|
||||
}
|
||||
|
||||
@@ -199,31 +156,15 @@ namespace chaiscript
|
||||
* http://www.sgi.com/tech/stl/Container.html
|
||||
*/
|
||||
template<typename ContainerType>
|
||||
ModulePtr container_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
||||
ModulePtr container_type(const std::string &/*type*/, ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
assignable_type<ContainerType>(type, m);
|
||||
|
||||
m->add(fun<size_t (ContainerType::*)() const>(&ContainerType::size), "size");
|
||||
m->add(fun<size_t (ContainerType::*)() const>(&ContainerType::max_size), "max_size");
|
||||
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");
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add forward container concept to the given ContainerType
|
||||
* http://www.sgi.com/tech/stl/ForwardContainer.html
|
||||
*/
|
||||
template<typename ContainerType>
|
||||
ModulePtr forward_container_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
input_range_type<ContainerType>(type, m);
|
||||
container_type<ContainerType>(type, m);
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add default constructable concept to the given Type
|
||||
* http://www.sgi.com/tech/stl/DefaultConstructible.html
|
||||
@@ -276,11 +217,8 @@ namespace chaiscript
|
||||
* http://www.sgi.com/tech/stl/Sequence.html
|
||||
*/
|
||||
template<typename ContainerType>
|
||||
ModulePtr sequence_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
||||
ModulePtr sequence_type(const std::string &/*type*/, ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
forward_container_type<ContainerType>(type, m);
|
||||
default_constructible_type<ContainerType>(type, m);
|
||||
|
||||
std::string insert_name;
|
||||
if (typeid(typename ContainerType::value_type) == typeid(Boxed_Value))
|
||||
{
|
||||
@@ -300,14 +238,11 @@ namespace chaiscript
|
||||
* 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()))
|
||||
ModulePtr back_insertion_sequence_type(const std::string &/*type*/, ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
sequence_type<ContainerType>(type, m);
|
||||
|
||||
|
||||
typedef typename ContainerType::reference (ContainerType::*backptr)();
|
||||
|
||||
m->add(fun(backptr(&ContainerType::back)), "back");
|
||||
m->add(fun(static_cast<backptr>(&ContainerType::back)), "back");
|
||||
|
||||
std::string push_back_name;
|
||||
if (typeid(typename ContainerType::value_type) == typeid(Boxed_Value))
|
||||
@@ -317,33 +252,32 @@ namespace chaiscript
|
||||
push_back_name = "push_back";
|
||||
}
|
||||
|
||||
m->add(fun(&ContainerType::push_back), push_back_name);
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
random_access_container_type<VectorType>(type, m);
|
||||
back_insertion_sequence_type<VectorType>(type, m);
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a vector type with associated concepts
|
||||
* http://www.sgi.com/tech/stl/Vector.html
|
||||
*/
|
||||
*Front insertion sequence
|
||||
*http://www.sgi.com/tech/stl/FrontInsertionSequence.html
|
||||
*/
|
||||
template<typename ContainerType>
|
||||
ModulePtr associative_container_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
||||
ModulePtr front_insertion_sequence_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
forward_container_type<ContainerType>(type, m);
|
||||
default_constructible_type<ContainerType>(type, m);
|
||||
typedef typename ContainerType::reference (ContainerType::*frontptr)();
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -373,7 +307,6 @@ namespace chaiscript
|
||||
template<typename ContainerType>
|
||||
ModulePtr pair_associative_container_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
associative_container_type<ContainerType>(type, m);
|
||||
pair_type<typename ContainerType::value_type>(type + "_Pair", m);
|
||||
|
||||
return m;
|
||||
@@ -384,40 +317,9 @@ namespace chaiscript
|
||||
* 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()))
|
||||
ModulePtr unique_associative_container_type(const std::string &/*type*/, ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
associative_container_type<ContainerType>(type, m);
|
||||
m->add(fun<size_t (ContainerType::*)(const typename ContainerType::key_type &) const>(&ContainerType::count), "count");
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add sorted associative container concept to the given ContainerType
|
||||
* http://www.sgi.com/tech/stl/SortedAssociativeContainer.html
|
||||
*/
|
||||
template<typename ContainerType>
|
||||
ModulePtr sorted_associative_container_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
typedef std::pair<typename ContainerType::iterator, typename ContainerType::iterator>
|
||||
(ContainerType::*eq_range)(const typename ContainerType::key_type &);
|
||||
|
||||
reversible_container_type<ContainerType>(type, m);
|
||||
associative_container_type<ContainerType>(type, m);
|
||||
m->add(fun(eq_range(&ContainerType::equal_range)), "equal_range");
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add unique sorted associative container concept to the given ContainerType
|
||||
* http://www.sgi.com/tech/stl/UniqueSortedAssociativeContainer.html
|
||||
*/
|
||||
template<typename ContainerType>
|
||||
ModulePtr unique_sorted_associative_container_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
sorted_associative_container_type<ContainerType>(type, m);
|
||||
unique_associative_container_type<ContainerType>(type, m);
|
||||
m->add(fun(boost::function<int (const ContainerType *, const typename ContainerType::key_type &)>(boost::mem_fn(&ContainerType::count))), "count");
|
||||
|
||||
return m;
|
||||
}
|
||||
@@ -430,9 +332,80 @@ namespace chaiscript
|
||||
ModulePtr map_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(user_type<MapType>(), type);
|
||||
m->add(fun(&MapType::operator[]), "[]");
|
||||
unique_sorted_associative_container_type<MapType>(type, m);
|
||||
|
||||
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);
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -445,11 +418,15 @@ namespace chaiscript
|
||||
ModulePtr string_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(user_type<String>(), type);
|
||||
oper_add<String>(m);
|
||||
oper_add_equals<String>(m);
|
||||
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;
|
||||
@@ -461,13 +438,16 @@ namespace chaiscript
|
||||
}
|
||||
m->add(fun(&String::push_back), push_back_name);
|
||||
|
||||
typedef typename String::size_type (String::*find_func)(const String &, typename String::size_type) const;
|
||||
m->add(fun(find_func(&String::find)), "find");
|
||||
m->add(fun(find_func(&String::rfind)), "rfind");
|
||||
m->add(fun(find_func(&String::find_first_of)), "find_first_of");
|
||||
m->add(fun(find_func(&String::find_last_of)), "find_last_of");
|
||||
m->add(fun(find_func(&String::find_first_not_of)), "find_first_not_of");
|
||||
m->add(fun(find_func(&String::find_last_not_of)), "find_last_not_of");
|
||||
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");
|
||||
|
||||
return m;
|
||||
}
|
||||
|
@@ -1,6 +1,6 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009, Jonathan Turner (jturner@minnow-lang.org)
|
||||
// Copyright 2009-2010, Jonathan Turner (jturner@minnow-lang.org)
|
||||
// and Jason Turner (lefticus@gmail.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#define __boxed_value_hpp__
|
||||
|
||||
#include "type_info.hpp"
|
||||
#include "../chaiscript_threading.hpp"
|
||||
#include <map>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/any.hpp>
|
||||
@@ -16,6 +17,7 @@
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <boost/type_traits/add_const.hpp>
|
||||
#include <boost/integer_traits.hpp>
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
@@ -41,49 +43,27 @@ namespace chaiscript
|
||||
*/
|
||||
struct Data
|
||||
{
|
||||
/**
|
||||
* used to provide type-erased access to the internal boost::shared_ptr
|
||||
* reference count information
|
||||
*/
|
||||
struct Shared_Ptr_Proxy
|
||||
{
|
||||
virtual ~Shared_Ptr_Proxy()
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool unique(boost::any *) = 0;
|
||||
virtual long use_count(boost::any *) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Typed implementation of the Shared_Ptr_Proxy
|
||||
*/
|
||||
template<typename T>
|
||||
struct Shared_Ptr_Proxy_Impl : Shared_Ptr_Proxy
|
||||
{
|
||||
virtual ~Shared_Ptr_Proxy_Impl()
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool unique(boost::any *a)
|
||||
static bool unique(boost::any *a)
|
||||
{
|
||||
boost::shared_ptr<T> *ptr = boost::any_cast<boost::shared_ptr<T> >(a);
|
||||
return ptr->unique();
|
||||
}
|
||||
|
||||
virtual long use_count(boost::any *a)
|
||||
template<typename T>
|
||||
static bool is_null(boost::any *a)
|
||||
{
|
||||
boost::shared_ptr<T> *ptr = boost::any_cast<boost::shared_ptr<T> >(a);
|
||||
return ptr->use_count();
|
||||
return ptr->get() == 0;
|
||||
}
|
||||
};
|
||||
|
||||
Data(const Type_Info &ti,
|
||||
const boost::any &to,
|
||||
bool tr,
|
||||
const boost::shared_ptr<Shared_Ptr_Proxy> &t_proxy = boost::shared_ptr<Shared_Ptr_Proxy>())
|
||||
const boost::function<bool (boost::any*)> &t_unique = boost::function<bool (boost::any*)>(),
|
||||
const boost::function<bool (boost::any*)> &t_is_null = boost::function<bool (boost::any*)>())
|
||||
: m_type_info(ti), m_obj(to),
|
||||
m_is_ref(tr), m_ptr_proxy(t_proxy)
|
||||
m_is_ref(tr), m_unique(t_unique), m_is_null(t_is_null)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -92,7 +72,8 @@ namespace chaiscript
|
||||
m_type_info = rhs.m_type_info;
|
||||
m_obj = rhs.m_obj;
|
||||
m_is_ref = rhs.m_is_ref;
|
||||
m_ptr_proxy = rhs.m_ptr_proxy;
|
||||
m_unique = rhs.m_unique;
|
||||
m_is_null = rhs.m_is_null;
|
||||
|
||||
return *this;
|
||||
}
|
||||
@@ -100,7 +81,8 @@ namespace chaiscript
|
||||
Type_Info m_type_info;
|
||||
boost::any m_obj;
|
||||
bool m_is_ref;
|
||||
boost::shared_ptr<Shared_Ptr_Proxy> m_ptr_proxy;
|
||||
boost::function<bool (boost::any*)> m_unique;
|
||||
boost::function<bool (boost::any*)> m_is_null;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -134,21 +116,24 @@ namespace chaiscript
|
||||
template<typename T>
|
||||
boost::shared_ptr<Data> get(const boost::shared_ptr<T> &obj)
|
||||
{
|
||||
bool b_const = boost::is_const<T>::value;
|
||||
|
||||
boost::shared_ptr<Data> data(new Data(
|
||||
detail::Get_Type_Info<T>::get(),
|
||||
boost::any(obj),
|
||||
false,
|
||||
boost::shared_ptr<Data::Shared_Ptr_Proxy>(new Data::Shared_Ptr_Proxy_Impl<T>()))
|
||||
&Data::unique<T>,
|
||||
&Data::is_null<T>)
|
||||
);
|
||||
|
||||
std::map<const void *, Data>::iterator itr
|
||||
= m_ptrs.find(obj.get());
|
||||
std::map<std::pair<const void *, bool>, Data>::iterator itr
|
||||
= m_ptrs.find(std::make_pair(obj.get(), b_const));
|
||||
|
||||
if (itr != m_ptrs.end())
|
||||
{
|
||||
(*data) = (itr->second);
|
||||
} else {
|
||||
m_ptrs.insert(std::make_pair(obj.get(), *data));
|
||||
m_ptrs.insert(std::make_pair(std::make_pair(obj.get(), b_const), *data));
|
||||
}
|
||||
|
||||
return data;
|
||||
@@ -163,14 +148,16 @@ namespace chaiscript
|
||||
template<typename T>
|
||||
boost::shared_ptr<Data> get(boost::reference_wrapper<T> obj)
|
||||
{
|
||||
bool b_const = boost::is_const<T>::value;
|
||||
|
||||
boost::shared_ptr<Data> data(new Data(
|
||||
detail::Get_Type_Info<T>::get(),
|
||||
boost::any(obj),
|
||||
true)
|
||||
);
|
||||
|
||||
std::map<const void *, Data >::iterator itr
|
||||
= m_ptrs.find(obj.get_pointer());
|
||||
std::map<std::pair<const void *, bool>, Data >::iterator itr
|
||||
= m_ptrs.find(std::make_pair(obj.get_pointer(), b_const) );
|
||||
|
||||
// If the ptr is found in the cache and it is the correct type,
|
||||
// return it. It may be the incorrect type when two variables share the
|
||||
@@ -180,7 +167,7 @@ namespace chaiscript
|
||||
// Both t and t.x share the same memory location, but do not represent
|
||||
// objects of the same type.
|
||||
if (itr != m_ptrs.end()
|
||||
&& itr->second.m_type_info.m_bare_type_info == data->m_type_info.m_bare_type_info)
|
||||
&& itr->second.m_type_info.bare_equal(data->m_type_info))
|
||||
{
|
||||
(*data) = (itr->second);
|
||||
}
|
||||
@@ -195,12 +182,13 @@ namespace chaiscript
|
||||
detail::Get_Type_Info<T>::get(),
|
||||
boost::any(boost::shared_ptr<T>(new T(t))),
|
||||
false,
|
||||
boost::shared_ptr<Data::Shared_Ptr_Proxy>(new Data::Shared_Ptr_Proxy_Impl<T>()))
|
||||
&Data::unique<T>,
|
||||
&Data::is_null<T>)
|
||||
);
|
||||
|
||||
boost::shared_ptr<T> *ptr = boost::any_cast<boost::shared_ptr<T> >(&data->m_obj);
|
||||
|
||||
m_ptrs.insert(std::make_pair(ptr->get(), *data));
|
||||
m_ptrs.insert(std::make_pair(std::make_pair(ptr->get(), false), *data));
|
||||
return data;
|
||||
}
|
||||
|
||||
@@ -217,21 +205,23 @@ namespace chaiscript
|
||||
* Drop objects from the cache where there is only one (ie, our)
|
||||
* reference to it, so it may be destructed
|
||||
*/
|
||||
void cull()
|
||||
void cull(bool force = false)
|
||||
{
|
||||
|
||||
++m_cullcount;
|
||||
if (m_cullcount % 10 != 0)
|
||||
if (force || m_cullcount % 20 != 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
std::map<const void *, Data >::iterator itr = m_ptrs.begin();
|
||||
|
||||
std::map<std::pair<const void *, bool>, Data>::iterator itr = m_ptrs.begin();
|
||||
|
||||
while (itr != m_ptrs.end())
|
||||
{
|
||||
if (itr->second.m_ptr_proxy->unique(&itr->second.m_obj) == 1)
|
||||
if (itr->second.m_unique(&itr->second.m_obj))
|
||||
{
|
||||
std::map<const void *, Data >::iterator todel = itr;
|
||||
std::map<std::pair<const void *, bool>, Data >::iterator todel = itr;
|
||||
++itr;
|
||||
m_ptrs.erase(todel);
|
||||
} else {
|
||||
@@ -240,7 +230,7 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
std::map<const void *, Data > m_ptrs;
|
||||
std::map<std::pair<const void *, bool>, Data> m_ptrs;
|
||||
int m_cullcount;
|
||||
};
|
||||
|
||||
@@ -275,14 +265,24 @@ namespace chaiscript
|
||||
{
|
||||
}
|
||||
|
||||
void swap(Boxed_Value &rhs)
|
||||
{
|
||||
std::swap(m_data, rhs.m_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a reference to the static global Object_Cache
|
||||
*/
|
||||
Object_Cache &get_object_cache()
|
||||
static Object_Cache &get_object_cache()
|
||||
{
|
||||
static Object_Cache oc;
|
||||
return oc;
|
||||
}
|
||||
static chaiscript::threading::Thread_Storage<Object_Cache> oc;
|
||||
return *oc;
|
||||
}
|
||||
|
||||
static void clear_cache()
|
||||
{
|
||||
get_object_cache().m_ptrs.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* copy the values stored in rhs.m_data to m_data
|
||||
@@ -299,7 +299,8 @@ namespace chaiscript
|
||||
*/
|
||||
Boxed_Value &operator=(const Boxed_Value &rhs)
|
||||
{
|
||||
m_data = rhs.m_data;
|
||||
Boxed_Value temp(rhs);
|
||||
swap(temp);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -311,9 +312,29 @@ namespace chaiscript
|
||||
/**
|
||||
* return true if the object is uninitialized
|
||||
*/
|
||||
bool is_unknown() const
|
||||
bool is_undef() const
|
||||
{
|
||||
return m_data->m_type_info.m_is_unknown;
|
||||
return m_data->m_type_info.is_undef();
|
||||
}
|
||||
|
||||
bool is_const() const
|
||||
{
|
||||
return m_data->m_type_info.is_const();
|
||||
}
|
||||
|
||||
bool is_type(const Type_Info &ti) const
|
||||
{
|
||||
return m_data->m_type_info.bare_equal(ti);
|
||||
}
|
||||
|
||||
bool is_null() const
|
||||
{
|
||||
if (m_data->m_is_null)
|
||||
{
|
||||
return m_data->m_is_null(&m_data->m_obj);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
boost::any get() const
|
||||
@@ -326,6 +347,12 @@ namespace chaiscript
|
||||
return m_data->m_is_ref;
|
||||
}
|
||||
|
||||
bool is_pointer() const
|
||||
{
|
||||
return !is_ref();
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
boost::shared_ptr<Data> m_data;
|
||||
};
|
||||
@@ -347,14 +374,19 @@ namespace chaiscript
|
||||
{
|
||||
if (ob.is_ref())
|
||||
{
|
||||
if (!ob.get_type_info().m_is_const)
|
||||
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 {
|
||||
return boost::cref(*(boost::any_cast<boost::shared_ptr<Result> >(ob.get())));
|
||||
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())));
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -371,14 +403,19 @@ namespace chaiscript
|
||||
{
|
||||
if (ob.is_ref())
|
||||
{
|
||||
if (!ob.get_type_info().m_is_const)
|
||||
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 {
|
||||
return boost::cref(*(boost::any_cast<boost::shared_ptr<Result> >(ob.get())));
|
||||
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())));
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -395,14 +432,19 @@ namespace chaiscript
|
||||
{
|
||||
if (ob.is_ref())
|
||||
{
|
||||
if (!ob.get_type_info().m_is_const)
|
||||
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 {
|
||||
return (boost::any_cast<boost::shared_ptr<Result> >(ob.get())).get();
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -460,7 +502,26 @@ namespace chaiscript
|
||||
};
|
||||
|
||||
/**
|
||||
* Cast_Helper for casting to a boost::shared_ptr<> type
|
||||
* Cast_Helper for casting to a boost::shared_ptr<const> type
|
||||
*/
|
||||
template<typename Result>
|
||||
struct Cast_Helper<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 for casting to a const boost::shared_ptr<> & type
|
||||
*/
|
||||
template<typename Result>
|
||||
struct Cast_Helper<const boost::shared_ptr<Result> &>
|
||||
@@ -473,6 +534,25 @@ namespace chaiscript
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Cast_Helper for casting to a const boost::shared_ptr<const> & type
|
||||
*/
|
||||
template<typename Result>
|
||||
struct Cast_Helper<const 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());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
@@ -512,7 +592,7 @@ namespace chaiscript
|
||||
{
|
||||
public:
|
||||
bad_boxed_cast(const Type_Info &t_from, const std::type_info &t_to) throw()
|
||||
: from(t_from.m_type_info), to(&t_to), m_what("Cannot perform boxed_cast")
|
||||
: from(t_from), to(&t_to), m_what("Cannot perform boxed_cast")
|
||||
{
|
||||
}
|
||||
|
||||
@@ -527,7 +607,8 @@ namespace chaiscript
|
||||
{
|
||||
return m_what.c_str();
|
||||
}
|
||||
const std::type_info *from;
|
||||
|
||||
Type_Info from;
|
||||
const std::type_info *to;
|
||||
|
||||
private:
|
||||
@@ -558,12 +639,12 @@ namespace chaiscript
|
||||
Boxed_POD_Value(const Boxed_Value &v)
|
||||
: d(0), i(0), m_isfloat(false)
|
||||
{
|
||||
if (!v.get_type_info().m_type_info)
|
||||
if (v.get_type_info().is_undef())
|
||||
{
|
||||
throw boost::bad_any_cast();
|
||||
}
|
||||
|
||||
const std::type_info &inp_ = *v.get_type_info().m_type_info;
|
||||
const Type_Info &inp_ = v.get_type_info();
|
||||
|
||||
if (inp_ == typeid(double))
|
||||
{
|
||||
@@ -637,42 +718,117 @@ namespace chaiscript
|
||||
{
|
||||
if (!m_isfloat && !r.m_isfloat)
|
||||
{
|
||||
return Boxed_Value(i + r.i);
|
||||
return smart_size(i + r.i);
|
||||
}
|
||||
|
||||
return Boxed_Value(((m_isfloat)?d:i) + ((r.m_isfloat)?r.d:r.i));
|
||||
}
|
||||
|
||||
Boxed_Value operator*(const Boxed_POD_Value &r) const
|
||||
{
|
||||
if (!m_isfloat && !r.m_isfloat)
|
||||
{
|
||||
return Boxed_Value(i * r.i);
|
||||
}
|
||||
|
||||
return Boxed_Value(((m_isfloat)?d:i) * ((r.m_isfloat)?r.d:r.i));
|
||||
}
|
||||
|
||||
Boxed_Value operator/(const Boxed_POD_Value &r) const
|
||||
{
|
||||
if (!m_isfloat && !r.m_isfloat)
|
||||
{
|
||||
return Boxed_Value(i / r.i);
|
||||
}
|
||||
|
||||
return Boxed_Value(((m_isfloat)?d:i) / ((r.m_isfloat)?r.d:r.i));
|
||||
}
|
||||
|
||||
Boxed_Value operator-(const Boxed_POD_Value &r) const
|
||||
{
|
||||
if (!m_isfloat && !r.m_isfloat)
|
||||
{
|
||||
return Boxed_Value(i - r.i);
|
||||
return smart_size(i - r.i);
|
||||
}
|
||||
|
||||
return Boxed_Value(((m_isfloat)?d:i) - ((r.m_isfloat)?r.d:r.i));
|
||||
}
|
||||
|
||||
Boxed_Value operator&(const Boxed_POD_Value &r) const
|
||||
{
|
||||
if (!m_isfloat && !r.m_isfloat)
|
||||
{
|
||||
return Boxed_Value(i & r.i);
|
||||
}
|
||||
|
||||
throw bad_boxed_cast("& only valid for integer types");
|
||||
}
|
||||
|
||||
Boxed_Value operator^(const Boxed_POD_Value &r) const
|
||||
{
|
||||
if (!m_isfloat && !r.m_isfloat)
|
||||
{
|
||||
return Boxed_Value(i ^ r.i);
|
||||
}
|
||||
|
||||
throw bad_boxed_cast("^ only valid for integer types");
|
||||
}
|
||||
|
||||
Boxed_Value operator|(const Boxed_POD_Value &r) const
|
||||
{
|
||||
if (!m_isfloat && !r.m_isfloat)
|
||||
{
|
||||
return Boxed_Value(i | r.i);
|
||||
}
|
||||
|
||||
throw bad_boxed_cast("| only valid for integer types");
|
||||
}
|
||||
|
||||
Boxed_Value operator/(const Boxed_POD_Value &r) const
|
||||
{
|
||||
if (!m_isfloat && !r.m_isfloat)
|
||||
{
|
||||
return smart_size(i / r.i);
|
||||
}
|
||||
|
||||
return Boxed_Value(((m_isfloat)?d:i) / ((r.m_isfloat)?r.d:r.i));
|
||||
}
|
||||
|
||||
Boxed_Value operator<<(const Boxed_POD_Value &r) const
|
||||
{
|
||||
if (!m_isfloat && !r.m_isfloat)
|
||||
{
|
||||
return smart_size(i << r.i);
|
||||
}
|
||||
|
||||
throw bad_boxed_cast("<< only valid for integer types");
|
||||
}
|
||||
|
||||
|
||||
Boxed_Value operator*(const Boxed_POD_Value &r) const
|
||||
{
|
||||
if (!m_isfloat && !r.m_isfloat)
|
||||
{
|
||||
return smart_size(i * r.i);
|
||||
}
|
||||
|
||||
return Boxed_Value(((m_isfloat)?d:i) * ((r.m_isfloat)?r.d:r.i));
|
||||
}
|
||||
|
||||
|
||||
Boxed_Value operator%(const Boxed_POD_Value &r) const
|
||||
{
|
||||
if (!m_isfloat && !r.m_isfloat)
|
||||
{
|
||||
return smart_size(i % r.i);
|
||||
}
|
||||
|
||||
throw bad_boxed_cast("% only valid for integer types");
|
||||
}
|
||||
|
||||
Boxed_Value operator>>(const Boxed_POD_Value &r) const
|
||||
{
|
||||
if (!m_isfloat && !r.m_isfloat)
|
||||
{
|
||||
return smart_size(i >> r.i);
|
||||
}
|
||||
|
||||
throw bad_boxed_cast(">> only valid for integer types");
|
||||
}
|
||||
|
||||
Boxed_Value smart_size(boost::int64_t i) const
|
||||
{
|
||||
if (i < boost::integer_traits<int>::const_min
|
||||
|| i > boost::integer_traits<int>::const_max)
|
||||
{
|
||||
return Boxed_Value(i);
|
||||
} else {
|
||||
return Boxed_Value(static_cast<int>(i));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
double d;
|
||||
boost::int64_t i;
|
||||
|
||||
@@ -689,6 +845,20 @@ namespace chaiscript
|
||||
{
|
||||
typedef Boxed_POD_Value Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob)
|
||||
{
|
||||
return Boxed_POD_Value(ob);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Cast_Helper for converting from Boxed_Value to Boxed_POD_Value
|
||||
*/
|
||||
template<>
|
||||
struct Cast_Helper<const Boxed_POD_Value &>
|
||||
{
|
||||
typedef Boxed_POD_Value Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob)
|
||||
{
|
||||
return Boxed_POD_Value(ob);
|
||||
@@ -702,6 +872,30 @@ namespace chaiscript
|
||||
return Boxed_Value(t);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Boxed_Value const_var(T *t)
|
||||
{
|
||||
return Boxed_Value( const_cast<typename boost::add_const<T>::type>(t) );
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Boxed_Value const_var(const boost::shared_ptr<T> &t)
|
||||
{
|
||||
return Boxed_Value( boost::const_pointer_cast<typename boost::add_const<T>::type>(t) );
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Boxed_Value const_var(const boost::reference_wrapper<T> &t)
|
||||
{
|
||||
return Boxed_Value( boost::cref(t.get()) );
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Boxed_Value const_var(const T &t)
|
||||
{
|
||||
return Boxed_Value(boost::shared_ptr<typename boost::add_const<T>::type >(new T(t)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the two Boxed_Values share the same internal type
|
||||
*/
|
||||
@@ -709,8 +903,9 @@ namespace chaiscript
|
||||
{
|
||||
return l.get_type_info() == r.get_type_info();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009, Jonathan Turner (jturner@minnow-lang.org)
|
||||
// Copyright 2009-2010, Jonathan Turner (jturner@minnow-lang.org)
|
||||
// and Jason Turner (lefticus@gmail.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <set>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/tuple/tuple.hpp>
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
@@ -22,6 +23,8 @@
|
||||
#include "type_info.hpp"
|
||||
#include "proxy_functions.hpp"
|
||||
#include "proxy_constructors.hpp"
|
||||
#include "dynamic_object.hpp"
|
||||
#include "../chaiscript_threading.hpp"
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
@@ -40,16 +43,32 @@ namespace chaiscript
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void apply(T &t) const
|
||||
|
||||
//Add a bit of chaiscript to eval during module implementation
|
||||
Module &eval(const std::string &str)
|
||||
{
|
||||
m_evals.push_back(str);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Module &add(const boost::shared_ptr<Module> &m)
|
||||
{
|
||||
m->apply(*this, *this);
|
||||
return *m;
|
||||
}
|
||||
|
||||
template<typename Eval, typename Engine>
|
||||
void apply(Eval &t_eval, Engine &t_engine) const
|
||||
{
|
||||
apply(m_typeinfos.begin(), m_typeinfos.end(), t);
|
||||
apply(m_funcs.begin(), m_funcs.end(), t);
|
||||
apply(m_typeinfos.begin(), m_typeinfos.end(), t_engine);
|
||||
apply(m_funcs.begin(), m_funcs.end(), t_engine);
|
||||
apply_eval(m_evals.begin(), m_evals.end(), t_eval);
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<std::pair<Type_Info, std::string> > m_typeinfos;
|
||||
std::vector<std::pair<Proxy_Function, std::string> > m_funcs;
|
||||
std::vector<std::string> m_evals;
|
||||
|
||||
template<typename T, typename InItr>
|
||||
void apply(InItr begin, InItr end, T &t) const
|
||||
@@ -60,6 +79,18 @@ namespace chaiscript
|
||||
++begin;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T, typename InItr>
|
||||
void apply_eval(InItr begin, InItr end, T &t) const
|
||||
{
|
||||
while (begin != end)
|
||||
{
|
||||
t.eval(*begin);
|
||||
++begin;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
typedef boost::shared_ptr<Module> ModulePtr;
|
||||
@@ -73,7 +104,8 @@ namespace chaiscript
|
||||
{
|
||||
public:
|
||||
Dispatch_Function(const std::vector<std::pair<std::string, Proxy_Function > > &t_funcs)
|
||||
: m_funcs(t_funcs)
|
||||
: Proxy_Function_Base(std::vector<Type_Info>()),
|
||||
m_funcs(t_funcs)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -84,14 +116,9 @@ namespace chaiscript
|
||||
|
||||
virtual ~Dispatch_Function() {}
|
||||
|
||||
virtual Boxed_Value operator()(const std::vector<Boxed_Value> ¶ms)
|
||||
virtual Boxed_Value operator()(const std::vector<Boxed_Value> ¶ms) const
|
||||
{
|
||||
return dispatch(m_funcs, params);
|
||||
}
|
||||
|
||||
virtual std::vector<Type_Info> get_param_types() const
|
||||
{
|
||||
return std::vector<Type_Info>();
|
||||
return dispatch(m_funcs.begin(), m_funcs.end(), params);
|
||||
}
|
||||
|
||||
virtual int get_arity() const
|
||||
@@ -145,6 +172,19 @@ namespace chaiscript
|
||||
virtual ~reserved_word_error() throw() {}
|
||||
};
|
||||
|
||||
/**
|
||||
* Exception thrown in the case that a non-const object was added as a shared object
|
||||
*/
|
||||
struct global_non_const : std::runtime_error
|
||||
{
|
||||
global_non_const() throw()
|
||||
: std::runtime_error("a global object must be const")
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~global_non_const() throw() {}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Main class for the dispatchkit. Handles management
|
||||
@@ -155,13 +195,27 @@ namespace chaiscript
|
||||
public:
|
||||
typedef std::map<std::string, chaiscript::Type_Info> Type_Name_Map;
|
||||
typedef std::map<std::string, Boxed_Value> Scope;
|
||||
typedef boost::shared_ptr<std::deque<Scope> > Stack;
|
||||
typedef boost::tuples::tuple<std::map<std::string, Boxed_Value>, std::deque<Scope>, bool> StackData;
|
||||
typedef boost::shared_ptr<StackData> Stack;
|
||||
|
||||
struct State
|
||||
{
|
||||
std::multimap<std::string, Proxy_Function> m_functions;
|
||||
std::map<std::string, Boxed_Value> m_global_objects;
|
||||
Type_Name_Map m_types;
|
||||
std::set<std::string> m_reserved_words;
|
||||
};
|
||||
|
||||
Dispatch_Engine()
|
||||
: m_scopes(new Stack::element_type()),
|
||||
m_place_holder(boost::shared_ptr<Placeholder_Object>(new Placeholder_Object()))
|
||||
: m_place_holder(boost::shared_ptr<Placeholder_Object>(new Placeholder_Object()))
|
||||
{
|
||||
m_scopes->push_back(Scope());
|
||||
StackData &stack = get_stack_data();
|
||||
stack.get<1>().push_back(Scope());
|
||||
}
|
||||
|
||||
~Dispatch_Engine()
|
||||
{
|
||||
Boxed_Value::clear_cache();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -170,15 +224,10 @@ namespace chaiscript
|
||||
bool add(const Proxy_Function &f, const std::string &name)
|
||||
{
|
||||
validate_object_name(name);
|
||||
return add_function(f, name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a module's worth of registrations to the system
|
||||
*/
|
||||
void add(const ModulePtr &m)
|
||||
{
|
||||
m->apply(*this);
|
||||
StackData &stack = get_stack_data();
|
||||
stack.get<0>().erase(name);
|
||||
return add_function(f, name);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -188,12 +237,15 @@ namespace chaiscript
|
||||
void add(const Boxed_Value &obj, const std::string &name)
|
||||
{
|
||||
validate_object_name(name);
|
||||
for (int i = m_scopes->size()-1; i >= 0; --i)
|
||||
StackData &stack = get_stack_data();
|
||||
|
||||
for (int i = stack.get<1>().size()-1; i >= 0; --i)
|
||||
{
|
||||
std::map<std::string, Boxed_Value>::const_iterator itr = (*m_scopes)[i].find(name);
|
||||
if (itr != (*m_scopes)[i].end())
|
||||
std::map<std::string, Boxed_Value>::const_iterator itr = (stack.get<1>())[i].find(name);
|
||||
if (itr != (stack.get<1>())[i].end())
|
||||
{
|
||||
(*m_scopes)[i][name] = Boxed_Value(obj);
|
||||
stack.get<0>().erase(name);
|
||||
(stack.get<1>())[i][name] = obj;
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -206,8 +258,31 @@ namespace chaiscript
|
||||
*/
|
||||
void add_object(const std::string &name, const Boxed_Value &obj)
|
||||
{
|
||||
StackData &stack = get_stack_data();
|
||||
validate_object_name(name);
|
||||
m_scopes->back()[name] = Boxed_Value(obj);
|
||||
stack.get<0>().erase(name);
|
||||
stack.get<1>().back()[name] = obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new global shared object, between all the threads
|
||||
*/
|
||||
void add_global_const(const Boxed_Value &obj, const std::string &name)
|
||||
{
|
||||
StackData &stack = get_stack_data();
|
||||
validate_object_name(name);
|
||||
if (!obj.is_const())
|
||||
{
|
||||
throw global_non_const();
|
||||
}
|
||||
|
||||
stack.get<0>().erase(name);
|
||||
|
||||
#ifndef CHAISCRIPT_NO_THREADS
|
||||
boost::unique_lock<boost::shared_mutex> l(m_global_object_mutex);
|
||||
#endif
|
||||
|
||||
m_state.m_global_objects[name] = obj;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -215,7 +290,8 @@ namespace chaiscript
|
||||
*/
|
||||
void new_scope()
|
||||
{
|
||||
m_scopes->push_back(Scope());
|
||||
StackData &stack = get_stack_data();
|
||||
stack.get<1>().push_back(Scope());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -223,22 +299,22 @@ namespace chaiscript
|
||||
*/
|
||||
void pop_scope()
|
||||
{
|
||||
if (m_scopes->size() > 1)
|
||||
StackData &stack = get_stack_data();
|
||||
if (stack.get<1>().size() > 1)
|
||||
{
|
||||
m_scopes->pop_back();
|
||||
Scope &scope(stack.get<1>().back());
|
||||
for (Scope::const_iterator itr = scope.begin();
|
||||
itr != scope.end();
|
||||
++itr)
|
||||
{
|
||||
stack.get<0>().erase(itr->first);
|
||||
}
|
||||
stack.get<1>().pop_back();
|
||||
} else {
|
||||
throw std::range_error("Unable to pop global stack");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current stack
|
||||
*/
|
||||
Stack get_stack()
|
||||
{
|
||||
return m_scopes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Swaps out the stack with a new stack
|
||||
* \returns the old stack
|
||||
@@ -246,14 +322,30 @@ namespace chaiscript
|
||||
*/
|
||||
Stack set_stack(const Stack &s)
|
||||
{
|
||||
Stack old = m_scopes;
|
||||
m_scopes = s;
|
||||
Stack old = m_stack_holder->stack;
|
||||
m_stack_holder->stack = s;
|
||||
return old;
|
||||
}
|
||||
|
||||
Stack new_stack()
|
||||
Stack new_stack() const
|
||||
{
|
||||
return Stack(new Stack::element_type());
|
||||
Stack s(new Stack::element_type());
|
||||
s->get<1>().push_back(Scope());
|
||||
s->get<2>() = false;
|
||||
return s;
|
||||
}
|
||||
|
||||
Stack get_stack() const
|
||||
{
|
||||
return m_stack_holder->stack;
|
||||
}
|
||||
|
||||
void sync_cache()
|
||||
{
|
||||
#ifndef CHAISCRIPT_NO_THREADS
|
||||
boost::shared_lock<boost::shared_mutex> l(m_mutex);
|
||||
#endif
|
||||
sync_cache_no_lock();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -263,27 +355,57 @@ namespace chaiscript
|
||||
*/
|
||||
Boxed_Value get_object(const std::string &name) const
|
||||
{
|
||||
// Is it a placeholder object?
|
||||
if (name == "_")
|
||||
{
|
||||
return m_place_holder;
|
||||
}
|
||||
|
||||
for (int i = m_scopes->size()-1; i >= 0; --i)
|
||||
StackData &stack = get_stack_data();
|
||||
std::map<std::string, Boxed_Value> &cache = stack.get<0>();
|
||||
|
||||
// Is it in the cache?
|
||||
std::map<std::string, Boxed_Value>::const_iterator itr = cache.find(name);
|
||||
if (itr != cache.end())
|
||||
{
|
||||
std::map<std::string, Boxed_Value>::const_iterator itr = (*m_scopes)[i].find(name);
|
||||
if (itr != (*m_scopes)[i].end())
|
||||
return itr->second;
|
||||
}
|
||||
|
||||
// Is it in the stack?
|
||||
for (int i = stack.get<1>().size()-1; i >= 0; --i)
|
||||
{
|
||||
std::map<std::string, Boxed_Value>::const_iterator stackitr = (stack.get<1>())[i].find(name);
|
||||
if (stackitr != (stack.get<1>())[i].end())
|
||||
{
|
||||
cache[name] = stackitr->second;
|
||||
return stackitr->second;
|
||||
}
|
||||
}
|
||||
|
||||
// Is the value we are looking for a global?
|
||||
{
|
||||
#ifndef CHAISCRIPT_NO_THREADS
|
||||
boost::shared_lock<boost::shared_mutex> l(m_global_object_mutex);
|
||||
#endif
|
||||
|
||||
itr = m_state.m_global_objects.find(name);
|
||||
if (itr != m_state.m_global_objects.end())
|
||||
{
|
||||
cache[name] = itr->second;
|
||||
return itr->second;
|
||||
}
|
||||
}
|
||||
|
||||
// If all that failed, then check to see if it's a function
|
||||
std::vector<std::pair<std::string, std::multimap<std::string, Proxy_Function >::mapped_type> > funcs = get_function(name);
|
||||
|
||||
if (funcs.empty())
|
||||
{
|
||||
throw std::range_error("Object not known: " + name);
|
||||
} else {
|
||||
return Boxed_Value(Proxy_Function(new Dispatch_Function(funcs)));
|
||||
Boxed_Value f(Const_Proxy_Function(new Dispatch_Function(funcs)));
|
||||
cache[name] = f;
|
||||
return f;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -292,7 +414,13 @@ namespace chaiscript
|
||||
*/
|
||||
void add(const Type_Info &ti, const std::string &name)
|
||||
{
|
||||
m_types.insert(std::make_pair(name, ti));
|
||||
add_global_const(const_var(ti), name + "_type");
|
||||
|
||||
#ifndef CHAISCRIPT_NO_THREADS
|
||||
boost::unique_lock<boost::shared_mutex> l(m_mutex);
|
||||
#endif
|
||||
|
||||
m_state.m_types.insert(std::make_pair(name, ti));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -300,9 +428,13 @@ namespace chaiscript
|
||||
*/
|
||||
Type_Info get_type(const std::string &name) const
|
||||
{
|
||||
Type_Name_Map::const_iterator itr = m_types.find(name);
|
||||
#ifndef CHAISCRIPT_NO_THREADS
|
||||
boost::shared_lock<boost::shared_mutex> l(m_mutex);
|
||||
#endif
|
||||
|
||||
if (itr != m_types.end())
|
||||
Type_Name_Map::const_iterator itr = m_state.m_types.find(name);
|
||||
|
||||
if (itr != m_state.m_types.end())
|
||||
{
|
||||
return itr->second;
|
||||
}
|
||||
@@ -317,17 +449,21 @@ namespace chaiscript
|
||||
*/
|
||||
std::string get_type_name(const Type_Info &ti) const
|
||||
{
|
||||
for (Type_Name_Map::const_iterator itr = m_types.begin();
|
||||
itr != m_types.end();
|
||||
#ifndef CHAISCRIPT_NO_THREADS
|
||||
boost::shared_lock<boost::shared_mutex> l(m_mutex);
|
||||
#endif
|
||||
|
||||
for (Type_Name_Map::const_iterator itr = m_state.m_types.begin();
|
||||
itr != m_state.m_types.end();
|
||||
++itr)
|
||||
{
|
||||
if (itr->second.m_bare_type_info == ti.m_bare_type_info)
|
||||
if (itr->second.bare_equal(ti))
|
||||
{
|
||||
return itr->first;
|
||||
}
|
||||
}
|
||||
|
||||
return ti.m_bare_type_info->name();
|
||||
return ti.bare_name();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -335,17 +471,21 @@ namespace chaiscript
|
||||
*/
|
||||
std::vector<std::pair<std::string, Type_Info> > get_types() const
|
||||
{
|
||||
return std::vector<std::pair<std::string, Type_Info> >(m_types.begin(), m_types.end());
|
||||
#ifndef CHAISCRIPT_NO_THREADS
|
||||
boost::shared_lock<boost::shared_mutex> l(m_mutex);
|
||||
#endif
|
||||
|
||||
return std::vector<std::pair<std::string, Type_Info> >(m_state.m_types.begin(), m_state.m_types.end());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a function by name
|
||||
*/
|
||||
std::vector<std::pair<std::string, std::multimap<std::string, Proxy_Function >::mapped_type> >
|
||||
std::vector<std::pair<std::string, std::multimap<std::string, Proxy_Function >::mapped_type> >
|
||||
get_function(const std::string &t_name) const
|
||||
{
|
||||
std::pair<std::multimap<std::string, Proxy_Function >::const_iterator, std::multimap<std::string, Proxy_Function >::const_iterator> range
|
||||
= m_functions.equal_range(t_name);
|
||||
= get_function_cache().equal_range(t_name);
|
||||
|
||||
return std::vector<std::pair<std::string, std::multimap<std::string, Proxy_Function >::mapped_type> >(range.first, range.second);
|
||||
}
|
||||
@@ -355,7 +495,8 @@ namespace chaiscript
|
||||
*/
|
||||
bool function_exists(const std::string &name) const
|
||||
{
|
||||
return m_functions.find(name) != m_functions.end();
|
||||
std::multimap<std::string, Proxy_Function> &functions = get_function_cache();
|
||||
return functions.find(name) != functions.end();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -363,22 +504,206 @@ namespace chaiscript
|
||||
*/
|
||||
std::vector<std::pair<std::string, Proxy_Function > > get_functions() const
|
||||
{
|
||||
return std::vector<std::pair<std::string, Proxy_Function > >(m_functions.begin(), m_functions.end());
|
||||
std::multimap<std::string, Proxy_Function> &functions = get_function_cache();
|
||||
return std::vector<std::pair<std::string, Proxy_Function > >(functions.begin(), functions.end());
|
||||
}
|
||||
|
||||
void add_reserved_word(const std::string &name)
|
||||
{
|
||||
m_reserved_words.insert(name);
|
||||
#ifndef CHAISCRIPT_NO_THREADS
|
||||
boost::unique_lock<boost::shared_mutex> l(m_mutex);
|
||||
#endif
|
||||
|
||||
m_state.m_reserved_words.insert(name);
|
||||
}
|
||||
|
||||
Boxed_Value call_function(const std::string &t_name, const std::vector<Boxed_Value> ¶ms) const
|
||||
{
|
||||
std::multimap<std::string, Proxy_Function> &functions = get_function_cache();
|
||||
std::pair<std::multimap<std::string, Proxy_Function >::const_iterator, std::multimap<std::string, Proxy_Function >::const_iterator> range
|
||||
= functions.equal_range(t_name);
|
||||
|
||||
return dispatch(range.first, range.second, params);
|
||||
}
|
||||
|
||||
Boxed_Value call_function(const std::string &t_name) const
|
||||
{
|
||||
return call_function(t_name, std::vector<Boxed_Value>());
|
||||
}
|
||||
|
||||
Boxed_Value call_function(const std::string &t_name, const Boxed_Value &p1) const
|
||||
{
|
||||
std::vector<Boxed_Value> params;
|
||||
params.push_back(p1);
|
||||
return call_function(t_name, params);
|
||||
}
|
||||
|
||||
Boxed_Value call_function(const std::string &t_name, const Boxed_Value &p1, const Boxed_Value &p2) const
|
||||
{
|
||||
std::vector<Boxed_Value> params;
|
||||
params.push_back(p1);
|
||||
params.push_back(p2);
|
||||
return call_function(t_name, params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump object info to stdout
|
||||
*/
|
||||
void dump_object(Boxed_Value o) const
|
||||
{
|
||||
Type_Info ti = o.get_type_info();
|
||||
std::cout << (ti.is_const()?"const ":"") << get_type_name(ti) << std::endl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump type info to stdout
|
||||
*/
|
||||
void dump_type(const Type_Info &type) const
|
||||
{
|
||||
std::cout << (type.is_const()?"const ":"") << get_type_name(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump function to stdout
|
||||
*/
|
||||
void dump_function(const std::pair<const std::string, Proxy_Function > &f) const
|
||||
{
|
||||
std::vector<Type_Info> params = f.second->get_param_types();
|
||||
std::string annotation = f.second->annotation();
|
||||
|
||||
if (annotation.size() > 0) {
|
||||
std::cout << annotation;
|
||||
}
|
||||
dump_type(params.front());
|
||||
std::cout << " " << f.first << "(";
|
||||
|
||||
for (std::vector<Type_Info>::const_iterator itr = params.begin() + 1;
|
||||
itr != params.end();
|
||||
)
|
||||
{
|
||||
dump_type(*itr);
|
||||
++itr;
|
||||
|
||||
if (itr != params.end())
|
||||
{
|
||||
std::cout << ", ";
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << ") " << std::endl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump all system info to stdout
|
||||
*/
|
||||
void dump_system() const
|
||||
{
|
||||
std::cout << "Registered Types: " << std::endl;
|
||||
std::vector<std::pair<std::string, Type_Info> > types = get_types();
|
||||
for (std::vector<std::pair<std::string, Type_Info> >::const_iterator itr = types.begin();
|
||||
itr != types.end();
|
||||
++itr)
|
||||
{
|
||||
std::cout << itr->first << ": ";
|
||||
std::cout << itr->second.bare_name();
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
std::vector<std::pair<std::string, Proxy_Function > > funcs = get_functions();
|
||||
|
||||
std::cout << "Functions: " << std::endl;
|
||||
for (std::vector<std::pair<std::string, Proxy_Function > >::const_iterator itr = funcs.begin();
|
||||
itr != funcs.end();
|
||||
++itr)
|
||||
{
|
||||
dump_function(*itr);
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
/**
|
||||
* return true if the Boxed_Value matches the registered type by name
|
||||
*/
|
||||
bool is_type(Boxed_Value r, const std::string &user_typename) const
|
||||
{
|
||||
try {
|
||||
if (get_type(user_typename).bare_equal(r.get_type_info()))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
} catch (const std::range_error &) {
|
||||
}
|
||||
|
||||
try {
|
||||
const Dynamic_Object &d = boxed_cast<const Dynamic_Object &>(r);
|
||||
return d.get_type_name() == user_typename;
|
||||
} catch (const std::bad_cast &) {
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string type_name(Boxed_Value obj) const
|
||||
{
|
||||
return get_type_name(obj.get_type_info());
|
||||
}
|
||||
|
||||
State get_state()
|
||||
{
|
||||
#ifndef CHAISCRIPT_NO_THREADS
|
||||
boost::unique_lock<boost::shared_mutex> l(m_mutex);
|
||||
boost::unique_lock<boost::shared_mutex> l2(m_global_object_mutex);
|
||||
#endif
|
||||
|
||||
return m_state;
|
||||
}
|
||||
|
||||
void set_state(const State &t_state)
|
||||
{
|
||||
#ifndef CHAISCRIPT_NO_THREADS
|
||||
boost::unique_lock<boost::shared_mutex> l(m_mutex);
|
||||
boost::unique_lock<boost::shared_mutex> l2(m_global_object_mutex);
|
||||
#endif
|
||||
|
||||
m_state = t_state;
|
||||
sync_cache_no_lock();
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
/**
|
||||
* Returns the current stack
|
||||
* make const/non const versions
|
||||
*/
|
||||
StackData &get_stack_data() const
|
||||
{
|
||||
return *(m_stack_holder->stack);
|
||||
}
|
||||
|
||||
std::multimap<std::string, Proxy_Function> &get_function_cache() const
|
||||
{
|
||||
return m_stack_holder->function_cache;
|
||||
}
|
||||
|
||||
void sync_cache_no_lock()
|
||||
{
|
||||
m_stack_holder->stack->get<0>().clear();
|
||||
|
||||
get_function_cache() = m_state.m_functions;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Throw a reserved_word exception if the name is not allowed
|
||||
*/
|
||||
void validate_object_name(const std::string &name)
|
||||
void validate_object_name(const std::string &name) const
|
||||
{
|
||||
if (m_reserved_words.find(name) != m_reserved_words.end())
|
||||
#ifndef CHAISCRIPT_NO_THREADS
|
||||
boost::shared_lock<boost::shared_mutex> l(m_mutex);
|
||||
#endif
|
||||
|
||||
if (m_state.m_reserved_words.find(name) != m_state.m_reserved_words.end())
|
||||
{
|
||||
throw reserved_word_error(name);
|
||||
}
|
||||
@@ -391,8 +716,12 @@ namespace chaiscript
|
||||
*/
|
||||
bool add_function(const Proxy_Function &f, const std::string &t_name)
|
||||
{
|
||||
#ifndef CHAISCRIPT_NO_THREADS
|
||||
boost::unique_lock<boost::shared_mutex> l(m_mutex);
|
||||
#endif
|
||||
|
||||
std::pair<std::multimap<std::string, Proxy_Function >::const_iterator, std::multimap<std::string, Proxy_Function >::const_iterator> range
|
||||
= m_functions.equal_range(t_name);
|
||||
= m_state.m_functions.equal_range(t_name);
|
||||
|
||||
while (range.first != range.second)
|
||||
{
|
||||
@@ -403,110 +732,37 @@ namespace chaiscript
|
||||
++range.first;
|
||||
}
|
||||
|
||||
m_functions.insert(std::make_pair(t_name, f));
|
||||
m_state.m_functions.insert(std::make_pair(t_name, f));
|
||||
get_function_cache().insert(std::make_pair(t_name, f));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Stack m_scopes;
|
||||
#ifndef CHAISCRIPT_NO_THREADS
|
||||
mutable boost::shared_mutex m_mutex;
|
||||
mutable boost::shared_mutex m_global_object_mutex;
|
||||
#endif
|
||||
|
||||
std::multimap<std::string, Proxy_Function > m_functions;
|
||||
Type_Name_Map m_types;
|
||||
Boxed_Value m_place_holder;
|
||||
std::set<std::string> m_reserved_words;
|
||||
};
|
||||
|
||||
/**
|
||||
* Dump object info to stdout
|
||||
*/
|
||||
void dump_object(Boxed_Value o, const Dispatch_Engine &e)
|
||||
{
|
||||
Type_Info ti = o.get_type_info();
|
||||
std::cout << (ti.m_is_const?"const ":"") << e.get_type_name(ti) << std::endl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump type info to stdout
|
||||
*/
|
||||
void dump_type(const Type_Info &type, const Dispatch_Engine &e)
|
||||
{
|
||||
std::cout << (type.m_is_const?"const ":"") << e.get_type_name(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump function to stdout
|
||||
*/
|
||||
void dump_function(const std::pair<const std::string, Proxy_Function > &f, const Dispatch_Engine &e)
|
||||
{
|
||||
std::vector<Type_Info> params = f.second->get_param_types();
|
||||
std::string annotation = f.second->annotation();
|
||||
|
||||
if (annotation.size() > 0) {
|
||||
std::cout << annotation;
|
||||
}
|
||||
dump_type(params.front(), e);
|
||||
std::cout << " " << f.first << "(";
|
||||
|
||||
for (std::vector<Type_Info>::const_iterator itr = params.begin() + 1;
|
||||
itr != params.end();
|
||||
)
|
||||
{
|
||||
dump_type(*itr, e);
|
||||
++itr;
|
||||
|
||||
if (itr != params.end())
|
||||
struct Stack_Holder
|
||||
{
|
||||
std::cout << ", ";
|
||||
}
|
||||
}
|
||||
Stack_Holder()
|
||||
: stack(new StackData())
|
||||
{
|
||||
stack->get<2>() = true;
|
||||
}
|
||||
|
||||
std::cout << ") " << std::endl;
|
||||
}
|
||||
Stack stack;
|
||||
|
||||
/**
|
||||
* Dump all system info to stdout
|
||||
*/
|
||||
void dump_system(const Dispatch_Engine &s)
|
||||
{
|
||||
std::cout << "Registered Types: " << std::endl;
|
||||
std::vector<std::pair<std::string, Type_Info> > types = s.get_types();
|
||||
for (std::vector<std::pair<std::string, Type_Info> >::const_iterator itr = types.begin();
|
||||
itr != types.end();
|
||||
++itr)
|
||||
{
|
||||
std::cout << itr->first << ": ";
|
||||
std::cout << itr->second.m_bare_type_info->name();
|
||||
std::cout << std::endl;
|
||||
}
|
||||
std::multimap<std::string, Proxy_Function> function_cache;
|
||||
};
|
||||
|
||||
std::cout << std::endl;
|
||||
std::vector<std::pair<std::string, Proxy_Function > > funcs = s.get_functions();
|
||||
chaiscript::threading::Thread_Storage<Stack_Holder> m_stack_holder;
|
||||
|
||||
std::cout << "Functions: " << std::endl;
|
||||
for (std::vector<std::pair<std::string, Proxy_Function > >::const_iterator itr = funcs.begin();
|
||||
itr != funcs.end();
|
||||
++itr)
|
||||
{
|
||||
dump_function(*itr, s);
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
/**
|
||||
* return true if the Boxed_Value matches the registered type by name
|
||||
*/
|
||||
bool is_type(const Dispatch_Engine &e, const std::string &user_typename, Boxed_Value r)
|
||||
{
|
||||
try {
|
||||
return e.get_type(user_typename) == r.get_type_info();
|
||||
} catch (const std::range_error &) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
State m_state;
|
||||
|
||||
std::string type_name(const Dispatch_Engine &e, Boxed_Value obj)
|
||||
{
|
||||
return e.get_type_name(obj.get_type_info());
|
||||
}
|
||||
Boxed_Value m_place_holder;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
226
include/chaiscript/dispatchkit/dynamic_object.hpp
Normal file
226
include/chaiscript/dispatchkit/dynamic_object.hpp
Normal file
@@ -0,0 +1,226 @@
|
||||
#ifndef __DYNAMIC_OBJECT_HPP__
|
||||
#define __DYNAMIC_OBJECT_HPP__
|
||||
|
||||
#include <boost/optional.hpp>
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
class Dynamic_Object
|
||||
{
|
||||
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)
|
||||
{
|
||||
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
|
||||
{
|
||||
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))
|
||||
{
|
||||
return m_func->call_match(vals);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
virtual Boxed_Value operator()(const std::vector<Boxed_Value> ¶ms) const
|
||||
{
|
||||
if (dynamic_object_typename_match(params, m_type_name, m_ti))
|
||||
{
|
||||
return (*m_func)(params);
|
||||
} else {
|
||||
throw guard_error();
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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 bvs[0].get_type_info().bare_equal(*ti);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} 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
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
++begin;
|
||||
}
|
||||
|
||||
return std::vector<Type_Info>(begin, end);
|
||||
}
|
||||
|
||||
virtual ~Dynamic_Object_Constructor() {}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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());
|
||||
|
||||
return m_func->call_match(new_vals);
|
||||
}
|
||||
|
||||
virtual Boxed_Value operator()(const std::vector<Boxed_Value> ¶ms) 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;
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
private:
|
||||
std::string m_type_name;
|
||||
Proxy_Function m_func;
|
||||
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
@@ -1,6 +1,6 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009, Jonathan Turner (jturner@minnow-lang.org)
|
||||
// Copyright 2009-2010, Jonathan Turner (jturner@minnow-lang.org)
|
||||
// and Jason Turner (lefticus@gmail.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009, Jonathan Turner (jturner@minnow-lang.org)
|
||||
// Copyright 2009-2010, Jonathan Turner (jturner@minnow-lang.org)
|
||||
// and Jason Turner (lefticus@gmail.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
@@ -93,6 +93,7 @@ namespace chaiscript
|
||||
|
||||
}
|
||||
}
|
||||
#undef n
|
||||
|
||||
#endif
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009, Jonathan Turner (jturner@minnow-lang.org)
|
||||
// Copyright 2009-2010, Jonathan Turner (jturner@minnow-lang.org)
|
||||
// and Jason Turner (lefticus@gmail.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
@@ -23,29 +23,39 @@ namespace chaiscript
|
||||
template<typename Ret>
|
||||
struct Handle_Return
|
||||
{
|
||||
static Boxed_Value call(const boost::function<Ret ()> &f)
|
||||
static Boxed_Value handle(const Ret &r)
|
||||
{
|
||||
return Boxed_Value(f());
|
||||
return Boxed_Value(r);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Ret>
|
||||
struct Handle_Return<boost::shared_ptr<Ret> &>
|
||||
{
|
||||
static Boxed_Value call(const boost::function<boost::shared_ptr<Ret> & ()> &f)
|
||||
static Boxed_Value handle(const boost::shared_ptr<Ret> &r)
|
||||
{
|
||||
return Boxed_Value(f());
|
||||
return Boxed_Value(r);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Ret>
|
||||
struct Handle_Return<const boost::shared_ptr<Ret> &>
|
||||
{
|
||||
static Boxed_Value call(const boost::function<const boost::shared_ptr<Ret> & ()> &f)
|
||||
static Boxed_Value handle(const boost::shared_ptr<Ret> &r)
|
||||
{
|
||||
return Boxed_Value(f());
|
||||
return Boxed_Value(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
|
||||
@@ -53,9 +63,14 @@ namespace chaiscript
|
||||
template<typename Ret>
|
||||
struct Handle_Return<Ret &>
|
||||
{
|
||||
static Boxed_Value call(const boost::function<Ret &()> &f)
|
||||
static Boxed_Value handle(Ret &r)
|
||||
{
|
||||
return Boxed_Value(boost::ref(f()));
|
||||
return Boxed_Value(boost::ref(r));
|
||||
}
|
||||
|
||||
static Boxed_Value handle(const Ret &r)
|
||||
{
|
||||
return Boxed_Value(boost::cref(r));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -65,9 +80,9 @@ namespace chaiscript
|
||||
template<>
|
||||
struct Handle_Return<Boxed_Value>
|
||||
{
|
||||
static Boxed_Value call(const boost::function<Boxed_Value ()> &f)
|
||||
static Boxed_Value handle(const Boxed_Value &r)
|
||||
{
|
||||
return f();
|
||||
return r;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -77,21 +92,33 @@ namespace chaiscript
|
||||
template<>
|
||||
struct Handle_Return<Boxed_Value &>
|
||||
{
|
||||
static Boxed_Value call(const boost::function<Boxed_Value &()> &f)
|
||||
static Boxed_Value handle(const Boxed_Value &r)
|
||||
{
|
||||
return f();
|
||||
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<void>
|
||||
{
|
||||
static Boxed_Value call(const boost::function<void ()> &f)
|
||||
static Boxed_Value handle()
|
||||
{
|
||||
f();
|
||||
return Boxed_Value(Boxed_Value::Void_Type());
|
||||
}
|
||||
};
|
||||
|
442
include/chaiscript/dispatchkit/operators.hpp
Normal file
442
include/chaiscript/dispatchkit/operators.hpp
Normal file
@@ -0,0 +1,442 @@
|
||||
#ifndef __CHAISCRIPT_OPERATORS_HPP__
|
||||
#define __CHAISCRIPT_OPERATORS_HPP__
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
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)
|
||||
{
|
||||
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(¬_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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@@ -1,6 +1,6 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009, Jonathan Turner (jturner@minnow-lang.org)
|
||||
// Copyright 2009-2010, Jonathan Turner (jturner@minnow-lang.org)
|
||||
// and Jason Turner (lefticus@gmail.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
@@ -61,6 +61,7 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
}
|
||||
#undef n
|
||||
|
||||
#endif
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009, Jonathan Turner (jturner@minnow-lang.org)
|
||||
// Copyright 2009-2010, Jonathan Turner (jturner@minnow-lang.org)
|
||||
// and Jason Turner (lefticus@gmail.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
#include "type_info.hpp"
|
||||
#include <string>
|
||||
#include <boost/function.hpp>
|
||||
|
||||
#include <boost/type_traits/add_reference.hpp>
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
#include "proxy_functions_detail.hpp"
|
||||
@@ -63,8 +63,10 @@ namespace chaiscript
|
||||
{
|
||||
public:
|
||||
virtual ~Proxy_Function_Base() {}
|
||||
virtual Boxed_Value operator()(const std::vector<Boxed_Value> ¶ms) = 0;
|
||||
virtual std::vector<Type_Info> get_param_types() const = 0;
|
||||
virtual Boxed_Value operator()(const std::vector<Boxed_Value> ¶ms) const = 0;
|
||||
|
||||
std::vector<Type_Info> get_param_types() const { return m_types; }
|
||||
|
||||
virtual bool operator==(const Proxy_Function_Base &) const = 0;
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals) const = 0;
|
||||
|
||||
@@ -91,10 +93,11 @@ namespace chaiscript
|
||||
|
||||
const Type_Info &ti = types[1];
|
||||
|
||||
if (!ti.m_bare_type_info || !(vals[0].get_type_info().m_bare_type_info)
|
||||
|| (*ti.m_bare_type_info) == (*user_type<Boxed_Value>().m_bare_type_info)
|
||||
|| (*ti.m_bare_type_info) == (*user_type<Boxed_POD_Value>().m_bare_type_info)
|
||||
|| (*vals[0].get_type_info().m_bare_type_info) == (*ti.m_bare_type_info))
|
||||
|
||||
if (ti.is_undef() || vals[0].get_type_info().is_undef()
|
||||
|| ti.bare_equal(user_type<Boxed_Value>())
|
||||
|| ti.bare_equal(user_type<Boxed_POD_Value>())
|
||||
|| ti.bare_equal(vals[0].get_type_info()))
|
||||
{
|
||||
return true;
|
||||
} else {
|
||||
@@ -109,9 +112,36 @@ namespace chaiscript
|
||||
virtual int get_arity() const = 0;
|
||||
|
||||
virtual std::string annotation() const = 0;
|
||||
|
||||
protected:
|
||||
Proxy_Function_Base(const std::vector<Type_Info> &t_types)
|
||||
: m_types(t_types)
|
||||
{
|
||||
}
|
||||
|
||||
bool compare_types(const std::vector<Type_Info> &tis, const std::vector<Boxed_Value> &bvs) const
|
||||
{
|
||||
if (tis.size() - 1 != bvs.size())
|
||||
{
|
||||
return false;
|
||||
} else {
|
||||
const int size = bvs.size();
|
||||
for (int i = 0; i < size; ++i)
|
||||
{
|
||||
if (!(tis[i+1].bare_equal(bvs[i].get_type_info()) && tis[i+1].is_const() >= bvs[i].get_type_info().is_const() ))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<Type_Info> m_types;
|
||||
};
|
||||
|
||||
typedef boost::shared_ptr<Proxy_Function_Base> Proxy_Function;
|
||||
typedef boost::shared_ptr<const Proxy_Function_Base> Const_Proxy_Function;
|
||||
|
||||
/**
|
||||
* Exception thrown if a function's guard fails to execute
|
||||
@@ -139,8 +169,8 @@ namespace chaiscript
|
||||
int t_arity=-1,
|
||||
const std::string &t_description = "",
|
||||
const Proxy_Function &t_guard = Proxy_Function())
|
||||
: m_f(t_f), m_arity(t_arity), m_description(t_description), m_guard(t_guard),
|
||||
m_types(build_param_type_list(t_arity))
|
||||
: Proxy_Function_Base(build_param_type_list(t_arity)),
|
||||
m_f(t_f), m_arity(t_arity), m_description(t_description), m_guard(t_guard)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -157,7 +187,7 @@ namespace chaiscript
|
||||
|
||||
virtual ~Dynamic_Proxy_Function() {}
|
||||
|
||||
virtual Boxed_Value operator()(const std::vector<Boxed_Value> ¶ms)
|
||||
virtual Boxed_Value operator()(const std::vector<Boxed_Value> ¶ms) const
|
||||
{
|
||||
if (m_arity < 0 || params.size() == size_t(m_arity))
|
||||
{
|
||||
@@ -179,11 +209,6 @@ namespace chaiscript
|
||||
return m_arity;
|
||||
}
|
||||
|
||||
virtual std::vector<Type_Info> get_param_types() const
|
||||
{
|
||||
return m_types;
|
||||
}
|
||||
|
||||
virtual std::string annotation() const
|
||||
{
|
||||
return m_description;
|
||||
@@ -229,7 +254,6 @@ namespace chaiscript
|
||||
int m_arity;
|
||||
std::string m_description;
|
||||
Proxy_Function m_guard;
|
||||
std::vector<Type_Info> m_types;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -249,9 +273,10 @@ namespace chaiscript
|
||||
class Bound_Function : public Proxy_Function_Base
|
||||
{
|
||||
public:
|
||||
Bound_Function(const Proxy_Function &t_f,
|
||||
Bound_Function(const Const_Proxy_Function &t_f,
|
||||
const std::vector<Boxed_Value> &t_args)
|
||||
: m_f(t_f), m_args(t_args), m_arity(m_f->get_arity()<0?-1:(m_f->get_arity() - m_args.size()))
|
||||
: Proxy_Function_Base(std::vector<Type_Info>()),
|
||||
m_f(t_f), m_args(t_args), m_arity(m_f->get_arity()<0?-1:(m_f->get_arity() - m_args.size()))
|
||||
{
|
||||
}
|
||||
|
||||
@@ -267,7 +292,7 @@ namespace chaiscript
|
||||
return m_f->call_match(build_param_list(vals));
|
||||
}
|
||||
|
||||
virtual Boxed_Value operator()(const std::vector<Boxed_Value> ¶ms)
|
||||
virtual Boxed_Value operator()(const std::vector<Boxed_Value> ¶ms) const
|
||||
{
|
||||
return (*m_f)(build_param_list(params));
|
||||
}
|
||||
@@ -310,11 +335,6 @@ namespace chaiscript
|
||||
return args;
|
||||
}
|
||||
|
||||
virtual std::vector<Type_Info> get_param_types() const
|
||||
{
|
||||
return std::vector<Type_Info>();
|
||||
}
|
||||
|
||||
virtual int get_arity() const
|
||||
{
|
||||
return m_arity;
|
||||
@@ -326,7 +346,7 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
private:
|
||||
Proxy_Function m_f;
|
||||
Const_Proxy_Function m_f;
|
||||
std::vector<Boxed_Value> m_args;
|
||||
int m_arity;
|
||||
};
|
||||
@@ -341,7 +361,8 @@ namespace chaiscript
|
||||
{
|
||||
public:
|
||||
Proxy_Function_Impl(const boost::function<Func> &f)
|
||||
: m_f(f), m_dummy_func(0), m_types(build_param_type_list(m_dummy_func))
|
||||
: Proxy_Function_Base(build_param_type_list(static_cast<Func *>(0))),
|
||||
m_f(f), m_dummy_func(0)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -357,14 +378,9 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
virtual Boxed_Value operator()(const std::vector<Boxed_Value> ¶ms)
|
||||
virtual Boxed_Value operator()(const std::vector<Boxed_Value> ¶ms) const
|
||||
{
|
||||
return call_func(m_f, params);
|
||||
}
|
||||
|
||||
virtual std::vector<Type_Info> get_param_types() const
|
||||
{
|
||||
return m_types;
|
||||
return Do_Call<typename boost::function<Func>::result_type>::go(m_f, params);
|
||||
}
|
||||
|
||||
virtual int get_arity() const
|
||||
@@ -375,7 +391,12 @@ namespace chaiscript
|
||||
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals) const
|
||||
{
|
||||
return compare_types(m_dummy_func, vals);
|
||||
if (int(vals.size()) != get_arity())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return compare_types(m_types, vals) || compare_types_cast(m_dummy_func, vals);
|
||||
}
|
||||
|
||||
virtual std::string annotation() const
|
||||
@@ -386,7 +407,81 @@ namespace chaiscript
|
||||
private:
|
||||
boost::function<Func> m_f;
|
||||
Func *m_dummy_func;
|
||||
std::vector<Type_Info> m_types;
|
||||
};
|
||||
|
||||
/**
|
||||
* Attribute getter Proxy_Function implementation
|
||||
*/
|
||||
template<typename T, typename Class>
|
||||
class Attribute_Access : public Proxy_Function_Base
|
||||
{
|
||||
public:
|
||||
Attribute_Access(T Class::* t_attr)
|
||||
: Proxy_Function_Base(param_types()),
|
||||
m_attr(t_attr)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~Attribute_Access() {}
|
||||
|
||||
virtual bool operator==(const Proxy_Function_Base &t_func) const
|
||||
{
|
||||
try {
|
||||
const Attribute_Access<T, Class> &aa
|
||||
= dynamic_cast<const Attribute_Access<T, Class> &>(t_func);
|
||||
return m_attr == aa.m_attr;
|
||||
} catch (const std::bad_cast &) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
virtual Boxed_Value operator()(const std::vector<Boxed_Value> ¶ms) const
|
||||
{
|
||||
if (params.size() == 1)
|
||||
{
|
||||
const Boxed_Value &bv = params[0];
|
||||
if (bv.is_const())
|
||||
{
|
||||
const Class *o = boxed_cast<const Class *>(bv);
|
||||
return Handle_Return<typename boost::add_reference<T>::type>::handle(o->*m_attr);
|
||||
} else {
|
||||
Class *o = boxed_cast<Class *>(bv);
|
||||
return Handle_Return<typename boost::add_reference<T>::type>::handle(o->*m_attr);
|
||||
}
|
||||
} else {
|
||||
throw arity_error(params.size(), 1);
|
||||
}
|
||||
}
|
||||
|
||||
virtual int get_arity() const
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals) const
|
||||
{
|
||||
if (vals.size() != 1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return vals[0].get_type_info().bare_equal(user_type<Class>());
|
||||
}
|
||||
|
||||
virtual std::string annotation() const
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
private:
|
||||
static std::vector<Type_Info> param_types()
|
||||
{
|
||||
std::vector<Type_Info> v;
|
||||
v.push_back(user_type<T>());
|
||||
v.push_back(user_type<Class>());
|
||||
return v;
|
||||
}
|
||||
T Class::* m_attr;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -402,6 +497,11 @@ namespace chaiscript
|
||||
{
|
||||
}
|
||||
|
||||
dispatch_error(bool is_const) throw()
|
||||
: std::runtime_error(std::string("No matching function to dispatch to") + (is_const?", parameter is const":""))
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~dispatch_error() throw() {}
|
||||
};
|
||||
|
||||
@@ -410,17 +510,16 @@ namespace chaiscript
|
||||
* each function against the set of parameters, in order, until a matching
|
||||
* function is found or throw dispatch_error if no matching function is found
|
||||
*/
|
||||
Boxed_Value dispatch(const std::vector<std::pair<std::string, Proxy_Function> > &funcs,
|
||||
template<typename InItr>
|
||||
Boxed_Value dispatch(InItr begin, InItr end,
|
||||
const std::vector<Boxed_Value> &plist)
|
||||
{
|
||||
for (std::vector<std::pair<std::string, Proxy_Function> >::const_iterator itr = funcs.begin();
|
||||
itr != funcs.end();
|
||||
++itr)
|
||||
while (begin != end)
|
||||
{
|
||||
try {
|
||||
if (itr->second->filter(plist))
|
||||
if (begin->second->filter(plist))
|
||||
{
|
||||
return (*itr->second)(plist);
|
||||
return (*begin->second)(plist);
|
||||
}
|
||||
} catch (const bad_boxed_cast &) {
|
||||
//parameter failed to cast, try again
|
||||
@@ -430,8 +529,22 @@ namespace chaiscript
|
||||
//guard failed to allow the function to execute,
|
||||
//try again
|
||||
}
|
||||
++begin;
|
||||
}
|
||||
throw dispatch_error();
|
||||
|
||||
throw dispatch_error(plist.empty()?false:plist[0].is_const());
|
||||
}
|
||||
|
||||
/**
|
||||
* Take a vector of functions and a vector of parameters. Attempt to execute
|
||||
* each function against the set of parameters, in order, until a matching
|
||||
* function is found or throw dispatch_error if no matching function is found
|
||||
*/
|
||||
template<typename Funcs>
|
||||
Boxed_Value dispatch(const Funcs &funcs,
|
||||
const std::vector<Boxed_Value> &plist)
|
||||
{
|
||||
return dispatch(funcs.begin(), funcs.end(), plist);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,17 +1,15 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009, Jonathan Turner (jturner@minnow-lang.org)
|
||||
// Copyright 2009-2010, Jonathan Turner (jturner@minnow-lang.org)
|
||||
// and Jason Turner (lefticus@gmail.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 casthelper(z,n,text) ,chaiscript::boxed_cast< Param ## n >(params[n])
|
||||
#define comparetype(z,n,text) && ((detail::Get_Type_Info<Param ## n>::get() == params[n].get_type_info()))
|
||||
#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__
|
||||
@@ -45,6 +43,27 @@ namespace chaiscript
|
||||
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> ¶ms)
|
||||
{
|
||||
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> ¶ms)
|
||||
{
|
||||
call_func(fun, params);
|
||||
return Handle_Return<void>::handle();
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
#define BOOST_PP_ITERATION_LIMITS ( 0, 10 )
|
||||
@@ -68,7 +87,7 @@ namespace chaiscript
|
||||
std::vector<Type_Info> ti;
|
||||
ti.push_back(detail::Get_Type_Info<Ret>::get());
|
||||
|
||||
BOOST_PP_REPEAT(n, gettypeinfo, ~)
|
||||
BOOST_PP_REPEAT(n, gettypeinfo, ~)
|
||||
|
||||
return ti;
|
||||
}
|
||||
@@ -80,14 +99,14 @@ namespace chaiscript
|
||||
* 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)>
|
||||
Boxed_Value call_func(const boost::function<Ret (BOOST_PP_ENUM_PARAMS(n, Param))> &f,
|
||||
Ret call_func(const boost::function<Ret (BOOST_PP_ENUM_PARAMS(n, Param))> &f,
|
||||
const std::vector<Boxed_Value> ¶ms)
|
||||
{
|
||||
if (params.size() != n)
|
||||
{
|
||||
throw arity_error(params.size(), n);
|
||||
} else {
|
||||
return Handle_Return<Ret>::call(boost::bind(f BOOST_PP_REPEAT(n, casthelper, ~)));
|
||||
return f(BOOST_PP_REPEAT(n, casthelper, ~));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,25 +116,20 @@ namespace chaiscript
|
||||
* 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(Ret (*)(BOOST_PP_ENUM_PARAMS(n, Param)),
|
||||
const std::vector<Boxed_Value> ¶ms)
|
||||
bool compare_types_cast(Ret (*)(BOOST_PP_ENUM_PARAMS(n, Param)),
|
||||
const std::vector<Boxed_Value> & BOOST_PP_IF(n, params, ))
|
||||
{
|
||||
if (params.size() != n)
|
||||
{
|
||||
try {
|
||||
BOOST_PP_REPEAT(n, trycast, ~);
|
||||
} catch (const bad_boxed_cast &) {
|
||||
return false;
|
||||
} else {
|
||||
bool val = true BOOST_PP_REPEAT(n, comparetype, ~);
|
||||
if (val) return true;
|
||||
|
||||
try {
|
||||
BOOST_PP_REPEAT(n, trycast, ~);
|
||||
} catch (const bad_boxed_cast &) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#undef n
|
||||
|
||||
#endif
|
||||
|
@@ -1,102 +1,94 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009, Jonathan Turner (jturner@minnow-lang.org)
|
||||
// Copyright 2009-2010, Jonathan Turner (jturner@minnow-lang.org)
|
||||
// and Jason Turner (lefticus@gmail.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#include <boost/preprocessor.hpp>
|
||||
|
||||
#ifndef BOOST_PP_IS_ITERATING
|
||||
#ifndef __register_function_hpp__
|
||||
#define __register_function_hpp__
|
||||
|
||||
#include "dispatchkit.hpp"
|
||||
#include "bind_first.hpp"
|
||||
#include <boost/function.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#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
|
||||
{
|
||||
/**
|
||||
* Helper function for register_member function
|
||||
*/
|
||||
template<typename T, typename Class>
|
||||
T &get_member(T Class::* m, Class *obj)
|
||||
template<bool Object, bool MemFn>
|
||||
struct Fun_Helper
|
||||
{
|
||||
return (obj->*m);
|
||||
}
|
||||
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)));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
Proxy_Function fun_helper(const boost::function<T> &f)
|
||||
template<>
|
||||
struct Fun_Helper<false, true>
|
||||
{
|
||||
return Proxy_Function(new Proxy_Function_Impl<T>(f));
|
||||
}
|
||||
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))));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Automatically create a get_member helper function for an object
|
||||
* to allow for runtime dispatched access to public data members
|
||||
* for example, the case of std::pair<>::first and std::pair<>::second
|
||||
*/
|
||||
template<typename T, typename Class>
|
||||
Proxy_Function fun_helper(T Class::* m)
|
||||
|
||||
template<>
|
||||
struct Fun_Helper<true, false>
|
||||
{
|
||||
return fun_helper(boost::function<T& (Class *)>(boost::bind(&detail::get_member<T, Class>, m, _1)));
|
||||
}
|
||||
template<typename T, typename Class>
|
||||
static Proxy_Function go(T Class::* m)
|
||||
{
|
||||
return Proxy_Function(new Attribute_Access<T, Class>(m));
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#define BOOST_PP_ITERATION_LIMITS ( 0, 10 )
|
||||
#define BOOST_PP_FILENAME_1 <chaiscript/dispatchkit/register_function.hpp>
|
||||
#include BOOST_PP_ITERATE()
|
||||
template<typename T>
|
||||
Proxy_Function fun(const boost::function<T> &f)
|
||||
{
|
||||
return Proxy_Function(new Proxy_Function_Impl<T>(f));
|
||||
}
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
template<typename T>
|
||||
Proxy_Function fun(T t)
|
||||
{
|
||||
return detail::fun_helper(t);
|
||||
return detail::Fun_Helper<boost::function_types::is_member_object_pointer<T>::value, boost::function_types::is_member_function_pointer<T>::value>::go(t);
|
||||
}
|
||||
|
||||
template<typename T, typename Q>
|
||||
Proxy_Function fun(T t, const Q &q)
|
||||
{
|
||||
return fun(bind_first(t, q));
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
# endif
|
||||
#else
|
||||
# define n BOOST_PP_ITERATION()
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
/**
|
||||
* Register a global function of n parameters with name
|
||||
*/
|
||||
template<typename Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param)>
|
||||
Proxy_Function fun_helper(Ret (*f)(BOOST_PP_ENUM_PARAMS(n, Param)))
|
||||
{
|
||||
return fun_helper(boost::function<Ret (BOOST_PP_ENUM_PARAMS(n, Param))>(f));
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a class method of n parameters with name
|
||||
*/
|
||||
template<typename Ret, typename Class BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param)>
|
||||
Proxy_Function fun_helper(Ret (Class::*f)(BOOST_PP_ENUM_PARAMS(n, Param)))
|
||||
{
|
||||
return fun_helper(boost::function<Ret (Class* BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, Param))>(f));
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a const class method of n parameters with name
|
||||
*/
|
||||
template<typename Ret, typename Class BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param)>
|
||||
Proxy_Function fun_helper(Ret (Class::*f)(BOOST_PP_ENUM_PARAMS(n, Param))const)
|
||||
{
|
||||
return fun_helper(boost::function<Ret (const Class* BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, Param))>(f));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009, Jonathan Turner (jturner@minnow-lang.org)
|
||||
// Copyright 2009-2010, Jonathan Turner (jturner@minnow-lang.org)
|
||||
// and Jason Turner (lefticus@gmail.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
@@ -21,60 +21,102 @@ namespace chaiscript
|
||||
/**
|
||||
* compile time deduced information about a type
|
||||
*/
|
||||
struct Type_Info
|
||||
class Type_Info
|
||||
{
|
||||
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)
|
||||
: m_is_const(t_is_const), m_is_reference(t_is_reference), m_is_pointer(t_is_pointer),
|
||||
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)
|
||||
: 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_type_info(t_ti), m_bare_type_info(t_bareti),
|
||||
m_is_unknown(false)
|
||||
{
|
||||
}
|
||||
m_type_info(t_ti), m_bare_type_info(t_bareti),
|
||||
m_is_undef(false)
|
||||
{
|
||||
}
|
||||
|
||||
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_unknown(true)
|
||||
{
|
||||
}
|
||||
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_undef(true)
|
||||
{
|
||||
}
|
||||
|
||||
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_bare_type_info(ti.m_bare_type_info),
|
||||
m_is_unknown(ti.m_is_unknown)
|
||||
{
|
||||
}
|
||||
Type_Info &operator=(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_bare_type_info = ti.m_bare_type_info;
|
||||
m_is_unknown = ti.m_is_unknown;
|
||||
return *this;
|
||||
}
|
||||
bool operator<(const Type_Info &ti) const
|
||||
{
|
||||
return m_type_info < ti.m_type_info;
|
||||
}
|
||||
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_bare_type_info(ti.m_bare_type_info),
|
||||
m_is_undef(ti.m_is_undef)
|
||||
{
|
||||
}
|
||||
|
||||
bool operator==(const Type_Info &ti) const
|
||||
{
|
||||
return ti.m_type_info == m_type_info;
|
||||
}
|
||||
Type_Info &operator=(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_bare_type_info = ti.m_bare_type_info;
|
||||
m_is_undef = ti.m_is_undef;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool m_is_const;
|
||||
bool m_is_reference;
|
||||
bool m_is_pointer;
|
||||
bool m_is_void;
|
||||
const std::type_info *m_type_info;
|
||||
const std::type_info *m_bare_type_info;
|
||||
bool m_is_unknown;
|
||||
bool operator<(const Type_Info &ti) const
|
||||
{
|
||||
return m_type_info < ti.m_type_info;
|
||||
}
|
||||
|
||||
bool operator==(const Type_Info &ti) const
|
||||
{
|
||||
return ti.m_type_info == m_type_info
|
||||
|| (ti.m_type_info && m_type_info && *ti.m_type_info == *m_type_info);
|
||||
}
|
||||
|
||||
bool operator==(const std::type_info &ti) const
|
||||
{
|
||||
return m_type_info != 0 && (*m_type_info) == ti;
|
||||
}
|
||||
|
||||
bool bare_equal(const Type_Info &ti) const
|
||||
{
|
||||
return ti.m_bare_type_info == m_bare_type_info
|
||||
|| (ti.m_bare_type_info && m_bare_type_info && *ti.m_bare_type_info == *m_bare_type_info);
|
||||
}
|
||||
|
||||
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_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
|
||||
{
|
||||
if (m_bare_type_info)
|
||||
{
|
||||
return m_bare_type_info->name();
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
bool m_is_const;
|
||||
bool m_is_reference;
|
||||
bool m_is_pointer;
|
||||
bool m_is_void;
|
||||
const std::type_info *m_type_info;
|
||||
const std::type_info *m_bare_type_info;
|
||||
bool m_is_undef;
|
||||
};
|
||||
|
||||
namespace detail
|
||||
@@ -144,7 +186,6 @@ namespace chaiscript
|
||||
return detail::Get_Type_Info<T>::get();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
149
include/chaiscript/language/chaiscript_common.hpp
Normal file
149
include/chaiscript/language/chaiscript_common.hpp
Normal file
@@ -0,0 +1,149 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2010, Jonathan Turner (jturner@minnow-lang.org)
|
||||
// and Jason Turner (lefticus@gmail.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#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
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
typedef ModulePtr (*Create_Module_Func)();
|
||||
|
||||
/**
|
||||
* Types of AST nodes available to the parser and eval
|
||||
*/
|
||||
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}; };
|
||||
|
||||
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];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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() : line(0), column(0) { }
|
||||
};
|
||||
|
||||
typedef boost::shared_ptr<struct Token> TokenPtr;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
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 &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) {
|
||||
}
|
||||
|
||||
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 &filename)
|
||||
: std::runtime_error("File Not Found: " + filename)
|
||||
{ }
|
||||
|
||||
virtual ~File_Not_Found_Error() throw() {}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* 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) { }
|
||||
};
|
||||
|
||||
/**
|
||||
* Special type indicating a call to 'break'
|
||||
*/
|
||||
struct Break_Loop {
|
||||
TokenPtr location;
|
||||
|
||||
Break_Loop(const TokenPtr where) : location(where) { }
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* _CHAISCRIPT_COMMON_HPP */
|
||||
|
@@ -1,6 +1,6 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009, Jonathan Turner (jturner@minnow-lang.org)
|
||||
// Copyright 2009-2010, Jonathan Turner (jturner@minnow-lang.org)
|
||||
// and Jason Turner (lefticus@gmail.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
@@ -10,42 +10,286 @@
|
||||
#include <exception>
|
||||
#include <fstream>
|
||||
|
||||
#include <chaiscript/language/chaiscript_common.hpp>
|
||||
|
||||
#include "chaiscript_prelude.hpp"
|
||||
#include "chaiscript_parser.hpp"
|
||||
#ifdef _POSIX_VERSION
|
||||
#include <dlfcn.h>
|
||||
#else
|
||||
#ifdef WIN32
|
||||
#include <Windows.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <chaiscript/language/chaiscript_prelude.hpp>
|
||||
#include <chaiscript/language/chaiscript_parser.hpp>
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
struct load_module_error : std::runtime_error
|
||||
{
|
||||
load_module_error(const std::string &reason) throw()
|
||||
: std::runtime_error(reason)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~load_module_error() throw()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef _POSIX_VERSION
|
||||
struct Loadable_Module
|
||||
{
|
||||
struct DLModule
|
||||
{
|
||||
DLModule(const std::string &t_filename)
|
||||
: m_data(dlopen(t_filename.c_str(), RTLD_NOW))
|
||||
{
|
||||
if (!m_data)
|
||||
{
|
||||
throw load_module_error(dlerror());
|
||||
}
|
||||
}
|
||||
|
||||
DLModule(const DLModule &); // Explicitly unimplemented copy constructor
|
||||
DLModule &operator=(const DLModule &); // Explicitly unimplemented assignment operator
|
||||
|
||||
~DLModule()
|
||||
{
|
||||
dlclose(m_data);
|
||||
}
|
||||
|
||||
void *m_data;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct DLSym
|
||||
{
|
||||
DLSym(DLModule &t_mod, const std::string &t_symbol)
|
||||
: m_symbol(reinterpret_cast<T>(dlsym(t_mod.m_data, t_symbol.c_str())))
|
||||
{
|
||||
if (!m_symbol)
|
||||
{
|
||||
throw load_module_error(dlerror());
|
||||
}
|
||||
}
|
||||
|
||||
T m_symbol;
|
||||
};
|
||||
|
||||
Loadable_Module(const std::string &t_module_name, const std::string &t_filename)
|
||||
: m_dlmodule(t_filename), m_func(m_dlmodule, "create_chaiscript_module_" + t_module_name),
|
||||
m_moduleptr(m_func.m_symbol())
|
||||
{
|
||||
}
|
||||
|
||||
DLModule m_dlmodule;
|
||||
DLSym<Create_Module_Func> m_func;
|
||||
ModulePtr m_moduleptr;
|
||||
};
|
||||
#else
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
|
||||
struct Loadable_Module
|
||||
{
|
||||
template<typename T>
|
||||
static std::wstring towstring(const T &str)
|
||||
{
|
||||
return std::wstring(str.begin(), str.end());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static std::string tostring(const T &str)
|
||||
{
|
||||
return std::string(str.begin(), str.end());
|
||||
}
|
||||
|
||||
#ifdef _UNICODE
|
||||
template<typename T>
|
||||
static std::wstring toproperstring(const T &str)
|
||||
{
|
||||
return towstring(str);
|
||||
}
|
||||
#else
|
||||
template<typename T>
|
||||
static std::string toproperstring(const T &str)
|
||||
{
|
||||
return tostring(str);
|
||||
}
|
||||
#endif
|
||||
|
||||
static std::string GetErrorMessage(DWORD err)
|
||||
{
|
||||
#ifdef _UNICODE
|
||||
typedef LPWSTR StringType;
|
||||
std::wstring retval = L"Unknown Error";
|
||||
#else
|
||||
typedef LPSTR StringType;
|
||||
std::string retval = "Unknown Error";
|
||||
#endif
|
||||
StringType lpMsgBuf = 0;
|
||||
|
||||
FormatMessage(
|
||||
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||
FORMAT_MESSAGE_FROM_SYSTEM |
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL,
|
||||
err,
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||
(StringType)&lpMsgBuf,
|
||||
0, NULL );
|
||||
|
||||
if (lpMsgBuf)
|
||||
{
|
||||
retval = lpMsgBuf;
|
||||
}
|
||||
|
||||
LocalFree(lpMsgBuf);
|
||||
return tostring(retval);
|
||||
}
|
||||
|
||||
struct DLModule
|
||||
{
|
||||
DLModule(const std::string &t_filename)
|
||||
: m_data(LoadLibrary(toproperstring(t_filename).c_str()))
|
||||
{
|
||||
if (!m_data)
|
||||
{
|
||||
throw load_module_error(GetErrorMessage(GetLastError()));
|
||||
}
|
||||
}
|
||||
|
||||
~DLModule()
|
||||
{
|
||||
FreeLibrary(m_data);
|
||||
}
|
||||
|
||||
HMODULE m_data;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct DLSym
|
||||
{
|
||||
DLSym(DLModule &t_mod, const std::string &t_symbol)
|
||||
: m_symbol(reinterpret_cast<T>(GetProcAddress(t_mod.m_data, t_symbol.c_str())))
|
||||
{
|
||||
if (!m_symbol)
|
||||
{
|
||||
throw load_module_error(GetErrorMessage(GetLastError()));
|
||||
}
|
||||
}
|
||||
|
||||
T m_symbol;
|
||||
};
|
||||
|
||||
Loadable_Module(const std::string &t_module_name, const std::string &t_filename)
|
||||
: m_dlmodule(t_filename), m_func(m_dlmodule, "create_chaiscript_module_" + t_module_name),
|
||||
m_moduleptr(m_func.m_symbol())
|
||||
{
|
||||
}
|
||||
|
||||
DLModule m_dlmodule;
|
||||
DLSym<Create_Module_Func> m_func;
|
||||
ModulePtr m_moduleptr;
|
||||
};
|
||||
|
||||
#else
|
||||
struct Loadable_Module
|
||||
{
|
||||
Loadable_Module(const std::string &, const std::string &)
|
||||
{
|
||||
throw load_module_error("Loadable module support not available for your platform");
|
||||
}
|
||||
|
||||
ModulePtr get()
|
||||
{
|
||||
throw load_module_error("Loadable module support not available for your platform");
|
||||
}
|
||||
};
|
||||
#endif
|
||||
#endif
|
||||
|
||||
typedef boost::shared_ptr<Loadable_Module> Loadable_Module_Ptr;
|
||||
|
||||
|
||||
template <typename Eval_Engine>
|
||||
class ChaiScript_System {
|
||||
Eval_Engine engine;
|
||||
#ifndef CHAISCRIPT_NO_THREADS
|
||||
mutable boost::shared_mutex mutex;
|
||||
mutable boost::recursive_mutex use_mutex;
|
||||
#endif
|
||||
|
||||
std::set<std::string> loaded_files;
|
||||
std::map<std::string, Loadable_Module_Ptr> loaded_modules;
|
||||
std::set<std::string> active_loaded_modules;
|
||||
|
||||
ChaiScript_Parser parser;
|
||||
std::vector<std::string> modulepaths;
|
||||
std::vector<std::string> usepaths;
|
||||
|
||||
Eval_Engine engine;
|
||||
|
||||
|
||||
/**
|
||||
* Evaluates the given string in by parsing it and running the results through the evaluator
|
||||
*/
|
||||
Boxed_Value do_eval(const std::string &input, const std::string &filename = "__EVAL__") {
|
||||
Boxed_Value do_eval(const std::string &input, const std::string &filename = "__EVAL__", bool internal = false) {
|
||||
ChaiScript_Parser parser;
|
||||
|
||||
if (!internal)
|
||||
{
|
||||
engine.sync_cache();
|
||||
}
|
||||
|
||||
//debug_print(tokens);
|
||||
Boxed_Value value;
|
||||
parser.clear_match_stack();
|
||||
|
||||
// Keep a cache of all loaded filenames and use the char * from this cache to pass
|
||||
// to the parser. This is so that the parser does not have the overhead of passing
|
||||
// around and copying strings
|
||||
loaded_files.insert(filename);
|
||||
|
||||
try {
|
||||
if (parser.parse(input, loaded_files.find(filename)->c_str())) {
|
||||
//parser.show_match_stack();
|
||||
value = eval_token<Eval_Engine>(engine, parser.ast());
|
||||
//
|
||||
if (filename != "__EVAL__")
|
||||
{
|
||||
#ifndef CHAISCRIPT_NO_THREADS
|
||||
boost::unique_lock<boost::shared_mutex> l(mutex);
|
||||
#endif
|
||||
loaded_files.insert(filename);
|
||||
try {
|
||||
if (parser.parse(input, loaded_files.find(filename)->c_str())) {
|
||||
#ifndef CHAISCRIPT_NO_THREADS
|
||||
l.unlock();
|
||||
#endif
|
||||
//parser.show_match_stack();
|
||||
value = eval_token<Eval_Engine>(engine, parser.ast());
|
||||
}
|
||||
}
|
||||
catch (const Return_Value &rv) {
|
||||
value = rv.retval;
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
#ifndef CHAISCRIPT_NO_THREADS
|
||||
boost::shared_lock<boost::shared_mutex> l(mutex);
|
||||
#endif
|
||||
const char *fname = loaded_files.find("__EVAL__")->c_str();
|
||||
#ifndef CHAISCRIPT_NO_THREADS
|
||||
l.unlock();
|
||||
#endif
|
||||
|
||||
if (parser.parse(input, fname)) {
|
||||
//parser.show_match_stack();
|
||||
value = eval_token<Eval_Engine>(engine, parser.ast());
|
||||
}
|
||||
}
|
||||
catch (const Return_Value &rv) {
|
||||
value = rv.retval;
|
||||
}
|
||||
}
|
||||
catch (const Return_Value &rv) {
|
||||
value = rv.retval;
|
||||
|
||||
if (!internal)
|
||||
{
|
||||
engine.sync_cache();
|
||||
}
|
||||
|
||||
return value;
|
||||
@@ -54,24 +298,115 @@ namespace chaiscript
|
||||
/**
|
||||
* Evaluates the given boxed string, used during eval() inside of a script
|
||||
*/
|
||||
const Boxed_Value internal_eval(const std::vector<Boxed_Value> &vals) {
|
||||
return do_eval(boxed_cast<std::string>(vals.at(0)));
|
||||
const Boxed_Value internal_eval(const std::string &e) {
|
||||
return do_eval(e, "__EVAL__", true);
|
||||
}
|
||||
|
||||
void use(const std::string &filename)
|
||||
{
|
||||
if (loaded_files.count(filename) == 0)
|
||||
for (size_t i = 0; i < usepaths.size(); ++i)
|
||||
{
|
||||
eval_file(filename);
|
||||
|
||||
try {
|
||||
|
||||
const std::string appendedpath = usepaths[i] + filename;
|
||||
|
||||
#ifndef CHAISCRIPT_NO_THREADS
|
||||
boost::lock_guard<boost::recursive_mutex> l(use_mutex);
|
||||
boost::shared_lock<boost::shared_mutex> l2(mutex);
|
||||
#endif
|
||||
|
||||
if (loaded_files.count(appendedpath) == 0)
|
||||
{
|
||||
#ifndef CHAISCRIPT_NO_THREADS
|
||||
l2.unlock();
|
||||
#endif
|
||||
eval_file(appendedpath);
|
||||
} else {
|
||||
engine.sync_cache();
|
||||
}
|
||||
} catch (const File_Not_Found_Error &) {
|
||||
if (i == usepaths.size() - 1)
|
||||
{
|
||||
throw File_Not_Found_Error(filename);
|
||||
}
|
||||
|
||||
// failed to load, try the next path
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
ChaiScript_System() {
|
||||
ChaiScript_System(const std::vector<std::string> &t_modulepaths = std::vector<std::string>(),
|
||||
const std::vector<std::string> &t_usepaths = std::vector<std::string>())
|
||||
: modulepaths(t_modulepaths), usepaths(t_usepaths) {
|
||||
if (modulepaths.empty())
|
||||
{
|
||||
modulepaths.push_back("");
|
||||
}
|
||||
|
||||
if (usepaths.empty())
|
||||
{
|
||||
usepaths.push_back("");
|
||||
}
|
||||
|
||||
loaded_files.insert("__EVAL__"); // Make sure the default name is already registered
|
||||
build_eval_system();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a shared object, that can be used by all threads, to the system
|
||||
*/
|
||||
ChaiScript_System &add_global_const(const Boxed_Value &bv, const std::string &name)
|
||||
{
|
||||
engine.add_global_const(bv, name);
|
||||
return *this;
|
||||
}
|
||||
|
||||
struct State
|
||||
{
|
||||
std::set<std::string> loaded_files;
|
||||
typename Eval_Engine::State engine_state;
|
||||
std::set<std::string> active_loaded_modules;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a state object that represents the current
|
||||
* set of loaded files, the set of global variables and
|
||||
* the set of initialized functions
|
||||
*/
|
||||
State get_state()
|
||||
{
|
||||
#ifndef CHAISCRIPT_NO_THREADS
|
||||
boost::lock_guard<boost::recursive_mutex> l(use_mutex);
|
||||
boost::shared_lock<boost::shared_mutex> l2(mutex);
|
||||
#endif
|
||||
|
||||
State s;
|
||||
s.loaded_files = loaded_files;
|
||||
s.engine_state = engine.get_state();
|
||||
s.active_loaded_modules = active_loaded_modules;
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
* Restores the state from a saved State object.
|
||||
*/
|
||||
void set_state(const State &t_state)
|
||||
{
|
||||
#ifndef CHAISCRIPT_NO_THREADS
|
||||
boost::lock_guard<boost::recursive_mutex> l(use_mutex);
|
||||
boost::shared_lock<boost::shared_mutex> l2(mutex);
|
||||
#endif
|
||||
|
||||
loaded_files = t_state.loaded_files;
|
||||
active_loaded_modules = t_state.active_loaded_modules;
|
||||
engine.set_state(t_state.engine_state);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an object to the system: type, function, object
|
||||
*/
|
||||
@@ -87,11 +422,68 @@ namespace chaiscript
|
||||
*/
|
||||
ChaiScript_System &add(const ModulePtr &p)
|
||||
{
|
||||
engine.add(p);
|
||||
|
||||
p->apply(*this, this->get_eval_engine());
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a dynamic library containing a chaiscript module
|
||||
*/
|
||||
void load_module(const std::string &t_module_name)
|
||||
{
|
||||
std::vector<std::string> prefixes;
|
||||
prefixes.push_back("lib");
|
||||
prefixes.push_back("");
|
||||
|
||||
std::vector<std::string> postfixes;
|
||||
postfixes.push_back(".dll");
|
||||
postfixes.push_back(".so");
|
||||
postfixes.push_back("");
|
||||
|
||||
for (size_t i = 0; i < modulepaths.size(); ++i)
|
||||
{
|
||||
for (size_t j = 0; j < prefixes.size(); ++j)
|
||||
{
|
||||
for (size_t k = 0; k < postfixes.size(); ++k)
|
||||
{
|
||||
try {
|
||||
std::string name = modulepaths[i] + prefixes[j] + t_module_name + postfixes[k];
|
||||
load_module(t_module_name, name);
|
||||
return;
|
||||
} catch (const load_module_error &) {
|
||||
// Try next set
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw load_module_error("Unable to find module: " + t_module_name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a dynamic library and provide the file name to load it from
|
||||
*/
|
||||
void load_module(const std::string &t_module_name, const std::string &t_filename)
|
||||
{
|
||||
#ifndef CHAISCRIPT_NO_THREADS
|
||||
boost::lock_guard<boost::recursive_mutex> l(use_mutex);
|
||||
#endif
|
||||
|
||||
if (loaded_modules.count(t_module_name) == 0)
|
||||
{
|
||||
Loadable_Module_Ptr lm(new Loadable_Module(t_module_name, t_filename));
|
||||
loaded_modules[t_module_name] = lm;
|
||||
active_loaded_modules.insert(t_module_name);
|
||||
add(lm->m_moduleptr);
|
||||
} else if (active_loaded_modules.count(t_module_name) == 0) {
|
||||
active_loaded_modules.insert(t_module_name);
|
||||
add(loaded_modules[t_module_name]->m_moduleptr);
|
||||
} else {
|
||||
engine.sync_cache();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Helper for calling script code as if it were native C++ code
|
||||
* example:
|
||||
@@ -138,7 +530,7 @@ namespace chaiscript
|
||||
std::ifstream infile (filename.c_str(), std::ios::in | std::ios::ate);
|
||||
|
||||
if (!infile.is_open()) {
|
||||
throw std::runtime_error("Can not open: " + filename);
|
||||
throw File_Not_Found_Error(filename);
|
||||
}
|
||||
|
||||
std::streampos size = infile.tellg();
|
||||
@@ -174,28 +566,32 @@ namespace chaiscript
|
||||
engine.add_reserved_word("false");
|
||||
engine.add_reserved_word("_");
|
||||
|
||||
add(Bootstrap::bootstrap());
|
||||
|
||||
engine.add(Bootstrap::bootstrap());
|
||||
engine.add(fun(&Eval_Engine::dump_system, boost::ref(engine)), "dump_system");
|
||||
engine.add(fun(&Eval_Engine::dump_object, boost::ref(engine)), "dump_object");
|
||||
engine.add(fun(&Eval_Engine::is_type, boost::ref(engine)), "is_type");
|
||||
engine.add(fun(&Eval_Engine::type_name, boost::ref(engine)), "type_name");
|
||||
engine.add(fun(&Eval_Engine::function_exists, boost::ref(engine)), "function_exists");
|
||||
|
||||
engine.add(fun(boost::function<void ()>(boost::bind(&dump_system, boost::ref(engine)))), "dump_system");
|
||||
engine.add(fun(boost::function<void (Boxed_Value)>(boost::bind(&dump_object, _1, boost::ref(engine)))), "dump_object");
|
||||
engine.add(fun(boost::function<bool (Boxed_Value, const std::string &)>(boost::bind(&is_type, boost::ref(engine), _2, _1))),
|
||||
"is_type");
|
||||
engine.add(fun(&Eval_Engine::get_type_name, boost::ref(engine)), "name");
|
||||
|
||||
engine.add(fun(boost::function<std::string (Boxed_Value)>(boost::bind(&chaiscript::type_name, boost::ref(engine), _1))),
|
||||
"type_name");
|
||||
engine.add(fun(boost::function<bool (const std::string &)>(boost::bind(&Eval_Engine::function_exists, boost::ref(engine), _1))),
|
||||
"function_exists");
|
||||
|
||||
engine.add(vector_type<std::vector<Boxed_Value> >("Vector"));
|
||||
engine.add(string_type<std::string>("string"));
|
||||
engine.add(map_type<std::map<std::string, Boxed_Value> >("Map"));
|
||||
engine.add(pair_type<std::pair<Boxed_Value, Boxed_Value > >("Pair"));
|
||||
typedef void (ChaiScript_System<Eval_Engine>::*load_mod_1)(const std::string&);
|
||||
typedef void (ChaiScript_System<Eval_Engine>::*load_mod_2)(const std::string&, const std::string&);
|
||||
|
||||
engine.add(fun(boost::function<void (const std::string &)>(boost::bind(&ChaiScript_System<Eval_Engine>::use, this, _1))), "use");
|
||||
engine.add(fun(static_cast<load_mod_1>(&ChaiScript_System<Eval_Engine>::load_module), this), "load_module");
|
||||
engine.add(fun(static_cast<load_mod_2>(&ChaiScript_System<Eval_Engine>::load_module), this), "load_module");
|
||||
|
||||
|
||||
add(vector_type<std::vector<Boxed_Value> >("Vector"));
|
||||
add(string_type<std::string>("string"));
|
||||
add(map_type<std::map<std::string, Boxed_Value> >("Map"));
|
||||
add(pair_type<std::pair<Boxed_Value, Boxed_Value > >("Pair"));
|
||||
|
||||
engine.add(fun(&ChaiScript_System<Eval_Engine>::use, this), "use");
|
||||
engine.add(fun(&ChaiScript_System<Eval_Engine>::internal_eval, this), "eval");
|
||||
|
||||
engine.add(Proxy_Function(
|
||||
new Dynamic_Proxy_Function(boost::bind(&ChaiScript_System<Eval_Engine>::internal_eval, boost::ref(*this), _1), 1)), "eval");
|
||||
|
||||
do_eval(chaiscript_prelude, "standard prelude");
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009, Jonathan Turner (jturner@minnow-lang.org)
|
||||
// Copyright 2009-2010, Jonathan Turner (jturner@minnow-lang.org)
|
||||
// and Jason Turner (lefticus@gmail.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
@@ -9,277 +9,321 @@
|
||||
|
||||
//Note, the expression "[x,y]" in "collate" is parsed as two separate expressions
|
||||
//by C++, so CODE_STRING, takes two expressions and adds in the missing comma
|
||||
#define CODE_STRING(x, y) #x ", " #y
|
||||
#define CODE_STRING(x, y) #x ", " #y
|
||||
|
||||
#define chaiscript_prelude CODE_STRING(\
|
||||
def new(x) { eval(type_name(x))(); } \
|
||||
def clone(x) : function_exists(type_name(x)) { eval(type_name(x))(x); } \
|
||||
def lt(l, r) { if (call_exists(`<`, l, r)) { l < r } else { type_name(l) < type_name(r) } } \n\
|
||||
def gt(l, r) { if (call_exists(`>`, l, r)) { l > r } else { type_name(l) > type_name(r) } } \n\
|
||||
def eq(l, r) { if (call_exists(`==`, l, r)) { l == r } else { false } } \n\
|
||||
def new(x) { eval(type_name(x))(); } \n\
|
||||
def clone(x) : function_exists(type_name(x)) && call_exists(eval(type_name(x)), x) { eval(type_name(x))(x); } \n\
|
||||
# to_string for Pair()\n\
|
||||
def to_string(x) : call_exists(first, x) && call_exists(second, x) { \
|
||||
"<" + x.first.to_string() + ", " + x.second.to_string() + ">"; \
|
||||
}\
|
||||
def to_string(x) : call_exists(first, x) && call_exists(second, x) { \n\
|
||||
"<" + x.first.to_string() + ", " + x.second.to_string() + ">"; \n\
|
||||
}\n\
|
||||
# to_string for containers\n\
|
||||
def to_string(x) : call_exists(range, x) && !x.is_type("string"){ \
|
||||
"[" + x.join(", ") + "]"; \
|
||||
}\
|
||||
def to_string(x) : call_exists(range, x) && !x.is_type("string"){ \n\
|
||||
"[" + x.join(", ") + "]"; \n\
|
||||
}\n\
|
||||
# Basic to_string function\n\
|
||||
def to_string(x) { \
|
||||
internal_to_string(x); \
|
||||
}\
|
||||
def to_string(x) { \n\
|
||||
internal_to_string(x); \n\
|
||||
}\n\
|
||||
# Prints to console with no carriage return\n\
|
||||
def puts(x) { \
|
||||
print_string(x.to_string()); \
|
||||
} \
|
||||
def puts(x) { \n\
|
||||
print_string(x.to_string()); \n\
|
||||
} \n\
|
||||
# Prints to console with carriage return\n\
|
||||
def print(x) { \
|
||||
println_string(x.to_string()); \
|
||||
} \
|
||||
def print(x) { \n\
|
||||
println_string(x.to_string()); \n\
|
||||
} \n\
|
||||
# Returns the maximum value of two numbers\n\
|
||||
def max(a, b) { if (a>b) { a } else { b } } \
|
||||
def max(a, b) { if (a>b) { a } else { b } } \n\
|
||||
# Returns the minimum value of two numbers\n\
|
||||
def min(a, b) { if (a<b) { a } else { b } } \
|
||||
def min(a, b) { if (a<b) { a } else { b } } \n\
|
||||
# Returns true if the value is odd\n\
|
||||
def odd(x) { if (x % 2 == 1) { true } else { false } } \
|
||||
def odd(x) { if (x % 2 == 1) { true } else { false } } \n\
|
||||
# Returns true if the value is even\n\
|
||||
def even(x) { if (x % 2 == 0) { true } else { false } } \
|
||||
def even(x) { if (x % 2 == 0) { true } else { false } } \n\
|
||||
# Pushes the second value onto the container first value while making a clone of the value\n\
|
||||
def push_back(container, x) : call_exists(push_back_ref, container, x) { container.push_back_ref(clone(x)) } \n\
|
||||
# Pushes the second value onto the front of the container first value while making a clone of the value\n\
|
||||
def push_front(container, x) : call_exists(push_front_ref, container, x) { container.push_front_ref(clone(x)) } \n\
|
||||
# Inserts the third value at the position of the second value into the container of the first\n\
|
||||
# while making a clone. \n\
|
||||
def insert_at(container, pos, x) { container.insert_ref_at(pos, clone(x)); } \n\
|
||||
# Returns the reverse of the given container\n\
|
||||
def reverse(container) {\
|
||||
var retval = new(container); \
|
||||
var r = retro(range(container)); \
|
||||
while (!r.empty()) { \
|
||||
retval.push_back(r.front()); \
|
||||
r.pop_front(); \
|
||||
} \
|
||||
retval; \
|
||||
} \
|
||||
def reverse(container) {\n\
|
||||
var retval = new(container); \n\
|
||||
var r = range(container); \n\
|
||||
while (!r.empty()) { \n\
|
||||
retval.push_back(r.back()); \n\
|
||||
r.pop_back(); \n\
|
||||
} \n\
|
||||
retval; \n\
|
||||
} \n\
|
||||
# Return a range from a range \n\
|
||||
def range(r) : call_exists(empty, r) && call_exists(pop_front, r) && call_exists(pop_back, r) && call_exists(back, r) && call_exists(front, r) { return clone(r); }\n\
|
||||
# The retro attribute that contains the underlying range \n\
|
||||
attr retro::m_range; \n\
|
||||
# Creates a retro from a retro by returning the original range\n\
|
||||
def retro(r) : call_exists(get_type_name, r) && get_type_name(r) == "retro" { clone(r.m_range) }\n\
|
||||
# Creates a retro range from a range\n\
|
||||
def retro::retro(r) : call_exists(empty, r) && call_exists(pop_front, r) && call_exists(pop_back, r) && call_exists(back, r) && call_exists(front, r) { this.m_range = r; }\n\
|
||||
# Returns the first value of a retro\n\
|
||||
def retro::front() { back(this.m_range) }\n\
|
||||
# Returns the last value of a retro\n\
|
||||
def retro::back() { front(this.m_range) }\n\
|
||||
# Moves the back iterator of a retro towards the front by one \n\
|
||||
def retro::pop_back() { pop_front(this.m_range) }\n\
|
||||
# Moves the front iterator of a retro towards the back by one \n\
|
||||
def retro::pop_front() { pop_back(this.m_range) } \n\
|
||||
# returns true if the retro is out of elements \n\
|
||||
def retro::empty() { empty(this.m_range); } \n\
|
||||
# Performs the second value function over the container first value\n\
|
||||
def for_each(container, func) : call_exists(range, container) { \
|
||||
var range = range(container); \
|
||||
while (!range.empty()) { \
|
||||
func(range.front()); \
|
||||
range.pop_front(); \
|
||||
} \
|
||||
} \
|
||||
def back_inserter(container) { \
|
||||
bind(push_back, container, _); \
|
||||
}\
|
||||
\
|
||||
def map(container, func, inserter) : call_exists(range, container) { \
|
||||
var range = range(container); \
|
||||
while (!range.empty()) { \
|
||||
inserter(func(range.front())); \
|
||||
range.pop_front(); \
|
||||
} \
|
||||
} \
|
||||
def for_each(container, func) : call_exists(range, container) { \n\
|
||||
var t_range = range(container); \n\
|
||||
while (!t_range.empty()) { \n\
|
||||
func(t_range.front()); \n\
|
||||
t_range.pop_front(); \n\
|
||||
} \n\
|
||||
} \n\
|
||||
def back_inserter(container) { \n\
|
||||
bind(push_back, container, _); \n\
|
||||
}\n\
|
||||
\n\
|
||||
def contains(container, item, compare_func) : call_exists(range, container) { \n\
|
||||
var t_range = range(container); \n\
|
||||
while (!t_range.empty()) { \n\
|
||||
if ( compare_func(t_range.front(), item) ) { return true; } \n\
|
||||
t_range.pop_front(); \n\
|
||||
} \n\
|
||||
return false; \n\
|
||||
} \n\
|
||||
def contains(container, item) { return contains(container, item, eq) } \n\
|
||||
def map(container, func, inserter) : call_exists(range, container) { \n\
|
||||
var range = range(container); \n\
|
||||
while (!range.empty()) { \n\
|
||||
inserter(func(range.front())); \n\
|
||||
range.pop_front(); \n\
|
||||
} \n\
|
||||
} \n\
|
||||
# Performs the second value function over the container first value. Creates a new container with the results\n\
|
||||
def map(container, func) { \
|
||||
var retval = new(container); \
|
||||
map(container, func, back_inserter(retval));\
|
||||
retval;\
|
||||
}\
|
||||
def map(container, func) { \n\
|
||||
var retval = new(container); \n\
|
||||
map(container, func, back_inserter(retval));\n\
|
||||
retval;\n\
|
||||
}\n\
|
||||
# Performs the second value function over the container first value. Starts with initial and continues with each element.\n\
|
||||
def foldl(container, func, initial) : call_exists(range, container){ \
|
||||
var retval = initial; \
|
||||
var range = range(container); \
|
||||
while (!range.empty()) { \
|
||||
retval = (func(range.front(), retval)); \
|
||||
range.pop_front(); \
|
||||
} \
|
||||
retval; \
|
||||
} \
|
||||
def foldl(container, func, initial) : call_exists(range, container){ \n\
|
||||
var retval = initial; \n\
|
||||
var range = range(container); \n\
|
||||
while (!range.empty()) { \n\
|
||||
retval = (func(range.front(), retval)); \n\
|
||||
range.pop_front(); \n\
|
||||
} \n\
|
||||
retval; \n\
|
||||
} \n\
|
||||
# Returns the sum of the elements of the given value\n\
|
||||
def sum(container) { foldl(container, `+`, 0.0) } \
|
||||
def sum(container) { foldl(container, `+`, 0.0) } \n\
|
||||
# Returns the product of the elements of the given value\n\
|
||||
def product(container) { foldl(container, `*`, 1.0) } \
|
||||
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) { \
|
||||
var retval = x; \
|
||||
var len = y.size(); \
|
||||
var i = 0; \
|
||||
while (i < len) { \
|
||||
retval.push_back(y[i]); \
|
||||
++i; \
|
||||
} \
|
||||
retval; \
|
||||
} \
|
||||
def take(container, num, inserter) : call_exists(range, container) { \
|
||||
var r = range(container); \
|
||||
var i = num; \
|
||||
while ((i > 0) && (!r.empty())) { \
|
||||
inserter(r.front()); \
|
||||
r.pop_front(); \
|
||||
--i; \
|
||||
} \
|
||||
} \
|
||||
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\
|
||||
} \n\
|
||||
retval; \n\
|
||||
} \n\
|
||||
def take(container, num, inserter) : call_exists(range, container) { \n\
|
||||
var r = range(container); \n\
|
||||
var i = num; \n\
|
||||
while ((i > 0) && (!r.empty())) { \n\
|
||||
inserter(r.front()); \n\
|
||||
r.pop_front(); \n\
|
||||
--i; \n\
|
||||
} \n\
|
||||
} \n\
|
||||
# Returns a new container with the given number of elements taken from the container\n\
|
||||
def take(container, num) {\
|
||||
var retval = new(container); \
|
||||
take(container, num, back_inserter(retval)); \
|
||||
retval; \
|
||||
}\
|
||||
def take_while(container, f, inserter) : call_exists(range, container) { \
|
||||
var r = range(container); \
|
||||
while ((!r.empty()) && f(r.front())) { \
|
||||
inserter(r.front()); \
|
||||
r.pop_front(); \
|
||||
} \
|
||||
} \
|
||||
def take(container, num) {\n\
|
||||
var retval = new(container); \n\
|
||||
take(container, num, back_inserter(retval)); \n\
|
||||
retval; \n\
|
||||
}\n\
|
||||
def take_while(container, f, inserter) : call_exists(range, container) { \n\
|
||||
var r = range(container); \n\
|
||||
while ((!r.empty()) && f(r.front())) { \n\
|
||||
inserter(r.front()); \n\
|
||||
r.pop_front(); \n\
|
||||
} \n\
|
||||
} \n\
|
||||
# Returns a new container with the given elements match the second value function\n\
|
||||
def take_while(container, f) {\
|
||||
var retval = new(container); \
|
||||
take_while(container, f, back_inserter(retval)); \
|
||||
retval;\
|
||||
}\
|
||||
def drop(container, num, inserter) : call_exists(range, container) { \
|
||||
var r = range(container); \
|
||||
var i = num; \
|
||||
while ((i > 0) && (!r.empty())) { \
|
||||
r.pop_front(); \
|
||||
--i; \
|
||||
} \
|
||||
while (!r.empty()) { \
|
||||
inserter(r.front()); \
|
||||
r.pop_front(); \
|
||||
} \
|
||||
} \
|
||||
def take_while(container, f) {\n\
|
||||
var retval = new(container); \n\
|
||||
take_while(container, f, back_inserter(retval)); \n\
|
||||
retval;\n\
|
||||
}\n\
|
||||
def drop(container, num, inserter) : call_exists(range, container) { \n\
|
||||
var r = range(container); \n\
|
||||
var i = num; \n\
|
||||
while ((i > 0) && (!r.empty())) { \n\
|
||||
r.pop_front(); \n\
|
||||
--i; \n\
|
||||
} \n\
|
||||
while (!r.empty()) { \n\
|
||||
inserter(r.front()); \n\
|
||||
r.pop_front(); \n\
|
||||
} \n\
|
||||
} \n\
|
||||
# Returns a new container with the given number of elements dropped from the given container \n\
|
||||
def drop(container, num) {\
|
||||
var retval = new(container); \
|
||||
drop(container, num, back_inserter(retval)); \
|
||||
retval; \
|
||||
}\
|
||||
def drop_while(container, f, inserter) : call_exists(range, container) { \
|
||||
var r = range(container); \
|
||||
while ((!r.empty())&& f(r.front())) { \
|
||||
r.pop_front(); \
|
||||
} \
|
||||
while (!r.empty()) { \
|
||||
inserter(r.front()); \
|
||||
r.pop_front(); \
|
||||
} \
|
||||
} \
|
||||
def drop(container, num) {\n\
|
||||
var retval = new(container); \n\
|
||||
drop(container, num, back_inserter(retval)); \n\
|
||||
retval; \n\
|
||||
}\n\
|
||||
def drop_while(container, f, inserter) : call_exists(range, container) { \n\
|
||||
var r = range(container); \n\
|
||||
while ((!r.empty())&& f(r.front())) { \n\
|
||||
r.pop_front(); \n\
|
||||
} \n\
|
||||
while (!r.empty()) { \n\
|
||||
inserter(r.front()); \n\
|
||||
r.pop_front(); \n\
|
||||
} \n\
|
||||
} \n\
|
||||
# Returns a new container with the given elements dropped that match the second value function\n\
|
||||
def drop_while(container, f) {\
|
||||
var retval = new(container); \
|
||||
drop_while(container, f, back_inserter(retval)); \
|
||||
retval; \
|
||||
}\
|
||||
def drop_while(container, f) {\n\
|
||||
var retval = new(container); \n\
|
||||
drop_while(container, f, back_inserter(retval)); \n\
|
||||
retval; \n\
|
||||
}\n\
|
||||
# Applies the second value function to the container. Starts with the first two elements. Expects at least 2 elements.\n\
|
||||
def reduce(container, func) : container.size() >= 2 && call_exists(range, container) { \
|
||||
var r = range(container); \
|
||||
var retval = r.front(); \
|
||||
r.pop_front(); \
|
||||
retval = func(retval, r.front()); \
|
||||
r.pop_front(); \
|
||||
while (!r.empty()) { \
|
||||
retval = func(retval, r.front()); \
|
||||
r.pop_front(); \
|
||||
} \
|
||||
retval; \
|
||||
} \
|
||||
def reduce(container, func) : container.size() >= 2 && call_exists(range, container) { \n\
|
||||
var r = range(container); \n\
|
||||
var retval = r.front(); \n\
|
||||
r.pop_front(); \n\
|
||||
retval = func(retval, r.front()); \n\
|
||||
r.pop_front(); \n\
|
||||
while (!r.empty()) { \n\
|
||||
retval = func(retval, r.front()); \n\
|
||||
r.pop_front(); \n\
|
||||
} \n\
|
||||
retval; \n\
|
||||
} \n\
|
||||
# Returns a string of the elements in container delimited by the second value string\n\
|
||||
def join(container, delim) { \
|
||||
var retval = ""; \
|
||||
var range = range(container); \
|
||||
if (!range.empty()) { \
|
||||
retval += to_string(range.front()); \
|
||||
range.pop_front(); \
|
||||
while (!range.empty()) { \
|
||||
retval += delim; \
|
||||
retval += to_string(range.front()); \
|
||||
range.pop_front(); \
|
||||
} \
|
||||
} \
|
||||
retval; \
|
||||
} \
|
||||
def filter(container, f, inserter) : call_exists(range, container) { \
|
||||
var r = range(container); \
|
||||
while (!r.empty()) { \
|
||||
if (f(r.front())) { \
|
||||
inserter(r.front()); \
|
||||
} \
|
||||
r.pop_front(); \
|
||||
} \
|
||||
} \
|
||||
def join(container, delim) { \n\
|
||||
var retval = ""; \n\
|
||||
var range = range(container); \n\
|
||||
if (!range.empty()) { \n\
|
||||
retval += to_string(range.front()); \n\
|
||||
range.pop_front(); \n\
|
||||
while (!range.empty()) { \n\
|
||||
retval += delim; \n\
|
||||
retval += to_string(range.front()); \n\
|
||||
range.pop_front(); \n\
|
||||
} \n\
|
||||
} \n\
|
||||
retval; \n\
|
||||
} \n\
|
||||
def filter(container, f, inserter) : call_exists(range, container) { \n\
|
||||
var r = range(container); \n\
|
||||
while (!r.empty()) { \n\
|
||||
if (f(r.front())) { \n\
|
||||
inserter(r.front()); \n\
|
||||
} \n\
|
||||
r.pop_front(); \n\
|
||||
} \n\
|
||||
} \n\
|
||||
# Returns a new Vector which match the second value function\n\
|
||||
def filter(container, f) { \
|
||||
var retval = new(container); \
|
||||
filter(container, f, back_inserter(retval));\
|
||||
retval;\
|
||||
}\
|
||||
def generate_range(x, y, inserter) { \
|
||||
var i = x; \
|
||||
while (i <= y) { \
|
||||
inserter(i); \
|
||||
++i; \
|
||||
} \
|
||||
} \
|
||||
def filter(container, f) { \n\
|
||||
var retval = new(container); \n\
|
||||
filter(container, f, back_inserter(retval));\n\
|
||||
retval;\n\
|
||||
}\n\
|
||||
def generate_range(x, y, inserter) { \n\
|
||||
var i = x; \n\
|
||||
while (i <= y) { \n\
|
||||
inserter(i); \n\
|
||||
++i; \n\
|
||||
} \n\
|
||||
} \n\
|
||||
# Returns a new Vector which represents the range from the first value to the second value\n\
|
||||
def generate_range(x, y) { \
|
||||
var retval = Vector(); \
|
||||
generate_range(x,y,back_inserter(retval)); \
|
||||
retval; \
|
||||
}\
|
||||
def generate_range(x, y) { \n\
|
||||
var retval = Vector(); \n\
|
||||
generate_range(x,y,back_inserter(retval)); \n\
|
||||
retval; \n\
|
||||
}\n\
|
||||
# Returns a new Vector with the first value to the second value as its elements\n\
|
||||
def collate(x, y) { \
|
||||
[x, y]; \
|
||||
} \
|
||||
def zip_with(f, x, y, inserter) : call_exists(range, x) && call_exists(range, y) { \
|
||||
var r_x = range(x); \
|
||||
var r_y = range(y); \
|
||||
while (!r_x.empty() && !r_y.empty()) { \
|
||||
inserter(f(r_x.front(), r_y.front())); \
|
||||
r_x.pop_front(); \
|
||||
r_y.pop_front(); \
|
||||
} \
|
||||
} \
|
||||
def collate(x, y) { \n\
|
||||
[x, y]; \n\
|
||||
} \n\
|
||||
def zip_with(f, x, y, inserter) : call_exists(range, x) && call_exists(range, y) { \n\
|
||||
var r_x = range(x); \n\
|
||||
var r_y = range(y); \n\
|
||||
while (!r_x.empty() && !r_y.empty()) { \n\
|
||||
inserter(f(r_x.front(), r_y.front())); \n\
|
||||
r_x.pop_front(); \n\
|
||||
r_y.pop_front(); \n\
|
||||
} \n\
|
||||
} \n\
|
||||
# Returns a new Vector which joins matching elements of the second and third value with the first value function\n\
|
||||
def zip_with(f, x, y) { \
|
||||
var retval = Vector(); \
|
||||
zip_with(f,x,y,back_inserter(retval)); \
|
||||
retval;\
|
||||
}\
|
||||
def zip_with(f, x, y) { \n\
|
||||
var retval = Vector(); \n\
|
||||
zip_with(f,x,y,back_inserter(retval)); \n\
|
||||
retval;\n\
|
||||
}\n\
|
||||
# Returns a new Vector which joins matching elements of the first and second\n\
|
||||
def zip(x, y) { \
|
||||
zip_with(collate, x, y); \
|
||||
}\
|
||||
def zip(x, y) { \n\
|
||||
zip_with(collate, x, y); \n\
|
||||
}\n\
|
||||
# Returns the position of the second value string in the first value string\n\
|
||||
def find(str, substr) { \
|
||||
int(find(str, substr, size_t(0))); \
|
||||
} \
|
||||
def string::find(substr) : is_type(substr, "string") { \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 rfind(str, substr) { \
|
||||
int(rfind(str, substr, size_t(-1))); \
|
||||
} \
|
||||
def string::rfind(substr) : is_type(substr, "string") { \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 find_first_of(str, list) { \
|
||||
int(find_first_of(str, list, size_t(0))); \
|
||||
} \
|
||||
def string::find_first_of(list) : is_type(list, "string") { \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 find_last_of(str, list) { \
|
||||
int(find_last_of(str, list, size_t(-1))); \
|
||||
} \
|
||||
def string::find_last_of(list) : is_type(list, "string") { \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 find_first_not_of(str, list) { \
|
||||
int(find_first_not_of(str, list, size_t(0))); \
|
||||
} \
|
||||
def string::find_first_not_of(list) : is_type(list, "string") { \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 find_last_not_of(str, list) { \
|
||||
int(find_last_not_of(str, list, size_t(-1))); \
|
||||
} \
|
||||
def ltrim(str) { \
|
||||
drop_while(str, fun(x) { x == ' ' || x == '\t' }); \
|
||||
} \
|
||||
def rtrim(str) { \
|
||||
reverse(drop_while(reverse(str), fun(x) { x == ' ' || x == '\t' })); \
|
||||
} \
|
||||
def trim(str) { \
|
||||
ltrim(rtrim(str)); \
|
||||
} \
|
||||
def string::find_last_not_of(list) : is_type(list, "string") { \n\
|
||||
int(find_last_not_of(this, list, -1)); \n\
|
||||
} \n\
|
||||
def string::ltrim() { \n\
|
||||
drop_while(this, fun(x) { x == ' ' || x == '\t' }); \n\
|
||||
} \n\
|
||||
def string::rtrim() { \n\
|
||||
reverse(drop_while(reverse(this), fun(x) { x == ' ' || x == '\t' })); \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\
|
||||
var range = range(container); \n\
|
||||
while (!range.empty()) { \n\
|
||||
if (compare_func(range.front(), value)) { \n\
|
||||
return range; \n\
|
||||
} else { \n\
|
||||
range.pop_front(); \n\
|
||||
} \n\
|
||||
} \n\
|
||||
return range; \n\
|
||||
} \n\
|
||||
def find(container, value) { return find(container, value, eq) } \
|
||||
)
|
||||
#endif /* CHAISCRIPT_PRELUDE_HPP_ */
|
||||
|
@@ -1,4 +1,4 @@
|
||||
Copyright 2009 Jason and Jonathan Turner. All Rights Reserved.
|
||||
Copyright 2009-2010 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:
|
||||
|
@@ -1,196 +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="C:\Programming\chaiscript\trunk\include"
|
||||
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"
|
||||
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>
|
@@ -1,19 +0,0 @@
|
||||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioPropertySheet
|
||||
ProjectType="Visual C++"
|
||||
Version="8.00"
|
||||
Name="Boost"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalIncludeDirectories=""C:\Programming\Boost\include\boost-1_38""
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
AdditionalLibraryDirectories="C:\Programming\Boost\lib"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalLibraryDirectories="C:\Programming\Boost\lib"
|
||||
/>
|
||||
</VisualStudioPropertySheet>
|
@@ -1,26 +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
|
||||
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
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
@@ -1,270 +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="0"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UseUnicodeResponseFiles="false"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories=""$(ProjectDir)\..\..\include""
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
|
||||
MinimalRebuild="true"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="3"
|
||||
DisableLanguageExtensions="true"
|
||||
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="0"
|
||||
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=""$(ProjectDir)\..\..\include""
|
||||
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\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\dispatchkit\dispatchkit.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\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>
|
@@ -1,6 +1,6 @@
|
||||
ChaiScript v1.0
|
||||
ChaiScript v2.3.3
|
||||
http://www.chaiscript.com
|
||||
(c) 2009 Jason Turner and Jonathan Turner
|
||||
(c) 2009-2010 Jason Turner and Jonathan Turner
|
||||
Release under the BSD license, see "license.txt" for details.
|
||||
|
||||
[Introduction]
|
||||
|
@@ -1,25 +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
|
||||
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"
|
@@ -1,3 +1,2 @@
|
||||
var i = 1
|
||||
var j = eval("5 + 4")
|
||||
print(j)
|
||||
|
@@ -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)
|
||||
|
@@ -1,6 +1,6 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009, Jonathan Turner (jturner@minnow-lang.org)
|
||||
// Copyright 2009-2010, Jonathan Turner (jturner@minnow-lang.org)
|
||||
// and Jason Turner (lefticus@gmail.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
@@ -22,6 +22,22 @@ void log(const std::string &module, const std::string &msg)
|
||||
std::cout << "[" << boost::posix_time::microsec_clock::local_time() << "] <" << module << "> " << msg << std::endl;
|
||||
}
|
||||
|
||||
void bound_log(const std::string &msg)
|
||||
{
|
||||
log(msg);
|
||||
}
|
||||
|
||||
void hello_world(const chaiscript::Boxed_Value &o)
|
||||
{
|
||||
std::cout << "Hello World" << std::endl;
|
||||
}
|
||||
|
||||
void hello_constructor(const chaiscript::Boxed_Value &o)
|
||||
{
|
||||
std::cout << "Hello Constructor" << std::endl;
|
||||
}
|
||||
|
||||
|
||||
struct System
|
||||
{
|
||||
std::map<std::string, boost::function<std::string (const std::string &) > > m_callbacks;
|
||||
@@ -45,7 +61,7 @@ struct System
|
||||
}
|
||||
};
|
||||
|
||||
void take_shared_ptr(const boost::shared_ptr<std::string> &p)
|
||||
void take_shared_ptr(const boost::shared_ptr<const std::string> &p)
|
||||
{
|
||||
std::cout << *p << std::endl;
|
||||
}
|
||||
@@ -59,6 +75,9 @@ int main(int argc, char *argv[]) {
|
||||
System system;
|
||||
chai.add(var(&system), "system");
|
||||
|
||||
//Add a bound callback method
|
||||
chai.add(fun(&System::add_callback, system), "add_callback_bound");
|
||||
|
||||
//Register the two methods of the System structure.
|
||||
chai.add(fun(&System::add_callback), "add_callback");
|
||||
chai.add(fun(&System::do_callbacks), "do_callbacks");
|
||||
@@ -91,7 +110,7 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
//Finally, it is possible to register any boost::function as a system function, in this
|
||||
//way, we can, for instance add a bound member function to the system
|
||||
chai.add(fun(boost::function<void ()>(boost::bind(&System::do_callbacks, boost::ref(system), "Bound Test"))), "do_callbacks");
|
||||
chai.add(fun(&System::do_callbacks, boost::ref(system), std::string("Bound Test")), "do_callbacks");
|
||||
|
||||
//Call bound version of do_callbacks
|
||||
chai("do_callbacks()");
|
||||
@@ -124,13 +143,33 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
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_var_null())");
|
||||
|
||||
// test the global const action
|
||||
chai.add_global_const(const_var(1), "constvar");
|
||||
chai("def getvar() { return constvar; }");
|
||||
chai("print( getvar() )");
|
||||
|
||||
|
||||
//Ability to create our own container types when needed. std::vector and std::map are
|
||||
//mostly supported currently
|
||||
chai.add(bootstrap::vector_type<std::vector<int> >("IntVector"));
|
||||
|
||||
|
||||
chai("dump_system()");
|
||||
// Test ability to register a function that excepts a shared_ptr version of a type
|
||||
chai("take_shared_ptr(\"Hello World as a shared_ptr\");");
|
||||
|
||||
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.eval("var x = TestType()");
|
||||
// chai.eval("x.attr = \"hi\"");
|
||||
// chai.eval("print(x.attr)");
|
||||
chai.eval("x.hello_world()");
|
||||
}
|
||||
|
||||
|
83
src/main.cpp
83
src/main.cpp
@@ -1,27 +1,91 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009, Jonathan Turner (jturner@minnow-lang.org)
|
||||
// Copyright 2009-2010, Jonathan Turner (jturner@minnow-lang.org)
|
||||
// and Jason Turner (lefticus@gmail.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <list>
|
||||
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
|
||||
#ifdef READLINE_AVAILABLE
|
||||
#include <readline/readline.h>
|
||||
#include <readline/history.h>
|
||||
#endif
|
||||
|
||||
#include <chaiscript/chaiscript.hpp>
|
||||
|
||||
|
||||
void print_help() {
|
||||
std::cout << "ChaiScript evaluator. To evaluate and expression, type it and press <enter>." << std::endl;
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
bool throws_exception(const chaiscript::Proxy_Function &f)
|
||||
{
|
||||
try {
|
||||
chaiscript::functor<void ()>(f)();
|
||||
} catch (...) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
std::string input;
|
||||
chaiscript::ChaiScript chai;
|
||||
|
||||
std::vector<std::string> usepaths;
|
||||
std::vector<std::string> modulepaths;
|
||||
|
||||
const char *usepath = getenv("CHAI_USE_PATH");
|
||||
const char *modulepath = getenv("CHAI_MODULE_PATH");
|
||||
|
||||
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(&exit), "exit");
|
||||
chai.add(chaiscript::fun(&throws_exception), "throws_exception");
|
||||
|
||||
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;
|
||||
@@ -35,7 +99,7 @@ int main(int argc, char *argv[]) {
|
||||
val = chai.eval(input);
|
||||
|
||||
//Then, we try to print the result of the evaluation to the user
|
||||
if (val.get_type_info().m_bare_type_info && *(val.get_type_info().m_bare_type_info) != typeid(void)) {
|
||||
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);
|
||||
}
|
||||
@@ -49,20 +113,21 @@ int main(int argc, char *argv[]) {
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "eval> ";
|
||||
std::getline(std::cin, input);
|
||||
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;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
|
83
src/memory_leak_test.cpp
Normal file
83
src/memory_leak_test.cpp
Normal file
@@ -0,0 +1,83 @@
|
||||
#include <iostream>
|
||||
|
||||
#include "chaiscript/chaiscript.hpp"
|
||||
|
||||
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)
|
||||
{
|
||||
chaiscript::Boxed_Value val;
|
||||
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();
|
||||
}
|
||||
}
|
38
src/multithreaded.cpp
Normal file
38
src/multithreaded.cpp
Normal file
@@ -0,0 +1,38 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2010, Jonathan Turner (jturner@minnow-lang.org)
|
||||
// and Jason Turner (lefticus@gmail.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <list>
|
||||
|
||||
#include <chaiscript/chaiscript.hpp>
|
||||
#include <boost/thread.hpp>
|
||||
|
||||
void do_work(chaiscript::ChaiScript &c)
|
||||
{
|
||||
// c("use(\"work.chai\"); do_chai_work(num_iterations);");
|
||||
c("use(\"work.chai\"); do_chai_work(10000);");
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
std::string input;
|
||||
chaiscript::ChaiScript chai;
|
||||
|
||||
//chai.add_shared_object(chaiscript::Boxed_Value(10000), "num_iterations");
|
||||
|
||||
std::vector<boost::shared_ptr<boost::thread> > threads;
|
||||
|
||||
for (int i = 0; i < argc - 1; ++i)
|
||||
{
|
||||
threads.push_back(boost::shared_ptr<boost::thread>(new boost::thread(boost::bind(do_work, boost::ref(chai)))));
|
||||
}
|
||||
|
||||
for (int i = 0; i < argc - 1; ++i)
|
||||
{
|
||||
threads[i]->join();
|
||||
}
|
||||
}
|
||||
|
9
src/stl_extra.cpp
Normal file
9
src/stl_extra.cpp
Normal file
@@ -0,0 +1,9 @@
|
||||
|
||||
#include <chaiscript/chaiscript.hpp>
|
||||
#include <string>
|
||||
|
||||
|
||||
CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_stl_extra()
|
||||
{
|
||||
return chaiscript::bootstrap::list_type<std::list<chaiscript::Boxed_Value> >("List");
|
||||
}
|
16
src/test_module.cpp
Normal file
16
src/test_module.cpp
Normal file
@@ -0,0 +1,16 @@
|
||||
|
||||
#include <chaiscript/chaiscript.hpp>
|
||||
#include <string>
|
||||
|
||||
std::string hello_world()
|
||||
{
|
||||
return "Hello World";
|
||||
}
|
||||
|
||||
CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_test_module()
|
||||
{
|
||||
chaiscript::ModulePtr m(new chaiscript::Module());
|
||||
|
||||
m->add(chaiscript::fun(hello_world), "hello_world");
|
||||
return m;
|
||||
}
|
10
src/work.chai
Normal file
10
src/work.chai
Normal file
@@ -0,0 +1,10 @@
|
||||
def do_chai_work(num_iters)
|
||||
{
|
||||
var i = 0;
|
||||
for (var k = 0; k<num_iters * 10; ++k)
|
||||
{
|
||||
i += k;
|
||||
}
|
||||
|
||||
print(i);
|
||||
}
|
@@ -1,2 +1,2 @@
|
||||
var prod = bind(foldl, _, `*`, 1.0)
|
||||
print(prod([3, 4, 5]))
|
||||
assert_equal(60, prod([3, 4, 5]))
|
||||
|
@@ -1 +0,0 @@
|
||||
60
|
1
unittests/block_start.chai
Normal file
1
unittests/block_start.chai
Normal file
@@ -0,0 +1 @@
|
||||
{print("hello")}
|
@@ -1 +1 @@
|
||||
print(!true)
|
||||
assert_equal(false, !true)
|
||||
|
@@ -1 +0,0 @@
|
||||
false
|
@@ -4,4 +4,4 @@ while (i < 10) {
|
||||
break
|
||||
}
|
||||
}
|
||||
print(i)
|
||||
assert_equal(5, i);
|
||||
|
@@ -1 +0,0 @@
|
||||
5
|
@@ -1 +1 @@
|
||||
print('b')
|
||||
assert_equal("b", to_string('b'))
|
||||
|
@@ -1 +0,0 @@
|
||||
b
|
7
unittests/classification.chai
Normal file
7
unittests/classification.chai
Normal 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());
|
@@ -1 +1,3 @@
|
||||
print(collate(1, 2))
|
||||
var v = collate(1, 2)
|
||||
assert_equal(1, v[0])
|
||||
assert_equal(2, v[1])
|
||||
|
@@ -1 +0,0 @@
|
||||
[1, 2]
|
@@ -1 +1 @@
|
||||
print(1 > 2)
|
||||
assert_equal(false, 1 > 2);
|
||||
|
@@ -1 +0,0 @@
|
||||
false
|
@@ -1 +1 @@
|
||||
print(1 < 2)
|
||||
assert_equal(true, 1 < 2)
|
||||
|
@@ -1 +0,0 @@
|
||||
true
|
@@ -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]);
|
||||
|
@@ -1 +0,0 @@
|
||||
[1, 2, 3, 4]
|
@@ -1 +1 @@
|
||||
print(3.5.to_string() + "bob")
|
||||
assert_equal("3.5bob", 3.5.to_string() + "bob");
|
||||
|
@@ -1 +0,0 @@
|
||||
3.5bob
|
@@ -1 +1 @@
|
||||
print(3.to_string + "bob")
|
||||
assert_equal("3bob", 3.to_string + "bob")
|
||||
|
@@ -1 +0,0 @@
|
||||
3bob
|
@@ -1 +1 @@
|
||||
print("3.5".to_double() + 3.3)
|
||||
assert_equal(6.8, "3.5".to_double() + 3.3)
|
||||
|
@@ -1 +0,0 @@
|
||||
6.7999999999999998
|
@@ -1 +1 @@
|
||||
print("4".to_int() + 4)
|
||||
assert_equal(8, "4".to_int() + 4)
|
||||
|
@@ -1 +0,0 @@
|
||||
8
|
@@ -1 +1 @@
|
||||
print(drop([1, 2, 3, 4], 2))
|
||||
assert_equal([3,4], drop([1, 2, 3, 4], 2))
|
||||
|
@@ -1 +0,0 @@
|
||||
[3, 4]
|
@@ -1 +1 @@
|
||||
print(drop_while([1, 2, 3], odd))
|
||||
assert_equal([2, 3], drop_while([1, 2, 3], odd))
|
||||
|
@@ -1 +0,0 @@
|
||||
[2, 3]
|
4
unittests/equ_shortform.chai
Normal file
4
unittests/equ_shortform.chai
Normal file
@@ -0,0 +1,4 @@
|
||||
var x=.5
|
||||
assert_equal(.5, x)
|
||||
var y=-.5
|
||||
assert_equal(-.5, y)
|
@@ -1 +1 @@
|
||||
print(eval("3 + 4"))
|
||||
assert_equal(7, eval("3 + 4"))
|
||||
|
@@ -1 +0,0 @@
|
||||
7
|
@@ -1 +1 @@
|
||||
print(even(4))
|
||||
assert_equal(true, even(4))
|
||||
|
@@ -1 +0,0 @@
|
||||
true
|
9
unittests/exception.chai
Normal file
9
unittests/exception.chai
Normal file
@@ -0,0 +1,9 @@
|
||||
var x = 1
|
||||
try {
|
||||
throw(x)
|
||||
x = 2
|
||||
}
|
||||
catch(e) {
|
||||
x = e + 3
|
||||
}
|
||||
assert_equal(4, x);
|
32
unittests/exception_finally.chai
Normal file
32
unittests/exception_finally.chai
Normal file
@@ -0,0 +1,32 @@
|
||||
var finallyone = false;
|
||||
|
||||
try {
|
||||
throw(3)
|
||||
}
|
||||
catch(x) {
|
||||
assert_equal(3, x)
|
||||
}
|
||||
finally {
|
||||
finallyone = true;
|
||||
}
|
||||
|
||||
assert_equal(true, finallyone);
|
||||
|
||||
var try2 = false;
|
||||
var catch2 = false;
|
||||
var finally2 = false;
|
||||
|
||||
|
||||
try {
|
||||
try2 = true;
|
||||
}
|
||||
catch {
|
||||
catch2 = true;
|
||||
}
|
||||
finally {
|
||||
finally2 = true;
|
||||
}
|
||||
|
||||
assert_equal(true, try2);
|
||||
assert_equal(false, catch2);
|
||||
assert_equal(true, finally2);
|
34
unittests/exception_guards.chai
Normal file
34
unittests/exception_guards.chai
Normal file
@@ -0,0 +1,34 @@
|
||||
var results = [];
|
||||
|
||||
for (var i = 2; i < 6; ++i) {
|
||||
try {
|
||||
throw(i)
|
||||
}
|
||||
catch(e) : e < 2 {
|
||||
results.push_back("c1: " + e.to_string());
|
||||
}
|
||||
catch(e) : e < 4 {
|
||||
results.push_back("c2: " + e.to_string());
|
||||
}
|
||||
catch(e) {
|
||||
results.push_back("c3: " + e.to_string());
|
||||
}
|
||||
catch {
|
||||
// Should never get called
|
||||
assert_equal(false, true)
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
throw(3)
|
||||
}
|
||||
catch(e) : e < 3
|
||||
{
|
||||
// Should never get called
|
||||
assert_equal(false, true);
|
||||
}
|
||||
catch {
|
||||
results.push_back("defaultcatch");
|
||||
}
|
||||
|
||||
assert_equal(["c2: 2", "c2: 3", "c3: 4", "c3: 5", "defaultcatch"], results);
|
@@ -1 +1 @@
|
||||
print(filter([1, 2, 3, 4], odd))
|
||||
assert_equal([1,3], filter([1, 2, 3, 4], odd))
|
||||
|
@@ -1 +0,0 @@
|
||||
[1, 3]
|
@@ -1,2 +1,7 @@
|
||||
print(1.2)
|
||||
print(.5)
|
||||
assert_equal(true, 1.2 < 2)
|
||||
assert_equal(true, 1.2 > 1)
|
||||
assert_equal(1.2, 1.2)
|
||||
|
||||
assert_equal(true, .5 > 0)
|
||||
assert_equal(true, .5 < 1)
|
||||
assert_equal(0.5, .5)
|
||||
|
@@ -1,2 +0,0 @@
|
||||
1.2
|
||||
0.5
|
@@ -1 +1 @@
|
||||
print(foldl([1, 2, 3, 4], `+`, 0))
|
||||
assert_equal(10, foldl([1, 2, 3, 4], `+`, 0))
|
||||
|
@@ -1 +0,0 @@
|
||||
10
|
@@ -1,3 +1,7 @@
|
||||
var ret = []
|
||||
|
||||
for (var i = 0; i < 5; ++i) {
|
||||
print(i)
|
||||
ret.push_back(i);
|
||||
}
|
||||
|
||||
assert_equal([0,1,2,3,4], ret);
|
||||
|
@@ -1,5 +0,0 @@
|
||||
0
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
@@ -1,3 +0,0 @@
|
||||
1
|
||||
2
|
||||
3
|
3
unittests/for_each_range.chai
Normal file
3
unittests/for_each_range.chai
Normal file
@@ -0,0 +1,3 @@
|
||||
var v = [1,2,3];
|
||||
var r = range(v);
|
||||
for_each(r, fun(x) { assert_equal(true, x>0); } )
|
4
unittests/for_each_retro.chai
Normal file
4
unittests/for_each_retro.chai
Normal file
@@ -0,0 +1,4 @@
|
||||
// Don't bother checking the output from this one, just makes sure it executes
|
||||
var v = [1,2,3];
|
||||
var r = retro(range(v));
|
||||
for_each(r, print)
|
3
unittests/function_reassignment.chai
Normal file
3
unittests/function_reassignment.chai
Normal file
@@ -0,0 +1,3 @@
|
||||
var x = `+`
|
||||
x = `-`
|
||||
assert_equal(1, x(5,4))
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user