Skip to content

Commit

Permalink
Remove YLISP_DEFERRED and use a static struct.
Browse files Browse the repository at this point in the history
Tail call optimization is implemented by passing a YLispValue up the
struct to represent a function call that is the result of the function.
But as it is only used to pass a value up the stack, only a single
instance is ever needed. Implement this with a static struct instead of
allocating a new YLispValue for every tail call.
  • Loading branch information
fragglet committed Jun 10, 2013
1 parent 14f4d72 commit cec04bd
Showing 1 changed file with 10 additions and 10 deletions.
20 changes: 10 additions & 10 deletions yoctolisp.c
Expand Up @@ -37,7 +37,7 @@ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

typedef enum {
YLISP_CELL, YLISP_STRING, YLISP_NUMBER, YLISP_BOOLEAN, YLISP_SYMBOL,
YLISP_CONTEXT, YLISP_FUNCTION, YLISP_BUILTIN, YLISP_DEFERRED,
YLISP_CONTEXT, YLISP_FUNCTION, YLISP_BUILTIN
} YLispValueType;

enum {
Expand Down Expand Up @@ -102,6 +102,9 @@ static unsigned int num_symbols = 0;

static YLispValue *root_context;

// A deferred call, passed up the stack (only one ever exists)
static YLispValue deferred_call;

static YLispValue *ylisp_value(YLispValueType type)
{
YLispValue *result = calloc(1, sizeof(YLispValue));
Expand Down Expand Up @@ -526,16 +529,13 @@ static YLispValue *set_variable(YLispValue *context, YLispValue *name,

static YLispValue *defer_eval(YLispValue *context, YLispValue *code)
{
YLispValue *deferred;

if (code->type != YLISP_CELL) {
return ylisp_eval(context, code);
}

deferred = ylisp_value(YLISP_DEFERRED);
deferred->v.func.context = context;
deferred->v.func.code = code;
return deferred;
deferred_call.v.func.context = context;
deferred_call.v.func.code = code;
return &deferred_call;
}

static YLispValue *run_function_body(YLispValue *context, YLispValue *code)
Expand Down Expand Up @@ -671,9 +671,9 @@ static YLispValue *eval_list(YLispValue *context, YLispValue *code)
YLispValue *result = eval_list_inner(context, code);

// Tail call optimization: expand deferred call.
while (result != NULL && result->type == YLISP_DEFERRED) {
context = result->v.func.context;
code = result->v.func.code;
while (result == &deferred_call) {
context = deferred_call.v.func.context;
code = deferred_call.v.func.code;
pin_variable(&context);
result = eval_list_inner(context, code);
unpin_variable(&context);
Expand Down

0 comments on commit cec04bd

Please sign in to comment.