207 lines
7.0 KiB
C++
207 lines
7.0 KiB
C++
/*
|
|
@! 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;
|
|
Scoped_Arena _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<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 | COMPILE_AND_RUN);
|
|
}
|
|
}
|
|
printf("End of program\n");
|
|
#if OS_WINDOWS
|
|
if (IsDebuggerPresent()) {
|
|
Breakpoint;
|
|
}
|
|
#endif
|
|
|
|
return 0;
|
|
}
|