Fixed Memory Leaks. :)
This commit is contained in:
+29
-49
@@ -83,6 +83,7 @@ proc built_in_load(String* file_name) -> Lisp_Object* {
|
||||
try result = eval_expr(program->data[i]);
|
||||
}
|
||||
delete program;
|
||||
free(file_content);
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -315,18 +316,6 @@ proc load_built_ins_into_environment() -> void {
|
||||
define_special((define-syntax form (:doc "") . body), "TODO") {
|
||||
fetch(form, doc, body);
|
||||
|
||||
// static Lisp_Object *form_symbol = Memory::get_or_create_lisp_object_symbol("form");
|
||||
// static Lisp_Object *doc_symbol = Memory::get_or_create_lisp_object_symbol("doc");
|
||||
// static Lisp_Object *body_symbol = Memory::get_or_create_lisp_object_symbol("body");
|
||||
|
||||
// printf("\n\nin define-syntax:: envi stack depth: %d\n",
|
||||
// Globals::Current_Execution::envi_stack.next_index);
|
||||
// print_environment(get_current_environment());
|
||||
|
||||
// Lisp_Object *form = lookup_symbol(form_symbol, get_current_environment());
|
||||
// Lisp_Object *doc = lookup_symbol(doc_symbol, get_current_environment());
|
||||
// Lisp_Object *body = lookup_symbol(body_symbol, get_current_environment());
|
||||
|
||||
try assert_type(doc, Lisp_Object_Type::String);
|
||||
// if no doc string, we dont have to store it
|
||||
if (Memory::get_c_str(doc)[0] == '\0') {
|
||||
@@ -343,20 +332,19 @@ proc load_built_ins_into_environment() -> void {
|
||||
|
||||
// creating new lisp object and setting type
|
||||
Lisp_Object* func;
|
||||
try func = Memory::create_lisp_object();
|
||||
Memory::set_type(func, Lisp_Object_Type::Function);
|
||||
func->value.function.type = Function_Type::Macro;
|
||||
new((&func->value.function.args.positional.symbols)) Array_List<Environment*>(16);
|
||||
new((&func->value.function.args.keyword.keywords)) Array_List<Environment*>(16);
|
||||
new((&func->value.function.args.keyword.values)) Array_List<Environment*>(16);
|
||||
try func = Memory::create_lisp_object_function(Function_Type::Macro);
|
||||
|
||||
// Lisp_Object* func;
|
||||
// try func = Memory::create_lisp_object();
|
||||
// Memory::set_type(func, Lisp_Object_Type::Function);
|
||||
// func->value.function->type = Function_Type::Macro;
|
||||
if (doc) func->docstring = doc->value.string;
|
||||
|
||||
in_caller_env {
|
||||
// setting parent env
|
||||
func->value.function.parent_environment = get_current_environment();
|
||||
func->value.function->parent_environment = get_current_environment();
|
||||
create_arguments_from_lambda_list_and_inject(lambdalist, func);
|
||||
func->value.function.body = maybe_wrap_body_in_begin(body);
|
||||
func->value.function->body = maybe_wrap_body_in_begin(body);
|
||||
define_symbol(symbol, func);
|
||||
}
|
||||
return Memory::nil;
|
||||
@@ -394,21 +382,16 @@ proc load_built_ins_into_environment() -> void {
|
||||
|
||||
// creating new lisp object and setting type
|
||||
Lisp_Object* func;
|
||||
try func = Memory::create_lisp_object();
|
||||
Memory::set_type(func, Lisp_Object_Type::Function);
|
||||
func->value.function.type = Function_Type::Lambda;
|
||||
new((&func->value.function.args.positional.symbols)) Array_List<Environment*>(16);
|
||||
new((&func->value.function.args.keyword.keywords)) Array_List<Environment*>(16);
|
||||
new((&func->value.function.args.keyword.values)) Array_List<Environment*>(16);
|
||||
try func = Memory::create_lisp_object_function(Function_Type::Lambda);
|
||||
|
||||
if (doc)
|
||||
func->docstring = doc->value.string;
|
||||
|
||||
in_caller_env {
|
||||
// setting parent env
|
||||
func->value.function.parent_environment = get_current_environment();
|
||||
func->value.function->parent_environment = get_current_environment();
|
||||
create_arguments_from_lambda_list_and_inject(lambdalist, func);
|
||||
func->value.function.body = maybe_wrap_body_in_begin(body);
|
||||
func->value.function->body = maybe_wrap_body_in_begin(body);
|
||||
define_symbol(symbol, func);
|
||||
}
|
||||
|
||||
@@ -536,12 +519,10 @@ proc load_built_ins_into_environment() -> void {
|
||||
Lisp_Object* quasiquote_sym = Memory::get_or_create_lisp_object_symbol("quasiquote");
|
||||
Lisp_Object* unquote_sym = Memory::get_or_create_lisp_object_symbol("unquote");
|
||||
Lisp_Object* unquote_splicing_sym = Memory::get_or_create_lisp_object_symbol("unquote-splicing");
|
||||
/* recursive lambdas in lambdas yay!! */
|
||||
// NOTE(Felix): first we have to initialize the variable
|
||||
// with a garbage lambda, so that we can then overwrite it
|
||||
// a recursive lambda
|
||||
std::function<Lisp_Object*(Lisp_Object*)> unquoteSomeExpressions; // = [] (Lisp_Object* expr) -> Lisp_Object* {return nullptr;};
|
||||
unquoteSomeExpressions = [&] (Lisp_Object* expr) -> Lisp_Object* {
|
||||
const auto unquoteSomeExpressions = [&] (const auto & self, Lisp_Object* expr) -> Lisp_Object* {
|
||||
// if it is an atom, return it
|
||||
if (Memory::get_type(expr) != Lisp_Object_Type::Pair)
|
||||
return Memory::copy_lisp_object(expr);
|
||||
@@ -584,7 +565,7 @@ proc load_built_ins_into_environment() -> void {
|
||||
if (Memory::get_type(head->value.pair.first) == Lisp_Object_Type::Pair &&
|
||||
head->value.pair.first->value.pair.first == unquote_splicing_sym)
|
||||
{
|
||||
Lisp_Object* spliced = unquoteSomeExpressions(head->value.pair.first);
|
||||
Lisp_Object* spliced = self(self, head->value.pair.first);
|
||||
|
||||
if (spliced == Memory::nil) {
|
||||
head = head->value.pair.rest;
|
||||
@@ -615,7 +596,7 @@ proc load_built_ins_into_environment() -> void {
|
||||
try newPairHead->value.pair.rest = Memory::create_lisp_object_pair(Memory::nil, Memory::nil);
|
||||
newPairHead = newPairHead->value.pair.rest;
|
||||
}
|
||||
newPairHead->value.pair.first = unquoteSomeExpressions(head->value.pair.first);
|
||||
newPairHead->value.pair.first = self(self, head->value.pair.first);
|
||||
}
|
||||
|
||||
// if (Memory::get_type(head->value.pair.rest) != Lisp_Object_Type::Pair) {
|
||||
@@ -630,7 +611,7 @@ proc load_built_ins_into_environment() -> void {
|
||||
return newPair;
|
||||
};
|
||||
|
||||
expr = unquoteSomeExpressions(expr);
|
||||
expr = unquoteSomeExpressions(unquoteSomeExpressions, expr);
|
||||
return expr;
|
||||
};
|
||||
define_special((and . args), "TODO") {
|
||||
@@ -694,18 +675,17 @@ proc load_built_ins_into_environment() -> void {
|
||||
define_special((lambda args . body), "TODO") {
|
||||
fetch(args, body);
|
||||
|
||||
Lisp_Object* fun;
|
||||
try fun = Memory::create_lisp_object();
|
||||
Memory::set_type(fun, Lisp_Object_Type::Function);
|
||||
fun->value.function.type = Function_Type::Lambda;
|
||||
// creating new lisp object and setting type
|
||||
Lisp_Object* func;
|
||||
try func = Memory::create_lisp_object_function(Function_Type::Lambda);
|
||||
|
||||
in_caller_env {
|
||||
fun->value.function.parent_environment = get_current_environment();
|
||||
func->value.function->parent_environment = get_current_environment();
|
||||
}
|
||||
|
||||
try create_arguments_from_lambda_list_and_inject(args, fun);
|
||||
fun->value.function.body = maybe_wrap_body_in_begin(body);
|
||||
return fun;
|
||||
try create_arguments_from_lambda_list_and_inject(args, func);
|
||||
func->value.function->body = maybe_wrap_body_in_begin(body);
|
||||
return func;
|
||||
};
|
||||
// define_special((special-lambda args . body), "TODO") {
|
||||
// fetch(args, body);
|
||||
@@ -713,14 +693,14 @@ proc load_built_ins_into_environment() -> void {
|
||||
// Lisp_Object* fun;
|
||||
// try fun = Memory::create_lisp_object();
|
||||
// Memory::set_type(fun, Lisp_Object_Type::Function);
|
||||
// fun->value.function.type = Function_Type::Special_Lambda;
|
||||
// fun->value.function->type = Function_Type::Special_Lambda;
|
||||
|
||||
// in_caller_env {
|
||||
// fun->value.function.parent_environment = get_current_environment();
|
||||
// fun->value.function->parent_environment = get_current_environment();
|
||||
// }
|
||||
|
||||
// try create_arguments_from_lambda_list_and_inject(args, fun);
|
||||
// fun->value.function.body = maybe_wrap_body_in_begin(body);
|
||||
// fun->value.function->body = maybe_wrap_body_in_begin(body);
|
||||
// return fun;
|
||||
// };
|
||||
define((apply fun args), "TODO") {
|
||||
@@ -834,7 +814,7 @@ proc load_built_ins_into_environment() -> void {
|
||||
case Lisp_Object_Type::Continuation: return Memory::get_or_create_lisp_object_keyword("continuation");
|
||||
case Lisp_Object_Type::CFunction: return Memory::get_or_create_lisp_object_keyword("cfunction");
|
||||
case Lisp_Object_Type::Function: {
|
||||
Function* fun = &n->value.function;
|
||||
Function* fun = n->value.function;
|
||||
if (fun->type == Function_Type::Lambda)
|
||||
return Memory::get_or_create_lisp_object_keyword("lambda");
|
||||
// else if (fun->type == Function_Type::Special_Lambda)
|
||||
@@ -892,7 +872,7 @@ proc load_built_ins_into_environment() -> void {
|
||||
{
|
||||
Arguments* args;
|
||||
if (Memory::get_type(val) == Lisp_Object_Type::Function)
|
||||
args = &val->value.function.args;
|
||||
args = &val->value.function->args;
|
||||
else
|
||||
args = &val->value.cFunction->args;
|
||||
|
||||
@@ -941,10 +921,10 @@ proc load_built_ins_into_environment() -> void {
|
||||
try assert_type(n, Lisp_Object_Type::Function);
|
||||
|
||||
puts("body:\n");
|
||||
print(n->value.function.body);
|
||||
print(n->value.function->body);
|
||||
puts("\n");
|
||||
printf("parent_env: %lld\n",
|
||||
(long long)n->value.function.parent_environment);
|
||||
(long long)n->value.function->parent_environment);
|
||||
|
||||
return Memory::nil;
|
||||
};
|
||||
|
||||
@@ -101,11 +101,14 @@
|
||||
)(__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
// NOTE(Felix): we have to copy the string because we need
|
||||
// it to be mutable for the parser to work, because the
|
||||
// parser relys on being able to temporaily put in markers
|
||||
// in the code
|
||||
// NOTE(Felix): we have to copy the string because we need it to be
|
||||
// mutable for the parser to work, 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
|
||||
#define _define_helper(def, docs, special) \
|
||||
Parser::parser_file = file_name_built_ins; \
|
||||
Parser::parser_line = __LINE__; \
|
||||
Parser::parser_col = 0; \
|
||||
auto label(params,__LINE__) = Parser::parse_single_expression( \
|
||||
Memory::get_c_str(Memory::create_string(#def))); \
|
||||
if_error_log_location_and_return(); \
|
||||
@@ -115,13 +118,9 @@
|
||||
auto label(sfun,__LINE__) = Memory::create_lisp_object_cfunction(special); \
|
||||
create_arguments_from_lambda_list_and_inject(label(params,__LINE__)->value.pair.rest, label(sfun,__LINE__)); \
|
||||
if_error_log_location_and_return(); \
|
||||
label(sfun,__LINE__)->sourceCodeLocation = new(Source_Code_Location); \
|
||||
label(sfun,__LINE__)->sourceCodeLocation->file = file_name_built_ins; \
|
||||
label(sfun,__LINE__)->sourceCodeLocation->line = __LINE__; \
|
||||
label(sfun,__LINE__)->sourceCodeLocation->column = 0; \
|
||||
label(sfun,__LINE__)->docstring = Memory::create_string(docs); \
|
||||
define_symbol(label(sym,__LINE__), label(sfun,__LINE__)); \
|
||||
label(sfun,__LINE__)->value.cFunction->body = (std::function<Lisp_Object* ()>)[&]() -> Lisp_Object*
|
||||
label(sfun,__LINE__)->value.cFunction->body = []() -> Lisp_Object*
|
||||
|
||||
#define define(def, docs) _define_helper(def, docs, false)
|
||||
#define define_special(def, docs) _define_helper(def, docs, true)
|
||||
|
||||
+1
-1
@@ -30,7 +30,7 @@ proc create_error(const char* c_func_name,const char* c_file_name, int c_file_li
|
||||
}
|
||||
// visualize_lisp_machine();
|
||||
using Globals::error;
|
||||
error = new(Error);
|
||||
error = (Error*)malloc(sizeof(Error)) ;
|
||||
error->type = type;
|
||||
error->message = message;
|
||||
|
||||
|
||||
+23
-14
@@ -17,8 +17,8 @@ proc create_extended_environment_for_function_application(
|
||||
new_env = Memory::create_child_environment(get_root_environment());
|
||||
arg_spec = &function->value.cFunction->args;
|
||||
} else {
|
||||
new_env = Memory::create_child_environment(function->value.function.parent_environment);
|
||||
arg_spec = &function->value.function.args;
|
||||
new_env = Memory::create_child_environment(function->value.function->parent_environment);
|
||||
arg_spec = &function->value.function->args;
|
||||
}
|
||||
if (should_evaluate) {
|
||||
try arguments = eval_arguments(arguments);
|
||||
@@ -51,7 +51,7 @@ proc create_extended_environment_for_function_application(
|
||||
// NOTE(Felix): We have to copy all the arguments,
|
||||
// otherwise we change the program code. XXX(Felix): T C
|
||||
// functions we pass by reference...
|
||||
try_void sym = arg_spec->positional.symbols.data[i];
|
||||
sym = arg_spec->positional.symbols.data[i];
|
||||
if (is_c_function) {
|
||||
define_symbol(sym, arguments->value.pair.first);
|
||||
} else {
|
||||
@@ -240,7 +240,7 @@ proc apply_arguments_to_function(Lisp_Object* arguments, Lisp_Object* function,
|
||||
if (Memory::get_type(function) == Lisp_Object_Type::CFunction)
|
||||
try result = function->value.cFunction->body();
|
||||
else // if lisp function
|
||||
try result = eval_expr(function->value.function.body);
|
||||
try result = eval_expr(function->value.function->body);
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -256,16 +256,14 @@ proc create_arguments_from_lambda_list_and_inject(Lisp_Object* arguments, Lisp_O
|
||||
if (Memory::get_type(function) == Lisp_Object_Type::CFunction) {
|
||||
result = &function->value.cFunction->args;
|
||||
} else {
|
||||
result = &function->value.function.args;
|
||||
result = &function->value.function->args;
|
||||
}
|
||||
|
||||
::new (&result->positional.symbols) Array_List<Lisp_Object*>;
|
||||
::new (&result->keyword.keywords) Array_List<Lisp_Object*>;
|
||||
::new (&result->keyword.values) Array_List<Lisp_Object*>;
|
||||
// ::new (&result->positional.symbols) Array_List<Lisp_Object*>;
|
||||
// ::new (&result->keyword.keywords) Array_List<Lisp_Object*>;
|
||||
// ::new (&result->keyword.values) Array_List<Lisp_Object*>;
|
||||
|
||||
// first init the fields
|
||||
// result->positional = create_positional_argument_list(16);
|
||||
// result->keyword = create_keyword_argument_list(16);
|
||||
result->rest = nullptr;
|
||||
|
||||
// okay let's try to read some positional arguments
|
||||
@@ -357,6 +355,11 @@ proc list_length(Lisp_Object* node) -> int {
|
||||
return 0;
|
||||
}
|
||||
|
||||
proc copy_scl(Source_Code_Location*) -> Source_Code_Location* {
|
||||
// TODO(Felix):
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
proc eval_arguments(Lisp_Object* arguments) -> Lisp_Object* {
|
||||
profile_this;
|
||||
// int my_out_arguments_length = 0;
|
||||
@@ -374,7 +377,8 @@ proc eval_arguments(Lisp_Object* arguments) -> Lisp_Object* {
|
||||
while (Memory::get_type(current_head) == Lisp_Object_Type::Pair) {
|
||||
try evaluated_arguments_head->value.pair.first = eval_expr(current_head->value.pair.first);
|
||||
|
||||
evaluated_arguments_head->value.pair.first->sourceCodeLocation = current_head->value.pair.first->sourceCodeLocation;
|
||||
evaluated_arguments_head->value.pair.first->sourceCodeLocation =
|
||||
copy_scl(current_head->value.pair.first->sourceCodeLocation);
|
||||
current_head = current_head->value.pair.rest;
|
||||
|
||||
if (Memory::get_type(current_head) == Lisp_Object_Type::Pair) {
|
||||
@@ -451,7 +455,7 @@ proc eval_expr(Lisp_Object* node) -> Lisp_Object* {
|
||||
try result = apply_arguments_to_function(
|
||||
arguments,
|
||||
lispOperator,
|
||||
lispOperator->value.function.type == Function_Type::Lambda);
|
||||
lispOperator->value.function->type == Function_Type::Lambda);
|
||||
|
||||
// NOTE(Felix): The parser does not understnad (import ..)
|
||||
// so it cannot expand imported macros at read time
|
||||
@@ -460,15 +464,20 @@ proc eval_expr(Lisp_Object* node) -> Lisp_Object* {
|
||||
// stray macros fying around, in that case, we expand them
|
||||
// and bake them in, so they do not have to be expanded
|
||||
// later again. We will call this "lazy macro expansion"
|
||||
if (lispOperator->value.function.type == Function_Type::Macro) {
|
||||
if (lispOperator->value.function->type == Function_Type::Macro) {
|
||||
// bake in the macro expansion:
|
||||
*node = *result;
|
||||
*node = *Memory::copy_lisp_object(result);
|
||||
result->sourceCodeLocation = copy_scl(result->sourceCodeLocation);
|
||||
// eval again because macro
|
||||
try result = eval_expr(result);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
create_generic_error("The first element of the pair was not a function but: %s",
|
||||
Lisp_Object_Type_to_string(Memory::get_type(lispOperator)));
|
||||
return nullptr;
|
||||
}
|
||||
default: {
|
||||
create_generic_error("%s is not a function.", Lisp_Object_Type_to_string(Memory::get_type(node)));
|
||||
|
||||
+3
-3
@@ -46,10 +46,10 @@ namespace GC {
|
||||
// NOTE(Felix): We dont have to mark the symbols, keywords
|
||||
// for parameter names, as symbols and keywords are never
|
||||
// garbage collected
|
||||
maybe_mark(node->value.function.parent_environment);
|
||||
maybe_mark(node->value.function.body);
|
||||
maybe_mark(node->value.function->parent_environment);
|
||||
maybe_mark(node->value.function->body);
|
||||
// mark the default arguemnt values:
|
||||
for (auto it : node->value.function.args.keyword.values) {
|
||||
for (auto it : node->value.function->args.keyword.values) {
|
||||
if (it)
|
||||
maybe_mark(it);
|
||||
}
|
||||
|
||||
+29
-32
@@ -64,9 +64,8 @@ proc escape_string(char* in) -> char* {
|
||||
return ret;
|
||||
}
|
||||
|
||||
proc unescape_string(char* in) -> bool {
|
||||
if (!in)
|
||||
return true;
|
||||
proc unescape_string(char* in) -> int {
|
||||
if (!in) return 0;
|
||||
|
||||
char *out = in, *p = in;
|
||||
const char *int_err = nullptr;
|
||||
@@ -117,9 +116,7 @@ proc unescape_string(char* in) -> bool {
|
||||
|
||||
/* Set the end of string. */
|
||||
*out = '\0';
|
||||
if (int_err)
|
||||
return false;
|
||||
return true;
|
||||
return out - in;
|
||||
}
|
||||
|
||||
proc read_entire_file(char* filename) -> char* {
|
||||
@@ -358,11 +355,11 @@ proc print(Lisp_Object* node, bool print_repr, FILE* file) -> void {
|
||||
fprintf(file, "[%s]", Memory::get_c_str(node->userType->value.symbol.identifier));
|
||||
break;
|
||||
}
|
||||
if (node->value.function.type == Function_Type::Lambda)
|
||||
if (node->value.function->type == Function_Type::Lambda)
|
||||
fputs("[lambda]", file);
|
||||
// else if (node->value.function.type == Function_Type::Special_Lambda)
|
||||
// else if (node->value.function->type == Function_Type::Special_Lambda)
|
||||
// fputs("[special-lambda]", file);
|
||||
else if (node->value.function.type == Function_Type::Macro)
|
||||
else if (node->value.function->type == Function_Type::Macro)
|
||||
fputs("[macro]", file);
|
||||
else
|
||||
assert(false);
|
||||
@@ -372,33 +369,33 @@ proc print(Lisp_Object* node, bool print_repr, FILE* file) -> void {
|
||||
|
||||
// first check if it is a quotation form, in that case we want
|
||||
// to print it prettier
|
||||
if (Memory::get_type(head->value.pair.first) == Lisp_Object_Type::Symbol) {
|
||||
String* identifier = head->value.pair.first->value.symbol.identifier;
|
||||
// if (Memory::get_type(head->value.pair.first) == Lisp_Object_Type::Symbol) {
|
||||
// String* identifier = head->value.pair.first->value.symbol.identifier;
|
||||
|
||||
|
||||
auto symbol = head->value.pair.first;
|
||||
auto quote_sym = Memory::get_or_create_lisp_object_symbol("quote");
|
||||
auto unquote_sym = Memory::get_or_create_lisp_object_symbol("unquote");
|
||||
auto quasiquote_sym = Memory::get_or_create_lisp_object_symbol("quasiquote");
|
||||
if (symbol == quote_sym || symbol == unquote_sym)
|
||||
{
|
||||
putc(symbol == quote_sym
|
||||
? '\''
|
||||
: ',', file);
|
||||
// auto symbol = head->value.pair.first;
|
||||
// auto quote_sym = Memory::get_or_create_lisp_object_symbol("quote");
|
||||
// auto unquote_sym = Memory::get_or_create_lisp_object_symbol("unquote");
|
||||
// auto quasiquote_sym = Memory::get_or_create_lisp_object_symbol("quasiquote");
|
||||
// if (symbol == quote_sym || symbol == unquote_sym)
|
||||
// {
|
||||
// putc(symbol == quote_sym
|
||||
// ? '\''
|
||||
// : ',', file);
|
||||
|
||||
assert_type(head->value.pair.rest, Lisp_Object_Type::Pair);
|
||||
assert(head->value.pair.rest->value.pair.rest == Memory::nil);
|
||||
// assert_type(head->value.pair.rest, Lisp_Object_Type::Pair);
|
||||
// assert(head->value.pair.rest->value.pair.rest == Memory::nil);
|
||||
|
||||
print(head->value.pair.rest->value.pair.first, print_repr, file);
|
||||
break;
|
||||
}
|
||||
else if (symbol == quasiquote_sym) {
|
||||
putc('`', file);
|
||||
assert_type(head->value.pair.rest, Lisp_Object_Type::Pair);
|
||||
print(head->value.pair.rest->value.pair.first, print_repr, file);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// print(head->value.pair.rest->value.pair.first, print_repr, file);
|
||||
// break;
|
||||
// }
|
||||
// else if (symbol == quasiquote_sym) {
|
||||
// putc('`', file);
|
||||
// assert_type(head->value.pair.rest, Lisp_Object_Type::Pair);
|
||||
// print(head->value.pair.rest->value.pair.first, print_repr, file);
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
|
||||
putc('(', file);
|
||||
|
||||
|
||||
+4
-3
@@ -3,7 +3,6 @@
|
||||
|
||||
#define _CRTDBG_MAP_ALLOC
|
||||
#include <stdlib.h>
|
||||
#include <crtdbg.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
@@ -11,12 +10,14 @@
|
||||
#include <cmath>
|
||||
#include <ctype.h>
|
||||
#include <stdarg.h>
|
||||
#include <functional>
|
||||
#include <errno.h>
|
||||
#include <new>
|
||||
// #include <functional>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# include <crtdbg.h>
|
||||
# include <direct.h>
|
||||
# include <windows.h>
|
||||
|
||||
#else
|
||||
# include <unistd.h>
|
||||
# include <signal.h>
|
||||
|
||||
+19
-1
@@ -41,7 +41,25 @@ proc append_to_keyword_argument_list(Keyword_Arguments* args,
|
||||
}
|
||||
|
||||
Lisp_Object::~Lisp_Object() {
|
||||
if (Memory::get_type(this) == Lisp_Object_Type::HashMap) {
|
||||
free(sourceCodeLocation);
|
||||
sourceCodeLocation = 0;
|
||||
|
||||
switch (Memory::get_type(this)) {
|
||||
case Lisp_Object_Type::HashMap: {
|
||||
this->value.hashMap.~Hash_Map();
|
||||
} break;
|
||||
case Lisp_Object_Type::CFunction: {
|
||||
this->value.cFunction->args.positional.symbols.~Array_List();
|
||||
this->value.cFunction->args.keyword.keywords.~Array_List();
|
||||
this->value.cFunction->args.keyword.values.~Array_List();
|
||||
delete this->value.cFunction;
|
||||
} break;
|
||||
case Lisp_Object_Type::Function:{
|
||||
this->value.function->args.positional.symbols.~Array_List();
|
||||
this->value.function->args.keyword.keywords.~Array_List();
|
||||
this->value.function->args.keyword.values.~Array_List();
|
||||
delete this->value.function;
|
||||
} break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
+3
-2
@@ -1,13 +1,14 @@
|
||||
#include "libslime.cpp"
|
||||
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
if (argc > 1) {
|
||||
if (Slime::string_equal(argv[1], "--run-tests")) {
|
||||
int res = Slime::run_all_tests();
|
||||
Slime::Memory::free_everything();
|
||||
// Slime::interprete_file((char*)"generate-docs.slime");
|
||||
|
||||
#ifdef _MSC_VER
|
||||
_CrtDumpMemoryLeaks();
|
||||
#endif
|
||||
return res ? 0 : 1;
|
||||
}
|
||||
|
||||
|
||||
+34
-15
@@ -11,12 +11,12 @@ namespace Memory {
|
||||
// ------------------
|
||||
// lisp_objects
|
||||
// ------------------
|
||||
Bucket_Allocator<Lisp_Object, 1024> object_memory;
|
||||
Bucket_Allocator<Lisp_Object> object_memory(1024, 8);
|
||||
|
||||
// ------------------
|
||||
// environments
|
||||
// ------------------
|
||||
Bucket_Allocator<Environment, 1024> environment_memory;
|
||||
Bucket_Allocator<Environment> environment_memory(1024, 8);
|
||||
|
||||
// ------------------
|
||||
// strings
|
||||
@@ -146,6 +146,12 @@ namespace Memory {
|
||||
|
||||
proc free_everything() -> void {
|
||||
free(string_memory);
|
||||
object_memory.for_each([](Lisp_Object* lo){
|
||||
lo->~Lisp_Object();
|
||||
});
|
||||
environment_memory.for_each([](Environment* env){
|
||||
env->~Environment();
|
||||
});
|
||||
}
|
||||
|
||||
proc init(int sms) -> void {
|
||||
@@ -183,18 +189,24 @@ namespace Memory {
|
||||
global_keyword_table.~Hash_Map();
|
||||
file_to_env_map.~Hash_Map();
|
||||
|
||||
::new(&global_symbol_table) Hash_Map<char*, Lisp_Object*>;
|
||||
::new(&global_keyword_table) Hash_Map<char*, Lisp_Object*>;
|
||||
::new(&file_to_env_map) Hash_Map<char*, Lisp_Object*>;
|
||||
new(&global_symbol_table) Hash_Map<char*, Lisp_Object*>;
|
||||
new(&global_keyword_table) Hash_Map<char*, Lisp_Object*>;
|
||||
new(&file_to_env_map) Hash_Map<char*, Lisp_Object*>;
|
||||
|
||||
try_void Parser::standard_in = create_string("stdin");
|
||||
|
||||
object_memory.for_each([](Lisp_Object* lo){
|
||||
lo->~Lisp_Object();
|
||||
});
|
||||
environment_memory.for_each([](Environment* env){
|
||||
env->~Environment();
|
||||
});
|
||||
|
||||
object_memory.~Bucket_Allocator();
|
||||
// environment_memory.~Bucket_Allocator();
|
||||
environment_memory.~Bucket_Allocator();
|
||||
|
||||
::new(&object_memory) Bucket_Allocator<Lisp_Object, 1024>;
|
||||
::new(&environment_memory) Bucket_Allocator<Environment, 1024>;
|
||||
::new(&object_memory) Bucket_Allocator<Lisp_Object>(1024, 8);
|
||||
::new(&environment_memory) Bucket_Allocator<Environment>(1024, 8);
|
||||
|
||||
next_free_spot_in_string_memory = string_memory;
|
||||
|
||||
@@ -342,16 +354,20 @@ namespace Memory {
|
||||
Lisp_Object* node;
|
||||
try node = create_lisp_object();
|
||||
set_type(node, Lisp_Object_Type::CFunction);
|
||||
// node->value.lambdaWrapper = new Lambda_Wrapper(function);
|
||||
node->value.cFunction = new(cFunction);
|
||||
node->value.cFunction->args = {};
|
||||
new((&node->value.cFunction->args.positional.symbols)) Array_List<Environment*>(16);
|
||||
new((&node->value.cFunction->args.keyword.keywords)) Array_List<Environment*>(16);
|
||||
new((&node->value.cFunction->args.keyword.values)) Array_List<Environment*>(16);
|
||||
node->value.cFunction = new cFunction;
|
||||
node->value.cFunction->is_special_form = is_special;
|
||||
return node;
|
||||
}
|
||||
|
||||
proc create_lisp_object_function(Function_Type ft) -> Lisp_Object* {
|
||||
Lisp_Object* func;
|
||||
try func = Memory::create_lisp_object();
|
||||
Memory::set_type(func, Lisp_Object_Type::Function);
|
||||
func->value.function = new Function;
|
||||
func->value.function->type = ft;
|
||||
return func;
|
||||
}
|
||||
|
||||
proc create_lisp_object_pair(Lisp_Object* first, Lisp_Object* rest) -> Lisp_Object* {
|
||||
Lisp_Object* node;
|
||||
try node = create_lisp_object();
|
||||
@@ -368,7 +384,9 @@ namespace Memory {
|
||||
// we don't copy singleton objects
|
||||
if (n == Memory::nil || n == Memory::t ||
|
||||
Memory::get_type(n) == Lisp_Object_Type::Symbol ||
|
||||
Memory::get_type(n) == Lisp_Object_Type::Keyword)
|
||||
Memory::get_type(n) == Lisp_Object_Type::Keyword ||
|
||||
Memory::get_type(n) == Lisp_Object_Type::Function ||
|
||||
Memory::get_type(n) == Lisp_Object_Type::CFunction)
|
||||
{
|
||||
return n;
|
||||
}
|
||||
@@ -376,6 +394,7 @@ namespace Memory {
|
||||
Lisp_Object* target;
|
||||
try target = create_lisp_object();
|
||||
*target = *n;
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
|
||||
+17
-14
@@ -31,7 +31,7 @@ namespace Parser {
|
||||
}
|
||||
|
||||
proc inject_scl(Lisp_Object* lo) -> void {
|
||||
lo->sourceCodeLocation = new(Source_Code_Location);
|
||||
lo->sourceCodeLocation = (Source_Code_Location*)malloc(sizeof(Source_Code_Location));
|
||||
lo->sourceCodeLocation->file = parser_file;
|
||||
lo->sourceCodeLocation->line = parser_line;
|
||||
lo->sourceCodeLocation->column = parser_col;
|
||||
@@ -65,7 +65,6 @@ namespace Parser {
|
||||
++parser_col;
|
||||
++(*index_in_text);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
proc eat_until_code(char* text, int* index_in_text) -> void {
|
||||
@@ -120,7 +119,7 @@ namespace Parser {
|
||||
Lisp_Object* ret;
|
||||
try ret = Memory::create_lisp_object_number(number);
|
||||
|
||||
inject_scl(ret);
|
||||
// inject_scl(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -132,7 +131,7 @@ namespace Parser {
|
||||
Lisp_Object* ret;
|
||||
try ret = Memory::get_or_create_lisp_object_keyword(str_keyword);
|
||||
|
||||
inject_scl(ret);
|
||||
// inject_scl(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -142,7 +141,7 @@ namespace Parser {
|
||||
Lisp_Object* ret;
|
||||
try ret = Memory::get_or_create_lisp_object_symbol(str_symbol);
|
||||
|
||||
inject_scl(ret);
|
||||
// inject_scl(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -157,7 +156,7 @@ namespace Parser {
|
||||
Lisp_Object* ret;
|
||||
try ret = Memory::create_lisp_object_string(
|
||||
Memory::create_string("", 0));
|
||||
inject_scl(ret);
|
||||
// inject_scl(ret);
|
||||
|
||||
// plus one because we want to go after the quotes
|
||||
*index_in_text += 1;
|
||||
@@ -169,10 +168,10 @@ namespace Parser {
|
||||
// okay so the first letter was not actually closing the string...
|
||||
int string_length = 0;
|
||||
bool escaping = false;
|
||||
while (!(text[*index_in_text+string_length] == '"' && !escaping))
|
||||
{
|
||||
if (escaping)
|
||||
while (escaping || text[*index_in_text+string_length] != '"') {
|
||||
if (escaping) {
|
||||
escaping = false;
|
||||
}
|
||||
else
|
||||
if (text[*index_in_text+string_length] == '\\')
|
||||
escaping = true;
|
||||
@@ -186,9 +185,10 @@ namespace Parser {
|
||||
// NOTE(Felix): Tactic: Through unescaping the string will
|
||||
// only get shorter, so we replace it inplace and later jump
|
||||
// to the original end of the string.
|
||||
try unescape_string(text+(*index_in_text));
|
||||
int new_len;
|
||||
try new_len = unescape_string(text+(*index_in_text));
|
||||
|
||||
String* string = Memory::create_string("", string_length);
|
||||
String* string = Memory::create_string("", new_len);
|
||||
|
||||
// TODO(Felix): manually copy to parse control sequences
|
||||
// correctly without the need to unescape the string, also
|
||||
@@ -196,6 +196,7 @@ namespace Parser {
|
||||
// characters since last new line so we can update the parser
|
||||
// location more easily
|
||||
strcpy(&string->data, text+(*index_in_text));
|
||||
// printf("------ %s\n", &string->data);
|
||||
|
||||
text[*index_in_text+string_length] = '"';
|
||||
|
||||
@@ -218,7 +219,7 @@ namespace Parser {
|
||||
Lisp_Object* ret;
|
||||
try ret = Memory::create_lisp_object_string(string);
|
||||
|
||||
inject_scl(ret);
|
||||
// inject_scl(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -285,7 +286,8 @@ namespace Parser {
|
||||
try ret = Memory::create_list(Memory::get_or_create_lisp_object_symbol("unquote-splicing"), result);
|
||||
}
|
||||
|
||||
if (ret) inject_scl(ret);
|
||||
// if (ret && ret != Memory::nil && ret != Memory::t)
|
||||
// inject_scl(ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -313,7 +315,7 @@ namespace Parser {
|
||||
Lisp_Object* expression = head;
|
||||
|
||||
while (true) {
|
||||
inject_scl(head);
|
||||
// inject_scl(head);
|
||||
if (text[*index_in_text] == '(' ||
|
||||
text[*index_in_text] == '\''||
|
||||
text[*index_in_text] == '`' ||
|
||||
@@ -363,6 +365,7 @@ namespace Parser {
|
||||
} else {
|
||||
try head->value.pair.rest = Memory::create_lisp_object_pair(Memory::nil, Memory::nil);
|
||||
head = head->value.pair.rest;
|
||||
// inject_scl(head);
|
||||
}
|
||||
}
|
||||
return expression;
|
||||
|
||||
+2
-2
@@ -118,7 +118,7 @@ struct Function {
|
||||
};
|
||||
|
||||
struct cFunction {
|
||||
std::function<Lisp_Object* ()> body;
|
||||
Lisp_Object* (*body)();
|
||||
Arguments args;
|
||||
bool is_special_form;
|
||||
};
|
||||
@@ -134,7 +134,7 @@ struct Lisp_Object {
|
||||
String* string;
|
||||
Pair pair;
|
||||
Vector vector;
|
||||
Function function;
|
||||
Function* function;
|
||||
cFunction* cFunction;
|
||||
void* pointer;
|
||||
Continuation continuation;
|
||||
|
||||
+1
-1
@@ -656,7 +656,7 @@ proc run_all_tests() -> bool {
|
||||
invoke_test_script("hashmaps");
|
||||
invoke_test_script("singular_imports");
|
||||
|
||||
// Memory::print_status();
|
||||
// // Memory::print_status();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user