diff --git a/include/chaiscript/chaiscript.hpp b/include/chaiscript/chaiscript.hpp
index 5c5ff5a..91686db 100644
--- a/include/chaiscript/chaiscript.hpp
+++ b/include/chaiscript/chaiscript.hpp
@@ -25,6 +25,147 @@
/// \sa http://www.chaiscript.com
/// \sa http://www.github.com/ChaiScript/ChaiScript
+/// \page LangObjectSystemRef ChaiScript Language Object Model Reference
+///
+///
+/// ChaiScript supports has an object system built in, for types defined within the ChaiScript system.
+///
+/// \code
+/// attr Rectangle::height
+/// attr Rectangle::width
+/// def Rectangle::Rectangle() { this.height = 10; this.width = 20 }
+/// def Rectangle::area() { this.height * this.width }
+///
+/// var rect = Rectangle()
+/// rect.height = 30
+/// print(rect.area())
+/// \endcode
+///
+/// \sa \ref keywordattr
+/// \sa \ref keyworddef
+
+
+/// \page LangKeywordRef ChaiScript Language Keyword Reference
+///
+///
+///
+/// \section keywordattr attr
+/// Defines a ChaiScript object attribute
+///
+/// \code
+/// Attribute Definition ::= "attr" class_name "::" attribute_name
+/// \endcode
+///
+/// \sa \ref LangObjectSystemRef
+///
+///
+/// \section keywordbreak break
+/// Stops execution of a looping block.
+///
+/// \code
+/// Break Statement ::= "break"
+/// \endcode
+///
+/// \sa \ref keywordfor
+/// \sa \ref keywordwhile
+///
+///
+///
+/// \section keyworddef def
+/// Begins a function or method definition
+///
+/// \code
+/// Function Definition ::= [annotation + CR/LF] "def" identifier "(" [arg ("," arg)*] ")" [":" guard] block
+/// Method Definition ::= [annotation + CR/LF] "def" class_name "::" method_name "(" [arg ("," arg)*] ")" [":" guard] block
+/// \endcode
+///
+/// annotation: meta-annotation on function, currently used as documentation. Optional.
+/// identifier: name of function. Required.
+/// args: comma-delimited list of parameter names. Optional.
+/// guards: guarding statement that act as a prerequisite for the function. Optional.
+/// { }: scoped block as function body. Required.
+///
+/// Functions return values in one of two ways:
+///
+/// By using an explicit return call, optionally passing the value to be returned.
+/// By implicitly returning the value of the last expression (if it is not a while or for loop).
+///
+/// Method definitions for known types extend those types with new methods. This includes C++ and ChaiScript defined types.
+/// Method definitions for unknown types implicitly define the named type.
+///
+/// \sa \ref LangObjectSystemRef
+///
+///
+///
+/// \section keywordelse else
+/// \sa \ref keywordif
+///
+///
+///
+/// \section keywordfor for
+/// \code
+/// For Block ::= "for" "(" [initial] ";" stop_condition ";" loop_expression ")" block
+/// \endcode
+/// This loop can be broken using the \ref keywordbreak command.
+///
+///
+///
+/// \section keywordfun fun
+/// Begins an anonymous function declaration (sometimes called a lambda).
+///
+/// \code
+/// Lambda ::= "fun" "(" [variable] ("," variable)* ")" block
+/// \endcode
+///
+/// \b Examples:
+///
+/// \code
+/// // Generate an anonymous function object that adds 2 to its parameter
+/// var f = fun(x) { x + 2; }
+/// \endcode
+///
+/// \sa \ref keyworddef for more details on ChaiScript functions
+///
+///
+///
+/// \section keywordif if
+/// Begins a conditional block of code that only executes if the condition evaluates as true.
+/// \code
+/// If Block ::= "if" "(" condition ")" block
+/// Else If Block ::= "else if" "(" condition ")" block
+/// Else Block ::= "else" block
+/// \endcode
+/// \b Example:
+/// \code
+/// if (true) {
+/// // do something
+/// } else if (false) {
+/// // do something else
+/// } else {
+/// // otherwise do this
+/// }
+/// \endcode
+///
+///
+///
+/// \section keywordtry try
+/// \code
+/// Try Block ::= "try" block
+/// ("catch" ["(" variable ")"] [":" guards] block)+
+/// ["finally" block]
+/// \endcode
+///
+///
+///
+/// \section keywordwhile while
+///
+/// Begins a conditional block of code that loops 0 or more times, as long as the condition is true
+///
+/// \code
+/// While Block ::= "while" "(" condition ")" block
+/// \endcode
+/// This loop can be broken using the \ref keywordbreak command.
+
/// \namespace chaiscript
/// \brief Namespace chaiscript contains every API call that the average user will be concerned with.
diff --git a/include/chaiscript/dispatchkit/bootstrap.hpp b/include/chaiscript/dispatchkit/bootstrap.hpp
index 7bd30d0..757f989 100644
--- a/include/chaiscript/dispatchkit/bootstrap.hpp
+++ b/include/chaiscript/dispatchkit/bootstrap.hpp
@@ -311,7 +311,7 @@ namespace chaiscript
/// \brief Adds a constructor for a POD type
/// \tparam T The type to add the constructor for
- /// \param[in] T The name of the type
+ /// \param[in] type The name of the type
/// \param[in,out] m The Module to add the constructor to
template
ModulePtr construct_pod(const std::string &type, ModulePtr m = ModulePtr(new Module()))
diff --git a/include/chaiscript/dispatchkit/boxed_cast.hpp b/include/chaiscript/dispatchkit/boxed_cast.hpp
index 242771b..e082ce3 100644
--- a/include/chaiscript/dispatchkit/boxed_cast.hpp
+++ b/include/chaiscript/dispatchkit/boxed_cast.hpp
@@ -24,12 +24,49 @@
namespace chaiscript
{
-
- /**
- * boxed_cast function for casting a Boxed_Value into a given type
- * example:
- * int &i = boxed_cast(boxedvalue);
- */
+
+ /// \brief Function for extracting a value stored in a Boxed_Value object
+ /// \tparam Type The type to extract from the Boxed_Value
+ /// \param[in] bv The Boxed_Value to extract a typed value from
+ /// \returns Type equivalent to the requested type
+ /// \throws exception::bad_boxed_cast If the requested conversion is not possible
+ ///
+ /// boxed_cast will attempt to make conversions between value, &, *, boost::shared_ptr, boost::reference_wrapper,
+ /// and boost::function (const and non-const) where possible. boxed_cast is used internally during function
+ /// dispatch. This means that all of these conversions will be attempted automatically for you during
+ /// ChaiScript function calls.
+ ///
+ /// \li non-const values can be extracted as const or non-const
+ /// \li const values can be extracted only as const
+ /// \li Boxed_Value constructed from pointer or boost::reference_wrapper can be extracted as reference,
+ /// pointer or value types
+ /// \li Boxed_Value constructed from boost::shared_ptr or value types can be extracted as reference,
+ /// pointer, value, or boost::shared_ptr types
+ ///
+ /// Conversions to boost::function objects are attempted as well
+ ///
+ /// Example:
+ /// \code
+ /// // All of the following should succeed
+ /// chaiscript::Boxed_Value bv(1);
+ /// boost::shared_ptr spi = chaiscript::boxed_cast >(bv);
+ /// int i = chaiscript::boxed_cast(bv);
+ /// int *ip = chaiscript::boxed_cast(bv);
+ /// int &ir = chaiscript::boxed_cast(bv);
+ /// boost::shared_ptr cspi = chaiscript::boxed_cast >(bv);
+ /// const int ci = chaiscript::boxed_cast(bv);
+ /// const int *cip = chaiscript::boxed_cast(bv);
+ /// const int &cir = chaiscript::boxed_cast(bv);
+ /// \endcode
+ ///
+ /// boost::function conversion example
+ /// \code
+ /// chaiscript::ChaiScript chai;
+ /// Boxed_Value bv = chai.eval("`+`"); // Get the functor for the + operator which is built in
+ /// boost::function f = chaiscript::boxed_cast >(bv);
+ /// int i = f(2,3);
+ /// assert(i == 5);
+ /// \endcode
template
typename detail::Cast_Helper::Result_Type boxed_cast(const Boxed_Value &bv)
{
diff --git a/include/chaiscript/dispatchkit/boxed_value.hpp b/include/chaiscript/dispatchkit/boxed_value.hpp
index dc2aff8..76070f1 100644
--- a/include/chaiscript/dispatchkit/boxed_value.hpp
+++ b/include/chaiscript/dispatchkit/boxed_value.hpp
@@ -270,50 +270,97 @@ namespace chaiscript
boost::shared_ptr m_data;
};
- /// Clean wrapper for providing the user with a Boxed_Value
- /// Suggested use: chai.add(var(myvariable), "myvariable");
+ /// \brief Creates a Boxed_Value. If the object passed in is a value type, it is copied. If it is a pointer, boost::shared_ptr, or boost::reference_type
+ /// a copy is not made.
/// \param t The value to box
+ ///
+ /// Example:
+ /// \code
+ /// int i;
+ /// chaiscript::ChaiScript chai;
+ /// chai.add(chaiscript::var(i), "i");
+ /// chai.add(chaiscript::var(&i), "ip");
+ /// \endcode
template
Boxed_Value var(T t)
{
return Boxed_Value(t);
}
- /// Wrapper for providing the user with a Boxed_Value that is const inside
- /// of the ChaiScript engine.
- /// Suggested use: chai.add(const_var(myvariable), "myvariable");
- /// \param t The value to box
- template
- Boxed_Value const_var(T *t)
- {
- return Boxed_Value( const_cast::type *>(t) );
- }
+ namespace detail {
+ /// \brief Takes a value, copies it and returns a Boxed_Value object that is immutable
+ /// \param[in] t Value to copy and make const
+ /// \returns Immutable Boxed_Value
+ /// \sa Boxed_Value::is_const
+ template
+ Boxed_Value const_var_impl(const T &t)
+ {
+ return Boxed_Value(boost::shared_ptr::type >(new T(t)));
+ }
- /// boost::shared_ptr overload for const_var
- template
- Boxed_Value const_var(const boost::shared_ptr &t)
- {
- return Boxed_Value( boost::const_pointer_cast::type>(t) );
- }
+ /// \brief Takes a pointer to a value, adds const to the pointed to type and returns an immutable Boxed_Value.
+ /// Does not copy the pointed to value.
+ /// \param[in] t Pointer to make immutable
+ /// \returns Immutable Boxed_Value
+ /// \sa Boxed_Value::is_const
+ template
+ Boxed_Value const_var_impl(T *t)
+ {
+ return Boxed_Value( const_cast::type *>(t) );
+ }
- /// boost::reference_wrapper overload for const_var
- template
- Boxed_Value const_var(const boost::reference_wrapper &t)
- {
- return Boxed_Value( boost::cref(t.get()) );
- }
+ /// \brief Takes a boost::shared_ptr to a value, adds const to the pointed to type and returns an immutable Boxed_Value.
+ /// Does not copy the pointed to value.
+ /// \param[in] t Pointer to make immutable
+ /// \returns Immutable Boxed_Value
+ /// \sa Boxed_Value::is_const
+ template
+ Boxed_Value const_var_impl(const boost::shared_ptr &t)
+ {
+ return Boxed_Value( boost::const_pointer_cast::type>(t) );
+ }
- /// Generic overload for const_var
+ /// \brief Takes a boost::reference_wrapper value, adds const to the referenced type and returns an immutable Boxed_Value.
+ /// Does not copy the referenced value.
+ /// \param[in] t Reference object to make immutable
+ /// \returns Immutable Boxed_Value
+ /// \sa Boxed_Value::is_const
+ template
+ Boxed_Value const_var_impl(const boost::reference_wrapper &t)
+ {
+ return Boxed_Value( boost::cref(t.get()) );
+ }
+ }
+
+ /// \brief Takes an object and returns an immutable Boxed_Value. If the object is a boost::reference or pointer type
+ /// the value is not copied. If it is an object type, it is copied.
+ /// \param[in] t Object to make immutable
+ /// \returns Immutable Boxed_Value
+ /// \sa chaiscript::Boxed_Value::is_const
+ /// \sa chaiscript::var
+ ///
+ /// Example:
+ /// \code
+ /// enum Colors
+ /// {
+ /// Blue,
+ /// Green,
+ /// Red
+ /// };
+ /// chaiscript::ChaiScript chai
+ /// chai.add(chaiscript::const_var(Blue), "Blue"); // add immutable constant
+ /// chai.add(chaiscript::const_var(Red), "Red");
+ /// chai.add(chaiscript::const_var(Green), "Green");
+ /// \endcode
template
Boxed_Value const_var(const T &t)
{
- return Boxed_Value(boost::shared_ptr::type >(new T(t)));
+ return detail::const_var_impl(t);
}
- /**
- * Return true if the two Boxed_Values share the same internal type
- */
+
+ /// \returns true if the two Boxed_Values share the same internal type
static bool type_match(Boxed_Value l, Boxed_Value r)
{
return l.get_type_info() == r.get_type_info();
diff --git a/include/chaiscript/dispatchkit/dynamic_cast_conversion.hpp b/include/chaiscript/dispatchkit/dynamic_cast_conversion.hpp
index 1ee3c99..dd14ff8 100644
--- a/include/chaiscript/dispatchkit/dynamic_cast_conversion.hpp
+++ b/include/chaiscript/dispatchkit/dynamic_cast_conversion.hpp
@@ -230,6 +230,18 @@ namespace chaiscript
/// (through a tertiary dll that is shared between the modules, static linking the new type
/// into both loadable modules would not be portable), you need to register the base type
/// relationship in all modules that use the newly added type in a polymorphic way.
+ ///
+ /// Example:
+ /// \code
+ /// class Base
+ /// {};
+ /// class Derived : public Base
+ /// {};
+ ///
+ /// chaiscript::ChaiScript chai;
+ /// chai.add(chaiscript::base_class());
+ /// \endcode
+ ///
/// \todo Move share static type registration code into a mechanism that allows it to be properly
/// shared by all modules
template
diff --git a/include/chaiscript/dispatchkit/proxy_constructors.hpp b/include/chaiscript/dispatchkit/proxy_constructors.hpp
index 73e0afe..fcd019b 100644
--- a/include/chaiscript/dispatchkit/proxy_constructors.hpp
+++ b/include/chaiscript/dispatchkit/proxy_constructors.hpp
@@ -22,6 +22,17 @@
namespace chaiscript
{
+ /// \brief Generates a constructor function for use with ChaiScript
+ ///
+ /// \tparam T The signature of the constructor to generate. In the form of: ClassType (ParamType1, ParamType2, ...)
+ ///
+ /// Example:
+ /// \code
+ /// chaiscript::ChaiScript chai;
+ /// // Create a new function that creates a MyClass object using the (int, float) constructor
+ /// // and call that function "MyClass" so that it appears as a normal constructor to the user.
+ /// chai.add(constructor(), "MyClass");
+ /// \endcode
template
Proxy_Function constructor()
{
diff --git a/include/chaiscript/dispatchkit/proxy_functions.hpp b/include/chaiscript/dispatchkit/proxy_functions.hpp
index a29a06c..b03e89f 100644
--- a/include/chaiscript/dispatchkit/proxy_functions.hpp
+++ b/include/chaiscript/dispatchkit/proxy_functions.hpp
@@ -184,9 +184,7 @@ namespace chaiscript
namespace exception
{
- /**
- * Exception thrown if a function's guard fails to execute
- */
+ /// \brief Exception thrown if a function's guard fails
class guard_error : public std::runtime_error
{
public:
@@ -581,12 +579,11 @@ 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
- */
+ /// \brief Exception thrown in the case that a method dispatch fails
+ /// because no matching function was found
+ ///
+ /// May be thrown due to an arity_error, a guard_error or a bad_boxed_cast
+ /// exception
class dispatch_error : public std::runtime_error
{
public:
diff --git a/include/chaiscript/dispatchkit/register_function.hpp b/include/chaiscript/dispatchkit/register_function.hpp
index 8db8113..766187f 100644
--- a/include/chaiscript/dispatchkit/register_function.hpp
+++ b/include/chaiscript/dispatchkit/register_function.hpp
@@ -65,24 +65,85 @@ namespace chaiscript
}
}
+ /// \brief Creates a new Proxy_Function object from a boost::function object
+ /// \param[in] f boost::function to expose to ChaiScript
+ ///
+ /// \b Example:
+ /// \code
+ /// boost::function f = get_some_function();
+ /// chaiscript::ChaiScript chai;
+ /// chai.add(fun(f), "some_function");
+ /// \endcode
template
Proxy_Function fun(const boost::function &f)
{
return Proxy_Function(new dispatch::Proxy_Function_Impl(f));
}
+ /// \brief Creates a new Proxy_Function object from a free function, member function or data member
+ /// \param[in] t Function / member to expose
+ ///
+ /// \b Example:
+ /// \code
+ /// int myfunction(const std::string &);
+ /// class MyClass
+ /// {
+ /// public:
+ /// void memberfunction();
+ /// int memberdata;
+ /// };
+ ///
+ /// chaiscript::ChaiScript chai;
+ /// chai.add(fun(&myfunction), "myfunction");
+ /// chai.add(fun(&MyClass::memberfunction), "memberfunction");
+ /// chai.add(fun(&MyClass::memberdata), "memberdata");
+ /// \endcode
template
Proxy_Function fun(T t)
{
return dispatch::detail::Fun_Helper::value, boost::function_types::is_member_function_pointer::value>::go(t);
}
+ /// \brief Creates a new Proxy_Function object from a free function, member function or data member and binds the first parameter of it
+ /// \param[in] t Function / member to expose
+ /// \param[in] q Value to bind to first parameter
+ ///
+ /// \b Example:
+ /// \code
+ /// struct MyClass
+ /// {
+ /// void memberfunction(int);
+ /// };
+ ///
+ /// MyClass obj;
+ /// chaiscript::ChaiScript chai;
+ /// // Add function taking only one argument, an int, and permanently bound to "obj"
+ /// chai.add(fun(&MyClass::memberfunction, boost::ref(obj)), "memberfunction");
+ /// \endcode
template
Proxy_Function fun(T t, const Q &q)
{
return fun(detail::bind_first(t, q));
}
+ /// \brief Creates a new Proxy_Function object from a free function or member function and binds the first and second parameters of it
+ /// \param[in] t Function / member to expose
+ /// \param[in] q Value to bind to first parameter
+ /// \param[in] r Value to bind to second parameter
+ ///
+ /// \b Example:
+ /// \code
+ /// struct MyClass
+ /// {
+ /// void memberfunction(int);
+ /// };
+ ///
+ /// MyClass obj;
+ /// chaiscript::ChaiScript chai;
+ /// // Add function taking only no arguments, and permanently bound to "obj" and "1"
+ /// // memberfunction() will be equivalent to obj.memberfunction(1)
+ /// chai.add(fun(&MyClass::memberfunction, boost::ref(obj), 1), "memberfunction");
+ /// \endcode
template
Proxy_Function fun(T t, const Q &q, const R &r)
{
diff --git a/include/chaiscript/dispatchkit/type_info.hpp b/include/chaiscript/dispatchkit/type_info.hpp
index da9a601..605fbb6 100644
--- a/include/chaiscript/dispatchkit/type_info.hpp
+++ b/include/chaiscript/dispatchkit/type_info.hpp
@@ -212,13 +212,30 @@ namespace chaiscript
};
}
+ /// \brief Creates a Type_Info object representing the type passed in
+ /// \tparam T Type of object to get a Type_Info for, derived from the passed in parameter
+ /// \return Type_Info for T
+ ///
+ /// \b Example:
+ /// \code
+ /// int i;
+ /// chaiscript::Type_Info ti = chaiscript::user_type(i);
+ /// \endcode
template
- Type_Info user_type(T)
+ Type_Info user_type(const T &/*t*/)
{
return detail::Get_Type_Info::get();
}
+ /// \brief Creates a Type_Info object representing the templated type
+ /// \tparam T Type of object to get a Type_Info for
+ /// \return Type_Info for T
+ ///
+ /// \b Example:
+ /// \code
+ /// chaiscript::Type_Info ti = chaiscript::user_type();
+ /// \endcode
template
Type_Info user_type()
{
diff --git a/include/chaiscript/language/chaiscript_engine.hpp b/include/chaiscript/language/chaiscript_engine.hpp
index 16364bf..4efcec6 100644
--- a/include/chaiscript/language/chaiscript_engine.hpp
+++ b/include/chaiscript/language/chaiscript_engine.hpp
@@ -30,6 +30,7 @@ namespace chaiscript
{
namespace exception
{
+ /// \brief Thrown if an error occurs while attempting to load a binary module
struct load_module_error : std::runtime_error
{
load_module_error(const std::string &t_reason) throw()
@@ -356,7 +357,35 @@ namespace chaiscript
do_eval(chaiscript_prelude, "standard prelude");
}
+ /**
+ * Helper function for loading a file
+ */
+ std::string load_file(const std::string &t_filename) {
+ std::ifstream infile(t_filename.c_str(), std::ios::in | std::ios::ate | std::ios::binary );
+
+ if (!infile.is_open()) {
+ throw exception::file_not_found_error(t_filename);
+ }
+
+ std::streampos size = infile.tellg();
+ infile.seekg(0, std::ios::beg);
+
+ assert(size >= 0);
+
+ if (size == std::streampos(0))
+ {
+ return std::string();
+ } else {
+ std::vector v(static_cast(size));
+ infile.read(&v[0], size);
+ return std::string(v.begin(), v.end());
+ }
+ }
+
public:
+ /// \brief Constructor for ChaiScript
+ /// \param[in] t_modulepaths Vector of paths to search when attempting to load a binary module
+ /// \param[in] t_usepaths Vector of paths to search when attempting to "use" an included ChaiScript file
ChaiScript(const std::vector &t_modulepaths = std::vector(),
const std::vector &t_usepaths = std::vector())
: m_modulepaths(t_modulepaths), m_usepaths(t_usepaths)
@@ -374,15 +403,20 @@ namespace chaiscript
build_eval_system();
}
- /**
- * Adds a shared object, that can be used by all threads, to the system
- */
+ /// \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_name Name of the value to add
+ /// \throw exception::global_non_const If t_bv is not a constant object
+ /// \sa Boxed_Value::is_const
ChaiScript &add_global_const(const Boxed_Value &t_bv, const std::string &t_name)
{
m_engine.add_global_const(t_bv, t_name);
return *this;
}
+ /// \brief Represents the current state of the ChaiScript system. State and be saved and restored
+ /// \sa ChaiScript::get_state
+ /// \sa ChaiScript::set_state
struct State
{
std::set used_files;
@@ -390,11 +424,15 @@ namespace chaiscript
std::set active_loaded_modules;
};
- /**
- * Returns a state object that represents the current
- * set of loaded files, the set of global variables and
- * the set of initialized functions
- */
+ /// \brief Returns a state object that represents the current state of the system
+ /// \return Current state of the system
+ ///
+ /// \b Example:
+ ///
+ /// \code
+ /// chaiscript::ChaiScript chai;
+ /// chaiscript::ChaiScript::State s = chai.get_state(); // represents bootstrapped initial state
+ /// \endcode
State get_state()
{
chaiscript::detail::threading::lock_guard l(m_use_mutex);
@@ -407,9 +445,16 @@ namespace chaiscript
return s;
}
- /**
- * Restores the state from a saved State object.
- */
+ /// \brief Sets the state of the system
+ /// \param[in] t_state New state to set
+ ///
+ /// \b Example:
+ /// \code
+ /// chaiscript::ChaiScript chai;
+ /// chaiscript::ChaiScript::State s = chai.get_state(); // get initial state
+ /// chai.add(chaiscript::fun(&somefunction), "somefunction");
+ /// chai.set_state(s); // restore initial state, which does not have the recently added "somefunction"
+ /// \endcode
void set_state(const State &t_state)
{
chaiscript::detail::threading::lock_guard l(m_use_mutex);
@@ -420,9 +465,19 @@ namespace chaiscript
m_engine.set_state(t_state.engine_state);
}
- /**
- * Adds an object to the system: type, function, object
- */
+ /// \brief Adds a type, function or object to ChaiScript
+ /// \param[in] t_t Item to add
+ /// \param[in] t_name Name of item to add
+ /// \returns Reference to current ChaiScript object
+ ///
+ /// \b Examples:
+ /// \code
+ /// chaiscript::ChaiScript chai;
+ /// chai.add(chaiscript::user_type(), "MyClass"); // Add explicit type info (not strictly necessary)
+ /// chai.add(chaiscript::fun(&MyClass::function), "function"); // Add a class method
+ /// MyClass obj;
+ /// chai.add(chaiscript::var(&obj), "obj"); // Add a pointer to a locally defined object
+ /// \endcode
template
ChaiScript &add(const T &t_t, const std::string &t_name)
{
@@ -430,18 +485,42 @@ namespace chaiscript
return *this;
}
- /**
- * Adds a module object to the system
- */
+ /// \brief Add a new conversion for upcasting to a base class
+ /// \sa chaiscript::base_class
+ /// \param[in] d Base class / parent class
+ ///
+ /// \b Example:
+ /// \code
+ /// chaiscript::ChaiScript chai;
+ /// chai.add(chaiscript::base_class());
+ /// \endcode
+ ChaiScript &add(const Dynamic_Cast_Conversion &d)
+ {
+ m_engine.add(d);
+ return *this;
+ }
+
+ /// \brief Adds all elements of a module to ChaiScript runtime
+ /// \param[in] t_p The module to add.
+ /// \sa chaiscript::Module
ChaiScript &add(const ModulePtr &t_p)
{
t_p->apply(*this, this->get_eval_engine());
return *this;
}
- /**
- * Load a dynamic library containing a chaiscript module
- */
+ /// \brief Load a binary module from a dynamic library. Works on platforms that support
+ /// dynamic libraries.
+ /// \param[in] t_module_name Name of the module to load
+ ///
+ /// The module is searched for in the registered module path folders (chaiscript::ChaiScript::ChaiScript)
+ /// and with standard prefixes and postfixes: ("lib"|"")\(".dll"|".so"|"").
+ ///
+ /// Once the file is located, the system looks for the symbol "create_chaiscript_module_\".
+ /// If no file can be found matching the search criteria and containing the appropriate entry point
+ /// (the symbol mentioned above), an exception is thrown.
+ ///
+ /// \throw exception::load_module_error In the event that no matching module can be found.
void load_module(const std::string &t_module_name)
{
std::vector errors;
@@ -490,9 +569,13 @@ namespace chaiscript
throw exception::load_module_error("Unable to find module: " + t_module_name + " Errors: " + errstring);
}
- /**
- * Load a dynamic library and provide the file name to load it from
- */
+ /// \brief Load a binary module from a dynamic library. Works on platforms that support
+ /// dynamic libraries.
+ ///
+ /// \param[in] t_module_name Module name to load
+ /// \param[in] t_filename Ignore normal filename search process and use specific filename
+ ///
+ /// \sa ChaiScript::load_module(const std::string &t_module_name)
void load_module(const std::string &t_module_name, const std::string &t_filename)
{
chaiscript::detail::threading::lock_guard l(m_use_mutex);
@@ -510,62 +593,61 @@ namespace chaiscript
}
- /**
- * Evaluate a string via eval method
- */
+ /// \brief Evaluates a string. Equivalent to ChaiScript::eval.
+ ///
+ /// \param[in] t_script Script to execute
+ ///
+ /// \return result of the script execution
+ ///
+ /// \throw exception::eval_error In the case that evaluation fails.
Boxed_Value operator()(const std::string &t_script)
{
return do_eval(t_script);
}
-
- /**
- * Helper function for loading a file
- */
- std::string load_file(const std::string &t_filename) {
- std::ifstream infile(t_filename.c_str(), std::ios::in | std::ios::ate | std::ios::binary );
-
- if (!infile.is_open()) {
- throw exception::file_not_found_error(t_filename);
- }
-
- std::streampos size = infile.tellg();
- infile.seekg(0, std::ios::beg);
-
- assert(size >= 0);
-
- if (size == std::streampos(0))
- {
- return std::string();
- } else {
- std::vector v(static_cast(size));
- infile.read(&v[0], size);
- return std::string(v.begin(), v.end());
- }
- }
-
-
+ /// \brief Evaluates a string and returns a typesafe result.
+ ///
+ /// \tparam T Type to extract from the result value of the script execution
+ /// \param[in] t_input Script to execute
+ ///
+ /// \return result of the script execution
+ ///
+ /// \throw exception::eval_error In the case that evaluation fails.
+ /// \throw exception::bad_boxed_cast In the case that evaluation succeeds but the result value cannot be converted
+ /// to the requested type.
template
T eval(const std::string &t_input)
{
return boxed_cast(do_eval(t_input));
}
+ /// \brief Evaluates a string.
+ ///
+ /// \param[in] t_input Script to execute
+ ///
+ /// \return result of the script execution
+ ///
+ /// \throw exception::eval_error In the case that evaluation fails.
Boxed_Value eval(const std::string &t_input)
{
return do_eval(t_input);
}
- /**
- * Loads the file specified by filename, evaluates it, and returns the result
- */
+ /// \brief Loads the file specified by filename, evaluates it, and returns the result.
+ /// \param[in] t_filename File to load and parse.
+ /// \return result of the script execution
+ /// \throw exception::eval_error In the case that evaluation fails.
Boxed_Value eval_file(const std::string &t_filename) {
return do_eval(load_file(t_filename), t_filename);
}
- /**
- * Loads the file specified by filename, evaluates it, and returns the as the specified type
- */
+ /// \brief Loads the file specified by filename, evaluates it, and returns the typesafe result.
+ /// \tparam T Type to extract from the result value of the script execution
+ /// \param[in] t_filename File to load and parse.
+ /// \return result of the script execution
+ /// \throw exception::eval_error In the case that evaluation fails.
+ /// \throw exception::bad_boxed_cast In the case that evaluation succeeds but the result value cannot be converted
+ /// to the requested type.
template
T eval_file(const std::string &t_filename) {
return boxed_cast(do_eval(load_file(t_filename), t_filename));
diff --git a/include/chaiscript/language/chaiscript_prelude_docs.hpp b/include/chaiscript/language/chaiscript_prelude_docs.hpp
new file mode 100644
index 0000000..df1ca18
--- /dev/null
+++ b/include/chaiscript/language/chaiscript_prelude_docs.hpp
@@ -0,0 +1,242 @@
+
+/// \brief Items in this namespace exist in the ChaiScript language runtime. They are not part of the C++ API
+namespace ChaiScript_Language
+{
+
+/// \page LangStandardLibraryRef ChaiScript Language Standard Libary Reference
+///
+/// ChaiScript, at its core, has some very functional programming-inspired habits. Few places show this off as clearly
+/// as the prelude, itself a name taken as a nod to the popular functional language Haskell. This prelude is available
+/// to all standard ChaiScript applications, and provides a simple foundation for using numbers, strings, and ranges
+/// (the general category of containers and their iteration).
+///
+/// \section LibraryStrings Strings
+///
+
+
+/// \brief Converts o into a string.
+///
+/// \code
+/// eval> to_string(3).is_type("string")
+/// true
+/// \endcode
+string to_string(Object o);
+
+
+/// \brief Prints o to the terminal, without a trailing carriage return. Applies conversions to string automatically.
+/// \code
+/// eval> puts("hi, "); puts("there")
+/// hi, thereeval>
+/// \endcode
+/// \sa to_string
+/// \sa print
+void puts(Object o);
+
+
+/// \brief Prints o to the terminal, with a trailing carriage return. Applies conversions to string automatically
+/// \code
+/// eval> print("hello")
+/// hello
+/// eval>
+/// \endcode
+/// \sa to_string
+/// \sa puts
+void print(Object o);
+
+/// \brief ChaiScript representation of std::string. It is an std::string but only some member are exposed to ChaiScript.
+///
+/// Because the ChaiScript string object is an std::string, it is directly convertable to and from std::string
+/// using the chaiscript::boxed_cast and chaiscript::var functions.
+///
+/// With the exception of string::trim, string::rtrim, string::ltrim, all members are direct passthroughs to the
+/// std::string of the same name.
+///
+/// \note Object and function notations are equivalent in ChaiScript. This means that
+/// \c "bob".find("b") and \c find("bob", "b") are exactly the same. Most examples below follow the
+/// second formation of the function calls.
+/// \sa \ref keyworddef for extending existing C++ classes in ChaiScript
+class string
+{
+ public:
+ /// \brief Finds the first instance of substr.
+ /// \code
+ /// eval> find("abab", "ab")
+ /// 0
+ /// \endcode
+ int find(string s) const;
+
+
+ /// \brief Finds the last instance of substr.
+ /// \code
+ /// eval> rfind("abab", "ab")
+ /// 2
+ /// \endcode
+ int rfind(string s) const;
+
+ /// Finds the first of characters in list in the string.
+ ///
+ /// \code
+ /// eval> find_first_of("abab", "bec")
+ /// 1
+ /// \endcode
+ int find_first_of(string list) const;
+
+ /// Finds the last of characters in list in the string.
+ ///
+ /// \code
+ /// eval> find_last_of("abab", "bec")
+ /// 3
+ /// \endcode
+ int find_last_of(string list) const;
+
+ /// Finds the first non-matching character to list in the str string.
+ ///
+ /// \code
+ /// eval> find_first_not_of("abcd", "fec")
+ /// 0
+ /// \endcode
+ int find_first_not_of(string list) const;
+
+ ///find_last_not_of(str, list): Finds the last non-matching character to list in the str string.
+ ///
+ /// \code
+ /// eval> find_last_not_of("abcd", "fec")
+ /// 3
+ /// \endcode
+ int find_last_not_of(string list) const;
+
+ /// Removes whitespace from the front of the string, returning a new string
+ ///
+ /// \note This function is implemented as a ChaiScript function using the def member function notation.
+ ///
+ /// \code
+ /// eval> ltrim(" bob")
+ /// bob
+ /// \endcode
+ ///
+ /// \sa \ref keyworddef
+ string lstrim() const;
+
+ /// Removes whitespace from the back of the string, returning a new string
+ ///
+ /// \note This function is implemented as a ChaiScript function using the def member function notation.
+ ///
+ /// \code
+ /// eval> rtrim("bob ") + "|"
+ /// bob|
+ /// \endcode
+ ///
+ /// \sa \ref keyworddef
+ string rtrim() const;
+
+ /// Removes whitespace from the front and back of the string, returning a new string
+ ///
+ /// \note This function is implemented as a ChaiScript function using the def member function notation.
+ ///
+ /// \code
+ /// eval> trim(" bob ") + "|"
+ /// bob|
+ /// \endcode
+ ///
+ /// Equivalent to rtrim(ltrim(" bob "));
+ ///
+ /// \sa \ref keyworddef
+ string trim() const;
+};
+
+///Numbers
+///
+///max(a, b): Returns the maximum value of a or b.
+///
+///eval> max(4, 10)
+///10
+///min(a, b): Returns the minimum value of a or b.
+///
+///eval> min(4, 10)
+///4
+///even(x): Returns true if x is even, otherwise returns false.
+///
+///eval> even(4)
+///true
+///odd(x): Returns true if x is odd, otherwise returns false.
+///
+///eval> odd(4)
+///false
+///Containers
+///
+///for_each(container, f): Applies the function f over each element in the container.
+///
+///eval> for_each([1, 2, 3], print)
+///1
+///2
+///3
+///map(container, f): Applies f over each element in the container, joining all the results.
+///
+///eval> map([1, 2, 3], odd)
+///[true, false, true]
+///foldl(container, f, initial): Starts with the initial value and applies the function f to it and the first element of the container. The result is then applied to the second element, and so on until the elements are exhausted.
+///
+///eval> foldl([1, 2, 3, 4], `+`, 0)
+///10
+///sum(container): Returns the sum total of the values in the container.
+///
+///eval> sum([1, 2, 3, 4])
+///10
+///product(container): Returns the product of the value in the container.
+///
+///eval> product([1, 2, 3, 4])
+///24
+///take(container, num): Takes num elements from the container, returning them.
+///
+///eval> take([1, 2, 3, 4], 2)
+///[1, 2]
+///take_while(container, f): Takes elements from the container that match function f, stopping at the first non-match, returning them as a new Vector.
+///
+///eval> take_while([1, 2, 3], odd)
+///[1]
+///drop(container, num): Drops num elements from the container, returning the remainder.
+///
+///eval> drop([1, 2, 3, 4], 2)
+///[3, 4]
+///drop_while(container, f): Drops elements from the container that match f, stopping at the first non-match, returning the remainder.
+///
+///eval> drop_while([1, 2, 3], odd)
+///[2, 3]
+///reduce(container, f): Similar to foldl, this takes the first two elements as its starting values for f. This assumes container has at least 2 elements.
+///
+///eval> reduce([1, 2, 3, 4], `+`)
+///10
+///filter(container, f): Takes elements from container that match function f, return them.
+///
+///eval> filter([1, 2, 3, 4], odd)
+///[1, 3]
+///join(container, delim): Joins the elements of the container into a string, delimiting each with the delim string.
+///
+///eval> join([1, 2, 3], "*")
+///1*2*3
+///reverse(container): Returns the contents of the container in reversed order.
+///
+///eval> reverse([1, 2, 3, 4, 5, 6, 7])
+///[7, 6, 5, 4, 3, 2, 1]
+///generate_range(x, y): Generates a new Vector filled with values starting at x and ending with y.
+///
+///eval> generate_range(1, 10)
+///[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
+///concat(x, y): Returns a new Vector with x and y concatenated.
+///
+///eval> concat([1, 2, 3], [4, 5, 6])
+///[1, 2, 3, 4, 5, 6]
+///collate(x, y): Returns a new Vector with x and y as its values.
+///
+///eval> collate(1, 2)
+///[1, 2]
+///zip_with(f, x, y): Applies f to elements of x and y, returning a new Vector with the result of each application.
+///
+///eval> zip_with(`+`, [1, 2, 3], [4, 5, 6])
+///[5, 7, 9]
+///zip(x, y): Collates elements of x and y, returning a new Vector with the result.
+///
+///eval> zip([1, 2, 3], [4, 5, 6])
+///[[1, 4], [2, 5], [3, 6]]
+}
+