From 115e6e7f9e79656e77a7c5d17df2f2624b69a1e9 Mon Sep 17 00:00:00 2001 From: Ginger Bill Date: Mon, 10 Jul 2017 23:28:53 +0100 Subject: [PATCH] Update demo for both subtyping and union based Entity --- code/demo.odin | 191 ++++++++++++++++++++++++--------------------- src/check_expr.cpp | 2 + 2 files changed, 102 insertions(+), 91 deletions(-) diff --git a/code/demo.odin b/code/demo.odin index c5ab3698b..d84539bce 100644 --- a/code/demo.odin +++ b/code/demo.odin @@ -20,6 +20,7 @@ import ( */ ) + general_stuff :: proc() { // Complex numbers a := 3 + 4i; @@ -251,112 +252,120 @@ explicit_parametric_polymorphic_procedures :: proc() { a, b = b, a; // Or use this syntax for this silly example case - // A more complicated example using subtyping - // Something like this could be used in a game Vector2 :: struct {x, y: f32;}; + { + // A more complicated example using subtyping + // Something like this could be used in a game - Entity :: struct { - using position: Vector2; - flags: u64; - id: u64; - batch_index: u32; - slot_index: u32; - portable_id: u32; - derived: any; - } - - Rock :: struct { - using entity: ^Entity; - heavy: bool; - } - Door :: struct { - using entity: ^Entity; - open: bool; - } - Monster :: struct { - using entity: ^Entity; - is_robot: bool; - is_zombie: bool; - } - - EntityManager :: struct { - batches: [dynamic]^EntityBatch; - next_portable_id: u32; - } - - ENTITIES_PER_BATCH :: 16; - EntityBatch :: struct { - data: [ENTITIES_PER_BATCH]Entity; - occupied: [ENTITIES_PER_BATCH]bool; - batch_index: u32; - } - - use_empty_slot :: proc(manager: ^EntityManager, batch: ^EntityBatch) -> ^Entity { - for ok, i in batch.occupied { - if ok do continue; - batch.occupied[i] = true; - - e := &batch.data[i]; - e.batch_index = u32(batch.batch_index); - e.slot_index = u32(i); - e.portable_id = manager.next_portable_id; - manager.next_portable_id++; - return e; - } - return nil; - } - - gen_new_entity :: proc(manager: ^EntityManager) -> ^Entity { - for b in manager.batches { - e := use_empty_slot(manager, b); - if e != nil do return e; + Entity :: struct { + using position: Vector2; + flags: u64; + id: u64; + derived: any; } - new_batch := new(EntityBatch); - append(&manager.batches, new_batch); - new_batch.batch_index = u32(len(manager.batches)-1); + Rock :: struct { + using entity: Entity; + heavy: bool; + } + Door :: struct { + using entity: Entity; + open: bool; + } + Monster :: struct { + using entity: Entity; + is_robot: bool; + is_zombie: bool; + } - return use_empty_slot(manager, new_batch); + new_entity :: proc(T: type, x, y: f32) -> ^T { + result := new(T); + result.derived = result^; + result.x = x; + result.y = y; + + return result; + } + + entities: [dynamic]^Entity; + + rock := new_entity(Rock, 3, 5); + + // Named arguments work too! + door := new_entity(T = Door, x = 3, y = 6); + + // And named arguments can be any order + monster := new_entity( + y = 1, + x = 2, + T = Monster, + ); + + append(&entities, rock, door, monster); + + fmt.println("Subtyping"); + for entity in entities { + match e in entity.derived { + case Rock: fmt.println("Rock", e.x, e.y); + case Door: fmt.println("Door", e.x, e.y); + case Monster: fmt.println("Monster", e.x, e.y); + } + } } + { + Entity :: struct { + using position: Vector2; + flags: u64; + id: u64; + variant: union { Rock, Door, Monster }; + } + Rock :: struct { + using entity: ^Entity; + heavy: bool; + } + Door :: struct { + using entity: ^Entity; + open: bool; + } + Monster :: struct { + using entity: ^Entity; + is_robot: bool; + is_zombie: bool; + } + new_entity :: proc(T: type, x, y: f32) -> ^T { + result := new(Entity); + result.variant = T{entity = result}; + result.x = x; + result.y = y; - new_entity :: proc(manager: ^EntityManager, T: type, x, y: f32) -> ^T { - result := new(T); - result.entity = gen_new_entity(manager); - result.derived.data = result; - result.derived.type_info = type_info(T); + return ^T(&result.variant); + } - result.position.x = x; - result.position.y = y; + entities: [dynamic]^Entity; - return result; - } + rock := new_entity(Rock, 3, 5); - manager: EntityManager; - entities: [dynamic]^Entity; + // Named arguments work too! + door := new_entity(T = Door, x = 3, y = 6); - rock := new_entity(&manager, Rock, 3, 5); + // And named arguments can be any order + monster := new_entity( + y = 1, + x = 2, + T = Monster, + ); - // Named arguments work too! - door := new_entity(manager = &manager, T = Door, x = 3, y = 6); + append(&entities, rock, door, monster); - // And named arguments can be any order - monster := new_entity( - y = 1, - x = 2, - manager = &manager, - T = Monster, - ); - - append(&entities, rock, door, monster); - - // An alternative to `union`s - for entity in entities { - match e in entity.derived { - case Rock: fmt.println("Rock", e.portable_id, e.x, e.y); - case Door: fmt.println("Door", e.portable_id, e.x, e.y); - case Monster: fmt.println("Monster", e.portable_id, e.x, e.y); + fmt.println("Union"); + for entity in entities { + match e in entity.variant { + case Rock: fmt.println("Rock", e.x, e.y); + case Door: fmt.println("Door", e.x, e.y); + case Monster: fmt.println("Monster", e.x, e.y); + } } } } diff --git a/src/check_expr.cpp b/src/check_expr.cpp index fab388d9f..5e87c080b 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -3338,6 +3338,7 @@ bool check_is_castable_to(Checker *c, Operand *operand, Type *y) { // Cast between pointers if (is_type_pointer(src) && is_type_pointer(dst)) { + #if 0 Type *s = base_type(type_deref(src)); if (is_type_union(s)) { // NOTE(bill): Should the error be here?! @@ -3349,6 +3350,7 @@ bool check_is_castable_to(Checker *c, Operand *operand, Type *y) { gb_string_free(xs); return false; } + #endif return true; }