diff --git a/src/compiler/Compiler.c b/src/compiler/Compiler.c new file mode 100644 index 0000000..d15aa5b --- /dev/null +++ b/src/compiler/Compiler.c @@ -0,0 +1,140 @@ +#include "Compiler_internal.h" + + +void Compiler_init(Compiler* cmp){ + memset(cmp, 0, sizeof(Compiler)); + cmp->state = CompilerState_Initial; + cmp->tokens = List_Token_alloc(4096); + cmp->line_lengths = List_u32_alloc(1024); +} + +void Compiler_free(Compiler* cmp){ + free(cmp->code); + free(cmp->tokens.data); + free(cmp->line_lengths.data); +} + +CodePos Compiler_getLineAndColumn(Compiler* cmp, u32 pos){ + u32 prev_lines_len = 0; + if(pos >= cmp->code_len) + return CodePos_create(0, 0); + + for(u32 i = 0; i < cmp->line_lengths.len; i++){ + u32 line_len = cmp->line_lengths.data[i]; + if(prev_lines_len + line_len > pos) + return CodePos_create(i + 1, pos + 1 - prev_lines_len); + prev_lines_len += line_len; + } + + return CodePos_create(0, 0); +} + +void _Compiler_setError(Compiler* cmp, cstr context, cstr format, ...){ + // happens at the end of file + if(cmp->pos >= cmp->code_len) + cmp->pos = cmp->code_len - 1; + char position_str[32]; + CodePos code_pos = Compiler_getLineAndColumn(cmp, cmp->pos); + sprintf(position_str, "[at %u:%u][", code_pos.line, code_pos.column); + char* real_format = strcat_malloc(position_str, context, "] ", format); + va_list argv; + va_start(argv, format); + char* NULLABLE(buf) = vsprintf_malloc(512, real_format, argv); + va_end(argv); + free(real_format); + if(buf == NULL){ + buf = malloc(16); + strcpy(buf, "SPRINTF FAILED"); + } + cmp->state = CompilerState_Error; + cmp->error_message = buf; +} + +#define setError(FORMAT, ...) {\ + Compiler_setError(cmp, FORMAT, ##__VA_ARGS__);\ +} + +static bool compileFile(Compiler* cmp, FILE* f){ + returnErrorIf_auto(cmp->state != CompilerState_Parsing); + cmp->state = CompilerState_Compiling; + + return true; +} + +bool Compiler_compile(Compiler* cmp, cstr source_file_name, cstr out_file_name, bool debug){ + FILE* f = fopen(source_file_name, "rb"); + if(f == NULL) + returnError("ERROR: can't open file '%s'", source_file_name); + + List_u8 buf = List_u8_alloc(64 * 1024); + int ret; + while((ret = fgetc(f)) != EOF) { + List_u8_push(&buf, ret); + } + if(ferror(f)){ + free(buf.data); + fclose(f); + returnError("can't read file '%s'", source_file_name); + } + fclose(f); + + if(buf.len == 0){ + free(buf.data); + fclose(f); + returnError("soucre file is empty"); + } + + cmp->code = (char*)buf.data; + cmp->code_len = buf.len; + List_u8_push(&buf, 0); + + f = fopen(out_file_name, "wb"); + if(f == NULL){ + free(buf.data); + returnError("ERROR: can't open file '%s'", out_file_name); + } + + if(debug){ + printf("----------------------------------[%s]---------------------------------\n", source_file_name); + fputs(cmp->code, stdout); + fputc('\n', stdout); + } + + bool success = Compiler_lex(cmp); + if(debug){ + printf("------------------------------------[lines]-----------------------------------\n"); + for(u32 i = 0; i < cmp->line_lengths.len; i++){ + printf("[%u] length: %u\n", i+1, cmp->line_lengths.data[i]); + } + printf("------------------------------------[tokens]-----------------------------------\n"); + for(u32 i = 0; i < cmp->tokens.len; i++){ + Token t = cmp->tokens.data[i]; + CodePos pos = Compiler_getLineAndColumn(cmp, t.begin); + char* tokstr = malloc(4096); + strncpy(tokstr, cmp->code + t.begin, t.length); + tokstr[t.length] = 0; + printf("[l:%3u, c:%3u] %s '%s'\n", + pos.line, pos.column, + TokenType_toString(t.type), tokstr); + free(tokstr); + } + } + if(!success){ + fclose(f); + return false; + } + + success = Compiler_parse(cmp); + if(!success){ + fclose(f); + return false; + } + + success = compileFile(cmp, f); + fclose(f); + if(success){ + cmp->state = CompilerState_Success; + } + + return success; +} diff --git a/src/compiler/compiler.c b/src/compiler/Lexer.c similarity index 100% rename from src/compiler/compiler.c rename to src/compiler/Lexer.c diff --git a/src/main.c b/src/main.c index 8393dfc..d6c3658 100644 --- a/src/main.c +++ b/src/main.c @@ -135,15 +135,16 @@ i32 compileSources(cstr source_file, cstr out_file){ Compiler cmp; Compiler_init(&cmp); bool success = Compiler_compile(&cmp, source_file, out_file, true); - Compiler_free(&cmp); if(!success){ if(cmp.error_message){ printfe("COMPILER ERROR: %s\n", cmp.error_message); free(cmp.error_message); } else printfe("COMPILER ERROR: unknown (error_message is null)\n"); + Compiler_free(&cmp); return 111; } - + + Compiler_free(&cmp); return 0; }