diff --git a/CMakeLists.txt b/CMakeLists.txt index 0130cfc..1deb880 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -91,7 +91,7 @@ endif() include_directories(include) -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 (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.chai include/chaiscript/language/chaiscript_prelude_docs.hpp include/chaiscript/utility/utility.hpp) set_source_files_properties(${Chai_INCLUDES} PROPERTIES HEADER_FILE_ONLY TRUE) diff --git a/include/chaiscript/language/chaiscript_engine.hpp b/include/chaiscript/language/chaiscript_engine.hpp index 497aeb3..c3c43e4 100644 --- a/include/chaiscript/language/chaiscript_engine.hpp +++ b/include/chaiscript/language/chaiscript_engine.hpp @@ -28,7 +28,7 @@ #endif -#include "chaiscript_prelude.hpp" +#include "chaiscript_prelude.chai" #include "chaiscript_parser.hpp" #include "../dispatchkit/exception_specification.hpp" @@ -351,7 +351,7 @@ namespace chaiscript m_engine.add(fun(&ChaiScript::internal_eval, this), "eval"); m_engine.add(fun(&ChaiScript::internal_eval_ast, this), "eval"); - do_eval(chaiscript_prelude, "standard prelude"); + do_eval(ChaiScript_Prelude::chaiscript_prelude, "standard prelude"); } /** diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index a113860..3172672 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -12,7 +12,6 @@ #include #include -#include "chaiscript_prelude.hpp" #include "chaiscript_common.hpp" namespace chaiscript diff --git a/include/chaiscript/language/chaiscript_prelude.chai b/include/chaiscript/language/chaiscript_prelude.chai new file mode 100644 index 0000000..29d9b2f --- /dev/null +++ b/include/chaiscript/language/chaiscript_prelude.chai @@ -0,0 +1,530 @@ +// This file is distributed under the BSD License. +// See "license.txt" for details. +// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) +// and Jason Turner (jason@emptycrate.com) +// http://www.chaiscript.com + +#ifndef CHAISCRIPT_PRELUDE_HPP_ +#define CHAISCRIPT_PRELUDE_HPP_ + +namespace chaiscript { +struct ChaiScript_Prelude { + constexpr static const char *chaiscript_prelude=R""( + +def lt(l, r) { + if (call_exists(`<`, l, r)) { + l < r + } else { + type_name(l) < type_name(r) + } +} + + +def gt(l, r) { + if (call_exists(`>`, l, r)) { + l > r + } else { + type_name(l) > type_name(r) + } +} + +def eq(l, r) { + if (call_exists(`==`, l, r)) { + l == r + } else { + false + } +} + +def new(x) { + eval(type_name(x))(); +} + +def clone(x) : function_exists(type_name(x)) && call_exists(eval(type_name(x)), x) +{ + eval(type_name(x))(x); +} + + +# to_string for Pair() +def to_string(x) : call_exists(first, x) && call_exists(second, x) { + "<" + x.first.to_string() + ", " + x.second.to_string() + ">"; +} + +# to_string for containers +def to_string(x) : call_exists(range, x) && !x.is_type("string"){ + "[" + x.join(", ") + "]"; +} + +# Basic to_string function +def to_string(x) { + internal_to_string(x); +} + +# Prints to console with no carriage return +def puts(x) { + print_string(x.to_string()); +} + +# Prints to console with carriage return +def print(x) { + println_string(x.to_string()); +} + +# Returns the maximum value of two numbers +def max(a, b) { + if (a>b) { + a + } else { + b + } +} + +# Returns the minimum value of two numbers +def min(a, b) +{ + if (a 0) && (!r.empty())) { + inserter(r.front()); + r.pop_front(); + --i; + } +} + + +# Returns a new container with the given number of elements taken from the container +def take(container, num) { + auto retval = new(container); + take(container, num, back_inserter(retval)); + retval; +} + + +def take_while(container, f, inserter) : call_exists(range, container) { + auto r = range(container); + while ((!r.empty()) && f(r.front())) { + inserter(r.front()); + r.pop_front(); + } +} + + +# Returns a new container with the given elements match the second value function +def take_while(container, f) { + auto retval = new(container); + take_while(container, f, back_inserter(retval)); + retval; +} + + +def drop(container, num, inserter) : call_exists(range, container) { + auto r = range(container); + auto i = num; + while ((i > 0) && (!r.empty())) { + r.pop_front(); + --i; + } + while (!r.empty()) { + inserter(r.front()); + r.pop_front(); + } +} + + +# Returns a new container with the given number of elements dropped from the given container +def drop(container, num) { + auto retval = new(container); + drop(container, num, back_inserter(retval)); + retval; +} + + +def drop_while(container, f, inserter) : call_exists(range, container) { + auto r = range(container); + while ((!r.empty())&& f(r.front())) { + r.pop_front(); + } + while (!r.empty()) { + inserter(r.front()); + r.pop_front(); + } +} + + +# Returns a new container with the given elements dropped that match the second value function +def drop_while(container, f) { + auto retval = new(container); + drop_while(container, f, back_inserter(retval)); + retval; +} + + +# Applies the second value function to the container. Starts with the first two elements. Expects at least 2 elements. +def reduce(container, func) : container.size() >= 2 && call_exists(range, container) { + auto r = range(container); + auto retval = r.front(); + r.pop_front(); + retval = func(retval, r.front()); + r.pop_front(); + while (!r.empty()) { + retval = func(retval, r.front()); + r.pop_front(); + } + retval; +} + + +# Returns a string of the elements in container delimited by the second value string +def join(container, delim) { + auto retval = ""; + auto range = range(container); + if (!range.empty()) { + retval += to_string(range.front()); + range.pop_front(); + while (!range.empty()) { + retval += delim; + retval += to_string(range.front()); + range.pop_front(); + } + } + retval; +} + + +def filter(container, f, inserter) : call_exists(range, container) { + auto r = range(container); + while (!r.empty()) { + if (f(r.front())) { + inserter(r.front()); + } + r.pop_front(); + } +} + + +# Returns a new Vector which match the second value function +def filter(container, f) { + auto retval = new(container); + filter(container, f, back_inserter(retval)); + retval; +} + + +def generate_range(x, y, inserter) { + auto i = x; + while (i <= y) { + inserter(i); + ++i; + } +} + + +# Returns a new Vector which represents the range from the first value to the second value +def generate_range(x, y) { + auto retval = Vector(); + generate_range(x,y,back_inserter(retval)); + retval; +} + + +# Returns a new Vector with the first value to the second value as its elements +def collate(x, y) { + return [x, y]; +} + + +def zip_with(f, x, y, inserter) : call_exists(range, x) && call_exists(range, y) { + auto r_x = range(x); + auto r_y = range(y); + while (!r_x.empty() && !r_y.empty()) { + inserter(f(r_x.front(), r_y.front())); + r_x.pop_front(); + r_y.pop_front(); + } +} + + +# Returns a new Vector which joins matching elements of the second and third value with the first value function +def zip_with(f, x, y) { + auto retval = Vector(); + zip_with(f,x,y,back_inserter(retval)); + retval; +} + + +# Returns a new Vector which joins matching elements of the first and second +def zip(x, y) { + zip_with(collate, x, y); +} + + +# Returns the position of the second value string in the first value string +def string::find(substr) : is_type(substr, "string") { + int(find(this, substr, 0)); +} + + +# Returns the position of last match of the second value string in the first value string +def string::rfind(substr) : is_type(substr, "string") { + int(rfind(this, substr, -1)); +} + + +# Returns the position of the first match of elements in the second value string in the first value string +def string::find_first_of(list) : is_type(list, "string") { + int(find_first_of(this, list, 0)); +} + + +# Returns the position of the last match of elements in the second value string in the first value string +def string::find_last_of(list) : is_type(list, "string") { + int(find_last_of(this, list, -1)); +} + + +# Returns the position of the first non-matching element in the second value string in the first value string +def string::find_first_not_of(list) : is_type(list, "string") { + int(find_first_not_of(this, list, 0)); +} + + +# Returns the position of the last non-matching element in the second value string in the first value string +def string::find_last_not_of(list) : is_type(list, "string") { + int(find_last_not_of(this, list, -1)); +} + + +def string::ltrim() { + drop_while(this, fun(x) { x == ' ' || x == '\t' || x == '\r' || x == '\n'}); +} + + +def string::rtrim() { + reverse(drop_while(reverse(this), fun(x) { x == ' ' || x == '\t' || x == '\r' || x == '\n'})); +} + + +def string::trim() { + ltrim(rtrim(this)); +} + + +def find(container, value, compare_func) : call_exists(range, container) && is_type(compare_func, "Function") { + auto range = range(container); + while (!range.empty()) { + if (compare_func(range.front(), value)) { + return range; + } else { + range.pop_front(); + } + } + return range; +} + + +def find(container, value) { + return find(container, value, eq) +} + + +)""; + +}; +} + +#endif /* CHAISCRIPT_PRELUDE_HPP_ */ diff --git a/include/chaiscript/language/chaiscript_prelude.hpp b/include/chaiscript/language/chaiscript_prelude.hpp deleted file mode 100644 index cee93d0..0000000 --- a/include/chaiscript/language/chaiscript_prelude.hpp +++ /dev/null @@ -1,329 +0,0 @@ -// This file is distributed under the BSD License. -// See "license.txt" for details. -// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) -// and Jason Turner (jason@emptycrate.com) -// http://www.chaiscript.com - -#ifndef CHAISCRIPT_PRELUDE_HPP_ -#define CHAISCRIPT_PRELUDE_HPP_ - -//Note, the expression "[x,y]" in "collate" is parsed as two separate expressions -//by C++, so CODE_STRING, takes two expressions and adds in the missing comma -#define CODE_STRING(x, y) #x ", " #y - -#define chaiscript_prelude CODE_STRING(\ -def lt(l, r) { if (call_exists(`<`, l, r)) { l < r } else { type_name(l) < type_name(r) } } \n\ -def gt(l, r) { if (call_exists(`>`, l, r)) { l > r } else { type_name(l) > type_name(r) } } \n\ -def eq(l, r) { if (call_exists(`==`, l, r)) { l == r } else { false } } \n\ -def new(x) { eval(type_name(x))(); } \n\ -def clone(x) : function_exists(type_name(x)) && call_exists(eval(type_name(x)), x) { eval(type_name(x))(x); } \n\ -# to_string for Pair()\n\ -def to_string(x) : call_exists(first, x) && call_exists(second, x) { \n\ - "<" + x.first.to_string() + ", " + x.second.to_string() + ">"; \n\ -}\n\ -# to_string for containers\n\ -def to_string(x) : call_exists(range, x) && !x.is_type("string"){ \n\ - "[" + x.join(", ") + "]"; \n\ -}\n\ -# Basic to_string function\n\ -def to_string(x) { \n\ - internal_to_string(x); \n\ -}\n\ -# Prints to console with no carriage return\n\ -def puts(x) { \n\ - print_string(x.to_string()); \n\ -} \n\ -# Prints to console with carriage return\n\ -def print(x) { \n\ - println_string(x.to_string()); \n\ -} \n\ -# Returns the maximum value of two numbers\n\ -def max(a, b) { if (a>b) { a } else { b } } \n\ -# Returns the minimum value of two numbers\n\ -def min(a, b) { if (a 0) && (!r.empty())) { \n\ - inserter(r.front()); \n\ - r.pop_front(); \n\ - --i; \n\ - } \n\ -} \n\ -# Returns a new container with the given number of elements taken from the container\n\ -def take(container, num) {\n\ - auto retval = new(container); \n\ - take(container, num, back_inserter(retval)); \n\ - retval; \n\ -}\n\ -def take_while(container, f, inserter) : call_exists(range, container) { \n\ - auto r = range(container); \n\ - while ((!r.empty()) && f(r.front())) { \n\ - inserter(r.front()); \n\ - r.pop_front(); \n\ - } \n\ -} \n\ -# Returns a new container with the given elements match the second value function\n\ -def take_while(container, f) {\n\ - auto retval = new(container); \n\ - take_while(container, f, back_inserter(retval)); \n\ - retval;\n\ -}\n\ -def drop(container, num, inserter) : call_exists(range, container) { \n\ - auto r = range(container); \n\ - auto i = num; \n\ - while ((i > 0) && (!r.empty())) { \n\ - r.pop_front(); \n\ - --i; \n\ - } \n\ - while (!r.empty()) { \n\ - inserter(r.front()); \n\ - r.pop_front(); \n\ - } \n\ -} \n\ -# Returns a new container with the given number of elements dropped from the given container \n\ -def drop(container, num) {\n\ - auto retval = new(container); \n\ - drop(container, num, back_inserter(retval)); \n\ - retval; \n\ -}\n\ -def drop_while(container, f, inserter) : call_exists(range, container) { \n\ - auto r = range(container); \n\ - while ((!r.empty())&& f(r.front())) { \n\ - r.pop_front(); \n\ - } \n\ - while (!r.empty()) { \n\ - inserter(r.front()); \n\ - r.pop_front(); \n\ - } \n\ -} \n\ -# Returns a new container with the given elements dropped that match the second value function\n\ -def drop_while(container, f) {\n\ - auto retval = new(container); \n\ - drop_while(container, f, back_inserter(retval)); \n\ - retval; \n\ -}\n\ -# Applies the second value function to the container. Starts with the first two elements. Expects at least 2 elements.\n\ -def reduce(container, func) : container.size() >= 2 && call_exists(range, container) { \n\ - auto r = range(container); \n\ - auto retval = r.front(); \n\ - r.pop_front(); \n\ - retval = func(retval, r.front()); \n\ - r.pop_front(); \n\ - while (!r.empty()) { \n\ - retval = func(retval, r.front()); \n\ - r.pop_front(); \n\ - } \n\ - retval; \n\ -} \n\ -# Returns a string of the elements in container delimited by the second value string\n\ -def join(container, delim) { \n\ - auto retval = ""; \n\ - auto range = range(container); \n\ - if (!range.empty()) { \n\ - retval += to_string(range.front()); \n\ - range.pop_front(); \n\ - while (!range.empty()) { \n\ - retval += delim; \n\ - retval += to_string(range.front()); \n\ - range.pop_front(); \n\ - } \n\ - } \n\ - retval; \n\ -} \n\ -def filter(container, f, inserter) : call_exists(range, container) { \n\ - auto r = range(container); \n\ - while (!r.empty()) { \n\ - if (f(r.front())) { \n\ - inserter(r.front()); \n\ - } \n\ - r.pop_front(); \n\ - } \n\ -} \n\ -# Returns a new Vector which match the second value function\n\ -def filter(container, f) { \n\ - auto retval = new(container); \n\ - filter(container, f, back_inserter(retval));\n\ - retval;\n\ -}\n\ -def generate_range(x, y, inserter) { \n\ - auto i = x; \n\ - while (i <= y) { \n\ - inserter(i); \n\ - ++i; \n\ - } \n\ -} \n\ -# Returns a new Vector which represents the range from the first value to the second value\n\ -def generate_range(x, y) { \n\ - auto retval = Vector(); \n\ - generate_range(x,y,back_inserter(retval)); \n\ - retval; \n\ -}\n\ -# Returns a new Vector with the first value to the second value as its elements\n\ -def collate(x, y) { \n\ - return [x, y]; \n\ -} \n\ -def zip_with(f, x, y, inserter) : call_exists(range, x) && call_exists(range, y) { \n\ - auto r_x = range(x); \n\ - auto r_y = range(y); \n\ - while (!r_x.empty() && !r_y.empty()) { \n\ - inserter(f(r_x.front(), r_y.front())); \n\ - r_x.pop_front(); \n\ - r_y.pop_front(); \n\ - } \n\ -} \n\ -# Returns a new Vector which joins matching elements of the second and third value with the first value function\n\ -def zip_with(f, x, y) { \n\ - auto retval = Vector(); \n\ - zip_with(f,x,y,back_inserter(retval)); \n\ - retval;\n\ -}\n\ -# Returns a new Vector which joins matching elements of the first and second\n\ -def zip(x, y) { \n\ - zip_with(collate, x, y); \n\ -}\n\ -# Returns the position of the second value string in the first value string\n\ -def string::find(substr) : is_type(substr, "string") { \n\ - int(find(this, substr, 0)); \n\ -} \n\ -# Returns the position of last match of the second value string in the first value string\n\ -def string::rfind(substr) : is_type(substr, "string") { \n\ - int(rfind(this, substr, -1)); \n\ -} \n\ -# Returns the position of the first match of elements in the second value string in the first value string\n\ -def string::find_first_of(list) : is_type(list, "string") { \n\ - int(find_first_of(this, list, 0)); \n\ -} \n\ -# Returns the position of the last match of elements in the second value string in the first value string\n\ -def string::find_last_of(list) : is_type(list, "string") { \n\ - int(find_last_of(this, list, -1)); \n\ -} \n\ -# Returns the position of the first non-matching element in the second value string in the first value string\n\ -def string::find_first_not_of(list) : is_type(list, "string") { \n\ - int(find_first_not_of(this, list, 0)); \n\ -} \n\ -# Returns the position of the last non-matching element in the second value string in the first value string\n\ -def string::find_last_not_of(list) : is_type(list, "string") { \n\ - int(find_last_not_of(this, list, -1)); \n\ -} \n\ -def string::ltrim() { \n\ - drop_while(this, fun(x) { x == ' ' || x == '\t' || x == '\r' || x == '\n'}); \n\ -} \n\ -def string::rtrim() { \n\ - reverse(drop_while(reverse(this), fun(x) { x == ' ' || x == '\t' || x == '\r' || x == '\n'})); \n\ -} \n\ -def string::trim() { \n\ - ltrim(rtrim(this)); \n\ -} \n\ -def find(container, value, compare_func) : call_exists(range, container) && is_type(compare_func, "Function") { \n\ - auto range = range(container); \n\ - while (!range.empty()) { \n\ - if (compare_func(range.front(), value)) { \n\ - return range; \n\ - } else { \n\ - range.pop_front(); \n\ - } \n\ - } \n\ - return range; \n\ -} \n\ -def find(container, value) { return find(container, value, eq) } \ -) -#endif /* CHAISCRIPT_PRELUDE_HPP_ */