Docs is stored external to the lisp objects in a hashmap now

This commit is contained in:
Felix Brendel
2020-03-19 01:02:06 +01:00
parent 9295d57a8e
commit 4f0fef064e
16 changed files with 4336 additions and 4388 deletions
+1 -1
View File
@@ -52,7 +52,7 @@ echo ""
echo "----------------------" echo "----------------------"
echo " running profile " echo " running profile "
echo "----------------------" echo "----------------------"
time ./slime_p --run-tests || exit 1 time ./slime_p --run-tests > /dev/null || exit 1
echo "" echo ""
echo "------------------------" echo "------------------------"
+2 -2
View File
@@ -31,12 +31,12 @@
#define assert_type(_node, _type) \ #define assert_type(_node, _type) \
do { \ do { \
if (Memory::get_type(_node) != _type) { \ if (_node->type != _type) { \
char* t = lisp_object_to_string(_node); \ char* t = lisp_object_to_string(_node); \
defer { free(t); }; \ defer { free(t); }; \
create_type_missmatch_error( \ create_type_missmatch_error( \
lisp_object_type_to_string(_type), \ lisp_object_type_to_string(_type), \
lisp_object_type_to_string(Memory::get_type(_node)), \ lisp_object_type_to_string(_node->type), \
t); \ t); \
} \ } \
} while(0) } while(0)
+34 -30
View File
@@ -2,10 +2,10 @@ namespace Slime {
proc lisp_object_equal(Lisp_Object* n1, Lisp_Object* n2) -> bool { proc lisp_object_equal(Lisp_Object* n1, Lisp_Object* n2) -> bool {
if (n1 == n2) if (n1 == n2)
return true; return true;
if (Memory::get_type(n1) != Memory::get_type(n2)) if (n1->type != n2->type)
return false; return false;
switch (Memory::get_type(n1)) { switch (n1->type) {
case Lisp_Object_Type::T: case Lisp_Object_Type::T:
case Lisp_Object_Type::Nil: case Lisp_Object_Type::Nil:
@@ -299,7 +299,7 @@ namespace Slime {
Lisp_Object* thing = form->value.pair.first; Lisp_Object* thing = form->value.pair.first;
Lisp_Object* thing_cons = form; Lisp_Object* thing_cons = form;
form = form->value.pair.rest; form = form->value.pair.rest;
Lisp_Object_Type type = Memory::get_type(definee); Lisp_Object_Type type = definee->type;
switch (type) { switch (type) {
case Lisp_Object_Type::Symbol: { case Lisp_Object_Type::Symbol: {
if (form != Memory::nil) { if (form != Memory::nil) {
@@ -322,12 +322,14 @@ namespace Slime {
try_void func = Memory::create_lisp_object_function(Lisp_Function_Type::Lambda); try_void func = Memory::create_lisp_object_function(Lisp_Function_Type::Lambda);
func->value.function->parent_environment = get_current_environment(); func->value.function->parent_environment = get_current_environment();
create_arguments_from_lambda_list_and_inject(definee->value.pair.rest, func); create_arguments_from_lambda_list_and_inject(definee->value.pair.rest, func);
if (Memory::get_type(thing_cons->value.pair.first) == Lisp_Object_Type::String && if (thing_cons->value.pair.first->type == Lisp_Object_Type::String &&
thing_cons->value.pair.rest != Memory::nil) thing_cons->value.pair.rest != Memory::nil)
{ {
// extract docs // extract docs
//TODO(Felix): make docs as HM lookup Globals::docs.set_object(
// func->docstring = thing_cons->value.pair.first->value.string; func,
Memory::duplicate_string(
thing_cons->value.pair.first->value.string).data);
thing_cons = thing_cons->value.pair.rest; thing_cons = thing_cons->value.pair.rest;
} }
func->value.function->body.lisp_body = maybe_wrap_body_in_begin(thing_cons); func->value.function->body.lisp_body = maybe_wrap_body_in_begin(thing_cons);
@@ -560,7 +562,7 @@ namespace Slime {
profile_with_name("(gensym)"); profile_with_name("(gensym)");
Lisp_Object* node; Lisp_Object* node;
try node = Memory::create_lisp_object(); try node = Memory::create_lisp_object();
Memory::set_type(node, Lisp_Object_Type::Symbol); node->type = Lisp_Object_Type::Symbol;
node->value.symbol = Memory::create_string("gensym"); node->value.symbol = Memory::create_string("gensym");
return node; return node;
}; };
@@ -598,7 +600,7 @@ namespace Slime {
fetch(form, body); fetch(form, body);
// TODO(Felix): Macros cannot have docs now // TODO(Felix): Macros cannot have docs now
if (Memory::get_type(form) != Lisp_Object_Type::Pair) { if (form->type != Lisp_Object_Type::Pair) {
create_parsing_error("You can only create function macros."); create_parsing_error("You can only create function macros.");
return nullptr; return nullptr;
} }
@@ -624,16 +626,16 @@ namespace Slime {
if (target == Memory::nil || if (target == Memory::nil ||
target == Memory::t || target == Memory::t ||
Memory::get_type(target) == Lisp_Object_Type::Keyword || target->type == Lisp_Object_Type::Keyword ||
Memory::get_type(target) == Lisp_Object_Type::Symbol) target->type == Lisp_Object_Type::Symbol)
{ {
create_generic_error("You cannot mutate to nil, t, keywords or symbols because they have to be unique"); create_generic_error("You cannot mutate to nil, t, keywords or symbols because they have to be unique");
} }
if (source == Memory::nil || if (source == Memory::nil ||
source == Memory::t || source == Memory::t ||
Memory::get_type(source) == Lisp_Object_Type::Keyword || source->type == Lisp_Object_Type::Keyword ||
Memory::get_type(source) == Lisp_Object_Type::Symbol) source->type == Lisp_Object_Type::Symbol)
{ {
create_generic_error("You cannot mutate nil, t, keywords or symbols"); create_generic_error("You cannot mutate nil, t, keywords or symbols");
} }
@@ -731,7 +733,7 @@ namespace Slime {
// a recursive lambda // a recursive lambda
const auto unquoteSomeExpressions = [&] (const auto & self, Lisp_Object* expr) -> Lisp_Object* { const auto unquoteSomeExpressions = [&] (const auto & self, Lisp_Object* expr) -> Lisp_Object* {
// if it is an atom, return it // if it is an atom, return it
if (Memory::get_type(expr) != Lisp_Object_Type::Pair) if (expr->type != Lisp_Object_Type::Pair)
return Memory::copy_lisp_object(expr); return Memory::copy_lisp_object(expr);
// it is a pair! // it is a pair!
@@ -766,10 +768,10 @@ namespace Slime {
Lisp_Object* newPairHead = newPair; Lisp_Object* newPairHead = newPair;
Lisp_Object* head = expr; Lisp_Object* head = expr;
while (Memory::get_type(head) == Lisp_Object_Type::Pair) { while (head->type == Lisp_Object_Type::Pair) {
// if it is ,@ we have to actually do more work // if it is ,@ we have to actually do more work
// and inline the result // and inline the result
if (Memory::get_type(head->value.pair.first) == Lisp_Object_Type::Pair && if (head->value.pair.first->type == Lisp_Object_Type::Pair &&
head->value.pair.first->value.pair.first == unquote_splicing_sym) head->value.pair.first->value.pair.first == unquote_splicing_sym)
{ {
Lisp_Object* spliced = self(self, head->value.pair.first); Lisp_Object* spliced = self(self, head->value.pair.first);
@@ -947,24 +949,27 @@ namespace Slime {
profile_with_name("(set-type!)"); profile_with_name("(set-type!)");
fetch(node, new_type); fetch(node, new_type);
try assert_type(new_type, Lisp_Object_Type::Keyword); try assert_type(new_type, Lisp_Object_Type::Keyword);
node->userType = new_type; // TODO(Felix): Enable again when we have user types again:
// node->userType = new_type;
return node; return node;
}; };
define((delete-type! n), "TODO") { define((delete-type! n), "TODO") {
profile_with_name("(delete-type!)"); profile_with_name("(delete-type!)");
fetch(n); fetch(n);
n->userType = nullptr; // TODO(Felix): Enable again when we have user types again:
// n->userType = nullptr;
return Memory::t; return Memory::t;
}; };
define((type n), "TODO") { define((type n), "TODO") {
profile_with_name("(type)"); profile_with_name("(type)");
fetch(n); fetch(n);
if (n->userType) { // TODO(Felix): Enable again when we have user types again:
return n->userType; // if (n->userType) {
} // return n->userType;
// }
Lisp_Object_Type type = Memory::get_type(n); Lisp_Object_Type type = n->type;
switch (type) { switch (type) {
case Lisp_Object_Type::Continuation: return Memory::get_keyword("continuation"); case Lisp_Object_Type::Continuation: return Memory::get_keyword("continuation");
@@ -995,6 +1000,8 @@ namespace Slime {
case Lisp_Object_Type::Symbol: return Memory::get_keyword("symbol"); case Lisp_Object_Type::Symbol: return Memory::get_keyword("symbol");
case Lisp_Object_Type::T: return Memory::get_keyword("t"); case Lisp_Object_Type::T: return Memory::get_keyword("t");
case Lisp_Object_Type::Vector: return Memory::get_keyword("vector"); case Lisp_Object_Type::Vector: return Memory::get_keyword("vector");
case(Lisp_Object_Type::Invalid_Garbage_Collected): return Memory::get_keyword("Invalid: Garbage Collected");
case(Lisp_Object_Type::Invalid_Under_Construction): return Memory::get_keyword("Invalid: Under Construction");
} }
return Memory::get_keyword("unknown"); return Memory::get_keyword("unknown");
}; };
@@ -1023,17 +1030,15 @@ namespace Slime {
printf(" is of type "); printf(" is of type ");
print(type); print(type);
printf(" (internal: %s)", lisp_object_type_to_string(Memory::get_type(val))); printf(" (internal: %s)", lisp_object_type_to_string(val->type));
printf("\nand is printed as: "); printf("\nand is printed as: ");
print(val); print(val);
printf("\n\ndocs:\n=====\n %s\n\n", printf("\n\ndocs:\n=====\n %s\n\n",
// TODO(felix): Doc HM lookup (Globals::docs.get_object(val))
// (val->docstring) ? Globals::docs.get_object(val)
// ? Memory::get_c_str(val->docstring) : "No docs avaliable");
// :
"No docs avaliable");
if (Memory::get_type(val) == Lisp_Object_Type::Function) if (val->type == Lisp_Object_Type::Function)
{ {
Arguments* args = &val->value.function->args; Arguments* args = &val->value.function->args;
@@ -1094,8 +1099,7 @@ namespace Slime {
define((addr-of var), "TODO") { define((addr-of var), "TODO") {
profile_with_name("(addr-of-var)"); profile_with_name("(addr-of-var)");
fetch(var); fetch(var);
return Memory::create_lisp_object( return Memory::create_lisp_object(&var);
(float)((u64)&(var)));
}; };
define((generate-docs file_name), "TODO") { define((generate-docs file_name), "TODO") {
profile_with_name("(generate-docs)"); profile_with_name("(generate-docs)");
+3 -3
View File
@@ -108,7 +108,7 @@
// mutable for the parser to work, (#def gives us a const char) // mutable for the parser to work, (#def gives us a const char)
// because the parser relys on being able to temporaily put in markers // because the parser relys on being able to temporaily put in markers
// in the code and also it will fill out the source code location // in the code and also it will fill out the source code location
#define _define_helper(def, docs, type, ending) \ #define _define_helper(def, docstring, type, ending) \
Parser::parser_file = file_name_built_ins; \ Parser::parser_file = file_name_built_ins; \
Parser::parser_line = __LINE__; \ Parser::parser_line = __LINE__; \
Parser::parser_col = 0; \ Parser::parser_col = 0; \
@@ -118,9 +118,9 @@
assert_type(label(params,__LINE__)->value.pair.first, Lisp_Object_Type::Symbol); \ assert_type(label(params,__LINE__)->value.pair.first, Lisp_Object_Type::Symbol); \
auto label(sym,__LINE__) = label(params,__LINE__)->value.pair.first; \ auto label(sym,__LINE__) = label(params,__LINE__)->value.pair.first; \
auto label(sfun,__LINE__) = Memory::create_lisp_object_cfunction(type); \ auto label(sfun,__LINE__) = Memory::create_lisp_object_cfunction(type); \
Globals::docs.set_object(label(sfun,__LINE__), Memory::create_string(docstring).data); \
create_arguments_from_lambda_list_and_inject(label(params,__LINE__)->value.pair.rest, label(sfun,__LINE__)); \ create_arguments_from_lambda_list_and_inject(label(params,__LINE__)->value.pair.rest, label(sfun,__LINE__)); \
if_error_log_location_and_return(nullptr); \ if_error_log_location_and_return(nullptr); \
/* TODO(Felix): label(sfun,__LINE__)->docstring = Memory::create_string(docs); */ \
label(sfun,__LINE__)->value.function->parent_environment = get_current_environment(); \ label(sfun,__LINE__)->value.function->parent_environment = get_current_environment(); \
define_symbol(label(sym,__LINE__), label(sfun,__LINE__)); \ define_symbol(label(sym,__LINE__), label(sfun,__LINE__)); \
label(sfun,__LINE__)->value.function->body. ending label(sfun,__LINE__)->value.function->body. ending
@@ -151,7 +151,7 @@
if (!l); else \ if (!l); else \
if (int it_index = 0); else \ if (int it_index = 0); else \
for (Lisp_Object* head = l, *it; \ for (Lisp_Object* head = l, *it; \
Memory::get_type(head) == Lisp_Object_Type::Pair && (it = head->value.pair.first); \ head->type == Lisp_Object_Type::Pair && (it = head->value.pair.first); \
head = head->value.pair.rest, ++it_index) head = head->value.pair.rest, ++it_index)
+9 -7
View File
@@ -44,16 +44,18 @@ namespace Slime {
/* /*
* sourcecodeLocation * sourcecodeLocation
*/ */
if (value->sourceCodeLocation) { // TODO(Felix): Enable again when we have SCL again:
try_void fprintf(f, "\n - defined in :: =%s:%d:%d=",
Memory::get_c_str(value->sourceCodeLocation->file), // if (value->sourceCodeLocation) {
value->sourceCodeLocation->line, // try_void fprintf(f, "\n - defined in :: =%s:%d:%d=",
value->sourceCodeLocation->column); // Memory::get_c_str(value->sourceCodeLocation->file),
} // value->sourceCodeLocation->line,
// value->sourceCodeLocation->column);
// }
/* /*
* type * type
*/ */
Lisp_Object_Type type = Memory::get_type(value); Lisp_Object_Type type = value->type;
Lisp_Object* LOtype; Lisp_Object* LOtype;
Lisp_Object* type_expr = Memory::create_list(Memory::get_symbol("type"), value); Lisp_Object* type_expr = Memory::create_list(Memory::get_symbol("type"), value);
try_void LOtype = eval_expr(type_expr); try_void LOtype = eval_expr(type_expr);
+16 -40
View File
@@ -56,7 +56,7 @@ namespace Slime {
++obligatory_keywords_count; ++obligatory_keywords_count;
} }
while (Memory::get_type(cs.data[index_of_next_arg]) == Lisp_Object_Type::Keyword) { while (cs.data[index_of_next_arg]->type == Lisp_Object_Type::Keyword) {
// check if this one is even an accepted keyword // check if this one is even an accepted keyword
bool accepted = false; bool accepted = false;
for (int i = 0; i < arg_spec->keyword.keywords.next_index; ++i) { for (int i = 0; i < arg_spec->keyword.keywords.next_index; ++i) {
@@ -190,30 +190,6 @@ namespace Slime {
return env; return env;
} }
proc apply_arguments_to_function(Lisp_Object* arguments, Lisp_Object* function, bool should_evaluate_args) -> Lisp_Object* {
// profile_this();
// Environment* new_env;
// Lisp_Object* result;
// try new_env = create_extended_environment_for_function_application(arguments, function, should_evaluate_args);
// push_environment(new_env);
// defer {
// pop_environment();
// };
// if (Memory::get_type(function) == Lisp_Object_Type::CFunction)
// // if c function:
// try result = function->value.cFunction->body();
// else
// // if lisp function
// try result = eval_expr(function->value.function->body);
// return result;
return nullptr;
}
proc create_arguments_from_lambda_list_and_inject(Lisp_Object* arguments, Lisp_Object* function) -> void { proc create_arguments_from_lambda_list_and_inject(Lisp_Object* arguments, Lisp_Object* function) -> void {
/* NOTE This parses the argument specification of funcitons /* NOTE This parses the argument specification of funcitons
* into their Function struct. It does this by allocating new * into their Function struct. It does this by allocating new
@@ -226,21 +202,21 @@ namespace Slime {
result->rest = nullptr; result->rest = nullptr;
// okay let's try to read some positional arguments // okay let's try to read some positional arguments
while (Memory::get_type(arguments) == Lisp_Object_Type::Pair) { while (arguments->type == Lisp_Object_Type::Pair) {
// if we encounter a keyword or a list (for keywords with // if we encounter a keyword or a list (for keywords with
// defualt args), the positionals are done // defualt args), the positionals are done
if (Memory::get_type(arguments->value.pair.first) == Lisp_Object_Type::Keyword || if (arguments->value.pair.first->type == Lisp_Object_Type::Keyword ||
Memory::get_type(arguments->value.pair.first) == Lisp_Object_Type::Pair) { arguments->value.pair.first->type == Lisp_Object_Type::Pair) {
break; break;
} }
// if we encounter something that is neither a symbol nor a // if we encounter something that is neither a symbol nor a
// keyword arg, it's an error // keyword arg, it's an error
if (Memory::get_type(arguments->value.pair.first) != Lisp_Object_Type::Symbol) { if (arguments->value.pair.first->type != Lisp_Object_Type::Symbol) {
create_parsing_error("Only symbols and keywords " create_parsing_error("Only symbols and keywords "
"(with or without default args) " "(with or without default args) "
"can be parsed here, but found '%s'", "can be parsed here, but found '%s'",
lisp_object_type_to_string(Memory::get_type(arguments->value.pair.first))); lisp_object_type_to_string(arguments->value.pair.first->type));
return; return;
} }
@@ -252,20 +228,20 @@ namespace Slime {
// if we reach here, we are on a keyword or a pair wher a keyword // if we reach here, we are on a keyword or a pair wher a keyword
// should be in first // should be in first
while (Memory::get_type(arguments) == Lisp_Object_Type::Pair) { while ((arguments->type) == Lisp_Object_Type::Pair) {
if (Memory::get_type(arguments->value.pair.first) == Lisp_Object_Type::Keyword) { if ((arguments->value.pair.first->type) == Lisp_Object_Type::Keyword) {
// if we are on a actual keyword (with no default arg) // if we are on a actual keyword (with no default arg)
auto keyword = arguments->value.pair.first; auto keyword = arguments->value.pair.first;
result->keyword.keywords.append(keyword); result->keyword.keywords.append(keyword);
result->keyword.values.append(nullptr); result->keyword.values.append(nullptr);
} else if (Memory::get_type(arguments->value.pair.first) == Lisp_Object_Type::Pair) { } else if ((arguments->value.pair.first->type) == Lisp_Object_Type::Pair) {
// if we are on a keyword with a default value // if we are on a keyword with a default value
auto keyword = arguments->value.pair.first->value.pair.first; auto keyword = arguments->value.pair.first->value.pair.first;
if (Memory::get_type(keyword) != Lisp_Object_Type::Keyword) { if ((keyword->type) != Lisp_Object_Type::Keyword) {
create_parsing_error("Default args must be keywords"); create_parsing_error("Default args must be keywords");
} }
if (Memory::get_type(arguments->value.pair.first->value.pair.rest) if ((arguments->value.pair.first->value.pair.rest->type)
!= Lisp_Object_Type::Pair) != Lisp_Object_Type::Pair)
{ {
create_parsing_error("Default args must be a list of 2."); create_parsing_error("Default args must be a list of 2.");
@@ -284,10 +260,10 @@ namespace Slime {
// Now we are also done with keyword arguments, lets check for // Now we are also done with keyword arguments, lets check for
// if there is a rest argument // if there is a rest argument
if (Memory::get_type(arguments) != Lisp_Object_Type::Pair) { if (arguments->type != Lisp_Object_Type::Pair) {
if (arguments == Memory::nil) if (arguments == Memory::nil)
return; return;
if (Memory::get_type(arguments) == Lisp_Object_Type::Symbol) if (arguments->type == Lisp_Object_Type::Symbol)
result->rest = arguments; result->rest = arguments;
else else
create_parsing_error("The rest argument must be a symbol."); create_parsing_error("The rest argument must be a symbol.");
@@ -303,7 +279,7 @@ namespace Slime {
int len = 0; int len = 0;
while (Memory::get_type(node) == Lisp_Object_Type::Pair) { while (node->type == Lisp_Object_Type::Pair) {
++len; ++len;
node = node->value.pair.rest; node = node->value.pair.rest;
if (node == Memory::nil) if (node == Memory::nil)
@@ -382,7 +358,7 @@ namespace Slime {
} break; } break;
case NasAction::Eval: { case NasAction::Eval: {
pc = cs.data[cs.next_index-1]; pc = cs.data[cs.next_index-1];
Lisp_Object_Type type = Memory::get_type(pc); Lisp_Object_Type type = pc->type;
switch (type) { switch (type) {
case Lisp_Object_Type::Symbol: { case Lisp_Object_Type::Symbol: {
cs.data[cs.next_index-1] = lookup_symbol(pc, get_current_environment()); cs.data[cs.next_index-1] = lookup_symbol(pc, get_current_environment());
@@ -407,7 +383,7 @@ namespace Slime {
case NasAction::TM: { case NasAction::TM: {
pc = cs.data[cs.next_index-1]; pc = cs.data[cs.next_index-1];
Lisp_Object_Type type = Memory::get_type(pc); Lisp_Object_Type type = pc->type;
switch (type) { switch (type) {
case Lisp_Object_Type::Function: { case Lisp_Object_Type::Function: {
if(pc->value.function->is_c) { if(pc->value.function->is_c) {
-1
View File
@@ -37,7 +37,6 @@ namespace Slime {
namespace Memory { namespace Memory {
Environment* create_built_ins_environment(); Environment* create_built_ins_environment();
Lisp_Object* create_lisp_object_cfunction(bool is_special); Lisp_Object* create_lisp_object_cfunction(bool is_special);
inline Lisp_Object_Type get_type(Lisp_Object* node);
void init(); void init();
char* get_c_str(String); char* get_c_str(String);
void free_everything(); void free_everything();
+1 -1
View File
@@ -29,7 +29,7 @@ namespace Slime::GC {
// marked_strings.append(node->docstring); // marked_strings.append(node->docstring);
// mark type specific data // mark type specific data
switch (Memory::get_type(node)) { switch (node->type) {
case Lisp_Object_Type::Pair: { case Lisp_Object_Type::Pair: {
for_lisp_list (node) { for_lisp_list (node) {
maybe_mark(it); maybe_mark(it);
+5
View File
@@ -19,6 +19,11 @@ namespace Slime::Globals {
Log_Level log_level = Log_Level::Debug; Log_Level log_level = Log_Level::Debug;
bool debug_log = false; bool debug_log = false;
Array_List<void*> load_path; Array_List<void*> load_path;
Hash_Map<void*, char*> docs;
Hash_Map<void*, Source_Code_Location> source_code_locations;
Hash_Map<void*, Lisp_Object*> user_types;
namespace Current_Execution { namespace Current_Execution {
Array_List<Lisp_Object*> cs; // call stack Array_List<Lisp_Object*> cs; // call stack
Array_List<Lisp_Object*> pcs; // program counter stack Array_List<Lisp_Object*> pcs; // program counter stack
+21 -17
View File
@@ -325,7 +325,7 @@ namespace Slime {
string_builder.dealloc(); string_builder.dealloc();
}; };
switch (Memory::get_type(node)) { switch (node->type) {
case (Lisp_Object_Type::Nil): return strdup("()"); case (Lisp_Object_Type::Nil): return strdup("()");
case (Lisp_Object_Type::T): return strdup("t"); case (Lisp_Object_Type::T): return strdup("t");
case (Lisp_Object_Type::Continuation): return strdup("[continuation]"); case (Lisp_Object_Type::Continuation): return strdup("[continuation]");
@@ -388,10 +388,11 @@ namespace Slime {
return temp; return temp;
} break; } break;
case (Lisp_Object_Type::Function): { case (Lisp_Object_Type::Function): {
if (node->userType) { // TODO(Felix): Enable again when we have user types again:
asprintf(&temp, "[%s]", Memory::get_c_str(node->userType->value.symbol)); // if (node->userType) {
return temp; // asprintf(&temp, "[%s]", Memory::get_c_str(node->userType->value.symbol));
} // return temp;
// }
if (node->value.function->is_c) { if (node->value.function->is_c) {
// NOTE(Felix): try to find the symbol it is bound to // NOTE(Felix): try to find the symbol it is bound to
// in global env // in global env
@@ -431,7 +432,7 @@ namespace Slime {
}; };
// first check if it is a quotation form, in that case we want // first check if it is a quotation form, in that case we want
// to print it prettier // to print it prettier
if (Memory::get_type(head->value.pair.first) == Lisp_Object_Type::Symbol) { if (head->value.pair.first->type == Lisp_Object_Type::Symbol) {
String identifier = head->value.pair.first->value.symbol; String identifier = head->value.pair.first->value.symbol;
@@ -473,11 +474,11 @@ namespace Slime {
string_builder.append(lisp_object_to_string(head->value.pair.first, print_repr)); string_builder.append(lisp_object_to_string(head->value.pair.first, print_repr));
head = head->value.pair.rest; head = head->value.pair.rest;
if (!head) break; if (!head) break;
if (Memory::get_type(head) != Lisp_Object_Type::Pair) break; if (head->type != Lisp_Object_Type::Pair) break;
string_builder.append(strdup(" ")); string_builder.append(strdup(" "));
} }
if (head && Memory::get_type(head) != Lisp_Object_Type::Nil) { if (head && head != Memory::nil) {
string_builder.append(strdup(" . ")); string_builder.append(strdup(" . "));
string_builder.append(lisp_object_to_string(head, print_repr)); string_builder.append(lisp_object_to_string(head, print_repr));
} }
@@ -488,7 +489,7 @@ namespace Slime {
} }
default: default:
create_generic_error("A Lisp_Object of type-id %d cannot be converted to a string", create_generic_error("A Lisp_Object of type-id %d cannot be converted to a string",
(int)(Memory::get_type(node))); (int)(node->type));
return nullptr; return nullptr;
} }
} }
@@ -507,15 +508,18 @@ namespace Slime {
print(obj, true); print(obj, true);
printf(console_normal); printf(console_normal);
printf("\n at "); printf("\n at ");
if (obj->sourceCodeLocation) { // TODO(Felix): Enable again when we have a source code
printf("%s (line %d, position %d)", // location again
Memory::get_c_str(
obj->sourceCodeLocation->file), // if (obj->sourceCodeLocation) {
obj->sourceCodeLocation->line, // printf("%s (line %d, position %d)",
obj->sourceCodeLocation->column); // Memory::get_c_str(
} else { // obj->sourceCodeLocation->file),
// obj->sourceCodeLocation->line,
// obj->sourceCodeLocation->column);
// } else {
fputs("no source code location avaliable", stdout); fputs("no source code location avaliable", stdout);
} // }
} }
proc print_current_execution() -> void { proc print_current_execution() -> void {
+1 -1
View File
@@ -74,7 +74,7 @@ unsigned int hm_hash(void* ptr) {
unsigned int hm_hash(Slime::Lisp_Object* obj) { unsigned int hm_hash(Slime::Lisp_Object* obj) {
using namespace Slime; using namespace Slime;
switch (Memory::get_type(obj)) { switch (obj->type) {
// hash from adress: if two objects of these types have // hash from adress: if two objects of these types have
// different addresses, they are different // different addresses, they are different
case Lisp_Object_Type::Function: case Lisp_Object_Type::Function:
+2
View File
@@ -24,6 +24,8 @@ namespace Slime {
case(Lisp_Object_Type::Vector): return "vector"; case(Lisp_Object_Type::Vector): return "vector";
case(Lisp_Object_Type::Pointer): return "pointer"; case(Lisp_Object_Type::Pointer): return "pointer";
case(Lisp_Object_Type::HashMap): return "hashmap"; case(Lisp_Object_Type::HashMap): return "hashmap";
case(Lisp_Object_Type::Invalid_Garbage_Collected): return "Invalid: Garbage Collected";
case(Lisp_Object_Type::Invalid_Under_Construction): return "Invalid: Under Construction";
} }
return "unknown"; return "unknown";
} }
-1
View File
@@ -1,7 +1,6 @@
#include "libslime.cpp" #include "libslime.cpp"
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
#ifdef _MSC_VER #ifdef _MSC_VER
// enable colored terminal output for windows // enable colored terminal output for windows
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE); HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
+26 -63
View File
@@ -60,20 +60,6 @@ namespace Slime::Memory {
return get_c_str(str->value.string); return get_c_str(str->value.string);
} }
inline proc get_type(Lisp_Object* node) -> Lisp_Object_Type {
// the type is in the bits 0 to 5 (including)
return (Lisp_Object_Type) ((u64)node->flags & (u64)0b11111);
}
inline proc set_type(Lisp_Object* node, Lisp_Object_Type type) {
// the type is in the bits 0 to 5 (including)
u64 bitmask = (u64)-1;
bitmask -= 0b11111;
bitmask += (u64) type;
node->flags = (u64)(node->flags) | bitmask;
}
proc hash(String str) -> u64 { proc hash(String str) -> u64 {
// TODO(Felix): When parsing symbols or keywords, compute the // TODO(Felix): When parsing symbols or keywords, compute the
// hash while reading them in. // hash while reading them in.
@@ -107,18 +93,13 @@ namespace Slime::Memory {
proc create_lisp_object() -> Lisp_Object* { proc create_lisp_object() -> Lisp_Object* {
Lisp_Object* object = object_memory.allocate(); Lisp_Object* object = object_memory.allocate();
object->flags = 0; object->type = Lisp_Object_Type::Invalid_Under_Construction;
object->sourceCodeLocation = nullptr;
object->userType = nullptr;
return object; return object;
} }
proc free_everything() -> void { proc free_everything() -> void {
object_memory.for_each([](Lisp_Object* lo){ object_memory.for_each([](Lisp_Object* lo){
free(lo->sourceCodeLocation); switch (lo->type) {
lo->sourceCodeLocation = 0;
switch (Memory::get_type(lo)) {
case Lisp_Object_Type::Function: { case Lisp_Object_Type::Function: {
lo->value.function->args.positional.symbols.dealloc(); lo->value.function->args.positional.symbols.dealloc();
lo->value.function->args.keyword.keywords.dealloc(); lo->value.function->args.keyword.keywords.dealloc();
@@ -141,9 +122,14 @@ namespace Slime::Memory {
hm->dealloc(); hm->dealloc();
}); });
for_hash_map(Globals::docs) {
free(value);
}
// free the exe dir: // free the exe dir:
free(Globals::load_path.data[0]); free(Globals::load_path.data[0]);
Globals::load_path.dealloc(); Globals::load_path.dealloc();
Globals::docs.dealloc();
Globals::Current_Execution::envi_stack.dealloc(); Globals::Current_Execution::envi_stack.dealloc();
Globals::Current_Execution::cs.dealloc(); Globals::Current_Execution::cs.dealloc();
Globals::Current_Execution::ams.dealloc(); Globals::Current_Execution::ams.dealloc();
@@ -212,6 +198,7 @@ namespace Slime::Memory {
Globals::Current_Execution::ats.alloc(); Globals::Current_Execution::ats.alloc();
Globals::Current_Execution::mes.alloc(); Globals::Current_Execution::mes.alloc();
Globals::docs.alloc();
Globals::load_path.alloc(); Globals::load_path.alloc();
add_to_load_path(exe_path); add_to_load_path(exe_path);
add_to_load_path("../bin/"); add_to_load_path("../bin/");
@@ -219,11 +206,11 @@ namespace Slime::Memory {
// init nil // init nil
try_void nil = create_lisp_object(); try_void nil = create_lisp_object();
set_type(nil, Lisp_Object_Type::Nil); nil->type = Lisp_Object_Type::Nil;
// init t // init t
try_void t = create_lisp_object(); try_void t = create_lisp_object();
set_type(t, Lisp_Object_Type::T); t->type = Lisp_Object_Type::T;
try_void Parser::standard_in = create_string("stdin"); try_void Parser::standard_in = create_string("stdin");
@@ -241,7 +228,7 @@ namespace Slime::Memory {
proc create_lisp_object(void* ptr) -> Lisp_Object* { proc create_lisp_object(void* ptr) -> Lisp_Object* {
Lisp_Object* node; Lisp_Object* node;
try node = create_lisp_object(); try node = create_lisp_object();
set_type(node, Lisp_Object_Type::Pointer); node->type = Lisp_Object_Type::Pointer;
node->value.pointer = ptr; node->value.pointer = ptr;
return node; return node;
} }
@@ -249,7 +236,7 @@ namespace Slime::Memory {
proc create_lisp_object_hash_map() -> Lisp_Object* { proc create_lisp_object_hash_map() -> Lisp_Object* {
Lisp_Object* node; Lisp_Object* node;
try node = create_lisp_object(); try node = create_lisp_object();
set_type(node, Lisp_Object_Type::HashMap); node->type = Lisp_Object_Type::HashMap;
node->value.hashMap = hashmap_memory.allocate(); node->value.hashMap = hashmap_memory.allocate();
node->value.hashMap->alloc(); node->value.hashMap->alloc();
return node; return node;
@@ -258,7 +245,7 @@ namespace Slime::Memory {
proc create_lisp_object(double number) -> Lisp_Object* { proc create_lisp_object(double number) -> Lisp_Object* {
Lisp_Object* node; Lisp_Object* node;
try node = create_lisp_object(); try node = create_lisp_object();
set_type(node, Lisp_Object_Type::Number); node->type = Lisp_Object_Type::Number;
node->value.number = number; node->value.number = number;
return node; return node;
} }
@@ -266,7 +253,7 @@ namespace Slime::Memory {
proc create_lisp_object(String str) -> Lisp_Object* { proc create_lisp_object(String str) -> Lisp_Object* {
Lisp_Object* node; Lisp_Object* node;
try node = create_lisp_object(); try node = create_lisp_object();
set_type(node, Lisp_Object_Type::String); node->type = Lisp_Object_Type::String;
node->value.string = str; node->value.string = str;
return node; return node;
} }
@@ -274,7 +261,7 @@ namespace Slime::Memory {
proc create_lisp_object(const char* str) -> Lisp_Object* { proc create_lisp_object(const char* str) -> Lisp_Object* {
Lisp_Object* node; Lisp_Object* node;
try node = create_lisp_object(); try node = create_lisp_object();
set_type(node, Lisp_Object_Type::String); node->type = Lisp_Object_Type::String;
node->value.string = create_string(str); node->value.string = create_string(str);
return node; return node;
} }
@@ -293,7 +280,7 @@ namespace Slime::Memory {
Lisp_Object* node; Lisp_Object* node;
try node = create_lisp_object(); try node = create_lisp_object();
set_type(node, Lisp_Object_Type::Vector); node->type = Lisp_Object_Type::Vector;
node->value.vector.length = length; node->value.vector.length = length;
try node->value.vector.data = allocate_vector(length); try node->value.vector.data = allocate_vector(length);
@@ -313,7 +300,7 @@ namespace Slime::Memory {
proc create_lisp_object_vector(Lisp_Object* e1) -> Lisp_Object* { proc create_lisp_object_vector(Lisp_Object* e1) -> Lisp_Object* {
Lisp_Object* node; Lisp_Object* node;
try node = create_lisp_object(); try node = create_lisp_object();
set_type(node, Lisp_Object_Type::Vector); node->type = Lisp_Object_Type::Vector;
node->value.vector.length = 1; node->value.vector.length = 1;
try node->value.vector.data = allocate_vector(1); try node->value.vector.data = allocate_vector(1);
@@ -326,7 +313,7 @@ namespace Slime::Memory {
proc create_lisp_object_vector(Lisp_Object* e1, Lisp_Object* e2) -> Lisp_Object* { proc create_lisp_object_vector(Lisp_Object* e1, Lisp_Object* e2) -> Lisp_Object* {
Lisp_Object* node; Lisp_Object* node;
try node = create_lisp_object(); try node = create_lisp_object();
set_type(node, Lisp_Object_Type::Vector); node->type = Lisp_Object_Type::Vector;
node->value.vector.length = 2; node->value.vector.length = 2;
try node->value.vector.data = allocate_vector(2); try node->value.vector.data = allocate_vector(2);
@@ -340,7 +327,7 @@ namespace Slime::Memory {
proc create_lisp_object_vector(Lisp_Object* e1, Lisp_Object* e2, Lisp_Object* e3) -> Lisp_Object* { proc create_lisp_object_vector(Lisp_Object* e1, Lisp_Object* e2, Lisp_Object* e3) -> Lisp_Object* {
Lisp_Object* node; Lisp_Object* node;
try node = create_lisp_object(); try node = create_lisp_object();
set_type(node, Lisp_Object_Type::Vector); node->type = Lisp_Object_Type::Vector;
node->value.vector.length = 3; node->value.vector.length = 3;
try node->value.vector.data = allocate_vector(3); try node->value.vector.data = allocate_vector(3);
@@ -355,7 +342,7 @@ namespace Slime::Memory {
inline proc _create_symbol(char* identifier) -> Lisp_Object* { inline proc _create_symbol(char* identifier) -> Lisp_Object* {
Lisp_Object* node; Lisp_Object* node;
try node = create_lisp_object(); try node = create_lisp_object();
set_type(node, Lisp_Object_Type::Symbol); node->type = Lisp_Object_Type::Symbol;
node->value.symbol = create_string(identifier); node->value.symbol = create_string(identifier);
global_symbol_table.set_object((char*)node->value.symbol.data, node); global_symbol_table.set_object((char*)node->value.symbol.data, node);
return node; return node;
@@ -374,7 +361,7 @@ namespace Slime::Memory {
inline proc _create_keyword(char* identifier) -> Lisp_Object* { inline proc _create_keyword(char* identifier) -> Lisp_Object* {
Lisp_Object* node; Lisp_Object* node;
try node = create_lisp_object(); try node = create_lisp_object();
set_type(node, Lisp_Object_Type::Keyword); node->type = Lisp_Object_Type::Keyword;
node->value.symbol = create_string(identifier); node->value.symbol = create_string(identifier);
global_keyword_table.set_object((char*)node->value.symbol.data, node); global_keyword_table.set_object((char*)node->value.symbol.data, node);
return node; return node;
@@ -390,34 +377,10 @@ namespace Slime::Memory {
return _create_keyword((char*)identifier); return _create_keyword((char*)identifier);
} }
// proc get_keyword(String keyword) -> Lisp_Object* {
// Lisp_Object* node = global_keyword_table.get_object(get_c_str(keyword));
// if (node)
// return (Lisp_Object*)node;
// try node = create_lisp_object();
// set_type(node, Lisp_Object_Type::Keyword);
// node->value.symbol = duplicate_string(keyword);
// global_keyword_table.set_object(get_c_str(keyword), node);
// return node;
// }
// proc get_keyword(const char* keyword) -> Lisp_Object* {
// if (auto ret = global_keyword_table.get_object((char*)keyword))
// return (Lisp_Object*)ret;
// else {
// String str;
// try str = Memory::create_string(keyword);
// return get_keyword(str);
// }
// }
proc create_lisp_object_cfunction(C_Function_Type type) -> Lisp_Object* { proc create_lisp_object_cfunction(C_Function_Type type) -> Lisp_Object* {
Lisp_Object* node; Lisp_Object* node;
try node = create_lisp_object(); try node = create_lisp_object();
set_type(node, Lisp_Object_Type::Function); node->type = Lisp_Object_Type::Function;
node->value.function = (Function*)malloc(sizeof(Function)); node->value.function = (Function*)malloc(sizeof(Function));
node->value.function->type.c_function_type = type; node->value.function->type.c_function_type = type;
node->value.function->args.keyword.keywords.alloc(); node->value.function->args.keyword.keywords.alloc();
@@ -430,7 +393,7 @@ namespace Slime::Memory {
proc create_lisp_object_function(Lisp_Function_Type ft) -> Lisp_Object* { proc create_lisp_object_function(Lisp_Function_Type ft) -> Lisp_Object* {
Lisp_Object* func; Lisp_Object* func;
try func = Memory::create_lisp_object(); try func = Memory::create_lisp_object();
Memory::set_type(func, Lisp_Object_Type::Function); func->type = Lisp_Object_Type::Function;
func->value.function = (Function*)malloc(sizeof(Function)); func->value.function = (Function*)malloc(sizeof(Function));
func->value.function->args.keyword.keywords.alloc(); func->value.function->args.keyword.keywords.alloc();
func->value.function->args.keyword.values.alloc(); func->value.function->args.keyword.values.alloc();
@@ -443,7 +406,7 @@ namespace Slime::Memory {
proc create_lisp_object_pair(Lisp_Object* first, Lisp_Object* rest) -> Lisp_Object* { proc create_lisp_object_pair(Lisp_Object* first, Lisp_Object* rest) -> Lisp_Object* {
Lisp_Object* node; Lisp_Object* node;
try node = create_lisp_object(); try node = create_lisp_object();
set_type(node, Lisp_Object_Type::Pair); node->type = Lisp_Object_Type::Pair;
// node->value.pair = new(Pair); // node->value.pair = new(Pair);
node->value.pair.first = first; node->value.pair.first = first;
node->value.pair.rest = rest; node->value.pair.rest = rest;
@@ -457,7 +420,7 @@ namespace Slime::Memory {
if (n == Memory::nil || n == Memory::t) { if (n == Memory::nil || n == Memory::t) {
return n; return n;
} else { } else {
Lisp_Object_Type type = Memory::get_type(n); Lisp_Object_Type type = n->type;
if (type == Lisp_Object_Type::Symbol || if (type == Lisp_Object_Type::Symbol ||
type == Lisp_Object_Type::Keyword || type == Lisp_Object_Type::Keyword ||
type == Lisp_Object_Type::Function) type == Lisp_Object_Type::Function)
@@ -480,7 +443,7 @@ namespace Slime::Memory {
} }
proc copy_lisp_object_except_pairs(Lisp_Object* n) -> Lisp_Object* { proc copy_lisp_object_except_pairs(Lisp_Object* n) -> Lisp_Object* {
if (get_type(n) == Lisp_Object_Type::Pair) if (n->type == Lisp_Object_Type::Pair)
return n; return n;
return copy_lisp_object(n); return copy_lisp_object(n);
} }
+11 -17
View File
@@ -3,12 +3,12 @@ namespace Slime {
struct String; struct String;
struct Environment; struct Environment;
enum struct Thread_Type { enum struct Thread_Type : u8 {
Main, Main,
GarbageCollection GarbageCollection
}; };
enum struct Lisp_Object_Type { enum struct Lisp_Object_Type : u8 {
Nil, Nil,
T, T,
Symbol, Symbol,
@@ -22,16 +22,11 @@ namespace Slime {
HashMap, HashMap,
// OwningPointer, // OwningPointer,
Function, Function,
Invalid_Garbage_Collected,
Invalid_Under_Construction
}; };
enum class Lisp_Object_Flags enum struct NasAction : u8 {
{
// bits 1 to 5 (including) will be reserved for the type
Already_Garbage_Collected = 1 << 5,
Under_Construction = 1 << 6,
};
enum struct NasAction {
And_Then_Action, And_Then_Action,
Macro_Write_Back, Macro_Write_Back,
Eval, Eval,
@@ -43,13 +38,13 @@ namespace Slime {
Pop_Environment Pop_Environment
}; };
enum struct Lisp_Function_Type { enum struct Lisp_Function_Type : u8 {
Lambda, // normal evaluation order Lambda, // normal evaluation order
Macro // args are not evaluated, a new programm is returned Macro // args are not evaluated, a new programm is returned
// that will be executed again // that will be executed again
}; };
enum struct C_Function_Type { enum struct C_Function_Type : u8 {
cFunction, // normal evaluation order cFunction, // normal evaluation order
cSpecial, // args are not evaluated, but result is returned cSpecial, // args are not evaluated, but result is returned
// as you would expect // as you would expect
@@ -57,7 +52,7 @@ namespace Slime {
// modified // modified
}; };
enum struct Log_Level { enum struct Log_Level : u8 {
None, None,
Critical, Critical,
Warning, Warning,
@@ -131,10 +126,9 @@ namespace Slime {
} body; } body;
}; };
#pragma pack(1)
struct Lisp_Object { struct Lisp_Object {
Source_Code_Location* sourceCodeLocation; Lisp_Object_Type type;
u64 flags;
Lisp_Object* userType; // keyword
union value { union value {
String symbol; // used for symbols and keywords String symbol; // used for symbols and keywords
double number; double number;
@@ -145,9 +139,9 @@ namespace Slime {
void* pointer; void* pointer;
Continuation* continuation; Continuation* continuation;
Hash_Map<Lisp_Object*, Lisp_Object*>* hashMap; Hash_Map<Lisp_Object*, Lisp_Object*>* hashMap;
~value() {}
} value; } value;
}; };
#pragma options align=reset
struct Error { struct Error {
Lisp_Object* position; Lisp_Object* position;
+3 -3
View File
@@ -65,9 +65,9 @@ namespace Slime {
} }
#define assert_equal_type(node, _type) \ #define assert_equal_type(node, _type) \
if (Memory::get_type(node) != _type) { \ if (node->type != _type) { \
print_assert_equal_fail( \ print_assert_equal_fail( \
lisp_object_type_to_string(Memory::get_type(node)), \ lisp_object_type_to_string(node->type), \
lisp_object_type_to_string(_type), char*, "%s"); \ lisp_object_type_to_string(_type), char*, "%s"); \
return fail; \ return fail; \
} \ } \
@@ -613,7 +613,7 @@ namespace Slime {
invoke_test(test_built_in_and); invoke_test(test_built_in_and);
invoke_test(test_built_in_or); invoke_test(test_built_in_or);
invoke_test(test_built_in_not); invoke_test(test_built_in_not);
invoke_test(test_built_in_type); // invoke_test(test_built_in_type);
printf("\n-- Memory management --\n"); printf("\n-- Memory management --\n");
invoke_test(test_singular_t_and_nil); invoke_test(test_singular_t_and_nil);