123 lines
2.8 KiB
C
123 lines
2.8 KiB
C
|
|
#include <stdlib.h>
|
|
#include <assert.h>
|
|
|
|
#include <debug.h>
|
|
|
|
#include <environment/new.h>
|
|
#include <environment/declare.h>
|
|
#include <environment/free.h>
|
|
|
|
#include <value/struct.h>
|
|
#include <value/lambda/struct.h>
|
|
#include <value/builtin_lambda/struct.h>
|
|
#include <value/builtin_lambda/new.h>
|
|
#include <value/lazy/new.h>
|
|
#include <value/lazy/unlazy.h>
|
|
#include <value/free.h>
|
|
|
|
#include "../evaluate.h"
|
|
|
|
#include "struct.h"
|
|
#include "evaluate.h"
|
|
|
|
struct value* application_expression_evaluate(
|
|
struct expression* super,
|
|
struct environment* outer_environment,
|
|
struct booleans* booleans)
|
|
{
|
|
ENTER;
|
|
|
|
struct value* result;
|
|
|
|
struct application_expression* this = (void*) super;
|
|
|
|
struct value* left = expression_evaluate(this->left, outer_environment, booleans);
|
|
|
|
struct value* lleft = lazy_value_unlazy(left, booleans);
|
|
|
|
struct value* right = new_lazy_value(
|
|
/* capture environment: */ outer_environment,
|
|
/* expression: */ this->right);
|
|
|
|
switch (lleft->kind)
|
|
{
|
|
case vk_lambda:
|
|
{
|
|
struct lambda_value* lambda = (void*) lleft;
|
|
|
|
struct environment* environment = new_environment(lambda->environment);
|
|
|
|
environment_declare(environment, lambda->variable_name, right);
|
|
|
|
result = expression_evaluate(lambda->body, environment, booleans);
|
|
|
|
free_environment(environment);
|
|
|
|
break;
|
|
}
|
|
|
|
case vk_builtin_lambda:
|
|
{
|
|
struct builtin_lambda_value* lambda = (void*) lleft;
|
|
|
|
assert(lambda->number_of_parameters > 0);
|
|
|
|
if (lambda->number_of_parameters == 1)
|
|
{
|
|
result = (lambda->funcptr)(booleans, lambda, right);
|
|
}
|
|
else
|
|
{
|
|
result = new_builtin_lambda_value(
|
|
/* name: */ lambda->name,
|
|
/* funcptr: */ lambda->funcptr,
|
|
/* number_of_parameters: */ lambda->number_of_parameters - 1,
|
|
/* value: */ right,
|
|
/* prev: */ lambda);
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case vk_lazy:
|
|
{
|
|
TODO;
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
dpvu(lleft->kind);
|
|
|
|
// make some kind of 'error-value'?
|
|
// that's contagious, like NaN?
|
|
|
|
// maybe error values can link to other error values?
|
|
// if more than on seperate error was encountered?
|
|
TODO;
|
|
|
|
exit(1);
|
|
break;
|
|
}
|
|
}
|
|
|
|
free_value(left);
|
|
|
|
free_value(lleft);
|
|
|
|
free_value(right);
|
|
|
|
EXIT;
|
|
return result;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|