2019-01-14 03:16:25 +01:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
#include "util.h"
|
2019-01-29 00:07:33 +01:00
|
|
|
#include "internals.h"
|
2019-02-09 14:06:53 +01:00
|
|
|
#include "eval.h"
|
2019-01-14 03:16:25 +01:00
|
|
|
|
2019-02-05 20:08:25 +01:00
|
|
|
int currentRecursionDepth = 0;
|
|
|
|
#define MAXRECURSIONDEPTH 1000
|
|
|
|
|
2019-02-05 16:35:05 +01:00
|
|
|
object apply(object function, object parameters, env currentEnv);
|
2019-01-14 03:16:25 +01:00
|
|
|
|
2019-02-05 16:35:05 +01:00
|
|
|
object eval(object input, env currentEnv)
|
2019-01-14 03:16:25 +01:00
|
|
|
{
|
|
|
|
object result;
|
|
|
|
|
2019-01-27 16:31:32 +01:00
|
|
|
if (TYPE(input) == symbolObject)
|
2019-01-19 14:42:56 +01:00
|
|
|
{
|
2019-02-05 16:35:05 +01:00
|
|
|
result = referVariable(SYM(input), currentEnv);
|
2019-01-14 03:16:25 +01:00
|
|
|
}
|
|
|
|
else if (TYPE(input) == consObject)
|
|
|
|
{
|
|
|
|
if (!properList(input))
|
|
|
|
{
|
2019-02-09 14:06:53 +01:00
|
|
|
SIGERR(improperListError);
|
2019-01-14 03:16:25 +01:00
|
|
|
}
|
2019-01-19 20:30:52 +01:00
|
|
|
else
|
2019-01-14 03:16:25 +01:00
|
|
|
{
|
2019-02-09 14:06:53 +01:00
|
|
|
int regularEvalOrder = 1;
|
|
|
|
CAR(input) = eval(CAR(input), currentEnv);
|
|
|
|
if (TYPE(CAR(input)) == procedureObject &&
|
|
|
|
PROC_TYPE(CAR(input)) == builtinProc &&
|
|
|
|
PROC_SPECIAL(CAR(input)))
|
2019-01-27 16:31:32 +01:00
|
|
|
{
|
2019-02-09 14:06:53 +01:00
|
|
|
regularEvalOrder = 0;
|
2019-01-27 16:31:32 +01:00
|
|
|
}
|
|
|
|
|
2019-02-09 14:06:53 +01:00
|
|
|
object *currentCell = &CDR(input);
|
2019-01-19 20:30:52 +01:00
|
|
|
int noErrors = 1;
|
2019-02-09 14:06:53 +01:00
|
|
|
if (regularEvalOrder)
|
2019-01-14 03:16:25 +01:00
|
|
|
{
|
2019-01-27 16:31:32 +01:00
|
|
|
while (TYPE(*currentCell) != nilObject)
|
2019-01-19 20:30:52 +01:00
|
|
|
{
|
|
|
|
CAR(*currentCell) =
|
2019-02-05 16:35:05 +01:00
|
|
|
eval(CAR(*currentCell),
|
|
|
|
currentEnv);
|
2019-01-19 20:30:52 +01:00
|
|
|
|
2019-02-05 16:35:05 +01:00
|
|
|
if (TYPE(CAR(*currentCell)) ==
|
|
|
|
errorObject)
|
2019-01-27 16:31:32 +01:00
|
|
|
{
|
|
|
|
noErrors = 0;
|
2019-02-09 14:06:53 +01:00
|
|
|
object err = copyObject(
|
|
|
|
CAR(*currentCell));
|
|
|
|
deleteObject(input);
|
|
|
|
SIGERR(ERR(err));
|
2019-01-27 16:31:32 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
currentCell = &CDR(*currentCell);
|
2019-01-19 20:30:52 +01:00
|
|
|
}
|
2019-01-14 03:16:25 +01:00
|
|
|
}
|
|
|
|
|
2019-01-19 20:30:52 +01:00
|
|
|
if (noErrors)
|
|
|
|
{
|
2019-02-05 16:35:05 +01:00
|
|
|
result = apply(CAR(input), CDR(input),
|
|
|
|
currentEnv);
|
2019-01-19 20:30:52 +01:00
|
|
|
}
|
2019-01-14 03:16:25 +01:00
|
|
|
}
|
|
|
|
}
|
2019-01-27 16:31:32 +01:00
|
|
|
else
|
|
|
|
{
|
|
|
|
result = copyObject(input);
|
|
|
|
}
|
2019-01-14 03:16:25 +01:00
|
|
|
|
2019-01-19 20:30:52 +01:00
|
|
|
deleteObject(input);
|
2019-01-14 03:16:25 +01:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2019-02-05 16:35:05 +01:00
|
|
|
object apply(object procedure, object parameters, env currentEnv)
|
2019-01-14 03:16:25 +01:00
|
|
|
{
|
|
|
|
object result;
|
|
|
|
|
2019-01-27 16:31:32 +01:00
|
|
|
if (TYPE(procedure) != procedureObject)
|
2019-01-14 03:16:25 +01:00
|
|
|
{
|
2019-02-09 14:06:53 +01:00
|
|
|
SIGERR(notApplicableError);
|
2019-01-14 03:16:25 +01:00
|
|
|
}
|
2019-01-27 16:31:32 +01:00
|
|
|
|
|
|
|
if (PROC_TYPE(procedure) == builtinProc)
|
2019-01-14 03:16:25 +01:00
|
|
|
{
|
2019-01-29 00:07:33 +01:00
|
|
|
object(*f)() = PROC_BUILTIN(procedure);
|
2019-02-09 14:06:53 +01:00
|
|
|
if (f == defineInt || f == lambdaInt || f == ifInt)
|
2019-02-05 16:35:05 +01:00
|
|
|
{
|
|
|
|
result = f(parameters, currentEnv);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
result = f(parameters);
|
|
|
|
}
|
2019-01-29 00:07:33 +01:00
|
|
|
|
2019-01-27 16:31:32 +01:00
|
|
|
return result;
|
2019-01-14 03:16:25 +01:00
|
|
|
}
|
2019-01-27 16:31:32 +01:00
|
|
|
|
2019-02-05 20:08:25 +01:00
|
|
|
if (++currentRecursionDepth > MAXRECURSIONDEPTH)
|
|
|
|
{
|
|
|
|
--currentRecursionDepth;
|
|
|
|
SIGERR(maxRecursionDepthError);
|
|
|
|
}
|
2019-01-27 16:31:32 +01:00
|
|
|
object args = copyObject(PROC_COMP_ARGS(procedure));
|
|
|
|
object body = copyObject(PROC_COMP_BODY(procedure));
|
2019-02-05 16:35:05 +01:00
|
|
|
env definitionEnv = PROC_COMP_ENV(procedure);
|
2019-01-27 16:31:32 +01:00
|
|
|
if (listLength(parameters) != listLength(args))
|
2019-01-14 03:16:25 +01:00
|
|
|
{
|
2019-02-09 14:06:53 +01:00
|
|
|
SIGERR(argumentNumberError);
|
2019-01-14 03:16:25 +01:00
|
|
|
}
|
|
|
|
|
2019-02-05 16:35:05 +01:00
|
|
|
env procEnv = createEnvironment(definitionEnv);
|
2019-01-27 16:31:32 +01:00
|
|
|
object *currentArg = &args;
|
|
|
|
object *currentParam = ¶meters;
|
|
|
|
while (TYPE(*currentArg) != nilObject)
|
|
|
|
{
|
2019-02-05 16:35:05 +01:00
|
|
|
addSymbolVariable(SYM(CAR(*currentArg)), CAR(*currentParam),
|
|
|
|
procEnv);
|
2019-01-27 16:31:32 +01:00
|
|
|
currentArg = &CDR(*currentArg);
|
|
|
|
currentParam = &CDR(*currentParam);
|
|
|
|
}
|
|
|
|
object *currentSubProc = &body;
|
|
|
|
while (TYPE(*currentSubProc) != nilObject)
|
|
|
|
{
|
2019-02-05 16:35:05 +01:00
|
|
|
CAR(*currentSubProc) = eval(CAR(*currentSubProc), procEnv);
|
2019-01-27 16:31:32 +01:00
|
|
|
if (TYPE(CDR(*currentSubProc)) == nilObject)
|
|
|
|
{
|
2019-02-05 20:08:25 +01:00
|
|
|
result = copyObject(CAR(*currentSubProc));
|
2019-01-27 16:31:32 +01:00
|
|
|
}
|
|
|
|
currentSubProc = &CDR(*currentSubProc);
|
|
|
|
}
|
|
|
|
deleteObject(args);
|
|
|
|
deleteObject(body);
|
2019-02-05 16:35:05 +01:00
|
|
|
removeEnvironment(procEnv);
|
2019-02-05 20:08:25 +01:00
|
|
|
--currentRecursionDepth;
|
2019-01-27 16:31:32 +01:00
|
|
|
|
2019-01-14 03:16:25 +01:00
|
|
|
return result;
|
|
|
|
}
|