176 lines
6.1 KiB
C++
176 lines
6.1 KiB
C++
/*
|
|
|
|
Features
|
|
- 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()
|
|
- 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 (IsDebuggerPresent()) {
|
|
Breakpoint;
|
|
}
|
|
|
|
return 0;
|
|
}
|