cirilisp/eval.c

143 lines
2.8 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "util.h"
#include "internals.h"
#include "eval.h"
int currentRecursionDepth = 0;
#define MAXRECURSIONDEPTH 1000
object apply(object function, object parameters, env currentEnv);
object eval(object input, env currentEnv)
{
object result;
if (TYPE(input) == symbolObject)
{
result = referVariable(SYM(input), currentEnv);
}
else if (TYPE(input) == consObject)
{
if (!properList(input))
{
SIGERR(improperListError);
}
else
{
int regularEvalOrder = 1;
CAR(input) = eval(CAR(input), currentEnv);
if (TYPE(CAR(input)) == procedureObject &&
PROC_TYPE(CAR(input)) == builtinProc &&
PROC_SPECIAL(CAR(input)))
{
regularEvalOrder = 0;
}
object *currentCell = &CDR(input);
int noErrors = 1;
if (regularEvalOrder)
{
while (TYPE(*currentCell) != nilObject)
{
CAR(*currentCell) =
eval(CAR(*currentCell),
currentEnv);
if (TYPE(CAR(*currentCell)) ==
errorObject)
{
noErrors = 0;
object err = copyObject(
CAR(*currentCell));
deleteObject(input);
SIGERR(ERR(err));
break;
}
currentCell = &CDR(*currentCell);
}
}
if (noErrors)
{
result = apply(CAR(input), CDR(input),
currentEnv);
}
}
}
else
{
result = copyObject(input);
}
deleteObject(input);
return result;
}
object apply(object procedure, object parameters, env currentEnv)
{
object result;
if (TYPE(procedure) != procedureObject)
{
SIGERR(notApplicableError);
}
if (PROC_TYPE(procedure) == builtinProc)
{
object(*f)() = PROC_BUILTIN(procedure);
if (f == defineInt || f == lambdaInt || f == ifInt)
{
result = f(parameters, currentEnv);
}
else
{
result = f(parameters);
}
return result;
}
if (++currentRecursionDepth > MAXRECURSIONDEPTH)
{
--currentRecursionDepth;
SIGERR(maxRecursionDepthError);
}
object args = copyObject(PROC_COMP_ARGS(procedure));
object body = copyObject(PROC_COMP_BODY(procedure));
env definitionEnv = PROC_COMP_ENV(procedure);
if (listLength(parameters) != listLength(args))
{
SIGERR(argumentNumberError);
}
env procEnv = createEnvironment(definitionEnv);
object *currentArg = &args;
object *currentParam = &parameters;
while (TYPE(*currentArg) != nilObject)
{
addSymbolVariable(SYM(CAR(*currentArg)), CAR(*currentParam),
procEnv);
currentArg = &CDR(*currentArg);
currentParam = &CDR(*currentParam);
}
object *currentSubProc = &body;
while (TYPE(*currentSubProc) != nilObject)
{
CAR(*currentSubProc) = eval(CAR(*currentSubProc), procEnv);
if (TYPE(CDR(*currentSubProc)) == nilObject)
{
result = copyObject(CAR(*currentSubProc));
}
currentSubProc = &CDR(*currentSubProc);
}
deleteObject(args);
deleteObject(body);
removeEnvironment(procEnv);
--currentRecursionDepth;
return result;
}