فهرست منبع

Untyped `nil`

Ginger Bill 9 سال پیش
والد
کامیت
50301557b2

+ 1 - 0
.gitignore

@@ -254,3 +254,4 @@ paket-files/
 *.sln
 !misc/llvm-bim/lli.exe
 !misc/llvm-bim/opt.exe
+builds

+ 4 - 4
build.bat

@@ -12,15 +12,15 @@ if %release_mode% EQU 0 ( rem Debug
 	set compiler_flags=%compiler_flags% -Od -MDd -Z7
 	rem -DDISPLAY_TIMING
 ) else ( rem Release
-	set compiler_flags=%compiler_flags% -O2 -MT
+	set compiler_flags=%compiler_flags% -O2 -MT -Z7
 )
 
 set compiler_warnings= ^
-	-we4013 -we4706 ^
+	-we4013 -we4706 -we4002 ^
 	-wd4100 -wd4127 -wd4189 ^
 	-wd4201 -wd4204 -wd4244 ^
 	-wd4306 ^
-	-wd4480 ^
+	-wd4456 -wd4457 -wd4480 ^
 	-wd4505 -wd4512 -wd4550
 
 set compiler_includes=
@@ -31,7 +31,7 @@ set linker_flags= -incremental:no -opt:ref -subsystem:console
 if %release_mode% EQU 0 ( rem Debug
 	set linker_flags=%linker_flags% -debug
 ) else ( rem Release
-	set linker_flags=%linker_flags%
+	set linker_flags=%linker_flags% -debug
 )
 
 set compiler_settings=%compiler_includes% %compiler_flags% %compiler_warnings%

+ 11 - 5
code/demo.odin

@@ -1,9 +1,15 @@
 #import "fmt.odin"
-#import "utf8.odin"
-#import "hash.odin"
-#import "mem.odin"
-#import "game.odin"
+
+A :: {2}f32{1, 2}
+B :: {2}f32{3, 4}
 
 main :: proc() {
-	fmt.println("Hellope")
+	Fruit :: union {
+		A: int
+		B: f32
+		C: struct {
+			x: int
+		}
+	}
 }
+

+ 5 - 5
code/game.odin

@@ -50,7 +50,7 @@ make_window :: proc(title: string, msg, height: int, window_proc: win32.WNDPROC)
 	c_class_name := class_name.data
 	w.c_title = to_c_string(title)
 
-	instance := GetModuleHandleA(null)
+	instance := GetModuleHandleA(nil)
 
 	w.wc = WNDCLASSEXA{
 		size       = size_of(WNDCLASSEXA) as u32,
@@ -70,9 +70,9 @@ make_window :: proc(title: string, msg, height: int, window_proc: win32.WNDPROC)
 	                         WS_VISIBLE | WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
 	                         CW_USEDEFAULT, CW_USEDEFAULT,
 	                         w.width as i32, w.height as i32,
-	                         null, null, instance, null)
+	                         nil, nil, instance, nil)
 
-	if w.hwnd == null {
+	if w.hwnd == nil {
 		win32_print_last_error()
 		return w, false
 	}
@@ -92,7 +92,7 @@ make_window :: proc(title: string, msg, height: int, window_proc: win32.WNDPROC)
 			layer_type   = PFD_MAIN_PLANE,
 		}
 
-		SetPixelFormat(w.dc, ChoosePixelFormat(w.dc, ^pfd), null)
+		SetPixelFormat(w.dc, ChoosePixelFormat(w.dc, ^pfd), nil)
 		w.opengl_context = wglCreateContext(w.dc)
 		wglMakeCurrent(w.dc, w.opengl_context)
 
@@ -154,7 +154,7 @@ run :: proc() {
 		prev_time = curr_time
 
 		msg: MSG
-		for PeekMessageA(^msg, null, 0, 0, PM_REMOVE) > 0 {
+		for PeekMessageA(^msg, nil, 0, 0, PM_REMOVE) > 0 {
 			if msg.message == WM_QUIT {
 				running = false
 			}

+ 66 - 0
code/old_demos/demo004.odin

@@ -0,0 +1,66 @@
+#import "fmt.odin"
+#import "utf8.odin"
+#import "hash.odin"
+#import "mem.odin"
+
+main :: proc() {
+	{ // New Standard Library stuff
+		s := "Hello"
+		fmt.println(s,
+		            utf8.valid_string(s),
+		            hash.murmur64(s.data, s.count))
+
+		// utf8.odin
+		// hash.odin
+		//     - crc, fnv, fnva, murmur
+		// mem.odin
+		//     - Custom allocators
+		//     - Helpers
+	}
+
+	{
+		arena: mem.Arena
+		mem.init_arena_from_context(^arena, mem.megabytes(16)) // Uses default allocator
+		defer mem.free_arena(^arena)
+
+		push_allocator mem.arena_allocator(^arena) {
+			x := new(int)
+			x^ = 1337
+
+			fmt.println(x^)
+		}
+
+		/*
+			push_allocator x {
+				...
+			}
+
+			is equivalent to:
+
+			{
+				prev_allocator := __context.allocator
+				__context.allocator = x
+				defer __context.allocator = prev_allocator
+
+				...
+			}
+		*/
+
+		// You can also "push" a context
+
+		c := current_context() // Create copy of the allocator
+		c.allocator = mem.arena_allocator(^arena)
+
+		push_context c {
+			x := new(int)
+			x^ = 365
+
+			fmt.println(x^)
+		}
+	}
+
+	// Backend improvements
+	// - Minimal dependency building (only build what is needed)
+	// - Numerous bugs fixed
+	// - Mild parsing recovery after bad syntax error
+}

+ 16 - 16
core/runtime.odin → core/_preload.odin

@@ -14,10 +14,10 @@ Type_Info :: union {
 	}
 	Record :: struct #ordered {
 		fields:  []Member
-		packed:  bool
-		ordered: bool
 		size:    int // in bytes
 		align:   int // in bytes
+		packed:  bool
+		ordered: bool
 	}
 
 	Named: struct #ordered {
@@ -60,15 +60,15 @@ Type_Info :: union {
 	Union:     Record
 	Raw_Union: Record
 	Enum: struct #ordered {
-		base: ^Type_Info
+		base:   ^Type_Info
 		values: []i64
 		names:  []string
 	}
 }
 
 type_info_base :: proc(info: ^Type_Info) -> ^Type_Info {
-	if info == null {
-		return null
+	if info == nil {
+		return nil
 	}
 	match type i : info {
 	case Type_Info.Named:
@@ -142,7 +142,7 @@ current_context :: proc() -> Context { // Copy of context
 __check_context :: proc() {
 	c := ^__context
 
-	if c.allocator.procedure == null {
+	if c.allocator.procedure == nil {
 		c.allocator = __default_allocator()
 	}
 	if c.thread_id == 0 {
@@ -155,20 +155,20 @@ alloc :: proc(size: int) -> rawptr #inline { return alloc_align(size, DEFAULT_AL
 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)
+	return a.procedure(a.data, Allocator.Mode.ALLOC, size, alignment, nil, 0, 0)
 }
 
 free :: proc(ptr: rawptr) #inline {
 	__check_context()
 	a := current_context().allocator
-	if ptr != null {
+	if ptr != nil {
 		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)
+	a.procedure(a.data, Allocator.Mode.FREE_ALL, 0, 0, nil, 0, 0)
 }
 
 
@@ -181,13 +181,13 @@ resize_align :: proc(ptr: rawptr, old_size, new_size, alignment: int) -> rawptr
 
 
 default_resize_align :: proc(old_memory: rawptr, old_size, new_size, alignment: int) -> rawptr {
-	if old_memory == null {
+	if old_memory == nil {
 		return alloc_align(new_size, alignment)
 	}
 
 	if new_size == 0 {
 		free(old_memory)
-		return null
+		return nil
 	}
 
 	if new_size == old_size {
@@ -195,8 +195,8 @@ default_resize_align :: proc(old_memory: rawptr, old_size, new_size, alignment:
 	}
 
 	new_memory := alloc_align(new_size, alignment)
-	if new_memory == null {
-		return null
+	if new_memory == nil {
+		return nil
 	}
 
 	mem.copy(new_memory, old_memory, min(old_size, new_size));
@@ -220,7 +220,7 @@ __default_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator.Mode,
 
 	case FREE:
 		os.heap_free(mem.allocation_header(old_memory))
-		return null
+		return nil
 
 	case FREE_ALL:
 		// NOTE(bill): Does nothing
@@ -234,13 +234,13 @@ __default_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator.Mode,
 		return mem.zero(ptr, size)
 	}
 
-	return null
+	return nil
 }
 
 __default_allocator :: proc() -> Allocator {
 	return Allocator{
 		procedure = __default_allocator_proc,
-		data = null,
+		data = nil,
 	}
 }
 

+ 19 - 15
core/fmt.odin

@@ -197,7 +197,7 @@ print__f64 :: proc(buffer: ^[]byte, f: f64, decimal_places: int) {
 }
 
 print_type_to_buffer :: proc(buf: ^[]byte, ti: ^Type_Info) {
-	if ti == null { return }
+	if ti == nil { return }
 
 	using Type_Info
 	match type info : ti {
@@ -230,7 +230,7 @@ print_type_to_buffer :: proc(buf: ^[]byte, ti: ^Type_Info) {
 		print_type_to_buffer(buf, info.elem)
 	case Procedure:
 		print_string_to_buffer(buf, "proc")
-		if info.params == null {
+		if info.params == nil {
 			print_string_to_buffer(buf, "()")
 		} else {
 			count := (info.params as ^Tuple).fields.count
@@ -238,7 +238,7 @@ print_type_to_buffer :: proc(buf: ^[]byte, ti: ^Type_Info) {
 			print_type_to_buffer(buf, info.params)
 			if count == 1 { print_string_to_buffer(buf, ")") }
 		}
-		if info.results != null {
+		if info.results != nil {
 			print_string_to_buffer(buf, " -> ")
 			print_type_to_buffer(buf, info.results)
 		}
@@ -320,7 +320,11 @@ print_type_to_buffer :: proc(buf: ^[]byte, ti: ^Type_Info) {
 }
 
 
-print_any_to_buffer :: proc(buf: ^[]byte, arg: any)  {
+print_any_to_buffer :: proc(buf: ^[]byte, arg: any) {
+	if arg.type_info == nil {
+		print_string_to_buffer(buf, "<nil>")
+		return
+	}
 	using Type_Info
 	match type info : arg.type_info {
 	case Named:
@@ -352,7 +356,7 @@ print_any_to_buffer :: proc(buf: ^[]byte, arg: any)  {
 	case Integer:
 		if info.signed {
 			i: i64 = 0;
-			if arg.data != null {
+			if arg.data != nil {
 				match info.size {
 				case 1:  i = (arg.data as ^i8)^   as i64
 				case 2:  i = (arg.data as ^i16)^  as i64
@@ -363,7 +367,7 @@ print_any_to_buffer :: proc(buf: ^[]byte, arg: any)  {
 			print_i64_to_buffer(buf, i)
 		} else {
 			i: u64 = 0;
-			if arg.data != null {
+			if arg.data != nil {
 				match info.size {
 				case 1:  i = (arg.data as ^u8)^   as u64
 				case 2:  i = (arg.data as ^u16)^  as u64
@@ -376,7 +380,7 @@ print_any_to_buffer :: proc(buf: ^[]byte, arg: any)  {
 
 	case Float:
 		f: f64 = 0
-		if arg.data != null {
+		if arg.data != nil {
 			match info.size {
 			case 4: f = (arg.data as ^f32)^ as f64
 			case 8: f = (arg.data as ^f64)^ as f64
@@ -386,27 +390,27 @@ print_any_to_buffer :: proc(buf: ^[]byte, arg: any)  {
 
 	case String:
 		s := ""
-		if arg.data != null {
+		if arg.data != nil {
 			s = (arg.data as ^string)^
 		}
 		print_string_to_buffer(buf, s)
 
 	case Boolean:
 		v := false;
-		if arg.data != null {
+		if arg.data != nil {
 			v = (arg.data as ^bool)^
 		}
 		print_bool_to_buffer(buf, v)
 
 	case Pointer:
-		if arg.data != null {
+		if arg.data != nil {
 			if arg.type_info == type_info(^Type_Info) {
 				print_type_to_buffer(buf, (arg.data as ^^Type_Info)^)
 			} else {
 				print_pointer_to_buffer(buf, (arg.data as ^rawptr)^)
 			}
 		} else {
-			print_pointer_to_buffer(buf, null)
+			print_pointer_to_buffer(buf, nil)
 		}
 
 	case Enum:
@@ -414,7 +418,7 @@ print_any_to_buffer :: proc(buf: ^[]byte, arg: any)  {
 		match type i : info.base {
 		case Integer:
 			if i.signed {
-				if arg.data != null {
+				if arg.data != nil {
 					match i.size {
 					case 1:  value = (arg.data as ^i8)^   as i64
 					case 2:  value = (arg.data as ^i16)^  as i64
@@ -423,7 +427,7 @@ print_any_to_buffer :: proc(buf: ^[]byte, arg: any)  {
 					}
 				}
 			} else {
-				if arg.data != null {
+				if arg.data != nil {
 					match i.size {
 					case 1:  value = (arg.data as ^u8)^   as i64
 					case 2:  value = (arg.data as ^u16)^  as i64
@@ -582,7 +586,7 @@ bprint :: proc(buf: ^[]byte, args: ..any) {
 	is_type_string :: proc(info: ^Type_Info) -> bool {
 		using Type_Info
 		info = type_info_base(info)
-		if info == null {
+		if info == nil {
 			return false
 		}
 
@@ -597,7 +601,7 @@ bprint :: proc(buf: ^[]byte, args: ..any) {
 	prev_string := false
 	for i := 0; i < args.count; i++ {
 		arg := args[i]
-		is_string := arg.data != null && is_type_string(arg.type_info)
+		is_string := arg.data != nil && is_type_string(arg.type_info)
 		if i > 0 && !is_string && !prev_string {
 			print_space_to_buffer(buf)
 		}

+ 3 - 3
core/mem.odin

@@ -143,7 +143,7 @@ init_sub_arena :: proc(sub, parent: ^Arena, size: int) {
 }
 
 free_arena :: proc(using a: ^Arena) {
-	if backing.procedure != null {
+	if backing.procedure != nil {
 		push_allocator backing {
 			free(memory.data)
 			memory = memory[0:0:0]
@@ -170,7 +170,7 @@ arena_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator.Mode,
 
 		if arena.memory.count + total_size > arena.memory.capacity {
 			fmt.fprintln(os.stderr, "Arena out of memory")
-			return null
+			return nil
 		}
 
 		#no_bounds_check end := ^arena.memory[arena.memory.count]
@@ -190,7 +190,7 @@ arena_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator.Mode,
 		return default_resize_align(old_memory, old_size, size, alignment)
 	}
 
-	return null
+	return nil
 }
 
 begin_temp_arena_memory :: proc(a: ^Arena) -> Temp_Arena_Memory {

+ 5 - 5
core/os.odin

@@ -9,7 +9,7 @@ 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)}
+	f := File{CreateFileA(^buf[0], FILE_GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, 0, nil)}
 	success := f.handle != INVALID_HANDLE_VALUE as File.Handle
 
 	return f, success
@@ -20,7 +20,7 @@ create :: proc(name: string) -> (File, bool) {
 	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),
+		handle = CreateFileA(^buf[0], FILE_GENERIC_WRITE, FILE_SHARE_READ, nil, CREATE_ALWAYS, 0, nil),
 	}
 	success := f.handle != INVALID_HANDLE_VALUE as File.Handle
 	return f, success
@@ -32,7 +32,7 @@ close :: proc(using f: ^File) {
 
 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
+	return win32.WriteFile(handle, buf.data, buf.count as i32, ^bytes_written, nil) != 0
 }
 
 
@@ -72,7 +72,7 @@ read_entire_file :: proc(name: string) -> (string, bool) {
 	}
 
 	data := new_slice(u8, length)
-	if data.data == null {
+	if data.data == nil {
 		return "", false
 	}
 
@@ -89,7 +89,7 @@ read_entire_file :: proc(name: string) -> (string, bool) {
 			to_read = MAX
 		}
 
-		win32.ReadFile(f.handle as win32.HANDLE, ^data[total_read], to_read, ^single_read_length, null)
+		win32.ReadFile(f.handle as win32.HANDLE, ^data[total_read], to_read, ^single_read_length, nil)
 		if single_read_length <= 0 {
 			free(data.data)
 			return "", false

+ 6 - 6
core/utf8.odin

@@ -12,14 +12,14 @@ Accept_Range :: struct {
 }
 
 accept_ranges := [5]Accept_Range{
-	Accept_Range{0x80, 0xbf},
-	Accept_Range{0xa0, 0xbf},
-	Accept_Range{0x80, 0x9f},
-	Accept_Range{0x90, 0xbf},
-	Accept_Range{0x80, 0x8f},
+	{0x80, 0xbf},
+	{0xa0, 0xbf},
+	{0x80, 0x9f},
+	{0x90, 0xbf},
+	{0x80, 0x8f},
 }
 
-accept_sizes := [256]u8{
+accept_sizes := [256]byte{
 	0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, // 0x00-0x0f
 	0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, // 0x10-0x1f
 	0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, // 0x20-0x2f

+ 0 - 200
misc/llvm-bin/CODE_OWNERS.TXT

@@ -1,200 +0,0 @@
-This file is a list of the people responsible for ensuring that patches for a
-particular part of LLVM are reviewed, either by themself or by someone else.
-They are also the gatekeepers for their part of LLVM, with the final word on
-what goes in or not.
-
-The list is sorted by surname and formatted to allow easy grepping and
-beautification by scripts.  The fields are: name (N), email (E), web-address
-(W), PGP key ID and fingerprint (P), description (D), and snail-mail address
-(S). Each entry should contain at least the (N), (E) and (D) fields.
-
-N: Joe Abbey
-E: [email protected]
-D: LLVM Bitcode (lib/Bitcode/* include/llvm/Bitcode/*)
-
-N: Owen Anderson
-E: [email protected]
-D: SelectionDAG (lib/CodeGen/SelectionDAG/*)
-
-N: Rafael Avila de Espindola
-E: [email protected]
-D: Gold plugin (tools/gold/*)
-
-N: Justin Bogner
-E: [email protected]
-D: InstrProfiling and related parts of ProfileData
-
-N: Chandler Carruth
-E: [email protected]
-E: [email protected]
-D: Config, ADT, Support, inlining & related passes, SROA/mem2reg & related passes, CMake, library layering
-
-N: Evan Cheng
-E: [email protected]
-D: parts of code generator not covered by someone else
-
-N: Eric Christopher
-E: [email protected]
-D: Debug Information, autotools/configure/make build, inline assembly
-
-N: Greg Clayton
-E: [email protected]
-D: LLDB
-
-N: Marshall Clow
-E: [email protected]
-D: libc++
-
-N: Peter Collingbourne
-E: [email protected]
-D: llgo
-
-N: Quentin Colombet
-E: [email protected]
-D: Register allocators
-
-N: Duncan P. N. Exon Smith
-E: [email protected]
-D: Branch weights and BlockFrequencyInfo
-
-N: Hal Finkel
-E: [email protected]
-D: BBVectorize, the loop reroller, alias analysis and the PowerPC target
-
-N: Dan Gohman
-E: [email protected]
-D: WebAssembly Backend (lib/Target/WebAssembly/*)
-
-N: Renato Golin
-E: [email protected]
-D: ARM Linux support
-
-N: Venkatraman Govindaraju
-E: [email protected]
-D: Sparc Backend (lib/Target/Sparc/*)
-
-N: Tobias Grosser
-E: [email protected]
-D: Polly
-
-N: James Grosbach
-E: [email protected]
-D: MC layer
-
-N: Justin Holewinski
-E: [email protected]
-D: NVPTX Target (lib/Target/NVPTX/*)
-
-N: Lang Hames
-E: [email protected]
-D: MCJIT, RuntimeDyld and JIT event listeners
-
-N: Galina Kistanova
-E: [email protected]
-D: LLVM Buildbot
-
-N: Anton Korobeynikov
-E: [email protected]
-D: Exception handling, Windows codegen, ARM EABI
-
-N: Benjamin Kramer
-E: [email protected]
-D: DWARF Parser
-
-N: Sergei Larin
-E: [email protected]
-D: VLIW Instruction Scheduling, Packetization
-
-N: Chris Lattner
-E: [email protected]
-W: http://nondot.org/~sabre/
-D: Everything not covered by someone else
-
-N: David Majnemer
-E: [email protected]
-D: IR Constant Folder, InstCombine
-
-N: Dylan McKay
-E: [email protected]
-D: AVR Backend
-
-N: Tim Northover
-E: [email protected]
-D: AArch64 backend, misc ARM backend
-
-N: Diego Novillo
-E: [email protected]
-D: SampleProfile and related parts of ProfileData
-
-N: Jakob Olesen
-E: [email protected]
-D: TableGen
-
-N: Richard Osborne
-E: [email protected]
-D: XCore Backend
-
-N: Krzysztof Parzyszek
-E: [email protected]
-D: Hexagon Backend
-
-N: Paul Robinson
-E: [email protected]
-D: Sony PlayStation®4 support
-
-N: Chad Rosier
-E: [email protected]
-D: Fast-Isel
-
-N: Nadav Rotem
-E: [email protected]
-D: X86 Backend, Loop Vectorizer
-
-N: Daniel Sanders
-E: [email protected]
-D: MIPS Backend (lib/Target/Mips/*)
-
-N: Duncan Sands
-E: [email protected]
-D: DragonEgg
-
-N: Kostya Serebryany
-E: [email protected]
-D: AddressSanitizer, ThreadSanitizer (LLVM parts)
-
-N: Michael Spencer
-E: [email protected]
-D: Windows parts of Support, Object, ar, nm, objdump, ranlib, size
-
-N: Alexei Starovoitov
-E: [email protected]
-D: BPF backend
-
-N: Tom Stellard
-E: [email protected]
-E: [email protected]
-D: Release manager for the 3.5 and 3.6 branches, R600 Backend, libclc
-
-N: Evgeniy Stepanov
-E: [email protected]
-D: MemorySanitizer (LLVM part)
-
-N: Andrew Trick
-E: [email protected]
-D: IndVar Simplify, Loop Strength Reduction, Instruction Scheduling
-
-N: Ulrich Weigand
-E: [email protected]
-D: SystemZ Backend
-
-N: Bill Wendling
-E: [email protected]
-D: libLTO, IR Linker
-
-N: Peter Zotov
-E: [email protected]
-D: OCaml bindings
-
-N: Andrey Churbanov
-E: [email protected]
-D: OpenMP runtime library

+ 0 - 467
misc/llvm-bin/CREDITS.TXT

@@ -1,467 +0,0 @@
-This file is a partial list of people who have contributed to the LLVM
-project.  If you have contributed a patch or made some other contribution to
-LLVM, please submit a patch to this file to add yourself, and it will be
-done!
-
-The list is sorted by surname and formatted to allow easy grepping and
-beautification by scripts.  The fields are: name (N), email (E), web-address
-(W), PGP key ID and fingerprint (P), description (D), snail-mail address
-(S), and (I) IRC handle.
-
-
-N: Vikram Adve
-E: [email protected]
-W: http://www.cs.uiuc.edu/~vadve/
-D: The Sparc64 backend, provider of much wisdom, and motivator for LLVM
-
-N: Owen Anderson
-E: [email protected]
-D: LCSSA pass and related LoopUnswitch work
-D: GVNPRE pass, DataLayout refactoring, random improvements
-
-N: Henrik Bach
-D: MingW Win32 API portability layer
-
-N: Aaron Ballman
-E: [email protected]
-D: __declspec attributes, Windows support, general bug fixing
-
-N: Nate Begeman
-E: [email protected]
-D: PowerPC backend developer
-D: Target-independent code generator and analysis improvements
-
-N: Daniel Berlin
-E: [email protected]
-D: ET-Forest implementation.
-D: Sparse bitmap
-
-N: David Blaikie
-E: [email protected]
-D: General bug fixing/fit & finish, mostly in Clang
-
-N: Neil Booth
-E: [email protected]
-D: APFloat implementation.
-
-N: Misha Brukman
-E: [email protected]
-W: http://misha.brukman.net
-D: Portions of X86 and Sparc JIT compilers, PowerPC backend
-D: Incremental bitcode loader
-
-N: Cameron Buschardt
-E: [email protected]
-D: The `mem2reg' pass - promotes values stored in memory to registers
-
-N: Brendon Cahoon
-E: [email protected]
-D: Loop unrolling with run-time trip counts.
-
-N: Chandler Carruth
-E: [email protected]
-E: [email protected]
-D: Hashing algorithms and interfaces
-D: Inline cost analysis
-D: Machine block placement pass
-D: SROA
-
-N: Casey Carter
-E: [email protected]
-D: Fixes to the Reassociation pass, various improvement patches
-
-N: Evan Cheng
-E: [email protected]
-D: ARM and X86 backends
-D: Instruction scheduler improvements
-D: Register allocator improvements
-D: Loop optimizer improvements
-D: Target-independent code generator improvements
-
-N: Dan Villiom Podlaski Christiansen
-E: [email protected]
-E: [email protected]
-W: http://villiom.dk
-D: LLVM Makefile improvements
-D: Clang diagnostic & driver tweaks
-S: Aarhus, Denmark
-
-N: Jeff Cohen
-E: [email protected]
-W: http://jolt-lang.org
-D: Native Win32 API portability layer
-
-N: John T. Criswell
-E: [email protected]
-D: Original Autoconf support, documentation improvements, bug fixes
-
-N: Anshuman Dasgupta
-E: [email protected]
-D: Deterministic finite automaton based infrastructure for VLIW packetization
-
-N: Stefanus Du Toit
-E: [email protected]
-D: Bug fixes and minor improvements
-
-N: Rafael Avila de Espindola
-E: [email protected]
-D: The ARM backend
-
-N: Dave Estes
-E: [email protected]
-D: AArch64 machine description for Cortex-A53
-
-N: Alkis Evlogimenos
-E: [email protected]
-D: Linear scan register allocator, many codegen improvements, Java frontend
-
-N: Hal Finkel
-E: [email protected]
-D: Basic-block autovectorization, PowerPC backend improvements
-
-N: Eric Fiselier
-E: [email protected]
-D: LIT patches and documentation.
-
-N: Ryan Flynn
-E: [email protected]
-D: Miscellaneous bug fixes
-
-N: Brian Gaeke
-E: [email protected]
-W: http://www.students.uiuc.edu/~gaeke/
-D: Portions of X86 static and JIT compilers; initial SparcV8 backend
-D: Dynamic trace optimizer
-D: FreeBSD/X86 compatibility fixes, the llvm-nm tool
-
-N: Nicolas Geoffray
-E: [email protected]
-W: http://www-src.lip6.fr/homepages/Nicolas.Geoffray/
-D: PPC backend fixes for Linux
-
-N: Louis Gerbarg
-E: [email protected]
-D: Portions of the PowerPC backend
-
-N: Saem Ghani
-E: [email protected]
-D: Callgraph class cleanups
-
-N: Mikhail Glushenkov
-E: [email protected]
-D: Author of llvmc2
-
-N: Dan Gohman
-E: [email protected]
-D: Miscellaneous bug fixes
-D: WebAssembly Backend
-
-N: David Goodwin
-E: [email protected]
-D: Thumb-2 code generator
-
-N: David Greene
-E: [email protected]
-D: Miscellaneous bug fixes
-D: Register allocation refactoring
-
-N: Gabor Greif
-E: [email protected]
-D: Improvements for space efficiency
-
-N: James Grosbach
-E: [email protected]
-I: grosbach
-D: SjLj exception handling support
-D: General fixes and improvements for the ARM back-end
-D: MCJIT
-D: ARM integrated assembler and assembly parser
-D: Led effort for the backend formerly known as ARM64
-
-N: Lang Hames
-E: [email protected]
-D: PBQP-based register allocator
-
-N: Gordon Henriksen
-E: [email protected]
-D: Pluggable GC support
-D: C interface
-D: Ocaml bindings
-
-N: Raul Fernandes Herbster
-E: [email protected]
-D: JIT support for ARM
-
-N: Paolo Invernizzi
-E: [email protected]
-D: Visual C++ compatibility fixes
-
-N: Patrick Jenkins
-E: [email protected]
-D: Nightly Tester
-
-N: Dale Johannesen
-E: [email protected]
-D: ARM constant islands improvements
-D: Tail merging improvements
-D: Rewrite X87 back end
-D: Use APFloat for floating point constants widely throughout compiler
-D: Implement X87 long double
-
-N: Brad Jones
-E: [email protected]
-D: Support for packed types
-
-N: Rod Kay
-E: [email protected]
-D: Author of LLVM Ada bindings
-
-N: Eric Kidd
-W: http://randomhacks.net/
-D: llvm-config script
-
-N: Anton Korobeynikov
-E: [email protected]
-D: Mingw32 fixes, cross-compiling support, stdcall/fastcall calling conv.
-D: x86/linux PIC codegen, aliases, regparm/visibility attributes
-D: Switch lowering refactoring
-
-N: Sumant Kowshik
-E: [email protected]
-D: Author of the original C backend
-
-N: Benjamin Kramer
-E: [email protected]
-D: Miscellaneous bug fixes
-
-N: Sundeep Kushwaha
-E: [email protected]
-D: Implemented DFA-based target independent VLIW packetizer
-
-N: Christopher Lamb
-E: [email protected]
-D: aligned load/store support, parts of noalias and restrict support
-D: vreg subreg infrastructure, X86 codegen improvements based on subregs
-D: address spaces
-
-N: Jim Laskey
-E: [email protected]
-D: Improvements to the PPC backend, instruction scheduling
-D: Debug and Dwarf implementation
-D: Auto upgrade mangler
-D: llvm-gcc4 svn wrangler
-
-N: Chris Lattner
-E: [email protected]
-W: http://nondot.org/~sabre/
-D: Primary architect of LLVM
-
-N: Tanya Lattner (Tanya Brethour)
-E: [email protected]
-W: http://nondot.org/~tonic/
-D: The initial llvm-ar tool, converted regression testsuite to dejagnu
-D: Modulo scheduling in the SparcV9 backend
-D: Release manager (1.7+)
-
-N: Sylvestre Ledru
-E: [email protected]
-W: http://sylvestre.ledru.info/
-W: http://llvm.org/apt/
-D: Debian and Ubuntu packaging
-D: Continuous integration with jenkins
-
-N: Andrew Lenharth
-E: [email protected]
-W: http://www.lenharth.org/~andrewl/
-D: Alpha backend
-D: Sampling based profiling
-
-N: Nick Lewycky
-E: [email protected]
-D: PredicateSimplifier pass
-
-N: Tony Linthicum, et. al.
-E: [email protected]
-D: Backend for Qualcomm's Hexagon VLIW processor.
-
-N: Bruno Cardoso Lopes
-E: [email protected]
-I: bruno
-W: http://brunocardoso.cc
-D: Mips backend
-D: Random ARM integrated assembler and assembly parser improvements
-D: General X86 AVX1 support
-
-N: Duraid Madina
-E: [email protected]
-W: http://kinoko.c.u-tokyo.ac.jp/~duraid/
-D: IA64 backend, BigBlock register allocator
-
-N: John McCall
-E: [email protected]
-D: Clang semantic analysis and IR generation
-
-N: Michael McCracken
-E: [email protected]
-D: Line number support for llvmgcc
-
-N: Vladimir Merzliakov
-E: [email protected]
-D: Test suite fixes for FreeBSD
-
-N: Scott Michel
-E: [email protected]
-D: Added STI Cell SPU backend.
-
-N: Kai Nacke
-E: [email protected]
-D: Support for implicit TLS model used with MS VC runtime
-D: Dumping of Win64 EH structures
-
-N: Takumi Nakamura
-E: [email protected]
-E: [email protected]
-D: Cygwin and MinGW support.
-D: Win32 tweaks.
-S: Yokohama, Japan
-
-N: Edward O'Callaghan
-E: [email protected]
-W: http://www.auroraux.org
-D: Add Clang support with various other improvements to utils/NewNightlyTest.pl
-D: Fix and maintain Solaris & AuroraUX support for llvm, various build warnings
-D: and error clean ups.
-
-N: Morten Ofstad
-E: [email protected]
-D: Visual C++ compatibility fixes
-
-N: Jakob Stoklund Olesen
-E: [email protected]
-D: Machine code verifier
-D: Blackfin backend
-D: Fast register allocator
-D: Greedy register allocator
-
-N: Richard Osborne
-E: [email protected]
-D: XCore backend
-
-N: Devang Patel
-E: [email protected]
-D: LTO tool, PassManager rewrite, Loop Pass Manager, Loop Rotate
-D: GCC PCH Integration (llvm-gcc), llvm-gcc improvements
-D: Optimizer improvements, Loop Index Split
-
-N: Ana Pazos
-E: [email protected]
-D: Fixes and improvements to the AArch64 backend
-
-N: Wesley Peck
-E: [email protected]
-W: http://wesleypeck.com/
-D: MicroBlaze backend
-
-N: Francois Pichet
-E: [email protected]
-D: MSVC support
-
-N: Vladimir Prus
-W: http://vladimir_prus.blogspot.com
-E: [email protected]
-D: Made inst_iterator behave like a proper iterator, LowerConstantExprs pass
-
-N: Kalle Raiskila
-E: [email protected]
-D: Some bugfixes to CellSPU
-
-N: Xerxes Ranby
-E: [email protected]
-D: Cmake dependency chain and various bug fixes
-
-N: Alex Rosenberg
-E: [email protected]
-I: arosenberg
-D: ARM calling conventions rewrite, hard float support
-
-N: Chad Rosier
-E: [email protected]
-I: mcrosier
-D: AArch64 fast instruction selection pass
-D: Fixes and improvements to the ARM fast-isel pass
-D: Fixes and improvements to the AArch64 backend
-
-N: Nadav Rotem
-E: [email protected]
-D: X86 code generation improvements, Loop Vectorizer.
-
-N: Roman Samoilov
-E: [email protected]
-D: MSIL backend
-
-N: Duncan Sands
-E: [email protected]
-I: baldrick
-D: Ada support in llvm-gcc
-D: Dragonegg plugin
-D: Exception handling improvements
-D: Type legalizer rewrite
-
-N: Ruchira Sasanka
-E: [email protected]
-D: Graph coloring register allocator for the Sparc64 backend
-
-N: Arnold Schwaighofer
-E: [email protected]
-D: Tail call optimization for the x86 backend
-
-N: Shantonu Sen
-E: [email protected]
-D: Miscellaneous bug fixes
-
-N: Anand Shukla
-E: [email protected]
-D: The `paths' pass
-
-N: Michael J. Spencer
-E: [email protected]
-D: Shepherding Windows COFF support into MC.
-D: Lots of Windows stuff.
-
-N: Reid Spencer
-E: [email protected]
-W: http://reidspencer.com/
-D: Lots of stuff, see: http://wiki.llvm.org/index.php/User:Reid
-
-N: Alp Toker
-E: [email protected]
-W: http://atoker.com/
-D: C++ frontend next generation standards implementation
-
-N: Craig Topper
-E: [email protected]
-D: X86 codegen and disassembler improvements. AVX2 support.
-
-N: Edwin Torok
-E: [email protected]
-D: Miscellaneous bug fixes
-
-N: Adam Treat
-E: [email protected]
-D: C++ bugs filed, and C++ front-end bug fixes.
-
-N: Lauro Ramos Venancio
-E: [email protected]
-D: ARM backend improvements
-D: Thread Local Storage implementation
-
-N: Bill Wendling
-I: wendling
-E: [email protected]
-D: Release manager, IR Linker, LTO
-D: Bunches of stuff
-
-N: Bob Wilson
-E: [email protected]
-D: Advanced SIMD (NEON) support in the ARM backend.
-

+ 0 - 70
misc/llvm-bin/LICENSE.TXT

@@ -1,70 +0,0 @@
-==============================================================================
-LLVM Release License
-==============================================================================
-University of Illinois/NCSA
-Open Source License
-
-Copyright (c) 2003-2015 University of Illinois at Urbana-Champaign.
-All rights reserved.
-
-Developed by:
-
-    LLVM Team
-
-    University of Illinois at Urbana-Champaign
-
-    http://llvm.org
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of
-this software and associated documentation files (the "Software"), to deal with
-the Software without restriction, including without limitation the rights to
-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
-of the Software, and to permit persons to whom the Software is furnished to do
-so, subject to the following conditions:
-
-    * Redistributions of source code must retain the above copyright notice,
-      this list of conditions and the following disclaimers.
-
-    * Redistributions in binary form must reproduce the above copyright notice,
-      this list of conditions and the following disclaimers in the
-      documentation and/or other materials provided with the distribution.
-
-    * Neither the names of the LLVM Team, University of Illinois at
-      Urbana-Champaign, nor the names of its contributors may be used to
-      endorse or promote products derived from this Software without specific
-      prior written permission.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
-FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
-CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
-SOFTWARE.
-
-==============================================================================
-Copyrights and Licenses for Third Party Software Distributed with LLVM:
-==============================================================================
-The LLVM software contains code written by third parties.  Such software will
-have its own individual LICENSE.TXT file in the directory in which it appears.
-This file will describe the copyrights, license, and restrictions which apply
-to that code.
-
-The disclaimer of warranty in the University of Illinois Open Source License
-applies to all code in the LLVM Distribution, and nothing in any of the
-other licenses gives permission to use the names of the LLVM Team or the
-University of Illinois to endorse or promote products derived from this
-Software.
-
-The following pieces of software have additional or alternate copyrights,
-licenses, and/or restrictions:
-
-Program             Directory
--------             ---------
-Autoconf            llvm/autoconf
-                    llvm/projects/ModuleMaker/autoconf
-Google Test         llvm/utils/unittest/googletest
-OpenBSD regex       llvm/lib/Support/{reg*, COPYRIGHT.regex}
-pyyaml tests        llvm/test/YAMLParser/{*.data, LICENSE.TXT}
-ARM contributions   llvm/lib/Target/ARM/LICENSE.TXT
-md5 contributions   llvm/lib/Support/MD5.cpp llvm/include/llvm/Support/MD5.h

BIN
misc/llvm-bin/lli.exe


BIN
misc/llvm-bin/opt.exe


+ 1 - 1
misc/shell.bat

@@ -1,8 +1,8 @@
 @echo off
 
 call "C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\vcvarsall.bat" x64 1> NUL
-rem call "C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\vcvarsall.bat" x86 1> NUL
 rem call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x64 1> NUL
+rem call "C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\vcvarsall.bat" x86 1> NUL
 set _NO_DEBUG_HEAP=1
 
 set path=w:\Odin\misc;%path%

+ 17 - 3
src/checker/checker.cpp

@@ -33,6 +33,10 @@ struct Operand {
 	BuiltinProcId builtin_id;
 };
 
+b32 is_operand_nil(Operand *o) {
+	return o->mode == Addressing_Value && o->type == t_untyped_nil;
+}
+
 struct TypeAndValue {
 	AddressingMode mode;
 	Type *type;
@@ -241,7 +245,9 @@ struct Checker {
 	gbArray(ProcedureInfo) procs; // NOTE(bill): Procedures to check
 
 	gbArena     arena;
+	gbArena     tmp_arena;
 	gbAllocator allocator;
+	gbAllocator tmp_allocator;
 
 	CheckerContext context;
 
@@ -501,9 +507,10 @@ void init_universal_scope(void) {
 	}
 
 // Constants
-	add_global_constant(a, make_string("true"),  t_untyped_bool,    make_exact_value_bool(true));
-	add_global_constant(a, make_string("false"), t_untyped_bool,    make_exact_value_bool(false));
-	add_global_constant(a, make_string("null"),  t_untyped_pointer, make_exact_value_pointer(NULL));
+	add_global_constant(a, make_string("true"),  t_untyped_bool, make_exact_value_bool(true));
+	add_global_constant(a, make_string("false"), t_untyped_bool, make_exact_value_bool(false));
+
+	add_global_entity(make_entity_nil(a, NULL, make_token_ident(make_string("nil")), t_untyped_nil));
 
 // Builtin Procedures
 	for (isize i = 0; i < gb_count_of(builtin_procs); i++) {
@@ -564,7 +571,10 @@ void init_checker(Checker *c, Parser *parser, BaseTypeSizes sizes) {
 	}
 	isize arena_size = 2 * item_size * total_token_count;
 	gb_arena_init_from_allocator(&c->arena, a, arena_size);
+	gb_arena_init_from_allocator(&c->tmp_arena, a, arena_size);
+
 	c->allocator = gb_arena_allocator(&c->arena);
+	c->tmp_allocator = gb_arena_allocator(&c->tmp_arena);
 
 	c->global_scope = make_scope(universal_scope, c->allocator);
 	c->context.scope = c->global_scope;
@@ -705,6 +715,10 @@ void add_type_info_type(Checker *c, Type *t) {
 		return;
 	}
 	t = default_type(t);
+	if (is_type_untyped(t)) {
+		return; // Could be nil
+	}
+
 	if (map_get(&c->info.type_info_map, hash_pointer(t)) != NULL) {
 		// Types have already been added
 		return;

+ 9 - 0
src/checker/entity.cpp

@@ -10,6 +10,7 @@ enum BuiltinProcId;
 	ENTITY_KIND(Procedure), \
 	ENTITY_KIND(Builtin), \
 	ENTITY_KIND(ImportName), \
+	ENTITY_KIND(Nil), \
 	ENTITY_KIND(Count),
 
 
@@ -68,6 +69,8 @@ struct Entity {
 			Scope *scope;
 			b32 used;
 		} ImportName;
+		struct {
+		} Nil;
 	};
 };
 
@@ -155,6 +158,12 @@ Entity *make_entity_import_name(gbAllocator a, Scope *scope, Token token, Type *
 	return entity;
 }
 
+Entity *make_entity_nil(gbAllocator a, Scope *scope, Token token, Type *type) {
+	Entity *entity = alloc_entity(a, Entity_Nil, scope, token, type);
+	return entity;
+}
+
+
 Entity *make_entity_dummy_variable(gbAllocator a, Scope *file_scope, Token token) {
 	token.string = make_string("_");
 	return make_entity_variable(a, file_scope, token, NULL);

+ 135 - 80
src/checker/expr.cpp

@@ -68,13 +68,16 @@ b32 check_is_assignable_to(Checker *c, Operand *operand, Type *type, b32 is_argu
 	if (is_type_untyped(src)) {
 		switch (dst->kind) {
 		case Type_Basic:
-			if (operand->mode == Addressing_Constant)
+			if (operand->mode == Addressing_Constant) {
 				return check_value_is_expressible(c, operand->value, dst, NULL);
-			if (src->kind == Type_Basic)
-				return src->Basic.kind == Basic_UntypedBool && is_type_boolean(dst);
+			}
+			if (src->kind == Type_Basic && src->Basic.kind == Basic_UntypedBool) {
+				return is_type_boolean(dst);
+			}
 			break;
-		case Type_Pointer:
-			return src->Basic.kind == Basic_UntypedPointer;
+		}
+		if (type_has_nil(dst)) {
+			return is_operand_nil(operand);
 		}
 	}
 
@@ -85,6 +88,10 @@ b32 check_is_assignable_to(Checker *c, Operand *operand, Type *type, b32 is_argu
 		return true;
 	}
 
+	if (is_type_untyped_nil(src)) {
+		return type_has_nil(dst);
+	}
+
 	// ^T <- rawptr
 	// TODO(bill): Should C-style (not C++) pointer cast be allowed?
 	// if (is_type_pointer(dst) && is_type_rawptr(src)) {
@@ -146,7 +153,13 @@ void check_assignment(Checker *c, Operand *operand, Type *type, String context_n
 	if (is_type_untyped(operand->type)) {
 		Type *target_type = type;
 
-		if (type == NULL || is_type_any(type)) {
+		if (type == NULL || is_type_any(type) || is_type_untyped_nil(type)) {
+			if (type == NULL && base_type(operand->type) == t_untyped_nil) {
+				error(ast_node_token(operand->expr), "Use of untyped nil in %.*s", LIT(context_name));
+				operand->mode = Addressing_Invalid;
+				return;
+			}
+
 			add_type_info_type(c, type);
 			target_type = default_type(operand->type);
 		}
@@ -229,14 +242,15 @@ void check_fields(Checker *c, AstNode *node, AstNodeArray decls,
 	isize other_field_index = 0;
 	Entity *using_index_expr = NULL;
 
+
+	gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena);
+	defer (gb_temp_arena_memory_end(tmp));
 	struct Delay {
 		Entity *e;
 		AstNode *t;
 	};
-	gbArray(Delay) delayed_const; gb_array_init(delayed_const, gb_heap_allocator());
-	gbArray(Delay) delayed_type;  gb_array_init(delayed_type,  gb_heap_allocator());
-	defer (gb_array_free(delayed_const));
-	defer (gb_array_free(delayed_type));
+	gbArray(Delay) delayed_const; gb_array_init_reserve(delayed_const, c->tmp_allocator, other_field_count);
+	gbArray(Delay) delayed_type;  gb_array_init_reserve(delayed_type,  c->tmp_allocator, other_field_count);
 
 	gb_for_array(decl_index, decls) {
 		AstNode *decl = decls[decl_index];
@@ -729,8 +743,8 @@ void check_enum_type(Checker *c, Type *enum_type, Type *named_type, AstNode *nod
 		make_token_ident(make_string("max_value")), constant_type, make_exact_value_integer(max_value));
 }
 
-Type *check_get_params(Checker *c, Scope *scope, AstNodeArray fields, b32 *is_variadic_) {
-	if (fields == NULL || gb_array_count(fields) == 0)
+Type *check_get_params(Checker *c, Scope *scope, AstNodeArray params, b32 *is_variadic_) {
+	if (params == NULL || gb_array_count(params) == 0)
 		return NULL;
 
 	b32 is_variadic = false;
@@ -738,33 +752,32 @@ Type *check_get_params(Checker *c, Scope *scope, AstNodeArray fields, b32 *is_va
 	Type *tuple = make_type_tuple(c->allocator);
 
 	isize variable_count = 0;
-	gb_for_array(i, fields) {
-		AstNode *field = fields[i];
-		ast_node(f, Field, field);
-		variable_count += gb_array_count(f->names);
+	gb_for_array(i, params) {
+		AstNode *field = params[i];
+		ast_node(p, Parameter, field);
+		variable_count += gb_array_count(p->names);
 	}
 
 	Entity **variables = gb_alloc_array(c->allocator, Entity *, variable_count);
 	isize variable_index = 0;
-	gb_for_array(i, fields) {
-		AstNode *field = fields[i];
-		ast_node(f, Field, field);
-		AstNode *type_expr = f->type;
+	gb_for_array(i, params) {
+		ast_node(p, Parameter, params[i]);
+		AstNode *type_expr = p->type;
 		if (type_expr) {
 			if (type_expr->kind == AstNode_Ellipsis) {
 				type_expr = type_expr->Ellipsis.expr;
-				if (i+1 == gb_array_count(fields)) {
+				if (i+1 == gb_array_count(params)) {
 					is_variadic = true;
 				} else {
-					error(ast_node_token(field), "Invalid AST: Invalid variadic parameter");
+					error(ast_node_token(params[i]), "Invalid AST: Invalid variadic parameter");
 				}
 			}
 
 			Type *type = check_type(c, type_expr);
-			gb_for_array(j, f->names) {
-				AstNode *name = f->names[j];
+			gb_for_array(j, p->names) {
+				AstNode *name = p->names[j];
 				if (name->kind == AstNode_Ident) {
-					Entity *param = make_entity_param(c->allocator, scope, name->Ident, type, f->is_using);
+					Entity *param = make_entity_param(c->allocator, scope, name->Ident, type, p->is_using);
 					add_entity(c, scope, name, param);
 					variables[variable_index++] = param;
 				} else {
@@ -774,10 +787,10 @@ Type *check_get_params(Checker *c, Scope *scope, AstNodeArray fields, b32 *is_va
 		}
 	}
 
-	if (is_variadic && gb_array_count(fields) > 0) {
+	if (is_variadic && gb_array_count(params) > 0) {
 		// NOTE(bill): Change last variadic parameter to be a slice
 		// Custom Calling convention for variadic parameters
-		Entity *end = variables[gb_array_count(fields)-1];
+		Entity *end = variables[gb_array_count(params)-1];
 		end->type = make_type_slice(c->allocator, end->type);
 	}
 
@@ -927,6 +940,10 @@ void check_identifier(Checker *c, Operand *o, AstNode *n, Type *named_type, Cycl
 		error(ast_node_token(n), "Use of import `%.*s` not in selector", LIT(e->ImportName.name));
 		return;
 
+	case Entity_Nil:
+		o->mode = Addressing_Value;
+		break;
+
 	default:
 		compiler_error("Compiler error: Unknown EntityKind");
 		break;
@@ -1184,15 +1201,20 @@ b32 check_binary_op(Checker *c, Operand *o, Token op) {
 		}
 		break;
 
-	case Token_Mod:
 	case Token_And:
 	case Token_Or:
+	case Token_AndEq:
+	case Token_OrEq:
+		if (!is_type_integer(type) && !is_type_boolean(type)) {
+			error(op, "Operator `%.*s` is only allowed with integers or booleans", LIT(op.string));
+			return false;
+		}
+		break;
+
+	case Token_Mod:
 	case Token_Xor:
 	case Token_AndNot:
-
 	case Token_ModEq:
-	case Token_AndEq:
-	case Token_OrEq:
 	case Token_XorEq:
 	case Token_AndNotEq:
 		if (!is_type_integer(type)) {
@@ -1350,7 +1372,17 @@ void check_unary_expr(Checker *c, Operand *o, Token op, AstNode *node) {
 
 	if (o->mode == Addressing_Constant) {
 		Type *type = base_type(o->type);
-		GB_ASSERT(type->kind == Type_Basic);
+		if (type->kind != Type_Basic) {
+			gbString xt = type_to_string(o->type);
+			gbString err_str = expr_to_string(node);
+			defer (gb_string_free(xt));
+			defer (gb_string_free(err_str));
+			error(op, "Invalid type, `%s`, for constant unary expression `%s`", xt, err_str);
+			o->mode = Addressing_Invalid;
+			return;
+		}
+
+
 		i32 precision = 0;
 		if (is_type_unsigned(type))
 			precision = cast(i32)(8 * type_size_of(c->sizes, c->allocator, type));
@@ -1368,6 +1400,9 @@ void check_unary_expr(Checker *c, Operand *o, Token op, AstNode *node) {
 }
 
 void check_comparison(Checker *c, Operand *x, Operand *y, Token op) {
+	gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena);
+	defer (gb_temp_arena_memory_end(tmp));
+
 	gbString err_str = NULL;
 	defer ({
 		if (err_str != NULL)
@@ -1392,16 +1427,16 @@ void check_comparison(Checker *c, Operand *x, Operand *y, Token op) {
 
 		if (!defined) {
 			gbString type_string = type_to_string(x->type);
-			err_str = gb_string_make(gb_heap_allocator(),
+			defer (gb_string_free(type_string));
+			err_str = gb_string_make(c->tmp_allocator,
 			                         gb_bprintf("operator `%.*s` not defined for type `%s`", LIT(op.string), type_string));
-			gb_string_free(type_string);
 		}
 	} else {
 		gbString xt = type_to_string(x->type);
 		gbString yt = type_to_string(y->type);
 		defer(gb_string_free(xt));
 		defer(gb_string_free(yt));
-		err_str = gb_string_make(gb_heap_allocator(),
+		err_str = gb_string_make(c->tmp_allocator,
 		                         gb_bprintf("mismatched types `%s` and `%s`", xt, yt));
 	}
 
@@ -1853,7 +1888,15 @@ void check_binary_expr(Checker *c, Operand *x, AstNode *node) {
 		ExactValue b = y->value;
 
 		Type *type = base_type(x->type);
-		GB_ASSERT(type->kind == Type_Basic);
+		if (type->kind != Type_Basic) {
+			gbString xt = type_to_string(x->type);
+			defer (gb_string_free(xt));
+			err_str = expr_to_string(node);
+			error(op, "Invalid type, `%s`, for constant binary expression `%s`", xt, err_str);
+			x->mode = Addressing_Invalid;
+			return;
+		}
+
 		if (op.kind == Token_Quo && is_type_integer(type)) {
 			op.kind = Token_QuoEq; // NOTE(bill): Hack to get division of integers
 		}
@@ -1932,8 +1975,10 @@ void convert_untyped_error(Checker *c, Operand *operand, Type *target_type) {
 
 	if (operand->mode == Addressing_Constant) {
 		if (operand->value.value_integer == 0) {
-			// NOTE(bill): Doesn't matter what the type is as it's still zero in the union
-			extra_text = " - Did you want `null`?";
+			if (make_string(expr_str) != "nil") { // HACK NOTE(bill): Just in case
+				// NOTE(bill): Doesn't matter what the type is as it's still zero in the union
+				extra_text = " - Did you want `nil`?";
+			}
 		}
 	}
 	error(ast_node_token(operand->expr), "Cannot convert `%s` to `%s`%s", expr_str, type_str, extra_text);
@@ -1989,36 +2034,27 @@ void convert_to_typed(Checker *c, Operand *operand, Type *target_type) {
 					return;
 				}
 				break;
+
+			case Basic_UntypedNil:
+				if (!type_has_nil(target_type)) {
+					convert_untyped_error(c, operand, target_type);
+					return;
+				}
+				break;
 			}
 		}
 		break;
-	case Type_Pointer:
-		switch (operand->type->Basic.kind) {
-		case Basic_UntypedPointer:
-			target_type = t_untyped_pointer;
-			break;
-		default:
-			convert_untyped_error(c, operand, target_type);
-			return;
-		}
-		break;
 
-	case Type_Proc:
-		switch (operand->type->Basic.kind) {
-		case Basic_UntypedPointer:
-			break;
-		default:
+	default:
+		if (!type_has_nil(target_type)) {
 			convert_untyped_error(c, operand, target_type);
 			return;
 		}
 		break;
-
-	default:
-		convert_untyped_error(c, operand, target_type);
-		return;
 	}
 
 	operand->type = target_type;
+	update_expr_type(c, operand->expr, target_type, true);
 }
 
 b32 check_index_value(Checker *c, AstNode *index_value, i64 max_count, i64 *value) {
@@ -2415,6 +2451,7 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
 			error(ast_node_token(expr), "Invalid argument to `type_info`");
 			return false;
 		}
+
 		add_type_info_type(c, type);
 
 		operand->mode = Addressing_Value;
@@ -2993,10 +3030,12 @@ void check_call_arguments(Checker *c, Operand *operand, Type *proc_type, AstNode
 		return;
 	}
 
+	gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena);
+	defer (gb_temp_arena_memory_end(tmp));
+
 	isize operand_count = 0;
 	gbArray(Operand) operands;
-	gb_array_init_reserve(operands, gb_heap_allocator(), 2*param_count);
-	defer (gb_array_free(operands));
+	gb_array_init_reserve(operands, c->tmp_allocator, 2*param_count);
 
 	gb_for_array(i, ce->args) {
 		Operand o = {};
@@ -3374,12 +3413,12 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint
 					error(ast_node_token(e), "Index %lld is out of bounds (>= %lld) for vector literal", index, t->Vector.count);
 				}
 
-				Operand o = {};
-				check_expr_with_type_hint(c, &o, e, elem_type);
-				check_assignment(c, &o, elem_type, context_name);
+				Operand operand = {};
+				check_expr_with_type_hint(c, &operand, e, elem_type);
+				check_assignment(c, &operand, elem_type, context_name);
 
 				if (is_constant) {
-					is_constant = o.mode == Addressing_Constant;
+					is_constant = operand.mode == Addressing_Constant;
 				}
 			}
 			if (max < index)
@@ -3730,10 +3769,9 @@ void check_expr_or_type(Checker *c, Operand *o, AstNode *e) {
 	check_expr_base(c, o, e);
 	check_not_tuple(c, o);
 	if (o->mode == Addressing_NoValue) {
-		AstNode *e = o->expr;
-		gbString str = expr_to_string(e);
+		gbString str = expr_to_string(o->expr);
 		defer (gb_string_free(str));
-		error(ast_node_token(e),
+		error(ast_node_token(o->expr),
 		      "`%s` used as value or type", str);
 		o->mode = Addressing_Invalid;
 	}
@@ -3742,15 +3780,14 @@ void check_expr_or_type(Checker *c, Operand *o, AstNode *e) {
 
 gbString write_expr_to_string(gbString str, AstNode *node);
 
-gbString write_fields_to_string(gbString str, AstNodeArray fields, char *sep) {
-	gb_for_array(i, fields) {
-		AstNode *field = fields[i];
-		ast_node(f, Field, field);
+gbString write_params_to_string(gbString str, AstNodeArray params, char *sep) {
+	gb_for_array(i, params) {
+		ast_node(p, Parameter, params[i]);
 		if (i > 0) {
 			str = gb_string_appendc(str, sep);
 		}
 
-		str = write_expr_to_string(str, field);
+		str = write_expr_to_string(str, params[i]);
 	}
 	return str;
 }
@@ -3885,19 +3922,19 @@ gbString write_expr_to_string(gbString str, AstNode *node) {
 		str = write_expr_to_string(str, vt->elem);
 	case_end;
 
-	case_ast_node(f, Field, node);
-		if (f->is_using) {
+	case_ast_node(p, Parameter, node);
+		if (p->is_using) {
 			str = gb_string_appendc(str, "using ");
 		}
-		gb_for_array(i, f->names) {
-			AstNode *name = f->names[i];
+		gb_for_array(i, p->names) {
+			AstNode *name = p->names[i];
 			if (i > 0)
 				str = gb_string_appendc(str, ", ");
 			str = write_expr_to_string(str, name);
 		}
 
 		str = gb_string_appendc(str, ": ");
-		str = write_expr_to_string(str, f->type);
+		str = write_expr_to_string(str, p->type);
 	case_end;
 
 	case_ast_node(ce, CallExpr, node);
@@ -3916,7 +3953,7 @@ gbString write_expr_to_string(gbString str, AstNode *node) {
 
 	case_ast_node(pt, ProcType, node);
 		str = gb_string_appendc(str, "proc(");
-		str = write_fields_to_string(str, pt->params, ", ");
+		str = write_params_to_string(str, pt->params, ", ");
 		str = gb_string_appendc(str, ")");
 	case_end;
 
@@ -3924,19 +3961,37 @@ gbString write_expr_to_string(gbString str, AstNode *node) {
 		str = gb_string_appendc(str, "struct ");
 		if (st->is_packed)  str = gb_string_appendc(str, "#packed ");
 		if (st->is_ordered) str = gb_string_appendc(str, "#ordered ");
-		// str = write_fields_to_string(str, st->decl_list, ", ");
+		gb_for_array(i, st->decls) {
+			if (i > 0) {
+				str = gb_string_appendc(str, "; ");
+			}
+			str = write_expr_to_string(str, st->decls[i]);
+		}
+		// str = write_params_to_string(str, st->decl_list, ", ");
 		str = gb_string_appendc(str, "}");
 	case_end;
 
 	case_ast_node(st, RawUnionType, node);
 		str = gb_string_appendc(str, "raw_union {");
-		// str = write_fields_to_string(str, st->decl_list, ", ");
+		gb_for_array(i, st->decls) {
+			if (i > 0) {
+				str = gb_string_appendc(str, "; ");
+			}
+			str = write_expr_to_string(str, st->decls[i]);
+		}
+		// str = write_params_to_string(str, st->decl_list, ", ");
 		str = gb_string_appendc(str, "}");
 	case_end;
 
 	case_ast_node(st, UnionType, node);
 		str = gb_string_appendc(str, "union {");
-		// str = write_fields_to_string(str, st->decl_list, ", ");
+		gb_for_array(i, st->decls) {
+			if (i > 0) {
+				str = gb_string_appendc(str, "; ");
+			}
+			str = write_expr_to_string(str, st->decls[i]);
+		}
+		// str = write_params_to_string(str, st->decl_list, ", ");
 		str = gb_string_appendc(str, "}");
 	case_end;
 

+ 33 - 19
src/checker/stmt.cpp

@@ -11,14 +11,19 @@ void check_stmt(Checker *c, AstNode *node, u32 flags);
 void check_proc_decl(Checker *c, Entity *e, DeclInfo *d);
 
 void check_stmt_list(Checker *c, AstNodeArray stmts, u32 flags) {
+	if (stmts == NULL) {
+		return;
+	}
+
+	gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena);
+	defer (gb_temp_arena_memory_end(tmp));
+
 	struct Delay {
 		Entity *e;
 		DeclInfo *d;
 	};
-	gbArray(Delay) delayed_const; gb_array_init(delayed_const, gb_heap_allocator());
-	gbArray(Delay) delayed_type;  gb_array_init(delayed_type,  gb_heap_allocator());
-	defer (gb_array_free(delayed_const));
-	defer (gb_array_free(delayed_type));
+	gbArray(Delay) delayed_const; gb_array_init_reserve(delayed_const, c->tmp_allocator, gb_array_count(stmts));
+	gbArray(Delay) delayed_type;  gb_array_init_reserve(delayed_type,  c->tmp_allocator, gb_array_count(stmts));
 
 	gb_for_array(i, stmts) {
 		AstNode *node = stmts[i];
@@ -312,8 +317,8 @@ Type *check_init_variable(Checker *c, Entity *e, Operand *operand, String contex
 		// NOTE(bill): Use the type of the operand
 		Type *t = operand->type;
 		if (is_type_untyped(t)) {
-			if (t == t_invalid) {
-				error(e->token, "Use of untyped thing in %.*s", LIT(context_name));
+			if (t == t_invalid || is_type_untyped_nil(t)) {
+				error(e->token, "Use of untyped nil in %.*s", LIT(context_name));
 				e->type = t_invalid;
 				return NULL;
 			}
@@ -331,13 +336,17 @@ Type *check_init_variable(Checker *c, Entity *e, Operand *operand, String contex
 }
 
 void check_init_variables(Checker *c, Entity **lhs, isize lhs_count, AstNodeArray inits, String context_name) {
-	if ((lhs == NULL || lhs_count == 0) && gb_array_count(inits) == 0)
+	if ((lhs == NULL || lhs_count == 0) && (inits == NULL || gb_array_count(inits) == 0)) {
 		return;
+	}
+
+	gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena);
+	defer (gb_temp_arena_memory_end(tmp));
 
-	// TODO(bill): Do not use heap allocation here if I can help it
+	// NOTE(bill): If there is a bad syntax error, rhs > lhs which would mean there would need to be
+	// an extra allocation
 	gbArray(Operand) operands;
-	gb_array_init_reserve(operands, gb_heap_allocator(), 2*lhs_count);
-	defer (gb_array_free(operands));
+	gb_array_init_reserve(operands, c->tmp_allocator, 2*lhs_count);
 
 	gb_for_array(i, inits) {
 		AstNode *rhs = inits[i];
@@ -907,10 +916,13 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
 				return;
 			}
 
-			// TODO(bill): Do not use heap allocation here if I can help it
+			gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena);
+			defer (gb_temp_arena_memory_end(tmp));
+
+			// NOTE(bill): If there is a bad syntax error, rhs > lhs which would mean there would need to be
+			// an extra allocation
 			gbArray(Operand) operands;
-			gb_array_init(operands, gb_heap_allocator());
-			defer (gb_array_free(operands));
+			gb_array_init_reserve(operands, c->tmp_allocator, 2 * gb_array_count(as->lhs));
 
 			gb_for_array(i, as->rhs) {
 				AstNode *rhs = as->rhs[i];
@@ -1091,8 +1103,8 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
 			AstNode *stmt = bs->stmts[i];
 			AstNode *default_stmt = NULL;
 			if (stmt->kind == AstNode_CaseClause) {
-				ast_node(c, CaseClause, stmt);
-				if (gb_array_count(c->list) == 0) {
+				ast_node(cc, CaseClause, stmt);
+				if (gb_array_count(cc->list) == 0) {
 					default_stmt = stmt;
 				}
 			} else {
@@ -1158,9 +1170,11 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
 					HashKey key = hash_exact_value(y.value);
 					auto *found = map_get(&seen, key);
 					if (found != NULL) {
+						gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena);
+						defer (gb_temp_arena_memory_end(tmp));
+
 						isize count = multi_map_count(&seen, key);
-						TypeAndToken *taps = gb_alloc_array(gb_heap_allocator(), TypeAndToken, count);
-						defer (gb_free(gb_heap_allocator(), taps));
+						TypeAndToken *taps = gb_alloc_array(c->tmp_allocator, TypeAndToken, count);
 
 						multi_map_get_all(&seen, key, taps);
 						b32 continue_outer = false;
@@ -1227,8 +1241,8 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
 			AstNode *stmt = bs->stmts[i];
 			AstNode *default_stmt = NULL;
 			if (stmt->kind == AstNode_CaseClause) {
-				ast_node(c, CaseClause, stmt);
-				if (gb_array_count(c->list) == 0) {
+				ast_node(cc, CaseClause, stmt);
+				if (gb_array_count(cc->list) == 0) {
 					default_stmt = stmt;
 				}
 			} else {

+ 47 - 10
src/checker/type.cpp

@@ -22,9 +22,9 @@ enum BasicKind {
 	Basic_UntypedBool,
 	Basic_UntypedInteger,
 	Basic_UntypedFloat,
-	Basic_UntypedPointer,
 	Basic_UntypedString,
 	Basic_UntypedRune,
+	Basic_UntypedNil,
 
 	Basic_Count,
 
@@ -309,9 +309,9 @@ gb_global Type basic_types[] = {
 	{Type_Basic, 0, {Basic_UntypedBool,    BasicFlag_Boolean | BasicFlag_Untyped,  STR_LIT("untyped bool")}},
 	{Type_Basic, 0, {Basic_UntypedInteger, BasicFlag_Integer | BasicFlag_Untyped,  STR_LIT("untyped integer")}},
 	{Type_Basic, 0, {Basic_UntypedFloat,   BasicFlag_Float   | BasicFlag_Untyped,  STR_LIT("untyped float")}},
-	{Type_Basic, 0, {Basic_UntypedPointer, BasicFlag_Pointer | BasicFlag_Untyped,  STR_LIT("untyped pointer")}},
 	{Type_Basic, 0, {Basic_UntypedString,  BasicFlag_String  | BasicFlag_Untyped,  STR_LIT("untyped string")}},
 	{Type_Basic, 0, {Basic_UntypedRune,    BasicFlag_Integer | BasicFlag_Untyped,  STR_LIT("untyped rune")}},
+	{Type_Basic, 0, {Basic_UntypedNil,     BasicFlag_Untyped,                      STR_LIT("untyped nil")}},
 };
 
 gb_global Type basic_type_aliases[] = {
@@ -339,9 +339,9 @@ gb_global Type *t_any             = &basic_types[Basic_any];
 gb_global Type *t_untyped_bool    = &basic_types[Basic_UntypedBool];
 gb_global Type *t_untyped_integer = &basic_types[Basic_UntypedInteger];
 gb_global Type *t_untyped_float   = &basic_types[Basic_UntypedFloat];
-gb_global Type *t_untyped_pointer = &basic_types[Basic_UntypedPointer];
 gb_global Type *t_untyped_string  = &basic_types[Basic_UntypedString];
 gb_global Type *t_untyped_rune    = &basic_types[Basic_UntypedRune];
+gb_global Type *t_untyped_nil     = &basic_types[Basic_UntypedNil];
 gb_global Type *t_byte            = &basic_type_aliases[0];
 gb_global Type *t_rune            = &basic_type_aliases[1];
 
@@ -548,6 +548,11 @@ b32 is_type_any(Type *t) {
 	t = base_type(t);
 	return (t->kind == Type_Basic && t->Basic.kind == Basic_any);
 }
+b32 is_type_untyped_nil(Type *t) {
+	t = base_type(t);
+	return (t->kind == Type_Basic && t->Basic.kind == Basic_UntypedNil);
+}
+
 
 
 b32 is_type_indexable(Type *t) {
@@ -555,12 +560,31 @@ b32 is_type_indexable(Type *t) {
 }
 
 
+b32 type_has_nil(Type *t) {
+	t = base_type(t);
+	switch (t->kind) {
+	case Type_Basic:
+		return is_type_rawptr(t);
+
+	case Type_Tuple:
+		return false;
+
+	case Type_Record:
+		switch (t->Record.kind) {
+		case TypeRecord_Enum:
+			return false;
+		}
+		break;
+	}
+	return true;
+}
+
 
 b32 is_type_comparable(Type *t) {
 	t = base_type(t);
 	switch (t->kind) {
 	case Type_Basic:
-		return true;
+		return t->kind != Basic_UntypedNil;
 	case Type_Pointer:
 		return true;
 	case Type_Record: {
@@ -681,12 +705,12 @@ b32 are_types_identical(Type *x, Type *y) {
 Type *default_type(Type *type) {
 	if (type->kind == Type_Basic) {
 		switch (type->Basic.kind) {
-		case Basic_UntypedBool:    return &basic_types[Basic_bool];
-		case Basic_UntypedInteger: return &basic_types[Basic_int];
-		case Basic_UntypedFloat:   return &basic_types[Basic_f64];
-		case Basic_UntypedString:  return &basic_types[Basic_string];
-		case Basic_UntypedRune:    return &basic_types[Basic_rune];
-		case Basic_UntypedPointer: return &basic_types[Basic_rawptr];
+		case Basic_UntypedBool:    return t_bool;
+		case Basic_UntypedInteger: return t_int;
+		case Basic_UntypedFloat:   return t_f64;
+		case Basic_UntypedString:  return t_string;
+		case Basic_UntypedRune:    return t_rune;
+		// case Basic_UntypedPointer: return &basic_types[Basic_rawptr];
 		}
 	}
 	return type;
@@ -952,6 +976,17 @@ i64 type_align_of(BaseTypeSizes s, gbAllocator allocator, Type *t) {
 		return gb_clamp(size, 1, s.max_align);
 	} break;
 
+	case Type_Tuple: {
+		i64 max = 1;
+		for (isize i = 0; i < t->Tuple.variable_count; i++) {
+			i64 align = type_align_of(s, allocator, t->Tuple.variables[i]->type);
+			if (max < align) {
+				max = align;
+			}
+		}
+		return max;
+	} break;
+
 	case Type_Record: {
 		switch (t->Record.kind) {
 		case TypeRecord_Struct:
@@ -964,6 +999,8 @@ i64 type_align_of(BaseTypeSizes s, gbAllocator allocator, Type *t) {
 					}
 				}
 				return max;
+			} else if (t->Record.field_count > 0) {
+				return type_align_of(s, allocator, t->Record.fields[0]->type);
 			}
 			break;
 		case TypeRecord_Union: {

+ 12 - 11
src/codegen/codegen.cpp

@@ -21,8 +21,9 @@ b32 ssa_gen_init(ssaGen *s, Checker *c) {
 	// TODO(bill): generate appropriate output name
 	int pos = cast(int)string_extension_position(c->parser->init_fullpath);
 	gbFileError err = gb_file_create(&s->output_file, gb_bprintf("%.*s.ll", pos, c->parser->init_fullpath.text));
-	if (err != gbFileError_None)
+	if (err != gbFileError_None) {
 		return false;
+	}
 
 	return true;
 }
@@ -434,10 +435,10 @@ void ssa_gen_tree(ssaGen *s) {
 							ssaValue *ordered = ssa_make_const_bool(a, t->Record.struct_is_ordered);
 							ssaValue *size    = ssa_make_const_int(a, type_size_of(m->sizes, a, t));
 							ssaValue *align   = ssa_make_const_int(a, type_align_of(m->sizes, a, t));
-							ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, 1, t_bool_ptr), packed);
-							ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, 2, t_bool_ptr), ordered);
-							ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, 3, t_int_ptr),  size);
-							ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, 4, t_int_ptr),  align);
+							ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, 1, t_int_ptr),  size);
+							ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, 2, t_int_ptr),  align);
+							ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, 3, t_bool_ptr), packed);
+							ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, 4, t_bool_ptr), ordered);
 						}
 
 						ssaValue *memory = type_info_member_offset(proc, type_info_member_data, t->Record.field_count, &type_info_member_index);
@@ -481,8 +482,8 @@ void ssa_gen_tree(ssaGen *s) {
 						{
 							ssaValue *size    = ssa_make_const_int(a, type_size_of(m->sizes, a, t));
 							ssaValue *align   = ssa_make_const_int(a, type_align_of(m->sizes, a, t));
-							ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, 3, t_int_ptr),  size);
-							ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, 4, t_int_ptr),  align);
+							ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, 1, t_int_ptr),  size);
+							ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, 2, t_int_ptr),  align);
 						}
 						break;
 					case TypeRecord_RawUnion: {
@@ -490,8 +491,8 @@ void ssa_gen_tree(ssaGen *s) {
 						{
 							ssaValue *size    = ssa_make_const_int(a, type_size_of(m->sizes, a, t));
 							ssaValue *align   = ssa_make_const_int(a, type_align_of(m->sizes, a, t));
-							ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, 3, t_int_ptr),  size);
-							ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, 4, t_int_ptr),  align);
+							ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, 1, t_int_ptr),  size);
+							ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, 2, t_int_ptr),  align);
 						}
 
 						ssaValue *memory = type_info_member_offset(proc, type_info_member_data, t->Record.field_count, &type_info_member_index);
@@ -605,8 +606,8 @@ void ssa_gen_tree(ssaGen *s) {
 					tag = ssa_add_local_generated(proc, t_type_info_tuple);
 
 					{
-						ssaValue *align   = ssa_make_const_int(a, type_align_of(m->sizes, a, t));
-						ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, 4, t_int_ptr),  align);
+						ssaValue *align = ssa_make_const_int(a, type_align_of(m->sizes, a, t));
+						ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, 2, t_int_ptr), align);
 					}
 
 					ssaValue *memory = type_info_member_offset(proc, type_info_member_data, t->Tuple.variable_count, &type_info_member_index);

+ 16 - 10
src/codegen/print_llvm.cpp

@@ -157,13 +157,7 @@ void ssa_print_type(ssaFileBuffer *f, ssaModule *m, Type *t) {
 		case Basic_string: ssa_fprintf(f, "%%..string");              break;
 		case Basic_uint:   ssa_fprintf(f, "i%lld", word_bits);        break;
 		case Basic_int:    ssa_fprintf(f, "i%lld", word_bits);        break;
-		case Basic_any:
-			ssa_fprintf(f, "{");
-			ssa_print_type(f, m, t_type_info_ptr);
-			ssa_fprintf(f, ", ");
-			ssa_print_type(f, m, t_rawptr);
-			ssa_fprintf(f, "}");
-			break;
+		case Basic_any:    ssa_fprintf(f, "%%..any");                 break;
 		}
 		break;
 	case Type_Array:
@@ -491,7 +485,8 @@ void ssa_print_exact_value(ssaFileBuffer *f, ssaModule *m, ExactValue value, Typ
 	} break;
 
 	default:
-		GB_PANIC("Invalid ExactValue: %d", value.kind);
+		ssa_fprintf(f, "zeroinitializer");
+		// GB_PANIC("Invalid ExactValue: %d", value.kind);
 		break;
 	}
 }
@@ -538,6 +533,10 @@ void ssa_print_value(ssaFileBuffer *f, ssaModule *m, ssaValue *value, Type *type
 		}
 	} break;
 
+	case ssaValue_Nil:
+		ssa_fprintf(f, "zeroinitializer");
+		break;
+
 	case ssaValue_TypeName:
 		ssa_print_encoded_local(f, value->TypeName.name);
 		break;
@@ -1045,9 +1044,16 @@ void ssa_print_llvm_ir(ssaFileBuffer *f, ssaModule *m) {
 	ssa_fprintf(f, " = type {i8*, ");
 	ssa_print_type(f, m, t_int);
 	ssa_fprintf(f, "} ; Basic_string\n");
-
 	ssa_print_encoded_local(f, make_string("..rawptr"));
-	ssa_fprintf(f, " = type i8* ; Basic_rawptr\n\n");
+	ssa_fprintf(f, " = type i8* ; Basic_rawptr\n");
+
+	ssa_print_encoded_local(f, make_string("..any"));
+	ssa_fprintf(f, " = type {");
+	ssa_print_type(f, m, t_type_info_ptr);
+	ssa_fprintf(f, ", ");
+	ssa_print_type(f, m, t_rawptr);
+	ssa_fprintf(f, "} ; Basic_any\n");
+
 
 	gb_for_array(member_index, m->members.entries) {
 		auto *entry = &m->members.entries[member_index];

+ 24 - 5
src/codegen/ssa.cpp

@@ -298,6 +298,7 @@ enum ssaValueKind {
 
 	ssaValue_Constant,
 	ssaValue_ConstantSlice,
+	ssaValue_Nil,
 	ssaValue_TypeName,
 	ssaValue_Global,
 	ssaValue_Param,
@@ -323,6 +324,9 @@ struct ssaValue {
 			ssaValue *backing_array;
 			i64 count;
 		} ConstantSlice;
+		struct {
+			Type *type;
+		} Nil;
 		struct {
 			String name;
 			Type * type;
@@ -540,6 +544,8 @@ Type *ssa_type(ssaValue *value) {
 		return value->Constant.type;
 	case ssaValue_ConstantSlice:
 		return value->ConstantSlice.type;
+	case ssaValue_Nil:
+		return value->Nil.type;
 	case ssaValue_TypeName:
 		return value->TypeName.type;
 	case ssaValue_Global:
@@ -643,6 +649,12 @@ ssaValue *ssa_make_value_param(gbAllocator a, ssaProcedure *parent, Entity *e) {
 	v->Param.type   = e->type;
 	return v;
 }
+ssaValue *ssa_make_value_nil(gbAllocator a, Type *type) {
+	ssaValue *v = ssa_alloc_value(a, ssaValue_Nil);
+	v->Nil.type = type;
+	return v;
+}
+
 
 
 ssaValue *ssa_make_instr_local(ssaProcedure *p, Entity *e, b32 zero_initialized) {
@@ -975,11 +987,8 @@ ssaValue *ssa_emit_comment(ssaProcedure *p, String text) {
 ssaValue *ssa_add_local(ssaProcedure *proc, Entity *e, b32 zero_initialized = true) {
 	ssaBlock *b = proc->decl_block; // all variables must be in the first block
 	ssaValue *instr = ssa_make_instr_local(proc, e, zero_initialized);
-	ssaValue *zero = ssa_make_instr_zero_init(proc, instr);
 	instr->Instr.parent = b;
-	zero ->Instr.parent = b;
 	gb_array_append(b->instrs, instr);
-	gb_array_append(b->instrs, zero);
 
 	// if (zero_initialized) {
 		ssa_emit_zero_init(proc, instr);
@@ -1301,9 +1310,9 @@ ssaValue *ssa_emit_comp(ssaProcedure *proc, Token op, ssaValue *left, ssaValue *
 
 	if (are_types_identical(a, b)) {
 		// NOTE(bill): No need for a conversion
-	} else if (left->kind == ssaValue_Constant) {
+	} else if (left->kind == ssaValue_Constant || left->kind == ssaValue_Nil) {
 		left = ssa_emit_conv(proc, left, ssa_type(right));
-	} else if (right->kind == ssaValue_Constant) {
+	} else if (right->kind == ssaValue_Constant || right->kind == ssaValue_Nil) {
 		right = ssa_emit_conv(proc, right, ssa_type(left));
 	}
 
@@ -1880,6 +1889,10 @@ ssaValue *ssa_emit_conv(ssaProcedure *proc, ssaValue *value, Type *t, b32 is_arg
 	if (is_type_any(dst)) {
 		ssaValue *result = ssa_add_local_generated(proc, t_any);
 
+		if (is_type_untyped_nil(src)) {
+			return ssa_emit_load(proc, result);
+		}
+
 		ssaValue *data = NULL;
 		if (value->kind == ssaValue_Instr &&
 		    value->Instr.kind == ssaInstr_Load) {
@@ -1905,6 +1918,10 @@ ssaValue *ssa_emit_conv(ssaProcedure *proc, ssaValue *value, Type *t, b32 is_arg
 		return ssa_emit_load(proc, result);
 	}
 
+	if (is_type_untyped_nil(src) && type_has_nil(dst)) {
+		return ssa_make_value_nil(proc->module->allocator, t);
+	}
+
 
 	gb_printf_err("Not Identical %s != %s\n", type_to_string(src_type), type_to_string(t));
 	gb_printf_err("Not Identical %s != %s\n", type_to_string(src), type_to_string(dst));
@@ -2035,6 +2052,8 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
 			         "\t at %.*s(%td:%td)", LIT(builtin_procs[e->Builtin.id].name),
 			         LIT(token.pos.file), token.pos.line, token.pos.column);
 			return NULL;
+		} else if (e->kind == Entity_Nil) {
+			return ssa_make_value_nil(proc->module->allocator, tv->type);
 		}
 
 		auto *found = map_get(&proc->module->values, hash_pointer(e));

+ 2 - 0
src/exact_value.cpp

@@ -275,6 +275,8 @@ ExactValue exact_binary_operator_value(Token op, ExactValue x, ExactValue y) {
 		switch (op.kind) {
 		case Token_CmpAnd: return make_exact_value_bool(x.value_bool && y.value_bool);
 		case Token_CmpOr:  return make_exact_value_bool(x.value_bool || y.value_bool);
+		case Token_And:    return make_exact_value_bool(x.value_bool & y.value_bool);
+		case Token_Or:     return make_exact_value_bool(x.value_bool | y.value_bool);
 		default: goto error;
 		}
 		break;

+ 84 - 74
src/parser.cpp

@@ -131,7 +131,7 @@ AST_NODE_KIND(_ExprBegin,  "",  struct{}) \
 	AST_NODE_KIND(DerefExpr,    "dereference expression", struct { Token op; AstNode *expr; }) \
 	AST_NODE_KIND(CallExpr,     "call expression", struct { \
 		AstNode *proc; \
-		gbArray(AstNode *) args; \
+		AstNodeArray args; \
 		Token open, close; \
 		Token ellipsis; \
 		CallExprKind kind; \
@@ -256,7 +256,7 @@ AST_NODE_KIND(_DeclBegin,      "", struct{}) \
 	AST_NODE_KIND(ForeignSystemLibrary, "foreign system library", struct { Token token, filepath; }) \
 AST_NODE_KIND(_DeclEnd,   "", struct{}) \
 AST_NODE_KIND(_TypeBegin, "", struct{}) \
-	AST_NODE_KIND(Field, "field", struct { \
+	AST_NODE_KIND(Parameter, "parameter", struct { \
 		AstNodeArray names; \
 		AstNode *type; \
 		b32 is_using; \
@@ -444,11 +444,11 @@ Token ast_node_token(AstNode *node) {
 		return node->ImportDecl.token;
 	case AstNode_ForeignSystemLibrary:
 		return node->ForeignSystemLibrary.token;
-	case AstNode_Field: {
-		if (node->Field.names)
-			return ast_node_token(node->Field.names[0]);
+	case AstNode_Parameter: {
+		if (node->Parameter.names)
+			return ast_node_token(node->Parameter.names[0]);
 		else
-			return ast_node_token(node->Field.type);
+			return ast_node_token(node->Parameter.type);
 	}
 	case AstNode_ProcType:
 		return node->ProcType.token;
@@ -545,7 +545,7 @@ gb_inline AstNode *make_paren_expr(AstFile *f, AstNode *expr, Token open, Token
 	return result;
 }
 
-gb_inline AstNode *make_call_expr(AstFile *f, AstNode *proc, gbArray(AstNode *)args, Token open, Token close, Token ellipsis) {
+gb_inline AstNode *make_call_expr(AstFile *f, AstNode *proc, AstNodeArray args, Token open, Token close, Token ellipsis) {
 	AstNode *result = make_node(f, AstNode_CallExpr);
 	result->CallExpr.proc = proc;
 	result->CallExpr.args = args;
@@ -823,11 +823,11 @@ gb_inline AstNode *make_const_decl(AstFile *f, AstNodeArray names, AstNode *type
 	return result;
 }
 
-gb_inline AstNode *make_field(AstFile *f, AstNodeArray names, AstNode *type, b32 is_using) {
-	AstNode *result = make_node(f, AstNode_Field);
-	result->Field.names = names;
-	result->Field.type = type;
-	result->Field.is_using = is_using;
+gb_inline AstNode *make_parameter(AstFile *f, AstNodeArray names, AstNode *type, b32 is_using) {
+	AstNode *result = make_node(f, AstNode_Parameter);
+	result->Parameter.names = names;
+	result->Parameter.type = type;
+	result->Parameter.is_using = is_using;
 	return result;
 }
 
@@ -961,6 +961,19 @@ gb_inline Token expect_token(AstFile *f, TokenKind kind) {
 	return prev;
 }
 
+gb_inline Token expect_token_after(AstFile *f, TokenKind kind, char *msg) {
+	Token prev = f->curr_token;
+	if (prev.kind != kind) {
+		syntax_error(f->curr_token, "Expected `%.*s` after %s, got `%.*s`",
+		             LIT(token_strings[kind]),
+		             msg,
+		             LIT(token_strings[prev.kind]));
+	}
+	next_token(f);
+	return prev;
+}
+
+
 gb_inline Token expect_operator(AstFile *f) {
 	Token prev = f->curr_token;
 	if (!gb_is_between(prev.kind, Token__OperatorBegin+1, Token__OperatorEnd-1)) {
@@ -1650,7 +1663,7 @@ AstNode *parse_binary_expr(AstFile *f, b32 lhs, i32 prec_in) {
 
 					expression = call;
 				} else  */{
-					AstNode *right = parse_binary_expr(f, false, prec+1);
+					right = parse_binary_expr(f, false, prec+1);
 					gbArray(AstNode *) args;
 					gb_array_init_reserve(args, gb_arena_allocator(&f->arena), 2);
 					gb_array_append(args, expression);
@@ -1841,58 +1854,54 @@ AstNode *parse_proc_type(AstFile *f) {
 	return make_proc_type(f, proc_token, params, results);
 }
 
-AstNode *parse_field_decl(AstFile *f) {
-	b32 is_using = false;
-	if (allow_token(f, Token_using)) {
-		is_using = true;
-	}
 
-	AstNodeArray names = parse_lhs_expr_list(f);
-	if (gb_array_count(names) == 0) {
-		syntax_error(f->curr_token, "Empty field declaration");
-	}
+AstNodeArray parse_parameter_list(AstFile *f) {
+	AstNodeArray params = make_ast_node_array(f);
 
-	if (gb_array_count(names) > 1 && is_using) {
-		syntax_error(f->curr_token, "Cannot apply `using` to more than one of the same type");
-		is_using = false;
-	}
+	while (f->curr_token.kind == Token_Identifier ||
+	       f->curr_token.kind == Token_using) {
+		b32 is_using = false;
+		if (allow_token(f, Token_using)) {
+			is_using = true;
+		}
 
+		AstNodeArray names = parse_lhs_expr_list(f);
+		if (gb_array_count(names) == 0) {
+			syntax_error(f->curr_token, "Empty parameter declaration");
+		}
+
+		if (gb_array_count(names) > 1 && is_using) {
+			syntax_error(f->curr_token, "Cannot apply `using` to more than one of the same type");
+			is_using = false;
+		}
 
-	expect_token(f, Token_Colon);
+		expect_token_after(f, Token_Colon, "parameter list");
 
-	AstNode *type = NULL;
-	if (f->curr_token.kind == Token_Ellipsis) {
-		Token ellipsis = f->curr_token;
-		next_token(f);
-		type = parse_type_attempt(f);
-		if (type == NULL) {
-			syntax_error(f->curr_token, "variadic parameter is missing a type after `..`");
-			type = make_bad_expr(f, ellipsis, f->curr_token);
-		} else {
-			if (gb_array_count(names) > 1) {
-				syntax_error(f->curr_token, "mutliple variadic parameters, only  `..`");
+		AstNode *type = NULL;
+		if (f->curr_token.kind == Token_Ellipsis) {
+			Token ellipsis = f->curr_token;
+			next_token(f);
+			type = parse_type_attempt(f);
+			if (type == NULL) {
+				syntax_error(f->curr_token, "variadic parameter is missing a type after `..`");
+				type = make_bad_expr(f, ellipsis, f->curr_token);
 			} else {
-				type = make_ellipsis(f, ellipsis, type);
+				if (gb_array_count(names) > 1) {
+					syntax_error(f->curr_token, "mutliple variadic parameters, only  `..`");
+				} else {
+					type = make_ellipsis(f, ellipsis, type);
+				}
 			}
+		} else {
+			type = parse_type_attempt(f);
 		}
-	} else {
-		type = parse_type_attempt(f);
-	}
 
-	if (type == NULL) {
-		syntax_error(f->curr_token, "Expected a type for this field declaration");
-	}
 
-	AstNode *field = make_field(f, names, type, is_using);
-	return field;
-}
+		if (type == NULL) {
+			syntax_error(f->curr_token, "Expected a type for this parameter declaration");
+		}
 
-AstNodeArray parse_parameter_list(AstFile *f) {
-	AstNodeArray params = make_ast_node_array(f);
-	while (f->curr_token.kind == Token_Identifier ||
-	       f->curr_token.kind == Token_using) {
-		AstNode *field = parse_field_decl(f);
-		gb_array_append(params, field);
+		gb_array_append(params, make_parameter(f, names, type, is_using));
 		if (f->curr_token.kind != Token_Comma) {
 			break;
 		}
@@ -2011,7 +2020,7 @@ AstNode *parse_identifier_or_type(AstFile *f, u32 flags) {
 		b32 is_packed = false;
 		b32 is_ordered = false;
 		while (allow_token(f, Token_Hash)) {
-			Token tag = expect_token(f, Token_Identifier);
+			Token tag = expect_token_after(f, Token_Identifier, "`#`");
 			if (tag.string == "packed") {
 				if (is_packed) {
 					syntax_error(tag, "Duplicate struct tag `#%.*s`", LIT(tag.string));
@@ -2031,7 +2040,7 @@ AstNode *parse_identifier_or_type(AstFile *f, u32 flags) {
 			syntax_error(token, "`#ordered` is not needed with `#packed` which implies ordering");
 		}
 
-		Token open = expect_token(f, Token_OpenBrace);
+		Token open = expect_token_after(f, Token_OpenBrace, "`struct`");
 		isize decl_count = 0;
 		AstNodeArray decls = parse_struct_params(f, &decl_count, true);
 		Token close = expect_token(f, Token_CloseBrace);
@@ -2041,7 +2050,7 @@ AstNode *parse_identifier_or_type(AstFile *f, u32 flags) {
 
 	case Token_union: {
 		Token token = expect_token(f, Token_union);
-		Token open = expect_token(f, Token_OpenBrace);
+		Token open = expect_token_after(f, Token_OpenBrace, "`union`");
 		isize decl_count = 0;
 		AstNodeArray decls = parse_struct_params(f, &decl_count, false);
 		Token close = expect_token(f, Token_CloseBrace);
@@ -2050,7 +2059,7 @@ AstNode *parse_identifier_or_type(AstFile *f, u32 flags) {
 	}
 
 	case Token_raw_union: {
-		Token token = expect_token(f, Token_raw_union);
+		Token token = expect_token_after(f, Token_OpenBrace, "`raw_union`");
 		Token open = expect_token(f, Token_OpenBrace);
 		isize decl_count = 0;
 		AstNodeArray decls = parse_struct_params(f, &decl_count, true);
@@ -2070,7 +2079,7 @@ AstNode *parse_identifier_or_type(AstFile *f, u32 flags) {
 
 		AstNodeArray fields = make_ast_node_array(f);
 
-		open  = expect_token(f, Token_OpenBrace);
+		open = expect_token_after(f, Token_OpenBrace, "`enum`");
 
 		while (f->curr_token.kind != Token_CloseBrace &&
 		       f->curr_token.kind != Token_EOF) {
@@ -2161,7 +2170,7 @@ Token parse_procedure_signature(AstFile *f,
 	Token proc_token = expect_token(f, Token_proc);
 	expect_token(f, Token_OpenParen);
 	*params = parse_parameter_list(f);
-	expect_token(f, Token_CloseParen);
+	expect_token_after(f, Token_CloseParen, "parameter list");
 	*results = parse_results(f);
 	return proc_token;
 }
@@ -2210,17 +2219,17 @@ AstNode *parse_decl(AstFile *f, AstNodeArray names) {
 	AstNodeArray values = NULL;
 	AstNode *type = NULL;
 
-	gb_for_array(i, names) {
-		AstNode *name = names[i];
-		if (name->kind == AstNode_Ident) {
-			String n = name->Ident.string;
-			// NOTE(bill): Check for reserved identifiers
-			if (n == "context") {
-				syntax_error(ast_node_token(name), "`context` is a reserved identifier");
-				break;
-			}
-		}
-	}
+	// gb_for_array(i, names) {
+	// 	AstNode *name = names[i];
+	// 	if (name->kind == AstNode_Ident) {
+	// 		String n = name->Ident.string;
+	// 		// NOTE(bill): Check for reserved identifiers
+	// 		if (n == "context") {
+	// 			syntax_error(ast_node_token(name), "`context` is a reserved identifier");
+	// 			break;
+	// 		}
+	// 	}
+	// }
 
 	if (allow_token(f, Token_Colon)) {
 		if (!allow_token(f, Token_type)) {
@@ -2258,8 +2267,7 @@ AstNode *parse_decl(AstFile *f, AstNodeArray names) {
 				// NOTE(bill): Do not fail though
 			}
 
-			AstNode *type = parse_type(f);
-			return make_type_decl(f, token, names[0], type);
+			return make_type_decl(f, token, names[0], parse_type(f));
 		} else if (f->curr_token.kind == Token_proc &&
 		    is_mutable == false) {
 		    // NOTE(bill): Procedure declarations
@@ -2434,6 +2442,7 @@ AstNode *parse_case_clause(AstFile *f) {
 		expect_token(f, Token_default);
 	}
 	expect_token(f, Token_Colon); // TODO(bill): Is this the best syntax?
+	// expect_token(f, Token_ArrowRight); // TODO(bill): Is this the best syntax?
 	AstNodeArray stmts = parse_stmt_list(f);
 
 	return make_case_clause(f, token, list, stmts);
@@ -2449,6 +2458,7 @@ AstNode *parse_type_case_clause(AstFile *f) {
 		expect_token(f, Token_default);
 	}
 	expect_token(f, Token_Colon); // TODO(bill): Is this the best syntax?
+	// expect_token(f, Token_ArrowRight); // TODO(bill): Is this the best syntax?
 	AstNodeArray stmts = parse_stmt_list(f);
 
 	return make_case_clause(f, token, clause, stmts);
@@ -3069,7 +3079,7 @@ ParseFileError parse_files(Parser *p, char *init_filename) {
 	p->init_fullpath = init_fullpath;
 
 	{
-		String s = get_fullpath_core(gb_heap_allocator(), make_string("runtime.odin"));
+		String s = get_fullpath_core(gb_heap_allocator(), make_string("_preload.odin"));
 		ImportedFile runtime_file = {s, s, init_pos};
 		gb_array_append(p->imports, runtime_file);
 	}

+ 4 - 4
src/printer.cpp

@@ -190,11 +190,11 @@ void print_ast(AstNode *node, isize indent) {
 			}
 		}
 		break;
-	case AstNode_Field:
-		gb_for_array(i, node->Field.names) {
-			print_ast(node->Field.names[i], indent+1);
+	case AstNode_Parameter:
+		gb_for_array(i, node->Parameter.names) {
+			print_ast(node->Parameter.names[i], indent+1);
 		}
-		print_ast(node->Field.type, indent);
+		print_ast(node->Parameter.type, indent);
 		break;
 	case AstNode_PointerType:
 		print_indent(indent);

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 6586 - 6583
src/utf8proc/utf8proc_data.c


برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است