Browse Source

Update demo for both subtyping and union based Entity

Ginger Bill 8 years ago
parent
commit
115e6e7f9e
2 changed files with 99 additions and 88 deletions
  1. 97 88
      code/demo.odin
  2. 2 0
      src/check_expr.cpp

+ 97 - 88
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;
+			derived:        any;
+		}
 
-	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;
+		}
 
-	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(T);
+			result.derived = result^;
+			result.x = x;
+			result.y = y;
 
-	EntityManager :: struct {
-		batches: [dynamic]^EntityBatch;
-		next_portable_id: u32;
-	}
+			return result;
+		}
 
-	ENTITIES_PER_BATCH :: 16;
-	EntityBatch :: struct {
-		data:        [ENTITIES_PER_BATCH]Entity;
-		occupied:    [ENTITIES_PER_BATCH]bool;
-		batch_index: u32;
-	}
+		entities: [dynamic]^Entity;
 
-	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;
-	}
+		rock := new_entity(Rock, 3, 5);
 
-	gen_new_entity :: proc(manager: ^EntityManager) -> ^Entity {
-		for b in manager.batches {
-			e := use_empty_slot(manager, b);
-			if e != nil do return e;
-		}
+		// 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,
+		);
 
-		new_batch := new(EntityBatch);
-		append(&manager.batches, new_batch);
-		new_batch.batch_index = u32(len(manager.batches)-1);
+		append(&entities, rock, door, monster);
 
-		return use_empty_slot(manager, new_batch);
+		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;
 
+			return ^T(&result.variant);
+		}
 
-	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);
+		entities: [dynamic]^Entity;
 
-		result.position.x = x;
-		result.position.y = y;
+		rock := new_entity(Rock, 3, 5);
 
-		return result;
-	}
+		// Named arguments work too!
+		door := new_entity(T = Door, x = 3, y = 6);
 
-	manager: EntityManager;
-	entities: [dynamic]^Entity;
+		// And named arguments can be any order
+		monster := new_entity(
+			y = 1,
+			x = 2,
+			T = Monster,
+		);
 
-	rock    := new_entity(&manager, Rock, 3, 5);
+		append(&entities, rock, door, monster);
 
-	// Named arguments work too!
-	door    := new_entity(manager = &manager, T = Door, x = 3, y = 6);
-
-	// 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);
+			}
 		}
 	}
 }

+ 2 - 0
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;
 	}