148 lines
4.2 KiB
C
148 lines
4.2 KiB
C
/* splc0.c — SPL compiler CLI (stage 1, 引导用)
|
|
*
|
|
* splc0 --dump tokens|ast|all <file> dump 前端产物
|
|
* splc0 <in> <out> 编译 (阶段 B 实现)
|
|
*/
|
|
#define __SCC_LOG_IMPL_IMPORT_SRC__
|
|
#include "../stage0/include/utils.h"
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "spl_ast.h"
|
|
#include "spl_lexer.h"
|
|
#include "spl_sema.h"
|
|
#include "spl_tok.h"
|
|
|
|
static char *read_file(const char *path, long *out_len) {
|
|
FILE *f = fopen(path, "rb");
|
|
if (!f) {
|
|
perror("fopen");
|
|
return NULL;
|
|
}
|
|
fseek(f, 0, SEEK_END);
|
|
long len = ftell(f);
|
|
fseek(f, 0, SEEK_SET);
|
|
char *buf = malloc((size_t)len + 1);
|
|
if (!buf) {
|
|
fclose(f);
|
|
return NULL;
|
|
}
|
|
fread(buf, 1, (size_t)len, f);
|
|
fclose(f);
|
|
buf[len] = '\0';
|
|
*out_len = len;
|
|
return buf;
|
|
}
|
|
|
|
static const char *const tok_type_names[] = {
|
|
#define X(name, enum_name, dummy) #enum_name,
|
|
KEYWORD_TABLE
|
|
#undef X
|
|
#define X(name, enum_name, dummy) #enum_name,
|
|
TOKEN_TABLE
|
|
#undef X
|
|
};
|
|
|
|
static void dump_tokens(const char *src, const char *fname) {
|
|
spl_tok_vec_t toks = spl_lex(src, fname);
|
|
printf("tokens got (%zu)\n", toks.size);
|
|
for (usize i = 0; i < toks.size; i++) {
|
|
const spl_tok_t *t = &toks.data[i];
|
|
printf("[%s] %.*s (%zu:%zu)\n", tok_type_names[t->type], (int)t->len, t->lexeme, t->line,
|
|
t->col);
|
|
}
|
|
vec_free(toks);
|
|
}
|
|
|
|
static void dump_ast(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_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);
|
|
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) {
|
|
long len;
|
|
char *src = read_file(path, &len);
|
|
if (!src)
|
|
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;
|
|
if (do_tokens)
|
|
dump_tokens(src, path);
|
|
if (do_ast)
|
|
dump_ast(src, path);
|
|
if (do_sema)
|
|
dump_sema(src, path);
|
|
free(src);
|
|
return 0;
|
|
}
|
|
|
|
int main(int argc, char **argv) {
|
|
if (argc < 2) {
|
|
LOG_FATAL("Usage: splc0 [--dump <flags>] <in> [out]\n");
|
|
return 1;
|
|
}
|
|
if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-h") == 0) {
|
|
LOG_INFO("splc0 <in> <out> compile (.spl -> .sir, 阶段 B)\n");
|
|
LOG_INFO("splc0 --dump <flags> <file> dump: tokens,ast,sema,all\n");
|
|
return 0;
|
|
}
|
|
int argi = 1;
|
|
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");
|
|
return 1;
|
|
}
|
|
return cmd_dump(argv[argi + 1], argv[argi + 2]);
|
|
}
|
|
LOG_FATAL("splc0: compile todo\n");
|
|
return 1;
|
|
}
|