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

Merge branch 'master' into middle-end

gingerBill 3 жил өмнө
parent
commit
6d73c254b2

+ 2 - 0
core/sys/win32/user32.odin

@@ -111,6 +111,8 @@ foreign user32 {
 	@(link_name="SetWindowTextW")   set_window_text_w   :: proc(hwnd: Hwnd, c_string: Wstring) -> Bool ---
 	@(link_name="RegisterClassA")   register_class_a    :: proc(wc: ^Wnd_Class_A) -> i16 ---
 	@(link_name="RegisterClassW")   register_class_w    :: proc(wc: ^Wnd_Class_W) -> i16 ---
+	@(link_name="UnregisterClassA") unregister_class_a  :: proc(class_name: cstring, instance: Hinstance) -> Bool ---
+	@(link_name="UnregisterClassW") unregister_class_w  :: proc(class_name: Wstring, instance: Hinstance) -> Bool ---
 	@(link_name="RegisterClassExA") register_class_ex_a :: proc(wc: ^Wnd_Class_Ex_A) -> i16 ---
 	@(link_name="RegisterClassExW") register_class_ex_w :: proc(wc: ^Wnd_Class_Ex_W) -> i16 ---
 

+ 1 - 1
core/sys/windows/types.odin

@@ -578,7 +578,7 @@ PROCESS_INFORMATION :: struct {
 }
 
 // FYI: This is STARTUPINFOW, not STARTUPINFOA
-STARTUPINFO :: struct #packed {
+STARTUPINFO :: struct {
 	cb: DWORD,
 	lpReserved: LPWSTR,
 	lpDesktop: LPWSTR,

+ 60 - 60
core/unicode/utf8/utf8string/string.odin

@@ -16,140 +16,140 @@ String :: struct {
 }
 
 @(private)
-_len :: builtin.len; // helper procedure
+_len :: builtin.len // helper procedure
 
 init :: proc(s: ^String, contents: string) -> ^String {
-	s.contents = contents;
-	s.byte_pos = 0;
-	s.rune_pos = 0;
+	s.contents = contents
+	s.byte_pos = 0
+	s.rune_pos = 0
 
 	for i in 0..<_len(contents) {
 		if contents[i] >= utf8.RUNE_SELF {
-			s.rune_count = utf8.rune_count_in_string(contents);
-			_, s.width = utf8.decode_rune_in_string(contents);
-			s.non_ascii = i;
-			return s;
+			s.rune_count = utf8.rune_count_in_string(contents)
+			_, s.width = utf8.decode_rune_in_string(contents)
+			s.non_ascii = i
+			return s
 		}
 	}
 
-	s.rune_count = _len(contents);
-	s.width = 0;
-	s.non_ascii = _len(contents);
-	return s;
+	s.rune_count = _len(contents)
+	s.width = 0
+	s.non_ascii = _len(contents)
+	return s
 }
 
 to_string :: proc(s: ^String) -> string {
-	return s.contents;
+	return s.contents
 }
 
 len :: proc(s: ^String) -> int {
-	return s.rune_count;
+	return s.rune_count
 }
 
 
 is_ascii :: proc(s: ^String) -> bool {
-	return s.width == 0;
+	return s.width == 0
 }
 
 at :: proc(s: ^String, i: int, loc := #caller_location) -> (r: rune) {
-	runtime.bounds_check_error_loc(loc, i, s.rune_count);
+	runtime.bounds_check_error_loc(loc, i, s.rune_count)
 
 	if i < s.non_ascii {
-		return rune(s.contents[i]);
+		return rune(s.contents[i])
 	}
 
 	switch i {
 	case 0:
-		r, s.width = utf8.decode_rune_in_string(s.contents);
-		s.rune_pos = 0;
-		s.byte_pos = 0;
-		return;
+		r, s.width = utf8.decode_rune_in_string(s.contents)
+		s.rune_pos = 0
+		s.byte_pos = 0
+		return
 
 	case s.rune_count-1:
-		r, s.width = utf8.decode_rune_in_string(s.contents);
-		s.rune_pos = i;
-		s.byte_pos = _len(s.contents) - s.width;
-		return;
+		r, s.width = utf8.decode_rune_in_string(s.contents)
+		s.rune_pos = i
+		s.byte_pos = _len(s.contents) - s.width
+		return
 
 	case s.rune_pos-1:
-		r, s.width = utf8.decode_rune_in_string(s.contents[0:s.byte_pos]);
-		s.rune_pos = i;
-		s.byte_pos -= s.width;
-		return;
+		r, s.width = utf8.decode_rune_in_string(s.contents[0:s.byte_pos])
+		s.rune_pos = i
+		s.byte_pos -= s.width
+		return
 
 	case s.rune_pos+1:
-		s.rune_pos = i;
-		s.byte_pos += s.width;
-		fallthrough;
+		s.rune_pos = i
+		s.byte_pos += s.width
+		fallthrough
 	case s.rune_pos:
-		r, s.width = utf8.decode_rune_in_string(s.contents[s.byte_pos:]);
-		return;
+		r, s.width = utf8.decode_rune_in_string(s.contents[s.byte_pos:])
+		return
 	}
 
 	// Linear scan
-	scan_forward := true;
+	scan_forward := true
 	if i < s.rune_pos {
 		if i < (s.rune_pos-s.non_ascii)/2 {
-			s.byte_pos, s.rune_pos = s.non_ascii, s.non_ascii;
+			s.byte_pos, s.rune_pos = s.non_ascii, s.non_ascii
 		} else {
-			scan_forward = false;
+			scan_forward = false
 		}
 	} else if i-s.rune_pos < (s.rune_count-s.rune_pos)/2 {
-		// scan_forward = true;
+		// scan_forward = true
 	} else {
-		s.byte_pos, s.rune_pos = _len(s.contents), s.rune_count;
-		scan_forward = false;
+		s.byte_pos, s.rune_pos = _len(s.contents), s.rune_count
+		scan_forward = false
 	}
 
 	if scan_forward {
 		for {
-			r, s.width = utf8.decode_rune_in_string(s.contents[s.byte_pos:]);
+			r, s.width = utf8.decode_rune_in_string(s.contents[s.byte_pos:])
 			if s.rune_pos == i {
-				return;
+				return
 			}
-			s.rune_pos += 1;
-			s.byte_pos += s.width;
+			s.rune_pos += 1
+			s.byte_pos += s.width
 
 		}
 	} else {
 		for {
-			r, s.width = utf8.decode_last_rune_in_string(s.contents[:s.byte_pos]);
-			s.rune_pos -= 1;
-			s.byte_pos -= s.width;
+			r, s.width = utf8.decode_last_rune_in_string(s.contents[:s.byte_pos])
+			s.rune_pos -= 1
+			s.byte_pos -= s.width
 			if s.rune_pos == i {
-				return;
+				return
 			}
 		}
 	}
 }
 
 slice :: proc(s: ^String, i, j: int, loc := #caller_location) -> string {
-	runtime.slice_expr_error_lo_hi_loc(loc, i, j, s.rune_count);
+	runtime.slice_expr_error_lo_hi_loc(loc, i, j, s.rune_count)
 
 	if j < s.non_ascii {
-		return s.contents[i:j];
+		return s.contents[i:j]
 	}
 
 	if i == j {
-		return "";
+		return ""
 	}
 
-	lo, hi: int;
+	lo, hi: int
 	if i < s.non_ascii {
-		lo = i;
+		lo = i
 	} else if i == s.rune_count {
-		lo = _len(s.contents);
+		lo = _len(s.contents)
 	} else {
-		at(s, i, loc);
-		lo = s.byte_pos;
+		at(s, i, loc)
+		lo = s.byte_pos
 	}
 
 	if j == s.rune_count {
-		hi = _len(s.contents);
+		hi = _len(s.contents)
 	} else {
-		at(s, j, loc);
-		hi = s.byte_pos;
+		at(s, j, loc)
+		hi = s.byte_pos
 	}
 
-	return s.contents[lo:hi];
+	return s.contents[lo:hi]
 }

+ 2 - 0
examples/all/all_main.odin

@@ -104,6 +104,7 @@ import time           "core:time"
 
 import unicode        "core:unicode"
 import utf8           "core:unicode/utf8"
+import utf8string     "core:unicode/utf8/utf8string"
 import utf16          "core:unicode/utf16"
 
 main :: proc(){}
@@ -193,4 +194,5 @@ _ :: thread
 _ :: time
 _ :: unicode
 _ :: utf8
+_ :: utf8string
 _ :: utf16

+ 63 - 16
src/check_expr.cpp

@@ -4881,25 +4881,16 @@ bool is_expr_constant_zero(Ast *expr) {
 	return false;
 }
 
-
-CALL_ARGUMENT_CHECKER(check_call_arguments_internal) {
-	ast_node(ce, CallExpr, call);
-	GB_ASSERT(is_type_proc(proc_type));
-	proc_type = base_type(proc_type);
-	TypeProc *pt = &proc_type->Proc;
-
+isize get_procedure_param_count_excluding_defaults(Type *pt, isize *param_count_) {
+	GB_ASSERT(pt != nullptr);
+	GB_ASSERT(pt->kind == Type_Proc);
 	isize param_count = 0;
 	isize param_count_excluding_defaults = 0;
-	bool variadic = pt->variadic;
-	bool vari_expand = (ce->ellipsis.pos.line != 0);
-	i64 score = 0;
-	bool show_error = show_error_mode == CallArgumentMode_ShowErrors;
-
-
+	bool variadic = pt->Proc.variadic;
 	TypeTuple *param_tuple = nullptr;
 
-	if (pt->params != nullptr) {
-		param_tuple = &pt->params->Tuple;
+	if (pt->Proc.params != nullptr) {
+		param_tuple = &pt->Proc.params->Tuple;
 
 		param_count = param_tuple->variables.count;
 		if (variadic) {
@@ -4939,6 +4930,31 @@ CALL_ARGUMENT_CHECKER(check_call_arguments_internal) {
 		}
 	}
 
+	if (param_count_) *param_count_ = param_count;
+	return param_count_excluding_defaults;
+}
+
+
+CALL_ARGUMENT_CHECKER(check_call_arguments_internal) {
+	ast_node(ce, CallExpr, call);
+	GB_ASSERT(is_type_proc(proc_type));
+	proc_type = base_type(proc_type);
+	TypeProc *pt = &proc_type->Proc;
+
+	isize param_count = 0;
+	isize param_count_excluding_defaults = get_procedure_param_count_excluding_defaults(proc_type, &param_count);
+	bool variadic = pt->variadic;
+	bool vari_expand = (ce->ellipsis.pos.line != 0);
+	i64 score = 0;
+	bool show_error = show_error_mode == CallArgumentMode_ShowErrors;
+
+
+	TypeTuple *param_tuple = nullptr;
+	if (pt->params != nullptr) {
+		param_tuple = &pt->params->Tuple;
+	}
+
+
 	CallArgumentError err = CallArgumentError_None;
 	Type *final_proc_type = proc_type;
 	Entity *gen_entity = nullptr;
@@ -5611,7 +5627,37 @@ CallArgumentData check_call_arguments(CheckerContext *c, Operand *operand, Type
 	if (operand->mode == Addressing_ProcGroup) {
 		check_entity_decl(c, operand->proc_group, nullptr, nullptr);
 
-		Array<Entity *> procs = proc_group_entities(c, *operand);
+		auto procs = proc_group_entities_cloned(c, *operand);
+
+		if (procs.count > 1) {
+			isize max_arg_count = args.count;
+			for_array(i, args) {
+				// NOTE(bill): The only thing that may have multiple values
+				// will be a call expression (assuming `or_return` and `()` will be stripped)
+				Ast *arg = strip_or_return_expr(args[i]);
+				if (arg && arg->kind == Ast_CallExpr) {
+					max_arg_count = ISIZE_MAX;
+					break;
+				}
+			}
+
+			for (isize proc_index = 0; proc_index < procs.count; /**/) {
+				Entity *proc = procs[proc_index];
+				Type *pt = base_type(proc->type);
+				if (!(pt != nullptr && is_type_proc(pt))) {
+					continue;
+				}
+
+				isize param_count = 0;
+				isize param_count_excluding_defaults = get_procedure_param_count_excluding_defaults(pt, &param_count);
+
+				if (param_count_excluding_defaults > max_arg_count) {
+					array_unordered_remove(&procs, proc_index);
+				} else {
+					proc_index++;
+				}
+			}
+		}
 
 		if (procs.count == 1) {
 			Ast *ident = operand->expr;
@@ -5641,6 +5687,7 @@ CallArgumentData check_call_arguments(CheckerContext *c, Operand *operand, Type
 			return data;
 		}
 
+
 		Entity **lhs = nullptr;
 		isize lhs_count = -1;
 

+ 0 - 14
src/check_type.cpp

@@ -1960,20 +1960,6 @@ bool check_procedure_type(CheckerContext *ctx, Type *type, Ast *proc_type_node,
 	if (params)  param_count  = params ->Tuple.variables.count;
 	if (results) result_count = results->Tuple.variables.count;
 
-	if (param_count > 0) {
-		for_array(i, params->Tuple.variables) {
-			Entity *param = params->Tuple.variables[i];
-			if (param->kind == Entity_Variable) {
-				ParameterValue pv = param->Variable.param_value;
-				if (pv.kind == ParameterValue_Constant &&
-				    pv.value.kind == ExactValue_Procedure) {
-					type->Proc.has_proc_default_values = true;
-					break;
-				}
-			}
-		}
-	}
-
 	if (result_count > 0) {
 		Entity *first = results->Tuple.variables[0];
 		type->Proc.has_named_results = first->token.string != "";

+ 9 - 0
src/checker.cpp

@@ -2657,6 +2657,15 @@ Array<Entity *> proc_group_entities(CheckerContext *c, Operand o) {
 	return procs;
 }
 
+Array<Entity *> proc_group_entities_cloned(CheckerContext *c, Operand o) {
+	auto entities = proc_group_entities(c, o);
+	if (entities.count == 0) {
+		return {};
+	}
+	return array_clone(permanent_allocator(), entities);
+}
+
+
 
 
 void init_core_type_info(Checker *c) {

+ 10 - 0
src/entity.cpp

@@ -118,6 +118,16 @@ struct ParameterValue {
 	};
 };
 
+bool has_parameter_value(ParameterValue const &param_value) {
+	if (param_value.kind != ParameterValue_Invalid) {
+		return true;
+	}
+	if (param_value.original_ast_expr != nullptr) {
+		return true;
+	}
+	return false;
+}
+
 enum EntityConstantFlags : u32 {
 	EntityConstantFlag_ImplicitEnumValue = 1<<0,
 };

+ 0 - 1
src/types.cpp

@@ -186,7 +186,6 @@ struct TypeProc {
 	bool     c_vararg;
 	bool     is_polymorphic;
 	bool     is_poly_specialized;
-	bool     has_proc_default_values;
 	bool     has_named_results;
 	bool     diverging; // no return
 	bool     return_by_pointer;