Before implementing import name resolution, then after fic macro imports

This commit is contained in:
Felix Brendel
2019-06-03 16:19:37 +02:00
parent 3fb2326dd3
commit f77e4c56b3
20 changed files with 295 additions and 3226 deletions
+8 -22
View File
@@ -30,7 +30,8 @@ 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));
char* full_file_name = find_slime_file(file_name);
char* file_content = read_entire_file(full_file_name );
if (file_content) {
Lisp_Object* result = Memory::nil;
Lisp_Object_Array_List* program;
@@ -50,6 +51,7 @@ proc built_in_import(String* file_name, Environment* env) -> Lisp_Object* {
// create new empty environment
Environment* new_env;
try new_env = Memory::create_child_environment(Globals::root_environment);
append_to_array_list(env->parents, new_env);
Environment* old_macro_env = Parser::environment_for_macros;
Parser::environment_for_macros = new_env;
@@ -58,8 +60,6 @@ proc built_in_import(String* file_name, Environment* env) -> Lisp_Object* {
Parser::environment_for_macros = old_macro_env;
append_to_array_list(env->parents, new_env);
return res;
}
@@ -391,10 +391,9 @@ proc load_built_ins_into_environment(Environment* env) -> void {
defun("mutate", cLambda {
try evaluated_arguments = eval_arguments(arguments, env, &arguments_length);
try assert_arguments_length(2, arguments_length);
Lisp_Object* target = evaluated_arguments->value.pair.first;
Lisp_Object* source = evaluated_arguments->value.pair.rest->value.pair.first;
#
if (target == Memory::nil ||
target == Memory::t ||
Memory::get_type(target) == Lisp_Object_Type::Keyword ||
@@ -724,8 +723,8 @@ proc load_built_ins_into_environment(Environment* env) -> void {
try assert_type(type, Lisp_Object_Type::Keyword);
evaluated_arguments->value.pair.first->userType = type;
return type;
object->userType = type;
return object;
});
defun("delete-type", cLambda {
try evaluated_arguments = eval_arguments(arguments, env, &arguments_length);
@@ -850,6 +849,7 @@ proc load_built_ins_into_environment(Environment* env) -> void {
puts("body:\n");
print(evaluated_arguments->value.pair.first->value.function.body);
puts("\n");
printf("parent_env: %lld\n", (long long)evaluated_arguments->value.pair.first->value.function.parent_environment);
return Memory::nil;
});
@@ -947,21 +947,7 @@ proc load_built_ins_into_environment(Environment* env) -> void {
try evaluated_arguments = eval_arguments(arguments, env, &arguments_length);
try assert_arguments_length(1, arguments_length);
if (evaluated_arguments->value.pair.first == Memory::nil ||
evaluated_arguments->value.pair.first == Memory::t ||
Memory::get_type(evaluated_arguments->value.pair.first) == Lisp_Object_Type::Symbol ||
Memory::get_type(evaluated_arguments->value.pair.first) == Lisp_Object_Type::Keyword)
{
// we don't copy singleton objects
return evaluated_arguments->value.pair.first;
}
Lisp_Object* target = Memory::create_lisp_object();
Lisp_Object* source = evaluated_arguments->value.pair.first;
*target = *source;
return target;
return Memory::copy_lisp_object(evaluated_arguments->value.pair.first);
});
defun("error", cLambda {
// TODO(Felix): make the error function useful
+2 -1
View File
@@ -71,6 +71,7 @@ proc print_environment_indent(Environment* env, int indent) -> void {
print_indent(indent);
print(env->values[i]);
printf(" %s", env->keys[i]);
printf(" (%lld)", (long long)env->values[i]);
puts("");
}
for (int i = 0; i < env->parents->next_index; ++i) {
@@ -82,6 +83,6 @@ proc print_environment_indent(Environment* env, int indent) -> void {
}
proc print_environment(Environment* env) -> void {
printf("\n=== Environment ===\n");
printf("\n=== Environment === (%lld)\n", (long long)env);
print_environment_indent(env, 0);
}
+21 -54
View File
@@ -14,8 +14,13 @@ 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?
// NOTE(Felix): We have to copy all the arguments, otherwise
// we change the program code.
try sym = Memory::get_or_create_lisp_object_symbol(function->positional_arguments->identifiers[i]);
define_symbol(sym, arguments->value.pair.first, new_env);
define_symbol(
sym,
Memory::copy_lisp_object_except_pairs(arguments->value.pair.first),
new_env);
arguments = arguments->value.pair.rest;
}
@@ -82,7 +87,10 @@ proc apply_arguments_to_function(Lisp_Object* arguments, Function* function) ->
// if not set it and then add it to the array list
try sym = Memory::get_or_create_lisp_object_symbol(arguments->value.pair.first->value.symbol.identifier);
// NOTE(Felix): It seems we do not need to evaluate the argument here...
try define_symbol(sym, arguments->value.pair.rest->value.pair.first, new_env);
try define_symbol(
sym,
Memory::copy_lisp_object_except_pairs(arguments->value.pair.rest->value.pair.first),
new_env);
append_to_array_list(read_in_keywords, arguments->value.pair.first->value.symbol.identifier);
@@ -122,7 +130,7 @@ proc apply_arguments_to_function(Lisp_Object* arguments, Function* function) ->
// to use it or if the user supplied his own
if (!was_set) {
try sym = Memory::get_or_create_lisp_object_symbol(defined_keyword);
try val = Memory::copy_lisp_object(function->keyword_arguments->values->data[i]);
try val = Memory::copy_lisp_object_except_pairs(function->keyword_arguments->values->data[i]);
define_symbol(sym, val, new_env);
}
}
@@ -137,7 +145,12 @@ proc apply_arguments_to_function(Lisp_Object* arguments, Function* function) ->
} else {
if (function->rest_argument) {
try sym = Memory::get_or_create_lisp_object_symbol(function->rest_argument);
define_symbol(sym, arguments, new_env);
define_symbol(
sym,
// NOTE(Felix): arguments will be a list, and I THINK
// we do not need to copy it...
arguments,
new_env);
} else {
// rest was not declared but additional arguments were found
create_generic_error(
@@ -152,20 +165,9 @@ proc apply_arguments_to_function(Lisp_Object* arguments, Function* function) ->
return result;
}
/*
(begin
(define type--before type)
(define type
(lambda (e)
(if (and (= (type--before e) :pair) (= (first e) :my-type))
:my-type
(type--before e))))
)
*/
/**
This parses the argument specification of funcitons into their
Function struct. It dois this by allocating new
Function struct. It does this by allocating new
positional_arguments, keyword_arguments and rest_argument and
filling it in
*/
@@ -382,7 +384,6 @@ proc eval_expr(Lisp_Object* node, Environment* env) -> Lisp_Object* {
case Lisp_Object_Type::Symbol: {
Lisp_Object* symbol;
try symbol = lookup_symbol(node, env);
return symbol;
}
case Lisp_Object_Type::Pair: {
@@ -409,7 +410,8 @@ proc eval_expr(Lisp_Object* node, Environment* env) -> Lisp_Object* {
// check for lisp function
if (Memory::get_type(lispOperator) == Lisp_Object_Type::Function) {
// only for lambdas we evaluate the arguments before
// apllying
// apllying, for the other types, special-lambda and macro
// we do not need.
if (lispOperator->value.function.type == Function_Type::Lambda) {
try arguments = eval_arguments(arguments, env, &arguments_length);
}
@@ -440,25 +442,7 @@ proc interprete_file (char* file_name) -> Lisp_Object* {
try user_env = Memory::create_child_environment(root_env);
Parser::environment_for_macros = user_env;
// save the current working directory
char cwd[1024];
getcwd(cwd, 1024);
// get the direction of the exe
char* exe_path = exe_dir();
// switch to the exe directory for loading pre.slime
chdir(exe_path);
free(exe_path);
built_in_import(Memory::create_string("pre.slime"), user_env);
// switch back to the users directory
chdir(cwd);
Lisp_Object* result;
result = built_in_load(Memory::create_string(file_name), user_env);
Lisp_Object* result = built_in_load(Memory::create_string(file_name), user_env);
if (Globals::error) {
log_error();
@@ -480,23 +464,6 @@ proc interprete_stdin(bool is_emacs_repl = false) -> void {
return;
}
// save the current working directory
char cwd[1024];
getcwd(cwd, 1024);
// get the direction of the exe
char* exe_path = exe_dir();
// switch to the exe directory for loading pre.slime
chdir(exe_path);
free(exe_path);
built_in_import(Memory::create_string("pre.slime"), user_env);
// switch back to the users directory
chdir(cwd);
Parser::environment_for_macros = user_env;
printf("Welcome to the lispy interpreter.\n");
+4
View File
@@ -12,6 +12,8 @@ proc load_built_ins_into_environment(Environment*) -> void;
proc parse_argument_list(Lisp_Object*, Function*) -> void;
proc print_environment(Environment*) -> void;
proc exe_dir() -> char*;
proc Lisp_Object_Type_to_string(Lisp_Object_Type type) -> const char*;
proc visualize_lisp_machine() -> void;
@@ -24,6 +26,8 @@ namespace Memory {
namespace Parser {
extern Environment* environment_for_macros;
extern String* standard_in;
extern String* parser_file;
extern int parser_line;
+5 -1
View File
@@ -90,6 +90,10 @@ proc unescape_string(char* in) -> bool {
return true;
}
proc find_slime_file(String* filename) -> char* {
return Memory::get_c_str(filename);
}
proc read_entire_file(char* filename) -> char* {
char *fileContent = nullptr;
FILE *fp = fopen(filename, "r");
@@ -351,7 +355,7 @@ proc log_error() -> void {
puts(console_normal);
}
char* exe_dir() {
proc exe_dir() -> char* {
size_t size = 512, i, n;
char *path, *temp;
+32 -3
View File
@@ -182,7 +182,7 @@ namespace Memory {
set_type(t, Lisp_Object_Type::T);
try_void Globals::root_environment = create_built_ins_environment();
try_void Parser::standard_in = create_string("stdin");
try_void Parser::standard_in = create_string("stdin");
}
proc reset() -> void {
@@ -283,7 +283,14 @@ namespace Memory {
}
proc copy_lisp_object(Lisp_Object* n) -> Lisp_Object* {
if (n == nil || n == t)
// TODO(Felix): If argument is a list (pair), do a FULL copy,
// we don't copy singleton objects
if (
n == Memory::nil || n == Memory::t ||
Memory::get_type(n) == Lisp_Object_Type::Symbol ||
Memory::get_type(n) == Lisp_Object_Type::Keyword
)
return n;
Lisp_Object* target;
@@ -292,6 +299,12 @@ namespace Memory {
return target;
}
proc copy_lisp_object_except_pairs(Lisp_Object* n) -> Lisp_Object* {
if (get_type(n) == Lisp_Object_Type::Pair)
return n;
return copy_lisp_object(n);
}
proc create_child_environment(Environment* parent) -> Environment* {
int index;
@@ -337,8 +350,24 @@ namespace Memory {
proc create_built_ins_environment() -> Environment* {
Environment* ret;
try ret = create_child_environment(nullptr);
try ret = create_empty_environment();
load_built_ins_into_environment(ret);
Parser::environment_for_macros = ret;
// save the current working directory
char cwd[1024];
getcwd(cwd, 1024);
// get the direction of the exe
char* exe_path = exe_dir();
chdir(exe_path);
free(exe_path);
built_in_load(Memory::create_string("pre.slime"), ret);
chdir(cwd);
return ret;
}
+3
View File
@@ -455,6 +455,9 @@ namespace Parser {
Memory::get_type(macro) == Lisp_Object_Type::Function &&
macro->value.function.type == Function_Type::Macro)
{
// printf("Found macro: ") ;
// print(parsed_symbol);
// printf("\n");
try expression = eval_expr(expression, environment_for_macros);
} else break;
}
+5 -11
View File
@@ -572,21 +572,15 @@ proc test_singular_t_and_nil() -> testresult {
}
proc test_file(const char* file) -> testresult {
Environment* root_env;
Environment* user_env;
Memory::reset();
assert_no_error();
root_env = Memory::create_built_ins_environment();
assert_no_error();
user_env = Memory::create_child_environment(root_env);
Environment* root_env = Globals::root_environment;
Environment* user_env = Memory::create_child_environment(root_env);
assert_no_error();
Parser::environment_for_macros = user_env;
built_in_import(Memory::create_string("pre.slime"), user_env);
assert_no_error();
Lisp_Object* result = built_in_load(Memory::create_string(file), user_env);
assert_no_error();
@@ -595,8 +589,7 @@ proc test_file(const char* file) -> testresult {
}
proc run_all_tests() -> bool {
Memory::init(4096 * 2000, 1024, 4096 * 16);
Parser::environment_for_macros = Globals::root_environment;
Memory::init(4096 * 2000, 1024 * 32, 4096 * 16);
// get the direction of the exe
char* exe_path = exe_dir();
@@ -638,8 +631,9 @@ proc run_all_tests() -> bool {
invoke_test_script("evaluation_of_default_args");
invoke_test_script("lexical_scope");
invoke_test_script("class_macro");
invoke_test_script("sicp");
invoke_test_script("import_and_load");
invoke_test_script("sicp");
invoke_test_script("macro_expand");
return result;
}