Browse Source

&x.(type)

gingerBill 7 years ago
parent
commit
d75291097e
4 changed files with 119 additions and 29 deletions
  1. 25 21
      core/math.odin
  2. 1 1
      core/sys/windows.odin
  3. 19 4
      src/check_expr.cpp
  4. 74 3
      src/ir.cpp

+ 25 - 21
core/math.odin

@@ -55,13 +55,13 @@ foreign __llvm_core {
 	fmuladd :: proc(a, b, c: f64) -> f64 ---;
 	fmuladd :: proc(a, b, c: f64) -> f64 ---;
 }
 }
 
 
-tan :: proc "c" (θ: f32) -> f32 do return sin(θ)/cos(θ);
-tan :: proc "c" (θ: f64) -> f64 do return sin(θ)/cos(θ);
+tan :: proc "c" (θ: f32) -> f32 { return sin(θ)/cos(θ); }
+tan :: proc "c" (θ: f64) -> f64 { return sin(θ)/cos(θ); }
 
 
-lerp   :: proc(a, b: $T, t: $E) -> (x: T) do return a*(1-t) + b*t;
+lerp   :: proc(a, b: $T, t: $E) -> (x: T) { return a*(1-t) + b*t; }
 
 
-unlerp :: proc(a, b, x: f32) -> (t: f32) do return (x-a)/(b-a);
-unlerp :: proc(a, b, x: f64) -> (t: f64) do return (x-a)/(b-a);
+unlerp :: proc(a, b, x: f32) -> (t: f32) { return (x-a)/(b-a); }
+unlerp :: proc(a, b, x: f64) -> (t: f64) { return (x-a)/(b-a); }
 
 
 
 
 sign :: proc(x: f32) -> f32 { return x >= 0 ? +1 : -1; }
 sign :: proc(x: f32) -> f32 { return x >= 0 ? +1 : -1; }
@@ -94,8 +94,8 @@ floor :: proc(x: f64) -> f64 { return x >= 0 ? f64(i64(x)) : f64(i64(x-0.5)); }
 ceil :: proc(x: f32) -> f32 { return x < 0 ? f32(i64(x)) : f32(i64(x+1)); }// TODO: Get accurate versions
 ceil :: proc(x: f32) -> f32 { return x < 0 ? f32(i64(x)) : f32(i64(x+1)); }// TODO: Get accurate versions
 ceil :: proc(x: f64) -> f64 { return x < 0 ? f64(i64(x)) : f64(i64(x+1)); }// TODO: Get accurate versions
 ceil :: proc(x: f64) -> f64 { return x < 0 ? f64(i64(x)) : f64(i64(x+1)); }// TODO: Get accurate versions
 
 
-remainder :: proc(x, y: f32) -> f32 do return x - round(x/y) * y;
-remainder :: proc(x, y: f64) -> f64 do return x - round(x/y) * y;
+remainder :: proc(x, y: f32) -> f32 { return x - round(x/y) * y; }
+remainder :: proc(x, y: f64) -> f64 { return x - round(x/y) * y; }
 
 
 mod :: proc(x, y: f32) -> f32 {
 mod :: proc(x, y: f32) -> f32 {
 	result: f32;
 	result: f32;
@@ -117,30 +117,34 @@ mod :: proc(x, y: f64) -> f64 {
 }
 }
 
 
 
 
-to_radians :: proc(degrees: f32) -> f32 do return degrees * TAU / 360;
-to_degrees :: proc(radians: f32) -> f32 do return radians * 360 / TAU;
+to_radians :: proc(degrees: f32) -> f32 { return degrees * TAU / 360; }
+to_degrees :: proc(radians: f32) -> f32 { return radians * 360 / TAU; }
 
 
 
 
 
 
 dot :: proc(a, b: $T/[$N]$E) -> E {
 dot :: proc(a, b: $T/[$N]$E) -> E {
 	res: E;
 	res: E;
-	for i in 0..N do res += a[i] * b[i];
+	for i in 0..N { res += a[i] * b[i]; }
 	return res;
 	return res;
 }
 }
 
 
-cross :: proc(x, y: $T/[3]$E) -> T {
-	a := swizzle(x, 1, 2, 0) * swizzle(y, 2, 0, 1);
-	b := swizzle(x, 2, 0, 1) * swizzle(y, 1, 2, 0);
-	return T(a - b);
+cross :: proc(a, b: $T/[2]$E) -> E {
+	return a[0]*b[1] - a[1]*b[0];
+}
+
+cross :: proc(a, b: $T/[3]$E) -> T {
+	i := swizzle(a, 1, 2, 0) * swizzle(b, 2, 0, 1);
+	j := swizzle(a, 2, 0, 1) * swizzle(b, 1, 2, 0);
+	return T(i - j);
 }
 }
 
 
 
 
-mag :: proc(v: $T/[$N]$E) -> E do return sqrt(dot(v, v));
+length :: proc(v: $T/[$N]$E) -> E { return sqrt(dot(v, v)); }
 
 
-norm :: proc(v: $T/[$N]$E) -> T do return v / mag(v);
+norm :: proc(v: $T/[$N]$E) -> T { return v / length(v); }
 
 
 norm0 :: proc(v: $T/[$N]$E) -> T {
 norm0 :: proc(v: $T/[$N]$E) -> T {
-	m := mag(v);
+	m := length(v);
 	return m == 0 ? 0 : v/m;
 	return m == 0 ? 0 : v/m;
 }
 }
 
 
@@ -155,7 +159,7 @@ mat4_identity :: proc() -> Mat4 {
 	};
 	};
 }
 }
 
 
-mat4_transpose :: proc(m: Mat4) -> Mat4 {
+transpose :: proc(m: Mat4) -> Mat4 {
 	for j in 0..4 {
 	for j in 0..4 {
 		for i in 0..4 {
 		for i in 0..4 {
 			m[i][j], m[j][i] = m[j][i], m[i][j];
 			m[i][j], m[j][i] = m[j][i], m[i][j];
@@ -313,9 +317,9 @@ look_at :: proc(eye, centre, up: Vec3) -> Mat4 {
 	u := cross(s, f);
 	u := cross(s, f);
 
 
 	return Mat4{
 	return Mat4{
-		{+s[0], +u[0], -f[0], 0},
-		{+s[1], +u[1], -f[1], 0},
-		{+s[2], +u[2], -f[2], 0},
+		{+s.x, +u.x, -f.x, 0},
+		{+s.y, +u.y, -f.y, 0},
+		{+s.z, +u.z, -f.z, 0},
 		{-dot(s, eye), -dot(u, eye), dot(f, eye), 1},
 		{-dot(s, eye), -dot(u, eye), dot(f, eye), 1},
 	};
 	};
 }
 }

+ 1 - 1
core/sys/windows.odin

@@ -668,7 +668,7 @@ HIWORD :: proc(lParam: Lparam) -> u16 { return u16((u32(lParam) >> 16) & 0xffff)
 LOWORD :: proc(wParam: Wparam) -> u16 { return u16(wParam); }
 LOWORD :: proc(wParam: Wparam) -> u16 { return u16(wParam); }
 LOWORD :: proc(lParam: Lparam) -> u16 { return u16(lParam); }
 LOWORD :: proc(lParam: Lparam) -> u16 { return u16(lParam); }
 
 
-is_key_down :: inline proc(key: Key_Code) -> bool do return get_async_key_state(i32(key)) < 0;
+is_key_down :: inline proc(key: Key_Code) -> bool { return get_async_key_state(i32(key)) < 0; }
 
 
 
 
 
 

+ 19 - 4
src/check_expr.cpp

@@ -1357,6 +1357,25 @@ void check_is_expressible(Checker *c, Operand *o, Type *type) {
 }
 }
 
 
 bool check_is_not_addressable(Checker *c, Operand *o) {
 bool check_is_not_addressable(Checker *c, Operand *o) {
+	if (o->mode == Addressing_OptionalOk) {
+		AstNode *expr = unparen_expr(o->expr);
+		if (expr->kind != AstNode_TypeAssertion) {
+			return true;
+		}
+		ast_node(ta, TypeAssertion, expr);
+		TypeAndValue tv = type_and_value_of_expr(&c->info, ta->expr);
+		if (is_type_pointer(tv.type)) {
+			return false;
+		}
+		if (is_type_union(tv.type) && tv.mode == Addressing_Variable) {
+			return false;
+		}
+		if (is_type_any(tv.type)) {
+			return false;
+		}
+		return true;
+
+	}
 	if (o->mode != Addressing_Variable) {
 	if (o->mode != Addressing_Variable) {
 		return true;
 		return true;
 	}
 	}
@@ -1370,10 +1389,6 @@ bool check_is_not_addressable(Checker *c, Operand *o) {
 void check_unary_expr(Checker *c, Operand *o, Token op, AstNode *node) {
 void check_unary_expr(Checker *c, Operand *o, Token op, AstNode *node) {
 	switch (op.kind) {
 	switch (op.kind) {
 	case Token_And: { // Pointer address
 	case Token_And: { // Pointer address
-		if (o->mode == Addressing_Type) {
-			o->type = make_type_pointer(c->allocator, o->type);
-			return;
-		}
 		if (check_is_not_addressable(c, o)) {
 		if (check_is_not_addressable(c, o)) {
 			if (ast_node_expect(node, AstNode_UnaryExpr)) {
 			if (ast_node_expect(node, AstNode_UnaryExpr)) {
 				ast_node(ue, UnaryExpr, node);
 				ast_node(ue, UnaryExpr, node);

+ 74 - 3
src/ir.cpp

@@ -3824,8 +3824,9 @@ void ir_gen_global_type_name(irModule *m, Entity *e, String name) {
 		return;
 		return;
 	}
 	}
 
 
-	if (!ptr_set_exists(&m->min_dep_set, e)) return;
-
+	if (!ptr_set_exists(&m->min_dep_set, e)) {
+		return;
+	}
 	irValue *t = ir_value_type_name(m->allocator, name, e->type);
 	irValue *t = ir_value_type_name(m->allocator, name, e->type);
 	ir_module_add_value(m, e, t);
 	ir_module_add_value(m, e, t);
 	map_set(&m->members, hash_string(name), t);
 	map_set(&m->members, hash_string(name), t);
@@ -4874,8 +4875,78 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) {
 
 
 	case_ast_node(ue, UnaryExpr, expr);
 	case_ast_node(ue, UnaryExpr, expr);
 		switch (ue->op.kind) {
 		switch (ue->op.kind) {
-		case Token_And:
+		case Token_And: {
+			AstNode *ue_expr = unparen_expr(ue->expr);
+			if (ue_expr->kind == AstNode_TypeAssertion) {
+				gbAllocator a = proc->module->allocator;
+
+
+				GB_ASSERT(is_type_pointer(tv.type));
+
+				ast_node(ta, TypeAssertion, ue_expr);
+				TokenPos pos = ast_node_token(expr).pos;
+				Type *type = type_of_expr(proc->module->info, ue_expr);
+				GB_ASSERT(!is_type_tuple(type));
+
+				irValue *e = ir_build_expr(proc, ta->expr);
+				Type *t = type_deref(ir_type(e));
+				if (is_type_union(t)) {
+					irValue *v = e;
+					if (!is_type_pointer(ir_type(v))) {
+						v = ir_address_from_load_or_generate_local(proc, v);
+					}
+					Type *src_type = type_deref(ir_type(v));
+					Type *dst_type = type;
+
+					irValue *src_tag = ir_emit_load(proc, ir_emit_union_tag_ptr(proc, v));
+					irValue *dst_tag = ir_const_union_tag(a, src_type, dst_type);
+
+					irValue *ok = ir_emit_comp(proc, Token_CmpEq, src_tag, dst_tag);
+					irValue **args = gb_alloc_array(a, irValue *, 6);
+					args[0] = ok;
+
+					args[1] = ir_find_or_add_entity_string(proc->module, pos.file);
+					args[2] = ir_const_int(a, pos.line);
+					args[3] = ir_const_int(a, pos.column);
+
+					args[4] = ir_type_info(proc, src_type);
+					args[5] = ir_type_info(proc, dst_type);
+					ir_emit_global_call(proc, "__type_assertion_check", args, 6);
+
+					irValue *data_ptr = v;
+					return ir_emit_conv(proc, data_ptr, tv.type);
+				} else if (is_type_any(t)) {
+					irValue *v = e;
+					if (is_type_pointer(ir_type(v))) {
+						v = ir_emit_load(proc, v);
+					}
+
+					irValue *data_ptr = ir_emit_struct_ev(proc, v, 0);
+					irValue *any_ti = ir_emit_struct_ev(proc, v, 1);
+					irValue *ti_ptr = ir_type_info(proc, type);
+
+
+					irValue *ok = ir_emit_comp(proc, Token_CmpEq, any_ti, ti_ptr);
+					irValue **args = gb_alloc_array(a, irValue *, 6);
+					args[0] = ok;
+
+					args[1] = ir_find_or_add_entity_string(proc->module, pos.file);
+					args[2] = ir_const_int(a, pos.line);
+					args[3] = ir_const_int(a, pos.column);
+
+					args[4] = any_ti;
+					args[5] = ti_ptr;
+					ir_emit_global_call(proc, "__type_assertion_check", args, 6);
+
+					return ir_emit_conv(proc, data_ptr, tv.type);
+				} else {
+					GB_PANIC("TODO(bill): type assertion %s", type_to_string(type));
+				}
+
+			}
+
 			return ir_emit_ptr_offset(proc, ir_build_addr_ptr(proc, ue->expr), v_zero); // Make a copy of the pointer
 			return ir_emit_ptr_offset(proc, ir_build_addr_ptr(proc, ue->expr), v_zero); // Make a copy of the pointer
+		}
 		default:
 		default:
 			return ir_emit_unary_arith(proc, ue->op.kind, ir_build_expr(proc, ue->expr), tv.type);
 			return ir_emit_unary_arith(proc, ue->op.kind, ir_build_expr(proc, ue->expr), tv.type);
 		}
 		}