stage1 重构词法分析

This commit is contained in:
zzy
2026-08-16 23:23:56 +08:00
parent d3c63dab5c
commit 4d9509c167
8 changed files with 426 additions and 2151 deletions

View File

@@ -77,6 +77,8 @@ static inline usize map_hash_str(const char *s) {
for (usize(idx) = 0; (idx) < (map).cap; ++(idx)) \
if ((map).data[(idx)].state == __MAP_SLOT_OCCUPIED)
#define unsafe_map_at(map, idx) ((map).data[(idx)])
/**
* 插入(若键已存在则更新值)
* 注意:扩容使用 realloc失败会 abort可自行修改错误处理

View File

@@ -58,6 +58,7 @@ static inline spl_ast_node_t *node_at(spl_ast_t *ast, spl_ast_node_ref_t ref) {
static spl_ast_node_ref_t new_node(parser_t *p, spl_ast_node_kind_t kind, const spl_tok_t *tok) {
spl_ast_node_t n = {0};
n.kind = kind;
n.resolved_def_id = 0;
if (tok) {
n.dbg.dbg_name = spl_ast_kind_name(kind);
n.dbg.fname = tok->fname;
@@ -1833,6 +1834,7 @@ void spl_ast_dump(spl_ast_t *ast, spl_ast_node_ref_t node) {
return;
dump_stack_t stack;
vec_init(stack);
printf("AST:\n");
dump_node(ast, node, &stack, 1);
}
@@ -2109,6 +2111,7 @@ static void dump_node(spl_ast_t *ast, spl_ast_node_ref_t node_ref, dump_stack_t
case SPL_AST_TYPE_STRUCT:
case SPL_AST_TYPE_UNION:
case SPL_AST_TYPE_ENUM:
case SPL_AST_TYPE_SHAPE:
dump_vec(ast, node->type_expr.attr_list, stack);
dump_vec(ast, node->type_expr.aggregate_list, stack);
break;

View File

@@ -1,8 +1,6 @@
#ifndef __SPL_DBG_H__
#define __SPL_DBG_H__
#include "spl_tok.h"
typedef struct {
const char *fname;
int line;

File diff suppressed because it is too large Load Diff

View File

@@ -4,32 +4,51 @@
#include "spl_ast.h"
#include "spl_type.h"
typedef enum {
SPL_SYMBOL_KIND_ERROR,
SPL_SYMBOL_KIND_VAR,
SPL_SYMBOL_KIND_MEMBER,
SPL_SYMBOL_KIND_FN,
SPL_SYMBOL_KIND_TYPE,
} spl_symbol_kind_t;
typedef struct {
const char *name;
spl_symbol_kind_t kind;
spl_def_id_t node;
} spl_symbol_t;
typedef usize spl_scope_id_t; /* 0 is error */
typedef struct {
spl_scope_id_t parent;
MAP(const char *, spl_def_id_t) symbols;
MAP(const char *, spl_symbol_t) symbols;
} spl_scope_node_t;
typedef VEC(spl_scope_node_t) spl_scope_node_vec_t;
typedef struct {
spl_ast_t *ast;
spl_type_t type;
spl_scope_node_vec_t scopes;
spl_scope_id_t root_scope;
spl_scope_id_t current_scope;
spl_def_id_t root_def;
} spl_scope_t;
void spl_scope_init(spl_scope_t *scope);
void spl_scope_drop(spl_scope_t *scope);
spl_scope_id_t spl_scope_alloc(spl_scope_t *scope);
bool spl_scope_insert(spl_scope_t *scope, spl_scope_id_t id, spl_symbol_t symbol);
typedef VEC(const char *) spl_symbol_path_t;
bool spl_scope_find(spl_scope_t *scop, const char *symbol_name, spl_symbol_t *out);
typedef struct {
spl_ast_t *ast;
spl_type_t *type;
spl_scope_t *scope;
spl_symbol_t root;
int error_count;
} spl_sema_t;
void spl_sema_init(spl_sema_t *sema);
void spl_sema_init(spl_sema_t *sema, spl_ast_t *ast, spl_type_t *type, spl_scope_t *scope);
void spl_sema_drop(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);
bool spl_sema_scope_insert(spl_sema_t *sema, spl_scope_id_t id, const char *symbol_name,
spl_def_id_t symbol_val);
typedef VEC(const char *) spl_symbol_path_t;
spl_def_id_t spl_sema_scope_find(spl_sema_t *sema, spl_symbol_path_t path);
void spl_sema_run(spl_sema_t *sema);
void spl_sema_dump(spl_sema_t *sema);
#endif /* __SPL_SEMA_H__ */

View File

@@ -1,7 +1,48 @@
#include "spl_type.h"
static usize spl_type_hash(spl_type_node_t n) { return 0; }
static int spl_type_eq(spl_type_node_t n1, spl_type_node_t n2) { return 1; }
static usize spl_type_hash(spl_type_node_t n) { return n.kind; }
static int spl_type_eq(spl_type_node_t n1, spl_type_node_t n2) {
if (n1.kind != n2.kind)
return 1;
switch (n1.kind) {
case SPL_TYPE_ERROR:
case SPL_TYPE_VOID:
case SPL_TYPE_BOOL:
break;
case SPL_TYPE_INT:
if (n1.int_type.bits != n2.int_type.bits)
return 1;
if (n1.int_type.is_signed != n2.int_type.is_signed)
return 1;
break;
case SPL_TYPE_FLOAT:
if (n1.float_type.bits != n2.float_type.bits)
return 1;
break;
case SPL_TYPE_PTR:
if (n1.ptr_pointee != n2.ptr_pointee)
return 1;
break;
case SPL_TYPE_SLICE:
if (n1.slice_element != n2.slice_element)
return 1;
break;
case SPL_TYPE_RANGE:
if (n1.range_element != n2.range_element)
return 1;
break;
case SPL_TYPE_ARRAY:
if (n1.array_type.element != n2.array_type.element)
return 1;
if (n1.array_type.len != n2.array_type.len)
return 1;
break;
// TODO
default:
return 1;
}
return 0;
}
spl_type_id_t spl_type_node_push(spl_type_t *type, spl_type_node_t type_node) {
spl_type_id_t ret = 0;

View File

@@ -2,6 +2,7 @@
#define __SPL_TYPE_H__
#include "../stage0/include/utils.h"
#include "spl_dbg.h"
typedef usize spl_type_id_t; /* 0 is error */
typedef VEC(spl_type_id_t) spl_type_id_vec_t;
@@ -77,6 +78,7 @@ typedef struct {
SPL_DEF_DISTINCT, // newtype
SPL_DEF_ALIAS, // sametypes
} kind;
spl_dbg_node_t dbg_node;
spl_type_id_t type_id;
union {
spl_var_def_t var_def;

View File

@@ -11,15 +11,24 @@
#include <string.h>
#include "spl_ast.h"
#include "spl_ast2ir.h"
#include "spl_ir2vm.h"
// #include "spl_ast2ir.h"
// #include "spl_ir2vm.h"
#include "spl_lexer.h"
#include "spl_sema.h"
#include "spl_tok.h"
typedef enum {
DUMP_NONE,
DUMP_TOKEN,
DUMP_AST,
DUMP_SEMA,
DUMP_IR,
} dump_t;
static char *read_file(const char *path, long *out_len) {
FILE *f = fopen(path, "rb");
if (!f) {
fprintf(stderr, "path `%s` ", path);
perror("fopen");
return NULL;
}
@@ -47,8 +56,7 @@ static const char *const tok_type_names[] = {
#undef X
};
static void dump_tokens(const char *src, const char *fname) {
spl_tok_vec_t toks = spl_lex(src, fname);
static void dump_tokens(spl_tok_vec_t toks) {
printf("tokens got (%zu)\n", toks.size);
for (usize i = 0; i < toks.size; i++) {
const spl_tok_t *t = &toks.data[i];
@@ -58,170 +66,47 @@ static void dump_tokens(const char *src, const char *fname) {
vec_free(toks);
}
static void dump_ast(const char *src, const char *fname) {
static int compile_spl(const char *src, const char *fname, const char *outpath, int gen_debug,
dump_t dump) {
spl_tok_vec_t toks = spl_lex(src, fname);
if (dump == DUMP_TOKEN) {
dump_tokens(toks);
// memory leak
return 0;
}
spl_ast_t ast;
spl_ast_init(&ast, &toks);
spl_ast_prase(&ast);
if (ast.parsed < 0) {
printf("parse failed, skip AST dump\n");
spl_ast_drop(&ast);
return;
}
spl_ast_valid(&ast);
spl_ast_dump(&ast, ast.root);
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);
// if (ast.parsed < 0) {
// printf("parse failed, skip sema dump\n");
// spl_ast_drop(&ast);
// return;
// }
// spl_ast_valid(&ast);
// spl_sema_t sema;
// spl_sema_init(&sema);
// sema.ast = &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 void dump_ir(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);
// if (ast.parsed < 0) {
// printf("parse failed, skip IR\n");
// spl_ast_drop(&ast);
// return;
// }
// spl_ast_valid(&ast);
// spl_sema_t sema;
// spl_sema_init(&sema);
// sema.ast = &ast;
// spl_sema_run(&sema);
// spl_sema_check(&sema);
// if (sema.error_count) {
// printf("sema errors=%d, skip IR\n", sema.error_count);
// spl_sema_drop(&sema);
// spl_ast_drop(&ast);
// return;
// }
// spl_ast2ir_t a2ir;
// spl_ast2ir_init(&a2ir, &sema);
// spl_ast2ir_run(&a2ir);
// if (a2ir.err_count)
// printf("ast2ir errors=%d\n", a2ir.err_count);
// spl_ir_dump(&a2ir.ir, &sema.type);
// spl_ast2ir_drop(&a2ir);
// spl_sema_drop(&sema);
// spl_ast_drop(&ast);
// }
static int cmd_dump(const char *flags, const char *path) {
long len;
char *src = read_file(path, &len);
if (!src)
printf("parse failed, no output\n");
// memory leak
return 1;
int do_tokens = strstr(flags, "tokens") != 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;
int do_ir = strstr(flags, "ir") != NULL || strcmp(flags, "all") == 0;
if (do_tokens)
dump_tokens(src, path);
if (do_ast)
dump_ast(src, path);
// if (do_sema)
// dump_sema(src, path);
// if (do_ir)
// dump_ir(src, path);
free(src);
}
// spl_ast_valid(&ast); TODO
if (dump == DUMP_AST) {
spl_ast_dump(&ast, ast.root);
// memory leak
return 0;
}
/* -g在 .sir 尾部追加 debug 段文本IR 行 + VAR 行spl_cli -g 读取 */
static void gen_debug_map(const char *outpath, spl_ast_t *ast, const spl_ir_t *ir,
const spl_ir2vm_t *ir2vm) {
FILE *f = fopen(outpath, "ab");
if (!f)
return;
fprintf(f, "SPLDBG\n");
// for (usize i = 0; i < ir2vm->fdbg.size; i++) {
// const spl_ir2vm_fdbg_t *fd = &ir2vm->fdbg.data[i];
// if (fd->fid >= ir->funcs.size)
// continue;
// const spl_ir_func_t *fn = &ir->funcs.data[fd->fid];
// const char *fname = fn->name ? fn->name : "?";
// for (usize ref = 1; ref < fd->node_first_ip.size; ref++) {
// usize ip = fd->node_first_ip.data[ref];
// if (ip == (usize)-1)
// continue;
// const spl_ir_node_t *n = &fn->nodes.data[ref];
// fprintf(f, "IR %zu %zu %d %s\n", ip, ref, ast_line(ast, n->src_ref),
// spl_ir_kind_name(n->kind));
// }
// for (usize j = 0; j < fn->dbg_vars.size; j++) {
// const spl_ir_dbg_var_t *dv = &fn->dbg_vars.data[j];
// if (!dv->name)
// continue;
// fprintf(f, "VAR %s %s %zu %zu %d\n", fname, dv->name, dv->offset, dv->tid,
// dv->is_param);
// }
// }
fclose(f);
spl_sema_t sema;
spl_type_t type;
spl_scope_t scope;
spl_type_init(&type);
spl_scope_init(&scope);
spl_sema_init(&sema, &ast, &type, &scope);
sema.ast = &ast;
spl_sema_run(&sema);
if (sema.error_count) {
printf("sema errors=%d, no output\n", sema.error_count);
// memory leak
return 1;
}
if (dump == DUMP_SEMA) {
spl_sema_dump(&sema);
spl_ast_dump(&ast, ast.root);
// memory leak
return 0;
}
static int compile_spl(const char *src, const char *fname, const char *outpath, int gen_debug) {
// spl_tok_vec_t toks = spl_lex(src, fname);
// spl_ast_t ast;
// spl_ast_init(&ast, &toks);
// spl_ast_prase(&ast);
// if (ast.parsed < 0) {
// printf("parse failed, no output\n");
// spl_ast_drop(&ast);
// return 1;
// }
// spl_ast_valid(&ast);
// spl_sema_t sema;
// spl_sema_init(&sema);
// sema.ast = &ast;
// spl_sema_run(&sema);
// spl_sema_check(&sema);
// if (sema.error_count) {
// printf("sema errors=%d, no output\n", sema.error_count);
// spl_sema_drop(&sema);
// spl_ast_drop(&ast);
// return 1;
// }
// spl_ast2ir_t a2ir;
// spl_ast2ir_init(&a2ir, &sema);
// spl_ast2ir_run(&a2ir);
@@ -252,7 +137,7 @@ int main(int argc, char **argv) {
}
if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-h") == 0) {
LOG_INFO("splc0 <in> <out> compile (.spl -> .sir, stage B)");
LOG_INFO("splc0 --dump <flags> <file> dump: tokens,ast,sema,ir,all");
LOG_INFO("splc0 --dump <flags> <file> dump: lex,ast,sema,ir");
return 0;
}
int argi = 1;
@@ -260,12 +145,28 @@ int main(int argc, char **argv) {
LOG_FATAL("Usage: splc0 [--dump <flags>] <in> [out]");
return 1;
}
dump_t dump = DUMP_NONE;
if (strcmp(argv[argi], "--dump") == 0) {
if (argc < argi + 3) {
LOG_INFO("splc0: --dump need <flags> <file>");
return 1;
}
return cmd_dump(argv[argi + 1], argv[argi + 2]);
const char *flags = argv[argi + 1];
if (strstr(flags, "lex") != NULL) {
dump = DUMP_TOKEN;
}
if (strstr(flags, "ast") != NULL) {
dump = DUMP_AST;
}
if (strstr(flags, "sema") != NULL) {
dump = DUMP_SEMA;
}
if (strstr(flags, "ir") != NULL) {
dump = DUMP_IR;
}
argi += 2;
}
/* splc0 [-g] <in> <out> */
if (argc < argi + 2) {
@@ -285,7 +186,7 @@ int main(int argc, char **argv) {
char *src = read_file(argv[argi], &len);
if (!src)
return 1;
int rc = compile_spl(src, argv[argi], argv[argi + 1], gen_debug);
int rc = compile_spl(src, argv[argi], argv[argi + 1], gen_debug, dump);
free(src);
return rc;
}