stage1 完成07,08测试
This commit is contained in:
@@ -458,6 +458,10 @@ const char *spl_type_name(spl_type_t type) {
|
||||
return "f32";
|
||||
case SPL_F64:
|
||||
return "f64";
|
||||
case SPL_USIZE:
|
||||
return "usize";
|
||||
case SPL_ISIZE:
|
||||
return "isize";
|
||||
case SPL_PTR:
|
||||
return "ptr";
|
||||
default:
|
||||
|
||||
@@ -94,7 +94,7 @@ typedef enum {
|
||||
X(SPL_NLIB, "nlib", 1, 0, 0, "dlopen library (name idx)") \
|
||||
/* 调试 */ \
|
||||
X(SPL_BK, "breakpoint", 0, 0, 0, "break point when exec will stop run") \
|
||||
X(SPL_DBG, "dbg", 0, 1, 1, "print top of stack as hex")
|
||||
X(SPL_DBG, "dbg", 0, 0, 0, "print VM debug info (stack, backtrace, locals)")
|
||||
|
||||
/* clang-format on */
|
||||
|
||||
|
||||
@@ -995,8 +995,23 @@ int spl_vm_run_once(spl_vm_t *vm) {
|
||||
|
||||
/* ========== Debug ========== */
|
||||
case SPL_DBG: {
|
||||
fprintf(stderr, "---DGB: current ip %zu---\n", vm->ip);
|
||||
spl_vm_dump_instr(vm, vm->ip - 6);
|
||||
spl_vm_dump_instr(vm, vm->ip - 5);
|
||||
spl_vm_dump_instr(vm, vm->ip - 4);
|
||||
spl_vm_dump_instr(vm, vm->ip - 3);
|
||||
spl_vm_dump_instr(vm, vm->ip - 2);
|
||||
spl_vm_dump_instr(vm, vm->ip - 1);
|
||||
spl_vm_dump_instr(vm, vm->ip);
|
||||
spl_vm_dump_instr(vm, vm->ip + 1);
|
||||
spl_vm_backtrace(vm, vm->fp);
|
||||
return 2; /* breakpoint: pause execution */
|
||||
spl_vm_stackdump(vm, vm->sp);
|
||||
fprintf(stderr, "---DGB END ---\n");
|
||||
break;
|
||||
}
|
||||
|
||||
case SPL_BK: {
|
||||
return 0; /* breakpoint: pause execution */
|
||||
}
|
||||
|
||||
default:
|
||||
@@ -1057,7 +1072,7 @@ void spl_vm_stackdump(spl_vm_t *vm, spl_val_t sp) {
|
||||
fprintf(stderr, " stack (sp=%zd, fp=%zd):\n", sp, vm->fp);
|
||||
spl_val_t start = sp > 16 ? sp - 16 : 0;
|
||||
for (spl_val_t i = start; i < sp; i++) {
|
||||
fprintf(stderr, " [%zd] = 0x%016zx (%zd)\n", i, vm->stacks.data[i], vm->stacks.data[i]);
|
||||
fprintf(stderr, " [%3zd] = 0x%016zx (%zd)\n", i, vm->stacks.data[i], vm->stacks.data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1070,7 +1085,7 @@ int spl_vm_backtrace(spl_vm_t *vm, spl_val_t fp) {
|
||||
spl_val_t _saved_ip = vm->frames.data[i].saved_ip;
|
||||
spl_val_t _saved_fp = vm->frames.data[i].saved_fp;
|
||||
const char *_fn = func_name_by_ip(vm->prog, _saved_ip - 1);
|
||||
fprintf(stderr, " [%zd] %s (fp=%zd, ip=%zd, args=%zd)\n", i, _fn, _saved_fp, _saved_ip,
|
||||
fprintf(stderr, " [%3zd] %s (fp=%zd, ip=%zd, args=%zd)\n", i, _fn, _saved_fp, _saved_ip,
|
||||
vm->frames.data[i].nargs);
|
||||
}
|
||||
const char *_cur = func_name_by_ip(vm->prog, vm->ip);
|
||||
|
||||
@@ -515,6 +515,54 @@ spl_expr_result_t spl_parse_expr(spl_comp_t *ctx, int min_prec) {
|
||||
case TOK_L_BRACKET:
|
||||
left = parse_array_literal(ctx);
|
||||
break;
|
||||
case TOK_AT: {
|
||||
/* @builtin(...) — compiler intrinsic */
|
||||
advance(ctx); /* consume @ */
|
||||
skip_nl(ctx);
|
||||
tok = peek(ctx);
|
||||
if (!tok || tok->type != TOK_IDENT) {
|
||||
spl_comp_error(ctx, "expected builtin name after '@'");
|
||||
break;
|
||||
}
|
||||
char bname[256];
|
||||
usize bnlen = tok->len < 255 ? tok->len : 255;
|
||||
memcpy(bname, tok->lexeme, bnlen); bname[bnlen] = '\0';
|
||||
advance(ctx); /* consume builtin name */
|
||||
|
||||
if (strcmp(bname, "dbg") == 0) {
|
||||
/* @dbg(...) — print VM debug info */
|
||||
if (peek(ctx)->type == TOK_L_PAREN) {
|
||||
advance(ctx); /* skip ( */
|
||||
int nargs = 0;
|
||||
if (peek(ctx)->type != TOK_R_PAREN) {
|
||||
for (;;) {
|
||||
spl_parse_expr(ctx, PREC_MIN);
|
||||
nargs++;
|
||||
if (peek(ctx)->type == TOK_COMMA) { advance(ctx); continue; }
|
||||
break;
|
||||
}
|
||||
}
|
||||
expect(ctx, TOK_R_PAREN);
|
||||
|
||||
/* Emit SPL_DBG and DROP for each arg */
|
||||
for (int i = 0; i < nargs; i++) {
|
||||
spl_emit(ctx, SPL_DBG, SPL_USIZE, 0);
|
||||
spl_emit(ctx, SPL_DROP, SPL_VOID, 0);
|
||||
}
|
||||
if (nargs == 0) {
|
||||
spl_emit(ctx, SPL_DBG, SPL_VOID, 0);
|
||||
}
|
||||
} else {
|
||||
/* @dbg with no parens — just debug */
|
||||
spl_emit(ctx, SPL_DBG, SPL_VOID, 0);
|
||||
}
|
||||
/* @dbg is a void expression */
|
||||
left = (spl_expr_result_t){ spl_type_basic(SPL_VOID), 0 };
|
||||
} else {
|
||||
spl_comp_error(ctx, "unknown builtin '@%s'", bname);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
/* If it's a keyword-as-type (i32, u8, etc.), parse as function call target or type constructor */
|
||||
if (peek(ctx)->type >= KW_AS && peek(ctx)->type <= KW_ANY) {
|
||||
|
||||
@@ -656,7 +656,7 @@ static void parse_expr_stmt(spl_comp_t *ctx) {
|
||||
if (is_assign)
|
||||
ctx->addr_of_mode = 0;
|
||||
|
||||
if (!is_assign && expr.type)
|
||||
if (!is_assign && expr.type && expr.type->kind == TYPE_BASIC && expr.type->basic_type != SPL_VOID)
|
||||
spl_emit(ctx, SPL_DROP, SPL_VOID, 0);
|
||||
if (peek(ctx)->type == TOK_SEMICOLON)
|
||||
advance(ctx);
|
||||
|
||||
@@ -47,8 +47,18 @@ fn main() i32 {
|
||||
|
||||
/* ---- 指向数组元素的指针 ---- */
|
||||
var buf: [4]i32 = [4]i32{1, 2, 3, 4};
|
||||
// @dbg(); /* 数组初始化后的栈状态 */
|
||||
var elem_ptr: *i32 = &buf[0];
|
||||
if elem_ptr.* != 1 { ret 9; }
|
||||
// @dbg(); /* &buf[0] 之后:栈上应有指针值 */
|
||||
var loaded := elem_ptr.*;
|
||||
// @dbg(); /* 解引用后:loaded 值 */
|
||||
if loaded != 1 { ret 9; }
|
||||
|
||||
elem_ptr = &buf[1];
|
||||
// @dbg(); /* &buf[1] 之后 */
|
||||
var loaded2 := elem_ptr.*;
|
||||
// @dbg(); /* 解引用后:loaded2 值 */
|
||||
if loaded2 != 2 { ret 10; }
|
||||
|
||||
ret 0;
|
||||
}
|
||||
|
||||
@@ -12,11 +12,19 @@ type Color = enum {
|
||||
}
|
||||
|
||||
type Expr = enum {
|
||||
Int: i32,
|
||||
Add: struct { left: *Expr, right: *Expr },
|
||||
val: i32,
|
||||
add: struct { left: *Expr, right: *Expr },
|
||||
tag: Tag,
|
||||
|
||||
type Tag = enum {
|
||||
TagA,
|
||||
TagB,
|
||||
TagC,
|
||||
}
|
||||
}
|
||||
|
||||
fn main() i32 {
|
||||
vm_printf("enum values: %d %d %d\n", Color.Red, Color.Green, Color.Blue);
|
||||
vm_printf("enum values: %d %d %d\n", Expr.Tag.TagA, Expr.Tag.TagB, Expr.Tag.TagC);
|
||||
ret 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user