#!/bin/sh
+rm libruntime.a runtime/*.o
+
for f in runtime/*.c; do
printf "CC %s\n" "$f"
gcc -c -I. -O2 -o "${f%.c}.o" "$f" &
def item = 42
set hash["foo"] = item
assert hash["foo"] == 42
+ assert hash["foo"] == "bar"
assert hash["baz"] == "boo"
}
//#define VALUE_FALSE 0x2llu
//#define VALUE_TRUE 0x3llu
-//#define NAN_TAG_RECORD 0x0000000000000000llu
+#define NAN_TAG_DICT 0x0000000000000000llu
#define NAN_TAG_ARRAY 0x0001000000000000llu
#define NAN_TAG_STRING 0x0002000000000000llu
//#define NAN_TAG_BLOCK 0x0003000000000000llu
typedef struct {
uint64_t length;
- Value values[];
+ uint64_t capacity;
+ Value* values;
} Array;
+typedef struct DictNode {
+ struct DictNode* left;
+ struct DictNode* right;
+ Value key;
+ Value value;
+ uint32_t hash;
+} DictNode;
+
+typedef struct {
+ uint64_t length;
+ DictNode* root;
+} Dict;
+
/* Value Tests
*************************************************/
}
static inline bool IsArray(Value val) {
- return (val.as_uint64 & HIGH16_TAG) == NAN_TAG_STRING;
+ return (val.as_uint64 & HIGH16_TAG) == NAN_TAG_ARRAY;
}
static inline bool IsDict(Value val) {
- return (val.as_uint64 & HIGH16_TAG) == NAN_TAG_STRING;
+ return (val.as_uint64 & HIGH16_TAG) == NAN_TAG_DICT;
}
return (String*)(val.as_uint64 & MASK_POINTER);
}
+static Array* ValueAsArray(Value val) {
+ assert(IsArray(val));
+ return (Array*)(val.as_uint64 & MASK_POINTER);
+}
+
+static Dict* ValueAsDict(Value val) {
+ assert(IsDict(val));
+ return (Dict*)(val.as_uint64 & MASK_POINTER);
+}
+
//static Array* to_array(Value val) {
// assert(is_array(val));
#include "runtime.h"
+static uint64_t NextPow2(uint64_t val) {
+ val--;
+ val |= val >> 1;
+ val |= val >> 2;
+ val |= val >> 4;
+ val |= val >> 8;
+ val |= val >> 16;
+ val |= val >> 32;
+ val++;
+ return val;
+}
+
Value MakeArray(int32_t nslots) {
-// Value* record = calloc(2,sizeof(Value));
-// record[0] = MakeInt(1);
-// record[1] = MakeInt(nslots); //
-// record[2] = MakeInt(nslots); //
-// return (Value){ .as_uint64 = (NAN_TAG_ARRAY | (uintptr_t)record) };
- return MakeNil();
+ Array* array = calloc(1, sizeof(Array));
+ array->length = nslots;
+ array->capacity = NextPow2(nslots);
+ array->values = calloc(nslots, sizeof(Value));
+ return (Value){ .as_uint64 = (NAN_TAG_ARRAY | (uintptr_t)array) };
}
void Array_Set(Value array, int index, Value value)
{
+ Array* ary = ValueAsArray(array);
+ if (index >= ary->length) {
+ Error(MakeString("array index out of bounds"));
+ }
+ ary->values[index] = value;
}
Value Array_Get(Value array, int index)
{
- return MakeNil();
+ Array* ary = ValueAsArray(array);
+ if (index >= ary->length) {
+ Error(MakeString("array index out of bounds"));
+ }
+ return ary->values[index];
}
--- /dev/null
+#include "runtime.h"
+
+static uint32_t Hash(Value val) {
+ String* string = ValueAsString(val);
+ char* key = string->bytes;
+ uint32_t a=31415u, b=27183u, hash;
+ for (hash=0; *key; key++, a *= b) {
+ hash = (a * hash) + *key;
+ }
+ hash = (hash + 0x7ed55d16) + (hash << 12);
+ hash = (hash ^ 0xc761c23c) ^ (hash >> 19);
+ hash = (hash + 0x165667b1) + (hash << 5);
+ hash = (hash + 0xd3a2646c) ^ (hash << 9);
+ hash = (hash + 0xfd7046c5) + (hash << 3);
+ hash = (hash ^ 0xb55a4f09) ^ (hash >> 16);
+ return hash;
+}
+
+static int CompareNode(DictNode* left, DictNode* right) {
+ int cmp = left->hash - right->hash;
+ if (cmp == 0) {
+ cmp = ValueAsBool(OpEq(left->key, right->key)) ? 0 : 1;
+ }
+ return cmp;
+}
+
+static DictNode** FindNode(DictNode** root, DictNode* node) {
+ DictNode** curr = root;
+ while(*curr != NULL) {
+ int cmp = CompareNode(node, *curr);
+ if (cmp < 0)
+ curr = &((*curr)->left);
+ else if (cmp > 0)
+ curr = &((*curr)->right);
+ else
+ break;
+ }
+ return curr;
+}
+
+Value MakeDict(int32_t nslots) {
+ Dict* dict = calloc(1, sizeof(Dict));
+ return (Value){ .as_uint64 = (NAN_TAG_DICT | (uintptr_t)dict) };
+}
+
+void Dict_Set(Value dictionary, Value key, Value value)
+{
+ DictNode node = {
+ .hash = Hash(key),
+ .key = key,
+ .value = value
+ };
+ Dict* dict = ValueAsDict(dictionary);
+ DictNode** curr = FindNode(&(dict->root), &node);
+ if (!*curr) {
+ DictNode* new_node = calloc(1, sizeof(DictNode));
+ *new_node = node;
+ *curr = new_node;
+ } else {
+ (*curr)->value = value;
+ }
+}
+
+Value Dict_Get(Value dictionary, Value key)
+{
+ DictNode node = {
+ .hash = Hash(key),
+ .key = key,
+ };
+ Dict* dict = ValueAsDict(dictionary);
+ DictNode** curr = FindNode(&(dict->root), &node);
+ Value result = MakeNil();
+ if (*curr) {
+ result = (*curr)->value;
+ }
+ return result;
+}
+++ /dev/null
-#include "runtime.h"
-
-Value MakeDict(int32_t nslots) {
-// Value* record = calloc(2,sizeof(Value));
-// record[0] = MakeInt(1);
-// record[1] = MakeInt(nslots); //
-// record[2] = MakeInt(nslots); //
-// return (Value){ .as_uint64 = (NAN_TAG_ARRAY | (uintptr_t)record) };
- return MakeNil();
-}
-
-void Dict_Set(Value hash, Value key, Value value)
-{
-}
-
-Value Dict_Get(Value hash, Value key)
-{
- return MakeNil();
-}
String* str = calloc(sizeof(String) + sz + 1, 1);
str->length = sz;
strncpy(str->bytes, s, sz+1);
- return (Value){
- .as_uint64 = (NAN_TAG_STRING | (uint64_t)str)
- };
+ Value ret = (Value){ .as_uint64 = (NAN_TAG_STRING | (uint64_t)str) };
+ assert(IsString(ret));
+ return ret;
}
Value String_Get(Value hash, int index)