From d75291097ea6a457ffd5721c9cc7810b98513574 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 30 Nov 2017 23:09:21 +0000 Subject: [PATCH] &x.(type) --- core/math.odin | 46 ++++++++++++++------------ core/sys/windows.odin | 2 +- src/check_expr.cpp | 23 ++++++++++--- src/ir.cpp | 77 +++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 119 insertions(+), 29 deletions(-) diff --git a/core/math.odin b/core/math.odin index e6edebca7..4aa5423b0 100644 --- a/core/math.odin +++ b/core/math.odin @@ -55,13 +55,13 @@ foreign __llvm_core { 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; } @@ -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: 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 { 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 { 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; } -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 { - m := mag(v); + m := length(v); 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 i in 0..4 { 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); 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}, }; } diff --git a/core/sys/windows.odin b/core/sys/windows.odin index a1bf146f5..b3bec0939 100644 --- a/core/sys/windows.odin +++ b/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(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; } diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 6f7243301..cf1005055 100644 --- a/src/check_expr.cpp +++ b/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) { + 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) { 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) { switch (op.kind) { 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 (ast_node_expect(node, AstNode_UnaryExpr)) { ast_node(ue, UnaryExpr, node); diff --git a/src/ir.cpp b/src/ir.cpp index 3df1db92b..1867e2ecf 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -3824,8 +3824,9 @@ void ir_gen_global_type_name(irModule *m, Entity *e, String name) { 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); ir_module_add_value(m, e, 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); 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 + } default: return ir_emit_unary_arith(proc, ue->op.kind, ir_build_expr(proc, ue->expr), tv.type); }