stage2 提供sys包装 解决stage1的bug
This commit is contained in:
1 parent
5de4937637
commit
1a6df012cd
5 files changed
+178
-29
No files matched your search
@@ -941,17 +941,6 @@ static spl_ast_node_ref_t parse_type_base(spl_parser_t *p) {
|
|||||||
spl_ast_node_t *tp = node_at(p->ast, ref);
|
spl_ast_node_t *tp = node_at(p->ast, ref);
|
||||||
SET_STR_FIELD(p->ast, tp->type_path.name, bt);
|
SET_STR_FIELD(p->ast, tp->type_path.name, bt);
|
||||||
vec_init(tp->type_path.generic_args);
|
vec_init(tp->type_path.generic_args);
|
||||||
|
|
||||||
while (peek(p) && peek(p)->type == TOK_DOT) {
|
|
||||||
advance(p);
|
|
||||||
const spl_tok_t *seg = peek(p);
|
|
||||||
if (!seg || seg->type != TOK_IDENT) {
|
|
||||||
PARSE_ERROR(p, SPL_DIAG_KIND_PARSE_EXPECTED, seg,
|
|
||||||
"expected identifier after '.' in type path");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
advance(p);
|
|
||||||
}
|
|
||||||
return ref;
|
return ref;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+7
-18
@@ -764,7 +764,10 @@ static void sema_collect_signatures(spl_sema_t *sema) {
|
|||||||
usize n = vec_size(sema->type->def_table);
|
usize n = vec_size(sema->type->def_table);
|
||||||
for (usize i = 1; i < n; ++i) {
|
for (usize i = 1; i < n; ++i) {
|
||||||
spl_def_node_t *d = &vec_at(sema->type->def_table, i);
|
spl_def_node_t *d = &vec_at(sema->type->def_table, i);
|
||||||
if (d->kind == SPL_DEF_FN && d->state == SPL_DECL_UNRESOLVED)
|
/* Nested imports share def_table, but each module has its own scope.
|
||||||
|
* Resolve other modules' signatures only when processing their AST. */
|
||||||
|
if (d->owner_ast == sema->ast && d->kind == SPL_DEF_FN &&
|
||||||
|
d->state == SPL_DECL_UNRESOLVED)
|
||||||
sema_eval_decl(sema, i);
|
sema_eval_decl(sema, i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1042,11 +1045,10 @@ static void sema_bind_pattern(spl_sema_t *sema, spl_ast_node_ref_t pat_ref,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* type 解包:把容器 struct 的 methods 里的名字引入当前 scope。
|
/* type 解包:把 struct 的 methods 里的名字引入当前 scope。
|
||||||
语法层由 pattern 承载,语义层在这里分派。
|
语法层由 pattern 承载,语义层在这里分派。
|
||||||
约束:
|
约束:
|
||||||
- 源类型必须是 LANG_TYPE_STRUCT 且 agg_type.variants 为空
|
- 源类型必须是 LANG_TYPE_STRUCT;实例字段不会被导入
|
||||||
(即 @import 返回的容器 struct,不是普通带字段的 struct)
|
|
||||||
- PATTERN_DOT 不允许有 sub_pattern(编译期没有 payload 概念)
|
- PATTERN_DOT 不允许有 sub_pattern(编译期没有 payload 概念)
|
||||||
- PATTERN_FIELD 不允许带 sub pattern(同上)
|
- PATTERN_FIELD 不允许带 sub pattern(同上)
|
||||||
- 不做递归导出,显式即所得 */
|
- 不做递归导出,显式即所得 */
|
||||||
@@ -1166,19 +1168,6 @@ static void sema_do_type_unpack(spl_sema_t *sema, spl_ast_node_t *decl, spl_ast_
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
spl_type_id_t src_ir = spl_lang_type_get_ir_type(sema->type, src_lang);
|
|
||||||
spl_type_node_t *irn = spl_type_node(&sema->type->ir, src_ir);
|
|
||||||
if (!irn) {
|
|
||||||
spl_diag_error(sema->diag, SPL_DIAG_KIND_TYPE_MISMATCH, &decl->dbg,
|
|
||||||
"type unpack source IR unresolved");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (vec_size(irn->agg_type.variants) != 0) {
|
|
||||||
spl_diag_error(sema->diag, SPL_DIAG_KIND_TYPE_MISMATCH, &decl->dbg,
|
|
||||||
"type unpack source has fields; only container struct allowed");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
sema_type_unpack_walk(sema, pat, src_lang);
|
sema_type_unpack_walk(sema, pat, src_lang);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1373,7 +1362,7 @@ static spl_lang_type_id_t sema_coerce(spl_sema_t *sema, spl_ast_node_ref_t ref,
|
|||||||
case SPL_AST_EXPR_AGGREGATE_LIT: {
|
case SPL_AST_EXPR_AGGREGATE_LIT: {
|
||||||
spl_lang_type_node_t *en = spl_lang_type_node(sema->type, expected);
|
spl_lang_type_node_t *en = spl_lang_type_node(sema->type, expected);
|
||||||
if (!en || (en->kind != SPL_LANG_TYPE_STRUCT && en->kind != SPL_LANG_TYPE_UNION &&
|
if (!en || (en->kind != SPL_LANG_TYPE_STRUCT && en->kind != SPL_LANG_TYPE_UNION &&
|
||||||
en->kind != SPL_LANG_TYPE_ENUM))
|
en->kind != SPL_LANG_TYPE_ENUM && en->kind != SPL_LANG_TYPE_SLICE))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (n->aggregate_literal.name) {
|
if (n->aggregate_literal.name) {
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
// Expect retcode = 6
|
||||||
|
|
||||||
|
// exit.spl
|
||||||
|
// usage: type exit = @import("exit.spl"); exit.ok();
|
||||||
|
|
||||||
|
#extern(vm) fn vm_exit(code: i32);
|
||||||
|
|
||||||
|
fn now(code: i32) {
|
||||||
|
vm_exit(code);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ok() {
|
||||||
|
vm_exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fail() {
|
||||||
|
vm_exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main(): void {
|
||||||
|
now(6);
|
||||||
|
}
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
#extern(vm) fn vm_fopen(path: *any, mode: *any): *any;
|
||||||
|
#extern(vm) fn vm_fclose(f: *any): i32;
|
||||||
|
#extern(vm) fn vm_fread(buf: *any, sz: usize, n: usize, f: *any): usize;
|
||||||
|
#extern(vm) fn vm_fwrite(buf: *any, sz: usize, n: usize, f: *any): usize;
|
||||||
|
#extern(vm) fn vm_fsize(f: *any): usize;
|
||||||
|
#extern(vm) fn vm_stdin(): *any;
|
||||||
|
#extern(vm) fn vm_stdout(): *any;
|
||||||
|
#extern(vm) fn vm_stderr(): *any;
|
||||||
|
#extern(vm) fn vm_putchar(c: i32): i32;
|
||||||
|
#extern(vm) fn vm_getchar(): i32;
|
||||||
|
|
||||||
|
handle: *any,
|
||||||
|
type File = @self;
|
||||||
|
|
||||||
|
fn stdin(): File { ret File { .handle = vm_stdin() }; }
|
||||||
|
fn stdout(): File { ret File { .handle = vm_stdout() }; }
|
||||||
|
fn stderr(): File { ret File { .handle = vm_stderr() }; }
|
||||||
|
|
||||||
|
fn open(path: *u8, mode: *u8): File {
|
||||||
|
ret File { .handle = vm_fopen(path as *any, mode as *any) };
|
||||||
|
}
|
||||||
|
|
||||||
|
fn valid(f: *File): bool {
|
||||||
|
ret f.handle != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write(f: *File, data: *u8, n: u64): u64 {
|
||||||
|
if f.handle == null { ret 0; }
|
||||||
|
ret vm_fwrite(data as *any, 1, n, f.handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_byte(f: *File, b: u8): u64 {
|
||||||
|
var tmp: u8 = b;
|
||||||
|
ret write(f, &tmp, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read(f: *File, buf: *u8, n: u64): u64 {
|
||||||
|
if f.handle == null { ret 0; }
|
||||||
|
ret vm_fread(buf as *any, 1, n, f.handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn size(f: *File): u64 {
|
||||||
|
if f.handle == null { ret 0; }
|
||||||
|
ret vm_fsize(f.handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn close(f: *File): i32 {
|
||||||
|
if f.handle == null { ret -1; }
|
||||||
|
var r = vm_fclose(f.handle);
|
||||||
|
f.handle = null;
|
||||||
|
ret r;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn putchar(c: u8) {
|
||||||
|
vm_putchar(c as i32);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn getchar(): i32 {
|
||||||
|
ret vm_getchar();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main(): void {
|
||||||
|
var out = stdout();
|
||||||
|
@assert(out.handle != null, "stdout");
|
||||||
|
var msg = "file: ok\n";
|
||||||
|
var n = write(&out, msg.ptr, msg.len);
|
||||||
|
@assert(n == msg.len, "write");
|
||||||
|
putchar(46 as u8);
|
||||||
|
putchar(10 as u8);
|
||||||
|
}
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
#extern(vm) fn vm_alloc(sz: usize): *any;
|
||||||
|
#extern(vm) fn vm_free(p: *any);
|
||||||
|
#extern(vm) fn vm_realloc(p: *any, sz: usize): *any;
|
||||||
|
#extern(vm) fn vm_memcpy(dst: *any, src: *any, n: usize): *any;
|
||||||
|
#extern(vm) fn vm_memcmp(a: *any, b: *any, n: usize): isize;
|
||||||
|
|
||||||
|
fn alloc(sz: usize): *any {
|
||||||
|
if sz == 0 { ret null; }
|
||||||
|
ret vm_alloc(sz);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn free(p: *any) {
|
||||||
|
if p == null { ret; }
|
||||||
|
vm_free(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn realloc(p: *any, sz: usize): *any {
|
||||||
|
if p == null { ret alloc(sz); }
|
||||||
|
if sz == 0 { free(p); ret null; }
|
||||||
|
ret vm_realloc(p, sz);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn copy(dst: *any, src: *any, n: usize): *any {
|
||||||
|
if n == 0 { ret dst; }
|
||||||
|
ret vm_memcpy(dst, src, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn cmp(a: *any, b: *any, n: usize): isize {
|
||||||
|
if n == 0 { ret 0; }
|
||||||
|
ret vm_memcmp(a, b, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set(dst: *any, byte: u8, n: usize): *any {
|
||||||
|
var d = dst as *u8;
|
||||||
|
var i: usize = 0;
|
||||||
|
while i < n {
|
||||||
|
d[i] = byte;
|
||||||
|
i = i + 1;
|
||||||
|
}
|
||||||
|
ret dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn zero(dst: *any, n: usize): *any {
|
||||||
|
ret set(dst, 0 as u8, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main(): void {
|
||||||
|
var p = alloc(16);
|
||||||
|
@assert(p != null, "alloc");
|
||||||
|
var q = alloc(16);
|
||||||
|
@assert(p != q, "distinct");
|
||||||
|
@assert(alloc(0) == null, "alloc(0)");
|
||||||
|
|
||||||
|
var a: u8 = 42;
|
||||||
|
var b: u8 = 0;
|
||||||
|
copy(&b as *any, &a as *any, 1);
|
||||||
|
@assert(b == 42, "copy");
|
||||||
|
|
||||||
|
var x: u8 = 1;
|
||||||
|
var y: u8 = 2;
|
||||||
|
@assert(cmp(&x as *any, &y as *any, 1) < 0, "cmp lt");
|
||||||
|
@assert(cmp(&y as *any, &x as *any, 1) > 0, "cmp gt");
|
||||||
|
@assert(cmp(&x as *any, &x as *any, 1) == 0, "cmp eq");
|
||||||
|
|
||||||
|
var buf = alloc(8);
|
||||||
|
zero(buf, 8);
|
||||||
|
var bp = buf as *u8;
|
||||||
|
@assert(bp[0] == 0, "zero");
|
||||||
|
@assert(bp[7] == 0, "zero end");
|
||||||
|
set(buf, 0xAB as u8, 8);
|
||||||
|
@assert(bp[0] == 0xAB as u8, "set");
|
||||||
|
|
||||||
|
var r = realloc(p, 32);
|
||||||
|
@assert(r != null, "realloc");
|
||||||
|
free(r);
|
||||||
|
free(q);
|
||||||
|
free(buf);
|
||||||
|
free(null);
|
||||||
|
}
|
||||||
Reference in new issue
Block a user