From bd365e5176f3bc5f5e249d1a0763520e2973c2ec Mon Sep 17 00:00:00 2001 From: Ginger Bill Date: Wed, 14 Sep 2016 22:58:24 +0100 Subject: [PATCH] Fix namespacing issues for #import; allow using ImportName --- code/basic.odin | 4 - code/demo.odin | 8 +- code/game.odin | 74 ++--- code/math.odin | 54 ++-- code/opengl.odin | 82 +++--- code/print.odin | 584 ---------------------------------------- code/runtime.odin | 42 +-- code/win32.odin | 20 +- src/checker/checker.cpp | 16 +- src/checker/expr.cpp | 32 ++- src/checker/stmt.cpp | 59 ++-- src/parser.cpp | 9 +- 12 files changed, 223 insertions(+), 761 deletions(-) delete mode 100644 code/basic.odin delete mode 100644 code/print.odin diff --git a/code/basic.odin b/code/basic.odin deleted file mode 100644 index 696b42dbc..000000000 --- a/code/basic.odin +++ /dev/null @@ -1,4 +0,0 @@ -#load "runtime.odin" -#load "win32.odin" -#load "file.odin" -#load "print.odin" diff --git a/code/demo.odin b/code/demo.odin index 3d737a001..f40a8e625 100644 --- a/code/demo.odin +++ b/code/demo.odin @@ -1,10 +1,12 @@ -#import "print.odin" as _ +#import "fmt.odin" as fmt +#import "game.odin" as game test_proc :: proc() { - println("Hello?") + fmt.println("Hello?") } main :: proc() { - println("% % % %", "Hellope", true, 6.28, {4}int{1, 2, 3, 4}) + // fmt.println("% % % %", "Hellope", true, 6.28, {4}int{1, 2, 3, 4}) + game.run() } diff --git a/code/game.odin b/code/game.odin index 128639870..ef159f6e1 100644 --- a/code/game.odin +++ b/code/game.odin @@ -1,44 +1,47 @@ -#load "basic.odin" -#load "opengl.odin" -#load "math.odin" +#import "win32.odin" as win32 +#import "fmt.odin" as fmt +#import "opengl.odin" as gl +#import "math.odin" as math TWO_HEARTS :: #rune "💕" -win32_perf_count_freq := GetQueryPerformanceFrequency() +win32_perf_count_freq := win32.GetQueryPerformanceFrequency() time_now :: proc() -> f64 { assert(win32_perf_count_freq != 0) counter: i64 - _ = QueryPerformanceCounter(^counter) + _ = win32.QueryPerformanceCounter(^counter) result := counter as f64 / win32_perf_count_freq as f64 return result } win32_print_last_error :: proc() { - err_code := GetLastError() as int + err_code := win32.GetLastError() as int if err_code != 0 { - println("GetLastError:", err_code) + fmt.println("GetLastError: %", err_code) } } // Yuk! to_c_string :: proc(s: string) -> []u8 { - c_str := new_slice(u8, len(s)+1) + c_str := new_slice(u8, s.count+1) _ = copy(c_str, s as []byte) - c_str[len(s)] = 0 + c_str[s.count] = 0 return c_str } Window :: struct { width, height: int - wc: WNDCLASSEXA - dc: HDC - hwnd: HWND - opengl_context, rc: HGLRC + wc: win32.WNDCLASSEXA + dc: win32.HDC + hwnd: win32.HWND + opengl_context, rc: win32.HGLRC c_title: []u8 } -make_window :: proc(title: string, msg, height: int, window_proc: WNDPROC) -> (Window, bool) { +make_window :: proc(title: string, msg, height: int, window_proc: win32.WNDPROC) -> (Window, bool) { + using win32 + w: Window w.width, w.height = msg, height @@ -58,7 +61,7 @@ make_window :: proc(title: string, msg, height: int, window_proc: WNDPROC) -> (W }; if RegisterClassExA(^w.wc) == 0 { - win32_print_last_error( ) + win32_print_last_error() return w, false } @@ -112,15 +115,16 @@ make_window :: proc(title: string, msg, height: int, window_proc: WNDPROC) -> (W } destroy_window :: proc(w: ^Window) { - delete(w.c_title) + free(w.c_title.data) } display_window :: proc(w: ^Window) { - SwapBuffers(w.dc) + win32.SwapBuffers(w.dc) } -run_game :: proc() { +run :: proc() { + using win32 win32_proc :: proc(hwnd: HWND, msg: u32, wparam: WPARAM, lparam: LPARAM) -> LRESULT #no_inline { if msg == WM_DESTROY || msg == WM_CLOSE || msg == WM_QUIT { ExitProcess(0) @@ -140,7 +144,7 @@ run_game :: proc() { prev_time := time_now() running := true - pos := Vec2{100, 100} + pos := math.Vec2{100, 100} for running { curr_time := time_now() @@ -162,38 +166,38 @@ run_game :: proc() { { SPEED :: 500 - v: Vec2 + v: math.Vec2 if is_key_down(Key_Code.RIGHT) { v[0] += 1 } if is_key_down(Key_Code.LEFT) { v[0] -= 1 } if is_key_down(Key_Code.UP) { v[1] += 1 } if is_key_down(Key_Code.DOWN) { v[1] -= 1 } - v = vec2_norm0(v) + v = math.vec2_norm0(v) - pos += v * Vec2{SPEED * dt} + pos += v * math.Vec2{SPEED * dt} } - glClearColor(0.5, 0.7, 1.0, 1.0) - glClear(GL_COLOR_BUFFER_BIT) + gl.clear_color(0.5, 0.7, 1.0, 1.0) + gl.clear(gl.COLOR_BUFFER_BIT) - glLoadIdentity() - glOrtho(0, window.width as f64, - 0, window.height as f64, 0, 1) + gl.load_identity() + gl.ortho(0, window.width as f64, + 0, window.height as f64, 0, 1) draw_rect :: proc(x, y, w, h: f32) { - glBegin(GL_TRIANGLES) + gl.begin(gl.TRIANGLES) - glColor3f(1, 0, 0); glVertex3f(x, y, 0) - glColor3f(0, 1, 0); glVertex3f(x+w, y, 0) - glColor3f(0, 0, 1); glVertex3f(x+w, y+h, 0) + gl.color3f(1, 0, 0); gl.vertex3f(x, y, 0) + gl.color3f(0, 1, 0); gl.vertex3f(x+w, y, 0) + gl.color3f(0, 0, 1); gl.vertex3f(x+w, y+h, 0) - glColor3f(0, 0, 1); glVertex3f(x+w, y+h, 0) - glColor3f(1, 1, 0); glVertex3f(x, y+h, 0) - glColor3f(1, 0, 0); glVertex3f(x, y, 0) + gl.color3f(0, 0, 1); gl.vertex3f(x+w, y+h, 0) + gl.color3f(1, 1, 0); gl.vertex3f(x, y+h, 0) + gl.color3f(1, 0, 0); gl.vertex3f(x, y, 0) - glEnd() + gl.end() } draw_rect(pos[0], pos[1], 50, 50) diff --git a/code/math.odin b/code/math.odin index 3a6f4595d..d7539bcb4 100644 --- a/code/math.odin +++ b/code/math.odin @@ -1,24 +1,42 @@ -MATH_TAU :: 6.28318530717958647692528676655900576 -MATH_PI :: 3.14159265358979323846264338327950288 -MATH_ONE_OVER_TAU :: 0.636619772367581343075535053490057448 -MATH_ONE_OVER_PI :: 0.159154943091895335768883763372514362 +TAU :: 6.28318530717958647692528676655900576 +PI :: 3.14159265358979323846264338327950288 +ONE_OVER_TAU :: 0.636619772367581343075535053490057448 +ONE_OVER_PI :: 0.159154943091895335768883763372514362 -MATH_E :: 2.71828182845904523536 -MATH_SQRT_TWO :: 1.41421356237309504880168872420969808 -MATH_SQRT_THREE :: 1.73205080756887729352744634150587236 -MATH_SQRT_FIVE :: 2.23606797749978969640917366873127623 +E :: 2.71828182845904523536 +SQRT_TWO :: 1.41421356237309504880168872420969808 +SQRT_THREE :: 1.73205080756887729352744634150587236 +SQRT_FIVE :: 2.23606797749978969640917366873127623 -MATH_LOG_TWO :: 0.693147180559945309417232121458176568 -MATH_LOG_TEN :: 2.30258509299404568401799145468436421 +LOG_TWO :: 0.693147180559945309417232121458176568 +LOG_TEN :: 2.30258509299404568401799145468436421 -MATH_EPSILON :: 1.19209290e-7 +EPSILON :: 1.19209290e-7 -τ :: MATH_TAU -π :: MATH_PI +τ :: TAU +π :: PI -Vec2 :: type {2}f32 -Vec3 :: type {3}f32 -Vec4 :: type {4}f32 +// Vec2 :: type raw_union { +// using xy_: struct {x, y: f32} +// v: {2}f32 +// e: [2]f32 +// } +// Vec3 :: type raw_union { +// using xyz_: struct {x, y, z: f32} +// xy: Vec2 +// v: {3}f32 +// e: [3]f32 +// } +// Vec4 :: type raw_union { +// using xyzw_: struct {x, y, z, w: f32} +// xy: Vec2 +// xyz: Vec3 +// v: {4}f32 +// e: [4]f32 +// } +Vec2 :: type {2}f32 +Vec3 :: type {3}f32 +Vec4 :: type {4}f32 Mat2 :: type {4}f32 Mat3 :: type {9}f32 @@ -78,8 +96,8 @@ fmod :: proc(x, y: f32) -> f32 { } -to_radians :: proc(degrees: f32) -> f32 { return degrees * MATH_TAU / 360 } -to_degrees :: proc(radians: f32) -> f32 { return radians * 360 / MATH_TAU } +to_radians :: proc(degrees: f32) -> f32 { return degrees * TAU / 360 } +to_degrees :: proc(radians: f32) -> f32 { return radians * 360 / TAU } diff --git a/code/opengl.odin b/code/opengl.odin index ce540af8e..0028770fc 100644 --- a/code/opengl.odin +++ b/code/opengl.odin @@ -1,49 +1,49 @@ #foreign_system_library "opengl32" -GL_ZERO :: 0x0000 -GL_ONE :: 0x0001 -GL_TRIANGLES :: 0x0004 -GL_BLEND :: 0x0be2 -GL_SRC_ALPHA :: 0x0302 -GL_ONE_MINUS_SRC_ALPHA :: 0x0303 -GL_TEXTURE_2D :: 0x0de1 -GL_RGBA8 :: 0x8058 -GL_UNSIGNED_BYTE :: 0x1401 -GL_BGRA_EXT :: 0x80e1 -GL_TEXTURE_MAX_LEVEL :: 0x813d -GL_RGBA :: 0x1908 +ZERO :: 0x0000 +ONE :: 0x0001 +TRIANGLES :: 0x0004 +BLEND :: 0x0be2 +SRC_ALPHA :: 0x0302 +ONE_MINUS_SRC_ALPHA :: 0x0303 +TEXTURE_2D :: 0x0de1 +RGBA8 :: 0x8058 +UNSIGNED_BYTE :: 0x1401 +BGRA_EXT :: 0x80e1 +TEXTURE_MAX_LEVEL :: 0x813d +RGBA :: 0x1908 -GL_NEAREST :: 0x2600 -GL_LINEAR :: 0x2601 +NEAREST :: 0x2600 +LINEAR :: 0x2601 -GL_DEPTH_BUFFER_BIT :: 0x00000100 -GL_STENCIL_BUFFER_BIT :: 0x00000400 -GL_COLOR_BUFFER_BIT :: 0x00004000 +DEPTH_BUFFER_BIT :: 0x00000100 +STENCIL_BUFFER_BIT :: 0x00000400 +COLOR_BUFFER_BIT :: 0x00004000 -GL_TEXTURE_MAX_ANISOTROPY_EXT :: 0x84fe +TEXTURE_MAX_ANISOTROPY_EXT :: 0x84fe -GL_TEXTURE_MAG_FILTER :: 0x2800 -GL_TEXTURE_MIN_FILTER :: 0x2801 -GL_TEXTURE_WRAP_S :: 0x2802 -GL_TEXTURE_WRAP_T :: 0x2803 +TEXTURE_MAG_FILTER :: 0x2800 +TEXTURE_MIN_FILTER :: 0x2801 +TEXTURE_WRAP_S :: 0x2802 +TEXTURE_WRAP_T :: 0x2803 -glClear :: proc(mask: u32) #foreign -glClearColor :: proc(r, g, b, a: f32) #foreign -glBegin :: proc(mode: i32) #foreign -glEnd :: proc() #foreign -glColor3f :: proc(r, g, b: f32) #foreign -glColor4f :: proc(r, g, b, a: f32) #foreign -glVertex2f :: proc(x, y: f32) #foreign -glVertex3f :: proc(x, y, z: f32) #foreign -glTexCoord2f :: proc(u, v: f32) #foreign -glLoadIdentity :: proc() #foreign -glOrtho :: proc(left, right, bottom, top, near, far: f64) #foreign -glBlendFunc :: proc(sfactor, dfactor: i32) #foreign -glEnable :: proc(cap: i32) #foreign -glDisable :: proc(cap: i32) #foreign -glGenTextures :: proc(count: i32, result: ^u32) #foreign -glTexParameteri :: proc(target, pname, param: i32) #foreign -glTexParameterf :: proc(target: i32, pname: i32, param: f32) #foreign -glBindTexture :: proc(target: i32, texture: u32) #foreign -glTexImage2D :: proc(target, level, internal_format, width, height, border, format, _type: i32, pixels: rawptr) #foreign +clear :: proc(mask: u32) #foreign "glClear" +clear_color :: proc(r, g, b, a: f32) #foreign "glClearColor" +begin :: proc(mode: i32) #foreign "glBegin" +end :: proc() #foreign "glEnd" +color3f :: proc(r, g, b: f32) #foreign "glColor3f" +color4f :: proc(r, g, b, a: f32) #foreign "glColor4f" +vertex2f :: proc(x, y: f32) #foreign "glVertex2f" +vertex3f :: proc(x, y, z: f32) #foreign "glVertex3f" +tex_coord2f :: proc(u, v: f32) #foreign "glTexCoord2f" +load_identity :: proc() #foreign "glLoadIdentity" +ortho :: proc(left, right, bottom, top, near, far: f64) #foreign "glOrtho" +blend_func :: proc(sfactor, dfactor: i32) #foreign "glBlendFunc" +enable :: proc(cap: i32) #foreign "glEnable" +disable :: proc(cap: i32) #foreign "glDisable" +gen_textures :: proc(count: i32, result: ^u32) #foreign "glGenTextures" +tex_parameteri :: proc(target, pname, param: i32) #foreign "glTexParameteri" +tex_parameterf :: proc(target: i32, pname: i32, param: f32) #foreign "glTexParameterf" +bind_texture :: proc(target: i32, texture: u32) #foreign "glBindTexture" +tex_image2d :: proc(target, level, internal_format, width, height, border, format, _type: i32, pixels: rawptr) #foreign "glTexImage2D" diff --git a/code/print.odin b/code/print.odin deleted file mode 100644 index b8f326151..000000000 --- a/code/print.odin +++ /dev/null @@ -1,584 +0,0 @@ -#import "runtime.odin" as _ -#import "os.odin" as os - -print_byte_buffer :: proc(buf: ^[]byte, b: []byte) { - if buf.count < buf.capacity { - n := min(buf.capacity-buf.count, b.count) - if n > 0 { - offset := ptr_offset(buf.data, buf.count) - memory_copy(offset, ^b[0], n) - buf.count += n - } - } -} - -print_string_to_buffer :: proc(buf: ^[]byte, s: string) { - print_byte_buffer(buf, s as []byte) -} - - -byte_reverse :: proc(b: []byte) { - n := b.count - for i := 0; i < n/2; i++ { - b[i], b[n-1-i] = b[n-1-i], b[i] - } -} - -encode_rune :: proc(r: rune) -> ([4]byte, int) { - buf: [4]byte - i := r as u32 - mask: byte : 0x3f - if i <= 1<<7-1 { - buf[0] = r as byte - return buf, 1 - } - if i <= 1<<11-1 { - buf[0] = 0xc0 | (r>>6) as byte - buf[1] = 0x80 | (r) as byte & mask - return buf, 2 - } - - // Invalid or Surrogate range - if i > 0x0010ffff || - (i >= 0xd800 && i <= 0xdfff) { - r = 0xfffd - } - - if i <= 1<<16-1 { - buf[0] = 0xe0 | (r>>12) as byte - buf[1] = 0x80 | (r>>6) as byte & mask - buf[2] = 0x80 | (r) as byte & mask - return buf, 3 - } - - buf[0] = 0xf0 | (r>>18) as byte - buf[1] = 0x80 | (r>>12) as byte & mask - buf[2] = 0x80 | (r>>6) as byte & mask - buf[3] = 0x80 | (r) as byte & mask - return buf, 4 -} - -print_rune_to_buffer :: proc(buf: ^[]byte, r: rune) { - b, n := encode_rune(r) - print_string_to_buffer(buf, b[:n] as string) -} - -print_space_to_buffer :: proc(buf: ^[]byte) { print_rune_to_buffer(buf, #rune " ") } -print_nl_to_buffer :: proc(buf: ^[]byte) { print_rune_to_buffer(buf, #rune "\n") } - -print_int_to_buffer :: proc(buf: ^[]byte, i: int) { - print_int_base_to_buffer(buf, i, 10); -} -PRINT__NUM_TO_CHAR_TABLE :: "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz@$" -print_int_base_to_buffer :: proc(buffer: ^[]byte, i, base: int) { - - buf: [65]byte - len := 0 - negative := false - if i < 0 { - negative = true - i = -i - } - if i == 0 { - buf[len] = #rune "0" - len++ - } - for i > 0 { - buf[len] = PRINT__NUM_TO_CHAR_TABLE[i % base] - len++ - i /= base - } - - if negative { - buf[len] = #rune "-" - len++ - } - - byte_reverse(buf[:len]) - print_string_to_buffer(buffer, buf[:len] as string) -} - -print_uint_to_buffer :: proc(buffer: ^[]byte, i: uint) { - print_uint_base_to_buffer(buffer, i, 10, 0, #rune " ") -} -print_uint_base_to_buffer :: proc(buffer: ^[]byte, i, base: uint, min_width: int, pad_char: byte) { - buf: [65]byte - len := 0 - if i == 0 { - buf[len] = #rune "0" - len++ - } - for i > 0 { - buf[len] = PRINT__NUM_TO_CHAR_TABLE[i % base] - len++ - i /= base - } - for len < min_width { - buf[len] = pad_char - len++ - } - - byte_reverse(buf[:len]) - print_string_to_buffer(buffer, buf[:len] as string) -} - -print_bool_to_buffer :: proc(buffer: ^[]byte, b : bool) { - if b { print_string_to_buffer(buffer, "true") } - else { print_string_to_buffer(buffer, "false") } -} - -print_pointer_to_buffer :: proc(buffer: ^[]byte, p: rawptr) #inline { print_uint_base_to_buffer(buffer, p as uint, 16, 0, #rune " ") } - -print_f32_to_buffer :: proc(buffer: ^[]byte, f: f32) #inline { print__f64(buffer, f as f64, 7) } -print_f64_to_buffer :: proc(buffer: ^[]byte, f: f64) #inline { print__f64(buffer, f, 10) } - -print__f64 :: proc(buffer: ^[]byte, f: f64, decimal_places: int) { - if f == 0 { - print_rune_to_buffer(buffer, #rune "0") - return - } - if f < 0 { - print_rune_to_buffer(buffer, #rune "-") - f = -f - } - - print_u64_to_buffer :: proc(buffer: ^[]byte, i: u64) { - buf: [22]byte - len := 0 - if i == 0 { - buf[len] = #rune "0" - len++ - } - for i > 0 { - buf[len] = PRINT__NUM_TO_CHAR_TABLE[i % 10] - len++ - i /= 10 - } - byte_reverse(buf[:len]) - print_string_to_buffer(buffer, buf[:len] as string) - } - - i := f as u64 - print_u64_to_buffer(buffer, i) - f -= i as f64 - - print_rune_to_buffer(buffer, #rune ".") - - mult := 10.0 - for decimal_places := 6; decimal_places >= 0; decimal_places-- { - i = (f * mult) as u64 - print_u64_to_buffer(buffer, i as u64) - f -= i as f64 / mult - mult *= 10 - } -} - -print_type_to_buffer :: proc(buf: ^[]byte, ti: ^Type_Info) { - if ti == null { return } - - using Type_Info - match type info : ti { - case Named: - print_string_to_buffer(buf, info.name) - case Integer: - match { - case ti == type_info(int): - print_string_to_buffer(buf, "int") - case ti == type_info(uint): - print_string_to_buffer(buf, "uint") - default: - if info.signed { - print_string_to_buffer(buf, "i") - } else { - print_string_to_buffer(buf, "u") - } - print_int_to_buffer(buf, 8*info.size) - } - - case Float: - match info.size { - case 4: print_string_to_buffer(buf, "f32") - case 8: print_string_to_buffer(buf, "f64") - } - case String: print_string_to_buffer(buf, "string") - case Boolean: print_string_to_buffer(buf, "bool") - case Pointer: - print_string_to_buffer(buf, "^") - print_type_to_buffer(buf, info.elem) - case Procedure: - print_string_to_buffer(buf, "proc") - if info.params == null { - print_string_to_buffer(buf, "()") - } else { - count := (info.params as ^Tuple).fields.count - if count == 1 { print_string_to_buffer(buf, "(") } - print_type_to_buffer(buf, info.params) - if count == 1 { print_string_to_buffer(buf, ")") } - } - if info.results != null { - print_string_to_buffer(buf, " -> ") - print_type_to_buffer(buf, info.results) - } - case Tuple: - count := info.fields.count - if count != 1 { print_string_to_buffer(buf, "(") } - for i := 0; i < count; i++ { - if i > 0 { print_string_to_buffer(buf, ", ") } - - f := info.fields[i] - - if f.name.count > 0 { - print_string_to_buffer(buf, f.name) - print_string_to_buffer(buf, ": ") - } - print_type_to_buffer(buf, f.type_info) - } - if count != 1 { print_string_to_buffer(buf, ")") } - - case Array: - print_string_to_buffer(buf, "[") - print_int_to_buffer(buf, info.count) - print_string_to_buffer(buf, "]") - print_type_to_buffer(buf, info.elem) - case Slice: - print_string_to_buffer(buf, "[") - print_string_to_buffer(buf, "]") - print_type_to_buffer(buf, info.elem) - case Vector: - print_string_to_buffer(buf, "{") - print_int_to_buffer(buf, info.count) - print_string_to_buffer(buf, "}") - print_type_to_buffer(buf, info.elem) - - case Struct: - print_string_to_buffer(buf, "struct ") - if info.packed { print_string_to_buffer(buf, "#packed ") } - if info.ordered { print_string_to_buffer(buf, "#ordered ") } - print_string_to_buffer(buf, "{") - for i := 0; i < info.fields.count; i++ { - if i > 0 { - print_string_to_buffer(buf, ", ") - } - print_any_to_buffer(buf, info.fields[i].name) - print_string_to_buffer(buf, ": ") - print_type_to_buffer(buf, info.fields[i].type_info) - } - print_string_to_buffer(buf, "}") - - case Union: - print_string_to_buffer(buf, "union {") - for i := 0; i < info.fields.count; i++ { - if i > 0 { - print_string_to_buffer(buf, ", ") - } - print_any_to_buffer(buf, info.fields[i].name) - print_string_to_buffer(buf, ": ") - print_type_to_buffer(buf, info.fields[i].type_info) - } - print_string_to_buffer(buf, "}") - - case Raw_Union: - print_string_to_buffer(buf, "raw_union {") - for i := 0; i < info.fields.count; i++ { - if i > 0 { - print_string_to_buffer(buf, ", ") - } - print_any_to_buffer(buf, info.fields[i].name) - print_string_to_buffer(buf, ": ") - print_type_to_buffer(buf, info.fields[i].type_info) - } - print_string_to_buffer(buf, "}") - - case Enum: - print_string_to_buffer(buf, "enum ") - print_type_to_buffer(buf, info.base) - print_string_to_buffer(buf, "{}") - } -} - - -print_any_to_buffer :: proc(buf: ^[]byte, arg: any) { - using Type_Info - match type info : arg.type_info { - case Named: - a: any - a.type_info = info.base - a.data = arg.data - match type b : info.base { - case Struct: - print_string_to_buffer(buf, info.name) - print_string_to_buffer(buf, "{") - for i := 0; i < b.fields.count; i++ { - f := b.fields[i]; - if i > 0 { - print_string_to_buffer(buf, ", ") - } - print_any_to_buffer(buf, f.name) - print_string_to_buffer(buf, " = ") - v: any - v.type_info = f.type_info - v.data = ptr_offset(arg.data as ^byte, f.offset) - print_any_to_buffer(buf, v) - } - print_string_to_buffer(buf, "}") - - default: - print_any_to_buffer(buf, a) - } - - case Integer: - if info.signed { - i: int = 0; - if arg.data != null { - match info.size { - case 1: i = (arg.data as ^i8)^ as int - case 2: i = (arg.data as ^i16)^ as int - case 4: i = (arg.data as ^i32)^ as int - case 8: i = (arg.data as ^i64)^ as int - case 16: i = (arg.data as ^i128)^ as int - } - } - print_int_to_buffer(buf, i) - } else { - i: uint = 0; - if arg.data != null { - match info.size { - case 1: i = (arg.data as ^u8)^ as uint - case 2: i = (arg.data as ^u16)^ as uint - case 4: i = (arg.data as ^u32)^ as uint - case 8: i = (arg.data as ^u64)^ as uint - case 16: i = (arg.data as ^u128)^ as uint - } - } - print_uint_to_buffer(buf, i) - } - - case Float: - f: f64 = 0 - if arg.data != null { - match info.size { - case 4: f = (arg.data as ^f32)^ as f64 - case 8: f = (arg.data as ^f64)^ as f64 - } - } - print_f64_to_buffer(buf, f) - - case String: - s := "" - if arg.data != null { - s = (arg.data as ^string)^ - } - print_string_to_buffer(buf, s) - - case Boolean: - v := false; - if arg.data != null { - v = (arg.data as ^bool)^ - } - print_bool_to_buffer(buf, v) - - case Pointer: - v := null; - if arg.data != null { - v = (arg.data as ^rawptr)^ - } - print_pointer_to_buffer(buf, v) - - case Enum: - v: any - v.data = arg.data - v.type_info = info.base - print_any_to_buffer(buf, v) - - - case Array: - print_string_to_buffer(buf, "[") - defer print_string_to_buffer(buf, "]") - - for i := 0; i < info.count; i++ { - if i > 0 { - print_string_to_buffer(buf, ", ") - } - - elem: any - elem.data = (arg.data as int + i*info.elem_size) as rawptr - elem.type_info = info.elem - print_any_to_buffer(buf, elem) - } - - case Slice: - slice := arg.data as ^[]byte - print_string_to_buffer(buf, "[") - defer print_string_to_buffer(buf, "]") - - for i := 0; i < slice.count; i++ { - if i > 0 { - print_string_to_buffer(buf, ", ") - } - - elem: any - elem.data = ptr_offset(slice.data, i*info.elem_size) - elem.type_info = info.elem - print_any_to_buffer(buf, elem) - } - - case Vector: - print_string_to_buffer(buf, "<") - defer print_string_to_buffer(buf, ">") - - for i := 0; i < info.count; i++ { - if i > 0 { - print_string_to_buffer(buf, ", ") - } - - elem: any - elem.data = ptr_offset(arg.data as ^byte, i*info.elem_size) - elem.type_info = info.elem - print_any_to_buffer(buf, elem) - } - - - case Struct: - print_string_to_buffer(buf, "struct") - print_string_to_buffer(buf, "{") - defer print_string_to_buffer(buf, "}") - - for i := 0; i < info.fields.count; i++ { - if i > 0 { - print_string_to_buffer(buf, ", ") - } - print_any_to_buffer(buf, info.fields[i].name) - print_string_to_buffer(buf, " = ") - a: any - a.data = ptr_offset(arg.data as ^byte, info.fields[i].offset) - a.type_info = info.fields[i].type_info - print_any_to_buffer(buf, a) - } - - case Union: - print_string_to_buffer(buf, "(union)") - case Raw_Union: - print_string_to_buffer(buf, "(raw_union)") - case Procedure: - print_type_to_buffer(buf, arg.type_info) - print_string_to_buffer(buf, " @ 0x") - print_pointer_to_buffer(buf, (arg.data as ^rawptr)^) - - default: - } -} - -type_info_is_string :: proc(info: ^Type_Info) -> bool { - using Type_Info - if info == null { - return false - } - - for { - match type i : info { - case Named: - info = i.base - continue - case String: - return true - default: - return false - } - } - return false -} - - -print_to_buffer :: proc(buf: ^[]byte, fmt: string, args: ..any) { - is_digit :: proc(r: rune) -> bool #inline { - return r >= #rune "0" && r <= #rune "9" - } - - parse_int :: proc(s: string, offset: int) -> (int, int) { - result := 0 - - for ; offset < s.count; offset++ { - c := s[offset] as rune - if !is_digit(c) { - break - } - - result *= 10 - result += (c - #rune "0") as int - } - - return result, offset - } - - prev := 0 - implicit_index := 0 - - for i := 0; i < fmt.count; i++ { - r := fmt[i] as rune - index := implicit_index - - if r != #rune "%" { - continue - } - - print_string_to_buffer(buf, fmt[prev:i]) - i++ // Skip % - if i < fmt.count { - next := fmt[i] as rune - - if next == #rune "%" { - print_string_to_buffer(buf, "%") - i++ - prev = i - continue - } - - if is_digit(next) { - index, i = parse_int(fmt, i) - } - } - - if 0 <= index && index < args.count { - print_any_to_buffer(buf, args[index]) - implicit_index = index+1 - } else { - // TODO(bill): Error check index out bounds - print_string_to_buffer(buf, "") - } - - prev = i - } - - print_string_to_buffer(buf, fmt[prev:]) -} - -PRINT_BUF_SIZE :: 1<<12 - -print_to_file :: proc(f: ^os.File, fmt: string, args: ..any) { - data: [PRINT_BUF_SIZE]byte - buf := data[:0] - print_to_buffer(^buf, fmt, ..args) - os.write(f, buf) -} - -println_to_file :: proc(f: ^os.File, fmt: string, args: ..any) { - data: [PRINT_BUF_SIZE]byte - buf := data[:0] - print_to_buffer(^buf, fmt, ..args) - print_nl_to_buffer(^buf) - os.write(f, buf) -} - - -print :: proc(fmt: string, args: ..any) { - print_to_file(os.file_get_standard(os.File_Standard.OUTPUT), fmt, ..args) -} -print_err :: proc(fmt: string, args: ..any) { - print_to_file(os.file_get_standard(os.File_Standard.ERROR), fmt, ..args) -} -println :: proc(fmt: string, args: ..any) { - println_to_file(os.file_get_standard(os.File_Standard.OUTPUT), fmt, ..args) -} -println_err :: proc(fmt: string, args: ..any) { - println_to_file(os.file_get_standard(os.File_Standard.ERROR), fmt, ..args) -} diff --git a/code/runtime.odin b/code/runtime.odin index 2c3a8ca43..4a440dc89 100644 --- a/code/runtime.odin +++ b/code/runtime.odin @@ -1,9 +1,9 @@ -#global_scope +#shared_global_scope -// TODO(bill): Remove #import in runtime.odin +// 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 "print.odin" as _ +#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 @@ -14,8 +14,8 @@ Type_Info :: union { offset: int // offsets are not used in tuples } Record :: struct #ordered { - fields: []Member - packed: bool + fields: []Member + packed: bool ordered: bool } @@ -25,7 +25,7 @@ Type_Info :: union { base: ^Type_Info } Integer: struct #ordered { - size: int // in bytes + size: int // in bytes signed: bool } Float: struct #ordered { @@ -37,23 +37,23 @@ Type_Info :: union { elem: ^Type_Info } Procedure: struct #ordered { - params: ^Type_Info // Type_Info.Tuple - results: ^Type_Info // Type_Info.Tuple + params: ^Type_Info // Type_Info.Tuple + results: ^Type_Info // Type_Info.Tuple variadic: bool } Array: struct #ordered { - elem: ^Type_Info + elem: ^Type_Info elem_size: int - count: int + count: int } Slice: struct #ordered { - elem: ^Type_Info + elem: ^Type_Info elem_size: int } Vector: struct #ordered { - elem: ^Type_Info + elem: ^Type_Info elem_size: int - count: int + count: int } Tuple: Record Struct: Record @@ -171,7 +171,7 @@ __string_ge :: proc(a, b : string) -> bool #inline { return __string_cmp(a, b) > __assert :: proc(msg: string) { - os.write(os.file_get_standard(os.File_Standard.ERROR), msg as []byte) + os.write(os.get_standard_file(os.File_Standard.ERROR), msg as []byte) __debug_trap() } @@ -181,8 +181,8 @@ __bounds_check_error :: proc(file: string, line, column: int, return } // TODO(bill): Probably reduce the need for `print` in the runtime if possible - 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 +191,8 @@ __slice_expr_error :: proc(file: string, line, column: int, if 0 <= low && low <= high && high <= max { return } - println_err("%(%:%) Invalid slice indices: [%:%:%]", - file, line, column, low, high, max) + 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 +200,8 @@ __substring_expr_error :: proc(file: string, line, column: int, if 0 <= low && low <= high { return } - println_err("%(%:%) Invalid substring indices: [%:%:%]", - file, line, column, low, high) + fmt.println_err("%(%:%) Invalid substring indices: [%:%:%]", + file, line, column, low, high) __debug_trap() } diff --git a/code/win32.odin b/code/win32.odin index 794812054..aa80e4002 100644 --- a/code/win32.odin +++ b/code/win32.odin @@ -1,12 +1,6 @@ #foreign_system_library "user32" #foreign_system_library "gdi32" - -test_proc :: proc() { - x := "Goodbye?" -} - - HANDLE :: type rawptr HWND :: type HANDLE HDC :: type HANDLE @@ -70,10 +64,10 @@ MSG :: struct #ordered { -GetLastError :: proc() -> i32 #foreign -ExitProcess :: proc(exit_code: u32) #foreign -GetDesktopWindow :: proc() -> HWND #foreign -GetCursorPos :: proc(p: ^POINT) -> i32 #foreign +GetLastError :: proc() -> i32 #foreign +ExitProcess :: proc(exit_code: u32) #foreign +GetDesktopWindow :: proc() -> HWND #foreign +GetCursorPos :: proc(p: ^POINT) -> i32 #foreign ScreenToClient :: proc(h: HWND, p: ^POINT) -> i32 #foreign GetModuleHandleA :: proc(module_name: ^u8) -> HINSTANCE #foreign @@ -99,11 +93,11 @@ CreateWindowExA :: proc(ex_style: u32, param: rawptr) -> HWND #foreign ShowWindow :: proc(hwnd: HWND, cmd_show: i32) -> BOOL #foreign -UpdateWindow :: proc(hwnd: HWND) -> BOOL #foreign +TranslateMessage :: proc(msg: ^MSG) -> BOOL #foreign +DispatchMessageA :: proc(msg: ^MSG) -> LRESULT #foreign +UpdateWindow :: proc(hwnd: HWND) -> BOOL #foreign PeekMessageA :: proc(msg: ^MSG, hwnd: HWND, msg_filter_min, msg_filter_max, remove_msg: u32) -> BOOL #foreign -TranslateMessage :: proc(msg: ^MSG) -> BOOL #foreign -DispatchMessageA :: proc(msg: ^MSG) -> LRESULT #foreign DefWindowProcA :: proc(hwnd: HWND, msg: u32, wparam: WPARAM, lparam: LPARAM) -> LRESULT #foreign diff --git a/src/checker/checker.cpp b/src/checker/checker.cpp index 6de9858eb..c95403e3c 100644 --- a/src/checker/checker.cpp +++ b/src/checker/checker.cpp @@ -118,6 +118,7 @@ struct Scope { b32 is_global; b32 is_file; b32 is_init; + AstFile *file; }; enum ExprKind { @@ -635,6 +636,10 @@ void add_entity_use(CheckerInfo *i, AstNode *identifier, Entity *entity) { GB_ASSERT(identifier->kind == AstNode_Ident); HashKey key = hash_pointer(identifier); map_set(&i->uses, key, entity); + + if (entity != NULL && entity->kind == Entity_ImportName) { + entity->ImportName.used = true; + } } @@ -820,8 +825,10 @@ void check_parsed_files(Checker *c) { scope = make_scope(c->global_scope, c->allocator); scope->is_global = f->is_global_scope; scope->is_file = true; + scope->file = f; if (i == 0) { // NOTE(bill): First file is always the initial file + // thus it must contain main scope->is_init = true; } @@ -830,7 +837,8 @@ void check_parsed_files(Checker *c) { } f->scope = scope; - map_set(&file_scopes, hash_string(f->tokenizer.fullpath), scope); + HashKey key = hash_string(f->tokenizer.fullpath); + map_set(&file_scopes, key, scope); } // Collect Entities @@ -980,6 +988,7 @@ void check_parsed_files(Checker *c) { } } } else { + GB_ASSERT(id->import_name.string.len > 0); Entity *e = make_entity_import_name(c->allocator, file_scope, id->import_name, t_invalid, id->fullpath, id->import_name.string, scope); @@ -995,10 +1004,11 @@ void check_parsed_files(Checker *c) { if (e->kind == kind) { DeclInfo *d = entry->value; + add_curr_ast_file(c, d->scope->file); + Scope *prev_scope = c->context.scope; c->context.scope = d->scope; - defer (c->context.scope = prev_scope); - + GB_ASSERT(d->scope == e->scope); check_entity_decl(c, e, d, NULL); } } diff --git a/src/checker/expr.cpp b/src/checker/expr.cpp index 0d113af23..982c28942 100644 --- a/src/checker/expr.cpp +++ b/src/checker/expr.cpp @@ -287,7 +287,6 @@ void check_fields(Checker *c, AstNode *node, AstNodeArray decls, Entity *e = make_entity_type_name(c->allocator, c->context.scope, name_token, NULL); add_entity(c, c->context.scope, td->name, e); - gb_printf("%.*s\n", LIT(e->token.string)); check_type_decl(c, e, td->type, NULL, NULL); HashKey key = hash_string(name_token.string); @@ -734,8 +733,25 @@ void check_identifier(Checker *c, Operand *o, AstNode *n, Type *named_type, Cycl if (are_strings_equal(n->Ident.string, make_string("_"))) { error(&c->error_collector, n->Ident, "`_` cannot be used as a value type"); } else { + auto *entries = c->context.scope->elements.entries; + // gb_for_array(i, entries) { + // Entity *elem = entries[i].value; + // if (i > 0) { + // gb_printf(", "); + // } + // gb_printf("%.*s", LIT(elem->token.string)); + // } + // for (Scope *s = c->context.scope; s != NULL; s = s->parent) { + // Entity *elem = s->elements.entries[0].value; + // if (elem == NULL) continue; + // gb_printf("%.*s\n", LIT(elem->token.pos.file)); + // } + // gb_printf("\n"); + + + // Entity *e = scope_lookup_entity(c->context.scope, n->Ident.string); error(&c->error_collector, n->Ident, - "Undeclared named: `%.*s`", LIT(n->Ident.string)); + "Undeclared name: %.*s", LIT(n->Ident.string)); } return; } @@ -915,11 +931,9 @@ Type *check_type(Checker *c, AstNode *e, Type *named_type, CycleChecker *cycle_c type = make_type_array(c->allocator, check_type(c, at->elem, NULL, cycle_checker), check_array_count(c, at->count)); - type->flags |= e->type_flags; set_base_type(named_type, type); } else { type = make_type_slice(c->allocator, check_type(c, at->elem)); - type->flags |= e->type_flags; set_base_type(named_type, type); } goto end; @@ -935,7 +949,6 @@ Type *check_type(Checker *c, AstNode *e, Type *named_type, CycleChecker *cycle_c error(&c->error_collector, ast_node_token(vt->elem), "Vector element type must be numerical or a boolean. Got `%s`", err_str); } type = make_type_vector(c->allocator, elem, count); - type->flags |= e->type_flags; set_base_type(named_type, type); goto end; case_end; @@ -947,7 +960,6 @@ Type *check_type(Checker *c, AstNode *e, Type *named_type, CycleChecker *cycle_c check_struct_type(c, type, e, cycle_checker); check_close_scope(c); type->Record.node = e; - type->flags |= e->type_flags; goto end; case_end; @@ -958,7 +970,6 @@ Type *check_type(Checker *c, AstNode *e, Type *named_type, CycleChecker *cycle_c check_union_type(c, type, e, cycle_checker); check_close_scope(c); type->Record.node = e; - type->flags |= e->type_flags; goto end; case_end; @@ -969,7 +980,6 @@ Type *check_type(Checker *c, AstNode *e, Type *named_type, CycleChecker *cycle_c check_raw_union_type(c, type, e, cycle_checker); check_close_scope(c); type->Record.node = e; - type->flags |= e->type_flags; goto end; case_end; @@ -978,22 +988,21 @@ Type *check_type(Checker *c, AstNode *e, Type *named_type, CycleChecker *cycle_c set_base_type(named_type, type); check_enum_type(c, type, named_type, e); type->Record.node = e; - type->flags |= e->type_flags; goto end; case_end; case_ast_node(pt, PointerType, e); type = make_type_pointer(c->allocator, check_type(c, pt->type)); - type->flags |= e->type_flags; set_base_type(named_type, type); goto end; case_end; case_ast_node(pt, ProcType, e); type = alloc_type(c->allocator, Type_Proc); - type->flags |= e->type_flags; set_base_type(named_type, type); + check_open_scope(c, e); check_procedure_type(c, type, e); + check_close_scope(c); goto end; case_end; @@ -1003,7 +1012,6 @@ Type *check_type(Checker *c, AstNode *e, Type *named_type, CycleChecker *cycle_c check_expr_or_type(c, &o, e); if (o.mode == Addressing_Type) { type = o.type; - type->flags |= e->type_flags; goto end; } } diff --git a/src/checker/stmt.cpp b/src/checker/stmt.cpp index d97b68d14..aedf4eec9 100644 --- a/src/checker/stmt.cpp +++ b/src/checker/stmt.cpp @@ -446,7 +446,7 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d, b32 check_body_later) { // add_proc_entity(c, d->scope, pd->name, e); if (d->scope->is_proc) { // Nested procedures - add_entity(c, d->scope, pd->name, e); + add_entity(c, d->scope->parent, pd->name, e); } @@ -562,11 +562,7 @@ void check_var_decl(Checker *c, Entity *e, Entity **entities, isize entity_count void check_entity_decl(Checker *c, Entity *e, DeclInfo *d, Type *named_type, CycleChecker *cycle_checker) { if (e->type != NULL) { - if (e->type->kind == Type_Named && e->type->Named.base == NULL) { - // NOTE(bill): Some weird declaration error from Entity_ImportName - } else { - return; - } + return; } if (d == NULL) { @@ -578,26 +574,42 @@ void check_entity_decl(Checker *c, Entity *e, DeclInfo *d, Type *named_type, Cyc } } + c->context.decl = d; + + if (e->kind == Entity_Procedure) { + check_proc_decl(c, e, d, true); + return; + } + + + switch (e->kind) { case Entity_Constant: { Scope *prev = c->context.scope; c->context.scope = d->scope; - c->context.decl = d; + defer (c->context.scope = prev); check_const_decl(c, e, d->type_expr, d->init_expr); - - c->context.scope = prev; } break; + case Entity_Variable: { Scope *prev = c->context.scope; c->context.scope = d->scope; - c->context.decl = d; + defer (c->context.scope = prev); check_var_decl(c, e, d->entities, d->entity_count, d->type_expr, d->init_expr); - - c->context.scope = prev; } break; + + case Entity_Procedure: { + check_proc_decl(c, e, d, true); + } break; + + case Entity_TypeName: { + Scope *prev = c->context.scope; + c->context.scope = d->scope; + defer (c->context.scope = prev); + CycleChecker local_cycle_checker = {}; if (cycle_checker == NULL) { cycle_checker = &local_cycle_checker; @@ -608,11 +620,7 @@ void check_entity_decl(Checker *c, Entity *e, DeclInfo *d, Type *named_type, Cyc gb_array_free(local_cycle_checker.path); } } break; - case Entity_Procedure: - check_proc_decl(c, e, d, true); - break; } - } @@ -1309,7 +1317,14 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) { Entity *decl = scope->elements.entries[i].value; Entity *found = scope_insert_entity(c->context.scope, decl); if (found != NULL) { - error(&c->error_collector, us->token, "Namespace collision while `using` `%s` of: %.*s", expr_str, LIT(found->token.string)); + error(&c->error_collector, us->token, + "Namespace collision while `using` `%s` of: %.*s\n" + "\tat %.*s(%td:%td)\n" + "\tat %.*s(%td:%td)", + expr_str, LIT(found->token.string), + LIT(found->token.pos.file), found->token.pos.line, found->token.pos.column, + LIT(decl->token.pos.file), decl->token.pos.line, decl->token.pos.column + ); return; } } @@ -1406,13 +1421,11 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) { case_ast_node(pd, ProcDecl, node); ast_node(name, Ident, pd->name); Entity *e = make_entity_procedure(c->allocator, c->context.scope, *name, NULL); - // add_proc_entity(c, c->context.scope, pd->name, e); + add_entity(c, c->context.scope, pd->name, e); - DeclInfo decl = {}; - init_declaration_info(&decl, e->scope); - decl.proc_decl = node; - check_proc_decl(c, e, &decl, false); - destroy_declaration_info(&decl); + DeclInfo *decl = make_declaration_info(c->allocator, e->scope); + decl->proc_decl = node; + check_proc_decl(c, e, decl, false); case_end; case_ast_node(td, TypeDecl, node); diff --git a/src/parser.cpp b/src/parser.cpp index 57f5f8eff..c13fc774c 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -2539,18 +2539,19 @@ AstNode *parse_stmt(AstFile *f) { case Token_Hash: { s = parse_tag_stmt(f, NULL); String tag = s->TagStmt.name.string; - if (are_strings_equal(tag, make_string("global_scope"))) { + if (are_strings_equal(tag, make_string("shared_global_scope"))) { if (f->curr_proc == NULL) { f->is_global_scope = true; return make_empty_stmt(f, f->cursor[0]); } - ast_file_err(f, token, "You cannot use #global_scope within a procedure. This must be done at the file scope."); + ast_file_err(f, token, "You cannot use #shared_global_scope within a procedure. This must be done at the file scope."); return make_bad_decl(f, token, f->cursor[0]); } else if (are_strings_equal(tag, make_string("import"))) { // TODO(bill): better error messages + Token import_name; Token file_path = expect_token(f, Token_String); - Token as = expect_token(f, Token_as); - Token import_name = expect_token(f, Token_Identifier); + expect_token(f, Token_as); + import_name = expect_token(f, Token_Identifier); if (f->curr_proc == NULL) { return make_import_decl(f, s->TagStmt.token, file_path, import_name);