diff --git a/mie/include/mie/parse/lex.h b/mie/include/mie/parse/lex.h index 0434d7d..7c37101 100644 --- a/mie/include/mie/parse/lex.h +++ b/mie/include/mie/parse/lex.h @@ -17,6 +17,7 @@ MIE_API void mie_lex_destroy(struct mie_lex *lex); MIE_API enum mie_status mie_lex_get_status(const struct mie_lex *lex); MIE_API struct mie_line_source *mie_lex_get_line_source(const struct mie_lex *lex); +MIE_API const struct mie_file_cell *mie_lex_get_cursor(const struct mie_lex *lex); MIE_API struct mie_token *mie_lex_peek(struct mie_lex *lex); MIE_API void mie_lex_advance(struct mie_lex *lex); diff --git a/mie/include/mie/parse/parser.h b/mie/include/mie/parse/parser.h index 5b65188..885fc41 100644 --- a/mie/include/mie/parse/parser.h +++ b/mie/include/mie/parse/parser.h @@ -25,6 +25,30 @@ struct mie_register; struct mie_attribute_map; struct mie_attribute; +#define MIE_PARSE_ITEM_NONE {.i_type = MIE_PARSER_ITEM_NONE} +#define MIE_PARSE_ITEM_TOKEN(tok) \ + {.i_type = MIE_PARSER_ITEM_TOK, .i_tok = (tok)} +#define MIE_PARSE_ITEM_CSTR(s) {.i_type = MIE_PARSER_ITEM_CSTR, .i_cstr = (s)} + +struct mie_parser_scope { + struct mie_region *s_region; + struct mie_name_map *s_names; +}; + +enum mie_parser_item_type { + MIE_PARSER_ITEM_NONE = 0, + MIE_PARSER_ITEM_TOK, + MIE_PARSER_ITEM_CSTR, +}; + +struct mie_parser_item { + enum mie_parser_item_type i_type; + union { + unsigned int i_tok; + const char *i_cstr; + }; +}; + MIE_API struct mie_parser *mie_parser_create( struct mie_ctx *ctx, struct mie_lex *lex); MIE_API void mie_parser_destroy(struct mie_parser *ctx); @@ -51,6 +75,8 @@ MIE_API bool mie_parser_parse_float( struct mie_parser *ctx, double *out, struct mie_file_span *loc); MIE_API bool mie_parser_parse_word( struct mie_parser *ctx, b_string *out, struct mie_file_span *loc); +MIE_API bool mie_parser_parse_name( + struct mie_parser *ctx, b_string *out, struct mie_file_span *loc); MIE_API bool mie_parser_parse_instname( struct mie_parser *ctx, b_string *out, struct mie_file_span *loc); MIE_API bool mie_parser_parse_graphname( @@ -71,17 +97,22 @@ MIE_API bool mie_parser_parse_symname( struct mie_parser *ctx, b_string *out, struct mie_file_span *loc); MIE_API bool mie_parser_parse_string( struct mie_parser *ctx, b_string *out, struct mie_file_span *loc); -MIE_API bool mie_parser_parse_keyword(struct mie_parser *ctx, const char *kw); +MIE_API bool mie_parser_parse_keyword( + struct mie_parser *ctx, const char *kw, struct mie_file_span *loc); MIE_API bool mie_parser_parse_symbol( struct mie_parser *ctx, enum mie_token_symbol sym); MIE_API bool mie_parser_parse_linefeed(struct mie_parser *ctx); MIE_API bool mie_parser_parse_type( - struct mie_parser *ctx, const struct mie_type **out); + struct mie_parser *ctx, const char *context, + const struct mie_type **out, struct mie_file_span *out_span); MIE_API bool mie_parser_parse_type_list( - struct mie_parser *ctx, MIE_VECTOR_REF_PARAM(const struct mie_type *, out)); + struct mie_parser *ctx, const char *context, + MIE_VECTOR_REF_PARAM(const struct mie_type *, out), + struct mie_file_span *out_span); MIE_API bool mie_parser_parse_function_type( - struct mie_parser *ctx, struct mie_type **out); + struct mie_parser *ctx, const char *context, struct mie_type **out, + struct mie_file_span *out_span); MIE_API bool mie_parser_parse_operand( struct mie_parser *ctx, struct mie_op_arg *out); @@ -89,30 +120,33 @@ MIE_API bool mie_parser_parse_operand_list( struct mie_parser *ctx, MIE_VECTOR_REF_PARAM(struct mie_op_arg, out)); MIE_API bool mie_parser_parse_parameter( - struct mie_parser *ctx, struct mie_op_arg *out); + struct mie_parser *ctx, bool include_type, struct mie_op_arg *out, + const char *context); MIE_API bool mie_parser_parse_parameter_list( - struct mie_parser *ctx, MIE_VECTOR_REF_PARAM(struct mie_op_arg, out)); + struct mie_parser *ctx, bool include_type, + MIE_VECTOR_REF_PARAM(struct mie_op_arg, out), const char *context); MIE_API bool mie_parser_parse_unknown_keyword(struct mie_parser *ctx, b_string *out); MIE_API bool mie_parser_parse_unknown_symbol( struct mie_parser *ctx, enum mie_token_symbol sym); MIE_API bool mie_parser_parse_register( - struct mie_parser *ctx, struct mie_name_map *names, - struct mie_register *out); + struct mie_parser *ctx, struct mie_parser_scope *scope, + const char *context, struct mie_register *out); MIE_API bool mie_parser_parse_register_list( - struct mie_parser *ctx, struct mie_name_map *names, - MIE_VECTOR_REF_PARAM(struct mie_register, out)); + struct mie_parser *ctx, struct mie_parser_scope *scope, + const char *context, MIE_VECTOR_REF_PARAM(struct mie_register, out)); MIE_API bool mie_parser_parse_region( - struct mie_parser *ctx, struct mie_op *parent, struct mie_region *region); + struct mie_parser *ctx, struct mie_op *parent, + struct mie_region *region, struct mie_block *first_block); MIE_API bool mie_parser_parse_region_list( struct mie_parser *ctx, struct mie_op *parent); MIE_API bool mie_parser_parse_anonymous_block( - struct mie_parser *ctx, struct mie_name_map *names, + struct mie_parser *ctx, struct mie_parser_scope *scope, struct mie_block *block); MIE_API bool mie_parser_parse_block( - struct mie_parser *ctx, struct mie_name_map *names, + struct mie_parser *ctx, struct mie_parser_scope *scope, struct mie_block *block); MIE_API bool mie_parser_parse_successor( @@ -122,11 +156,34 @@ MIE_API bool mie_parser_parse_successor_list( MIE_API bool mie_parser_parse_module(struct mie_parser *ctx, struct mie_module *mod); MIE_API bool mie_parser_parse_op( - struct mie_parser *ctx, struct mie_name_map *names, struct mie_op *dest); + struct mie_parser *ctx, struct mie_parser_scope *scope, + struct mie_op *dest); MIE_API bool mie_parser_parse_attribute( struct mie_parser *ctx, const struct mie_attribute **dest); MIE_API bool mie_parser_parse_attribute_map( struct mie_parser *ctx, struct mie_attribute_map *out); +MIE_API struct mie_diag *mie_parser_report_error_simple( + struct mie_parser *parser, const char *dialect, unsigned int diag_class, + unsigned int msg, const struct mie_file_span *loc); +MIE_API void mie_parser_report_unexpected_token_v( + struct mie_parser *parser, + const struct mie_parser_item expected_tokens[], const char *context); +MIE_API void mie_parser_report_unexpected_token_s( + struct mie_parser *parser, const char *expected_token, const char *context); +static inline void mie_parser_report_unexpected_token( + struct mie_parser *parser, unsigned int expected_token, const char *context) +{ + struct mie_parser_item t[] + = {MIE_PARSE_ITEM_TOKEN(expected_token), MIE_PARSE_ITEM_NONE}; + mie_parser_report_unexpected_token_v(parser, t, context); +} + +MIE_API struct mie_name *mie_parser_scope_put_name( + struct mie_parser_scope *scope, struct mie_name *entry, + const char *hint, enum mie_name_map_flags flags); +MIE_API struct mie_register *mie_parser_scope_find_value( + struct mie_parser_scope *scope, const char *name); + #endif diff --git a/mie/include/mie/parse/token.h b/mie/include/mie/parse/token.h index f121cc6..07eedc0 100644 --- a/mie/include/mie/parse/token.h +++ b/mie/include/mie/parse/token.h @@ -39,6 +39,7 @@ enum mie_token_type { MIE_TOK_TYPENAME = 0x4000u, /* word or name, prefixed with a # hash */ MIE_TOK_ATTRIBNAME = 0x8000u, + __MIE_TOK_UBOUND = 0x9000u, }; enum mie_token_value_type { @@ -51,7 +52,7 @@ enum mie_token_value_type { enum mie_token_symbol { MIE_SYM_NONE = 0, - MIE_SYM_COLON, + MIE_SYM_COLON = __MIE_TOK_UBOUND, MIE_SYM_EQUAL, MIE_SYM_COMMA, MIE_SYM_HYPHEN, @@ -64,6 +65,7 @@ enum mie_token_symbol { MIE_SYM_TILDE, MIE_SYM_BANG, MIE_SYM_ATSIGN, + MIE_SYM_QUESTION, MIE_SYM_LEFT_BRACE, MIE_SYM_RIGHT_BRACE, MIE_SYM_LEFT_BRACKET, diff --git a/mie/parse/lex.c b/mie/parse/lex.c index 4878432..2c6f4c4 100644 --- a/mie/parse/lex.c +++ b/mie/parse/lex.c @@ -40,6 +40,7 @@ static struct lex_token_def symbols[] = { LEX_TOKEN_DEF(MIE_SYM_HASH, "#"), LEX_TOKEN_DEF(MIE_SYM_ATSIGN, "@"), LEX_TOKEN_DEF(MIE_SYM_BANG, "!"), + LEX_TOKEN_DEF(MIE_SYM_QUESTION, "?"), LEX_TOKEN_DEF(MIE_SYM_TILDE, "~"), LEX_TOKEN_DEF(MIE_SYM_LEFT_BRACE, "{"), LEX_TOKEN_DEF(MIE_SYM_RIGHT_BRACE, "}"), @@ -216,6 +217,11 @@ struct mie_line_source *mie_lex_get_line_source(const struct mie_lex *lex) return lex->lex_source; } +const struct mie_file_cell *mie_lex_get_cursor(const struct mie_lex *lex) +{ + return &lex->lex_source->s_cursor; +} + static bool char_can_begin_symbol(char c) { for (size_t i = 0; i < nr_symbols; i++) { @@ -526,6 +532,7 @@ static enum mie_status read_ident(struct mie_lex *lex, enum mie_token_type type) return push_string_token(lex, type, s); } else { push_symbol(lex, MIE_SYM_ASTERISK); + lex->lex_token_start.c_col++; return push_string_token(lex, MIE_TOK_WORD, s); } break; diff --git a/mie/parse/parser.c b/mie/parse/parser.c index c787fb8..57aa0fb 100644 --- a/mie/parse/parser.c +++ b/mie/parse/parser.c @@ -1,13 +1,19 @@ +#include #include #include #include +#include +#include +#include #include #include #include #include +#include #include #include #include +#include #include #include #include @@ -235,6 +241,7 @@ bool mie_parser_parse_float( } TOKEN_PARSER(word, MIE_TOK_WORD); +TOKEN_PARSER(name, MIE_TOK_NAME); TOKEN_PARSER(instname, MIE_TOK_INSTNAME); TOKEN_PARSER(graphname, MIE_TOK_GRAPHNAME); TOKEN_PARSER(opname, MIE_TOK_OPNAME); @@ -246,6 +253,17 @@ TOKEN_PARSER(typename, MIE_TOK_TYPENAME); TOKEN_PARSER(symname, MIE_TOK_SYMNAME); TOKEN_PARSER(string, MIE_TOK_STRING); +bool mie_parser_parse_keyword( + struct mie_parser *ctx, const char *kw, struct mie_file_span *loc) +{ + b_string *str = get_temp_string(ctx); + if (!mie_parser_parse_word(ctx, str, loc)) { + return false; + } + + return strcmp(b_string_ptr(str), kw) == 0; +} + bool mie_parser_parse_symbol(struct mie_parser *ctx, enum mie_token_symbol sym) { struct mie_token *tok = mie_lex_peek(ctx->p_lex); @@ -273,7 +291,8 @@ bool mie_parser_parse_linefeed(struct mie_parser *ctx) } static bool parse_builtin_type_name( - struct mie_parser *ctx, const struct mie_type **out) + struct mie_parser *ctx, const char *context, + const struct mie_type **out, struct mie_file_span *out_span) { b_string *name = get_temp_string(ctx); struct mie_file_span loc; @@ -281,6 +300,10 @@ static bool parse_builtin_type_name( return false; } + if (out_span) { + *out_span = loc; + } + const struct mie_type_definition *type_info = NULL; const struct mie_type *type = NULL; size_t width = 0; @@ -314,6 +337,9 @@ static bool parse_builtin_type_name( } if (!type_info) { + mie_parser_report_error_simple( + ctx, "builtin", MIE_BUILTIN_E_UNRESOLVED_TYPE, + MIE_BUILTIN_MSG_UNRESOLVED_BUILTIN_TYPE, &loc); return false; } @@ -342,11 +368,18 @@ static bool parse_builtin_type_name( type = NULL; } + if (out_span) { + out_span->s_end = *mie_lex_get_cursor(ctx->p_lex); + out_span->s_end.c_col--; + } + *out = type; return type != NULL; } -static bool parse_type_name(struct mie_parser *ctx, const struct mie_type **out) +static bool parse_type_name( + struct mie_parser *ctx, const char *context, + const struct mie_type **out, struct mie_file_span *out_span) { b_string *name = get_temp_string(ctx); struct mie_file_span loc; @@ -354,10 +387,17 @@ static bool parse_type_name(struct mie_parser *ctx, const struct mie_type **out) return false; } + if (out_span) { + out_span->s_start = loc.s_start; + } + const struct mie_type_definition *ty_def = get_type_by_full_name(ctx, name); if (!ty_def) { + mie_parser_report_error_simple( + ctx, "builtin", MIE_BUILTIN_E_UNRESOLVED_TYPE, + MIE_BUILTIN_MSG_UNRESOLVED_DIALECT_TYPE, &loc); return false; } @@ -371,31 +411,49 @@ static bool parse_type_name(struct mie_parser *ctx, const struct mie_type **out) ctx->p_ctx, ty_def->ty_parent->d_name, ty_def->ty_name); } + if (out_span) { + out_span->s_end = *mie_lex_get_cursor(ctx->p_lex); + out_span->s_end.c_col--; + } + *out = ty; return ty != NULL; } -static bool parse_composite_type(struct mie_parser *ctx, const struct mie_type **out) +static bool parse_composite_type( + struct mie_parser *ctx, const char *context, + const struct mie_type **out, struct mie_file_span *out_span) { const struct mie_type *temp = NULL; + struct mie_file_span span; MIE_VECTOR_DEFINE(const struct mie_type *, type_list_1); MIE_VECTOR_DEFINE(const struct mie_type *, type_list_2); - if (!mie_parser_parse_type_list(ctx, MIE_VECTOR_REF(type_list_1))) { + if (!mie_parser_parse_type_list( + ctx, context, MIE_VECTOR_REF(type_list_1), &span)) { return false; } + if (out_span) { + *out_span = span; + } + if (!mie_parser_parse_symbol(ctx, MIE_SYM_HYPHEN_RIGHT_ANGLE)) { *out = mie_ctx_get_storage_type( ctx->p_ctx, type_list_1.items, type_list_1.count); + if (out_span) { + out_span->s_end = span.s_end; + } + return *out != NULL; } bool ok = false; if (mie_parser_peek_symbol(ctx) == MIE_SYM_LEFT_PAREN) { - ok = mie_parser_parse_type_list(ctx, MIE_VECTOR_REF(type_list_2)); + ok = mie_parser_parse_type_list( + ctx, context, MIE_VECTOR_REF(type_list_2), &span); } else { - ok = mie_parser_parse_type(ctx, &temp); + ok = mie_parser_parse_type(ctx, context, &temp, &span); if (temp) { mie_vector_push_back(type_list_2, &temp, NULL); @@ -408,6 +466,10 @@ static bool parse_composite_type(struct mie_parser *ctx, const struct mie_type * return false; } + if (out_span) { + out_span->s_end = span.s_end; + } + temp = mie_ctx_get_function_type( ctx->p_ctx, type_list_1.items, type_list_1.count, type_list_2.items, type_list_2.count); @@ -418,34 +480,54 @@ static bool parse_composite_type(struct mie_parser *ctx, const struct mie_type * return temp != NULL; } -bool mie_parser_parse_type(struct mie_parser *ctx, const struct mie_type **out) +bool mie_parser_parse_type( + struct mie_parser *ctx, const char *context, + const struct mie_type **out, struct mie_file_span *out_span) { if (mie_parser_peek_symbol(ctx) == MIE_SYM_LEFT_PAREN) { - return parse_composite_type(ctx, out); + return parse_composite_type(ctx, context, out, out_span); } + struct mie_parser_item expected[] = { + MIE_PARSE_ITEM_TOKEN(MIE_SYM_LEFT_PAREN), + MIE_PARSE_ITEM_TOKEN(MIE_TOK_TYPENAME), + MIE_PARSE_ITEM_NONE, + }; + switch (mie_parser_peek_type(ctx)) { case MIE_TOK_WORD: - return parse_builtin_type_name(ctx, out); + return parse_builtin_type_name(ctx, context, out, out_span); case MIE_TOK_TYPENAME: - return parse_type_name(ctx, out); + return parse_type_name(ctx, context, out, out_span); default: + mie_parser_report_unexpected_token_v(ctx, expected, context); return false; } } bool mie_parser_parse_type_list( - struct mie_parser *ctx, MIE_VECTOR_REF_PARAM(const struct mie_type *, out)) + struct mie_parser *ctx, const char *context, + MIE_VECTOR_REF_PARAM(const struct mie_type *, out), + struct mie_file_span *out_span) { bool ok = false; const struct mie_type **type_slot = NULL; + if (out_span) { + out_span->s_start = *mie_lex_get_cursor(ctx->p_lex); + } if (!mie_parser_parse_symbol(ctx, MIE_SYM_LEFT_PAREN)) { + mie_parser_report_unexpected_token(ctx, MIE_SYM_LEFT_PAREN, context); return false; } if (mie_parser_parse_symbol(ctx, MIE_SYM_RIGHT_PAREN)) { /* empty type list */ + if (out_span) { + out_span->s_end = *mie_lex_get_cursor(ctx->p_lex); + out_span->s_end.c_col--; + } + return true; } @@ -454,7 +536,7 @@ bool mie_parser_parse_type_list( return false; } - if (!mie_parser_parse_type(ctx, type_slot)) { + if (!mie_parser_parse_type(ctx, context, type_slot, NULL)) { mie_vector_ref_pop_back(out, NULL); return false; } @@ -469,13 +551,15 @@ bool mie_parser_parse_type_list( return false; } - if (!mie_parser_parse_type(ctx, type_slot)) { + if (!mie_parser_parse_type(ctx, context, type_slot, NULL)) { mie_vector_ref_pop_back(out, NULL); return false; } } if (!mie_parser_parse_symbol(ctx, MIE_SYM_RIGHT_PAREN)) { + mie_parser_report_unexpected_token( + ctx, MIE_SYM_RIGHT_PAREN, context); return false; } @@ -483,16 +567,23 @@ bool mie_parser_parse_type_list( } MIE_API bool mie_parser_parse_function_type( - struct mie_parser *ctx, struct mie_type **out) + struct mie_parser *ctx, const char *context, struct mie_type **out, + struct mie_file_span *out_span) { const struct mie_type *type = NULL; MIE_VECTOR_DEFINE(const struct mie_type *, in_parts); MIE_VECTOR_DEFINE(const struct mie_type *, out_parts); + struct mie_file_span span; - if (!mie_parser_parse_type_list(ctx, MIE_VECTOR_REF(in_parts))) { + if (!mie_parser_parse_type_list( + ctx, context, MIE_VECTOR_REF(in_parts), &span)) { return false; } + if (out_span) { + out_span->s_start = span.s_start; + } + if (!mie_parser_parse_symbol(ctx, MIE_SYM_HYPHEN_RIGHT_ANGLE)) { mie_vector_destroy(in_parts, NULL); mie_vector_destroy(out_parts, NULL); @@ -501,9 +592,10 @@ MIE_API bool mie_parser_parse_function_type( bool ok = false; if (mie_parser_peek_symbol(ctx) == MIE_SYM_LEFT_PAREN) { - ok = mie_parser_parse_type_list(ctx, MIE_VECTOR_REF(out_parts)); + ok = mie_parser_parse_type_list( + ctx, context, MIE_VECTOR_REF(out_parts), &span); } else { - ok = mie_parser_parse_type(ctx, &type); + ok = mie_parser_parse_type(ctx, context, &type, &span); if (type) { mie_vector_push_back(out_parts, &type, NULL); @@ -516,6 +608,10 @@ MIE_API bool mie_parser_parse_function_type( return false; } + if (out_span) { + out_span->s_end = span.s_end; + } + type = mie_ctx_get_function_type( ctx->p_ctx, in_parts.items, in_parts.count, out_parts.items, out_parts.count); @@ -597,7 +693,9 @@ bool mie_parser_parse_operand_list( return true; } -bool mie_parser_parse_parameter(struct mie_parser *ctx, struct mie_op_arg *out) +bool mie_parser_parse_parameter( + struct mie_parser *ctx, bool include_type, struct mie_op_arg *out, + const char *context) { memset(out, 0x0, sizeof *out); b_string *str = get_temp_string(ctx); @@ -610,16 +708,28 @@ bool mie_parser_parse_parameter(struct mie_parser *ctx, struct mie_op_arg *out) out->arg_unresolved.reg_name = b_string_steal(str); out->arg_unresolved.reg_flags = MIE_REGISTER_F_MACHINE; } else { + struct mie_parser_item required[] = { + MIE_PARSE_ITEM_TOKEN(MIE_TOK_VREGNAME), + MIE_PARSE_ITEM_TOKEN(MIE_TOK_MREGNAME), + MIE_PARSE_ITEM_NONE, + }; + mie_parser_report_unexpected_token_v(ctx, required, context); return false; } out->arg_span = loc; + if (!include_type) { + return true; + } + if (!mie_parser_parse_symbol(ctx, MIE_SYM_COLON)) { + mie_parser_report_unexpected_token(ctx, MIE_SYM_COLON, context); return false; } - if (!mie_parser_parse_type(ctx, &out->arg_unresolved.reg_type)) { + if (!mie_parser_parse_type( + ctx, context, &out->arg_unresolved.reg_type, NULL)) { return false; } @@ -627,7 +737,8 @@ bool mie_parser_parse_parameter(struct mie_parser *ctx, struct mie_op_arg *out) } bool mie_parser_parse_parameter_list( - struct mie_parser *ctx, MIE_VECTOR_REF_PARAM(struct mie_op_arg, out)) + struct mie_parser *ctx, bool include_type, + MIE_VECTOR_REF_PARAM(struct mie_op_arg, out), const char *context) { bool ok = false; struct mie_op_arg *operand = NULL; @@ -643,7 +754,7 @@ bool mie_parser_parse_parameter_list( return false; } - if (!mie_parser_parse_parameter(ctx, operand)) { + if (!mie_parser_parse_parameter(ctx, include_type, operand, context)) { return false; } @@ -659,6 +770,12 @@ bool mie_parser_parse_parameter_list( type = MIE_TOKEN_TYPE(tok); if (type != MIE_TOK_VREGNAME && type != MIE_TOK_MREGNAME) { + struct mie_parser_item required[] = { + MIE_PARSE_ITEM_TOKEN(MIE_TOK_VREGNAME), + MIE_PARSE_ITEM_TOKEN(MIE_TOK_MREGNAME), + MIE_PARSE_ITEM_NONE, + }; + mie_parser_report_unexpected_token_v(ctx, required, context); return false; } @@ -667,7 +784,8 @@ bool mie_parser_parse_parameter_list( return false; } - if (!mie_parser_parse_parameter(ctx, operand)) { + if (!mie_parser_parse_parameter( + ctx, include_type, operand, context)) { return false; } } @@ -676,14 +794,20 @@ bool mie_parser_parse_parameter_list( } bool mie_parser_parse_register( - struct mie_parser *ctx, struct mie_name_map *names, struct mie_register *out) + struct mie_parser *ctx, struct mie_parser_scope *scope, + const char *context, struct mie_register *out) { memset(out, 0x0, sizeof *out); - if (!names) { + if (!scope) { return false; } + struct mie_parser_item expected[] = { + MIE_PARSE_ITEM_TOKEN(MIE_TOK_VREGNAME), + MIE_PARSE_ITEM_TOKEN(MIE_TOK_MREGNAME), + MIE_PARSE_ITEM_NONE, + }; struct mie_token *tok = mie_parser_peek(ctx); enum mie_token_type type = MIE_TOKEN_TYPE(tok); switch (type) { @@ -694,6 +818,7 @@ bool mie_parser_parse_register( out->reg_flags |= MIE_REGISTER_F_MACHINE; break; default: + mie_parser_report_unexpected_token_v(ctx, expected, context); return false; } @@ -701,13 +826,13 @@ bool mie_parser_parse_register( b_string *tmp = get_temp_string(ctx); switch (tok->tok_value_type) { case MIE_TOK_V_STRING: - name = mie_name_map_put( - names, &out->reg_name, tok->tok_str, MIE_NAME_MAP_F_STRICT); + name = mie_parser_scope_put_name( + scope, &out->reg_name, tok->tok_str, MIE_NAME_MAP_F_STRICT); break; case MIE_TOK_V_INT: b_string_append_cstrf(tmp, "%lld", tok->tok_int); - name = mie_name_map_put( - names, &out->reg_name, b_string_ptr(tmp), + name = mie_parser_scope_put_name( + scope, &out->reg_name, b_string_ptr(tmp), MIE_NAME_MAP_F_STRICT); break; default: @@ -717,12 +842,22 @@ bool mie_parser_parse_register( out->reg_span = tok->tok_location; mie_parser_advance(ctx); - return name != NULL; + if (name) { + return true; + } + + struct mie_diag *diag = mie_parser_report_error_simple( + ctx, "builtin", MIE_BUILTIN_E_NAME_ALREADY_IN_USE, + MIE_BUILTIN_MSG_NAME_ALREADY_IN_USE, &tok->tok_location); + mie_diag_push_msg( + diag, ctx->p_ctx, "builtin", + MIE_BUILTIN_MSG_NAME_ALREADY_USED_HERE); + return false; } bool mie_parser_parse_register_list( - struct mie_parser *ctx, struct mie_name_map *names, - MIE_VECTOR_REF_PARAM(struct mie_register, out)) + struct mie_parser *ctx, struct mie_parser_scope *scope, + const char *context, MIE_VECTOR_REF_PARAM(struct mie_register, out)) { bool ok = false; struct mie_register *reg = NULL; @@ -735,7 +870,7 @@ bool mie_parser_parse_register_list( reg = mie_vector_ref_emplace_back(out, &mie_register_vector_ops); - if (!mie_parser_parse_register(ctx, names, reg)) { + if (!mie_parser_parse_register(ctx, scope, context, reg)) { return false; } @@ -756,7 +891,7 @@ bool mie_parser_parse_register_list( reg = mie_vector_ref_emplace_back(out, &mie_register_vector_ops); - if (!mie_parser_parse_register(ctx, names, reg)) { + if (!mie_parser_parse_register(ctx, scope, context, reg)) { return false; } } @@ -765,11 +900,20 @@ bool mie_parser_parse_register_list( } bool mie_parser_parse_region( - struct mie_parser *ctx, struct mie_op *parent, struct mie_region *region) + struct mie_parser *ctx, struct mie_op *parent, + struct mie_region *region, struct mie_block *first_block) { - region->r_names = mie_name_map_create(NULL); + if (mie_op_has_trait(parent, "builtin", "isolated-from-above")) { + region->r_names = mie_name_map_create(NULL); + } + region->r_parent = parent; + struct mie_parser_scope scope = { + .s_region = region, + .s_names = region->r_names, + }; + if (!mie_parser_parse_symbol(ctx, MIE_SYM_LEFT_BRACE)) { return false; } @@ -778,12 +922,14 @@ bool mie_parser_parse_region( return false; } - struct mie_block *block = NULL; + struct mie_block *block = first_block; if (mie_parser_peek_type(ctx) != MIE_TOK_BLOCKNAME) { - block = mie_region_add_block(region); + if (!block) { + block = mie_region_add_block(region); + } - if (!mie_parser_parse_anonymous_block(ctx, region->r_names, block)) { + if (!mie_parser_parse_anonymous_block(ctx, &scope, block)) { return false; } } @@ -795,7 +941,7 @@ bool mie_parser_parse_region( block = mie_region_add_block(region); - if (!mie_parser_parse_block(ctx, region->r_names, block)) { + if (!mie_parser_parse_block(ctx, &scope, block)) { return false; } } @@ -811,7 +957,7 @@ bool mie_parser_parse_region_list(struct mie_parser *ctx, struct mie_op *parent) struct mie_region *region = mie_op_add_region(parent); - if (!mie_parser_parse_region(ctx, parent, region)) { + if (!mie_parser_parse_region(ctx, parent, region, NULL)) { return false; } @@ -826,7 +972,7 @@ bool mie_parser_parse_region_list(struct mie_parser *ctx, struct mie_op *parent) struct mie_region *region = mie_op_add_region(parent); - if (!mie_parser_parse_region(ctx, parent, region)) { + if (!mie_parser_parse_region(ctx, parent, region, NULL)) { return false; } @@ -836,13 +982,14 @@ bool mie_parser_parse_region_list(struct mie_parser *ctx, struct mie_op *parent) } bool mie_parser_parse_anonymous_block( - struct mie_parser *ctx, struct mie_name_map *names, struct mie_block *block) + struct mie_parser *ctx, struct mie_parser_scope *scope, + struct mie_block *block) { mie_parser_parse_linefeed(ctx); struct mie_op *op = mie_block_add_op(block); - if (!mie_parser_parse_op(ctx, names, op)) { + if (!mie_parser_parse_op(ctx, scope, op)) { return false; } @@ -859,7 +1006,7 @@ bool mie_parser_parse_anonymous_block( struct mie_op *op = mie_block_add_op(block); - if (!mie_parser_parse_op(ctx, names, op)) { + if (!mie_parser_parse_op(ctx, scope, op)) { return false; } @@ -872,9 +1019,10 @@ bool mie_parser_parse_anonymous_block( } static bool parse_block_parameters( - struct mie_parser *ctx, struct mie_name_map *names, struct mie_block *block) + struct mie_parser *ctx, struct mie_parser_scope *scope, + struct mie_block *block) { - if (!names) { + if (!scope) { return false; } @@ -884,7 +1032,9 @@ static bool parse_block_parameters( MIE_VECTOR_DEFINE(struct mie_op_arg, block_params); - if (!mie_parser_parse_parameter_list(ctx, MIE_VECTOR_REF(block_params))) { + if (!mie_parser_parse_parameter_list( + ctx, true, MIE_VECTOR_REF(block_params), + "block parameters")) { return false; } @@ -901,8 +1051,8 @@ static bool parse_block_parameters( | MIE_REGISTER_F_BLOCK_PARAM; param_reg->reg_type = block_params.items[i].arg_unresolved.reg_type; param_reg->reg_block = block; - if (!mie_name_map_put( - names, ¶m_reg->reg_name, + if (!mie_parser_scope_put_name( + scope, ¶m_reg->reg_name, block_params.items[i].arg_unresolved.reg_name, MIE_NAME_MAP_F_STRICT)) { return false; @@ -913,9 +1063,10 @@ static bool parse_block_parameters( } bool mie_parser_parse_block( - struct mie_parser *ctx, struct mie_name_map *names, struct mie_block *block) + struct mie_parser *ctx, struct mie_parser_scope *scope, + struct mie_block *block) { - if (!names) { + if (!scope) { return NULL; } @@ -926,8 +1077,8 @@ bool mie_parser_parse_block( return false; } - if (!mie_name_map_put( - names, &block->b_name, b_string_ptr(str), + if (!mie_parser_scope_put_name( + scope, &block->b_name, b_string_ptr(str), MIE_NAME_MAP_F_STRICT)) { return false; } @@ -935,7 +1086,7 @@ bool mie_parser_parse_block( memcpy(&block->b_name.n_span, &span, sizeof span); if (mie_parser_peek_symbol(ctx) == MIE_SYM_LEFT_PAREN - && !parse_block_parameters(ctx, names, block)) { + && !parse_block_parameters(ctx, scope, block)) { return false; } @@ -954,7 +1105,7 @@ bool mie_parser_parse_block( } struct mie_op *op = mie_block_add_op(block); - if (!mie_parser_parse_op(ctx, names, op)) { + if (!mie_parser_parse_op(ctx, scope, op)) { return false; } @@ -986,7 +1137,9 @@ bool mie_parser_parse_successor(struct mie_parser *ctx, struct mie_op_successor goto fail; } - if (!mie_parser_parse_parameter_list(ctx, MIE_VECTOR_REF(out->s_args))) { + if (!mie_parser_parse_parameter_list( + ctx, true, MIE_VECTOR_REF(out->s_args), + "successor arguments")) { goto fail; } @@ -1048,13 +1201,135 @@ bool mie_parser_parse_successor_list( } static bool parse_custom_op( - struct mie_parser *ctx, struct mie_name_map *names, struct mie_op *dest) + struct mie_parser *ctx, struct mie_parser_scope *scope, struct mie_op *dest) { - return false; + b_string *str = get_temp_string(ctx); + struct mie_file_span loc; + if (!mie_parser_parse_name(ctx, str, &dest->op_name_span)) { + return false; + } + + dest->op_name = b_string_steal(str); + + if (!mie_resolve_op_self(dest, ctx->p_ctx)) { + struct mie_diag *diag = mie_ctx_push_diag( + ctx->p_ctx, dest->op_src, &dest->op_name_span.s_start, + "builtin", MIE_BUILTIN_E_UNKNOWN_OP); + mie_diag_push_msg( + diag, ctx->p_ctx, "builtin", MIE_BUILTIN_MSG_UNKNOWN_OP); + struct mie_diag_highlight hl[] = { + MIE_DIAG_HL(ERROR, loc), + }; + struct mie_diag_amendment am[] = { + MIE_DIAG_ADD("~", loc.s_start), + }; + + mie_diag_push_snippet( + diag, loc.s_start.c_row, loc.s_end.c_row, NULL, 0, hl, 1); + + mie_diag_push_msg( + diag, ctx->p_ctx, "builtin", + MIE_BUILTIN_MSG_USE_GENERIC_OP_SYNTAX); + + hl[0].hl_type = MIE_DIAG_HIGHLIGHT_HINT; + hl[0].hl_span.s_end = hl[0].hl_span.s_start; + + mie_diag_push_snippet( + diag, loc.s_start.c_row, loc.s_end.c_row, am, 1, hl, 1); + + return false; + } + + if (!dest->op_info->op_parse) { + struct mie_diag *diag = mie_ctx_push_diag( + ctx->p_ctx, dest->op_src, &loc.s_start, "builtin", + MIE_BUILTIN_E_INTERNAL_ERROR); + mie_diag_push_msg( + diag, ctx->p_ctx, "builtin", + MIE_BUILTIN_MSG_OP_HAS_NO_PARSER); + struct mie_diag_highlight hl[] = { + MIE_DIAG_HL(ERROR, loc), + }; + + mie_diag_push_snippet( + diag, loc.s_start.c_row, loc.s_end.c_row, NULL, 0, hl, 1); + + mie_diag_push_msg( + diag, ctx->p_ctx, "builtin", + MIE_BUILTIN_MSG_DIALECT_INTERNAL_ERROR); + return false; + } + + enum mie_status status = dest->op_info->op_parse(ctx, scope, dest); + return status == MIE_SUCCESS; +} + +static bool parse_builtin_op( + struct mie_parser *ctx, struct mie_parser_scope *scope, struct mie_op *dest) +{ + b_string *str = get_temp_string(ctx); + struct mie_file_span loc; + if (!mie_parser_parse_word(ctx, str, &loc)) { + return false; + } + + dest->op_name = b_bstr_fmt(NULL, "builtin.%s", b_string_ptr(str)); + + if (!mie_resolve_op_self(dest, ctx->p_ctx)) { + struct mie_diag *diag = mie_ctx_push_diag( + ctx->p_ctx, dest->op_src, &loc.s_start, "builtin", + MIE_BUILTIN_E_UNKNOWN_OP); + mie_diag_push_msg( + diag, ctx->p_ctx, "builtin", MIE_BUILTIN_MSG_UNKNOWN_OP); + struct mie_diag_highlight hl[] = { + MIE_DIAG_HL(ERROR, loc), + }; + struct mie_diag_amendment am[] = { + MIE_DIAG_ADD("~", loc.s_start), + }; + + mie_diag_push_snippet( + diag, loc.s_start.c_row, loc.s_end.c_row, NULL, 0, hl, 1); + + mie_diag_push_msg( + diag, ctx->p_ctx, "builtin", + MIE_BUILTIN_MSG_USE_GENERIC_OP_SYNTAX); + + hl[0].hl_type = MIE_DIAG_HIGHLIGHT_HINT; + hl[0].hl_span.s_end = hl[0].hl_span.s_start; + + mie_diag_push_snippet( + diag, loc.s_start.c_row, loc.s_end.c_row, am, 1, hl, 1); + + return false; + } + + if (!dest->op_info->op_parse) { + struct mie_diag *diag = mie_ctx_push_diag( + ctx->p_ctx, dest->op_src, &loc.s_start, "builtin", + MIE_BUILTIN_E_INTERNAL_ERROR); + mie_diag_push_msg( + diag, ctx->p_ctx, "builtin", + MIE_BUILTIN_MSG_OP_HAS_NO_PARSER); + struct mie_diag_highlight hl[] = { + MIE_DIAG_HL(ERROR, loc), + }; + + mie_diag_push_snippet( + diag, loc.s_start.c_row, loc.s_end.c_row, NULL, 0, hl, 1); + + mie_diag_push_msg( + diag, ctx->p_ctx, "builtin", + MIE_BUILTIN_MSG_DIALECT_INTERNAL_ERROR); + return false; + } + + enum mie_status status = dest->op_info->op_parse(ctx, scope, dest); + return status == MIE_SUCCESS; } static bool parse_generic_op( - struct mie_parser *ctx, struct mie_name_map *names, struct mie_op *dest) + struct mie_parser *ctx, struct mie_parser_scope *scope, struct mie_op *dest) { b_string *str = get_temp_string(ctx); struct mie_file_span loc; @@ -1064,6 +1339,10 @@ static bool parse_generic_op( dest->op_name = b_string_steal(str); + /* resolve the op now. we need to know if the op is isolated-from-above + * in order to add register/block names to the correct region name maps. */ + mie_resolve_op_self(dest, ctx->p_ctx); + if (!mie_parser_parse_symbol(ctx, MIE_SYM_LEFT_PAREN)) { return false; } @@ -1115,7 +1394,9 @@ static bool parse_generic_op( } struct mie_function_type *func_type = NULL; - if (!mie_parser_parse_function_type(ctx, (struct mie_type **)&func_type)) { + if (!mie_parser_parse_function_type( + ctx, "operation type signature", + (struct mie_type **)&func_type, NULL)) { return false; } @@ -1142,13 +1423,13 @@ static bool parse_generic_op( } static bool parse_graph_op( - struct mie_parser *ctx, struct mie_name_map *names, struct mie_op *dest) + struct mie_parser *ctx, struct mie_parser_scope *scope, struct mie_op *dest) { return false; } bool mie_parser_parse_op( - struct mie_parser *ctx, struct mie_name_map *names, struct mie_op *dest) + struct mie_parser *ctx, struct mie_parser_scope *scope, struct mie_op *dest) { if (mie_parser_check_eof(ctx)) { return false; @@ -1156,7 +1437,8 @@ bool mie_parser_parse_op( if (mie_parser_check_type(ctx, MIE_TOK_MREGNAME | MIE_TOK_VREGNAME)) { if (!mie_parser_parse_register_list( - ctx, names, MIE_VECTOR_REF(dest->op_result))) { + ctx, scope, "operation results", + MIE_VECTOR_REF(dest->op_result))) { return false; } @@ -1176,13 +1458,16 @@ bool mie_parser_parse_op( if (mie_parser_check_type(ctx, MIE_TOK_NAME)) { /* custom-format operation */ - return parse_custom_op(ctx, names, dest); + return parse_custom_op(ctx, scope, dest); } else if (mie_parser_check_type(ctx, MIE_TOK_OPNAME)) { /* generic-format operation */ - return parse_generic_op(ctx, names, dest); + return parse_generic_op(ctx, scope, dest); } else if (mie_parser_check_type(ctx, MIE_TOK_GRAPHNAME)) { /* graph-node operation */ - return parse_graph_op(ctx, names, dest); + return parse_graph_op(ctx, scope, dest); + } else if (mie_parser_check_type(ctx, MIE_TOK_WORD)) { + /* custom-format builtin operation */ + return parse_builtin_op(ctx, scope, dest); } else { /* not sure what this is */ return false; @@ -1328,3 +1613,252 @@ bool mie_parser_parse_attribute_map( return true; } + +static const char *token_diag_string(unsigned int token) +{ +#define TOK_STR(tok, str) \ + case MIE_TOK_##tok: \ + return str +#define SYM_STR(sym, str) \ + case MIE_SYM_##sym: \ + return str + + switch (token) { + TOK_STR(LINEFEED, "end of line"); + TOK_STR(INT, "integer constant"); + TOK_STR(FLOAT, "floating-point constant"); + TOK_STR(SYMBOL, "symbol"); + TOK_STR(STRING, "string"); + TOK_STR(WORD, "word"); + TOK_STR(NAME, "name"); + TOK_STR(INSTNAME, "instruction name"); + TOK_STR(SYMNAME, "symbol name"); + TOK_STR(OPNAME, "operation name"); + TOK_STR(GRAPHNAME, "graph operation name"); + TOK_STR(VREGNAME, "virtual register name"); + TOK_STR(MREGNAME, "machine register name"); + TOK_STR(BLOCKNAME, "block name"); + TOK_STR(TYPENAME, "type name"); + TOK_STR(ATTRIBNAME, "attribute name"); + SYM_STR(COLON, "`:`"); + SYM_STR(EQUAL, "`=`"); + SYM_STR(COMMA, "`,`"); + SYM_STR(HYPHEN, "`-`"); + SYM_STR(ASTERISK, "`*`"); + SYM_STR(PLUS, "`+`"); + SYM_STR(PERCENT, "`%`"); + SYM_STR(DOLLAR, "`$`"); + SYM_STR(CARET, "`^`"); + SYM_STR(HASH, "`#`"); + SYM_STR(TILDE, "`~`"); + SYM_STR(BANG, "`!`"); + SYM_STR(QUESTION, "`?`"); + SYM_STR(ATSIGN, "`@`"); + SYM_STR(LEFT_BRACE, "`{`"); + SYM_STR(RIGHT_BRACE, "`}`"); + SYM_STR(LEFT_BRACKET, "`[[`"); + SYM_STR(RIGHT_BRACKET, "`]`"); + SYM_STR(LEFT_PAREN, "`(`"); + SYM_STR(RIGHT_PAREN, "`)`"); + SYM_STR(LEFT_ANGLE, "`<`"); + SYM_STR(RIGHT_ANGLE, "`>`"); + SYM_STR(HYPHEN_RIGHT_ANGLE, "`->`"); + default: + return ""; + } +} + +struct mie_diag *mie_parser_report_error_simple( + struct mie_parser *parser, const char *dialect, unsigned int diag_class, + unsigned int msg, const struct mie_file_span *loc) +{ + struct mie_diag *diag = mie_ctx_push_diag( + parser->p_ctx, mie_lex_get_line_source(parser->p_lex), + &loc->s_start, dialect, diag_class); + mie_diag_push_msg(diag, parser->p_ctx, dialect, msg); + + const struct mie_diag_highlight hl[] = { + MIE_DIAG_HL(ERROR, *loc), + }; + + mie_diag_push_snippet( + diag, loc->s_start.c_row, loc->s_end.c_row, NULL, 0, hl, 1); + + return diag; +} + +void mie_parser_report_unexpected_token_v( + struct mie_parser *parser, + const struct mie_parser_item expected_tokens[], const char *context) +{ + b_bstr str; + b_bstr_begin_dynamic(&str); + struct mie_token *tok = mie_lex_peek(parser->p_lex); + + b_bstr_write_cstr(&str, "expected ", NULL); + + for (size_t i = 0; expected_tokens[i].i_type != MIE_PARSER_ITEM_NONE; i++) { + bool end = expected_tokens[i + 1].i_type == MIE_PARSER_ITEM_NONE; + + if (end && i > 0) { + b_bstr_write_cstr(&str, " or ", NULL); + } else if (i > 0) { + b_bstr_write_cstr(&str, ", ", NULL); + } + + switch (expected_tokens[i].i_type) { + case MIE_PARSER_ITEM_TOK: + b_bstr_write_fmt( + &str, NULL, "[blue]%s[reset]", + token_diag_string(expected_tokens[i].i_tok)); + break; + case MIE_PARSER_ITEM_CSTR: + b_bstr_write_fmt( + &str, NULL, "[blue]%s[reset]", + expected_tokens[i].i_cstr); + break; + default: + break; + } + } + + if (context) { + b_bstr_write_fmt( + &str, NULL, " while parsing [cyan]%s[reset]", context); + } + + b_bstr_write_cstr(&str, "; found [red]", NULL); + if (MIE_TOKEN_TYPE(tok) == MIE_TOK_SYMBOL) { + b_bstr_write_cstr(&str, token_diag_string(tok->tok_sym), NULL); + } else if (tok != NULL) { + b_bstr_write_cstr(&str, token_diag_string(tok->tok_type), NULL); + } else { + b_bstr_write_cstr(&str, "end of file", NULL); + } + b_bstr_write_cstr(&str, "[reset]", NULL); + b_bstr_write_cstr(&str, ".", NULL); + + char *s = b_bstr_end(&str); + + const struct mie_file_cell *loc = tok ? &tok->tok_location.s_start + : mie_lex_get_cursor(parser->p_lex); + struct mie_file_span span + = tok ? tok->tok_location + : (struct mie_file_span) { + .s_start = *mie_lex_get_cursor(parser->p_lex), + .s_end = *mie_lex_get_cursor(parser->p_lex), + }; + + struct mie_diag *diag = mie_ctx_push_diag( + parser->p_ctx, mie_lex_get_line_source(parser->p_lex), loc, + "builtin", MIE_BUILTIN_E_UNEXPECTED_TOKEN); + mie_diag_push_string(diag, s); + free(s); + + const struct mie_diag_highlight hl[] = { + MIE_DIAG_HL(ERROR, span), + }; + + mie_diag_push_snippet( + diag, span.s_start.c_row, span.s_end.c_row, NULL, 0, hl, 1); +} + +void mie_parser_report_unexpected_token_s( + struct mie_parser *parser, const char *expected_token, const char *context) +{ + b_bstr str; + b_bstr_begin_dynamic(&str); + struct mie_token *tok = mie_lex_peek(parser->p_lex); + + b_bstr_write_fmt(&str, NULL, "expected [blue]%s[reset]", expected_token); + if (context) { + b_bstr_write_fmt( + &str, NULL, " while parsing [cyan]%s[reset]", context); + } + + b_bstr_write_cstr(&str, "; found [red]", NULL); + + if (MIE_TOKEN_TYPE(tok) == MIE_TOK_SYMBOL) { + b_bstr_write_cstr(&str, token_diag_string(tok->tok_sym), NULL); + } else if (tok != NULL) { + b_bstr_write_cstr(&str, token_diag_string(tok->tok_type), NULL); + } else { + b_bstr_write_cstr(&str, "end of file", NULL); + } + b_bstr_write_cstr(&str, "[reset].", NULL); + + char *s = b_bstr_end(&str); + + const struct mie_file_cell *loc = tok ? &tok->tok_location.s_start + : mie_lex_get_cursor(parser->p_lex); + struct mie_file_span span + = tok ? tok->tok_location + : (struct mie_file_span) { + .s_start = *mie_lex_get_cursor(parser->p_lex), + .s_end = *mie_lex_get_cursor(parser->p_lex), + }; + + struct mie_diag *diag = mie_ctx_push_diag( + parser->p_ctx, mie_lex_get_line_source(parser->p_lex), loc, + "builtin", MIE_BUILTIN_E_UNEXPECTED_TOKEN); + mie_diag_push_string(diag, s); + free(s); + + const struct mie_diag_highlight hl[] = { + MIE_DIAG_HL(ERROR, span), + }; + + mie_diag_push_snippet( + diag, span.s_start.c_row, span.s_end.c_row, NULL, 0, hl, 1); +} + +static struct mie_name_map *find_name_map(struct mie_region *region) +{ + while (region) { + if (region->r_names) { + return region->r_names; + } + + struct mie_op *op = region->r_parent; + struct mie_block *block = op ? op->op_container : NULL; + region = block ? block->b_parent : NULL; + } + + return NULL; +} + +struct mie_name *mie_parser_scope_put_name( + struct mie_parser_scope *scope, struct mie_name *entry, + const char *hint, enum mie_name_map_flags flags) +{ + struct mie_name_map *names = scope ? find_name_map(scope->s_region) : NULL; + if (!names) { + return NULL; + } + + return mie_name_map_put(names, entry, hint, flags); +} + +struct mie_register *mie_parser_scope_find_value( + struct mie_parser_scope *scope, const char *name) +{ + struct mie_region *region = scope ? scope->s_region : NULL; + + bool end = false; + while (region) { + if (region->r_names) { + end = true; + } + + struct mie_register *reg = mie_region_find_register(region, name); + if (reg) { + return reg; + } + + struct mie_op *op = region->r_parent; + struct mie_block *block = op ? op->op_container : NULL; + region = block ? block->b_parent : NULL; + } + + return NULL; +}