mirror of
https://github.com/ChaiScript/ChaiScript.git
synced 2026-04-30 19:09:26 +08:00
* Fix #571: Add per-instance IO redirection via set_print_handler/set_println_handler The print_string and println_string functions were previously registered as static functions writing directly to stdout, making it impossible to redirect ChaiScript output to custom destinations (e.g., GUI windows, loggers, or buffers). This moves their registration from Bootstrap::bootstrap() to ChaiScript_Basic::build_eval_system() as lambdas that dispatch through configurable std::function handlers, allowing each ChaiScript instance to independently redirect its output via set_print_handler() and set_println_handler(). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Address review: add IO redirection section to cheatsheet Documents set_print_handler() and set_println_handler() with usage examples for GUI embedding and output capture. Requested by @lefticus in PR #657 review. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Address review: define println in terms of print, expose set_print_handler to ChaiScript Remove separate println_handler — println_string now dispatches through the single print handler with a newline appended. Only set_print_handler is needed to redirect all output. The set_print_handler function is also registered in the ChaiScript engine, so scripts can capture and redirect their own output. Requested by @lefticus in PR #657 review. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Address review: populate null print handler when No_IO is set When No_IO is active, the default m_print_handler is now a no-op instead of writing to stdout. The stdout handler is only installed when No_IO is not set. Users can still override the handler via set_print_handler() even with No_IO enabled. Requested by @lefticus in PR #657 review. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: leftibot <leftibot@users.noreply.github.com> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
840 lines
25 KiB
C++
840 lines
25 KiB
C++
// This file is distributed under the BSD License.
|
|
// See "license.txt" for details.
|
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
|
// Copyright 2009-2018, Jason Turner (jason@emptycrate.com)
|
|
// http://www.chaiscript.com
|
|
|
|
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
|
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
|
|
|
#ifndef CHAISCRIPT_HPP_
|
|
#define CHAISCRIPT_HPP_
|
|
|
|
/// @mainpage
|
|
/// [ChaiScript](http://www.chaiscript.com") is a scripting language designed specifically for integration with C++. It provides
|
|
/// seamless integration with C++ on all levels, including shared_ptr objects, functors and exceptions.
|
|
///
|
|
/// The parts of the ChaiScript API that the average user will be concerned with are contained in the
|
|
/// chaiscript namespace and the chaiscript::ChaiScript class.
|
|
///
|
|
/// The end user parts of the API are extremely simple both in size and ease of use.
|
|
///
|
|
/// Currently, all source control and project management aspects of ChaiScript occur on
|
|
/// [github](http://www.github.com/ChaiScript/ChaiScript").
|
|
///
|
|
/// ------------------------------------------------------------
|
|
///
|
|
/// @sa chaiscript
|
|
/// @sa chaiscript::ChaiScript
|
|
/// @sa ChaiScript_Language for Built in Functions
|
|
/// @sa @ref LangGettingStarted
|
|
/// @sa @ref LangKeywordRef
|
|
/// @sa @ref LangInPlaceRef
|
|
/// @sa @ref LangObjectSystemRef
|
|
/// @sa http://www.chaiscript.com
|
|
/// @sa http://www.github.com/ChaiScript/ChaiScript
|
|
///
|
|
/// -----------------------------------------------------------
|
|
///
|
|
/// @section gettingstarted API Getting Started
|
|
///
|
|
/// - @ref basics
|
|
/// - @ref compiling
|
|
/// - @ref eval
|
|
/// - @ref adding_items
|
|
/// - @ref operatoroverloading
|
|
/// - @ref add_class
|
|
/// - @ref pointer_conversions
|
|
/// - @ref baseclasses
|
|
/// - @ref functionobjects
|
|
/// - @ref threading
|
|
/// - @ref exceptions
|
|
///
|
|
///
|
|
/// @subsection basics Basics
|
|
///
|
|
/// Basic simple example:
|
|
///
|
|
/// ~~~~~~~{.cpp}
|
|
/// //main.cpp
|
|
/// #include <chaiscript/chaiscript.hpp>
|
|
///
|
|
/// double function(int i, double j)
|
|
/// {
|
|
/// return i * j;
|
|
/// }
|
|
///
|
|
/// int main()
|
|
/// {
|
|
/// chaiscript::ChaiScript chai;
|
|
/// chai.add(chaiscript::fun(&function), "function");
|
|
///
|
|
/// double d = chai.eval<double>("function(3, 4.75);");
|
|
/// }
|
|
/// ~~~~~~~
|
|
///
|
|
/// ------------------------------------------------------
|
|
///
|
|
/// @subsection compiling Compiling ChaiScript Applications
|
|
///
|
|
/// ChaiScript is a header only library with only one dependency: The
|
|
/// operating system provided dynamic library loader, which has to be specified on some platforms.
|
|
///
|
|
/// @subsubsection compilinggcc Compiling with GCC
|
|
///
|
|
/// To compile the above application on a Unix like operating system (MacOS, Linux) with GCC you need to link
|
|
/// the dynamic loader. For example:
|
|
///
|
|
/// ~~~~~~~~
|
|
/// gcc main.cpp -I/path/to/chaiscript/headers -ldl
|
|
/// ~~~~~~~~
|
|
///
|
|
/// Alternatively, you may compile without threading support.
|
|
///
|
|
/// ~~~~~~~~
|
|
/// gcc main.cpp -I/path/to/chaiscript/headers -ldl -DCHAISCRIPT_NO_THREADS
|
|
/// ~~~~~~~~
|
|
///
|
|
/// ------------------------------------------
|
|
///
|
|
/// @subsection eval Evaluating Scripts
|
|
///
|
|
/// Scripts can be evaluated with the () operator, eval method or eval_file method.
|
|
///
|
|
/// @subsubsection parenoperator () Operator
|
|
///
|
|
/// operator() can be used as a handy shortcut for evaluating ChaiScript snippets.
|
|
///
|
|
/// ~~~~~~~~{.cpp}
|
|
/// chaiscript::ChaiScript chai;
|
|
/// chai("print(@"hello world@")");
|
|
/// ~~~~~~~~
|
|
///
|
|
/// @sa chaiscript::ChaiScript::operator()(const std::string &)
|
|
///
|
|
/// @subsubsection evalmethod Method 'eval'
|
|
///
|
|
/// The eval method is somewhat more verbose and can be used to get type safely return values
|
|
/// from the script.
|
|
///
|
|
/// ~~~~~~~~{.cpp}
|
|
/// chaiscript::ChaiScript chai;
|
|
/// chai.eval("callsomefunc()");
|
|
/// int result = chai.eval<int>("1 + 3");
|
|
/// // result now equals 4
|
|
/// ~~~~~~~~
|
|
///
|
|
/// @sa chaiscript::ChaiScript::eval
|
|
///
|
|
/// @subsubsection evalfilemethod Method 'eval_file'
|
|
///
|
|
/// The 'eval_file' method loads a file from disk and executes the script in it
|
|
///
|
|
/// ~~~~~~~~{.cpp}
|
|
/// chaiscript::ChaiScript chai;
|
|
/// chai.eval_file("myfile.chai");
|
|
/// std::string result = chai.eval_file<std::string>("myfile.chai") // extract the last value returned from the file
|
|
/// ~~~~~~~~
|
|
///
|
|
/// @sa chaiscript::ChaiScript::eval_file
|
|
///
|
|
/// --------------------------------------------------
|
|
///
|
|
/// @subsection adding_items Adding Items to ChaiScript
|
|
///
|
|
/// ChaiScript supports 4 basic things that can be added: objects, functions, type infos and Modules
|
|
///
|
|
/// @subsubsection adding_objects Adding Objects
|
|
///
|
|
/// Named objects can be created with the chaiscript::var function. Note: adding a object
|
|
/// adds it to the current thread scope, not to a global scope. If you have multiple
|
|
/// threads that need to access the same variables you will need to add them
|
|
/// separately for each thread, from the thread itself.
|
|
///
|
|
/// ~~~~~~~~~{.cpp}
|
|
/// using namespace chaiscript;
|
|
/// ChaiScript chai;
|
|
/// int i = 5;
|
|
/// chai.add(var(i), "i");
|
|
/// chai("print(i)");
|
|
/// ~~~~~~~~~
|
|
///
|
|
/// Immutable objects can be created with the chaiscript::const_var function.
|
|
///
|
|
/// ~~~~~~~~~{.cpp}
|
|
/// chai.add(const_var(i), "i");
|
|
/// chai("i = 5"); // exception throw, cannot assign const var
|
|
/// ~~~~~~~~~
|
|
///
|
|
/// Named variables can only be accessed from the context they are created in.
|
|
/// If you want a global variable, it must be const, and created with the
|
|
/// chaiscript::ChaiScript::add_global_const function.
|
|
///
|
|
/// ~~~~~~~~~{.cpp}
|
|
/// chai.add_global_const(const_var(i), "i");
|
|
/// chai("def somefun() { print(i); }; somefun();");
|
|
/// ~~~~~~~~~
|
|
///
|
|
/// @subsubsection adding_functions Adding Functions
|
|
///
|
|
/// Functions, methods and members are all added using the same function: chaiscript::fun.
|
|
///
|
|
/// ~~~~~~~~~{.cpp}
|
|
/// using namespace chaiscript;
|
|
///
|
|
/// class MyClass {
|
|
/// public:
|
|
/// int memberdata;
|
|
/// void method();
|
|
/// void method2(int);
|
|
/// static void staticmethod();
|
|
/// void overloadedmethod();
|
|
/// void overloadedmethod(const std::string &);
|
|
/// };
|
|
///
|
|
/// ChaiScript chai;
|
|
/// chai.add(fun(&MyClass::memberdata), "memberdata");
|
|
/// chai.add(fun(&MyClass::method), "method");
|
|
/// chai.add(fun(&MyClass::staticmethod), "staticmethod");
|
|
/// ~~~~~~~~~
|
|
///
|
|
/// Overloaded methods will need some help, to hint the compiler as to which overload you want:
|
|
///
|
|
/// ~~~~~~~~~{.cpp}
|
|
/// chai.add(fun<void (MyClass::*)()>(&MyClass::overloadedmethod), "overloadedmethod");
|
|
/// chai.add(fun<void (MyClass::*)(const std::string &)>(&MyClass::overloadedmethod), "overloadedmethod");
|
|
/// ~~~~~~~~~
|
|
///
|
|
/// There are also shortcuts built into chaiscript::fun for binding up to the first two parameters of the function.
|
|
///
|
|
/// ~~~~~~~~~{.cpp}
|
|
/// MyClass obj;
|
|
/// chai.add(fun(&MyClass::method, &obj), "method");
|
|
/// chai("method()"); // equiv to obj.method()
|
|
/// chai.add(fun(&MyClass::method2, &obj, 3), "method2");
|
|
/// chai("method2()"); // equiv to obj.method2(3)
|
|
/// ~~~~~~~~~
|
|
///
|
|
/// @subsubsection addingtypeinfo Adding Type Info
|
|
///
|
|
/// ChaiScript will automatically support any type implicitly provided to it in the form
|
|
/// of objects and function parameters / return types. However, it can be nice to let ChaiScript
|
|
/// know more details about the types you are giving it. For instance, the "clone" functionality
|
|
/// cannot work unless there is a copy constructor registered and the name of the type is known
|
|
/// (so that ChaiScript can look up the copy constructor).
|
|
///
|
|
/// Continuing with the example "MyClass" from above:
|
|
///
|
|
/// ~~~~~~~~{.cpp}
|
|
/// chai.add(user_type<MyClass>(), "MyClass");
|
|
/// ~~~~~~~~
|
|
///
|
|
/// @subsubsection adding_modules Adding Modules
|
|
///
|
|
/// Modules are holders for collections of ChaiScript registrations.
|
|
///
|
|
/// ~~~~~~~~{.cpp}
|
|
/// ModulePtr module = get_sum_module();
|
|
/// chai.add(module);
|
|
/// ~~~~~~~~
|
|
///
|
|
/// @sa chaiscript::Module
|
|
///
|
|
/// -----------------------------------------------------------------------
|
|
///
|
|
/// @subsection operatoroverloading Operator Overloading
|
|
///
|
|
/// Operators are just like any other function in ChaiScript, to overload an operator, simply register it.
|
|
///
|
|
/// ~~~~~~~~{.cpp}
|
|
/// class MyClass {
|
|
/// MyClass operator+(const MyClass &) const;
|
|
/// };
|
|
///
|
|
/// chai.add(fun(&MyClass::operator+), "+");
|
|
///
|
|
/// std::string append_string_int(const std::string &t_lhs, int t_rhs)
|
|
/// {
|
|
/// std::stringstream ss;
|
|
/// ss << t_lhs << t_rhs;
|
|
/// return ss.str();
|
|
/// }
|
|
///
|
|
/// chai.add(fun(append_string_int), "+");
|
|
/// ~~~~~~~~
|
|
///
|
|
/// @sa @ref adding_functions
|
|
///
|
|
/// -----------------------------------------------------------------------
|
|
///
|
|
/// @subsection add_class Class Helper Utility
|
|
///
|
|
/// Much of the work of adding new classes to ChaiScript can be reduced with the help
|
|
/// of the add_class helper utility.
|
|
///
|
|
/// ~~~~~~~~{.cpp}
|
|
/// class Test
|
|
/// {
|
|
/// public:
|
|
/// void function() {}
|
|
/// std::string function2() { return "Function2"; }
|
|
/// void function3() {}
|
|
/// std::string functionOverload(double) { return "double"; }
|
|
/// std::string functionOverload(int) { return "int"; }
|
|
/// };
|
|
///
|
|
/// int main()
|
|
/// {
|
|
/// chaiscript::ModulePtr m = chaiscript::ModulePtr(new chaiscript::Module());
|
|
///
|
|
/// chaiscript::utility::add_class<chaiscript::Test>(*m,
|
|
/// "Test",
|
|
/// { constructor<Test()>(),
|
|
/// constructor<Test(const Test &)>() },
|
|
/// { {fun(&Test::function), "function"},
|
|
/// {fun(&Test::function2), "function2"},
|
|
/// {fun(&Test::function2), "function3"}
|
|
/// {fun(static_cast<std::string Test::*(double)>(&Test::functionOverload)), "functionOverload"}
|
|
/// {fun(static_cast<std::string Test::*(int)>(&Test::functionOverload)), "functionOverload"} }
|
|
/// );
|
|
///
|
|
///
|
|
/// chaiscript::ChaiScript chai;
|
|
/// chai.add(m);
|
|
/// }
|
|
/// ~~~~~~~~
|
|
///
|
|
/// @sa @ref adding_modules
|
|
///
|
|
/// -----------------------------------------------------------------------
|
|
///
|
|
/// @subsection pointer_conversions Pointer / Object Conversions
|
|
///
|
|
/// As much as possible, ChaiScript attempts to convert between &, *, const &, const *, std::shared_ptr<T>,
|
|
/// std::shared_ptr<const T>, std::reference_wrapper<T>, std::reference_wrapper<const T> and value types automatically.
|
|
///
|
|
/// If a chaiscript::var object was created in C++ from a pointer, it cannot be converted to a shared_ptr (this would add invalid reference
|
|
/// counting). Const may be added, but never removed.
|
|
///
|
|
/// The take away is that you can pretty much expect function calls to Just Work when you need them to.
|
|
///
|
|
/// ~~~~~~~~{.cpp}
|
|
/// void fun1(const int *);
|
|
/// void fun2(int *);
|
|
/// void fun3(int);
|
|
/// void fun4(int &);
|
|
/// void fun5(const int &);
|
|
/// void fun5(std::shared_ptr<int>);
|
|
/// void fun6(std::shared_ptr<const int>);
|
|
/// void fun7(const std::shared_ptr<int> &);
|
|
/// void fun8(const std::shared_ptr<const int> &);
|
|
/// void fun9(std::reference_wrapper<int>);
|
|
/// void fun10(std::reference_wrapper<const int>);
|
|
///
|
|
/// int main()
|
|
/// {
|
|
/// using namespace chaiscript
|
|
/// chaiscript::ChaiScript chai;
|
|
/// chai.add(fun(fun1), "fun1");
|
|
/// chai.add(fun(fun2), "fun2");
|
|
/// chai.add(fun(fun3), "fun3");
|
|
/// chai.add(fun(fun4), "fun4");
|
|
/// chai.add(fun(fun5), "fun5");
|
|
/// chai.add(fun(fun6), "fun6");
|
|
/// chai.add(fun(fun7), "fun7");
|
|
/// chai.add(fun(fun8), "fun8");
|
|
/// chai.add(fun(fun9), "fun9");
|
|
/// chai.add(fun(fun10), "fun10");
|
|
///
|
|
/// chai("var i = 10;");
|
|
/// chai("fun1(i)");
|
|
/// chai("fun2(i)");
|
|
/// chai("fun3(i)");
|
|
/// chai("fun4(i)");
|
|
/// chai("fun5(i)");
|
|
/// chai("fun6(i)");
|
|
/// chai("fun7(i)");
|
|
/// chai("fun8(i)");
|
|
/// chai("fun9(i)");
|
|
/// chai("fun10(i)");
|
|
/// }
|
|
/// ~~~~~~~~
|
|
///
|
|
/// See the unit test unittests/boxed_cast_test.cpp for a complete breakdown of the automatic casts that
|
|
/// available and tested.
|
|
///
|
|
/// -----------------------------------------------------------------------
|
|
///
|
|
/// @subsection baseclasses Base Classes
|
|
///
|
|
/// ChaiScript supports handling of passing a derived class object to a function expecting a base class object.
|
|
/// For the process to work, the base/derived relationship must be registered with the engine.
|
|
///
|
|
/// ~~~~~~~~{.cpp}
|
|
/// class Base {};
|
|
/// class Derived : public Base {};
|
|
/// void myfunction(Base *b);
|
|
///
|
|
/// int main()
|
|
/// {
|
|
/// chaiscript::ChaiScript chai;
|
|
/// chai.add(chaiscript::base_class<Base, Derived>());
|
|
/// Derived d;
|
|
/// chai.add(chaiscript::var(&d), "d");
|
|
/// chai.add(chaiscript::fun(&myfunction), "myfunction");
|
|
/// chai("myfunction(d)");
|
|
/// }
|
|
/// ~~~~~~~~
|
|
///
|
|
/// -----------------------------------------------------------------------
|
|
///
|
|
///
|
|
/// @subsection functionobjects Function Objects
|
|
///
|
|
/// Functions are first class objects in ChaiScript and ChaiScript supports automatic conversion
|
|
/// between ChaiScript functions and std::function objects.
|
|
///
|
|
/// ~~~~~~~~{.cpp}
|
|
/// void callafunc(const std::function<void (const std::string &)> &t_func)
|
|
/// {
|
|
/// t_func("bob");
|
|
/// }
|
|
///
|
|
/// int main()
|
|
/// {
|
|
/// chaiscript::ChaiScript chai;
|
|
/// chai.add(chaiscript::fun(&callafunc), "callafunc");
|
|
/// chai("callafunc(fun(x) { print(x); })"); // pass a lambda function to the registered function
|
|
/// // which expects a typed std::function
|
|
///
|
|
/// std::function<void ()> f = chai.eval<std::function<void ()> >("dump_system");
|
|
/// f(); // call the ChaiScript function dump_system, from C++
|
|
/// }
|
|
/// ~~~~~~~~
|
|
///
|
|
/// -----------------------------------------------------------------------
|
|
///
|
|
///
|
|
/// @subsection threading Threading
|
|
///
|
|
/// Thread safety is automatically handled within the ChaiScript system. Objects can be added
|
|
/// and scripts executed from multiple threads. For each thread that executes scripts, a new
|
|
/// context is created and managed by the engine.
|
|
///
|
|
/// Thread safety can be disabled by defining CHAISCRIPT_NO_THREADS when using the library.
|
|
///
|
|
/// Disabling thread safety increases performance in many cases.
|
|
///
|
|
/// -----------------------------------------------------------------------
|
|
///
|
|
///
|
|
/// @subsection exceptions Exception Handling
|
|
///
|
|
/// @subsubsection exceptionsbasics Exception Handling Basics
|
|
///
|
|
/// Exceptions can be thrown in ChaiScript and caught in C++ or thrown in C++ and caught in
|
|
/// ChaiScript.
|
|
///
|
|
/// ~~~~~~~~{.cpp}
|
|
/// void throwexception()
|
|
/// {
|
|
/// throw std::runtime_error("err");
|
|
/// }
|
|
///
|
|
/// int main()
|
|
/// {
|
|
/// // Throw in C++, catch in ChaiScript
|
|
/// chaiscript::ChaiScript chai;
|
|
/// chai.add(chaiscript::fun(&throwexception), "throwexception");
|
|
/// chai("try { throwexception(); } catch (e) { print(e.what()); }"); // prints "err"
|
|
///
|
|
/// // Throw in ChaiScript, catch in C++
|
|
/// try {
|
|
/// chai("throw(1)");
|
|
/// } catch (chaiscript::Boxed_Value bv) {
|
|
/// int i = chaiscript::boxed_cast<int>(bv);
|
|
/// // i == 1
|
|
/// }
|
|
/// }
|
|
/// ~~~~~~~~
|
|
///
|
|
/// @subsubsection exceptionsautomatic Exception Handling Automatic Unboxing
|
|
///
|
|
/// As an alternative to the manual unboxing of exceptions shown above, exception specifications allow the user to tell
|
|
/// ChaiScript what possible exceptions are expected from the script being executed.
|
|
///
|
|
/// Example:
|
|
/// ~~~~~~~~{.cpp}
|
|
/// chaiscript::ChaiScript chai;
|
|
///
|
|
/// try {
|
|
/// chai.eval("throw(runtime_error(@"error@"))", chaiscript::exception_specification<int, double, float, const std::string &, const
|
|
/// std::exception &>());
|
|
/// } catch (const double e) {
|
|
/// } catch (int) {
|
|
/// } catch (float) {
|
|
/// } catch (const std::string &) {
|
|
/// } catch (const std::exception &e) {
|
|
/// // This is the one what will be called in the specific throw() above
|
|
/// }
|
|
/// ~~~~~~~~
|
|
///
|
|
/// @sa chaiscript::Exception_Handler for details on automatic exception unboxing
|
|
/// @sa chaiscript::exception_specification
|
|
|
|
/// @page LangObjectSystemRef ChaiScript Language Object Model Reference
|
|
///
|
|
///
|
|
/// ChaiScript has an object system built in, for types defined within the ChaiScript system.
|
|
///
|
|
/// ~~~~~~~~~
|
|
/// attr Rectangle::height
|
|
/// attr Rectangle::width
|
|
/// def Rectangle::Rectangle() { this.height = 10; this.width = 20 }
|
|
/// def Rectangle::area() { this.height * this.width }
|
|
///
|
|
/// var rect = Rectangle()
|
|
/// rect.height = 30
|
|
/// print(rect.area())
|
|
/// ~~~~~~~~~
|
|
///
|
|
/// Since ChaiScript 5.4.0 it has been possible to use the "class" keyword to simplify this code.
|
|
///
|
|
/// ~~~~~~~~~
|
|
/// class Rectangle {
|
|
/// attr height
|
|
/// attr width
|
|
/// def Rectangle() { this.height = 10; this.width = 20 }
|
|
/// def area() { this.height * this.width }
|
|
/// }
|
|
///
|
|
/// var rect = Rectangle()
|
|
/// rect.height = 30
|
|
/// print(rect.area())
|
|
/// ~~~~~~~~~
|
|
///
|
|
/// @sa @ref keywordattr
|
|
/// @sa @ref keyworddef
|
|
|
|
/// @page LangInPlaceRef ChaiScript Language In-Place Creation Reference
|
|
/// @section inplacevector Vector
|
|
///
|
|
/// ~~~~~~~~~
|
|
/// In-place Vector ::= "[" [expression ("," expression)*] "]"
|
|
/// ~~~~~~~~~
|
|
///
|
|
/// @section inplacerangedvector Ranged Vector
|
|
///
|
|
/// ~~~~~~~~~
|
|
/// In-place Ranged Vector ::= "[" value ".." value "]"
|
|
/// ~~~~~~~~~
|
|
///
|
|
/// Creates a vector over a range (eg. 1..10)
|
|
///
|
|
/// @section inplacemap Map
|
|
///
|
|
/// ~~~~~~~~
|
|
/// In-place Map ::= "[" (string ":" expression)+ "]"
|
|
/// ~~~~~~~~
|
|
|
|
/// @page LangGettingStarted ChaiScript Language Getting Started
|
|
///
|
|
/// ChaiScript is a simple language that should feel familiar to anyone who knows
|
|
/// C++ or ECMAScript (JavaScript).
|
|
///
|
|
/// -----------------------------------------------------------------------
|
|
///
|
|
/// @section chaiscriptloops Loops
|
|
///
|
|
/// Common looping constructs exist in ChaiScript
|
|
///
|
|
/// ~~~~~~~~
|
|
/// var i = 0;
|
|
/// while (i < 10)
|
|
/// {
|
|
/// // do something
|
|
/// ++i;
|
|
/// }
|
|
/// ~~~~~~~~
|
|
///
|
|
/// ~~~~~~~~
|
|
/// for (var i = 0; i < 10; ++i)
|
|
/// {
|
|
/// // do something
|
|
/// }
|
|
/// ~~~~~~~~
|
|
///
|
|
/// @sa @ref keywordfor
|
|
/// @sa @ref keywordwhile
|
|
///
|
|
/// -----------------------------------------------------------------------
|
|
///
|
|
/// @section chaiscriptifs Conditionals
|
|
///
|
|
/// If statements work as expected
|
|
///
|
|
/// ~~~~~~~~
|
|
/// var b = true;
|
|
///
|
|
/// if (b) {
|
|
/// // do something
|
|
/// } else if (c < 10) {
|
|
/// // do something else
|
|
/// } else {
|
|
/// // or do this
|
|
/// }
|
|
/// ~~~~~~~~
|
|
///
|
|
/// @sa @ref keywordif
|
|
///
|
|
/// -----------------------------------------------------------------------
|
|
///
|
|
/// @section chaiscriptfunctions Functions
|
|
///
|
|
/// Functions are defined with the def keyword
|
|
///
|
|
/// ~~~~~~~~
|
|
/// def myfun(x) { print(x); }
|
|
///
|
|
/// myfun(10);
|
|
/// ~~~~~~~~
|
|
///
|
|
/// Functions may have "guards" which determine if which is called.
|
|
///
|
|
/// ~~~~~~~~
|
|
/// eval> def myfun2(x) : x < 10 { print("less than 10"); }
|
|
/// eval> def myfun2(x) : x >= 10 { print("10 or greater"); }
|
|
/// eval> myfun2(5)
|
|
/// less than 10
|
|
/// eval> myfun2(12)
|
|
/// 10 or greater
|
|
/// ~~~~~~~~
|
|
///
|
|
/// @sa @ref keyworddef
|
|
/// @sa @ref keywordattr
|
|
/// @sa @ref LangObjectSystemRef
|
|
///
|
|
/// -----------------------------------------------------------------------
|
|
///
|
|
/// @section chaiscriptfunctionobjects Function Objects
|
|
///
|
|
/// Functions are first class types in ChaiScript and can be used as variables.
|
|
///
|
|
/// ~~~~~~~~
|
|
/// eval> var p = print;
|
|
/// eval> p(1);
|
|
/// 1
|
|
/// ~~~~~~~~
|
|
///
|
|
/// They can also be passed to functions.
|
|
///
|
|
/// ~~~~~~~~
|
|
/// eval> def callfunc(f, lhs, rhs) { return f(lhs, rhs); }
|
|
/// eval> def do_something(lhs, rhs) { print("lhs: ${lhs}, rhs: ${rhs}"); }
|
|
/// eval> callfunc(do_something, 1, 2);
|
|
/// lhs: 1, rhs: 2
|
|
/// ~~~~~~~~
|
|
///
|
|
/// Operators can also be treated as functions by using the back tick operator. Building on the above example:
|
|
///
|
|
/// ~~~~~~~~
|
|
/// eval> callfunc(`+`, 1, 4);
|
|
/// 5
|
|
/// eval> callfunc(`*`, 3, 2);
|
|
/// 6
|
|
/// ~~~~~~~~
|
|
///
|
|
/// -----------------------------------------------------------------------
|
|
///
|
|
/// @sa @ref LangKeywordRef
|
|
/// @sa ChaiScript_Language for Built in Functions
|
|
|
|
/// @page LangKeywordRef ChaiScript Language Keyword Reference
|
|
///
|
|
///
|
|
/// -----------------------------------------------------------------------
|
|
///
|
|
/// @section keywordattr attr
|
|
/// Defines a ChaiScript object attribute
|
|
///
|
|
/// ~~~~~~~~
|
|
/// Attribute Definition ::= "attr" class_name "::" attribute_name
|
|
/// ~~~~~~~~
|
|
///
|
|
/// @sa @ref LangObjectSystemRef
|
|
///
|
|
///
|
|
/// -----------------------------------------------------------------------
|
|
///
|
|
/// @section keywordauto auto
|
|
///
|
|
/// Defines a variable
|
|
///
|
|
/// ~~~~~~~~
|
|
/// Variable ::= "auto" identifier
|
|
/// ~~~~~~~~
|
|
///
|
|
/// Synonym for @ref keywordvar
|
|
///
|
|
/// -----------------------------------------------------------------------
|
|
///
|
|
/// @section keywordbreak break
|
|
/// Stops execution of a looping block.
|
|
///
|
|
/// ~~~~~~~~
|
|
/// Break Statement ::= "break"
|
|
/// ~~~~~~~~
|
|
///
|
|
/// @sa @ref keywordfor
|
|
/// @sa @ref keywordwhile
|
|
///
|
|
///
|
|
/// -----------------------------------------------------------------------
|
|
///
|
|
/// @section keyworddef def
|
|
/// Begins a function or method definition
|
|
///
|
|
/// ~~~~~~~~
|
|
/// Function Definition ::= "def" identifier "(" [[type] arg ("," [type] arg)*] ")" [":" guard] block
|
|
/// Method Definition ::= "def" class_name "::" method_name "(" [[type] arg ("," [type] arg)*] ")" [":" guard] block
|
|
/// ~~~~~~~~
|
|
///
|
|
/// identifier: name of function. Required.
|
|
/// args: comma-delimited list of parameter names with optional type specifiers. Optional.
|
|
/// guards: guarding statement that act as a prerequisite for the function. Optional.
|
|
/// { }: scoped block as function body. Required.
|
|
///
|
|
/// Functions return values in one of two ways:
|
|
///
|
|
/// By using an explicit return call, optionally passing the value to be returned.
|
|
/// By implicitly returning the value of the last expression (if it is not a while or for loop).
|
|
///
|
|
/// Method definitions for known types extend those types with new methods. This includes C++ and ChaiScript defined types.
|
|
/// Method definitions for unknown types implicitly define the named type.
|
|
///
|
|
/// @sa @ref LangObjectSystemRef
|
|
///
|
|
///
|
|
/// -----------------------------------------------------------------------
|
|
///
|
|
/// @section keywordelse else
|
|
/// @sa @ref keywordif
|
|
///
|
|
///
|
|
/// -----------------------------------------------------------------------
|
|
///
|
|
/// @section keywordfor for
|
|
/// ~~~~~~~~
|
|
/// For Block ::= "for" "(" [initial] ";" stop_condition ";" loop_expression ")" block
|
|
/// ~~~~~~~~
|
|
/// This loop can be broken using the @ref keywordbreak command.
|
|
///
|
|
///
|
|
/// -----------------------------------------------------------------------
|
|
///
|
|
/// @section keywordfun fun
|
|
/// Begins an anonymous function declaration (sometimes called a lambda).
|
|
///
|
|
/// ~~~~~~~~
|
|
/// Lambda ::= "fun" "(" [variable] ("," variable)* ")" block
|
|
/// ~~~~~~~~
|
|
///
|
|
/// _Example_
|
|
///
|
|
/// ~~~~~~~~
|
|
/// // Generate an anonymous function object that adds 2 to its parameter
|
|
/// var f = fun(x) { x + 2; }
|
|
/// ~~~~~~~~
|
|
///
|
|
/// @sa @ref keyworddef for more details on ChaiScript functions
|
|
///
|
|
///
|
|
/// -----------------------------------------------------------------------
|
|
///
|
|
/// @section keywordif if
|
|
/// Begins a conditional block of code that only executes if the condition evaluates as true.
|
|
/// ~~~~~~~~
|
|
/// If Block ::= "if" "(" condition ")" block
|
|
/// Else If Block ::= "else if" "(" condition ")" block
|
|
/// Else Block ::= "else" block
|
|
/// ~~~~~~~~
|
|
///
|
|
/// _Example_
|
|
///
|
|
/// ~~~~~~~~
|
|
/// if (true) {
|
|
/// // do something
|
|
/// } else if (false) {
|
|
/// // do something else
|
|
/// } else {
|
|
/// // otherwise do this
|
|
/// }
|
|
/// ~~~~~~~~
|
|
///
|
|
///
|
|
/// -----------------------------------------------------------------------
|
|
///
|
|
/// @section keywordtry try
|
|
/// ~~~~~~~~
|
|
/// Try Block ::= "try" block
|
|
/// ("catch" ["(" [type] variable ")"] [":" guards] block)+
|
|
/// ["finally" block]
|
|
/// ~~~~~~~~
|
|
///
|
|
/// @sa ChaiScript_Language::throw
|
|
///
|
|
///
|
|
/// -----------------------------------------------------------------------
|
|
///
|
|
/// @section keywordwhile while
|
|
///
|
|
/// Begins a conditional block of code that loops 0 or more times, as long as the condition is true
|
|
///
|
|
/// ~~~~~~~~
|
|
/// While Block ::= "while" "(" condition ")" block
|
|
/// ~~~~~~~~
|
|
///
|
|
/// This loop can be broken using the @ref keywordbreak command.
|
|
///
|
|
///
|
|
/// -----------------------------------------------------------------------
|
|
///
|
|
/// @section keywordvar var
|
|
///
|
|
/// Defines a variable
|
|
///
|
|
/// ~~~~~~~~
|
|
/// Variable ::= "var" identifier
|
|
/// ~~~~~~~~
|
|
///
|
|
/// Synonym for @ref keywordauto
|
|
|
|
/// @namespace chaiscript
|
|
/// @brief Namespace chaiscript contains every API call that the average user will be concerned with.
|
|
|
|
/// @namespace chaiscript::detail
|
|
/// @brief Classes and functions reserved for internal use. Items in this namespace are not supported.
|
|
|
|
#include "chaiscript_basic.hpp"
|
|
#include "chaiscript_stdlib.hpp"
|
|
#include "language/chaiscript_parser.hpp"
|
|
|
|
namespace chaiscript {
|
|
class ChaiScript : public ChaiScript_Basic {
|
|
public:
|
|
ChaiScript(std::vector<std::string> t_modulepaths = {},
|
|
std::vector<std::string> t_usepaths = {},
|
|
std::vector<Options> t_opts = chaiscript::default_options(),
|
|
std::vector<Library_Options> t_lib_opts = {})
|
|
: ChaiScript_Basic(chaiscript::Std_Lib::library(t_lib_opts),
|
|
std::make_unique<parser::ChaiScript_Parser<eval::Noop_Tracer, optimizer::Optimizer_Default>>(),
|
|
std::move(t_modulepaths),
|
|
std::move(t_usepaths),
|
|
std::move(t_opts),
|
|
std::find(t_lib_opts.begin(), t_lib_opts.end(), Library_Options::No_IO) != t_lib_opts.end()) {
|
|
}
|
|
};
|
|
} // namespace chaiscript
|
|
|
|
#endif /* CHAISCRIPT_HPP_ */
|