From 459b6188a9df3e6c61cbd7daef24b56dfd3ed395 Mon Sep 17 00:00:00 2001 From: zzy <2450266535@qq.com> Date: Mon, 20 Jul 2026 20:53:41 +0800 Subject: [PATCH] =?UTF-8?q?stage1=20-=20=E5=85=A8=E9=9D=A2=E9=87=8D?= =?UTF-8?q?=E6=9E=84=20stage1=20=E7=BC=96=E8=AF=91=E5=99=A8=E6=9E=B6?= =?UTF-8?q?=E6=9E=84=EF=BC=9A=E7=B1=BB=E5=9E=8B=E7=B3=BB=E7=BB=9F=EF=BC=88?= =?UTF-8?q?arena=20+=20items=EF=BC=89=E3=80=81IR=20=E5=8F=91=E5=B0=84?= =?UTF-8?q?=E5=B1=82=EF=BC=88spl=5Femit.h/c=EF=BC=89=E3=80=81=E7=BB=9F?= =?UTF-8?q?=E4=B8=80=E6=89=80=E6=9C=89=20emit=20=E8=B0=83=E7=94=A8?= =?UTF-8?q?=E7=82=B9=E3=80=82=20-=20=E5=AE=9E=E7=8E=B0=20as=20=E7=B1=BB?= =?UTF-8?q?=E5=9E=8B=E8=BD=AC=E6=8D=A2=E8=BF=90=E7=AE=97=E7=AC=A6=E3=80=81?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=20&&/||=20=E7=9F=AD=E8=B7=AF=E6=B1=82?= =?UTF-8?q?=E5=80=BC=20bug=E3=80=82=20-=20=E5=9C=A8=20splc1.spl=20?= =?UTF-8?q?=E4=B8=AD=E5=AE=9E=E7=8E=B0=20Vec/Map/Emit=20=E5=9F=BA=E7=A1=80?= =?UTF-8?q?=E5=BA=93=EF=BC=88~50=20=E4=B8=AA=E6=96=B9=E6=B3=95=EF=BC=89?= =?UTF-8?q?=E3=80=82=20-=20=E4=BF=AE=E5=A4=8D=E5=AE=9E=E4=BE=8B=E6=96=B9?= =?UTF-8?q?=E6=B3=95=E8=B0=83=E7=94=A8=E4=B8=AD=20self=20=E5=8F=82?= =?UTF-8?q?=E6=95=B0=E8=A2=AB=E9=94=99=E8=AF=AF=E4=B8=A2=E5=BC=83=E7=9A=84?= =?UTF-8?q?=20bug=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- stage1/spl_comp.c | 10 +- stage1/spl_comp.h | 12 +- stage1/spl_emit.c | 92 ++++++++++----- stage1/spl_emit.h | 23 +++- stage1/spl_expr.c | 209 +++++++++++++++++----------------- stage1/spl_lex_util.c | 9 ++ stage1/spl_lex_util.h | 11 ++ stage1/spl_lexer.h | 8 +- stage1/spl_parser.c | 63 ++++++---- stage1/spl_stmt.c | 68 +++++++---- stage1/splc0.c | 1 + stage1/test06_for.spl | 2 +- stage1/test11_enum.spl | 2 +- stage1/test13_extern.spl | 8 +- stage1/test15_defer.spl | 2 +- stage1/test16_methods.spl | 2 +- stage1/test17_integration.spl | 2 +- 17 files changed, 307 insertions(+), 217 deletions(-) diff --git a/stage1/spl_comp.c b/stage1/spl_comp.c index 94a484c..ba0a71b 100644 --- a/stage1/spl_comp.c +++ b/stage1/spl_comp.c @@ -1,6 +1,7 @@ /* spl_comp.c — SPL compiler main logic and codegen helpers */ #include "spl_comp.h" +#include "spl_lex_util.h" #include #include #include @@ -61,10 +62,8 @@ void spl_comp_reset(spl_comp_t *ctx) { ctx->addr_of_mode = 0; free(ctx->break_patches); ctx->break_patches = NULL; - vec_free(ctx->emit.call_fixups); - vec_init(ctx->emit.call_fixups); - vec_free(ctx->emit.call_fixup_funcs); - vec_init(ctx->emit.call_fixup_funcs); + vec_free(ctx->emit.fixups); + vec_init(ctx->emit.fixups); } void spl_comp_error(spl_comp_t *ctx, const char *fmt, ...) { @@ -172,8 +171,7 @@ int spl_lookup_func(spl_comp_t *ctx, const char *name) { if (items) { vec_for(*items, j) { spl_type_item_t *it = &vec_at(*items, j); - if (it->item_kind == ITEM_METHOD && it->name && - strcmp(it->name, name) == 0) + if (it->item_kind == ITEM_METHOD && it->name && strcmp(it->name, name) == 0) return it->method.func_idx; } } diff --git a/stage1/spl_comp.h b/stage1/spl_comp.h index dd8b555..5932c3c 100644 --- a/stage1/spl_comp.h +++ b/stage1/spl_comp.h @@ -10,8 +10,8 @@ #include #include -#include "spl_type.h" #include "spl_emit.h" +#include "spl_type.h" /* Forward declarations */ typedef struct spl_comp spl_comp_t; @@ -162,8 +162,7 @@ spl_expr_result_t spl_parse_expr(spl_comp_t *ctx, int min_prec); spl_expr_result_t spl_parse_struct_literal(spl_comp_t *ctx, int type_idx); /* Match arm pattern comparison */ -int spl_emit_match_enum_cmp(spl_comp_t *ctx, int enum_type_idx, int val_offset, - int by_value); +int spl_emit_match_enum_cmp(spl_comp_t *ctx, int enum_type_idx, int val_offset, int by_value); void spl_emit_match_value_cmp(spl_comp_t *ctx, int val_offset); /* ============================================================ @@ -178,9 +177,6 @@ spl_expr_result_t spl_parse_block_expr(spl_comp_t *ctx); * Remaining helpers in spl_comp.c * ============================================================ */ -void spl_emit_ret(spl_comp_t *ctx, int ret_type_idx); -void spl_emit_store_init(spl_comp_t *ctx, int var_offset, int var_type_idx); - /* Variable management */ int spl_declare_var(spl_comp_t *ctx, const char *name, int type_idx, int is_const); spl_var_info_t *spl_lookup_var(spl_comp_t *ctx, const char *name); @@ -207,8 +203,4 @@ void spl_emit_defer_epilogue(spl_comp_t *ctx, int depth); /* Register runtime natives (stub) */ void spl_comp_register(spl_prog_t *prog); -/* Shared token helpers (defined in spl_parser.c) */ -spl_tok_t *peek(spl_comp_t *ctx); -spl_tok_t *advance(spl_comp_t *ctx); - #endif /* __SPL_COMP_H__ */ diff --git a/stage1/spl_emit.c b/stage1/spl_emit.c index 7481a25..9383382 100644 --- a/stage1/spl_emit.c +++ b/stage1/spl_emit.c @@ -1,6 +1,7 @@ /* spl_emit.c — IR emission: frame allocator + Layer 1/2 ops */ #include "spl_emit.h" +#include "spl_comp.h" #include "spl_type.h" #include @@ -11,15 +12,13 @@ void spl_emit_init(spl_emit_t *e, spl_prog_t *prog) { memset(e, 0, sizeof(*e)); e->prog = prog; - vec_init(e->call_fixups); - vec_init(e->call_fixup_funcs); + vec_init(e->fixups); } void spl_emit_drop(spl_emit_t *e) { if (!e) return; - vec_free(e->call_fixups); - vec_free(e->call_fixup_funcs); + vec_free(e->fixups); } /* ============================================================ @@ -30,8 +29,7 @@ int fa_alloc_type(spl_frame_alloc_t *fa, spl_type_ctx_t *tctx, int type_idx) { return fa_alloc(fa, spl_type_size(tctx, type_idx)); } -static spl_val_t emit_raw(spl_emit_t *e, uint16_t opcode, uint16_t type, - spl_val_t imm) { +spl_val_t emit_raw(spl_emit_t *e, uint16_t opcode, uint16_t type, spl_val_t imm) { return spl_prog_emit(e->prog, opcode, type, imm); } @@ -46,19 +44,11 @@ void emit_rot(spl_emit_t *e) { emit_raw(e, SPL_ROT, SPL_VOID, 0); } void emit_pick(spl_emit_t *e, int n) { emit_raw(e, SPL_PICK, SPL_VOID, n); } void emit_push_i32(spl_emit_t *e, int v) { emit_raw(e, SPL_PUSH, SPL_I32, (spl_val_t)v); } -void emit_push_usize(spl_emit_t *e, usize v) { - emit_raw(e, SPL_PUSH, SPL_USIZE, (spl_val_t)v); -} -void emit_push_u64(spl_emit_t *e, uint64_t v) { - emit_raw(e, SPL_PUSH, SPL_U64, (spl_val_t)v); -} -void emit_push_f64(spl_emit_t *e, uint64_t v) { - emit_raw(e, SPL_PUSH, SPL_F64, (spl_val_t)v); -} +void emit_push_usize(spl_emit_t *e, usize v) { emit_raw(e, SPL_PUSH, SPL_USIZE, (spl_val_t)v); } +void emit_push_u64(spl_emit_t *e, uint64_t v) { emit_raw(e, SPL_PUSH, SPL_U64, (spl_val_t)v); } +void emit_push_f64(spl_emit_t *e, uint64_t v) { emit_raw(e, SPL_PUSH, SPL_F64, (spl_val_t)v); } void emit_push_ptr(spl_emit_t *e, spl_val_t v) { emit_raw(e, SPL_PUSH, SPL_PTR, v); } -void emit_push_type(spl_emit_t *e, uint16_t bt, spl_val_t v) { - emit_raw(e, SPL_PUSH, bt, v); -} +void emit_push_type(spl_emit_t *e, uint16_t bt, spl_val_t v) { emit_raw(e, SPL_PUSH, bt, v); } void emit_load_ptr(spl_emit_t *e) { emit_raw(e, SPL_LOAD, SPL_PTR, 0); } void emit_load_usize(spl_emit_t *e) { emit_raw(e, SPL_LOAD, SPL_USIZE, 0); } @@ -95,9 +85,7 @@ void emit_laddr(spl_emit_t *e, int offset) { emit_raw(e, SPL_LADDR, SPL_PTR, off void emit_gaddr(spl_emit_t *e, int idx) { emit_raw(e, SPL_GADDR, SPL_PTR, idx); } void emit_call(spl_emit_t *e, int nargs) { emit_raw(e, SPL_CALL, SPL_VOID, nargs); } -void emit_ncall(spl_emit_t *e, int nargs) { - emit_raw(e, SPL_NCALL, SPL_VOID, nargs); -} +void emit_ncall(spl_emit_t *e, int nargs) { emit_raw(e, SPL_NCALL, SPL_VOID, nargs); } void emit_alloc(spl_emit_t *e, int slots) { emit_raw(e, SPL_ALLOC, SPL_VOID, slots); } void emit_binop(spl_emit_t *e, uint16_t op, uint16_t bt) { emit_raw(e, op, bt, 0); } @@ -143,8 +131,8 @@ void emit_copy_addr_to_addr(spl_emit_t *e, usize nslots, int depth) { emit_drop(e); } -void emit_load_to_var(spl_emit_t *e, spl_type_ctx_t *tctx, int ptr_slot_offset, - usize byte_offset, int data_type_idx, int var_offset) { +void emit_load_to_var(spl_emit_t *e, spl_type_ctx_t *tctx, int ptr_slot_offset, usize byte_offset, + int data_type_idx, int var_offset) { emit_laddr(e, ptr_slot_offset); emit_load_ptr(e); emit_ptr_add(e, byte_offset); @@ -176,8 +164,8 @@ void emit_ptr_add(spl_emit_t *e, usize byte_off) { spl_val_t emit_call_with_fixup(spl_emit_t *e, int nargs, int func_idx) { spl_val_t fixup_addr = emit_raw(e, SPL_PUSH, SPL_PTR, 0); emit_call(e, nargs); - vec_push(e->call_fixups, fixup_addr); - vec_push(e->call_fixup_funcs, func_idx); + spl_fixup_entry_t fe = {fixup_addr, func_idx}; + vec_push(e->fixups, fe); return fixup_addr; } @@ -192,12 +180,54 @@ void emit_return(spl_emit_t *e, spl_type_ctx_t *tctx, int ret_type_idx) { } void emit_patch_call_fixups(spl_emit_t *e, spl_prog_t *prog) { - for (usize i = 0; i < vec_size(e->call_fixups); i++) { - spl_val_t insn_idx = vec_at(e->call_fixups, i); - int pfi = vec_at(e->call_fixup_funcs, i); - if (pfi >= 0 && pfi < (int)vec_size(prog->funcs)) { - spl_val_t addr = vec_at(prog->funcs, pfi).address; - vec_at(prog->insns, insn_idx).imm = addr; + for (usize i = 0; i < vec_size(e->fixups); i++) { + spl_fixup_entry_t *fe = &vec_at(e->fixups, i); + if (fe->func_idx >= 0 && fe->func_idx < (int)vec_size(prog->funcs)) { + spl_val_t addr = vec_at(prog->funcs, fe->func_idx).address; + vec_at(prog->insns, fe->insn_idx).imm = addr; } } } + +void spl_emit_ret(spl_comp_t *ctx, int ret_type_idx) { + if (spl_type_needs_multi_slot(&ctx->tctx, ret_type_idx)) { + emit_laddr(&ctx->emit, (int)sizeof(spl_val_t)); + emit_swap(&ctx->emit); + emit_copy_addr_to_addr(&ctx->emit, spl_type_slot_count(&ctx->tctx, ret_type_idx), 0); + } + emit_return(&ctx->emit, &ctx->tctx, ret_type_idx); +} + +void spl_emit_store_init(spl_comp_t *ctx, int var_offset, int var_type_idx) { + if (var_type_idx >= 0 && (spl_type_kind(&ctx->tctx, var_type_idx) == TYPE_STRUCT || + spl_type_kind(&ctx->tctx, var_type_idx) == TYPE_ENUM)) { + usize sz = spl_type_size(&ctx->tctx, var_type_idx); + if (sz <= sizeof(spl_val_t)) { + emit_store_to_laddr(&ctx->emit, var_offset, + spl_type_emit_type(&ctx->tctx, var_type_idx)); + } else { + usize nslots = (sz + sizeof(spl_val_t) - 1) / sizeof(spl_val_t); + emit_frame_copy(&ctx->emit, var_offset, nslots); + } + } else if (var_type_idx >= 0 && spl_type_kind(&ctx->tctx, var_type_idx) == TYPE_ARRAY) { + int elem_idx = spl_type_elem_type(&ctx->tctx, var_type_idx); + spl_type_t bt = spl_type_emit_type(&ctx->tctx, elem_idx); + usize stride = spl_type_elem_stride(&ctx->tctx, elem_idx); + int arr_len = (int)spl_type_array_len(&ctx->tctx, var_type_idx); + for (int i = arr_len - 1; i >= 0; i--) { + emit_laddr(&ctx->emit, var_offset + (int)(i * stride)); + emit_swap(&ctx->emit); + if (elem_idx >= 0 && !spl_type_is_scalar(&ctx->tctx, elem_idx)) { + emit_copy_addr_to_addr(&ctx->emit, spl_type_slot_count(&ctx->tctx, elem_idx), 0); + } else { + emit_store_type(&ctx->emit, bt); + } + } + } else if (var_type_idx >= 0 && spl_type_kind(&ctx->tctx, var_type_idx) == TYPE_SLICE) { + emit_store_to_laddr(&ctx->emit, var_offset + (int)sizeof(spl_val_t), SPL_USIZE); + emit_store_to_laddr(&ctx->emit, var_offset, SPL_PTR); + } else { + spl_type_t bt = spl_type_emit_type(&ctx->tctx, var_type_idx); + emit_store_to_laddr(&ctx->emit, var_offset, bt); + } +} diff --git a/stage1/spl_emit.h b/stage1/spl_emit.h index 0f8dac3..6273782 100644 --- a/stage1/spl_emit.h +++ b/stage1/spl_emit.h @@ -48,11 +48,15 @@ static inline void fa_free(spl_frame_alloc_t *fa, int mark) { fa->current_bytes * Emit context * ============================================================ */ +typedef struct { + spl_val_t insn_idx; + int func_idx; +} spl_fixup_entry_t; + typedef struct { spl_prog_t *prog; spl_frame_alloc_t frame; - VEC(spl_val_t) call_fixups; - VEC(int) call_fixup_funcs; + VEC(spl_fixup_entry_t) fixups; } spl_emit_t; void spl_emit_init(spl_emit_t *e, spl_prog_t *prog); @@ -119,14 +123,17 @@ void emit_binop(spl_emit_t *e, uint16_t op, uint16_t bt); void emit_dbg_void(spl_emit_t *e); void emit_dbg_usize(spl_emit_t *e); +/* Low-level emit (raw opcode + type + imm) */ +spl_val_t emit_raw(spl_emit_t *e, uint16_t opcode, uint16_t type, spl_val_t imm); + /* ============================================================ * Layer 2 — semantic-level helpers * ============================================================ */ void emit_frame_copy(spl_emit_t *e, int dest_offset, usize nslots); void emit_copy_addr_to_addr(spl_emit_t *e, usize nslots, int depth); -void emit_load_to_var(spl_emit_t *e, spl_type_ctx_t *tctx, int ptr_slot_offset, - usize byte_offset, int data_type_idx, int var_offset); +void emit_load_to_var(spl_emit_t *e, spl_type_ctx_t *tctx, int ptr_slot_offset, usize byte_offset, + int data_type_idx, int var_offset); void emit_store_to_laddr(spl_emit_t *e, int offset, uint16_t type); void emit_ptr_add(spl_emit_t *e, usize byte_off); spl_val_t emit_call_with_fixup(spl_emit_t *e, int nargs, int func_idx); @@ -135,4 +142,12 @@ void emit_return(spl_emit_t *e, spl_type_ctx_t *tctx, int ret_type_idx); /* Patch all fixups */ void emit_patch_call_fixups(spl_emit_t *e, spl_prog_t *prog); +/* ============================================================ + * Layer 3 — compiler-level helpers (need spl_comp_t for tctx) + * ============================================================ */ + +struct spl_comp; +void spl_emit_ret(struct spl_comp *ctx, int ret_type_idx); +void spl_emit_store_init(struct spl_comp *ctx, int var_offset, int var_type_idx); + #endif /* __SPL_EMIT_H__ */ diff --git a/stage1/spl_expr.c b/stage1/spl_expr.c index 92c65d1..b810a8e 100644 --- a/stage1/spl_expr.c +++ b/stage1/spl_expr.c @@ -52,8 +52,7 @@ static int tok_prec(spl_tok_type_t t) { } static spl_expr_result_t parse_infix(spl_comp_t *ctx, spl_expr_result_t left, spl_tok_type_t op); -static void emit_load_or_addr_type(spl_comp_t *ctx, spl_expr_result_t *result, - int type_idx); +static void emit_load_or_addr_type(spl_comp_t *ctx, spl_expr_result_t *result, int type_idx); static spl_expr_result_t parse_postfix_expr(spl_comp_t *ctx, spl_expr_result_t left); static void emit_slice_create(spl_comp_t *ctx, usize stride) { @@ -90,7 +89,8 @@ static int spl_resolve_type_member(spl_comp_t *ctx, int type_idx, const char *fi spl_type_item_vec_t *items = spl_type_items(&ctx->tctx, type_idx); vec_for(*items, i) { spl_type_item_t *it = &vec_at(*items, i); - if (it->item_kind != ITEM_VARIANT) continue; + if (it->item_kind != ITEM_VARIANT) + continue; if (strcmp(it->name, field) == 0) { emit_push_i32(&ctx->emit, it->enum_field.value); *result = (spl_expr_result_t){type_idx, 0}; @@ -365,7 +365,8 @@ static void parse_one_field_init(spl_comp_t *ctx, spl_type_item_vec_t *items, in vec_for(*items, fi) { spl_type_item_t *it = &vec_at(*items, fi); - if (it->item_kind != ITEM_FIELD) continue; + if (it->item_kind != ITEM_FIELD) + continue; if (strcmp(it->name, fname) == 0) { emit_laddr(&ctx->emit, base_offset); usize byte_off = extra_offset + it->aggregate_field.offset; @@ -403,7 +404,8 @@ static void parse_one_field_init(spl_comp_t *ctx, spl_type_item_vec_t *items, in emit_ptr_add(&ctx->emit, i * stride); spl_parse_expr(ctx, PREC_MIN); if (elem_type_idx >= 0 && !spl_type_is_scalar(&ctx->tctx, elem_type_idx)) { - emit_copy_addr_to_addr(&ctx->emit, spl_type_slot_count(&ctx->tctx, elem_type_idx), 1); + emit_copy_addr_to_addr(&ctx->emit, + spl_type_slot_count(&ctx->tctx, elem_type_idx), 1); } else { emit_store_type(&ctx->emit, st); } @@ -425,8 +427,11 @@ static void parse_one_field_init(spl_comp_t *ctx, spl_type_item_vec_t *items, in fv = spl_parse_expr(ctx, PREC_MIN); } (void)fv; - usize nslots = (spl_type_size(&ctx->tctx, ft_idx) + sizeof(spl_val_t) - 1) / sizeof(spl_val_t); - emit_frame_copy(&ctx->emit, base_offset + (int)extra_offset + (int)it->aggregate_field.offset, nslots); + usize nslots = + (spl_type_size(&ctx->tctx, ft_idx) + sizeof(spl_val_t) - 1) / sizeof(spl_val_t); + emit_frame_copy(&ctx->emit, + base_offset + (int)extra_offset + (int)it->aggregate_field.offset, + nslots); emit_drop(&ctx->emit); } else { spl_expr_result_t fv = spl_parse_expr(ctx, PREC_MIN); @@ -512,7 +517,8 @@ spl_expr_result_t spl_parse_struct_literal(spl_comp_t *ctx, int type_idx) { spl_type_item_vec_t *items = spl_type_items(&ctx->tctx, type_idx); vec_for(*items, vi) { spl_type_item_t *v = &vec_at(*items, vi); - if (v->item_kind != ITEM_VARIANT) continue; + if (v->item_kind != ITEM_VARIANT) + continue; if (strcmp(v->name, vname) == 0) { found = 1; emit_laddr(&ctx->emit, base_offset); @@ -620,15 +626,16 @@ static void spl_check_arg_type(spl_comp_t *ctx, const char *fname, int arg_type_ } } -static int parse_call_args_checked(spl_comp_t *ctx, const char *fname, - int *param_type_indices, int nparams) { +static int parse_call_args_checked(spl_comp_t *ctx, const char *fname, int *param_type_indices, + int nparams) { int nargs = 0; int nlogical = 0; if (peek(ctx)->type != TOK_R_PAREN) { for (;;) { spl_expr_result_t arg = spl_parse_expr(ctx, PREC_MIN); if (param_type_indices && nlogical < nparams && param_type_indices[nlogical] >= 0) - spl_check_arg_type(ctx, fname, arg.type_idx, param_type_indices[nlogical], nlogical); + spl_check_arg_type(ctx, fname, arg.type_idx, param_type_indices[nlogical], + nlogical); int arg_slots = 1; if (param_type_indices && nlogical < nparams && param_type_indices[nlogical] >= 0 && @@ -636,7 +643,8 @@ static int parse_call_args_checked(spl_comp_t *ctx, const char *fname, spl_type_kind(&ctx->tctx, param_type_indices[nlogical]) != TYPE_PTR && spl_type_needs_multi_slot(&ctx->tctx, param_type_indices[nlogical])) { usize nslots = (spl_type_size(&ctx->tctx, param_type_indices[nlogical]) + - sizeof(spl_val_t) - 1) / sizeof(spl_val_t); + sizeof(spl_val_t) - 1) / + sizeof(spl_val_t); for (usize i = 0; i < nslots; i++) { emit_dup(&ctx->emit); emit_ptr_add(&ctx->emit, i * sizeof(spl_val_t)); @@ -738,8 +746,7 @@ static spl_expr_result_t parse_group(spl_comp_t *ctx) { return r; } -static void emit_load_or_addr_type(spl_comp_t *ctx, spl_expr_result_t *result, - int type_idx) { +static void emit_load_or_addr_type(spl_comp_t *ctx, spl_expr_result_t *result, int type_idx) { if (spl_type_is_scalar(&ctx->tctx, type_idx)) { if (!ctx->addr_of_mode) { emit_load_type(&ctx->emit, spl_type_emit_type(&ctx->tctx, type_idx)); @@ -776,8 +783,7 @@ static spl_expr_result_t parse_prefix_op(spl_comp_t *ctx) { } break; case TOK_MUL: - if (right.type_idx >= 0 && - spl_type_kind(&ctx->tctx, right.type_idx) == TYPE_PTR && + if (right.type_idx >= 0 && spl_type_kind(&ctx->tctx, right.type_idx) == TYPE_PTR && spl_type_elem_type(&ctx->tctx, right.type_idx) >= 0) { if (right.is_lvalue) { emit_load_ptr(&ctx->emit); @@ -907,9 +913,8 @@ static spl_expr_result_t parse_postfix_expr(spl_comp_t *ctx, spl_expr_result_t l int is_ptr_self = 0; if (spl_type_kind(&ctx->tctx, methods_type_idx) == TYPE_PTR) { int elem_idx = spl_type_elem_type(&ctx->tctx, methods_type_idx); - if (elem_idx >= 0 && - (spl_type_kind(&ctx->tctx, elem_idx) == TYPE_STRUCT || - spl_type_kind(&ctx->tctx, elem_idx) == TYPE_ENUM)) { + if (elem_idx >= 0 && (spl_type_kind(&ctx->tctx, elem_idx) == TYPE_STRUCT || + spl_type_kind(&ctx->tctx, elem_idx) == TYPE_ENUM)) { is_ptr_self = 1; methods_type_idx = elem_idx; } @@ -919,7 +924,8 @@ static spl_expr_result_t parse_postfix_expr(spl_comp_t *ctx, spl_expr_result_t l spl_type_item_vec_t *m_items = spl_type_items(&ctx->tctx, methods_type_idx); vec_for(*m_items, mi) { spl_type_item_t *mit = &vec_at(*m_items, mi); - if (mit->item_kind != ITEM_METHOD) continue; + if (mit->item_kind != ITEM_METHOD) + continue; if (strcmp(mit->name, fname) == 0) { spl_func_info_t *func = &vec_at(ctx->funcs, mit->method.func_idx); @@ -931,7 +937,8 @@ static spl_expr_result_t parse_postfix_expr(spl_comp_t *ctx, spl_expr_result_t l int is_instance = 0; if (func->nparams > 0 && func->param_type_indices[0] >= 0 && spl_type_kind(&ctx->tctx, func->param_type_indices[0]) == TYPE_PTR && - spl_type_elem_type(&ctx->tctx, func->param_type_indices[0]) == methods_type_idx) { + spl_type_elem_type(&ctx->tctx, func->param_type_indices[0]) == + methods_type_idx) { is_instance = 1; } @@ -978,7 +985,8 @@ static spl_expr_result_t parse_postfix_expr(spl_comp_t *ctx, spl_expr_result_t l spl_type_item_vec_t *f_items = spl_type_items(&ctx->tctx, left.type_idx); vec_for(*f_items, fi) { spl_type_item_t *fit = &vec_at(*f_items, fi); - if (fit->item_kind != ITEM_FIELD) continue; + if (fit->item_kind != ITEM_FIELD) + continue; if (strcmp(fit->name, fname) == 0) { emit_ptr_add(&ctx->emit, fit->aggregate_field.offset); emit_load_or_addr_type(ctx, &left, fit->aggregate_field.type_idx); @@ -997,7 +1005,8 @@ static spl_expr_result_t parse_postfix_expr(spl_comp_t *ctx, spl_expr_result_t l spl_type_item_vec_t *st_items = spl_type_items(&ctx->tctx, elem_idx); vec_for(*st_items, si) { spl_type_item_t *sit = &vec_at(*st_items, si); - if (sit->item_kind != ITEM_FIELD) continue; + if (sit->item_kind != ITEM_FIELD) + continue; if (strcmp(sit->name, fname) == 0) { emit_ptr_add(&ctx->emit, sit->aggregate_field.offset); emit_load_or_addr_type(ctx, &left, sit->aggregate_field.type_idx); @@ -1024,13 +1033,15 @@ static spl_expr_result_t parse_postfix_expr(spl_comp_t *ctx, spl_expr_result_t l int sl_elem_idx = spl_type_elem_type(&ctx->tctx, left.type_idx); if (ctx->addr_of_mode) { left = (spl_expr_result_t){sl_elem_idx >= 0 - ? spl_type_ptr(&ctx->tctx, sl_elem_idx) - : spl_type_basic(&ctx->tctx, SPL_PTR), 1}; + ? spl_type_ptr(&ctx->tctx, sl_elem_idx) + : spl_type_basic(&ctx->tctx, SPL_PTR), + 1}; } else { emit_load_ptr(&ctx->emit); left = (spl_expr_result_t){sl_elem_idx >= 0 - ? spl_type_ptr(&ctx->tctx, sl_elem_idx) - : spl_type_basic(&ctx->tctx, SPL_PTR), 0}; + ? spl_type_ptr(&ctx->tctx, sl_elem_idx) + : spl_type_basic(&ctx->tctx, SPL_PTR), + 0}; } } continue; @@ -1072,9 +1083,11 @@ static spl_expr_result_t parse_postfix_expr(spl_comp_t *ctx, spl_expr_result_t l expect(ctx, TOK_R_BRACKET); if (!has_explicit_end) { - if (left.type_idx >= 0 && spl_type_kind(&ctx->tctx, left.type_idx) == TYPE_ARRAY) { + if (left.type_idx >= 0 && + spl_type_kind(&ctx->tctx, left.type_idx) == TYPE_ARRAY) { emit_push_u64(&ctx->emit, spl_type_array_len(&ctx->tctx, left.type_idx)); - } else if (left.type_idx >= 0 && spl_type_kind(&ctx->tctx, left.type_idx) == TYPE_SLICE) { + } else if (left.type_idx >= 0 && + spl_type_kind(&ctx->tctx, left.type_idx) == TYPE_SLICE) { emit_pick(&ctx->emit, 1); emit_push_u64(&ctx->emit, sizeof(spl_val_t)); emit_add_u64(&ctx->emit); @@ -1108,18 +1121,19 @@ static spl_expr_result_t parse_postfix_expr(spl_comp_t *ctx, spl_expr_result_t l emit_slice_create(ctx, stride); } } - left = (spl_expr_result_t){left.type_idx >= 0 + left = (spl_expr_result_t){ + left.type_idx >= 0 ? spl_type_slice(&ctx->tctx, spl_type_elem_type(&ctx->tctx, left.type_idx)) - : -1, 0}; + : -1, + 0}; continue; } expect(ctx, TOK_R_BRACKET); - if (left.type_idx >= 0 && - (spl_type_kind(&ctx->tctx, left.type_idx) == TYPE_ARRAY || - spl_type_kind(&ctx->tctx, left.type_idx) == TYPE_PTR || - spl_type_kind(&ctx->tctx, left.type_idx) == TYPE_SLICE)) { + if (left.type_idx >= 0 && (spl_type_kind(&ctx->tctx, left.type_idx) == TYPE_ARRAY || + spl_type_kind(&ctx->tctx, left.type_idx) == TYPE_PTR || + spl_type_kind(&ctx->tctx, left.type_idx) == TYPE_SLICE)) { int idx_elem_idx = spl_type_elem_type(&ctx->tctx, left.type_idx); if (spl_type_kind(&ctx->tctx, left.type_idx) == TYPE_SLICE) { @@ -1141,6 +1155,34 @@ static spl_expr_result_t parse_postfix_expr(spl_comp_t *ctx, spl_expr_result_t l continue; } + if (opt == KW_AS) { + usize saved = ctx->tok_idx; + int saved_err = ctx->has_error; + char saved_msg[COMP_ERROR_MAX]; + memcpy(saved_msg, ctx->error_msg, COMP_ERROR_MAX); + advance(ctx); /* as */ + skip_nl(ctx); + int target_type_idx = spl_type_parse(&ctx->tctx, ctx); + if (target_type_idx < 0) { + ctx->tok_idx = saved; + ctx->has_error = saved_err; + memcpy(ctx->error_msg, saved_msg, COMP_ERROR_MAX); + break; + } + usize src_sz = spl_type_size(&ctx->tctx, left.type_idx); + usize dst_sz = spl_type_size(&ctx->tctx, target_type_idx); + if (dst_sz > src_sz) { + int src_signed = + spl_type_is_integer(spl_type_basic_type(&ctx->tctx, left.type_idx)); + uint16_t opc = src_signed ? SPL_SEXT : SPL_ZEXT; + emit_raw(&ctx->emit, opc, 0, dst_sz * 8); + } else if (dst_sz < src_sz) { + emit_raw(&ctx->emit, SPL_TRUNC, 0, dst_sz * 8); + } + left = (spl_expr_result_t){target_type_idx, 0}; + continue; + } + break; } return left; @@ -1175,13 +1217,19 @@ static spl_expr_result_t parse_infix(spl_comp_t *ctx, spl_expr_result_t left, sp if (op == TOK_AND_AND) { spl_val_t bz_addr = emit_bz_here(&ctx->emit); spl_parse_expr(ctx, next_prec); + spl_val_t jmp_addr = emit_jmp_here(&ctx->emit); emit_patch_here(&ctx->emit, bz_addr); + emit_push_i32(&ctx->emit, 0); + emit_patch_here(&ctx->emit, jmp_addr); return (spl_expr_result_t){spl_type_basic(&ctx->tctx, SPL_I32), 0}; } if (op == TOK_OR_OR) { spl_val_t bnz_addr = emit_bnz_here(&ctx->emit); spl_parse_expr(ctx, next_prec); + spl_val_t jmp_addr = emit_jmp_here(&ctx->emit); emit_patch_here(&ctx->emit, bnz_addr); + emit_push_i32(&ctx->emit, 1); + emit_patch_here(&ctx->emit, jmp_addr); return (spl_expr_result_t){spl_type_basic(&ctx->tctx, SPL_I32), 0}; } @@ -1198,9 +1246,9 @@ static spl_expr_result_t parse_infix(spl_comp_t *ctx, spl_expr_result_t left, sp if (left.is_lvalue) { spl_type_t bt = spl_type_emit_type(&ctx->tctx, left.type_idx); if (op == TOK_ASSIGN && left.type_idx >= 0 && - !spl_type_is_scalar(&ctx->tctx, left.type_idx) && - right.is_lvalue) { - emit_copy_addr_to_addr(&ctx->emit, spl_type_slot_count(&ctx->tctx, left.type_idx), 0); + !spl_type_is_scalar(&ctx->tctx, left.type_idx) && right.is_lvalue) { + emit_copy_addr_to_addr(&ctx->emit, spl_type_slot_count(&ctx->tctx, left.type_idx), + 0); } else if (op == TOK_ASSIGN) { emit_store_type(&ctx->emit, bt); } else { @@ -1233,8 +1281,7 @@ static spl_expr_result_t parse_infix(spl_comp_t *ctx, spl_expr_result_t left, sp return (spl_expr_result_t){result_type_idx, 0}; } -int spl_emit_match_enum_cmp(spl_comp_t *ctx, int enum_type_idx, - int val_offset, int by_value) { +int spl_emit_match_enum_cmp(spl_comp_t *ctx, int enum_type_idx, int val_offset, int by_value) { char vname[256]; if (peek(ctx)->type == TOK_DOT) { @@ -1259,27 +1306,27 @@ int spl_emit_match_enum_cmp(spl_comp_t *ctx, int enum_type_idx, spl_tok_copy_name(vtok, vname, sizeof(vname)); } -lookup: - { - spl_type_item_vec_t *e_items = spl_type_items(&ctx->tctx, enum_type_idx); - vec_for(*e_items, vi) { - spl_type_item_t *vit = &vec_at(*e_items, vi); - if (vit->item_kind != ITEM_VARIANT) continue; - if (strcmp(vit->name, vname) == 0) { - emit_laddr(&ctx->emit, val_offset); - if (by_value) { - emit_load_type(&ctx->emit, SPL_I32); - } else { - emit_load_ptr(&ctx->emit); - emit_ptr_add(&ctx->emit, 0); - emit_load_type(&ctx->emit, SPL_I32); - } - emit_push_i32(&ctx->emit, vit->enum_field.value); - emit_binop(&ctx->emit, SPL_EQ, SPL_I32); - return (int)vi; +lookup: { + spl_type_item_vec_t *e_items = spl_type_items(&ctx->tctx, enum_type_idx); + vec_for(*e_items, vi) { + spl_type_item_t *vit = &vec_at(*e_items, vi); + if (vit->item_kind != ITEM_VARIANT) + continue; + if (strcmp(vit->name, vname) == 0) { + emit_laddr(&ctx->emit, val_offset); + if (by_value) { + emit_load_type(&ctx->emit, SPL_I32); + } else { + emit_load_ptr(&ctx->emit); + emit_ptr_add(&ctx->emit, 0); + emit_load_type(&ctx->emit, SPL_I32); } + emit_push_i32(&ctx->emit, vit->enum_field.value); + emit_binop(&ctx->emit, SPL_EQ, SPL_I32); + return (int)vi; } } +} spl_comp_error(ctx, "unknown variant '%s' in match", vname); return -1; } @@ -1290,49 +1337,3 @@ void spl_emit_match_value_cmp(spl_comp_t *ctx, int val_offset) { spl_parse_expr(ctx, PREC_LOGOR); emit_binop(&ctx->emit, SPL_EQ, SPL_I32); } - -void spl_emit_ret(spl_comp_t *ctx, int ret_type_idx) { - if (spl_type_needs_multi_slot(&ctx->tctx, ret_type_idx)) { - /* Stack: [src_addr] — copy from src into fp+sizeof(spl_val_t) return area */ - emit_laddr(&ctx->emit, (int)sizeof(spl_val_t)); - emit_swap(&ctx->emit); - emit_copy_addr_to_addr(&ctx->emit, - spl_type_slot_count(&ctx->tctx, ret_type_idx), 0); - /* Stack empty after copy. emit_return pushes laddr + ret. */ - } - emit_return(&ctx->emit, &ctx->tctx, ret_type_idx); -} - -void spl_emit_store_init(spl_comp_t *ctx, int var_offset, int var_type_idx) { - if (var_type_idx >= 0 && - (spl_type_kind(&ctx->tctx, var_type_idx) == TYPE_STRUCT || - spl_type_kind(&ctx->tctx, var_type_idx) == TYPE_ENUM)) { - usize sz = spl_type_size(&ctx->tctx, var_type_idx); - if (sz <= sizeof(spl_val_t)) { - emit_store_to_laddr(&ctx->emit, var_offset, spl_type_emit_type(&ctx->tctx, var_type_idx)); - } else { - usize nslots = (sz + sizeof(spl_val_t) - 1) / sizeof(spl_val_t); - emit_frame_copy(&ctx->emit, var_offset, nslots); - } - } else if (var_type_idx >= 0 && spl_type_kind(&ctx->tctx, var_type_idx) == TYPE_ARRAY) { - int elem_idx = spl_type_elem_type(&ctx->tctx, var_type_idx); - spl_type_t bt = spl_type_emit_type(&ctx->tctx, elem_idx); - usize stride = spl_type_elem_stride(&ctx->tctx, elem_idx); - int arr_len = (int)spl_type_array_len(&ctx->tctx, var_type_idx); - for (int i = arr_len - 1; i >= 0; i--) { - emit_laddr(&ctx->emit, var_offset + (int)(i * stride)); - emit_swap(&ctx->emit); - if (elem_idx >= 0 && !spl_type_is_scalar(&ctx->tctx, elem_idx)) { - emit_copy_addr_to_addr(&ctx->emit, spl_type_slot_count(&ctx->tctx, elem_idx), 0); - } else { - emit_store_type(&ctx->emit, bt); - } - } - } else if (var_type_idx >= 0 && spl_type_kind(&ctx->tctx, var_type_idx) == TYPE_SLICE) { - emit_store_to_laddr(&ctx->emit, var_offset + (int)sizeof(spl_val_t), SPL_USIZE); - emit_store_to_laddr(&ctx->emit, var_offset, SPL_PTR); - } else { - spl_type_t bt = spl_type_emit_type(&ctx->tctx, var_type_idx); - emit_store_to_laddr(&ctx->emit, var_offset, bt); - } -} diff --git a/stage1/spl_lex_util.c b/stage1/spl_lex_util.c index b6d639a..6138174 100644 --- a/stage1/spl_lex_util.c +++ b/stage1/spl_lex_util.c @@ -4,6 +4,15 @@ #include #include +spl_tok_t *peek(spl_comp_t *ctx) { return &vec_at(ctx->toks, ctx->tok_idx); } + +spl_tok_t *advance(spl_comp_t *ctx) { + spl_tok_t *t = &vec_at(ctx->toks, ctx->tok_idx); + if (t->type != TOK_EOF) + ctx->tok_idx++; + return t; +} + int expect(spl_comp_t *ctx, spl_tok_type_t type) { if (peek(ctx)->type == type) { advance(ctx); diff --git a/stage1/spl_lex_util.h b/stage1/spl_lex_util.h index 8ba44a3..0bcb1ca 100644 --- a/stage1/spl_lex_util.h +++ b/stage1/spl_lex_util.h @@ -4,11 +4,22 @@ #include "spl_comp.h" +/* Token stream access */ +spl_tok_t *peek(spl_comp_t *ctx); +spl_tok_t *advance(spl_comp_t *ctx); + /* Token matching helpers */ int expect(spl_comp_t *ctx, spl_tok_type_t type); int match(spl_comp_t *ctx, spl_tok_type_t type); void skip_nl(spl_comp_t *ctx); +/* Token introspection */ +const char *spl_tok_type_name(spl_tok_type_t type); +void spl_tok_dump(spl_tok_t *tok); +void spl_tok_vec_dump(spl_tok_vec_t *toks); +void spl_tok_vec_drop(spl_tok_vec_t *toks); +usize spl_tok_copy_name(spl_tok_t *tok, char *buf, usize buf_size); + /* Parse an integer literal value, handling optional '-' prefix for negatives. * Returns 1 on success (value in *val), 0 if current token isn't an integer. * On success, advances past all consumed tokens. On failure, does not advance. */ diff --git a/stage1/spl_lexer.h b/stage1/spl_lexer.h index 4631b5c..fb28580 100644 --- a/stage1/spl_lexer.h +++ b/stage1/spl_lexer.h @@ -17,6 +17,7 @@ X(defer , KW_DEFER , SPL_V0) \ X(else , KW_ELSE , SPL_V0) \ X(enum , KW_ENUM , SPL_V0) \ + X(extern , KW_EXTERN , SPL_V0) \ X(false , KW_FALSE , SPL_V0) \ X(fn , KW_FN , SPL_V0) \ X(for , KW_FOR , SPL_V0) \ @@ -129,13 +130,6 @@ typedef VEC(spl_tok_t) spl_tok_vec_t; /* Lexer entry point */ spl_tok_vec_t spl_lex(const char *source, const char *fname); -/* Utility functions */ -const char *spl_tok_type_name(spl_tok_type_t type); -void spl_tok_dump(spl_tok_t *tok); -void spl_tok_vec_dump(spl_tok_vec_t *toks); -void spl_tok_vec_drop(spl_tok_vec_t *toks); -usize spl_tok_copy_name(spl_tok_t *tok, char *buf, usize buf_size); - /* Decode escape sequence, advance *s past it. Returns 0 on success. */ int spl_decode_escape(const char **s, char *out); diff --git a/stage1/spl_parser.c b/stage1/spl_parser.c index d61d8fd..27805b8 100644 --- a/stage1/spl_parser.c +++ b/stage1/spl_parser.c @@ -4,15 +4,6 @@ #include "spl_lex_util.h" #include -spl_tok_t *peek(spl_comp_t *ctx) { return &vec_at(ctx->toks, ctx->tok_idx); } - -spl_tok_t *advance(spl_comp_t *ctx) { - spl_tok_t *t = &vec_at(ctx->toks, ctx->tok_idx); - if (t->type != TOK_EOF) - ctx->tok_idx++; - return t; -} - /* ============================================================ * Parse function definition * ============================================================ */ @@ -52,8 +43,8 @@ static int parse_params_decl(spl_comp_t *ctx, char pnames[][256], int ptypes[]) return nparams; } -static int parse_fn_body(spl_comp_t *ctx, const char *fn_name, int ret_type_idx, - int nparams, char pnames[][256], int ptypes[], int is_pub) { +static int parse_fn_body(spl_comp_t *ctx, const char *fn_name, int ret_type_idx, int nparams, + char pnames[][256], int ptypes[], int is_pub) { int fi = spl_declare_func(ctx, fn_name, ret_type_idx, nparams, 0, is_pub); ctx->current_func_idx = fi; ctx->current_ret_type_idx = ret_type_idx; @@ -84,8 +75,7 @@ static int parse_fn_body(spl_comp_t *ctx, const char *fn_name, int ret_type_idx, total_phys_slots += (int)((psz + sizeof(spl_val_t) - 1) / sizeof(spl_val_t)); } if (spl_type_needs_multi_slot(&ctx->tctx, ret_type_idx)) { - usize min_bytes = - spl_type_slot_count(&ctx->tctx, ret_type_idx) * sizeof(spl_val_t); + usize min_bytes = spl_type_slot_count(&ctx->tctx, ret_type_idx) * sizeof(spl_val_t); if ((usize)ctx->emit.frame.peak_bytes < min_bytes) ctx->emit.frame.peak_bytes = (int)min_bytes; } @@ -137,9 +127,13 @@ static void parse_fn_decl(spl_comp_t *ctx, int is_extern, int is_pub) { skip_nl(ctx); } + int fi; + if (is_extern) { - spl_declare_func(ctx, fn_name, ret_type_idx, nparams, 1, is_pub); + fi = spl_declare_func(ctx, fn_name, ret_type_idx, nparams, 1, is_pub); spl_ensure_native(ctx, fn_name); + if (ctx->tctx.current_type_idx == 0) + spl_type_add_method(&ctx->tctx, 0, fn_name, fi); if (peek(ctx)->type == TOK_SEMICOLON) advance(ctx); return; @@ -152,7 +146,9 @@ static void parse_fn_decl(spl_comp_t *ctx, int is_extern, int is_pub) { skip_nl(ctx); - parse_fn_body(ctx, fn_name, ret_type_idx, nparams, pnames, ptypes, is_pub); + fi = parse_fn_body(ctx, fn_name, ret_type_idx, nparams, pnames, ptypes, is_pub); + if (ctx->tctx.current_type_idx == 0) + spl_type_add_method(&ctx->tctx, 0, fn_name, fi); } /* ============================================================ @@ -449,19 +445,40 @@ void spl_parse_prog(spl_comp_t *ctx) { parse_type_decl(ctx); break; } - case TOK_SHARP: - advance(ctx); /* # */ - if (peek(ctx)->type == TOK_L_BRACKET) { - advance(ctx); /* [ */ - while (peek(ctx)->type != TOK_R_BRACKET && peek(ctx)->type != TOK_EOF) - advance(ctx); - if (peek(ctx)->type == TOK_R_BRACKET) - advance(ctx); + case TOK_AT: + case TOK_SHARP: { + int tt = peek(ctx)->type; + advance(ctx); /* @ or # */ + skip_nl(ctx); + if (tt == TOK_AT) { + /* @extern(vm) fn ... */ + if (peek(ctx)->type == KW_EXTERN) { + advance(ctx); /* extern */ + skip_nl(ctx); + if (peek(ctx)->type == TOK_L_PAREN) { + advance(ctx); /* ( */ + skip_nl(ctx); + advance(ctx); /* target name (e.g. "vm") */ + skip_nl(ctx); + if (peek(ctx)->type == TOK_R_PAREN) + advance(ctx); + } + } + } else { + /* #[extern("vm")] fn ... (legacy) */ + if (peek(ctx)->type == TOK_L_BRACKET) { + advance(ctx); /* [ */ + while (peek(ctx)->type != TOK_R_BRACKET && peek(ctx)->type != TOK_EOF) + advance(ctx); + if (peek(ctx)->type == TOK_R_BRACKET) + advance(ctx); + } } skip_nl(ctx); if (peek(ctx)->type == KW_FN) parse_fn_decl(ctx, 1, 0); break; + } default: { int prev = ctx->tok_idx; spl_parse_stmt(ctx); diff --git a/stage1/spl_stmt.c b/stage1/spl_stmt.c index eed691e..629afb4 100644 --- a/stage1/spl_stmt.c +++ b/stage1/spl_stmt.c @@ -163,10 +163,11 @@ spl_expr_result_t spl_parse_block_expr(spl_comp_t *ctx) { } spl_tok_type_t t = peek(ctx)->type; - int is_keyword = (t == KW_RET || t == KW_VAR || t == KW_CONST || t == KW_IF || - t == KW_WHILE || t == KW_LOOP || t == KW_FOR || t == KW_BREAK || - t == KW_CONTINUE || t == KW_DEFER || t == KW_MATCH || t == KW_TYPE || - t == TOK_L_BRACE || t == TOK_SHARP || t == TOK_LINE_COMMENT); + int is_keyword = + (t == KW_RET || t == KW_VAR || t == KW_CONST || t == KW_IF || t == KW_WHILE || + t == KW_LOOP || t == KW_FOR || t == KW_BREAK || t == KW_CONTINUE || t == KW_DEFER || + t == KW_MATCH || t == KW_TYPE || t == TOK_L_BRACE || t == TOK_AT || t == TOK_SHARP || + t == TOK_LINE_COMMENT); if (is_keyword) { /* Keyword statement — produces void */ @@ -433,7 +434,7 @@ static void parse_for_stmt(spl_comp_t *ctx) { /* Condition: idx < len */ emit_pick(&ctx->emit, 1); /* copy len */ emit_pick(&ctx->emit, 1); /* copy idx */ - emit_swap(&ctx->emit); /* [idx, len] → [len, idx] → SWAP → [idx, len] */ + emit_swap(&ctx->emit); /* [idx, len] → [len, idx] → SWAP → [idx, len] */ emit_ult_usize(&ctx->emit); spl_val_t bz_addr = emit_bz_here(&ctx->emit); @@ -454,7 +455,8 @@ static void parse_for_stmt(spl_comp_t *ctx) { spl_type_size(&ctx->tctx, elem_type_idx) > sizeof(spl_val_t)) { emit_frame_copy(&ctx->emit, val_offset, spl_type_slot_count(&ctx->tctx, elem_type_idx)); } else { - spl_type_t elem_bt = elem_type_idx >= 0 ? spl_type_emit_type(&ctx->tctx, elem_type_idx) : SPL_I32; + spl_type_t elem_bt = + elem_type_idx >= 0 ? spl_type_emit_type(&ctx->tctx, elem_type_idx) : SPL_I32; emit_load_type(&ctx->emit, elem_bt); emit_store_to_laddr(&ctx->emit, val_offset, elem_bt); } @@ -545,8 +547,8 @@ static void parse_defer_stmt(spl_comp_t *ctx) { /* Parse an enum variant pattern in a match arm: .VariantName * Delegates comparison to expr layer (spl_emit_match_enum_cmp). * Returns the variant item index, or -1 on error. */ -static int parse_match_enum_variant(spl_comp_t *ctx, int enum_type_idx, - int val_offset, int by_value) { +static int parse_match_enum_variant(spl_comp_t *ctx, int enum_type_idx, int val_offset, + int by_value) { return spl_emit_match_enum_cmp(ctx, enum_type_idx, val_offset, by_value); } @@ -561,9 +563,8 @@ static void parse_match_value_pattern(spl_comp_t *ctx, int val_offset) { * Declares local variables and loads corresponding field data * from the matched value's data area (offset 4+). * Sets *scope_pushed = 1 if bindings declared. */ -static void parse_match_enum_bindings(spl_comp_t *ctx, int enum_type_idx, - int variant_item_idx, int val_offset, - int *scope_pushed) { +static void parse_match_enum_bindings(spl_comp_t *ctx, int enum_type_idx, int variant_item_idx, + int val_offset, int *scope_pushed) { advance(ctx); /* ( */ skip_nl(ctx); if (peek(ctx)->type == TOK_R_PAREN) { @@ -603,7 +604,8 @@ static void parse_match_enum_bindings(spl_comp_t *ctx, int enum_type_idx, } } int boffset = spl_declare_var(ctx, bname, btype_idx, 0); - emit_load_to_var(&ctx->emit, &ctx->tctx, val_offset, field_byte_off, btype_idx, boffset); + emit_load_to_var(&ctx->emit, &ctx->tctx, val_offset, field_byte_off, btype_idx, + boffset); bi++; skip_nl(ctx); @@ -721,7 +723,8 @@ static void parse_match_stmt(spl_comp_t *ctx) { skip_nl(ctx); if (peek(ctx)->type != TOK_ASSIGN) { if (n_bnz < 128) - bnz_addrs[n_bnz++] = emit_bnz_here(&ctx->emit); /* fallthrough to body */ + bnz_addrs[n_bnz++] = + emit_bnz_here(&ctx->emit); /* fallthrough to body */ continue; } break; @@ -738,8 +741,8 @@ static void parse_match_stmt(spl_comp_t *ctx) { /* --- Parse enum bindings (only for last variant) --- */ if (is_enum_match && has_parens && arm_variant_item >= 0) { - parse_match_enum_bindings(ctx, enum_type_idx, arm_variant_item, - val_offset, &scope_pushed); + parse_match_enum_bindings(ctx, enum_type_idx, arm_variant_item, val_offset, + &scope_pushed); } skip_nl(ctx); @@ -793,13 +796,31 @@ static void parse_match_stmt(spl_comp_t *ctx) { * ============================================================ */ static void parse_extern_decl(spl_comp_t *ctx) { - advance(ctx); /* # */ - expect(ctx, TOK_L_BRACKET); - /* Skip extern("vm") or just look for fn */ - while (peek(ctx)->type != TOK_R_BRACKET && peek(ctx)->type != TOK_EOF) - advance(ctx); - if (peek(ctx)->type == TOK_R_BRACKET) - advance(ctx); + int tt = peek(ctx)->type; + advance(ctx); /* @ or # */ + skip_nl(ctx); + if (tt == TOK_AT) { + /* @extern(vm) fn ... */ + if (peek(ctx)->type == KW_EXTERN) { + advance(ctx); /* extern */ + skip_nl(ctx); + if (peek(ctx)->type == TOK_L_PAREN) { + advance(ctx); /* ( */ + skip_nl(ctx); + advance(ctx); /* target name */ + skip_nl(ctx); + if (peek(ctx)->type == TOK_R_PAREN) + advance(ctx); + } + } + } else { + /* #[extern("vm")] fn ... (legacy) */ + expect(ctx, TOK_L_BRACKET); + while (peek(ctx)->type != TOK_R_BRACKET && peek(ctx)->type != TOK_EOF) + advance(ctx); + if (peek(ctx)->type == TOK_R_BRACKET) + advance(ctx); + } skip_nl(ctx); @@ -970,7 +991,8 @@ void spl_parse_stmt(spl_comp_t *ctx) { case TOK_LINE_COMMENT: advance(ctx); break; - case TOK_SHARP: /* #[extern(...)] */ + case TOK_AT: /* @extern(...) */ + case TOK_SHARP: /* #[extern(...)] (legacy) */ parse_extern_decl(ctx); break; default: diff --git a/stage1/splc0.c b/stage1/splc0.c index 1ce26ff..220dd61 100644 --- a/stage1/splc0.c +++ b/stage1/splc0.c @@ -7,6 +7,7 @@ #include "../stage0/spl_ir.h" #include "spl_comp.h" +#include "spl_lex_util.h" #include #include #include diff --git a/stage1/test06_for.spl b/stage1/test06_for.spl index e2b661d..20d575d 100644 --- a/stage1/test06_for.spl +++ b/stage1/test06_for.spl @@ -3,7 +3,7 @@ * 难度:2/5 * 验证点:for begin..end as i、for slice as val、for slice,0.. as val,idx */ -#[extern("vm")] fn vm_printf(fmt: *u8, ...) void; +@extern(vm) fn vm_printf(fmt: *u8, ...) void; fn main() i32 { /* for 数值区间:for 0..N as i */ diff --git a/stage1/test11_enum.spl b/stage1/test11_enum.spl index 987ddb9..d345596 100644 --- a/stage1/test11_enum.spl +++ b/stage1/test11_enum.spl @@ -3,7 +3,7 @@ * 难度:3/5 * 验证点:enum 定义、简单枚举值、带数据枚举变体 */ -#[extern("vm")] fn vm_printf(fmt: *u8, ...) void; +@extern(vm) fn vm_printf(fmt: *u8, ...) void; type Color = enum { Red, diff --git a/stage1/test13_extern.spl b/stage1/test13_extern.spl index a388075..076dbdd 100644 --- a/stage1/test13_extern.spl +++ b/stage1/test13_extern.spl @@ -1,12 +1,12 @@ /* ===== 模块6:函数 ===== * test13_extern — 外部 VM 函数与字符串 * 难度:2/5 - * 验证点:#[extern("vm")] 声明、vm_printf 调用、 + * 验证点:@extern(vm) 声明、vm_printf 调用、 * 字符串字面量、字符串参数传递 */ -#[extern("vm")] fn vm_printf(fmt: *u8, ...) void; -#[extern("vm")] fn vm_strlen(s: *i8) i32; -#[extern("vm")] fn vm_strcmp(a: *i8, b: *i8) i32; +@extern(vm) fn vm_printf(fmt: *u8, ...) void; +@extern(vm) fn vm_strlen(s: *i8) i32; +@extern(vm) fn vm_strcmp(a: *i8, b: *i8) i32; fn main() i32 { /* vm_printf 输出测试 */ diff --git a/stage1/test15_defer.spl b/stage1/test15_defer.spl index c0c34e9..f60853e 100644 --- a/stage1/test15_defer.spl +++ b/stage1/test15_defer.spl @@ -4,7 +4,7 @@ * 验证点:defer 语句、defer 块、多个 defer(逆序执行)、 * 函数中 defer、块作用域 defer */ -#[extern("vm")] fn vm_printf(fmt: *u8, ...) void; +@extern(vm) fn vm_printf(fmt: *u8, ...) void; fn with_cleanup() void { defer vm_printf(" inner defer\n"); diff --git a/stage1/test16_methods.spl b/stage1/test16_methods.spl index e168163..5bf8c3f 100644 --- a/stage1/test16_methods.spl +++ b/stage1/test16_methods.spl @@ -3,7 +3,7 @@ * 难度:3/5 * 验证点:struct 方法、enum 方法、self 参数自动填充、方法调用 */ -#[extern("vm")] fn vm_printf(fmt: *u8, ...) void; +@extern(vm) fn vm_printf(fmt: *u8, ...) void; type Point = struct { x: i32, diff --git a/stage1/test17_integration.spl b/stage1/test17_integration.spl index e99dd7c..d8995a7 100644 --- a/stage1/test17_integration.spl +++ b/stage1/test17_integration.spl @@ -3,7 +3,7 @@ * 难度:3/5 * 验证点:多特性组合——指针 + 结构体 + 函数 + 循环 + 数组 + 切片 */ -#[extern("vm")] fn vm_printf(fmt: *u8, ...) void; +@extern(vm) fn vm_printf(fmt: *u8, ...) void; type Point = struct { x: i32,