Allow for parse time evaluation of const values.
The goal is to allow for more evaluation at parse time, in general, to increase eval time performance. - Make AST_Node non-constructable except by derived classes. - Make data in AST_Node const (as much as possible). - Replace reflection "text = " with replace_child() (where the replacement must be with a new parse tree). - Evaluate floats, strings, ints, chars at parse time to avoid repeat evaluations (~10% speed up in loops in -O3)
This commit is contained in:
@@ -61,48 +61,57 @@ namespace chaiscript
|
|||||||
* The struct that doubles as both a parser ast_node and an AST node
|
* The struct that doubles as both a parser ast_node and an AST node
|
||||||
*/
|
*/
|
||||||
struct AST_Node {
|
struct AST_Node {
|
||||||
std::string text;
|
public:
|
||||||
int identifier;
|
const std::string text;
|
||||||
boost::shared_ptr<std::string> filename;
|
const int identifier;
|
||||||
File_Position start, end;
|
boost::shared_ptr<const std::string> filename;
|
||||||
std::vector<AST_NodePtr> children;
|
File_Position start, end;
|
||||||
AST_NodePtr annotation;
|
std::vector<AST_NodePtr> children;
|
||||||
|
AST_NodePtr annotation;
|
||||||
|
|
||||||
AST_Node(const std::string &t_ast_node_text, int t_id, const boost::shared_ptr<std::string> &t_fname,
|
/**
|
||||||
int t_start_line, int t_start_col, int t_end_line, int t_end_col) :
|
* Prints the contents of an AST node, including its children, recursively
|
||||||
text(t_ast_node_text), identifier(t_id), filename(t_fname),
|
*/
|
||||||
start(t_start_line, t_start_col), end(t_end_line, t_end_col)
|
std::string to_string(std::string t_prepend = "") {
|
||||||
{
|
std::ostringstream oss;
|
||||||
}
|
|
||||||
|
|
||||||
AST_Node(const std::string &t_ast_node_text, int t_id, const boost::shared_ptr<std::string> &t_fname) :
|
oss << t_prepend << "(" << ast_node_type_to_string(this->identifier) << ") "
|
||||||
text(t_ast_node_text), identifier(t_id), filename(t_fname) {}
|
<< this->text << " : " << this->start.line << ", " << this->start.column << std::endl;
|
||||||
|
|
||||||
virtual ~AST_Node() {}
|
for (unsigned int j = 0; j < this->children.size(); ++j) {
|
||||||
|
oss << this->children[j]->to_string(t_prepend + " ");
|
||||||
/**
|
}
|
||||||
* Prints the contents of an AST node, including its children, recursively
|
return oss.str();
|
||||||
*/
|
|
||||||
std::string to_string(std::string t_prepend = "") {
|
|
||||||
std::ostringstream oss;
|
|
||||||
|
|
||||||
oss << t_prepend << "(" << ast_node_type_to_string(this->identifier) << ") "
|
|
||||||
<< this->text << " : " << this->start.line << ", " << this->start.column << std::endl;
|
|
||||||
|
|
||||||
for (unsigned int j = 0; j < this->children.size(); ++j) {
|
|
||||||
oss << this->children[j]->to_string(t_prepend + " ");
|
|
||||||
}
|
}
|
||||||
return oss.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string internal_to_string() {
|
std::string internal_to_string() {
|
||||||
return to_string();
|
return to_string();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual Boxed_Value eval(chaiscript::detail::Dispatch_Engine &)
|
||||||
|
{
|
||||||
|
Boxed_Value bv;
|
||||||
|
throw std::runtime_error("Undispatched ast_node (internal error)");
|
||||||
|
}
|
||||||
|
|
||||||
|
void replace_child(const AST_NodePtr &t_child, const AST_NodePtr &t_new_child)
|
||||||
|
{
|
||||||
|
std::replace(children.begin(), children.end(), t_child, t_new_child);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
AST_Node(const std::string &t_ast_node_text, int t_id, const boost::shared_ptr<std::string> &t_fname,
|
||||||
|
int t_start_line, int t_start_col, int t_end_line, int t_end_col) :
|
||||||
|
text(t_ast_node_text), identifier(t_id), filename(t_fname),
|
||||||
|
start(t_start_line, t_start_col), end(t_end_line, t_end_col)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
AST_Node(const std::string &t_ast_node_text, int t_id, const boost::shared_ptr<std::string> &t_fname) :
|
||||||
|
text(t_ast_node_text), identifier(t_id), filename(t_fname) {}
|
||||||
|
|
||||||
|
virtual ~AST_Node() {}
|
||||||
|
|
||||||
virtual Boxed_Value eval(chaiscript::detail::Dispatch_Engine &) {
|
|
||||||
Boxed_Value bv;
|
|
||||||
throw std::runtime_error("Undispatched ast_node (internal error)");
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@@ -89,23 +89,30 @@ namespace chaiscript
|
|||||||
struct Int_AST_Node : public AST_Node {
|
struct Int_AST_Node : public AST_Node {
|
||||||
public:
|
public:
|
||||||
Int_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Int, const boost::shared_ptr<std::string> &t_fname=boost::shared_ptr<std::string>(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
|
Int_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Int, const boost::shared_ptr<std::string> &t_fname=boost::shared_ptr<std::string>(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
|
||||||
AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
|
AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col), m_value(const_var(int(atoi(this->text.c_str())))) { }
|
||||||
virtual ~Int_AST_Node() {}
|
virtual ~Int_AST_Node() {}
|
||||||
virtual Boxed_Value eval(chaiscript::detail::Dispatch_Engine &){
|
virtual Boxed_Value eval(chaiscript::detail::Dispatch_Engine &){
|
||||||
return const_var(int(atoi(this->text.c_str())));
|
return m_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Boxed_Value m_value;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Float_AST_Node : public AST_Node {
|
struct Float_AST_Node : public AST_Node {
|
||||||
public:
|
public:
|
||||||
Float_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Float, const boost::shared_ptr<std::string> &t_fname=boost::shared_ptr<std::string>(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
|
Float_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Float, const boost::shared_ptr<std::string> &t_fname=boost::shared_ptr<std::string>(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
|
||||||
AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
|
AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col),
|
||||||
|
m_value(const_var(double(atof(this->text.c_str())))) { }
|
||||||
virtual ~Float_AST_Node() {}
|
virtual ~Float_AST_Node() {}
|
||||||
virtual Boxed_Value eval(chaiscript::detail::Dispatch_Engine &){
|
virtual Boxed_Value eval(chaiscript::detail::Dispatch_Engine &){
|
||||||
return const_var(double(atof(this->text.c_str())));
|
return m_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Boxed_Value m_value;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Id_AST_Node : public AST_Node {
|
struct Id_AST_Node : public AST_Node {
|
||||||
@@ -472,7 +479,7 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
catch(const exception::dispatch_error &e){
|
catch(const exception::dispatch_error &e){
|
||||||
t_ss.set_stack(prev_stack);
|
t_ss.set_stack(prev_stack);
|
||||||
throw exception::eval_error(std::string(e.what()));
|
throw exception::eval_error(std::string(e.what()) + " for function: " + fun_name);
|
||||||
}
|
}
|
||||||
catch(detail::Return_Value &rv) {
|
catch(detail::Return_Value &rv) {
|
||||||
t_ss.set_stack(prev_stack);
|
t_ss.set_stack(prev_stack);
|
||||||
@@ -510,23 +517,30 @@ namespace chaiscript
|
|||||||
struct Quoted_String_AST_Node : public AST_Node {
|
struct Quoted_String_AST_Node : public AST_Node {
|
||||||
public:
|
public:
|
||||||
Quoted_String_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Quoted_String, const boost::shared_ptr<std::string> &t_fname=boost::shared_ptr<std::string>(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
|
Quoted_String_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Quoted_String, const boost::shared_ptr<std::string> &t_fname=boost::shared_ptr<std::string>(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
|
||||||
AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
|
AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col),
|
||||||
|
m_value(const_var(this->text)) { }
|
||||||
virtual ~Quoted_String_AST_Node() {}
|
virtual ~Quoted_String_AST_Node() {}
|
||||||
virtual Boxed_Value eval(chaiscript::detail::Dispatch_Engine &){
|
virtual Boxed_Value eval(chaiscript::detail::Dispatch_Engine &) {
|
||||||
return const_var(this->text);
|
return m_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Boxed_Value m_value;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Single_Quoted_String_AST_Node : public AST_Node {
|
struct Single_Quoted_String_AST_Node : public AST_Node {
|
||||||
public:
|
public:
|
||||||
Single_Quoted_String_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Single_Quoted_String, const boost::shared_ptr<std::string> &t_fname=boost::shared_ptr<std::string>(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
|
Single_Quoted_String_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Single_Quoted_String, const boost::shared_ptr<std::string> &t_fname=boost::shared_ptr<std::string>(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
|
||||||
AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
|
AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col),
|
||||||
|
m_value(const_var(char(this->text[0]))) { }
|
||||||
virtual ~Single_Quoted_String_AST_Node() {}
|
virtual ~Single_Quoted_String_AST_Node() {}
|
||||||
virtual Boxed_Value eval(chaiscript::detail::Dispatch_Engine &){
|
virtual Boxed_Value eval(chaiscript::detail::Dispatch_Engine &){
|
||||||
return const_var(char(this->text[0]));
|
return m_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Boxed_Value m_value;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Lambda_AST_Node : public AST_Node {
|
struct Lambda_AST_Node : public AST_Node {
|
||||||
@@ -656,7 +670,7 @@ namespace chaiscript
|
|||||||
While_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::While, const boost::shared_ptr<std::string> &t_fname=boost::shared_ptr<std::string>(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
|
While_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::While, const boost::shared_ptr<std::string> &t_fname=boost::shared_ptr<std::string>(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
|
||||||
AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
|
AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
|
||||||
virtual ~While_AST_Node() {}
|
virtual ~While_AST_Node() {}
|
||||||
virtual Boxed_Value eval(chaiscript::detail::Dispatch_Engine &t_ss){
|
virtual Boxed_Value eval(chaiscript::detail::Dispatch_Engine &t_ss) {
|
||||||
bool cond;
|
bool cond;
|
||||||
|
|
||||||
t_ss.new_scope();
|
t_ss.new_scope();
|
||||||
|
@@ -1312,7 +1312,12 @@ namespace chaiscript
|
|||||||
has_matches = false;
|
has_matches = false;
|
||||||
if (Keyword("else", true)) {
|
if (Keyword("else", true)) {
|
||||||
if (Keyword("if")) {
|
if (Keyword("if")) {
|
||||||
m_match_stack.back()->text = "else if";
|
AST_NodePtr back(m_match_stack.back());
|
||||||
|
m_match_stack.back() = AST_NodePtr(new eval::If_AST_Node("else if", back->identifier));
|
||||||
|
m_match_stack.back()->start = back->start;
|
||||||
|
m_match_stack.back()->end = back->end;
|
||||||
|
m_match_stack.back()->children = back->children;
|
||||||
|
m_match_stack.back()->annotation = back->annotation;
|
||||||
if (!Char('(')) {
|
if (!Char('(')) {
|
||||||
throw exception::eval_error("Incomplete 'else if' expression", File_Position(m_line, m_col), *m_filename);
|
throw exception::eval_error("Incomplete 'else if' expression", File_Position(m_line, m_col), *m_filename);
|
||||||
}
|
}
|
||||||
|
@@ -62,7 +62,7 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_reflect
|
|||||||
|
|
||||||
CHAISCRIPT_CLASS( m,
|
CHAISCRIPT_CLASS( m,
|
||||||
chaiscript::AST_Node,
|
chaiscript::AST_Node,
|
||||||
(chaiscript::AST_Node (const std::string &, int, const boost::shared_ptr<std::string> &)),
|
,
|
||||||
((text))
|
((text))
|
||||||
((identifier))
|
((identifier))
|
||||||
((filename))
|
((filename))
|
||||||
@@ -70,6 +70,7 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_reflect
|
|||||||
((end))
|
((end))
|
||||||
((internal_to_string))
|
((internal_to_string))
|
||||||
((children))
|
((children))
|
||||||
|
((replace_child))
|
||||||
);
|
);
|
||||||
|
|
||||||
CHAISCRIPT_CLASS( m,
|
CHAISCRIPT_CLASS( m,
|
||||||
|
@@ -8,7 +8,11 @@ assert_equal(eval(a), 7)
|
|||||||
var childs := a.children.front().children
|
var childs := a.children.front().children
|
||||||
var node := childs[0]
|
var node := childs[0]
|
||||||
|
|
||||||
node.text = "9"
|
var parser2 := ChaiScript_Parser()
|
||||||
|
parser2.parse("9", "INPUT")
|
||||||
|
|
||||||
|
|
||||||
|
a.children.front().replace_child(childs[0], parser2.ast())
|
||||||
|
|
||||||
assert_equal(eval(a), 13)
|
assert_equal(eval(a), 13)
|
||||||
assert_equal(node.filename, "INPUT")
|
assert_equal(node.filename, "INPUT")
|
||||||
|
Reference in New Issue
Block a user