Files
spl/stage1/splc0.c

202 lines
5.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_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;
}
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(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];
printf("[%s] %.*s (%zu:%zu)\n", tok_type_names[t->type], (int)t->len, t->lexeme, t->line,
t->col);
}
vec_free(toks);
}
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, no output\n");
// memory leak
return 1;
}
// spl_ast_valid(&ast); TODO
if (dump == DUMP_AST) {
spl_ast_dump(&ast, ast.root);
// memory leak
return 0;
}
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;
}
spl_ast2ir_t a2ir;
spl_ir_builder_t ir_builder;
spl_ir_builder_init(&ir_builder);
spl_ast2ir_init(&a2ir, &ir_builder, &sema);
spl_ast2ir_run(&a2ir);
if (a2ir.err_count) {
printf("ast2ir errors=%d, no output\n", a2ir.err_count);
spl_ast2ir_drop(&a2ir);
spl_sema_drop(&sema);
spl_ast_drop(&ast);
return 1;
}
if (dump == DUMP_IR) {
spl_ir_dump(&ir_builder.ir, &type);
// memory leak
return 0;
}
// spl_ir2vm_t ir2vm;
// spl_ir2vm_init(&ir2vm, &a2ir.ir, &sema.type);
// int rc = spl_ir2vm_run(&ir2vm, outpath);
// if (gen_debug && rc == 0)
// gen_debug_map(outpath, &ast, &a2ir.ir, &ir2vm);
// spl_ir2vm_drop(&ir2vm);
// spl_ast2ir_drop(&a2ir);
// spl_sema_drop(&sema);
// spl_ast_drop(&ast);
// return rc ? 1 : 0;
return 0;
}
int main(int argc, char **argv) {
if (argc < 2) {
LOG_FATAL("Usage: splc0 [--dump <flags>] <in> [out]");
return 1;
}
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: lex,ast,sema,ir");
return 0;
}
int argi = 1;
if (argi >= argc) {
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;
}
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) {
LOG_FATAL("Usage: splc0 <in> <out> [-g] or splc0 --dump <flags> <file>\n");
return 1;
}
int gen_debug = 0;
if (strcmp(argv[argi], "-g") == 0) {
gen_debug = 1;
argi++;
}
if (argc < argi + 2) {
LOG_FATAL("Usage: splc0 <in> <out> [-g] or splc0 --dump <flags> <file>\n");
return 1;
}
long len;
char *src = read_file(argv[argi], &len);
if (!src)
return 1;
int rc = compile_spl(src, argv[argi], argv[argi + 1], gen_debug, dump);
free(src);
return rc;
}