Поправљени багови у "ако", промењен систем детектовања специјалних форми

This commit is contained in:
kappa 2019-02-09 14:06:53 +01:00
parent b7f3124302
commit e8705cec39
8 changed files with 127 additions and 213 deletions

View file

@ -8,8 +8,8 @@ PREFIX = /usr/local
# флегови за C компајлер и линкер
CPPFLAGS = -D_POSIX_C_SOURCE=200200L
CFLAGS = -g -std=c99 -pedantic -Wall -O0
# CFLAGS = -std=c99 -pedantic -Wall -O3
# CFLAGS = -g -std=c99 -pedantic -Wall -O0
CFLAGS = -std=c99 -pedantic -Wall -O3
LDFLAGS = -lm -lc
CC = cc

36
eval.c
View file

@ -4,6 +4,7 @@
#include "util.h"
#include "internals.h"
#include "eval.h"
int currentRecursionDepth = 0;
#define MAXRECURSIONDEPTH 1000
@ -22,22 +23,22 @@ object eval(object input, env currentEnv)
{
if (!properList(input))
{
TYPE(result) = errorObject;
ERR(result) = improperListError;
SIGERR(improperListError);
}
else
{
int specialForm = 0;
if (TYPE(CAR(input)) == symbolObject &&
isSpecialForm(SYM(CAR(input))))
int regularEvalOrder = 1;
CAR(input) = eval(CAR(input), currentEnv);
if (TYPE(CAR(input)) == procedureObject &&
PROC_TYPE(CAR(input)) == builtinProc &&
PROC_SPECIAL(CAR(input)))
{
specialForm = 1;
CAR(input) = eval(CAR(input), currentEnv);
regularEvalOrder = 0;
}
object *currentCell = &input;
object *currentCell = &CDR(input);
int noErrors = 1;
if (!specialForm)
if (regularEvalOrder)
{
while (TYPE(*currentCell) != nilObject)
{
@ -49,9 +50,10 @@ object eval(object input, env currentEnv)
errorObject)
{
noErrors = 0;
TYPE(result) = errorObject;
ERR(result) =
ERR(CAR(*currentCell));
object err = copyObject(
CAR(*currentCell));
deleteObject(input);
SIGERR(ERR(err));
break;
}
currentCell = &CDR(*currentCell);
@ -80,15 +82,13 @@ object apply(object procedure, object parameters, env currentEnv)
if (TYPE(procedure) != procedureObject)
{
TYPE(result) = errorObject;
ERR(result) = notApplicableError;
return result;
SIGERR(notApplicableError);
}
if (PROC_TYPE(procedure) == builtinProc)
{
object(*f)() = PROC_BUILTIN(procedure);
if (f == define || f == lambda || f == ifStatement)
if (f == defineInt || f == lambdaInt || f == ifInt)
{
result = f(parameters, currentEnv);
}
@ -110,9 +110,7 @@ object apply(object procedure, object parameters, env currentEnv)
env definitionEnv = PROC_COMP_ENV(procedure);
if (listLength(parameters) != listLength(args))
{
TYPE(result) = errorObject;
ERR(result) = argumentNumberError;
return result;
SIGERR(argumentNumberError);
}
env procEnv = createEnvironment(definitionEnv);

24
init.c
View file

@ -16,16 +16,16 @@ void init()
* ћирилицу */
globalEnv = createEnvironment(NULL);
addSymbolInternal("+", &add);
addSymbolInternal("-", &subtract);
addSymbolInternal("*", &multiply);
addSymbolInternal("/", &divide);
addSymbolInternal("навод", &quote);
addSymbolInternal("дефиниши", &define);
addSymbolInternal("тачно->нетачно", &exactToInexact);
addSymbolInternal("нетачно->тачно", &inexactToExact);
addSymbolInternal("ламбда", &lambda);
addSymbolInternal("<", &less);
addSymbolInternal(">", &greater);
addSymbolInternal("ако", &ifStatement);
addSymbolInternal("+", &addInt, 0);
addSymbolInternal("-", &subtractInt, 0);
addSymbolInternal("*", &multiplyInt, 0);
addSymbolInternal("/", &divideInt, 0);
addSymbolInternal("навод", &quoteInt, 1);
addSymbolInternal("дефиниши", &defineInt, 1);
addSymbolInternal("тачно->нетачно", &exactToInexactInt, 0);
addSymbolInternal("нетачно->тачно", &inexactToExactInt, 0);
addSymbolInternal("ламбда", &lambdaInt, 1);
addSymbolInternal("<", &lessInt, 0);
addSymbolInternal(">", &greaterInt, 0);
addSymbolInternal("ако", &ifInt, 1);
}

View file

@ -33,15 +33,14 @@ int allSyms(object list)
object add(object parameters)
object addInt(object parameters)
{
object result;
TYPE(result) = numberObject;
if (!allNums(parameters))
{
TYPE(result) = errorObject;
ERR(result) = typeError;
SIGERR(typeError);
}
else if (listLength(parameters) == 0)
{
@ -51,7 +50,7 @@ object add(object parameters)
{
object first, rest;
first = CAR(parameters);
rest = add(CDR(parameters));
rest = addInt(CDR(parameters));
result = plusNum(first, rest);
}
@ -59,20 +58,18 @@ object add(object parameters)
return result;
}
object subtract(object parameters)
object subtractInt(object parameters)
{
object result;
TYPE(result) = numberObject;
if (!allNums(parameters))
{
TYPE(result) = errorObject;
ERR(result) = typeError;
SIGERR(typeError);
}
else if (listLength(parameters) == 0)
{
TYPE(result) = errorObject;
ERR(result) = argumentNumberError;
SIGERR(argumentNumberError);
}
else if (listLength(parameters) == 1)
{
@ -81,21 +78,20 @@ object subtract(object parameters)
else
{
result = plusNum(CAR(parameters),
minusNum(add(CDR(parameters))));
minusNum(addInt(CDR(parameters))));
}
return result;
}
object multiply(object parameters)
object multiplyInt(object parameters)
{
object result;
TYPE(result) = numberObject;
if (!allNums(parameters))
{
TYPE(result) = errorObject;
ERR(result) = typeError;
SIGERR(typeError);
}
else if (listLength(parameters) == 0)
{
@ -105,7 +101,7 @@ object multiply(object parameters)
{
object first, rest;
first = CAR(parameters);
rest = multiply(CDR(parameters));
rest = multiplyInt(CDR(parameters));
result = timesNum(first,rest);
}
@ -113,20 +109,18 @@ object multiply(object parameters)
return result;
}
object divide(object parameters)
object divideInt(object parameters)
{
object result;
TYPE(result) = numberObject;
if (!allNums(parameters))
{
TYPE(result) = errorObject;
ERR(result) = typeError;
SIGERR(typeError);
}
else if (listLength(parameters) == 0)
{
TYPE(result) = errorObject;
ERR(result) = argumentNumberError;
SIGERR(argumentNumberError);
}
else if (listLength(parameters) == 1)
{
@ -134,11 +128,11 @@ object divide(object parameters)
}
else
{
object check = inverseNum(multiply(CDR(parameters)));
object check = inverseNum(multiplyInt(CDR(parameters)));
if (TYPE(check) != errorObject)
{
result = timesNum(CAR(parameters),
inverseNum(multiply(CDR(parameters))));
inverseNum(multiplyInt(CDR(parameters))));
}
else
{
@ -150,19 +144,17 @@ object divide(object parameters)
return result;
}
object exactToInexact(object parameters)
object exactToInexactInt(object parameters)
{
object result;
if (listLength(parameters) != 1)
{
TYPE(result) = errorObject;
ERR(result) = argumentNumberError;
SIGERR(argumentNumberError);
}
else if (TYPE(CAR(parameters)) != numberObject)
{
TYPE(result) = errorObject;
ERR(result) = typeError;
SIGERR(typeError);
}
else
{
@ -172,19 +164,17 @@ object exactToInexact(object parameters)
return result;
}
object inexactToExact(object parameters)
object inexactToExactInt(object parameters)
{
object result;
if (listLength(parameters) != 1)
{
TYPE(result) = errorObject;
ERR(result) = argumentNumberError;
SIGERR(argumentNumberError);
}
else if (TYPE(CAR(parameters)) != numberObject)
{
TYPE(result) = errorObject;
ERR(result) = typeError;
SIGERR(typeError);
}
else
{
@ -194,13 +184,12 @@ object inexactToExact(object parameters)
return result;
}
object quote(object parameters)
object quoteInt(object parameters)
{
object result;
if (listLength(parameters) != 1)
{
TYPE(result) = errorObject;
ERR(result) = argumentNumberError;
SIGERR(argumentNumberError);
}
else
{
@ -239,18 +228,16 @@ breakloop:
}
}
object lambda(object parameters, env currentEnv)
object lambdaInt(object parameters, env currentEnv)
{
object result;
if (listLength(parameters) < 2)
{
TYPE(result) = errorObject;
ERR(result) = argumentNumberError;
SIGERR(argumentNumberError);
}
else if (!validArgumentList(CAR(parameters)))
{
TYPE(result) = errorObject;
ERR(result) = typeError;
SIGERR(typeError);
}
else
{
@ -265,28 +252,29 @@ object lambda(object parameters, env currentEnv)
return result;
}
object define(object parameters, env currentEnv)
object defineInt(object parameters, env currentEnv)
{
object result;
object result, value;
if (listLength(parameters) == 0)
{
TYPE(result) = errorObject;
ERR(result) = argumentNumberError;
SIGERR(argumentNumberError);
}
else if (TYPE(CAR(parameters)) == symbolObject)
{
if (listLength(parameters) == 2)
{
result = copyObject(CAR(parameters));
addSymbolVariable(SYM(result),
eval(copyObject(CAR(CDR(parameters))),
currentEnv),
currentEnv);
value = eval(copyObject(CAR(CDR(parameters))),
currentEnv);
if (TYPE(value) == errorObject)
{
SIGERR(ERR(value));
}
addSymbolVariable(SYM(result), value, currentEnv);
}
else
{
TYPE(result) = errorObject;
ERR(result) = argumentNumberError;
SIGERR(argumentNumberError);
}
}
else if (TYPE(CAR(parameters)) == consObject)
@ -300,32 +288,30 @@ object define(object parameters, env currentEnv)
deleteObject(CAR(parameters));
CAR(parameters) = copyObject(args);
deleteObject(args);
object proc = lambda(parameters, currentEnv);
object proc = lambdaInt(parameters,
currentEnv);
addSymbolVariable(SYM(result), proc,
currentEnv);
}
else
{
TYPE(result) = errorObject;
ERR(result) = typeError;
SIGERR(typeError);
}
}
else
{
TYPE(result) = errorObject;
ERR(result) = argumentNumberError;
SIGERR(argumentNumberError);
}
}
else
{
TYPE(result) = errorObject;
ERR(result) = typeError;
SIGERR(typeError);
}
return result;
}
object less(object parameters)
object lessInt(object parameters)
{
if (!allNums(parameters))
{
@ -355,7 +341,7 @@ object less(object parameters)
return result;
}
object greater(object parameters)
object greaterInt(object parameters)
{
if (!allNums(parameters))
{
@ -385,13 +371,17 @@ object greater(object parameters)
return result;
}
object ifStatement(object parameters, env currentEnv)
object ifInt(object parameters, env currentEnv)
{
object predicate, result;
switch (listLength(parameters))
{
case 2:
predicate = eval(CAR(parameters), currentEnv);
predicate = eval(copyObject(CAR(parameters)), currentEnv);
if (TYPE(predicate) == errorObject)
{
SIGERR(ERR(predicate));
}
if (TYPE(predicate) == boolObject && BOOL(predicate) == 0)
{
@ -402,9 +392,18 @@ object ifStatement(object parameters, env currentEnv)
result = eval(copyObject(CAR(CDR(parameters))),
currentEnv);
}
if (TYPE(result) == errorObject)
{
SIGERR(ERR(result));
}
break;
case 3:
predicate = eval(CAR(parameters), currentEnv);
predicate = eval(copyObject(CAR(parameters)), currentEnv);
if (TYPE(predicate) == errorObject)
{
SIGERR(ERR(predicate));
}
if (TYPE(predicate) == boolObject && BOOL(predicate) == 0)
{
@ -416,6 +415,11 @@ object ifStatement(object parameters, env currentEnv)
result = eval(copyObject(CAR(CDR(parameters))),
currentEnv);
}
if (TYPE(result) == errorObject)
{
SIGERR(ERR(result));
}
break;
default:
SIGERR(argumentNumberError);

View file

@ -1,15 +1,15 @@
#pragma once
#include "util.h"
object add(object parameters);
object subtract(object parameters);
object multiply(object parameters);
object divide(object parameters);
object exactToInexact(object parameters);
object inexactToExact(object parameters);
object quote(object parameters);
object lambda(object parameters);
object define(object parameters);
object less(object parameters);
object greater(object parameters);
object ifStatement(object parameters);
object addInt(object parameters);
object subtractInt(object parameters);
object multiplyInt(object parameters);
object divideInt(object parameters);
object exactToInexactInt(object parameters);
object inexactToExactInt(object parameters);
object quoteInt(object parameters);
object lambdaInt(object parameters);
object defineInt(object parameters);
object lessInt(object parameters);
object greaterInt(object parameters);
object ifInt(object parameters);

73
read.c
View file

@ -126,83 +126,14 @@ int lengthDigitArray(char *s)
return i;
}
int isFracNumToken(char *s)
{
int digitNum1 = lengthDigitArray(s);
if (digitNum1 == 0)
{
return 0;
}
else if (s[digitNum1] == '\0')
{
return 1;
}
else if (s[digitNum1] == '/')
{
int digitNum2 = lengthDigitArray(s + digitNum1 + 1);
if (digitNum2 == 0)
{
return 0;
}
else if (s[digitNum1 + 1 + digitNum2] == '\0')
{
return 1;
}
else
{
return 0;
}
}
else
{
return 0;
}
}
int isRealNumToken(char *s)
{
int digitNum1 = lengthDigitArray(s);
if (digitNum1 == 0)
{
return 0;
}
else if (s[digitNum1] == '\0')
{
return 1;
}
else if (s[digitNum1] == ',')
{
int digitNum2 = lengthDigitArray(s + digitNum1 + 1);
if (digitNum2 == 0)
{
return 0;
}
else if (s[digitNum1 + 1 + digitNum2] == '\0')
{
return 1;
}
else
{
return 0;
}
}
else
{
return 0;
}
}
object getToken()
{
object result;
wchar_t *buffer = getBuffer();
wint_t c;
int i = 0;
buffer[0] = c = scanwc(stdin);
c = scanwc(stdin);
buffer[0] = towlower(c);
if (isEscape(c))
{
while (!isEscape(c = scanwc(stdin)))

33
util.c
View file

@ -62,7 +62,7 @@ void removeEnvironment(env input)
free(input);
}
void addSymbolInternal(char *symbol, object (*function)())
void addSymbolInternal(char *symbol, object (*function)(), int isSpecialForm)
{
entry **e = findEntry(&globalEnv->table, symbol);
@ -79,6 +79,7 @@ void addSymbolInternal(char *symbol, object (*function)())
PROC((*e)->value) = createProcedure();
PROC_TYPE((*e)->value) = builtinProc;
PROC_BUILTIN((*e)->value) = function;
PROC_SPECIAL((*e)->value) = isSpecialForm;
(*e)->name = malloc(sizeof(char) * (strlen(symbol) + 1));
strcpy((*e)->name, symbol);
(*e)->left = (*e)->right = NULL;
@ -123,29 +124,6 @@ object referVariable(char *symbol,env currentEnv)
}
}
#define SPECIALFORMSNUM 4
int isSpecialForm(char *symbol)
{
int result = 0;
char *specialForms[] =
{
"навод",
"дефиниши",
"ламбда",
"ако"
};
for (int i = 0; i < SPECIALFORMSNUM; ++i)
{
if (!strcmp(symbol, specialForms[i]))
{
result = 1;
}
}
return result;
}
int properList(object list)
{
object *current = &list;
@ -224,6 +202,7 @@ object copyObject(object input)
if (PROC_TYPE(result) == builtinProc)
{
PROC_BUILTIN(result) = PROC_BUILTIN(input);
PROC_SPECIAL(result) = PROC_SPECIAL(input);
}
else
{
@ -340,8 +319,7 @@ object shortenFractionNum(object a)
if (NUM_DENOM(result) == 0)
{
deleteObject(result);
TYPE(result) = errorObject;
ERR(result) = divisionByZeroError;
SIGERR(divisionByZeroError);
}
else if (NUM_NUMER(result) == 0)
{
@ -442,8 +420,7 @@ object inverseNum(object a)
if (NUM_NUMER(result) == 0)
{
deleteObject(result);
TYPE(result) = errorObject;
ERR(result) = divisionByZeroError;
SIGERR(divisionByZeroError);
}
else
{

20
util.h
View file

@ -15,15 +15,16 @@
#define SIGERR(error) \
{\
object result;\
TYPE(result) = errorObject;\
ERR(result) = error;\
return result;\
object __result;\
TYPE(__result) = errorObject;\
ERR(__result) = error;\
return __result;\
}
#define PROC(x) ((x).value.proc)
#define PROC_TYPE(x) ((x).value.proc->type)
#define PROC_BUILTIN(x) ((x).value.proc->value.builtin)
#define PROC_BUILTIN(x) ((x).value.proc->value.builtin.pointer)
#define PROC_SPECIAL(x) ((x).value.proc->value.builtin.isSpecialForm)
#define PROC_COMP_ARGS(x) ((x).value.proc->value.compound.args)
#define PROC_COMP_BODY(x) ((x).value.proc->value.compound.body)
#define PROC_COMP_ENV(x) ((x).value.proc->value.compound.environment)
@ -142,7 +143,11 @@ struct procedure
procType type;
union
{
object (*builtin)(object);
struct
{
object (*pointer)(object);
int isSpecialForm;
} builtin;
struct
{
object args;
@ -158,7 +163,7 @@ env globalEnv;
env createEnvironment(env enclosing);
void removeEnvironment(env input);
void addSymbolInternal(char *symbol, object (*function)());
void addSymbolInternal(char *symbol, object (*function)(), int isSpecialForm);
void addSymbolVariable(char *symbol, object variable, env currentEnv);
/* функције помоћу којих се дефинишу нове променљиве: addSymbolVariable се
* позива током корисничких дефиниција у програму, док се addSymbolInternal
@ -171,7 +176,6 @@ object referVariable(char *symbol, env currentEnv);
/* враћа вредност на коју се односи име симбола у табели */
/******************************* */
int isSpecialForm(char *symbol);
int properList(object list);
int listLength(object list);
void deleteObject(object input);