202 lines
5.2 KiB
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 = *
|
|
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;
|
|
}
|