Fix namespacing issues for #import; allow using ImportName

This commit is contained in:
Ginger Bill
2016-09-14 22:58:24 +01:00
parent 79f575ae8e
commit bd365e5176
12 changed files with 223 additions and 761 deletions

View File

@@ -1,4 +0,0 @@
#load "runtime.odin"
#load "win32.odin"
#load "file.odin"
#load "print.odin"

View File

@@ -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()
}

View File

@@ -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)

View File

@@ -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 }

View File

@@ -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"

View File

@@ -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)
}

View File

@@ -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()
}

View File

@@ -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

View File

@@ -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);
}
}

View File

@@ -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;
}
}

View File

@@ -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);

View File

@@ -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);