2019-02-04 21:16:35 +01:00
|
|
|
#include <string.h>
|
|
|
|
|
2019-01-19 14:42:56 +01:00
|
|
|
#include "util.h"
|
2019-01-22 00:08:27 +01:00
|
|
|
#include "eval.h"
|
2019-01-19 14:42:56 +01:00
|
|
|
|
2019-01-29 00:07:33 +01:00
|
|
|
int allNums(object list)
|
2019-01-19 14:42:56 +01:00
|
|
|
{
|
|
|
|
object *currentCell = &list;
|
|
|
|
while (TYPE(*currentCell) != nilObject)
|
|
|
|
{
|
|
|
|
if (TYPE(CAR(*currentCell)) != numberObject)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
currentCell = &CDR(*currentCell);
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2019-01-29 00:07:33 +01:00
|
|
|
int allSyms(object list)
|
|
|
|
{
|
|
|
|
object *currentCell = &list;
|
|
|
|
while (TYPE(*currentCell) != nilObject)
|
|
|
|
{
|
|
|
|
if (TYPE(CAR(*currentCell)) != symbolObject)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
currentCell = &CDR(*currentCell);
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2019-02-04 21:16:35 +01:00
|
|
|
|
|
|
|
|
2019-02-09 14:06:53 +01:00
|
|
|
object addInt(object parameters)
|
2019-01-19 14:42:56 +01:00
|
|
|
{
|
|
|
|
object result;
|
|
|
|
TYPE(result) = numberObject;
|
|
|
|
|
2019-01-29 00:07:33 +01:00
|
|
|
if (!allNums(parameters))
|
2019-01-19 14:42:56 +01:00
|
|
|
{
|
2019-02-09 14:06:53 +01:00
|
|
|
SIGERR(typeError);
|
2019-01-19 14:42:56 +01:00
|
|
|
}
|
|
|
|
else if (listLength(parameters) == 0)
|
|
|
|
{
|
2019-01-20 23:48:12 +01:00
|
|
|
result = longlongToNumber(0LL);
|
2019-01-19 14:42:56 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
object first, rest;
|
|
|
|
first = CAR(parameters);
|
2019-02-09 14:06:53 +01:00
|
|
|
rest = addInt(CDR(parameters));
|
2019-01-19 14:42:56 +01:00
|
|
|
|
2019-01-20 23:48:12 +01:00
|
|
|
result = plusNum(first, rest);
|
2019-01-19 14:42:56 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2019-02-09 14:06:53 +01:00
|
|
|
object subtractInt(object parameters)
|
2019-01-19 14:42:56 +01:00
|
|
|
{
|
|
|
|
object result;
|
|
|
|
TYPE(result) = numberObject;
|
|
|
|
|
2019-01-29 00:07:33 +01:00
|
|
|
if (!allNums(parameters))
|
2019-01-19 14:42:56 +01:00
|
|
|
{
|
2019-02-09 14:06:53 +01:00
|
|
|
SIGERR(typeError);
|
2019-01-19 14:42:56 +01:00
|
|
|
}
|
|
|
|
else if (listLength(parameters) == 0)
|
|
|
|
{
|
2019-02-09 14:06:53 +01:00
|
|
|
SIGERR(argumentNumberError);
|
2019-01-19 14:42:56 +01:00
|
|
|
}
|
|
|
|
else if (listLength(parameters) == 1)
|
|
|
|
{
|
2019-01-20 23:48:12 +01:00
|
|
|
result = minusNum(CAR(parameters));
|
2019-01-19 14:42:56 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-01-20 23:48:12 +01:00
|
|
|
result = plusNum(CAR(parameters),
|
2019-02-09 14:06:53 +01:00
|
|
|
minusNum(addInt(CDR(parameters))));
|
2019-01-19 14:42:56 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2019-02-09 14:06:53 +01:00
|
|
|
object multiplyInt(object parameters)
|
2019-01-19 14:42:56 +01:00
|
|
|
{
|
|
|
|
object result;
|
|
|
|
TYPE(result) = numberObject;
|
|
|
|
|
2019-01-29 00:07:33 +01:00
|
|
|
if (!allNums(parameters))
|
2019-01-19 14:42:56 +01:00
|
|
|
{
|
2019-02-09 14:06:53 +01:00
|
|
|
SIGERR(typeError);
|
2019-01-19 14:42:56 +01:00
|
|
|
}
|
|
|
|
else if (listLength(parameters) == 0)
|
|
|
|
{
|
2019-01-20 23:48:12 +01:00
|
|
|
result = longlongToNumber(1LL);
|
2019-01-19 14:42:56 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
object first, rest;
|
|
|
|
first = CAR(parameters);
|
2019-02-09 14:06:53 +01:00
|
|
|
rest = multiplyInt(CDR(parameters));
|
2019-01-19 14:42:56 +01:00
|
|
|
|
2019-01-20 23:48:12 +01:00
|
|
|
result = timesNum(first,rest);
|
2019-01-19 14:42:56 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2019-02-09 14:06:53 +01:00
|
|
|
object divideInt(object parameters)
|
2019-01-19 14:42:56 +01:00
|
|
|
{
|
|
|
|
object result;
|
|
|
|
TYPE(result) = numberObject;
|
|
|
|
|
2019-01-29 00:07:33 +01:00
|
|
|
if (!allNums(parameters))
|
2019-01-19 14:42:56 +01:00
|
|
|
{
|
2019-02-09 14:06:53 +01:00
|
|
|
SIGERR(typeError);
|
2019-01-19 14:42:56 +01:00
|
|
|
}
|
|
|
|
else if (listLength(parameters) == 0)
|
|
|
|
{
|
2019-02-09 14:06:53 +01:00
|
|
|
SIGERR(argumentNumberError);
|
2019-01-19 14:42:56 +01:00
|
|
|
}
|
|
|
|
else if (listLength(parameters) == 1)
|
|
|
|
{
|
2019-01-20 23:48:12 +01:00
|
|
|
result = inverseNum(CAR(parameters));
|
2019-01-19 14:42:56 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-02-09 14:06:53 +01:00
|
|
|
object check = inverseNum(multiplyInt(CDR(parameters)));
|
2019-01-20 23:48:12 +01:00
|
|
|
if (TYPE(check) != errorObject)
|
2019-01-19 14:42:56 +01:00
|
|
|
{
|
2019-01-20 23:48:12 +01:00
|
|
|
result = timesNum(CAR(parameters),
|
2019-02-09 14:06:53 +01:00
|
|
|
inverseNum(multiplyInt(CDR(parameters))));
|
2019-01-19 14:42:56 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-01-20 23:48:12 +01:00
|
|
|
result = check;
|
2019-01-19 14:42:56 +01:00
|
|
|
}
|
2019-01-20 23:48:12 +01:00
|
|
|
result = shortenFractionNum(result);
|
2019-01-19 14:42:56 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
2019-01-19 20:30:52 +01:00
|
|
|
|
2019-02-09 14:06:53 +01:00
|
|
|
object exactToInexactInt(object parameters)
|
2019-01-21 18:44:56 +01:00
|
|
|
{
|
|
|
|
object result;
|
|
|
|
|
|
|
|
if (listLength(parameters) != 1)
|
|
|
|
{
|
2019-02-09 14:06:53 +01:00
|
|
|
SIGERR(argumentNumberError);
|
2019-01-21 18:44:56 +01:00
|
|
|
}
|
|
|
|
else if (TYPE(CAR(parameters)) != numberObject)
|
|
|
|
{
|
2019-02-09 14:06:53 +01:00
|
|
|
SIGERR(typeError);
|
2019-01-21 18:44:56 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
result = exactToInexactNum(CAR(parameters));
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2019-02-09 14:06:53 +01:00
|
|
|
object inexactToExactInt(object parameters)
|
2019-01-21 18:44:56 +01:00
|
|
|
{
|
|
|
|
object result;
|
|
|
|
|
|
|
|
if (listLength(parameters) != 1)
|
|
|
|
{
|
2019-02-09 14:06:53 +01:00
|
|
|
SIGERR(argumentNumberError);
|
2019-01-21 18:44:56 +01:00
|
|
|
}
|
|
|
|
else if (TYPE(CAR(parameters)) != numberObject)
|
|
|
|
{
|
2019-02-09 14:06:53 +01:00
|
|
|
SIGERR(typeError);
|
2019-01-21 18:44:56 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
result = inexactToExactNum(CAR(parameters));
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2019-02-09 14:06:53 +01:00
|
|
|
object quoteInt(object parameters)
|
2019-01-19 20:30:52 +01:00
|
|
|
{
|
|
|
|
object result;
|
|
|
|
if (listLength(parameters) != 1)
|
|
|
|
{
|
2019-02-09 14:06:53 +01:00
|
|
|
SIGERR(argumentNumberError);
|
2019-01-19 20:30:52 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
result = copyObject(CAR(parameters));
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
2019-01-22 00:08:27 +01:00
|
|
|
|
2019-02-04 21:16:35 +01:00
|
|
|
int validArgumentList(object list)
|
|
|
|
{
|
|
|
|
if (!properList(list) || !allSyms(list))
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
int allUniqueSyms = 1;
|
|
|
|
object *currentSymbol1 = &list;
|
|
|
|
while (TYPE(*currentSymbol1) != nilObject)
|
|
|
|
{
|
|
|
|
object *currentSymbol2 = &CDR(*currentSymbol1);
|
|
|
|
while (TYPE(*currentSymbol2) != nilObject)
|
|
|
|
{
|
|
|
|
if (!strcmp(SYM(CAR(*currentSymbol1)),
|
|
|
|
SYM(CAR(*currentSymbol2))))
|
|
|
|
{
|
|
|
|
allUniqueSyms = 0;
|
|
|
|
goto breakloop;
|
|
|
|
}
|
|
|
|
currentSymbol2 = &CDR(*currentSymbol2);
|
|
|
|
}
|
|
|
|
currentSymbol1 = &CDR(*currentSymbol1);
|
|
|
|
}
|
|
|
|
breakloop:
|
|
|
|
return allUniqueSyms;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-09 14:06:53 +01:00
|
|
|
object lambdaInt(object parameters, env currentEnv)
|
2019-01-29 00:07:33 +01:00
|
|
|
{
|
|
|
|
object result;
|
|
|
|
if (listLength(parameters) < 2)
|
|
|
|
{
|
2019-02-09 14:06:53 +01:00
|
|
|
SIGERR(argumentNumberError);
|
2019-01-29 00:07:33 +01:00
|
|
|
}
|
2019-02-04 21:16:35 +01:00
|
|
|
else if (!validArgumentList(CAR(parameters)))
|
2019-01-29 00:07:33 +01:00
|
|
|
{
|
2019-02-09 14:06:53 +01:00
|
|
|
SIGERR(typeError);
|
2019-01-29 00:07:33 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
TYPE(result) = procedureObject;
|
|
|
|
PROC(result) = createProcedure();
|
|
|
|
PROC_TYPE(result) = compoundProc;
|
|
|
|
PROC_COMP_ARGS(result) = copyObject(CAR(parameters));
|
|
|
|
PROC_COMP_BODY(result) = copyObject(CDR(parameters));
|
2019-02-05 16:35:05 +01:00
|
|
|
PROC_COMP_ENV(result) = currentEnv;
|
2019-01-29 00:07:33 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2019-02-09 14:06:53 +01:00
|
|
|
object defineInt(object parameters, env currentEnv)
|
2019-01-22 00:08:27 +01:00
|
|
|
{
|
2019-02-09 14:06:53 +01:00
|
|
|
object result, value;
|
2019-01-29 00:07:33 +01:00
|
|
|
if (listLength(parameters) == 0)
|
2019-01-22 00:08:27 +01:00
|
|
|
{
|
2019-02-09 14:06:53 +01:00
|
|
|
SIGERR(argumentNumberError);
|
2019-01-22 00:08:27 +01:00
|
|
|
}
|
|
|
|
else if (TYPE(CAR(parameters)) == symbolObject)
|
|
|
|
{
|
2019-01-29 00:07:33 +01:00
|
|
|
if (listLength(parameters) == 2)
|
|
|
|
{
|
|
|
|
result = copyObject(CAR(parameters));
|
2019-02-09 14:06:53 +01:00
|
|
|
value = eval(copyObject(CAR(CDR(parameters))),
|
|
|
|
currentEnv);
|
|
|
|
if (TYPE(value) == errorObject)
|
|
|
|
{
|
|
|
|
SIGERR(ERR(value));
|
|
|
|
}
|
|
|
|
addSymbolVariable(SYM(result), value, currentEnv);
|
2019-01-29 00:07:33 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-02-09 14:06:53 +01:00
|
|
|
SIGERR(argumentNumberError);
|
2019-01-29 00:07:33 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (TYPE(CAR(parameters)) == consObject)
|
|
|
|
{
|
|
|
|
if (listLength(parameters) >= 2)
|
|
|
|
{
|
|
|
|
if (allSyms(CAR(parameters)))
|
|
|
|
{
|
|
|
|
result = copyObject(CAR(CAR(parameters)));
|
|
|
|
object args = copyObject(CDR(CAR(parameters)));
|
|
|
|
deleteObject(CAR(parameters));
|
|
|
|
CAR(parameters) = copyObject(args);
|
|
|
|
deleteObject(args);
|
2019-02-09 14:06:53 +01:00
|
|
|
object proc = lambdaInt(parameters,
|
|
|
|
currentEnv);
|
2019-02-05 16:35:05 +01:00
|
|
|
addSymbolVariable(SYM(result), proc,
|
|
|
|
currentEnv);
|
2019-01-29 00:07:33 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-02-09 14:06:53 +01:00
|
|
|
SIGERR(typeError);
|
2019-01-29 00:07:33 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-02-09 14:06:53 +01:00
|
|
|
SIGERR(argumentNumberError);
|
2019-01-29 00:07:33 +01:00
|
|
|
}
|
2019-01-22 00:08:27 +01:00
|
|
|
}
|
2019-01-27 16:31:32 +01:00
|
|
|
else
|
|
|
|
{
|
2019-02-09 14:06:53 +01:00
|
|
|
SIGERR(typeError);
|
2019-01-27 16:31:32 +01:00
|
|
|
}
|
2019-01-22 00:08:27 +01:00
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
2019-02-07 23:07:02 +01:00
|
|
|
|
2019-02-09 14:06:53 +01:00
|
|
|
object lessInt(object parameters)
|
2019-02-07 23:07:02 +01:00
|
|
|
{
|
|
|
|
if (!allNums(parameters))
|
|
|
|
{
|
|
|
|
SIGERR(typeError);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (listLength(parameters) == 0 || listLength(parameters) == 1)
|
|
|
|
{
|
|
|
|
return intToBool(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
int resultInt = 1;
|
|
|
|
object *current = ¶meters;
|
|
|
|
while (TYPE(CDR(*current)) != nilObject)
|
|
|
|
{
|
|
|
|
if (cmp(CAR(*current), CAR(CDR(*current))) >= 0)
|
|
|
|
{
|
|
|
|
resultInt = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
current = &CDR(*current);
|
|
|
|
}
|
|
|
|
|
|
|
|
object result;
|
|
|
|
TYPE(result) = boolObject;
|
|
|
|
BOOL(result) = resultInt;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2019-02-09 14:06:53 +01:00
|
|
|
object greaterInt(object parameters)
|
2019-02-07 23:07:02 +01:00
|
|
|
{
|
|
|
|
if (!allNums(parameters))
|
|
|
|
{
|
|
|
|
SIGERR(typeError);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (listLength(parameters) == 0 || listLength(parameters) == 1)
|
|
|
|
{
|
|
|
|
return intToBool(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
int resultInt = 1;
|
|
|
|
object *current = ¶meters;
|
|
|
|
while (TYPE(CDR(*current)) != nilObject)
|
|
|
|
{
|
|
|
|
if (cmp(CAR(*current), CAR(CDR(*current))) <= 0)
|
|
|
|
{
|
|
|
|
resultInt = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
current = &CDR(*current);
|
|
|
|
}
|
|
|
|
|
|
|
|
object result;
|
|
|
|
TYPE(result) = boolObject;
|
|
|
|
BOOL(result) = resultInt;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2019-02-09 14:06:53 +01:00
|
|
|
object ifInt(object parameters, env currentEnv)
|
2019-02-07 23:07:02 +01:00
|
|
|
{
|
|
|
|
object predicate, result;
|
|
|
|
switch (listLength(parameters))
|
|
|
|
{
|
|
|
|
case 2:
|
2019-02-09 14:06:53 +01:00
|
|
|
predicate = eval(copyObject(CAR(parameters)), currentEnv);
|
|
|
|
if (TYPE(predicate) == errorObject)
|
|
|
|
{
|
|
|
|
SIGERR(ERR(predicate));
|
|
|
|
}
|
2019-02-07 23:07:02 +01:00
|
|
|
|
|
|
|
if (TYPE(predicate) == boolObject && BOOL(predicate) == 0)
|
|
|
|
{
|
|
|
|
TYPE(result) = unspecifiedObject;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
result = eval(copyObject(CAR(CDR(parameters))),
|
|
|
|
currentEnv);
|
|
|
|
}
|
2019-02-09 14:06:53 +01:00
|
|
|
|
|
|
|
if (TYPE(result) == errorObject)
|
|
|
|
{
|
|
|
|
SIGERR(ERR(result));
|
|
|
|
}
|
2019-02-07 23:07:02 +01:00
|
|
|
break;
|
|
|
|
case 3:
|
2019-02-09 14:06:53 +01:00
|
|
|
predicate = eval(copyObject(CAR(parameters)), currentEnv);
|
|
|
|
if (TYPE(predicate) == errorObject)
|
|
|
|
{
|
|
|
|
SIGERR(ERR(predicate));
|
|
|
|
}
|
2019-02-07 23:07:02 +01:00
|
|
|
|
|
|
|
if (TYPE(predicate) == boolObject && BOOL(predicate) == 0)
|
|
|
|
{
|
|
|
|
result = eval(copyObject(CAR(CDR(CDR(parameters)))),
|
|
|
|
currentEnv);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
result = eval(copyObject(CAR(CDR(parameters))),
|
|
|
|
currentEnv);
|
|
|
|
}
|
2019-02-09 14:06:53 +01:00
|
|
|
|
|
|
|
if (TYPE(result) == errorObject)
|
|
|
|
{
|
|
|
|
SIGERR(ERR(result));
|
|
|
|
}
|
2019-02-07 23:07:02 +01:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
SIGERR(argumentNumberError);
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|