mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-05 15:18:49 +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"
|
|
||||||
+5
-3
@@ -1,10 +1,12 @@
|
|||||||
#import "print.odin" as _
|
#import "fmt.odin" as fmt
|
||||||
|
#import "game.odin" as game
|
||||||
|
|
||||||
test_proc :: proc() {
|
test_proc :: proc() {
|
||||||
println("Hello?")
|
fmt.println("Hello?")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
main :: proc() {
|
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()
|
||||||
}
|
}
|
||||||
|
|||||||
+39
-35
@@ -1,44 +1,47 @@
|
|||||||
#load "basic.odin"
|
#import "win32.odin" as win32
|
||||||
#load "opengl.odin"
|
#import "fmt.odin" as fmt
|
||||||
#load "math.odin"
|
#import "opengl.odin" as gl
|
||||||
|
#import "math.odin" as math
|
||||||
|
|
||||||
TWO_HEARTS :: #rune "💕"
|
TWO_HEARTS :: #rune "💕"
|
||||||
|
|
||||||
win32_perf_count_freq := GetQueryPerformanceFrequency()
|
win32_perf_count_freq := win32.GetQueryPerformanceFrequency()
|
||||||
time_now :: proc() -> f64 {
|
time_now :: proc() -> f64 {
|
||||||
assert(win32_perf_count_freq != 0)
|
assert(win32_perf_count_freq != 0)
|
||||||
|
|
||||||
counter: i64
|
counter: i64
|
||||||
_ = QueryPerformanceCounter(^counter)
|
_ = win32.QueryPerformanceCounter(^counter)
|
||||||
result := counter as f64 / win32_perf_count_freq as f64
|
result := counter as f64 / win32_perf_count_freq as f64
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
win32_print_last_error :: proc() {
|
win32_print_last_error :: proc() {
|
||||||
err_code := GetLastError() as int
|
err_code := win32.GetLastError() as int
|
||||||
if err_code != 0 {
|
if err_code != 0 {
|
||||||
println("GetLastError:", err_code)
|
fmt.println("GetLastError: %", err_code)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Yuk!
|
// Yuk!
|
||||||
to_c_string :: proc(s: string) -> []u8 {
|
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)
|
_ = copy(c_str, s as []byte)
|
||||||
c_str[len(s)] = 0
|
c_str[s.count] = 0
|
||||||
return c_str
|
return c_str
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Window :: struct {
|
Window :: struct {
|
||||||
width, height: int
|
width, height: int
|
||||||
wc: WNDCLASSEXA
|
wc: win32.WNDCLASSEXA
|
||||||
dc: HDC
|
dc: win32.HDC
|
||||||
hwnd: HWND
|
hwnd: win32.HWND
|
||||||
opengl_context, rc: HGLRC
|
opengl_context, rc: win32.HGLRC
|
||||||
c_title: []u8
|
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: Window
|
||||||
w.width, w.height = msg, height
|
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 {
|
if RegisterClassExA(^w.wc) == 0 {
|
||||||
win32_print_last_error( )
|
win32_print_last_error()
|
||||||
return w, false
|
return w, false
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,15 +115,16 @@ make_window :: proc(title: string, msg, height: int, window_proc: WNDPROC) -> (W
|
|||||||
}
|
}
|
||||||
|
|
||||||
destroy_window :: proc(w: ^Window) {
|
destroy_window :: proc(w: ^Window) {
|
||||||
delete(w.c_title)
|
free(w.c_title.data)
|
||||||
}
|
}
|
||||||
|
|
||||||
display_window :: proc(w: ^Window) {
|
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 {
|
win32_proc :: proc(hwnd: HWND, msg: u32, wparam: WPARAM, lparam: LPARAM) -> LRESULT #no_inline {
|
||||||
if msg == WM_DESTROY || msg == WM_CLOSE || msg == WM_QUIT {
|
if msg == WM_DESTROY || msg == WM_CLOSE || msg == WM_QUIT {
|
||||||
ExitProcess(0)
|
ExitProcess(0)
|
||||||
@@ -140,7 +144,7 @@ run_game :: proc() {
|
|||||||
prev_time := time_now()
|
prev_time := time_now()
|
||||||
running := true
|
running := true
|
||||||
|
|
||||||
pos := Vec2{100, 100}
|
pos := math.Vec2{100, 100}
|
||||||
|
|
||||||
for running {
|
for running {
|
||||||
curr_time := time_now()
|
curr_time := time_now()
|
||||||
@@ -162,38 +166,38 @@ run_game :: proc() {
|
|||||||
|
|
||||||
{
|
{
|
||||||
SPEED :: 500
|
SPEED :: 500
|
||||||
v: Vec2
|
v: math.Vec2
|
||||||
|
|
||||||
if is_key_down(Key_Code.RIGHT) { v[0] += 1 }
|
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.LEFT) { v[0] -= 1 }
|
||||||
if is_key_down(Key_Code.UP) { v[1] += 1 }
|
if is_key_down(Key_Code.UP) { v[1] += 1 }
|
||||||
if is_key_down(Key_Code.DOWN) { 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)
|
gl.clear_color(0.5, 0.7, 1.0, 1.0)
|
||||||
glClear(GL_COLOR_BUFFER_BIT)
|
gl.clear(gl.COLOR_BUFFER_BIT)
|
||||||
|
|
||||||
glLoadIdentity()
|
gl.load_identity()
|
||||||
glOrtho(0, window.width as f64,
|
gl.ortho(0, window.width as f64,
|
||||||
0, window.height as f64, 0, 1)
|
0, window.height as f64, 0, 1)
|
||||||
|
|
||||||
draw_rect :: proc(x, y, w, h: f32) {
|
draw_rect :: proc(x, y, w, h: f32) {
|
||||||
glBegin(GL_TRIANGLES)
|
gl.begin(gl.TRIANGLES)
|
||||||
|
|
||||||
glColor3f(1, 0, 0); glVertex3f(x, y, 0)
|
gl.color3f(1, 0, 0); gl.vertex3f(x, y, 0)
|
||||||
glColor3f(0, 1, 0); glVertex3f(x+w, y, 0)
|
gl.color3f(0, 1, 0); gl.vertex3f(x+w, y, 0)
|
||||||
glColor3f(0, 0, 1); glVertex3f(x+w, y+h, 0)
|
gl.color3f(0, 0, 1); gl.vertex3f(x+w, y+h, 0)
|
||||||
|
|
||||||
glColor3f(0, 0, 1); glVertex3f(x+w, y+h, 0)
|
gl.color3f(0, 0, 1); gl.vertex3f(x+w, y+h, 0)
|
||||||
glColor3f(1, 1, 0); glVertex3f(x, y+h, 0)
|
gl.color3f(1, 1, 0); gl.vertex3f(x, y+h, 0)
|
||||||
glColor3f(1, 0, 0); glVertex3f(x, y, 0)
|
gl.color3f(1, 0, 0); gl.vertex3f(x, y, 0)
|
||||||
|
|
||||||
glEnd()
|
gl.end()
|
||||||
}
|
}
|
||||||
|
|
||||||
draw_rect(pos[0], pos[1], 50, 50)
|
draw_rect(pos[0], pos[1], 50, 50)
|
||||||
|
|||||||
+36
-18
@@ -1,24 +1,42 @@
|
|||||||
MATH_TAU :: 6.28318530717958647692528676655900576
|
TAU :: 6.28318530717958647692528676655900576
|
||||||
MATH_PI :: 3.14159265358979323846264338327950288
|
PI :: 3.14159265358979323846264338327950288
|
||||||
MATH_ONE_OVER_TAU :: 0.636619772367581343075535053490057448
|
ONE_OVER_TAU :: 0.636619772367581343075535053490057448
|
||||||
MATH_ONE_OVER_PI :: 0.159154943091895335768883763372514362
|
ONE_OVER_PI :: 0.159154943091895335768883763372514362
|
||||||
|
|
||||||
MATH_E :: 2.71828182845904523536
|
E :: 2.71828182845904523536
|
||||||
MATH_SQRT_TWO :: 1.41421356237309504880168872420969808
|
SQRT_TWO :: 1.41421356237309504880168872420969808
|
||||||
MATH_SQRT_THREE :: 1.73205080756887729352744634150587236
|
SQRT_THREE :: 1.73205080756887729352744634150587236
|
||||||
MATH_SQRT_FIVE :: 2.23606797749978969640917366873127623
|
SQRT_FIVE :: 2.23606797749978969640917366873127623
|
||||||
|
|
||||||
MATH_LOG_TWO :: 0.693147180559945309417232121458176568
|
LOG_TWO :: 0.693147180559945309417232121458176568
|
||||||
MATH_LOG_TEN :: 2.30258509299404568401799145468436421
|
LOG_TEN :: 2.30258509299404568401799145468436421
|
||||||
|
|
||||||
MATH_EPSILON :: 1.19209290e-7
|
EPSILON :: 1.19209290e-7
|
||||||
|
|
||||||
τ :: MATH_TAU
|
τ :: TAU
|
||||||
π :: MATH_PI
|
π :: PI
|
||||||
|
|
||||||
Vec2 :: type {2}f32
|
// Vec2 :: type raw_union {
|
||||||
Vec3 :: type {3}f32
|
// using xy_: struct {x, y: f32}
|
||||||
Vec4 :: type {4}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
|
Mat2 :: type {4}f32
|
||||||
Mat3 :: type {9}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_radians :: proc(degrees: f32) -> f32 { return degrees * TAU / 360 }
|
||||||
to_degrees :: proc(radians: f32) -> f32 { return radians * 360 / MATH_TAU }
|
to_degrees :: proc(radians: f32) -> f32 { return radians * 360 / TAU }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+41
-41
@@ -1,49 +1,49 @@
|
|||||||
#foreign_system_library "opengl32"
|
#foreign_system_library "opengl32"
|
||||||
|
|
||||||
GL_ZERO :: 0x0000
|
ZERO :: 0x0000
|
||||||
GL_ONE :: 0x0001
|
ONE :: 0x0001
|
||||||
GL_TRIANGLES :: 0x0004
|
TRIANGLES :: 0x0004
|
||||||
GL_BLEND :: 0x0be2
|
BLEND :: 0x0be2
|
||||||
GL_SRC_ALPHA :: 0x0302
|
SRC_ALPHA :: 0x0302
|
||||||
GL_ONE_MINUS_SRC_ALPHA :: 0x0303
|
ONE_MINUS_SRC_ALPHA :: 0x0303
|
||||||
GL_TEXTURE_2D :: 0x0de1
|
TEXTURE_2D :: 0x0de1
|
||||||
GL_RGBA8 :: 0x8058
|
RGBA8 :: 0x8058
|
||||||
GL_UNSIGNED_BYTE :: 0x1401
|
UNSIGNED_BYTE :: 0x1401
|
||||||
GL_BGRA_EXT :: 0x80e1
|
BGRA_EXT :: 0x80e1
|
||||||
GL_TEXTURE_MAX_LEVEL :: 0x813d
|
TEXTURE_MAX_LEVEL :: 0x813d
|
||||||
GL_RGBA :: 0x1908
|
RGBA :: 0x1908
|
||||||
|
|
||||||
GL_NEAREST :: 0x2600
|
NEAREST :: 0x2600
|
||||||
GL_LINEAR :: 0x2601
|
LINEAR :: 0x2601
|
||||||
|
|
||||||
GL_DEPTH_BUFFER_BIT :: 0x00000100
|
DEPTH_BUFFER_BIT :: 0x00000100
|
||||||
GL_STENCIL_BUFFER_BIT :: 0x00000400
|
STENCIL_BUFFER_BIT :: 0x00000400
|
||||||
GL_COLOR_BUFFER_BIT :: 0x00004000
|
COLOR_BUFFER_BIT :: 0x00004000
|
||||||
|
|
||||||
GL_TEXTURE_MAX_ANISOTROPY_EXT :: 0x84fe
|
TEXTURE_MAX_ANISOTROPY_EXT :: 0x84fe
|
||||||
|
|
||||||
GL_TEXTURE_MAG_FILTER :: 0x2800
|
TEXTURE_MAG_FILTER :: 0x2800
|
||||||
GL_TEXTURE_MIN_FILTER :: 0x2801
|
TEXTURE_MIN_FILTER :: 0x2801
|
||||||
GL_TEXTURE_WRAP_S :: 0x2802
|
TEXTURE_WRAP_S :: 0x2802
|
||||||
GL_TEXTURE_WRAP_T :: 0x2803
|
TEXTURE_WRAP_T :: 0x2803
|
||||||
|
|
||||||
glClear :: proc(mask: u32) #foreign
|
clear :: proc(mask: u32) #foreign "glClear"
|
||||||
glClearColor :: proc(r, g, b, a: f32) #foreign
|
clear_color :: proc(r, g, b, a: f32) #foreign "glClearColor"
|
||||||
glBegin :: proc(mode: i32) #foreign
|
begin :: proc(mode: i32) #foreign "glBegin"
|
||||||
glEnd :: proc() #foreign
|
end :: proc() #foreign "glEnd"
|
||||||
glColor3f :: proc(r, g, b: f32) #foreign
|
color3f :: proc(r, g, b: f32) #foreign "glColor3f"
|
||||||
glColor4f :: proc(r, g, b, a: f32) #foreign
|
color4f :: proc(r, g, b, a: f32) #foreign "glColor4f"
|
||||||
glVertex2f :: proc(x, y: f32) #foreign
|
vertex2f :: proc(x, y: f32) #foreign "glVertex2f"
|
||||||
glVertex3f :: proc(x, y, z: f32) #foreign
|
vertex3f :: proc(x, y, z: f32) #foreign "glVertex3f"
|
||||||
glTexCoord2f :: proc(u, v: f32) #foreign
|
tex_coord2f :: proc(u, v: f32) #foreign "glTexCoord2f"
|
||||||
glLoadIdentity :: proc() #foreign
|
load_identity :: proc() #foreign "glLoadIdentity"
|
||||||
glOrtho :: proc(left, right, bottom, top, near, far: f64) #foreign
|
ortho :: proc(left, right, bottom, top, near, far: f64) #foreign "glOrtho"
|
||||||
glBlendFunc :: proc(sfactor, dfactor: i32) #foreign
|
blend_func :: proc(sfactor, dfactor: i32) #foreign "glBlendFunc"
|
||||||
glEnable :: proc(cap: i32) #foreign
|
enable :: proc(cap: i32) #foreign "glEnable"
|
||||||
glDisable :: proc(cap: i32) #foreign
|
disable :: proc(cap: i32) #foreign "glDisable"
|
||||||
glGenTextures :: proc(count: i32, result: ^u32) #foreign
|
gen_textures :: proc(count: i32, result: ^u32) #foreign "glGenTextures"
|
||||||
glTexParameteri :: proc(target, pname, param: i32) #foreign
|
tex_parameteri :: proc(target, pname, param: i32) #foreign "glTexParameteri"
|
||||||
glTexParameterf :: proc(target: i32, pname: i32, param: f32) #foreign
|
tex_parameterf :: proc(target: i32, pname: i32, param: f32) #foreign "glTexParameterf"
|
||||||
glBindTexture :: proc(target: i32, texture: u32) #foreign
|
bind_texture :: proc(target: i32, texture: u32) #foreign "glBindTexture"
|
||||||
glTexImage2D :: proc(target, level, internal_format, width, height, border, format, _type: i32, pixels: rawptr) #foreign
|
tex_image2d :: proc(target, level, internal_format, width, height, border, format, _type: i32, pixels: rawptr) #foreign "glTexImage2D"
|
||||||
|
|
||||||
|
|||||||
-584
@@ -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)
|
|
||||||
}
|
|
||||||
+21
-21
@@ -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 "win32.odin" as win32
|
||||||
#import "os.odin" as os
|
#import "os.odin" as os
|
||||||
#import "print.odin" as _
|
#import "fmt.odin" as fmt
|
||||||
|
|
||||||
// IMPORTANT NOTE(bill): Do not change the order of any of this data
|
// IMPORTANT NOTE(bill): Do not change the order of any of this data
|
||||||
// The compiler relies upon this _exact_ order
|
// The compiler relies upon this _exact_ order
|
||||||
@@ -14,8 +14,8 @@ Type_Info :: union {
|
|||||||
offset: int // offsets are not used in tuples
|
offset: int // offsets are not used in tuples
|
||||||
}
|
}
|
||||||
Record :: struct #ordered {
|
Record :: struct #ordered {
|
||||||
fields: []Member
|
fields: []Member
|
||||||
packed: bool
|
packed: bool
|
||||||
ordered: bool
|
ordered: bool
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -25,7 +25,7 @@ Type_Info :: union {
|
|||||||
base: ^Type_Info
|
base: ^Type_Info
|
||||||
}
|
}
|
||||||
Integer: struct #ordered {
|
Integer: struct #ordered {
|
||||||
size: int // in bytes
|
size: int // in bytes
|
||||||
signed: bool
|
signed: bool
|
||||||
}
|
}
|
||||||
Float: struct #ordered {
|
Float: struct #ordered {
|
||||||
@@ -37,23 +37,23 @@ Type_Info :: union {
|
|||||||
elem: ^Type_Info
|
elem: ^Type_Info
|
||||||
}
|
}
|
||||||
Procedure: struct #ordered {
|
Procedure: struct #ordered {
|
||||||
params: ^Type_Info // Type_Info.Tuple
|
params: ^Type_Info // Type_Info.Tuple
|
||||||
results: ^Type_Info // Type_Info.Tuple
|
results: ^Type_Info // Type_Info.Tuple
|
||||||
variadic: bool
|
variadic: bool
|
||||||
}
|
}
|
||||||
Array: struct #ordered {
|
Array: struct #ordered {
|
||||||
elem: ^Type_Info
|
elem: ^Type_Info
|
||||||
elem_size: int
|
elem_size: int
|
||||||
count: int
|
count: int
|
||||||
}
|
}
|
||||||
Slice: struct #ordered {
|
Slice: struct #ordered {
|
||||||
elem: ^Type_Info
|
elem: ^Type_Info
|
||||||
elem_size: int
|
elem_size: int
|
||||||
}
|
}
|
||||||
Vector: struct #ordered {
|
Vector: struct #ordered {
|
||||||
elem: ^Type_Info
|
elem: ^Type_Info
|
||||||
elem_size: int
|
elem_size: int
|
||||||
count: int
|
count: int
|
||||||
}
|
}
|
||||||
Tuple: Record
|
Tuple: Record
|
||||||
Struct: Record
|
Struct: Record
|
||||||
@@ -171,7 +171,7 @@ __string_ge :: proc(a, b : string) -> bool #inline { return __string_cmp(a, b) >
|
|||||||
|
|
||||||
|
|
||||||
__assert :: proc(msg: string) {
|
__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()
|
__debug_trap()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -181,8 +181,8 @@ __bounds_check_error :: proc(file: string, line, column: int,
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
// TODO(bill): Probably reduce the need for `print` in the runtime if possible
|
// TODO(bill): Probably reduce the need for `print` in the runtime if possible
|
||||||
println_err("%(%:%) Index % is out of bounds range [0, %)",
|
fmt.println_err("%(%:%) Index % is out of bounds range [0, %)",
|
||||||
file, line, column, index, count)
|
file, line, column, index, count)
|
||||||
__debug_trap()
|
__debug_trap()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -191,8 +191,8 @@ __slice_expr_error :: proc(file: string, line, column: int,
|
|||||||
if 0 <= low && low <= high && high <= max {
|
if 0 <= low && low <= high && high <= max {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
println_err("%(%:%) Invalid slice indices: [%:%:%]",
|
fmt.println_err("%(%:%) Invalid slice indices: [%:%:%]",
|
||||||
file, line, column, low, high, max)
|
file, line, column, low, high, max)
|
||||||
__debug_trap()
|
__debug_trap()
|
||||||
}
|
}
|
||||||
__substring_expr_error :: proc(file: string, line, column: int,
|
__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 {
|
if 0 <= low && low <= high {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
println_err("%(%:%) Invalid substring indices: [%:%:%]",
|
fmt.println_err("%(%:%) Invalid substring indices: [%:%:%]",
|
||||||
file, line, column, low, high)
|
file, line, column, low, high)
|
||||||
__debug_trap()
|
__debug_trap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+7
-13
@@ -1,12 +1,6 @@
|
|||||||
#foreign_system_library "user32"
|
#foreign_system_library "user32"
|
||||||
#foreign_system_library "gdi32"
|
#foreign_system_library "gdi32"
|
||||||
|
|
||||||
|
|
||||||
test_proc :: proc() {
|
|
||||||
x := "Goodbye?"
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
HANDLE :: type rawptr
|
HANDLE :: type rawptr
|
||||||
HWND :: type HANDLE
|
HWND :: type HANDLE
|
||||||
HDC :: type HANDLE
|
HDC :: type HANDLE
|
||||||
@@ -70,10 +64,10 @@ MSG :: struct #ordered {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
GetLastError :: proc() -> i32 #foreign
|
GetLastError :: proc() -> i32 #foreign
|
||||||
ExitProcess :: proc(exit_code: u32) #foreign
|
ExitProcess :: proc(exit_code: u32) #foreign
|
||||||
GetDesktopWindow :: proc() -> HWND #foreign
|
GetDesktopWindow :: proc() -> HWND #foreign
|
||||||
GetCursorPos :: proc(p: ^POINT) -> i32 #foreign
|
GetCursorPos :: proc(p: ^POINT) -> i32 #foreign
|
||||||
ScreenToClient :: proc(h: HWND, p: ^POINT) -> i32 #foreign
|
ScreenToClient :: proc(h: HWND, p: ^POINT) -> i32 #foreign
|
||||||
|
|
||||||
GetModuleHandleA :: proc(module_name: ^u8) -> HINSTANCE #foreign
|
GetModuleHandleA :: proc(module_name: ^u8) -> HINSTANCE #foreign
|
||||||
@@ -99,11 +93,11 @@ CreateWindowExA :: proc(ex_style: u32,
|
|||||||
param: rawptr) -> HWND #foreign
|
param: rawptr) -> HWND #foreign
|
||||||
|
|
||||||
ShowWindow :: proc(hwnd: HWND, cmd_show: i32) -> BOOL #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,
|
PeekMessageA :: proc(msg: ^MSG, hwnd: HWND,
|
||||||
msg_filter_min, msg_filter_max, remove_msg: u32) -> BOOL #foreign
|
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
|
DefWindowProcA :: proc(hwnd: HWND, msg: u32, wparam: WPARAM, lparam: LPARAM) -> LRESULT #foreign
|
||||||
|
|
||||||
|
|||||||
+13
-3
@@ -118,6 +118,7 @@ struct Scope {
|
|||||||
b32 is_global;
|
b32 is_global;
|
||||||
b32 is_file;
|
b32 is_file;
|
||||||
b32 is_init;
|
b32 is_init;
|
||||||
|
AstFile *file;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum ExprKind {
|
enum ExprKind {
|
||||||
@@ -635,6 +636,10 @@ void add_entity_use(CheckerInfo *i, AstNode *identifier, Entity *entity) {
|
|||||||
GB_ASSERT(identifier->kind == AstNode_Ident);
|
GB_ASSERT(identifier->kind == AstNode_Ident);
|
||||||
HashKey key = hash_pointer(identifier);
|
HashKey key = hash_pointer(identifier);
|
||||||
map_set(&i->uses, key, entity);
|
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 = make_scope(c->global_scope, c->allocator);
|
||||||
scope->is_global = f->is_global_scope;
|
scope->is_global = f->is_global_scope;
|
||||||
scope->is_file = true;
|
scope->is_file = true;
|
||||||
|
scope->file = f;
|
||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
// NOTE(bill): First file is always the initial file
|
// NOTE(bill): First file is always the initial file
|
||||||
|
// thus it must contain main
|
||||||
scope->is_init = true;
|
scope->is_init = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -830,7 +837,8 @@ void check_parsed_files(Checker *c) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
f->scope = scope;
|
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
|
// Collect Entities
|
||||||
@@ -980,6 +988,7 @@ void check_parsed_files(Checker *c) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
GB_ASSERT(id->import_name.string.len > 0);
|
||||||
Entity *e = make_entity_import_name(c->allocator, file_scope, id->import_name, t_invalid,
|
Entity *e = make_entity_import_name(c->allocator, file_scope, id->import_name, t_invalid,
|
||||||
id->fullpath, id->import_name.string,
|
id->fullpath, id->import_name.string,
|
||||||
scope);
|
scope);
|
||||||
@@ -995,10 +1004,11 @@ void check_parsed_files(Checker *c) {
|
|||||||
if (e->kind == kind) {
|
if (e->kind == kind) {
|
||||||
DeclInfo *d = entry->value;
|
DeclInfo *d = entry->value;
|
||||||
|
|
||||||
|
add_curr_ast_file(c, d->scope->file);
|
||||||
|
|
||||||
Scope *prev_scope = c->context.scope;
|
Scope *prev_scope = c->context.scope;
|
||||||
c->context.scope = d->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);
|
check_entity_decl(c, e, d, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+20
-12
@@ -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);
|
Entity *e = make_entity_type_name(c->allocator, c->context.scope, name_token, NULL);
|
||||||
add_entity(c, c->context.scope, td->name, e);
|
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);
|
check_type_decl(c, e, td->type, NULL, NULL);
|
||||||
|
|
||||||
HashKey key = hash_string(name_token.string);
|
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("_"))) {
|
if (are_strings_equal(n->Ident.string, make_string("_"))) {
|
||||||
error(&c->error_collector, n->Ident, "`_` cannot be used as a value type");
|
error(&c->error_collector, n->Ident, "`_` cannot be used as a value type");
|
||||||
} else {
|
} 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,
|
error(&c->error_collector, n->Ident,
|
||||||
"Undeclared named: `%.*s`", LIT(n->Ident.string));
|
"Undeclared name: %.*s", LIT(n->Ident.string));
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -915,11 +931,9 @@ Type *check_type(Checker *c, AstNode *e, Type *named_type, CycleChecker *cycle_c
|
|||||||
type = make_type_array(c->allocator,
|
type = make_type_array(c->allocator,
|
||||||
check_type(c, at->elem, NULL, cycle_checker),
|
check_type(c, at->elem, NULL, cycle_checker),
|
||||||
check_array_count(c, at->count));
|
check_array_count(c, at->count));
|
||||||
type->flags |= e->type_flags;
|
|
||||||
set_base_type(named_type, type);
|
set_base_type(named_type, type);
|
||||||
} else {
|
} else {
|
||||||
type = make_type_slice(c->allocator, check_type(c, at->elem));
|
type = make_type_slice(c->allocator, check_type(c, at->elem));
|
||||||
type->flags |= e->type_flags;
|
|
||||||
set_base_type(named_type, type);
|
set_base_type(named_type, type);
|
||||||
}
|
}
|
||||||
goto end;
|
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);
|
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 = make_type_vector(c->allocator, elem, count);
|
||||||
type->flags |= e->type_flags;
|
|
||||||
set_base_type(named_type, type);
|
set_base_type(named_type, type);
|
||||||
goto end;
|
goto end;
|
||||||
case_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_struct_type(c, type, e, cycle_checker);
|
||||||
check_close_scope(c);
|
check_close_scope(c);
|
||||||
type->Record.node = e;
|
type->Record.node = e;
|
||||||
type->flags |= e->type_flags;
|
|
||||||
goto end;
|
goto end;
|
||||||
case_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_union_type(c, type, e, cycle_checker);
|
||||||
check_close_scope(c);
|
check_close_scope(c);
|
||||||
type->Record.node = e;
|
type->Record.node = e;
|
||||||
type->flags |= e->type_flags;
|
|
||||||
goto end;
|
goto end;
|
||||||
case_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_raw_union_type(c, type, e, cycle_checker);
|
||||||
check_close_scope(c);
|
check_close_scope(c);
|
||||||
type->Record.node = e;
|
type->Record.node = e;
|
||||||
type->flags |= e->type_flags;
|
|
||||||
goto end;
|
goto end;
|
||||||
case_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);
|
set_base_type(named_type, type);
|
||||||
check_enum_type(c, type, named_type, e);
|
check_enum_type(c, type, named_type, e);
|
||||||
type->Record.node = e;
|
type->Record.node = e;
|
||||||
type->flags |= e->type_flags;
|
|
||||||
goto end;
|
goto end;
|
||||||
case_end;
|
case_end;
|
||||||
|
|
||||||
case_ast_node(pt, PointerType, e);
|
case_ast_node(pt, PointerType, e);
|
||||||
type = make_type_pointer(c->allocator, check_type(c, pt->type));
|
type = make_type_pointer(c->allocator, check_type(c, pt->type));
|
||||||
type->flags |= e->type_flags;
|
|
||||||
set_base_type(named_type, type);
|
set_base_type(named_type, type);
|
||||||
goto end;
|
goto end;
|
||||||
case_end;
|
case_end;
|
||||||
|
|
||||||
case_ast_node(pt, ProcType, e);
|
case_ast_node(pt, ProcType, e);
|
||||||
type = alloc_type(c->allocator, Type_Proc);
|
type = alloc_type(c->allocator, Type_Proc);
|
||||||
type->flags |= e->type_flags;
|
|
||||||
set_base_type(named_type, type);
|
set_base_type(named_type, type);
|
||||||
|
check_open_scope(c, e);
|
||||||
check_procedure_type(c, type, e);
|
check_procedure_type(c, type, e);
|
||||||
|
check_close_scope(c);
|
||||||
goto end;
|
goto end;
|
||||||
case_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);
|
check_expr_or_type(c, &o, e);
|
||||||
if (o.mode == Addressing_Type) {
|
if (o.mode == Addressing_Type) {
|
||||||
type = o.type;
|
type = o.type;
|
||||||
type->flags |= e->type_flags;
|
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+36
-23
@@ -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);
|
// add_proc_entity(c, d->scope, pd->name, e);
|
||||||
if (d->scope->is_proc) {
|
if (d->scope->is_proc) {
|
||||||
// Nested procedures
|
// 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) {
|
void check_entity_decl(Checker *c, Entity *e, DeclInfo *d, Type *named_type, CycleChecker *cycle_checker) {
|
||||||
if (e->type != NULL) {
|
if (e->type != NULL) {
|
||||||
if (e->type->kind == Type_Named && e->type->Named.base == NULL) {
|
return;
|
||||||
// NOTE(bill): Some weird declaration error from Entity_ImportName
|
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (d == NULL) {
|
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) {
|
switch (e->kind) {
|
||||||
case Entity_Constant: {
|
case Entity_Constant: {
|
||||||
Scope *prev = c->context.scope;
|
Scope *prev = c->context.scope;
|
||||||
c->context.scope = d->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);
|
check_const_decl(c, e, d->type_expr, d->init_expr);
|
||||||
|
|
||||||
c->context.scope = prev;
|
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case Entity_Variable: {
|
case Entity_Variable: {
|
||||||
Scope *prev = c->context.scope;
|
Scope *prev = c->context.scope;
|
||||||
c->context.scope = d->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);
|
check_var_decl(c, e, d->entities, d->entity_count, d->type_expr, d->init_expr);
|
||||||
|
|
||||||
c->context.scope = prev;
|
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case Entity_Procedure: {
|
||||||
|
check_proc_decl(c, e, d, true);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
|
||||||
case Entity_TypeName: {
|
case Entity_TypeName: {
|
||||||
|
Scope *prev = c->context.scope;
|
||||||
|
c->context.scope = d->scope;
|
||||||
|
defer (c->context.scope = prev);
|
||||||
|
|
||||||
CycleChecker local_cycle_checker = {};
|
CycleChecker local_cycle_checker = {};
|
||||||
if (cycle_checker == NULL) {
|
if (cycle_checker == NULL) {
|
||||||
cycle_checker = &local_cycle_checker;
|
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);
|
gb_array_free(local_cycle_checker.path);
|
||||||
}
|
}
|
||||||
} break;
|
} 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 *decl = scope->elements.entries[i].value;
|
||||||
Entity *found = scope_insert_entity(c->context.scope, decl);
|
Entity *found = scope_insert_entity(c->context.scope, decl);
|
||||||
if (found != NULL) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1406,13 +1421,11 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
|||||||
case_ast_node(pd, ProcDecl, node);
|
case_ast_node(pd, ProcDecl, node);
|
||||||
ast_node(name, Ident, pd->name);
|
ast_node(name, Ident, pd->name);
|
||||||
Entity *e = make_entity_procedure(c->allocator, c->context.scope, *name, NULL);
|
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 = {};
|
DeclInfo *decl = make_declaration_info(c->allocator, e->scope);
|
||||||
init_declaration_info(&decl, e->scope);
|
decl->proc_decl = node;
|
||||||
decl.proc_decl = node;
|
check_proc_decl(c, e, decl, false);
|
||||||
check_proc_decl(c, e, &decl, false);
|
|
||||||
destroy_declaration_info(&decl);
|
|
||||||
case_end;
|
case_end;
|
||||||
|
|
||||||
case_ast_node(td, TypeDecl, node);
|
case_ast_node(td, TypeDecl, node);
|
||||||
|
|||||||
+5
-4
@@ -2539,18 +2539,19 @@ AstNode *parse_stmt(AstFile *f) {
|
|||||||
case Token_Hash: {
|
case Token_Hash: {
|
||||||
s = parse_tag_stmt(f, NULL);
|
s = parse_tag_stmt(f, NULL);
|
||||||
String tag = s->TagStmt.name.string;
|
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) {
|
if (f->curr_proc == NULL) {
|
||||||
f->is_global_scope = true;
|
f->is_global_scope = true;
|
||||||
return make_empty_stmt(f, f->cursor[0]);
|
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]);
|
return make_bad_decl(f, token, f->cursor[0]);
|
||||||
} else if (are_strings_equal(tag, make_string("import"))) {
|
} else if (are_strings_equal(tag, make_string("import"))) {
|
||||||
// TODO(bill): better error messages
|
// TODO(bill): better error messages
|
||||||
|
Token import_name;
|
||||||
Token file_path = expect_token(f, Token_String);
|
Token file_path = expect_token(f, Token_String);
|
||||||
Token as = expect_token(f, Token_as);
|
expect_token(f, Token_as);
|
||||||
Token import_name = expect_token(f, Token_Identifier);
|
import_name = expect_token(f, Token_Identifier);
|
||||||
|
|
||||||
if (f->curr_proc == NULL) {
|
if (f->curr_proc == NULL) {
|
||||||
return make_import_decl(f, s->TagStmt.token, file_path, import_name);
|
return make_import_decl(f, s->TagStmt.token, file_path, import_name);
|
||||||
|
|||||||
Reference in New Issue
Block a user