mirror of
https://github.com/odin-lang/Odin.git
synced 2025-12-31 10:22:08 +00:00
Call expression, either handle all or ignore all results.
This commit is contained in:
@@ -1,16 +1,28 @@
|
||||
#import "runtime.odin" as _
|
||||
#import "punity.odin" as punity
|
||||
#import "punity.odin" as pn
|
||||
#import "fmt.odin" as fmt
|
||||
|
||||
test :: proc() {
|
||||
thing :: proc() {
|
||||
thing :: proc() {
|
||||
fmt.println("Hello1")
|
||||
}
|
||||
|
||||
fmt.println("Hello")
|
||||
}
|
||||
}
|
||||
|
||||
main :: proc() {
|
||||
init :: proc() {
|
||||
test()
|
||||
|
||||
init :: proc(c: ^pn.Core) {
|
||||
|
||||
}
|
||||
|
||||
step :: proc() {
|
||||
|
||||
step :: proc(c: ^pn.Core) {
|
||||
if pn.key_down(pn.Key.ESCAPE) {
|
||||
c.running = false
|
||||
}
|
||||
}
|
||||
|
||||
punity.run(init, step)
|
||||
pn.run(init, step)
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ time_now :: proc() -> f64 {
|
||||
assert(win32_perf_count_freq != 0)
|
||||
|
||||
counter: i64
|
||||
_ = win32.QueryPerformanceCounter(^counter)
|
||||
win32.QueryPerformanceCounter(^counter)
|
||||
result := counter as f64 / win32_perf_count_freq as f64
|
||||
return result
|
||||
}
|
||||
@@ -24,7 +24,7 @@ win32_print_last_error :: proc() {
|
||||
// Yuk!
|
||||
to_c_string :: proc(s: string) -> []u8 {
|
||||
c_str := new_slice(u8, s.count+1)
|
||||
_ = copy(c_str, s as []byte)
|
||||
copy(c_str, s as []byte)
|
||||
c_str[s.count] = 0
|
||||
return c_str
|
||||
}
|
||||
@@ -157,8 +157,8 @@ run :: proc() {
|
||||
if msg.message == WM_QUIT {
|
||||
running = false
|
||||
}
|
||||
_ = TranslateMessage(^msg)
|
||||
_ = DispatchMessageA(^msg)
|
||||
TranslateMessage(^msg)
|
||||
DispatchMessageA(^msg)
|
||||
}
|
||||
|
||||
if is_key_down(Key_Code.ESCAPE) {
|
||||
|
||||
@@ -1,10 +1,5 @@
|
||||
#shared_global_scope
|
||||
|
||||
// TODO(bill): Create a standard library "location" so I don't have to manually import "runtime.odin"
|
||||
#import "win32.odin" as win32
|
||||
#import "os.odin" as os
|
||||
#import "fmt.odin" as fmt
|
||||
|
||||
// IMPORTANT NOTE(bill): Do not change the order of any of this data
|
||||
// The compiler relies upon this _exact_ order
|
||||
Type_Info :: union {
|
||||
@@ -80,20 +75,22 @@ byte_swap16 :: proc(b: u16) -> u16 #foreign "llvm.bswap.i16"
|
||||
byte_swap32 :: proc(b: u32) -> u32 #foreign "llvm.bswap.i32"
|
||||
byte_swap64 :: proc(b: u64) -> u64 #foreign "llvm.bswap.i64"
|
||||
|
||||
fmuladd_f32 :: proc(a, b, c: f32) -> f32 #foreign "llvm.fmuladd.f32"
|
||||
fmuladd_f64 :: proc(a, b, c: f64) -> f64 #foreign "llvm.fmuladd.f64"
|
||||
fmuladd32 :: proc(a, b, c: f32) -> f32 #foreign "llvm.fmuladd.f32"
|
||||
fmuladd64 :: proc(a, b, c: f64) -> f64 #foreign "llvm.fmuladd.f64"
|
||||
|
||||
heap_alloc :: proc(len: int) -> rawptr {
|
||||
return win32.HeapAlloc(win32.GetProcessHeap(), win32.HEAP_ZERO_MEMORY, len)
|
||||
heap_alloc :: proc(len: int) -> rawptr {
|
||||
c_malloc :: proc(len: int) -> rawptr #foreign "malloc"
|
||||
return c_malloc(len)
|
||||
}
|
||||
|
||||
heap_free :: proc(ptr: rawptr) {
|
||||
_ = win32.HeapFree(win32.GetProcessHeap(), 0, ptr)
|
||||
c_free :: proc(ptr: rawptr) #foreign "free"
|
||||
c_free(ptr)
|
||||
}
|
||||
|
||||
current_thread_id :: proc() -> int {
|
||||
id := win32.GetCurrentThreadId()
|
||||
return id as int
|
||||
GetCurrentThreadId :: proc() -> u32 #foreign #dll_import
|
||||
return GetCurrentThreadId() as int
|
||||
}
|
||||
|
||||
memory_zero :: proc(data: rawptr, len: int) {
|
||||
@@ -168,10 +165,16 @@ __string_gt :: proc(a, b : string) -> bool #inline { return __string_cmp(a, b) >
|
||||
__string_le :: proc(a, b : string) -> bool #inline { return __string_cmp(a, b) <= 0 }
|
||||
__string_ge :: proc(a, b : string) -> bool #inline { return __string_cmp(a, b) >= 0 }
|
||||
|
||||
__print_err_str :: proc(s: string) {
|
||||
|
||||
}
|
||||
__print_err_int :: proc(i: int) {
|
||||
|
||||
}
|
||||
|
||||
__assert :: proc(msg: string) {
|
||||
_ = os.write(os.get_standard_file(os.File_Standard.ERROR), msg as []byte)
|
||||
// TODO(bill): Write message
|
||||
__print_err_str(msg)
|
||||
__debug_trap()
|
||||
}
|
||||
|
||||
@@ -180,9 +183,10 @@ __bounds_check_error :: proc(file: string, line, column: int,
|
||||
if 0 <= index && index < count {
|
||||
return
|
||||
}
|
||||
// TODO(bill): Write message
|
||||
// TODO(bill): Probably reduce the need for `print` in the runtime if possible
|
||||
fmt.println_err("%(%:%) Index % is out of bounds range [0, %)",
|
||||
file, line, column, index, count)
|
||||
// fmt.println_err("%(%:%) Index % is out of bounds range [0, %)",
|
||||
// file, line, column, index, count)
|
||||
__debug_trap()
|
||||
}
|
||||
|
||||
@@ -191,8 +195,9 @@ __slice_expr_error :: proc(file: string, line, column: int,
|
||||
if 0 <= low && low <= high && high <= max {
|
||||
return
|
||||
}
|
||||
fmt.println_err("%(%:%) Invalid slice indices: [%:%:%]",
|
||||
file, line, column, low, high, max)
|
||||
// TODO(bill): Write message
|
||||
// fmt.println_err("%(%:%) Invalid slice indices: [%:%:%]",
|
||||
// file, line, column, low, high, max)
|
||||
__debug_trap()
|
||||
}
|
||||
__substring_expr_error :: proc(file: string, line, column: int,
|
||||
@@ -200,8 +205,9 @@ __substring_expr_error :: proc(file: string, line, column: int,
|
||||
if 0 <= low && low <= high {
|
||||
return
|
||||
}
|
||||
fmt.println_err("%(%:%) Invalid substring indices: [%:%:%]",
|
||||
file, line, column, low, high)
|
||||
// TODO(bill): Write message
|
||||
// fmt.println_err("%(%:%) Invalid substring indices: [%:%:%]",
|
||||
// file, line, column, low, high)
|
||||
__debug_trap()
|
||||
}
|
||||
|
||||
|
||||
@@ -83,14 +83,15 @@ RECT :: struct #ordered {
|
||||
}
|
||||
|
||||
|
||||
GetLastError :: proc() -> i32 #foreign #dll_import
|
||||
ExitProcess :: proc(exit_code: u32) #foreign #dll_import
|
||||
GetDesktopWindow :: proc() -> HWND #foreign #dll_import
|
||||
GetCursorPos :: proc(p: ^POINT) -> i32 #foreign #dll_import
|
||||
ScreenToClient :: proc(h: HWND, p: ^POINT) -> i32 #foreign #dll_import
|
||||
GetModuleHandleA :: proc(module_name: ^u8) -> HINSTANCE #foreign #dll_import
|
||||
GetStockObject :: proc(fn_object: i32) -> HGDIOBJ #foreign #dll_import
|
||||
PostQuitMessage :: proc(exit_code: i32) #foreign #dll_import
|
||||
GetLastError :: proc() -> i32 #foreign #dll_import
|
||||
ExitProcess :: proc(exit_code: u32) #foreign #dll_import
|
||||
GetDesktopWindow :: proc() -> HWND #foreign #dll_import
|
||||
GetCursorPos :: proc(p: ^POINT) -> i32 #foreign #dll_import
|
||||
ScreenToClient :: proc(h: HWND, p: ^POINT) -> i32 #foreign #dll_import
|
||||
GetModuleHandleA :: proc(module_name: ^u8) -> HINSTANCE #foreign #dll_import
|
||||
GetStockObject :: proc(fn_object: i32) -> HGDIOBJ #foreign #dll_import
|
||||
PostQuitMessage :: proc(exit_code: i32) #foreign #dll_import
|
||||
SetWindowTextA :: proc(hwnd: HWND, c_string: ^u8) -> BOOL #foreign #dll_import
|
||||
|
||||
QueryPerformanceFrequency :: proc(result: ^i64) -> i32 #foreign #dll_import
|
||||
QueryPerformanceCounter :: proc(result: ^i64) -> i32 #foreign #dll_import
|
||||
@@ -122,7 +123,7 @@ AdjustWindowRect :: proc(rect: ^RECT, style: u32, menu: BOOL) -> BOOL #foreign #
|
||||
|
||||
GetQueryPerformanceFrequency :: proc() -> i64 {
|
||||
r: i64
|
||||
_ = QueryPerformanceFrequency(^r)
|
||||
QueryPerformanceFrequency(^r)
|
||||
return r
|
||||
}
|
||||
|
||||
@@ -287,6 +288,7 @@ wglDeleteContext :: proc(hglrc: HGLRC) -> BOOL #foreign #dll_import
|
||||
|
||||
|
||||
|
||||
GetKeyState :: proc(v_key: i32) -> i16 #foreign #dll_import
|
||||
GetAsyncKeyState :: proc(v_key: i32) -> i16 #foreign #dll_import
|
||||
|
||||
is_key_down :: proc(key: Key_Code) -> bool {
|
||||
|
||||
@@ -1034,7 +1034,9 @@ void check_parsed_files(Checker *c) {
|
||||
Entity *e = scope->elements.entries[elem_index].value;
|
||||
// NOTE(bill): Do not add other imported entities
|
||||
if (e->scope == scope && e->kind != Entity_ImportName) {
|
||||
add_entity(c, file_scope, NULL, e);
|
||||
if (is_entity_exported(e)) {
|
||||
add_entity(c, file_scope, NULL, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -51,7 +51,7 @@ struct Entity {
|
||||
b8 is_field; // Is struct field
|
||||
} Variable;
|
||||
struct {
|
||||
struct DeclInfo *decl; // Usually NULL
|
||||
// struct DeclInfo *decl; // Usually NULL
|
||||
} TypeName;
|
||||
struct {
|
||||
b8 pure;
|
||||
@@ -66,6 +66,15 @@ struct Entity {
|
||||
};
|
||||
};
|
||||
|
||||
b32 is_entity_exported(Entity *e) {
|
||||
// TODO(bill): Do I really want non-exported entities?
|
||||
// if (e->token.string.len >= 1 &&
|
||||
// e->token.string.text[0] == '_') {
|
||||
// return false;
|
||||
// }
|
||||
return true;
|
||||
}
|
||||
|
||||
gb_global gbAtomic64 entity_guid_counter = {0};
|
||||
|
||||
EntityGuid next_entity_guid(void) {
|
||||
|
||||
@@ -835,27 +835,28 @@ void check_identifier(Checker *c, Operand *o, AstNode *n, Type *named_type, Cycl
|
||||
}
|
||||
|
||||
i64 check_array_count(Checker *c, AstNode *e) {
|
||||
if (e) {
|
||||
Operand o = {};
|
||||
check_expr(c, &o, e);
|
||||
if (o.mode != Addressing_Constant) {
|
||||
if (o.mode != Addressing_Invalid) {
|
||||
error(&c->error_collector, ast_node_token(e), "Array count must be a constant");
|
||||
}
|
||||
if (e == NULL) {
|
||||
return 0;
|
||||
}
|
||||
Operand o = {};
|
||||
check_expr(c, &o, e);
|
||||
if (o.mode != Addressing_Constant) {
|
||||
if (o.mode != Addressing_Invalid) {
|
||||
error(&c->error_collector, ast_node_token(e), "Array count must be a constant");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if (is_type_untyped(o.type) || is_type_integer(o.type)) {
|
||||
if (o.value.kind == ExactValue_Integer) {
|
||||
i64 count = o.value.value_integer;
|
||||
if (count >= 0)
|
||||
return count;
|
||||
error(&c->error_collector, ast_node_token(e), "Invalid array count");
|
||||
return 0;
|
||||
}
|
||||
if (is_type_untyped(o.type) || is_type_integer(o.type)) {
|
||||
if (o.value.kind == ExactValue_Integer) {
|
||||
i64 count = o.value.value_integer;
|
||||
if (count >= 0)
|
||||
return count;
|
||||
error(&c->error_collector, ast_node_token(e), "Invalid array count");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
error(&c->error_collector, ast_node_token(e), "Array count must be an integer");
|
||||
}
|
||||
|
||||
error(&c->error_collector, ast_node_token(e), "Array count must be an integer");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2001,17 +2002,24 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node) {
|
||||
if (e != NULL && e->kind == Entity_ImportName) {
|
||||
check_op_expr = false;
|
||||
entity = scope_lookup_entity(e->ImportName.scope, selector->Ident.string);
|
||||
add_entity_use(&c->info, selector, entity);
|
||||
if (entity == NULL) {
|
||||
gbString sel_str = expr_to_string(selector);
|
||||
defer (gb_string_free(sel_str));
|
||||
error(&c->error_collector, ast_node_token(op_expr), "`%s` is not declared in `%.*s`", sel_str, LIT(name));
|
||||
error(&c->error_collector, ast_node_token(op_expr), "`%s` is not declared by `%.*s`", sel_str, LIT(name));
|
||||
goto error;
|
||||
}
|
||||
if (entity->type == NULL) { // Not setup yet
|
||||
check_entity_decl(c, entity, NULL, NULL);
|
||||
}
|
||||
GB_ASSERT(entity->type != NULL);
|
||||
if (!is_entity_exported(entity)) {
|
||||
gbString sel_str = expr_to_string(selector);
|
||||
defer (gb_string_free(sel_str));
|
||||
error(&c->error_collector, ast_node_token(op_expr), "`%s` is not exported by `%.*s`", sel_str, LIT(name));
|
||||
// NOTE(bill): Not really an error so don't goto error
|
||||
}
|
||||
|
||||
add_entity_use(&c->info, selector, entity);
|
||||
}
|
||||
}
|
||||
if (check_op_expr) {
|
||||
|
||||
@@ -8,6 +8,7 @@ enum StmtFlag : u32 {
|
||||
|
||||
|
||||
void check_stmt(Checker *c, AstNode *node, u32 flags);
|
||||
void check_proc_decl(Checker *c, Entity *e, DeclInfo *d, b32 check_body_later);
|
||||
|
||||
void check_stmt_list(Checker *c, AstNodeArray stmts, u32 flags) {
|
||||
b32 ft_ok = (flags & Stmt_FallthroughAllowed) != 0;
|
||||
@@ -437,6 +438,44 @@ void check_proc_body(Checker *c, Token token, DeclInfo *decl, Type *type, AstNod
|
||||
check_scope_usage(c, c->context.scope);
|
||||
}
|
||||
|
||||
b32 are_signatures_similar_enough(Type *a_, Type *b_) {
|
||||
GB_ASSERT(a_->kind == Type_Proc);
|
||||
GB_ASSERT(b_->kind == Type_Proc);
|
||||
auto *a = &a_->Proc;
|
||||
auto *b = &b_->Proc;
|
||||
|
||||
if (a->param_count != b->param_count) {
|
||||
return false;
|
||||
}
|
||||
if (a->result_count != b->result_count) {
|
||||
return false;
|
||||
}
|
||||
for (isize i = 0; i < a->param_count; i++) {
|
||||
Type *x = get_base_type(a->params->Tuple.variables[i]->type);
|
||||
Type *y = get_base_type(b->params->Tuple.variables[i]->type);
|
||||
if (is_type_pointer(x) && is_type_pointer(y)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!are_types_identical(x, y)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (isize i = 0; i < a->result_count; i++) {
|
||||
Type *x = get_base_type(a->results->Tuple.variables[i]->type);
|
||||
Type *y = get_base_type(b->results->Tuple.variables[i]->type);
|
||||
if (is_type_pointer(x) && is_type_pointer(y)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!are_types_identical(x, y)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void check_proc_decl(Checker *c, Entity *e, DeclInfo *d, b32 check_body_later) {
|
||||
GB_ASSERT(e->type == NULL);
|
||||
|
||||
@@ -446,13 +485,6 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d, b32 check_body_later) {
|
||||
check_open_scope(c, pd->type);
|
||||
defer (check_close_scope(c));
|
||||
check_procedure_type(c, proc_type, pd->type);
|
||||
// add_proc_entity(c, d->scope, pd->name, e);
|
||||
if (d->scope->is_proc) {
|
||||
// Nested procedures
|
||||
add_entity(c, d->scope->parent, pd->name, e);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
b32 is_foreign = (pd->tags & ProcTag_foreign) != 0;
|
||||
@@ -460,8 +492,7 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d, b32 check_body_later) {
|
||||
b32 is_no_inline = (pd->tags & ProcTag_no_inline) != 0;
|
||||
|
||||
|
||||
|
||||
if (d->scope == c->global_scope &&
|
||||
if ((d->scope->is_file || d->scope->is_global) &&
|
||||
are_strings_equal(e->token.string, make_string("main"))) {
|
||||
if (proc_type != NULL) {
|
||||
auto *pt = &proc_type->Proc;
|
||||
@@ -511,7 +542,7 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d, b32 check_body_later) {
|
||||
TokenPos pos = f->token.pos;
|
||||
Type *this_type = get_base_type(e->type);
|
||||
Type *other_type = get_base_type(f->type);
|
||||
if (!are_types_identical(this_type, other_type)) {
|
||||
if (!are_signatures_similar_enough(this_type, other_type)) {
|
||||
error(&c->error_collector, ast_node_token(d->proc_decl),
|
||||
"Redeclaration of #foreign procedure `%.*s` with different type signatures\n"
|
||||
"\tat %.*s(%td:%td)",
|
||||
@@ -577,7 +608,10 @@ void check_entity_decl(Checker *c, Entity *e, DeclInfo *d, Type *named_type, Cyc
|
||||
}
|
||||
}
|
||||
|
||||
c->context.decl = d;
|
||||
// c->context.decl = d;
|
||||
// Scope *prev = c->context.scope;
|
||||
// c->context.scope = d->scope;
|
||||
// defer (c->context.scope = prev);
|
||||
|
||||
if (e->kind == Entity_Procedure) {
|
||||
check_proc_decl(c, e, d, true);
|
||||
@@ -759,6 +793,12 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
||||
default: {
|
||||
gbString expr_str = expr_to_string(operand.expr);
|
||||
defer (gb_string_free(expr_str));
|
||||
if (kind == Expr_Stmt) {
|
||||
return;
|
||||
}
|
||||
if (operand.expr->kind == AstNode_CallExpr) {
|
||||
return;
|
||||
}
|
||||
|
||||
error(&c->error_collector, ast_node_token(node), "Expression is not used: `%s`", expr_str);
|
||||
} break;
|
||||
|
||||
@@ -2535,6 +2535,23 @@ ssaAddr ssa_build_addr(ssaProcedure *proc, AstNode *expr) {
|
||||
}
|
||||
|
||||
Entity *e = entity_of_ident(proc->module->info, expr);
|
||||
|
||||
if (e->kind == Entity_Constant) {
|
||||
if (get_base_type(e->type) == t_string) {
|
||||
// HACK TODO(bill): This is lazy but it works
|
||||
String str = e->Constant.value.value_string;
|
||||
ssaValue *global_array = ssa_add_global_string_array(proc->module, str);
|
||||
ssaValue *elem = ssa_array_elem(proc, global_array);
|
||||
ssaValue *len = ssa_make_const_int(proc->module->allocator, str.len);
|
||||
ssaValue *v = ssa_add_local_generated(proc, e->type);
|
||||
ssaValue *str_elem = ssa_emit_struct_gep(proc, v, v_zero32, ssa_type(elem));
|
||||
ssaValue *str_len = ssa_emit_struct_gep(proc, v, v_one32, t_int);
|
||||
ssa_emit_store(proc, str_elem, elem);
|
||||
ssa_emit_store(proc, str_len, len);
|
||||
return ssa_make_addr(v, expr);
|
||||
}
|
||||
}
|
||||
|
||||
ssaValue *v = NULL;
|
||||
ssaValue **found = map_get(&proc->module->values, hash_pointer(e));
|
||||
if (found) {
|
||||
@@ -2555,20 +2572,35 @@ ssaAddr ssa_build_addr(ssaProcedure *proc, AstNode *expr) {
|
||||
|
||||
case_ast_node(se, SelectorExpr, expr);
|
||||
ssa_emit_comment(proc, make_string("SelectorExpr"));
|
||||
Type *type = get_base_type(type_of_expr(proc->module->info, se->expr));
|
||||
String selector = unparen_expr(se->selector)->Ident.string;
|
||||
Type *type = get_base_type(type_of_expr(proc->module->info, se->expr));
|
||||
|
||||
|
||||
if (type == t_invalid) {
|
||||
// Imports
|
||||
Entity *imp = entity_of_ident(proc->module->info, se->expr);
|
||||
GB_ASSERT(imp->kind == Entity_ImportName);
|
||||
// Entity *e = scope_lookup_entity(e->ImportName.scope, selector);
|
||||
if (imp != NULL) {
|
||||
GB_ASSERT(imp->kind == Entity_ImportName);
|
||||
}
|
||||
return ssa_build_addr(proc, unparen_expr(se->selector));
|
||||
} else {
|
||||
} /* else if (type == t_string) {
|
||||
Selection sel = lookup_field(type, selector, false);
|
||||
GB_ASSERT(sel.entity != NULL);
|
||||
|
||||
ssaValue *e = ssa_build_addr(proc, se->expr).addr;
|
||||
e = ssa_emit_deep_field_gep(proc, type, e, sel);
|
||||
return ssa_make_addr(e, expr);
|
||||
// NOTE(bill): This could a constant and the only non constant
|
||||
// selector is the `.data`, so build the expression instead
|
||||
ssaValue *e = ssa_build_expr(proc, se->expr);
|
||||
ssaValue *a = ssa_build_addr(proc, se->expr).addr;
|
||||
|
||||
a = ssa_emit_deep_field_gep(proc, type, a, sel);
|
||||
return ssa_make_addr(a, expr);
|
||||
} */else {
|
||||
Selection sel = lookup_field(type, selector, false);
|
||||
GB_ASSERT(sel.entity != NULL);
|
||||
|
||||
ssaValue *a = ssa_build_addr(proc, se->expr).addr;
|
||||
a = ssa_emit_deep_field_gep(proc, type, a, sel);
|
||||
return ssa_make_addr(a, expr);
|
||||
}
|
||||
case_end;
|
||||
|
||||
|
||||
@@ -128,10 +128,10 @@ int main(int argc, char **argv) {
|
||||
exit_code = win32_exec_command_line_app(
|
||||
// "../misc/llvm-bin/opt %s -o %.*s.bc "
|
||||
"opt %s -o %.*s.bc "
|
||||
// "-memcpyopt "
|
||||
// "-mem2reg "
|
||||
// "-die -dse "
|
||||
// "-dce "
|
||||
"-memcpyopt "
|
||||
"-mem2reg "
|
||||
"-die -dse "
|
||||
"-dce "
|
||||
// "-S "
|
||||
// "-debug-pass=Arguments "
|
||||
"",
|
||||
|
||||
@@ -45,6 +45,7 @@ struct AstFile {
|
||||
|
||||
struct ImportedFile {
|
||||
String path;
|
||||
String rel_path;
|
||||
TokenPos pos; // #import
|
||||
};
|
||||
|
||||
@@ -2736,7 +2737,7 @@ void destroy_parser(Parser *p) {
|
||||
}
|
||||
|
||||
// NOTE(bill): Returns true if it's added
|
||||
b32 try_add_import_path(Parser *p, String path, TokenPos pos) {
|
||||
b32 try_add_import_path(Parser *p, String path, String rel_path, TokenPos pos) {
|
||||
gb_for_array(i, p->imports) {
|
||||
String import = p->imports[i].path;
|
||||
if (are_strings_equal(import, path)) {
|
||||
@@ -2746,6 +2747,7 @@ b32 try_add_import_path(Parser *p, String path, TokenPos pos) {
|
||||
|
||||
ImportedFile item;
|
||||
item.path = path;
|
||||
item.rel_path = rel_path;
|
||||
item.pos = pos;
|
||||
gb_array_append(p->imports, item);
|
||||
return true;
|
||||
@@ -2807,8 +2809,10 @@ void parse_file(Parser *p, AstFile *f) {
|
||||
String filepath = f->tokenizer.fullpath;
|
||||
String base_dir = filepath;
|
||||
for (isize i = filepath.len-1; i >= 0; i--) {
|
||||
if (base_dir.text[i] == GB_PATH_SEPARATOR)
|
||||
if (base_dir.text[i] == '\\' ||
|
||||
base_dir.text[i] == '/') {
|
||||
break;
|
||||
}
|
||||
base_dir.len--;
|
||||
}
|
||||
|
||||
@@ -2843,7 +2847,7 @@ void parse_file(Parser *p, AstFile *f) {
|
||||
String import_file = make_string(path_str);
|
||||
|
||||
id->fullpath = import_file;
|
||||
if (!try_add_import_path(p, import_file, ast_node_token(node).pos)) {
|
||||
if (!try_add_import_path(p, import_file, file_str, ast_node_token(node).pos)) {
|
||||
// gb_free(gb_heap_allocator(), import_file.text);
|
||||
}
|
||||
} else if (node->kind == AstNode_ForeignSystemLibrary) {
|
||||
@@ -2866,15 +2870,40 @@ ParseFileError parse_files(Parser *p, char *init_filename) {
|
||||
char *fullpath_str = gb_path_get_full_name(gb_heap_allocator(), init_filename);
|
||||
String init_fullpath = make_string(fullpath_str);
|
||||
TokenPos init_pos = {};
|
||||
ImportedFile init_imported_file = {init_fullpath, init_pos};
|
||||
ImportedFile init_imported_file = {init_fullpath, init_fullpath, init_pos};
|
||||
gb_array_append(p->imports, init_imported_file);
|
||||
p->init_fullpath = init_fullpath;
|
||||
|
||||
// {
|
||||
// // IMPORTANT TODO(bill): Don't embed this, do it relative to the .exe
|
||||
// char *path = gb_path_get_full_name(gb_heap_allocator(), "W:/Odin/core/__runtime.odin");
|
||||
// String s = make_string(path);
|
||||
// ImportedFile runtime_file = {s, s, init_pos};
|
||||
// gb_array_append(p->imports, runtime_file);
|
||||
// }
|
||||
|
||||
gb_for_array(i, p->imports) {
|
||||
String import_path = p->imports[i].path;
|
||||
String import_rel_path = p->imports[i].rel_path;
|
||||
TokenPos pos = p->imports[i].pos;
|
||||
AstFile file = {};
|
||||
ParseFileError err = init_ast_file(&file, import_path);
|
||||
|
||||
// if (err == ParseFile_NotFound) {
|
||||
// // HACK(bill): Check core directory
|
||||
// char buf[300] = {};
|
||||
// char core[] = "W:/Odin/core/";
|
||||
// isize len = gb_size_of(core)-1;
|
||||
// gb_memcopy(buf, core, len);
|
||||
// gb_memcopy(buf+len, import_rel_path.text, import_rel_path.len);
|
||||
// char *path = gb_path_get_full_name(gb_heap_allocator(), buf);
|
||||
// gb_printf_err("%s\n", path);
|
||||
|
||||
// import_path = make_string(path);
|
||||
// err = init_ast_file(&file, import_path);
|
||||
// p->imports[i].path = import_path;
|
||||
// }
|
||||
|
||||
if (err != ParseFile_None) {
|
||||
if (pos.line != 0) {
|
||||
gb_printf_err("%.*s(%td:%td) ", LIT(pos.file), pos.line, pos.column);
|
||||
|
||||
Reference in New Issue
Block a user