work transfer to laptop
This commit is contained in:
+99
-99
@@ -366,118 +366,118 @@ namespace Parser {
|
||||
}
|
||||
|
||||
// check if we have to create or delete or run macros
|
||||
while (Memory::get_type(expression->value.pair.first) == Lisp_Object_Type::Symbol) {
|
||||
Lisp_Object* parsed_symbol = expression->value.pair.first;
|
||||
if (string_equal("define-syntax", parsed_symbol->value.symbol.identifier)) {
|
||||
// create a new macro
|
||||
Lisp_Object* arguments = expression->value.pair.rest;
|
||||
Lisp_Object* body;
|
||||
int arguments_length;
|
||||
// while (Memory::get_type(expression->value.pair.first) == Lisp_Object_Type::Symbol) {
|
||||
// Lisp_Object* parsed_symbol = expression->value.pair.first;
|
||||
// if (string_equal("define-syntax", parsed_symbol->value.symbol.identifier)) {
|
||||
// // create a new macro
|
||||
// Lisp_Object* arguments = expression->value.pair.rest;
|
||||
// Lisp_Object* body;
|
||||
// int arguments_length;
|
||||
|
||||
// HACK(Felix): almost code duplicate from
|
||||
// `built_ins.cpp`: special-lambda
|
||||
try arguments_length = list_length(arguments);
|
||||
// // HACK(Felix): almost code duplicate from
|
||||
// // `built_ins.cpp`: special-lambda
|
||||
// try arguments_length = list_length(arguments);
|
||||
|
||||
// (define-syntax (defun name args :rest body) (...))
|
||||
if (arguments_length < 2) {
|
||||
create_wrong_number_of_arguments_error(3, arguments_length);
|
||||
return nullptr;
|
||||
}
|
||||
// // (define-syntax (defun name args :rest body) (...))
|
||||
// if (arguments_length < 2) {
|
||||
// create_wrong_number_of_arguments_error(3, arguments_length);
|
||||
// return nullptr;
|
||||
// }
|
||||
|
||||
assert_type(arguments->value.pair.first, Lisp_Object_Type::Pair);
|
||||
// assert_type(arguments->value.pair.first, Lisp_Object_Type::Pair);
|
||||
|
||||
// extract the name
|
||||
Lisp_Object* symbol_for_macro = arguments->value.pair.first->value.pair.first;
|
||||
body = arguments->value.pair.rest;
|
||||
arguments = arguments->value.pair.first->value.pair.rest;
|
||||
// // extract the name
|
||||
// Lisp_Object* symbol_for_macro = arguments->value.pair.first->value.pair.first;
|
||||
// body = arguments->value.pair.rest;
|
||||
// arguments = arguments->value.pair.first->value.pair.rest;
|
||||
|
||||
// Function* function = new(Function);
|
||||
Lisp_Object* macro;
|
||||
try macro = Memory::create_lisp_object();
|
||||
Memory::set_type(macro, Lisp_Object_Type::Function);
|
||||
macro->value.function.parent_environment = get_current_environment();
|
||||
macro->value.function.type = Function_Type::Macro;
|
||||
// // Function* function = new(Function);
|
||||
// Lisp_Object* macro;
|
||||
// try macro = Memory::create_lisp_object();
|
||||
// Memory::set_type(macro, Lisp_Object_Type::Function);
|
||||
// macro->value.function.parent_environment = get_current_environment();
|
||||
// macro->value.function.type = Function_Type::Macro;
|
||||
|
||||
// if parameters were specified
|
||||
if (arguments != Memory::nil) {
|
||||
try assert_type(arguments, Lisp_Object_Type::Pair);
|
||||
try parse_argument_list(arguments, ¯o->value.function);
|
||||
} else {
|
||||
macro->value.function.args.positional = create_positional_argument_list(1);
|
||||
macro->value.function.args.keyword = create_keyword_argument_list(1);
|
||||
macro->value.function.args.rest = nullptr;
|
||||
}
|
||||
// // if parameters were specified
|
||||
// if (arguments != Memory::nil) {
|
||||
// try assert_type(arguments, Lisp_Object_Type::Pair);
|
||||
// try create_arguments_from_lambda_list_and_inject(arguments, macro);
|
||||
// } else {
|
||||
// macro->value.function.args.positional = create_positional_argument_list(1);
|
||||
// macro->value.function.args.keyword = create_keyword_argument_list(1);
|
||||
// macro->value.function.args.rest = nullptr;
|
||||
// }
|
||||
|
||||
// arguments = arguments->value.pair.rest;
|
||||
// if there is a docstring, use it
|
||||
if (Memory::get_type(body->value.pair.first) == Lisp_Object_Type::String) {
|
||||
macro->docstring = body->value.pair.first->value.string;
|
||||
body = body->value.pair.rest;
|
||||
} else {
|
||||
macro->docstring = nullptr;
|
||||
}
|
||||
// // arguments = arguments->value.pair.rest;
|
||||
// // if there is a docstring, use it
|
||||
// if (Memory::get_type(body->value.pair.first) == Lisp_Object_Type::String) {
|
||||
// macro->docstring = body->value.pair.first->value.string;
|
||||
// body = body->value.pair.rest;
|
||||
// } else {
|
||||
// macro->docstring = nullptr;
|
||||
// }
|
||||
|
||||
// we are now in the function body, just wrap it in an
|
||||
// implicit begin
|
||||
try macro->value.function.body = Memory::create_lisp_object_pair(
|
||||
Memory::get_or_create_lisp_object_symbol("begin"),
|
||||
body);
|
||||
// // we are now in the function body, just wrap it in an
|
||||
// // implicit begin
|
||||
// try macro->value.function.body = Memory::create_lisp_object_pair(
|
||||
// Memory::get_or_create_lisp_object_symbol("begin"),
|
||||
// body);
|
||||
|
||||
inject_scl(macro);
|
||||
// macro->value.function = function;
|
||||
define_symbol(symbol_for_macro, macro);
|
||||
// inject_scl(macro);
|
||||
// // macro->value.function = function;
|
||||
// define_symbol(symbol_for_macro, macro);
|
||||
|
||||
// print_environment(environment_for_macros);
|
||||
return Memory::nil;
|
||||
// // print_environment(environment_for_macros);
|
||||
// return Memory::nil;
|
||||
|
||||
} else if (string_equal("delete-syntax", parsed_symbol->value.symbol.identifier)) {
|
||||
/* --- deleting an existing macro --- */
|
||||
// TODO(Felix): this is a hard one because when
|
||||
// environments will be made from hashmaps, how can we
|
||||
// delete stuff from hashmaps? If we do probing on
|
||||
// collision and then delte the first colliding entry,
|
||||
// how can we find the second one? How many probes do
|
||||
// we have to do to know for sure that an elemenet is
|
||||
// not in the hashmap? It would be much easier if we
|
||||
// never deleted any elements from the hashmap, so
|
||||
// that, when an entry is not found immidiately, we
|
||||
// know for sure that it does not exist in the table.
|
||||
// } else if (string_equal("delete-syntax", parsed_symbol->value.symbol.identifier)) {
|
||||
// /* --- deleting an existing macro --- */
|
||||
// // TODO(Felix): this is a hard one because when
|
||||
// // environments will be made from hashmaps, how can we
|
||||
// // delete stuff from hashmaps? If we do probing on
|
||||
// // collision and then delte the first colliding entry,
|
||||
// // how can we find the second one? How many probes do
|
||||
// // we have to do to know for sure that an elemenet is
|
||||
// // not in the hashmap? It would be much easier if we
|
||||
// // never deleted any elements from the hashmap, so
|
||||
// // that, when an entry is not found immidiately, we
|
||||
// // know for sure that it does not exist in the table.
|
||||
|
||||
create_generic_error("deleting macros has not yet be implemented,"
|
||||
"and I don't know if it is a good idea to do so.");
|
||||
return nullptr;
|
||||
} else {
|
||||
// if threre is a macro named like this, then macroexpand
|
||||
// if not it is regular code, dont touch.
|
||||
break;
|
||||
// create_generic_error("deleting macros has not yet be implemented,"
|
||||
// "and I don't know if it is a good idea to do so.");
|
||||
// return nullptr;
|
||||
// } else {
|
||||
// // if threre is a macro named like this, then macroexpand
|
||||
// // if not it is regular code, dont touch.
|
||||
// break;
|
||||
|
||||
Lisp_Object* macro = try_lookup_symbol(parsed_symbol, get_current_environment());
|
||||
if (macro &&
|
||||
Memory::get_type(macro) == Lisp_Object_Type::Function &&
|
||||
macro->value.function.type == Function_Type::Macro)
|
||||
{
|
||||
// printf("pretending to expand macro at %s %d %d: ",
|
||||
// Memory::get_c_str(parser_file),
|
||||
// parser_line, parser_col);
|
||||
// print(parsed_symbol);
|
||||
// printf("\n");
|
||||
// NOTE(Felix): Execute it as a special lambda,
|
||||
// because if we keep it as a macro, the evaluator
|
||||
// will think it is a stray macro that was not yet
|
||||
// expanded, and attempt to evaluate it twice (1.
|
||||
// for expanding, and 2. for evaluating)
|
||||
macro->value.function.type = Function_Type::Special_Lambda;
|
||||
// NOTE(Felix): deferred so even if eval expr
|
||||
// fails, and returns, the type will be be
|
||||
// resetted to macro.
|
||||
defer {
|
||||
macro->value.function.type = Function_Type::Macro;
|
||||
};
|
||||
try expression = eval_expr(expression);
|
||||
break;
|
||||
} else break;
|
||||
}
|
||||
}
|
||||
// Lisp_Object* macro = try_lookup_symbol(parsed_symbol, get_current_environment());
|
||||
// if (macro &&
|
||||
// Memory::get_type(macro) == Lisp_Object_Type::Function &&
|
||||
// macro->value.function.type == Function_Type::Macro)
|
||||
// {
|
||||
// // printf("pretending to expand macro at %s %d %d: ",
|
||||
// // Memory::get_c_str(parser_file),
|
||||
// // parser_line, parser_col);
|
||||
// // print(parsed_symbol);
|
||||
// // printf("\n");
|
||||
// // NOTE(Felix): Execute it as a special lambda,
|
||||
// // because if we keep it as a macro, the evaluator
|
||||
// // will think it is a stray macro that was not yet
|
||||
// // expanded, and attempt to evaluate it twice (1.
|
||||
// // for expanding, and 2. for evaluating)
|
||||
// macro->value.function.type = Function_Type::Special_Lambda;
|
||||
// // NOTE(Felix): deferred so even if eval expr
|
||||
// // fails, and returns, the type will be be
|
||||
// // resetted to macro.
|
||||
// defer {
|
||||
// macro->value.function.type = Function_Type::Macro;
|
||||
// };
|
||||
// try expression = eval_expr(expression);
|
||||
// break;
|
||||
// } else break;
|
||||
// }
|
||||
// }
|
||||
|
||||
return expression;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user