Compare commits

...

63 Commits

Author SHA1 Message Date
Jason Turner
254d176266 Set CMakeLists.txt to version 4.0.0 for release 2012-06-01 14:00:20 -06:00
Jason Turner
a5f29e93f5 Eliminate all VC++10 64bit Warnings. 2012-06-01 12:21:14 -06:00
Jason Turner
7f253bd6c1 Catch a few things found with more aggressive g++ warnings 2012-06-01 08:47:40 -06:00
Jason Turner
7cbd494123 It seems boost dropped the BOOST_GCC define? 2012-05-28 11:35:53 -06:00
Jason Turner
ed15cc1730 Clean up a few warnings found in Windows. 2012-05-28 10:48:19 -06:00
Jason Turner
db8863c736 Merge branch 'master' of https://github.com/ChaiScript/ChaiScript 2012-05-25 07:10:32 -06:00
Jason Turner
4233d21e5b Correct scope of operator calls
- Enhance reflection module to indicate inheritance
  - Add ability to catch errors thrown from a eval
    inside of a script
2012-05-24 19:25:29 -06:00
Jason Turner
f65e095e4d Update release notes 2012-05-24 15:45:52 -06:00
Jason Turner
7ad58c7bcd Apply cpo path from vim mailing list 2012-05-21 12:09:39 -06:00
Jason Turner
433905b33c Merge branch 'master' of https://github.com/ChaiScript/ChaiScript 2012-05-21 10:17:33 -06:00
Jason Turner
3a7eff1478 Move to a bit smarter stack based object management
- we store all function parameters until the f
    outer function call exits

  - this results in more values being stored longer than
    they need to be, but the results are predictable
    and no leaks
2012-05-21 10:16:16 -06:00
Jason Turner
ef46d1bf60 Remove Boxed_Value dependencies, they are not a solution 2012-05-21 08:18:33 -06:00
Jason Turner
654f7e6b01 Add unit test exposing how scope can leak into operator calls 2012-05-21 07:56:38 -06:00
Jonathan Turner
4aec12c68f Allow operator exprs to span lines 2012-05-20 10:47:50 -07:00
Jonathan Turner
a818e7b185 Merge branch 'master' of github.com:ChaiScript/ChaiScript 2012-05-20 10:17:43 -07:00
Jonathan Turner
5aed00dd0b Add ternary condition (?:) operator 2012-05-20 10:17:21 -07:00
Jason Turner
349425fe8a Make vector inplace construction consistent with map
- Clone elements into both vector and map
  - Be sure to drop dependencies after elements are cloned in
2012-05-20 07:04:22 -06:00
Jason Turner
6c57729779 Add unit test for pass_by_preference 2012-05-19 21:42:02 -06:00
Jason Turner
56757973b6 Actually reenable function 2012-05-19 18:05:41 -06:00
Jason Turner
f1f4aeb4be Add test and reenable function I accidentally commented out 2012-05-19 18:04:51 -06:00
Jason Turner
804de05a0a Fix object_lifetime_test which was broken by last perfomance fix 2012-05-19 09:50:49 -06:00
Jason Turner
0fd4b828f2 Fix some minor issues found by clang's static analyzer 2012-05-19 09:16:21 -06:00
Jason Turner
ae02706c71 Approx 12% speedup for function call heavy profile.chai 2012-05-19 07:09:55 -06:00
Jason Turner
c386af6813 Merge branch 'master' of https://github.com/ChaiScript/ChaiScript 2012-05-18 16:58:33 -06:00
Jason Turner
08c153abea Clean up some additional exception handling with new stack handler 2012-05-18 16:37:39 -06:00
Jason Turner
897ad7007f Get system introspection functions fully working 2012-05-18 16:25:13 -06:00
Jason Turner
13fb930676 First part of system introspection for objs and funcs added 2012-05-18 15:31:42 -06:00
Jonathan Turner
8af41b1d3c Add unit test for ignoring hash bang. 2012-05-18 08:43:03 -07:00
Jonathan Turner
025db4ce3a Oops. Properly handle empty switch statements. 2012-05-17 13:20:15 -07:00
Jonathan Turner
78f02c375e Add syntax support for switch/case/default. 2012-05-17 12:48:57 -07:00
Jonathan Turner
4e14a57016 Add support for switch/case/default statements. 2012-05-17 12:43:25 -07:00
Jason Turner
af1e02b0bb Update copyrights to 2012 #23 2012-05-16 11:55:51 -06:00
Jason Turner
4bcaa75fa4 Throw eval exception if a variable or function is redefined #28 2012-05-16 11:40:43 -06:00
Jason Turner
7deb2311f5 Restore CMakeLists.txt on head to working version
Reverted to revision: 277b4eec9a
2012-05-15 19:48:46 -06:00
Jonathan Turner
730bad9728 Adding support for building with clang/libcxx. 2012-05-15 14:58:38 -07:00
Jason Turner
437f6a03a9 Slight cleanup of the boxed_number cleanups from mgee 2012-05-14 18:09:55 -06:00
Jason Turner
94fefa0690 Fix broken example.cpp 2012-05-14 18:09:36 -06:00
Jason Turner
91dc3604f5 Merge pull request #27 from mgee/master
Improve Boxed_Number
2012-05-14 16:55:03 -07:00
Markus Groß
59dfc847ae Make Boxed_Number assignable from Boxed_Value. 2012-05-14 21:34:28 +02:00
Markus Groß
cdfefed385 Add default constructor for Boxed_Number 2012-05-14 20:13:39 +02:00
Jason Turner
b0b1549503 Fix cast for unsigned short #26 2012-05-14 09:33:35 -06:00
Jason Turner
277b4eec9a Add failing test for short comparisons #26 2012-05-14 09:22:03 -06:00
Jonathan Turner
41b0c7768c Adding header files to CMakeLists.txt. Hopefully this will help them
show up in IDEs (works for Qt Creator so far).
2012-03-11 14:06:18 -06:00
Jason Turner
3b95931973 Fixup some documentation 2012-01-30 11:53:12 -07:00
Jason Turner
13f98fa8ce Move "use" function to be public 2012-01-30 11:26:46 -07:00
Jason Turner
b0953fb466 Minor cleanup releated to attribute fix 2012-01-30 08:55:12 -07:00
Jason Turner
1186926f30 Fix duplicate object attribute name problem 2012-01-30 08:48:01 -07:00
Jason Turner
70db5d67ff Add failing unit test for dynamic object attributes with the same name 2012-01-30 07:55:54 -07:00
Jason Turner
d9727973c1 Add files missing from last checkin 2011-09-09 17:08:51 -06:00
Jason Turner
0293762904 Add ability to provide global consts in Module objects. Issue #14 2011-09-09 16:52:32 -06:00
Jason Turner
95c6131ce7 Add missing unit test file 2011-09-09 16:01:29 -06:00
Jason Turner
e326fe6f2d Add test for constructing from a pointer return value and fix test so it works. Task #13 2011-09-09 14:38:55 -06:00
Jason Turner
2b64c90a0e Merge branch 'master' of https://github.com/ChaiScript/ChaiScript
Conflicts:
	CMakeLists.txt

Fixed conflicted CMakeLists.txt
2011-09-09 13:58:19 -06:00
Jason Turner
dd0d91c7e3 Merge pull request #10 from svenstaro/master
Consistency fixes
2011-09-09 12:42:48 -07:00
Jason Turner
a386142fa6 Get chaiscript compiling with -pedantic. Closes issue #9 2011-09-09 13:40:50 -06:00
Sven-Hendrik Haase
cacc744411 More consistency fixes 2011-08-03 19:25:02 +02:00
Sven-Hendrik Haase
2d23578e0b Removing unused variables 2011-08-03 19:22:18 +02:00
Sven-Hendrik Haase
f8880066ea Consistency fix 2011-08-03 16:10:13 +02:00
Jason Turner
a85423869f Edited releasenotes.txt via GitHub 2011-06-18 15:41:27 -07:00
Jason Turner
469c02ad14 Edited releasenotes.txt via GitHub 2011-06-18 15:35:26 -07:00
Jason Turner
a549e41558 Merge branch 'master' of https://github.com/ChaiScript/ChaiScript 2011-06-11 17:05:53 -06:00
Jason Turner
a82c892a4e Merge branch 'master' of https://github.com/ChaiScript/ChaiScript 2011-06-11 07:15:02 -06:00
Jason Turner
c839e4bc21 Handle unnecessary MSVC compiler warnings. 2011-06-08 19:19:59 -06:00
65 changed files with 1179 additions and 345 deletions

View File

@@ -16,8 +16,8 @@ set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/license.txt")
set(CPACK_RESOURCE_FILE_README "${CMAKE_CURRENT_SOURCE_DIR}/readme.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_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/description.txt")
set(CPACK_PACKAGE_VERSION_MAJOR 3) set(CPACK_PACKAGE_VERSION_MAJOR 4)
set(CPACK_PACKAGE_VERSION_MINOR 1) set(CPACK_PACKAGE_VERSION_MINOR 0)
set(CPACK_PACKAGE_VERSION_PATCH 0) set(CPACK_PACKAGE_VERSION_PATCH 0)
set(CPACK_PACKAGE_EXECUTABLES "chai;ChaiScript Eval") set(CPACK_PACKAGE_EXECUTABLES "chai;ChaiScript Eval")
set(CPACK_PACKAGE_VENDOR "ChaiScript.com") set(CPACK_PACKAGE_VENDOR "ChaiScript.com")
@@ -39,40 +39,44 @@ configure_file(Doxyfile.in ${CMAKE_BINARY_DIR}/Doxyfile)
include(CTest) include(CTest)
include(CPack) include(CPack)
FIND_LIBRARY(READLINE_LIBRARY NAMES readline PATH /usr/lib /usr/local/lib /opt/local/lib) find_library(READLINE_LIBRARY NAMES readline PATH /usr/lib /usr/local/lib /opt/local/lib)
enable_testing() enable_testing()
MESSAGE(STATUS "Detecting readline support") message(STATUS "Detecting readline support")
if (READLINE_LIBRARY) if (READLINE_LIBRARY)
MESSAGE(STATUS "Found: ${READLINE_LIBRARY}") message(STATUS "Found: ${READLINE_LIBRARY}")
SET (READLINE_LIB readline) set (READLINE_LIB readline)
ADD_DEFINITIONS(/DREADLINE_AVAILABLE) add_definitions(/DREADLINE_AVAILABLE)
else(READLINE_LIBRARY) else(READLINE_LIBRARY)
MESSAGE(STATUS "Not Found") message(STATUS "Not Found")
SET (READLINE_LIB ) set (READLINE_LIB )
SET (READLINE_FLAG ) set (READLINE_FLAG )
endif(READLINE_LIBRARY) endif(READLINE_LIBRARY)
IF(MSVC) if(MSVC)
ADD_DEFINITIONS(/W4) add_definitions(/W4)
IF(CMAKE_CL_64) if(CMAKE_CL_64)
ADD_DEFINITIONS(/bigobj) add_definitions(/bigobj)
ENDIF() endif()
ELSE() else()
ADD_DEFINITIONS(-Wall -Wextra -Wshadow) add_definitions(-Wall -Wextra -Wshadow -pedantic)
IF (APPLE) if (APPLE)
# -Wno-missing-field-initializers is for boost on macos # -Wno-missing-field-initializers is for boost on macos
ADD_DEFINITIONS(-Wno-missing-field-initializers -Wno-sign-compare) add_definitions(-Wno-missing-field-initializers -Wno-sign-compare)
ENDIF() endif()
ENDIF() endif()
include_directories(include) include_directories(include)
SET(Boost_ADDITIONAL_VERSIONS "1.44" "1.44.0" "1.43" "1.43.0" "1.42" "1.42.0" "1.41") set(Boost_ADDITIONAL_VERSIONS "1.44" "1.44.0" "1.43" "1.43.0" "1.42" "1.42.0" "1.41")
SET(Boost_USE_MULTITHREADED ON) set(Boost_USE_MULTITHREADED ON)
set (Chai_INCLUDES include/chaiscript/chaiscript.hpp include/chaiscript/chaiscript_threading.hpp include/chaiscript/dispatchkit/bad_boxed_cast.hpp include/chaiscript/dispatchkit/bind_first.hpp include/chaiscript/dispatchkit/bootstrap.hpp include/chaiscript/dispatchkit/bootstrap_stl.hpp include/chaiscript/dispatchkit/boxed_cast.hpp include/chaiscript/dispatchkit/boxed_cast_helper.hpp include/chaiscript/dispatchkit/boxed_number.hpp include/chaiscript/dispatchkit/boxed_value.hpp include/chaiscript/dispatchkit/dispatchkit.hpp include/chaiscript/dispatchkit/dynamic_cast_conversion.hpp include/chaiscript/dispatchkit/dynamic_object.hpp include/chaiscript/dispatchkit/exception_specification.hpp include/chaiscript/dispatchkit/function_call.hpp include/chaiscript/dispatchkit/function_call_detail.hpp include/chaiscript/dispatchkit/handle_return.hpp include/chaiscript/dispatchkit/operators.hpp include/chaiscript/dispatchkit/proxy_constructors.hpp include/chaiscript/dispatchkit/proxy_functions.hpp include/chaiscript/dispatchkit/proxy_functions_detail.hpp include/chaiscript/dispatchkit/register_function.hpp include/chaiscript/dispatchkit/type_info.hpp include/chaiscript/language/chaiscript_algebraic.hpp include/chaiscript/language/chaiscript_common.hpp include/chaiscript/language/chaiscript_engine.hpp include/chaiscript/language/chaiscript_eval.hpp include/chaiscript/language/chaiscript_parser.hpp include/chaiscript/language/chaiscript_prelude.hpp include/chaiscript/language/chaiscript_prelude_docs.hpp include/chaiscript/utility/utility.hpp)
set_source_files_properties(${Chai_INCLUDES} PROPERTIES HEADER_FILE_ONLY TRUE)
if (MULTITHREAD_SUPPORT_ENABLED) if (MULTITHREAD_SUPPORT_ENABLED)
find_package(Boost 1.36.0 COMPONENTS thread) find_package(Boost 1.36.0 COMPONENTS thread)
@@ -83,18 +87,18 @@ if (MULTITHREAD_SUPPORT_ENABLED)
message(FATAL_ERROR "Can not find Boost") message(FATAL_ERROR "Can not find Boost")
endif(Boost_FOUND) endif(Boost_FOUND)
else() else()
ADD_DEFINITIONS(-DCHAISCRIPT_NO_THREADS) add_definitions(-DCHAISCRIPT_NO_THREADS)
endif() endif()
if (CMAKE_HOST_UNIX) if (CMAKE_HOST_UNIX)
SET(DYNAMIC_LOADER "dl") set(DYNAMIC_LOADER "dl")
endif(CMAKE_HOST_UNIX) endif(CMAKE_HOST_UNIX)
if (MSVC) if (MSVC)
# Boost on MSVC does automatic linking # Boost on MSVC does automatic linking
SET(LIBS ${DYNAMIC_LOADER} ${READLINE_LIB}) set(LIBS ${DYNAMIC_LOADER} ${READLINE_LIB})
else() else()
SET(LIBS ${DYNAMIC_LOADER} ${Boost_LIBRARIES} ${READLINE_LIB}) set(LIBS ${DYNAMIC_LOADER} ${Boost_LIBRARIES} ${READLINE_LIB})
endif() endif()
if (CMAKE_COMPILER_2005) if (CMAKE_COMPILER_2005)
@@ -104,7 +108,7 @@ endif()
include_directories(${Boost_INCLUDE_DIRS}) include_directories(${Boost_INCLUDE_DIRS})
include_directories(${Boost_INCLUDE_DIR}) include_directories(${Boost_INCLUDE_DIR})
add_executable(chai src/main.cpp) add_executable(chai src/main.cpp ${Chai_INCLUDES})
target_link_libraries(chai ${LIBS}) target_link_libraries(chai ${LIBS})
if (BUILD_SAMPLES) if (BUILD_SAMPLES)
@@ -128,7 +132,7 @@ file(GLOB UNIT_TESTS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/unittests/ ${CMAKE_CUR
list(SORT UNIT_TESTS) list(SORT UNIT_TESTS)
IF(BUILD_TESTING) if(BUILD_TESTING)
option(UNIT_TEST_LIGHT "Unit tests light (expect module loading failures)" FALSE) option(UNIT_TEST_LIGHT "Unit tests light (expect module loading failures)" FALSE)
foreach(filename ${UNIT_TESTS}) foreach(filename ${UNIT_TESTS})
@@ -136,13 +140,13 @@ IF(BUILD_TESTING)
add_test(${filename} chai ${CMAKE_CURRENT_SOURCE_DIR}/unittests/unit_test.inc ${CMAKE_CURRENT_SOURCE_DIR}/unittests/${filename}) add_test(${filename} chai ${CMAKE_CURRENT_SOURCE_DIR}/unittests/unit_test.inc ${CMAKE_CURRENT_SOURCE_DIR}/unittests/${filename})
endforeach(filename) endforeach(filename)
SET_PROPERTY(TEST ${UNIT_TESTS} set_property(TEST ${UNIT_TESTS}
PROPERTY ENVIRONMENT PROPERTY ENVIRONMENT
"CHAI_USE_PATH=${CMAKE_CURRENT_SOURCE_DIR}/unittests/" "CHAI_USE_PATH=${CMAKE_CURRENT_SOURCE_DIR}/unittests/"
"CHAI_MODULE_PATH=${CMAKE_CURRENT_BINARY_DIR}/" "CHAI_MODULE_PATH=${CMAKE_CURRENT_BINARY_DIR}/"
) )
IF (NOT UNIT_TEST_LIGHT) if (NOT UNIT_TEST_LIGHT)
add_executable(utility_test unittests/utility_test.cpp) add_executable(utility_test unittests/utility_test.cpp)
target_link_libraries(utility_test ${LIBS}) target_link_libraries(utility_test ${LIBS})
add_test(NAME Utility_Test COMMAND utility_test) add_test(NAME Utility_Test COMMAND utility_test)
@@ -179,6 +183,11 @@ IF(BUILD_TESTING)
target_link_libraries(eval_catch_exception_test ${LIBS}) target_link_libraries(eval_catch_exception_test ${LIBS})
add_test(NAME Eval_Catch_Exception_Test COMMAND eval_catch_exception_test) add_test(NAME Eval_Catch_Exception_Test COMMAND eval_catch_exception_test)
add_executable(short_comparison_test unittests/short_comparison_test.cpp)
target_link_libraries(short_comparison_test ${LIBS})
add_test(NAME Short_Comparison_Test COMMAND short_comparison_test)
add_executable(multifile_test unittests/multifile_test_main.cpp unittests/multifile_test_chai.cpp add_executable(multifile_test unittests/multifile_test_main.cpp unittests/multifile_test_chai.cpp
unittests/multifile_test_module.cpp) unittests/multifile_test_module.cpp)
target_link_libraries(multifile_test ${LIBS}) target_link_libraries(multifile_test ${LIBS})
@@ -188,8 +197,8 @@ IF(BUILD_TESTING)
target_link_libraries(test_module ${LIBS}) target_link_libraries(test_module ${LIBS})
install(TARGETS test_module RUNTIME DESTINATION bin LIBRARY DESTINATION lib/chaiscript) install(TARGETS test_module RUNTIME DESTINATION bin LIBRARY DESTINATION lib/chaiscript)
ENDIF() endif()
ENDIF(BUILD_TESTING) endif(BUILD_TESTING)
install(TARGETS chai ${MODULES} RUNTIME DESTINATION bin LIBRARY DESTINATION lib/chaiscript ) install(TARGETS chai ${MODULES} RUNTIME DESTINATION bin LIBRARY DESTINATION lib/chaiscript )
install(DIRECTORY include/chaiscript DESTINATION include install(DIRECTORY include/chaiscript DESTINATION include
@@ -209,8 +218,7 @@ install(DIRECTORY samples DESTINATION share/chaiscript
PATTERN "*/.git*" EXCLUDE PATTERN "*/.git*" EXCLUDE
PATTERN "*~" EXCLUDE) PATTERN "*~" EXCLUDE)
configure_file(contrib/pkgconfig/chaiscript.pc.in lib/pkgconfig/chaiscript.pc @ONLY) configure_file(contrib/pkgconfig/chaiscript.pc.in lib/pkgconfig/chaiscript.pc @ONLY)
install(FILES "${chaiscript_BINARY_DIR}/lib/pkgconfig/chaiscript.pc" install(FILES "${chaiscript_BINARY_DIR}/lib/pkgconfig/chaiscript.pc"
DESTINATION lib/pkgconfig) DESTINATION lib/pkgconfig)

View File

@@ -48,7 +48,7 @@ $language_data = array (
'ESCAPE_CHAR' => '\\', 'ESCAPE_CHAR' => '\\',
'KEYWORDS' => array( 'KEYWORDS' => array(
1 => array( 1 => array(
'break', 'else', 'else if', 'eval', 'for', 'if', 'return', 'while', 'try', 'catch', 'finally', 'break', 'else', 'else if', 'eval', 'for', 'if', 'return', 'while', 'try', 'catch', 'finally', 'case', 'switch', 'default',
), ),
2 => array( 2 => array(
'def', 'false', 'fun', 'true', 'var', 'attr', 'def', 'false', 'fun', 'true', 'var', 'attr',

View File

@@ -7,6 +7,9 @@ if exists("b:current_syntax")
finish finish
end end
let s:cpo_save = &cpo
set cpo&vim
syn case match syn case match
" syncing method " syncing method
@@ -42,7 +45,7 @@ syn match chaiscriptNumber "\<0b[01]\+\>"
" Various language features " Various language features
syn keyword chaiscriptCond if else syn keyword chaiscriptCond if else
syn keyword chaiscriptRepeat while for do syn keyword chaiscriptRepeat while for do
syn keyword chaiscriptStatement break continue return syn keyword chaiscriptStatement break continue return switch case default
syn keyword chaiscriptExceptions try catch throw syn keyword chaiscriptExceptions try catch throw
"Keyword "Keyword
@@ -91,4 +94,6 @@ hi def link chaiscriptEval Special
let b:current_syntax = "chaiscript" let b:current_syntax = "chaiscript"
let &cpo = s:cpo_save
unlet s:cpo_save
" vim: nowrap sw=2 sts=2 ts=8 noet " vim: nowrap sw=2 sts=2 ts=8 noet

View File

@@ -1,6 +1,6 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com) // and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
@@ -192,8 +192,8 @@
/// Overloaded methods will need some help, to hint the compiler as to which overload you want: /// Overloaded methods will need some help, to hint the compiler as to which overload you want:
/// ///
/// \code /// \code
/// chai.add(fun<void (MyClass::*)()>(&MyClass::overloadedmethod), "overloadedmethod")); /// chai.add(fun<void (MyClass::*)()>(&MyClass::overloadedmethod), "overloadedmethod");
/// chai.add(fun<void (MyClass::*)(const std::string &)>(&MyClass::overloadedmethod, "overloadedmethod")); /// chai.add(fun<void (MyClass::*)(const std::string &)>(&MyClass::overloadedmethod), "overloadedmethod");
/// \endcode /// \endcode
/// ///
/// There are also shortcuts built into chaiscript::fun for binding up to the first two parameters of the function. /// There are also shortcuts built into chaiscript::fun for binding up to the first two parameters of the function.

View File

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

View File

@@ -1,6 +1,6 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com) // and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
@@ -33,7 +33,7 @@ namespace chaiscript
} }
bad_boxed_cast(const std::string &t_what) throw() bad_boxed_cast(const std::string &t_what) throw()
: m_what(t_what) : to(0), m_what(t_what)
{ {
} }

View File

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

View File

@@ -1,6 +1,6 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com) // and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
@@ -422,9 +422,6 @@ namespace chaiscript
m->add(fun(&Type_Info::name), "cpp_name"); m->add(fun(&Type_Info::name), "cpp_name");
m->add(fun(&Type_Info::bare_name), "cpp_bare_name"); m->add(fun(&Type_Info::bare_name), "cpp_bare_name");
m->add(fun(&Type_Info::bare_equal), "bare_equal"); m->add(fun(&Type_Info::bare_equal), "bare_equal");
typedef bool (Type_Info::*typeinfocompare)(const Type_Info &) const;
m->add(fun(typeinfocompare(&Type_Info::operator==)), "==");
m->add(fun(&Type_Info::bare_equal), "bare_equal");
basic_constructors<bool>("bool", m); basic_constructors<bool>("bool", m);

View File

@@ -1,6 +1,6 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com) // and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
@@ -147,6 +147,64 @@ namespace chaiscript
}; };
namespace detail { namespace detail {
template<typename T>
int return_int_impl(const boost::function<typename T::size_type (const T *)> &t_func, const T *t_obj)
{
#ifdef BOOST_MSVC
#pragma warning(push)
#pragma warning(disable : 4267)
#endif
return t_func(t_obj);
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif
}
template<typename T>
boost::function<int (const T *)> return_int(size_t (T::*t_func)() const)
{
return boost::bind(&return_int_impl<T>, boost::function<size_t (const T *)>(boost::mem_fn(t_func)), _1);
}
template<typename T, typename P1>
int return_int_impl(const boost::function<typename T::size_type (const T *, P1)> &t_func, const T *t_obj, P1 p1)
{
#ifdef BOOST_MSVC
#pragma warning(push)
#pragma warning(disable : 4267)
#endif
return t_func(t_obj, p1);
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif
}
template<typename T, typename P1>
boost::function<int (const T *, P1)> return_int(size_t (T::*t_func)(P1) const)
{
return boost::bind(&return_int_impl<T, P1>, boost::function<size_t (const T *, P1)>(boost::mem_fn(t_func)), _1, _2);
}
template<typename T, typename P1, typename P2>
int return_int_impl(const boost::function<typename T::size_type (const T *, P1, P2)> &t_func, const T *t_obj, P1 p1, P2 p2)
{
#ifdef BOOST_MSVC
#pragma warning(push)
#pragma warning(disable : 4267)
#endif
return t_func(t_obj, p1, p2);
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif
}
template<typename T, typename P1, typename P2>
boost::function<int (const T *, P1, P2)> return_int(size_t (T::*t_func)(P1, P2) const)
{
return boost::bind(&return_int_impl<T, P1, P2>, boost::function<size_t (const T *, P1, P2)>(boost::mem_fn(t_func)), _1, _2, _3);
}
/** /**
* Add Bidir_Range support for the given ContainerType * Add Bidir_Range support for the given ContainerType
*/ */
@@ -255,7 +313,9 @@ namespace chaiscript
template<typename ContainerType> 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()))
{ {
m->add(fun(boost::function<int (const ContainerType *)>(boost::mem_fn(&ContainerType::size))), "size"); boost::function<int (const ContainerType *)> f = detail::return_int(&ContainerType::size);
m->add(fun(f), "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<bool (ContainerType::*)() const>(&ContainerType::empty), "empty");
m->add(fun<void (ContainerType::*)()>(&ContainerType::clear), "clear"); m->add(fun<void (ContainerType::*)()>(&ContainerType::clear), "clear");
@@ -390,7 +450,7 @@ namespace chaiscript
template<typename ContainerType> 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()))
{ {
m->add(fun(boost::function<int (const ContainerType *, const typename ContainerType::key_type &)>(boost::mem_fn(&ContainerType::count))), "count"); m->add(fun(boost::function<int (const ContainerType *, const typename ContainerType::key_type &)>(detail::return_int(&ContainerType::count))), "count");
return m; return m;
} }
@@ -512,15 +572,14 @@ namespace chaiscript
m->add(fun(&String::push_back), push_back_name); m->add(fun(&String::push_back), push_back_name);
typedef typename String::size_type (String::*find_func_ptr)(const String &, typename String::size_type) const; typedef 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; 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(detail::return_int(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(detail::return_int(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(detail::return_int(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(detail::return_int(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(detail::return_int(static_cast<find_func_ptr>(&String::find_first_not_of)))), "find_first_not_of");
m->add(fun(find_func(boost::mem_fn(static_cast<find_func_ptr>(&String::find_last_not_of)))), "find_last_not_of"); m->add(fun(find_func(detail::return_int(static_cast<find_func_ptr>(&String::find_last_not_of)))), "find_last_not_of");
m->add(fun(&String::c_str), "c_str"); m->add(fun(&String::c_str), "c_str");
m->add(fun(&String::data), "data"); m->add(fun(&String::data), "data");

View File

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

View File

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

View File

@@ -1,6 +1,6 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com) // and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
@@ -14,13 +14,21 @@
namespace chaiscript namespace chaiscript
{ {
#ifdef BOOST_MSVC
#pragma warning(push)
#pragma warning(disable : 4244 4018 4389 4146)
#endif
/// \brief Represents any numeric type, generically. Used internally for generic operations between POD values /// \brief Represents any numeric type, generically. Used internally for generic operations between POD values
class Boxed_Number class Boxed_Number
{ {
private: private:
struct boolean struct boolean
{ {
#ifdef __GNUC__
#pragma GCC diagnostic ignored "-Wsign-compare" #pragma GCC diagnostic ignored "-Wsign-compare"
#endif
template<typename T, typename U> template<typename T, typename U>
static Boxed_Value go(Operators::Opers t_oper, const T &t, const U &u, const Boxed_Value &) static Boxed_Value go(Operators::Opers t_oper, const T &t, const U &u, const Boxed_Value &)
{ {
@@ -41,7 +49,6 @@ namespace chaiscript
default: default:
throw boost::bad_any_cast(); throw boost::bad_any_cast();
} }
throw boost::bad_any_cast();
} }
}; };
@@ -137,7 +144,6 @@ namespace chaiscript
default: default:
throw boost::bad_any_cast(); throw boost::bad_any_cast();
} }
throw boost::bad_any_cast();
} }
}; };
@@ -163,7 +169,6 @@ namespace chaiscript
default: default:
throw boost::bad_any_cast(); throw boost::bad_any_cast();
} }
throw boost::bad_any_cast();
} }
}; };
@@ -276,7 +281,7 @@ namespace chaiscript
} else if (inp_ == typeid(boost::int8_t)) { } else if (inp_ == typeid(boost::int8_t)) {
return oper_rhs<boost::int8_t, false>(t_oper, t_lhs, t_rhs); return oper_rhs<boost::int8_t, false>(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(boost::int16_t)) { } else if (inp_ == typeid(boost::int16_t)) {
return oper_rhs<boost::int32_t, false>(t_oper, t_lhs, t_rhs); return oper_rhs<boost::int16_t, false>(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(boost::int32_t)) { } else if (inp_ == typeid(boost::int32_t)) {
return oper_rhs<boost::int32_t, false>(t_oper, t_lhs, t_rhs); return oper_rhs<boost::int32_t, false>(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(boost::int64_t)) { } else if (inp_ == typeid(boost::int64_t)) {
@@ -297,19 +302,15 @@ namespace chaiscript
public: public:
Boxed_Number()
: bv(Boxed_Value(0))
{
}
Boxed_Number(const Boxed_Value &v) Boxed_Number(const Boxed_Value &v)
: bv(v) : bv(v)
{ {
const Type_Info &inp_ = v.get_type_info(); validate_boxed_number(v);
if (inp_ == typeid(bool))
{
throw boost::bad_any_cast();
}
if (!inp_.is_arithmetic())
{
throw boost::bad_any_cast();
}
} }
@@ -378,6 +379,27 @@ namespace chaiscript
return oper(Operators::assign_bitwise_and, this->bv, t_rhs.bv); return oper(Operators::assign_bitwise_and, this->bv, t_rhs.bv);
} }
void validate_boxed_number(const Boxed_Value &v)
{
const Type_Info &inp_ = v.get_type_info();
if (inp_ == typeid(bool))
{
throw boost::bad_any_cast();
}
if (!inp_.is_arithmetic())
{
throw boost::bad_any_cast();
}
}
Boxed_Number operator=(const Boxed_Value &v)
{
validate_boxed_number(v);
bv = v;
return *this;
}
Boxed_Number operator=(const Boxed_Number &t_rhs) const Boxed_Number operator=(const Boxed_Number &t_rhs) const
{ {
return oper(Operators::assign, this->bv, t_rhs.bv); return oper(Operators::assign, this->bv, t_rhs.bv);
@@ -681,6 +703,10 @@ namespace chaiscript
}; };
} }
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif
} }

View File

@@ -1,6 +1,6 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com) // and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
@@ -71,7 +71,6 @@ namespace chaiscript
void *m_data_ptr; void *m_data_ptr;
const void *m_const_data_ptr; const void *m_const_data_ptr;
bool m_is_ref; bool m_is_ref;
std::vector<boost::shared_ptr<Data> > m_dependencies;
}; };
struct Object_Data struct Object_Data
@@ -242,24 +241,6 @@ namespace chaiscript
return !is_ref(); return !is_ref();
} }
void clear_dependencies()
{
m_data->m_dependencies.clear();
}
template<typename InItr>
void add_dependencies(InItr begin, const InItr &end)
{
while (begin != end)
{
if (begin->m_data != m_data)
{
m_data->m_dependencies.push_back(begin->m_data);
}
++begin;
}
}
void *get_ptr() const void *get_ptr() const
{ {
return m_data->m_data_ptr; return m_data->m_data_ptr;

View File

@@ -1,6 +1,6 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com) // and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
@@ -18,6 +18,7 @@
#include <vector> #include <vector>
#include <iostream> #include <iostream>
#include <deque> #include <deque>
#include <list>
#include "boxed_value.hpp" #include "boxed_value.hpp"
#include "type_info.hpp" #include "type_info.hpp"
@@ -32,6 +33,71 @@
namespace chaiscript namespace chaiscript
{ {
namespace exception
{
/**
* Exception thrown in the case that an object name is invalid because it is a reserved word
*/
class reserved_word_error : public std::runtime_error
{
public:
reserved_word_error(const std::string &t_word) throw()
: std::runtime_error("Reserved word not allowed in object name: " + t_word), m_word(t_word)
{
}
virtual ~reserved_word_error() throw() {}
std::string word() const
{
return m_word;
}
private:
std::string m_word;
};
/**
* Exception thrown in the case that an object name is invalid because it already exists in current context
*/
class name_conflict_error : public std::runtime_error
{
public:
name_conflict_error(const std::string &t_name) throw()
: std::runtime_error("Name already exists in current context " + t_name), m_name(t_name)
{
}
virtual ~name_conflict_error() throw() {}
std::string name() const
{
return m_name;
}
private:
std::string m_name;
};
/**
* Exception thrown in the case that a non-const object was added as a shared object
*/
class global_non_const : public std::runtime_error
{
public:
global_non_const() throw()
: std::runtime_error("a global object must be const")
{
}
virtual ~global_non_const() throw() {}
};
}
/// \brief Holds a collection of ChaiScript settings which can be applied to the ChaiScript runtime. /// \brief Holds a collection of ChaiScript settings which can be applied to the ChaiScript runtime.
/// Used to implement loadable module support. /// Used to implement loadable module support.
class Module class Module
@@ -55,6 +121,17 @@ namespace chaiscript
return *this; return *this;
} }
Module &add_global_const(const Boxed_Value &t_bv, const std::string &t_name)
{
if (!t_bv.is_const())
{
throw exception::global_non_const();
}
m_globals.push_back(std::make_pair(t_bv, t_name));
return *this;
}
//Add a bit of chaiscript to eval during module implementation //Add a bit of chaiscript to eval during module implementation
Module &eval(const std::string &str) Module &eval(const std::string &str)
@@ -76,11 +153,13 @@ namespace chaiscript
apply(m_funcs.begin(), m_funcs.end(), t_engine); apply(m_funcs.begin(), m_funcs.end(), t_engine);
apply_eval(m_evals.begin(), m_evals.end(), t_eval); apply_eval(m_evals.begin(), m_evals.end(), t_eval);
apply_single(m_conversions.begin(), m_conversions.end(), t_engine); apply_single(m_conversions.begin(), m_conversions.end(), t_engine);
apply_globals(m_globals.begin(), m_globals.end(), t_engine);
} }
private: private:
std::vector<std::pair<Type_Info, std::string> > m_typeinfos; std::vector<std::pair<Type_Info, std::string> > m_typeinfos;
std::vector<std::pair<Proxy_Function, std::string> > m_funcs; std::vector<std::pair<Proxy_Function, std::string> > m_funcs;
std::vector<std::pair<Boxed_Value, std::string> > m_globals;
std::vector<std::string> m_evals; std::vector<std::string> m_evals;
std::vector<Dynamic_Cast_Conversion> m_conversions; std::vector<Dynamic_Cast_Conversion> m_conversions;
@@ -89,7 +168,22 @@ namespace chaiscript
{ {
while (begin != end) while (begin != end)
{ {
t.add(begin->first, begin->second); try {
t.add(begin->first, begin->second);
} catch (const exception::name_conflict_error &) {
/// \todo Should we throw an error if there's a name conflict
/// while applying a module?
}
++begin;
}
}
template<typename T, typename InItr>
void apply_globals(InItr begin, InItr end, T &t) const
{
while (begin != end)
{
t.add_global_const(begin->first, begin->second);
++begin; ++begin;
} }
} }
@@ -266,48 +360,6 @@ namespace chaiscript
}; };
} }
namespace exception
{
/**
* Exception thrown in the case that a multi method dispatch fails
* because no matching function was found
* at runtime due to either an arity_error, a guard_error or a bad_boxed_cast
* exception
*/
class reserved_word_error : public std::runtime_error
{
public:
reserved_word_error(const std::string &t_word) throw()
: std::runtime_error("Reserved word not allowed in object name: " + t_word), m_word(t_word)
{
}
virtual ~reserved_word_error() throw() {}
std::string word() const
{
return m_word;
}
private:
std::string m_word;
};
/**
* Exception thrown in the case that a non-const object was added as a shared object
*/
class global_non_const : public std::runtime_error
{
public:
global_non_const() throw()
: std::runtime_error("a global object must be const")
{
}
virtual ~global_non_const() throw() {}
};
}
namespace detail namespace detail
{ {
@@ -326,6 +378,7 @@ namespace chaiscript
struct State struct State
{ {
std::map<std::string, std::vector<Proxy_Function> > m_functions; std::map<std::string, std::vector<Proxy_Function> > m_functions;
std::map<std::string, Proxy_Function> m_function_objects;
std::map<std::string, Boxed_Value> m_global_objects; std::map<std::string, Boxed_Value> m_global_objects;
Type_Name_Map m_types; Type_Name_Map m_types;
std::set<std::string> m_reserved_words; std::set<std::string> m_reserved_words;
@@ -353,10 +406,10 @@ namespace chaiscript
/** /**
* Add a new named Proxy_Function to the system * Add a new named Proxy_Function to the system
*/ */
bool add(const Proxy_Function &f, const std::string &name) void add(const Proxy_Function &f, const std::string &name)
{ {
validate_object_name(name); validate_object_name(name);
return add_function(f, name); add_function(f, name);
} }
/** /**
@@ -381,6 +434,7 @@ namespace chaiscript
add_object(name, obj); add_object(name, obj);
} }
/** /**
* Adds a named object to the current scope * Adds a named object to the current scope
*/ */
@@ -388,7 +442,15 @@ namespace chaiscript
{ {
StackData &stack = get_stack_data(); StackData &stack = get_stack_data();
validate_object_name(name); validate_object_name(name);
stack.back()[name] = obj;
Scope &scope = stack.back();
Scope::iterator itr = scope.find(name);
if (itr != stack.back().end())
{
throw exception::name_conflict_error(name);
} else {
stack.back().insert(std::make_pair(name, obj));
}
} }
/** /**
@@ -404,7 +466,12 @@ namespace chaiscript
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_global_object_mutex); chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_global_object_mutex);
m_state.m_global_objects[name] = obj; if (m_state.m_global_objects.find(name) != m_state.m_global_objects.end())
{
throw exception::name_conflict_error(name);
} else {
m_state.m_global_objects.insert(std::make_pair(name, obj));
}
} }
/** /**
@@ -430,28 +497,24 @@ namespace chaiscript
} }
} }
/**
* Swaps out the stack with a new stack
* \returns the old stack
* \param[in] s The new stack
*/
Stack set_stack(const Stack &s)
{
Stack old = m_stack_holder->stack;
m_stack_holder->stack = s;
return old;
}
Stack new_stack() const /// Pushes a new stack on to the list of stacks
void new_stack()
{ {
Stack s(new Stack::element_type()); Stack s(new Stack::element_type());
s->push_back(Scope()); s->push_back(Scope());
return s; m_stack_holder->stacks.push_back(s);
} }
void pop_stack()
{
m_stack_holder->stacks.pop_back();
}
/// \returns the current stack
Stack get_stack() const Stack get_stack() const
{ {
return m_stack_holder->stack; return m_stack_holder->stacks.back();
} }
/** /**
@@ -491,21 +554,7 @@ namespace chaiscript
} }
// If all that failed, then check to see if it's a function // If all that failed, then check to see if it's a function
std::vector<Proxy_Function> funcs = get_function(name); return get_function_object(name);
if (funcs.empty())
{
throw std::range_error("Object not known: " + name);
} else {
if (funcs.size() == 1)
{
// Return the first item if there is only one,
// no reason to take the cast of the extra level of dispatch
return const_var(*funcs.begin());
} else {
return Boxed_Value(Const_Proxy_Function(new Dispatch_Function(funcs)));
}
}
} }
/** /**
@@ -588,9 +637,26 @@ namespace chaiscript
} else { } else {
return std::vector<Proxy_Function>(); return std::vector<Proxy_Function>();
} }
} }
/// \returns a function object (Boxed_Value wrapper) if it exists
/// \throws std::range_error if it does not
Boxed_Value get_function_object(const std::string &t_name) const
{
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
const std::map<std::string, Proxy_Function> &funs = get_function_objects_int();
std::map<std::string, Proxy_Function>::const_iterator itr = funs.find(t_name);
if (itr != funs.end())
{
return const_var(itr->second);
} else {
throw std::range_error("Object not found: " + t_name);
}
}
/** /**
* Return true if a function exists * Return true if a function exists
*/ */
@@ -602,6 +668,57 @@ namespace chaiscript
return functions.find(name) != functions.end(); return functions.find(name) != functions.end();
} }
///
/// Get a map of all objects that can be seen from the current scope in a scripting context
///
std::map<std::string, Boxed_Value> get_scripting_objects() const
{
// We don't want the current context, but one up if it exists
StackData &stack = (m_stack_holder->stacks.size()==1)?(*(m_stack_holder->stacks.back())):(*m_stack_holder->stacks[m_stack_holder->stacks.size()-2]);
std::map<std::string, Boxed_Value> retval;
// note: map insert doesn't overwrite existing values, which is why this works
for (StackData::reverse_iterator itr = stack.rbegin(); itr != stack.rend(); ++itr)
{
retval.insert(itr->begin(), itr->end());
}
// add the global values
{
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_global_object_mutex);
retval.insert(m_state.m_global_objects.begin(), m_state.m_global_objects.end());
}
return retval;
}
///
/// Get a map of all functions that can be seen from a scripting context
///
std::map<std::string, Boxed_Value> get_function_objects() const
{
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
const std::map<std::string, Proxy_Function> &funs = get_function_objects_int();
std::map<std::string, Boxed_Value> objs;
for (std::map<std::string, Proxy_Function>::const_iterator itr = funs.begin();
itr != funs.end();
++itr)
{
objs.insert(std::make_pair(itr->first, const_var(itr->second)));
}
return objs;
}
/** /**
* Get a vector of all registered functions * Get a vector of all registered functions
*/ */
@@ -781,6 +898,29 @@ namespace chaiscript
m_state = t_state; m_state = t_state;
} }
void save_function_params(const std::vector<Boxed_Value> &t_params)
{
m_stack_holder->call_params.insert(m_stack_holder->call_params.begin(), t_params.begin(), t_params.end());
}
void new_function_call()
{
++m_stack_holder->call_depth;
}
void pop_function_call()
{
--m_stack_holder->call_depth;
assert(m_stack_holder->call_depth >= 0);
if (m_stack_holder->call_depth == 0)
{
/// \todo Critical: this needs to be smarter, memory can expand quickly
/// in tight loops involving function calls
m_stack_holder->call_params.clear();
}
}
private: private:
/** /**
@@ -789,7 +929,17 @@ namespace chaiscript
*/ */
StackData &get_stack_data() const StackData &get_stack_data() const
{ {
return *(m_stack_holder->stack); return *(m_stack_holder->stacks.back());
}
const std::map<std::string, Proxy_Function> &get_function_objects_int() const
{
return m_state.m_function_objects;
}
std::map<std::string, Proxy_Function> &get_function_objects_int()
{
return m_state.m_function_objects;
} }
const std::map<std::string, std::vector<Proxy_Function> > &get_functions_int() const const std::map<std::string, std::vector<Proxy_Function> > &get_functions_int() const
@@ -911,11 +1061,10 @@ namespace chaiscript
} }
/** /**
* Implementation detail for adding a function. Returns * Implementation detail for adding a function.
* true if the function was added, false if a function with the * \throws exception::name_conflict_error if there's a function matching the given one being added
* same signature and name already exists.
*/ */
bool add_function(const Proxy_Function &t_f, const std::string &t_name) void add_function(const Proxy_Function &t_f, const std::string &t_name)
{ {
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex); chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
@@ -924,6 +1073,8 @@ namespace chaiscript
std::map<std::string, std::vector<Proxy_Function> >::iterator itr std::map<std::string, std::vector<Proxy_Function> >::iterator itr
= funcs.find(t_name); = funcs.find(t_name);
std::map<std::string, Proxy_Function> &func_objs = get_function_objects_int();
if (itr != funcs.end()) if (itr != funcs.end())
{ {
std::vector<Proxy_Function> &vec = itr->second; std::vector<Proxy_Function> &vec = itr->second;
@@ -933,19 +1084,21 @@ namespace chaiscript
{ {
if ((*t_f) == *(*itr2)) if ((*t_f) == *(*itr2))
{ {
return false; throw exception::name_conflict_error(t_name);
} }
} }
vec.push_back(t_f); vec.push_back(t_f);
std::stable_sort(vec.begin(), vec.end(), &function_less_than); std::stable_sort(vec.begin(), vec.end(), &function_less_than);
func_objs[t_name] = Proxy_Function(new Dispatch_Function(vec));
} else { } else {
std::vector<Proxy_Function> vec; std::vector<Proxy_Function> vec;
vec.push_back(t_f); vec.push_back(t_f);
funcs.insert(std::make_pair(t_name, vec)); funcs.insert(std::make_pair(t_name, vec));
func_objs[t_name] = t_f;
} }
return true;
} }
mutable chaiscript::detail::threading::shared_mutex m_mutex; mutable chaiscript::detail::threading::shared_mutex m_mutex;
@@ -954,12 +1107,17 @@ namespace chaiscript
struct Stack_Holder struct Stack_Holder
{ {
Stack_Holder() Stack_Holder()
: stack(new StackData()) : call_depth(0)
{ {
stack->push_back(Scope()); Stack s(new StackData());
s->push_back(Scope());
stacks.push_back(s);
} }
Stack stack; std::deque<Stack> stacks;
std::list<Boxed_Value> call_params;
int call_depth;
}; };
std::vector<Dynamic_Cast_Conversion> m_conversions; std::vector<Dynamic_Cast_Conversion> m_conversions;

View File

@@ -1,6 +1,6 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com) // and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
@@ -48,6 +48,7 @@ namespace chaiscript
{ {
public: public:
virtual Boxed_Value convert(const Boxed_Value &derived) = 0; virtual Boxed_Value convert(const Boxed_Value &derived) = 0;
const Type_Info &base() const Type_Info &base()
{ {
return m_base; return m_base;
@@ -63,6 +64,8 @@ namespace chaiscript
{ {
} }
virtual ~Dynamic_Conversion() {}
private: private:
Type_Info m_base; Type_Info m_base;
Type_Info m_derived; Type_Info m_derived;

View File

@@ -1,6 +1,6 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com) // and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
@@ -44,20 +44,6 @@ namespace chaiscript
namespace detail namespace detail
{ {
struct Dynamic_Object_Attribute
{
static Boxed_Value func(const std::string &t_type_name, const std::string &t_attr_name,
Dynamic_Object &t_do)
{
if (t_do.get_type_name() != t_type_name)
{
throw exception::bad_boxed_cast("Dynamic object type mismatch");
}
return t_do.get_attr(t_attr_name);
}
};
/** /**
* A Proxy_Function implementation designed for calling a function * A Proxy_Function implementation designed for calling a function
* that is automatically guarded based on the first param based on the * that is automatically guarded based on the first param based on the

View File

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

View File

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

View File

@@ -1,6 +1,6 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com) // and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
@@ -34,6 +34,15 @@ namespace chaiscript
} }
}; };
template<typename Ret>
struct Handle_Return<Ret *>
{
static Boxed_Value handle(Ret *p)
{
return Boxed_Value(p);
}
};
template<typename Ret> template<typename Ret>
struct Handle_Return<boost::shared_ptr<Ret> &> struct Handle_Return<boost::shared_ptr<Ret> &>
{ {

View File

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

View File

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

View File

@@ -1,6 +1,6 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com) // and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
@@ -74,7 +74,6 @@ namespace chaiscript
Boxed_Value operator()(const std::vector<Boxed_Value> &params) const Boxed_Value operator()(const std::vector<Boxed_Value> &params) const
{ {
Boxed_Value bv = do_call(params); Boxed_Value bv = do_call(params);
bv.add_dependencies(params.begin(), params.end());
return bv; return bv;
} }
@@ -219,7 +218,12 @@ namespace chaiscript
virtual bool operator==(const Proxy_Function_Base &rhs) const virtual bool operator==(const Proxy_Function_Base &rhs) const
{ {
return this == &rhs; const Dynamic_Proxy_Function *prhs = dynamic_cast<const Dynamic_Proxy_Function *>(&rhs);
return this == &rhs
|| (prhs
&& this->m_arity == prhs->m_arity
&& !this->m_guard && !prhs->m_guard);
} }
virtual bool call_match(const std::vector<Boxed_Value> &vals) const virtual bool call_match(const std::vector<Boxed_Value> &vals) const

View File

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

View File

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

View File

@@ -1,6 +1,6 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com) // and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
@@ -39,39 +39,40 @@ namespace chaiscript
public: public:
Type_Info(bool t_is_const, bool t_is_reference, bool t_is_pointer, bool t_is_void, Type_Info(bool t_is_const, bool t_is_reference, bool t_is_pointer, bool t_is_void,
bool t_is_arithmetic, const std::type_info *t_ti, const std::type_info *t_bareti) bool t_is_arithmetic, const std::type_info *t_ti, const std::type_info *t_bareti)
: m_is_const(t_is_const), m_is_reference(t_is_reference), m_is_pointer(t_is_pointer), : m_type_info(t_ti), m_bare_type_info(t_bareti),
m_is_const(t_is_const), m_is_reference(t_is_reference), m_is_pointer(t_is_pointer),
m_is_void(t_is_void), m_is_arithmetic(t_is_arithmetic), m_is_void(t_is_void), m_is_arithmetic(t_is_arithmetic),
m_type_info(t_ti), m_bare_type_info(t_bareti),
m_is_undef(false) m_is_undef(false)
{ {
} }
Type_Info() Type_Info()
: m_is_const(false), m_is_reference(false), m_is_pointer(false), : m_type_info(0), m_bare_type_info(0),
m_is_void(false), m_is_arithmetic(false), m_type_info(0), m_bare_type_info(0), m_is_const(false), m_is_reference(false), m_is_pointer(false),
m_is_void(false), m_is_arithmetic(false),
m_is_undef(true) m_is_undef(true)
{ {
} }
Type_Info(const Type_Info &ti) Type_Info(const Type_Info &ti)
: m_is_const(ti.m_is_const), m_is_reference(ti.m_is_reference), : m_type_info(ti.m_type_info),
m_bare_type_info(ti.m_bare_type_info),
m_is_const(ti.m_is_const), m_is_reference(ti.m_is_reference),
m_is_pointer(ti.m_is_pointer), m_is_pointer(ti.m_is_pointer),
m_is_void(ti.m_is_void), m_is_arithmetic(ti.m_is_arithmetic), m_is_void(ti.m_is_void), m_is_arithmetic(ti.m_is_arithmetic),
m_type_info(ti.m_type_info),
m_bare_type_info(ti.m_bare_type_info),
m_is_undef(ti.m_is_undef) m_is_undef(ti.m_is_undef)
{ {
} }
Type_Info &operator=(const Type_Info &ti) Type_Info &operator=(const Type_Info &ti)
{ {
m_type_info = ti.m_type_info;
m_bare_type_info = ti.m_bare_type_info;
m_is_const = ti.m_is_const; m_is_const = ti.m_is_const;
m_is_reference = ti.m_is_reference; m_is_reference = ti.m_is_reference;
m_is_pointer = ti.m_is_pointer; m_is_pointer = ti.m_is_pointer;
m_is_void = ti.m_is_void; m_is_void = ti.m_is_void;
m_is_arithmetic = ti.m_is_arithmetic; m_is_arithmetic = ti.m_is_arithmetic;
m_type_info = ti.m_type_info;
m_bare_type_info = ti.m_bare_type_info;
m_is_undef = ti.m_is_undef; m_is_undef = ti.m_is_undef;
return *this; return *this;
} }
@@ -126,13 +127,13 @@ namespace chaiscript
} }
private: private:
const std::type_info *m_type_info;
const std::type_info *m_bare_type_info;
bool m_is_const; bool m_is_const;
bool m_is_reference; bool m_is_reference;
bool m_is_pointer; bool m_is_pointer;
bool m_is_void; bool m_is_void;
bool m_is_arithmetic; bool m_is_arithmetic;
const std::type_info *m_type_info;
const std::type_info *m_bare_type_info;
bool m_is_undef; bool m_is_undef;
}; };

View File

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

View File

@@ -1,6 +1,6 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com) // and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
@@ -23,7 +23,7 @@ namespace chaiscript
Comparison, Addition, Subtraction, Multiplication, Division, Modulus, Array_Call, Dot_Access, Quoted_String, Single_Quoted_String, Comparison, Addition, Subtraction, Multiplication, Division, Modulus, Array_Call, Dot_Access, Quoted_String, Single_Quoted_String,
Lambda, Block, Def, While, If, For, Inline_Array, Inline_Map, Return, File, Prefix, Break, Map_Pair, Value_Range, 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, Inline_Range, Annotation, Try, Catch, Finally, Method, Attr_Decl, Shift, Equality, Bitwise_And, Bitwise_Xor, Bitwise_Or,
Logical_And, Logical_Or Logical_And, Logical_Or, Switch, Case, Default, Ternary_Cond
}; };
}; };
@@ -37,7 +37,7 @@ namespace chaiscript
"Comparison", "Addition", "Subtraction", "Multiplication", "Division", "Modulus", "Array_Call", "Dot_Access", "Quoted_String", "Single_Quoted_String", "Comparison", "Addition", "Subtraction", "Multiplication", "Division", "Modulus", "Array_Call", "Dot_Access", "Quoted_String", "Single_Quoted_String",
"Lambda", "Block", "Def", "While", "If", "For", "Inline_Array", "Inline_Map", "Return", "File", "Prefix", "Break", "Map_Pair", "Value_Range", "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", "Inline_Range", "Annotation", "Try", "Catch", "Finally", "Method", "Attr_Decl", "Shift", "Equality", "Bitwise_And", "Bitwise_Xor", "Bitwise_Or",
"Logical_And", "Logical_Or"}; "Logical_And", "Logical_Or", "Switch", "Case", "Default", "Ternary Condition"};
return ast_node_types[ast_node_type]; return ast_node_types[ast_node_type];
} }
@@ -213,6 +213,57 @@ namespace chaiscript
chaiscript::detail::Dispatch_Engine &m_de; chaiscript::detail::Dispatch_Engine &m_de;
}; };
/// Creates a new functon call and pops it on destruction
struct Function_Push_Pop
{
Function_Push_Pop(chaiscript::detail::Dispatch_Engine &t_de)
: m_de(t_de)
{
m_de.new_function_call();
}
~Function_Push_Pop()
{
m_de.pop_function_call();
}
void save_params(const std::vector<Boxed_Value> &t_params)
{
m_de.save_function_params(t_params);
}
private:
// explicitly unimplemented copy and assignment
Function_Push_Pop(const Function_Push_Pop &);
Function_Push_Pop& operator=(const Function_Push_Pop &);
chaiscript::detail::Dispatch_Engine &m_de;
};
/// Creates a new scope then pops it on destruction
struct Stack_Push_Pop
{
Stack_Push_Pop(chaiscript::detail::Dispatch_Engine &t_de)
: m_de(t_de)
{
m_de.new_stack();
}
~Stack_Push_Pop()
{
m_de.pop_stack();
}
private:
// explicitly unimplemented copy and assignment
Stack_Push_Pop(const Stack_Push_Pop &);
Stack_Push_Pop& operator=(const Stack_Push_Pop &);
chaiscript::detail::Dispatch_Engine &m_de;
};
} }
} }
} }

View File

@@ -1,6 +1,6 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com) // and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
@@ -76,7 +76,7 @@ namespace chaiscript
struct DLSym struct DLSym
{ {
DLSym(DLModule &t_mod, const std::string &t_symbol) DLSym(DLModule &t_mod, const std::string &t_symbol)
: m_symbol(reinterpret_cast<T>(dlsym(t_mod.m_data, t_symbol.c_str()))) : m_symbol(cast_symbol(dlsym(t_mod.m_data, t_symbol.c_str())))
{ {
if (!m_symbol) if (!m_symbol)
{ {
@@ -84,6 +84,19 @@ namespace chaiscript
} }
} }
static T cast_symbol(void *p)
{
union cast_union
{
T func_ptr;
void *in_ptr;
};
cast_union c;
c.in_ptr = p;
return c.func_ptr;
}
T m_symbol; T m_symbol;
}; };
@@ -261,7 +274,11 @@ namespace chaiscript
const Boxed_Value internal_eval_ast(const AST_NodePtr &t_ast) const Boxed_Value internal_eval_ast(const AST_NodePtr &t_ast)
{ {
return t_ast->eval(m_engine); try {
return t_ast->eval(m_engine);
} catch (const exception::eval_error &t_ee) {
throw Boxed_Value(t_ee);
}
} }
@@ -269,37 +286,14 @@ namespace chaiscript
* Evaluates the given string, used during eval() inside of a script * Evaluates the given string, used during eval() inside of a script
*/ */
const Boxed_Value internal_eval(const std::string &t_e) { const Boxed_Value internal_eval(const std::string &t_e) {
return do_eval(t_e, "__EVAL__", true); try {
} return do_eval(t_e, "__EVAL__", true);
} catch (const exception::eval_error &t_ee) {
void use(const std::string &t_filename) throw Boxed_Value(t_ee);
{
for (size_t i = 0; i < m_usepaths.size(); ++i)
{
try {
const std::string appendedpath = m_usepaths[i] + t_filename;
chaiscript::detail::threading::lock_guard<chaiscript::detail::threading::recursive_mutex> l(m_use_mutex);
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l2(m_mutex);
if (m_used_files.count(appendedpath) == 0)
{
m_used_files.insert(appendedpath);
l2.unlock();
eval_file(appendedpath);
}
} catch (const exception::file_not_found_error &) {
if (i == m_usepaths.size() - 1)
{
throw exception::file_not_found_error(t_filename);
}
// failed to load, try the next path
}
} }
} }
/** /**
* Returns the current evaluation m_engine * Returns the current evaluation m_engine
*/ */
@@ -312,6 +306,7 @@ namespace chaiscript
*/ */
void build_eval_system() { void build_eval_system() {
using namespace bootstrap; using namespace bootstrap;
m_engine.add_reserved_word("auto");
m_engine.add_reserved_word("def"); m_engine.add_reserved_word("def");
m_engine.add_reserved_word("fun"); m_engine.add_reserved_word("fun");
m_engine.add_reserved_word("while"); m_engine.add_reserved_word("while");
@@ -336,6 +331,8 @@ namespace chaiscript
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::is_type, boost::ref(m_engine)), "is_type"); m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::is_type, boost::ref(m_engine)), "is_type");
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::type_name, boost::ref(m_engine)), "type_name"); m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::type_name, boost::ref(m_engine)), "type_name");
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::function_exists, boost::ref(m_engine)), "function_exists"); m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::function_exists, boost::ref(m_engine)), "function_exists");
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::get_function_objects, boost::ref(m_engine)), "get_functions");
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::get_scripting_objects, boost::ref(m_engine)), "get_objects");
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::get_type_name, boost::ref(m_engine)), "name"); m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::get_type_name, boost::ref(m_engine)), "name");
@@ -404,6 +401,40 @@ namespace chaiscript
build_eval_system(); build_eval_system();
} }
/// \brief Loads and parses a file. If the file is already, it is not reloaded
/// The use paths specified at ChaiScript construction time are searched for the
/// requested file.
///
/// \param[in] t_filename Filename to load and evaluate
void use(const std::string &t_filename)
{
for (size_t i = 0; i < m_usepaths.size(); ++i)
{
try {
const std::string appendedpath = m_usepaths[i] + t_filename;
chaiscript::detail::threading::lock_guard<chaiscript::detail::threading::recursive_mutex> l(m_use_mutex);
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l2(m_mutex);
if (m_used_files.count(appendedpath) == 0)
{
m_used_files.insert(appendedpath);
l2.unlock();
eval_file(appendedpath);
}
return; // return, we loaded it, or it was already loaded
} catch (const exception::file_not_found_error &) {
if (i == m_usepaths.size() - 1)
{
throw exception::file_not_found_error(t_filename);
}
// failed to load, try the next path
}
}
}
/// \brief Adds a constant object that is available in all contexts and to all threads /// \brief Adds a constant object that is available in all contexts and to all threads
/// \param[in] t_bv Boxed_Value to add as a global /// \param[in] t_bv Boxed_Value to add as a global
/// \param[in] t_name Name of the value to add /// \param[in] t_name Name of the value to add

View File

@@ -1,6 +1,6 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com) // and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
@@ -54,6 +54,12 @@ namespace chaiscript
Operators::Opers t_oper, const std::string &t_oper_string, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs) Operators::Opers t_oper, const std::string &t_oper_string, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs)
{ {
try { try {
chaiscript::eval::detail::Function_Push_Pop fpp(t_ss);
std::vector<Boxed_Value> params(2);
params.push_back(t_lhs);
params.push_back(t_rhs);
fpp.save_params(params);
if (t_oper != Operators::invalid && t_lhs.get_type_info().is_arithmetic() && t_rhs.get_type_info().is_arithmetic()) if (t_oper != Operators::invalid && t_lhs.get_type_info().is_arithmetic() && t_rhs.get_type_info().is_arithmetic())
{ {
// If it's an arithmetic operation we want to short circuit dispatch // If it's an arithmetic operation we want to short circuit dispatch
@@ -64,6 +70,7 @@ namespace chaiscript
} }
} else { } else {
chaiscript::eval::detail::Stack_Push_Pop spp(t_ss);
return t_ss.call_function(t_oper_string, t_lhs, t_rhs); return t_ss.call_function(t_oper_string, t_lhs, t_rhs);
} }
} }
@@ -182,6 +189,7 @@ namespace chaiscript
AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
virtual ~Fun_Call_AST_Node() {} virtual ~Fun_Call_AST_Node() {}
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss){ virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss){
chaiscript::eval::detail::Function_Push_Pop fpp(t_ss);
dispatch::Param_List_Builder plb; dispatch::Param_List_Builder plb;
if ((this->children.size() > 1) && (this->children[1]->identifier == AST_Node_Type::Arg_List)) { if ((this->children.size() > 1) && (this->children[1]->identifier == AST_Node_Type::Arg_List)) {
@@ -190,36 +198,21 @@ namespace chaiscript
} }
} }
chaiscript::detail::Dispatch_Engine::Stack prev_stack = t_ss.get_stack(); fpp.save_params(plb.objects);
chaiscript::detail::Dispatch_Engine::Stack new_stack = t_ss.new_stack();
Boxed_Value fn = this->children[0]->eval(t_ss);
try { try {
Boxed_Value fn = this->children[0]->eval(t_ss); chaiscript::eval::detail::Stack_Push_Pop spp(t_ss);
const Boxed_Value &retval = (*boxed_cast<const Const_Proxy_Function &>(fn))(plb);
try { return retval;
t_ss.set_stack(new_stack);
const Boxed_Value &retval = (*boxed_cast<const Const_Proxy_Function &>(fn))(plb);
t_ss.set_stack(prev_stack);
return retval;
}
catch(const exception::dispatch_error &e){
t_ss.set_stack(prev_stack);
throw exception::eval_error(std::string(e.what()) + " with function '" + this->children[0]->text + "'");
}
catch(detail::Return_Value &rv) {
t_ss.set_stack(prev_stack);
return rv.retval;
}
catch(...) {
t_ss.set_stack(prev_stack);
throw;
}
} }
catch(exception::eval_error &) { catch(const exception::dispatch_error &e){
t_ss.set_stack(prev_stack); throw exception::eval_error(std::string(e.what()) + " with function '" + this->children[0]->text + "'");
throw; }
catch(detail::Return_Value &rv) {
return rv.retval;
} }
} }
}; };
@@ -296,7 +289,6 @@ namespace chaiscript
try { try {
if (lhs.is_undef()) { if (lhs.is_undef()) {
retval = t_ss.call_function("clone", retval); retval = t_ss.call_function("clone", retval);
retval.clear_dependencies();
} }
try { try {
@@ -340,6 +332,8 @@ namespace chaiscript
} }
catch (const exception::reserved_word_error &) { catch (const exception::reserved_word_error &) {
throw exception::eval_error("Reserved word used as variable '" + this->children[0]->text + "'"); throw exception::eval_error("Reserved word used as variable '" + this->children[0]->text + "'");
} catch (const exception::name_conflict_error &e) {
throw exception::eval_error("Variable redefined '" + e.name() + "'");
} }
return t_ss.get_object(this->children[0]->text); return t_ss.get_object(this->children[0]->text);
} }
@@ -419,11 +413,20 @@ namespace chaiscript
AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
virtual ~Array_Call_AST_Node() {} virtual ~Array_Call_AST_Node() {}
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss){ virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss){
chaiscript::eval::detail::Function_Push_Pop fpp(t_ss);
Boxed_Value retval = this->children[0]->eval(t_ss); Boxed_Value retval = this->children[0]->eval(t_ss);
std::vector<Boxed_Value> params;
params.push_back(retval);
for (size_t i = 1; i < this->children.size(); ++i) { for (size_t i = 1; i < this->children.size(); ++i) {
try { try {
retval = t_ss.call_function("[]", retval, this->children[i]->eval(t_ss)); Boxed_Value p1(this->children[i]->eval(t_ss));
chaiscript::eval::detail::Stack_Push_Pop spp(t_ss);
params.push_back(p1);
fpp.save_params(params);
params.clear();
retval = t_ss.call_function("[]", retval, p1);
} }
catch(std::out_of_range &) { catch(std::out_of_range &) {
throw exception::eval_error("Out of bounds exception"); throw exception::eval_error("Out of bounds exception");
@@ -447,6 +450,7 @@ namespace chaiscript
if (this->children.size() > 1) { if (this->children.size() > 1) {
for (size_t i = 2; i < this->children.size(); i+=2) { for (size_t i = 2; i < this->children.size(); i+=2) {
chaiscript::eval::detail::Function_Push_Pop fpp(t_ss);
dispatch::Param_List_Builder plb; dispatch::Param_List_Builder plb;
plb << retval; plb << retval;
@@ -456,6 +460,8 @@ namespace chaiscript
} }
} }
fpp.save_params(plb.objects);
std::string fun_name; std::string fun_name;
if ((this->children[i]->identifier == AST_Node_Type::Fun_Call) || (this->children[i]->identifier == AST_Node_Type::Array_Call)) { if ((this->children[i]->identifier == AST_Node_Type::Fun_Call) || (this->children[i]->identifier == AST_Node_Type::Array_Call)) {
fun_name = this->children[i]->children[0]->text; fun_name = this->children[i]->children[0]->text;
@@ -464,26 +470,17 @@ namespace chaiscript
fun_name = this->children[i]->text; fun_name = this->children[i]->text;
} }
chaiscript::detail::Dispatch_Engine::Stack prev_stack = t_ss.get_stack();
chaiscript::detail::Dispatch_Engine::Stack new_stack = t_ss.new_stack();
try { try {
t_ss.set_stack(new_stack); chaiscript::eval::detail::Stack_Push_Pop spp(t_ss);
retval = t_ss.call_function(fun_name, plb); retval = t_ss.call_function(fun_name, plb);
t_ss.set_stack(prev_stack);
} }
catch(const exception::dispatch_error &e){ catch(const exception::dispatch_error &e){
t_ss.set_stack(prev_stack);
throw exception::eval_error(std::string(e.what()) + " for function: " + fun_name); throw exception::eval_error(std::string(e.what()) + " for function: " + fun_name);
} }
catch(detail::Return_Value &rv) { catch(detail::Return_Value &rv) {
t_ss.set_stack(prev_stack);
retval = rv.retval; retval = rv.retval;
} }
catch(...) {
t_ss.set_stack(prev_stack);
throw;
}
if (this->children[i]->identifier == AST_Node_Type::Array_Call) { if (this->children[i]->identifier == AST_Node_Type::Array_Call) {
for (size_t j = 1; j < this->children[i]->children.size(); ++j) { for (size_t j = 1; j < this->children[i]->children.size(); ++j) {
try { try {
@@ -639,6 +636,8 @@ namespace chaiscript
} }
catch (const exception::reserved_word_error &e) { catch (const exception::reserved_word_error &e) {
throw exception::eval_error("Reserved word used as function name '" + e.word() + "'"); throw exception::eval_error("Reserved word used as function name '" + e.word() + "'");
} catch (const exception::name_conflict_error &e) {
throw exception::eval_error("Function redefined '" + e.name() + "'");
} }
return Boxed_Value(); return Boxed_Value();
} }
@@ -681,6 +680,29 @@ namespace chaiscript
}; };
struct Ternary_Cond_AST_Node : public AST_Node {
public:
Ternary_Cond_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::If, const boost::shared_ptr<std::string> &t_fname=boost::shared_ptr<std::string>(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
virtual ~Ternary_Cond_AST_Node() {}
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss){
bool cond;
try {
cond = boxed_cast<bool>(this->children[0]->eval(t_ss));
}
catch (const exception::bad_boxed_cast &) {
throw exception::eval_error("If condition not boolean");
}
if (cond) {
return this->children[1]->eval(t_ss);
}
else {
return this->children[2]->eval(t_ss);
}
}
};
struct If_AST_Node : public AST_Node { struct If_AST_Node : public AST_Node {
public: public:
If_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::If, const boost::shared_ptr<std::string> &t_fname=boost::shared_ptr<std::string>(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : If_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::If, const boost::shared_ptr<std::string> &t_fname=boost::shared_ptr<std::string>(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
@@ -776,20 +798,97 @@ namespace chaiscript
}; };
struct Switch_AST_Node : public AST_Node {
public:
Switch_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Switch, const boost::shared_ptr<std::string> &t_fname=boost::shared_ptr<std::string>(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
virtual ~Switch_AST_Node() {}
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) {
Boxed_Value match_value;
bool breaking = false;
size_t currentCase = 1;
bool hasMatched = false;
chaiscript::eval::detail::Scope_Push_Pop spp(t_ss);
match_value = this->children[0]->eval(t_ss);
while (!breaking && (currentCase < this->children.size())) {
try {
if (this->children[currentCase]->identifier == AST_Node_Type::Case) {
//This is a little odd, but because want to see both the switch and the case simultaneously, I do a downcast here.
try {
if (hasMatched || boxed_cast<bool>(t_ss.call_function("==", match_value, this->children[currentCase]->children[0]->eval(t_ss)))) {
this->children[currentCase]->eval(t_ss);
hasMatched = true;
}
}
catch (const exception::bad_boxed_cast &) {
throw exception::eval_error("Internal error: case guard evaluation not boolean");
}
}
else if (this->children[currentCase]->identifier == AST_Node_Type::Default) {
this->children[currentCase]->eval(t_ss);
breaking = true;
}
}
catch (detail::Break_Loop &) {
breaking = true;
}
++currentCase;
}
return Boxed_Value();
}
};
struct Case_AST_Node : public AST_Node {
public:
Case_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Case, const boost::shared_ptr<std::string> &t_fname=boost::shared_ptr<std::string>(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
virtual ~Case_AST_Node() {}
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) {
chaiscript::eval::detail::Scope_Push_Pop spp(t_ss);
this->children[1]->eval(t_ss);
return Boxed_Value();
}
};
struct Default_AST_Node : public AST_Node {
public:
Default_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Default, const boost::shared_ptr<std::string> &t_fname=boost::shared_ptr<std::string>(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
virtual ~Default_AST_Node() {}
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) {
chaiscript::eval::detail::Scope_Push_Pop spp(t_ss);
this->children[0]->eval(t_ss);
return Boxed_Value();
}
};
struct Inline_Array_AST_Node : public AST_Node { struct Inline_Array_AST_Node : public AST_Node {
public: public:
Inline_Array_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Inline_Array, const boost::shared_ptr<std::string> &t_fname=boost::shared_ptr<std::string>(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : Inline_Array_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Inline_Array, const boost::shared_ptr<std::string> &t_fname=boost::shared_ptr<std::string>(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
virtual ~Inline_Array_AST_Node() {} virtual ~Inline_Array_AST_Node() {}
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss){ virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss){
std::vector<Boxed_Value> vec; try {
if (this->children.size() > 0) { std::vector<Boxed_Value> vec;
for (size_t i = 0; i < this->children[0]->children.size(); ++i) { if (this->children.size() > 0) {
vec.push_back(this->children[0]->children[i]->eval(t_ss)); for (size_t i = 0; i < this->children[0]->children.size(); ++i) {
Boxed_Value bv = t_ss.call_function("clone", this->children[0]->children[i]->eval(t_ss));
vec.push_back(bv);
}
} }
return const_var(vec);
}
catch (const exception::dispatch_error &) {
throw exception::eval_error("Can not find appropriate 'clone' or copy constructor for vector elements");
} }
return const_var(vec);
} }
}; };
@@ -803,13 +902,14 @@ namespace chaiscript
try { try {
std::map<std::string, Boxed_Value> retval; std::map<std::string, Boxed_Value> retval;
for (size_t i = 0; i < this->children[0]->children.size(); ++i) { for (size_t i = 0; i < this->children[0]->children.size(); ++i) {
Boxed_Value bv = t_ss.call_function("clone", this->children[0]->children[i]->children[1]->eval(t_ss));
retval[boxed_cast<std::string>(this->children[0]->children[i]->children[0]->eval(t_ss))] retval[boxed_cast<std::string>(this->children[0]->children[i]->children[0]->eval(t_ss))]
= t_ss.call_function("clone", this->children[0]->children[i]->children[1]->eval(t_ss)); = bv;
} }
return const_var(retval); return const_var(retval);
} }
catch (const exception::dispatch_error &) { catch (const exception::dispatch_error &) {
throw exception::eval_error("Can not find appropriate 'Map()'"); throw exception::eval_error("Can not find appropriate 'clone' or copy constructor for map elements");
} }
} }
@@ -856,6 +956,7 @@ namespace chaiscript
virtual ~Prefix_AST_Node() {} virtual ~Prefix_AST_Node() {}
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss){ virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss){
chaiscript::eval::detail::Function_Push_Pop fpp(t_ss);
Boxed_Value bv(this->children[1]->eval(t_ss)); Boxed_Value bv(this->children[1]->eval(t_ss));
Operators::Opers oper = Operators::to_operator(children[0]->text, true); Operators::Opers oper = Operators::to_operator(children[0]->text, true);
@@ -864,6 +965,10 @@ namespace chaiscript
{ {
return Boxed_Number::do_oper(oper, bv); return Boxed_Number::do_oper(oper, bv);
} else { } else {
chaiscript::eval::detail::Stack_Push_Pop spp(t_ss);
std::vector<Boxed_Value> params;
params.push_back(bv);
fpp.save_params(params);
return t_ss.call_function(this->children[0]->text, bv); return t_ss.call_function(this->children[0]->text, bv);
} }
} catch (const exception::dispatch_error &) { } catch (const exception::dispatch_error &) {
@@ -950,6 +1055,7 @@ namespace chaiscript
end_point = this->children.size() - 1; end_point = this->children.size() - 1;
} }
for (unsigned int i = 1; i < end_point; ++i) { for (unsigned int i = 1; i < end_point; ++i) {
chaiscript::eval::detail::Scope_Push_Pop catchscope(t_ss);
AST_NodePtr catch_block = this->children[i]; AST_NodePtr catch_block = this->children[i];
if (catch_block->children.size() == 1) { if (catch_block->children.size() == 1) {
@@ -992,6 +1098,7 @@ namespace chaiscript
} }
catch (Boxed_Value &except) { catch (Boxed_Value &except) {
for (size_t i = 1; i < this->children.size(); ++i) { for (size_t i = 1; i < this->children.size(); ++i) {
chaiscript::eval::detail::Scope_Push_Pop catchscope(t_ss);
AST_NodePtr catch_block = this->children[i]; AST_NodePtr catch_block = this->children[i];
if (catch_block->children.size() == 1) { if (catch_block->children.size() == 1) {
@@ -1006,7 +1113,7 @@ namespace chaiscript
break; break;
} }
else if (catch_block->children.size() == 3) { else if (catch_block->children.size() == 3) {
//Variable capture, no guards //Variable capture, guards
t_ss.add_object(catch_block->children[0]->text, except); t_ss.add_object(catch_block->children[0]->text, except);
bool guard; bool guard;
@@ -1134,6 +1241,8 @@ namespace chaiscript
} }
catch (const exception::reserved_word_error &e) { catch (const exception::reserved_word_error &e) {
throw exception::eval_error("Reserved word used as method name '" + e.word() + "'"); throw exception::eval_error("Reserved word used as method name '" + e.word() + "'");
} catch (const exception::name_conflict_error &e) {
throw exception::eval_error("Method redefined '" + e.name() + "'");
} }
return Boxed_Value(); return Boxed_Value();
} }
@@ -1147,12 +1256,22 @@ namespace chaiscript
virtual ~Attr_Decl_AST_Node() {} virtual ~Attr_Decl_AST_Node() {}
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss){ virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss){
try { try {
t_ss.add(fun(boost::function<Boxed_Value (dispatch::Dynamic_Object &)>(boost::bind(&dispatch::detail::Dynamic_Object_Attribute::func, this->children[0]->text,
this->children[1]->text, _1))), this->children[1]->text); t_ss.add(Proxy_Function
(new dispatch::detail::Dynamic_Object_Function(
this->children[0]->text,
fun(boost::function<Boxed_Value (dispatch::Dynamic_Object &)>(boost::bind(&dispatch::Dynamic_Object::get_attr,
_1,
this->children[1]->text
)))
)
), this->children[1]->text);
} }
catch (const exception::reserved_word_error &) { catch (const exception::reserved_word_error &) {
throw exception::eval_error("Reserved word used as attribute '" + this->children[1]->text + "'"); throw exception::eval_error("Reserved word used as attribute '" + this->children[1]->text + "'");
} catch (const exception::name_conflict_error &e) {
throw exception::eval_error("Attribute redefined '" + e.name() + "'");
} }
return Boxed_Value(); return Boxed_Value();
} }

View File

@@ -1,6 +1,6 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com) // and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
@@ -66,6 +66,11 @@ namespace chaiscript
void setup_operators() void setup_operators()
{ {
m_operators.push_back(AST_Node_Type::Ternary_Cond);
std::vector<std::string> ternary_cond;
ternary_cond.push_back("?");
m_operator_matches.push_back(ternary_cond);
m_operators.push_back(AST_Node_Type::Logical_Or); m_operators.push_back(AST_Node_Type::Logical_Or);
std::vector<std::string> logical_or; std::vector<std::string> logical_or;
logical_or.push_back("||"); logical_or.push_back("||");
@@ -131,6 +136,7 @@ namespace chaiscript
m_alphabet[a][c]=false; m_alphabet[a][c]=false;
} }
} }
m_alphabet[detail::symbol_alphabet][static_cast<int>('?')]=true;
m_alphabet[detail::symbol_alphabet][static_cast<int>('+')]=true; m_alphabet[detail::symbol_alphabet][static_cast<int>('+')]=true;
m_alphabet[detail::symbol_alphabet][static_cast<int>('-')]=true; m_alphabet[detail::symbol_alphabet][static_cast<int>('-')]=true;
m_alphabet[detail::symbol_alphabet][static_cast<int>('*')]=true; m_alphabet[detail::symbol_alphabet][static_cast<int>('*')]=true;
@@ -322,7 +328,6 @@ namespace chaiscript
*/ */
bool Float_() { bool Float_() {
bool retval = false; bool retval = false;
std::string::const_iterator start = m_input_pos;
if (has_more_input() && char_in_alphabet(*m_input_pos,detail::float_alphabet) ) { if (has_more_input() && char_in_alphabet(*m_input_pos,detail::float_alphabet) ) {
while (has_more_input() && char_in_alphabet(*m_input_pos,detail::int_alphabet) ) { while (has_more_input() && char_in_alphabet(*m_input_pos,detail::int_alphabet) ) {
@@ -1416,6 +1421,90 @@ namespace chaiscript
return retval; return retval;
} }
/**
* Reads a case block from input
*/
bool Case() {
bool retval = false;
size_t prev_stack_top = m_match_stack.size();
if (Keyword("case")) {
retval = true;
if (!Char('(')) {
throw exception::eval_error("Incomplete 'case' expression", File_Position(m_line, m_col), *m_filename);
}
if (!(Operator() && Char(')'))) {
throw exception::eval_error("Incomplete 'case' expression", File_Position(m_line, m_col), *m_filename);
}
while (Eol()) {}
if (!Block()) {
throw exception::eval_error("Incomplete 'case' block", File_Position(m_line, m_col), *m_filename);
}
build_match(AST_NodePtr(new eval::Case_AST_Node()), prev_stack_top);
}
else if (Keyword("default")) {
while (Eol()) {}
if (!Block()) {
throw exception::eval_error("Incomplete 'default' block", File_Position(m_line, m_col), *m_filename);
}
build_match(AST_NodePtr(new eval::Default_AST_Node()), prev_stack_top);
}
return retval;
}
/**
* Reads a switch statement from input
*/
bool Switch() {
size_t prev_stack_top = m_match_stack.size();
if (Keyword("switch")) {
if (!Char('(')) {
throw exception::eval_error("Incomplete 'switch' expression", File_Position(m_line, m_col), *m_filename);
}
if (!(Operator() && Char(')'))) {
throw exception::eval_error("Incomplete 'switch' expression", File_Position(m_line, m_col), *m_filename);
}
while (Eol()) {}
if (Char('{')) {
while (Eol()) {}
while (Case()) {
while (Eol());
}
while (Eol());
if (!Char('}')) {
throw exception::eval_error("Incomplete block", File_Position(m_line, m_col), *m_filename);
}
}
else {
throw exception::eval_error("Incomplete block", File_Position(m_line, m_col), *m_filename);
}
build_match(AST_NodePtr(new eval::Switch_AST_Node()), prev_stack_top);
return true;
} else {
return false;
}
}
/** /**
* Reads a curly-brace C-style block from input * Reads a curly-brace C-style block from input
*/ */
@@ -1478,7 +1567,6 @@ namespace chaiscript
*/ */
bool Dot_Fun_Array() { bool Dot_Fun_Array() {
bool retval = false; bool retval = false;
std::string::const_iterator prev_pos = m_input_pos;
size_t prev_stack_top = m_match_stack.size(); size_t prev_stack_top = m_match_stack.size();
if (Lambda() || Num(true) || Quoted_String(true) || Single_Quoted_String(true) || if (Lambda() || Num(true) || Quoted_String(true) || Single_Quoted_String(true) ||
@@ -1720,6 +1808,7 @@ namespace chaiscript
retval = true; retval = true;
if (Operator_Helper(t_precedence)) { if (Operator_Helper(t_precedence)) {
do { do {
while (Eol()) {}
if (!Operator(t_precedence+1)) { if (!Operator(t_precedence+1)) {
throw exception::eval_error("Incomplete " throw exception::eval_error("Incomplete "
+ std::string(ast_node_type_to_string(m_operators[t_precedence])) + " expression", + std::string(ast_node_type_to_string(m_operators[t_precedence])) + " expression",
@@ -1730,6 +1819,23 @@ namespace chaiscript
case(AST_Node_Type::Comparison) : case(AST_Node_Type::Comparison) :
build_match(AST_NodePtr(new eval::Comparison_AST_Node()), prev_stack_top); build_match(AST_NodePtr(new eval::Comparison_AST_Node()), prev_stack_top);
break; break;
case(AST_Node_Type::Ternary_Cond) :
m_match_stack.erase(m_match_stack.begin() + m_match_stack.size() - 2,
m_match_stack.begin() + m_match_stack.size() - 1);
if (Symbol(":")) {
if (!Operator(t_precedence+1)) {
throw exception::eval_error("Incomplete "
+ std::string(ast_node_type_to_string(m_operators[t_precedence])) + " expression",
File_Position(m_line, m_col), *m_filename);
}
build_match(AST_NodePtr(new eval::Ternary_Cond_AST_Node()), prev_stack_top);
}
else {
throw exception::eval_error("Incomplete "
+ std::string(ast_node_type_to_string(m_operators[t_precedence])) + " expression",
File_Position(m_line, m_col), *m_filename);
}
break;
case(AST_Node_Type::Addition) : case(AST_Node_Type::Addition) :
oper = m_match_stack.at(m_match_stack.size()-2); oper = m_match_stack.at(m_match_stack.size()-2);
m_match_stack.erase(m_match_stack.begin() + m_match_stack.size() - 2, m_match_stack.erase(m_match_stack.begin() + m_match_stack.size() - 2,
@@ -1887,7 +1993,6 @@ namespace chaiscript
bool saw_eol = true; bool saw_eol = true;
while (has_more) { while (has_more) {
has_more = false;
int prev_line = m_line; int prev_line = m_line;
int prev_col = m_col; int prev_col = m_col;
if (Def()) { if (Def()) {
@@ -1930,6 +2035,14 @@ namespace chaiscript
retval = true; retval = true;
saw_eol = true; saw_eol = true;
} }
else if (Switch()) {
if (!saw_eol) {
throw exception::eval_error("Two function definitions missing line separator", File_Position(prev_line, prev_col), *m_filename);
}
has_more = true;
retval = true;
saw_eol = true;
}
else if (Return()) { else if (Return()) {
if (!saw_eol) { if (!saw_eol) {
throw exception::eval_error("Two expressions missing line separator", File_Position(prev_line, prev_col), *m_filename); throw exception::eval_error("Two expressions missing line separator", File_Position(prev_line, prev_col), *m_filename);

View File

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

View File

@@ -1,6 +1,6 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com) // and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
@@ -49,10 +49,20 @@
CHAISCRIPT_CLASS_METHODS((_module)(_class_name)(_class_name_translator)(_method_name_translator), _methods) \ CHAISCRIPT_CLASS_METHODS((_module)(_class_name)(_class_name_translator)(_method_name_translator), _methods) \
} }
#define CHAISCRIPT_CLASS_NO_CONSTRUCTOR_EX(_module, _class_name, _class_name_translator, _method_name_translator, _methods) \
{ \
_module->add(chaiscript::user_type<_class_name>(), _class_name_translator (BOOST_PP_STRINGIZE(_class_name))); \
CHAISCRIPT_CLASS_METHODS((_module)(_class_name)(_class_name_translator)(_method_name_translator), _methods) \
}
#define CHAISCRIPT_CLASS(_module, _class_name, _constructors, _methods) \ #define CHAISCRIPT_CLASS(_module, _class_name, _constructors, _methods) \
CHAISCRIPT_CLASS_EX(_module, _class_name, chaiscript::utility::class_name_translator, \ CHAISCRIPT_CLASS_EX(_module, _class_name, chaiscript::utility::class_name_translator, \
chaiscript::utility::method_name_translator, _constructors, _methods) chaiscript::utility::method_name_translator, _constructors, _methods)
#define CHAISCRIPT_CLASS_NO_CONSTRUCTOR(_module, _class_name, _methods) \
CHAISCRIPT_CLASS_NO_CONSTRUCTOR_EX(_module, _class_name, chaiscript::utility::class_name_translator, \
chaiscript::utility::method_name_translator, _methods)
namespace chaiscript namespace chaiscript
{ {
/// \brief Classes and functions which provide general utility to the end user. /// \brief Classes and functions which provide general utility to the end user.

View File

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

View File

@@ -1,6 +1,6 @@
ChaiScript ChaiScript
http://www.chaiscript.com http://www.chaiscript.com
(c) 2009-2011 Jason Turner and Jonathan Turner (c) 2009-2012 Jason Turner and Jonathan Turner
Release under the BSD license, see "license.txt" for details. Release under the BSD license, see "license.txt" for details.
[Introduction] [Introduction]

View File

@@ -1,3 +1,31 @@
Changes since 3.1.0
* svenstaro: Unused variables and CMake consistency fixes
* Added support for returning pointers from functions (#13)
* Compile with -pedantic (#9)
* Fix issues with multiple ChaiScript object types having the same attribute name (#15)
* Prevent variable redeclaration in same scope (#22)
* mgee: Boxed_Number improvements (#27)
* Support switch statements (#34)
* Fix uint16 comparions (#26)
* Add ability to add const_var globals in Module objects (#14)
* Add support for ternary operators ?:
* Add headers to CMakeLists so they show up in IDEs
* Add ability to get vector of defined objects and vector of defined functions
* Fix memory leak in cyclical references
* Clean up static analysis issues discovered
* Fix vector construction to be consistent with map construction
* Increased unit tests to 161
* Performance enhancements
Changes since 3.0.0
* Numeric operations performance increased approximately 10x
* Looping operations performance increased up to 2x
* Engine start up time decreased
* Several parsing bugs related to index operators fixed
* Added full support for all C algebraic types: double, long double, float, int, long, char,
uint8_t, uint16_t, uint32_t, uint64_t, int8_t, int16_t, int32_t, int64_t
* Enhanced support for capturing of exceptions thrown from ChaiScript in C++
Changes since 2.3.3 Changes since 2.3.3
* Code simplifications * Code simplifications

View File

@@ -165,7 +165,7 @@ int main(int /*argc*/, char * /*argv*/[]) {
//Dynamic objects test //Dynamic objects test
chai.add(chaiscript::Proxy_Function(new dispatch::detail::Dynamic_Object_Function("TestType", fun(&hello_world))), "hello_world"); chai.add(chaiscript::Proxy_Function(new dispatch::detail::Dynamic_Object_Function("TestType", fun(&hello_world))), "hello_world");
chai.add(chaiscript::Proxy_Function(new dispatch::detail::Dynamic_Object_Constructor("TestType", fun(&hello_constructor))), "TestType"); chai.add(chaiscript::Proxy_Function(new dispatch::detail::Dynamic_Object_Constructor("TestType", fun(&hello_constructor))), "TestType");
chai.add(fun(boost::function<Boxed_Value (dispatch::Dynamic_Object &)>(boost::bind(&dispatch::detail::Dynamic_Object_Attribute::func, "TestType", "attr", _1))), "attr"); // chai.add(fun(boost::function<Boxed_Value (dispatch::Dynamic_Object &)>(boost::bind(&dispatch::detail::Dynamic_Object_Attribute::func, "TestType", "attr", _1))), "attr");
chai.eval("var x = TestType()"); chai.eval("var x = TestType()");
// chai.eval("x.attr = \"hi\""); // chai.eval("x.attr = \"hi\"");

View File

@@ -215,6 +215,7 @@ int main(int argc, char *argv[])
case eInteractive : interactive(chai); break; case eInteractive : interactive(chai); break;
case eCommand : val = chai.eval(arg); break; case eCommand : val = chai.eval(arg); break;
case eFile : val = chai.eval_file(arg); break; case eFile : val = chai.eval_file(arg); break;
default : std::cout << "Unrecognized execution mode" << std::endl; return EXIT_FAILURE;
} }
} }
catch (const chaiscript::exception::eval_error &ee) { catch (const chaiscript::exception::eval_error &ee) {

View File

@@ -49,12 +49,12 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_reflect
m->add(chaiscript::fun(&has_parse_tree), "has_parse_tree"); m->add(chaiscript::fun(&has_parse_tree), "has_parse_tree");
m->add(chaiscript::fun(&get_parse_tree), "get_parse_tree"); m->add(chaiscript::fun(&get_parse_tree), "get_parse_tree");
m->add(chaiscript::base_class<std::exception, chaiscript::exception::eval_error>());
chaiscript::bootstrap::standard_library::vector_type<std::vector<boost::shared_ptr<chaiscript::AST_Node> > >("AST_NodeVector", m); chaiscript::bootstrap::standard_library::vector_type<std::vector<boost::shared_ptr<chaiscript::AST_Node> > >("AST_NodeVector", m);
CHAISCRIPT_CLASS( m, CHAISCRIPT_CLASS_NO_CONSTRUCTOR( m,
chaiscript::exception::eval_error, chaiscript::exception::eval_error,
,
((reason)) ((reason))
((call_stack)) ((call_stack))
); );
@@ -67,9 +67,8 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_reflect
((column)) ((column))
); );
CHAISCRIPT_CLASS( m, CHAISCRIPT_CLASS_NO_CONSTRUCTOR( m,
chaiscript::AST_Node, chaiscript::AST_Node,
,
((text)) ((text))
((identifier)) ((identifier))
((filename)) ((filename))

View File

@@ -7,11 +7,22 @@ class TestBaseType
public: public:
TestBaseType() {} TestBaseType() {}
TestBaseType(int) {} TestBaseType(int) {}
TestBaseType(int *) {}
virtual ~TestBaseType() {} virtual ~TestBaseType() {}
virtual int func() { return 0; } virtual int func() { return 0; }
}; };
enum TestEnum
{
TestValue1 = 1
};
int to_int(TestEnum t)
{
return t;
}
class TestDerivedType : public TestBaseType class TestDerivedType : public TestBaseType
{ {
public: public:
@@ -24,6 +35,11 @@ std::string hello_world()
return "Hello World"; return "Hello World";
} }
int *get_new_int()
{
return new int(1);
}
// MSVC doesn't like that we are using C++ return types from our C declared module // MSVC doesn't like that we are using C++ return types from our C declared module
// but this is the best way to do it for cross platform compatibility // but this is the best way to do it for cross platform compatibility
#ifdef BOOST_MSVC #ifdef BOOST_MSVC
@@ -44,6 +60,7 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_test_mo
m->add(chaiscript::constructor<TestBaseType ()>(), "TestBaseType"); m->add(chaiscript::constructor<TestBaseType ()>(), "TestBaseType");
// m->add(chaiscript::constructor<TestBaseType (int)>(), "TestBaseType"); // m->add(chaiscript::constructor<TestBaseType (int)>(), "TestBaseType");
m->add(chaiscript::constructor<TestBaseType (const TestBaseType &)>(), "TestBaseType"); m->add(chaiscript::constructor<TestBaseType (const TestBaseType &)>(), "TestBaseType");
m->add(chaiscript::constructor<TestBaseType (int *)>(), "TestBaseType");
m->add(chaiscript::constructor<TestDerivedType ()>(), "TestDerivedType"); m->add(chaiscript::constructor<TestDerivedType ()>(), "TestDerivedType");
m->add(chaiscript::constructor<TestDerivedType (const TestDerivedType &)>(), "TestDerivedType"); m->add(chaiscript::constructor<TestDerivedType (const TestDerivedType &)>(), "TestDerivedType");
@@ -52,6 +69,15 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_test_mo
m->add(chaiscript::fun(&TestBaseType::func), "func"); m->add(chaiscript::fun(&TestBaseType::func), "func");
m->add(chaiscript::fun(&get_new_int), "get_new_int");
m->add_global_const(chaiscript::const_var(TestValue1), "TestValue1");
m->add(chaiscript::user_type<TestEnum>(), "TestEnum");
m->add(chaiscript::fun(&to_int), "to_int");
return m; return m;
} }

View File

@@ -301,8 +301,8 @@ int main()
passed &= built_in_type_test<int>(5, true); passed &= built_in_type_test<int>(5, true);
passed &= built_in_type_test<double>(1.1, true); passed &= built_in_type_test<double>(1.1, true);
passed &= built_in_type_test<char>('a', true); passed &= built_in_type_test<char>('a', true);
passed &= built_in_type_test<uint8_t>('a', true); passed &= built_in_type_test<boost::uint8_t>('a', true);
passed &= built_in_type_test<int64_t>('a', true); passed &= built_in_type_test<boost::int64_t>('a', true);
passed &= built_in_type_test<bool>(false, false); passed &= built_in_type_test<bool>(false, false);
passed &= built_in_type_test<std::string>("Hello World", false); passed &= built_in_type_test<std::string>("Hello World", false);

View File

@@ -60,7 +60,7 @@ int test_5()
try { try {
chai.eval("throw(runtime_error(\"error\"))", chaiscript::exception_specification<int, double, float, const std::string &, const std::exception &>()); chai.eval("throw(runtime_error(\"error\"))", chaiscript::exception_specification<int, double, float, const std::string &, const std::exception &>());
} catch (const double e) { } catch (const double) {
std::cout << "test_5 failed with double" << std::endl; std::cout << "test_5 failed with double" << std::endl;
return EXIT_FAILURE; return EXIT_FAILURE;
} catch (int) { } catch (int) {
@@ -72,7 +72,7 @@ int test_5()
} catch (const std::string &) { } catch (const std::string &) {
std::cout << "test_5 failed with string" << std::endl; std::cout << "test_5 failed with string" << std::endl;
return EXIT_FAILURE; return EXIT_FAILURE;
} catch (const std::exception &e) { } catch (const std::exception &) {
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
@@ -95,10 +95,10 @@ int test_unhandled()
} catch (float) { } catch (float) {
std::cout << "test_unhandled failed with float" << std::endl; std::cout << "test_unhandled failed with float" << std::endl;
return EXIT_FAILURE; return EXIT_FAILURE;
} catch (const std::exception &e) { } catch (const std::exception &) {
std::cout << "test_unhandled failed with std::exception" << std::endl; std::cout << "test_unhandled failed with std::exception" << std::endl;
return EXIT_FAILURE; return EXIT_FAILURE;
} catch (const chaiscript::Boxed_Value &bv) { } catch (const chaiscript::Boxed_Value &) {
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }

View File

@@ -17,7 +17,7 @@ int main()
chaiscript::ChaiScript chai; chaiscript::ChaiScript chai;
chai.eval("def test_fun(x) { return 3; }"); chai.eval("def test_fun(x) { return 3; }");
chai.eval("def test_fun(x) : x == \"hi\" { return 4; }"); chai.eval("def test_fun(x) : x == \"hi\" { return 4; }");
chai.eval("def test_fun(x) { return 5; }"); // chai.eval("def test_fun(x) { return 5; }");
chai.add(chaiscript::fun(&test_one), "test_fun"); chai.add(chaiscript::fun(&test_one), "test_fun");
chai.add(chaiscript::fun(&test_two), "test_fun"); chai.add(chaiscript::fun(&test_two), "test_fun");

View File

@@ -0,0 +1,2 @@
assert_throws("Function already defined", fun() { def foo(x) { x + 1 }; def foo(x) { x + 1 } } );

View File

@@ -0,0 +1,7 @@
load_module("test_module")
assert_equal(to_int(TestValue1), 1)
assert_equal(TestValue1.type_name(), "TestEnum")

4
unittests/hashbang.chai Normal file
View File

@@ -0,0 +1,4 @@
#!/usr/bin/env chai
//We just have to reach this point for success
assert_equal(true, true);

View File

@@ -1,3 +1,14 @@
var x = ["bob":1, "fred":2] var x = ["bob":1, "fred":2]
assert_equal(2, x.size()); assert_equal(2, x.size());
// Make sure vector elements are copied into place for consistency with
// map inplace construction
var i = 1;
var y = ["a":i];
assert_equal(1, y["a"]);
i = 3;
assert_equal(3, i);
assert_equal(1, y["a"]);

View File

@@ -0,0 +1,4 @@
var x = 3 +
4
assert_equal(x, 7);

View File

@@ -0,0 +1,9 @@
attr bob::z
def bob::bob() { this.z = 10 }
attr bob2::z
def bob2::bob2() { this.z = 12 }
var b = bob();
var b2 = bob2();

View File

@@ -38,19 +38,19 @@ int main()
chaiscript::ChaiScript chai; chaiscript::ChaiScript chai;
chai.add(m); chai.add(m);
chai.add(chaiscript::fun(&Test::count), "count"); // chai.add(chaiscript::fun(&Test::count), "count");
int count = chai.eval<int>("count()"); int count = chai.eval<int>("count()");
int count2 = chai.eval<int>("var i = 0; { var t = Test(); } return i;"); int count2 = chai.eval<int>("var i = 0; { var t = Test(); } return i;");
int count3 = chai.eval<int>("var i = 0; { var t = Test(); i = count(); } return i;"); int count3 = chai.eval<int>("i = 0; { var t = Test(); i = count(); } return i;");
int count4 = chai.eval<int>("var i = 0; { var t = Test(); { var t2 = Test(); i = count(); } } return i;"); int count4 = chai.eval<int>("i = 0; { var t = Test(); { var t2 = Test(); i = count(); } } return i;");
int count5 = chai.eval<int>("var i = 0; { var t = Test(); { var t2 = Test(); } i = count(); } return i;"); int count5 = chai.eval<int>("i = 0; { var t = Test(); { var t2 = Test(); } i = count(); } return i;");
int count6 = chai.eval<int>("var i = 0; { var t = Test(); { var t2 = Test(); } } i = count(); return i;"); int count6 = chai.eval<int>("i = 0; { var t = Test(); { var t2 = Test(); } } i = count(); return i;");
if (count == 0 if (count == 0
&& count2 == 0 && count2 == 0

View File

@@ -0,0 +1,8 @@
load_module("reflection")
try {
eval("def `+`(x, y) \n { \n print(i); \n } \n \n var i = 10; \n \"1\" + 1;\n")
assert_false(true); // we should never get here
} catch (e) {
assert_equal("Error: \"Can not find object: i\" ", e.what());
}

View File

@@ -0,0 +1,19 @@
def f(x) { x+= 2; }
var i = 1;
assert_equal(i, 1);
f(i);
assert_equal(i, 3);
def g(x) { x+= " World"; }
var s = "Hello";
assert_equal(s, "Hello");
g(s);
assert_equal(s, "Hello World");

View File

@@ -0,0 +1,8 @@
load_module("test_module")
var i = 1;
var t0 = TestBaseType(i);
var t1 = TestBaseType(get_new_int())

View File

@@ -0,0 +1,29 @@
#include <chaiscript/utility/utility.hpp>
class Test {
public:
Test() : value_(5) {}
short get_value() { return value_; }
short value_;
};
int main()
{
chaiscript::ChaiScript chai;
chai.add(chaiscript::user_type<Test>(), "Test");
chai.add(chaiscript::constructor<Test()>(), "Test");
chai.add(chaiscript::fun(&Test::get_value), "get_value");
chai.eval("var t := Test();");
if (chai.eval<bool>("t.get_value() == 5"))
{
return EXIT_SUCCESS;
} else {
return EXIT_FAILURE;
}
}

View File

@@ -0,0 +1,22 @@
var total = 0;
switch(2) {
case (1) {
total += 1;
break;
}
case (2) {
total += 2;
break;
}
case (3) {
total += 4;
break;
}
case (4) {
total += 8;
break;
}
}
assert_equal(total, 2)

View File

@@ -0,0 +1,18 @@
var total = 0;
switch(2) {
case (1) {
total += 1;
}
case (3) {
total += 4;
}
case (4) {
total += 8;
}
default {
total += 16;
}
}
assert_equal(total, 16)

View File

@@ -0,0 +1,4 @@
switch(true) { }
// We just have to get here without error for success
assert_equal(true, true);

View File

@@ -0,0 +1,18 @@
var total = 0;
switch(2) {
case (1) {
total += 1;
}
case (2) {
total += 2;
}
case (3) {
total += 4;
}
case (4) {
total += 8;
}
}
assert_equal(total, 14);

View File

@@ -0,0 +1,19 @@
var total = 0;
switch(2) {
case (1) {
total += 1;
}
case (2) {
total += 2;
}
case (3) {
total += 4;
break;
}
case (4) {
total += 8;
}
}
assert_equal(total, 6)

View File

@@ -0,0 +1,18 @@
var funcs = get_functions();
assert_true(funcs.size() > 0);
assert_true(funcs["to_string"].get_type_info().bare_equal(Function_type));
var i = 1;
var objs = get_objects();
assert_true(objs.size() > 0);
assert_true(objs["i"].get_type_info().bare_equal(int_type));
assert_true(objs.count("j") == 0);

View File

@@ -0,0 +1,3 @@
for_each(range([1..10]), fun(x) {print(x);} );
assert_true(true);

View File

@@ -0,0 +1,2 @@
var x = 4;
assert_equal(x < 3 ? 4 < 1 : 5 > 3, true);

View File

@@ -5,7 +5,7 @@ def assert_equal(x, y)
// Passes // Passes
} else { } else {
// Fails // Fails
print("assert_equal failure: got " + to_string(y) + " expected " + to_string(x)); print("assert_equal failure: got '" + to_string(y) + "' expected '" + to_string(x) + "'");
exit(-1); exit(-1);
} }
} }
@@ -23,7 +23,7 @@ def assert_true(f)
{ {
if (!f) if (!f)
{ {
print("assert_false failure"); print("assert_true failure");
exit(-1); exit(-1);
} }
} }

View File

@@ -30,8 +30,8 @@ int main()
chaiscript::ChaiScript chai; chaiscript::ChaiScript chai;
chai.add(m); chai.add(m);
if (chai.eval<std::string>("var t = Test(); t.function2(); ") == "Function2" if (chai.eval<std::string>("var t = Test(); t.function2(); ") == "Function2"
&& chai.eval<std::string>("var t = Test(); t.functionOverload(1); ") == "int" && chai.eval<std::string>("var t2 = Test(); t2.functionOverload(1); ") == "int"
&& chai.eval<std::string>("var t = Test(); t.functionOverload(1.1); ") == "double") && chai.eval<std::string>("var t3 = Test(); t3.functionOverload(1.1); ") == "double")
{ {
chai.eval("t = Test();"); chai.eval("t = Test();");
return EXIT_SUCCESS; return EXIT_SUCCESS;

View File

@@ -0,0 +1,2 @@
assert_throws("Variable already defined", fun() { var y = 10; var y = 20; })

View File

@@ -1,2 +1,14 @@
var x = [1, 2, 3] var x = [1, 2, 3]
assert_equal(3, x.size()) assert_equal(3, x.size())
// Make sure vector elements are copied into place for consistency with
// map inplace construction
var i = 1;
var y = [i];
assert_equal(1, y[0]);
i = 3;
assert_equal(3, i);
assert_equal(1, y[0]);