2
0
Эх сурвалжийг харах

Merge branch 'master' of https://github.com/odin-lang/Odin

gingerBill 5 сар өмнө
parent
commit
b07387321a

+ 1 - 0
build.bat

@@ -138,6 +138,7 @@ del *.ilk > NUL 2> NUL
 
 rc %rc_flags% %odin_rc%
 cl %compiler_settings% "src\main.cpp" "src\libtommath.cpp" /link %linker_settings% -OUT:%exe_name%
+if %errorlevel% neq 0 goto end_of_build
 mt -nologo -inputresource:%exe_name%;#1 -manifest misc\odin.manifest -outputresource:%exe_name%;#1 -validate_manifest -identity:"odin, processorArchitecture=amd64, version=%odin_version_full%, type=win32"
 if %errorlevel% neq 0 goto end_of_build
 

+ 2 - 2
core/encoding/hxa/read.odin

@@ -79,7 +79,6 @@ read :: proc(data: []byte, filename := "<input>", print_error := false, allocato
 	read_meta :: proc(r: ^Reader, capacity: u32le, allocator := context.allocator, loc := #caller_location) -> (meta_data: []Meta, err: Read_Error) {
 		meta_data = make([]Meta, int(capacity), allocator=allocator)
 		count := 0
-		defer meta_data = meta_data[:count]
 		for &m in meta_data {
 			m.name = read_name(r) or_return
 
@@ -105,6 +104,7 @@ read :: proc(data: []byte, filename := "<input>", print_error := false, allocato
 
 			count += 1
 		}
+		meta_data = meta_data[:count]
 		return
 	}
 
@@ -112,7 +112,6 @@ read :: proc(data: []byte, filename := "<input>", print_error := false, allocato
 		stack_count := read_value(r, u32le) or_return
 		layer_count := 0
 		layers = make(Layer_Stack, stack_count, allocator=allocator, loc=loc)
-		defer layers = layers[:layer_count]
 		for &layer in layers {
 			layer.name = read_name(r) or_return
 			layer.components = read_value(r, u8) or_return
@@ -136,6 +135,7 @@ read :: proc(data: []byte, filename := "<input>", print_error := false, allocato
 			layer_count += 1
 		}
 
+		layers = layers[:layer_count]
 		return
 	}
 

+ 3 - 7
core/fmt/fmt.odin

@@ -1802,11 +1802,8 @@ fmt_bit_set :: proc(fi: ^Info, v: any, name: string = "", verb: rune = 'v') {
 
 		e, is_enum := et.variant.(runtime.Type_Info_Enum)
 		commas := 0
-		loop: for i in 0 ..< bit_size {
-			if bits & (1<<i) == 0 {
-				continue loop
-			}
-
+		loop: for i in transmute(bit_set[0..<128])bits {
+			i := i64(i) + info.lower
 			if commas > 0 {
 				io.write_string(fi.writer, ", ", &fi.n)
 			}
@@ -1829,8 +1826,7 @@ fmt_bit_set :: proc(fi: ^Info, v: any, name: string = "", verb: rune = 'v') {
 					}
 				}
 			}
-			v := i64(i) + info.lower
-			io.write_i64(fi.writer, v, 10, &fi.n)
+			io.write_i64(fi.writer, i, 10, &fi.n)
 			commas += 1
 		}
 	}

+ 3 - 2
core/os/os2/process.odin

@@ -407,11 +407,9 @@ process_exec :: proc(
 	{
 		stdout_b: [dynamic]byte
 		stdout_b.allocator = allocator
-		defer stdout = stdout_b[:]
 
 		stderr_b: [dynamic]byte
 		stderr_b.allocator = allocator
-		defer stderr = stderr_b[:]
 
 		buf: [1024]u8 = ---
 		
@@ -450,6 +448,9 @@ process_exec :: proc(
 				}
 			}
 		}
+
+		stdout = stdout_b[:]
+		stderr = stderr_b[:]
 	}
 
 	if err != nil {

+ 48 - 17
core/text/regex/regex.odin

@@ -28,6 +28,8 @@ Creation_Error :: enum {
 	Expected_Delimiter,
 	// An unknown letter was supplied to `create_by_user` after the last delimiter.
 	Unknown_Flag,
+	// An unsupported flag was supplied.
+	Unsupported_Flag,
 }
 
 Error :: union #shared_nil {
@@ -67,12 +69,12 @@ Regular_Expression :: struct {
 
 /*
 An iterator to repeatedly match a pattern against a string, to be used with `*_iterator` procedures.
+Note: Does not handle `.Multiline` properly.
 */
 Match_Iterator :: struct {
-	haystack: string,
-	offset:   int,
 	regex:    Regular_Expression,
 	capture:  Capture,
+	vm:       virtual_machine.Machine,
 	idx:      int,
 	temp:     runtime.Allocator,
 }
@@ -283,10 +285,15 @@ create_iterator :: proc(
 	flags := flags
 	flags += {.Global} // We're iterating over a string, so the next match could start anywhere
 
-	result.haystack = str
-	result.regex    = create(pattern, flags, permanent_allocator, temporary_allocator) or_return
-	result.capture  = preallocate_capture()
-	result.temp     = temporary_allocator
+	if .Multiline in flags {
+		return {}, .Unsupported_Flag
+	}
+
+	result.regex         = create(pattern, flags, permanent_allocator, temporary_allocator) or_return
+	result.capture       = preallocate_capture()
+	result.temp          = temporary_allocator
+	result.vm            = virtual_machine.create(result.regex.program, str)
+	result.vm.class_data = result.regex.class_data
 
 	return
 }
@@ -435,6 +442,7 @@ match_with_preallocated_capture :: proc(
 
 /*
 Iterate over a `Match_Iterator` and return successive captures.
+Note: Does not handle `.Multiline` properly.
 
 Inputs:
 - it: Pointer to the `Match_Iterator` to iterate over.
@@ -444,24 +452,47 @@ Returns:
 - ok:     A bool indicating if there was a match, stopping the iteration on `false`.
 */
 match_iterator :: proc(it: ^Match_Iterator) -> (result: Capture, index: int, ok: bool) {
+	assert(len(it.capture.groups) >= common.MAX_CAPTURE_GROUPS,
+		"Pre-allocated RegEx capture `groups` must be at least 10 elements long.")
+	assert(len(it.capture.pos) >= common.MAX_CAPTURE_GROUPS,
+		"Pre-allocated RegEx capture `pos` must be at least 10 elements long.")
+
 	runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
+
+	saved: ^[2 * common.MAX_CAPTURE_GROUPS]int
+	{
+		context.allocator = it.temp
+		if .Unicode in it.regex.flags {
+			saved, ok = virtual_machine.run(&it.vm, true)
+		} else {
+			saved, ok = virtual_machine.run(&it.vm, false)
+		}
+	}
+
+	str := string(it.vm.memory)
 	num_groups: int
-	num_groups, ok = match_with_preallocated_capture(
-		it.regex,
-		it.haystack[it.offset:],
-		&it.capture,
-		it.temp,
-	)
+
+	if saved != nil {
+		n := 0
+
+		#no_bounds_check for i := 0; i < len(saved); i += 2 {
+			a, b := saved[i], saved[i + 1]
+			if a == -1 || b == -1 {
+				continue
+			}
+
+			it.capture.groups[n] = str[a:b]
+			it.capture.pos[n]    = {a, b}
+			n += 1
+		}
+		num_groups = n
+	}
 
 	defer if ok {
 		it.idx += 1
 	}
 
 	if num_groups > 0 {
-		for i in 0..<num_groups {
-			it.capture.pos[i] += it.offset
-		}
-		it.offset = it.capture.pos[0][1]
 		result = {it.capture.pos[:num_groups], it.capture.groups[:num_groups]}
 	}
 	return result, it.idx, ok
@@ -474,7 +505,6 @@ match :: proc {
 }
 
 reset :: proc(it: ^Match_Iterator) {
-	it.offset = 0
 	it.idx    = 0
 }
 
@@ -544,6 +574,7 @@ destroy_iterator :: proc(it: Match_Iterator, allocator := context.allocator) {
 	context.allocator = allocator
 	destroy(it.regex)
 	destroy(it.capture)
+	virtual_machine.destroy(it.vm)
 }
 
 destroy :: proc {

+ 10 - 1
core/text/regex/virtual_machine/virtual_machine.odin

@@ -627,8 +627,9 @@ opcode_count :: proc(code: Program) -> (opcodes: int) {
 	return
 }
 
-create :: proc(code: Program, str: string) -> (vm: Machine) {
+create :: proc(code: Program, str: string, allocator := context.allocator) -> (vm: Machine) {
 	assert(len(code) > 0, "RegEx VM has no instructions.")
+	context.allocator = allocator
 
 	vm.memory = str
 	vm.code = code
@@ -644,3 +645,11 @@ create :: proc(code: Program, str: string) -> (vm: Machine) {
 
 	return
 }
+
+destroy :: proc(vm: Machine, allocator := context.allocator) {
+	context.allocator = allocator
+
+	delete(vm.busy_map)
+	free(vm.threads)
+	free(vm.next_threads)
+}

+ 3 - 1
src/check_type.cpp

@@ -2082,7 +2082,9 @@ gb_internal Type *check_get_params(CheckerContext *ctx, Scope *scope, Ast *_para
 					if (type != t_invalid && !check_is_assignable_to(ctx, &op, type, allow_array_programming)) {
 						bool ok = true;
 						if (p->flags&FieldFlag_any_int) {
-							if ((!is_type_integer(op.type) && !is_type_enum(op.type)) || (!is_type_integer(type) && !is_type_enum(type))) {
+							if (op.type == nullptr) {
+								ok = false;
+							} else if ((!is_type_integer(op.type) && !is_type_enum(op.type)) || (!is_type_integer(type) && !is_type_enum(type))) {
 								ok = false;
 							} else if (!check_is_castable_to(ctx, &op, type)) {
 								ok = false;

+ 1 - 2
tests/core/text/regex/test_core_text_regex.odin

@@ -1126,9 +1126,8 @@ test_match_iterator :: proc(t: ^testing.T) {
 		testing.expect_value(t, err, nil)
 		(err == nil) or_continue
 
-		count: int
 		for capture, idx in regex.match(&it) {
-			if count > len(test.expected) {
+			if idx >= len(test.expected) {
 				break
 			}
 			check_capture(t, capture, test.expected[idx])

+ 3 - 2
vendor/glfw/bindings/bindings.odin

@@ -193,7 +193,6 @@ foreign glfw {
 	SetWindowPosCallback          :: proc(window: WindowHandle, cbfun: WindowPosProc)          -> WindowPosProc ---
 	SetFramebufferSizeCallback    :: proc(window: WindowHandle, cbfun: FramebufferSizeProc)    -> FramebufferSizeProc ---
 	SetDropCallback               :: proc(window: WindowHandle, cbfun: DropProc)               -> DropProc ---
-	SetMonitorCallback            :: proc(window: WindowHandle, cbfun: MonitorProc)            -> MonitorProc ---
 	SetWindowMaximizeCallback     :: proc(window: WindowHandle, cbfun: WindowMaximizeProc)     -> WindowMaximizeProc ---
 	SetWindowContentScaleCallback :: proc(window: WindowHandle, cbfun: WindowContentScaleProc) -> WindowContentScaleProc ---
 
@@ -204,7 +203,9 @@ foreign glfw {
 	SetCharCallback        :: proc(window: WindowHandle, cbfun: CharProc)        -> CharProc ---
 	SetCharModsCallback    :: proc(window: WindowHandle, cbfun: CharModsProc)    -> CharModsProc ---
 	SetCursorEnterCallback :: proc(window: WindowHandle, cbfun: CursorEnterProc) -> CursorEnterProc ---
-	SetJoystickCallback    :: proc(cbfun: JoystickProc)    -> JoystickProc ---
+
+	SetMonitorCallback  :: proc(cbfun: MonitorProc)  -> MonitorProc ---
+	SetJoystickCallback :: proc(cbfun: JoystickProc) -> JoystickProc ---
 
 	SetErrorCallback :: proc(cbfun: ErrorProc) -> ErrorProc ---
 

+ 1 - 1
vendor/glfw/bindings/types.odin

@@ -48,7 +48,7 @@ WindowMaximizeProc     :: #type proc "c" (window: WindowHandle, iconified: c.int
 WindowContentScaleProc :: #type proc "c" (window: WindowHandle, xscale, yscale: f32)
 FramebufferSizeProc    :: #type proc "c" (window: WindowHandle, width, height: c.int)
 DropProc               :: #type proc "c" (window: WindowHandle, count: c.int, paths: [^]cstring)
-MonitorProc            :: #type proc "c" (window: WindowHandle, event: c.int)
+MonitorProc            :: #type proc "c" (monitor: MonitorHandle, event: c.int)
 
 KeyProc                :: #type proc "c" (window: WindowHandle, key, scancode, action, mods: c.int)
 MouseButtonProc        :: #type proc "c" (window: WindowHandle, button, action, mods: c.int)