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

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 компајлер и линкер # флегови за C компајлер и линкер
CPPFLAGS = -D_POSIX_C_SOURCE=200200L CPPFLAGS = -D_POSIX_C_SOURCE=200200L
CFLAGS = -g -std=c99 -pedantic -Wall -O0 # CFLAGS = -g -std=c99 -pedantic -Wall -O0
# CFLAGS = -std=c99 -pedantic -Wall -O3 CFLAGS = -std=c99 -pedantic -Wall -O3
LDFLAGS = -lm -lc LDFLAGS = -lm -lc
CC = cc CC = cc

36
eval.c
View file

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

24
init.c
View file

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

View file

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

View file

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

73
read.c
View file

@ -126,83 +126,14 @@ int lengthDigitArray(char *s)
return i; 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 getToken()
{ {
object result; object result;
wchar_t *buffer = getBuffer(); wchar_t *buffer = getBuffer();
wint_t c; wint_t c;
int i = 0; int i = 0;
buffer[0] = c = scanwc(stdin); c = scanwc(stdin);
buffer[0] = towlower(c);
if (isEscape(c)) if (isEscape(c))
{ {
while (!isEscape(c = scanwc(stdin))) while (!isEscape(c = scanwc(stdin)))

33
util.c
View file

@ -62,7 +62,7 @@ void removeEnvironment(env input)
free(input); free(input);
} }
void addSymbolInternal(char *symbol, object (*function)()) void addSymbolInternal(char *symbol, object (*function)(), int isSpecialForm)
{ {
entry **e = findEntry(&globalEnv->table, symbol); entry **e = findEntry(&globalEnv->table, symbol);
@ -79,6 +79,7 @@ void addSymbolInternal(char *symbol, object (*function)())
PROC((*e)->value) = createProcedure(); PROC((*e)->value) = createProcedure();
PROC_TYPE((*e)->value) = builtinProc; PROC_TYPE((*e)->value) = builtinProc;
PROC_BUILTIN((*e)->value) = function; PROC_BUILTIN((*e)->value) = function;
PROC_SPECIAL((*e)->value) = isSpecialForm;
(*e)->name = malloc(sizeof(char) * (strlen(symbol) + 1)); (*e)->name = malloc(sizeof(char) * (strlen(symbol) + 1));
strcpy((*e)->name, symbol); strcpy((*e)->name, symbol);
(*e)->left = (*e)->right = NULL; (*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) int properList(object list)
{ {
object *current = &list; object *current = &list;
@ -224,6 +202,7 @@ object copyObject(object input)
if (PROC_TYPE(result) == builtinProc) if (PROC_TYPE(result) == builtinProc)
{ {
PROC_BUILTIN(result) = PROC_BUILTIN(input); PROC_BUILTIN(result) = PROC_BUILTIN(input);
PROC_SPECIAL(result) = PROC_SPECIAL(input);
} }
else else
{ {
@ -340,8 +319,7 @@ object shortenFractionNum(object a)
if (NUM_DENOM(result) == 0) if (NUM_DENOM(result) == 0)
{ {
deleteObject(result); deleteObject(result);
TYPE(result) = errorObject; SIGERR(divisionByZeroError);
ERR(result) = divisionByZeroError;
} }
else if (NUM_NUMER(result) == 0) else if (NUM_NUMER(result) == 0)
{ {
@ -442,8 +420,7 @@ object inverseNum(object a)
if (NUM_NUMER(result) == 0) if (NUM_NUMER(result) == 0)
{ {
deleteObject(result); deleteObject(result);
TYPE(result) = errorObject; SIGERR(divisionByZeroError);
ERR(result) = divisionByZeroError;
} }
else else
{ {

20
util.h
View file

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