Browse Source

Correct and improve type inference for swizzling expressions

gingerBill 4 years ago
parent
commit
193fd0eecb
3 changed files with 35 additions and 31 deletions
  1. 9 0
      examples/demo/demo.odin
  2. 3 19
      src/check_builtin.cpp
  3. 23 12
      src/check_expr.cpp

+ 9 - 0
examples/demo/demo.odin

@@ -8,6 +8,9 @@ import "core:time"
 import "core:reflect"
 import "core:reflect"
 import "core:runtime"
 import "core:runtime"
 import "intrinsics"
 import "intrinsics"
+import "core:encoding/json"
+
+_ :: json;
 
 
 /*
 /*
 	The Odin programming language is fast, concise, readable, pragmatic and open sourced.
 	The Odin programming language is fast, concise, readable, pragmatic and open sourced.
@@ -1203,6 +1206,12 @@ array_programming :: proc() {
 			return i - j;
 			return i - j;
 		}
 		}
 
 
+		cross_shorter :: proc(a, b: Vector3) -> Vector3 {
+			i := a.yzx * b.zxy;
+			j := a.zxy * b.yzx;
+			return i - j;
+		}
+
 		blah :: proc(a: Vector3) -> f32 {
 		blah :: proc(a: Vector3) -> f32 {
 			return a.x + a.y + a.z;
 			return a.x + a.y + a.z;
 		}
 		}

+ 3 - 19
src/check_builtin.cpp

@@ -718,7 +718,8 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
 
 
 	case BuiltinProc_swizzle: {
 	case BuiltinProc_swizzle: {
 		// swizzle :: proc(v: [N]T, ..int) -> [M]T
 		// swizzle :: proc(v: [N]T, ..int) -> [M]T
-		Type *type = base_type(operand->type);
+		Type *original_type = operand->type;
+		Type *type = base_type(original_type);
 		i64 max_count = 0;
 		i64 max_count = 0;
 		Type *elem_type = nullptr;
 		Type *elem_type = nullptr;
 
 
@@ -775,9 +776,6 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
 			return false;
 			return false;
 		}
 		}
 
 
-		if (arg_count < max_count) {
-			operand->type = alloc_type_array(elem_type, arg_count);
-		}
 		if (type->kind == Type_Array) {
 		if (type->kind == Type_Array) {
 			if (operand->mode == Addressing_Variable) {
 			if (operand->mode == Addressing_Variable) {
 				operand->mode = Addressing_SwizzleVariable;
 				operand->mode = Addressing_SwizzleVariable;
@@ -788,21 +786,7 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
 			operand->mode = Addressing_Value;
 			operand->mode = Addressing_Value;
 		}
 		}
 
 
-		Type *array_type = base_type(type_deref(operand->type));
-		GB_ASSERT(array_type->kind == Type_Array);
-
-		Type *swizzle_array_type = nullptr;
-		Type *bth = base_type(type_hint);
-		if (bth != nullptr && bth->kind == Type_Array &&
-		    bth->Array.count == arg_count &&
-		    are_types_identical(bth->Array.elem, array_type->Array.elem)) {
-			swizzle_array_type = type_hint;
-		} else {
-			swizzle_array_type = alloc_type_array(array_type->Array.elem, arg_count);
-		}
-
-		operand->type = swizzle_array_type;
-
+		operand->type = determine_swizzle_array_type(original_type, type_hint, arg_count);
 		break;
 		break;
 	}
 	}
 
 

+ 23 - 12
src/check_expr.cpp

@@ -3632,6 +3632,27 @@ void check_did_you_mean_scope(String const &name, Scope *scope) {
 	check_did_you_mean_print(&d);
 	check_did_you_mean_print(&d);
 }
 }
 
 
+Type *determine_swizzle_array_type(Type *original_type, Type *type_hint, isize new_count) {
+	Type *array_type = base_type(type_deref(original_type));
+	GB_ASSERT(array_type->kind == Type_Array);
+	Type *elem_type = array_type->Array.elem;
+
+	Type *swizzle_array_type = nullptr;
+	Type *bth = base_type(type_deref(type_hint));
+	if (bth != nullptr && bth->kind == Type_Array &&
+	    bth->Array.count == new_count &&
+	    are_types_identical(bth->Array.elem, elem_type)) {
+		swizzle_array_type = type_hint;
+	} else {
+		i64 max_count = array_type->Array.count;
+		if (new_count == max_count) {
+			swizzle_array_type = original_type;
+		} else {
+			swizzle_array_type = alloc_type_array(elem_type, new_count);
+		}
+	}
+	return swizzle_array_type;
+}
 
 
 
 
 Entity *check_selector(CheckerContext *c, Operand *operand, Ast *node, Type *type_hint) {
 Entity *check_selector(CheckerContext *c, Operand *operand, Ast *node, Type *type_hint) {
@@ -3842,21 +3863,11 @@ Entity *check_selector(CheckerContext *c, Operand *operand, Ast *node, Type *typ
 			se->swizzle_count = index_count;
 			se->swizzle_count = index_count;
 			se->swizzle_indices = indices;
 			se->swizzle_indices = indices;
 
 
-			Type *array_type = base_type(type_deref(operand->type));
-			GB_ASSERT(array_type->kind == Type_Array);
+			Type *original_type = operand->type;
 
 
-			Type *swizzle_array_type = nullptr;
-			Type *bth = base_type(type_hint);
-			if (bth != nullptr && bth->kind == Type_Array &&
-			    bth->Array.count == index_count &&
-			    are_types_identical(bth->Array.elem, array_type->Array.elem)) {
-				swizzle_array_type = type_hint;
-			} else {
-				swizzle_array_type = alloc_type_array(array_type->Array.elem, index_count);
-			}
 			AddressingMode prev_mode = operand->mode;
 			AddressingMode prev_mode = operand->mode;
 			operand->mode = Addressing_SwizzleValue;
 			operand->mode = Addressing_SwizzleValue;
-			operand->type = swizzle_array_type;
+			operand->type = determine_swizzle_array_type(original_type, type_hint, index_count);
 			operand->expr = node;
 			operand->expr = node;
 
 
 			switch (prev_mode) {
 			switch (prev_mode) {