Files
corelang/core_main.cpp
2023-04-22 13:28:21 +02:00

180 lines
6.2 KiB
C++

/*
Features
- Labeled blocks / gotos :LabeledBlock
- Add := for default arguments in lambda. (a := false, b := false)
- Add struct default values.
- Add for loop:
- for i: int = 0, i < 10, i+=1
- for diff: array
- iterator how to do this without function poly ? for it := iter_begin(), iter_valid(), iter_advance()
- Defer
- Expand macros
- Using directive to bring symbols into local scope
- Other kinds of casts, a cast from structs of same layout, a cast without conversion
- Inject symbols into a declaration / namespace ??
- Optionally pass size and alignment calculations to C ?
Cleanup
- Look into unifying lambda expressions and lambda declarations
- Ast_Module shouldn't require Ast_File to hold declarations etc. I think
- Look into a different way of passing arguments in typechecking
- Separate out the codegen stage cause that can change
- Robust c declaration generation
- Nicer / more readable expression generation
- Detecting if return was called
- 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
- Clean way to free all memory and reset the compiler
- Bring the table?
- Nice way of creating valid declarations programatically
core_create_namespace("memes", {
core_basic_type(
}, 4);
Robustness
- Test suite that expects test to error out
- 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
- 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}
Bytecode interpreter
- Ir
- Interpreter
- Code generation
Fun
- Inject stack traces into the program
- Inject instrumentation into the program
Ideas
- Constant arrays that evaluate fully at compile time
- Rust like enum where you associate values(other structs) with key
*/
#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;
const U32 DONT_USE_C_COMPILER = 0x10;
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("generated_main.c"_s, result);
assert(r);
F64 total_compiler_time = os_time() - pctx->time.start;
printf("%f - ", total_compiler_time);
Scoped_Arena scratch(pctx->scratch);
F64 begin = os_time();
if (!is_flag_set(compile_flags, DONT_USE_C_COMPILER)) {
String_Builder builder = {scratch.arena};
builder.addf("clang generated_main.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.arena, &builder);
system((const char *)compiler_call.str);
printf("%s\n", 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);
if (!is_flag_set(compile_flags, DONT_USE_C_COMPILER)) 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);
printf("lines lexed= %d\n", pctx->lines_lexed);
}
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.arena, "a.exe %Q", testing);
#else
String sys = string_fmt(scratch.arena, "./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<String> 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) {
Scoped_Arena _scope(&scratch);
Array<OS_File_Info> examples = os_list_dir(&scratch, &scratch, "examples"_s);
Array<OS_File_Info> tests = os_list_dir(&scratch, &scratch, "tests"_s);
For(examples) {
if (it.is_directory) continue;
String filename = string_skip_to_last_slash(it.relative_path);
if (filename.len && filename.str[0] == '_') 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 | DONT_USE_C_COMPILER);
}
}
printf("End of program\n");
#if 1
if (IsDebuggerPresent()) {
Breakpoint;
}
#endif
return 0;
}