10 #ifndef CHAISCRIPT_COMMON_HPP_ 11 #define CHAISCRIPT_COMMON_HPP_ 20 #include "../chaiscript_defines.hpp" 21 #include "../dispatchkit/boxed_value.hpp" 22 #include "../dispatchkit/dispatchkit.hpp" 23 #include "../dispatchkit/proxy_functions.hpp" 24 #include "../dispatchkit/type_info.hpp" 25 #include <unordered_set> 29 struct AST_Node_Trace;
38 static bool is_reserved_word(
const T &s) noexcept {
39 const static std::unordered_set<std::uint32_t>
40 words{utility::hash(
"def"), utility::hash(
"fun"), utility::hash(
"while"), utility::hash(
"for"), utility::hash(
"if"), utility::hash(
"else"), utility::hash(
"&&"), utility::hash(
"||"), utility::hash(
","), utility::hash(
"auto"), utility::hash(
"return"), utility::hash(
"break"), utility::hash(
"true"), utility::hash(
"false"), utility::hash(
"class"), utility::hash(
"attr"), utility::hash(
"var"), utility::hash(
"global"), utility::hash(
"GLOBAL"), utility::hash(
"_"), utility::hash(
"__LINE__"), utility::hash(
"__FILE__"), utility::hash(
"__FUNC__"), utility::hash(
"__CLASS__")};
42 return words.count(utility::hash(s)) == 1;
46 static bool valid_object_name(
const T &name) noexcept {
47 return name.find(
"::") == std::string::npos && !is_reserved_word(name);
51 static void validate_object_name(
const T &name) {
52 if (is_reserved_word(name)) {
56 if (name.find(
"::") != std::string::npos) {
69 Unused_Return_Fun_Call,
114 enum class Operator_Precedence {
131 constexpr
const char *ast_node_type_to_string(
AST_Node_Type ast_node_type) noexcept {
132 constexpr
const char *
const ast_node_types[] = {
"Id",
"Fun_Call",
"Unused_Return_Fun_Call",
"Arg_List",
"Equation",
"Var_Decl",
"Assign_Decl",
"Array_Call",
"Dot_Access",
"Lambda",
"Block",
"Scopeless_Block",
"Def",
"While",
"If",
"For",
"Ranged_For",
"Inline_Array",
"Inline_Map",
"Return",
"File",
"Prefix",
"Break",
"Continue",
"Map_Pair",
"Value_Range",
"Inline_Range",
"Try",
"Catch",
"Finally",
"Method",
"Attr_Decl",
"Logical_And",
"Logical_Or",
"Reference",
"Switch",
"Case",
"Default",
"Noop",
"Class",
"Binary",
"Arg",
"Global_Decl",
"Constant",
"Compiled"};
134 return ast_node_types[
static_cast<int>(ast_node_type)];
143 constexpr
File_Position(
int t_file_line,
int t_file_column) noexcept
145 , column(t_file_column) {
152 Parse_Location(std::string t_fname =
"",
const int t_start_line = 0,
const int t_start_col = 0,
const int t_end_line = 0,
const int t_end_col = 0)
153 : start(t_start_line, t_start_col)
154 , end(t_end_line, t_end_col)
155 , filename(std::make_shared<std::string>(std::move(t_fname))) {
159 const int t_start_line = 0,
160 const int t_start_col = 0,
161 const int t_end_line = 0,
162 const int t_end_col = 0)
163 : start(t_start_line, t_start_col)
164 , end(t_end_line, t_end_col)
165 , filename(std::move(t_fname)) {
170 std::shared_ptr<std::string> filename;
177 const std::string text;
180 const std::string &filename()
const noexcept {
return *location.filename; }
182 const File_Position &start()
const noexcept {
return location.start; }
184 const File_Position &end()
const noexcept {
return location.end; }
186 std::string pretty_print()
const {
187 std::ostringstream oss;
191 for (
auto &elem : get_children()) {
192 oss << elem.get().pretty_print() <<
' ';
198 virtual std::vector<std::reference_wrapper<AST_Node>> get_children()
const = 0;
202 std::string
to_string(
const std::string &t_prepend =
"")
const {
203 std::ostringstream oss;
205 oss << t_prepend <<
"(" << ast_node_type_to_string(this->identifier) <<
") " << this->text <<
" : " << this->location.start.line
206 <<
", " << this->location.start.column <<
'\n';
208 for (
auto &elem : get_children()) {
209 oss << elem.get().to_string(t_prepend +
" ");
216 virtual ~
AST_Node() noexcept =
default;
225 , text(std::move(t_ast_node_text))
226 , location(std::move(t_loc)) {
232 using AST_NodePtr_Const = std::unique_ptr<const AST_Node>;
236 const std::string text;
239 const std::string &filename()
const noexcept {
return *location.filename; }
241 const File_Position &start()
const noexcept {
return location.start; }
243 const File_Position &end()
const noexcept {
return location.end; }
245 std::string pretty_print()
const {
246 std::ostringstream oss;
250 for (
const auto &elem : children) {
251 oss << elem.pretty_print() <<
' ';
257 std::vector<AST_Node_Trace> get_children(
const AST_Node &node) {
258 const auto node_children = node.get_children();
259 return std::vector<AST_Node_Trace>(node_children.begin(), node_children.end());
263 : identifier(node.identifier)
265 , location(node.location)
266 , children(get_children(node)) {
269 std::vector<AST_Node_Trace> children;
273 namespace exception {
277 : std::runtime_error(t_reason) {
280 load_module_error(
const std::string &t_name,
const std::vector<load_module_error> &t_errors)
281 : std::runtime_error(format_error(t_name, t_errors)) {
287 static std::string format_error(
const std::string &t_name,
const std::vector<load_module_error> &t_errors) {
288 std::stringstream ss;
289 ss <<
"Error loading module '" << t_name <<
"'\n" 290 <<
" The following locations were searched:\n";
292 for (
const auto &err : t_errors) {
293 ss <<
" " << err.what() <<
"\n";
304 std::string filename;
306 std::vector<AST_Node_Trace> call_stack;
310 const std::string &t_fname,
311 const std::vector<Boxed_Value> &t_parameters,
312 const std::vector<chaiscript::Const_Proxy_Function> &t_functions,
315 : std::runtime_error(format(t_why, t_where, t_fname, t_parameters, t_dot_notation, t_ss))
317 , start_position(t_where)
319 , detail(format_detail(t_functions, t_dot_notation, t_ss)) {
323 const std::vector<Boxed_Value> &t_parameters,
324 const std::vector<chaiscript::Const_Proxy_Function> &t_functions,
327 : std::runtime_error(format(t_why, t_parameters, t_dot_notation, t_ss))
329 , detail(format_detail(t_functions, t_dot_notation, t_ss)) {
333 : std::runtime_error(format(t_why, t_where, t_fname))
335 , start_position(t_where)
336 , filename(t_fname) {
339 explicit eval_error(
const std::string &t_why) noexcept
340 : std::runtime_error(
"Error: \"" + t_why +
"\" ")
346 std::string pretty_print()
const {
347 std::ostringstream ss;
350 if (!call_stack.empty()) {
351 ss <<
"during evaluation at (" << fname(call_stack[0]) <<
" " << startpos(call_stack[0]) <<
")\n";
354 ss <<
" " << fname(call_stack[0]) <<
" (" << startpos(call_stack[0]) <<
") '" << pretty(call_stack[0]) <<
"'";
355 for (
size_t j = 1; j < call_stack.size(); ++j) {
356 if (
id(call_stack[j]) != chaiscript::AST_Node_Type::Block && id(call_stack[j]) != chaiscript::AST_Node_Type::File) {
358 ss <<
" from " << fname(call_stack[j]) <<
" (" << startpos(call_stack[j]) <<
") '" << pretty(call_stack[j]) <<
"'";
375 static std::string pretty(
const T &t) {
376 return t.pretty_print();
380 static const std::string &fname(
const T &t) noexcept {
385 static std::string startpos(
const T &t) {
386 std::ostringstream oss;
387 oss << t.start().line <<
", " << t.start().column;
391 static std::string format_why(
const std::string &t_why) {
return "Error: \"" + t_why +
"\""; }
395 int arity = t_func->get_arity();
396 std::vector<Type_Info> types = t_func->get_param_types();
401 if (t_dot_notation) {
402 retval =
"(Object)." + retval;
404 }
else if (types.size() <= 1) {
407 std::stringstream ss;
410 std::string paramstr;
412 for (
size_t index = 1; index != types.size(); ++index) {
413 paramstr += (types[index].is_const() ?
"const " :
"");
416 if (index == 1 && t_dot_notation) {
418 if (types.size() == 2) {
426 ss << paramstr.substr(0, paramstr.size() - 2);
432 std::shared_ptr<const dispatch::Dynamic_Proxy_Function> dynfun
435 if (dynfun && dynfun->has_parse_tree()) {
440 if (dynfunguard && dynfunguard->has_parse_tree()) {
441 retval +=
" : " + format_guard(dynfunguard->get_parse_tree());
445 retval +=
"\n Defined at " + format_location(dynfun->get_parse_tree());
452 static std::string format_guard(
const T &t) {
453 return t.pretty_print();
457 static std::string format_location(
const T &t) {
458 std::ostringstream oss;
459 oss <<
"(" << t.filename() <<
" " << t.start().line <<
", " << t.start().column <<
")";
463 static std::string format_detail(
const std::vector<chaiscript::Const_Proxy_Function> &t_functions,
466 std::stringstream ss;
467 if (t_functions.size() == 1) {
468 assert(t_functions[0]);
469 ss <<
" Expected: " << format_types(t_functions[0], t_dot_notation, t_ss) <<
'\n';
471 ss <<
" " << t_functions.size() <<
" overloads available:\n";
473 for (
const auto &t_function : t_functions) {
474 ss <<
" " << format_types((t_function), t_dot_notation, t_ss) <<
'\n';
483 std::stringstream ss;
486 if (!t_parameters.empty()) {
487 std::string paramstr;
489 for (
auto itr = t_parameters.begin(); itr != t_parameters.end(); ++itr) {
490 paramstr += (itr->is_const() ?
"const " :
"");
491 paramstr += t_ss.type_name(*itr);
493 if (itr == t_parameters.begin() && t_dot_notation) {
495 if (t_parameters.size() == 1) {
503 ss << paramstr.substr(0, paramstr.size() - 2);
510 static std::string format_filename(
const std::string &t_fname) {
511 std::stringstream ss;
513 if (t_fname !=
"__EVAL__") {
514 ss <<
"in '" << t_fname <<
"' ";
516 ss <<
"during evaluation ";
522 static std::string format_location(
const File_Position &t_where) {
523 std::stringstream ss;
524 ss <<
"at (" << t_where.line <<
", " << t_where.column <<
")";
528 static std::string format(
const std::string &t_why,
530 const std::string &t_fname,
531 const std::vector<Boxed_Value> &t_parameters,
534 std::stringstream ss;
536 ss << format_why(t_why);
539 ss <<
"With parameters: " << format_parameters(t_parameters, t_dot_notation, t_ss);
542 ss << format_filename(t_fname);
545 ss << format_location(t_where);
550 static std::string format(
const std::string &t_why,
551 const std::vector<Boxed_Value> &t_parameters,
554 std::stringstream ss;
556 ss << format_why(t_why);
559 ss <<
"With parameters: " << format_parameters(t_parameters, t_dot_notation, t_ss);
565 static std::string format(
const std::string &t_why,
const File_Position &t_where,
const std::string &t_fname) {
566 std::stringstream ss;
568 ss << format_why(t_why);
571 ss << format_filename(t_fname);
574 ss << format_location(t_where);
583 : std::runtime_error(
"File Not Found: " + t_filename)
584 , filename(t_filename) {
590 std::string filename;
607 virtual AST_NodePtr parse(
const std::string &t_input,
const std::string &t_fname) = 0;
608 virtual void debug_print(
const AST_Node &t, std::string prepend =
"")
const = 0;
609 virtual void *get_tracer_ptr() = 0;
617 T &get_tracer() noexcept {
619 return *
static_cast<T *
>(get_tracer_ptr());
651 m_ds->new_scope(m_ds.stack_holder());
669 m_ds->new_function_call(m_ds.stack_holder(), m_ds.conversion_saves());
672 ~
Function_Push_Pop() { m_ds->pop_function_call(m_ds.stack_holder(), m_ds.conversion_saves()); }
674 void save_params(
const Function_Params &t_params) { m_ds->save_function_params(t_params); }
689 m_ds->new_stack(m_ds.stack_holder());
Thrown if an error occurs while attempting to load a binary module.
Definition: chaiscript_common.hpp:275
Creates a new scope then pops it on destruction.
Definition: chaiscript_common.hpp:681
Special type indicating a call to 'continue'.
Definition: chaiscript_common.hpp:639
Creates a new function call and pops it on destruction.
Definition: chaiscript_common.hpp:661
Exception thrown in the case that an object name is invalid because it is a reserved word...
Definition: dispatchkit.hpp:61
Namespace chaiscript contains every API call that the average user will be concerned with...
Definition: function_params.hpp:16
std::shared_ptr< Module > ModulePtr
Convenience typedef for Module objects to be added to the ChaiScript runtime.
Definition: dispatchkit.hpp:220
Convenience type for file positions.
Definition: chaiscript_common.hpp:139
Definition: chaiscript_common.hpp:605
AST_Node_Type
Types of AST nodes available to the parser and eval.
Definition: chaiscript_common.hpp:66
A wrapper for holding any valid C++ type.
Definition: boxed_value.hpp:24
Thrown in the event that a Boxed_Value cannot be cast to the desired type.
Definition: bad_boxed_cast.hpp:31
std::string get_type_name(const Type_Info &ti) const
Returns the registered name of a known type_info object compares the "bare_type_info" for the broades...
Definition: dispatchkit.hpp:582
ModulePtr(*)() Create_Module_Func
Signature of module entry point that all binary loadable modules must implement.
Definition: chaiscript_common.hpp:63
Creates a new scope then pops it on destruction.
Definition: chaiscript_common.hpp:643
Special type indicating a call to 'break'.
Definition: chaiscript_common.hpp:635
Definition: chaiscript_common.hpp:36
Struct that doubles as both a parser ast_node and an AST node.
Definition: chaiscript_common.hpp:174
std::shared_ptr< const dispatch::Proxy_Function_Base > Const_Proxy_Function
Const version of Proxy_Function.
Definition: proxy_functions.hpp:281
Definition: chaiscript_common.hpp:151
std::shared_ptr< dispatch::Proxy_Function_Base > Proxy_Function
Common typedef used for passing of any registered function in ChaiScript.
Definition: proxy_functions.hpp:277
Special type for returned values.
Definition: chaiscript_common.hpp:630
decltype(auto) boxed_cast(const Boxed_Value &bv) const
casts an object while applying any Dynamic_Conversion available
Definition: dispatchkit.hpp:375
Definition: chaiscript_common.hpp:234
std::string to_string(const std::string &t_prepend="") const
Prints the contents of an AST node, including its children, recursively.
Definition: chaiscript_common.hpp:202
Definition: dispatchkit.hpp:1166
Errors generated during parsing or evaluation.
Definition: chaiscript_common.hpp:301
Exception thrown in the case that an object name is invalid because it contains illegal characters...
Definition: dispatchkit.hpp:79
Main class for the dispatchkit.
Definition: dispatchkit.hpp:354
std::unique_ptr< AST_Node > AST_NodePtr
Typedef for pointers to AST_Node objects. Used in building of the AST_Node tree.
Definition: proxy_functions.hpp:42
A Proxy_Function implementation that is not type safe, the called function is expecting a vector<Boxe...
Definition: proxy_functions.hpp:300
Errors generated when loading a file.
Definition: chaiscript_common.hpp:581