stage1 修复设计问题 实现ast2ir
This commit is contained in:
@@ -151,7 +151,8 @@ static void parse_error(parser_t *p, spl_tok_t *t, const char *msg) {
|
||||
const char *fn = (t && t->fname) ? t->fname : "<unknown>";
|
||||
usize line = t ? t->line : 0;
|
||||
usize col = t ? t->col : 0;
|
||||
LOG_FATAL("%s:%llu:%llu: error: %s", fn, (unsigned long long)line, (unsigned long long)col, msg);
|
||||
LOG_FATAL("%s:%llu:%llu: error: %s", fn, (unsigned long long)line, (unsigned long long)col,
|
||||
msg);
|
||||
}
|
||||
|
||||
static int expect(parser_t *p, spl_tok_type_t type, const char *what) {
|
||||
|
||||
@@ -35,6 +35,8 @@ typedef VEC(spl_ast_node_ref_t) spl_ast_node_ref_vec_t;
|
||||
struct spl_ast_node {
|
||||
spl_ast_node_kind_t kind;
|
||||
spl_ast_loc_t loc;
|
||||
|
||||
usize resolved_def_id;
|
||||
union {
|
||||
struct {
|
||||
spl_ast_node_ref_vec_t attr_list; /* attr_item */
|
||||
|
||||
2879
stage1/spl_ast2ir.c
2879
stage1/spl_ast2ir.c
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,19 @@
|
||||
#ifndef __SPL_AST2IR_H__
|
||||
#define __SPL_AST2IR_H__
|
||||
|
||||
#include "spl_ir.h"
|
||||
#include "spl_sema.h"
|
||||
|
||||
typedef struct {
|
||||
const spl_sema_t *sema;
|
||||
spl_ir_t ir;
|
||||
VEC(char *) owned_names; /* 本模块 malloc 的函数名,drop 时释放 */
|
||||
int err_count;
|
||||
} spl_ast2ir_t;
|
||||
|
||||
void spl_ast2ir_init(spl_ast2ir_t *ast2ir, const spl_sema_t *sema);
|
||||
void spl_ast2ir_drop(spl_ast2ir_t *ast2ir);
|
||||
|
||||
void spl_ast2ir_run(spl_ast2ir_t *ast2ir);
|
||||
|
||||
#endif /* __SPL_AST2IR_H__ */
|
||||
|
||||
483
stage1/spl_ir.c
483
stage1/spl_ir.c
@@ -1 +1,484 @@
|
||||
/* spl_ir.c — function-based SIR IR (arena 容器 + 文本 dump) */
|
||||
|
||||
#include "spl_ir.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/* ---- 内置函数名字表(与 spl_ir_kind_t 枚举一一对应) ---- */
|
||||
static const char *const ir_kind_names[] = {
|
||||
#define X(a, b, c) #a,
|
||||
SPL_IR_FN_TABLE
|
||||
#undef X
|
||||
};
|
||||
|
||||
void spl_ir_init(spl_ir_t *ir) {
|
||||
memset(ir, 0, sizeof *ir);
|
||||
vec_init(ir->funcs);
|
||||
/* func ref 0 保留为 error,占位 */
|
||||
spl_ir_func_t f0;
|
||||
memset(&f0, 0, sizeof f0);
|
||||
vec_push(ir->funcs, f0);
|
||||
}
|
||||
|
||||
static void node_drop_vecs(spl_ir_node_t *n) {
|
||||
if (!n)
|
||||
return;
|
||||
switch (n->kind) {
|
||||
case SPL_IR_AGG_CONSTRUCT:
|
||||
vec_free(n->agg_construct.fields);
|
||||
break;
|
||||
case SPL_IR_CONTROL_CALL:
|
||||
vec_free(n->control_call.params);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void spl_ir_drop(spl_ir_t *ir) {
|
||||
for (usize i = 0; i < ir->funcs.size; i++) {
|
||||
spl_ir_func_t *f = &ir->funcs.data[i];
|
||||
for (usize j = 0; j < f->nodes.size; j++)
|
||||
node_drop_vecs(&f->nodes.data[j]);
|
||||
vec_free(f->nodes);
|
||||
vec_free(f->labels);
|
||||
}
|
||||
vec_free(ir->funcs);
|
||||
}
|
||||
|
||||
spl_ir_func_ref_t spl_ir_alloc_fn(spl_ir_t *ir) {
|
||||
spl_ir_func_t f;
|
||||
memset(&f, 0, sizeof f);
|
||||
vec_init(f.nodes);
|
||||
vec_init(f.labels);
|
||||
vec_push(ir->funcs, f);
|
||||
return ir->funcs.size - 1;
|
||||
}
|
||||
|
||||
spl_ir_node_ref_t spl_ir_alloc_node(spl_ir_t *ir, spl_ir_func_ref_t fn_id) {
|
||||
if (!fn_id || fn_id >= ir->funcs.size)
|
||||
return 0;
|
||||
spl_ir_func_t *f = &ir->funcs.data[fn_id];
|
||||
spl_ir_node_t n;
|
||||
memset(&n, 0, sizeof n);
|
||||
if (f->nodes.size == 0) {
|
||||
vec_push(f->nodes, n); /* 占位:node ref 0 保留为 error */
|
||||
}
|
||||
vec_push(f->nodes, n);
|
||||
return f->nodes.size - 1;
|
||||
}
|
||||
|
||||
spl_ir_node_t *spl_ir_node(spl_ir_t *ir, spl_ir_func_ref_t fn_id, spl_ir_node_ref_t node_id) {
|
||||
if (!fn_id || fn_id >= ir->funcs.size)
|
||||
return NULL;
|
||||
spl_ir_func_t *f = &ir->funcs.data[fn_id];
|
||||
if (!node_id || node_id >= f->nodes.size)
|
||||
return NULL;
|
||||
return &f->nodes.data[node_id];
|
||||
}
|
||||
|
||||
spl_ir_func_t *spl_ir_func(spl_ir_t *ir, spl_ir_func_ref_t fn_id) {
|
||||
if (!fn_id || fn_id >= ir->funcs.size)
|
||||
return NULL;
|
||||
return &ir->funcs.data[fn_id];
|
||||
}
|
||||
|
||||
/* ================================================================
|
||||
* dump
|
||||
* ================================================================ */
|
||||
|
||||
static void ir_type_dump(const spl_type_t *ty, spl_type_id_t tid) {
|
||||
spl_type_node_t *n = spl_type_node((spl_type_t *)ty, tid);
|
||||
if (!n) {
|
||||
printf("?");
|
||||
return;
|
||||
}
|
||||
switch (n->kind) {
|
||||
case SPL_TYPE_VOID:
|
||||
printf("void");
|
||||
break;
|
||||
case SPL_TYPE_BOOL:
|
||||
printf("bool");
|
||||
break;
|
||||
case SPL_TYPE_INT:
|
||||
printf("%s%zu", n->int_type.is_signed ? "i" : "u", n->int_type.bits);
|
||||
break;
|
||||
case SPL_TYPE_FLOAT:
|
||||
printf("f%zu", n->float_type.bits);
|
||||
break;
|
||||
case SPL_TYPE_PTR:
|
||||
printf("*");
|
||||
ir_type_dump(ty, n->ptr_pointee);
|
||||
break;
|
||||
case SPL_TYPE_SLICE:
|
||||
printf("[]");
|
||||
ir_type_dump(ty, n->slice_element);
|
||||
break;
|
||||
case SPL_TYPE_RANGE:
|
||||
printf("range[");
|
||||
ir_type_dump(ty, n->range_element);
|
||||
printf("]");
|
||||
break;
|
||||
case SPL_TYPE_ARRAY:
|
||||
printf("[%zu]", n->array_type.len);
|
||||
ir_type_dump(ty, n->array_type.element);
|
||||
break;
|
||||
case SPL_TYPE_STRUCT:
|
||||
printf("struct#%zu", tid);
|
||||
break;
|
||||
case SPL_TYPE_UNION:
|
||||
printf("union#%zu", tid);
|
||||
break;
|
||||
case SPL_TYPE_ENUM:
|
||||
printf("enum#%zu", tid);
|
||||
break;
|
||||
case SPL_TYPE_FN:
|
||||
printf("fn<");
|
||||
for (usize i = 0; i < n->fn_type.params.size; i++) {
|
||||
if (i)
|
||||
printf(",");
|
||||
ir_type_dump(ty, n->fn_type.params.data[i]);
|
||||
}
|
||||
printf("->");
|
||||
ir_type_dump(ty, n->fn_type.ret);
|
||||
printf(">");
|
||||
break;
|
||||
case SPL_TYPE_ID:
|
||||
ir_type_dump(ty, n->type_id);
|
||||
break;
|
||||
default:
|
||||
printf("?%zu", tid);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static const char *node_name(spl_ir_kind_t k) {
|
||||
if ((usize)k < sizeof(ir_kind_names) / sizeof(ir_kind_names[0]))
|
||||
return ir_kind_names[k];
|
||||
return "?";
|
||||
}
|
||||
|
||||
static int node_produces_value(spl_ir_kind_t k) {
|
||||
switch (k) {
|
||||
case SPL_IR_MEM_STORE:
|
||||
case SPL_IR_MEM_COPY:
|
||||
case SPL_IR_MEM_SET:
|
||||
case SPL_IR_MEM_FENCE:
|
||||
case SPL_IR_CONTROL_BR:
|
||||
case SPL_IR_CONTROL_JMP:
|
||||
case SPL_IR_CONTROL_RET:
|
||||
case SPL_IR_CONTROL_UNREACHABLE:
|
||||
case SPL_IR_CONTROL_TRAP:
|
||||
case SPL_IR_DBG_BREAKPOINT:
|
||||
case SPL_IR_DBG_DECLARE:
|
||||
return 0;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void dump_ref(spl_ir_node_ref_t r) { printf("%%%zu", r); }
|
||||
|
||||
static void dump_node(const spl_type_t *ty, const spl_ir_node_t *n) {
|
||||
switch (n->kind) {
|
||||
case SPL_IR_TYPE_CONST:
|
||||
printf("@type.const(");
|
||||
ir_type_dump(ty, n->type_const.tid);
|
||||
printf(")(");
|
||||
{
|
||||
spl_type_node_t *t = spl_type_node((spl_type_t *)ty, n->type_const.tid);
|
||||
if (t && t->kind == SPL_TYPE_INT)
|
||||
printf("%lld", (long long)n->type_const.int_lit);
|
||||
else if (t && t->kind == SPL_TYPE_FLOAT)
|
||||
printf("%g", n->type_const.float_lit);
|
||||
else if (t && t->kind == SPL_TYPE_FN)
|
||||
printf("@fn#%zu", n->type_const.fn);
|
||||
else if (t && (t->kind == SPL_TYPE_PTR || t->kind == SPL_TYPE_SLICE)) {
|
||||
if (n->type_const.cstr_lit)
|
||||
printf("\"%s\"", n->type_const.cstr_lit);
|
||||
else
|
||||
printf("0");
|
||||
} else if (t && t->kind == SPL_TYPE_BOOL)
|
||||
printf("%lld", (long long)n->type_const.int_lit);
|
||||
else
|
||||
printf("?");
|
||||
}
|
||||
printf(")");
|
||||
break;
|
||||
case SPL_IR_ARITH_ADD:
|
||||
case SPL_IR_ARITH_SUB:
|
||||
case SPL_IR_ARITH_MUL:
|
||||
case SPL_IR_ARITH_DIV:
|
||||
case SPL_IR_ARITH_REM:
|
||||
case SPL_IR_ARITH_AND:
|
||||
case SPL_IR_ARITH_OR:
|
||||
case SPL_IR_ARITH_XOR:
|
||||
case SPL_IR_ARITH_SHL:
|
||||
case SPL_IR_ARITH_SHR:
|
||||
printf("@%s(", node_name(n->kind));
|
||||
ir_type_dump(ty, n->arith.tid);
|
||||
printf(")(");
|
||||
dump_ref(n->arith.left);
|
||||
if (n->arith.right) {
|
||||
printf(", ");
|
||||
dump_ref(n->arith.right);
|
||||
}
|
||||
printf(")");
|
||||
break;
|
||||
case SPL_IR_ARITH_NEG:
|
||||
case SPL_IR_ARITH_ABS:
|
||||
case SPL_IR_ARITH_NOT:
|
||||
printf("@%s(", node_name(n->kind));
|
||||
ir_type_dump(ty, n->arith.tid);
|
||||
printf(")(");
|
||||
dump_ref(n->arith.left);
|
||||
printf(")");
|
||||
break;
|
||||
case SPL_IR_CMP_EQ:
|
||||
case SPL_IR_CMP_NE:
|
||||
case SPL_IR_CMP_LT:
|
||||
case SPL_IR_CMP_LE:
|
||||
case SPL_IR_CMP_GT:
|
||||
case SPL_IR_CMP_GE:
|
||||
printf("@%s(", node_name(n->kind));
|
||||
ir_type_dump(ty, n->cmp.tid);
|
||||
printf(")(");
|
||||
dump_ref(n->cmp.a);
|
||||
printf(", ");
|
||||
dump_ref(n->cmp.b);
|
||||
printf(")");
|
||||
break;
|
||||
case SPL_IR_CAST_TRUNC:
|
||||
case SPL_IR_CAST_ZEXT:
|
||||
case SPL_IR_CAST_SEXT:
|
||||
case SPL_IR_CAST_FEXT:
|
||||
case SPL_IR_CAST_FTRUNC:
|
||||
case SPL_IR_CAST_BITCAST:
|
||||
case SPL_IR_CAST_PTR2INT:
|
||||
case SPL_IR_CAST_INT2PTR:
|
||||
case SPL_IR_CAST_BOOL2INT:
|
||||
case SPL_IR_CASE_INT2FLOAT:
|
||||
case SPL_IR_CASE_FLOAT2INT:
|
||||
printf("@%s(", node_name(n->kind));
|
||||
ir_type_dump(ty, n->cast.from_tid);
|
||||
printf(", ");
|
||||
ir_type_dump(ty, n->cast.to_tid);
|
||||
printf(")(");
|
||||
dump_ref(n->cast.val);
|
||||
printf(")");
|
||||
break;
|
||||
case SPL_IR_MEM_ALLOCA:
|
||||
printf("@mem.alloca(");
|
||||
ir_type_dump(ty, n->mem_alloc.tid);
|
||||
printf(")(");
|
||||
dump_ref(n->mem_alloc.count);
|
||||
printf(")");
|
||||
break;
|
||||
case SPL_IR_MEM_LOAD:
|
||||
printf("@mem.load(");
|
||||
ir_type_dump(ty, n->mem_load.tid);
|
||||
printf(")(");
|
||||
dump_ref(n->mem_load.ptr);
|
||||
printf(")");
|
||||
break;
|
||||
case SPL_IR_MEM_STORE:
|
||||
printf("@mem.store(");
|
||||
ir_type_dump(ty, n->mem_store.tid);
|
||||
printf(")(");
|
||||
dump_ref(n->mem_store.ptr);
|
||||
printf(", ");
|
||||
dump_ref(n->mem_store.val);
|
||||
printf(")");
|
||||
break;
|
||||
case SPL_IR_MEM_OFFSET:
|
||||
printf("@mem.offset(");
|
||||
ir_type_dump(ty, n->mem_offset.tid);
|
||||
printf(")(");
|
||||
dump_ref(n->mem_offset.ptr);
|
||||
printf(", ");
|
||||
dump_ref(n->mem_offset.offset);
|
||||
printf(")");
|
||||
break;
|
||||
case SPL_IR_MEM_COPY:
|
||||
printf("@mem.copy()(");
|
||||
dump_ref(n->mem_copy.dst);
|
||||
printf(", ");
|
||||
dump_ref(n->mem_copy.src);
|
||||
printf(", ");
|
||||
dump_ref(n->mem_copy.size);
|
||||
printf(")");
|
||||
break;
|
||||
case SPL_IR_MEM_SET:
|
||||
printf("@mem.set()(");
|
||||
dump_ref(n->mem_set.dst);
|
||||
printf(", ");
|
||||
dump_ref(n->mem_set.val);
|
||||
printf(", ");
|
||||
dump_ref(n->mem_set.size);
|
||||
printf(")");
|
||||
break;
|
||||
case SPL_IR_MEM_FENCE:
|
||||
printf("@mem.fence()(");
|
||||
dump_ref(n->mem_fence.ordering);
|
||||
printf(")");
|
||||
break;
|
||||
case SPL_IR_TYPE_BITSIZEOF:
|
||||
printf("@type.bitsizeof(");
|
||||
ir_type_dump(ty, n->bitsizeof.tid);
|
||||
printf(")()");
|
||||
break;
|
||||
case SPL_IR_TYPE_SIZEOF:
|
||||
printf("@type.sizeof(");
|
||||
ir_type_dump(ty, n->ir_sizeof.tid);
|
||||
printf(")()");
|
||||
break;
|
||||
case SPL_IR_TYPE_ALIGNOF:
|
||||
printf("@type.alignof(");
|
||||
ir_type_dump(ty, n->ir_alignof.tid);
|
||||
printf(")()");
|
||||
break;
|
||||
case SPL_IR_TYPE_OFFSETOF:
|
||||
printf("@type.offsetof(");
|
||||
ir_type_dump(ty, n->ir_offsetof.tid);
|
||||
printf(")(");
|
||||
dump_ref(n->ir_offsetof.field_idx);
|
||||
printf(")");
|
||||
break;
|
||||
case SPL_IR_TYPE_FIELD_COUNT:
|
||||
printf("@type.field_count(");
|
||||
ir_type_dump(ty, n->field_count.tid);
|
||||
printf(")()");
|
||||
break;
|
||||
case SPL_IR_AGG_CONSTRUCT:
|
||||
printf("@agg.construct(");
|
||||
ir_type_dump(ty, n->agg_construct.tid);
|
||||
printf(")(");
|
||||
for (usize i = 0; i < n->agg_construct.fields.size; i++) {
|
||||
if (i)
|
||||
printf(", ");
|
||||
dump_ref(n->agg_construct.fields.data[i]);
|
||||
}
|
||||
printf(")");
|
||||
break;
|
||||
case SPL_IR_AGG_EXTRACT:
|
||||
printf("@agg.extract(");
|
||||
ir_type_dump(ty, n->agg_extract.tid);
|
||||
printf(", %lld)(", (long long)n->agg_extract.field_idx);
|
||||
dump_ref(n->agg_extract.val);
|
||||
printf(")");
|
||||
break;
|
||||
case SPL_IR_AGG_INSERT:
|
||||
printf("@agg.insert(");
|
||||
ir_type_dump(ty, n->agg_insert.tid);
|
||||
printf(", %lld)(", (long long)n->agg_insert.field_idx);
|
||||
dump_ref(n->agg_insert.agg);
|
||||
printf(", ");
|
||||
dump_ref(n->agg_insert.field);
|
||||
printf(")");
|
||||
break;
|
||||
case SPL_IR_CONTROL_SELECT:
|
||||
printf("@control.select(");
|
||||
ir_type_dump(ty, n->control_select.tid);
|
||||
printf(")(");
|
||||
dump_ref(n->control_select.cond);
|
||||
printf(", ");
|
||||
dump_ref(n->control_select.true_val);
|
||||
printf(", ");
|
||||
dump_ref(n->control_select.false_val);
|
||||
printf(")");
|
||||
break;
|
||||
case SPL_IR_CONTROL_BR:
|
||||
printf("@control.br()(");
|
||||
dump_ref(n->control_br.cond);
|
||||
printf(", ");
|
||||
dump_ref(n->control_br.true_label);
|
||||
printf(", ");
|
||||
dump_ref(n->control_br.false_label);
|
||||
printf(")");
|
||||
break;
|
||||
case SPL_IR_CONTROL_JMP:
|
||||
printf("@control.jmp()(");
|
||||
dump_ref(n->control_jmp.label);
|
||||
printf(")");
|
||||
break;
|
||||
case SPL_IR_CONTROL_CALL:
|
||||
printf("@control.call(");
|
||||
ir_type_dump(ty, n->control_call.tid);
|
||||
printf(")(");
|
||||
dump_ref(n->control_call.func);
|
||||
for (usize i = 0; i < n->control_call.params.size; i++) {
|
||||
printf(", ");
|
||||
dump_ref(n->control_call.params.data[i]);
|
||||
}
|
||||
printf(")");
|
||||
break;
|
||||
case SPL_IR_CONTROL_PARAM:
|
||||
printf("@control.param(");
|
||||
ir_type_dump(ty, n->control_param.tid);
|
||||
printf(")(%lld)", (long long)n->control_param.idx);
|
||||
break;
|
||||
case SPL_IR_CONTROL_RET:
|
||||
printf("@control.ret(");
|
||||
ir_type_dump(ty, n->control_ret.tid);
|
||||
printf(")(");
|
||||
if (n->control_ret.val)
|
||||
dump_ref(n->control_ret.val);
|
||||
printf(")");
|
||||
break;
|
||||
case SPL_IR_CONTROL_UNREACHABLE:
|
||||
printf("@control.unreachable()()");
|
||||
break;
|
||||
case SPL_IR_CONTROL_TRAP:
|
||||
printf("@control.trap()()");
|
||||
break;
|
||||
case SPL_IR_DBG_BREAKPOINT:
|
||||
printf("@dbg.breakpoint()()");
|
||||
break;
|
||||
case SPL_IR_DBG_DECLARE:
|
||||
printf("@dbg.declare()()");
|
||||
break;
|
||||
default:
|
||||
printf("@%s()()", node_name(n->kind));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void dump_func(const spl_type_t *ty, const spl_ir_func_t *f) {
|
||||
printf("func @%s", f->name ? f->name : "?");
|
||||
if (f->fn_tid) {
|
||||
spl_type_node_t *t = spl_type_node((spl_type_t *)ty, f->fn_tid);
|
||||
if (t && t->kind == SPL_TYPE_FN) {
|
||||
printf("(");
|
||||
for (usize i = 0; i < t->fn_type.params.size; i++) {
|
||||
if (i)
|
||||
printf(", ");
|
||||
ir_type_dump(ty, t->fn_type.params.data[i]);
|
||||
}
|
||||
printf(") -> ");
|
||||
ir_type_dump(ty, t->fn_type.ret);
|
||||
}
|
||||
}
|
||||
printf(" {\n");
|
||||
usize li = 0;
|
||||
for (usize i = 1; i < f->nodes.size; i++) {
|
||||
if (li < f->labels.size && f->labels.data[li] == i) {
|
||||
printf("#bb%zu:\n", li);
|
||||
li++;
|
||||
}
|
||||
printf(" ");
|
||||
if (node_produces_value(f->nodes.data[i].kind))
|
||||
printf("%%%zu = ", i);
|
||||
dump_node(ty, &f->nodes.data[i]);
|
||||
printf("\n");
|
||||
}
|
||||
if (li < f->labels.size && f->labels.data[li] == f->nodes.size)
|
||||
printf("#bb%zu:\n", li);
|
||||
printf("}\n");
|
||||
}
|
||||
|
||||
void spl_ir_dump(spl_ir_t *ir, const spl_type_t *ty) {
|
||||
printf("; SPL IR module (%zu funcs)\n", ir->funcs.size - 1);
|
||||
for (usize i = 1; i < ir->funcs.size; i++)
|
||||
dump_func(ty, &ir->funcs.data[i]);
|
||||
}
|
||||
|
||||
140
stage1/spl_ir.h
140
stage1/spl_ir.h
@@ -2,6 +2,7 @@
|
||||
#define __SPL_IR_H__
|
||||
|
||||
#include "../stage0/include/utils.h"
|
||||
#include "spl_type.h"
|
||||
|
||||
/* clang-format off */
|
||||
#define SPL_IR_FN_TABLE \
|
||||
@@ -64,6 +65,7 @@
|
||||
X(control.br, V0, SPL_IR_CONTROL_BR) \
|
||||
X(control.jmp, V0, SPL_IR_CONTROL_JMP) \
|
||||
X(control.call, V0, SPL_IR_CONTROL_CALL) \
|
||||
X(control.param, V0, SPL_IR_CONTROL_PARAM) \
|
||||
X(control.ret, V0, SPL_IR_CONTROL_RET) \
|
||||
X(control.unreachable, V0, SPL_IR_CONTROL_UNREACHABLE) \
|
||||
X(control.trap, V0, SPL_IR_CONTROL_TRAP) \
|
||||
@@ -80,14 +82,136 @@ typedef enum {
|
||||
} spl_ir_kind_t;
|
||||
/* clang-format on */
|
||||
|
||||
typedef struct {
|
||||
spl_ir_kind_t kind;
|
||||
} spl_ir_node_t;
|
||||
typedef VEC(spl_ir_node_t) spl_ir_node_vec_t;
|
||||
|
||||
typedef usize spl_ir_node_ref_t; /* 0 is error */
|
||||
typedef VEC(spl_ir_node_ref_t) spl_ir_node_ref_vec_t;
|
||||
|
||||
typedef usize spl_ir_func_ref_t; /* 0 is error */
|
||||
|
||||
typedef struct {
|
||||
spl_ir_kind_t kind;
|
||||
union {
|
||||
struct {
|
||||
spl_type_id_t tid;
|
||||
spl_ir_node_ref_t left;
|
||||
spl_ir_node_ref_t right;
|
||||
} arith;
|
||||
struct {
|
||||
spl_type_id_t tid;
|
||||
spl_ir_node_ref_t a;
|
||||
spl_ir_node_ref_t b;
|
||||
} cmp;
|
||||
struct {
|
||||
spl_type_id_t from_tid;
|
||||
spl_type_id_t to_tid;
|
||||
spl_ir_node_ref_t val;
|
||||
} cast;
|
||||
struct {
|
||||
spl_type_id_t tid;
|
||||
spl_ir_node_ref_t count;
|
||||
} mem_alloc;
|
||||
struct {
|
||||
spl_type_id_t tid;
|
||||
spl_ir_node_ref_t ptr;
|
||||
} mem_load;
|
||||
struct {
|
||||
spl_type_id_t tid;
|
||||
spl_ir_node_ref_t ptr;
|
||||
spl_ir_node_ref_t val;
|
||||
} mem_store;
|
||||
struct {
|
||||
spl_type_id_t tid;
|
||||
spl_ir_node_ref_t ptr;
|
||||
spl_ir_node_ref_t offset;
|
||||
} mem_offset;
|
||||
struct {
|
||||
spl_type_id_t tid;
|
||||
spl_ir_node_ref_t dst;
|
||||
spl_ir_node_ref_t src;
|
||||
spl_ir_node_ref_t size;
|
||||
} mem_copy;
|
||||
struct {
|
||||
spl_type_id_t tid;
|
||||
spl_ir_node_ref_t dst;
|
||||
spl_ir_node_ref_t val;
|
||||
spl_ir_node_ref_t size;
|
||||
} mem_set;
|
||||
struct {
|
||||
spl_ir_node_ref_t ordering;
|
||||
} mem_fence;
|
||||
struct {
|
||||
spl_type_id_t tid;
|
||||
union {
|
||||
usize int_lit;
|
||||
double float_lit;
|
||||
const char *cstr_lit;
|
||||
char ch_lit;
|
||||
spl_ir_func_ref_t fn;
|
||||
};
|
||||
} type_const;
|
||||
struct {
|
||||
spl_type_id_t tid;
|
||||
} bitsizeof;
|
||||
struct {
|
||||
spl_type_id_t tid;
|
||||
} ir_sizeof;
|
||||
struct {
|
||||
spl_type_id_t tid;
|
||||
} ir_alignof;
|
||||
struct {
|
||||
spl_type_id_t tid;
|
||||
spl_ir_node_ref_t field_idx;
|
||||
} ir_offsetof;
|
||||
struct {
|
||||
spl_type_id_t tid;
|
||||
} field_count;
|
||||
|
||||
struct {
|
||||
spl_type_id_t tid;
|
||||
spl_ir_node_ref_vec_t fields;
|
||||
} agg_construct;
|
||||
struct {
|
||||
spl_type_id_t tid;
|
||||
isize field_idx;
|
||||
spl_ir_node_ref_t val;
|
||||
} agg_extract;
|
||||
struct {
|
||||
spl_type_id_t tid;
|
||||
isize field_idx;
|
||||
spl_ir_node_ref_t agg;
|
||||
spl_ir_node_ref_t field;
|
||||
} agg_insert;
|
||||
|
||||
struct {
|
||||
spl_type_id_t tid;
|
||||
spl_ir_node_ref_t cond;
|
||||
spl_ir_node_ref_t true_val;
|
||||
spl_ir_node_ref_t false_val;
|
||||
} control_select;
|
||||
struct {
|
||||
spl_ir_node_ref_t cond;
|
||||
spl_ir_node_ref_t true_label;
|
||||
spl_ir_node_ref_t false_label;
|
||||
} control_br;
|
||||
struct {
|
||||
spl_ir_node_ref_t label;
|
||||
} control_jmp;
|
||||
struct {
|
||||
spl_type_id_t tid;
|
||||
spl_ir_node_ref_t func;
|
||||
spl_ir_node_ref_vec_t params;
|
||||
} control_call;
|
||||
struct {
|
||||
spl_type_id_t tid;
|
||||
spl_ir_node_ref_t idx;
|
||||
} control_param;
|
||||
struct {
|
||||
spl_type_id_t tid;
|
||||
spl_ir_node_ref_t val;
|
||||
} control_ret;
|
||||
};
|
||||
} spl_ir_node_t;
|
||||
typedef VEC(spl_ir_node_t) spl_ir_node_vec_t;
|
||||
|
||||
typedef struct {
|
||||
enum {
|
||||
SPL_IR_ATTR_NONE,
|
||||
@@ -103,12 +227,12 @@ typedef VEC(spl_ir_attr_t) spl_ir_attr_vec_t;
|
||||
typedef struct {
|
||||
const char *name;
|
||||
spl_ir_attr_t attr;
|
||||
spl_type_id_t fn_tid;
|
||||
spl_ir_node_vec_t nodes;
|
||||
spl_ir_node_ref_vec_t labels;
|
||||
} spl_ir_func_t;
|
||||
typedef usize spl_ir_func_ref_t; /* 0 is error */
|
||||
typedef VEC(spl_ir_func_t) spl_ir_func_vec_t;
|
||||
|
||||
typedef VEC(spl_ir_func_t) spl_ir_func_vec_t;
|
||||
typedef struct {
|
||||
spl_ir_func_vec_t funcs;
|
||||
} spl_ir_t;
|
||||
@@ -122,6 +246,6 @@ spl_ir_func_ref_t spl_ir_alloc_fn(spl_ir_t *ir);
|
||||
spl_ir_node_t *spl_ir_node(spl_ir_t *ir, spl_ir_func_ref_t fn_id, spl_ir_node_ref_t node_id);
|
||||
spl_ir_func_t *spl_ir_func(spl_ir_t *ir, spl_ir_func_ref_t fn_id);
|
||||
|
||||
void spl_ir_dump(spl_ir_t *ir);
|
||||
void spl_ir_dump(spl_ir_t *ir, const spl_type_t *ty);
|
||||
|
||||
#endif /* __SPL_IR_H__ */
|
||||
|
||||
@@ -112,11 +112,11 @@ static spl_type_id_t find_type(spl_sema_t *sema, const char *name) {
|
||||
/* ---- 聚合成员登记(def 层 agg_def) ---- */
|
||||
|
||||
static void agg_add_member(spl_sema_t *sema, spl_def_id_t def, const char *name, spl_type_id_t type,
|
||||
spl_scope_id_t scope) {
|
||||
spl_scope_id_t scope, spl_def_id_t member_def) {
|
||||
spl_def_node_t *d = def_at(sema, def);
|
||||
if (!d || d->kind != SPL_DEF_AGG)
|
||||
return;
|
||||
spl_var_def_t v = {name, 0, type, scope};
|
||||
spl_var_def_t v = {name, member_def, type, scope};
|
||||
vec_push(d->agg_def, v);
|
||||
}
|
||||
|
||||
@@ -281,6 +281,9 @@ static spl_type_id_t resolve_type_expr(spl_sema_t *sema, spl_ast_node_ref_t ref)
|
||||
(atom->type_atom.kind == SPL_AST_TYPE_ANY || atom->type_atom.kind == SPL_AST_TYPE_PTR))
|
||||
sema_error(sema, ref, "bare `_` type only allowed as pointer target `*_`");
|
||||
}
|
||||
/* AST 注解:该 type_expr 解析到的 def(聚合/别名/内置为 0;ast2ir 据此直接取类型) */
|
||||
if (base)
|
||||
n->resolved_def_id = def_for_type(sema, base);
|
||||
return base;
|
||||
}
|
||||
|
||||
@@ -331,6 +334,7 @@ static agg_handle_t agg_prepare(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
||||
spl_def_id_t def = def_alloc(sema, SPL_DEF_AGG);
|
||||
def_at(sema, def)->type_id = tid;
|
||||
vec_init(def_at(sema, def)->agg_def);
|
||||
te->resolved_def_id = def; /* 注解:该 type_expr 解析到的 def */
|
||||
h.tid = tid;
|
||||
h.def = def;
|
||||
return h;
|
||||
@@ -366,13 +370,20 @@ static void agg_resolve(spl_sema_t *sema, spl_ast_node_ref_t ref, spl_type_id_t
|
||||
m->member_decl.type_expr ? resolve_type_expr(sema, m->member_decl.type_expr) : 0;
|
||||
/* resolve_type_expr 可能 alloc 新类型 → 两表 realloc,须重新取节点 */
|
||||
spl_type_node_t *tn = spl_type_node(&sema->type, tid);
|
||||
/* 每个 MEMBER_DECL 建一个 SPL_DEF_MEMBER def(结构字段/枚举变体) */
|
||||
spl_type_id_t mtype = 0;
|
||||
if (tn->kind == SPL_TYPE_ENUM) {
|
||||
vec_push(tn->enum_type.variants, ft ? ft : tid);
|
||||
agg_add_member(sema, def, m->member_decl.name, ft ? ft : tid, agg_scope);
|
||||
mtype = ft ? ft : tid; /* 哨兵:无载荷变体 = 枚举自身 tid */
|
||||
vec_push(tn->enum_type.variants, mtype);
|
||||
} else {
|
||||
mtype = ft;
|
||||
vec_push(tn->agg_field_types, ft);
|
||||
agg_add_member(sema, def, m->member_decl.name, ft, agg_scope);
|
||||
}
|
||||
spl_def_id_t mdef = def_alloc(sema, SPL_DEF_MEMBER);
|
||||
def_at(sema, mdef)->type_id = mtype;
|
||||
def_at(sema, mdef)->var_def.name = m->member_decl.name;
|
||||
agg_add_member(sema, def, m->member_decl.name, mtype, agg_scope, mdef);
|
||||
m->resolved_def_id = mdef; /* 注解:member_decl → 其 SPL_DEF_MEMBER def */
|
||||
break;
|
||||
}
|
||||
case SPL_AST_FN_DECL:
|
||||
@@ -416,13 +427,19 @@ static spl_type_id_t build_agg(spl_sema_t *sema, spl_ast_node_ref_t ref, spl_sco
|
||||
|
||||
/* 变量/常量/绑定节点:建 VAR def(不包 SPL_TYPE_ID) */
|
||||
static void register_binding(spl_sema_t *sema, const char *name, spl_ast_node_ref_t type_expr,
|
||||
spl_scope_id_t scope, spl_def_id_t agg_def) {
|
||||
spl_scope_id_t scope, spl_def_id_t agg_def,
|
||||
spl_ast_node_ref_t node_ref) {
|
||||
spl_type_id_t t = type_expr ? resolve_type_expr(sema, type_expr) : 0;
|
||||
spl_def_id_t def = new_var_def(sema, name, t, scope);
|
||||
if (!spl_sema_scope_insert(sema, scope, name, def))
|
||||
sema_error(sema, 0, "duplicate symbol");
|
||||
if (agg_def)
|
||||
agg_add_member(sema, agg_def, name, t, scope);
|
||||
agg_add_member(sema, agg_def, name, t, scope, def);
|
||||
if (node_ref) {
|
||||
spl_ast_node_t *nn = node_at(sema->ast, node_ref);
|
||||
if (nn)
|
||||
nn->resolved_def_id = def; /* 注解:var/const 声明 → 其 VAR def */
|
||||
}
|
||||
}
|
||||
|
||||
static void sema_var_decl(spl_sema_t *sema, spl_ast_node_ref_t ref, spl_scope_id_t scope,
|
||||
@@ -430,7 +447,7 @@ static void sema_var_decl(spl_sema_t *sema, spl_ast_node_ref_t ref, spl_scope_id
|
||||
spl_ast_node_t *n = node_at(sema->ast, ref);
|
||||
if (!n)
|
||||
return;
|
||||
register_binding(sema, n->var_decl.name, n->var_decl.type_expr, scope, agg_def);
|
||||
register_binding(sema, n->var_decl.name, n->var_decl.type_expr, scope, agg_def, ref);
|
||||
}
|
||||
|
||||
static void sema_const_decl(spl_sema_t *sema, spl_ast_node_ref_t ref, spl_scope_id_t scope,
|
||||
@@ -438,7 +455,7 @@ static void sema_const_decl(spl_sema_t *sema, spl_ast_node_ref_t ref, spl_scope_
|
||||
spl_ast_node_t *n = node_at(sema->ast, ref);
|
||||
if (!n)
|
||||
return;
|
||||
register_binding(sema, n->const_decl.name, n->const_decl.type_expr, scope, agg_def);
|
||||
register_binding(sema, n->const_decl.name, n->const_decl.type_expr, scope, agg_def, ref);
|
||||
}
|
||||
|
||||
/* fn 声明:建 fn type + FN_PARAMS def + 登记名字。不建 fn_scope(由 check 新建)。
|
||||
@@ -477,7 +494,8 @@ static void sema_fn_decl(spl_sema_t *sema, spl_ast_node_ref_t ref, spl_scope_id_
|
||||
if (!spl_sema_scope_insert(sema, scope, n->fn_decl.name, fdef))
|
||||
sema_error(sema, ref, "duplicate function name");
|
||||
if (agg_def)
|
||||
agg_add_member(sema, agg_def, n->fn_decl.name, fid, scope);
|
||||
agg_add_member(sema, agg_def, n->fn_decl.name, fid, scope, fdef);
|
||||
n->resolved_def_id = fdef; /* 注解:fn 声明 → 其 FN_PARAMS def */
|
||||
}
|
||||
|
||||
static void sema_type_decl(spl_sema_t *sema, spl_ast_node_ref_t ref, spl_scope_id_t scope,
|
||||
@@ -510,10 +528,11 @@ static void sema_type_decl(spl_sema_t *sema, spl_ast_node_ref_t ref, spl_scope_i
|
||||
if (!spl_sema_scope_insert(sema, scope, n->type_decl.name, def))
|
||||
sema_error(sema, ref, "duplicate type name");
|
||||
if (agg_def)
|
||||
agg_add_member(sema, agg_def, n->type_decl.name, tid, scope);
|
||||
agg_add_member(sema, agg_def, n->type_decl.name, tid, scope, def);
|
||||
/* 嵌套类型提升到文件作用域:兄弟聚合可裸名引用(如 Lexer 方法内 Tag.eof) */
|
||||
if (agg_def)
|
||||
spl_sema_scope_insert(sema, sema->root_scope, n->type_decl.name, def);
|
||||
n->resolved_def_id = def; /* 注解:type_decl → 其 AGG/ALIAS def */
|
||||
}
|
||||
|
||||
/* ================================================================
|
||||
@@ -937,14 +956,32 @@ static spl_type_id_t infer_array_lit(spl_sema_t *sema, spl_ast_node_ref_t ref, s
|
||||
/* 标识符:scope 查找(def → 类型) */
|
||||
static spl_type_id_t infer_ident(spl_sema_t *sema, spl_ast_node_ref_t ref, spl_ast_node_t *n) {
|
||||
spl_ast_node_t *pn = n->kind == SPL_AST_EXPR ? node_at(sema->ast, n->expr.op_expr.left) : n;
|
||||
spl_type_id_t t = find_type(sema, pn->primary_expr.ident);
|
||||
spl_def_id_t def = find_bare(sema, pn->primary_expr.ident);
|
||||
spl_type_id_t t = def_type(sema, def);
|
||||
if (!t) {
|
||||
sema_error(sema, ref, "undefined identifier");
|
||||
return 0;
|
||||
}
|
||||
/* 注解:IDENT 引用 → 其符号 def(var 用 VAR、fn 用 FN_PARAMS 等) */
|
||||
pn->resolved_def_id = def;
|
||||
return t;
|
||||
}
|
||||
|
||||
/* 表达式 ref 解析到的 def:取内层节点注解;裸 ident 兜底 find_bare */
|
||||
static spl_def_id_t expr_def_at(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
||||
spl_ast_node_t *n = node_at(sema->ast, ref);
|
||||
if (!n || n->kind != SPL_AST_EXPR)
|
||||
return 0;
|
||||
spl_ast_node_t *inner = node_at(sema->ast, n->expr.op_expr.left);
|
||||
if (!inner)
|
||||
return 0;
|
||||
if (inner->resolved_def_id)
|
||||
return inner->resolved_def_id;
|
||||
if (n->expr.op == SPL_AST_PRIMARY_EXPR && inner->primary_expr.kind == SPL_AST_IDENT)
|
||||
return find_bare(sema, inner->primary_expr.ident);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static spl_type_id_t infer_postfix(spl_sema_t *sema, spl_ast_node_ref_t ref, spl_ast_node_t *n);
|
||||
static spl_type_id_t infer_prefix(spl_sema_t *sema, spl_ast_node_ref_t ref, spl_ast_node_t *n);
|
||||
static void check_stmt(spl_sema_t *sema, spl_ast_node_ref_t ref, spl_sema_ctx_t ctx);
|
||||
@@ -1080,6 +1117,8 @@ static spl_type_id_t infer_postfix(spl_sema_t *sema, spl_ast_node_ref_t ref, spl
|
||||
/* 指针自动解引用一层 */
|
||||
if (t && t->kind == SPL_TYPE_PTR)
|
||||
base = underlying(sema, t->ptr_pointee);
|
||||
/* 注解:FIELD 节点 → 被访问聚合(自动解引用后)的 AGG def;非聚合为 0 */
|
||||
pf->resolved_def_id = def_for_type(sema, base);
|
||||
t = type_node(sema, base);
|
||||
if (!t) {
|
||||
sema_error(sema, ref, "field access on non-aggregate");
|
||||
@@ -1171,6 +1210,8 @@ static spl_type_id_t infer_postfix(spl_sema_t *sema, spl_ast_node_ref_t ref, spl
|
||||
sema_error(sema, ref, "call requires function type");
|
||||
return 0;
|
||||
}
|
||||
/* 注解:CALL 节点 → 被调 fn 的 def(从 callee primary 节点/裸名解析) */
|
||||
pf->resolved_def_id = expr_def_at(sema, pf->postfix_expr.primary_expr);
|
||||
spl_ast_node_ref_vec_t *args = &pf->postfix_expr.call_expr;
|
||||
/* 变参 fn(如 vm_printf)最后一个形参 name=NULL 且类型可为 0 */
|
||||
/* 注意:infer_expr 可能新分配类型使 type_table realloc,t 会失效,须每次刷新 */
|
||||
@@ -1623,11 +1664,13 @@ static void check_block(spl_sema_t *sema, spl_ast_node_ref_vec_t *block, spl_sco
|
||||
if (b->block_item.kind == SPL_AST_VARDECL) {
|
||||
spl_ast_node_t *vd = node_at(sema->ast, b->block_item.var_decl);
|
||||
if (vd)
|
||||
register_binding(sema, vd->var_decl.name, vd->var_decl.type_expr, scope, 0);
|
||||
register_binding(sema, vd->var_decl.name, vd->var_decl.type_expr, scope, 0,
|
||||
b->block_item.var_decl);
|
||||
} else if (b->block_item.kind == SPL_AST_CONSTDECL) {
|
||||
spl_ast_node_t *cd = node_at(sema->ast, b->block_item.const_decl);
|
||||
if (cd)
|
||||
register_binding(sema, cd->const_decl.name, cd->const_decl.type_expr, scope, 0);
|
||||
register_binding(sema, cd->const_decl.name, cd->const_decl.type_expr, scope, 0,
|
||||
b->block_item.const_decl);
|
||||
} else if (b->block_item.kind == SPL_AST_TYPEDECL) {
|
||||
spl_ast_node_t *td = node_at(sema->ast, b->block_item.type_decl);
|
||||
if (td)
|
||||
@@ -1664,6 +1707,10 @@ static void check_fn_body(spl_sema_t *sema, spl_ast_node_ref_t ref, spl_def_id_t
|
||||
if (pv->name) {
|
||||
spl_def_id_t pdef = new_var_def(sema, pv->name, pv->type_id, fn_scope);
|
||||
spl_sema_scope_insert(sema, fn_scope, pv->name, pdef);
|
||||
/* 注解:param_decl → 其在 fn_scope 的 VAR def */
|
||||
spl_ast_node_t *pd = node_at(sema->ast, n->fn_decl.param_list.data[i]);
|
||||
if (pd)
|
||||
pd->resolved_def_id = pdef;
|
||||
}
|
||||
}
|
||||
check_block(sema, &n->fn_decl.block, fn_scope, ctx);
|
||||
@@ -1745,7 +1792,7 @@ void spl_sema_run(spl_sema_t *sema) {
|
||||
continue;
|
||||
if (!spl_sema_scope_insert(sema, sema->root_scope, m->type_decl.name, h.def))
|
||||
sema_error(sema, mref, "duplicate type name");
|
||||
agg_add_member(sema, sema->root_def, m->type_decl.name, h.tid, sema->root_scope);
|
||||
agg_add_member(sema, sema->root_def, m->type_decl.name, h.tid, sema->root_scope, h.def);
|
||||
} else if (te) {
|
||||
spl_type_id_t tid = resolve_type_expr(sema, m->type_decl.type_expr);
|
||||
spl_def_id_t def = def_alloc(sema, SPL_DEF_ALIAS);
|
||||
@@ -1757,7 +1804,7 @@ void spl_sema_run(spl_sema_t *sema) {
|
||||
d->type_def.scope_id = sema->root_scope;
|
||||
if (!spl_sema_scope_insert(sema, sema->root_scope, m->type_decl.name, def))
|
||||
sema_error(sema, mref, "duplicate type name");
|
||||
agg_add_member(sema, sema->root_def, m->type_decl.name, tid, sema->root_scope);
|
||||
agg_add_member(sema, sema->root_def, m->type_decl.name, tid, sema->root_scope, def);
|
||||
}
|
||||
}
|
||||
/* 1b. fn 名(建 fn type + def) */
|
||||
|
||||
@@ -211,6 +211,8 @@ static const char *def_kind_name(spl_def_node_t *d) {
|
||||
return "builtin";
|
||||
case SPL_DEF_VAR:
|
||||
return "var";
|
||||
case SPL_DEF_MEMBER:
|
||||
return "member";
|
||||
case SPL_DEF_FN_PARAMS:
|
||||
return "fn_params";
|
||||
case SPL_DEF_AGG:
|
||||
@@ -296,6 +298,9 @@ void spl_type_def_dump(spl_type_t *type, spl_def_id_t id) {
|
||||
case SPL_DEF_VAR:
|
||||
printf(" var=%s", d->var_def.name ? d->var_def.name : "?");
|
||||
break;
|
||||
case SPL_DEF_MEMBER:
|
||||
printf(" member=%s", d->var_def.name ? d->var_def.name : "?");
|
||||
break;
|
||||
case SPL_DEF_ALIAS:
|
||||
case SPL_DEF_DISTINCT:
|
||||
printf(" type=%s", d->type_def.name ? d->type_def.name : "?");
|
||||
|
||||
@@ -65,6 +65,7 @@ typedef struct {
|
||||
enum {
|
||||
SPL_DEF_NONE,
|
||||
SPL_DEF_BUILTIN,
|
||||
SPL_DEF_MEMBER,
|
||||
SPL_DEF_VAR,
|
||||
SPL_DEF_FN_PARAMS,
|
||||
SPL_DEF_AGG, // include enum variants
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "spl_ast.h"
|
||||
#include "spl_ast2ir.h"
|
||||
#include "spl_lexer.h"
|
||||
#include "spl_sema.h"
|
||||
#include "spl_tok.h"
|
||||
@@ -102,6 +103,34 @@ static void dump_sema(const char *src, const char *fname) {
|
||||
spl_ast_drop(&ast);
|
||||
}
|
||||
|
||||
static void dump_ir(const char *src, const char *fname) {
|
||||
spl_tok_vec_t toks = spl_lex(src, fname);
|
||||
spl_ast_t ast;
|
||||
spl_ast_init(&ast, &toks);
|
||||
spl_ast_prase(&ast);
|
||||
spl_ast_valid(&ast);
|
||||
spl_sema_t sema;
|
||||
spl_sema_init(&sema);
|
||||
sema.ast = *
|
||||
spl_sema_run(&sema);
|
||||
spl_sema_check(&sema);
|
||||
if (sema.error_count) {
|
||||
printf("sema errors=%d, skip IR\n", sema.error_count);
|
||||
spl_sema_drop(&sema);
|
||||
spl_ast_drop(&ast);
|
||||
return;
|
||||
}
|
||||
spl_ast2ir_t a2ir;
|
||||
spl_ast2ir_init(&a2ir, &sema);
|
||||
spl_ast2ir_run(&a2ir);
|
||||
if (a2ir.err_count)
|
||||
printf("ast2ir errors=%d\n", a2ir.err_count);
|
||||
spl_ir_dump(&a2ir.ir, &sema.type);
|
||||
spl_ast2ir_drop(&a2ir);
|
||||
spl_sema_drop(&sema);
|
||||
spl_ast_drop(&ast);
|
||||
}
|
||||
|
||||
static int cmd_dump(const char *flags, const char *path) {
|
||||
long len;
|
||||
char *src = read_file(path, &len);
|
||||
@@ -110,12 +139,15 @@ static int cmd_dump(const char *flags, const char *path) {
|
||||
int do_tokens = strstr(flags, "tokens") != NULL || strcmp(flags, "all") == 0;
|
||||
int do_ast = strstr(flags, "ast") != NULL || strcmp(flags, "all") == 0;
|
||||
int do_sema = strstr(flags, "sema") != NULL || strcmp(flags, "all") == 0;
|
||||
int do_ir = strstr(flags, "ir") != NULL || strcmp(flags, "all") == 0;
|
||||
if (do_tokens)
|
||||
dump_tokens(src, path);
|
||||
if (do_ast)
|
||||
dump_ast(src, path);
|
||||
if (do_sema)
|
||||
dump_sema(src, path);
|
||||
if (do_ir)
|
||||
dump_ir(src, path);
|
||||
free(src);
|
||||
return 0;
|
||||
}
|
||||
@@ -127,7 +159,7 @@ int main(int argc, char **argv) {
|
||||
}
|
||||
if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-h") == 0) {
|
||||
LOG_INFO("splc0 <in> <out> compile (.spl -> .sir, 阶段 B)\n");
|
||||
LOG_INFO("splc0 --dump <flags> <file> dump: tokens,ast,sema,all\n");
|
||||
LOG_INFO("splc0 --dump <flags> <file> dump: tokens,ast,sema,ir,all\n");
|
||||
return 0;
|
||||
}
|
||||
int argi = 1;
|
||||
|
||||
@@ -20,8 +20,8 @@ type Optional = enum {
|
||||
|
||||
/* ---- 带结构体数据的枚举 ---- */
|
||||
type Point = struct {
|
||||
var x: i32;
|
||||
var y: i32;
|
||||
x: i32;
|
||||
y: i32;
|
||||
}
|
||||
|
||||
type Shape = enum {
|
||||
|
||||
@@ -1,54 +1,54 @@
|
||||
/* ===== å¤<C3A5>æ<EFBFBD>‚类型嵌套综å<C2BC>ˆæµ‹è¯• =====
|
||||
* test20_complex — 结构体嵌套、切片、数组、方法、类型别名、枚举等
|
||||
* 难度:5/5
|
||||
* test20_complex â€?结构体嵌套ã€<C3A3>切片ã€<C3A3>数组ã€<C3A3>方法ã€<C3A3>类型别å<C2AB><C3A5>ã€<C3A3>枚举ç‰
|
||||
* 难度�/5
|
||||
*/
|
||||
/* ---- 基础结构体 ---- */
|
||||
/* ---- 基础结构�---- */
|
||||
type Point = struct {
|
||||
var x: i32;
|
||||
var y: i32;
|
||||
x: i32,
|
||||
y: i32,
|
||||
}
|
||||
|
||||
/* ---- 嵌套结构体 ---- */
|
||||
/* ---- 嵌套结构�---- */
|
||||
type Rect = struct {
|
||||
var min: Point;
|
||||
var max: Point;
|
||||
min: Point,
|
||||
max: Point,
|
||||
}
|
||||
|
||||
/* ---- 含切片字段的结构体 (核心 bug 测试) ---- */
|
||||
/* ---- å<EFBFBD>«åˆ‡ç‰‡å—段的结构ä½?(æ ¸å¿ƒ bug 测试) ---- */
|
||||
type Buffer = struct {
|
||||
var data: []u8;
|
||||
var len: usize;
|
||||
data: []u8,
|
||||
len: usize,
|
||||
}
|
||||
|
||||
/* ---- 含数组字段的结构体 ---- */
|
||||
/* ---- å<EFBFBD>«æ•°ç»„å—æ®µçš„结构ä½?---- */
|
||||
type MatrixRow = struct {
|
||||
var items: [4]i32;
|
||||
items: [4]i32,
|
||||
}
|
||||
|
||||
/* ---- 含指针字段的结构体 ---- */
|
||||
/* ---- å<EFBFBD>«æŒ‡é’ˆå—段的结构ä½?---- */
|
||||
type Node = struct {
|
||||
var ptr: *i32;
|
||||
var val: i32;
|
||||
ptr: *i32,
|
||||
val: i32,
|
||||
}
|
||||
|
||||
/* ---- 多层级嵌套:结构体里的结构体里的切片 ---- */
|
||||
type Bundle = struct {
|
||||
var name: *u8;
|
||||
var buf: Buffer;
|
||||
var row: MatrixRow;
|
||||
var pt: Point;
|
||||
name: *u8,
|
||||
buf: Buffer,
|
||||
row: MatrixRow,
|
||||
pt: Point,
|
||||
}
|
||||
|
||||
/* ---- 枚举含数据 ---- */
|
||||
/* ---- 枚举å<EFBFBD>«æ•°æ<EFBFBD>?---- */
|
||||
type Status = enum {
|
||||
Active: i32;
|
||||
Inactive;
|
||||
Pending: Point;
|
||||
}
|
||||
|
||||
/* ---- 含方法的结构体 (方法定义在结构体内部) ---- */
|
||||
/* ---- å<EFBFBD>«æ–¹æ³•的结构ä½?(方法定义在结构体内部) ---- */
|
||||
type Counter = struct {
|
||||
var val: i32;
|
||||
val: i32,
|
||||
|
||||
fn inc(self: *Counter) i32 {
|
||||
self.val = self.val + 1;
|
||||
@@ -70,7 +70,7 @@ type Counter = struct {
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* 测试 1: 切片在结构体内部初始化 (修复的核心 bug)
|
||||
* 测试 1: 切片在结构体内部åˆ<C3A5>å§‹åŒ?(ä¿®å¤<C3A5>çš„æ ¸å¿?bug)
|
||||
* ============================================================ */
|
||||
|
||||
fn test_slice_in_struct() i32 {
|
||||
@@ -85,7 +85,7 @@ fn test_slice_in_struct() i32 {
|
||||
if b.data[1] != 66 { ret 3; }
|
||||
if b.data[3] != 68 { ret 4; }
|
||||
|
||||
/* Modify through slice — verify reflection */
|
||||
/* Modify through slice �verify reflection */
|
||||
b.data[0] = 90;
|
||||
if raw[0] != 90 { ret 5; }
|
||||
|
||||
@@ -150,7 +150,7 @@ fn test_nested_struct() i32 {
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* 测试 4: 结构体成员方法 (实例方法调用)
|
||||
* 测试 4: 结构体æˆ<C3A6>员方æ³?(实例方法调用)
|
||||
* ============================================================ */
|
||||
|
||||
fn test_struct_method() i32 {
|
||||
@@ -161,7 +161,7 @@ fn test_struct_method() i32 {
|
||||
if r1 != 1 { ret 1; }
|
||||
if c.val != 1 { ret 2; }
|
||||
|
||||
/* 带参数方法调用 c.add(&c, n) */
|
||||
/* 带å<EFBFBD>‚数方法调ç”?c.add(&c, n) */
|
||||
var r2: i32 = c.add(&c, 5);
|
||||
if r2 != 6 { ret 3; }
|
||||
if c.val != 6 { ret 4; }
|
||||
@@ -193,7 +193,7 @@ fn test_ptr_in_struct() i32 {
|
||||
v = 100;
|
||||
if n.ptr[0] != 100 { ret 3; }
|
||||
|
||||
/* 通过指针在结构体内修改 */
|
||||
/* 通过指针在结构体内修�*/
|
||||
n.ptr[0] = 200;
|
||||
if v != 200 { ret 4; }
|
||||
|
||||
@@ -201,7 +201,7 @@ fn test_ptr_in_struct() i32 {
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* 测试 6: 多层级复杂嵌套
|
||||
* 测试 6: 多层级å¤<C3A5>æ<EFBFBD>‚嵌å¥?
|
||||
* ============================================================ */
|
||||
|
||||
fn test_complex_nesting() i32 {
|
||||
@@ -289,7 +289,7 @@ fn test_enum_complex() i32 {
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* 主函数
|
||||
* 主函�
|
||||
* ============================================================ */
|
||||
|
||||
fn main() i32 {
|
||||
|
||||
Reference in New Issue
Block a user