mirror of
https://github.com/odin-lang/Odin.git
synced 2026-02-15 23:54:07 +00:00
Fix namespacing issues for #import; allow using ImportName
This commit is contained in:
@@ -1,4 +0,0 @@
|
||||
#load "runtime.odin"
|
||||
#load "win32.odin"
|
||||
#load "file.odin"
|
||||
#load "print.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()
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 }
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
584
code/print.odin
584
code/print.odin
@@ -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, "<invalid>")
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user