Update function call stuff

This commit is contained in:
2026-07-19 00:14:16 -07:00
parent bd7ca2fa25
commit 67b68f8c61
10 changed files with 177 additions and 115 deletions
+64 -54
View File
@@ -13,24 +13,32 @@ void lisp_init_stack(void) {
the_stack.max_depth = LISP_STACK_MAX_DEPTH;
the_stack.depth = 0;
the_stack.frames = lisp_malloc(sizeof(StackFrame) * the_stack.max_depth);
the_stack.nogc_retval = Qnil;
the_stack.unwind_info.set = false;
}
static void teardown_local_references(struct LocalReferences *restrict refs) {
static inline void
maybe_clear_object_local_reference(StackFrame *restrict frame, LispVal *obj) {
if (OBJECT_LOWEST_LOCAL_REFERENCE(obj) == frame) {
SET_OBJECT_LOWEST_LOCAL_REFERENCE(obj, NULL);
}
}
static void teardown_local_references(StackFrame *restrict frame) {
assert(frame->kind == STACK_FRAME_LOCAL_REFERENCES);
struct LocalReferences *restrict refs = &frame->local_references;
size_t last_block_size = refs->num_refs % LOCAL_REFERENCES_BLOCK_LENGTH;
size_t num_full_blocks = refs->num_refs / LOCAL_REFERENCES_BLOCK_LENGTH;
for (size_t i = 0; i < num_full_blocks; ++i) {
for (size_t j = 0; j < LOCAL_REFERENCES_BLOCK_LENGTH; ++j) {
assert(OBJECTP(refs->blocks[i]->refs[j]));
SET_OBJECT_HAS_LOCAL_REFERENCE(refs->blocks[i]->refs[j], false);
maybe_clear_object_local_reference(frame, refs->blocks[i]->refs[j]);
}
lisp_free(refs->blocks[i]);
}
for (size_t i = 0; i < last_block_size; ++i) {
assert(OBJECTP(refs->blocks[num_full_blocks]->refs[i]));
SET_OBJECT_HAS_LOCAL_REFERENCE(refs->blocks[num_full_blocks]->refs[i],
false);
maybe_clear_object_local_reference(
frame, refs->blocks[num_full_blocks]->refs[i]);
}
lisp_free(refs->blocks[num_full_blocks]);
lisp_free(refs->blocks);
@@ -39,54 +47,12 @@ static void teardown_local_references(struct LocalReferences *restrict refs) {
void lisp_teardown_stack(void) {
for (size_t i = 0; i < the_stack.depth; ++i) {
if (the_stack.frames[i].kind == STACK_FRAME_LOCAL_REFERENCES) {
teardown_local_references(&the_stack.frames[i].local_references);
teardown_local_references(&the_stack.frames[i]);
}
}
lisp_free(the_stack.frames);
}
void unwind_to(StackFrame *frame) {
the_stack.unwind_info.set = true;
the_stack.unwind_info.cause = UNWIND_NORMAL;
the_stack.unwind_info.target = frame;
while (&the_stack.frames[the_stack.depth - 1] > frame) {
StackFrame *restrict top = &the_stack.frames[--the_stack.depth];
switch (top->kind) {
case STACK_FRAME_DYNAMIC_BINDING:
if (top->dynamic_binding.symbol == Qlexical_environment) {
Vlexical_environment = top->dynamic_binding.old_value;
} else {
SET_SYMBOL_VALUE(top->dynamic_binding.symbol,
top->dynamic_binding.old_value);
}
break;
case STACK_FRAME_UNWIND_PROTECT:
longjmp(*top->unwind_protect.target, LISP_LONGJMP_FOR_UNWIND);
case STACK_FRAME_LOCAL_REFERENCES:
teardown_local_references(&top->local_references);
break;
case STACK_FRAME_CALL:
case STACK_FRAME_CONDITION_CASE:
// nothing to do
break;
}
}
the_stack.unwind_info.set = false;
}
noreturn void continue_unwinding(void) {
assert(the_stack.unwind_info.set);
switch (the_stack.unwind_info.cause) {
case UNWIND_NORMAL:
unwind_to(the_stack.unwind_info.target);
case UNWIND_EXCEPTION:
// TODO implement
abort();
default:
abort();
}
}
static ALWAYS_INLINE StackFrame *PUSH_NEW_FRAME(enum StackFrameKind kind) {
if (the_stack.depth == the_stack.max_depth) {
// TODO error
@@ -103,15 +69,15 @@ static ALWAYS_INLINE StackFrame *PUSH_NEW_FRAME(enum StackFrameKind kind) {
return frame;
}
void push_call_frame(LispVal *name, LispVal *fobj, LispVal *args) {
void push_call_frame(LispVal *name, LispVal *args) {
StackFrame *frame = PUSH_NEW_FRAME(STACK_FRAME_CALL);
frame->call.name = name;
frame->call.fobj = fobj;
frame->call.args = args;
frame->call.evaled_args = false;
}
void set_stack_evaluated_args(StackFrame *restrict frame, LispVal *args) {
void set_stack_evaluated_args(StackFrame *restrict frame, LispVal *fobj,
LispVal *args) {
gc_mark_stack_for_rescan();
assert(frame->kind == STACK_FRAME_CALL);
frame->call.args = args;
@@ -142,7 +108,8 @@ void push_local_reference_frame(void) {
frame->last_references = frame;
}
static void store_local_reference_in_frame(StackFrame *frame, LispVal *obj) {
static void store_local_reference_in_frame(StackFrame *restrict frame,
LispVal *obj) {
struct LocalReferences *restrict refs = &frame->local_references;
size_t num_full_blocks = refs->num_refs / LOCAL_REFERENCES_BLOCK_LENGTH;
if (num_full_blocks == refs->num_blocks) {
@@ -157,7 +124,7 @@ static void store_local_reference_in_frame(StackFrame *frame, LispVal *obj) {
refs->blocks[num_full_blocks]
->refs[refs->num_refs++ % LOCAL_REFERENCES_BLOCK_LENGTH] = obj;
}
SET_OBJECT_HAS_LOCAL_REFERENCE(obj, true);
SET_OBJECT_LOWEST_LOCAL_REFERENCE(obj, frame);
// mark the frame for rescan
frame->marked = false;
gc_mark_stack_for_rescan();
@@ -166,7 +133,8 @@ static void store_local_reference_in_frame(StackFrame *frame, LispVal *obj) {
void add_local_reference_no_recurse(StackFrame *restrict frame, LispVal *obj) {
frame = frame->last_references;
assert(frame->kind == STACK_FRAME_LOCAL_REFERENCES);
if (OBJECTP(obj) && !OBJECT_HAS_LOCAL_REFERENCE_P(obj)) {
StackFrame *current_frame = OBJECT_LOWEST_LOCAL_REFERENCE(obj);
if (OBJECTP(obj) && (!current_frame || current_frame > frame)) {
store_local_reference_in_frame(frame, obj);
}
}
@@ -278,3 +246,45 @@ void set_lexical_variable(LispVal *name, LispVal *value) {
assert(SYMBOLP(name));
Vlexical_environment = Fplist_put(Vlexical_environment, name, value);
}
void unwind_to(StackFrame *frame) {
the_stack.unwind_info.set = true;
the_stack.unwind_info.cause = UNWIND_NORMAL;
the_stack.unwind_info.target = frame;
while (&the_stack.frames[the_stack.depth - 1] > frame) {
StackFrame *restrict top = &the_stack.frames[--the_stack.depth];
switch (top->kind) {
case STACK_FRAME_DYNAMIC_BINDING:
if (top->dynamic_binding.symbol == Qlexical_environment) {
Vlexical_environment = top->dynamic_binding.old_value;
} else {
SET_SYMBOL_VALUE(top->dynamic_binding.symbol,
top->dynamic_binding.old_value);
}
break;
case STACK_FRAME_UNWIND_PROTECT:
longjmp(*top->unwind_protect.target, LISP_LONGJMP_FOR_UNWIND);
case STACK_FRAME_LOCAL_REFERENCES:
teardown_local_references(top);
break;
case STACK_FRAME_CALL:
case STACK_FRAME_CONDITION_CASE:
// nothing to do
break;
}
}
the_stack.unwind_info.set = false;
}
noreturn void continue_unwinding(void) {
assert(the_stack.unwind_info.set);
switch (the_stack.unwind_info.cause) {
case UNWIND_NORMAL:
unwind_to(the_stack.unwind_info.target);
case UNWIND_EXCEPTION:
// TODO implement
abort();
default:
abort();
}
}