/* @! Dont fully rely on files!!! @! Language.core shouldnt be a file! @! Nice way of creating valid declarations programatically @! Add a token global that implies Ast is in the executable @! Ast_Module should be Ast_File @! Stringify Core_Message list @! Separate out the codegen stage cause that can change @! Look into String_Builders in Core_Ctx @! Look into stage allocator and perhaps use it more often to reduce scenarios with 2 allocators, and simplify stuff @! Cleanup big int allocator @! Clean way to free all memory and reset the compiler @! Bring the Table<> core_create_namespace("memes", { core_basic_type( }, 4); Fix backlog - [ ] Fix and decide what to do when initializing global variable using not constants C:/AProgramming/cparse/compiler/modules/Language.core:180:28: error: initializer element is not a compile-time constant - [ ] Test and bulletproof any, slices - [ ] Test suite that expects test to error out - [ ] String declaration in Language.core this way we can compound create it and access fields and stuff - [ ] This error is valid error case when someone creates a compound out of basic type C:/AProgramming/cparse/compiler/examples/arms_race/arms_race.core:137 Internal compiler error: Invalid type was passed to the compound expression, should have been an array, struct or slice result := String{data, filesize} - [ ] Fix tuple being able to colapse into a single variable - [ ] Fix Found multiple definitions of not showing multiple definitions in the error message - [ ] How to cast from U64 to pointer? ``` Future features - [ ] Add some directive that passes metadata arguments to compiler, stores them in array and then those can be searched etc. Then we could add the link thing there - [ ] The ability for a type to also be a namespace seems like a good idea, a common pattern emerges. Not sure how to execute it though without complications. Data for sure needs to be nicely visible in a struct and those functions should be separate - [ ] Other kinds of casts, a cast from structs of same layout, a cast without conversion - [ ] Inject symbols into a declaration / namespace ?? - [ ] Using directive to bring symbols into local scope ### - [ ] Way to import and force evaluate #import_lazy #import ? Redesign: - [ ] Casting syntax In the future - [ ] Cleanup - [ ] Add ability to do i: int = 0 inside for loops for i: int = 0, i < 10, i+=1 - [ ] Complicated c declaration generation - [ ] Expand macros - [ ] Defer - [ ] Basic - [ ] Detecting if return was called - [ ] Builtin data structures - [ ] Some way to take slice of data - [ ] Dynamic arrays - [ ] Hash tables - [ ] Programming constructs - [ ] Using language construct - [ ] Named loops and breaking out of them - [ ] Bytecode interpreter - [ ] Ir - [ ] Interpreter - [ ] Code generation - [ ] Parametric Polymorphism Ideas - [ ] #test construct that would gather all tests and run them on start of program or something - [ ] Inject stack traces into the program - [ ] Constant arrays that evaluate fully at compile time - [ ] Rust like enum where you associate values(other structs) with key - [ ] Cast from array to pointer? - [ ] Ternary operator? - [ ] Optionally pass size and alignment calculations to C ? */ #include "core_compiler_includes.cpp" const U32 COMPILE_NULL = 0x0; const U32 COMPILE_PRINT_STATS = 0x1; const U32 COMPILE_PRINT_ALLOCATOR_STATS_BEFORE_DESTROY = 0x2; const U32 COMPILE_AND_RUN = 0x4; const U32 COMPILE_TESTING = 0x8; static void compile_file(Allocator *allocator, String filename, U32 compile_flags = COMPILE_NULL) { if (is_flag_set(compile_flags, COMPILE_AND_RUN)) { printf("%s - ", filename.str); } String result = compile_file_to_string(allocator, filename); B32 r = os_write_file("program.c"_s, result); assert(r); F64 total_compiler_time = os_time() - pctx->time.start; printf("%f - ", total_compiler_time); Arena *scratch = pctx->scratch; Scratch_Scope _scope(scratch); F64 begin = os_time(); String_Builder builder = {scratch}; builder.addf("clang program.c -Wall -Wno-unused-function -Wno-parentheses-equality -g -o a" OS_EXE " "); For(pctx->files_to_link) { builder.addf("-l%Q ", it->intern_val); } String compiler_call = string_flatten(scratch, &builder); system((const char *)compiler_call.str); F64 end = os_time(); if (is_flag_set(compile_flags, COMPILE_PRINT_STATS)) { printf("total = %f\n", os_time() - pctx->time.start); printf("core_total = %f\n", pctx->time.total); printf("clang = %f\n", end - begin); printf("parsing = %f\n", pctx->time.parsing); printf("typecheck = %f\n", pctx->time.typechecking); printf("generatin = %f\n", pctx->time.code_generation); } if (is_flag_set(compile_flags, COMPILE_PRINT_ALLOCATOR_STATS_BEFORE_DESTROY)) { // @! Allocator stats } if (is_flag_set(compile_flags, COMPILE_AND_RUN)) { String testing = compile_flags & COMPILE_TESTING ? "testing"_s : ""_s; #if OS_WINDOWS String sys = string_fmt(scratch, "a.exe %Q", testing); #else String sys = string_fmt(scratch, "./a.out %Q", testing); #endif int result = system((char *)sys.str); assert(result != -1); if (result == 0) { printf(PRINTF_GREEN "OK!" PRINTF_RESET); } if (result != 0) { printf(PRINTF_RED "ERROR!" PRINTF_RESET); } printf("\n"); } } int main(int argument_count, char **arguments) { os_enable_console_colors(); Arena arena = {}; Arena scratch = {}; arena_init(&arena, "Pernament arena"_s); arena_init(&scratch, "Pernament scratch arena"_s); Array args = {&scratch}; for (int i = 1; i < argument_count; i += 1) { String arg = string_from_cstring(arguments[i]); args.add(arg); } if (!args.len) { printf("Please specify a file to compile!"); return 0; } For(args) { if (it == "-testing"_s) { Scratch_Scope _scope(&scratch); Array examples = os_list_dir(&scratch, &scratch, "examples"_s); Array tests = os_list_dir(&scratch, &scratch, "tests"_s); For(examples) { if (it.is_directory) continue; compile_file(&arena, it.absolute_path, COMPILE_AND_RUN | COMPILE_TESTING); } For(tests) { if (it.is_directory) continue; compile_file(&arena, it.absolute_path, COMPILE_AND_RUN | COMPILE_TESTING); } } else { String program_name = string_from_cstring(arguments[1]); compile_file(&arena, program_name, COMPILE_PRINT_STATS); } } printf("End of program\n"); #if OS_WINDOWS if (IsDebuggerPresent()) { Breakpoint; } #endif return 0; }