singulat t and nil

This commit is contained in:
Felix Brendel
2019-02-24 14:44:23 +01:00
parent 8c827029be
commit 1bd77be7f6
7 changed files with 162 additions and 107 deletions
+47 -47
View File
@@ -43,7 +43,7 @@ proc lisp_object_equal(Lisp_Object* n1, Lisp_Object* n2) -> bool {
proc built_in_load(String* file_name, Environment* env) -> Lisp_Object* {
char* file_content = read_entire_file(Memory::get_c_str(file_name));
if (file_content) {
Lisp_Object* result = Memory::create_lisp_object_nil();
Lisp_Object* result = Memory::nil;
Lisp_Object_Array_List* program;
try {
program = Parser::parse_program(file_name, file_content);
@@ -72,7 +72,7 @@ proc load_built_ins_into_environment(Environment* env) -> void {
proc defun = [&](const char* name, auto fun) {
define_symbol(
Memory::create_lisp_object_symbol(name),
Memory::get_or_create_lisp_object_symbol(name),
Memory::create_lisp_object_cfunction(fun),
env);
};
@@ -84,17 +84,17 @@ proc load_built_ins_into_environment(Environment* env) -> void {
}
if (arguments->type == Lisp_Object_Type::Nil)
return Memory::create_lisp_object_t();
return Memory::t;
Lisp_Object* first = arguments->value.pair->first;
while (arguments->type == Lisp_Object_Type::Pair) {
if (!lisp_object_equal(arguments->value.pair->first, first))
return Memory::create_lisp_object_nil();
return Memory::nil;
arguments = arguments->value.pair->rest;
}
return Memory::create_lisp_object_t();
return Memory::t;
});
defun(">", cLambda {
int arguments_length;
@@ -110,13 +110,13 @@ proc load_built_ins_into_environment(Environment* env) -> void {
}
if (arguments->value.pair->first->value.number->value >= last_number)
return Memory::create_lisp_object_nil();
return Memory::nil;
last_number = arguments->value.pair->first->value.number->value;
arguments = arguments->value.pair->rest;
}
return Memory::create_lisp_object_t();
return Memory::t;
});
defun(">=", cLambda {
int arguments_length;
@@ -132,13 +132,13 @@ proc load_built_ins_into_environment(Environment* env) -> void {
}
if (arguments->value.pair->first->value.number->value > last_number)
return Memory::create_lisp_object_nil();
return Memory::nil;
last_number = arguments->value.pair->first->value.number->value;
arguments = arguments->value.pair->rest;
}
return Memory::create_lisp_object_t();
return Memory::t;
});
defun("<", cLambda {
int arguments_length;
@@ -154,13 +154,13 @@ proc load_built_ins_into_environment(Environment* env) -> void {
}
if (arguments->value.pair->first->value.number->value <= last_number)
return Memory::create_lisp_object_nil();
return Memory::nil;
last_number = arguments->value.pair->first->value.number->value;
arguments = arguments->value.pair->rest;
}
return Memory::create_lisp_object_t();
return Memory::t;
});
defun("<=", cLambda {
int arguments_length;
@@ -176,13 +176,13 @@ proc load_built_ins_into_environment(Environment* env) -> void {
}
if (arguments->value.pair->first->value.number->value < last_number)
return Memory::create_lisp_object_nil();
return Memory::nil;
last_number = arguments->value.pair->first->value.number->value;
arguments = arguments->value.pair->rest;
}
return Memory::create_lisp_object_t();
return Memory::t;
});
defun("+", cLambda {
int arguments_length;
@@ -407,7 +407,7 @@ proc load_built_ins_into_environment(Environment* env) -> void {
try {
result = eval_expr(else_part->value.pair->first, env);
}
else return Memory::create_lisp_object_nil();
else return Memory::nil;
return result;
});
defun("quote", cLambda {
@@ -474,7 +474,7 @@ proc load_built_ins_into_environment(Environment* env) -> void {
newPairHead = newPairHead->value.pair->rest;
head = head->value.pair->rest;
}
newPairHead->value.pair->rest = Memory::create_lisp_object_nil();
newPairHead->value.pair->rest = Memory::nil;
return newPair;
};
@@ -496,10 +496,10 @@ proc load_built_ins_into_environment(Environment* env) -> void {
}
arguments = arguments->value.pair->rest;
if (!result) return Memory::create_lisp_object_nil();
if (!result) return Memory::nil;
}
return Memory::create_lisp_object_t();
return Memory::t;
});
defun("or", cLambda {
bool result = false;
@@ -512,10 +512,10 @@ proc load_built_ins_into_environment(Environment* env) -> void {
}
arguments = arguments->value.pair->rest;
if (result) return Memory::create_lisp_object_t();
if (result) return Memory::t;
}
return Memory::create_lisp_object_nil();
return Memory::nil;
});
defun("not", cLambda {
try {
@@ -530,8 +530,8 @@ proc load_built_ins_into_environment(Environment* env) -> void {
truthy = is_truthy(arguments->value.pair->first, env);
}
if (truthy)
return Memory::create_lisp_object_nil();
return Memory::create_lisp_object_t();
return Memory::nil;
return Memory::t;
});
defun("while", cLambda {
try {
@@ -544,7 +544,7 @@ proc load_built_ins_into_environment(Environment* env) -> void {
Lisp_Object* condition_part = arguments->value.pair->first;
Lisp_Object* condition;
Lisp_Object* then_part = arguments->value.pair->rest;
Lisp_Object* result = Memory::create_lisp_object_nil();
Lisp_Object* result = Memory::nil;
while (true) {
try {
@@ -659,7 +659,7 @@ proc load_built_ins_into_environment(Environment* env) -> void {
// we are now in the function body, just wrap it in an
// implicit prog
function->body = Memory::create_lisp_object_pair(
Memory::create_lisp_object_symbol("prog"),
Memory::get_or_create_lisp_object_symbol("prog"),
arguments);
Lisp_Object* ret = Memory::create_lisp_object();
@@ -709,7 +709,7 @@ proc load_built_ins_into_environment(Environment* env) -> void {
// we are now in the function body, just wrap it in an
// implicit prog
function->body = Memory::create_lisp_object_pair(
Memory::create_lisp_object_symbol("prog"),
Memory::get_or_create_lisp_object_symbol("prog"),
arguments);
Lisp_Object* ret = Memory::create_lisp_object();
@@ -774,7 +774,7 @@ proc load_built_ins_into_environment(Environment* env) -> void {
report_error(Error_Type::Wrong_Number_Of_Arguments);
}
if (evaluated_arguments->value.pair->first->type == Lisp_Object_Type::Nil)
return Memory::create_lisp_object_nil();
return Memory::nil;
if (evaluated_arguments->value.pair->first->type != Lisp_Object_Type::Pair)
report_error(Error_Type::Type_Missmatch);
@@ -788,7 +788,7 @@ proc load_built_ins_into_environment(Environment* env) -> void {
report_error(Error_Type::Wrong_Number_Of_Arguments);
}
if (evaluated_arguments->value.pair->first->type == Lisp_Object_Type::Nil)
return Memory::create_lisp_object_nil();
return Memory::nil;
if (evaluated_arguments->value.pair->first->type != Lisp_Object_Type::Pair)
report_error(Error_Type::Type_Missmatch);
@@ -821,7 +821,7 @@ proc load_built_ins_into_environment(Environment* env) -> void {
report_error(Error_Type::Wrong_Number_Of_Arguments);
}
evaluated_arguments->value.pair->first->userType = nullptr;
return Memory::create_lisp_object_t();
return Memory::t;
});
defun("type", cLambda {
try {
@@ -837,26 +837,26 @@ proc load_built_ins_into_environment(Environment* env) -> void {
Lisp_Object_Type type = evaluated_arguments->value.pair->first->type;
switch (type) {
case Lisp_Object_Type::CFunction: return Memory::create_lisp_object_keyword("cfunction");
case Lisp_Object_Type::CFunction: return Memory::get_or_create_lisp_object_keyword("cfunction");
case Lisp_Object_Type::Function: {
Function* fun = evaluated_arguments->value.pair->first->value.function;
if (fun->type == Function_Type::Lambda)
return Memory::create_lisp_object_keyword("lambda");
return Memory::get_or_create_lisp_object_keyword("lambda");
else if (fun->type == Function_Type::Special_Lambda)
return Memory::create_lisp_object_keyword("special-lambda");
return Memory::get_or_create_lisp_object_keyword("special-lambda");
else if (fun->type == Function_Type::Macro)
return Memory::create_lisp_object_keyword("macro");
else return Memory::create_lisp_object_keyword("unknown");
return Memory::get_or_create_lisp_object_keyword("macro");
else return Memory::get_or_create_lisp_object_keyword("unknown");
}
case Lisp_Object_Type::Keyword: return Memory::create_lisp_object_keyword("keyword");
case Lisp_Object_Type::Nil: return Memory::create_lisp_object_keyword("nil");
case Lisp_Object_Type::T: return Memory::create_lisp_object_keyword("t");
case Lisp_Object_Type::Number: return Memory::create_lisp_object_keyword("number");
case Lisp_Object_Type::Pair: return Memory::create_lisp_object_keyword("pair");
case Lisp_Object_Type::String: return Memory::create_lisp_object_keyword("string");
case Lisp_Object_Type::Symbol: return Memory::create_lisp_object_keyword("symbol");
case Lisp_Object_Type::Keyword: return Memory::get_or_create_lisp_object_keyword("keyword");
case Lisp_Object_Type::Nil: return Memory::get_or_create_lisp_object_keyword("nil");
case Lisp_Object_Type::T: return Memory::get_or_create_lisp_object_keyword("t");
case Lisp_Object_Type::Number: return Memory::get_or_create_lisp_object_keyword("number");
case Lisp_Object_Type::Pair: return Memory::get_or_create_lisp_object_keyword("pair");
case Lisp_Object_Type::String: return Memory::get_or_create_lisp_object_keyword("string");
case Lisp_Object_Type::Symbol: return Memory::get_or_create_lisp_object_keyword("symbol");
}
return Memory::create_lisp_object_keyword("unknown");
return Memory::get_or_create_lisp_object_keyword("unknown");
});
defun("info", cLambda {
try {
@@ -871,8 +871,8 @@ proc load_built_ins_into_environment(Environment* env) -> void {
Lisp_Object* type = eval_expr(
Memory::create_lisp_object_pair(
Memory::create_lisp_object_symbol("type"),
Memory::create_lisp_object_pair(arguments->value.pair->first, Memory::create_lisp_object_nil())),
Memory::get_or_create_lisp_object_symbol("type"),
Memory::create_lisp_object_pair(arguments->value.pair->first, Memory::nil)),
env);
if (type) {
@@ -936,7 +936,7 @@ proc load_built_ins_into_environment(Environment* env) -> void {
delete_error();
}
return Memory::create_lisp_object_nil();
return Memory::nil;
});
defun("print", cLambda {
try {
@@ -947,7 +947,7 @@ proc load_built_ins_into_environment(Environment* env) -> void {
}
print(evaluated_arguments->value.pair->first);
// printf("\n");
return Memory::create_lisp_object_nil();
return Memory::nil;
});
defun("read", cLambda {
try {
@@ -991,11 +991,11 @@ proc load_built_ins_into_environment(Environment* env) -> void {
defun("break", cLambda {
print_environment(env);
debug_break();
return Memory::create_lisp_object_nil();
return Memory::nil;
});
defun("memstat", cLambda {
Memory::print_status();
return Memory::create_lisp_object_nil();
return Memory::nil;
});
defun("try", cLambda {
try {
@@ -1089,7 +1089,7 @@ proc load_built_ins_into_environment(Environment* env) -> void {
report_error(Error_Type::Type_Missmatch);
}
return Memory::create_lisp_object_symbol(Memory::duplicate_string(source->value.string));
return Memory::get_or_create_lisp_object_symbol(Memory::duplicate_string(source->value.string));
});
defun("symbol->string", cLambda {
try {
+2 -2
View File
@@ -39,10 +39,10 @@ proc lookup_symbol(Lisp_Object* node, Environment* env) -> Lisp_Object* {
}
if (string_equal(Memory::get_c_str(sym->identifier), "nil")) {
return Memory::create_lisp_object_nil();
return Memory::nil;
}
if (string_equal(Memory::get_c_str(sym->identifier), "t")) {
return Memory::create_lisp_object_t();
return Memory::t;
}
create_error(Error_Type::Symbol_Not_Defined, node->sourceCodeLocation);
+10 -14
View File
@@ -8,7 +8,7 @@ proc apply_arguments_to_function(Lisp_Object* arguments, Function* function) ->
// their identifiers but before we converted them to
// strings from symbols... Wo maybe just use the symbols?
define_symbol(
Memory::create_lisp_object_symbol(function->positional_arguments->identifiers[i]),
Memory::get_or_create_lisp_object_symbol(function->positional_arguments->identifiers[i]),
arguments->value.pair->first, new_env);
} else {
@@ -69,7 +69,7 @@ proc apply_arguments_to_function(Lisp_Object* arguments, Function* function) ->
// if not set it and then add it to the array list
define_symbol(
Memory::create_lisp_object_symbol(arguments->value.pair->first->value.keyword->identifier),
Memory::get_or_create_lisp_object_symbol(arguments->value.pair->first->value.keyword->identifier),
arguments->value.pair->rest->value.pair->first,
new_env);
@@ -108,7 +108,7 @@ proc apply_arguments_to_function(Lisp_Object* arguments, Function* function) ->
// to use it or if the user supplied his own
if (!was_set) {
define_symbol(
Memory::create_lisp_object_symbol(defined_keyword),
Memory::get_or_create_lisp_object_symbol(defined_keyword),
Memory::copy_lisp_object(function->keyword_arguments->values->data[i]), new_env);
}
}
@@ -118,13 +118,13 @@ proc apply_arguments_to_function(Lisp_Object* arguments, Function* function) ->
if (arguments->type == Lisp_Object_Type::Nil) {
if (function->rest_argument) {
define_symbol(
Memory::create_lisp_object_symbol(function->rest_argument),
Memory::create_lisp_object_nil(), new_env);
Memory::get_or_create_lisp_object_symbol(function->rest_argument),
Memory::nil, new_env);
}
} else {
if (function->rest_argument) {
define_symbol(
Memory::create_lisp_object_symbol(function->rest_argument),
Memory::get_or_create_lisp_object_symbol(function->rest_argument),
arguments, new_env);
} else {
// rest was not declared but additional arguments were found
@@ -353,12 +353,12 @@ proc eval_expr(Lisp_Object* node, Environment* env) -> Lisp_Object* {
return nullptr; \
}
if (error)
return nullptr;
switch (node->type) {
case Lisp_Object_Type::T:
case Lisp_Object_Type::Nil:
case Lisp_Object_Type::Number:
case Lisp_Object_Type::Keyword:
case Lisp_Object_Type::String:
return node;
case Lisp_Object_Type::Symbol: {
Lisp_Object* symbol;
@@ -367,10 +367,6 @@ proc eval_expr(Lisp_Object* node, Environment* env) -> Lisp_Object* {
}
return symbol;
}
case Lisp_Object_Type::Number:
case Lisp_Object_Type::Keyword:
case Lisp_Object_Type::String:
return node;
case Lisp_Object_Type::Pair: {
Lisp_Object* lispOperator;
if (node->value.pair->first->type != Lisp_Object_Type::CFunction &&
@@ -448,7 +444,7 @@ proc interprete_file (char* file_name) -> Lisp_Object* {
Memory::create_string(file_name), file_content);
}
Lisp_Object* result = Memory::create_lisp_object_nil();
Lisp_Object* result = Memory::nil;
for (int i = 0; i < program->next_index; ++i) {
try {
result = eval_expr(program->data[i], env);
+46 -25
View File
@@ -19,15 +19,12 @@ namespace Memory {
String* string_memory;
String* next_free_spot_in_string_memory;
proc init() {
free_spots_in_object_memory = create_Int_array_list();
free_spots_in_string_memory = create_Void_Ptr_array_list();
object_memory = (Lisp_Object*)malloc(object_memory_size * sizeof(Lisp_Object));
string_memory = (String*)malloc(object_memory_size * sizeof(Lisp_Object));
next_free_spot_in_string_memory = string_memory;
}
// ------------------
// immutables
// ------------------
Lisp_Object* nil = nullptr;
Lisp_Object* t = nullptr;
proc print_status() {
printf("Memory Status:\n"
@@ -99,19 +96,39 @@ namespace Memory {
return object;
}
proc create_lisp_object_nil() -> Lisp_Object* {
Lisp_Object* node = create_lisp_object();
node->type = Lisp_Object_Type::Nil;
node->value.pair = nullptr;
return node;
proc init() {
free_spots_in_object_memory = create_Int_array_list();
free_spots_in_string_memory = create_Void_Ptr_array_list();
object_memory = (Lisp_Object*)malloc(object_memory_size * sizeof(Lisp_Object));
string_memory = (String*)malloc(object_memory_size * sizeof(Lisp_Object));
next_free_spot_in_string_memory = string_memory;
// init nil
nil = create_lisp_object();
nil->type = Lisp_Object_Type::Nil;
nil->value.pair = nullptr;
// init t
t = create_lisp_object();
t->type = Lisp_Object_Type::T;
t->value.pair = nullptr;
}
proc create_lisp_object_t() -> Lisp_Object* {
Lisp_Object* node = create_lisp_object();
node->type = Lisp_Object_Type::T;
node->value.pair = nullptr;
return node;
}
// proc get_lisp_object_nil() -> Lisp_Object* {
// Lisp_Object* node = create_lisp_object();
// node->type = Lisp_Object_Type::Nil;
// node->value.pair = nullptr;
// return node;
// }
// proc get_lisp_object_t() -> Lisp_Object* {
// Lisp_Object* node = create_lisp_object();
// node->type = Lisp_Object_Type::T;
// node->value.pair = nullptr;
// return node;
// }
proc create_lisp_object_number(double number) -> Lisp_Object* {
Lisp_Object* node = create_lisp_object();
@@ -128,7 +145,9 @@ namespace Memory {
return node;
}
proc create_lisp_object_symbol(String* identifier) -> Lisp_Object* {
proc get_or_create_lisp_object_symbol(String* identifier) -> Lisp_Object* {
// TODO(Felix): if we already have it stored somewhere then
// reuse it and dont create new one
Lisp_Object* node = create_lisp_object();
node->type = Lisp_Object_Type::Symbol;
node->value.symbol = new(Symbol);
@@ -136,12 +155,14 @@ namespace Memory {
return node;
}
proc create_lisp_object_symbol(const char* identifier) -> Lisp_Object* {
return create_lisp_object_symbol(
proc get_or_create_lisp_object_symbol(const char* identifier) -> Lisp_Object* {
return get_or_create_lisp_object_symbol(
Memory::create_string(identifier));
}
proc create_lisp_object_keyword(String* keyword) -> Lisp_Object* {
proc get_or_create_lisp_object_keyword(String* keyword) -> Lisp_Object* {
// TODO(Felix): if we already have it stored somewhere then
// reuse it and dont create new one
Lisp_Object* node = create_lisp_object();
node->type = Lisp_Object_Type::Keyword;
node->value.keyword = new(Keyword);
@@ -149,8 +170,8 @@ namespace Memory {
return node;
}
proc create_lisp_object_keyword(const char* keyword) -> Lisp_Object* {
return create_lisp_object_keyword(
proc get_or_create_lisp_object_keyword(const char* keyword) -> Lisp_Object* {
return get_or_create_lisp_object_keyword(
Memory::create_string(keyword));
}
+13 -13
View File
@@ -119,7 +119,7 @@ namespace Parser {
++(*index_in_text);
++parser_col;
String* str_keyword = read_atom(text, index_in_text);
Lisp_Object* ret = Memory::create_lisp_object_keyword(str_keyword);
Lisp_Object* ret = Memory::get_or_create_lisp_object_keyword(str_keyword);
inject_scl(ret);
return ret;
@@ -128,7 +128,7 @@ namespace Parser {
proc parse_symbol(char* text, int* index_in_text) -> Lisp_Object* {
// we are now at the first char of the symbol
String* str_symbol = read_atom(text, index_in_text);
Lisp_Object* ret = Memory::create_lisp_object_symbol(str_symbol);
Lisp_Object* ret = Memory::get_or_create_lisp_object_symbol(str_symbol);
inject_scl(ret);
return ret;
}
@@ -243,16 +243,16 @@ namespace Parser {
if (quoteType == '\'')
return Memory::create_lisp_object_pair(
Memory::create_lisp_object_symbol("quote"),
Memory::create_lisp_object_pair(result, Memory::create_lisp_object_nil()));
Memory::get_or_create_lisp_object_symbol("quote"),
Memory::create_lisp_object_pair(result, Memory::nil));
else if (quoteType == '`')
return Memory::create_lisp_object_pair(
Memory::create_lisp_object_symbol("quasiquote"),
Memory::create_lisp_object_pair(result, Memory::create_lisp_object_nil()));
Memory::get_or_create_lisp_object_symbol("quasiquote"),
Memory::create_lisp_object_pair(result, Memory::nil));
// it has to be an unquote
return Memory::create_lisp_object_pair(
Memory::create_lisp_object_symbol("unquote"),
Memory::create_lisp_object_pair(result, Memory::create_lisp_object_nil()));
Memory::get_or_create_lisp_object_symbol("unquote"),
Memory::create_lisp_object_pair(result, Memory::nil));
}
@@ -267,7 +267,7 @@ namespace Parser {
if (text[(*index_in_text)] == ')') {
++(*index_in_text);
++parser_col;
return Memory::create_lisp_object_nil();
return Memory::nil;
}
// okay there is something
@@ -299,7 +299,7 @@ namespace Parser {
if (text[(*index_in_text)] == ')') {
head->value.pair->rest = Memory::create_lisp_object_nil();
head->value.pair->rest = Memory::nil;
++parser_col;
++(*index_in_text);
break;
@@ -384,7 +384,7 @@ namespace Parser {
// we are now in the function body, just wrap it in an
// implicit prog
function->body = Memory::create_lisp_object_pair(
Memory::create_lisp_object_symbol("prog"),
Memory::get_or_create_lisp_object_symbol("prog"),
arguments);
Lisp_Object* macro = Memory::create_lisp_object();
@@ -393,7 +393,7 @@ namespace Parser {
define_symbol(symbol_for_macro, macro, environment_for_macros);
// print_environment(environment_for_macros);
return Memory::create_lisp_object_nil();
return Memory::nil;
} else if (string_equal("delete-syntax", expression->value.pair->first->value.symbol->identifier)) {
/* --- deleting an existing macro --- */
@@ -449,7 +449,7 @@ namespace Parser {
Lisp_Object* result;
eat_until_code(text, &index_in_text);
if (text[(index_in_text)] == '\0')
return Memory::create_lisp_object_nil();
return Memory::nil;
if (text[index_in_text] == '(' ||
text[index_in_text] == '\'' ||
text[index_in_text] == '`' ||
+37
View File
@@ -425,6 +425,41 @@ proc test_built_in_type() -> testresult {
return pass;
}
proc test_singular_t_and_nil() -> testresult {
Environment* env = Memory::create_built_ins_environment();
// nil testing
char exp_string1[] = "()";
char exp_string2[] = "nil";
Lisp_Object* expression = Parser::parse_single_expression(exp_string1);
Lisp_Object* result = eval_expr(expression, env);
assert_no_error();
assert_not_null(result);
assert_equal_type(result, Lisp_Object_Type::Nil);
assert_equal_int(expression, result);
Lisp_Object* expression2 = Parser::parse_single_expression(exp_string2);
Lisp_Object* result2 = eval_expr(expression2, env);
assert_no_error();
assert_not_null(result);
assert_equal_type(result, Lisp_Object_Type::Nil);
assert_equal_int(result, result2);
assert_equal_int(expression, Memory::nil);
// t testing
char exp_string3[] = "t";
Lisp_Object* expression3 = Parser::parse_single_expression(exp_string3);
Lisp_Object* result3 = eval_expr(expression3, env);
assert_no_error();
assert_not_null(result3);
assert_equal_int(result3, Memory::t);
return pass;
}
proc run_all_tests() -> void {
log_level = Log_Level::None;
Memory::init();
@@ -449,6 +484,8 @@ proc run_all_tests() -> void {
invoke_test(test_built_in_type);
printf("\n-- Memory management --\n");
invoke_test(test_singular_t_and_nil);
printf("\n-- Lexical scope --\n");
printf("\n-- Macros --\n");