aboutsummaryrefslogtreecommitdiff
path: root/code
diff options
context:
space:
mode:
authorGinger Bill <bill@gingerbill.org>2017-07-17 15:08:36 +0100
committerGinger Bill <bill@gingerbill.org>2017-07-17 15:08:36 +0100
commit9a8759efefa24f5ae1e6d91b67dca72357a99ff9 (patch)
treef0c5087618010a4fa4d85cbe019426f9c18a7ede /code
parent054948e701c1340e72ac236d58da15ca9e6d617c (diff)
Polymorphic type specialization for procedures
Diffstat (limited to 'code')
-rw-r--r--code/demo.odin164
1 files changed, 156 insertions, 8 deletions
diff --git a/code/demo.odin b/code/demo.odin
index 6e0ae84fa..a1ffabb6e 100644
--- a/code/demo.odin
+++ b/code/demo.odin
@@ -1,5 +1,116 @@
import "fmt.odin";
+Table :: struct(Key, Value: type) {
+ Slot :: struct {
+ occupied: bool;
+ hash: u32;
+ key: Key;
+ value: Value;
+ }
+ SIZE_MIN :: 32;
+
+ count: int;
+ allocator: Allocator;
+ slots: []Slot;
+}
+
+allocate :: proc(table: ^$T/Table, capacity: int) {
+ c := context;
+ if table.allocator.procedure != nil do c.allocator = table.allocator;
+
+ push_context c {
+ table.slots = make([]T.Slot, max(capacity, T.SIZE_MIN));
+ }
+}
+
+expand :: proc(table: ^$T/Table) {
+ c := context;
+ if table.allocator.procedure != nil do c.allocator = table.allocator;
+
+ push_context c {
+ old_slots := table.slots;
+
+ cap := max(2*cap(table.slots), T.SIZE_MIN);
+ allocate(table, cap);
+
+ for s in old_slots do if s.occupied {
+ put(table, s.key, s.value);
+ }
+
+ free(old_slots);
+ }
+}
+
+put :: proc(table: ^$T/Table, key: T.Key, value: T.Value) {
+// put :: proc(table: ^Table($K, $V), key: K, value: V) {
+ hash := get_hash(key); // Ad-hoc method which would fail in differentcope
+ index := find_index(table, key, hash);
+ if index < 0 {
+ if f64(table.count) >= 0.75*cast(f64)cap(table.slots) {
+ expand(table);
+ }
+ assert(table.count <= cap(table.slots));
+
+ hash := get_hash(key);
+ index = cast(int)(hash % cast(u32)cap(table.slots));
+
+ for table.slots[index].occupied {
+ index += 1;
+ if index >= cap(table.slots) {
+ index = 0;
+ }
+ }
+
+ table.count++;
+ }
+
+ slot := &table.slots[index];
+ slot.occupied = true;
+ slot.hash = hash;
+ slot.key = key;
+ slot.value = value;
+}
+
+
+// find :: proc(table: ^$T/Table, key: T.Key) -> (T.Value, bool) {
+find :: proc(table: ^Table($Key, $Value), key: Key) -> (Value, bool) {
+ hash := get_hash(key);
+ index := find_index(table, key, hash);
+ if index < 0 {
+ return Value{}, false;
+ }
+ return table.slots[index].value, true;
+}
+
+find_index :: proc(table: ^Table($Key, $Value), key: Key, hash: u32) -> int {
+ if cap(table.slots) <= 0 do return -1;
+
+ slot := int(hash % cast(u32)cap(table.slots));
+
+ index := slot;
+ for table.slots[index].occupied {
+ if table.slots[index].hash == hash {
+ if table.slots[index].key == key {
+ return index;
+ }
+ }
+
+ index++;
+ if index >= cap(table.slots) do index = 0;
+ }
+
+ return -1;
+}
+
+get_hash :: proc(s: string) -> u32 {
+ // djb2
+ hash: u32 = 5381;
+ for i in 0..len(s) do hash = (hash<<5) + hash + u32(s[i]);
+ return hash;
+}
+
+
+
Vector :: struct(N: int, T: type) {
using _: raw_union {
using e: [N]T;
@@ -16,14 +127,51 @@ Vector :: struct(N: int, T: type) {
Vector3 :: Vector(3, f32);
+add :: proc(a, b: $T/Vector) -> T {
+ c := a;
+ for i in 0..3 {
+ c[i] += b[i];
+ }
+ return c;
+}
+
+foo1 :: proc(a: type/Vector) { fmt.println("foo1", a{}); }
+// foo2 :: proc(a: type/Vector(3, f32)) {}
+foo3 :: proc(a: type/Vector(3, $T)) {fmt.println("foo3", a{}); }
+// foo4 :: proc(a: type/Vector3) {}
+
+
+
main :: proc() {
- v: Vector3;
- v[0] = 1;
- v[1] = 4;
- v[2] = 9;
- fmt.println(v.e);
- v.x = 4;
- v.y = 9;
- v.z = 16;
+ foo1(Vector(3, f32));
+ foo1(Vector3);
+ foo3(Vector(3, f32));
+ foo3(Vector3);
+
+
+ a, b: Vector3;
+ a[0] = 1;
+ a[1] = 4;
+ a[2] = 9;
+
+ b.x = 3;
+ b.y = 4;
+ b.z = 5;
+
+ v := add(a, b);
fmt.println(v.v);
+
+
+ table: Table(string, int);
+
+ for i in 0..36 do put(&table, "Hellope", i);
+ for i in 0..42 do put(&table, "World!", i);
+
+
+ found, _ := find(&table, "Hellope");
+ fmt.printf("found is %v\n", found);
+
+ found, _ = find(&table, "World!");
+ fmt.printf("found is %v\n", found);
+
}