Browse Source

#import search rule: relative then core/

Ginger Bill 9 years ago
parent
commit
2d6171f3e5
10 changed files with 81 additions and 1621 deletions
  1. 9 9
      build.bat
  2. 0 583
      code/fmt.odin
  3. 0 49
      code/opengl.odin
  4. 0 107
      code/os.odin
  5. 0 353
      code/runtime.odin
  6. 0 451
      code/win32.odin
  7. 9 2
      src/checker/checker.cpp
  8. 61 21
      src/parser.cpp
  9. 2 1
      src/string.cpp
  10. 0 45
      syntax.odin

+ 9 - 9
build.bat

@@ -31,32 +31,32 @@ set linker_flags= -incremental:no -opt:ref -subsystem:console
 
 if %release_mode% EQU 0 ( rem Debug
 	set linker_flags=%linker_flags% -debug
-	set libs=%libs% ..\src\utf8proc\utf8proc_debug.lib
+	set libs=%libs% src\utf8proc\utf8proc_debug.lib
 ) else ( rem Release
 	set linker_flags=%linker_flags%
-	set libs=%libs% ..\src\utf8proc\utf8proc.lib
+	set libs=%libs% src\utf8proc\utf8proc.lib
 )
 
 set compiler_settings=%compiler_includes% %compiler_flags% %compiler_warnings%
 set linker_settings=%libs% %linker_flags%
 
 
-set build_dir= "bin\"
-if not exist %build_dir% mkdir %build_dir%
-pushd %build_dir%
+rem set build_dir= "\"
+rem if not exist %build_dir% mkdir %build_dir%
+rem pushd %build_dir%
 	del *.pdb > NUL 2> NUL
 	del *.ilk > NUL 2> NUL
 
 	del ..\misc\*.pdb > NUL 2> NUL
 	del ..\misc\*.ilk > NUL 2> NUL
 
-	cl %compiler_settings% "..\src\main.cpp" ^
+	cl %compiler_settings% "src\main.cpp" ^
 		/link %linker_settings% -OUT:%exe_name% ^
-	&& odin run ..\code/demo.odin
-	rem odin run ..\code/demo.odin
+	&& odin run code/demo.odin
+	rem odin run code/demo.odin
 
 
 	:do_not_compile_exe
-popd
+rem popd
 :end_of_build
 

+ 0 - 583
code/fmt.odin

@@ -1,583 +0,0 @@
-#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.get_standard_file(os.File_Standard.OUTPUT), fmt, ..args)
-}
-print_err :: proc(fmt: string, args: ..any) {
-	print_to_file(os.get_standard_file(os.File_Standard.ERROR), fmt, ..args)
-}
-println :: proc(fmt: string, args: ..any) {
-	println_to_file(os.get_standard_file(os.File_Standard.OUTPUT), fmt, ..args)
-}
-println_err :: proc(fmt: string, args: ..any) {
-	println_to_file(os.get_standard_file(os.File_Standard.ERROR), fmt, ..args)
-}

+ 0 - 49
code/opengl.odin

@@ -1,49 +0,0 @@
-#foreign_system_library "opengl32"
-
-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
-
-NEAREST :: 0x2600
-LINEAR  :: 0x2601
-
-DEPTH_BUFFER_BIT   :: 0x00000100
-STENCIL_BUFFER_BIT :: 0x00000400
-COLOR_BUFFER_BIT   :: 0x00004000
-
-TEXTURE_MAX_ANISOTROPY_EXT :: 0x84fe
-
-TEXTURE_MAG_FILTER  :: 0x2800
-TEXTURE_MIN_FILTER  :: 0x2801
-TEXTURE_WRAP_S      :: 0x2802
-TEXTURE_WRAP_T      :: 0x2803
-
-Clear          :: proc(mask: u32)                                #foreign "glClear"
-ClearColor     :: 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"
-TexCoord2f     :: proc(u, v: f32)                                #foreign "glTexCoord2f"
-LoadIdentity   :: proc()                                         #foreign "glLoadIdentity"
-Ortho          :: proc(left, right, bottom, top, near, far: f64) #foreign "glOrtho"
-BlendFunc      :: proc(sfactor, dfactor: i32)                    #foreign "glBlendFunc"
-Enable         :: proc(cap: i32)                                 #foreign "glEnable"
-Disable        :: proc(cap: i32)                                 #foreign "glDisable"
-GenTextures    :: proc(count: i32, result: ^u32)                 #foreign "glGenTextures"
-TexParameteri  :: proc(target, pname, param: i32)                #foreign "glTexParameteri"
-TexParameterf  :: proc(target: i32, pname: i32, param: f32)      #foreign "glTexParameterf"
-BindTexture    :: proc(target: i32, texture: u32)                #foreign "glBindTexture"
-TexImage2D     :: proc(target, level, internal_format, width, height, border, format, _type: i32, pixels: rawptr) #foreign "glTexImage2D"
-

+ 0 - 107
code/os.odin

@@ -1,107 +0,0 @@
-#import "runtime.odin" as _ // TODO(bill): make the compile import this automatically
-#import "win32.odin" as win32
-
-File :: type struct {
-	Handle :: type win32.HANDLE
-	handle: Handle
-}
-
-open :: proc(name: string) -> (File, bool) {
-	using win32
-	buf: [300]byte
-	copy(buf[:], name as []byte)
-	f := File{CreateFileA(^buf[0], FILE_GENERIC_READ, FILE_SHARE_READ, null, OPEN_EXISTING, 0, null)}
-	success := f.handle != INVALID_HANDLE_VALUE as File.Handle
-
-	return f, success
-}
-
-create :: proc(name: string) -> (File, bool) {
-	using win32
-	buf: [300]byte
-	copy(buf[:], name as []byte)
-	f := File{
-		handle = CreateFileA(^buf[0], FILE_GENERIC_WRITE, FILE_SHARE_READ, null, CREATE_ALWAYS, 0, null),
-	}
-	success := f.handle != INVALID_HANDLE_VALUE as File.Handle
-	return f, success
-}
-
-
-close :: proc(using f: ^File) {
-	win32.CloseHandle(handle)
-}
-
-write :: proc(using f: ^File, buf: []byte) -> bool {
-	bytes_written: i32
-	return win32.WriteFile(handle, buf.data, buf.count as i32, ^bytes_written, null) != 0
-}
-
-
-File_Standard :: type enum {
-	INPUT,
-	OUTPUT,
-	ERROR,
-	COUNT,
-}
-
-__std_files := __set_file_standards();
-
-__set_file_standards :: proc() -> [File_Standard.COUNT as int]File {
-	return [File_Standard.COUNT as int]File{
-		File{handle = win32.GetStdHandle(win32.STD_INPUT_HANDLE)},
-		File{handle = win32.GetStdHandle(win32.STD_OUTPUT_HANDLE)},
-		File{handle = win32.GetStdHandle(win32.STD_ERROR_HANDLE)},
-	}
-}
-
-get_standard_file :: proc(std: File_Standard) -> ^File {
-	return ^__std_files[std]
-}
-
-
-read_entire_file :: proc(name: string) -> (string, bool) {
-	buf: [300]byte
-	copy(buf[:], name as []byte)
-
-	f, file_ok := open(name)
-	if !file_ok {
-		return "", false
-	}
-	defer close(^f)
-
-	length: i64
-	file_size_ok := win32.GetFileSizeEx(f.handle as win32.HANDLE, ^length) != 0
-	if !file_size_ok {
-		return "", false
-	}
-
-	data := new_slice(u8, length)
-	if data.data == null {
-		return "", false
-	}
-
-	single_read_length: i32
-	total_read: i64
-
-	for total_read < length {
-		remaining := length - total_read
-		to_read: u32
-		MAX :: 1<<32-1
-		if remaining <= MAX {
-			to_read = remaining as u32
-		} else {
-			to_read = MAX
-		}
-
-		win32.ReadFile(f.handle as win32.HANDLE, ^data[total_read], to_read, ^single_read_length, null)
-		if single_read_length <= 0 {
-			free(data.data)
-			return "", false
-		}
-
-		total_read += single_read_length as i64
-	}
-
-	return data as string, true
-}

+ 0 - 353
code/runtime.odin

@@ -1,353 +0,0 @@
-#shared_global_scope
-
-// IMPORTANT NOTE(bill): Do not change the order of any of this data
-// The compiler relies upon this _exact_ order
-Type_Info :: union {
-	Member :: struct #ordered {
-		name:      string     // can be empty if tuple
-		type_info: ^Type_Info
-		offset:    int        // offsets are not used in tuples
-	}
-	Record :: struct #ordered {
-		fields:  []Member
-		packed:  bool
-		ordered: bool
-	}
-
-
-	Named: struct #ordered {
-		name: string
-		base: ^Type_Info
-	}
-	Integer: struct #ordered {
-		size:   int // in bytes
-		signed: bool
-	}
-	Float: struct #ordered {
-		size: int // in bytes
-	}
-	String:  struct #ordered {}
-	Boolean: struct #ordered {}
-	Pointer: struct #ordered {
-		elem: ^Type_Info
-	}
-	Procedure: struct #ordered {
-		params:   ^Type_Info // Type_Info.Tuple
-		results:  ^Type_Info // Type_Info.Tuple
-		variadic: bool
-	}
-	Array: struct #ordered {
-		elem:      ^Type_Info
-		elem_size: int
-		count:     int
-	}
-	Slice: struct #ordered {
-		elem:      ^Type_Info
-		elem_size: int
-	}
-	Vector: struct #ordered {
-		elem:      ^Type_Info
-		elem_size: int
-		count:     int
-	}
-	Tuple:     Record
-	Struct:    Record
-	Union:     Record
-	Raw_Union: Record
-	Enum: struct #ordered {
-		base: ^Type_Info
-	}
-}
-
-
-
-assume :: proc(cond: bool) #foreign "llvm.assume"
-
-__debug_trap       :: proc()        #foreign "llvm.debugtrap"
-__trap             :: proc()        #foreign "llvm.trap"
-read_cycle_counter :: proc() -> u64 #foreign "llvm.readcyclecounter"
-
-bit_reverse16 :: proc(b: u16) -> u16 #foreign "llvm.bitreverse.i16"
-bit_reverse32 :: proc(b: u32) -> u32 #foreign "llvm.bitreverse.i32"
-bit_reverse64 :: proc(b: u64) -> u64 #foreign "llvm.bitreverse.i64"
-
-byte_swap16 :: proc(b: u16) -> u16 #foreign "llvm.bswap.i16"
-byte_swap32 :: proc(b: u32) -> u32 #foreign "llvm.bswap.i32"
-byte_swap64 :: proc(b: u64) -> u64 #foreign "llvm.bswap.i64"
-
-fmuladd32 :: proc(a, b, c: f32) -> f32 #foreign "llvm.fmuladd.f32"
-fmuladd64 :: proc(a, b, c: f64) -> f64 #foreign "llvm.fmuladd.f64"
-
-heap_alloc :: proc(len: int) -> rawptr {
-	c_malloc :: proc(len: int) -> rawptr #foreign "malloc"
-	return c_malloc(len)
-}
-
-heap_free :: proc(ptr: rawptr) {
-	c_free :: proc(ptr: rawptr) #foreign "free"
-	c_free(ptr)
-}
-
-current_thread_id :: proc() -> int {
-	GetCurrentThreadId :: proc() -> u32 #foreign #dll_import
-	return GetCurrentThreadId() as int
-}
-
-memory_zero :: proc(data: rawptr, len: int) {
-	llvm_memset_64bit :: proc(dst: rawptr, val: byte, len: int, align: i32, is_volatile: bool) #foreign "llvm.memset.p0i8.i64"
-	llvm_memset_64bit(data, 0, len, 1, false)
-}
-
-memory_compare :: proc(dst, src: rawptr, len: int) -> int {
-	// TODO(bill): make a faster `memory_compare`
-	a := slice_ptr(dst as ^byte, len)
-	b := slice_ptr(src as ^byte, len)
-	for i := 0; i < len; i++ {
-		if a[i] != b[i] {
-			return (a[i] - b[i]) as int
-		}
-	}
-	return 0
-}
-
-memory_copy :: proc(dst, src: rawptr, len: int) #inline {
-	llvm_memmove_64bit :: proc(dst, src: rawptr, len: int, align: i32, is_volatile: bool) #foreign "llvm.memmove.p0i8.p0i8.i64"
-	llvm_memmove_64bit(dst, src, len, 1, false)
-}
-
-__string_eq :: proc(a, b: string) -> bool {
-	if a.count != b.count {
-		return false
-	}
-	if ^a[0] == ^b[0] {
-		return true
-	}
-	return memory_compare(^a[0], ^b[0], a.count) == 0
-}
-
-__string_cmp :: proc(a, b : string) -> int {
-	// Translation of http://mgronhol.github.io/fast-strcmp/
-	n := min(a.count, b.count)
-
-	fast := n/size_of(int) + 1
-	offset := (fast-1)*size_of(int)
-	curr_block := 0
-	if n <= size_of(int) {
-		fast = 0
-	}
-
-	la := slice_ptr(^a[0] as ^int, fast)
-	lb := slice_ptr(^b[0] as ^int, fast)
-
-	for ; curr_block < fast; curr_block++ {
-		if (la[curr_block] ~ lb[curr_block]) != 0 {
-			for pos := curr_block*size_of(int); pos < n; pos++ {
-				if (a[pos] ~ b[pos]) != 0 {
-					return a[pos] as int - b[pos] as int
-				}
-			}
-		}
-
-	}
-
-	for ; offset < n; offset++ {
-		if (a[offset] ~ b[offset]) != 0 {
-			return a[offset] as int - b[offset] as int
-		}
-	}
-
-	return 0
-}
-
-__string_ne :: proc(a, b : string) -> bool #inline { return !__string_eq(a, b) }
-__string_lt :: proc(a, b : string) -> bool #inline { return __string_cmp(a, b) < 0 }
-__string_gt :: proc(a, b : string) -> bool #inline { return __string_cmp(a, b) > 0 }
-__string_le :: proc(a, b : string) -> bool #inline { return __string_cmp(a, b) <= 0 }
-__string_ge :: proc(a, b : string) -> bool #inline { return __string_cmp(a, b) >= 0 }
-
-__print_err_str :: proc(s: string) {
-
-}
-__print_err_int :: proc(i: int) {
-
-}
-
-__assert :: proc(msg: string) {
-	// TODO(bill): Write message
-	__print_err_str(msg)
-	__debug_trap()
-}
-
-__bounds_check_error :: proc(file: string, line, column: int,
-                             index, count: int) {
-	if 0 <= index && index < count {
-		return
-	}
-	// TODO(bill): Write message
-	// TODO(bill): Probably reduce the need for `print` in the runtime if possible
-	// fmt.println_err("%(%:%) Index % is out of bounds range [0, %)",
-	//                 file, line, column, index, count)
-	__debug_trap()
-}
-
-__slice_expr_error :: proc(file: string, line, column: int,
-                           low, high, max: int) {
-	if 0 <= low && low <= high && high <= max {
-		return
-	}
-	// TODO(bill): Write message
-	// fmt.println_err("%(%:%) Invalid slice indices: [%:%:%]",
-	//                 file, line, column, low, high, max)
-	__debug_trap()
-}
-__substring_expr_error :: proc(file: string, line, column: int,
-                               low, high: int) {
-	if 0 <= low && low <= high {
-		return
-	}
-	// TODO(bill): Write message
-	// fmt.println_err("%(%:%) Invalid substring indices: [%:%:%]",
-	//                 file, line, column, low, high)
-	__debug_trap()
-}
-
-
-
-
-
-
-
-
-
-
-
-Allocator :: struct {
-	Mode :: enum {
-		ALLOC,
-		FREE,
-		FREE_ALL,
-		RESIZE,
-	}
-	Proc :: type proc(allocator_data: rawptr, mode: Mode,
-	                  size, alignment: int,
-	                  old_memory: rawptr, old_size: int, flags: u64) -> rawptr
-
-
-	procedure: Proc;
-	data:      rawptr
-}
-
-
-Context :: struct {
-	thread_id: int
-
-	allocator: Allocator
-
-	user_data:  rawptr
-	user_index: int
-}
-
-#thread_local __context: Context
-
-
-DEFAULT_ALIGNMENT :: align_of({4}f32)
-
-
-current_context :: proc() -> ^Context {
-	return ^__context
-}
-
-__check_context :: proc() {
-	c := current_context()
-	assert(c != null)
-
-	if c.allocator.procedure == null {
-		c.allocator = __default_allocator()
-	}
-	if c.thread_id == 0 {
-		c.thread_id = current_thread_id()
-	}
-}
-
-alloc :: proc(size: int) -> rawptr #inline { return alloc_align(size, DEFAULT_ALIGNMENT) }
-
-alloc_align :: proc(size, alignment: int) -> rawptr #inline {
-	__check_context()
-	a := current_context().allocator
-	return a.procedure(a.data, Allocator.Mode.ALLOC, size, alignment, null, 0, 0)
-}
-
-free :: proc(ptr: rawptr) #inline {
-	__check_context()
-	a := current_context().allocator
-	_ = a.procedure(a.data, Allocator.Mode.FREE, 0, 0, ptr, 0, 0)
-}
-free_all :: proc() #inline {
-	__check_context()
-	a := current_context().allocator
-	_ = a.procedure(a.data, Allocator.Mode.FREE_ALL, 0, 0, null, 0, 0)
-}
-
-
-resize       :: proc(ptr: rawptr, old_size, new_size: int) -> rawptr #inline { return resize_align(ptr, old_size, new_size, DEFAULT_ALIGNMENT) }
-resize_align :: proc(ptr: rawptr, old_size, new_size, alignment: int) -> rawptr #inline {
-	a := current_context().allocator
-	return a.procedure(a.data, Allocator.Mode.RESIZE, new_size, alignment, ptr, old_size, 0)
-}
-
-
-
-default_resize_align :: proc(old_memory: rawptr, old_size, new_size, alignment: int) -> rawptr {
-	if old_memory == null {
-		return alloc_align(new_size, alignment)
-	}
-
-	if new_size == 0 {
-		free(old_memory)
-		return null
-	}
-
-	if new_size == old_size {
-		return old_memory
-	}
-
-	new_memory := alloc_align(new_size, alignment)
-	if new_memory == null {
-		return null
-	}
-
-	memory_copy(new_memory, old_memory, min(old_size, new_size));
-	free(old_memory)
-	return new_memory
-}
-
-
-__default_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator.Mode,
-                                 size, alignment: int,
-                                 old_memory: rawptr, old_size: int, flags: u64) -> rawptr {
-	using Allocator.Mode
-	match mode {
-	case ALLOC:
-		return heap_alloc(size)
-	case RESIZE:
-		return default_resize_align(old_memory, old_size, size, alignment)
-	case FREE:
-		heap_free(old_memory)
-		return null
-	case FREE_ALL:
-		// NOTE(bill): Does nothing
-	}
-
-	return null
-}
-
-__default_allocator :: proc() -> Allocator {
-	return Allocator{
-		procedure = __default_allocator_proc,
-		data = null,
-	}
-}
-
-
-
-

+ 0 - 451
code/win32.odin

@@ -1,451 +0,0 @@
-#foreign_system_library "user32"
-#foreign_system_library "gdi32"
-
-HANDLE    :: type rawptr
-HWND      :: type HANDLE
-HDC       :: type HANDLE
-HINSTANCE :: type HANDLE
-HICON     :: type HANDLE
-HCURSOR   :: type HANDLE
-HMENU     :: type HANDLE
-HBRUSH    :: type HANDLE
-HGDIOBJ   :: type HANDLE
-WPARAM    :: type uint
-LPARAM    :: type int
-LRESULT   :: type int
-ATOM      :: type i16
-BOOL      :: type i32
-WNDPROC   :: type proc(hwnd: HWND, msg: u32, wparam: WPARAM, lparam: LPARAM) -> LRESULT
-
-INVALID_HANDLE_VALUE :: (-1 as int) as HANDLE
-
-CS_VREDRAW    :: 0x0001
-CS_HREDRAW    :: 0x0002
-CS_OWNDC      :: 0x0020
-CW_USEDEFAULT :: 0x80000000
-
-WS_OVERLAPPED       :: 0
-WS_MAXIMIZEBOX      :: 0x00010000
-WS_MINIMIZEBOX      :: 0x00020000
-WS_THICKFRAME       :: 0x00040000
-WS_SYSMENU          :: 0x00080000
-WS_CAPTION          :: 0x00C00000
-WS_VISIBLE          :: 0x10000000
-WS_OVERLAPPEDWINDOW :: WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU|WS_THICKFRAME|WS_MINIMIZEBOX|WS_MAXIMIZEBOX
-
-WM_DESTROY :: 0x0002
-WM_CLOSE   :: 0x0010
-WM_QUIT    :: 0x0012
-WM_KEYDOWN :: 0x0100
-WM_KEYUP   :: 0x0101
-
-PM_REMOVE :: 1
-
-COLOR_BACKGROUND :: 1 as HBRUSH
-BLACK_BRUSH :: 4
-
-SM_CXSCREEN :: 0
-SM_CYSCREEN :: 1
-
-SW_SHOW :: 5
-
-POINT :: struct #ordered {
-	x, y: i32
-}
-
-
-WNDCLASSEXA :: struct #ordered {
-	size, style:           u32
-	wnd_proc:              WNDPROC
-	cls_extra, wnd_extra:  i32
-	instance:              HINSTANCE
-	icon:                  HICON
-	cursor:                HCURSOR
-	background:            HBRUSH
-	menu_name, class_name: ^u8
-	sm:                    HICON
-}
-
-MSG :: struct #ordered {
-	hwnd:    HWND
-	message: u32
-	wparam:  WPARAM
-	lparam:  LPARAM
-	time:    u32
-	pt:      POINT
-}
-
-RECT :: struct #ordered {
-	left:   i32
-	top:    i32
-	right:  i32
-	bottom: i32
-}
-
-
-GetLastError     :: proc() -> i32                           #foreign #dll_import
-ExitProcess      :: proc(exit_code: u32)                    #foreign #dll_import
-GetDesktopWindow :: proc() -> HWND                          #foreign #dll_import
-GetCursorPos     :: proc(p: ^POINT) -> i32                  #foreign #dll_import
-ScreenToClient   :: proc(h: HWND, p: ^POINT) -> i32         #foreign #dll_import
-GetModuleHandleA :: proc(module_name: ^u8) -> HINSTANCE     #foreign #dll_import
-GetStockObject   :: proc(fn_object: i32) -> HGDIOBJ         #foreign #dll_import
-PostQuitMessage  :: proc(exit_code: i32)                    #foreign #dll_import
-SetWindowTextA   :: proc(hwnd: HWND, c_string: ^u8) -> BOOL #foreign #dll_import
-
-QueryPerformanceFrequency :: proc(result: ^i64) -> i32 #foreign #dll_import
-QueryPerformanceCounter   :: proc(result: ^i64) -> i32 #foreign #dll_import
-
-Sleep :: proc(ms: i32) -> i32 #foreign #dll_import
-
-OutputDebugStringA :: proc(c_str: ^u8) #foreign #dll_import
-
-
-RegisterClassExA :: proc(wc: ^WNDCLASSEXA) -> ATOM #foreign #dll_import
-CreateWindowExA  :: proc(ex_style: u32,
-                         class_name, title: ^u8,
-                         style: u32,
-                         x, y, w, h: i32,
-                         parent: HWND, menu: HMENU, instance: HINSTANCE,
-                         param: rawptr) -> HWND #foreign #dll_import
-
-ShowWindow       :: proc(hwnd: HWND, cmd_show: i32) -> BOOL #foreign #dll_import
-TranslateMessage :: proc(msg: ^MSG) -> BOOL                 #foreign #dll_import
-DispatchMessageA :: proc(msg: ^MSG) -> LRESULT              #foreign #dll_import
-UpdateWindow     :: proc(hwnd: HWND) -> BOOL                #foreign #dll_import
-PeekMessageA     :: proc(msg: ^MSG, hwnd: HWND,
-                         msg_filter_min, msg_filter_max, remove_msg: u32) -> BOOL #foreign #dll_import
-
-DefWindowProcA   :: proc(hwnd: HWND, msg: u32, wparam: WPARAM, lparam: LPARAM) -> LRESULT #foreign #dll_import
-
-AdjustWindowRect :: proc(rect: ^RECT, style: u32, menu: BOOL) -> BOOL #foreign #dll_import
-
-
-GetQueryPerformanceFrequency :: proc() -> i64 {
-	r: i64
-	QueryPerformanceFrequency(^r)
-	return r
-}
-
-GetCommandLineA :: proc() -> ^u8 #foreign #dll_import
-GetSystemMetrics :: proc(index: i32) -> i32 #foreign #dll_import
-GetCurrentThreadId :: proc() -> u32 #foreign #dll_import
-
-// File Stuff
-
-CloseHandle  :: proc(h: HANDLE) -> i32 #foreign #dll_import
-GetStdHandle :: proc(h: i32) -> HANDLE #foreign #dll_import
-CreateFileA  :: proc(filename: ^u8, desired_access, share_mode: u32,
-                     security: rawptr,
-                     creation, flags_and_attribs: u32, template_file: HANDLE) -> HANDLE #foreign #dll_import
-ReadFile     :: proc(h: HANDLE, buf: rawptr, to_read: u32, bytes_read: ^i32, overlapped: rawptr) -> BOOL #foreign #dll_import
-WriteFile    :: proc(h: HANDLE, buf: rawptr, len: i32, written_result: ^i32, overlapped: rawptr) -> i32 #foreign #dll_import
-
-GetFileSizeEx :: proc(file_handle: HANDLE, file_size: ^i64) -> BOOL #foreign #dll_import
-
-FILE_SHARE_READ      :: 0x00000001
-FILE_SHARE_WRITE     :: 0x00000002
-FILE_SHARE_DELETE    :: 0x00000004
-FILE_GENERIC_ALL     :: 0x10000000
-FILE_GENERIC_EXECUTE :: 0x20000000
-FILE_GENERIC_WRITE   :: 0x40000000
-FILE_GENERIC_READ    :: 0x80000000
-
-STD_INPUT_HANDLE  :: -10
-STD_OUTPUT_HANDLE :: -11
-STD_ERROR_HANDLE  :: -12
-
-CREATE_NEW        :: 1
-CREATE_ALWAYS     :: 2
-OPEN_EXISTING     :: 3
-OPEN_ALWAYS       :: 4
-TRUNCATE_EXISTING :: 5
-
-
-HeapAlloc :: proc(h: HANDLE, flags: u32, bytes: int) -> rawptr #foreign #dll_import
-HeapFree  :: proc(h: HANDLE, flags: u32, memory: rawptr) -> BOOL #foreign #dll_import
-GetProcessHeap :: proc() -> HANDLE #foreign #dll_import
-
-
-HEAP_ZERO_MEMORY :: 0x00000008
-
-
-
-// GDI
-
-BITMAPINFO :: struct #ordered {
-	HEADER :: struct #ordered {
-		size:              u32
-		width, height:     i32
-		planes, bit_count: i16
-		compression:       u32
-		size_image:        u32
-		x_pels_per_meter:  i32
-		y_pels_per_meter:  i32
-		clr_used:          u32
-		clr_important:     u32
-	}
-	using header: HEADER
-	colors:       [1]RGBQUAD
-}
-
-
-RGBQUAD :: struct #ordered {
-	blue, green, red, reserved: byte
-}
-
-BI_RGB         :: 0
-DIB_RGB_COLORS :: 0x00
-SRCCOPY        : u32 : 0x00cc0020
-
-StretchDIBits :: proc(hdc: HDC,
-                      x_dst, y_dst, width_dst, height_dst: i32,
-                      x_src, y_src, width_src, header_src: i32,
-                      bits: rawptr, bits_info: ^BITMAPINFO,
-                      usage: u32,
-                      rop: u32) -> i32 #foreign #dll_import
-
-
-
-
-
-
-// Windows OpenGL
-
-PFD_TYPE_RGBA             :: 0
-PFD_TYPE_COLORINDEX       :: 1
-PFD_MAIN_PLANE            :: 0
-PFD_OVERLAY_PLANE         :: 1
-PFD_UNDERLAY_PLANE        :: -1
-PFD_DOUBLEBUFFER          :: 1
-PFD_STEREO                :: 2
-PFD_DRAW_TO_WINDOW        :: 4
-PFD_DRAW_TO_BITMAP        :: 8
-PFD_SUPPORT_GDI           :: 16
-PFD_SUPPORT_OPENGL        :: 32
-PFD_GENERIC_FORMAT        :: 64
-PFD_NEED_PALETTE          :: 128
-PFD_NEED_SYSTEM_PALETTE   :: 0x00000100
-PFD_SWAP_EXCHANGE         :: 0x00000200
-PFD_SWAP_COPY             :: 0x00000400
-PFD_SWAP_LAYER_BUFFERS    :: 0x00000800
-PFD_GENERIC_ACCELERATED   :: 0x00001000
-PFD_DEPTH_DONTCARE        :: 0x20000000
-PFD_DOUBLEBUFFER_DONTCARE :: 0x40000000
-PFD_STEREO_DONTCARE       :: 0x80000000
-
-HGLRC :: type HANDLE
-PROC  :: type proc()
-wglCreateContextAttribsARBType :: type proc(hdc: HDC, hshareContext: rawptr, attribList: ^i32) -> HGLRC
-
-
-PIXELFORMATDESCRIPTOR :: struct #ordered {
-	size,
-	version,
-	flags: u32
-
-	pixel_type,
-	color_bits,
-	red_bits,
-	red_shift,
-	green_bits,
-	green_shift,
-	blue_bits,
-	blue_shift,
-	alpha_bits,
-	alpha_shift,
-	accum_bits,
-	accum_red_bits,
-	accum_green_bits,
-	accum_blue_bits,
-	accum_alpha_bits,
-	depth_bits,
-	stencil_bits,
-	aux_buffers,
-	layer_type,
-	reserved: byte
-
-	layer_mask,
-	visible_mask,
-	damage_mask: u32
-}
-
-GetDC             :: proc(h: HANDLE) -> HDC #foreign
-SetPixelFormat    :: proc(hdc: HDC, pixel_format: i32, pfd: ^PIXELFORMATDESCRIPTOR ) -> BOOL #foreign #dll_import
-ChoosePixelFormat :: proc(hdc: HDC, pfd: ^PIXELFORMATDESCRIPTOR) -> i32 #foreign #dll_import
-SwapBuffers       :: proc(hdc: HDC) -> BOOL #foreign #dll_import
-ReleaseDC         :: proc(wnd: HWND, hdc: HDC) -> i32 #foreign #dll_import
-
-WGL_CONTEXT_MAJOR_VERSION_ARB             :: 0x2091
-WGL_CONTEXT_MINOR_VERSION_ARB             :: 0x2092
-WGL_CONTEXT_PROFILE_MASK_ARB              :: 0x9126
-WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB :: 0x0002
-
-wglCreateContext  :: proc(hdc: HDC) -> HGLRC #foreign #dll_import
-wglMakeCurrent    :: proc(hdc: HDC, hglrc: HGLRC) -> BOOL #foreign #dll_import
-wglGetProcAddress :: proc(c_str: ^u8) -> PROC #foreign #dll_import
-wglDeleteContext  :: proc(hglrc: HGLRC) -> BOOL #foreign #dll_import
-
-
-
-GetKeyState      :: proc(v_key: i32) -> i16 #foreign #dll_import
-GetAsyncKeyState :: proc(v_key: i32) -> i16 #foreign #dll_import
-
-is_key_down :: proc(key: Key_Code) -> bool {
-	return GetAsyncKeyState(key as i32) < 0
-}
-
-Key_Code :: enum i32 {
-	LBUTTON    = 0x01,
-	RBUTTON    = 0x02,
-	CANCEL     = 0x03,
-	MBUTTON    = 0x04,
-
-	BACK       = 0x08,
-	TAB        = 0x09,
-
-	CLEAR      = 0x0C,
-	RETURN     = 0x0D,
-
-	SHIFT      = 0x10,
-	CONTROL    = 0x11,
-	MENU       = 0x12,
-	PAUSE      = 0x13,
-	CAPITAL    = 0x14,
-
-	KANA       = 0x15,
-	HANGEUL    = 0x15,
-	HANGUL     = 0x15,
-	JUNJA      = 0x17,
-	FINAL      = 0x18,
-	HANJA      = 0x19,
-	KANJI      = 0x19,
-
-	ESCAPE     = 0x1B,
-
-	CONVERT    = 0x1C,
-	NONCONVERT = 0x1D,
-	ACCEPT     = 0x1E,
-	MODECHANGE = 0x1F,
-
-	SPACE      = 0x20,
-	PRIOR      = 0x21,
-	NEXT       = 0x22,
-	END        = 0x23,
-	HOME       = 0x24,
-	LEFT       = 0x25,
-	UP         = 0x26,
-	RIGHT      = 0x27,
-	DOWN       = 0x28,
-	SELECT     = 0x29,
-	PRINT      = 0x2A,
-	EXECUTE    = 0x2B,
-	SNAPSHOT   = 0x2C,
-	INSERT     = 0x2D,
-	DELETE     = 0x2E,
-	HELP       = 0x2F,
-
-	NUM0 = #rune "0",
-	NUM1 = #rune "1",
-	NUM2 = #rune "2",
-	NUM3 = #rune "3",
-	NUM4 = #rune "4",
-	NUM5 = #rune "5",
-	NUM6 = #rune "6",
-	NUM7 = #rune "7",
-	NUM8 = #rune "8",
-	NUM9 = #rune "9",
-
-	A = #rune "A",
-	B = #rune "B",
-	C = #rune "C",
-	D = #rune "D",
-	E = #rune "E",
-	F = #rune "F",
-	G = #rune "G",
-	H = #rune "H",
-	I = #rune "I",
-	J = #rune "J",
-	K = #rune "K",
-	L = #rune "L",
-	M = #rune "M",
-	N = #rune "N",
-	O = #rune "O",
-	P = #rune "P",
-	Q = #rune "Q",
-	R = #rune "R",
-	S = #rune "S",
-	T = #rune "T",
-	U = #rune "U",
-	V = #rune "V",
-	W = #rune "W",
-	X = #rune "X",
-	Y = #rune "Y",
-	Z = #rune "Z",
-
-	LWIN       = 0x5B,
-	RWIN       = 0x5C,
-	APPS       = 0x5D,
-
-	NUMPAD0    = 0x60,
-	NUMPAD1    = 0x61,
-	NUMPAD2    = 0x62,
-	NUMPAD3    = 0x63,
-	NUMPAD4    = 0x64,
-	NUMPAD5    = 0x65,
-	NUMPAD6    = 0x66,
-	NUMPAD7    = 0x67,
-	NUMPAD8    = 0x68,
-	NUMPAD9    = 0x69,
-	MULTIPLY   = 0x6A,
-	ADD        = 0x6B,
-	SEPARATOR  = 0x6C,
-	SUBTRACT   = 0x6D,
-	DECIMAL    = 0x6E,
-	DIVIDE     = 0x6F,
-	F1         = 0x70,
-	F2         = 0x71,
-	F3         = 0x72,
-	F4         = 0x73,
-	F5         = 0x74,
-	F6         = 0x75,
-	F7         = 0x76,
-	F8         = 0x77,
-	F9         = 0x78,
-	F10        = 0x79,
-	F11        = 0x7A,
-	F12        = 0x7B,
-	F13        = 0x7C,
-	F14        = 0x7D,
-	F15        = 0x7E,
-	F16        = 0x7F,
-	F17        = 0x80,
-	F18        = 0x81,
-	F19        = 0x82,
-	F20        = 0x83,
-	F21        = 0x84,
-	F22        = 0x85,
-	F23        = 0x86,
-	F24        = 0x87,
-
-	NUMLOCK    = 0x90,
-	SCROLL     = 0x91,
-
-	LSHIFT     = 0xA0,
-	RSHIFT     = 0xA1,
-	LCONTROL   = 0xA2,
-	RCONTROL   = 0xA3,
-	LMENU      = 0xA4,
-	RMENU      = 0xA5,
-	PROCESSKEY = 0xE5,
-	ATTN       = 0xF6,
-	CRSEL      = 0xF7,
-	EXSEL      = 0xF8,
-	EREOF      = 0xF9,
-	PLAY       = 0xFA,
-	ZOOM       = 0xFB,
-	NONAME     = 0xFC,
-	PA1        = 0xFD,
-	OEM_CLEAR  = 0xFE,
-}
-

+ 9 - 2
src/checker/checker.cpp

@@ -840,7 +840,11 @@ void init_type_info_types(Checker *c) {
 	if (t_type_info == NULL) {
 		String type_info_str = make_string("Type_Info");
 		Entity *e = current_scope_lookup_entity(c->global_scope, type_info_str);
-		GB_ASSERT_MSG(e != NULL, "Internal Compiler Error: Could not find type declaration for `Type_Info`");
+		if (e == NULL) {
+			gb_printf_err("Internal Compiler Error: Could not find type declaration for `Type_Info`\n");
+			gb_printf_err("Is `runtime.odin` missing from the `core` directory?\n");
+			gb_exit(1);
+		}
 		t_type_info = e->type;
 		t_type_info_ptr = make_type_pointer(c->allocator, t_type_info);
 
@@ -849,7 +853,10 @@ void init_type_info_types(Checker *c) {
 		t_type_info_member = record->other_fields[0]->type;
 		t_type_info_member_ptr = make_type_pointer(c->allocator, t_type_info_member);
 
-		GB_ASSERT_MSG(record->field_count == 16, "Internal Compiler Error: Invalid `Type_Info` layout");
+		if (record->field_count != 16) {
+			gb_printf_err("Internal Compiler Error: Invalid `Type_Info` layout\n");
+			gb_exit(1);
+		}
 		t_type_info_named     = record->fields[ 1]->type;
 		t_type_info_integer   = record->fields[ 2]->type;
 		t_type_info_float     = record->fields[ 3]->type;

+ 61 - 21
src/parser.cpp

@@ -2741,6 +2741,45 @@ b32 try_add_import_path(Parser *p, String path, String rel_path, TokenPos pos) {
 	return true;
 }
 
+String get_fullpath_relative(gbAllocator a, String base_dir, String path) {
+	isize str_len = base_dir.len+path.len;
+	u8 *str = gb_alloc_array(gb_heap_allocator(), u8, str_len+1);
+	defer (gb_free(gb_heap_allocator(), str));
+
+	gb_memcopy(str, base_dir.text, base_dir.len);
+	gb_memcopy(str+base_dir.len, path.text, path.len);
+	str[str_len] = '\0';
+	// HACK(bill): memory leak
+	char *path_str = gb_path_get_full_name(a, cast(char *)str);
+	return make_string(path_str);
+}
+
+String get_fullpath_core(gbAllocator a, String path) {
+	char buf[300] = {};
+	u32 buf_len = GetModuleFileNameA(GetModuleHandleA(NULL), buf, gb_size_of(buf));
+	for (isize i = buf_len-1; i >= 0; i--) {
+		if (buf[i] == '\\' ||
+		    buf[i] == '/') {
+			break;
+		}
+		buf_len--;
+	}
+
+	char core[] = "core/";
+	isize core_len = gb_size_of(core)-1;
+
+	isize str_len = buf_len + core_len + path.len;
+	u8 *str = gb_alloc_array(gb_heap_allocator(), u8, str_len+1);
+	defer (gb_free(gb_heap_allocator(), str));
+
+	gb_memcopy(str, buf, buf_len);
+	gb_memcopy(str+buf_len, core, core_len);
+	gb_memcopy(str+buf_len+core_len, path.text, path.len);
+	str[str_len] = '\0';
+	// HACK(bill): memory leak
+	char *path_str = gb_path_get_full_name(a, cast(char *)str);
+	return make_string(path_str);}
+
 // NOTE(bill): Returns true if it's added
 b32 try_add_foreign_system_library_path(Parser *p, String import_file) {
 	gb_for_array(i, p->system_libraries) {
@@ -2803,6 +2842,7 @@ void parse_file(Parser *p, AstFile *f) {
 		}
 		base_dir.len--;
 	}
+	gbAllocator allocator = gb_heap_allocator(); // TODO(bill): Change this allocator
 
 	f->decls = parse_stmt_list(f);
 
@@ -2819,25 +2859,27 @@ void parse_file(Parser *p, AstFile *f) {
 				String file_str = id->relpath.string;
 
 				if (!is_import_path_valid(file_str)) {
-					syntax_error(ast_node_token(node), "Invalid `load` path");
+					if (id->is_load) {
+						syntax_error(ast_node_token(node), "Invalid #load path");
+					} else {
+						syntax_error(ast_node_token(node), "Invalid #import path");
+					}
 					continue;
 				}
 
-				isize str_len = base_dir.len+file_str.len;
-				u8 *str = gb_alloc_array(gb_heap_allocator(), u8, str_len+1);
-				defer (gb_free(gb_heap_allocator(), str));
-
-				gb_memcopy(str, base_dir.text, base_dir.len);
-				gb_memcopy(str+base_dir.len, file_str.text, file_str.len);
-				str[str_len] = '\0';
-				// HACK(bill): memory leak
-				char *path_str = gb_path_get_full_name(gb_heap_allocator(), cast(char *)str);
-				String import_file = make_string(path_str);
+				String import_file = {};
+				String rel_path = get_fullpath_relative(allocator, base_dir, file_str);
+				import_file = rel_path;
+				if (!gb_file_exists(cast(char *)rel_path.text)) { // NOTE(bill): This should be null terminated
+					String abs_path = get_fullpath_core(allocator, file_str);
+					if (gb_file_exists(cast(char *)abs_path.text)) {
+						import_file = abs_path;
+					}
+				}
 
 				id->fullpath = import_file;
-				if (!try_add_import_path(p, import_file, file_str, ast_node_token(node).pos)) {
-					// gb_free(gb_heap_allocator(), import_file.text);
-				}
+				try_add_import_path(p, import_file, file_str, ast_node_token(node).pos);
+
 			} else if (node->kind == AstNode_ForeignSystemLibrary) {
 				auto *id = &node->ForeignSystemLibrary;
 				String file_str = id->filepath.string;
@@ -2862,13 +2904,11 @@ ParseFileError parse_files(Parser *p, char *init_filename) {
 	gb_array_append(p->imports, init_imported_file);
 	p->init_fullpath = init_fullpath;
 
-	// {
-	// 	// IMPORTANT TODO(bill): Don't embed this, do it relative to the .exe
-	// 	char *path = gb_path_get_full_name(gb_heap_allocator(), "W:/Odin/core/__runtime.odin");
-	// 	String s = make_string(path);
-	// 	ImportedFile runtime_file = {s, s, init_pos};
-	// 	gb_array_append(p->imports, runtime_file);
-	// }
+	{
+		String s = get_fullpath_core(gb_heap_allocator(), make_string("runtime.odin"));
+		ImportedFile runtime_file = {s, s, init_pos};
+		gb_array_append(p->imports, runtime_file);
+	}
 
 	gb_for_array(i, p->imports) {
 		String import_path = p->imports[i].path;

+ 2 - 1
src/string.cpp

@@ -13,8 +13,9 @@ typedef struct String {
 gb_inline String make_string(u8 *text, isize len) {
 	String s;
 	s.text = text;
-	if (len < 0)
+	if (len < 0) {
 		len = gb_strlen(cast(char *)text);
+	}
 	s.len = len;
 	return s;
 }

+ 0 - 45
syntax.odin

@@ -1,45 +0,0 @@
-main :: proc(args: []string) -> i32 {
-	if args.count < 2 {
-		io.println("Please specify a .odin file");
-		return 1;
-	}
-
-	for arg_index := 1; arg_index < args.count; arg_index++ {
-		arg := args[arg_index];
-		filename := arg;
-		ext := filepath.path_extension(filename);
-		if (ext != "odin") {
-			io.println("File is not a .odin file");
-			return 1;
-		}
-		output_name := filepath.change_extension(filename, "c");
-
-		parser: Parser;
-		err: Error;
-		parser, err = make_parser(filename);
-		if err {
-			handle_error();
-		}
-		defer destroy_parser(*parser);
-
-		root_node := parse_statement_list(*parser, null);
-
-		code_generator: CodeGenerator;
-		code_generator, err = make_code_generator(*parser, root);
-		if err {
-			handle_error();
-		}
-		defer destroy_code_generator(*code_generator);
-
-		output: File;
-		output, err = file_create(output_nameu);
-		if err {
-			handle_error();
-		}
-		defer file_close(*output);
-
-		convert_to_c_code(*code_generator, root, *output);
-	}
-
-	return 0;
-};