hashmaps are now first class objects in the language
This commit is contained in:
+30
-5
@@ -23,12 +23,15 @@ proc lisp_object_equal(Lisp_Object* n1, Lisp_Object* n2) -> bool {
|
||||
case Lisp_Object_Type::Continuation: return false;
|
||||
case Lisp_Object_Type::T: // code for t and nil should never be
|
||||
// reached since they are memory unique
|
||||
case Lisp_Object_Type::Nil: return true;
|
||||
case Lisp_Object_Type::Nil: return true;
|
||||
case Lisp_Object_Type::Number: return n1->value.number == n2->value.number;
|
||||
case Lisp_Object_Type::String: return string_equal(n1->value.string, n2->value.string);
|
||||
case Lisp_Object_Type::HashMap:
|
||||
case Lisp_Object_Type::Pair:
|
||||
case Lisp_Object_Type::Vector:
|
||||
create_not_yet_implemented_error();
|
||||
case Lisp_Object_Type::Symbol:
|
||||
case Lisp_Object_Type::Keyword:
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -102,7 +105,7 @@ proc load_built_ins_into_environment() -> void {
|
||||
|
||||
|
||||
#define fetch1(var) \
|
||||
Lisp_Object* var##_symbol = Memory::get_or_create_lisp_object_symbol(#var); \
|
||||
Lisp_Object* var##_symbol = Memory::get_or_create_lisp_object_symbol(#var); \
|
||||
Lisp_Object* var = lookup_symbol(var##_symbol, get_current_environment()); \
|
||||
if (Globals::error) printf("in %s:%d\n", __FILE__, __LINE__)
|
||||
|
||||
@@ -794,6 +797,27 @@ proc load_built_ins_into_environment() -> void {
|
||||
fetch(args);
|
||||
return args;
|
||||
};
|
||||
define((create-hash-map), "TODO") {
|
||||
Lisp_Object* ret;
|
||||
try ret = Memory::create_lisp_object_hash_map();
|
||||
return ret;
|
||||
};
|
||||
define((hash-map-get hm key), "TODO") {
|
||||
fetch(hm, key);
|
||||
try assert_type(hm, Lisp_Object_Type::HashMap);
|
||||
|
||||
Lisp_Object* ret = (Lisp_Object*)hm_get_object(hm->value.hashMap, key);
|
||||
if (!ret)
|
||||
create_symbol_undefined_error("The key was not set in the hashmap");
|
||||
|
||||
return ret;
|
||||
};
|
||||
define((hash-map-set! hm key value), "TODO") {
|
||||
fetch(hm, key, value);
|
||||
try assert_type(hm, Lisp_Object_Type::HashMap);
|
||||
hm_set(hm->value.hashMap, key, value);
|
||||
return Memory::nil;
|
||||
};
|
||||
define((vector . args), "TODO") {
|
||||
fetch(args);
|
||||
Lisp_Object* ret;
|
||||
@@ -855,15 +879,16 @@ proc load_built_ins_into_environment() -> void {
|
||||
return Memory::get_or_create_lisp_object_keyword("macro");
|
||||
else return Memory::get_or_create_lisp_object_keyword("unknown");
|
||||
}
|
||||
case Lisp_Object_Type::HashMap: return Memory::get_or_create_lisp_object_keyword("hashmap");
|
||||
case Lisp_Object_Type::Keyword: return Memory::get_or_create_lisp_object_keyword("keyword");
|
||||
case Lisp_Object_Type::Nil: return Memory::get_or_create_lisp_object_keyword("nil");
|
||||
case Lisp_Object_Type::T: return Memory::get_or_create_lisp_object_keyword("t");
|
||||
case Lisp_Object_Type::Pointer: return Memory::get_or_create_lisp_object_keyword("pointer");
|
||||
case Lisp_Object_Type::Number: return Memory::get_or_create_lisp_object_keyword("number");
|
||||
case Lisp_Object_Type::Pair: return Memory::get_or_create_lisp_object_keyword("pair");
|
||||
case Lisp_Object_Type::Vector: return Memory::get_or_create_lisp_object_keyword("vector");
|
||||
case Lisp_Object_Type::Pointer: return Memory::get_or_create_lisp_object_keyword("pointer");
|
||||
case Lisp_Object_Type::String: return Memory::get_or_create_lisp_object_keyword("string");
|
||||
case Lisp_Object_Type::Symbol: return Memory::get_or_create_lisp_object_keyword("symbol");
|
||||
case Lisp_Object_Type::T: return Memory::get_or_create_lisp_object_keyword("t");
|
||||
case Lisp_Object_Type::Vector: return Memory::get_or_create_lisp_object_keyword("vector");
|
||||
}
|
||||
return Memory::get_or_create_lisp_object_keyword("unknown");
|
||||
};
|
||||
|
||||
+7
-2
@@ -21,6 +21,7 @@ proc create_error(const char* c_file_name, int c_file_line, Lisp_Object* type, S
|
||||
// visualize_lisp_machine();
|
||||
|
||||
using Globals::error;
|
||||
|
||||
error = new(Error);
|
||||
error->type = type;
|
||||
error->message = message;
|
||||
@@ -29,10 +30,14 @@ proc create_error(const char* c_file_name, int c_file_line, Lisp_Object* type, S
|
||||
|
||||
proc create_error(const char* c_file_name, int c_file_line, Lisp_Object* type, const char* format, ...) -> void {
|
||||
// HACK(Felix): the length of all error strings is 200!!!!!!!!!!
|
||||
|
||||
using Globals::error;
|
||||
|
||||
int length = 200;
|
||||
String* formatted_string = Memory::create_string("", length);
|
||||
|
||||
if (error) {
|
||||
error = new(Error);
|
||||
error->type = type;
|
||||
}
|
||||
int written_length;
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// proc assert_type(Lisp_Object*, Lisp_Object_Type) -> void;
|
||||
proc lisp_object_equal(Lisp_Object*,Lisp_Object*) -> bool;
|
||||
proc built_in_load(String*) -> Lisp_Object*;
|
||||
proc built_in_import(String*) -> Lisp_Object*;
|
||||
proc create_error(const char* c_file_name, int c_file_line, Lisp_Object* type, String* message) -> void;
|
||||
@@ -56,3 +57,54 @@ namespace Globals {
|
||||
#endif
|
||||
Error* error = nullptr;
|
||||
}
|
||||
|
||||
|
||||
inline bool hm_objects_match(char* a, char* b) {
|
||||
return strcmp(a, b) == 0;
|
||||
}
|
||||
|
||||
inline bool hm_objects_match(void* a, void* b) {
|
||||
return a == b;
|
||||
}
|
||||
|
||||
u32 hm_hash(void* ptr) {
|
||||
return ((unsigned long long)ptr * 2654435761) % 4294967296;
|
||||
}
|
||||
|
||||
u32 hm_hash(char* str) {
|
||||
u32 value = str[0] << 7;
|
||||
int i = 0;
|
||||
while (str[i]) {
|
||||
value = (10000003 * value) ^ str[i++];
|
||||
}
|
||||
return value ^ i;
|
||||
}
|
||||
|
||||
inline bool hm_objects_match(Lisp_Object* a, Lisp_Object* b) {
|
||||
return lisp_object_equal(a, b);
|
||||
}
|
||||
|
||||
u32 hm_hash(Lisp_Object* obj) {
|
||||
switch (Memory::get_type(obj)) {
|
||||
// hash from adress: if two objects of these types have
|
||||
// different addresses, they are different
|
||||
case Lisp_Object_Type::CFunction:
|
||||
case Lisp_Object_Type::Function:
|
||||
case Lisp_Object_Type::Symbol:
|
||||
case Lisp_Object_Type::Keyword:
|
||||
case Lisp_Object_Type::Continuation:
|
||||
case Lisp_Object_Type::Nil:
|
||||
case Lisp_Object_Type::T:
|
||||
return hm_hash((void*) obj);
|
||||
// hash from contents: even if objects are themselved
|
||||
// different, they cauld be equivalent:
|
||||
case Lisp_Object_Type::Pointer: return hm_hash((void*) obj->value.pointer);
|
||||
case Lisp_Object_Type::Number: return hm_hash((void*) (unsigned long long)obj->value.number); // HACK(Felix): yes
|
||||
case Lisp_Object_Type::String: return hm_hash((char*) &obj->value.string->data);
|
||||
case Lisp_Object_Type::Vector:
|
||||
case Lisp_Object_Type::Pair:
|
||||
case Lisp_Object_Type::HashMap:
|
||||
create_not_yet_implemented_error();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
Submodule src/ftb updated: 2f6954b520...94ad64f6bb
@@ -284,6 +284,7 @@ proc print(Lisp_Object* node, bool print_repr = false, FILE* file = stdout) -> v
|
||||
case (Lisp_Object_Type::Continuation): fputs("[continuation]", file); break;
|
||||
case (Lisp_Object_Type::CFunction): fputs("[C-function]", file); break;
|
||||
case (Lisp_Object_Type::Pointer): fputs("[pointer]", file); break;
|
||||
case (Lisp_Object_Type::HashMap): fputs("[hashmap]", file); break;
|
||||
case (Lisp_Object_Type::String): {
|
||||
if (print_repr) {
|
||||
putc('\"', file);
|
||||
|
||||
@@ -23,6 +23,7 @@ proc Lisp_Object_Type_to_string(Lisp_Object_Type type) -> const char* {
|
||||
case(Lisp_Object_Type::Pair): return "pair";
|
||||
case(Lisp_Object_Type::Vector): return "vector";
|
||||
case(Lisp_Object_Type::Pointer): return "pointer";
|
||||
case(Lisp_Object_Type::HashMap): return "hashmap";
|
||||
}
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
+18
-4
@@ -227,6 +227,14 @@ namespace Memory {
|
||||
return node;
|
||||
}
|
||||
|
||||
proc create_lisp_object_hash_map() -> Lisp_Object* {
|
||||
Lisp_Object* node;
|
||||
try node = create_lisp_object();
|
||||
set_type(node, Lisp_Object_Type::HashMap);
|
||||
node->value.hashMap = create_Lisp_Obj_hashmap();
|
||||
return node;
|
||||
}
|
||||
|
||||
proc create_lisp_object_number(double number) -> Lisp_Object* {
|
||||
Lisp_Object* node;
|
||||
try node = create_lisp_object();
|
||||
@@ -321,8 +329,11 @@ namespace Memory {
|
||||
proc get_or_create_lisp_object_symbol(const char* identifier) -> Lisp_Object* {
|
||||
if (auto ret = hm_get_object(global_symbol_table, (char*)identifier))
|
||||
return (Lisp_Object*)ret;
|
||||
else
|
||||
return create_new_lisp_object_symbol(Memory::create_string(identifier));
|
||||
else {
|
||||
String* str;
|
||||
try str = Memory::create_string(identifier);
|
||||
return create_new_lisp_object_symbol(str);
|
||||
}
|
||||
}
|
||||
|
||||
proc get_or_create_lisp_object_keyword(String* keyword) -> Lisp_Object* {
|
||||
@@ -335,8 +346,11 @@ namespace Memory {
|
||||
proc get_or_create_lisp_object_keyword(const char* keyword) -> Lisp_Object* {
|
||||
if (auto ret = hm_get_object(global_keyword_table, (char*)keyword))
|
||||
return (Lisp_Object*)ret;
|
||||
else
|
||||
return create_new_lisp_object_keyword(Memory::create_string(keyword));
|
||||
else {
|
||||
String* str;
|
||||
try str = Memory::create_string(keyword);
|
||||
return create_new_lisp_object_keyword(str);
|
||||
}
|
||||
}
|
||||
|
||||
proc create_lisp_object_cfunction(bool is_special) -> Lisp_Object* {
|
||||
|
||||
+17
-34
@@ -10,31 +10,12 @@ define_array_list(int, Int);
|
||||
define_array_list(void*, Void_Ptr);
|
||||
|
||||
// HASH MAPS
|
||||
inline bool hm_objects_match(char* a, char* b) {
|
||||
return strcmp(a, b) == 0;
|
||||
}
|
||||
|
||||
inline bool hm_objects_match(void* a, void* b) {
|
||||
return a == b;
|
||||
}
|
||||
|
||||
u32 hm_hash(void* ptr) {
|
||||
return ((unsigned long long)ptr * 2654435761) % 4294967296;
|
||||
}
|
||||
|
||||
u32 hm_hash(char* str) {
|
||||
u32 value = str[0] << 7;
|
||||
int i = 0;
|
||||
while (str[i]) {
|
||||
value = (10000003 * value) ^ str[i++];
|
||||
}
|
||||
return value ^ i;
|
||||
}
|
||||
|
||||
define_hash_map(char*, String);
|
||||
define_hash_map(void*, Void_Ptr);
|
||||
#define for_str_hash_map(hm) __for_hm_generator(char*, hm)
|
||||
#define for_ptr_hash_map(hm) __for_hm_generator(void*, hm)
|
||||
define_hash_map(char*, String);
|
||||
define_hash_map(Lisp_Object*, Lisp_Obj);
|
||||
define_hash_map(void*, Void_Ptr);
|
||||
#define for_str_hash_map(hm) __for_hm_generator(char*, hm)
|
||||
#define for_ptr_hash_map(hm) __for_hm_generator(void*, hm)
|
||||
#define for_lisp_obj_hash_map(hm) __for_hm_generator(Lisp_Object*, hm)
|
||||
|
||||
// STRUCTS
|
||||
enum struct Thread_Type {
|
||||
@@ -54,6 +35,7 @@ enum struct Lisp_Object_Type {
|
||||
Vector,
|
||||
Continuation,
|
||||
Pointer,
|
||||
HashMap,
|
||||
// OwningPointer,
|
||||
Function,
|
||||
CFunction,
|
||||
@@ -162,15 +144,16 @@ struct Lisp_Object {
|
||||
Lisp_Object* userType; // keyword
|
||||
String* docstring;
|
||||
union {
|
||||
Symbol symbol; // used for symbols and keywords
|
||||
double number;
|
||||
String* string;
|
||||
Pair pair;
|
||||
Vector vector;
|
||||
Function function;
|
||||
cFunction* cFunction;
|
||||
void* pointer;
|
||||
Continuation continuation;
|
||||
Symbol symbol; // used for symbols and keywords
|
||||
double number;
|
||||
String* string;
|
||||
Pair pair;
|
||||
Vector vector;
|
||||
Function function;
|
||||
cFunction* cFunction;
|
||||
void* pointer;
|
||||
Continuation continuation;
|
||||
Lisp_Obj_Hash_Map* hashMap;
|
||||
} value;
|
||||
};
|
||||
|
||||
|
||||
+3
-2
@@ -607,7 +607,7 @@ proc run_all_tests() -> bool {
|
||||
|
||||
bool result = true;
|
||||
|
||||
Memory::init(4096 * 4096, 1024 * 512, 4096 * 16 * 100);
|
||||
Memory::init(200000, 10240, 409600);
|
||||
Environment* root_env = get_root_environment();
|
||||
Environment* user_env = Memory::create_child_environment(root_env);
|
||||
push_environment(user_env);
|
||||
@@ -654,8 +654,9 @@ proc run_all_tests() -> bool {
|
||||
invoke_test_script("macro_expand");
|
||||
invoke_test_script("automata");
|
||||
invoke_test_script("sicp");
|
||||
invoke_test_script("hashmaps");
|
||||
|
||||
// visualize_lisp_machine();
|
||||
// Memory::print_status();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user