Make optimizer pluggable
This commit is contained in:
@@ -181,7 +181,7 @@ namespace chaiscript
|
|||||||
//! to the passed in values
|
//! to the passed in values
|
||||||
bool filter(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const
|
bool filter(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const
|
||||||
{
|
{
|
||||||
assert(m_arity == -1 || (m_arity > 1 && vals.size() == m_arity));
|
assert(m_arity == -1 || (m_arity > 0 && static_cast<int>(vals.size()) == m_arity));
|
||||||
|
|
||||||
if (m_arity < 0)
|
if (m_arity < 0)
|
||||||
{
|
{
|
||||||
|
@@ -72,17 +72,14 @@ namespace chaiscript
|
|||||||
|
|
||||||
chaiscript::detail::Dispatch_Engine m_engine;
|
chaiscript::detail::Dispatch_Engine m_engine;
|
||||||
|
|
||||||
|
std::unique_ptr<parser::ChaiScript_Parser_Base> m_parser;
|
||||||
|
|
||||||
/// Evaluates the given string in by parsing it and running the results through the evaluator
|
/// Evaluates the given string in by parsing it and running the results through the evaluator
|
||||||
Boxed_Value do_eval(const std::string &t_input, const std::string &t_filename = "__EVAL__", bool /* t_internal*/ = false)
|
Boxed_Value do_eval(const std::string &t_input, const std::string &t_filename = "__EVAL__", bool /* t_internal*/ = false)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
parser::ChaiScript_Parser parser;
|
const auto p = m_parser->parse(t_input, t_filename);
|
||||||
if (parser.parse(t_input, t_filename)) {
|
return p->eval(m_engine);
|
||||||
//parser.show_match_stack();
|
|
||||||
return parser.optimized_ast()->eval(m_engine);
|
|
||||||
} else {
|
|
||||||
return Boxed_Value();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (chaiscript::eval::detail::Return_Value &rv) {
|
catch (chaiscript::eval::detail::Return_Value &rv) {
|
||||||
return rv.retval;
|
return rv.retval;
|
||||||
@@ -180,8 +177,8 @@ namespace chaiscript
|
|||||||
m_engine.add(fun([this](const std::string &t_str){ return internal_eval(t_str); }), "eval");
|
m_engine.add(fun([this](const std::string &t_str){ return internal_eval(t_str); }), "eval");
|
||||||
m_engine.add(fun([this](const AST_NodePtr &t_ast){ return eval(t_ast); }), "eval");
|
m_engine.add(fun([this](const AST_NodePtr &t_ast){ return eval(t_ast); }), "eval");
|
||||||
|
|
||||||
m_engine.add(fun([](const std::string &t_str, const bool t_dump){ return parse(t_str, t_dump); }), "parse");
|
m_engine.add(fun([this](const std::string &t_str, const bool t_dump){ return parse(t_str, t_dump); }), "parse");
|
||||||
m_engine.add(fun([](const std::string &t_str){ return parse(t_str); }), "parse");
|
m_engine.add(fun([this](const std::string &t_str){ return parse(t_str); }), "parse");
|
||||||
|
|
||||||
|
|
||||||
m_engine.add(fun([this](const Boxed_Value &t_bv, const std::string &t_name){ add_global_const(t_bv, t_name); }), "add_global_const");
|
m_engine.add(fun([this](const Boxed_Value &t_bv, const std::string &t_name){ add_global_const(t_bv, t_name); }), "add_global_const");
|
||||||
@@ -221,7 +218,8 @@ namespace chaiscript
|
|||||||
ChaiScript(const ModulePtr &t_lib,
|
ChaiScript(const ModulePtr &t_lib,
|
||||||
std::vector<std::string> t_modulepaths = std::vector<std::string>(),
|
std::vector<std::string> t_modulepaths = std::vector<std::string>(),
|
||||||
std::vector<std::string> t_usepaths = std::vector<std::string>())
|
std::vector<std::string> t_usepaths = std::vector<std::string>())
|
||||||
: m_module_paths(std::move(t_modulepaths)), m_use_paths(std::move(t_usepaths))
|
: m_module_paths(std::move(t_modulepaths)), m_use_paths(std::move(t_usepaths)),
|
||||||
|
m_parser(std::make_unique<parser::ChaiScript_Parser<optimizer::For_Loop_Optimizer>>())
|
||||||
{
|
{
|
||||||
if (m_module_paths.empty())
|
if (m_module_paths.empty())
|
||||||
{
|
{
|
||||||
@@ -245,7 +243,8 @@ namespace chaiscript
|
|||||||
/// \param[in] t_usepaths Vector of paths to search when attempting to "use" an included ChaiScript file
|
/// \param[in] t_usepaths Vector of paths to search when attempting to "use" an included ChaiScript file
|
||||||
ChaiScript( std::vector<std::string> t_modulepaths = std::vector<std::string>(),
|
ChaiScript( std::vector<std::string> t_modulepaths = std::vector<std::string>(),
|
||||||
std::vector<std::string> t_usepaths = std::vector<std::string>())
|
std::vector<std::string> t_usepaths = std::vector<std::string>())
|
||||||
: m_module_paths(std::move(t_modulepaths)), m_use_paths(std::move(t_usepaths))
|
: m_module_paths(std::move(t_modulepaths)), m_use_paths(std::move(t_usepaths)),
|
||||||
|
m_parser(std::make_unique<parser::ChaiScript_Parser<optimizer::For_Loop_Optimizer>>())
|
||||||
{
|
{
|
||||||
if (m_module_paths.empty())
|
if (m_module_paths.empty())
|
||||||
{
|
{
|
||||||
@@ -321,18 +320,13 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static 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)
|
||||||
{
|
{
|
||||||
parser::ChaiScript_Parser parser;
|
const auto ast = m_parser->parse(t_input, "PARSE");
|
||||||
if (parser.parse(t_input, "PARSE")) {
|
|
||||||
const auto ast = parser.optimized_ast();
|
|
||||||
if (t_debug_print) {
|
if (t_debug_print) {
|
||||||
parser.debug_print(ast);
|
m_parser->debug_print(ast);
|
||||||
}
|
|
||||||
return parser.optimized_ast();
|
|
||||||
} else {
|
|
||||||
throw chaiscript::exception::eval_error("Unknown error while parsing");
|
|
||||||
}
|
}
|
||||||
|
return ast;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -56,7 +56,21 @@ namespace chaiscript
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
class ChaiScript_Parser {
|
class ChaiScript_Parser_Base
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
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 ~ChaiScript_Parser_Base() = default;
|
||||||
|
ChaiScript_Parser_Base() = default;
|
||||||
|
ChaiScript_Parser_Base(const ChaiScript_Parser_Base &) = default;
|
||||||
|
ChaiScript_Parser_Base(ChaiScript_Parser_Base &&) = default;
|
||||||
|
ChaiScript_Parser_Base &operator=(ChaiScript_Parser_Base &&) = delete;
|
||||||
|
ChaiScript_Parser_Base &operator=(const ChaiScript_Parser_Base &&) = delete;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename Optimizer>
|
||||||
|
class ChaiScript_Parser : public ChaiScript_Parser_Base {
|
||||||
|
|
||||||
static std::array<std::array<bool, detail::lengthof_alphabet>, detail::max_alphabet> build_alphabet()
|
static std::array<std::array<bool, detail::lengthof_alphabet>, detail::max_alphabet> build_alphabet()
|
||||||
{
|
{
|
||||||
@@ -276,24 +290,26 @@ namespace chaiscript
|
|||||||
|
|
||||||
Position m_position;
|
Position m_position;
|
||||||
|
|
||||||
optimizer::For_Loop_Optimizer m_optimizer;
|
Optimizer m_optimizer;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ChaiScript_Parser()
|
explicit ChaiScript_Parser(Optimizer optimizer=Optimizer())
|
||||||
: m_optimizer(optimizer::For_Loop_Optimizer())
|
: m_optimizer(std::move(optimizer))
|
||||||
{
|
{
|
||||||
m_match_stack.reserve(2);
|
m_match_stack.reserve(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
ChaiScript_Parser(const ChaiScript_Parser &) = delete;
|
ChaiScript_Parser(const ChaiScript_Parser &) = default;
|
||||||
ChaiScript_Parser &operator=(const ChaiScript_Parser &) = delete;
|
ChaiScript_Parser &operator=(const ChaiScript_Parser &) = delete;
|
||||||
|
ChaiScript_Parser(ChaiScript_Parser &&) = default;
|
||||||
|
ChaiScript_Parser &operator=(ChaiScript_Parser &&) = delete;
|
||||||
|
|
||||||
|
|
||||||
/// test a char in an m_alphabet
|
/// test a char in an m_alphabet
|
||||||
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 {
|
void debug_print(AST_NodePtr 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 (unsigned int j = 0; j < t->children.size(); ++j) {
|
for (unsigned int j = 0; j < t->children.size(); ++j) {
|
||||||
debug_print(t->children[j], prepend + " ");
|
debug_print(t->children[j], prepend + " ");
|
||||||
@@ -301,10 +317,6 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the front-most AST node
|
/// Returns the front-most AST node
|
||||||
AST_NodePtr ast() const {
|
|
||||||
if (m_match_stack.empty()) throw exception::eval_error("Attempted to access AST of failed parse.");
|
|
||||||
return m_match_stack.front();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void optimize_returns(AST_NodePtr &p)
|
static void optimize_returns(AST_NodePtr &p)
|
||||||
@@ -327,10 +339,10 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
AST_NodePtr optimized_ast(bool t_optimize_returns = true) {
|
AST_NodePtr ast(bool t_optimize_returns = true) {
|
||||||
AST_NodePtr p = ast();
|
auto ptr = m_match_stack.front();
|
||||||
if (t_optimize_returns) { optimize_returns(p); }
|
if (t_optimize_returns) { optimize_returns(ptr); }
|
||||||
return p;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1063,9 +1075,7 @@ namespace chaiscript
|
|||||||
const auto ev_stack_top = m_match_stack.size();
|
const auto ev_stack_top = m_match_stack.size();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
ChaiScript_Parser parser;
|
m_match_stack.push_back(parse(eval_match, "instr eval"));
|
||||||
parser.parse(eval_match, "instr eval");
|
|
||||||
m_match_stack.push_back(parser.ast());
|
|
||||||
} catch (const exception::eval_error &e) {
|
} catch (const exception::eval_error &e) {
|
||||||
throw exception::eval_error(e.what(), File_Position(start.line, start.col), *m_filename);
|
throw exception::eval_error(e.what(), File_Position(start.line, start.col), *m_filename);
|
||||||
}
|
}
|
||||||
@@ -2342,8 +2352,15 @@ namespace chaiscript
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AST_NodePtr parse(const std::string &t_input, const std::string &t_fname) override
|
||||||
|
{
|
||||||
|
ChaiScript_Parser<Optimizer> parser(*this);
|
||||||
|
|
||||||
|
return parser.parse_internal(t_input, t_fname);
|
||||||
|
}
|
||||||
|
|
||||||
/// 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.
|
||||||
bool parse(const std::string &t_input, std::string t_fname) {
|
AST_NodePtr parse_internal(const std::string &t_input, std::string t_fname) {
|
||||||
m_position = Position(t_input.begin(), t_input.end());
|
m_position = Position(t_input.begin(), t_input.end());
|
||||||
m_filename = std::make_shared<std::string>(std::move(t_fname));
|
m_filename = std::make_shared<std::string>(std::move(t_fname));
|
||||||
|
|
||||||
@@ -2359,12 +2376,12 @@ namespace chaiscript
|
|||||||
throw exception::eval_error("Unparsed input", File_Position(m_position.line, m_position.col), t_fname);
|
throw exception::eval_error("Unparsed input", File_Position(m_position.line, m_position.col), t_fname);
|
||||||
} else {
|
} else {
|
||||||
build_match<eval::File_AST_Node>(0);
|
build_match<eval::File_AST_Node>(0);
|
||||||
// debug_print(ast());
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return false;
|
m_match_stack.push_back(chaiscript::make_shared<AST_Node, eval::Noop_AST_Node>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return ast();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user