mirror of
https://github.com/ChaiScript/ChaiScript.git
synced 2025-12-06 16:57:04 +08:00
Move away from shared_ptr for parse nodes
This commit is contained in:
parent
700a620552
commit
5a5600914c
@ -93,6 +93,16 @@ namespace chaiscript {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename B, typename D, typename ...Arg>
|
||||||
|
inline std::unique_ptr<B> make_unique(Arg && ... arg)
|
||||||
|
{
|
||||||
|
#ifdef CHAISCRIPT_USE_STD_MAKE_SHARED
|
||||||
|
return std::make_unique<D>(std::forward<Arg>(arg)...);
|
||||||
|
#else
|
||||||
|
return std::unique_ptr<B>(static_cast<B*>(new D(std::forward<Arg>(arg)...)));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
struct Build_Info {
|
struct Build_Info {
|
||||||
static int version_major()
|
static int version_major()
|
||||||
{
|
{
|
||||||
|
|||||||
@ -305,13 +305,13 @@ namespace chaiscript
|
|||||||
static bool has_parse_tree(const chaiscript::Const_Proxy_Function &t_pf)
|
static bool has_parse_tree(const chaiscript::Const_Proxy_Function &t_pf)
|
||||||
{
|
{
|
||||||
const auto pf = std::dynamic_pointer_cast<const chaiscript::dispatch::Dynamic_Proxy_Function>(t_pf);
|
const auto pf = std::dynamic_pointer_cast<const chaiscript::dispatch::Dynamic_Proxy_Function>(t_pf);
|
||||||
return pf && pf->get_parse_tree();
|
return bool(pf);
|
||||||
}
|
}
|
||||||
|
|
||||||
static chaiscript::AST_NodePtr get_parse_tree(const chaiscript::Const_Proxy_Function &t_pf)
|
static const chaiscript::AST_Node &get_parse_tree(const chaiscript::Const_Proxy_Function &t_pf)
|
||||||
{
|
{
|
||||||
const auto pf = std::dynamic_pointer_cast<const chaiscript::dispatch::Dynamic_Proxy_Function>(t_pf);
|
const auto pf = std::dynamic_pointer_cast<const chaiscript::dispatch::Dynamic_Proxy_Function>(t_pf);
|
||||||
if (pf && pf->get_parse_tree())
|
if (pf)
|
||||||
{
|
{
|
||||||
return pf->get_parse_tree();
|
return pf->get_parse_tree();
|
||||||
} else {
|
} else {
|
||||||
@ -545,7 +545,7 @@ namespace chaiscript
|
|||||||
std::vector<Boxed_Value> retval;
|
std::vector<Boxed_Value> retval;
|
||||||
std::transform(t_eval_error.call_stack.begin(), t_eval_error.call_stack.end(),
|
std::transform(t_eval_error.call_stack.begin(), t_eval_error.call_stack.end(),
|
||||||
std::back_inserter(retval),
|
std::back_inserter(retval),
|
||||||
&chaiscript::var<const std::shared_ptr<const chaiscript::AST_Node> &>);
|
&chaiscript::var<const chaiscript::AST_Node_Trace &>);
|
||||||
return retval;
|
return retval;
|
||||||
}), "call_stack"} }
|
}), "call_stack"} }
|
||||||
);
|
);
|
||||||
@ -574,7 +574,7 @@ namespace chaiscript
|
|||||||
const auto children = t_node.get_children();
|
const auto children = t_node.get_children();
|
||||||
std::transform(children.begin(), children.end(),
|
std::transform(children.begin(), children.end(),
|
||||||
std::back_inserter(retval),
|
std::back_inserter(retval),
|
||||||
&chaiscript::var<const std::shared_ptr<chaiscript::AST_Node> &>);
|
&chaiscript::var<const std::reference_wrapper<chaiscript::AST_Node> &>);
|
||||||
return retval;
|
return retval;
|
||||||
}), "children"}
|
}), "children"}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -41,7 +41,7 @@ namespace chaiscript
|
|||||||
class Boxed_Number;
|
class Boxed_Number;
|
||||||
struct AST_Node;
|
struct AST_Node;
|
||||||
|
|
||||||
typedef std::shared_ptr<AST_Node> AST_NodePtr;
|
typedef std::unique_ptr<AST_Node> AST_NodePtr;
|
||||||
|
|
||||||
namespace dispatch
|
namespace dispatch
|
||||||
{
|
{
|
||||||
@ -346,8 +346,8 @@ namespace chaiscript
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Dynamic_Proxy_Function(
|
Dynamic_Proxy_Function(
|
||||||
int t_arity=-1,
|
const int t_arity,
|
||||||
AST_NodePtr t_parsenode = AST_NodePtr(),
|
std::shared_ptr<AST_Node> t_parsenode,
|
||||||
Param_Types t_param_types = Param_Types(),
|
Param_Types t_param_types = Param_Types(),
|
||||||
Proxy_Function t_guard = Proxy_Function())
|
Proxy_Function t_guard = Proxy_Function())
|
||||||
: Proxy_Function_Base(build_param_type_list(t_param_types), t_arity),
|
: Proxy_Function_Base(build_param_type_list(t_param_types), t_arity),
|
||||||
@ -379,9 +379,9 @@ namespace chaiscript
|
|||||||
return m_guard;
|
return m_guard;
|
||||||
}
|
}
|
||||||
|
|
||||||
AST_NodePtr get_parse_tree() const
|
const AST_Node &get_parse_tree() const
|
||||||
{
|
{
|
||||||
return m_parsenode;
|
return *m_parsenode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -445,7 +445,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
Proxy_Function m_guard;
|
Proxy_Function m_guard;
|
||||||
AST_NodePtr m_parsenode;
|
std::shared_ptr<AST_Node> m_parsenode;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -457,7 +457,7 @@ namespace chaiscript
|
|||||||
Dynamic_Proxy_Function_Impl(
|
Dynamic_Proxy_Function_Impl(
|
||||||
Callable t_f,
|
Callable t_f,
|
||||||
int t_arity=-1,
|
int t_arity=-1,
|
||||||
AST_NodePtr t_parsenode = AST_NodePtr(),
|
std::shared_ptr<AST_Node> t_parsenode = AST_NodePtr(),
|
||||||
Param_Types t_param_types = Param_Types(),
|
Param_Types t_param_types = Param_Types(),
|
||||||
Proxy_Function t_guard = Proxy_Function())
|
Proxy_Function t_guard = Proxy_Function())
|
||||||
: Dynamic_Proxy_Function(
|
: Dynamic_Proxy_Function(
|
||||||
|
|||||||
@ -124,8 +124,10 @@ namespace chaiscript
|
|||||||
|
|
||||||
|
|
||||||
/// \brief Typedef for pointers to AST_Node objects. Used in building of the AST_Node tree
|
/// \brief Typedef for pointers to AST_Node objects. Used in building of the AST_Node tree
|
||||||
typedef std::shared_ptr<AST_Node> AST_NodePtr;
|
typedef std::unique_ptr<AST_Node> AST_NodePtr;
|
||||||
typedef std::shared_ptr<const AST_Node> AST_NodePtr_Const;
|
typedef std::unique_ptr<const AST_Node> AST_NodePtr_Const;
|
||||||
|
|
||||||
|
struct AST_Node_Trace;
|
||||||
|
|
||||||
|
|
||||||
/// \brief Classes which may be thrown during error cases when ChaiScript is executing.
|
/// \brief Classes which may be thrown during error cases when ChaiScript is executing.
|
||||||
@ -168,7 +170,7 @@ namespace chaiscript
|
|||||||
File_Position start_position;
|
File_Position start_position;
|
||||||
std::string filename;
|
std::string filename;
|
||||||
std::string detail;
|
std::string detail;
|
||||||
std::vector<AST_NodePtr_Const> call_stack;
|
std::vector<AST_Node_Trace> call_stack;
|
||||||
|
|
||||||
eval_error(const std::string &t_why, const File_Position &t_where, const std::string &t_fname,
|
eval_error(const std::string &t_why, const File_Position &t_where, const std::string &t_fname,
|
||||||
const std::vector<Boxed_Value> &t_parameters, const std::vector<chaiscript::Const_Proxy_Function> &t_functions,
|
const std::vector<Boxed_Value> &t_parameters, const std::vector<chaiscript::Const_Proxy_Function> &t_functions,
|
||||||
@ -228,26 +230,26 @@ namespace chaiscript
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
static AST_Node_Type id(const T& t)
|
static AST_Node_Type id(const T& t)
|
||||||
{
|
{
|
||||||
return t->identifier;
|
return t.identifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static std::string pretty(const T& t)
|
static std::string pretty(const T& t)
|
||||||
{
|
{
|
||||||
return t->pretty_print();
|
return t.pretty_print();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static const std::string &fname(const T& t)
|
static const std::string &fname(const T& t)
|
||||||
{
|
{
|
||||||
return t->filename();
|
return t.filename();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static std::string startpos(const T& t)
|
static std::string startpos(const T& t)
|
||||||
{
|
{
|
||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
oss << t->start().line << ", " << t->start().column;
|
oss << t.start().line << ", " << t.start().column;
|
||||||
return oss.str();
|
return oss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -330,20 +332,15 @@ namespace chaiscript
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
static std::string format_guard(const T &t)
|
static std::string format_guard(const T &t)
|
||||||
{
|
{
|
||||||
return t->pretty_print();
|
return t.pretty_print();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static std::string format_location(const T &t)
|
static std::string format_location(const T &t)
|
||||||
{
|
{
|
||||||
if (t) {
|
|
||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
oss << "(" << t->filename() << " " << t->start().line << ", " << t->start().column << ")";
|
oss << "(" << t.filename() << " " << t.start().line << ", " << t.start().column << ")";
|
||||||
return oss.str();
|
return oss.str();
|
||||||
} else {
|
|
||||||
return "(internal)";
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string format_detail(const std::vector<chaiscript::Const_Proxy_Function> &t_functions,
|
static std::string format_detail(const std::vector<chaiscript::Const_Proxy_Function> &t_functions,
|
||||||
@ -492,7 +489,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
|
|
||||||
/// \brief Struct that doubles as both a parser ast_node and an AST node.
|
/// \brief Struct that doubles as both a parser ast_node and an AST node.
|
||||||
struct AST_Node : std::enable_shared_from_this<AST_Node> {
|
struct AST_Node {
|
||||||
public:
|
public:
|
||||||
const AST_Node_Type identifier;
|
const AST_Node_Type identifier;
|
||||||
const std::string text;
|
const std::string text;
|
||||||
@ -516,14 +513,14 @@ namespace chaiscript
|
|||||||
|
|
||||||
oss << text;
|
oss << text;
|
||||||
|
|
||||||
for (auto & elem : this->get_children()) {
|
for (auto & elem : get_children()) {
|
||||||
oss << elem->pretty_print() << ' ';
|
oss << elem.get().pretty_print() << ' ';
|
||||||
}
|
}
|
||||||
|
|
||||||
return oss.str();
|
return oss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual std::vector<AST_NodePtr> get_children() const = 0;
|
virtual std::vector<std::reference_wrapper<AST_Node>> get_children() const = 0;
|
||||||
virtual Boxed_Value eval(const chaiscript::detail::Dispatch_State &t_e) const = 0;
|
virtual Boxed_Value eval(const chaiscript::detail::Dispatch_State &t_e) const = 0;
|
||||||
|
|
||||||
|
|
||||||
@ -534,8 +531,8 @@ namespace chaiscript
|
|||||||
oss << t_prepend << "(" << ast_node_type_to_string(this->identifier) << ") "
|
oss << t_prepend << "(" << ast_node_type_to_string(this->identifier) << ") "
|
||||||
<< this->text << " : " << this->location.start.line << ", " << this->location.start.column << '\n';
|
<< this->text << " : " << this->location.start.line << ", " << this->location.start.column << '\n';
|
||||||
|
|
||||||
for (auto & elem : this->get_children()) {
|
for (auto & elem : get_children()) {
|
||||||
oss << elem->to_string(t_prepend + " ");
|
oss << elem.get().to_string(t_prepend + " ");
|
||||||
}
|
}
|
||||||
return oss.str();
|
return oss.str();
|
||||||
}
|
}
|
||||||
@ -568,12 +565,60 @@ namespace chaiscript
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct AST_Node_Trace
|
||||||
|
{
|
||||||
|
const AST_Node_Type identifier;
|
||||||
|
const std::string text;
|
||||||
|
Parse_Location location;
|
||||||
|
|
||||||
|
const std::string &filename() const {
|
||||||
|
return *location.filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
const File_Position &start() const {
|
||||||
|
return location.start;
|
||||||
|
}
|
||||||
|
|
||||||
|
const File_Position &end() const {
|
||||||
|
return location.end;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string pretty_print() const
|
||||||
|
{
|
||||||
|
std::ostringstream oss;
|
||||||
|
|
||||||
|
oss << text;
|
||||||
|
|
||||||
|
for (const auto & elem : children) {
|
||||||
|
oss << elem.pretty_print() << ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
return oss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<AST_Node_Trace> get_children(const AST_Node &node)
|
||||||
|
{
|
||||||
|
const auto node_children = node.get_children();
|
||||||
|
return std::vector<AST_Node_Trace>(node_children.begin(), node_children.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
AST_Node_Trace(const AST_Node &node)
|
||||||
|
: identifier(node.identifier), text(node.text),
|
||||||
|
location(node.location), children(get_children(node))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::vector<AST_Node_Trace> children;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
namespace parser {
|
namespace parser {
|
||||||
class ChaiScript_Parser_Base
|
class ChaiScript_Parser_Base
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual AST_NodePtr parse(const std::string &t_input, const std::string &t_fname) = 0;
|
virtual AST_NodePtr parse(const std::string &t_input, const std::string &t_fname) = 0;
|
||||||
virtual void debug_print(AST_NodePtr t, std::string prepend = "") const = 0;
|
virtual void debug_print(const AST_Node &t, std::string prepend = "") const = 0;
|
||||||
virtual void *get_tracer_ptr() = 0;
|
virtual void *get_tracer_ptr() = 0;
|
||||||
virtual ~ChaiScript_Parser_Base() = default;
|
virtual ~ChaiScript_Parser_Base() = default;
|
||||||
ChaiScript_Parser_Base() = default;
|
ChaiScript_Parser_Base() = default;
|
||||||
|
|||||||
@ -332,9 +332,9 @@ explicit ChaiScript_Basic(std::unique_ptr<parser::ChaiScript_Parser_Base> &&pars
|
|||||||
|
|
||||||
AST_NodePtr parse(const std::string &t_input, const bool t_debug_print = false)
|
AST_NodePtr parse(const std::string &t_input, const bool t_debug_print = false)
|
||||||
{
|
{
|
||||||
const auto ast = m_parser->parse(t_input, "PARSE");
|
auto ast = m_parser->parse(t_input, "PARSE");
|
||||||
if (t_debug_print) {
|
if (t_debug_print) {
|
||||||
m_parser->debug_print(ast);
|
m_parser->debug_print(*ast);
|
||||||
}
|
}
|
||||||
return ast;
|
return ast;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -47,13 +47,13 @@ namespace chaiscript
|
|||||||
{
|
{
|
||||||
template<typename T> struct AST_Node_Impl;
|
template<typename T> struct AST_Node_Impl;
|
||||||
|
|
||||||
template<typename T> using AST_Node_Impl_Ptr = typename std::shared_ptr<AST_Node_Impl<T>>;
|
template<typename T> using AST_Node_Impl_Ptr = typename std::unique_ptr<AST_Node_Impl<T>>;
|
||||||
|
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
/// Helper function that will set up the scope around a function call, including handling the named function parameters
|
/// Helper function that will set up the scope around a function call, including handling the named function parameters
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static Boxed_Value eval_function(chaiscript::detail::Dispatch_Engine &t_ss, const AST_Node_Impl_Ptr<T> &t_node, const std::vector<std::string> &t_param_names, const std::vector<Boxed_Value> &t_vals, const std::map<std::string, Boxed_Value> *t_locals=nullptr, bool has_this_capture = false) {
|
static Boxed_Value eval_function(chaiscript::detail::Dispatch_Engine &t_ss, const AST_Node_Impl<T> &t_node, const std::vector<std::string> &t_param_names, const std::vector<Boxed_Value> &t_vals, const std::map<std::string, Boxed_Value> *t_locals=nullptr, bool has_this_capture = false) {
|
||||||
chaiscript::detail::Dispatch_State state(t_ss);
|
chaiscript::detail::Dispatch_State state(t_ss);
|
||||||
|
|
||||||
const Boxed_Value *thisobj = [&]() -> const Boxed_Value *{
|
const Boxed_Value *thisobj = [&]() -> const Boxed_Value *{
|
||||||
@ -83,7 +83,7 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return t_node->eval(state);
|
return t_node.eval(state);
|
||||||
} catch (detail::Return_Value &rv) {
|
} catch (detail::Return_Value &rv) {
|
||||||
return std::move(rv.retval);
|
return std::move(rv.retval);
|
||||||
}
|
}
|
||||||
@ -106,8 +106,14 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::vector<AST_NodePtr> get_children() const final {
|
std::vector<std::reference_wrapper<AST_Node>> get_children() const final {
|
||||||
return {children.begin(), children.end()};
|
std::vector<std::reference_wrapper<AST_Node>> retval;
|
||||||
|
retval.reserve(children.size());
|
||||||
|
for (auto &&child : children) {
|
||||||
|
retval.emplace_back(*child);
|
||||||
|
}
|
||||||
|
|
||||||
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
Boxed_Value eval(const chaiscript::detail::Dispatch_State &t_e) const final
|
Boxed_Value eval(const chaiscript::detail::Dispatch_State &t_e) const final
|
||||||
@ -116,7 +122,7 @@ namespace chaiscript
|
|||||||
T::trace(t_e, this);
|
T::trace(t_e, this);
|
||||||
return eval_internal(t_e);
|
return eval_internal(t_e);
|
||||||
} catch (exception::eval_error &ee) {
|
} catch (exception::eval_error &ee) {
|
||||||
ee.call_stack.push_back(shared_from_this());
|
ee.call_stack.push_back(*this);
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -364,44 +370,44 @@ namespace chaiscript
|
|||||||
AST_Node_Impl<T>(std::move(t_ast_node_text), AST_Node_Type::Arg_List, std::move(t_loc), std::move(t_children)) { }
|
AST_Node_Impl<T>(std::move(t_ast_node_text), AST_Node_Type::Arg_List, std::move(t_loc), std::move(t_children)) { }
|
||||||
|
|
||||||
|
|
||||||
static std::string get_arg_name(const AST_Node_Impl_Ptr<T> &t_node) {
|
static std::string get_arg_name(const AST_Node_Impl<T> &t_node) {
|
||||||
if (t_node->children.empty())
|
if (t_node.children.empty())
|
||||||
{
|
{
|
||||||
return t_node->text;
|
return t_node.text;
|
||||||
} else if (t_node->children.size() == 1) {
|
} else if (t_node.children.size() == 1) {
|
||||||
return t_node->children[0]->text;
|
return t_node.children[0]->text;
|
||||||
} else {
|
} else {
|
||||||
return t_node->children[1]->text;
|
return t_node.children[1]->text;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::vector<std::string> get_arg_names(const AST_Node_Impl_Ptr<T> &t_node) {
|
static std::vector<std::string> get_arg_names(const AST_Node_Impl<T> &t_node) {
|
||||||
std::vector<std::string> retval;
|
std::vector<std::string> retval;
|
||||||
|
|
||||||
for (const auto &node : t_node->children)
|
for (const auto &node : t_node.children)
|
||||||
{
|
{
|
||||||
retval.push_back(get_arg_name(node));
|
retval.push_back(get_arg_name(*node));
|
||||||
}
|
}
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::pair<std::string, Type_Info> get_arg_type(const AST_Node_Impl_Ptr<T> &t_node, const chaiscript::detail::Dispatch_State &t_ss)
|
static std::pair<std::string, Type_Info> get_arg_type(const AST_Node_Impl<T> &t_node, const chaiscript::detail::Dispatch_State &t_ss)
|
||||||
{
|
{
|
||||||
if (t_node->children.size() < 2)
|
if (t_node.children.size() < 2)
|
||||||
{
|
{
|
||||||
return {};
|
return {};
|
||||||
} else {
|
} else {
|
||||||
return {t_node->children[0]->text, t_ss->get_type(t_node->children[0]->text, false)};
|
return {t_node.children[0]->text, t_ss->get_type(t_node.children[0]->text, false)};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static dispatch::Param_Types get_arg_types(const AST_Node_Impl_Ptr<T> &t_node, const chaiscript::detail::Dispatch_State &t_ss) {
|
static dispatch::Param_Types get_arg_types(const AST_Node_Impl<T> &t_node, const chaiscript::detail::Dispatch_State &t_ss) {
|
||||||
std::vector<std::pair<std::string, Type_Info>> retval;
|
std::vector<std::pair<std::string, Type_Info>> retval;
|
||||||
|
|
||||||
for (const auto &child : t_node->children)
|
for (const auto &child : t_node.children)
|
||||||
{
|
{
|
||||||
retval.push_back(get_arg_type(child, t_ss));
|
retval.push_back(get_arg_type(*child, t_ss));
|
||||||
}
|
}
|
||||||
|
|
||||||
return dispatch::Param_Types(std::move(retval));
|
return dispatch::Param_Types(std::move(retval));
|
||||||
@ -621,9 +627,15 @@ namespace chaiscript
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
struct Lambda_AST_Node final : AST_Node_Impl<T> {
|
struct Lambda_AST_Node final : AST_Node_Impl<T> {
|
||||||
Lambda_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_Node_Impl_Ptr<T>> t_children) :
|
Lambda_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_Node_Impl_Ptr<T>> t_children) :
|
||||||
AST_Node_Impl<T>(t_ast_node_text, AST_Node_Type::Lambda, std::move(t_loc), std::move(t_children)),
|
AST_Node_Impl<T>(t_ast_node_text,
|
||||||
m_param_names(Arg_List_AST_Node<T>::get_arg_names(this->children[1])),
|
AST_Node_Type::Lambda,
|
||||||
m_this_capture(has_this_capture(this->children[0]->children))
|
std::move(t_loc),
|
||||||
|
std::vector<AST_Node_Impl_Ptr<T>>(std::make_move_iterator(t_children.begin()),
|
||||||
|
std::make_move_iterator(std::prev(t_children.end())))
|
||||||
|
),
|
||||||
|
m_param_names(Arg_List_AST_Node<T>::get_arg_names(*this->children[1])),
|
||||||
|
m_this_capture(has_this_capture(this->children[0]->children)),
|
||||||
|
m_lambda_node(std::move(t_children.back()))
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override {
|
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override {
|
||||||
@ -637,18 +649,18 @@ namespace chaiscript
|
|||||||
}();
|
}();
|
||||||
|
|
||||||
const auto numparams = this->children[1]->children.size();
|
const auto numparams = this->children[1]->children.size();
|
||||||
const auto param_types = Arg_List_AST_Node<T>::get_arg_types(this->children[1], t_ss);
|
const auto param_types = Arg_List_AST_Node<T>::get_arg_types(*this->children[1], t_ss);
|
||||||
|
|
||||||
const auto &lambda_node = this->children.back();
|
|
||||||
std::reference_wrapper<chaiscript::detail::Dispatch_Engine> engine(*t_ss);
|
std::reference_wrapper<chaiscript::detail::Dispatch_Engine> engine(*t_ss);
|
||||||
|
|
||||||
return Boxed_Value(
|
return Boxed_Value(
|
||||||
dispatch::make_dynamic_proxy_function(
|
dispatch::make_dynamic_proxy_function(
|
||||||
[engine, lambda_node, param_names = this->m_param_names, captures, this_capture = this->m_this_capture](const std::vector<Boxed_Value> &t_params)
|
[engine, lambda_node = this->m_lambda_node, param_names = this->m_param_names, captures,
|
||||||
|
this_capture = this->m_this_capture] (const std::vector<Boxed_Value> &t_params)
|
||||||
{
|
{
|
||||||
return detail::eval_function(engine, lambda_node, param_names, t_params, &captures, this_capture);
|
return detail::eval_function(engine, *lambda_node, param_names, t_params, &captures, this_capture);
|
||||||
},
|
},
|
||||||
static_cast<int>(numparams), lambda_node, param_types
|
static_cast<int>(numparams), m_lambda_node, param_types
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -664,7 +676,7 @@ namespace chaiscript
|
|||||||
private:
|
private:
|
||||||
const std::vector<std::string> m_param_names;
|
const std::vector<std::string> m_param_names;
|
||||||
const bool m_this_capture = false;
|
const bool m_this_capture = false;
|
||||||
|
const std::shared_ptr<AST_Node_Impl<T>> m_lambda_node;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
@ -699,55 +711,81 @@ namespace chaiscript
|
|||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct Def_AST_Node final : AST_Node_Impl<T> {
|
struct Def_AST_Node final : AST_Node_Impl<T> {
|
||||||
|
|
||||||
|
std::shared_ptr<AST_Node_Impl<T>> m_body_node;
|
||||||
|
std::shared_ptr<AST_Node_Impl<T>> m_guard_node;
|
||||||
|
|
||||||
Def_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_Node_Impl_Ptr<T>> t_children) :
|
Def_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_Node_Impl_Ptr<T>> t_children) :
|
||||||
AST_Node_Impl<T>(std::move(t_ast_node_text), AST_Node_Type::Def, std::move(t_loc), std::move(t_children)) { }
|
AST_Node_Impl<T>(std::move(t_ast_node_text), AST_Node_Type::Def, std::move(t_loc),
|
||||||
|
std::vector<AST_Node_Impl_Ptr<T>>(std::make_move_iterator(t_children.begin()),
|
||||||
|
std::make_move_iterator(std::prev(t_children.end(), has_guard(t_children)?2:1)))
|
||||||
|
),
|
||||||
|
m_body_node(get_body_node(std::move(t_children))),
|
||||||
|
m_guard_node(get_guard_node(std::move(t_children), t_children.size()-this->children.size()==2))
|
||||||
|
|
||||||
|
{ }
|
||||||
|
|
||||||
|
static std::shared_ptr<AST_Node_Impl<T>> get_guard_node(std::vector<AST_Node_Impl_Ptr<T>> &&vec, bool has_guard)
|
||||||
|
{
|
||||||
|
if (has_guard) {
|
||||||
|
return std::move(*std::prev(vec.end(), 2));
|
||||||
|
} else {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::shared_ptr<AST_Node_Impl<T>> get_body_node(std::vector<AST_Node_Impl_Ptr<T>> &&vec)
|
||||||
|
{
|
||||||
|
return std::move(vec.back());
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool has_guard(const std::vector<AST_Node_Impl_Ptr<T>> &t_children)
|
||||||
|
{
|
||||||
|
if ((t_children.size() > 2) && (t_children[1]->identifier == AST_Node_Type::Arg_List)) {
|
||||||
|
if (t_children.size() > 3) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (t_children.size() > 2) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{
|
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{
|
||||||
std::vector<std::string> t_param_names;
|
std::vector<std::string> t_param_names;
|
||||||
size_t numparams = 0;
|
size_t numparams = 0;
|
||||||
AST_Node_Impl_Ptr<T> guardnode;
|
|
||||||
|
|
||||||
dispatch::Param_Types param_types;
|
dispatch::Param_Types param_types;
|
||||||
|
|
||||||
if ((this->children.size() > 2) && (this->children[1]->identifier == AST_Node_Type::Arg_List)) {
|
if ((this->children.size() > 1) && (this->children[1]->identifier == AST_Node_Type::Arg_List)) {
|
||||||
numparams = this->children[1]->children.size();
|
numparams = this->children[1]->children.size();
|
||||||
t_param_names = Arg_List_AST_Node<T>::get_arg_names(this->children[1]);
|
t_param_names = Arg_List_AST_Node<T>::get_arg_names(*this->children[1]);
|
||||||
param_types = Arg_List_AST_Node<T>::get_arg_types(this->children[1], t_ss);
|
param_types = Arg_List_AST_Node<T>::get_arg_types(*this->children[1], t_ss);
|
||||||
|
|
||||||
if (this->children.size() > 3) {
|
|
||||||
guardnode = this->children[2];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
//no parameters
|
|
||||||
numparams = 0;
|
|
||||||
|
|
||||||
if (this->children.size() > 2) {
|
|
||||||
guardnode = this->children[1];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::reference_wrapper<chaiscript::detail::Dispatch_Engine> engine(*t_ss);
|
std::reference_wrapper<chaiscript::detail::Dispatch_Engine> engine(*t_ss);
|
||||||
std::shared_ptr<dispatch::Proxy_Function_Base> guard;
|
std::shared_ptr<dispatch::Proxy_Function_Base> guard;
|
||||||
if (guardnode) {
|
if (m_guard_node) {
|
||||||
guard = dispatch::make_dynamic_proxy_function(
|
guard = dispatch::make_dynamic_proxy_function(
|
||||||
[engine, guardnode, t_param_names](const std::vector<Boxed_Value> &t_params)
|
[engine, guardnode = m_guard_node, t_param_names](const std::vector<Boxed_Value> &t_params)
|
||||||
{
|
{
|
||||||
return detail::eval_function(engine, guardnode, t_param_names, t_params);
|
return detail::eval_function(engine, *guardnode, t_param_names, t_params);
|
||||||
},
|
},
|
||||||
static_cast<int>(numparams), guardnode);
|
static_cast<int>(numparams), m_guard_node);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const std::string & l_function_name = this->children[0]->text;
|
const std::string & l_function_name = this->children[0]->text;
|
||||||
const auto & func_node = this->children.back();
|
|
||||||
t_ss->add(
|
t_ss->add(
|
||||||
dispatch::make_dynamic_proxy_function(
|
dispatch::make_dynamic_proxy_function(
|
||||||
[engine, guardnode, func_node, t_param_names](const std::vector<Boxed_Value> &t_params)
|
[engine, func_node = m_body_node, t_param_names](const std::vector<Boxed_Value> &t_params)
|
||||||
{
|
{
|
||||||
return detail::eval_function(engine, func_node, t_param_names, t_params);
|
return detail::eval_function(engine, *func_node, t_param_names, t_params);
|
||||||
},
|
},
|
||||||
static_cast<int>(numparams), this->children.back(),
|
static_cast<int>(numparams), m_body_node,
|
||||||
param_types, guard), l_function_name);
|
param_types, guard), l_function_name);
|
||||||
} catch (const exception::name_conflict_error &e) {
|
} catch (const exception::name_conflict_error &e) {
|
||||||
throw exception::eval_error("Function redefined '" + e.name() + "'");
|
throw exception::eval_error("Function redefined '" + e.name() + "'");
|
||||||
@ -1230,32 +1268,32 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
for (size_t i = 1; i < end_point; ++i) {
|
for (size_t i = 1; i < end_point; ++i) {
|
||||||
chaiscript::eval::detail::Scope_Push_Pop catch_scope(t_ss);
|
chaiscript::eval::detail::Scope_Push_Pop catch_scope(t_ss);
|
||||||
AST_Node_Impl_Ptr<T> catch_block = this->children[i];
|
auto &catch_block = *this->children[i];
|
||||||
|
|
||||||
if (catch_block->children.size() == 1) {
|
if (catch_block.children.size() == 1) {
|
||||||
//No variable capture, no guards
|
//No variable capture, no guards
|
||||||
retval = catch_block->children[0]->eval(t_ss);
|
retval = catch_block.children[0]->eval(t_ss);
|
||||||
break;
|
break;
|
||||||
} else if (catch_block->children.size() == 2 || catch_block->children.size() == 3) {
|
} else if (catch_block.children.size() == 2 || catch_block.children.size() == 3) {
|
||||||
const auto name = Arg_List_AST_Node<T>::get_arg_name(catch_block->children[0]);
|
const auto name = Arg_List_AST_Node<T>::get_arg_name(*catch_block.children[0]);
|
||||||
|
|
||||||
if (dispatch::Param_Types(
|
if (dispatch::Param_Types(
|
||||||
std::vector<std::pair<std::string, Type_Info>>{Arg_List_AST_Node<T>::get_arg_type(catch_block->children[0], t_ss)}
|
std::vector<std::pair<std::string, Type_Info>>{Arg_List_AST_Node<T>::get_arg_type(*catch_block.children[0], t_ss)}
|
||||||
).match(std::vector<Boxed_Value>{t_except}, t_ss.conversions()).first)
|
).match(std::vector<Boxed_Value>{t_except}, t_ss.conversions()).first)
|
||||||
{
|
{
|
||||||
t_ss.add_object(name, t_except);
|
t_ss.add_object(name, t_except);
|
||||||
|
|
||||||
if (catch_block->children.size() == 2) {
|
if (catch_block.children.size() == 2) {
|
||||||
//Variable capture, no guards
|
//Variable capture, no guards
|
||||||
retval = catch_block->children[1]->eval(t_ss);
|
retval = catch_block.children[1]->eval(t_ss);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if (catch_block->children.size() == 3) {
|
else if (catch_block.children.size() == 3) {
|
||||||
//Variable capture, guards
|
//Variable capture, guards
|
||||||
|
|
||||||
bool guard = false;
|
bool guard = false;
|
||||||
try {
|
try {
|
||||||
guard = boxed_cast<bool>(catch_block->children[1]->eval(t_ss));
|
guard = boxed_cast<bool>(catch_block.children[1]->eval(t_ss));
|
||||||
} catch (const exception::bad_boxed_cast &) {
|
} catch (const exception::bad_boxed_cast &) {
|
||||||
if (this->children.back()->identifier == AST_Node_Type::Finally) {
|
if (this->children.back()->identifier == AST_Node_Type::Finally) {
|
||||||
this->children.back()->children[0]->eval(t_ss);
|
this->children.back()->children[0]->eval(t_ss);
|
||||||
@ -1263,7 +1301,7 @@ namespace chaiscript
|
|||||||
throw exception::eval_error("Guard condition not boolean");
|
throw exception::eval_error("Guard condition not boolean");
|
||||||
}
|
}
|
||||||
if (guard) {
|
if (guard) {
|
||||||
retval = catch_block->children[2]->eval(t_ss);
|
retval = catch_block.children[2]->eval(t_ss);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1335,8 +1373,18 @@ namespace chaiscript
|
|||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct Method_AST_Node final : AST_Node_Impl<T> {
|
struct Method_AST_Node final : AST_Node_Impl<T> {
|
||||||
|
std::shared_ptr<AST_Node_Impl<T>> m_body_node;
|
||||||
|
std::shared_ptr<AST_Node_Impl<T>> m_guard_node;
|
||||||
|
|
||||||
Method_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_Node_Impl_Ptr<T>> t_children) :
|
Method_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_Node_Impl_Ptr<T>> t_children) :
|
||||||
AST_Node_Impl<T>(std::move(t_ast_node_text), AST_Node_Type::Method, std::move(t_loc), std::move(t_children)) { }
|
AST_Node_Impl<T>(std::move(t_ast_node_text), AST_Node_Type::Method, std::move(t_loc),
|
||||||
|
std::vector<AST_Node_Impl_Ptr<T>>(std::make_move_iterator(t_children.begin()),
|
||||||
|
std::make_move_iterator(std::prev(t_children.end(), Def_AST_Node<T>::has_guard(t_children)?2:1)))
|
||||||
|
),
|
||||||
|
m_body_node(Def_AST_Node<T>::get_body_node(std::move(t_children))),
|
||||||
|
m_guard_node(Def_AST_Node<T>::get_guard_node(std::move(t_children), t_children.size()-this->children.size()==2))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{
|
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{
|
||||||
|
|
||||||
@ -1348,39 +1396,27 @@ namespace chaiscript
|
|||||||
std::vector<std::string> t_param_names{"this"};
|
std::vector<std::string> t_param_names{"this"};
|
||||||
dispatch::Param_Types param_types;
|
dispatch::Param_Types param_types;
|
||||||
|
|
||||||
if ((this->children.size() > 3)
|
if ((this->children.size() > 2)
|
||||||
&& (this->children[2]->identifier == AST_Node_Type::Arg_List)) {
|
&& (this->children[2]->identifier == AST_Node_Type::Arg_List)) {
|
||||||
auto args = Arg_List_AST_Node<T>::get_arg_names(this->children[2]);
|
auto args = Arg_List_AST_Node<T>::get_arg_names(*this->children[2]);
|
||||||
t_param_names.insert(t_param_names.end(), args.begin(), args.end());
|
t_param_names.insert(t_param_names.end(), args.begin(), args.end());
|
||||||
param_types = Arg_List_AST_Node<T>::get_arg_types(this->children[2], t_ss);
|
param_types = Arg_List_AST_Node<T>::get_arg_types(*this->children[2], t_ss);
|
||||||
|
|
||||||
if (this->children.size() > 4) {
|
|
||||||
guardnode = this->children[3];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
//no parameters
|
|
||||||
|
|
||||||
if (this->children.size() > 3) {
|
|
||||||
guardnode = this->children[2];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const size_t numparams = t_param_names.size();
|
const size_t numparams = t_param_names.size();
|
||||||
|
|
||||||
std::shared_ptr<dispatch::Proxy_Function_Base> guard;
|
std::shared_ptr<dispatch::Proxy_Function_Base> guard;
|
||||||
std::reference_wrapper<chaiscript::detail::Dispatch_Engine> engine(*t_ss);
|
std::reference_wrapper<chaiscript::detail::Dispatch_Engine> engine(*t_ss);
|
||||||
if (guardnode) {
|
if (m_guard_node) {
|
||||||
guard = dispatch::make_dynamic_proxy_function(
|
guard = dispatch::make_dynamic_proxy_function(
|
||||||
[engine, t_param_names, guardnode](const std::vector<Boxed_Value> &t_params) {
|
[engine, t_param_names, guardnode = m_guard_node](const std::vector<Boxed_Value> &t_params) {
|
||||||
return chaiscript::eval::detail::eval_function(engine, guardnode, t_param_names, t_params);
|
return chaiscript::eval::detail::eval_function(engine, *guardnode, t_param_names, t_params);
|
||||||
},
|
},
|
||||||
static_cast<int>(numparams), guardnode);
|
static_cast<int>(numparams), m_guard_node);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const std::string & function_name = this->children[1]->text;
|
const std::string & function_name = this->children[1]->text;
|
||||||
auto node = this->children.back();
|
|
||||||
|
|
||||||
if (function_name == class_name) {
|
if (function_name == class_name) {
|
||||||
param_types.push_front(class_name, Type_Info());
|
param_types.push_front(class_name, Type_Info());
|
||||||
@ -1388,10 +1424,10 @@ namespace chaiscript
|
|||||||
t_ss->add(
|
t_ss->add(
|
||||||
std::make_shared<dispatch::detail::Dynamic_Object_Constructor>(class_name,
|
std::make_shared<dispatch::detail::Dynamic_Object_Constructor>(class_name,
|
||||||
dispatch::make_dynamic_proxy_function(
|
dispatch::make_dynamic_proxy_function(
|
||||||
[engine, t_param_names, node](const std::vector<Boxed_Value> &t_params) {
|
[engine, t_param_names, node = m_body_node](const std::vector<Boxed_Value> &t_params) {
|
||||||
return chaiscript::eval::detail::eval_function(engine, node, t_param_names, t_params);
|
return chaiscript::eval::detail::eval_function(engine, *node, t_param_names, t_params);
|
||||||
},
|
},
|
||||||
static_cast<int>(numparams), node, param_types, guard
|
static_cast<int>(numparams), m_body_node, param_types, guard
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
function_name);
|
function_name);
|
||||||
@ -1402,15 +1438,17 @@ namespace chaiscript
|
|||||||
auto type = t_ss->get_type(class_name, false);
|
auto type = t_ss->get_type(class_name, false);
|
||||||
param_types.push_front(class_name, type);
|
param_types.push_front(class_name, type);
|
||||||
|
|
||||||
t_ss->add(std::make_shared<dispatch::detail::Dynamic_Object_Function>(class_name,
|
t_ss->add(
|
||||||
|
std::make_shared<dispatch::detail::Dynamic_Object_Function>(class_name,
|
||||||
dispatch::make_dynamic_proxy_function(
|
dispatch::make_dynamic_proxy_function(
|
||||||
[engine, t_param_names, node](const std::vector<Boxed_Value> &t_params) {
|
[engine, t_param_names, node = m_body_node](const std::vector<Boxed_Value> &t_params) {
|
||||||
return chaiscript::eval::detail::eval_function(engine, node, t_param_names, t_params);
|
return chaiscript::eval::detail::eval_function(engine, *node, t_param_names, t_params);
|
||||||
},
|
},
|
||||||
static_cast<int>(numparams), node, param_types, guard), type),
|
static_cast<int>(numparams), m_body_node, param_types, guard), type),
|
||||||
function_name);
|
function_name);
|
||||||
}
|
}
|
||||||
} catch (const exception::name_conflict_error &e) {
|
} catch (const exception::name_conflict_error &e) {
|
||||||
|
std::cout << "Method!!" << std::endl;
|
||||||
throw exception::eval_error("Method redefined '" + e.name() + "'");
|
throw exception::eval_error("Method redefined '" + e.name() + "'");
|
||||||
}
|
}
|
||||||
return void_var();
|
return void_var();
|
||||||
|
|||||||
@ -24,17 +24,26 @@ namespace chaiscript {
|
|||||||
|
|
||||||
template<typename Tracer>
|
template<typename Tracer>
|
||||||
auto optimize(eval::AST_Node_Impl_Ptr<Tracer> p) {
|
auto optimize(eval::AST_Node_Impl_Ptr<Tracer> p) {
|
||||||
(void)std::initializer_list<int>{ (p = static_cast<T&>(*this).optimize(p), 0)... };
|
(void)std::initializer_list<int>{ (p = static_cast<T&>(*this).optimize(std::move(p)), 0)... };
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
auto child_at(const eval::AST_Node_Impl_Ptr<T> &node, const size_t offset) {
|
eval::AST_Node_Impl<T> &child_at(eval::AST_Node_Impl<T> &node, const size_t offset) {
|
||||||
if (node->children[offset]->identifier == AST_Node_Type::Compiled) {
|
if (node.children[offset]->identifier == AST_Node_Type::Compiled) {
|
||||||
return dynamic_cast<const eval::Compiled_AST_Node<T>&>(*node->children[offset]).m_original_node;
|
return *(dynamic_cast<eval::Compiled_AST_Node<T> &>(*node.children[offset]).m_original_node);
|
||||||
} else {
|
} else {
|
||||||
return node->children[offset];
|
return *node.children[offset];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
const eval::AST_Node_Impl<T> &child_at(const eval::AST_Node_Impl<T> &node, const size_t offset) {
|
||||||
|
if (node.children[offset]->identifier == AST_Node_Type::Compiled) {
|
||||||
|
return *(dynamic_cast<const eval::Compiled_AST_Node<T> &>(*node.children[offset]).m_original_node);
|
||||||
|
} else {
|
||||||
|
return *node.children[offset];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -48,24 +57,24 @@ namespace chaiscript {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
auto child_count(const eval::AST_Node_Impl_Ptr<T> &node) {
|
auto child_count(const eval::AST_Node_Impl<T> &node) {
|
||||||
if (node->identifier == AST_Node_Type::Compiled) {
|
if (node.identifier == AST_Node_Type::Compiled) {
|
||||||
return dynamic_cast<const eval::Compiled_AST_Node<T>&>(*node).m_original_node->children.size();
|
return dynamic_cast<const eval::Compiled_AST_Node<T>&>(node).m_original_node->children.size();
|
||||||
} else {
|
} else {
|
||||||
return node->children.size();
|
return node.children.size();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, typename Callable>
|
template<typename T, typename Callable>
|
||||||
auto make_compiled_node(const eval::AST_Node_Impl_Ptr<T> &original_node, std::vector<eval::AST_Node_Impl_Ptr<T>> children, Callable callable)
|
auto make_compiled_node(eval::AST_Node_Impl_Ptr<T> original_node, std::vector<eval::AST_Node_Impl_Ptr<T>> children, Callable callable)
|
||||||
{
|
{
|
||||||
return chaiscript::make_shared<eval::AST_Node_Impl<T>, eval::Compiled_AST_Node<T>>(original_node, std::move(children), std::move(callable));
|
return chaiscript::make_unique<eval::AST_Node_Impl<T>, eval::Compiled_AST_Node<T>>(std::move(original_node), std::move(children), std::move(callable));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
struct Return {
|
struct Return {
|
||||||
template<typename T>
|
template<typename T>
|
||||||
auto optimize(const eval::AST_Node_Impl_Ptr<T> &p)
|
auto optimize(eval::AST_Node_Impl_Ptr<T> p)
|
||||||
{
|
{
|
||||||
if ( (p->identifier == AST_Node_Type::Def || p->identifier == AST_Node_Type::Lambda)
|
if ( (p->identifier == AST_Node_Type::Def || p->identifier == AST_Node_Type::Lambda)
|
||||||
&& !p->children.empty())
|
&& !p->children.empty())
|
||||||
@ -75,7 +84,7 @@ namespace chaiscript {
|
|||||||
auto &block_last_child = last_child->children.back();
|
auto &block_last_child = last_child->children.back();
|
||||||
if (block_last_child->identifier == AST_Node_Type::Return) {
|
if (block_last_child->identifier == AST_Node_Type::Return) {
|
||||||
if (block_last_child->children.size() == 1) {
|
if (block_last_child->children.size() == 1) {
|
||||||
last_child->children.back() = block_last_child->children[0];
|
last_child->children.back() = std::move(block_last_child->children[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -86,9 +95,9 @@ namespace chaiscript {
|
|||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
bool contains_var_decl_in_scope(const T &node)
|
bool contains_var_decl_in_scope(const eval::AST_Node_Impl<T> &node)
|
||||||
{
|
{
|
||||||
if (node->identifier == AST_Node_Type::Var_Decl) {
|
if (node.identifier == AST_Node_Type::Var_Decl) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,8 +105,8 @@ namespace chaiscript {
|
|||||||
|
|
||||||
for (size_t i = 0; i < num; ++i) {
|
for (size_t i = 0; i < num; ++i) {
|
||||||
const auto &child = child_at(node, i);
|
const auto &child = child_at(node, i);
|
||||||
if (child->identifier != AST_Node_Type::Block
|
if (child.identifier != AST_Node_Type::Block
|
||||||
&& child->identifier != AST_Node_Type::For
|
&& child.identifier != AST_Node_Type::For
|
||||||
&& contains_var_decl_in_scope(child)) {
|
&& contains_var_decl_in_scope(child)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -108,15 +117,16 @@ namespace chaiscript {
|
|||||||
|
|
||||||
struct Block {
|
struct Block {
|
||||||
template<typename T>
|
template<typename T>
|
||||||
auto optimize(const eval::AST_Node_Impl_Ptr<T> &node) {
|
auto optimize(eval::AST_Node_Impl_Ptr<T> node) {
|
||||||
if (node->identifier == AST_Node_Type::Block)
|
if (node->identifier == AST_Node_Type::Block)
|
||||||
{
|
{
|
||||||
if (!contains_var_decl_in_scope(node))
|
if (!contains_var_decl_in_scope(*node))
|
||||||
{
|
{
|
||||||
if (node->children.size() == 1) {
|
if (node->children.size() == 1) {
|
||||||
return node->children[0];
|
return std::move(node->children[0]);
|
||||||
} else {
|
} else {
|
||||||
return chaiscript::make_shared<eval::AST_Node_Impl<T>, eval::Scopeless_Block_AST_Node<T>>(node->text, node->location, node->children);
|
return chaiscript::make_unique<eval::AST_Node_Impl<T>, eval::Scopeless_Block_AST_Node<T>>(node->text, node->location,
|
||||||
|
std::move(node->children));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -127,7 +137,7 @@ namespace chaiscript {
|
|||||||
|
|
||||||
struct Dead_Code {
|
struct Dead_Code {
|
||||||
template<typename T>
|
template<typename T>
|
||||||
auto optimize(const eval::AST_Node_Impl_Ptr<T> &node) {
|
auto optimize(eval::AST_Node_Impl_Ptr<T> node) {
|
||||||
if (node->identifier == AST_Node_Type::Block)
|
if (node->identifier == AST_Node_Type::Block)
|
||||||
{
|
{
|
||||||
std::vector<size_t> keepers;
|
std::vector<size_t> keepers;
|
||||||
@ -135,10 +145,10 @@ namespace chaiscript {
|
|||||||
keepers.reserve(num_children);
|
keepers.reserve(num_children);
|
||||||
|
|
||||||
for (size_t i = 0; i < num_children; ++i) {
|
for (size_t i = 0; i < num_children; ++i) {
|
||||||
auto child = node->children[i];
|
const auto &child = *node->children[i];
|
||||||
if ( (child->identifier != AST_Node_Type::Id
|
if ( (child.identifier != AST_Node_Type::Id
|
||||||
&& child->identifier != AST_Node_Type::Constant
|
&& child.identifier != AST_Node_Type::Constant
|
||||||
&& child->identifier != AST_Node_Type::Noop)
|
&& child.identifier != AST_Node_Type::Noop)
|
||||||
|| i == num_children - 1) {
|
|| i == num_children - 1) {
|
||||||
keepers.push_back(i);
|
keepers.push_back(i);
|
||||||
}
|
}
|
||||||
@ -147,12 +157,16 @@ namespace chaiscript {
|
|||||||
if (keepers.size() == num_children) {
|
if (keepers.size() == num_children) {
|
||||||
return node;
|
return node;
|
||||||
} else {
|
} else {
|
||||||
std::vector<eval::AST_Node_Impl_Ptr<T>> new_children;
|
const auto new_children = [&](){
|
||||||
|
std::vector<eval::AST_Node_Impl_Ptr<T>> retval;
|
||||||
for (const auto x : keepers)
|
for (const auto x : keepers)
|
||||||
{
|
{
|
||||||
new_children.push_back(node->children[x]);
|
retval.push_back(std::move(node->children[x]));
|
||||||
}
|
}
|
||||||
return chaiscript::make_shared<eval::AST_Node_Impl<T>, eval::Block_AST_Node<T>>(node->text, node->location, new_children);
|
return retval;
|
||||||
|
};
|
||||||
|
|
||||||
|
return chaiscript::make_unique<eval::AST_Node_Impl<T>, eval::Block_AST_Node<T>>(node->text, node->location, new_children());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return node;
|
return node;
|
||||||
@ -162,29 +176,30 @@ namespace chaiscript {
|
|||||||
|
|
||||||
struct Unused_Return {
|
struct Unused_Return {
|
||||||
template<typename T>
|
template<typename T>
|
||||||
auto optimize(const eval::AST_Node_Impl_Ptr<T> &node) {
|
auto optimize(eval::AST_Node_Impl_Ptr<T> node) {
|
||||||
if ((node->identifier == AST_Node_Type::Block
|
if ((node->identifier == AST_Node_Type::Block
|
||||||
|| node->identifier == AST_Node_Type::Scopeless_Block)
|
|| node->identifier == AST_Node_Type::Scopeless_Block)
|
||||||
&& !node->children.empty())
|
&& !node->children.empty())
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < node->children.size()-1; ++i) {
|
for (size_t i = 0; i < node->children.size()-1; ++i) {
|
||||||
auto child = node->children[i];
|
auto child = node->children[i].get();
|
||||||
if (child->identifier == AST_Node_Type::Fun_Call) {
|
if (child->identifier == AST_Node_Type::Fun_Call) {
|
||||||
node->children[i] = chaiscript::make_shared<eval::AST_Node_Impl<T>, eval::Unused_Return_Fun_Call_AST_Node<T>>(child->text, child->location, std::move(child->children));
|
node->children[i] = chaiscript::make_unique<eval::AST_Node_Impl<T>, eval::Unused_Return_Fun_Call_AST_Node<T>>(child->text, child->location,
|
||||||
|
std::move(child->children));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if ((node->identifier == AST_Node_Type::For
|
} else if ((node->identifier == AST_Node_Type::For
|
||||||
|| node->identifier == AST_Node_Type::While)
|
|| node->identifier == AST_Node_Type::While)
|
||||||
&& child_count(node) > 0) {
|
&& child_count(*node) > 0) {
|
||||||
auto child = child_at(node, child_count(node) - 1);
|
auto &child = child_at(*node, child_count(*node) - 1);
|
||||||
if (child->identifier == AST_Node_Type::Block
|
if (child.identifier == AST_Node_Type::Block
|
||||||
|| child->identifier == AST_Node_Type::Scopeless_Block)
|
|| child.identifier == AST_Node_Type::Scopeless_Block)
|
||||||
{
|
{
|
||||||
auto num_sub_children = child_count(child);
|
auto num_sub_children = child_count(child);
|
||||||
for (size_t i = 0; i < num_sub_children; ++i) {
|
for (size_t i = 0; i < num_sub_children; ++i) {
|
||||||
auto sub_child = child_at(child, i);
|
auto &sub_child = child_at(child, i);
|
||||||
if (sub_child->identifier == AST_Node_Type::Fun_Call) {
|
if (sub_child.identifier == AST_Node_Type::Fun_Call) {
|
||||||
child->children[i] = chaiscript::make_shared<eval::AST_Node_Impl<T>, eval::Unused_Return_Fun_Call_AST_Node<T>>(sub_child->text, sub_child->location, std::move(sub_child->children));
|
child.children[i] = chaiscript::make_unique<eval::AST_Node_Impl<T>, eval::Unused_Return_Fun_Call_AST_Node<T>>(sub_child.text, sub_child.location, std::move(sub_child.children));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -195,17 +210,17 @@ namespace chaiscript {
|
|||||||
|
|
||||||
struct If {
|
struct If {
|
||||||
template<typename T>
|
template<typename T>
|
||||||
auto optimize(const eval::AST_Node_Impl_Ptr<T> &node) {
|
auto optimize(eval::AST_Node_Impl_Ptr<T> node) {
|
||||||
if ((node->identifier == AST_Node_Type::If)
|
if ((node->identifier == AST_Node_Type::If)
|
||||||
&& node->children.size() >= 2
|
&& node->children.size() >= 2
|
||||||
&& node->children[0]->identifier == AST_Node_Type::Constant)
|
&& node->children[0]->identifier == AST_Node_Type::Constant)
|
||||||
{
|
{
|
||||||
const auto condition = std::dynamic_pointer_cast<eval::Constant_AST_Node<T>>(node->children[0])->m_value;
|
const auto condition = dynamic_cast<eval::Constant_AST_Node<T> *>(node->children[0].get())->m_value;
|
||||||
if (condition.get_type_info().bare_equal_type_info(typeid(bool))) {
|
if (condition.get_type_info().bare_equal_type_info(typeid(bool))) {
|
||||||
if (boxed_cast<bool>(condition)) {
|
if (boxed_cast<bool>(condition)) {
|
||||||
return node->children[1];
|
return std::move(node->children[1]);
|
||||||
} else if (node->children.size() == 3) {
|
} else if (node->children.size() == 3) {
|
||||||
return node->children[2];
|
return std::move(node->children[2]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -216,7 +231,7 @@ namespace chaiscript {
|
|||||||
|
|
||||||
struct Partial_Fold {
|
struct Partial_Fold {
|
||||||
template<typename T>
|
template<typename T>
|
||||||
auto optimize(const eval::AST_Node_Impl_Ptr<T> &node) {
|
auto optimize(eval::AST_Node_Impl_Ptr<T> node) {
|
||||||
|
|
||||||
// Fold right side
|
// Fold right side
|
||||||
if (node->identifier == AST_Node_Type::Binary
|
if (node->identifier == AST_Node_Type::Binary
|
||||||
@ -228,9 +243,10 @@ namespace chaiscript {
|
|||||||
const auto &oper = node->text;
|
const auto &oper = node->text;
|
||||||
const auto parsed = Operators::to_operator(oper);
|
const auto parsed = Operators::to_operator(oper);
|
||||||
if (parsed != Operators::Opers::invalid) {
|
if (parsed != Operators::Opers::invalid) {
|
||||||
const auto rhs = std::dynamic_pointer_cast<eval::Constant_AST_Node<T>>(node->children[1])->m_value;
|
const auto rhs = dynamic_cast<eval::Constant_AST_Node<T> *>(node->children[1].get())->m_value;
|
||||||
if (rhs.get_type_info().is_arithmetic()) {
|
if (rhs.get_type_info().is_arithmetic()) {
|
||||||
return chaiscript::make_shared<eval::AST_Node_Impl<T>, eval::Fold_Right_Binary_Operator_AST_Node<T>>(node->text, node->location, node->children, rhs);
|
return chaiscript::make_unique<eval::AST_Node_Impl<T>, eval::Fold_Right_Binary_Operator_AST_Node<T>>(node->text, node->location,
|
||||||
|
std::move(node->children), rhs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (const std::exception &) {
|
} catch (const std::exception &) {
|
||||||
@ -244,7 +260,7 @@ namespace chaiscript {
|
|||||||
|
|
||||||
struct Constant_Fold {
|
struct Constant_Fold {
|
||||||
template<typename T>
|
template<typename T>
|
||||||
auto optimize(const eval::AST_Node_Impl_Ptr<T> &node) {
|
auto optimize(eval::AST_Node_Impl_Ptr<T> node) {
|
||||||
|
|
||||||
if (node->identifier == AST_Node_Type::Prefix
|
if (node->identifier == AST_Node_Type::Prefix
|
||||||
&& node->children.size() == 1
|
&& node->children.size() == 1
|
||||||
@ -253,14 +269,14 @@ namespace chaiscript {
|
|||||||
try {
|
try {
|
||||||
const auto &oper = node->text;
|
const auto &oper = node->text;
|
||||||
const auto parsed = Operators::to_operator(oper, true);
|
const auto parsed = Operators::to_operator(oper, true);
|
||||||
const auto lhs = std::dynamic_pointer_cast<eval::Constant_AST_Node<T>>(node->children[0])->m_value;
|
const auto lhs = dynamic_cast<const eval::Constant_AST_Node<T> *>(node->children[0].get())->m_value;
|
||||||
const auto match = oper + node->children[0]->text;
|
const auto match = oper + node->children[0]->text;
|
||||||
|
|
||||||
if (parsed != Operators::Opers::invalid && parsed != Operators::Opers::bitwise_and && lhs.get_type_info().is_arithmetic()) {
|
if (parsed != Operators::Opers::invalid && parsed != Operators::Opers::bitwise_and && lhs.get_type_info().is_arithmetic()) {
|
||||||
const auto val = Boxed_Number::do_oper(parsed, lhs);
|
const auto val = Boxed_Number::do_oper(parsed, lhs);
|
||||||
return chaiscript::make_shared<eval::AST_Node_Impl<T>, eval::Constant_AST_Node<T>>(std::move(match), node->location, std::move(val));
|
return chaiscript::make_unique<eval::AST_Node_Impl<T>, eval::Constant_AST_Node<T>>(std::move(match), node->location, std::move(val));
|
||||||
} else if (lhs.get_type_info().bare_equal_type_info(typeid(bool)) && oper == "!") {
|
} else if (lhs.get_type_info().bare_equal_type_info(typeid(bool)) && oper == "!") {
|
||||||
return chaiscript::make_shared<eval::AST_Node_Impl<T>, eval::Constant_AST_Node<T>>(std::move(match), node->location, Boxed_Value(!boxed_cast<bool>(lhs)));
|
return chaiscript::make_unique<eval::AST_Node_Impl<T>, eval::Constant_AST_Node<T>>(std::move(match), node->location, Boxed_Value(!boxed_cast<bool>(lhs)));
|
||||||
}
|
}
|
||||||
} catch (const std::exception &) {
|
} catch (const std::exception &) {
|
||||||
//failure to fold, that's OK
|
//failure to fold, that's OK
|
||||||
@ -271,8 +287,8 @@ namespace chaiscript {
|
|||||||
&& node->children[1]->identifier == AST_Node_Type::Constant)
|
&& node->children[1]->identifier == AST_Node_Type::Constant)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
const auto lhs = std::dynamic_pointer_cast<eval::Constant_AST_Node<T>>(node->children[0])->m_value;
|
const auto lhs = dynamic_cast<const eval::Constant_AST_Node<T> &>(*node->children[0]).m_value;
|
||||||
const auto rhs = std::dynamic_pointer_cast<eval::Constant_AST_Node<T>>(node->children[1])->m_value;
|
const auto rhs = dynamic_cast<const eval::Constant_AST_Node<T> &>(*node->children[1]).m_value;
|
||||||
if (lhs.get_type_info().bare_equal_type_info(typeid(bool)) && rhs.get_type_info().bare_equal_type_info(typeid(bool))) {
|
if (lhs.get_type_info().bare_equal_type_info(typeid(bool)) && rhs.get_type_info().bare_equal_type_info(typeid(bool))) {
|
||||||
const auto match = node->children[0]->text + " " + node->text + " " + node->children[1]->text;
|
const auto match = node->children[0]->text + " " + node->text + " " + node->children[1]->text;
|
||||||
const auto val = [lhs_val = boxed_cast<bool>(lhs), rhs_val = boxed_cast<bool>(rhs), id = node->identifier] {
|
const auto val = [lhs_val = boxed_cast<bool>(lhs), rhs_val = boxed_cast<bool>(rhs), id = node->identifier] {
|
||||||
@ -280,7 +296,7 @@ namespace chaiscript {
|
|||||||
else { return Boxed_Value(lhs_val || rhs_val); }
|
else { return Boxed_Value(lhs_val || rhs_val); }
|
||||||
}();
|
}();
|
||||||
|
|
||||||
return chaiscript::make_shared<eval::AST_Node_Impl<T>, eval::Constant_AST_Node<T>>(std::move(match), node->location, std::move(val));
|
return chaiscript::make_unique<eval::AST_Node_Impl<T>, eval::Constant_AST_Node<T>>(std::move(match), node->location, std::move(val));
|
||||||
}
|
}
|
||||||
} catch (const std::exception &) {
|
} catch (const std::exception &) {
|
||||||
//failure to fold, that's OK
|
//failure to fold, that's OK
|
||||||
@ -294,12 +310,12 @@ namespace chaiscript {
|
|||||||
const auto &oper = node->text;
|
const auto &oper = node->text;
|
||||||
const auto parsed = Operators::to_operator(oper);
|
const auto parsed = Operators::to_operator(oper);
|
||||||
if (parsed != Operators::Opers::invalid) {
|
if (parsed != Operators::Opers::invalid) {
|
||||||
const auto lhs = std::dynamic_pointer_cast<eval::Constant_AST_Node<T>>(node->children[0])->m_value;
|
const auto lhs = dynamic_cast<const eval::Constant_AST_Node<T> &>(*node->children[0]).m_value;
|
||||||
const auto rhs = std::dynamic_pointer_cast<eval::Constant_AST_Node<T>>(node->children[1])->m_value;
|
const auto rhs = dynamic_cast<const eval::Constant_AST_Node<T> &>(*node->children[1]).m_value;
|
||||||
if (lhs.get_type_info().is_arithmetic() && rhs.get_type_info().is_arithmetic()) {
|
if (lhs.get_type_info().is_arithmetic() && rhs.get_type_info().is_arithmetic()) {
|
||||||
const auto val = Boxed_Number::do_oper(parsed, lhs, rhs);
|
const auto val = Boxed_Number::do_oper(parsed, lhs, rhs);
|
||||||
const auto match = node->children[0]->text + " " + oper + " " + node->children[1]->text;
|
const auto match = node->children[0]->text + " " + oper + " " + node->children[1]->text;
|
||||||
return chaiscript::make_shared<eval::AST_Node_Impl<T>, eval::Constant_AST_Node<T>>(std::move(match), node->location, std::move(val));
|
return chaiscript::make_unique<eval::AST_Node_Impl<T>, eval::Constant_AST_Node<T>>(std::move(match), node->location, std::move(val));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (const std::exception &) {
|
} catch (const std::exception &) {
|
||||||
@ -312,13 +328,13 @@ namespace chaiscript {
|
|||||||
&& node->children[1]->children.size() == 1
|
&& node->children[1]->children.size() == 1
|
||||||
&& node->children[1]->children[0]->identifier == AST_Node_Type::Constant) {
|
&& node->children[1]->children[0]->identifier == AST_Node_Type::Constant) {
|
||||||
|
|
||||||
const auto arg = std::dynamic_pointer_cast<eval::Constant_AST_Node<T>>(node->children[1]->children[0])->m_value;
|
const auto arg = dynamic_cast<const eval::Constant_AST_Node<T> &>(*node->children[1]->children[0]).m_value;
|
||||||
if (arg.get_type_info().is_arithmetic()) {
|
if (arg.get_type_info().is_arithmetic()) {
|
||||||
const auto &fun_name = node->children[0]->text;
|
const auto &fun_name = node->children[0]->text;
|
||||||
|
|
||||||
const auto make_constant = [&node, &fun_name](auto val){
|
const auto make_constant = [&node, &fun_name](auto val){
|
||||||
const auto match = fun_name + "(" + node->children[1]->children[0]->text + ")";
|
const auto match = fun_name + "(" + node->children[1]->children[0]->text + ")";
|
||||||
return chaiscript::make_shared<eval::AST_Node_Impl<T>, eval::Constant_AST_Node<T>>(std::move(match), node->location, Boxed_Value(val));
|
return chaiscript::make_unique<eval::AST_Node_Impl<T>, eval::Constant_AST_Node<T>>(std::move(match), node->location, Boxed_Value(val));
|
||||||
};
|
};
|
||||||
|
|
||||||
if (fun_name == "double") {
|
if (fun_name == "double") {
|
||||||
@ -344,35 +360,36 @@ namespace chaiscript {
|
|||||||
|
|
||||||
struct For_Loop {
|
struct For_Loop {
|
||||||
template<typename T>
|
template<typename T>
|
||||||
auto optimize(const eval::AST_Node_Impl_Ptr<T> &for_node) {
|
auto optimize(eval::AST_Node_Impl_Ptr<T> for_node) {
|
||||||
|
|
||||||
if (for_node->identifier != AST_Node_Type::For) {
|
if (for_node->identifier != AST_Node_Type::For) {
|
||||||
return for_node;
|
return for_node;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto eq_node = child_at(for_node, 0);
|
const auto &eq_node = child_at(*for_node, 0);
|
||||||
const auto binary_node = child_at(for_node, 1);
|
const auto &binary_node = child_at(*for_node, 1);
|
||||||
const auto prefix_node = child_at(for_node, 2);
|
const auto &prefix_node = child_at(*for_node, 2);
|
||||||
|
|
||||||
if (eq_node->identifier == AST_Node_Type::Equation
|
if (child_count(*for_node) == 4
|
||||||
|
&& eq_node.identifier == AST_Node_Type::Equation
|
||||||
&& child_count(eq_node) == 2
|
&& child_count(eq_node) == 2
|
||||||
&& child_at(eq_node, 0)->identifier == AST_Node_Type::Var_Decl
|
&& child_at(eq_node, 0).identifier == AST_Node_Type::Var_Decl
|
||||||
&& child_at(eq_node, 1)->identifier == AST_Node_Type::Constant
|
&& child_at(eq_node, 1).identifier == AST_Node_Type::Constant
|
||||||
&& binary_node->identifier == AST_Node_Type::Binary
|
&& binary_node.identifier == AST_Node_Type::Binary
|
||||||
&& binary_node->text == "<"
|
&& binary_node.text == "<"
|
||||||
&& child_count(binary_node) == 2
|
&& child_count(binary_node) == 2
|
||||||
&& child_at(binary_node, 0)->identifier == AST_Node_Type::Id
|
&& child_at(binary_node, 0).identifier == AST_Node_Type::Id
|
||||||
&& child_at(binary_node, 0)->text == child_at(child_at(eq_node,0), 0)->text
|
&& child_at(binary_node, 0).text == child_at(child_at(eq_node,0), 0).text
|
||||||
&& child_at(binary_node, 1)->identifier == AST_Node_Type::Constant
|
&& child_at(binary_node, 1).identifier == AST_Node_Type::Constant
|
||||||
&& prefix_node->identifier == AST_Node_Type::Prefix
|
&& prefix_node.identifier == AST_Node_Type::Prefix
|
||||||
&& prefix_node->text == "++"
|
&& prefix_node.text == "++"
|
||||||
&& child_count(prefix_node) == 1
|
&& child_count(prefix_node) == 1
|
||||||
&& child_at(prefix_node, 0)->identifier == AST_Node_Type::Id
|
&& child_at(prefix_node, 0).identifier == AST_Node_Type::Id
|
||||||
&& child_at(prefix_node, 0)->text == child_at(child_at(eq_node,0), 0)->text)
|
&& child_at(prefix_node, 0).text == child_at(child_at(eq_node,0), 0).text)
|
||||||
{
|
{
|
||||||
const Boxed_Value &begin = std::dynamic_pointer_cast<const eval::Constant_AST_Node<T>>(child_at(eq_node, 1))->m_value;
|
const Boxed_Value &begin = dynamic_cast<const eval::Constant_AST_Node<T> &>(child_at(eq_node, 1)).m_value;
|
||||||
const Boxed_Value &end = std::dynamic_pointer_cast<const eval::Constant_AST_Node<T>>(child_at(binary_node, 1))->m_value;
|
const Boxed_Value &end = dynamic_cast<const eval::Constant_AST_Node<T> &>(child_at(binary_node, 1)).m_value;
|
||||||
const std::string &id = child_at(prefix_node, 0)->text;
|
const std::string &id = child_at(prefix_node, 0).text;
|
||||||
|
|
||||||
if (begin.get_type_info().bare_equal(user_type<int>())
|
if (begin.get_type_info().bare_equal(user_type<int>())
|
||||||
&& end.get_type_info().bare_equal(user_type<int>())) {
|
&& end.get_type_info().bare_equal(user_type<int>())) {
|
||||||
@ -380,9 +397,14 @@ namespace chaiscript {
|
|||||||
const auto start_int = boxed_cast<int>(begin);
|
const auto start_int = boxed_cast<int>(begin);
|
||||||
const auto end_int = boxed_cast<int>(end);
|
const auto end_int = boxed_cast<int>(end);
|
||||||
|
|
||||||
const auto body = child_at(for_node, 3);
|
// note that we are moving the last element out, then popping the empty shared_ptr
|
||||||
|
// from the vector
|
||||||
|
std::vector<eval::AST_Node_Impl_Ptr<T>> body_vector;
|
||||||
|
auto body_child = std::move(for_node->children[3]);
|
||||||
|
for_node->children.pop_back();
|
||||||
|
body_vector.emplace_back(std::move(body_child));
|
||||||
|
|
||||||
return make_compiled_node(for_node, {body},
|
return make_compiled_node(std::move(for_node), std::move(body_vector),
|
||||||
[id, start_int, end_int](const std::vector<eval::AST_Node_Impl_Ptr<T>> &children, const chaiscript::detail::Dispatch_State &t_ss) {
|
[id, start_int, end_int](const std::vector<eval::AST_Node_Impl_Ptr<T>> &children, const chaiscript::detail::Dispatch_State &t_ss) {
|
||||||
assert(children.size() == 1);
|
assert(children.size() == 1);
|
||||||
chaiscript::eval::detail::Scope_Push_Pop spp(t_ss);
|
chaiscript::eval::detail::Scope_Push_Pop spp(t_ss);
|
||||||
|
|||||||
@ -397,7 +397,7 @@ namespace chaiscript
|
|||||||
return m_optimizer;
|
return m_optimizer;
|
||||||
}
|
}
|
||||||
|
|
||||||
ChaiScript_Parser(const ChaiScript_Parser &) = default;
|
ChaiScript_Parser(const ChaiScript_Parser &) = delete;
|
||||||
ChaiScript_Parser &operator=(const ChaiScript_Parser &) = delete;
|
ChaiScript_Parser &operator=(const ChaiScript_Parser &) = delete;
|
||||||
ChaiScript_Parser(ChaiScript_Parser &&) = default;
|
ChaiScript_Parser(ChaiScript_Parser &&) = default;
|
||||||
ChaiScript_Parser &operator=(ChaiScript_Parser &&) = delete;
|
ChaiScript_Parser &operator=(ChaiScript_Parser &&) = delete;
|
||||||
@ -406,10 +406,10 @@ namespace chaiscript
|
|||||||
bool char_in_alphabet(char c, detail::Alphabet a) const { return m_alphabet[a][static_cast<uint8_t>(c)]; }
|
bool char_in_alphabet(char c, detail::Alphabet a) const { return m_alphabet[a][static_cast<uint8_t>(c)]; }
|
||||||
|
|
||||||
/// Prints the parsed ast_nodes as a tree
|
/// Prints the parsed ast_nodes as a tree
|
||||||
void debug_print(AST_NodePtr t, std::string prepend = "") const override {
|
void debug_print(const AST_Node &t, std::string prepend = "") const override {
|
||||||
std::cout << prepend << "(" << ast_node_type_to_string(t->identifier) << ") " << t->text << " : " << t->start().line << ", " << t->start().column << '\n';
|
std::cout << prepend << "(" << ast_node_type_to_string(t.identifier) << ") " << t.text << " : " << t.start().line << ", " << t.start().column << '\n';
|
||||||
for (const auto &node : t->get_children()) {
|
for (const auto &node : t.get_children()) {
|
||||||
debug_print(node, prepend + " ");
|
debug_print(node.get(), prepend + " ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -452,7 +452,7 @@ namespace chaiscript
|
|||||||
/// \todo fix the fact that a successful match that captured no ast_nodes doesn't have any real start position
|
/// \todo fix the fact that a successful match that captured no ast_nodes doesn't have any real start position
|
||||||
m_match_stack.push_back(
|
m_match_stack.push_back(
|
||||||
m_optimizer.optimize(
|
m_optimizer.optimize(
|
||||||
chaiscript::make_shared<chaiscript::eval::AST_Node_Impl<Tracer>, NodeType>(
|
chaiscript::make_unique<chaiscript::eval::AST_Node_Impl<Tracer>, NodeType>(
|
||||||
std::move(t_text),
|
std::move(t_text),
|
||||||
std::move(filepos),
|
std::move(filepos),
|
||||||
std::move(new_children)))
|
std::move(new_children)))
|
||||||
@ -779,9 +779,9 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, typename ... Param>
|
template<typename T, typename ... Param>
|
||||||
std::shared_ptr<eval::AST_Node_Impl<Tracer>> make_node(std::string t_match, const int t_prev_line, const int t_prev_col, Param && ...param)
|
std::unique_ptr<eval::AST_Node_Impl<Tracer>> make_node(std::string t_match, const int t_prev_line, const int t_prev_col, Param && ...param)
|
||||||
{
|
{
|
||||||
return chaiscript::make_shared<eval::AST_Node_Impl<Tracer>, T>(std::move(t_match), Parse_Location(m_filename, t_prev_line, t_prev_col, m_position.line, m_position.col), std::forward<Param>(param)...);
|
return chaiscript::make_unique<eval::AST_Node_Impl<Tracer>, T>(std::move(t_match), Parse_Location(m_filename, t_prev_line, t_prev_col, m_position.line, m_position.col), std::forward<Param>(param)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reads a number from the input, detecting if it's an integer or floating point
|
/// Reads a number from the input, detecting if it's an integer or floating point
|
||||||
@ -1759,7 +1759,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
if ((is_if_init && num_children == 3)
|
if ((is_if_init && num_children == 3)
|
||||||
|| (!is_if_init && num_children == 2)) {
|
|| (!is_if_init && num_children == 2)) {
|
||||||
m_match_stack.push_back(chaiscript::make_shared<eval::AST_Node_Impl<Tracer>, eval::Noop_AST_Node<Tracer>>());
|
m_match_stack.push_back(chaiscript::make_unique<eval::AST_Node_Impl<Tracer>, eval::Noop_AST_Node<Tracer>>());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!is_if_init) {
|
if (!is_if_init) {
|
||||||
@ -1849,7 +1849,7 @@ namespace chaiscript
|
|||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
m_match_stack.push_back(chaiscript::make_shared<eval::AST_Node_Impl<Tracer>, eval::Noop_AST_Node<Tracer>>());
|
m_match_stack.push_back(chaiscript::make_unique<eval::AST_Node_Impl<Tracer>, eval::Noop_AST_Node<Tracer>>());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1859,13 +1859,13 @@ namespace chaiscript
|
|||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
m_match_stack.push_back(chaiscript::make_shared<eval::AST_Node_Impl<Tracer>, eval::Constant_AST_Node<Tracer>>(Boxed_Value(true)));
|
m_match_stack.push_back(chaiscript::make_unique<eval::AST_Node_Impl<Tracer>, eval::Constant_AST_Node<Tracer>>(Boxed_Value(true)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Equation())
|
if (!Equation())
|
||||||
{
|
{
|
||||||
m_match_stack.push_back(chaiscript::make_shared<eval::AST_Node_Impl<Tracer>, eval::Noop_AST_Node<Tracer>>());
|
m_match_stack.push_back(chaiscript::make_unique<eval::AST_Node_Impl<Tracer>, eval::Noop_AST_Node<Tracer>>());
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -2005,7 +2005,7 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (m_match_stack.size() == prev_stack_top) {
|
if (m_match_stack.size() == prev_stack_top) {
|
||||||
m_match_stack.push_back(chaiscript::make_shared<eval::AST_Node_Impl<Tracer>, eval::Noop_AST_Node<Tracer>>());
|
m_match_stack.push_back(chaiscript::make_unique<eval::AST_Node_Impl<Tracer>, eval::Noop_AST_Node<Tracer>>());
|
||||||
}
|
}
|
||||||
|
|
||||||
build_match<eval::Block_AST_Node<Tracer>>(prev_stack_top);
|
build_match<eval::Block_AST_Node<Tracer>>(prev_stack_top);
|
||||||
@ -2029,7 +2029,7 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (m_match_stack.size() == prev_stack_top) {
|
if (m_match_stack.size() == prev_stack_top) {
|
||||||
m_match_stack.push_back(chaiscript::make_shared<eval::AST_Node_Impl<Tracer>, eval::Noop_AST_Node<Tracer>>());
|
m_match_stack.push_back(chaiscript::make_unique<eval::AST_Node_Impl<Tracer>, eval::Noop_AST_Node<Tracer>>());
|
||||||
}
|
}
|
||||||
|
|
||||||
build_match<eval::Block_AST_Node<Tracer>>(prev_stack_top);
|
build_match<eval::Block_AST_Node<Tracer>>(prev_stack_top);
|
||||||
@ -2105,13 +2105,13 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
if (m_match_stack.back()->children.empty()) { throw exception::eval_error("Incomplete dot access fun call", File_Position(m_position.line, m_position.col), *m_filename);
|
if (m_match_stack.back()->children.empty()) { throw exception::eval_error("Incomplete dot access fun call", File_Position(m_position.line, m_position.col), *m_filename);
|
||||||
}
|
}
|
||||||
auto dot_access = m_match_stack.back()->children[0];
|
auto dot_access = std::move(m_match_stack.back()->children[0]);
|
||||||
auto func_call = m_match_stack.back();
|
auto func_call = std::move(m_match_stack.back());
|
||||||
m_match_stack.pop_back();
|
m_match_stack.pop_back();
|
||||||
func_call->children.erase(func_call->children.begin());
|
func_call->children.erase(func_call->children.begin());
|
||||||
if (dot_access->children.empty()) { throw exception::eval_error("Incomplete dot access fun call", File_Position(m_position.line, m_position.col), *m_filename);
|
if (dot_access->children.empty()) { throw exception::eval_error("Incomplete dot access fun call", File_Position(m_position.line, m_position.col), *m_filename);
|
||||||
}
|
}
|
||||||
func_call->children.insert(func_call->children.begin(), dot_access->children.back());
|
func_call->children.insert(func_call->children.begin(), std::move(dot_access->children.back()));
|
||||||
dot_access->children.pop_back();
|
dot_access->children.pop_back();
|
||||||
dot_access->children.push_back(std::move(func_call));
|
dot_access->children.push_back(std::move(func_call));
|
||||||
if (dot_access->children.size() != 2) { throw exception::eval_error("Incomplete dot access fun call", File_Position(m_position.line, m_position.col), *m_filename);
|
if (dot_access->children.size() != 2) { throw exception::eval_error("Incomplete dot access fun call", File_Position(m_position.line, m_position.col), *m_filename);
|
||||||
@ -2517,24 +2517,23 @@ namespace chaiscript
|
|||||||
|
|
||||||
AST_NodePtr parse(const std::string &t_input, const std::string &t_fname) override
|
AST_NodePtr parse(const std::string &t_input, const std::string &t_fname) override
|
||||||
{
|
{
|
||||||
ChaiScript_Parser<Tracer, Optimizer> parser(*this);
|
ChaiScript_Parser<Tracer, Optimizer> parser(m_tracer, m_optimizer);
|
||||||
parser.m_match_stack.clear();
|
|
||||||
return parser.parse_internal(t_input, t_fname);
|
return parser.parse_internal(t_input, t_fname);
|
||||||
}
|
}
|
||||||
|
|
||||||
eval::AST_Node_Impl_Ptr<Tracer> parse_instr_eval(const std::string &t_input)
|
eval::AST_Node_Impl_Ptr<Tracer> parse_instr_eval(const std::string &t_input)
|
||||||
{
|
{
|
||||||
const auto last_position = m_position;
|
auto last_position = m_position;
|
||||||
const auto last_filename = m_filename;
|
auto last_filename = m_filename;
|
||||||
const auto last_match_stack = std::exchange(m_match_stack, decltype(m_match_stack){});
|
auto last_match_stack = std::exchange(m_match_stack, decltype(m_match_stack){});
|
||||||
|
|
||||||
const auto retval = parse_internal(t_input, "instr eval");
|
auto retval = parse_internal(t_input, "instr eval");
|
||||||
|
|
||||||
m_position = std::move(last_position);
|
m_position = std::move(last_position);
|
||||||
m_filename = std::move(last_filename);
|
m_filename = std::move(last_filename);
|
||||||
m_match_stack = std::move(last_match_stack);
|
m_match_stack = std::move(last_match_stack);
|
||||||
|
|
||||||
return std::dynamic_pointer_cast<eval::AST_Node_Impl<Tracer>>(retval);
|
return eval::AST_Node_Impl_Ptr<Tracer>(dynamic_cast<eval::AST_Node_Impl<Tracer>*>(retval.release()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses the given input string, tagging parsed ast_nodes with the given m_filename.
|
/// Parses the given input string, tagging parsed ast_nodes with the given m_filename.
|
||||||
@ -2546,7 +2545,6 @@ namespace chaiscript
|
|||||||
while (m_position.has_more() && (!Eol())) {
|
while (m_position.has_more() && (!Eol())) {
|
||||||
++m_position;
|
++m_position;
|
||||||
}
|
}
|
||||||
/// \todo respect // -*- coding: utf-8 -*- on line 1 or 2 see: http://evanjones.ca/python-utf8.html)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Statements(true)) {
|
if (Statements(true)) {
|
||||||
@ -2556,10 +2554,12 @@ namespace chaiscript
|
|||||||
build_match<eval::File_AST_Node<Tracer>>(0);
|
build_match<eval::File_AST_Node<Tracer>>(0);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
m_match_stack.push_back(chaiscript::make_shared<eval::AST_Node_Impl<Tracer>, eval::Noop_AST_Node<Tracer>>());
|
m_match_stack.push_back(chaiscript::make_unique<eval::AST_Node_Impl<Tracer>, eval::Noop_AST_Node<Tracer>>());
|
||||||
}
|
}
|
||||||
|
|
||||||
return m_match_stack.front();
|
AST_NodePtr retval(std::move(m_match_stack.front()));
|
||||||
|
m_match_stack.clear();
|
||||||
|
return retval;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@ -247,7 +247,7 @@ void interactive(chaiscript::ChaiScript_Basic& chai)
|
|||||||
catch (const chaiscript::exception::eval_error &ee) {
|
catch (const chaiscript::exception::eval_error &ee) {
|
||||||
std::cout << ee.what();
|
std::cout << ee.what();
|
||||||
if ( !ee.call_stack.empty() ) {
|
if ( !ee.call_stack.empty() ) {
|
||||||
std::cout << "during evaluation at (" << ee.call_stack[0]->start().line << ", " << ee.call_stack[0]->start().column << ")";
|
std::cout << "during evaluation at (" << ee.call_stack[0].start().line << ", " << ee.call_stack[0].start().column << ")";
|
||||||
}
|
}
|
||||||
std::cout << '\n';
|
std::cout << '\n';
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user