stage1 - 全面重构 stage1 编译器架构:类型系统(arena + items)、IR 发射层(spl_emit.h/c)、统一所有 emit 调用点。
- 实现 as 类型转换运算符、修复 &&/|| 短路求值 bug。 - 在 splc1.spl 中实现 Vec/Map/Emit 基础库(~50 个方法)。 - 修复实例方法调用中 self 参数被错误丢弃的 bug。
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
/* spl_comp.c — SPL compiler main logic and codegen helpers */
|
/* spl_comp.c — SPL compiler main logic and codegen helpers */
|
||||||
|
|
||||||
#include "spl_comp.h"
|
#include "spl_comp.h"
|
||||||
|
#include "spl_lex_util.h"
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -61,10 +62,8 @@ void spl_comp_reset(spl_comp_t *ctx) {
|
|||||||
ctx->addr_of_mode = 0;
|
ctx->addr_of_mode = 0;
|
||||||
free(ctx->break_patches);
|
free(ctx->break_patches);
|
||||||
ctx->break_patches = NULL;
|
ctx->break_patches = NULL;
|
||||||
vec_free(ctx->emit.call_fixups);
|
vec_free(ctx->emit.fixups);
|
||||||
vec_init(ctx->emit.call_fixups);
|
vec_init(ctx->emit.fixups);
|
||||||
vec_free(ctx->emit.call_fixup_funcs);
|
|
||||||
vec_init(ctx->emit.call_fixup_funcs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void spl_comp_error(spl_comp_t *ctx, const char *fmt, ...) {
|
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) {
|
if (items) {
|
||||||
vec_for(*items, j) {
|
vec_for(*items, j) {
|
||||||
spl_type_item_t *it = &vec_at(*items, j);
|
spl_type_item_t *it = &vec_at(*items, j);
|
||||||
if (it->item_kind == ITEM_METHOD && it->name &&
|
if (it->item_kind == ITEM_METHOD && it->name && strcmp(it->name, name) == 0)
|
||||||
strcmp(it->name, name) == 0)
|
|
||||||
return it->method.func_idx;
|
return it->method.func_idx;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,8 +10,8 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "spl_type.h"
|
|
||||||
#include "spl_emit.h"
|
#include "spl_emit.h"
|
||||||
|
#include "spl_type.h"
|
||||||
|
|
||||||
/* Forward declarations */
|
/* Forward declarations */
|
||||||
typedef struct spl_comp spl_comp_t;
|
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);
|
spl_expr_result_t spl_parse_struct_literal(spl_comp_t *ctx, int type_idx);
|
||||||
|
|
||||||
/* Match arm pattern comparison */
|
/* Match arm pattern comparison */
|
||||||
int spl_emit_match_enum_cmp(spl_comp_t *ctx, int enum_type_idx, int val_offset,
|
int spl_emit_match_enum_cmp(spl_comp_t *ctx, int enum_type_idx, int val_offset, int by_value);
|
||||||
int by_value);
|
|
||||||
void spl_emit_match_value_cmp(spl_comp_t *ctx, int val_offset);
|
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
|
* 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 */
|
/* Variable management */
|
||||||
int spl_declare_var(spl_comp_t *ctx, const char *name, int type_idx, int is_const);
|
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);
|
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) */
|
/* Register runtime natives (stub) */
|
||||||
void spl_comp_register(spl_prog_t *prog);
|
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__ */
|
#endif /* __SPL_COMP_H__ */
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
/* spl_emit.c — IR emission: frame allocator + Layer 1/2 ops */
|
/* spl_emit.c — IR emission: frame allocator + Layer 1/2 ops */
|
||||||
|
|
||||||
#include "spl_emit.h"
|
#include "spl_emit.h"
|
||||||
|
#include "spl_comp.h"
|
||||||
#include "spl_type.h"
|
#include "spl_type.h"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
@@ -11,15 +12,13 @@
|
|||||||
void spl_emit_init(spl_emit_t *e, spl_prog_t *prog) {
|
void spl_emit_init(spl_emit_t *e, spl_prog_t *prog) {
|
||||||
memset(e, 0, sizeof(*e));
|
memset(e, 0, sizeof(*e));
|
||||||
e->prog = prog;
|
e->prog = prog;
|
||||||
vec_init(e->call_fixups);
|
vec_init(e->fixups);
|
||||||
vec_init(e->call_fixup_funcs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void spl_emit_drop(spl_emit_t *e) {
|
void spl_emit_drop(spl_emit_t *e) {
|
||||||
if (!e)
|
if (!e)
|
||||||
return;
|
return;
|
||||||
vec_free(e->call_fixups);
|
vec_free(e->fixups);
|
||||||
vec_free(e->call_fixup_funcs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ============================================================
|
/* ============================================================
|
||||||
@@ -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));
|
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 emit_raw(spl_emit_t *e, uint16_t opcode, uint16_t type, spl_val_t imm) {
|
||||||
spl_val_t imm) {
|
|
||||||
return spl_prog_emit(e->prog, opcode, type, 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_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_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) {
|
void emit_push_usize(spl_emit_t *e, usize v) { emit_raw(e, SPL_PUSH, SPL_USIZE, (spl_val_t)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_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_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) {
|
void emit_push_type(spl_emit_t *e, uint16_t bt, spl_val_t v) { emit_raw(e, SPL_PUSH, bt, 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_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); }
|
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_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_call(spl_emit_t *e, int nargs) { emit_raw(e, SPL_CALL, SPL_VOID, nargs); }
|
||||||
void emit_ncall(spl_emit_t *e, int nargs) {
|
void emit_ncall(spl_emit_t *e, int nargs) { emit_raw(e, SPL_NCALL, SPL_VOID, 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_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); }
|
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);
|
emit_drop(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
void emit_load_to_var(spl_emit_t *e, spl_type_ctx_t *tctx, int ptr_slot_offset,
|
void emit_load_to_var(spl_emit_t *e, spl_type_ctx_t *tctx, int ptr_slot_offset, usize byte_offset,
|
||||||
usize byte_offset, int data_type_idx, int var_offset) {
|
int data_type_idx, int var_offset) {
|
||||||
emit_laddr(e, ptr_slot_offset);
|
emit_laddr(e, ptr_slot_offset);
|
||||||
emit_load_ptr(e);
|
emit_load_ptr(e);
|
||||||
emit_ptr_add(e, byte_offset);
|
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 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);
|
spl_val_t fixup_addr = emit_raw(e, SPL_PUSH, SPL_PTR, 0);
|
||||||
emit_call(e, nargs);
|
emit_call(e, nargs);
|
||||||
vec_push(e->call_fixups, fixup_addr);
|
spl_fixup_entry_t fe = {fixup_addr, func_idx};
|
||||||
vec_push(e->call_fixup_funcs, func_idx);
|
vec_push(e->fixups, fe);
|
||||||
return fixup_addr;
|
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) {
|
void emit_patch_call_fixups(spl_emit_t *e, spl_prog_t *prog) {
|
||||||
for (usize i = 0; i < vec_size(e->call_fixups); i++) {
|
for (usize i = 0; i < vec_size(e->fixups); i++) {
|
||||||
spl_val_t insn_idx = vec_at(e->call_fixups, i);
|
spl_fixup_entry_t *fe = &vec_at(e->fixups, i);
|
||||||
int pfi = vec_at(e->call_fixup_funcs, i);
|
if (fe->func_idx >= 0 && fe->func_idx < (int)vec_size(prog->funcs)) {
|
||||||
if (pfi >= 0 && pfi < (int)vec_size(prog->funcs)) {
|
spl_val_t addr = vec_at(prog->funcs, fe->func_idx).address;
|
||||||
spl_val_t addr = vec_at(prog->funcs, pfi).address;
|
vec_at(prog->insns, fe->insn_idx).imm = addr;
|
||||||
vec_at(prog->insns, 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -48,11 +48,15 @@ static inline void fa_free(spl_frame_alloc_t *fa, int mark) { fa->current_bytes
|
|||||||
* Emit context
|
* Emit context
|
||||||
* ============================================================ */
|
* ============================================================ */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
spl_val_t insn_idx;
|
||||||
|
int func_idx;
|
||||||
|
} spl_fixup_entry_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
spl_prog_t *prog;
|
spl_prog_t *prog;
|
||||||
spl_frame_alloc_t frame;
|
spl_frame_alloc_t frame;
|
||||||
VEC(spl_val_t) call_fixups;
|
VEC(spl_fixup_entry_t) fixups;
|
||||||
VEC(int) call_fixup_funcs;
|
|
||||||
} spl_emit_t;
|
} spl_emit_t;
|
||||||
|
|
||||||
void spl_emit_init(spl_emit_t *e, spl_prog_t *prog);
|
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_void(spl_emit_t *e);
|
||||||
void emit_dbg_usize(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
|
* Layer 2 — semantic-level helpers
|
||||||
* ============================================================ */
|
* ============================================================ */
|
||||||
|
|
||||||
void emit_frame_copy(spl_emit_t *e, int dest_offset, usize nslots);
|
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_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,
|
void emit_load_to_var(spl_emit_t *e, spl_type_ctx_t *tctx, int ptr_slot_offset, usize byte_offset,
|
||||||
usize byte_offset, int data_type_idx, int var_offset);
|
int data_type_idx, int var_offset);
|
||||||
void emit_store_to_laddr(spl_emit_t *e, int offset, uint16_t type);
|
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);
|
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 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 */
|
/* Patch all fixups */
|
||||||
void emit_patch_call_fixups(spl_emit_t *e, spl_prog_t *prog);
|
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__ */
|
#endif /* __SPL_EMIT_H__ */
|
||||||
|
|||||||
@@ -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 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,
|
static void emit_load_or_addr_type(spl_comp_t *ctx, spl_expr_result_t *result, int type_idx);
|
||||||
int type_idx);
|
|
||||||
static spl_expr_result_t parse_postfix_expr(spl_comp_t *ctx, spl_expr_result_t left);
|
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) {
|
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);
|
spl_type_item_vec_t *items = spl_type_items(&ctx->tctx, type_idx);
|
||||||
vec_for(*items, i) {
|
vec_for(*items, i) {
|
||||||
spl_type_item_t *it = &vec_at(*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) {
|
if (strcmp(it->name, field) == 0) {
|
||||||
emit_push_i32(&ctx->emit, it->enum_field.value);
|
emit_push_i32(&ctx->emit, it->enum_field.value);
|
||||||
*result = (spl_expr_result_t){type_idx, 0};
|
*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) {
|
vec_for(*items, fi) {
|
||||||
spl_type_item_t *it = &vec_at(*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) {
|
if (strcmp(it->name, fname) == 0) {
|
||||||
emit_laddr(&ctx->emit, base_offset);
|
emit_laddr(&ctx->emit, base_offset);
|
||||||
usize byte_off = extra_offset + it->aggregate_field.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);
|
emit_ptr_add(&ctx->emit, i * stride);
|
||||||
spl_parse_expr(ctx, PREC_MIN);
|
spl_parse_expr(ctx, PREC_MIN);
|
||||||
if (elem_type_idx >= 0 && !spl_type_is_scalar(&ctx->tctx, elem_type_idx)) {
|
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 {
|
} else {
|
||||||
emit_store_type(&ctx->emit, st);
|
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);
|
fv = spl_parse_expr(ctx, PREC_MIN);
|
||||||
}
|
}
|
||||||
(void)fv;
|
(void)fv;
|
||||||
usize nslots = (spl_type_size(&ctx->tctx, ft_idx) + sizeof(spl_val_t) - 1) / sizeof(spl_val_t);
|
usize nslots =
|
||||||
emit_frame_copy(&ctx->emit, base_offset + (int)extra_offset + (int)it->aggregate_field.offset, 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);
|
emit_drop(&ctx->emit);
|
||||||
} else {
|
} else {
|
||||||
spl_expr_result_t fv = spl_parse_expr(ctx, PREC_MIN);
|
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);
|
spl_type_item_vec_t *items = spl_type_items(&ctx->tctx, type_idx);
|
||||||
vec_for(*items, vi) {
|
vec_for(*items, vi) {
|
||||||
spl_type_item_t *v = &vec_at(*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) {
|
if (strcmp(v->name, vname) == 0) {
|
||||||
found = 1;
|
found = 1;
|
||||||
emit_laddr(&ctx->emit, base_offset);
|
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,
|
static int parse_call_args_checked(spl_comp_t *ctx, const char *fname, int *param_type_indices,
|
||||||
int *param_type_indices, int nparams) {
|
int nparams) {
|
||||||
int nargs = 0;
|
int nargs = 0;
|
||||||
int nlogical = 0;
|
int nlogical = 0;
|
||||||
if (peek(ctx)->type != TOK_R_PAREN) {
|
if (peek(ctx)->type != TOK_R_PAREN) {
|
||||||
for (;;) {
|
for (;;) {
|
||||||
spl_expr_result_t arg = spl_parse_expr(ctx, PREC_MIN);
|
spl_expr_result_t arg = spl_parse_expr(ctx, PREC_MIN);
|
||||||
if (param_type_indices && nlogical < nparams && param_type_indices[nlogical] >= 0)
|
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;
|
int arg_slots = 1;
|
||||||
if (param_type_indices && nlogical < nparams && param_type_indices[nlogical] >= 0 &&
|
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_kind(&ctx->tctx, param_type_indices[nlogical]) != TYPE_PTR &&
|
||||||
spl_type_needs_multi_slot(&ctx->tctx, param_type_indices[nlogical])) {
|
spl_type_needs_multi_slot(&ctx->tctx, param_type_indices[nlogical])) {
|
||||||
usize nslots = (spl_type_size(&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++) {
|
for (usize i = 0; i < nslots; i++) {
|
||||||
emit_dup(&ctx->emit);
|
emit_dup(&ctx->emit);
|
||||||
emit_ptr_add(&ctx->emit, i * sizeof(spl_val_t));
|
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;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void emit_load_or_addr_type(spl_comp_t *ctx, spl_expr_result_t *result,
|
static void emit_load_or_addr_type(spl_comp_t *ctx, spl_expr_result_t *result, int type_idx) {
|
||||||
int type_idx) {
|
|
||||||
if (spl_type_is_scalar(&ctx->tctx, type_idx)) {
|
if (spl_type_is_scalar(&ctx->tctx, type_idx)) {
|
||||||
if (!ctx->addr_of_mode) {
|
if (!ctx->addr_of_mode) {
|
||||||
emit_load_type(&ctx->emit, spl_type_emit_type(&ctx->tctx, type_idx));
|
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;
|
break;
|
||||||
case TOK_MUL:
|
case TOK_MUL:
|
||||||
if (right.type_idx >= 0 &&
|
if (right.type_idx >= 0 && spl_type_kind(&ctx->tctx, right.type_idx) == TYPE_PTR &&
|
||||||
spl_type_kind(&ctx->tctx, right.type_idx) == TYPE_PTR &&
|
|
||||||
spl_type_elem_type(&ctx->tctx, right.type_idx) >= 0) {
|
spl_type_elem_type(&ctx->tctx, right.type_idx) >= 0) {
|
||||||
if (right.is_lvalue) {
|
if (right.is_lvalue) {
|
||||||
emit_load_ptr(&ctx->emit);
|
emit_load_ptr(&ctx->emit);
|
||||||
@@ -907,8 +913,7 @@ static spl_expr_result_t parse_postfix_expr(spl_comp_t *ctx, spl_expr_result_t l
|
|||||||
int is_ptr_self = 0;
|
int is_ptr_self = 0;
|
||||||
if (spl_type_kind(&ctx->tctx, methods_type_idx) == TYPE_PTR) {
|
if (spl_type_kind(&ctx->tctx, methods_type_idx) == TYPE_PTR) {
|
||||||
int elem_idx = spl_type_elem_type(&ctx->tctx, methods_type_idx);
|
int elem_idx = spl_type_elem_type(&ctx->tctx, methods_type_idx);
|
||||||
if (elem_idx >= 0 &&
|
if (elem_idx >= 0 && (spl_type_kind(&ctx->tctx, elem_idx) == TYPE_STRUCT ||
|
||||||
(spl_type_kind(&ctx->tctx, elem_idx) == TYPE_STRUCT ||
|
|
||||||
spl_type_kind(&ctx->tctx, elem_idx) == TYPE_ENUM)) {
|
spl_type_kind(&ctx->tctx, elem_idx) == TYPE_ENUM)) {
|
||||||
is_ptr_self = 1;
|
is_ptr_self = 1;
|
||||||
methods_type_idx = elem_idx;
|
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);
|
spl_type_item_vec_t *m_items = spl_type_items(&ctx->tctx, methods_type_idx);
|
||||||
vec_for(*m_items, mi) {
|
vec_for(*m_items, mi) {
|
||||||
spl_type_item_t *mit = &vec_at(*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) {
|
if (strcmp(mit->name, fname) == 0) {
|
||||||
spl_func_info_t *func = &vec_at(ctx->funcs, mit->method.func_idx);
|
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;
|
int is_instance = 0;
|
||||||
if (func->nparams > 0 && func->param_type_indices[0] >= 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_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;
|
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);
|
spl_type_item_vec_t *f_items = spl_type_items(&ctx->tctx, left.type_idx);
|
||||||
vec_for(*f_items, fi) {
|
vec_for(*f_items, fi) {
|
||||||
spl_type_item_t *fit = &vec_at(*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) {
|
if (strcmp(fit->name, fname) == 0) {
|
||||||
emit_ptr_add(&ctx->emit, fit->aggregate_field.offset);
|
emit_ptr_add(&ctx->emit, fit->aggregate_field.offset);
|
||||||
emit_load_or_addr_type(ctx, &left, fit->aggregate_field.type_idx);
|
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);
|
spl_type_item_vec_t *st_items = spl_type_items(&ctx->tctx, elem_idx);
|
||||||
vec_for(*st_items, si) {
|
vec_for(*st_items, si) {
|
||||||
spl_type_item_t *sit = &vec_at(*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) {
|
if (strcmp(sit->name, fname) == 0) {
|
||||||
emit_ptr_add(&ctx->emit, sit->aggregate_field.offset);
|
emit_ptr_add(&ctx->emit, sit->aggregate_field.offset);
|
||||||
emit_load_or_addr_type(ctx, &left, sit->aggregate_field.type_idx);
|
emit_load_or_addr_type(ctx, &left, sit->aggregate_field.type_idx);
|
||||||
@@ -1025,12 +1034,14 @@ static spl_expr_result_t parse_postfix_expr(spl_comp_t *ctx, spl_expr_result_t l
|
|||||||
if (ctx->addr_of_mode) {
|
if (ctx->addr_of_mode) {
|
||||||
left = (spl_expr_result_t){sl_elem_idx >= 0
|
left = (spl_expr_result_t){sl_elem_idx >= 0
|
||||||
? spl_type_ptr(&ctx->tctx, sl_elem_idx)
|
? spl_type_ptr(&ctx->tctx, sl_elem_idx)
|
||||||
: spl_type_basic(&ctx->tctx, SPL_PTR), 1};
|
: spl_type_basic(&ctx->tctx, SPL_PTR),
|
||||||
|
1};
|
||||||
} else {
|
} else {
|
||||||
emit_load_ptr(&ctx->emit);
|
emit_load_ptr(&ctx->emit);
|
||||||
left = (spl_expr_result_t){sl_elem_idx >= 0
|
left = (spl_expr_result_t){sl_elem_idx >= 0
|
||||||
? spl_type_ptr(&ctx->tctx, sl_elem_idx)
|
? spl_type_ptr(&ctx->tctx, sl_elem_idx)
|
||||||
: spl_type_basic(&ctx->tctx, SPL_PTR), 0};
|
: spl_type_basic(&ctx->tctx, SPL_PTR),
|
||||||
|
0};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
continue;
|
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);
|
expect(ctx, TOK_R_BRACKET);
|
||||||
|
|
||||||
if (!has_explicit_end) {
|
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));
|
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_pick(&ctx->emit, 1);
|
||||||
emit_push_u64(&ctx->emit, sizeof(spl_val_t));
|
emit_push_u64(&ctx->emit, sizeof(spl_val_t));
|
||||||
emit_add_u64(&ctx->emit);
|
emit_add_u64(&ctx->emit);
|
||||||
@@ -1108,16 +1121,17 @@ static spl_expr_result_t parse_postfix_expr(spl_comp_t *ctx, spl_expr_result_t l
|
|||||||
emit_slice_create(ctx, stride);
|
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))
|
? spl_type_slice(&ctx->tctx, spl_type_elem_type(&ctx->tctx, left.type_idx))
|
||||||
: -1, 0};
|
: -1,
|
||||||
|
0};
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
expect(ctx, TOK_R_BRACKET);
|
expect(ctx, TOK_R_BRACKET);
|
||||||
|
|
||||||
if (left.type_idx >= 0 &&
|
if (left.type_idx >= 0 && (spl_type_kind(&ctx->tctx, left.type_idx) == TYPE_ARRAY ||
|
||||||
(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_PTR ||
|
||||||
spl_type_kind(&ctx->tctx, left.type_idx) == TYPE_SLICE)) {
|
spl_type_kind(&ctx->tctx, left.type_idx) == TYPE_SLICE)) {
|
||||||
int idx_elem_idx = spl_type_elem_type(&ctx->tctx, left.type_idx);
|
int idx_elem_idx = spl_type_elem_type(&ctx->tctx, left.type_idx);
|
||||||
@@ -1141,6 +1155,34 @@ static spl_expr_result_t parse_postfix_expr(spl_comp_t *ctx, spl_expr_result_t l
|
|||||||
continue;
|
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;
|
break;
|
||||||
}
|
}
|
||||||
return left;
|
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) {
|
if (op == TOK_AND_AND) {
|
||||||
spl_val_t bz_addr = emit_bz_here(&ctx->emit);
|
spl_val_t bz_addr = emit_bz_here(&ctx->emit);
|
||||||
spl_parse_expr(ctx, next_prec);
|
spl_parse_expr(ctx, next_prec);
|
||||||
|
spl_val_t jmp_addr = emit_jmp_here(&ctx->emit);
|
||||||
emit_patch_here(&ctx->emit, bz_addr);
|
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};
|
return (spl_expr_result_t){spl_type_basic(&ctx->tctx, SPL_I32), 0};
|
||||||
}
|
}
|
||||||
if (op == TOK_OR_OR) {
|
if (op == TOK_OR_OR) {
|
||||||
spl_val_t bnz_addr = emit_bnz_here(&ctx->emit);
|
spl_val_t bnz_addr = emit_bnz_here(&ctx->emit);
|
||||||
spl_parse_expr(ctx, next_prec);
|
spl_parse_expr(ctx, next_prec);
|
||||||
|
spl_val_t jmp_addr = emit_jmp_here(&ctx->emit);
|
||||||
emit_patch_here(&ctx->emit, bnz_addr);
|
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};
|
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) {
|
if (left.is_lvalue) {
|
||||||
spl_type_t bt = spl_type_emit_type(&ctx->tctx, left.type_idx);
|
spl_type_t bt = spl_type_emit_type(&ctx->tctx, left.type_idx);
|
||||||
if (op == TOK_ASSIGN && left.type_idx >= 0 &&
|
if (op == TOK_ASSIGN && left.type_idx >= 0 &&
|
||||||
!spl_type_is_scalar(&ctx->tctx, left.type_idx) &&
|
!spl_type_is_scalar(&ctx->tctx, left.type_idx) && right.is_lvalue) {
|
||||||
right.is_lvalue) {
|
emit_copy_addr_to_addr(&ctx->emit, spl_type_slot_count(&ctx->tctx, left.type_idx),
|
||||||
emit_copy_addr_to_addr(&ctx->emit, spl_type_slot_count(&ctx->tctx, left.type_idx), 0);
|
0);
|
||||||
} else if (op == TOK_ASSIGN) {
|
} else if (op == TOK_ASSIGN) {
|
||||||
emit_store_type(&ctx->emit, bt);
|
emit_store_type(&ctx->emit, bt);
|
||||||
} else {
|
} 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};
|
return (spl_expr_result_t){result_type_idx, 0};
|
||||||
}
|
}
|
||||||
|
|
||||||
int spl_emit_match_enum_cmp(spl_comp_t *ctx, int enum_type_idx,
|
int spl_emit_match_enum_cmp(spl_comp_t *ctx, int enum_type_idx, int val_offset, int by_value) {
|
||||||
int val_offset, int by_value) {
|
|
||||||
char vname[256];
|
char vname[256];
|
||||||
|
|
||||||
if (peek(ctx)->type == TOK_DOT) {
|
if (peek(ctx)->type == TOK_DOT) {
|
||||||
@@ -1259,12 +1306,12 @@ int spl_emit_match_enum_cmp(spl_comp_t *ctx, int enum_type_idx,
|
|||||||
spl_tok_copy_name(vtok, vname, sizeof(vname));
|
spl_tok_copy_name(vtok, vname, sizeof(vname));
|
||||||
}
|
}
|
||||||
|
|
||||||
lookup:
|
lookup: {
|
||||||
{
|
|
||||||
spl_type_item_vec_t *e_items = spl_type_items(&ctx->tctx, enum_type_idx);
|
spl_type_item_vec_t *e_items = spl_type_items(&ctx->tctx, enum_type_idx);
|
||||||
vec_for(*e_items, vi) {
|
vec_for(*e_items, vi) {
|
||||||
spl_type_item_t *vit = &vec_at(*e_items, vi);
|
spl_type_item_t *vit = &vec_at(*e_items, vi);
|
||||||
if (vit->item_kind != ITEM_VARIANT) continue;
|
if (vit->item_kind != ITEM_VARIANT)
|
||||||
|
continue;
|
||||||
if (strcmp(vit->name, vname) == 0) {
|
if (strcmp(vit->name, vname) == 0) {
|
||||||
emit_laddr(&ctx->emit, val_offset);
|
emit_laddr(&ctx->emit, val_offset);
|
||||||
if (by_value) {
|
if (by_value) {
|
||||||
@@ -1290,49 +1337,3 @@ void spl_emit_match_value_cmp(spl_comp_t *ctx, int val_offset) {
|
|||||||
spl_parse_expr(ctx, PREC_LOGOR);
|
spl_parse_expr(ctx, PREC_LOGOR);
|
||||||
emit_binop(&ctx->emit, SPL_EQ, SPL_I32);
|
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -4,6 +4,15 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
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) {
|
int expect(spl_comp_t *ctx, spl_tok_type_t type) {
|
||||||
if (peek(ctx)->type == type) {
|
if (peek(ctx)->type == type) {
|
||||||
advance(ctx);
|
advance(ctx);
|
||||||
|
|||||||
@@ -4,11 +4,22 @@
|
|||||||
|
|
||||||
#include "spl_comp.h"
|
#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 */
|
/* Token matching helpers */
|
||||||
int expect(spl_comp_t *ctx, spl_tok_type_t type);
|
int expect(spl_comp_t *ctx, spl_tok_type_t type);
|
||||||
int match(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);
|
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.
|
/* 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.
|
* 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. */
|
* On success, advances past all consumed tokens. On failure, does not advance. */
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
X(defer , KW_DEFER , SPL_V0) \
|
X(defer , KW_DEFER , SPL_V0) \
|
||||||
X(else , KW_ELSE , SPL_V0) \
|
X(else , KW_ELSE , SPL_V0) \
|
||||||
X(enum , KW_ENUM , SPL_V0) \
|
X(enum , KW_ENUM , SPL_V0) \
|
||||||
|
X(extern , KW_EXTERN , SPL_V0) \
|
||||||
X(false , KW_FALSE , SPL_V0) \
|
X(false , KW_FALSE , SPL_V0) \
|
||||||
X(fn , KW_FN , SPL_V0) \
|
X(fn , KW_FN , SPL_V0) \
|
||||||
X(for , KW_FOR , SPL_V0) \
|
X(for , KW_FOR , SPL_V0) \
|
||||||
@@ -129,13 +130,6 @@ typedef VEC(spl_tok_t) spl_tok_vec_t;
|
|||||||
/* Lexer entry point */
|
/* Lexer entry point */
|
||||||
spl_tok_vec_t spl_lex(const char *source, const char *fname);
|
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. */
|
/* Decode escape sequence, advance *s past it. Returns 0 on success. */
|
||||||
int spl_decode_escape(const char **s, char *out);
|
int spl_decode_escape(const char **s, char *out);
|
||||||
|
|
||||||
|
|||||||
@@ -4,15 +4,6 @@
|
|||||||
#include "spl_lex_util.h"
|
#include "spl_lex_util.h"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
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
|
* Parse function definition
|
||||||
* ============================================================ */
|
* ============================================================ */
|
||||||
@@ -52,8 +43,8 @@ static int parse_params_decl(spl_comp_t *ctx, char pnames[][256], int ptypes[])
|
|||||||
return nparams;
|
return nparams;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int parse_fn_body(spl_comp_t *ctx, const char *fn_name, int ret_type_idx,
|
static int parse_fn_body(spl_comp_t *ctx, const char *fn_name, int ret_type_idx, int nparams,
|
||||||
int nparams, char pnames[][256], int ptypes[], int is_pub) {
|
char pnames[][256], int ptypes[], int is_pub) {
|
||||||
int fi = spl_declare_func(ctx, fn_name, ret_type_idx, nparams, 0, is_pub);
|
int fi = spl_declare_func(ctx, fn_name, ret_type_idx, nparams, 0, is_pub);
|
||||||
ctx->current_func_idx = fi;
|
ctx->current_func_idx = fi;
|
||||||
ctx->current_ret_type_idx = ret_type_idx;
|
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));
|
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)) {
|
if (spl_type_needs_multi_slot(&ctx->tctx, ret_type_idx)) {
|
||||||
usize min_bytes =
|
usize min_bytes = spl_type_slot_count(&ctx->tctx, ret_type_idx) * sizeof(spl_val_t);
|
||||||
spl_type_slot_count(&ctx->tctx, ret_type_idx) * sizeof(spl_val_t);
|
|
||||||
if ((usize)ctx->emit.frame.peak_bytes < min_bytes)
|
if ((usize)ctx->emit.frame.peak_bytes < min_bytes)
|
||||||
ctx->emit.frame.peak_bytes = (int)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);
|
skip_nl(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int fi;
|
||||||
|
|
||||||
if (is_extern) {
|
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);
|
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)
|
if (peek(ctx)->type == TOK_SEMICOLON)
|
||||||
advance(ctx);
|
advance(ctx);
|
||||||
return;
|
return;
|
||||||
@@ -152,7 +146,9 @@ static void parse_fn_decl(spl_comp_t *ctx, int is_extern, int is_pub) {
|
|||||||
|
|
||||||
skip_nl(ctx);
|
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,8 +445,27 @@ void spl_parse_prog(spl_comp_t *ctx) {
|
|||||||
parse_type_decl(ctx);
|
parse_type_decl(ctx);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TOK_SHARP:
|
case TOK_AT:
|
||||||
advance(ctx); /* # */
|
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) {
|
if (peek(ctx)->type == TOK_L_BRACKET) {
|
||||||
advance(ctx); /* [ */
|
advance(ctx); /* [ */
|
||||||
while (peek(ctx)->type != TOK_R_BRACKET && peek(ctx)->type != TOK_EOF)
|
while (peek(ctx)->type != TOK_R_BRACKET && peek(ctx)->type != TOK_EOF)
|
||||||
@@ -458,10 +473,12 @@ void spl_parse_prog(spl_comp_t *ctx) {
|
|||||||
if (peek(ctx)->type == TOK_R_BRACKET)
|
if (peek(ctx)->type == TOK_R_BRACKET)
|
||||||
advance(ctx);
|
advance(ctx);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
skip_nl(ctx);
|
skip_nl(ctx);
|
||||||
if (peek(ctx)->type == KW_FN)
|
if (peek(ctx)->type == KW_FN)
|
||||||
parse_fn_decl(ctx, 1, 0);
|
parse_fn_decl(ctx, 1, 0);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
default: {
|
default: {
|
||||||
int prev = ctx->tok_idx;
|
int prev = ctx->tok_idx;
|
||||||
spl_parse_stmt(ctx);
|
spl_parse_stmt(ctx);
|
||||||
|
|||||||
@@ -163,10 +163,11 @@ spl_expr_result_t spl_parse_block_expr(spl_comp_t *ctx) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
spl_tok_type_t t = peek(ctx)->type;
|
spl_tok_type_t t = peek(ctx)->type;
|
||||||
int is_keyword = (t == KW_RET || t == KW_VAR || t == KW_CONST || t == KW_IF ||
|
int is_keyword =
|
||||||
t == KW_WHILE || t == KW_LOOP || t == KW_FOR || t == KW_BREAK ||
|
(t == KW_RET || t == KW_VAR || t == KW_CONST || t == KW_IF || t == KW_WHILE ||
|
||||||
t == KW_CONTINUE || t == KW_DEFER || t == KW_MATCH || t == KW_TYPE ||
|
t == KW_LOOP || t == KW_FOR || t == KW_BREAK || t == KW_CONTINUE || t == KW_DEFER ||
|
||||||
t == TOK_L_BRACE || t == TOK_SHARP || t == TOK_LINE_COMMENT);
|
t == KW_MATCH || t == KW_TYPE || t == TOK_L_BRACE || t == TOK_AT || t == TOK_SHARP ||
|
||||||
|
t == TOK_LINE_COMMENT);
|
||||||
|
|
||||||
if (is_keyword) {
|
if (is_keyword) {
|
||||||
/* Keyword statement — produces void */
|
/* Keyword statement — produces void */
|
||||||
@@ -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)) {
|
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));
|
emit_frame_copy(&ctx->emit, val_offset, spl_type_slot_count(&ctx->tctx, elem_type_idx));
|
||||||
} else {
|
} 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_load_type(&ctx->emit, elem_bt);
|
||||||
emit_store_to_laddr(&ctx->emit, val_offset, 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
|
/* Parse an enum variant pattern in a match arm: .VariantName
|
||||||
* Delegates comparison to expr layer (spl_emit_match_enum_cmp).
|
* Delegates comparison to expr layer (spl_emit_match_enum_cmp).
|
||||||
* Returns the variant item index, or -1 on error. */
|
* Returns the variant item index, or -1 on error. */
|
||||||
static int parse_match_enum_variant(spl_comp_t *ctx, int enum_type_idx,
|
static int parse_match_enum_variant(spl_comp_t *ctx, int enum_type_idx, int val_offset,
|
||||||
int val_offset, int by_value) {
|
int by_value) {
|
||||||
return spl_emit_match_enum_cmp(ctx, enum_type_idx, val_offset, 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
|
* Declares local variables and loads corresponding field data
|
||||||
* from the matched value's data area (offset 4+).
|
* from the matched value's data area (offset 4+).
|
||||||
* Sets *scope_pushed = 1 if bindings declared. */
|
* Sets *scope_pushed = 1 if bindings declared. */
|
||||||
static void parse_match_enum_bindings(spl_comp_t *ctx, int enum_type_idx,
|
static void parse_match_enum_bindings(spl_comp_t *ctx, int enum_type_idx, int variant_item_idx,
|
||||||
int variant_item_idx, int val_offset,
|
int val_offset, int *scope_pushed) {
|
||||||
int *scope_pushed) {
|
|
||||||
advance(ctx); /* ( */
|
advance(ctx); /* ( */
|
||||||
skip_nl(ctx);
|
skip_nl(ctx);
|
||||||
if (peek(ctx)->type == TOK_R_PAREN) {
|
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);
|
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++;
|
bi++;
|
||||||
skip_nl(ctx);
|
skip_nl(ctx);
|
||||||
@@ -721,7 +723,8 @@ static void parse_match_stmt(spl_comp_t *ctx) {
|
|||||||
skip_nl(ctx);
|
skip_nl(ctx);
|
||||||
if (peek(ctx)->type != TOK_ASSIGN) {
|
if (peek(ctx)->type != TOK_ASSIGN) {
|
||||||
if (n_bnz < 128)
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -738,8 +741,8 @@ static void parse_match_stmt(spl_comp_t *ctx) {
|
|||||||
|
|
||||||
/* --- Parse enum bindings (only for last variant) --- */
|
/* --- Parse enum bindings (only for last variant) --- */
|
||||||
if (is_enum_match && has_parens && arm_variant_item >= 0) {
|
if (is_enum_match && has_parens && arm_variant_item >= 0) {
|
||||||
parse_match_enum_bindings(ctx, enum_type_idx, arm_variant_item,
|
parse_match_enum_bindings(ctx, enum_type_idx, arm_variant_item, val_offset,
|
||||||
val_offset, &scope_pushed);
|
&scope_pushed);
|
||||||
}
|
}
|
||||||
|
|
||||||
skip_nl(ctx);
|
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) {
|
static void parse_extern_decl(spl_comp_t *ctx) {
|
||||||
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);
|
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)
|
while (peek(ctx)->type != TOK_R_BRACKET && peek(ctx)->type != TOK_EOF)
|
||||||
advance(ctx);
|
advance(ctx);
|
||||||
if (peek(ctx)->type == TOK_R_BRACKET)
|
if (peek(ctx)->type == TOK_R_BRACKET)
|
||||||
advance(ctx);
|
advance(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
skip_nl(ctx);
|
skip_nl(ctx);
|
||||||
|
|
||||||
@@ -970,7 +991,8 @@ void spl_parse_stmt(spl_comp_t *ctx) {
|
|||||||
case TOK_LINE_COMMENT:
|
case TOK_LINE_COMMENT:
|
||||||
advance(ctx);
|
advance(ctx);
|
||||||
break;
|
break;
|
||||||
case TOK_SHARP: /* #[extern(...)] */
|
case TOK_AT: /* @extern(...) */
|
||||||
|
case TOK_SHARP: /* #[extern(...)] (legacy) */
|
||||||
parse_extern_decl(ctx);
|
parse_extern_decl(ctx);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
#include "../stage0/spl_ir.h"
|
#include "../stage0/spl_ir.h"
|
||||||
#include "spl_comp.h"
|
#include "spl_comp.h"
|
||||||
|
#include "spl_lex_util.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
* 难度:2/5
|
* 难度:2/5
|
||||||
* 验证点:for begin..end as i、for slice as val、for slice,0.. as val,idx
|
* 验证点: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 {
|
fn main() i32 {
|
||||||
/* for 数值区间:for 0..N as i */
|
/* for 数值区间:for 0..N as i */
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
* 难度:3/5
|
* 难度:3/5
|
||||||
* 验证点:enum 定义、简单枚举值、带数据枚举变体
|
* 验证点:enum 定义、简单枚举值、带数据枚举变体
|
||||||
*/
|
*/
|
||||||
#[extern("vm")] fn vm_printf(fmt: *u8, ...) void;
|
@extern(vm) fn vm_printf(fmt: *u8, ...) void;
|
||||||
|
|
||||||
type Color = enum {
|
type Color = enum {
|
||||||
Red,
|
Red,
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
/* ===== 模块6:函数 =====
|
/* ===== 模块6:函数 =====
|
||||||
* test13_extern — 外部 VM 函数与字符串
|
* test13_extern — 外部 VM 函数与字符串
|
||||||
* 难度:2/5
|
* 难度:2/5
|
||||||
* 验证点:#[extern("vm")] 声明、vm_printf 调用、
|
* 验证点:@extern(vm) 声明、vm_printf 调用、
|
||||||
* 字符串字面量、字符串参数传递
|
* 字符串字面量、字符串参数传递
|
||||||
*/
|
*/
|
||||||
#[extern("vm")] fn vm_printf(fmt: *u8, ...) void;
|
@extern(vm) fn vm_printf(fmt: *u8, ...) void;
|
||||||
#[extern("vm")] fn vm_strlen(s: *i8) i32;
|
@extern(vm) fn vm_strlen(s: *i8) i32;
|
||||||
#[extern("vm")] fn vm_strcmp(a: *i8, b: *i8) i32;
|
@extern(vm) fn vm_strcmp(a: *i8, b: *i8) i32;
|
||||||
|
|
||||||
fn main() i32 {
|
fn main() i32 {
|
||||||
/* vm_printf 输出测试 */
|
/* vm_printf 输出测试 */
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
* 验证点:defer 语句、defer 块、多个 defer(逆序执行)、
|
* 验证点:defer 语句、defer 块、多个 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 {
|
fn with_cleanup() void {
|
||||||
defer vm_printf(" inner defer\n");
|
defer vm_printf(" inner defer\n");
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
* 难度:3/5
|
* 难度:3/5
|
||||||
* 验证点:struct 方法、enum 方法、self 参数自动填充、方法调用
|
* 验证点:struct 方法、enum 方法、self 参数自动填充、方法调用
|
||||||
*/
|
*/
|
||||||
#[extern("vm")] fn vm_printf(fmt: *u8, ...) void;
|
@extern(vm) fn vm_printf(fmt: *u8, ...) void;
|
||||||
|
|
||||||
type Point = struct {
|
type Point = struct {
|
||||||
x: i32,
|
x: i32,
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
* 难度:3/5
|
* 难度:3/5
|
||||||
* 验证点:多特性组合——指针 + 结构体 + 函数 + 循环 + 数组 + 切片
|
* 验证点:多特性组合——指针 + 结构体 + 函数 + 循环 + 数组 + 切片
|
||||||
*/
|
*/
|
||||||
#[extern("vm")] fn vm_printf(fmt: *u8, ...) void;
|
@extern(vm) fn vm_printf(fmt: *u8, ...) void;
|
||||||
|
|
||||||
type Point = struct {
|
type Point = struct {
|
||||||
x: i32,
|
x: i32,
|
||||||
|
|||||||
Reference in New Issue
Block a user