From cd49417972b82042633498e5942014c81e337c97 Mon Sep 17 00:00:00 2001 From: Max Wash Date: Tue, 27 Jan 2026 20:46:44 +0000 Subject: [PATCH] mie: add a system for registering and producing detailed diagnostic messages --- mie/ctx.c | 43 +++ mie/diag/diag.c | 106 +++++++ mie/diag/diag.h | 6 + mie/dialect/builtin/builtin.c | 7 + mie/dialect/builtin/diag.c | 16 ++ mie/include/mie/ctx.h | 12 + mie/include/mie/diag/amendment.h | 36 +++ mie/include/mie/diag/class.h | 18 ++ mie/include/mie/diag/component.h | 34 +++ mie/include/mie/diag/diag.h | 39 +++ mie/include/mie/diag/highlight.h | 18 ++ mie/include/mie/diag/msg.h | 10 + mie/include/mie/diag/snippet.h | 0 mie/include/mie/dialect/builtin.h | 10 + mie/include/mie/dialect/dialect.h | 9 + mie/include/mie/macros.h | 451 +++++++++++++++++------------- mie/include/mie/parse/lex.h | 5 +- mie/parse/lex.c | 28 +- mie/parse/lex.h | 1 + mie/parse/parser.c | 4 +- 20 files changed, 656 insertions(+), 197 deletions(-) create mode 100644 mie/diag/diag.c create mode 100644 mie/diag/diag.h create mode 100644 mie/dialect/builtin/diag.c create mode 100644 mie/include/mie/diag/amendment.h create mode 100644 mie/include/mie/diag/class.h create mode 100644 mie/include/mie/diag/component.h create mode 100644 mie/include/mie/diag/diag.h create mode 100644 mie/include/mie/diag/highlight.h create mode 100644 mie/include/mie/diag/msg.h create mode 100644 mie/include/mie/diag/snippet.h diff --git a/mie/ctx.c b/mie/ctx.c index 69689c3..91b9e84 100644 --- a/mie/ctx.c +++ b/mie/ctx.c @@ -4,6 +4,8 @@ #include #include #include +#include +#include #include #include #include @@ -484,3 +486,44 @@ enum mie_status mie_ctx_get_pass( *out = pass; return status; } + +struct mie_diag *mie_ctx_push_diag( + struct mie_ctx *ctx, struct mie_line_source *src, + const struct mie_file_cell *loc, const char *dialect_name, + unsigned long diag_class) +{ + struct mie_diag *diag = malloc(sizeof *diag); + if (!diag) { + return NULL; + } + + struct mie_dialect *dialect = mie_ctx_get_dialect(ctx, dialect_name); + if (!dialect) { + return NULL; + } + + if (diag_class >= dialect->d_nr_diag_classes) { + return NULL; + } + + memset(diag, 0x0, sizeof *diag); + + diag->diag_src = src; + diag->diag_loc = *loc; + diag->diag_parent = dialect; + diag->diag_class = &dialect->d_diag_classes[diag_class]; + + b_queue_push_back(&ctx->ctx_diag, &diag->diag_entry); + + return diag; +} + +struct mie_diag *mie_ctx_pop_diag(struct mie_ctx *ctx) +{ + b_queue_entry *entry = b_queue_pop_front(&ctx->ctx_diag); + if (!entry) { + return NULL; + } + + return b_unbox(struct mie_diag, entry, diag_entry); +} diff --git a/mie/diag/diag.c b/mie/diag/diag.c new file mode 100644 index 0000000..4b195ae --- /dev/null +++ b/mie/diag/diag.c @@ -0,0 +1,106 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct mie_diag_c_msg *diag_msg_create(const struct mie_diag_msg *content) +{ + struct mie_diag_c_msg *out = malloc(sizeof *out); + if (!out) { + return NULL; + } + + memset(out, 0x0, sizeof *out); + + out->msg_base.c_type = MIE_DIAG_COMPONENT_MSG; + out->msg_content = b_strdup(content->msg_content); + + return out; +} + +struct mie_diag_c_snippet *diag_snippet_create( + unsigned long first_line, unsigned long last_line, + const struct mie_diag_amendment *amendments, size_t nr_amendments, + const struct mie_diag_highlight *highlights, size_t nr_highlights) +{ + struct mie_diag_c_snippet *out = malloc(sizeof *out); + if (!out) { + return NULL; + } + + memset(out, 0x0, sizeof *out); + + out->s_base.c_type = MIE_DIAG_COMPONENT_SNIPPET; + out->s_first_line = first_line; + out->s_last_line = last_line; + + out->s_nr_amendments = nr_amendments; + out->s_amendments = calloc(nr_amendments, sizeof *amendments); + if (!out->s_amendments) { + free(out); + return NULL; + } + memcpy(out->s_amendments, amendments, nr_amendments * sizeof *amendments); + + out->s_nr_highlights = nr_highlights; + out->s_highlights = calloc(nr_highlights, sizeof *highlights); + if (!out->s_highlights) { + free(out->s_amendments); + free(out); + return NULL; + } + memcpy(out->s_highlights, highlights, nr_highlights * sizeof *highlights); + + return out; +} + +void mie_diag_set_location( + struct mie_diag *diag, unsigned long row, unsigned long col) +{ + diag->diag_loc.c_row = row; + diag->diag_loc.c_row = col; +} + +void mie_diag_push_msg( + struct mie_diag *diag, struct mie_ctx *ctx, const char *dialect_name, + unsigned long msg, ...) +{ + struct mie_dialect *dialect = mie_ctx_get_dialect(ctx, dialect_name); + if (!dialect) { + return; + } + + if (msg >= dialect->d_nr_diag_msgs) { + return; + } + + const struct mie_diag_msg *msg_info = &dialect->d_diag_msgs[msg]; + + struct mie_diag_c_msg *c_msg = diag_msg_create(msg_info); + if (!c_msg) { + return; + } + + b_queue_push_back(&diag->diag_components, &c_msg->msg_base.c_entry); +} + +void mie_diag_push_snippet( + struct mie_diag *diag, unsigned long first_line, unsigned long last_line, + const struct mie_diag_amendment *amendments, size_t nr_amendments, + const struct mie_diag_highlight *highlights, size_t nr_highlights) +{ + struct mie_diag_c_snippet *c_snippet = diag_snippet_create( + first_line, last_line, amendments, nr_amendments, highlights, + nr_highlights); + if (!c_snippet) { + return; + } + + b_queue_push_back(&diag->diag_components, &c_snippet->s_base.c_entry); +} diff --git a/mie/diag/diag.h b/mie/diag/diag.h new file mode 100644 index 0000000..d091022 --- /dev/null +++ b/mie/diag/diag.h @@ -0,0 +1,6 @@ +#ifndef _DIAG_DIAG_H_ +#define _DIAG_DIAG_H_ + +#include + +#endif diff --git a/mie/dialect/builtin/builtin.c b/mie/dialect/builtin/builtin.c index 0141ebd..5d24f53 100644 --- a/mie/dialect/builtin/builtin.c +++ b/mie/dialect/builtin/builtin.c @@ -1,4 +1,6 @@ #include +#include +#include #include #include #include @@ -81,9 +83,14 @@ struct mie_attribute *mie_ctx_get_index(struct mie_ctx *ctx, size_t val) dialect->ctx_indices, ctx, val); } +MIE_DIAG_CLASS_LIST_EXTERN(mie_builtin_diag); +MIE_DIAG_MSG_LIST_EXTERN(mie_builtin_msg); + MIE_DIALECT_BEGIN(mie_builtin, struct builtin_dialect, "builtin") MIE_DIALECT_INIT(init); MIE_DIALECT_CLEANUP(cleanup); + MIE_DIALECT_DIAG_CLASS_LIST(mie_builtin_diag); + MIE_DIALECT_DIAG_MSG_LIST(mie_builtin_msg); MIE_DIALECT_ADD_TRAIT(mie_builtin_isolated_from_above); MIE_DIALECT_ADD_TRAIT(mie_builtin_symbol_table); MIE_DIALECT_ADD_TYPE(mie_builtin_int); diff --git a/mie/dialect/builtin/diag.c b/mie/dialect/builtin/diag.c new file mode 100644 index 0000000..1926993 --- /dev/null +++ b/mie/dialect/builtin/diag.c @@ -0,0 +1,16 @@ +#include +#include +#include +#include + +#define MIE_DIAG_CLASS_PREFIX MIE_BUILTIN_E +#define MIE_DIAG_MSG_PREFIX MIE_BUILTIN_MSG + +MIE_DIAG_CLASS_LIST_BEGIN(mie_builtin_diag) + MIE_DIAG_CLASS(UNRECOGNISED_TOKEN, ERROR, "Unrecognised token") + MIE_DIAG_CLASS(UNRESOLVED_VALUE, ERROR, "Unresolved value") +MIE_DIAG_CLASS_LIST_END(mie_builtin_diag) + +MIE_DIAG_MSG_LIST_BEGIN(mie_builtin_msg) + MIE_DIAG_MSG(UNRECOGNISED_TOKEN, "encountered an unrecognised token.") +MIE_DIAG_MSG_LIST_END(mie_builtin_msg) diff --git a/mie/include/mie/ctx.h b/mie/include/mie/ctx.h index e53290e..b009e29 100644 --- a/mie/include/mie/ctx.h +++ b/mie/include/mie/ctx.h @@ -7,7 +7,10 @@ struct mie_op; struct mie_pass; +struct mie_diag; +struct mie_file_cell; struct mie_int_cache; +struct mie_line_source; struct mie_index_cache; struct mie_string_cache; struct mie_attribute_map; @@ -31,6 +34,8 @@ struct mie_ctx { struct mie_id_map ctx_attributes; /* map of struct mie_pass_definition */ struct mie_id_map ctx_passes; + /* queue of struct mie_diag */ + b_queue ctx_diag; }; MIE_API struct mie_ctx *mie_ctx_create(void); @@ -73,4 +78,11 @@ MIE_API enum mie_status mie_ctx_get_pass( struct mie_ctx *ctx, const char *name, const struct mie_attribute_map *args, struct mie_pass **out); +MIE_API struct mie_diag *mie_ctx_push_diag( + struct mie_ctx *ctx, struct mie_line_source *src, + const struct mie_file_cell *loc, const char *dialect, + unsigned long diag_class); + +MIE_API struct mie_diag *mie_ctx_pop_diag(struct mie_ctx *ctx); + #endif diff --git a/mie/include/mie/diag/amendment.h b/mie/include/mie/diag/amendment.h new file mode 100644 index 0000000..1e55e77 --- /dev/null +++ b/mie/include/mie/diag/amendment.h @@ -0,0 +1,36 @@ +#ifndef MIE_DIAG_AMENDMENT_H_ +#define MIE_DIAG_AMENDMENT_H_ + +#include + +enum mie_diag_amendment_type { + MIE_DIAG_AMENDMENT_NONE = 0, + MIE_DIAG_AMENDMENT_ADD, + MIE_DIAG_AMENDMENT_REMOVE, + MIE_DIAG_AMENDMENT_REPLACE, +}; + +struct mie_diag_amendment { + enum mie_diag_amendment_type a_type; + unsigned long __x; + + union { + struct { + struct mie_file_cell a_loc; + char *a_str; + } a_add; + + struct { + struct mie_file_cell a_loc; + unsigned long a_length; + } a_remove; + + struct { + struct mie_file_cell a_loc; + unsigned long a_length; + char *a_str; + } a_replace; + }; +}; + +#endif diff --git a/mie/include/mie/diag/class.h b/mie/include/mie/diag/class.h new file mode 100644 index 0000000..2371efc --- /dev/null +++ b/mie/include/mie/diag/class.h @@ -0,0 +1,18 @@ +#ifndef MIE_DIAG_CLASS_H_ +#define MIE_DIAG_CLASS_H_ + +enum mie_diag_class_type { + MIE_DIAG_CLASS_NONE = 0, + MIE_DIAG_CLASS_HINT, + MIE_DIAG_CLASS_WARNING, + MIE_DIAG_CLASS_ERROR, +}; + +struct mie_diag_class { + unsigned int c_id; + const char *c_id_str_short, *c_id_str_long; + enum mie_diag_class_type c_type; + const char *c_title; +}; + +#endif diff --git a/mie/include/mie/diag/component.h b/mie/include/mie/diag/component.h new file mode 100644 index 0000000..01a3fc1 --- /dev/null +++ b/mie/include/mie/diag/component.h @@ -0,0 +1,34 @@ +#ifndef MIE_DIAG_COMPONENT_H_ +#define MIE_DIAG_COMPONENT_H_ + +#include +#include + +enum mie_diag_component_type { + MIE_DIAG_COMPONENT_NONE = 0, + MIE_DIAG_COMPONENT_MSG, + MIE_DIAG_COMPONENT_SNIPPET, +}; + +struct mie_diag_component { + enum mie_diag_component_type c_type; + b_queue_entry c_entry; +}; + +struct mie_diag_c_snippet { + struct mie_diag_component s_base; + unsigned long s_first_line, s_last_line; + + struct mie_diag_amendment *s_amendments; + size_t s_nr_amendments; + + struct mie_diag_highlight *s_highlights; + size_t s_nr_highlights; +}; + +struct mie_diag_c_msg { + struct mie_diag_component msg_base; + char *msg_content; +}; + +#endif diff --git a/mie/include/mie/diag/diag.h b/mie/include/mie/diag/diag.h new file mode 100644 index 0000000..a59caa2 --- /dev/null +++ b/mie/include/mie/diag/diag.h @@ -0,0 +1,39 @@ +#ifndef MIE_DIAG_DIAG_H_ +#define MIE_DIAG_DIAG_H_ + +#include +#include + +struct mie_ctx; +struct mie_diag_class; +struct mie_diag_amendment; +struct mie_diag_highlight; + +enum mie_diag_type { + MIE_DIAG_NONE = 0, + MIE_DIAG_HINT, + MIE_DIAG_WARNING, + MIE_DIAG_ERROR, +}; + +struct mie_diag { + struct mie_dialect *diag_parent; + const struct mie_diag_class *diag_class; + + struct mie_line_source *diag_src; + struct mie_file_cell diag_loc; + b_queue_entry diag_entry; + b_queue diag_components; +}; + +MIE_API void mie_diag_set_location( + struct mie_diag *diag, unsigned long row, unsigned long col); +MIE_API void mie_diag_push_msg( + struct mie_diag *diag, struct mie_ctx *ctx, const char *dialect, + unsigned long msg, ...); +MIE_API void mie_diag_push_snippet( + struct mie_diag *diag, unsigned long first_line, unsigned long last_line, + const struct mie_diag_amendment *amendmends, size_t nr_amendments, + const struct mie_diag_highlight *highlights, size_t nr_highlights); + +#endif diff --git a/mie/include/mie/diag/highlight.h b/mie/include/mie/diag/highlight.h new file mode 100644 index 0000000..072dba3 --- /dev/null +++ b/mie/include/mie/diag/highlight.h @@ -0,0 +1,18 @@ +#ifndef MIE_DIAG_HIGHLIGHT_H_ +#define MIE_DIAG_HIGHLIGHT_H_ + +#include + +enum mie_diag_highlight_type { + MIE_DIAG_HIGHLIGHT_NONE = 0, + MIE_DIAG_HIGHLIGHT_HINT, + MIE_DIAG_HIGHLIGHT_WARNING, + MIE_DIAG_HIGHLIGHT_ERROR, +}; + +struct mie_diag_highlight { + enum mie_diag_highlight_type hl_type; + struct mie_file_span hl_span; +}; + +#endif diff --git a/mie/include/mie/diag/msg.h b/mie/include/mie/diag/msg.h new file mode 100644 index 0000000..b59c92f --- /dev/null +++ b/mie/include/mie/diag/msg.h @@ -0,0 +1,10 @@ +#ifndef MIE_DIAG_MSG_H_ +#define MIE_DIAG_MSG_H_ + +struct mie_diag_msg { + unsigned int msg_id; + const char *msg_id_str_short, *msg_id_str_long; + const char *msg_content; +}; + +#endif diff --git a/mie/include/mie/diag/snippet.h b/mie/include/mie/diag/snippet.h new file mode 100644 index 0000000..e69de29 diff --git a/mie/include/mie/dialect/builtin.h b/mie/include/mie/dialect/builtin.h index 53a96d6..42a8422 100644 --- a/mie/include/mie/dialect/builtin.h +++ b/mie/include/mie/dialect/builtin.h @@ -15,6 +15,16 @@ struct mie_op; struct mie_int_type; struct mie_float_type; +enum mie_builtin_diag { + MIE_BUILTIN_E_UNRECOGNISED_TOKEN, + MIE_BUILTIN_E_UNRESOLVED_VALUE, +}; + +enum mie_builtin_msg { + MIE_BUILTIN_MSG_UNRECOGNISED_TOKEN, + MIE_BUILTIN_MSG_UNRESOLVED_VALUE, +}; + enum mie_float_width { MIE_FLOAT_32 = 32, MIE_FLOAT_64 = 64, diff --git a/mie/include/mie/dialect/dialect.h b/mie/include/mie/dialect/dialect.h index 5ab5932..e154e98 100644 --- a/mie/include/mie/dialect/dialect.h +++ b/mie/include/mie/dialect/dialect.h @@ -13,6 +13,9 @@ struct mie_op_definition; struct mie_type_definition; struct mie_trait_definition; +struct mie_diag_class; +struct mie_diag_msg; + struct mie_dialect { mie_id d_id; char *d_name; @@ -27,6 +30,12 @@ struct mie_dialect { struct mie_id_map d_attributes; /* map of struct mie_interface_definition */ struct mie_id_map d_interfaces; + /* array of mie_diag_class */ + struct mie_diag_class *d_diag_classes; + size_t d_nr_diag_classes; + /* array of mie_diag_msg */ + struct mie_diag_msg *d_diag_msgs; + size_t d_nr_diag_msgs; enum mie_status (*d_cleanup)(struct mie_dialect *); }; diff --git a/mie/include/mie/macros.h b/mie/include/mie/macros.h index 0afc5a9..c48fe42 100644 --- a/mie/include/mie/macros.h +++ b/mie/include/mie/macros.h @@ -5,180 +5,186 @@ /* DIALECT DEFINITION MACROS */ /******************************************************************************/ -#define MIE_DIALECT_BEGIN(func_prefix, c_struct, dialect_name) \ - struct mie_dialect *func_prefix##_dialect_create(struct mie_ctx *ctx) \ - { \ - struct mie_dialect *self = mie_dialect_create( \ - ctx, dialect_name, sizeof(c_struct)); \ - if (!self) { \ - return NULL; \ - } \ - struct mie_op_definition *op = NULL; \ - struct mie_type_definition *type = NULL; \ - struct mie_trait_definition *trait = NULL; \ - struct mie_attribute_definition *attribute = NULL; \ - struct mie_interface_definition *interface = NULL; +#define MIE_DIALECT_BEGIN(func_prefix, c_struct, dialect_name) \ + struct mie_dialect* func_prefix##_dialect_create(struct mie_ctx* ctx) \ + { \ + struct mie_dialect* self = mie_dialect_create( \ + ctx, dialect_name, sizeof(c_struct)); \ + if (!self) { \ + return NULL; \ + } \ + struct mie_op_definition* op = NULL; \ + struct mie_type_definition* type = NULL; \ + struct mie_trait_definition* trait = NULL; \ + struct mie_attribute_definition* attribute = NULL; \ + struct mie_interface_definition* interface = NULL; -#define MIE_DIALECT_END() \ - return self; \ - } +#define MIE_DIALECT_END() \ + return self; \ + } -#define MIE_DIALECT_INIT(func) func(self) +#define MIE_DIALECT_INIT(func) func(self) #define MIE_DIALECT_CLEANUP(func) self->d_cleanup = (func) -#define MIE_DIALECT_ADD_OP(op_id) \ - extern struct mie_op_definition *op_id##_op_create( \ - struct mie_dialect *, struct mie_ctx *); \ - op = op_id##_op_create(self, ctx) -#define MIE_DIALECT_ADD_TYPE(type_id) \ - extern struct mie_type_definition *type_id##_type_create( \ - struct mie_dialect *, struct mie_ctx *); \ - type = type_id##_type_create(self, ctx) -#define MIE_DIALECT_ADD_TRAIT(trait_id) \ - extern struct mie_trait_definition *trait_id##_trait_create( \ - struct mie_dialect *, struct mie_ctx *); \ - trait = trait_id##_trait_create(self, ctx) -#define MIE_DIALECT_ADD_ATTRIBUTE(attr_id) \ - extern struct mie_attribute_definition *attr_id##_attribute_create( \ - struct mie_dialect *, struct mie_ctx *); \ - attribute = attr_id##_attribute_create(self, ctx) -#define MIE_DIALECT_ADD_INTERFACE(iface_id) \ - extern struct mie_interface_definition *iface_id##_interface_create( \ - struct mie_dialect *, struct mie_ctx *); \ - interface = iface_id##_interface_create(self, ctx) +#define MIE_DIALECT_DIAG_CLASS_LIST(list) \ + self->d_diag_classes = (list); \ + self->d_nr_diag_classes = (list##_count) +#define MIE_DIALECT_DIAG_MSG_LIST(list) \ + self->d_diag_msgs = (list); \ + self->d_nr_diag_msgs = (list##_count) +#define MIE_DIALECT_ADD_OP(op_id) \ + extern struct mie_op_definition* op_id##_op_create( \ + struct mie_dialect*, struct mie_ctx*); \ + op = op_id##_op_create(self, ctx) +#define MIE_DIALECT_ADD_TYPE(type_id) \ + extern struct mie_type_definition* type_id##_type_create( \ + struct mie_dialect*, struct mie_ctx*); \ + type = type_id##_type_create(self, ctx) +#define MIE_DIALECT_ADD_TRAIT(trait_id) \ + extern struct mie_trait_definition* trait_id##_trait_create( \ + struct mie_dialect*, struct mie_ctx*); \ + trait = trait_id##_trait_create(self, ctx) +#define MIE_DIALECT_ADD_ATTRIBUTE(attr_id) \ + extern struct mie_attribute_definition* attr_id##_attribute_create( \ + struct mie_dialect*, struct mie_ctx*); \ + attribute = attr_id##_attribute_create(self, ctx) +#define MIE_DIALECT_ADD_INTERFACE(iface_id) \ + extern struct mie_interface_definition* iface_id##_interface_create( \ + struct mie_dialect*, struct mie_ctx*); \ + interface = iface_id##_interface_create(self, ctx) /******************************************************************************/ /* OP DEFINITION MACROS */ /******************************************************************************/ -#define MIE_OP_DEFINITION_BEGIN(func_prefix, op_name) \ - struct mie_op_definition *func_prefix##_op_create( \ - struct mie_dialect *d, struct mie_ctx *ctx) \ - { \ - struct mie_op_definition *op \ - = mie_op_definition_create(d, op_name); \ - if (!op) { \ - return NULL; \ - } \ - const struct mie_trait *trait = NULL; \ - struct mie_interface *i = NULL; \ - const struct mie_interface_definition *id = NULL; +#define MIE_OP_DEFINITION_BEGIN(func_prefix, op_name) \ + struct mie_op_definition* func_prefix##_op_create( \ + struct mie_dialect* d, struct mie_ctx* ctx) \ + { \ + struct mie_op_definition* op \ + = mie_op_definition_create(d, op_name); \ + if (!op) { \ + return NULL; \ + } \ + const struct mie_trait* trait = NULL; \ + struct mie_interface* i = NULL; \ + const struct mie_interface_definition* id = NULL; -#define MIE_OP_DEFINITION_END() \ - return op; \ - } +#define MIE_OP_DEFINITION_END() \ + return op; \ + } #define MIE_OP_DEFINITION_PRINT(func) op->op_print = (func) #define MIE_OP_DEFINITION_PARSE(func) op->op_parse = (func) -#define MIE_OP_DEFINITION_TRAIT(trait_dialect, trait_name) \ - trait = mie_ctx_get_trait(ctx, trait_dialect, trait_name); \ - mie_op_definition_add_trait(op, trait); -#define MIE_OP_INTERFACE_BEGIN(dialect_name, if_name, c_struct) \ - id = mie_ctx_get_interface_definition(ctx, dialect_name, if_name); \ - if (id) { \ - c_struct *iface = (c_struct *)mie_interface_create(id); +#define MIE_OP_DEFINITION_TRAIT(trait_dialect, trait_name) \ + trait = mie_ctx_get_trait(ctx, trait_dialect, trait_name); \ + mie_op_definition_add_trait(op, trait); +#define MIE_OP_INTERFACE_BEGIN(dialect_name, if_name, c_struct) \ + id = mie_ctx_get_interface_definition(ctx, dialect_name, if_name); \ + if (id) { \ + c_struct* iface = (c_struct*)mie_interface_create(id); #define MIE_OP_INTERFACE_FUNC(func_name) iface->func_name -#define MIE_OP_INTERFACE_END() \ - mie_op_definition_add_interface(op, (struct mie_interface *)iface); \ - } +#define MIE_OP_INTERFACE_END() \ + mie_op_definition_add_interface(op, (struct mie_interface*)iface); \ + } /******************************************************************************/ /* TYPE DEFINITION MACROS */ /******************************************************************************/ -#define MIE_TYPE_DEFINITION_BEGIN(func_prefix, type_name) \ - struct mie_type_definition *func_prefix##_type_create( \ - struct mie_dialect *d, struct mie_ctx *ctx) \ - { \ - struct mie_type_definition *type \ - = mie_type_definition_create(d, type_name); \ - if (!type) { \ - return NULL; \ - } \ - const struct mie_trait *trait = NULL; +#define MIE_TYPE_DEFINITION_BEGIN(func_prefix, type_name) \ + struct mie_type_definition* func_prefix##_type_create( \ + struct mie_dialect* d, struct mie_ctx* ctx) \ + { \ + struct mie_type_definition* type \ + = mie_type_definition_create(d, type_name); \ + if (!type) { \ + return NULL; \ + } \ + const struct mie_trait* trait = NULL; -#define MIE_TYPE_DEFINITION_END() \ - return type; \ - } +#define MIE_TYPE_DEFINITION_END() \ + return type; \ + } -#define MIE_TYPE_DEFINITION_FLAGS(flags) type->ty_flags = flags -#define MIE_TYPE_DEFINITION_STRUCT(name) type->ty_data_size = sizeof(name) -#define MIE_TYPE_DEFINITION_INIT(func) type->ty_init = (func) -#define MIE_TYPE_DEFINITION_PRINT(func) type->ty_print = (func) -#define MIE_TYPE_DEFINITION_PARSE(func) type->ty_parse = (func) +#define MIE_TYPE_DEFINITION_FLAGS(flags) type->ty_flags = flags +#define MIE_TYPE_DEFINITION_STRUCT(name) type->ty_data_size = sizeof(name) +#define MIE_TYPE_DEFINITION_INIT(func) type->ty_init = (func) +#define MIE_TYPE_DEFINITION_PRINT(func) type->ty_print = (func) +#define MIE_TYPE_DEFINITION_PARSE(func) type->ty_parse = (func) #define MIE_TYPE_DEFINITION_BUILD_ID(func) type->ty_build_id = (func) -#define MIE_TYPE_DEFINITION_INIT(func) type->ty_init = (func) -#define MIE_TYPE_DEFINITION_CLEANUP(func) type->ty_cleanup = (func) -#define MIE_TYPE_DEFINITION_TRAIT(trait_dialect, trait_name) \ - trait = mie_ctx_get_trait(ctx, trait_dialect, trait_name); \ - mie_type_definition_add_trait(type, trait); +#define MIE_TYPE_DEFINITION_INIT(func) type->ty_init = (func) +#define MIE_TYPE_DEFINITION_CLEANUP(func) type->ty_cleanup = (func) +#define MIE_TYPE_DEFINITION_TRAIT(trait_dialect, trait_name) \ + trait = mie_ctx_get_trait(ctx, trait_dialect, trait_name); \ + mie_type_definition_add_trait(type, trait); /******************************************************************************/ /* TRAIT DEFINITION MACROS */ /******************************************************************************/ -#define MIE_TRAIT_DEFINITION_BEGIN(func_prefix, trait_name) \ - struct mie_trait_definition *func_prefix##_trait_create( \ - struct mie_dialect *d, struct mie_ctx *ctx) \ - { \ - struct mie_trait_definition *trait \ - = mie_trait_definition_create(d, trait_name); \ - if (!trait) { \ - return NULL; \ - } +#define MIE_TRAIT_DEFINITION_BEGIN(func_prefix, trait_name) \ + struct mie_trait_definition* func_prefix##_trait_create( \ + struct mie_dialect* d, struct mie_ctx* ctx) \ + { \ + struct mie_trait_definition* trait \ + = mie_trait_definition_create(d, trait_name); \ + if (!trait) { \ + return NULL; \ + } -#define MIE_TRAIT_DEFINITION_END() \ - return trait; \ - } +#define MIE_TRAIT_DEFINITION_END() \ + return trait; \ + } #define MIE_TRAIT_DEFINITION_TARGETS(targets) trait->tr_target = (targets) -#define MIE_TRAIT_DEFINITION_STRUCT(name) trait->tr_data_size = sizeof(name) -#define MIE_TRAIT_DEFINITION_PRINT(func) trait->tr_print = (func) -#define MIE_TRAIT_DEFINITION_BUILD_ID(func) trait->tr_build_id = (func) -#define MIE_TRAIT_DEFINITION_CLEANUP(func) trait->tr_cleanup = (func) -#define MIE_TRAIT_DEFINITION_VALIDATE(func) trait->tr_validate = (func) +#define MIE_TRAIT_DEFINITION_STRUCT(name) trait->tr_data_size = sizeof(name) +#define MIE_TRAIT_DEFINITION_PRINT(func) trait->tr_print = (func) +#define MIE_TRAIT_DEFINITION_BUILD_ID(func) trait->tr_build_id = (func) +#define MIE_TRAIT_DEFINITION_CLEANUP(func) trait->tr_cleanup = (func) +#define MIE_TRAIT_DEFINITION_VALIDATE(func) trait->tr_validate = (func) /******************************************************************************/ /* ATTRIBUTE DEFINITION MACROS */ /******************************************************************************/ -#define MIE_ATTRIBUTE_DEFINITION_BEGIN(func_prefix, attribute_name) \ - struct mie_attribute_definition *func_prefix##_attribute_create( \ - struct mie_dialect *d, struct mie_ctx *ctx) \ - { \ - struct mie_attribute_definition *attribute \ - = mie_attribute_definition_create(d, attribute_name); \ - if (!attribute) { \ - return NULL; \ - } +#define MIE_ATTRIBUTE_DEFINITION_BEGIN(func_prefix, attribute_name) \ + struct mie_attribute_definition* func_prefix##_attribute_create( \ + struct mie_dialect* d, struct mie_ctx* ctx) \ + { \ + struct mie_attribute_definition* attribute \ + = mie_attribute_definition_create(d, attribute_name); \ + if (!attribute) { \ + return NULL; \ + } -#define MIE_ATTRIBUTE_DEFINITION_END() \ - return attribute; \ - } +#define MIE_ATTRIBUTE_DEFINITION_END() \ + return attribute; \ + } -#define MIE_ATTRIBUTE_DEFINITION_STRUCT(name) \ - attribute->a_data_size = sizeof(name) -#define MIE_ATTRIBUTE_DEFINITION_INIT(func) attribute->a_init = (func) +#define MIE_ATTRIBUTE_DEFINITION_STRUCT(name) \ + attribute->a_data_size = sizeof(name) +#define MIE_ATTRIBUTE_DEFINITION_INIT(func) attribute->a_init = (func) #define MIE_ATTRIBUTE_DEFINITION_CLEANUP(func) attribute->a_cleanup = (func) -#define MIE_ATTRIBUTE_DEFINITION_PRINT(func) attribute->a_print = (func) -#define MIE_ATTRIBUTE_DEFINITION_PARSE(func) attribute->a_parse = (func) +#define MIE_ATTRIBUTE_DEFINITION_PRINT(func) attribute->a_print = (func) +#define MIE_ATTRIBUTE_DEFINITION_PARSE(func) attribute->a_parse = (func) /******************************************************************************/ /* INTERFACE DEFINITION MACROS */ /******************************************************************************/ -#define MIE_INTERFACE_DEFINITION_BEGIN(func_prefix, iface_name) \ - struct mie_interface_definition *func_prefix##_interface_create( \ - struct mie_dialect *d, struct mie_ctx *ctx) \ - { \ - struct mie_interface_definition *i \ - = mie_interface_definition_create(d, iface_name); \ - if (!i) { \ - return NULL; \ - } +#define MIE_INTERFACE_DEFINITION_BEGIN(func_prefix, iface_name) \ + struct mie_interface_definition* func_prefix##_interface_create( \ + struct mie_dialect* d, struct mie_ctx* ctx) \ + { \ + struct mie_interface_definition* i \ + = mie_interface_definition_create(d, iface_name); \ + if (!i) { \ + return NULL; \ + } -#define MIE_INTERFACE_DEFINITION_END() \ - return i; \ - } +#define MIE_INTERFACE_DEFINITION_END() \ + return i; \ + } #define MIE_INTERFACE_DEFINITION_STRUCT(name) i->if_size = sizeof(name) @@ -186,84 +192,143 @@ /* PASS DEFINITION MACROS */ /******************************************************************************/ -#define MIE_PASS_DEFINITION_BEGIN(prefix) \ - struct mie_pass_definition *prefix##_pass_create(struct mie_ctx *ctx) \ - { \ - struct mie_pass_definition *p = mie_pass_definition_create(); \ - if (!p) { \ - return NULL; \ - } +#define MIE_PASS_DEFINITION_BEGIN(prefix) \ + struct mie_pass_definition* prefix##_pass_create(struct mie_ctx* ctx) \ + { \ + struct mie_pass_definition* p = mie_pass_definition_create(); \ + if (!p) { \ + return NULL; \ + } -#define MIE_PASS_DEFINITION_END() \ - if (mie_ctx_register_pass(ctx, p) != MIE_SUCCESS) { \ - return NULL; \ - } \ - return p; \ - } +#define MIE_PASS_DEFINITION_END() \ + if (mie_ctx_register_pass(ctx, p) != MIE_SUCCESS) { \ + return NULL; \ + } \ + return p; \ + } -#define MIE_PASS_NAME(name) p->p_name = (name) +#define MIE_PASS_NAME(name) p->p_name = (name) #define MIE_PASS_DESCRIPTION(desc) p->p_description = (desc) -#define MIE_PASS_STRUCT(c_struct) p->p_data_size = sizeof(c_struct) -#define MIE_PASS_TYPE(type) p->p_type = (type) -#define MIE_PASS_INIT(func) p->p_init = (func) -#define MIE_PASS_TRANSFORM(func) \ - p->p_transform = (func); \ - p->p_type = MIE_PASS_TRANSFORM -#define MIE_PASS_ANALYSE(func) \ - p->p_analyse = (func); \ - p->p_type = MIE_PASS_ANALYSE -#define MIE_PASS_FILTER_OP(dialect, op) \ - p->p_filter.f_op = mie_ctx_get_op_definition(ctx, dialect, op) -#define MIE_PASS_FILTER_TRAIT(dialect, tr) \ - p->p_filter.f_trait = mie_ctx_get_trait_definition(ctx, dialect, tr) -#define MIE_PASS_FILTER_INTERFACE(dialect, ifn) \ - p->p_filter.f_iface = mie_ctx_get_iface_definition(ctx, dialect, ifn) +#define MIE_PASS_STRUCT(c_struct) p->p_data_size = sizeof(c_struct) +#define MIE_PASS_TYPE(type) p->p_type = (type) +#define MIE_PASS_INIT(func) p->p_init = (func) +#define MIE_PASS_TRANSFORM(func) \ + p->p_transform = (func); \ + p->p_type = MIE_PASS_TRANSFORM +#define MIE_PASS_ANALYSE(func) \ + p->p_analyse = (func); \ + p->p_type = MIE_PASS_ANALYSE +#define MIE_PASS_FILTER_OP(dialect, op) \ + p->p_filter.f_op = mie_ctx_get_op_definition(ctx, dialect, op) +#define MIE_PASS_FILTER_TRAIT(dialect, tr) \ + p->p_filter.f_trait = mie_ctx_get_trait_definition(ctx, dialect, tr) +#define MIE_PASS_FILTER_INTERFACE(dialect, ifn) \ + p->p_filter.f_iface = mie_ctx_get_iface_definition(ctx, dialect, ifn) /******************************************************************************/ /* PASS GROUP MACROS */ /******************************************************************************/ -#define MIE_PASS_GROUP_BEGIN(prefix) \ - enum mie_status prefix##_passes_register(struct mie_ctx *ctx) \ - { \ - struct mie_pass_definition *pass = NULL; +#define MIE_PASS_GROUP_BEGIN(prefix) \ + enum mie_status prefix##_passes_register(struct mie_ctx* ctx) \ + { \ + struct mie_pass_definition* pass = NULL; -#define MIE_PASS_GROUP_END() \ - return MIE_SUCCESS; \ - } +#define MIE_PASS_GROUP_END() \ + return MIE_SUCCESS; \ + } -#define MIE_PASS_GROUP_DECLARATION(prefix) \ - enum mie_status prefix##_passes_register(struct mie_ctx *); +#define MIE_PASS_GROUP_DECLARATION(prefix) \ + enum mie_status prefix##_passes_register(struct mie_ctx*); -#define MIE_PASS_GROUP_ADD_PASS(id) \ - do { \ - extern struct mie_pass_definition *id##_pass_create( \ - struct mie_ctx *); \ - pass = id##_pass_create(ctx); \ - if (!pass) { \ - return MIE_ERR_INTERNAL_FAILURE; \ - } \ - } while (0) +#define MIE_PASS_GROUP_ADD_PASS(id) \ + do { \ + extern struct mie_pass_definition* id##_pass_create( \ + struct mie_ctx*); \ + pass = id##_pass_create(ctx); \ + if (!pass) { \ + return MIE_ERR_INTERNAL_FAILURE; \ + } \ + } while (0) #endif /******************************************************************************/ -/* REWRITE PATTER MACROS */ +/* REWRITE PATTERN MACROS */ /******************************************************************************/ -#define MIE_REWRITE_PATTERN_BEGIN(name) \ - struct mie_pattern *name##_create(struct mie_pattern_set *set) \ - { \ - struct mie_pattern *self = mie_pattern_set_add(set); \ - if (!self) { \ - return NULL; \ - } -#define MIE_REWRITE_PATTERN_END() \ - return self; \ - } +#define MIE_REWRITE_PATTERN_BEGIN(name) \ + struct mie_pattern* name##_create(struct mie_pattern_set* set) \ + { \ + struct mie_pattern* self = mie_pattern_set_add(set); \ + if (!self) { \ + return NULL; \ + } +#define MIE_REWRITE_PATTERN_END() \ + return self; \ + } -#define MIE_REWRITE_PATTERN_ROOT(dialect_name, op_name) \ - self->p_root.t_dialect_name = (dialect_name); \ - self->p_root.t_op_name = (op_name) -#define MIE_REWRITE_PATTERN_MATCH(func) self->p_match = (func) +#define MIE_REWRITE_PATTERN_ROOT(dialect_name, op_name) \ + self->p_root.t_dialect_name = (dialect_name); \ + self->p_root.t_op_name = (op_name) +#define MIE_REWRITE_PATTERN_MATCH(func) self->p_match = (func) #define MIE_REWRITE_PATTERN_REWRITE(func) self->p_rewrite = (func) + +/******************************************************************************/ +/* DIAG CLASS MACROS */ +/******************************************************************************/ + +#define __MIE_CNAME2(x, y) x##_##y +#define __MIE_CNAME1(x, y) __MIE_CNAME2(x, y) +#define __MIE_CNAME(fun) __MIE_CNAME1(MIE_DIAG_CLASS_PREFIX, fun) + +#define __MIE_CSNAME2(x, y) #x #y +#define __MIE_CSNAME1(x, y) __MIE_CSNAME2(x, y) +#define __MIE_CSNAME(fun) __MIE_CSNAME1(MIE_DIAG_CLASS_PREFIX, fun) + +#define MIE_DIAG_CLASS_LIST_EXTERN(list_name) \ + extern struct mie_diag_class list_name[]; \ + extern const size_t list_name##_count +#define MIE_DIAG_CLASS_LIST_BEGIN(list_name) \ + struct mie_diag_class list_name[] = { +#define MIE_DIAG_CLASS_LIST_END(list_name) \ + } \ + ; \ + const size_t list_name##_count = sizeof(list_name) / sizeof(list_name[0]); +#define MIE_DIAG_CLASS(id, type, title) \ + [__MIE_CNAME(id)] = { \ + .c_id = __MIE_CNAME(id), \ + .c_type = MIE_DIAG_CLASS_##type, \ + .c_title = (title), \ + .c_id_str_short = #id, \ + .c_id_str_long = __MIE_CSNAME(id), \ + }, + +/******************************************************************************/ +/* DIAG MSG MACROS */ +/******************************************************************************/ + +#define __MIE_MNAME2(x, y) x##_##y +#define __MIE_MNAME1(x, y) __MIE_CNAME2(x, y) +#define __MIE_MNAME(fun) __MIE_CNAME1(MIE_DIAG_MSG_PREFIX, fun) + +#define __MIE_MSNAME2(x, y) #x #y +#define __MIE_MSNAME1(x, y) __MIE_CSNAME2(x, y) +#define __MIE_MSNAME(fun) __MIE_CSNAME1(MIE_DIAG_MSG_PREFIX, fun) + +#define MIE_DIAG_MSG_LIST_EXTERN(list_name) \ + extern struct mie_diag_msg list_name[]; \ + extern const size_t list_name##_count +#define MIE_DIAG_MSG_LIST_BEGIN(list_name) \ + struct mie_diag_msg list_name[] = { +#define MIE_DIAG_MSG_LIST_END(list_name) \ + } \ + ; \ + const size_t list_name##_count = sizeof(list_name) / sizeof(list_name[0]); +#define MIE_DIAG_MSG(id, content) \ + [__MIE_MNAME(id)] = { \ + .msg_id = __MIE_MNAME(id), \ + .msg_content = (content), \ + .msg_id_str_short = #id, \ + .msg_id_str_long = __MIE_MSNAME(id), \ + }, diff --git a/mie/include/mie/parse/lex.h b/mie/include/mie/parse/lex.h index 3ba7e57..b6a92d6 100644 --- a/mie/include/mie/parse/lex.h +++ b/mie/include/mie/parse/lex.h @@ -1,15 +1,18 @@ #ifndef MIE_PARSE_LEX_H_ #define MIE_PARSE_LEX_H_ +#include #include #include #include struct mie_lex; +struct mie_ctx; struct mie_token; struct mie_line_source; -MIE_API struct mie_lex *mie_lex_create(struct mie_line_source *src); +MIE_API struct mie_lex *mie_lex_create( + struct mie_line_source *src, struct mie_ctx *ctx); MIE_API void mie_lex_destroy(struct mie_lex *lex); MIE_API enum mie_status mie_lex_get_status(const struct mie_lex *lex); diff --git a/mie/parse/lex.c b/mie/parse/lex.c index 82a86e0..7b40511 100644 --- a/mie/parse/lex.c +++ b/mie/parse/lex.c @@ -7,6 +7,10 @@ #include #include #include +#include +#include +#include +#include #include #include #include @@ -66,6 +70,14 @@ static struct mie_lex_symbol_node *get_symbol_node( return NULL; } +static struct mie_diag *push_diag(struct mie_lex *lex, unsigned long diag_class) +{ + return mie_ctx_push_diag( + lex->lex_ctx, lex->lex_source, + mie_line_source_get_cursor(lex->lex_source), "builtin", + diag_class); +} + static b_string *get_temp_string(struct mie_lex *lex) { if (!lex->lex_temp) { @@ -145,7 +157,7 @@ static struct mie_lex_symbol_node *build_symbol_tree(void) return root; } -struct mie_lex *mie_lex_create(struct mie_line_source *src) +struct mie_lex *mie_lex_create(struct mie_line_source *src, struct mie_ctx *ctx) { struct mie_lex *lex = malloc(sizeof *lex); if (!lex) { @@ -154,6 +166,7 @@ struct mie_lex *mie_lex_create(struct mie_line_source *src) memset(lex, 0x0, sizeof *lex); + lex->lex_ctx = ctx; lex->lex_status = MIE_SUCCESS; lex->lex_source = src; @@ -591,6 +604,7 @@ static enum mie_status read_symbol(struct mie_lex *lex) } if (!node || node->s_def == NULL) { + push_diag(lex, MIE_BUILTIN_E_UNRECOGNISED_TOKEN); return MIE_ERR_BAD_SYNTAX; } @@ -753,6 +767,18 @@ static enum mie_status pump_tokens(struct mie_lex *lex) return read_number(lex, false); } + struct mie_diag *diag = push_diag(lex, MIE_BUILTIN_E_UNRECOGNISED_TOKEN); + mie_diag_push_msg( + diag, lex->lex_ctx, "builtin", MIE_BUILTIN_MSG_UNRECOGNISED_TOKEN); + const struct mie_file_cell *cursor + = mie_line_source_get_cursor(lex->lex_source); + unsigned long line = cursor->c_row; + const struct mie_diag_highlight hl[] = { + {.hl_type = MIE_DIAG_HIGHLIGHT_ERROR, + .hl_span = {.s_start = *cursor, .s_end = *cursor}}, + }; + const size_t nr_hl = sizeof hl / sizeof hl[0]; + mie_diag_push_snippet(diag, line, line, NULL, 0, hl, nr_hl); return MIE_ERR_BAD_SYNTAX; } diff --git a/mie/parse/lex.h b/mie/parse/lex.h index ad8ca64..1d1a96b 100644 --- a/mie/parse/lex.h +++ b/mie/parse/lex.h @@ -15,6 +15,7 @@ struct mie_lex { struct mie_line_source *lex_source; enum mie_status lex_status; + struct mie_ctx *lex_ctx; b_queue lex_queue; b_string *lex_temp; diff --git a/mie/parse/parser.c b/mie/parse/parser.c index e65405e..9713327 100644 --- a/mie/parse/parser.c +++ b/mie/parse/parser.c @@ -260,11 +260,11 @@ bool mie_parser_parse_symbol(struct mie_parser *ctx, enum mie_token_symbol sym) bool mie_parser_parse_linefeed(struct mie_parser *ctx) { struct mie_token *tok = mie_lex_peek(ctx->p_lex); - if (tok->tok_type != MIE_TOK_LINEFEED) { + if (!MIE_TOKEN_IS(tok, MIE_TOK_LINEFEED)) { return false; } - while (tok && tok->tok_type == MIE_TOK_LINEFEED) { + while (MIE_TOKEN_IS(tok, MIE_TOK_LINEFEED)) { mie_lex_advance(ctx->p_lex); tok = mie_lex_peek(ctx->p_lex); }