From e8705cec3919abaad5a1ff7ed9f18feede498cfd Mon Sep 17 00:00:00 2001 From: kappa Date: Sat, 9 Feb 2019 14:06:53 +0100 Subject: [PATCH] =?UTF-8?q?=D0=9F=D0=BE=D0=BF=D1=80=D0=B0=D0=B2=D1=99?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=20=D0=B1=D0=B0=D0=B3=D0=BE=D0=B2=D0=B8=20?= =?UTF-8?q?=D1=83=20"=D0=B0=D0=BA=D0=BE",=20=D0=BF=D1=80=D0=BE=D0=BC=D0=B5?= =?UTF-8?q?=D1=9A=D0=B5=D0=BD=20=D1=81=D0=B8=D1=81=D1=82=D0=B5=D0=BC=20?= =?UTF-8?q?=D0=B4=D0=B5=D1=82=D0=B5=D0=BA=D1=82=D0=BE=D0=B2=D0=B0=D1=9A?= =?UTF-8?q?=D0=B0=20=D1=81=D0=BF=D0=B5=D1=86=D0=B8=D1=98=D0=B0=D0=BB=D0=BD?= =?UTF-8?q?=D0=B8=D1=85=20=D1=84=D0=BE=D1=80=D0=BC=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Makefile | 4 +- eval.c | 36 +++++++-------- init.c | 24 +++++----- internals.c | 126 +++++++++++++++++++++++++++------------------------- internals.h | 24 +++++----- read.c | 73 +----------------------------- util.c | 33 +++----------- util.h | 20 +++++---- 8 files changed, 127 insertions(+), 213 deletions(-) diff --git a/Makefile b/Makefile index 1c207e8..0f99652 100644 --- a/Makefile +++ b/Makefile @@ -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 diff --git a/eval.c b/eval.c index 91a865f..a741a3c 100644 --- a/eval.c +++ b/eval.c @@ -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); diff --git a/init.c b/init.c index 41cde93..2c335e0 100644 --- a/init.c +++ b/init.c @@ -16,16 +16,16 @@ void init() * ћирилицу */ globalEnv = createEnvironment(NULL); - addSymbolInternal("+", &add); - addSymbolInternal("-", &subtract); - addSymbolInternal("*", &multiply); - addSymbolInternal("/", ÷); - addSymbolInternal("навод", "e); - addSymbolInternal("дефиниши", &define); - addSymbolInternal("тачно->нетачно", &exactToInexact); - addSymbolInternal("нетачно->тачно", &inexactToExact); - addSymbolInternal("ламбда", &lambda); - addSymbolInternal("<", &less); - addSymbolInternal(">", &greater); - addSymbolInternal("ако", &ifStatement); + addSymbolInternal("+", &addInt, 0); + addSymbolInternal("-", &subtractInt, 0); + addSymbolInternal("*", &multiplyInt, 0); + addSymbolInternal("/", ÷Int, 0); + addSymbolInternal("навод", "eInt, 1); + addSymbolInternal("дефиниши", &defineInt, 1); + addSymbolInternal("тачно->нетачно", &exactToInexactInt, 0); + addSymbolInternal("нетачно->тачно", &inexactToExactInt, 0); + addSymbolInternal("ламбда", &lambdaInt, 1); + addSymbolInternal("<", &lessInt, 0); + addSymbolInternal(">", &greaterInt, 0); + addSymbolInternal("ако", &ifInt, 1); } diff --git a/internals.c b/internals.c index b803c27..cdbf1c3 100644 --- a/internals.c +++ b/internals.c @@ -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); diff --git a/internals.h b/internals.h index e897f0b..54bc6dd 100644 --- a/internals.h +++ b/internals.h @@ -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); diff --git a/read.c b/read.c index 659f6f7..1e415c9 100644 --- a/read.c +++ b/read.c @@ -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))) diff --git a/util.c b/util.c index e5d807d..e5c9536 100644 --- a/util.c +++ b/util.c @@ -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 { diff --git a/util.h b/util.h index 46716f9..0031efc 100644 --- a/util.h +++ b/util.h @@ -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);