Browse Source

Fix namespacing issues for #import; allow using ImportName

Ginger Bill 9 years ago
parent
commit
bd365e5176
12 changed files with 227 additions and 765 deletions
  1. 0 4
      code/basic.odin
  2. 5 3
      code/demo.odin
  3. 39 35
      code/game.odin
  4. 41 23
      code/math.odin
  5. 41 41
      code/opengl.odin
  6. 0 584
      code/print.odin
  7. 21 21
      code/runtime.odin
  8. 7 13
      code/win32.odin
  9. 13 3
      src/checker/checker.cpp
  10. 20 12
      src/checker/expr.cpp
  11. 35 22
      src/checker/stmt.cpp
  12. 5 4
      src/parser.cpp

+ 0 - 4
code/basic.odin

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

+ 5 - 3
code/demo.odin

@@ -1,10 +1,12 @@
-#import "print.odin" as _
+#import "fmt.odin" as fmt
+#import "game.odin" as game
 
 test_proc :: proc() {
-	println("Hello?")
+	fmt.println("Hello?")
 }
 
 
 main :: proc() {
-	println("% % % %", "Hellope", true, 6.28, {4}int{1, 2, 3, 4})
+	// fmt.println("% % % %", "Hellope", true, 6.28, {4}int{1, 2, 3, 4})
+	game.run()
 }

+ 39 - 35
code/game.odin

@@ -1,44 +1,47 @@
-#load "basic.odin"
-#load "opengl.odin"
-#load "math.odin"
+#import "win32.odin"  as win32
+#import "fmt.odin"    as fmt
+#import "opengl.odin" as gl
+#import "math.odin"   as math
 
 TWO_HEARTS :: #rune "💕"
 
-win32_perf_count_freq := GetQueryPerformanceFrequency()
+win32_perf_count_freq := win32.GetQueryPerformanceFrequency()
 time_now :: proc() -> f64 {
 	assert(win32_perf_count_freq != 0)
 
 	counter: i64
-	_ = QueryPerformanceCounter(^counter)
+	_ = win32.QueryPerformanceCounter(^counter)
 	result := counter as f64 / win32_perf_count_freq as f64
 	return result
 }
 win32_print_last_error :: proc() {
-	err_code := GetLastError() as int
+	err_code := win32.GetLastError() as int
 	if err_code != 0 {
-		println("GetLastError:", err_code)
+		fmt.println("GetLastError: %", err_code)
 	}
 }
 
 // Yuk!
 to_c_string :: proc(s: string) -> []u8 {
-	c_str := new_slice(u8, len(s)+1)
+	c_str := new_slice(u8, s.count+1)
 	_ = copy(c_str, s as []byte)
-	c_str[len(s)] = 0
+	c_str[s.count] = 0
 	return c_str
 }
 
 
 Window :: struct {
 	width, height:      int
-	wc:                 WNDCLASSEXA
-	dc:                 HDC
-	hwnd:               HWND
-	opengl_context, rc: HGLRC
+	wc:                 win32.WNDCLASSEXA
+	dc:                 win32.HDC
+	hwnd:               win32.HWND
+	opengl_context, rc: win32.HGLRC
 	c_title:            []u8
 }
 
-make_window :: proc(title: string, msg, height: int, window_proc: WNDPROC) -> (Window, bool) {
+make_window :: proc(title: string, msg, height: int, window_proc: win32.WNDPROC) -> (Window, bool) {
+	using win32
+
 	w: Window
 	w.width, w.height = msg, height
 
@@ -58,7 +61,7 @@ make_window :: proc(title: string, msg, height: int, window_proc: WNDPROC) -> (W
 	};
 
 	if RegisterClassExA(^w.wc) == 0 {
-		win32_print_last_error( )
+		win32_print_last_error()
 		return w, false
 	}
 
@@ -112,15 +115,16 @@ make_window :: proc(title: string, msg, height: int, window_proc: WNDPROC) -> (W
 }
 
 destroy_window :: proc(w: ^Window) {
-	delete(w.c_title)
+	free(w.c_title.data)
 }
 
 display_window :: proc(w: ^Window) {
-	SwapBuffers(w.dc)
+	win32.SwapBuffers(w.dc)
 }
 
 
-run_game :: proc() {
+run :: proc() {
+	using win32
 	win32_proc :: proc(hwnd: HWND, msg: u32, wparam: WPARAM, lparam: LPARAM) -> LRESULT #no_inline {
 		if msg == WM_DESTROY || msg == WM_CLOSE || msg == WM_QUIT {
 			ExitProcess(0)
@@ -140,7 +144,7 @@ run_game :: proc() {
 	prev_time := time_now()
 	running := true
 
-	pos := Vec2{100, 100}
+	pos := math.Vec2{100, 100}
 
 	for running {
 		curr_time := time_now()
@@ -162,38 +166,38 @@ run_game :: proc() {
 
 		{
 			SPEED :: 500
-			v: Vec2
+			v: math.Vec2
 
 			if is_key_down(Key_Code.RIGHT) { v[0] += 1 }
 			if is_key_down(Key_Code.LEFT)  { v[0] -= 1 }
 			if is_key_down(Key_Code.UP)    { v[1] += 1 }
 			if is_key_down(Key_Code.DOWN)  { v[1] -= 1 }
 
-			v = vec2_norm0(v)
+			v = math.vec2_norm0(v)
 
-			pos += v * Vec2{SPEED * dt}
+			pos += v * math.Vec2{SPEED * dt}
 		}
 
 
-		glClearColor(0.5, 0.7, 1.0, 1.0)
-		glClear(GL_COLOR_BUFFER_BIT)
+		gl.clear_color(0.5, 0.7, 1.0, 1.0)
+		gl.clear(gl.COLOR_BUFFER_BIT)
 
-		glLoadIdentity()
-		glOrtho(0, window.width as f64,
-		        0, window.height as f64, 0, 1)
+		gl.load_identity()
+		gl.ortho(0, window.width as f64,
+		         0, window.height as f64, 0, 1)
 
 		draw_rect :: proc(x, y, w, h: f32) {
-			glBegin(GL_TRIANGLES)
+			gl.begin(gl.TRIANGLES)
 
-			glColor3f(1, 0, 0); glVertex3f(x,   y,   0)
-			glColor3f(0, 1, 0); glVertex3f(x+w, y,   0)
-			glColor3f(0, 0, 1); glVertex3f(x+w, y+h, 0)
+			gl.color3f(1, 0, 0); gl.vertex3f(x,   y,   0)
+			gl.color3f(0, 1, 0); gl.vertex3f(x+w, y,   0)
+			gl.color3f(0, 0, 1); gl.vertex3f(x+w, y+h, 0)
 
-			glColor3f(0, 0, 1); glVertex3f(x+w, y+h, 0)
-			glColor3f(1, 1, 0); glVertex3f(x,   y+h, 0)
-			glColor3f(1, 0, 0); glVertex3f(x,   y,   0)
+			gl.color3f(0, 0, 1); gl.vertex3f(x+w, y+h, 0)
+			gl.color3f(1, 1, 0); gl.vertex3f(x,   y+h, 0)
+			gl.color3f(1, 0, 0); gl.vertex3f(x,   y,   0)
 
-			glEnd()
+			gl.end()
 		}
 
 		draw_rect(pos[0], pos[1], 50, 50)

+ 41 - 23
code/math.odin

@@ -1,24 +1,42 @@
-MATH_TAU          :: 6.28318530717958647692528676655900576
-MATH_PI           :: 3.14159265358979323846264338327950288
-MATH_ONE_OVER_TAU :: 0.636619772367581343075535053490057448
-MATH_ONE_OVER_PI  :: 0.159154943091895335768883763372514362
-
-MATH_E            :: 2.71828182845904523536
-MATH_SQRT_TWO     :: 1.41421356237309504880168872420969808
-MATH_SQRT_THREE   :: 1.73205080756887729352744634150587236
-MATH_SQRT_FIVE    :: 2.23606797749978969640917366873127623
-
-MATH_LOG_TWO      :: 0.693147180559945309417232121458176568
-MATH_LOG_TEN      :: 2.30258509299404568401799145468436421
-
-MATH_EPSILON      :: 1.19209290e-7
-
-τ :: MATH_TAU
-π :: MATH_PI
-
-Vec2 :: type {2}f32
-Vec3 :: type {3}f32
-Vec4 :: type {4}f32
+TAU          :: 6.28318530717958647692528676655900576
+PI           :: 3.14159265358979323846264338327950288
+ONE_OVER_TAU :: 0.636619772367581343075535053490057448
+ONE_OVER_PI  :: 0.159154943091895335768883763372514362
+
+E            :: 2.71828182845904523536
+SQRT_TWO     :: 1.41421356237309504880168872420969808
+SQRT_THREE   :: 1.73205080756887729352744634150587236
+SQRT_FIVE    :: 2.23606797749978969640917366873127623
+
+LOG_TWO      :: 0.693147180559945309417232121458176568
+LOG_TEN      :: 2.30258509299404568401799145468436421
+
+EPSILON      :: 1.19209290e-7
+
+τ :: TAU
+π :: PI
+
+// 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 }
 
 
 

+ 41 - 41
code/opengl.odin

@@ -1,49 +1,49 @@
 #foreign_system_library "opengl32"
 
-GL_ZERO                 :: 0x0000
-GL_ONE                  :: 0x0001
-GL_TRIANGLES            :: 0x0004
-GL_BLEND                :: 0x0be2
-GL_SRC_ALPHA            :: 0x0302
-GL_ONE_MINUS_SRC_ALPHA  :: 0x0303
-GL_TEXTURE_2D           :: 0x0de1
-GL_RGBA8                :: 0x8058
-GL_UNSIGNED_BYTE        :: 0x1401
-GL_BGRA_EXT             :: 0x80e1
-GL_TEXTURE_MAX_LEVEL    :: 0x813d
-GL_RGBA                 :: 0x1908
+ZERO                 :: 0x0000
+ONE                  :: 0x0001
+TRIANGLES            :: 0x0004
+BLEND                :: 0x0be2
+SRC_ALPHA            :: 0x0302
+ONE_MINUS_SRC_ALPHA  :: 0x0303
+TEXTURE_2D           :: 0x0de1
+RGBA8                :: 0x8058
+UNSIGNED_BYTE        :: 0x1401
+BGRA_EXT             :: 0x80e1
+TEXTURE_MAX_LEVEL    :: 0x813d
+RGBA                 :: 0x1908
 
-GL_NEAREST :: 0x2600
-GL_LINEAR  :: 0x2601
+NEAREST :: 0x2600
+LINEAR  :: 0x2601
 
-GL_DEPTH_BUFFER_BIT   :: 0x00000100
-GL_STENCIL_BUFFER_BIT :: 0x00000400
-GL_COLOR_BUFFER_BIT   :: 0x00004000
+DEPTH_BUFFER_BIT   :: 0x00000100
+STENCIL_BUFFER_BIT :: 0x00000400
+COLOR_BUFFER_BIT   :: 0x00004000
 
-GL_TEXTURE_MAX_ANISOTROPY_EXT :: 0x84fe
+TEXTURE_MAX_ANISOTROPY_EXT :: 0x84fe
 
-GL_TEXTURE_MAG_FILTER  :: 0x2800
-GL_TEXTURE_MIN_FILTER  :: 0x2801
-GL_TEXTURE_WRAP_S      :: 0x2802
-GL_TEXTURE_WRAP_T      :: 0x2803
+TEXTURE_MAG_FILTER  :: 0x2800
+TEXTURE_MIN_FILTER  :: 0x2801
+TEXTURE_WRAP_S      :: 0x2802
+TEXTURE_WRAP_T      :: 0x2803
 
-glClear         :: proc(mask: u32)                                #foreign
-glClearColor    :: proc(r, g, b, a: f32)                          #foreign
-glBegin         :: proc(mode: i32)                                #foreign
-glEnd           :: proc()                                         #foreign
-glColor3f       :: proc(r, g, b: f32)                             #foreign
-glColor4f       :: proc(r, g, b, a: f32)                          #foreign
-glVertex2f      :: proc(x, y: f32)                                #foreign
-glVertex3f      :: proc(x, y, z: f32)                             #foreign
-glTexCoord2f    :: proc(u, v: f32)                                #foreign
-glLoadIdentity  :: proc()                                         #foreign
-glOrtho         :: proc(left, right, bottom, top, near, far: f64) #foreign
-glBlendFunc     :: proc(sfactor, dfactor: i32)                    #foreign
-glEnable        :: proc(cap: i32)                                 #foreign
-glDisable       :: proc(cap: i32)                                 #foreign
-glGenTextures   :: proc(count: i32, result: ^u32)                 #foreign
-glTexParameteri :: proc(target, pname, param: i32)                #foreign
-glTexParameterf :: proc(target: i32, pname: i32, param: f32)      #foreign
-glBindTexture   :: proc(target: i32, texture: u32)                #foreign
-glTexImage2D    :: proc(target, level, internal_format, width, height, border, format, _type: i32, pixels: rawptr) #foreign
+clear          :: proc(mask: u32)                                #foreign "glClear"
+clear_color    :: proc(r, g, b, a: f32)                          #foreign "glClearColor"
+begin          :: proc(mode: i32)                                #foreign "glBegin"
+end            :: proc()                                         #foreign "glEnd"
+color3f        :: proc(r, g, b: f32)                             #foreign "glColor3f"
+color4f        :: proc(r, g, b, a: f32)                          #foreign "glColor4f"
+vertex2f       :: proc(x, y: f32)                                #foreign "glVertex2f"
+vertex3f       :: proc(x, y, z: f32)                             #foreign "glVertex3f"
+tex_coord2f    :: proc(u, v: f32)                                #foreign "glTexCoord2f"
+load_identity  :: proc()                                         #foreign "glLoadIdentity"
+ortho          :: proc(left, right, bottom, top, near, far: f64) #foreign "glOrtho"
+blend_func     :: proc(sfactor, dfactor: i32)                    #foreign "glBlendFunc"
+enable         :: proc(cap: i32)                                 #foreign "glEnable"
+disable        :: proc(cap: i32)                                 #foreign "glDisable"
+gen_textures   :: proc(count: i32, result: ^u32)                 #foreign "glGenTextures"
+tex_parameteri :: proc(target, pname, param: i32)                #foreign "glTexParameteri"
+tex_parameterf :: proc(target: i32, pname: i32, param: f32)      #foreign "glTexParameterf"
+bind_texture   :: proc(target: i32, texture: u32)                #foreign "glBindTexture"
+tex_image2d    :: proc(target, level, internal_format, width, height, border, format, _type: i32, pixels: rawptr) #foreign "glTexImage2D"
 

+ 0 - 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)
-}

+ 21 - 21
code/runtime.odin

@@ -1,9 +1,9 @@
-#global_scope
+#shared_global_scope
 
-// TODO(bill): Remove #import in runtime.odin
+// TODO(bill): Create a standard library "location" so I don't have to manually import "runtime.odin"
 #import "win32.odin" as win32
-#import "os.odin"  as os
-#import "print.odin" as _
+#import "os.odin"    as os
+#import "fmt.odin"   as fmt
 
 // IMPORTANT NOTE(bill): Do not change the order of any of this data
 // The compiler relies upon this _exact_ order
@@ -14,8 +14,8 @@ Type_Info :: union {
 		offset:    int        // offsets are not used in tuples
 	}
 	Record :: struct #ordered {
-		fields: []Member
-		packed: bool
+		fields:  []Member
+		packed:  bool
 		ordered: bool
 	}
 
@@ -25,7 +25,7 @@ Type_Info :: union {
 		base: ^Type_Info
 	}
 	Integer: struct #ordered {
-		size: int // in bytes
+		size:   int // in bytes
 		signed: bool
 	}
 	Float: struct #ordered {
@@ -37,23 +37,23 @@ Type_Info :: union {
 		elem: ^Type_Info
 	}
 	Procedure: struct #ordered {
-		params:  ^Type_Info // Type_Info.Tuple
-		results: ^Type_Info // Type_Info.Tuple
+		params:   ^Type_Info // Type_Info.Tuple
+		results:  ^Type_Info // Type_Info.Tuple
 		variadic: bool
 	}
 	Array: struct #ordered {
-		elem: ^Type_Info
+		elem:      ^Type_Info
 		elem_size: int
-		count: int
+		count:     int
 	}
 	Slice: struct #ordered {
-		elem: ^Type_Info
+		elem:      ^Type_Info
 		elem_size: int
 	}
 	Vector: struct #ordered {
-		elem: ^Type_Info
+		elem:      ^Type_Info
 		elem_size: int
-		count: int
+		count:     int
 	}
 	Tuple:     Record
 	Struct:    Record
@@ -171,7 +171,7 @@ __string_ge :: proc(a, b : string) -> bool #inline { return __string_cmp(a, b) >
 
 
 __assert :: proc(msg: string) {
-	os.write(os.file_get_standard(os.File_Standard.ERROR), msg as []byte)
+	os.write(os.get_standard_file(os.File_Standard.ERROR), msg as []byte)
 	__debug_trap()
 }
 
@@ -181,8 +181,8 @@ __bounds_check_error :: proc(file: string, line, column: int,
 		return
 	}
 	// TODO(bill): Probably reduce the need for `print` in the runtime if possible
-	println_err("%(%:%) Index % is out of bounds range [0, %)",
-	            file, line, column, index, count)
+	fmt.println_err("%(%:%) Index % is out of bounds range [0, %)",
+	                file, line, column, index, count)
 	__debug_trap()
 }
 
@@ -191,8 +191,8 @@ __slice_expr_error :: proc(file: string, line, column: int,
 	if 0 <= low && low <= high && high <= max {
 		return
 	}
-	println_err("%(%:%) Invalid slice indices: [%:%:%]",
-	          file, line, column, low, high, max)
+	fmt.println_err("%(%:%) Invalid slice indices: [%:%:%]",
+	                file, line, column, low, high, max)
 	__debug_trap()
 }
 __substring_expr_error :: proc(file: string, line, column: int,
@@ -200,8 +200,8 @@ __substring_expr_error :: proc(file: string, line, column: int,
 	if 0 <= low && low <= high {
 		return
 	}
-	println_err("%(%:%) Invalid substring indices: [%:%:%]",
-	          file, line, column, low, high)
+	fmt.println_err("%(%:%) Invalid substring indices: [%:%:%]",
+	                file, line, column, low, high)
 	__debug_trap()
 }
 

+ 7 - 13
code/win32.odin

@@ -1,12 +1,6 @@
 #foreign_system_library "user32"
 #foreign_system_library "gdi32"
 
-
-test_proc :: proc() {
-	x := "Goodbye?"
-}
-
-
 HANDLE    :: type rawptr
 HWND      :: type HANDLE
 HDC       :: type HANDLE
@@ -70,10 +64,10 @@ MSG :: struct #ordered {
 
 
 
-GetLastError     :: proc() -> i32 #foreign
-ExitProcess      :: proc(exit_code: u32) #foreign
-GetDesktopWindow :: proc() -> HWND #foreign
-GetCursorPos     :: proc(p: ^POINT) -> i32 #foreign
+GetLastError     :: proc() -> i32                   #foreign
+ExitProcess      :: proc(exit_code: u32)            #foreign
+GetDesktopWindow :: proc() -> HWND                  #foreign
+GetCursorPos     :: proc(p: ^POINT) -> i32          #foreign
 ScreenToClient   :: proc(h: HWND, p: ^POINT) -> i32 #foreign
 
 GetModuleHandleA :: proc(module_name: ^u8) -> HINSTANCE #foreign
@@ -99,11 +93,11 @@ CreateWindowExA  :: proc(ex_style: u32,
                          param: rawptr) -> HWND #foreign
 
 ShowWindow       :: proc(hwnd: HWND, cmd_show: i32) -> BOOL #foreign
-UpdateWindow     :: proc(hwnd: HWND) -> BOOL #foreign
+TranslateMessage :: proc(msg: ^MSG) -> BOOL                 #foreign
+DispatchMessageA :: proc(msg: ^MSG) -> LRESULT              #foreign
+UpdateWindow     :: proc(hwnd: HWND) -> BOOL                #foreign
 PeekMessageA     :: proc(msg: ^MSG, hwnd: HWND,
                          msg_filter_min, msg_filter_max, remove_msg: u32) -> BOOL #foreign
-TranslateMessage :: proc(msg: ^MSG) -> BOOL #foreign
-DispatchMessageA :: proc(msg: ^MSG) -> LRESULT #foreign
 
 DefWindowProcA   :: proc(hwnd: HWND, msg: u32, wparam: WPARAM, lparam: LPARAM) -> LRESULT #foreign
 

+ 13 - 3
src/checker/checker.cpp

@@ -118,6 +118,7 @@ struct Scope {
 	b32 is_global;
 	b32 is_file;
 	b32 is_init;
+	AstFile *file;
 };
 
 enum ExprKind {
@@ -635,6 +636,10 @@ void add_entity_use(CheckerInfo *i, AstNode *identifier, Entity *entity) {
 	GB_ASSERT(identifier->kind == AstNode_Ident);
 	HashKey key = hash_pointer(identifier);
 	map_set(&i->uses, key, entity);
+
+	if (entity != NULL && entity->kind == Entity_ImportName) {
+		entity->ImportName.used = true;
+	}
 }
 
 
@@ -820,8 +825,10 @@ void check_parsed_files(Checker *c) {
 		scope = make_scope(c->global_scope, c->allocator);
 		scope->is_global = f->is_global_scope;
 		scope->is_file   = true;
+		scope->file      = f;
 		if (i == 0) {
 			// NOTE(bill): First file is always the initial file
+			// thus it must contain main
 			scope->is_init = true;
 		}
 
@@ -830,7 +837,8 @@ void check_parsed_files(Checker *c) {
 		}
 
 		f->scope = scope;
-		map_set(&file_scopes, hash_string(f->tokenizer.fullpath), scope);
+		HashKey key = hash_string(f->tokenizer.fullpath);
+		map_set(&file_scopes, key, scope);
 	}
 
 	// Collect Entities
@@ -980,6 +988,7 @@ void check_parsed_files(Checker *c) {
 					}
 				}
 			} else {
+				GB_ASSERT(id->import_name.string.len > 0);
 				Entity *e = make_entity_import_name(c->allocator, file_scope, id->import_name, t_invalid,
 				                                    id->fullpath, id->import_name.string,
 				                                    scope);
@@ -995,10 +1004,11 @@ void check_parsed_files(Checker *c) {
 			if (e->kind == kind) {
 				DeclInfo *d = entry->value;
 
+				add_curr_ast_file(c, d->scope->file);
+
 				Scope *prev_scope = c->context.scope;
 				c->context.scope = d->scope;
-				defer (c->context.scope = prev_scope);
-
+				GB_ASSERT(d->scope == e->scope);
 				check_entity_decl(c, e, d, NULL);
 			}
 		}

+ 20 - 12
src/checker/expr.cpp

@@ -287,7 +287,6 @@ void check_fields(Checker *c, AstNode *node, AstNodeArray decls,
 
 			Entity *e = make_entity_type_name(c->allocator, c->context.scope, name_token, NULL);
 			add_entity(c, c->context.scope, td->name, e);
-			gb_printf("%.*s\n", LIT(e->token.string));
 			check_type_decl(c, e, td->type, NULL, NULL);
 
 			HashKey key = hash_string(name_token.string);
@@ -734,8 +733,25 @@ void check_identifier(Checker *c, Operand *o, AstNode *n, Type *named_type, Cycl
 		if (are_strings_equal(n->Ident.string, make_string("_"))) {
 			error(&c->error_collector, n->Ident, "`_` cannot be used as a value type");
 		} else {
+			auto *entries = c->context.scope->elements.entries;
+			// gb_for_array(i, entries) {
+			// 	Entity *elem = entries[i].value;
+			// 	if (i > 0)  {
+			// 		gb_printf(", ");
+			// 	}
+			// 	gb_printf("%.*s", LIT(elem->token.string));
+			// }
+			// for (Scope *s = c->context.scope; s != NULL; s = s->parent) {
+			// 	Entity *elem = s->elements.entries[0].value;
+			// 	if (elem == NULL) continue;
+			// 	gb_printf("%.*s\n", LIT(elem->token.pos.file));
+			// }
+			// gb_printf("\n");
+
+
+			// Entity *e = scope_lookup_entity(c->context.scope, n->Ident.string);
 			error(&c->error_collector, n->Ident,
-			    "Undeclared named: `%.*s`", LIT(n->Ident.string));
+			      "Undeclared name: %.*s", LIT(n->Ident.string));
 		}
 		return;
 	}
@@ -915,11 +931,9 @@ Type *check_type(Checker *c, AstNode *e, Type *named_type, CycleChecker *cycle_c
 			type = make_type_array(c->allocator,
 			                       check_type(c, at->elem, NULL, cycle_checker),
 			                       check_array_count(c, at->count));
-			type->flags |= e->type_flags;
 			set_base_type(named_type, type);
 		} else {
 			type = make_type_slice(c->allocator, check_type(c, at->elem));
-			type->flags |= e->type_flags;
 			set_base_type(named_type, type);
 		}
 		goto end;
@@ -935,7 +949,6 @@ Type *check_type(Checker *c, AstNode *e, Type *named_type, CycleChecker *cycle_c
 			error(&c->error_collector, ast_node_token(vt->elem), "Vector element type must be numerical or a boolean. Got `%s`", err_str);
 		}
 		type = make_type_vector(c->allocator, elem, count);
-		type->flags |= e->type_flags;
 		set_base_type(named_type, type);
 		goto end;
 	case_end;
@@ -947,7 +960,6 @@ Type *check_type(Checker *c, AstNode *e, Type *named_type, CycleChecker *cycle_c
 		check_struct_type(c, type, e, cycle_checker);
 		check_close_scope(c);
 		type->Record.node = e;
-		type->flags |= e->type_flags;
 		goto end;
 	case_end;
 
@@ -958,7 +970,6 @@ Type *check_type(Checker *c, AstNode *e, Type *named_type, CycleChecker *cycle_c
 		check_union_type(c, type, e, cycle_checker);
 		check_close_scope(c);
 		type->Record.node = e;
-		type->flags |= e->type_flags;
 		goto end;
 	case_end;
 
@@ -969,7 +980,6 @@ Type *check_type(Checker *c, AstNode *e, Type *named_type, CycleChecker *cycle_c
 		check_raw_union_type(c, type, e, cycle_checker);
 		check_close_scope(c);
 		type->Record.node = e;
-		type->flags |= e->type_flags;
 		goto end;
 	case_end;
 
@@ -978,22 +988,21 @@ Type *check_type(Checker *c, AstNode *e, Type *named_type, CycleChecker *cycle_c
 		set_base_type(named_type, type);
 		check_enum_type(c, type, named_type, e);
 		type->Record.node = e;
-		type->flags |= e->type_flags;
 		goto end;
 	case_end;
 
 	case_ast_node(pt, PointerType, e);
 		type = make_type_pointer(c->allocator, check_type(c, pt->type));
-		type->flags |= e->type_flags;
 		set_base_type(named_type, type);
 		goto end;
 	case_end;
 
 	case_ast_node(pt, ProcType, e);
 		type = alloc_type(c->allocator, Type_Proc);
-		type->flags |= e->type_flags;
 		set_base_type(named_type, type);
+		check_open_scope(c, e);
 		check_procedure_type(c, type, e);
+		check_close_scope(c);
 		goto end;
 	case_end;
 
@@ -1003,7 +1012,6 @@ Type *check_type(Checker *c, AstNode *e, Type *named_type, CycleChecker *cycle_c
 			check_expr_or_type(c, &o, e);
 			if (o.mode == Addressing_Type) {
 				type = o.type;
-				type->flags |= e->type_flags;
 				goto end;
 			}
 		}

+ 35 - 22
src/checker/stmt.cpp

@@ -446,7 +446,7 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d, b32 check_body_later) {
 	// add_proc_entity(c, d->scope, pd->name, e);
 	if (d->scope->is_proc) {
 		// Nested procedures
-		add_entity(c, d->scope, pd->name, e);
+		add_entity(c, d->scope->parent, pd->name, e);
 	}
 
 
@@ -562,11 +562,7 @@ void check_var_decl(Checker *c, Entity *e, Entity **entities, isize entity_count
 
 void check_entity_decl(Checker *c, Entity *e, DeclInfo *d, Type *named_type, CycleChecker *cycle_checker) {
 	if (e->type != NULL) {
-		if (e->type->kind == Type_Named && e->type->Named.base == NULL) {
-			// NOTE(bill): Some weird declaration error from Entity_ImportName
-		} else {
-			return;
-		}
+		return;
 	}
 
 	if (d == NULL) {
@@ -578,26 +574,42 @@ void check_entity_decl(Checker *c, Entity *e, DeclInfo *d, Type *named_type, Cyc
 		}
 	}
 
+	c->context.decl = d;
+
+	if (e->kind == Entity_Procedure) {
+		check_proc_decl(c, e, d, true);
+		return;
+	}
+
+
+
 	switch (e->kind) {
 	case Entity_Constant: {
 		Scope *prev = c->context.scope;
 		c->context.scope = d->scope;
-		c->context.decl = d;
+		defer (c->context.scope = prev);
 
 		check_const_decl(c, e, d->type_expr, d->init_expr);
-
-		c->context.scope = prev;
 	} break;
+
 	case Entity_Variable: {
 		Scope *prev = c->context.scope;
 		c->context.scope = d->scope;
-		c->context.decl = d;
+		defer (c->context.scope = prev);
 
 		check_var_decl(c, e, d->entities, d->entity_count, d->type_expr, d->init_expr);
+	} break;
 
-		c->context.scope = prev;
+	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);

+ 5 - 4
src/parser.cpp

@@ -2539,18 +2539,19 @@ AstNode *parse_stmt(AstFile *f) {
 	case Token_Hash: {
 		s = parse_tag_stmt(f, NULL);
 		String tag = s->TagStmt.name.string;
-		if (are_strings_equal(tag, make_string("global_scope"))) {
+		if (are_strings_equal(tag, make_string("shared_global_scope"))) {
 			if (f->curr_proc == NULL) {
 				f->is_global_scope = true;
 				return make_empty_stmt(f, f->cursor[0]);
 			}
-			ast_file_err(f, token, "You cannot use #global_scope within a procedure. This must be done at the file scope.");
+			ast_file_err(f, token, "You cannot use #shared_global_scope within a procedure. This must be done at the file scope.");
 			return make_bad_decl(f, token, f->cursor[0]);
 		} else if (are_strings_equal(tag, make_string("import"))) {
 			// TODO(bill): better error messages
+			Token import_name;
 			Token file_path = expect_token(f, Token_String);
-			Token as = expect_token(f, Token_as);
-			Token import_name = expect_token(f, Token_Identifier);
+			expect_token(f, Token_as);
+			import_name = expect_token(f, Token_Identifier);
 
 			if (f->curr_proc == NULL) {
 				return make_import_decl(f, s->TagStmt.token, file_path, import_name);