some memory management
This commit is contained in:
Binary file not shown.
@@ -1,6 +0,0 @@
|
|||||||
void assert_type (Lisp_Object* node, Lisp_Object_Type type) {
|
|
||||||
if (!node)
|
|
||||||
create_error(Error_Type::Unknown_Error, nullptr);
|
|
||||||
if (node->type == type) return;
|
|
||||||
create_error(Error_Type::Type_Missmatch, node->sourceCodeLocation);
|
|
||||||
}
|
|
||||||
+69
-77
@@ -1,9 +1,3 @@
|
|||||||
Lisp_Object* eval_arguments(Lisp_Object* arguments, Environment* env, int *out_arguments_length);
|
|
||||||
int list_length(Lisp_Object* node);
|
|
||||||
Lisp_Object* eval_expr(Lisp_Object* node, Environment* env);
|
|
||||||
bool is_truthy (Lisp_Object* expression, Environment* env);
|
|
||||||
void parse_argument_list(Lisp_Object* arguments, Function* function);
|
|
||||||
|
|
||||||
bool lisp_object_equal(Lisp_Object* n1, Lisp_Object* n2) {
|
bool lisp_object_equal(Lisp_Object* n1, Lisp_Object* n2) {
|
||||||
if (n1 == n2)
|
if (n1 == n2)
|
||||||
return true;
|
return true;
|
||||||
@@ -55,17 +49,17 @@ Lisp_Object* built_in_equals(Lisp_Object* arguments, Environment* env) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (arguments->type == Lisp_Object_Type::Nil)
|
if (arguments->type == Lisp_Object_Type::Nil)
|
||||||
return create_lisp_object_t();
|
return Memory::create_lisp_object_t();
|
||||||
|
|
||||||
Lisp_Object* first = arguments->value.pair->first;
|
Lisp_Object* first = arguments->value.pair->first;
|
||||||
|
|
||||||
while (arguments->type == Lisp_Object_Type::Pair) {
|
while (arguments->type == Lisp_Object_Type::Pair) {
|
||||||
if (!lisp_object_equal(arguments->value.pair->first, first))
|
if (!lisp_object_equal(arguments->value.pair->first, first))
|
||||||
return create_lisp_object_nil();
|
return Memory::create_lisp_object_nil();
|
||||||
arguments = arguments->value.pair->rest;
|
arguments = arguments->value.pair->rest;
|
||||||
}
|
}
|
||||||
|
|
||||||
return create_lisp_object_t();
|
return Memory::create_lisp_object_t();
|
||||||
}
|
}
|
||||||
|
|
||||||
Lisp_Object* built_in_greater(Lisp_Object* arguments, Environment* env) {
|
Lisp_Object* built_in_greater(Lisp_Object* arguments, Environment* env) {
|
||||||
@@ -82,13 +76,13 @@ Lisp_Object* built_in_greater(Lisp_Object* arguments, Environment* env) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (arguments->value.pair->first->value.number->value >= last_number)
|
if (arguments->value.pair->first->value.number->value >= last_number)
|
||||||
return create_lisp_object_nil();
|
return Memory::create_lisp_object_nil();
|
||||||
|
|
||||||
last_number = arguments->value.pair->first->value.number->value;
|
last_number = arguments->value.pair->first->value.number->value;
|
||||||
arguments = arguments->value.pair->rest;
|
arguments = arguments->value.pair->rest;
|
||||||
}
|
}
|
||||||
|
|
||||||
return create_lisp_object_t();
|
return Memory::create_lisp_object_t();
|
||||||
}
|
}
|
||||||
|
|
||||||
Lisp_Object* built_in_greater_equal(Lisp_Object* arguments, Environment* env) {
|
Lisp_Object* built_in_greater_equal(Lisp_Object* arguments, Environment* env) {
|
||||||
@@ -105,13 +99,13 @@ Lisp_Object* built_in_greater_equal(Lisp_Object* arguments, Environment* env) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (arguments->value.pair->first->value.number->value > last_number)
|
if (arguments->value.pair->first->value.number->value > last_number)
|
||||||
return create_lisp_object_nil();
|
return Memory::create_lisp_object_nil();
|
||||||
|
|
||||||
last_number = arguments->value.pair->first->value.number->value;
|
last_number = arguments->value.pair->first->value.number->value;
|
||||||
arguments = arguments->value.pair->rest;
|
arguments = arguments->value.pair->rest;
|
||||||
}
|
}
|
||||||
|
|
||||||
return create_lisp_object_t();
|
return Memory::create_lisp_object_t();
|
||||||
}
|
}
|
||||||
|
|
||||||
Lisp_Object* built_in_less(Lisp_Object* arguments, Environment* env) {
|
Lisp_Object* built_in_less(Lisp_Object* arguments, Environment* env) {
|
||||||
@@ -128,13 +122,13 @@ Lisp_Object* built_in_less(Lisp_Object* arguments, Environment* env) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (arguments->value.pair->first->value.number->value <= last_number)
|
if (arguments->value.pair->first->value.number->value <= last_number)
|
||||||
return create_lisp_object_nil();
|
return Memory::create_lisp_object_nil();
|
||||||
|
|
||||||
last_number = arguments->value.pair->first->value.number->value;
|
last_number = arguments->value.pair->first->value.number->value;
|
||||||
arguments = arguments->value.pair->rest;
|
arguments = arguments->value.pair->rest;
|
||||||
}
|
}
|
||||||
|
|
||||||
return create_lisp_object_t();
|
return Memory::create_lisp_object_t();
|
||||||
}
|
}
|
||||||
|
|
||||||
Lisp_Object* built_in_less_equal(Lisp_Object* arguments, Environment* env) {
|
Lisp_Object* built_in_less_equal(Lisp_Object* arguments, Environment* env) {
|
||||||
@@ -151,13 +145,13 @@ Lisp_Object* built_in_less_equal(Lisp_Object* arguments, Environment* env) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (arguments->value.pair->first->value.number->value < last_number)
|
if (arguments->value.pair->first->value.number->value < last_number)
|
||||||
return create_lisp_object_nil();
|
return Memory::create_lisp_object_nil();
|
||||||
|
|
||||||
last_number = arguments->value.pair->first->value.number->value;
|
last_number = arguments->value.pair->first->value.number->value;
|
||||||
arguments = arguments->value.pair->rest;
|
arguments = arguments->value.pair->rest;
|
||||||
}
|
}
|
||||||
|
|
||||||
return create_lisp_object_t();
|
return Memory::create_lisp_object_t();
|
||||||
}
|
}
|
||||||
|
|
||||||
Lisp_Object* built_in_add(Lisp_Object* arguments, Environment* env) {
|
Lisp_Object* built_in_add(Lisp_Object* arguments, Environment* env) {
|
||||||
@@ -175,7 +169,7 @@ Lisp_Object* built_in_add(Lisp_Object* arguments, Environment* env) {
|
|||||||
arguments = arguments->value.pair->rest;
|
arguments = arguments->value.pair->rest;
|
||||||
}
|
}
|
||||||
|
|
||||||
return create_lisp_object_number(sum);
|
return Memory::create_lisp_object_number(sum);
|
||||||
}
|
}
|
||||||
|
|
||||||
Lisp_Object* built_in_substract(Lisp_Object* arguments, Environment* env) {
|
Lisp_Object* built_in_substract(Lisp_Object* arguments, Environment* env) {
|
||||||
@@ -198,7 +192,7 @@ Lisp_Object* built_in_substract(Lisp_Object* arguments, Environment* env) {
|
|||||||
difference -= arguments->value.pair->first->value.number->value;
|
difference -= arguments->value.pair->first->value.number->value;
|
||||||
arguments = arguments->value.pair->rest;
|
arguments = arguments->value.pair->rest;
|
||||||
}
|
}
|
||||||
return create_lisp_object_number(difference);
|
return Memory::create_lisp_object_number(difference);
|
||||||
}
|
}
|
||||||
|
|
||||||
Lisp_Object* built_in_multiply(Lisp_Object* arguments, Environment* env) {
|
Lisp_Object* built_in_multiply(Lisp_Object* arguments, Environment* env) {
|
||||||
@@ -221,7 +215,7 @@ Lisp_Object* built_in_multiply(Lisp_Object* arguments, Environment* env) {
|
|||||||
product *= arguments->value.pair->first->value.number->value;
|
product *= arguments->value.pair->first->value.number->value;
|
||||||
arguments = arguments->value.pair->rest;
|
arguments = arguments->value.pair->rest;
|
||||||
}
|
}
|
||||||
return create_lisp_object_number(product);
|
return Memory::create_lisp_object_number(product);
|
||||||
}
|
}
|
||||||
|
|
||||||
Lisp_Object* built_in_divide(Lisp_Object* arguments, Environment* env) {
|
Lisp_Object* built_in_divide(Lisp_Object* arguments, Environment* env) {
|
||||||
@@ -244,7 +238,7 @@ Lisp_Object* built_in_divide(Lisp_Object* arguments, Environment* env) {
|
|||||||
quotient /= arguments->value.pair->first->value.number->value;
|
quotient /= arguments->value.pair->first->value.number->value;
|
||||||
arguments = arguments->value.pair->rest;
|
arguments = arguments->value.pair->rest;
|
||||||
}
|
}
|
||||||
return create_lisp_object_number(quotient);
|
return Memory::create_lisp_object_number(quotient);
|
||||||
}
|
}
|
||||||
|
|
||||||
Lisp_Object* built_in_exponentiate(Lisp_Object* arguments, Environment* env) {
|
Lisp_Object* built_in_exponentiate(Lisp_Object* arguments, Environment* env) {
|
||||||
@@ -272,14 +266,14 @@ Lisp_Object* built_in_exponentiate(Lisp_Object* arguments, Environment* env) {
|
|||||||
|
|
||||||
double exponent = arguments->value.pair->first->value.number->value;
|
double exponent = arguments->value.pair->first->value.number->value;
|
||||||
|
|
||||||
return create_lisp_object_number(pow(base, exponent));
|
return Memory::create_lisp_object_number(pow(base, exponent));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Lisp_Object* built_in_load(char* file_name, Environment* env) {
|
Lisp_Object* built_in_load(char* file_name, Environment* env) {
|
||||||
char* file_content = read_entire_file(file_name);
|
char* file_content = read_entire_file(file_name);
|
||||||
if (file_content) {
|
if (file_content) {
|
||||||
Lisp_Object* result = create_lisp_object_nil();
|
Lisp_Object* result = Memory::create_lisp_object_nil();
|
||||||
Lisp_Object_Array_List* program;
|
Lisp_Object_Array_List* program;
|
||||||
try {
|
try {
|
||||||
program = Parser::parse_program(file_name, file_content);
|
program = Parser::parse_program(file_name, file_content);
|
||||||
@@ -308,8 +302,8 @@ void load_built_ins_into_environment(Environment* env) {
|
|||||||
|
|
||||||
auto defun = [&](char* name, std::function<Lisp_Object*(Lisp_Object*, Environment*)> fun) {
|
auto defun = [&](char* name, std::function<Lisp_Object*(Lisp_Object*, Environment*)> fun) {
|
||||||
define_symbol(
|
define_symbol(
|
||||||
create_lisp_object_symbol(name),
|
Memory::create_lisp_object_symbol(name),
|
||||||
create_lisp_object_cfunction(fun),
|
Memory::create_lisp_object_cfunction(fun),
|
||||||
env);
|
env);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -436,7 +430,7 @@ void load_built_ins_into_environment(Environment* env) {
|
|||||||
try {
|
try {
|
||||||
result = eval_expr(else_part->value.pair->first, env);
|
result = eval_expr(else_part->value.pair->first, env);
|
||||||
}
|
}
|
||||||
else return create_lisp_object_nil();
|
else return Memory::create_lisp_object_nil();
|
||||||
return result;
|
return result;
|
||||||
});
|
});
|
||||||
defun("quote", cLambda {
|
defun("quote", cLambda {
|
||||||
@@ -466,7 +460,7 @@ void load_built_ins_into_environment(Environment* env) {
|
|||||||
unquoteSomeExpressions = [&unquoteSomeExpressions, &env] (Lisp_Object* expr) -> Lisp_Object* {
|
unquoteSomeExpressions = [&unquoteSomeExpressions, &env] (Lisp_Object* expr) -> Lisp_Object* {
|
||||||
// if it is an atom, return it
|
// if it is an atom, return it
|
||||||
if (expr->type != Lisp_Object_Type::Pair)
|
if (expr->type != Lisp_Object_Type::Pair)
|
||||||
return copy_lisp_object(expr);
|
return Memory::copy_lisp_object(expr);
|
||||||
|
|
||||||
// it is a pair!
|
// it is a pair!
|
||||||
Lisp_Object* originalPair = expr->value.pair->first;
|
Lisp_Object* originalPair = expr->value.pair->first;
|
||||||
@@ -486,7 +480,7 @@ void load_built_ins_into_environment(Environment* env) {
|
|||||||
// funciton, we can't jsut modify it because otherwise
|
// funciton, we can't jsut modify it because otherwise
|
||||||
// we modify the body of the function and would bake
|
// we modify the body of the function and would bake
|
||||||
// in the result...
|
// in the result...
|
||||||
Lisp_Object* newPair = create_lisp_object_pair(nullptr, nullptr);
|
Lisp_Object* newPair = Memory::create_lisp_object_pair(nullptr, nullptr);
|
||||||
Lisp_Object* newPairHead = newPair;
|
Lisp_Object* newPairHead = newPair;
|
||||||
Lisp_Object* head = expr;
|
Lisp_Object* head = expr;
|
||||||
while (head->type == Lisp_Object_Type::Pair) {
|
while (head->type == Lisp_Object_Type::Pair) {
|
||||||
@@ -495,12 +489,12 @@ void load_built_ins_into_environment(Environment* env) {
|
|||||||
if (head->value.pair->rest->type != Lisp_Object_Type::Pair)
|
if (head->value.pair->rest->type != Lisp_Object_Type::Pair)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
newPairHead->value.pair->rest = create_lisp_object_pair(nullptr, nullptr);
|
newPairHead->value.pair->rest = Memory::create_lisp_object_pair(nullptr, nullptr);
|
||||||
|
|
||||||
newPairHead = newPairHead->value.pair->rest;
|
newPairHead = newPairHead->value.pair->rest;
|
||||||
head = head->value.pair->rest;
|
head = head->value.pair->rest;
|
||||||
}
|
}
|
||||||
newPairHead->value.pair->rest = create_lisp_object_nil();
|
newPairHead->value.pair->rest = Memory::create_lisp_object_nil();
|
||||||
|
|
||||||
return newPair;
|
return newPair;
|
||||||
};
|
};
|
||||||
@@ -522,10 +516,10 @@ void load_built_ins_into_environment(Environment* env) {
|
|||||||
}
|
}
|
||||||
arguments = arguments->value.pair->rest;
|
arguments = arguments->value.pair->rest;
|
||||||
|
|
||||||
if (!result) return create_lisp_object_nil();
|
if (!result) return Memory::create_lisp_object_nil();
|
||||||
}
|
}
|
||||||
|
|
||||||
return create_lisp_object_t();
|
return Memory::create_lisp_object_t();
|
||||||
});
|
});
|
||||||
defun("or", cLambda {
|
defun("or", cLambda {
|
||||||
bool result = false;
|
bool result = false;
|
||||||
@@ -538,10 +532,10 @@ void load_built_ins_into_environment(Environment* env) {
|
|||||||
}
|
}
|
||||||
arguments = arguments->value.pair->rest;
|
arguments = arguments->value.pair->rest;
|
||||||
|
|
||||||
if (result) return create_lisp_object_t();
|
if (result) return Memory::create_lisp_object_t();
|
||||||
}
|
}
|
||||||
|
|
||||||
return create_lisp_object_nil();
|
return Memory::create_lisp_object_nil();
|
||||||
});
|
});
|
||||||
defun("not", cLambda {
|
defun("not", cLambda {
|
||||||
try {
|
try {
|
||||||
@@ -556,8 +550,8 @@ void load_built_ins_into_environment(Environment* env) {
|
|||||||
truthy = is_truthy(arguments->value.pair->first, env);
|
truthy = is_truthy(arguments->value.pair->first, env);
|
||||||
}
|
}
|
||||||
if (truthy)
|
if (truthy)
|
||||||
return create_lisp_object_nil();
|
return Memory::create_lisp_object_nil();
|
||||||
return create_lisp_object_t();
|
return Memory::create_lisp_object_t();
|
||||||
});
|
});
|
||||||
defun("while", cLambda {
|
defun("while", cLambda {
|
||||||
try {
|
try {
|
||||||
@@ -570,7 +564,7 @@ void load_built_ins_into_environment(Environment* env) {
|
|||||||
Lisp_Object* condition_part = arguments->value.pair->first;
|
Lisp_Object* condition_part = arguments->value.pair->first;
|
||||||
Lisp_Object* condition;
|
Lisp_Object* condition;
|
||||||
Lisp_Object* then_part = arguments->value.pair->rest;
|
Lisp_Object* then_part = arguments->value.pair->rest;
|
||||||
Lisp_Object* result = create_lisp_object_nil();
|
Lisp_Object* result = Memory::create_lisp_object_nil();
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
try {
|
try {
|
||||||
@@ -595,7 +589,7 @@ void load_built_ins_into_environment(Environment* env) {
|
|||||||
if (arguments_length < 1)
|
if (arguments_length < 1)
|
||||||
report_error(Error_Type::Wrong_Number_Of_Arguments);
|
report_error(Error_Type::Wrong_Number_Of_Arguments);
|
||||||
|
|
||||||
Environment* let_env = create_child_environment(env);
|
Environment* let_env = Memory::create_child_environment(env);
|
||||||
Lisp_Object* bindings = arguments->value.pair->first;
|
Lisp_Object* bindings = arguments->value.pair->first;
|
||||||
while (true) {
|
while (true) {
|
||||||
if (bindings->type == Lisp_Object_Type::Nil) {
|
if (bindings->type == Lisp_Object_Type::Nil) {
|
||||||
@@ -684,11 +678,11 @@ void load_built_ins_into_environment(Environment* env) {
|
|||||||
|
|
||||||
// we are now in the function body, just wrap it in an
|
// we are now in the function body, just wrap it in an
|
||||||
// implicit prog
|
// implicit prog
|
||||||
function->body = create_lisp_object_pair(
|
function->body = Memory::create_lisp_object_pair(
|
||||||
create_lisp_object_symbol("prog"),
|
Memory::create_lisp_object_symbol("prog"),
|
||||||
arguments);
|
arguments);
|
||||||
|
|
||||||
Lisp_Object* ret = new(Lisp_Object);
|
Lisp_Object* ret = Memory::create_lisp_object();
|
||||||
ret->type = Lisp_Object_Type::Function;
|
ret->type = Lisp_Object_Type::Function;
|
||||||
ret->value.function = function;
|
ret->value.function = function;
|
||||||
return ret;
|
return ret;
|
||||||
@@ -734,11 +728,11 @@ void load_built_ins_into_environment(Environment* env) {
|
|||||||
|
|
||||||
// we are now in the function body, just wrap it in an
|
// we are now in the function body, just wrap it in an
|
||||||
// implicit prog
|
// implicit prog
|
||||||
function->body = create_lisp_object_pair(
|
function->body = Memory::create_lisp_object_pair(
|
||||||
create_lisp_object_symbol("prog"),
|
Memory::create_lisp_object_symbol("prog"),
|
||||||
arguments);
|
arguments);
|
||||||
|
|
||||||
Lisp_Object* ret = new(Lisp_Object);
|
Lisp_Object* ret = Memory::create_lisp_object();
|
||||||
ret->type = Lisp_Object_Type::Function;
|
ret->type = Lisp_Object_Type::Function;
|
||||||
ret->value.function = function;
|
ret->value.function = function;
|
||||||
return ret;
|
return ret;
|
||||||
@@ -790,7 +784,7 @@ void load_built_ins_into_environment(Environment* env) {
|
|||||||
if (arguments_length != 2) {
|
if (arguments_length != 2) {
|
||||||
report_error(Error_Type::Wrong_Number_Of_Arguments);
|
report_error(Error_Type::Wrong_Number_Of_Arguments);
|
||||||
}
|
}
|
||||||
return create_lisp_object_pair(evaluated_arguments->value.pair->first, evaluated_arguments->value.pair->rest->value.pair->first);
|
return Memory::create_lisp_object_pair(evaluated_arguments->value.pair->first, evaluated_arguments->value.pair->rest->value.pair->first);
|
||||||
});
|
});
|
||||||
defun("first", cLambda {
|
defun("first", cLambda {
|
||||||
try {
|
try {
|
||||||
@@ -800,7 +794,7 @@ void load_built_ins_into_environment(Environment* env) {
|
|||||||
report_error(Error_Type::Wrong_Number_Of_Arguments);
|
report_error(Error_Type::Wrong_Number_Of_Arguments);
|
||||||
}
|
}
|
||||||
if (evaluated_arguments->value.pair->first->type == Lisp_Object_Type::Nil)
|
if (evaluated_arguments->value.pair->first->type == Lisp_Object_Type::Nil)
|
||||||
return create_lisp_object_nil();
|
return Memory::create_lisp_object_nil();
|
||||||
if (evaluated_arguments->value.pair->first->type != Lisp_Object_Type::Pair)
|
if (evaluated_arguments->value.pair->first->type != Lisp_Object_Type::Pair)
|
||||||
report_error(Error_Type::Type_Missmatch);
|
report_error(Error_Type::Type_Missmatch);
|
||||||
|
|
||||||
@@ -814,7 +808,7 @@ void load_built_ins_into_environment(Environment* env) {
|
|||||||
report_error(Error_Type::Wrong_Number_Of_Arguments);
|
report_error(Error_Type::Wrong_Number_Of_Arguments);
|
||||||
}
|
}
|
||||||
if (evaluated_arguments->value.pair->first->type == Lisp_Object_Type::Nil)
|
if (evaluated_arguments->value.pair->first->type == Lisp_Object_Type::Nil)
|
||||||
return create_lisp_object_nil();
|
return Memory::create_lisp_object_nil();
|
||||||
if (evaluated_arguments->value.pair->first->type != Lisp_Object_Type::Pair)
|
if (evaluated_arguments->value.pair->first->type != Lisp_Object_Type::Pair)
|
||||||
report_error(Error_Type::Type_Missmatch);
|
report_error(Error_Type::Type_Missmatch);
|
||||||
|
|
||||||
@@ -830,26 +824,26 @@ void load_built_ins_into_environment(Environment* env) {
|
|||||||
|
|
||||||
Lisp_Object_Type type = evaluated_arguments->value.pair->first->type;
|
Lisp_Object_Type type = evaluated_arguments->value.pair->first->type;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case Lisp_Object_Type::CFunction: return create_lisp_object_keyword("cfunction");
|
case Lisp_Object_Type::CFunction: return Memory::create_lisp_object_keyword("cfunction");
|
||||||
case Lisp_Object_Type::Function: {
|
case Lisp_Object_Type::Function: {
|
||||||
Function* fun = evaluated_arguments->value.pair->first->value.function;
|
Function* fun = evaluated_arguments->value.pair->first->value.function;
|
||||||
if (fun->type == Function_Type::Lambda)
|
if (fun->type == Function_Type::Lambda)
|
||||||
return create_lisp_object_keyword("lambda");
|
return Memory::create_lisp_object_keyword("lambda");
|
||||||
else if (fun->type == Function_Type::Special_Lambda)
|
else if (fun->type == Function_Type::Special_Lambda)
|
||||||
return create_lisp_object_keyword("special-lambda");
|
return Memory::create_lisp_object_keyword("special-lambda");
|
||||||
else if (fun->type == Function_Type::Macro)
|
else if (fun->type == Function_Type::Macro)
|
||||||
return create_lisp_object_keyword("macro");
|
return Memory::create_lisp_object_keyword("macro");
|
||||||
else return create_lisp_object_keyword("unknown");
|
else return Memory::create_lisp_object_keyword("unknown");
|
||||||
}
|
}
|
||||||
case Lisp_Object_Type::Keyword: return create_lisp_object_keyword("keyword");
|
case Lisp_Object_Type::Keyword: return Memory::create_lisp_object_keyword("keyword");
|
||||||
case Lisp_Object_Type::Nil: return create_lisp_object_keyword("nil");
|
case Lisp_Object_Type::Nil: return Memory::create_lisp_object_keyword("nil");
|
||||||
case Lisp_Object_Type::T: return create_lisp_object_keyword("t");
|
case Lisp_Object_Type::T: return Memory::create_lisp_object_keyword("t");
|
||||||
case Lisp_Object_Type::Number: return create_lisp_object_keyword("number");
|
case Lisp_Object_Type::Number: return Memory::create_lisp_object_keyword("number");
|
||||||
case Lisp_Object_Type::Pair: return create_lisp_object_keyword("pair");
|
case Lisp_Object_Type::Pair: return Memory::create_lisp_object_keyword("pair");
|
||||||
case Lisp_Object_Type::String: return create_lisp_object_keyword("string");
|
case Lisp_Object_Type::String: return Memory::create_lisp_object_keyword("string");
|
||||||
case Lisp_Object_Type::Symbol: return create_lisp_object_keyword("symbol");
|
case Lisp_Object_Type::Symbol: return Memory::create_lisp_object_keyword("symbol");
|
||||||
}
|
}
|
||||||
return create_lisp_object_keyword("unknown");
|
return Memory::create_lisp_object_keyword("unknown");
|
||||||
});
|
});
|
||||||
defun("info", cLambda {
|
defun("info", cLambda {
|
||||||
try {
|
try {
|
||||||
@@ -863,9 +857,9 @@ void load_built_ins_into_environment(Environment* env) {
|
|||||||
print(arguments->value.pair->first);
|
print(arguments->value.pair->first);
|
||||||
|
|
||||||
Lisp_Object* type = eval_expr(
|
Lisp_Object* type = eval_expr(
|
||||||
create_lisp_object_pair(
|
Memory::create_lisp_object_pair(
|
||||||
create_lisp_object_symbol("type"),
|
Memory::create_lisp_object_symbol("type"),
|
||||||
create_lisp_object_pair(arguments->value.pair->first, create_lisp_object_nil())),
|
Memory::create_lisp_object_pair(arguments->value.pair->first, Memory::create_lisp_object_nil())),
|
||||||
env);
|
env);
|
||||||
|
|
||||||
if (type) {
|
if (type) {
|
||||||
@@ -924,7 +918,7 @@ void load_built_ins_into_environment(Environment* env) {
|
|||||||
delete_error();
|
delete_error();
|
||||||
}
|
}
|
||||||
|
|
||||||
return create_lisp_object_nil();
|
return Memory::create_lisp_object_nil();
|
||||||
});
|
});
|
||||||
defun("print", cLambda {
|
defun("print", cLambda {
|
||||||
try {
|
try {
|
||||||
@@ -935,7 +929,7 @@ void load_built_ins_into_environment(Environment* env) {
|
|||||||
}
|
}
|
||||||
print(evaluated_arguments->value.pair->first);
|
print(evaluated_arguments->value.pair->first);
|
||||||
// printf("\n");
|
// printf("\n");
|
||||||
return create_lisp_object_nil();
|
return Memory::create_lisp_object_nil();
|
||||||
});
|
});
|
||||||
defun("read", cLambda {
|
defun("read", cLambda {
|
||||||
try {
|
try {
|
||||||
@@ -954,7 +948,7 @@ void load_built_ins_into_environment(Environment* env) {
|
|||||||
print(evaluated_arguments->value.pair->first);
|
print(evaluated_arguments->value.pair->first);
|
||||||
}
|
}
|
||||||
char* line = read_line();
|
char* line = read_line();
|
||||||
return create_lisp_object_string(line, (int)strlen(line));
|
return Memory::create_lisp_object_string(line, (int)strlen(line));
|
||||||
});
|
});
|
||||||
defun("exit", cLambda {
|
defun("exit", cLambda {
|
||||||
try {
|
try {
|
||||||
@@ -979,7 +973,11 @@ void load_built_ins_into_environment(Environment* env) {
|
|||||||
if_debug {
|
if_debug {
|
||||||
__debugbreak();
|
__debugbreak();
|
||||||
}
|
}
|
||||||
return create_lisp_object_nil();
|
return Memory::create_lisp_object_nil();
|
||||||
|
});
|
||||||
|
defun("memstat", cLambda {
|
||||||
|
Memory::print_status();
|
||||||
|
return Memory::create_lisp_object_nil();
|
||||||
});
|
});
|
||||||
defun("try", cLambda {
|
defun("try", cLambda {
|
||||||
try {
|
try {
|
||||||
@@ -1039,7 +1037,7 @@ void load_built_ins_into_environment(Environment* env) {
|
|||||||
report_error(Error_Type::Type_Missmatch);
|
report_error(Error_Type::Type_Missmatch);
|
||||||
}
|
}
|
||||||
|
|
||||||
Lisp_Object* target = new(Lisp_Object);
|
Lisp_Object* target = Memory::create_lisp_object();
|
||||||
Lisp_Object* source = evaluated_arguments->value.pair->first;
|
Lisp_Object* source = evaluated_arguments->value.pair->first;
|
||||||
|
|
||||||
*target = *source;
|
*target = *source;
|
||||||
@@ -1074,7 +1072,7 @@ void load_built_ins_into_environment(Environment* env) {
|
|||||||
report_error(Error_Type::Type_Missmatch);
|
report_error(Error_Type::Type_Missmatch);
|
||||||
}
|
}
|
||||||
|
|
||||||
return create_lisp_object_symbol(_strdup(source->value.string->value));
|
return Memory::create_lisp_object_symbol(_strdup(source->value.string->value));
|
||||||
});
|
});
|
||||||
defun("symbol->string", cLambda {
|
defun("symbol->string", cLambda {
|
||||||
try {
|
try {
|
||||||
@@ -1092,7 +1090,7 @@ void load_built_ins_into_environment(Environment* env) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO(Felix): this is not really fast what we are doing here:
|
// TODO(Felix): this is not really fast what we are doing here:
|
||||||
return create_lisp_object_string(_strdup(source->value.symbol->identifier), (int)strlen(source->value.symbol->identifier));
|
return Memory::create_lisp_object_string(_strdup(source->value.symbol->identifier), (int)strlen(source->value.symbol->identifier));
|
||||||
});
|
});
|
||||||
defun("concat-strings", cLambda {
|
defun("concat-strings", cLambda {
|
||||||
try {
|
try {
|
||||||
@@ -1129,15 +1127,9 @@ void load_built_ins_into_environment(Environment* env) {
|
|||||||
|
|
||||||
resulting_string[index_in_string] = '\0';
|
resulting_string[index_in_string] = '\0';
|
||||||
|
|
||||||
return create_lisp_object_string(resulting_string, resulting_string_len);
|
return Memory::create_lisp_object_string(resulting_string, resulting_string_len);
|
||||||
});
|
});
|
||||||
|
|
||||||
#undef report_error
|
#undef report_error
|
||||||
#undef cLambda
|
#undef cLambda
|
||||||
}
|
}
|
||||||
|
|
||||||
Environment* create_built_ins_environment() {
|
|
||||||
Environment* ret = create_child_environment(nullptr);
|
|
||||||
load_built_ins_into_environment(ret);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|||||||
+3
-30
@@ -1,30 +1,3 @@
|
|||||||
struct Environment {
|
|
||||||
struct Environment* parent;
|
|
||||||
|
|
||||||
int capacity;
|
|
||||||
int next_index;
|
|
||||||
// TODO(Felix): Use a hashmap here.
|
|
||||||
char** keys;
|
|
||||||
Lisp_Object** values;
|
|
||||||
};
|
|
||||||
|
|
||||||
Environment* create_child_environment(Environment* parent) {
|
|
||||||
Environment* env = new(Environment);
|
|
||||||
|
|
||||||
int start_capacity = 16;
|
|
||||||
|
|
||||||
env->parent = parent;
|
|
||||||
env->capacity = start_capacity;
|
|
||||||
env->next_index = 0;
|
|
||||||
env->keys = (char**)malloc(start_capacity * sizeof(char*));
|
|
||||||
env->values = (Lisp_Object**)malloc(start_capacity * sizeof(Lisp_Object*));
|
|
||||||
|
|
||||||
return env;
|
|
||||||
}
|
|
||||||
|
|
||||||
Environment* create_empty_environment() {
|
|
||||||
return create_child_environment(nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void define_symbol(Lisp_Object* symbol, Lisp_Object* value, Environment* env) {
|
void define_symbol(Lisp_Object* symbol, Lisp_Object* value, Environment* env) {
|
||||||
// NOTE(Felix): right now we are simply adding the symol at the
|
// NOTE(Felix): right now we are simply adding the symol at the
|
||||||
@@ -68,10 +41,10 @@ Lisp_Object* lookup_symbol(Lisp_Object* node, Environment* env) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (string_equal(sym->identifier, "nil")) {
|
if (string_equal(sym->identifier, "nil")) {
|
||||||
return create_lisp_object_nil();
|
return Memory::create_lisp_object_nil();
|
||||||
}
|
}
|
||||||
if (string_equal(sym->identifier, "t")) {
|
if (string_equal(sym->identifier, "t")) {
|
||||||
return create_lisp_object_t();
|
return Memory::create_lisp_object_t();
|
||||||
}
|
}
|
||||||
|
|
||||||
create_error(Error_Type::Symbol_Not_Defined, node->sourceCodeLocation);
|
create_error(Error_Type::Symbol_Not_Defined, node->sourceCodeLocation);
|
||||||
@@ -87,8 +60,8 @@ void print_indent(int indent) {
|
|||||||
void print_environment_indent(Environment* env, int indent) {
|
void print_environment_indent(Environment* env, int indent) {
|
||||||
for (int i = 0; i < env->next_index; ++i) {
|
for (int i = 0; i < env->next_index; ++i) {
|
||||||
print_indent(indent);
|
print_indent(indent);
|
||||||
printf("%s -> ", env->keys[i]);
|
|
||||||
print(env->values[i]);
|
print(env->values[i]);
|
||||||
|
printf(" %s", env->keys[i]);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
if (env->parent) {
|
if (env->parent) {
|
||||||
|
|||||||
+8
-22
@@ -1,25 +1,3 @@
|
|||||||
enum struct Error_Type {
|
|
||||||
Ill_Formed_Arguments,
|
|
||||||
Ill_Formed_Lambda_List,
|
|
||||||
Ill_Formed_List,
|
|
||||||
Not_A_Function,
|
|
||||||
Not_Yet_Implemented,
|
|
||||||
Symbol_Not_Defined,
|
|
||||||
Syntax_Error,
|
|
||||||
Trailing_Garbage,
|
|
||||||
Type_Missmatch,
|
|
||||||
Unbalanced_Parenthesis,
|
|
||||||
Unexpected_Eof,
|
|
||||||
Unknown_Error,
|
|
||||||
Unknown_Keyword_Argument,
|
|
||||||
Wrong_Number_Of_Arguments,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Error {
|
|
||||||
Error_Type type;
|
|
||||||
Source_Code_Location* location;
|
|
||||||
};
|
|
||||||
|
|
||||||
Error* error;
|
Error* error;
|
||||||
|
|
||||||
void delete_error() {
|
void delete_error() {
|
||||||
@@ -52,6 +30,14 @@ char* Error_Type_to_string(Error_Type type) {
|
|||||||
case Error_Type::Unexpected_Eof: return "Parsing-error: Unexpected EOF";
|
case Error_Type::Unexpected_Eof: return "Parsing-error: Unexpected EOF";
|
||||||
case Error_Type::Unknown_Keyword_Argument: return "Evaluation-error: Unknown keyword argument";
|
case Error_Type::Unknown_Keyword_Argument: return "Evaluation-error: Unknown keyword argument";
|
||||||
case Error_Type::Wrong_Number_Of_Arguments: return "Evaluation-error: Wrong number of arguments";
|
case Error_Type::Wrong_Number_Of_Arguments: return "Evaluation-error: Wrong number of arguments";
|
||||||
|
case Error_Type::Out_Of_Memory: return "Runtime-error: Out of memory";
|
||||||
default: return "Unknown Error";
|
default: return "Unknown Error";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void assert_type(Lisp_Object* node, Lisp_Object_Type type) {
|
||||||
|
if (!node)
|
||||||
|
create_error(Error_Type::Unknown_Error, nullptr);
|
||||||
|
if (node->type == type) return;
|
||||||
|
create_error(Error_Type::Type_Missmatch, node->sourceCodeLocation);
|
||||||
|
}
|
||||||
|
|||||||
+10
-11
@@ -1,7 +1,7 @@
|
|||||||
Lisp_Object* eval_expr(Lisp_Object*, Environment*);
|
Lisp_Object* eval_expr(Lisp_Object*, Environment*);
|
||||||
|
|
||||||
Lisp_Object* apply_arguments_to_function(Lisp_Object* arguments, Function* function) {
|
Lisp_Object* apply_arguments_to_function(Lisp_Object* arguments, Function* function) {
|
||||||
Environment* new_env = create_child_environment(function->parent_environment);
|
Environment* new_env = Memory::create_child_environment(function->parent_environment);
|
||||||
|
|
||||||
// positional arguments
|
// positional arguments
|
||||||
for (int i = 0; i < function->positional_arguments->next_index; ++i) {
|
for (int i = 0; i < function->positional_arguments->next_index; ++i) {
|
||||||
@@ -10,7 +10,7 @@ Lisp_Object* apply_arguments_to_function(Lisp_Object* arguments, Function* funct
|
|||||||
// their identifiers but before we converted them to
|
// their identifiers but before we converted them to
|
||||||
// strings from symbols... Wo maybe just use the symbols?
|
// strings from symbols... Wo maybe just use the symbols?
|
||||||
define_symbol(
|
define_symbol(
|
||||||
create_lisp_object_symbol(function->positional_arguments->identifiers[i]),
|
Memory::create_lisp_object_symbol(function->positional_arguments->identifiers[i]),
|
||||||
arguments->value.pair->first, new_env);
|
arguments->value.pair->first, new_env);
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
@@ -71,7 +71,7 @@ Lisp_Object* apply_arguments_to_function(Lisp_Object* arguments, Function* funct
|
|||||||
|
|
||||||
// if not set it and then add it to the array list
|
// if not set it and then add it to the array list
|
||||||
define_symbol(
|
define_symbol(
|
||||||
create_lisp_object_symbol(arguments->value.pair->first->value.keyword->identifier),
|
Memory::create_lisp_object_symbol(arguments->value.pair->first->value.keyword->identifier),
|
||||||
arguments->value.pair->rest->value.pair->first,
|
arguments->value.pair->rest->value.pair->first,
|
||||||
new_env);
|
new_env);
|
||||||
|
|
||||||
@@ -110,8 +110,8 @@ Lisp_Object* apply_arguments_to_function(Lisp_Object* arguments, Function* funct
|
|||||||
// to use it or if the user supplied his own
|
// to use it or if the user supplied his own
|
||||||
if (!was_set) {
|
if (!was_set) {
|
||||||
define_symbol(
|
define_symbol(
|
||||||
create_lisp_object_symbol(defined_keyword),
|
Memory::create_lisp_object_symbol(defined_keyword),
|
||||||
copy_lisp_object(function->keyword_arguments->values->data[i]), new_env);
|
Memory::copy_lisp_object(function->keyword_arguments->values->data[i]), new_env);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -120,13 +120,13 @@ Lisp_Object* apply_arguments_to_function(Lisp_Object* arguments, Function* funct
|
|||||||
if (arguments->type == Lisp_Object_Type::Nil) {
|
if (arguments->type == Lisp_Object_Type::Nil) {
|
||||||
if (function->rest_argument) {
|
if (function->rest_argument) {
|
||||||
define_symbol(
|
define_symbol(
|
||||||
create_lisp_object_symbol(function->rest_argument),
|
Memory::create_lisp_object_symbol(function->rest_argument),
|
||||||
create_lisp_object_nil(), new_env);
|
Memory::create_lisp_object_nil(), new_env);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (function->rest_argument) {
|
if (function->rest_argument) {
|
||||||
define_symbol(
|
define_symbol(
|
||||||
create_lisp_object_symbol(function->rest_argument),
|
Memory::create_lisp_object_symbol(function->rest_argument),
|
||||||
arguments, new_env);
|
arguments, new_env);
|
||||||
} else {
|
} else {
|
||||||
// rest was not declared but additional arguments were found
|
// rest was not declared but additional arguments were found
|
||||||
@@ -326,7 +326,7 @@ Lisp_Object* eval_arguments(Lisp_Object* arguments, Environment* env, int *out_a
|
|||||||
return arguments;
|
return arguments;
|
||||||
}
|
}
|
||||||
|
|
||||||
Lisp_Object* evaluated_arguments = create_lisp_object_pair(nullptr, nullptr);
|
Lisp_Object* evaluated_arguments = Memory::create_lisp_object_pair(nullptr, nullptr);
|
||||||
Lisp_Object* evaluated_arguments_head = evaluated_arguments;
|
Lisp_Object* evaluated_arguments_head = evaluated_arguments;
|
||||||
Lisp_Object* current_head = arguments;
|
Lisp_Object* current_head = arguments;
|
||||||
while (current_head->type == Lisp_Object_Type::Pair) {
|
while (current_head->type == Lisp_Object_Type::Pair) {
|
||||||
@@ -337,7 +337,7 @@ Lisp_Object* eval_arguments(Lisp_Object* arguments, Environment* env, int *out_a
|
|||||||
current_head = current_head->value.pair->rest;
|
current_head = current_head->value.pair->rest;
|
||||||
|
|
||||||
if (current_head->type == Lisp_Object_Type::Pair) {
|
if (current_head->type == Lisp_Object_Type::Pair) {
|
||||||
evaluated_arguments_head->value.pair->rest = create_lisp_object_pair(nullptr, nullptr);
|
evaluated_arguments_head->value.pair->rest = Memory::create_lisp_object_pair(nullptr, nullptr);
|
||||||
evaluated_arguments_head = evaluated_arguments_head->value.pair->rest;
|
evaluated_arguments_head = evaluated_arguments_head->value.pair->rest;
|
||||||
} else if (current_head->type == Lisp_Object_Type::Nil) {
|
} else if (current_head->type == Lisp_Object_Type::Nil) {
|
||||||
evaluated_arguments_head->value.pair->rest = current_head;
|
evaluated_arguments_head->value.pair->rest = current_head;
|
||||||
@@ -360,7 +360,6 @@ Lisp_Object* eval_expr(Lisp_Object* node, Environment* env) {
|
|||||||
if (error)
|
if (error)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
Lisp_Object* ret = new(Lisp_Object);
|
|
||||||
switch (node->type) {
|
switch (node->type) {
|
||||||
case Lisp_Object_Type::T:
|
case Lisp_Object_Type::T:
|
||||||
case Lisp_Object_Type::Nil:
|
case Lisp_Object_Type::Nil:
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
Lisp_Object* eval_arguments(Lisp_Object* arguments, Environment* env, int *out_arguments_length);
|
||||||
|
Lisp_Object* eval_expr(Lisp_Object*, Environment*);
|
||||||
|
bool is_truthy (Lisp_Object* expression, Environment* env);
|
||||||
|
int list_length(Lisp_Object*);
|
||||||
|
void load_built_ins_into_environment(Environment*);
|
||||||
|
void parse_argument_list(Lisp_Object*, Function*);
|
||||||
+1
-7
@@ -60,7 +60,7 @@ constexpr bool is_debug_build = false;
|
|||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
\
|
\
|
||||||
name##_Array_List* create_##name##_array_list(int initial_capacity) { \
|
name##_Array_List* create_##name##_array_list(int initial_capacity = 16) { \
|
||||||
name##_Array_List* ret = new(name##_Array_List); \
|
name##_Array_List* ret = new(name##_Array_List); \
|
||||||
ret->data = (type*)malloc(initial_capacity * sizeof(type)); \
|
ret->data = (type*)malloc(initial_capacity * sizeof(type)); \
|
||||||
ret->next_index = 0; \
|
ret->next_index = 0; \
|
||||||
@@ -68,12 +68,6 @@ constexpr bool is_debug_build = false;
|
|||||||
return ret; \
|
return ret; \
|
||||||
}
|
}
|
||||||
|
|
||||||
define_array_list(char*, String);
|
|
||||||
|
|
||||||
// int string_equal(char* a, char* b) {
|
|
||||||
// return !strcmp(a, b);
|
|
||||||
// }
|
|
||||||
|
|
||||||
int string_equal(char input[],char check[])
|
int string_equal(char input[],char check[])
|
||||||
{
|
{
|
||||||
int i,result=1;
|
int i,result=1;
|
||||||
|
|||||||
@@ -8,14 +8,6 @@
|
|||||||
#define console_green ""
|
#define console_green ""
|
||||||
#define console_cyan ""
|
#define console_cyan ""
|
||||||
|
|
||||||
enum struct Log_Level {
|
|
||||||
None,
|
|
||||||
Critical,
|
|
||||||
Warning,
|
|
||||||
Info,
|
|
||||||
Debug,
|
|
||||||
};
|
|
||||||
|
|
||||||
Log_Level log_level = Log_Level::Debug;
|
Log_Level log_level = Log_Level::Debug;
|
||||||
|
|
||||||
void log_message(Log_Level type, char* message) {
|
void log_message(Log_Level type, char* message) {
|
||||||
|
|||||||
@@ -1,19 +1,3 @@
|
|||||||
struct Lisp_Object;
|
|
||||||
|
|
||||||
define_array_list(Lisp_Object*, Lisp_Object);
|
|
||||||
|
|
||||||
enum struct Lisp_Object_Type {
|
|
||||||
Nil,
|
|
||||||
T,
|
|
||||||
Symbol,
|
|
||||||
Keyword,
|
|
||||||
Number,
|
|
||||||
String,
|
|
||||||
Pair,
|
|
||||||
Function,
|
|
||||||
CFunction,
|
|
||||||
};
|
|
||||||
|
|
||||||
char* Lisp_Object_Type_to_string(Lisp_Object_Type type) {
|
char* Lisp_Object_Type_to_string(Lisp_Object_Type type) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case(Lisp_Object_Type::Nil): return "nil";
|
case(Lisp_Object_Type::Nil): return "nil";
|
||||||
@@ -29,46 +13,6 @@ char* Lisp_Object_Type_to_string(Lisp_Object_Type type) {
|
|||||||
return "unknown";
|
return "unknown";
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Symbol {
|
|
||||||
char* identifier;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Keyword {
|
|
||||||
char* identifier;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Number {
|
|
||||||
double value;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct String {
|
|
||||||
char* value;
|
|
||||||
int length;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Pair {
|
|
||||||
Lisp_Object* first;
|
|
||||||
Lisp_Object* rest;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Positional_Arguments {
|
|
||||||
// TODO(Felix) use Lisp_Object_symbols here instead, so we don't have
|
|
||||||
// to convert them to strings and back to symbols
|
|
||||||
char** identifiers;
|
|
||||||
int next_index;
|
|
||||||
int length;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Keyword_Arguments {
|
|
||||||
char** identifiers;
|
|
||||||
// NOTE(Felix): values[i] will be nullptr if no defalut value was
|
|
||||||
// declared for key identifiers[i]
|
|
||||||
Lisp_Object_Array_List* values;
|
|
||||||
int next_index;
|
|
||||||
int length;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
Positional_Arguments* create_positional_argument_list(int initial_capacity) {
|
Positional_Arguments* create_positional_argument_list(int initial_capacity) {
|
||||||
Positional_Arguments* ret = new(Positional_Arguments);
|
Positional_Arguments* ret = new(Positional_Arguments);
|
||||||
ret->identifiers = (char**)malloc(initial_capacity * sizeof(char*));
|
ret->identifiers = (char**)malloc(initial_capacity * sizeof(char*));
|
||||||
@@ -106,125 +50,3 @@ void append_to_keyword_argument_list(Keyword_Arguments* args,
|
|||||||
args->identifiers[args->next_index++] = identifier;
|
args->identifiers[args->next_index++] = identifier;
|
||||||
append_to_Lisp_Object_array_list(args->values, default_value);
|
append_to_Lisp_Object_array_list(args->values, default_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Environment;
|
|
||||||
|
|
||||||
enum struct Function_Type {
|
|
||||||
Lambda,
|
|
||||||
Special_Lambda,
|
|
||||||
Macro
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Function {
|
|
||||||
Function_Type type;
|
|
||||||
char* docstring;
|
|
||||||
Positional_Arguments* positional_arguments;
|
|
||||||
Keyword_Arguments* keyword_arguments;
|
|
||||||
// rest_argument will be nullptr if no rest argument is declared
|
|
||||||
char* rest_argument;
|
|
||||||
Lisp_Object* body; // implicit prog
|
|
||||||
Environment* parent_environment; // we are doing closures now!!
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
struct CFunction {
|
|
||||||
std::function<Lisp_Object* (Lisp_Object*, Environment*)> function;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Lisp_Object {
|
|
||||||
Source_Code_Location* sourceCodeLocation;
|
|
||||||
Lisp_Object_Type type;
|
|
||||||
union {
|
|
||||||
Symbol* symbol;
|
|
||||||
Keyword* keyword;
|
|
||||||
Number* number;
|
|
||||||
String* string;
|
|
||||||
Pair* pair;
|
|
||||||
Function* function;
|
|
||||||
CFunction* cfunction;
|
|
||||||
} value;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Parsed_Arguments {
|
|
||||||
Lisp_Object_Array_List* positional_arguments;
|
|
||||||
// TODO(Felix): Really use hashmap (keyword[sting] ->
|
|
||||||
// value[Lisp_Object*]) here
|
|
||||||
Lisp_Object_Array_List* keyword_keys;
|
|
||||||
Lisp_Object_Array_List* keyword_values;
|
|
||||||
};
|
|
||||||
|
|
||||||
Lisp_Object* create_lisp_object() {
|
|
||||||
Lisp_Object* node = new(Lisp_Object);
|
|
||||||
node->sourceCodeLocation = nullptr;
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
Lisp_Object* create_lisp_object_nil() {
|
|
||||||
Lisp_Object* node = create_lisp_object();
|
|
||||||
node->type = Lisp_Object_Type::Nil;
|
|
||||||
node->value.pair = nullptr;
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
Lisp_Object* create_lisp_object_t() {
|
|
||||||
Lisp_Object* node = create_lisp_object();
|
|
||||||
node->type = Lisp_Object_Type::T;
|
|
||||||
node->value.pair = nullptr;
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
Lisp_Object* create_lisp_object_number(double number) {
|
|
||||||
Lisp_Object* node = create_lisp_object();
|
|
||||||
node->type = Lisp_Object_Type::Number;
|
|
||||||
node->value.number = new(Number);
|
|
||||||
node->value.number->value = number;
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
Lisp_Object* create_lisp_object_string(char* str, int length) {
|
|
||||||
Lisp_Object* node = create_lisp_object();
|
|
||||||
node->type = Lisp_Object_Type::String;
|
|
||||||
node->value.string = new(String);
|
|
||||||
node->value.string->value = str;
|
|
||||||
node->value.string->length = length;
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
Lisp_Object* create_lisp_object_symbol(char* identifier) {
|
|
||||||
Lisp_Object* node = create_lisp_object();
|
|
||||||
node->type = Lisp_Object_Type::Symbol;
|
|
||||||
node->value.symbol = new(Symbol);
|
|
||||||
node->value.symbol->identifier = identifier;
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
Lisp_Object* create_lisp_object_keyword(char* keyword) {
|
|
||||||
Lisp_Object* node = create_lisp_object();
|
|
||||||
node->type = Lisp_Object_Type::Keyword;
|
|
||||||
node->value.keyword = new(Keyword);
|
|
||||||
node->value.keyword->identifier = keyword;
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
Lisp_Object* create_lisp_object_cfunction(std::function<Lisp_Object*(Lisp_Object*, Environment*)> function) {
|
|
||||||
Lisp_Object* node = create_lisp_object();
|
|
||||||
node->type = Lisp_Object_Type::CFunction;
|
|
||||||
node->value.cfunction = new(CFunction);
|
|
||||||
node->value.cfunction->function = function;
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
Lisp_Object* create_lisp_object_pair(Lisp_Object* first, Lisp_Object* rest) {
|
|
||||||
Lisp_Object* node = create_lisp_object();
|
|
||||||
node->type = Lisp_Object_Type::Pair;
|
|
||||||
node->value.pair = new(Pair);
|
|
||||||
node->value.pair->first = first;
|
|
||||||
node->value.pair->rest = rest;
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
Lisp_Object* copy_lisp_object(Lisp_Object* n) {
|
|
||||||
Lisp_Object* target = create_lisp_object();
|
|
||||||
*target = *n;
|
|
||||||
return target;
|
|
||||||
}
|
|
||||||
|
|||||||
+15
-10
@@ -9,10 +9,12 @@
|
|||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
#include "./helpers.cpp"
|
#include "./helpers.cpp"
|
||||||
|
#include "./structs.cpp"
|
||||||
|
#include "./forward_decls.cpp"
|
||||||
#include "./lisp_object.cpp"
|
#include "./lisp_object.cpp"
|
||||||
#include "./error.cpp"
|
#include "./error.cpp"
|
||||||
#include "./io.cpp"
|
#include "./io.cpp"
|
||||||
#include "./assert.cpp"
|
#include "./memory.cpp"
|
||||||
#include "./env.cpp"
|
#include "./env.cpp"
|
||||||
#include "./parse.cpp"
|
#include "./parse.cpp"
|
||||||
#include "./built_ins.cpp"
|
#include "./built_ins.cpp"
|
||||||
@@ -20,16 +22,17 @@
|
|||||||
#include "./testing.cpp"
|
#include "./testing.cpp"
|
||||||
|
|
||||||
Lisp_Object* interprete_file (char* file_name) {
|
Lisp_Object* interprete_file (char* file_name) {
|
||||||
|
Memory::init();
|
||||||
|
Environment* env = Memory::create_empty_environment();
|
||||||
|
Parser::init(env);
|
||||||
|
|
||||||
char* file_content = read_entire_file(file_name);
|
char* file_content = read_entire_file(file_name);
|
||||||
if (!file_content) {
|
if (!file_content) {
|
||||||
create_error(Error_Type::Unknown_Error, nullptr);
|
create_error(Error_Type::Unknown_Error, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
Environment* env = create_empty_environment();
|
|
||||||
load_built_ins_into_environment(env);
|
load_built_ins_into_environment(env);
|
||||||
|
|
||||||
Parser::init(env);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
built_in_load("pre.slime", env);
|
built_in_load("pre.slime", env);
|
||||||
}
|
}
|
||||||
@@ -39,7 +42,7 @@ Lisp_Object* interprete_file (char* file_name) {
|
|||||||
program = Parser::parse_program(file_name, file_content);
|
program = Parser::parse_program(file_name, file_content);
|
||||||
}
|
}
|
||||||
|
|
||||||
Lisp_Object* result = create_lisp_object_nil();
|
Lisp_Object* result = Memory::create_lisp_object_nil();
|
||||||
for (int i = 0; i < program->next_index; ++i) {
|
for (int i = 0; i < program->next_index; ++i) {
|
||||||
try {
|
try {
|
||||||
result = eval_expr(program->data[i], env);
|
result = eval_expr(program->data[i], env);
|
||||||
@@ -50,12 +53,14 @@ Lisp_Object* interprete_file (char* file_name) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int interprete_stdin () {
|
int interprete_stdin () {
|
||||||
printf("Welcome to the lispy interpreter.\n");
|
Memory::init();
|
||||||
char* line;
|
Environment* env = Memory::create_built_ins_environment();
|
||||||
Environment* env = create_built_ins_environment();
|
|
||||||
|
|
||||||
Parser::init(env);
|
Parser::init(env);
|
||||||
|
|
||||||
|
printf("Welcome to the lispy interpreter.\n");
|
||||||
|
|
||||||
|
char* line;
|
||||||
|
|
||||||
built_in_load("pre.slime", env);
|
built_in_load("pre.slime", env);
|
||||||
built_in_load("test.slime", env);
|
built_in_load("test.slime", env);
|
||||||
|
|
||||||
@@ -94,7 +99,7 @@ int main (int argc, char *argv[]) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
run_all_tests();
|
// run_all_tests();
|
||||||
return interprete_stdin();
|
return interprete_stdin();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+138
@@ -0,0 +1,138 @@
|
|||||||
|
namespace Memory {
|
||||||
|
|
||||||
|
constexpr int maxLispObjects = 4096 * 1024; // == 98304kb == 96mb
|
||||||
|
Int_Array_List* freeSpots;
|
||||||
|
Lisp_Object* memory;
|
||||||
|
int nextFreeSpot = 0;
|
||||||
|
|
||||||
|
void init() {
|
||||||
|
memory = (Lisp_Object*)malloc(maxLispObjects * sizeof(Lisp_Object));
|
||||||
|
freeSpots = create_Int_array_list();
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_status() {
|
||||||
|
printf("Memory Status:\n"
|
||||||
|
" - %f%% of the memory is used\n"
|
||||||
|
" - %d of %d total Lisp_Objects are in use\n"
|
||||||
|
" - %d holes in used memory (fragmentation)\n",
|
||||||
|
(1.0*nextFreeSpot - freeSpots->next_index)/maxLispObjects,
|
||||||
|
nextFreeSpot - freeSpots->next_index, maxLispObjects,
|
||||||
|
freeSpots->next_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
Lisp_Object* create_lisp_object() {
|
||||||
|
int index;
|
||||||
|
// if we have no free spots then append at the end
|
||||||
|
if (freeSpots->next_index == 0) {
|
||||||
|
// if we still have space
|
||||||
|
if (maxLispObjects == nextFreeSpot) {
|
||||||
|
create_error(Error_Type::Out_Of_Memory, nullptr);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
index = nextFreeSpot++;
|
||||||
|
} else {
|
||||||
|
// else fill a free spot
|
||||||
|
index = freeSpots->data[freeSpots->next_index--];
|
||||||
|
}
|
||||||
|
Lisp_Object* object = memory+index;
|
||||||
|
object->sourceCodeLocation = nullptr;
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
|
||||||
|
Lisp_Object* create_lisp_object_nil() {
|
||||||
|
Lisp_Object* node = create_lisp_object();
|
||||||
|
node->type = Lisp_Object_Type::Nil;
|
||||||
|
node->value.pair = nullptr;
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
Lisp_Object* create_lisp_object_t() {
|
||||||
|
Lisp_Object* node = create_lisp_object();
|
||||||
|
node->type = Lisp_Object_Type::T;
|
||||||
|
node->value.pair = nullptr;
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
Lisp_Object* create_lisp_object_number(double number) {
|
||||||
|
Lisp_Object* node = create_lisp_object();
|
||||||
|
node->type = Lisp_Object_Type::Number;
|
||||||
|
node->value.number = new(Number);
|
||||||
|
node->value.number->value = number;
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
Lisp_Object* create_lisp_object_string(char* str, int length) {
|
||||||
|
Lisp_Object* node = create_lisp_object();
|
||||||
|
node->type = Lisp_Object_Type::String;
|
||||||
|
node->value.string = new(String);
|
||||||
|
node->value.string->value = str;
|
||||||
|
node->value.string->length = length;
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
Lisp_Object* create_lisp_object_symbol(char* identifier) {
|
||||||
|
Lisp_Object* node = create_lisp_object();
|
||||||
|
node->type = Lisp_Object_Type::Symbol;
|
||||||
|
node->value.symbol = new(Symbol);
|
||||||
|
node->value.symbol->identifier = identifier;
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
Lisp_Object* create_lisp_object_keyword(char* keyword) {
|
||||||
|
Lisp_Object* node = create_lisp_object();
|
||||||
|
node->type = Lisp_Object_Type::Keyword;
|
||||||
|
node->value.keyword = new(Keyword);
|
||||||
|
node->value.keyword->identifier = keyword;
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
Lisp_Object* create_lisp_object_cfunction(std::function<Lisp_Object*(Lisp_Object*, Environment*)> function) {
|
||||||
|
Lisp_Object* node = create_lisp_object();
|
||||||
|
node->type = Lisp_Object_Type::CFunction;
|
||||||
|
node->value.cfunction = new(CFunction);
|
||||||
|
node->value.cfunction->function = function;
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
Lisp_Object* create_lisp_object_pair(Lisp_Object* first, Lisp_Object* rest) {
|
||||||
|
Lisp_Object* node = create_lisp_object();
|
||||||
|
node->type = Lisp_Object_Type::Pair;
|
||||||
|
node->value.pair = new(Pair);
|
||||||
|
node->value.pair->first = first;
|
||||||
|
node->value.pair->rest = rest;
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
Lisp_Object* copy_lisp_object(Lisp_Object* n) {
|
||||||
|
Lisp_Object* target = create_lisp_object();
|
||||||
|
*target = *n;
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
|
// environments
|
||||||
|
|
||||||
|
Environment* create_child_environment(Environment* parent) {
|
||||||
|
Environment* env = new(Environment);
|
||||||
|
|
||||||
|
int start_capacity = 16;
|
||||||
|
|
||||||
|
env->parent = parent;
|
||||||
|
env->capacity = start_capacity;
|
||||||
|
env->next_index = 0;
|
||||||
|
env->keys = (char**)malloc(start_capacity * sizeof(char*));
|
||||||
|
env->values = (Lisp_Object**)malloc(start_capacity * sizeof(Lisp_Object*));
|
||||||
|
|
||||||
|
return env;
|
||||||
|
}
|
||||||
|
|
||||||
|
Environment* create_empty_environment() {
|
||||||
|
return create_child_environment(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
Environment* create_built_ins_environment() {
|
||||||
|
Environment* ret = create_child_environment(nullptr);
|
||||||
|
load_built_ins_into_environment(ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+23
-32
@@ -1,11 +1,3 @@
|
|||||||
// forward decls -- start
|
|
||||||
void load_built_ins_into_environment(Environment*);
|
|
||||||
Lisp_Object* eval_expr(Lisp_Object*, Environment*);
|
|
||||||
void parse_argument_list(Lisp_Object*, Function*);
|
|
||||||
int list_length(Lisp_Object*);
|
|
||||||
// forward decls -- end
|
|
||||||
|
|
||||||
|
|
||||||
namespace Parser {
|
namespace Parser {
|
||||||
|
|
||||||
#define inject_scl(_ret) \
|
#define inject_scl(_ret) \
|
||||||
@@ -113,7 +105,7 @@ namespace Parser {
|
|||||||
double number;
|
double number;
|
||||||
char* str_number = read_atom(text, index_in_text);
|
char* str_number = read_atom(text, index_in_text);
|
||||||
sscanf(str_number, "%lf", &number);
|
sscanf(str_number, "%lf", &number);
|
||||||
Lisp_Object* ret = create_lisp_object_number(number);
|
Lisp_Object* ret = Memory::create_lisp_object_number(number);
|
||||||
inject_scl(ret);
|
inject_scl(ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -123,7 +115,7 @@ namespace Parser {
|
|||||||
++(*index_in_text);
|
++(*index_in_text);
|
||||||
++parser_col;
|
++parser_col;
|
||||||
char* str_keyword = read_atom(text, index_in_text);
|
char* str_keyword = read_atom(text, index_in_text);
|
||||||
Lisp_Object* ret = create_lisp_object_keyword(str_keyword);
|
Lisp_Object* ret = Memory::create_lisp_object_keyword(str_keyword);
|
||||||
inject_scl(ret);
|
inject_scl(ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -131,7 +123,7 @@ namespace Parser {
|
|||||||
Lisp_Object* parse_symbol(char* text, int* index_in_text) {
|
Lisp_Object* parse_symbol(char* text, int* index_in_text) {
|
||||||
// we are now at the first char of the symbol
|
// we are now at the first char of the symbol
|
||||||
char* str_symbol = read_atom(text, index_in_text);
|
char* str_symbol = read_atom(text, index_in_text);
|
||||||
Lisp_Object* ret = create_lisp_object_symbol(str_symbol);
|
Lisp_Object* ret = Memory::create_lisp_object_symbol(str_symbol);
|
||||||
inject_scl(ret);
|
inject_scl(ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -146,7 +138,7 @@ namespace Parser {
|
|||||||
if (text[*index_in_text] == '"') {
|
if (text[*index_in_text] == '"') {
|
||||||
char* str = new(char);
|
char* str = new(char);
|
||||||
*str = '\0';
|
*str = '\0';
|
||||||
Lisp_Object* ret = create_lisp_object_string(str, 0);
|
Lisp_Object* ret = Memory::create_lisp_object_string(str, 0);
|
||||||
inject_scl(ret);
|
inject_scl(ret);
|
||||||
|
|
||||||
// plus one because we want to go after the quotes
|
// plus one because we want to go after the quotes
|
||||||
@@ -187,7 +179,7 @@ namespace Parser {
|
|||||||
*index_in_text += string_length +1; // plus one because we want to
|
*index_in_text += string_length +1; // plus one because we want to
|
||||||
// go after the quotes
|
// go after the quotes
|
||||||
|
|
||||||
Lisp_Object* ret = create_lisp_object_string(string, string_length);
|
Lisp_Object* ret = Memory::create_lisp_object_string(string, string_length);
|
||||||
inject_scl(ret);
|
inject_scl(ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -246,17 +238,17 @@ namespace Parser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (quoteType == '\'')
|
if (quoteType == '\'')
|
||||||
return create_lisp_object_pair(
|
return Memory::create_lisp_object_pair(
|
||||||
create_lisp_object_symbol("quote"),
|
Memory::create_lisp_object_symbol("quote"),
|
||||||
create_lisp_object_pair(result, create_lisp_object_nil()));
|
Memory::create_lisp_object_pair(result, Memory::create_lisp_object_nil()));
|
||||||
else if (quoteType == '`')
|
else if (quoteType == '`')
|
||||||
return create_lisp_object_pair(
|
return Memory::create_lisp_object_pair(
|
||||||
create_lisp_object_symbol("quasiquote"),
|
Memory::create_lisp_object_symbol("quasiquote"),
|
||||||
create_lisp_object_pair(result, create_lisp_object_nil()));
|
Memory::create_lisp_object_pair(result, Memory::create_lisp_object_nil()));
|
||||||
// it has to be an unquote
|
// it has to be an unquote
|
||||||
return create_lisp_object_pair(
|
return Memory::create_lisp_object_pair(
|
||||||
create_lisp_object_symbol("unquote"),
|
Memory::create_lisp_object_symbol("unquote"),
|
||||||
create_lisp_object_pair(result, create_lisp_object_nil()));
|
Memory::create_lisp_object_pair(result, Memory::create_lisp_object_nil()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -271,11 +263,11 @@ namespace Parser {
|
|||||||
if (text[(*index_in_text)] == ')') {
|
if (text[(*index_in_text)] == ')') {
|
||||||
++(*index_in_text);
|
++(*index_in_text);
|
||||||
++parser_col;
|
++parser_col;
|
||||||
return create_lisp_object_nil();
|
return Memory::create_lisp_object_nil();
|
||||||
}
|
}
|
||||||
|
|
||||||
// okay there is something
|
// okay there is something
|
||||||
Lisp_Object* head = new(Lisp_Object);
|
Lisp_Object* head = Memory::create_lisp_object();
|
||||||
head->type = Lisp_Object_Type::Pair;
|
head->type = Lisp_Object_Type::Pair;
|
||||||
head->value.pair = new(Pair);
|
head->value.pair = new(Pair);
|
||||||
Lisp_Object* expression = head;
|
Lisp_Object* expression = head;
|
||||||
@@ -303,7 +295,7 @@ namespace Parser {
|
|||||||
|
|
||||||
|
|
||||||
if (text[(*index_in_text)] == ')') {
|
if (text[(*index_in_text)] == ')') {
|
||||||
head->value.pair->rest = create_lisp_object_nil();
|
head->value.pair->rest = Memory::create_lisp_object_nil();
|
||||||
++parser_col;
|
++parser_col;
|
||||||
++(*index_in_text);
|
++(*index_in_text);
|
||||||
break;
|
break;
|
||||||
@@ -325,7 +317,7 @@ namespace Parser {
|
|||||||
++(*index_in_text);
|
++(*index_in_text);
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
head->value.pair->rest = create_lisp_object_pair(nullptr, nullptr);
|
head->value.pair->rest = Memory::create_lisp_object_pair(nullptr, nullptr);
|
||||||
head = head->value.pair->rest;
|
head = head->value.pair->rest;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -387,17 +379,17 @@ namespace Parser {
|
|||||||
|
|
||||||
// we are now in the function body, just wrap it in an
|
// we are now in the function body, just wrap it in an
|
||||||
// implicit prog
|
// implicit prog
|
||||||
function->body = create_lisp_object_pair(
|
function->body = Memory::create_lisp_object_pair(
|
||||||
create_lisp_object_symbol("prog"),
|
Memory::create_lisp_object_symbol("prog"),
|
||||||
arguments);
|
arguments);
|
||||||
|
|
||||||
Lisp_Object* macro = new(Lisp_Object);
|
Lisp_Object* macro = Memory::create_lisp_object();
|
||||||
macro->type = Lisp_Object_Type::Function;
|
macro->type = Lisp_Object_Type::Function;
|
||||||
macro->value.function = function;
|
macro->value.function = function;
|
||||||
define_symbol(symbol_for_macro, macro, environment_for_macros);
|
define_symbol(symbol_for_macro, macro, environment_for_macros);
|
||||||
|
|
||||||
// print_environment(environment_for_macros);
|
// print_environment(environment_for_macros);
|
||||||
return create_lisp_object_nil();
|
return Memory::create_lisp_object_nil();
|
||||||
|
|
||||||
} else if (string_equal("delete-syntax", expression->value.pair->first->value.symbol->identifier)) {
|
} else if (string_equal("delete-syntax", expression->value.pair->first->value.symbol->identifier)) {
|
||||||
/* --- deleting an existing macro --- */
|
/* --- deleting an existing macro --- */
|
||||||
@@ -453,7 +445,7 @@ namespace Parser {
|
|||||||
Lisp_Object* result;
|
Lisp_Object* result;
|
||||||
eat_until_code(text, &index_in_text);
|
eat_until_code(text, &index_in_text);
|
||||||
if (text[(index_in_text)] == '\0')
|
if (text[(index_in_text)] == '\0')
|
||||||
return create_lisp_object_nil();
|
return Memory::create_lisp_object_nil();
|
||||||
if (text[index_in_text] == '(' ||
|
if (text[index_in_text] == '(' ||
|
||||||
text[index_in_text] == '\'' ||
|
text[index_in_text] == '\'' ||
|
||||||
text[index_in_text] == '`' ||
|
text[index_in_text] == '`' ||
|
||||||
@@ -536,5 +528,4 @@ namespace Parser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#undef inject_scl
|
#undef inject_scl
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+142
@@ -0,0 +1,142 @@
|
|||||||
|
struct Lisp_Object;
|
||||||
|
struct Environment;
|
||||||
|
|
||||||
|
define_array_list(Lisp_Object*, Lisp_Object);
|
||||||
|
define_array_list(char*, String);
|
||||||
|
define_array_list(int, Int);
|
||||||
|
|
||||||
|
enum struct Lisp_Object_Type {
|
||||||
|
Nil,
|
||||||
|
T,
|
||||||
|
Symbol,
|
||||||
|
Keyword,
|
||||||
|
Number,
|
||||||
|
String,
|
||||||
|
Pair,
|
||||||
|
Function,
|
||||||
|
CFunction,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum struct Log_Level {
|
||||||
|
None,
|
||||||
|
Critical,
|
||||||
|
Warning,
|
||||||
|
Info,
|
||||||
|
Debug,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Symbol {
|
||||||
|
char* identifier;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Keyword {
|
||||||
|
char* identifier;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Number {
|
||||||
|
double value;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct String {
|
||||||
|
char* value;
|
||||||
|
int length;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Pair {
|
||||||
|
Lisp_Object* first;
|
||||||
|
Lisp_Object* rest;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Positional_Arguments {
|
||||||
|
// TODO(Felix) use Lisp_Object_symbols here instead, so we don't have
|
||||||
|
// to convert them to strings and back to symbols
|
||||||
|
char** identifiers;
|
||||||
|
int next_index;
|
||||||
|
int length;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Keyword_Arguments {
|
||||||
|
char** identifiers;
|
||||||
|
// NOTE(Felix): values[i] will be nullptr if no defalut value was
|
||||||
|
// declared for key identifiers[i]
|
||||||
|
Lisp_Object_Array_List* values;
|
||||||
|
int next_index;
|
||||||
|
int length;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum struct Function_Type {
|
||||||
|
Lambda,
|
||||||
|
Special_Lambda,
|
||||||
|
Macro
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Function {
|
||||||
|
Function_Type type;
|
||||||
|
char* docstring;
|
||||||
|
Positional_Arguments* positional_arguments;
|
||||||
|
Keyword_Arguments* keyword_arguments;
|
||||||
|
// rest_argument will be nullptr if no rest argument is declared
|
||||||
|
char* rest_argument;
|
||||||
|
Lisp_Object* body; // implicit prog
|
||||||
|
Environment* parent_environment; // we are doing closures now!!
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct CFunction {
|
||||||
|
std::function<Lisp_Object* (Lisp_Object*, Environment*)> function;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Lisp_Object {
|
||||||
|
Source_Code_Location* sourceCodeLocation;
|
||||||
|
Lisp_Object_Type type;
|
||||||
|
union {
|
||||||
|
Symbol* symbol;
|
||||||
|
Keyword* keyword;
|
||||||
|
Number* number;
|
||||||
|
String* string;
|
||||||
|
Pair* pair;
|
||||||
|
Function* function;
|
||||||
|
CFunction* cfunction;
|
||||||
|
} value;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Parsed_Arguments {
|
||||||
|
Lisp_Object_Array_List* positional_arguments;
|
||||||
|
// TODO(Felix): Really use hashmap (keyword[sting] ->
|
||||||
|
// value[Lisp_Object*]) here
|
||||||
|
Lisp_Object_Array_List* keyword_keys;
|
||||||
|
Lisp_Object_Array_List* keyword_values;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Environment {
|
||||||
|
Environment* parent;
|
||||||
|
|
||||||
|
int capacity;
|
||||||
|
int next_index;
|
||||||
|
// TODO(Felix): Use a hashmap here.
|
||||||
|
char** keys;
|
||||||
|
Lisp_Object** values;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum struct Error_Type {
|
||||||
|
Ill_Formed_Arguments,
|
||||||
|
Ill_Formed_Lambda_List,
|
||||||
|
Ill_Formed_List,
|
||||||
|
Not_A_Function,
|
||||||
|
Not_Yet_Implemented,
|
||||||
|
Symbol_Not_Defined,
|
||||||
|
Syntax_Error,
|
||||||
|
Trailing_Garbage,
|
||||||
|
Type_Missmatch,
|
||||||
|
Unbalanced_Parenthesis,
|
||||||
|
Unexpected_Eof,
|
||||||
|
Unknown_Error,
|
||||||
|
Unknown_Keyword_Argument,
|
||||||
|
Wrong_Number_Of_Arguments,
|
||||||
|
Out_Of_Memory,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Error {
|
||||||
|
Error_Type type;
|
||||||
|
Source_Code_Location* location;
|
||||||
|
};
|
||||||
+15
-14
@@ -89,7 +89,7 @@ testresult test_eval_operands() {
|
|||||||
char operands_string[] = "((eval 1) (+ 1 2) \"okay\" (eval :haha))";
|
char operands_string[] = "((eval 1) (+ 1 2) \"okay\" (eval :haha))";
|
||||||
Lisp_Object* operands = Parser::parse_single_expression(operands_string);
|
Lisp_Object* operands = Parser::parse_single_expression(operands_string);
|
||||||
int operands_length;
|
int operands_length;
|
||||||
operands = eval_arguments(operands, create_built_ins_environment(), &operands_length);
|
operands = eval_arguments(operands, Memory::create_built_ins_environment(), &operands_length);
|
||||||
|
|
||||||
assert_no_error(error);
|
assert_no_error(error);
|
||||||
assert_equal_int(list_length(operands), 4);
|
assert_equal_int(list_length(operands), 4);
|
||||||
@@ -233,7 +233,7 @@ testresult test_parse_expression() {
|
|||||||
testresult test_built_in_add() {
|
testresult test_built_in_add() {
|
||||||
char exp_string[] = "(+ 10 4)";
|
char exp_string[] = "(+ 10 4)";
|
||||||
Lisp_Object* expression = Parser::parse_single_expression(exp_string);
|
Lisp_Object* expression = Parser::parse_single_expression(exp_string);
|
||||||
Lisp_Object* result = eval_expr(expression, create_built_ins_environment());
|
Lisp_Object* result = eval_expr(expression, Memory::create_built_ins_environment());
|
||||||
|
|
||||||
assert_no_error(error);
|
assert_no_error(error);
|
||||||
assert_not_null(result);
|
assert_not_null(result);
|
||||||
@@ -246,7 +246,7 @@ testresult test_built_in_add() {
|
|||||||
testresult test_built_in_substract() {
|
testresult test_built_in_substract() {
|
||||||
char exp_string[] = "(- 10 4)";
|
char exp_string[] = "(- 10 4)";
|
||||||
Lisp_Object* expression = Parser::parse_single_expression(exp_string);
|
Lisp_Object* expression = Parser::parse_single_expression(exp_string);
|
||||||
Lisp_Object* result = eval_expr(expression, create_built_ins_environment());
|
Lisp_Object* result = eval_expr(expression, Memory::create_built_ins_environment());
|
||||||
|
|
||||||
assert_no_error(error);
|
assert_no_error(error);
|
||||||
assert_not_null(result);
|
assert_not_null(result);
|
||||||
@@ -260,7 +260,7 @@ testresult test_built_in_substract() {
|
|||||||
testresult test_built_in_multiply() {
|
testresult test_built_in_multiply() {
|
||||||
char exp_string[] = "(* 10 4)";
|
char exp_string[] = "(* 10 4)";
|
||||||
Lisp_Object* expression = Parser::parse_single_expression(exp_string);
|
Lisp_Object* expression = Parser::parse_single_expression(exp_string);
|
||||||
Lisp_Object* result = eval_expr(expression, create_built_ins_environment());
|
Lisp_Object* result = eval_expr(expression, Memory::create_built_ins_environment());
|
||||||
|
|
||||||
assert_no_error(error);
|
assert_no_error(error);
|
||||||
assert_not_null(result);
|
assert_not_null(result);
|
||||||
@@ -274,7 +274,7 @@ testresult test_built_in_multiply() {
|
|||||||
testresult test_built_in_divide() {
|
testresult test_built_in_divide() {
|
||||||
char exp_string[] = "(/ 20 4)";
|
char exp_string[] = "(/ 20 4)";
|
||||||
Lisp_Object* expression = Parser::parse_single_expression(exp_string);
|
Lisp_Object* expression = Parser::parse_single_expression(exp_string);
|
||||||
Lisp_Object* result = eval_expr(expression, create_built_ins_environment());
|
Lisp_Object* result = eval_expr(expression, Memory::create_built_ins_environment());
|
||||||
|
|
||||||
assert_null(error);
|
assert_null(error);
|
||||||
assert_not_null(result);
|
assert_not_null(result);
|
||||||
@@ -288,7 +288,7 @@ testresult test_built_in_divide() {
|
|||||||
testresult test_built_in_if() {
|
testresult test_built_in_if() {
|
||||||
char exp_string1[] = "(if 1 4 5)";
|
char exp_string1[] = "(if 1 4 5)";
|
||||||
Lisp_Object* expression = Parser::parse_single_expression(exp_string1);
|
Lisp_Object* expression = Parser::parse_single_expression(exp_string1);
|
||||||
Lisp_Object* result = eval_expr(expression, create_built_ins_environment());
|
Lisp_Object* result = eval_expr(expression, Memory::create_built_ins_environment());
|
||||||
|
|
||||||
assert_no_error(error);
|
assert_no_error(error);
|
||||||
assert_not_null(result);
|
assert_not_null(result);
|
||||||
@@ -297,7 +297,7 @@ testresult test_built_in_if() {
|
|||||||
|
|
||||||
char exp_string2[] = "(if () 4 5)";
|
char exp_string2[] = "(if () 4 5)";
|
||||||
expression = Parser::parse_single_expression(exp_string2);
|
expression = Parser::parse_single_expression(exp_string2);
|
||||||
result = eval_expr(expression, create_built_ins_environment());
|
result = eval_expr(expression, Memory::create_built_ins_environment());
|
||||||
|
|
||||||
assert_no_error(error);
|
assert_no_error(error);
|
||||||
assert_not_null(result);
|
assert_not_null(result);
|
||||||
@@ -310,7 +310,7 @@ testresult test_built_in_if() {
|
|||||||
testresult test_built_in_and() {
|
testresult test_built_in_and() {
|
||||||
char exp_string1[] = "(and 1 \"asd\" 4)";
|
char exp_string1[] = "(and 1 \"asd\" 4)";
|
||||||
Lisp_Object* expression = Parser::parse_single_expression(exp_string1);
|
Lisp_Object* expression = Parser::parse_single_expression(exp_string1);
|
||||||
Lisp_Object* result = eval_expr(expression, create_built_ins_environment());
|
Lisp_Object* result = eval_expr(expression, Memory::create_built_ins_environment());
|
||||||
|
|
||||||
assert_no_error(error);
|
assert_no_error(error);
|
||||||
assert_not_null(result);
|
assert_not_null(result);
|
||||||
@@ -319,7 +319,7 @@ testresult test_built_in_and() {
|
|||||||
// a false case
|
// a false case
|
||||||
char exp_string2[] = "(and () \"asd\" 4)";
|
char exp_string2[] = "(and () \"asd\" 4)";
|
||||||
expression = Parser::parse_single_expression(exp_string2);
|
expression = Parser::parse_single_expression(exp_string2);
|
||||||
result = eval_expr(expression, create_built_ins_environment());
|
result = eval_expr(expression, Memory::create_built_ins_environment());
|
||||||
|
|
||||||
assert_no_error(error);
|
assert_no_error(error);
|
||||||
assert_not_null(result);
|
assert_not_null(result);
|
||||||
@@ -331,7 +331,7 @@ testresult test_built_in_and() {
|
|||||||
testresult test_built_in_or() {
|
testresult test_built_in_or() {
|
||||||
char exp_string1[] = "(or \"asd\" nil)";
|
char exp_string1[] = "(or \"asd\" nil)";
|
||||||
Lisp_Object* expression = Parser::parse_single_expression(exp_string1);
|
Lisp_Object* expression = Parser::parse_single_expression(exp_string1);
|
||||||
Lisp_Object* result = eval_expr(expression, create_built_ins_environment());
|
Lisp_Object* result = eval_expr(expression, Memory::create_built_ins_environment());
|
||||||
|
|
||||||
assert_no_error(error);
|
assert_no_error(error);
|
||||||
assert_not_null(result);
|
assert_not_null(result);
|
||||||
@@ -340,7 +340,7 @@ testresult test_built_in_or() {
|
|||||||
// a false case
|
// a false case
|
||||||
char exp_string2[] = "(or () ())";
|
char exp_string2[] = "(or () ())";
|
||||||
expression = Parser::parse_single_expression(exp_string2);
|
expression = Parser::parse_single_expression(exp_string2);
|
||||||
result = eval_expr(expression, create_built_ins_environment());
|
result = eval_expr(expression, Memory::create_built_ins_environment());
|
||||||
|
|
||||||
assert_no_error(error);
|
assert_no_error(error);
|
||||||
assert_not_null(result);
|
assert_not_null(result);
|
||||||
@@ -353,7 +353,7 @@ testresult test_built_in_or() {
|
|||||||
testresult test_built_in_not() {
|
testresult test_built_in_not() {
|
||||||
char exp_string1[] = "(not ())";
|
char exp_string1[] = "(not ())";
|
||||||
Lisp_Object* expression = Parser::parse_single_expression(exp_string1);
|
Lisp_Object* expression = Parser::parse_single_expression(exp_string1);
|
||||||
Lisp_Object* result = eval_expr(expression, create_built_ins_environment());
|
Lisp_Object* result = eval_expr(expression, Memory::create_built_ins_environment());
|
||||||
|
|
||||||
// a true case
|
// a true case
|
||||||
assert_no_error(error);
|
assert_no_error(error);
|
||||||
@@ -363,7 +363,7 @@ testresult test_built_in_not() {
|
|||||||
// a false case
|
// a false case
|
||||||
char exp_string2[] = "(not \"asd xD\")";
|
char exp_string2[] = "(not \"asd xD\")";
|
||||||
expression = Parser::parse_single_expression(exp_string2);
|
expression = Parser::parse_single_expression(exp_string2);
|
||||||
result = eval_expr(expression, create_built_ins_environment());
|
result = eval_expr(expression, Memory::create_built_ins_environment());
|
||||||
|
|
||||||
assert_no_error(error);
|
assert_no_error(error);
|
||||||
assert_not_null(result);
|
assert_not_null(result);
|
||||||
@@ -374,7 +374,8 @@ testresult test_built_in_not() {
|
|||||||
|
|
||||||
void run_all_tests() {
|
void run_all_tests() {
|
||||||
log_level = Log_Level::None;
|
log_level = Log_Level::None;
|
||||||
Parser::init(create_built_ins_environment());
|
Memory::init();
|
||||||
|
Parser::init(Memory::create_built_ins_environment());
|
||||||
|
|
||||||
printf("-- Parsing --\n");
|
printf("-- Parsing --\n");
|
||||||
invoke_test(test_parse_atom);
|
invoke_test(test_parse_atom);
|
||||||
|
|||||||
Reference in New Issue
Block a user