fixes splicing of nil and macros dont expand at parse time fr now
This commit is contained in:
+30
-13
@@ -496,8 +496,7 @@ proc load_built_ins_into_environment(Environment* env) -> void {
|
||||
// funciton, we can't just modify it because otherwise
|
||||
// we modify the body of the function and would bake
|
||||
// in the result...
|
||||
Lisp_Object* newPair;
|
||||
try newPair = Memory::create_lisp_object_pair(Memory::nil, Memory::nil);
|
||||
Lisp_Object* newPair = Memory::nil;
|
||||
Lisp_Object* newPairHead = newPair;
|
||||
Lisp_Object* head = expr;
|
||||
while (Memory::get_type(head) == Lisp_Object_Type::Pair) {
|
||||
@@ -509,25 +508,43 @@ proc load_built_ins_into_environment(Environment* env) -> void {
|
||||
{
|
||||
Lisp_Object* spliced = unquoteSomeExpressions(head->value.pair.first);
|
||||
|
||||
try assert_type(spliced, Lisp_Object_Type::Pair);
|
||||
newPairHead->value.pair.first = spliced->value.pair.first;
|
||||
newPairHead->value.pair.rest = spliced->value.pair.rest;
|
||||
if (spliced == Memory::nil) {
|
||||
head = head->value.pair.rest;
|
||||
continue;
|
||||
}
|
||||
|
||||
// now skip to the end
|
||||
while (newPairHead->value.pair.rest != Memory::nil) {
|
||||
try assert_type(spliced, Lisp_Object_Type::Pair);
|
||||
if (newPair == Memory::nil) {
|
||||
try newPair = Memory::create_lisp_object_pair(Memory::nil, Memory::nil);
|
||||
newPairHead = newPair;
|
||||
} else {
|
||||
try newPairHead->value.pair.rest = Memory::create_lisp_object_pair(Memory::nil, Memory::nil);
|
||||
newPairHead->value.pair.first = spliced->value.pair.first;
|
||||
newPairHead->value.pair.rest = spliced->value.pair.rest;
|
||||
|
||||
// now skip to the end
|
||||
while (newPairHead->value.pair.rest != Memory::nil) {
|
||||
newPairHead = newPairHead->value.pair.rest;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
if (newPair == Memory::nil) {
|
||||
try newPair = Memory::create_lisp_object_pair(Memory::nil, Memory::nil);
|
||||
newPairHead = newPair;
|
||||
} else {
|
||||
try newPairHead->value.pair.rest = Memory::create_lisp_object_pair(Memory::nil, Memory::nil);
|
||||
newPairHead = newPairHead->value.pair.rest;
|
||||
}
|
||||
} else {
|
||||
newPairHead->value.pair.first = unquoteSomeExpressions(head->value.pair.first);
|
||||
}
|
||||
|
||||
if (Memory::get_type(head->value.pair.rest) != Lisp_Object_Type::Pair)
|
||||
break;
|
||||
// if (Memory::get_type(head->value.pair.rest) != Lisp_Object_Type::Pair) {
|
||||
// break;
|
||||
// }
|
||||
|
||||
try newPairHead->value.pair.rest = Memory::create_lisp_object_pair(Memory::nil, Memory::nil);
|
||||
|
||||
newPairHead = newPairHead->value.pair.rest;
|
||||
head = head->value.pair.rest;
|
||||
|
||||
}
|
||||
newPairHead->value.pair.rest = Memory::nil;
|
||||
|
||||
|
||||
@@ -67,6 +67,11 @@ proc print_indent(int indent) -> void {
|
||||
}
|
||||
|
||||
proc print_environment_indent(Environment* env, int indent) -> void {
|
||||
// if(env == Globals::root_environment) {
|
||||
// print_indent(indent);
|
||||
// printf("[built-ins]-Environment (%lld)\n", (long long)env);
|
||||
// return;
|
||||
// }
|
||||
for (int i = 0; i < env->next_index; ++i) {
|
||||
print_indent(indent);
|
||||
print(env->values[i]);
|
||||
|
||||
@@ -418,6 +418,19 @@ proc eval_expr(Lisp_Object* node, Environment* env) -> Lisp_Object* {
|
||||
|
||||
Lisp_Object* result;
|
||||
try result = apply_arguments_to_function(arguments, &lispOperator->value.function);
|
||||
|
||||
// NOTE(Felix): The parser does not understnad (import ..)
|
||||
// so it cannot expand imported macros at read time
|
||||
// (because at read time, they are not imported yet, this
|
||||
// is done at runtime...). That is why we sometimes have
|
||||
// stray macros fying around, in that case, we expand them
|
||||
// and bake them in, so they do not have to be expanded
|
||||
// later again.
|
||||
if (lispOperator->value.function.type == Function_Type::Macro) {
|
||||
*node = *result;
|
||||
try result = eval_expr(result, env);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
+17
-1
@@ -449,16 +449,32 @@ namespace Parser {
|
||||
} 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, environment_for_macros);
|
||||
if (macro &&
|
||||
Memory::get_type(macro) == Lisp_Object_Type::Function &&
|
||||
macro->value.function.type == Function_Type::Macro)
|
||||
{
|
||||
// printf("Found 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, environment_for_macros);
|
||||
break;
|
||||
} else break;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user