stage1 重写进行代码设计并重构 提供diag替换老旧错误处理
This commit is contained in:
1 parent
7cbe2d2b9a
commit
e4347cc3ea
14 files changed
+983
-526
No files matched your search
@@ -0,0 +1,165 @@
|
||||
#ifndef __SPL_DIAG_H__
|
||||
#define __SPL_DIAG_H__
|
||||
|
||||
#include "../stage0/include/utils.h"
|
||||
#include "spl_dbg.h"
|
||||
|
||||
typedef enum {
|
||||
SPL_DIAG_LEVEL_NOTE = 0,
|
||||
SPL_DIAG_LEVEL_WARN,
|
||||
SPL_DIAG_LEVEL_ERROR,
|
||||
SPL_DIAG_LEVEL_FATAL,
|
||||
} spl_diag_level_t;
|
||||
|
||||
typedef enum {
|
||||
SPL_STAGE_NONE = 0,
|
||||
SPL_STAGE_LEX,
|
||||
SPL_STAGE_PARSE,
|
||||
SPL_STAGE_SEMA,
|
||||
SPL_STAGE_AST2IR,
|
||||
SPL_STAGE_IR2VM,
|
||||
SPL_STAGE_DRIVER,
|
||||
} spl_diag_stage_t;
|
||||
|
||||
/* kind 枚举:边写边补。新增时放对应分组末尾即可。 */
|
||||
typedef enum {
|
||||
SPL_DIAG_KIND_NONE = 0,
|
||||
|
||||
/* 词法 / 语法 */
|
||||
SPL_DIAG_KIND_LEX_UNEXPECTED,
|
||||
SPL_DIAG_KIND_PARSE_EXPECTED,
|
||||
SPL_DIAG_KIND_PARSE_UNRECOGNIZED,
|
||||
|
||||
/* sema */
|
||||
SPL_DIAG_KIND_UNDEFINED_SYMBOL,
|
||||
SPL_DIAG_KIND_DUPLICATE_SYMBOL,
|
||||
SPL_DIAG_KIND_TYPE_MISMATCH,
|
||||
SPL_DIAG_KIND_ARG_COUNT_MISMATCH,
|
||||
SPL_DIAG_KIND_NOT_A_FUNCTION,
|
||||
SPL_DIAG_KIND_NO_FIELD,
|
||||
SPL_DIAG_KIND_NO_METHOD,
|
||||
SPL_DIAG_KIND_INDEX_BASE_INVALID,
|
||||
SPL_DIAG_KIND_TUPLE_INDEX_OOB,
|
||||
SPL_DIAG_KIND_FITS_OVERFLOW,
|
||||
SPL_DIAG_KIND_CIRCULAR_DEP,
|
||||
SPL_DIAG_KIND_BREAK_OUTSIDE_LOOP,
|
||||
SPL_DIAG_KIND_CONTINUE_OUTSIDE_LOOP,
|
||||
SPL_DIAG_KIND_UNDEFINED_LABEL,
|
||||
SPL_DIAG_KIND_CAST_INVALID,
|
||||
SPL_DIAG_KIND_UNKNOWN_ATTR,
|
||||
SPL_DIAG_KIND_UNKNOWN_INTRIN,
|
||||
SPL_DIAG_KIND_INTRIN_ARG_COUNT,
|
||||
SPL_DIAG_KIND_VAR_UNINITIALIZED,
|
||||
SPL_DIAG_KIND_CANNOT_INFER,
|
||||
SPL_DIAG_KIND_MUST_RETURN_VALUE,
|
||||
|
||||
/* ast2ir */
|
||||
SPL_DIAG_KIND_UNHANDLED_NODE,
|
||||
SPL_DIAG_KIND_IMPLICIT_CAST_FAIL,
|
||||
SPL_DIAG_KIND_NO_LVALUE,
|
||||
SPL_DIAG_KIND_BAD_FIELD_INDEX,
|
||||
SPL_DIAG_KIND_BAD_BLOCK,
|
||||
|
||||
/* ir2vm */
|
||||
SPL_DIAG_KIND_IR_UNKNOWN_KIND,
|
||||
SPL_DIAG_KIND_FRAME_OVERFLOW,
|
||||
|
||||
/* 通用 */
|
||||
SPL_DIAG_KIND_INTERNAL,
|
||||
} spl_diag_kind_t;
|
||||
|
||||
typedef struct {
|
||||
spl_dbg_node_t loc;
|
||||
char *fn_name;
|
||||
char *label;
|
||||
} spl_diag_frame_t;
|
||||
typedef VEC(spl_diag_frame_t) spl_diag_frame_vec_t;
|
||||
|
||||
typedef struct {
|
||||
spl_dbg_node_t loc;
|
||||
char *message;
|
||||
} spl_diag_note_t;
|
||||
typedef VEC(spl_diag_note_t) spl_diag_note_vec_t;
|
||||
|
||||
typedef struct {
|
||||
spl_diag_level_t level;
|
||||
spl_diag_stage_t stage;
|
||||
spl_diag_kind_t kind;
|
||||
spl_dbg_node_t loc;
|
||||
char *message;
|
||||
spl_diag_frame_vec_t ctx;
|
||||
spl_diag_note_vec_t notes;
|
||||
} spl_diag_record_t;
|
||||
typedef VEC(spl_diag_record_t) spl_diag_record_vec_t;
|
||||
|
||||
typedef struct spl_diag {
|
||||
spl_diag_frame_vec_t ctx;
|
||||
spl_diag_record_vec_t records;
|
||||
usize num_printed;
|
||||
bool collect;
|
||||
usize n_errors;
|
||||
usize n_warns;
|
||||
usize n_fatals;
|
||||
spl_diag_stage_t stage;
|
||||
void *fout;
|
||||
bool color;
|
||||
} spl_diag_t;
|
||||
|
||||
void spl_diag_init(spl_diag_t *d, void *fout);
|
||||
void spl_diag_drop(spl_diag_t *d);
|
||||
void spl_diag_reset(spl_diag_t *d);
|
||||
void spl_diag_set_stage(spl_diag_t *d, spl_diag_stage_t stage);
|
||||
void spl_diag_set_output(spl_diag_t *d, FILE *out);
|
||||
void spl_diag_set_color(spl_diag_t *d, bool enabled);
|
||||
void spl_diag_set_collect(spl_diag_t *d, bool enabled);
|
||||
|
||||
void spl_diag_push(spl_diag_t *d, const spl_dbg_node_t *loc, const char *fn_name,
|
||||
const char *label);
|
||||
void spl_diag_pop(spl_diag_t *d);
|
||||
usize spl_diag_depth(const spl_diag_t *d);
|
||||
|
||||
/* ============================================================
|
||||
* 发射
|
||||
*
|
||||
* 每个级别都生成独立的 spl_diag_record_t:
|
||||
* - 计入 records(collect=true 时)
|
||||
* - error/fatal 计入 n_errors,warn 计入 n_warns
|
||||
* - 立刻输出到 out(如果非 NULL)
|
||||
*
|
||||
* 四种级别的语义区别:
|
||||
* note —— 一般信息;不阻塞;用在前序诊断之外的独立说明
|
||||
* warn —— 警告;不阻塞;driver 可忽略
|
||||
* error —— 用户代码错误;调用者应 return 0
|
||||
* fatal —— 用户代码错误到数据结构已损坏;调用者必须 return 0
|
||||
* ============================================================ */
|
||||
void spl_diag_note(spl_diag_t *d, spl_diag_kind_t kind, const spl_dbg_node_t *loc, const char *fmt,
|
||||
...);
|
||||
void spl_diag_warn(spl_diag_t *d, spl_diag_kind_t kind, const spl_dbg_node_t *loc, const char *fmt,
|
||||
...);
|
||||
void spl_diag_error(spl_diag_t *d, spl_diag_kind_t kind, const spl_dbg_node_t *loc, const char *fmt,
|
||||
...);
|
||||
void spl_diag_fatal(spl_diag_t *d, spl_diag_kind_t kind, const spl_dbg_node_t *loc, const char *fmt,
|
||||
...);
|
||||
|
||||
/* 挂到最近一条记录(records 末尾)的 notes 列表下。
|
||||
* 不生成独立记录、不计入计数,输出时显示为:
|
||||
* note: <loc>
|
||||
* <msg>
|
||||
* 使用场景:辅助说明前一条诊断,例如
|
||||
* spl_diag_error(d, DUPLICATE_SYMBOL, &n->dbg, "duplicate symbol `foo`");
|
||||
* spl_diag_attach_note(d, &prev->dbg, "previously defined here");
|
||||
* 约束:只在 records 非空时生效;否则静默丢弃,不报错。 */
|
||||
void spl_diag_attach_note(spl_diag_t *d, const spl_dbg_node_t *loc, const char *fmt, ...);
|
||||
|
||||
bool spl_diag_has_error(const spl_diag_t *d);
|
||||
bool spl_diag_has_fatal(const spl_diag_t *d);
|
||||
usize spl_diag_error_count(const spl_diag_t *d);
|
||||
usize spl_diag_warn_count(const spl_diag_t *d);
|
||||
|
||||
void spl_diag_summary(const spl_diag_t *d);
|
||||
|
||||
const char *spl_diag_kind_name(spl_diag_kind_t k);
|
||||
const char *spl_diag_stage_name(spl_diag_stage_t s);
|
||||
const char *spl_diag_level_name(spl_diag_level_t l);
|
||||
|
||||
#endif /* __SPL_DIAG_H__ */
|
||||
Reference in new issue
Block a user