hashmaps are now first class objects in the language

This commit is contained in:
Felix Brendel
2019-10-04 17:48:31 +02:00
parent ac70c14e5b
commit 5e82f9175d
15 changed files with 166 additions and 51 deletions
+30 -5
View File
@@ -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
View File
@@ -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);
+52
View File
@@ -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
+1
View File
@@ -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);
+1
View 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
View File
@@ -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
View File
@@ -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
View File
@@ -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;
}