Skip to content

Commit

Permalink
Finish unordered map std
Browse files Browse the repository at this point in the history
  • Loading branch information
marcauberer committed Mar 7, 2024
1 parent cc19010 commit 1d66ff2
Show file tree
Hide file tree
Showing 5 changed files with 304 additions and 97 deletions.
95 changes: 23 additions & 72 deletions media/test-project/test.spice
Original file line number Diff line number Diff line change
@@ -1,77 +1,28 @@
type Speak interface {
p sayHello(string);
}

type MakeSound interface {
p makeSound();
}

type Human struct : MakeSound, Speak {
string firstName
string lastName
unsigned int age
}

p Human.ctor(string firstName, string lastName, unsigned int age) {
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
}

p Human.makeSound() {
printf("Sigh...\n");
}

p Human.sayHello(string name) {
printf("Hi, %s!\n", name);
}

type Car struct : MakeSound {
string brand
string model
unsigned int seats
}

p Car.ctor(string brand, string model, unsigned int seats) {
this.brand = brand;
this.model = model;
this.seats = seats;
}

p Car.makeSound() {
printf("Wroom, wroom!\n");
}

type Parrot struct : MakeSound, Speak {
string name
unsigned int age
}

p Parrot.ctor(string name, unsigned int age) {
this.name = name;
this.age = age;
}

p Parrot.makeSound() {
printf("Sqawk!\n");
}

p Parrot.sayHello(string name) {
printf("Hello %s, squawk!\n", name);
}
import "std/data/unordered-map";

f<int> main() {
Human human = Human("John", "Doe", 25);
Car car = Car("Toyota", "Corolla", 5);
Parrot parrot = Parrot("Polly", 3);

human.makeSound();
car.makeSound();
parrot.makeSound();

human.sayHello("Jane");
parrot.sayHello("Jane");
return 0;
UnorderedMap<int, string> map;
map.upsert(1, "one");
map.upsert(2, "two");
map.upsert(3, "three");
assert map.contains(1);
assert map.contains(2);
assert map.contains(3);
assert !map.contains(4);
assert map.getSize() == 3;
for int i = 1; i <= 3; i++ {
printf("%s\n", map.get(i));
}
const Result<string> item4 = map.getSafe(4);
assert item4.isErr();
map.remove(2);
assert !map.contains(2);
assert map.getSize() == 2;
map.clear();
assert map.getSize() == 0;


printf("All assertions passed!\n");
}

/*import "bootstrap/util/block-allocator";
Expand Down
121 changes: 104 additions & 17 deletions std/data/hash-table.spice
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import "std/data/vector";
import "std/data/linked-list";
import "std/data/optional";
import "std/type/result";
import "std/type/error";
import "std/math/hash";

// Generic types for key and value
Expand All @@ -13,50 +14,136 @@ type HashEntry<K, V> struct {
}

public type HashTable<K, V> struct {
Vector<LinkedList<HashEntry<K, V>>> table
Vector<LinkedList<HashEntry<K, V>>> buckets
}

public p HashTable.ctor(unsigned long bucketCount = 100l) {
this.table = Vector<LinkedList<HashEntry<K, V>>>(bucketCount);
this.buckets = Vector<LinkedList<HashEntry<K, V>>>(bucketCount);
for unsigned long i = 0l; i < bucketCount; i++ {
this.table.pushBack(LinkedList<HashEntry<K, V>>());
this.buckets.pushBack(LinkedList<HashEntry<K, V>>());
}
}

/**
* Insert a key-value pair into the hash table.
* If the key already exists, the value is updated.
*
* @param key The key to insert
* @param value The value to insert
*/
public p HashTable.upsert(const K& key, const V& value) {
const unsigned long index = this.hash(key);
const LinkedList<HashEntry<K, V>>& list = this.table.get(index);
foreach const HashEntry<K, V>& entry : list {
const LinkedList<HashEntry<K, V>>& bucket = this.buckets.get(index);
foreach const HashEntry<K, V>& entry : bucket {
if (entry.key == key) {
entry.value = value;
return;
}
}
bucket.pushBack(HashEntry<K, V>{key, value});
}

public f<Optional<V>> HashTable.get(const K& key) {
/**
* Retrieve the value associated with the given key.
* If the key is not found, panic.
*
* @param key The key to look up
* @return The value associated with the key
*/
public f<V&> HashTable.get(const K& key) {
const unsigned long index = this.hash(key);
const LinkedList<HashEntry<K, V>>& list = this.table.get(index);
foreach const HashEntry<K, V>& entry : list {
const LinkedList<HashEntry<K, V>>& bucket = this.buckets.get(index);
foreach const HashEntry<K, V>& entry : bucket {
if (entry.key == key) {
return Optional<V>(entry.value);
return entry.value;
}
}
return Optional<V>();
panic(Error("The provided key was not found"));
}

/**
* Retrieve the value associated with the given key as Optional<T>.
* If the key is not found, return an empty optional.
*
* @param key The key to look up
* @return Optional<T>, containing the value associated with the key or empty if the key is not found
*/
public f<Result<V>> HashTable.getSafe(const K& key) {
const unsigned long index = this.hash(key);
const LinkedList<HashEntry<K, V>>& bucket = this.buckets.get(index);
foreach const HashEntry<K, V>& entry : bucket {
if (entry.key == key) {
return ok(entry.value);
}
}
return err<V>(Error("The provided key was not found"));
}

/**
* Remove the key-value pair associated with the given key.
* If the key is not found, do nothing.
*
* @param key The key to remove
*/
public p HashTable.remove(const K& key) {
const unsigned long index = this.hash(key);
LinkedList<HashEntry<K, V>>& list = this.table.get(index);
for (unsigned long i = 0l; i < list.getSize(); i++) {
if (list.get(i).key == key) {
list.remove(i);
LinkedList<HashEntry<K, V>>& bucket = this.buckets.get(index);
for unsigned long i = 0l; i < bucket.getSize(); i++ {
if (bucket.get(i).key == key) {
bucket.removeAt(i);
return;
}
}
}

/**
* Check if the hash table contains the given key.
*
* @param key The key to check for
* @return True if the key is found, false otherwise
*/
public f<bool> HashTable.contains(const K& key) {
const unsigned long index = this.hash(key);
const LinkedList<HashEntry<K, V>>& bucket = this.buckets.get(index);
foreach const HashEntry<K, V>& entry : bucket {
if (entry.key == key) {
return true;
}
}
return false;
}

/**
* Get the size of the hash table.
*
* @return The number of key-value pairs in the hash table
*/
public inline f<unsigned long> HashTable.getSize() {
result = 0l;
foreach LinkedList<HashEntry<K, V>>& bucket : this.buckets {
result += bucket.getSize();
}
}

/**
* Checks if the hash table is empty.
*
* @return True if empty, false otherwise.
*/
public inline f<bool> HashTable.isEmpty() {
return this.getSize() == 0l;
}

/**
* Clear the hash table, removing all key-value pairs.
*/
public inline p HashTable.clear() {
foreach LinkedList<HashEntry<K, V>>& bucket : this.buckets {
bucket.clear();
}
}

inline f<unsigned long> HashTable.hash(const K& key) {
K keyCopy = key;
return hash(keyCopy) % this.table.getSize();
const K keyCopy = key;
return hash(keyCopy) % this.buckets.getSize();
}
Loading

0 comments on commit 1d66ff2

Please sign in to comment.