mie: add a system for registering and producing detailed diagnostic messages

This commit is contained in:
2026-01-27 20:46:44 +00:00
parent bd5ba9e9fd
commit cd49417972
20 changed files with 656 additions and 197 deletions

View File

@@ -4,6 +4,8 @@
#include <blue/ds/string.h> #include <blue/ds/string.h>
#include <mie/attribute/attribute-definition.h> #include <mie/attribute/attribute-definition.h>
#include <mie/ctx.h> #include <mie/ctx.h>
#include <mie/diag/class.h>
#include <mie/diag/diag.h>
#include <mie/dialect/arith.h> #include <mie/dialect/arith.h>
#include <mie/dialect/builtin.h> #include <mie/dialect/builtin.h>
#include <mie/dialect/dialect.h> #include <mie/dialect/dialect.h>
@@ -484,3 +486,44 @@ enum mie_status mie_ctx_get_pass(
*out = pass; *out = pass;
return status; 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);
}

106
mie/diag/diag.c Normal file
View File

@@ -0,0 +1,106 @@
#include <blue/ds/string.h>
#include <mie/ctx.h>
#include <mie/diag/amendment.h>
#include <mie/diag/component.h>
#include <mie/diag/diag.h>
#include <mie/diag/highlight.h>
#include <mie/diag/msg.h>
#include <mie/dialect/dialect.h>
#include <stdlib.h>
#include <string.h>
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);
}

6
mie/diag/diag.h Normal file
View File

@@ -0,0 +1,6 @@
#ifndef _DIAG_DIAG_H_
#define _DIAG_DIAG_H_
#include <blue/core/queue.h>
#endif

View File

@@ -1,4 +1,6 @@
#include <mie/ctx.h> #include <mie/ctx.h>
#include <mie/diag/class.h>
#include <mie/diag/msg.h>
#include <mie/dialect/builtin.h> #include <mie/dialect/builtin.h>
#include <mie/dialect/dialect.h> #include <mie/dialect/dialect.h>
#include <mie/macros.h> #include <mie/macros.h>
@@ -81,9 +83,14 @@ struct mie_attribute *mie_ctx_get_index(struct mie_ctx *ctx, size_t val)
dialect->ctx_indices, ctx, 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_BEGIN(mie_builtin, struct builtin_dialect, "builtin")
MIE_DIALECT_INIT(init); MIE_DIALECT_INIT(init);
MIE_DIALECT_CLEANUP(cleanup); 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_isolated_from_above);
MIE_DIALECT_ADD_TRAIT(mie_builtin_symbol_table); MIE_DIALECT_ADD_TRAIT(mie_builtin_symbol_table);
MIE_DIALECT_ADD_TYPE(mie_builtin_int); MIE_DIALECT_ADD_TYPE(mie_builtin_int);

View File

@@ -0,0 +1,16 @@
#include <mie/diag/class.h>
#include <mie/diag/msg.h>
#include <mie/dialect/builtin.h>
#include <mie/macros.h>
#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)

View File

@@ -7,7 +7,10 @@
struct mie_op; struct mie_op;
struct mie_pass; struct mie_pass;
struct mie_diag;
struct mie_file_cell;
struct mie_int_cache; struct mie_int_cache;
struct mie_line_source;
struct mie_index_cache; struct mie_index_cache;
struct mie_string_cache; struct mie_string_cache;
struct mie_attribute_map; struct mie_attribute_map;
@@ -31,6 +34,8 @@ struct mie_ctx {
struct mie_id_map ctx_attributes; struct mie_id_map ctx_attributes;
/* map of struct mie_pass_definition */ /* map of struct mie_pass_definition */
struct mie_id_map ctx_passes; struct mie_id_map ctx_passes;
/* queue of struct mie_diag */
b_queue ctx_diag;
}; };
MIE_API struct mie_ctx *mie_ctx_create(void); 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, struct mie_ctx *ctx, const char *name,
const struct mie_attribute_map *args, struct mie_pass **out); 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 #endif

View File

@@ -0,0 +1,36 @@
#ifndef MIE_DIAG_AMENDMENT_H_
#define MIE_DIAG_AMENDMENT_H_
#include <mie/parse/file-span.h>
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

View File

@@ -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

View File

@@ -0,0 +1,34 @@
#ifndef MIE_DIAG_COMPONENT_H_
#define MIE_DIAG_COMPONENT_H_
#include <blue/core/queue.h>
#include <stddef.h>
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

View File

@@ -0,0 +1,39 @@
#ifndef MIE_DIAG_DIAG_H_
#define MIE_DIAG_DIAG_H_
#include <blue/core/queue.h>
#include <mie/parse/file-span.h>
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

View File

@@ -0,0 +1,18 @@
#ifndef MIE_DIAG_HIGHLIGHT_H_
#define MIE_DIAG_HIGHLIGHT_H_
#include <mie/parse/file-span.h>
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

View File

@@ -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

View File

View File

@@ -15,6 +15,16 @@ struct mie_op;
struct mie_int_type; struct mie_int_type;
struct mie_float_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 { enum mie_float_width {
MIE_FLOAT_32 = 32, MIE_FLOAT_32 = 32,
MIE_FLOAT_64 = 64, MIE_FLOAT_64 = 64,

View File

@@ -13,6 +13,9 @@ struct mie_op_definition;
struct mie_type_definition; struct mie_type_definition;
struct mie_trait_definition; struct mie_trait_definition;
struct mie_diag_class;
struct mie_diag_msg;
struct mie_dialect { struct mie_dialect {
mie_id d_id; mie_id d_id;
char *d_name; char *d_name;
@@ -27,6 +30,12 @@ struct mie_dialect {
struct mie_id_map d_attributes; struct mie_id_map d_attributes;
/* map of struct mie_interface_definition */ /* map of struct mie_interface_definition */
struct mie_id_map d_interfaces; 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 *); enum mie_status (*d_cleanup)(struct mie_dialect *);
}; };

View File

@@ -5,180 +5,186 @@
/* DIALECT DEFINITION MACROS */ /* DIALECT DEFINITION MACROS */
/******************************************************************************/ /******************************************************************************/
#define MIE_DIALECT_BEGIN(func_prefix, c_struct, dialect_name) \ #define MIE_DIALECT_BEGIN(func_prefix, c_struct, dialect_name) \
struct mie_dialect *func_prefix##_dialect_create(struct mie_ctx *ctx) \ struct mie_dialect* func_prefix##_dialect_create(struct mie_ctx* ctx) \
{ \ { \
struct mie_dialect *self = mie_dialect_create( \ struct mie_dialect* self = mie_dialect_create( \
ctx, dialect_name, sizeof(c_struct)); \ ctx, dialect_name, sizeof(c_struct)); \
if (!self) { \ if (!self) { \
return NULL; \ return NULL; \
} \ } \
struct mie_op_definition *op = NULL; \ struct mie_op_definition* op = NULL; \
struct mie_type_definition *type = NULL; \ struct mie_type_definition* type = NULL; \
struct mie_trait_definition *trait = NULL; \ struct mie_trait_definition* trait = NULL; \
struct mie_attribute_definition *attribute = NULL; \ struct mie_attribute_definition* attribute = NULL; \
struct mie_interface_definition *interface = NULL; struct mie_interface_definition* interface = NULL;
#define MIE_DIALECT_END() \ #define MIE_DIALECT_END() \
return self; \ 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_CLEANUP(func) self->d_cleanup = (func)
#define MIE_DIALECT_ADD_OP(op_id) \ #define MIE_DIALECT_DIAG_CLASS_LIST(list) \
extern struct mie_op_definition *op_id##_op_create( \ self->d_diag_classes = (list); \
struct mie_dialect *, struct mie_ctx *); \ self->d_nr_diag_classes = (list##_count)
op = op_id##_op_create(self, ctx) #define MIE_DIALECT_DIAG_MSG_LIST(list) \
#define MIE_DIALECT_ADD_TYPE(type_id) \ self->d_diag_msgs = (list); \
extern struct mie_type_definition *type_id##_type_create( \ self->d_nr_diag_msgs = (list##_count)
struct mie_dialect *, struct mie_ctx *); \ #define MIE_DIALECT_ADD_OP(op_id) \
type = type_id##_type_create(self, ctx) extern struct mie_op_definition* op_id##_op_create( \
#define MIE_DIALECT_ADD_TRAIT(trait_id) \ struct mie_dialect*, struct mie_ctx*); \
extern struct mie_trait_definition *trait_id##_trait_create( \ op = op_id##_op_create(self, ctx)
struct mie_dialect *, struct mie_ctx *); \ #define MIE_DIALECT_ADD_TYPE(type_id) \
trait = trait_id##_trait_create(self, ctx) extern struct mie_type_definition* type_id##_type_create( \
#define MIE_DIALECT_ADD_ATTRIBUTE(attr_id) \ struct mie_dialect*, struct mie_ctx*); \
extern struct mie_attribute_definition *attr_id##_attribute_create( \ type = type_id##_type_create(self, ctx)
struct mie_dialect *, struct mie_ctx *); \ #define MIE_DIALECT_ADD_TRAIT(trait_id) \
attribute = attr_id##_attribute_create(self, ctx) extern struct mie_trait_definition* trait_id##_trait_create( \
#define MIE_DIALECT_ADD_INTERFACE(iface_id) \ struct mie_dialect*, struct mie_ctx*); \
extern struct mie_interface_definition *iface_id##_interface_create( \ trait = trait_id##_trait_create(self, ctx)
struct mie_dialect *, struct mie_ctx *); \ #define MIE_DIALECT_ADD_ATTRIBUTE(attr_id) \
interface = iface_id##_interface_create(self, ctx) 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 */ /* OP DEFINITION MACROS */
/******************************************************************************/ /******************************************************************************/
#define MIE_OP_DEFINITION_BEGIN(func_prefix, op_name) \ #define MIE_OP_DEFINITION_BEGIN(func_prefix, op_name) \
struct mie_op_definition *func_prefix##_op_create( \ struct mie_op_definition* func_prefix##_op_create( \
struct mie_dialect *d, struct mie_ctx *ctx) \ struct mie_dialect* d, struct mie_ctx* ctx) \
{ \ { \
struct mie_op_definition *op \ struct mie_op_definition* op \
= mie_op_definition_create(d, op_name); \ = mie_op_definition_create(d, op_name); \
if (!op) { \ if (!op) { \
return NULL; \ return NULL; \
} \ } \
const struct mie_trait *trait = NULL; \ const struct mie_trait* trait = NULL; \
struct mie_interface *i = NULL; \ struct mie_interface* i = NULL; \
const struct mie_interface_definition *id = NULL; const struct mie_interface_definition* id = NULL;
#define MIE_OP_DEFINITION_END() \ #define MIE_OP_DEFINITION_END() \
return op; \ return op; \
} }
#define MIE_OP_DEFINITION_PRINT(func) op->op_print = (func) #define MIE_OP_DEFINITION_PRINT(func) op->op_print = (func)
#define MIE_OP_DEFINITION_PARSE(func) op->op_parse = (func) #define MIE_OP_DEFINITION_PARSE(func) op->op_parse = (func)
#define MIE_OP_DEFINITION_TRAIT(trait_dialect, trait_name) \ #define MIE_OP_DEFINITION_TRAIT(trait_dialect, trait_name) \
trait = mie_ctx_get_trait(ctx, trait_dialect, trait_name); \ trait = mie_ctx_get_trait(ctx, trait_dialect, trait_name); \
mie_op_definition_add_trait(op, trait); mie_op_definition_add_trait(op, trait);
#define MIE_OP_INTERFACE_BEGIN(dialect_name, if_name, c_struct) \ #define MIE_OP_INTERFACE_BEGIN(dialect_name, if_name, c_struct) \
id = mie_ctx_get_interface_definition(ctx, dialect_name, if_name); \ id = mie_ctx_get_interface_definition(ctx, dialect_name, if_name); \
if (id) { \ if (id) { \
c_struct *iface = (c_struct *)mie_interface_create(id); c_struct* iface = (c_struct*)mie_interface_create(id);
#define MIE_OP_INTERFACE_FUNC(func_name) iface->func_name #define MIE_OP_INTERFACE_FUNC(func_name) iface->func_name
#define MIE_OP_INTERFACE_END() \ #define MIE_OP_INTERFACE_END() \
mie_op_definition_add_interface(op, (struct mie_interface *)iface); \ mie_op_definition_add_interface(op, (struct mie_interface*)iface); \
} }
/******************************************************************************/ /******************************************************************************/
/* TYPE DEFINITION MACROS */ /* TYPE DEFINITION MACROS */
/******************************************************************************/ /******************************************************************************/
#define MIE_TYPE_DEFINITION_BEGIN(func_prefix, type_name) \ #define MIE_TYPE_DEFINITION_BEGIN(func_prefix, type_name) \
struct mie_type_definition *func_prefix##_type_create( \ struct mie_type_definition* func_prefix##_type_create( \
struct mie_dialect *d, struct mie_ctx *ctx) \ struct mie_dialect* d, struct mie_ctx* ctx) \
{ \ { \
struct mie_type_definition *type \ struct mie_type_definition* type \
= mie_type_definition_create(d, type_name); \ = mie_type_definition_create(d, type_name); \
if (!type) { \ if (!type) { \
return NULL; \ return NULL; \
} \ } \
const struct mie_trait *trait = NULL; const struct mie_trait* trait = NULL;
#define MIE_TYPE_DEFINITION_END() \ #define MIE_TYPE_DEFINITION_END() \
return type; \ return type; \
} }
#define MIE_TYPE_DEFINITION_FLAGS(flags) type->ty_flags = flags #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_STRUCT(name) type->ty_data_size = sizeof(name)
#define MIE_TYPE_DEFINITION_INIT(func) type->ty_init = (func) #define MIE_TYPE_DEFINITION_INIT(func) type->ty_init = (func)
#define MIE_TYPE_DEFINITION_PRINT(func) type->ty_print = (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_PARSE(func) type->ty_parse = (func)
#define MIE_TYPE_DEFINITION_BUILD_ID(func) type->ty_build_id = (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_INIT(func) type->ty_init = (func)
#define MIE_TYPE_DEFINITION_CLEANUP(func) type->ty_cleanup = (func) #define MIE_TYPE_DEFINITION_CLEANUP(func) type->ty_cleanup = (func)
#define MIE_TYPE_DEFINITION_TRAIT(trait_dialect, trait_name) \ #define MIE_TYPE_DEFINITION_TRAIT(trait_dialect, trait_name) \
trait = mie_ctx_get_trait(ctx, trait_dialect, trait_name); \ trait = mie_ctx_get_trait(ctx, trait_dialect, trait_name); \
mie_type_definition_add_trait(type, trait); mie_type_definition_add_trait(type, trait);
/******************************************************************************/ /******************************************************************************/
/* TRAIT DEFINITION MACROS */ /* TRAIT DEFINITION MACROS */
/******************************************************************************/ /******************************************************************************/
#define MIE_TRAIT_DEFINITION_BEGIN(func_prefix, trait_name) \ #define MIE_TRAIT_DEFINITION_BEGIN(func_prefix, trait_name) \
struct mie_trait_definition *func_prefix##_trait_create( \ struct mie_trait_definition* func_prefix##_trait_create( \
struct mie_dialect *d, struct mie_ctx *ctx) \ struct mie_dialect* d, struct mie_ctx* ctx) \
{ \ { \
struct mie_trait_definition *trait \ struct mie_trait_definition* trait \
= mie_trait_definition_create(d, trait_name); \ = mie_trait_definition_create(d, trait_name); \
if (!trait) { \ if (!trait) { \
return NULL; \ return NULL; \
} }
#define MIE_TRAIT_DEFINITION_END() \ #define MIE_TRAIT_DEFINITION_END() \
return trait; \ return trait; \
} }
#define MIE_TRAIT_DEFINITION_TARGETS(targets) trait->tr_target = (targets) #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_STRUCT(name) trait->tr_data_size = sizeof(name)
#define MIE_TRAIT_DEFINITION_PRINT(func) trait->tr_print = (func) #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_BUILD_ID(func) trait->tr_build_id = (func)
#define MIE_TRAIT_DEFINITION_CLEANUP(func) trait->tr_cleanup = (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_VALIDATE(func) trait->tr_validate = (func)
/******************************************************************************/ /******************************************************************************/
/* ATTRIBUTE DEFINITION MACROS */ /* ATTRIBUTE DEFINITION MACROS */
/******************************************************************************/ /******************************************************************************/
#define MIE_ATTRIBUTE_DEFINITION_BEGIN(func_prefix, attribute_name) \ #define MIE_ATTRIBUTE_DEFINITION_BEGIN(func_prefix, attribute_name) \
struct mie_attribute_definition *func_prefix##_attribute_create( \ struct mie_attribute_definition* func_prefix##_attribute_create( \
struct mie_dialect *d, struct mie_ctx *ctx) \ struct mie_dialect* d, struct mie_ctx* ctx) \
{ \ { \
struct mie_attribute_definition *attribute \ struct mie_attribute_definition* attribute \
= mie_attribute_definition_create(d, attribute_name); \ = mie_attribute_definition_create(d, attribute_name); \
if (!attribute) { \ if (!attribute) { \
return NULL; \ return NULL; \
} }
#define MIE_ATTRIBUTE_DEFINITION_END() \ #define MIE_ATTRIBUTE_DEFINITION_END() \
return attribute; \ return attribute; \
} }
#define MIE_ATTRIBUTE_DEFINITION_STRUCT(name) \ #define MIE_ATTRIBUTE_DEFINITION_STRUCT(name) \
attribute->a_data_size = sizeof(name) attribute->a_data_size = sizeof(name)
#define MIE_ATTRIBUTE_DEFINITION_INIT(func) attribute->a_init = (func) #define MIE_ATTRIBUTE_DEFINITION_INIT(func) attribute->a_init = (func)
#define MIE_ATTRIBUTE_DEFINITION_CLEANUP(func) attribute->a_cleanup = (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_PRINT(func) attribute->a_print = (func)
#define MIE_ATTRIBUTE_DEFINITION_PARSE(func) attribute->a_parse = (func) #define MIE_ATTRIBUTE_DEFINITION_PARSE(func) attribute->a_parse = (func)
/******************************************************************************/ /******************************************************************************/
/* INTERFACE DEFINITION MACROS */ /* INTERFACE DEFINITION MACROS */
/******************************************************************************/ /******************************************************************************/
#define MIE_INTERFACE_DEFINITION_BEGIN(func_prefix, iface_name) \ #define MIE_INTERFACE_DEFINITION_BEGIN(func_prefix, iface_name) \
struct mie_interface_definition *func_prefix##_interface_create( \ struct mie_interface_definition* func_prefix##_interface_create( \
struct mie_dialect *d, struct mie_ctx *ctx) \ struct mie_dialect* d, struct mie_ctx* ctx) \
{ \ { \
struct mie_interface_definition *i \ struct mie_interface_definition* i \
= mie_interface_definition_create(d, iface_name); \ = mie_interface_definition_create(d, iface_name); \
if (!i) { \ if (!i) { \
return NULL; \ return NULL; \
} }
#define MIE_INTERFACE_DEFINITION_END() \ #define MIE_INTERFACE_DEFINITION_END() \
return i; \ return i; \
} }
#define MIE_INTERFACE_DEFINITION_STRUCT(name) i->if_size = sizeof(name) #define MIE_INTERFACE_DEFINITION_STRUCT(name) i->if_size = sizeof(name)
@@ -186,84 +192,143 @@
/* PASS DEFINITION MACROS */ /* PASS DEFINITION MACROS */
/******************************************************************************/ /******************************************************************************/
#define MIE_PASS_DEFINITION_BEGIN(prefix) \ #define MIE_PASS_DEFINITION_BEGIN(prefix) \
struct mie_pass_definition *prefix##_pass_create(struct mie_ctx *ctx) \ struct mie_pass_definition* prefix##_pass_create(struct mie_ctx* ctx) \
{ \ { \
struct mie_pass_definition *p = mie_pass_definition_create(); \ struct mie_pass_definition* p = mie_pass_definition_create(); \
if (!p) { \ if (!p) { \
return NULL; \ return NULL; \
} }
#define MIE_PASS_DEFINITION_END() \ #define MIE_PASS_DEFINITION_END() \
if (mie_ctx_register_pass(ctx, p) != MIE_SUCCESS) { \ if (mie_ctx_register_pass(ctx, p) != MIE_SUCCESS) { \
return NULL; \ return NULL; \
} \ } \
return p; \ 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_DESCRIPTION(desc) p->p_description = (desc)
#define MIE_PASS_STRUCT(c_struct) p->p_data_size = sizeof(c_struct) #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_TYPE(type) p->p_type = (type)
#define MIE_PASS_INIT(func) p->p_init = (func) #define MIE_PASS_INIT(func) p->p_init = (func)
#define MIE_PASS_TRANSFORM(func) \ #define MIE_PASS_TRANSFORM(func) \
p->p_transform = (func); \ p->p_transform = (func); \
p->p_type = MIE_PASS_TRANSFORM p->p_type = MIE_PASS_TRANSFORM
#define MIE_PASS_ANALYSE(func) \ #define MIE_PASS_ANALYSE(func) \
p->p_analyse = (func); \ p->p_analyse = (func); \
p->p_type = MIE_PASS_ANALYSE p->p_type = MIE_PASS_ANALYSE
#define MIE_PASS_FILTER_OP(dialect, op) \ #define MIE_PASS_FILTER_OP(dialect, op) \
p->p_filter.f_op = mie_ctx_get_op_definition(ctx, dialect, op) p->p_filter.f_op = mie_ctx_get_op_definition(ctx, dialect, op)
#define MIE_PASS_FILTER_TRAIT(dialect, tr) \ #define MIE_PASS_FILTER_TRAIT(dialect, tr) \
p->p_filter.f_trait = mie_ctx_get_trait_definition(ctx, dialect, tr) p->p_filter.f_trait = mie_ctx_get_trait_definition(ctx, dialect, tr)
#define MIE_PASS_FILTER_INTERFACE(dialect, ifn) \ #define MIE_PASS_FILTER_INTERFACE(dialect, ifn) \
p->p_filter.f_iface = mie_ctx_get_iface_definition(ctx, dialect, ifn) p->p_filter.f_iface = mie_ctx_get_iface_definition(ctx, dialect, ifn)
/******************************************************************************/ /******************************************************************************/
/* PASS GROUP MACROS */ /* PASS GROUP MACROS */
/******************************************************************************/ /******************************************************************************/
#define MIE_PASS_GROUP_BEGIN(prefix) \ #define MIE_PASS_GROUP_BEGIN(prefix) \
enum mie_status prefix##_passes_register(struct mie_ctx *ctx) \ enum mie_status prefix##_passes_register(struct mie_ctx* ctx) \
{ \ { \
struct mie_pass_definition *pass = NULL; struct mie_pass_definition* pass = NULL;
#define MIE_PASS_GROUP_END() \ #define MIE_PASS_GROUP_END() \
return MIE_SUCCESS; \ return MIE_SUCCESS; \
} }
#define MIE_PASS_GROUP_DECLARATION(prefix) \ #define MIE_PASS_GROUP_DECLARATION(prefix) \
enum mie_status prefix##_passes_register(struct mie_ctx *); enum mie_status prefix##_passes_register(struct mie_ctx*);
#define MIE_PASS_GROUP_ADD_PASS(id) \ #define MIE_PASS_GROUP_ADD_PASS(id) \
do { \ do { \
extern struct mie_pass_definition *id##_pass_create( \ extern struct mie_pass_definition* id##_pass_create( \
struct mie_ctx *); \ struct mie_ctx*); \
pass = id##_pass_create(ctx); \ pass = id##_pass_create(ctx); \
if (!pass) { \ if (!pass) { \
return MIE_ERR_INTERNAL_FAILURE; \ return MIE_ERR_INTERNAL_FAILURE; \
} \ } \
} while (0) } while (0)
#endif #endif
/******************************************************************************/ /******************************************************************************/
/* REWRITE PATTER MACROS */ /* REWRITE PATTERN MACROS */
/******************************************************************************/ /******************************************************************************/
#define MIE_REWRITE_PATTERN_BEGIN(name) \ #define MIE_REWRITE_PATTERN_BEGIN(name) \
struct mie_pattern *name##_create(struct mie_pattern_set *set) \ struct mie_pattern* name##_create(struct mie_pattern_set* set) \
{ \ { \
struct mie_pattern *self = mie_pattern_set_add(set); \ struct mie_pattern* self = mie_pattern_set_add(set); \
if (!self) { \ if (!self) { \
return NULL; \ return NULL; \
} }
#define MIE_REWRITE_PATTERN_END() \ #define MIE_REWRITE_PATTERN_END() \
return self; \ return self; \
} }
#define MIE_REWRITE_PATTERN_ROOT(dialect_name, op_name) \ #define MIE_REWRITE_PATTERN_ROOT(dialect_name, op_name) \
self->p_root.t_dialect_name = (dialect_name); \ self->p_root.t_dialect_name = (dialect_name); \
self->p_root.t_op_name = (op_name) self->p_root.t_op_name = (op_name)
#define MIE_REWRITE_PATTERN_MATCH(func) self->p_match = (func) #define MIE_REWRITE_PATTERN_MATCH(func) self->p_match = (func)
#define MIE_REWRITE_PATTERN_REWRITE(func) self->p_rewrite = (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), \
},

View File

@@ -1,15 +1,18 @@
#ifndef MIE_PARSE_LEX_H_ #ifndef MIE_PARSE_LEX_H_
#define MIE_PARSE_LEX_H_ #define MIE_PARSE_LEX_H_
#include <blue/core/queue.h>
#include <blue/core/stream.h> #include <blue/core/stream.h>
#include <mie/misc.h> #include <mie/misc.h>
#include <mie/status.h> #include <mie/status.h>
struct mie_lex; struct mie_lex;
struct mie_ctx;
struct mie_token; struct mie_token;
struct mie_line_source; 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 void mie_lex_destroy(struct mie_lex *lex);
MIE_API enum mie_status mie_lex_get_status(const struct mie_lex *lex); MIE_API enum mie_status mie_lex_get_status(const struct mie_lex *lex);

View File

@@ -7,6 +7,10 @@
#include <blue/ds/number.h> #include <blue/ds/number.h>
#include <blue/ds/string.h> #include <blue/ds/string.h>
#include <ctype.h> #include <ctype.h>
#include <mie/ctx.h>
#include <mie/diag/diag.h>
#include <mie/diag/highlight.h>
#include <mie/dialect/builtin.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@@ -66,6 +70,14 @@ static struct mie_lex_symbol_node *get_symbol_node(
return NULL; 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) static b_string *get_temp_string(struct mie_lex *lex)
{ {
if (!lex->lex_temp) { if (!lex->lex_temp) {
@@ -145,7 +157,7 @@ static struct mie_lex_symbol_node *build_symbol_tree(void)
return root; 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); struct mie_lex *lex = malloc(sizeof *lex);
if (!lex) { if (!lex) {
@@ -154,6 +166,7 @@ struct mie_lex *mie_lex_create(struct mie_line_source *src)
memset(lex, 0x0, sizeof *lex); memset(lex, 0x0, sizeof *lex);
lex->lex_ctx = ctx;
lex->lex_status = MIE_SUCCESS; lex->lex_status = MIE_SUCCESS;
lex->lex_source = src; lex->lex_source = src;
@@ -591,6 +604,7 @@ static enum mie_status read_symbol(struct mie_lex *lex)
} }
if (!node || node->s_def == NULL) { if (!node || node->s_def == NULL) {
push_diag(lex, MIE_BUILTIN_E_UNRECOGNISED_TOKEN);
return MIE_ERR_BAD_SYNTAX; return MIE_ERR_BAD_SYNTAX;
} }
@@ -753,6 +767,18 @@ static enum mie_status pump_tokens(struct mie_lex *lex)
return read_number(lex, false); 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; return MIE_ERR_BAD_SYNTAX;
} }

View File

@@ -15,6 +15,7 @@ struct mie_lex {
struct mie_line_source *lex_source; struct mie_line_source *lex_source;
enum mie_status lex_status; enum mie_status lex_status;
struct mie_ctx *lex_ctx;
b_queue lex_queue; b_queue lex_queue;
b_string *lex_temp; b_string *lex_temp;

View File

@@ -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) bool mie_parser_parse_linefeed(struct mie_parser *ctx)
{ {
struct mie_token *tok = mie_lex_peek(ctx->p_lex); 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; return false;
} }
while (tok && tok->tok_type == MIE_TOK_LINEFEED) { while (MIE_TOKEN_IS(tok, MIE_TOK_LINEFEED)) {
mie_lex_advance(ctx->p_lex); mie_lex_advance(ctx->p_lex);
tok = mie_lex_peek(ctx->p_lex); tok = mie_lex_peek(ctx->p_lex);
} }