stage1 完成sema词法
This commit is contained in:
7
SPL.md
7
SPL.md
@@ -478,6 +478,13 @@ type T = TypeExpr — 完全同义。
|
|||||||
|
|
||||||
匹配: match 必须穷举 (或含 _),否则编译错误。
|
匹配: match 必须穷举 (或含 _),否则编译错误。
|
||||||
|
|
||||||
|
## 名称解析
|
||||||
|
|
||||||
|
1. 函数内部 (参数 + 块局部,每个 {} 建立子 scope)。
|
||||||
|
2. $root:文件聚合的 scope,所有顶层声明 (fn/type/var/const) 都是其成员。
|
||||||
|
|
||||||
|
无独立"全局"命名空间。$root 抽象不写死:@import(xxx) 返回的匿名结构即该模块当时的 $root,多文件时切换。字段/变体名不在 scope map 中 (存于聚合 def 的成员列表),裸名查找天然不命中字段;路径 a.b.c 首段裸名查 scope、后续段查聚合成员。
|
||||||
|
|
||||||
## 变量与常量
|
## 变量与常量
|
||||||
var x: T 或 var x := init: 可变量。
|
var x: T 或 var x := init: 可变量。
|
||||||
|
|
||||||
|
|||||||
@@ -151,10 +151,7 @@ static void parse_error(parser_t *p, spl_tok_t *t, const char *msg) {
|
|||||||
const char *fn = (t && t->fname) ? t->fname : "<unknown>";
|
const char *fn = (t && t->fname) ? t->fname : "<unknown>";
|
||||||
usize line = t ? t->line : 0;
|
usize line = t ? t->line : 0;
|
||||||
usize col = t ? t->col : 0;
|
usize col = t ? t->col : 0;
|
||||||
fprintf(stderr, "%s:%llu:%llu: error: %s\n", fn, (unsigned long long)line,
|
LOG_FATAL("%s:%llu:%llu: error: %s", fn, (unsigned long long)line, (unsigned long long)col, msg);
|
||||||
(unsigned long long)col, msg);
|
|
||||||
fflush(stderr);
|
|
||||||
abort();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int expect(parser_t *p, spl_tok_type_t type, const char *what) {
|
static int expect(parser_t *p, spl_tok_type_t type, const char *what) {
|
||||||
@@ -1383,7 +1380,8 @@ static spl_ast_node_ref_t parse_postfix(parser_t *p) {
|
|||||||
}
|
}
|
||||||
} else if (t->type == TOK_L_BRACKET) {
|
} else if (t->type == TOK_L_BRACKET) {
|
||||||
advance(p);
|
advance(p);
|
||||||
spl_ast_node_ref_t begin = parse_expr(p);
|
/* 切片 begin 用 parse_shift 解析:`a..b` 中 `..` 属切片标记而非 Range 表达式 */
|
||||||
|
spl_ast_node_ref_t begin = parse_shift(p);
|
||||||
if (peek(p) && peek(p)->type == TOK_RANGE) {
|
if (peek(p) && peek(p)->type == TOK_RANGE) {
|
||||||
advance(p);
|
advance(p);
|
||||||
spl_ast_node_ref_t end = 0;
|
spl_ast_node_ref_t end = 0;
|
||||||
@@ -1529,7 +1527,8 @@ static spl_ast_node_ref_t parse_primary(parser_t *p) {
|
|||||||
/* 结构体字面量 T { .f1 = e1, ... } */
|
/* 结构体字面量 T { .f1 = e1, ... } */
|
||||||
spl_ast_node_ref_vec_t agg_vec = parse_aggregate_init_body(p);
|
spl_ast_node_ref_vec_t agg_vec = parse_aggregate_init_body(p);
|
||||||
spl_ast_node_ref_t pr = mk_primary(p, t, SPL_AST_ARGGREGATE_INIT);
|
spl_ast_node_ref_t pr = mk_primary(p, t, SPL_AST_ARGGREGATE_INIT);
|
||||||
node_at(p->ast, pr)->primary_expr.aggregate_init_expr = agg_vec;
|
node_at(p->ast, pr)->primary_expr.aggregate_init.name = sdupn(t->lexeme, t->len);
|
||||||
|
node_at(p->ast, pr)->primary_expr.aggregate_init.expr = agg_vec;
|
||||||
return wrap_expr(p, pr);
|
return wrap_expr(p, pr);
|
||||||
}
|
}
|
||||||
spl_ast_node_ref_t pr = mk_primary(p, t, SPL_AST_IDENT);
|
spl_ast_node_ref_t pr = mk_primary(p, t, SPL_AST_IDENT);
|
||||||
@@ -1543,7 +1542,8 @@ static spl_ast_node_ref_t parse_primary(parser_t *p) {
|
|||||||
advance(p);
|
advance(p);
|
||||||
spl_ast_node_ref_vec_t agg_vec = parse_aggregate_init_body(p);
|
spl_ast_node_ref_vec_t agg_vec = parse_aggregate_init_body(p);
|
||||||
spl_ast_node_ref_t pr = mk_primary(p, t, SPL_AST_ARGGREGATE_INIT);
|
spl_ast_node_ref_t pr = mk_primary(p, t, SPL_AST_ARGGREGATE_INIT);
|
||||||
node_at(p->ast, pr)->primary_expr.aggregate_init_expr = agg_vec;
|
node_at(p->ast, pr)->primary_expr.aggregate_init.name = NULL;
|
||||||
|
node_at(p->ast, pr)->primary_expr.aggregate_init.expr = agg_vec;
|
||||||
return wrap_expr(p, pr);
|
return wrap_expr(p, pr);
|
||||||
}
|
}
|
||||||
parse_error(p, t, "unexpected '.' in expression");
|
parse_error(p, t, "unexpected '.' in expression");
|
||||||
@@ -2132,10 +2132,8 @@ static void expr_inline(spl_ast_t *ast, spl_ast_node_ref_t ref, char *out, size_
|
|||||||
snprintf(tmp, sizeof tmp, "%s", STR(pn->primary_expr.ident));
|
snprintf(tmp, sizeof tmp, "%s", STR(pn->primary_expr.ident));
|
||||||
break;
|
break;
|
||||||
case SPL_AST_ARGGREGATE_INIT:
|
case SPL_AST_ARGGREGATE_INIT:
|
||||||
tmp[0] = '{';
|
snprintf(tmp, sizeof tmp, "%s{ ", STR(pn->primary_expr.aggregate_init.name));
|
||||||
tmp[1] = ' ';
|
agg_items_inline(ast, &pn->primary_expr.aggregate_init.expr, tmp, sizeof tmp);
|
||||||
tmp[2] = '\0';
|
|
||||||
agg_items_inline(ast, &pn->primary_expr.aggregate_init_expr, tmp, sizeof tmp);
|
|
||||||
strncat(tmp, " }", sizeof tmp - strlen(tmp) - 1);
|
strncat(tmp, " }", sizeof tmp - strlen(tmp) - 1);
|
||||||
break;
|
break;
|
||||||
case SPL_AST_EXPR_EXPR:
|
case SPL_AST_EXPR_EXPR:
|
||||||
@@ -2480,11 +2478,11 @@ static void dump_primary_expr(spl_ast_t *ast, spl_ast_node_ref_t ref, const char
|
|||||||
node_label(prefix, is_last, "Ident %s", STR(n->primary_expr.ident));
|
node_label(prefix, is_last, "Ident %s", STR(n->primary_expr.ident));
|
||||||
break;
|
break;
|
||||||
case SPL_AST_ARGGREGATE_INIT:
|
case SPL_AST_ARGGREGATE_INIT:
|
||||||
node_label(prefix, is_last, "AggInit");
|
node_label(prefix, is_last, "AggInit %s", STR(n->primary_expr.aggregate_init.name));
|
||||||
spl_dumptree_child_prefix(dt, prefix, is_last, cp, sizeof cp);
|
spl_dumptree_child_prefix(dt, prefix, is_last, cp, sizeof cp);
|
||||||
for (usize i = 0; i < n->primary_expr.aggregate_init_expr.size; i++) {
|
for (usize i = 0; i < n->primary_expr.aggregate_init.expr.size; i++) {
|
||||||
spl_ast_node_t *it = &ast->buckets.data[n->primary_expr.aggregate_init_expr.data[i]];
|
spl_ast_node_t *it = &ast->buckets.data[n->primary_expr.aggregate_init.expr.data[i]];
|
||||||
int it_last = (int)(i == n->primary_expr.aggregate_init_expr.size - 1);
|
int it_last = (int)(i == n->primary_expr.aggregate_init.expr.size - 1);
|
||||||
node_label(cp, it_last, "Field .%s", STR(it->aggregate_init_item.ident));
|
node_label(cp, it_last, "Field .%s", STR(it->aggregate_init_item.ident));
|
||||||
if (it->aggregate_init_item.expr) {
|
if (it->aggregate_init_item.expr) {
|
||||||
char cq[512];
|
char cq[512];
|
||||||
@@ -3153,7 +3151,8 @@ static void drop_node(spl_ast_t *ast, spl_ast_node_ref_t ref, walk_ctx_t ctx) {
|
|||||||
free((void *)n->primary_expr.string_lit_expr);
|
free((void *)n->primary_expr.string_lit_expr);
|
||||||
break;
|
break;
|
||||||
case SPL_AST_ARGGREGATE_INIT:
|
case SPL_AST_ARGGREGATE_INIT:
|
||||||
drop_vec(ast, &n->primary_expr.aggregate_init_expr, CTX_AGG_ITEM);
|
free((void *)n->primary_expr.aggregate_init.name);
|
||||||
|
drop_vec(ast, &n->primary_expr.aggregate_init.expr, CTX_AGG_ITEM);
|
||||||
break;
|
break;
|
||||||
case SPL_AST_EXPR_EXPR:
|
case SPL_AST_EXPR_EXPR:
|
||||||
drop_node(ast, n->primary_expr.expr, CTX_EXPR);
|
drop_node(ast, n->primary_expr.expr, CTX_EXPR);
|
||||||
@@ -3382,7 +3381,7 @@ static void validate_node(spl_ast_t *ast, spl_ast_node_ref_t ref, walk_ctx_t ctx
|
|||||||
printf("valid: identifier missing name\n");
|
printf("valid: identifier missing name\n");
|
||||||
break;
|
break;
|
||||||
case SPL_AST_ARGGREGATE_INIT:
|
case SPL_AST_ARGGREGATE_INIT:
|
||||||
validate_vec(ast, &n->primary_expr.aggregate_init_expr, CTX_AGG_ITEM);
|
validate_vec(ast, &n->primary_expr.aggregate_init.expr, CTX_AGG_ITEM);
|
||||||
break;
|
break;
|
||||||
case SPL_AST_EXPR_EXPR:
|
case SPL_AST_EXPR_EXPR:
|
||||||
validate_node(ast, n->primary_expr.expr, CTX_EXPR);
|
validate_node(ast, n->primary_expr.expr, CTX_EXPR);
|
||||||
|
|||||||
@@ -253,7 +253,10 @@ struct spl_ast_node {
|
|||||||
const char *string_lit_expr; /* parsed c string */
|
const char *string_lit_expr; /* parsed c string */
|
||||||
const char *ident;
|
const char *ident;
|
||||||
|
|
||||||
spl_ast_node_ref_vec_t aggregate_init_expr; /* aggregate_init_item */
|
struct {
|
||||||
|
const char *name;
|
||||||
|
spl_ast_node_ref_vec_t expr; /* aggregate_init_item */
|
||||||
|
} aggregate_init;
|
||||||
|
|
||||||
spl_ast_node_ref_t expr;
|
spl_ast_node_ref_t expr;
|
||||||
struct {
|
struct {
|
||||||
|
|||||||
4
stage1/spl_emit.h
Normal file
4
stage1/spl_emit.h
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
#ifndef __SPL_EMIT_H__
|
||||||
|
#define __SPL_EMIT_H__
|
||||||
|
|
||||||
|
#endif /* __SPL_EMIT_H__ */
|
||||||
@@ -85,7 +85,7 @@ typedef struct {
|
|||||||
} spl_ir_node_t;
|
} spl_ir_node_t;
|
||||||
typedef VEC(spl_ir_node_t) spl_ir_node_vec_t;
|
typedef VEC(spl_ir_node_t) spl_ir_node_vec_t;
|
||||||
|
|
||||||
typedef usize spl_ir_node_ref_t;
|
typedef usize spl_ir_node_ref_t; /* 0 is error */
|
||||||
typedef VEC(spl_ir_node_ref_t) spl_ir_node_ref_vec_t;
|
typedef VEC(spl_ir_node_ref_t) spl_ir_node_ref_vec_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@@ -106,8 +106,9 @@ typedef struct {
|
|||||||
spl_ir_node_vec_t nodes;
|
spl_ir_node_vec_t nodes;
|
||||||
spl_ir_node_ref_vec_t labels;
|
spl_ir_node_ref_vec_t labels;
|
||||||
} spl_ir_func_t;
|
} spl_ir_func_t;
|
||||||
|
typedef usize spl_ir_func_ref_t; /* 0 is error */
|
||||||
typedef VEC(spl_ir_func_t) spl_ir_func_vec_t;
|
typedef VEC(spl_ir_func_t) spl_ir_func_vec_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
spl_ir_func_vec_t funcs;
|
spl_ir_func_vec_t funcs;
|
||||||
} spl_ir_t;
|
} spl_ir_t;
|
||||||
@@ -115,6 +116,12 @@ typedef struct {
|
|||||||
void spl_ir_init(spl_ir_t *ir);
|
void spl_ir_init(spl_ir_t *ir);
|
||||||
void spl_ir_drop(spl_ir_t *ir);
|
void spl_ir_drop(spl_ir_t *ir);
|
||||||
|
|
||||||
|
spl_ir_node_ref_t spl_ir_alloc_node(spl_ir_t *ir, spl_ir_func_ref_t fn_id);
|
||||||
|
spl_ir_func_ref_t spl_ir_alloc_fn(spl_ir_t *ir);
|
||||||
|
|
||||||
|
spl_ir_node_t *spl_ir_node(spl_ir_t *ir, spl_ir_func_ref_t fn_id, spl_ir_node_ref_t node_id);
|
||||||
|
spl_ir_func_t *spl_ir_func(spl_ir_t *ir, spl_ir_func_ref_t fn_id);
|
||||||
|
|
||||||
void spl_ir_dump(spl_ir_t *ir);
|
void spl_ir_dump(spl_ir_t *ir);
|
||||||
|
|
||||||
#endif /* __SPL_IR_H__ */
|
#endif /* __SPL_IR_H__ */
|
||||||
|
|||||||
1866
stage1/spl_sema.c
1866
stage1/spl_sema.c
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,7 @@
|
|||||||
typedef usize spl_scope_id_t; /* 0 is error */
|
typedef usize spl_scope_id_t; /* 0 is error */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
spl_scope_id_t parent;
|
spl_scope_id_t parent;
|
||||||
MAP(const char *, spl_type_id_t) symbols;
|
MAP(const char *, spl_def_id_t) symbols;
|
||||||
} spl_scope_node_t;
|
} spl_scope_node_t;
|
||||||
typedef VEC(spl_scope_node_t) spl_scope_node_vec_t;
|
typedef VEC(spl_scope_node_t) spl_scope_node_vec_t;
|
||||||
|
|
||||||
@@ -17,17 +17,19 @@ typedef struct {
|
|||||||
spl_scope_node_vec_t scopes;
|
spl_scope_node_vec_t scopes;
|
||||||
spl_scope_id_t root_scope;
|
spl_scope_id_t root_scope;
|
||||||
spl_scope_id_t current_scope;
|
spl_scope_id_t current_scope;
|
||||||
|
spl_def_id_t root_def;
|
||||||
int error_count;
|
int error_count;
|
||||||
} spl_sema_t;
|
} spl_sema_t;
|
||||||
|
|
||||||
void spl_sema_init(spl_sema_t *sema);
|
void spl_sema_init(spl_sema_t *sema);
|
||||||
void spl_sema_drop(spl_sema_t *sema);
|
void spl_sema_drop(spl_sema_t *sema);
|
||||||
void spl_sema_run(spl_sema_t *sema);
|
void spl_sema_run(spl_sema_t *sema);
|
||||||
|
void spl_sema_check(spl_sema_t *sema);
|
||||||
|
|
||||||
spl_scope_id_t spl_sema_scope_alloc(spl_sema_t *sema);
|
spl_scope_id_t spl_sema_scope_alloc(spl_sema_t *sema);
|
||||||
bool spl_sema_scope_insert(spl_sema_t *sema, spl_scope_id_t id, const char *symbol_name,
|
bool spl_sema_scope_insert(spl_sema_t *sema, spl_scope_id_t id, const char *symbol_name,
|
||||||
spl_type_id_t symbol_val);
|
spl_def_id_t symbol_val);
|
||||||
typedef VEC(const char *) spl_symbol_path_t;
|
typedef VEC(const char *) spl_symbol_path_t;
|
||||||
spl_type_id_t spl_sema_scope_find(spl_sema_t *sema, spl_symbol_path_t path);
|
spl_def_id_t spl_sema_scope_find(spl_sema_t *sema, spl_symbol_path_t path);
|
||||||
|
|
||||||
#endif /* __SPL_SEMA_H__ */
|
#endif /* __SPL_SEMA_H__ */
|
||||||
|
|||||||
@@ -1 +1,324 @@
|
|||||||
|
// WRITE BY AI
|
||||||
|
/* spl_type.c SPL 类型系统:type/def 两张完全独立的 arena 表 + 构造器 + dump
|
||||||
|
* type_table 按 spl_type_id_t 存匿名类型;def_table 按 spl_def_id_t 存命名实体。
|
||||||
|
* 两表 id 空间互不相干(0 均保留为 error)。 */
|
||||||
#include "spl_type.h"
|
#include "spl_type.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
static spl_type_id_t type_push(spl_type_t *type) {
|
||||||
|
spl_type_node_t n;
|
||||||
|
memset(&n, 0, sizeof n);
|
||||||
|
n.kind = SPL_TYPE_VOID;
|
||||||
|
vec_push(type->type_table, n);
|
||||||
|
return type->type_table.size - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 内置整型去重:同 bits/signed 复用同一 id(类型唯一化) */
|
||||||
|
spl_type_id_t spl_type_int(spl_type_t *type, usize bits, int is_signed) {
|
||||||
|
for (usize i = 1; i < type->type_table.size; i++) {
|
||||||
|
spl_type_node_t *n = &type->type_table.data[i];
|
||||||
|
if (n->kind == SPL_TYPE_INT && n->int_type.bits == bits &&
|
||||||
|
n->int_type.is_signed == is_signed)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
spl_type_id_t id = type_push(type);
|
||||||
|
type->type_table.data[id].kind = SPL_TYPE_INT;
|
||||||
|
type->type_table.data[id].int_type.bits = bits;
|
||||||
|
type->type_table.data[id].int_type.is_signed = is_signed;
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 内置浮点去重 */
|
||||||
|
spl_type_id_t spl_type_float(spl_type_t *type, usize bits) {
|
||||||
|
for (usize i = 1; i < type->type_table.size; i++) {
|
||||||
|
spl_type_node_t *n = &type->type_table.data[i];
|
||||||
|
if (n->kind == SPL_TYPE_FLOAT && n->float_type.bits == bits)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
spl_type_id_t id = type_push(type);
|
||||||
|
type->type_table.data[id].kind = SPL_TYPE_FLOAT;
|
||||||
|
type->type_table.data[id].float_type.bits = bits;
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
spl_type_id_t spl_type_void(spl_type_t *type) {
|
||||||
|
for (usize i = 1; i < type->type_table.size; i++)
|
||||||
|
if (type->type_table.data[i].kind == SPL_TYPE_VOID)
|
||||||
|
return i;
|
||||||
|
spl_type_id_t id = type_push(type);
|
||||||
|
type->type_table.data[id].kind = SPL_TYPE_VOID;
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
spl_type_id_t spl_type_bool(spl_type_t *type) {
|
||||||
|
for (usize i = 1; i < type->type_table.size; i++)
|
||||||
|
if (type->type_table.data[i].kind == SPL_TYPE_BOOL)
|
||||||
|
return i;
|
||||||
|
spl_type_id_t id = type_push(type);
|
||||||
|
type->type_table.data[id].kind = SPL_TYPE_BOOL;
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
spl_type_id_t spl_type_ptr(spl_type_t *type, spl_type_id_t val) {
|
||||||
|
spl_type_id_t id = type_push(type);
|
||||||
|
type->type_table.data[id].kind = SPL_TYPE_PTR;
|
||||||
|
type->type_table.data[id].ptr_pointee = val;
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
spl_type_id_t spl_type_slice(spl_type_t *type, spl_type_id_t val) {
|
||||||
|
spl_type_id_t id = type_push(type);
|
||||||
|
type->type_table.data[id].kind = SPL_TYPE_SLICE;
|
||||||
|
type->type_table.data[id].slice_element = val;
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
spl_type_id_t spl_type_range(spl_type_t *type, spl_type_id_t val) {
|
||||||
|
spl_type_id_t id = type_push(type);
|
||||||
|
type->type_table.data[id].kind = SPL_TYPE_RANGE;
|
||||||
|
type->type_table.data[id].range_element = val;
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
spl_type_id_t spl_type_array(spl_type_t *type, spl_type_id_t val, usize len) {
|
||||||
|
spl_type_id_t id = type_push(type);
|
||||||
|
type->type_table.data[id].kind = SPL_TYPE_ARRAY;
|
||||||
|
type->type_table.data[id].array_type.element = val;
|
||||||
|
type->type_table.data[id].array_type.len = len;
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 绑定节点/别名引用:type 节点指向被引用的类型 id
|
||||||
|
* (供未来"底层同型但类型系统不认"的 newtype 使用,暂不参与注册) */
|
||||||
|
spl_type_id_t spl_type_tid(spl_type_t *type, spl_type_id_t val) {
|
||||||
|
spl_type_id_t id = type_push(type);
|
||||||
|
type->type_table.data[id].kind = SPL_TYPE_ID;
|
||||||
|
type->type_table.data[id].type_id = val;
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 聚合类型:默认 STRUCT,字段类型列表 */
|
||||||
|
spl_type_id_t spl_type_agg(spl_type_t *type, spl_type_id_vec_t fields) {
|
||||||
|
spl_type_id_t id = type_push(type);
|
||||||
|
type->type_table.data[id].kind = SPL_TYPE_STRUCT;
|
||||||
|
type->type_table.data[id].agg_field_types = fields;
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
spl_type_id_t spl_type_enum(spl_type_t *type, spl_type_id_vec_t variants, spl_type_id_t tag) {
|
||||||
|
spl_type_id_t id = type_push(type);
|
||||||
|
type->type_table.data[id].kind = SPL_TYPE_ENUM;
|
||||||
|
type->type_table.data[id].enum_type.variants = variants;
|
||||||
|
type->type_table.data[id].enum_type.tag_type = tag;
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
spl_type_id_t spl_type_fn(spl_type_t *type, spl_type_id_vec_t params, spl_type_id_t ret) {
|
||||||
|
spl_type_id_t id = type_push(type);
|
||||||
|
type->type_table.data[id].kind = SPL_TYPE_FN;
|
||||||
|
type->type_table.data[id].fn_type.params = params;
|
||||||
|
type->type_table.data[id].fn_type.ret = ret;
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
void spl_type_init(spl_type_t *type) {
|
||||||
|
vec_init(type->type_table);
|
||||||
|
vec_init(type->def_table);
|
||||||
|
/* 两表 id 0 均保留为 error */
|
||||||
|
type_push(type);
|
||||||
|
spl_type_def_alloc(type);
|
||||||
|
/* 关键字/内置类型(去重后 i8..u64 等各占一个 id;def 由 sema 登记) */
|
||||||
|
spl_type_void(type);
|
||||||
|
spl_type_bool(type);
|
||||||
|
spl_type_int(type, 8, 1);
|
||||||
|
spl_type_int(type, 8, 0);
|
||||||
|
spl_type_int(type, 16, 1);
|
||||||
|
spl_type_int(type, 16, 0);
|
||||||
|
spl_type_int(type, 32, 1);
|
||||||
|
spl_type_int(type, 32, 0);
|
||||||
|
spl_type_int(type, 64, 1);
|
||||||
|
spl_type_int(type, 64, 0);
|
||||||
|
spl_type_float(type, 32);
|
||||||
|
spl_type_float(type, 64);
|
||||||
|
}
|
||||||
|
|
||||||
|
void spl_type_drop(spl_type_t *type) {
|
||||||
|
/* type 节点持有的内嵌 vec */
|
||||||
|
for (usize i = 0; i < type->type_table.size; i++) {
|
||||||
|
spl_type_node_t *n = &type->type_table.data[i];
|
||||||
|
switch (n->kind) {
|
||||||
|
case SPL_TYPE_STRUCT:
|
||||||
|
case SPL_TYPE_UNION:
|
||||||
|
vec_free(n->agg_field_types);
|
||||||
|
break;
|
||||||
|
case SPL_TYPE_ENUM:
|
||||||
|
vec_free(n->enum_type.variants);
|
||||||
|
break;
|
||||||
|
case SPL_TYPE_FN:
|
||||||
|
vec_free(n->fn_type.params);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* def 节点持有的内嵌 vec */
|
||||||
|
for (usize i = 0; i < type->def_table.size; i++) {
|
||||||
|
spl_def_node_t *d = &type->def_table.data[i];
|
||||||
|
switch (d->kind) {
|
||||||
|
case SPL_DEF_AGG:
|
||||||
|
vec_free(d->agg_def);
|
||||||
|
break;
|
||||||
|
case SPL_DEF_FN_PARAMS:
|
||||||
|
vec_free(d->fn_params_def);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vec_free(type->type_table);
|
||||||
|
vec_free(type->def_table);
|
||||||
|
}
|
||||||
|
|
||||||
|
spl_type_id_t spl_type_alloc(spl_type_t *type) { return type_push(type); }
|
||||||
|
|
||||||
|
spl_type_node_t *spl_type_node(spl_type_t *type, spl_type_id_t id) {
|
||||||
|
if (!id || id >= type->type_table.size)
|
||||||
|
return NULL;
|
||||||
|
return &type->type_table.data[id];
|
||||||
|
}
|
||||||
|
|
||||||
|
spl_def_id_t spl_type_def_alloc(spl_type_t *type) {
|
||||||
|
spl_def_node_t d;
|
||||||
|
memset(&d, 0, sizeof d);
|
||||||
|
d.kind = SPL_DEF_NONE;
|
||||||
|
vec_push(type->def_table, d);
|
||||||
|
return type->def_table.size - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
spl_def_node_t *spl_type_def(spl_type_t *type, spl_def_id_t id) {
|
||||||
|
if (!id || id >= type->def_table.size)
|
||||||
|
return NULL;
|
||||||
|
return &type->def_table.data[id];
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *def_kind_name(spl_def_node_t *d) {
|
||||||
|
switch (d->kind) {
|
||||||
|
case SPL_DEF_NONE:
|
||||||
|
return "none";
|
||||||
|
case SPL_DEF_BUILTIN:
|
||||||
|
return "builtin";
|
||||||
|
case SPL_DEF_VAR:
|
||||||
|
return "var";
|
||||||
|
case SPL_DEF_FN_PARAMS:
|
||||||
|
return "fn_params";
|
||||||
|
case SPL_DEF_AGG:
|
||||||
|
return "agg";
|
||||||
|
case SPL_DEF_DISTINCT:
|
||||||
|
return "distinct";
|
||||||
|
case SPL_DEF_ALIAS:
|
||||||
|
return "alias";
|
||||||
|
}
|
||||||
|
return "?";
|
||||||
|
}
|
||||||
|
|
||||||
|
void spl_type_pure_dump(spl_type_t *type, spl_type_id_t id) {
|
||||||
|
spl_type_node_t *n = spl_type_node(type, id);
|
||||||
|
if (!n) {
|
||||||
|
printf("(err)");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
switch (n->kind) {
|
||||||
|
case SPL_TYPE_VOID:
|
||||||
|
printf("void");
|
||||||
|
break;
|
||||||
|
case SPL_TYPE_BOOL:
|
||||||
|
printf("bool");
|
||||||
|
break;
|
||||||
|
case SPL_TYPE_INT:
|
||||||
|
printf("%s%zu", n->int_type.is_signed ? "i" : "u", n->int_type.bits);
|
||||||
|
break;
|
||||||
|
case SPL_TYPE_FLOAT:
|
||||||
|
printf("f%zu", n->float_type.bits);
|
||||||
|
break;
|
||||||
|
case SPL_TYPE_PTR:
|
||||||
|
printf("*");
|
||||||
|
spl_type_pure_dump(type, n->ptr_pointee);
|
||||||
|
break;
|
||||||
|
case SPL_TYPE_SLICE:
|
||||||
|
printf("[]");
|
||||||
|
spl_type_pure_dump(type, n->slice_element);
|
||||||
|
break;
|
||||||
|
case SPL_TYPE_RANGE:
|
||||||
|
printf("range[");
|
||||||
|
spl_type_pure_dump(type, n->range_element);
|
||||||
|
printf("]");
|
||||||
|
break;
|
||||||
|
case SPL_TYPE_ARRAY:
|
||||||
|
printf("[%zu]", n->array_type.len);
|
||||||
|
spl_type_pure_dump(type, n->array_type.element);
|
||||||
|
break;
|
||||||
|
case SPL_TYPE_STRUCT:
|
||||||
|
printf("struct{%zu fields}", n->agg_field_types.size);
|
||||||
|
break;
|
||||||
|
case SPL_TYPE_UNION:
|
||||||
|
printf("union{%zu fields}", n->agg_field_types.size);
|
||||||
|
break;
|
||||||
|
case SPL_TYPE_ENUM:
|
||||||
|
printf("enum{%zu variants}", n->enum_type.variants.size);
|
||||||
|
break;
|
||||||
|
case SPL_TYPE_FN: {
|
||||||
|
printf("fn(");
|
||||||
|
for (usize i = 0; i < n->fn_type.params.size; i++) {
|
||||||
|
if (i)
|
||||||
|
printf(",");
|
||||||
|
spl_type_pure_dump(type, n->fn_type.params.data[i]);
|
||||||
|
}
|
||||||
|
printf(") -> ");
|
||||||
|
spl_type_pure_dump(type, n->fn_type.ret);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SPL_TYPE_ID:
|
||||||
|
printf("id#%zu", n->type_id);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void spl_type_def_dump(spl_type_t *type, spl_def_id_t id) {
|
||||||
|
spl_def_node_t *d = spl_type_def(type, id);
|
||||||
|
if (!d) {
|
||||||
|
printf("(err)");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
printf("kind=%s type_id=%zu", def_kind_name(d), d->type_id);
|
||||||
|
switch (d->kind) {
|
||||||
|
case SPL_DEF_VAR:
|
||||||
|
printf(" var=%s", d->var_def.name ? d->var_def.name : "?");
|
||||||
|
break;
|
||||||
|
case SPL_DEF_ALIAS:
|
||||||
|
case SPL_DEF_DISTINCT:
|
||||||
|
printf(" type=%s", d->type_def.name ? d->type_def.name : "?");
|
||||||
|
break;
|
||||||
|
case SPL_DEF_AGG:
|
||||||
|
printf(" agg{");
|
||||||
|
for (usize i = 0; i < d->agg_def.size; i++) {
|
||||||
|
if (i)
|
||||||
|
printf(",");
|
||||||
|
printf("%s", d->agg_def.data[i].name ? d->agg_def.data[i].name : "?");
|
||||||
|
}
|
||||||
|
printf("}");
|
||||||
|
break;
|
||||||
|
case SPL_DEF_FN_PARAMS:
|
||||||
|
printf(" fn(");
|
||||||
|
for (usize i = 0; i < d->fn_params_def.size; i++) {
|
||||||
|
if (i)
|
||||||
|
printf(",");
|
||||||
|
printf("%s", d->fn_params_def.data[i].name ? d->fn_params_def.data[i].name : "?");
|
||||||
|
}
|
||||||
|
printf(")");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,6 +5,8 @@
|
|||||||
|
|
||||||
typedef usize spl_type_id_t; /* 0 is error */
|
typedef usize spl_type_id_t; /* 0 is error */
|
||||||
typedef VEC(spl_type_id_t) spl_type_id_vec_t;
|
typedef VEC(spl_type_id_t) spl_type_id_vec_t;
|
||||||
|
typedef usize spl_def_id_t; /* 0 is error */
|
||||||
|
typedef VEC(spl_def_id_t) spl_def_id_vec_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
enum {
|
enum {
|
||||||
@@ -14,6 +16,7 @@ typedef struct {
|
|||||||
SPL_TYPE_FLOAT,
|
SPL_TYPE_FLOAT,
|
||||||
SPL_TYPE_PTR,
|
SPL_TYPE_PTR,
|
||||||
SPL_TYPE_SLICE,
|
SPL_TYPE_SLICE,
|
||||||
|
SPL_TYPE_RANGE,
|
||||||
SPL_TYPE_ARRAY,
|
SPL_TYPE_ARRAY,
|
||||||
SPL_TYPE_STRUCT,
|
SPL_TYPE_STRUCT,
|
||||||
SPL_TYPE_UNION,
|
SPL_TYPE_UNION,
|
||||||
@@ -31,6 +34,7 @@ typedef struct {
|
|||||||
} float_type;
|
} float_type;
|
||||||
spl_type_id_t ptr_pointee;
|
spl_type_id_t ptr_pointee;
|
||||||
spl_type_id_t slice_element;
|
spl_type_id_t slice_element;
|
||||||
|
spl_type_id_t range_element;
|
||||||
struct {
|
struct {
|
||||||
spl_type_id_t element;
|
spl_type_id_t element;
|
||||||
usize len;
|
usize len;
|
||||||
@@ -46,13 +50,13 @@ typedef struct {
|
|||||||
} fn_type;
|
} fn_type;
|
||||||
spl_type_id_t type_id;
|
spl_type_id_t type_id;
|
||||||
};
|
};
|
||||||
usize byte_size; /* 布局缓存 */
|
|
||||||
} spl_type_node_t;
|
} spl_type_node_t;
|
||||||
typedef VEC(spl_type_node_t) spl_type_node_vec_t;
|
typedef VEC(spl_type_node_t) spl_type_node_vec_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
const char *name;
|
const char *name;
|
||||||
spl_type_id_t type;
|
spl_def_id_t def_id;
|
||||||
|
spl_type_id_t type_id;
|
||||||
usize scope_id;
|
usize scope_id;
|
||||||
} spl_var_def_t;
|
} spl_var_def_t;
|
||||||
typedef VEC(spl_var_def_t) spl_var_def_vec_t;
|
typedef VEC(spl_var_def_t) spl_var_def_vec_t;
|
||||||
@@ -67,6 +71,7 @@ typedef struct {
|
|||||||
SPL_DEF_DISTINCT, // newtype
|
SPL_DEF_DISTINCT, // newtype
|
||||||
SPL_DEF_ALIAS, // sametypes
|
SPL_DEF_ALIAS, // sametypes
|
||||||
} kind;
|
} kind;
|
||||||
|
spl_type_id_t type_id;
|
||||||
union {
|
union {
|
||||||
spl_var_def_t var_def;
|
spl_var_def_t var_def;
|
||||||
spl_var_def_vec_t agg_def; // include enum variants
|
spl_var_def_vec_t agg_def; // include enum variants
|
||||||
@@ -87,19 +92,19 @@ type (类型名) = (匿名类型)
|
|||||||
*/
|
*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
spl_type_node_vec_t type_table;
|
spl_type_node_vec_t type_table;
|
||||||
spl_def_node_vec_t def_table; /* 使用type_id作为索引 */
|
spl_def_node_vec_t def_table;
|
||||||
} spl_type_t;
|
} spl_type_t;
|
||||||
|
|
||||||
void spl_type_init(spl_type_t *type);
|
void spl_type_init(spl_type_t *type);
|
||||||
void spl_type_drop(spl_type_t *type);
|
void spl_type_drop(spl_type_t *type);
|
||||||
|
|
||||||
void spl_type_def_dump(spl_type_t *type, spl_type_id_t id);
|
void spl_type_def_dump(spl_type_t *type, spl_def_id_t id);
|
||||||
void spl_type_pure_dump(spl_type_t *type, spl_type_id_t id);
|
void spl_type_pure_dump(spl_type_t *type, spl_type_id_t id);
|
||||||
|
|
||||||
// alloc 时两表平行 push, 保证索引同步
|
|
||||||
spl_type_id_t spl_type_alloc(spl_type_t *type);
|
spl_type_id_t spl_type_alloc(spl_type_t *type);
|
||||||
spl_type_node_t *spl_type_node(spl_type_t *type, spl_type_id_t id);
|
spl_type_node_t *spl_type_node(spl_type_t *type, spl_type_id_t id);
|
||||||
spl_def_node_t *spl_type_def(spl_type_t *type, spl_type_id_t id);
|
spl_def_id_t spl_type_def_alloc(spl_type_t *type);
|
||||||
|
spl_def_node_t *spl_type_def(spl_type_t *type, spl_def_id_t id);
|
||||||
|
|
||||||
spl_type_id_t spl_type_void(spl_type_t *type);
|
spl_type_id_t spl_type_void(spl_type_t *type);
|
||||||
spl_type_id_t spl_type_bool(spl_type_t *type);
|
spl_type_id_t spl_type_bool(spl_type_t *type);
|
||||||
@@ -107,6 +112,7 @@ spl_type_id_t spl_type_int(spl_type_t *type, usize bits, int is_signed);
|
|||||||
spl_type_id_t spl_type_float(spl_type_t *type, usize bits);
|
spl_type_id_t spl_type_float(spl_type_t *type, usize bits);
|
||||||
spl_type_id_t spl_type_ptr(spl_type_t *type, spl_type_id_t val);
|
spl_type_id_t spl_type_ptr(spl_type_t *type, spl_type_id_t val);
|
||||||
spl_type_id_t spl_type_slice(spl_type_t *type, spl_type_id_t val);
|
spl_type_id_t spl_type_slice(spl_type_t *type, spl_type_id_t val);
|
||||||
|
spl_type_id_t spl_type_range(spl_type_t *type, spl_type_id_t val);
|
||||||
spl_type_id_t spl_type_array(spl_type_t *type, spl_type_id_t val, usize len);
|
spl_type_id_t spl_type_array(spl_type_t *type, spl_type_id_t val, usize len);
|
||||||
spl_type_id_t spl_type_tid(spl_type_t *type, spl_type_id_t val);
|
spl_type_id_t spl_type_tid(spl_type_t *type, spl_type_id_t val);
|
||||||
spl_type_id_t spl_type_agg(spl_type_t *type, spl_type_id_vec_t fields);
|
spl_type_id_t spl_type_agg(spl_type_t *type, spl_type_id_vec_t fields);
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
#include "spl_ast.h"
|
#include "spl_ast.h"
|
||||||
#include "spl_lexer.h"
|
#include "spl_lexer.h"
|
||||||
|
#include "spl_sema.h"
|
||||||
#include "spl_tok.h"
|
#include "spl_tok.h"
|
||||||
|
|
||||||
static char *read_file(const char *path, long *out_len) {
|
static char *read_file(const char *path, long *out_len) {
|
||||||
@@ -65,6 +66,42 @@ static void dump_ast(const char *src, const char *fname) {
|
|||||||
spl_ast_drop(&ast);
|
spl_ast_drop(&ast);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void dump_sema(const char *src, const char *fname) {
|
||||||
|
spl_tok_vec_t toks = spl_lex(src, fname);
|
||||||
|
spl_ast_t ast;
|
||||||
|
spl_ast_init(&ast, &toks);
|
||||||
|
spl_ast_prase(&ast);
|
||||||
|
spl_ast_valid(&ast);
|
||||||
|
spl_sema_t sema;
|
||||||
|
spl_sema_init(&sema);
|
||||||
|
sema.ast = *
|
||||||
|
spl_sema_run(&sema);
|
||||||
|
spl_sema_check(&sema);
|
||||||
|
printf("Sema root_scope=%zu scopes=%zu errors=%d\n", sema.root_scope, sema.scopes.size,
|
||||||
|
sema.error_count);
|
||||||
|
for (usize i = 0; i < sema.scopes.size; i++) {
|
||||||
|
printf("scope[%zu] parent=%zu\n", i, sema.scopes.data[i].parent);
|
||||||
|
map_for(sema.scopes.data[i].symbols, mi) {
|
||||||
|
printf(" %s -> def#%zu\n", sema.scopes.data[i].symbols.data[mi].key,
|
||||||
|
sema.scopes.data[i].symbols.data[mi].val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("TypeTable:\n");
|
||||||
|
for (usize i = 0; i < sema.type.type_table.size; i++) {
|
||||||
|
printf(" id#%zu type=", i);
|
||||||
|
spl_type_pure_dump(&sema.type, i);
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
printf("DefTable:\n");
|
||||||
|
for (usize i = 0; i < sema.type.def_table.size; i++) {
|
||||||
|
printf(" def#%zu ", i);
|
||||||
|
spl_type_def_dump(&sema.type, i);
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
spl_sema_drop(&sema);
|
||||||
|
spl_ast_drop(&ast);
|
||||||
|
}
|
||||||
|
|
||||||
static int cmd_dump(const char *flags, const char *path) {
|
static int cmd_dump(const char *flags, const char *path) {
|
||||||
long len;
|
long len;
|
||||||
char *src = read_file(path, &len);
|
char *src = read_file(path, &len);
|
||||||
@@ -72,10 +109,13 @@ static int cmd_dump(const char *flags, const char *path) {
|
|||||||
return 1;
|
return 1;
|
||||||
int do_tokens = strstr(flags, "tokens") != NULL || strcmp(flags, "all") == 0;
|
int do_tokens = strstr(flags, "tokens") != NULL || strcmp(flags, "all") == 0;
|
||||||
int do_ast = strstr(flags, "ast") != NULL || strcmp(flags, "all") == 0;
|
int do_ast = strstr(flags, "ast") != NULL || strcmp(flags, "all") == 0;
|
||||||
|
int do_sema = strstr(flags, "sema") != NULL || strcmp(flags, "all") == 0;
|
||||||
if (do_tokens)
|
if (do_tokens)
|
||||||
dump_tokens(src, path);
|
dump_tokens(src, path);
|
||||||
if (do_ast)
|
if (do_ast)
|
||||||
dump_ast(src, path);
|
dump_ast(src, path);
|
||||||
|
if (do_sema)
|
||||||
|
dump_sema(src, path);
|
||||||
free(src);
|
free(src);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -87,15 +127,20 @@ int main(int argc, char **argv) {
|
|||||||
}
|
}
|
||||||
if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-h") == 0) {
|
if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-h") == 0) {
|
||||||
LOG_INFO("splc0 <in> <out> compile (.spl -> .sir, 阶段 B)\n");
|
LOG_INFO("splc0 <in> <out> compile (.spl -> .sir, 阶段 B)\n");
|
||||||
LOG_INFO("splc0 --dump <flags> <file> dump: tokens,ast,all\n");
|
LOG_INFO("splc0 --dump <flags> <file> dump: tokens,ast,sema,all\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (strcmp(argv[1], "--dump") == 0) {
|
int argi = 1;
|
||||||
if (argc < 4) {
|
if (argi >= argc) {
|
||||||
|
LOG_FATAL("Usage: splc0 [--dump <flags>] <in> [out]\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (strcmp(argv[argi], "--dump") == 0) {
|
||||||
|
if (argc < argi + 3) {
|
||||||
LOG_INFO("splc0: --dump need <flags> <file>\n");
|
LOG_INFO("splc0: --dump need <flags> <file>\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return cmd_dump(argv[2], argv[3]);
|
return cmd_dump(argv[argi + 1], argv[argi + 2]);
|
||||||
}
|
}
|
||||||
LOG_FATAL("splc0: compile todo\n");
|
LOG_FATAL("splc0: compile todo\n");
|
||||||
return 1;
|
return 1;
|
||||||
|
|||||||
@@ -30,10 +30,10 @@ fn main() i32 {
|
|||||||
if nl != 10 { ret 6; }
|
if nl != 10 { ret 6; }
|
||||||
|
|
||||||
/* 布尔字面量 */
|
/* 布尔字面量 */
|
||||||
var t: i32 = true;
|
var t: bool = true;
|
||||||
if t != 1 { ret 7; }
|
if !t { ret 7; }
|
||||||
var f: i32 = false;
|
var f: bool = false;
|
||||||
if f != 0 { ret 8; }
|
if f { ret 8; }
|
||||||
|
|
||||||
/* null 指针 */
|
/* null 指针 */
|
||||||
var np: *i32 = null;
|
var np: *i32 = null;
|
||||||
|
|||||||
@@ -16,11 +16,11 @@ fn main() i32 {
|
|||||||
|
|
||||||
/* 比较结果为 0/1 */
|
/* 比较结果为 0/1 */
|
||||||
var eq := (42 == 42);
|
var eq := (42 == 42);
|
||||||
if eq != 1 { ret 9; }
|
if !eq { ret 9; }
|
||||||
var ne := (42 == 43);
|
var ne := (42 == 43);
|
||||||
if ne != 0 { ret 10; }
|
if ne { ret 10; }
|
||||||
var lt := (5 < 10);
|
var lt := (5 < 10);
|
||||||
if lt != 1 { ret 11; }
|
if !lt { ret 11; }
|
||||||
|
|
||||||
/* ---- 逻辑运算 ---- */
|
/* ---- 逻辑运算 ---- */
|
||||||
if (true) {} else { ret 12; }
|
if (true) {} else { ret 12; }
|
||||||
@@ -30,9 +30,9 @@ fn main() i32 {
|
|||||||
|
|
||||||
/* 逻辑非 */
|
/* 逻辑非 */
|
||||||
var not_t := !true;
|
var not_t := !true;
|
||||||
if not_t != 0 { ret 16; }
|
if not_t { ret 16; }
|
||||||
var not_f := !false;
|
var not_f := !false;
|
||||||
if not_f != 1 { ret 17; }
|
if !not_f { ret 17; }
|
||||||
|
|
||||||
// /* ---- 短路求值 ---- */
|
// /* ---- 短路求值 ---- */
|
||||||
// var short1 := 0;
|
// var short1 := 0;
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ fn test_param_pass_token() i32 {
|
|||||||
ret 0;
|
ret 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_get_tag(tok: Token) i32 {
|
fn test_get_tag(tok: Token) Tag {
|
||||||
ret tok.tag;
|
ret tok.tag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,8 +5,8 @@
|
|||||||
* 字符串字面量、字符串参数传递
|
* 字符串字面量、字符串参数传递
|
||||||
*/
|
*/
|
||||||
@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: *u8) i32;
|
||||||
@extern(vm) fn vm_strcmp(a: *i8, b: *i8) i32;
|
@extern(vm) fn vm_strcmp(a: *u8, b: *u8) i32;
|
||||||
|
|
||||||
fn main() i32 {
|
fn main() i32 {
|
||||||
/* vm_printf 输出测试 */
|
/* vm_printf 输出测试 */
|
||||||
|
|||||||
Reference in New Issue
Block a user