From d24fa3945d59f4ccaee8bd7bca87a092932d91ac Mon Sep 17 00:00:00 2001 From: kappa Date: Tue, 19 Feb 2019 09:49:55 +0100 Subject: [PATCH] =?UTF-8?q?=D0=98=D0=BC=D0=BF=D0=BB=D0=B5=D0=BC=D0=B5?= =?UTF-8?q?=D0=BD=D1=82=D0=B8=D1=80=D0=B0=D0=BD=D0=B5=20=D0=BA=D0=BE=D0=BC?= =?UTF-8?q?=D0=B0=D0=BD=D0=B4=D0=BD=D0=BE-=D0=BB=D0=B8=D0=BD=D0=B8=D1=98?= =?UTF-8?q?=D1=81=D0=BA=D0=B5=20=D0=BE=D0=BF=D1=86=D0=B8=D1=98=D0=B5,=20?= =?UTF-8?q?=D0=B4=D0=BE=D0=B4=D0=B0=D1=82=D0=B5=20=D1=84=D1=83=D0=BD=D0=BA?= =?UTF-8?q?=D1=86=D0=B8=D1=98=D0=B5=20=D0=B7=D0=B0=20=D0=BF=D1=80=D0=B5?= =?UTF-8?q?=D0=BF=D0=BE=D0=B7=D0=BD=D0=B0=D0=B2=D0=B0=D1=9A=D0=B5=20=D1=82?= =?UTF-8?q?=D0=B8=D0=BF=D0=BE=D0=B2=D0=B0=20=D0=B1=D1=80=D0=BE=D1=98=D0=B5?= =?UTF-8?q?=D0=B2=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Makefile | 5 ++-- cirilisp.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++----- eval.c | 10 ++++---- eval.h | 2 +- internals.c | 65 ++++++++++++++++++++++++++++++++++++++++++++----- internals.h | 4 +++ print.c | 2 +- print.h | 2 +- read.c | 18 +++++++++++--- read.h | 2 +- инит.ћ | 5 ++++ 11 files changed, 158 insertions(+), 27 deletions(-) diff --git a/Makefile b/Makefile index 6cfe63a..8c3f0ba 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,8 @@ PREFIX = /usr/local LIBPREFIX = $(PREFIX)/lib # флегови за C компајлер и линкер -CPPFLAGS = -D_POSIX_C_SOURCE=200200L -DDESTDIR=\"$(DESTDIR)\" +CPPFLAGS = -D_POSIX_C_SOURCE=200200L -DDESTDIR=\"$(DESTDIR)\" \ +-DVERSION=\"$(VERSION)\" CFLAGS = -g -std=c99 -pedantic -Wall -O0 # CFLAGS = -std=c99 -pedantic -Wall -O3 LDFLAGS = -lm -lc @@ -25,7 +26,7 @@ all: cirilisp $(L_SRC) .c.o: $(CC) -c $(CPPFLAGS) $(CFLAGS) $< -$(OBJ): $(INC) $(L_SRC) +$(OBJ): $(INC) cirilisp: $(OBJ) $(CC) -o $@ $(OBJ) $(LDFLAGS) diff --git a/cirilisp.c b/cirilisp.c index 30666d7..82bb38a 100644 --- a/cirilisp.c +++ b/cirilisp.c @@ -1,4 +1,5 @@ #include +#include #include #include @@ -16,13 +17,16 @@ int load(char *pathname) return 0; } object exp; - while (TYPE(exp = eval(read("", stream), globalEnv)) != EOFObject) + while (TYPE(exp = Eval(Read("", stream), globalEnv)) != EOFObject) { if (TYPE(exp) == errorObject) { - print(exp); + Print(exp); + } + else + { + deleteObject(exp); } - deleteObject(exp); } eofStatus = 0; fclose(stream); @@ -45,6 +49,8 @@ void init() addSymbolInternal("-", &subtractInt, 0); addSymbolInternal("*", &multiplyInt, 0); addSymbolInternal("/", ÷Int, 0); + addSymbolInternal("бројилац", &numeratorInt, 0); + addSymbolInternal("именилац", &denominatorInt, 0); addSymbolInternal("навод", "eInt, 1); addSymbolInternal("опиши", &defineInt, 1); addSymbolInternal("опиши-складњу", &defineMacroInt, 1); @@ -58,6 +64,8 @@ void init() addSymbolInternal("нил?", &nilQInt, 0); addSymbolInternal("конс?", &consQInt, 0); addSymbolInternal("број?", &numberQInt, 0); + addSymbolInternal("разломак?", &fractionQInt, 0); + addSymbolInternal("реалан?", &realQInt, 0); addSymbolInternal("симбол?", &symbolQInt, 0); addSymbolInternal("процедура?", &procedureQInt, 0); addSymbolInternal("булски?", &boolQInt, 0); @@ -77,18 +85,68 @@ void init() addSymbolInternal("направи-ниску", &makeStrInt, 0); addSymbolInternal("дужина-ниске", &strLengthInt, 0); - if (!load(DESTDIR"/usr/local/lib/cirilisp/инит.ћ")) + if (!load(DESTDIR "/usr/local/lib/cirilisp/инит.ћ")) { fprintf(stderr, "Није пронађена стандардна ЋИРЛИСП библиотека\ \nПрограм се није могао правилно покренути\n"); - exit(0); + exit(3); } } +const char *help = +"\ +Команда: cirilisp [-q|-v|-h] [<име фајла>]*\n\ +Опције:\n\ + -q Не започињи ЧПШП (\"Читај, процени, штампај\" петљу) након\n\ +евалуирања командних аргумената\n\ + -h Одштампај овај кратки помоћник и затвори програм\n\ + -v Одштампај верзију програма и затвори програм\n\ +"; + int main(int argc, char **argv) { init(); - while (print(eval(read("ШКЉ> ", stdin), globalEnv))) + + int quitFlag = 0, opt; + while ((opt = getopt(argc, argv, "qvh")) != -1) + { + switch (opt) + { + case 'q': + quitFlag = 1; + break; + case 'v': + printf("Верзија: " VERSION "\n"); + exit(0); + break; + case 'h': + printf(help); + exit(0); + break; + default: + fprintf(stderr, "Непозната командна опција"); + exit(1); + } + } + + while (argv[optind] != NULL) + { + if (!load(argv[optind])) + { + fprintf(stderr, "Није било могуће отворити фајл %s.\n\ +Проверите да ли дати фајл заиста постоји\n", argv[optind]); + exit(2); + } + ++optind; + } + + if (quitFlag) + { + exit(0); + } + + printf("Добродошли у ЋИРИЛИСП ЧПШП окружење, верзија: " VERSION "\n"); + while (Print(Eval(Read("ШКЉ> ", stdin), globalEnv))) ; printf("\nДостигнут крај улазног тока.\nЗбогом и дођите нам опет!\n"); diff --git a/eval.c b/eval.c index e713882..1b0505e 100644 --- a/eval.c +++ b/eval.c @@ -11,7 +11,7 @@ int maxRecursionDepth = 10000; object apply(object function, object parameters, env currentEnv); -object eval(object input, env currentEnv) +object Eval(object input, env currentEnv) { object result; @@ -29,7 +29,7 @@ object eval(object input, env currentEnv) else { int regularEvalOrder = 1; - CAR(input) = eval(CAR(input), currentEnv); + CAR(input) = Eval(CAR(input), currentEnv); if (TYPE(CAR(input)) == errorObject) { result = copyObject(CAR(input)); @@ -50,7 +50,7 @@ object eval(object input, env currentEnv) while (TYPE(*currentCell) != nilObject) { CAR(*currentCell) = - eval(CAR(*currentCell), + Eval(CAR(*currentCell), currentEnv); if (TYPE(CAR(*currentCell)) == @@ -77,7 +77,7 @@ object eval(object input, env currentEnv) PROC_SPECIAL(CAR(input)) && PROC_TYPE(CAR(input)) == compoundProc) { - result = eval(result, currentEnv); + result = Eval(result, currentEnv); } } } @@ -188,7 +188,7 @@ object apply(object procedure, object parameters, env currentEnv) object *currentSubProc = &body; while (TYPE(*currentSubProc) != nilObject) { - CAR(*currentSubProc) = eval(CAR(*currentSubProc), procEnv); + CAR(*currentSubProc) = Eval(CAR(*currentSubProc), procEnv); if (TYPE(CDR(*currentSubProc)) == nilObject) { result = copyObject(CAR(*currentSubProc)); diff --git a/eval.h b/eval.h index a4ff6bb..38937b6 100644 --- a/eval.h +++ b/eval.h @@ -1,4 +1,4 @@ #pragma once -object eval(object input, env currentEnv); +object Eval(object input, env currentEnv); object apply(object function, object parameters, env currentEnv); diff --git a/internals.c b/internals.c index 27c21f1..2222391 100644 --- a/internals.c +++ b/internals.c @@ -198,6 +198,36 @@ object inexactToExactInt(object parameters) return result; } +object fractionPart(object parameters, int part) +{ + if (listLength(parameters) != 1) + { + SIGERR(argumentNumberError); + } + if (TYPE(CAR(parameters)) != numberObject || + NUM_TYPE(CAR(parameters)) != fractionNum) + { + SIGERR(typeError); + } + object result; + TYPE(result) = numberObject; + NUM_TYPE(result) = fractionNum; + NUM_DENOM(result) = 1; + NUM_NUMER(result) = !part ? NUM_NUMER(CAR(parameters)) : + NUM_DENOM(CAR(parameters)); + return result; +} + +object numeratorInt(object parameters) +{ + return fractionPart(parameters, 0); +} + +object denominatorInt(object parameters) +{ + return fractionPart(parameters, 1); +} + object quoteInt(object parameters) { object result; @@ -286,7 +316,7 @@ object defineInt(object parameters, env currentEnv) if (listLength(parameters) == 2) { result = copyObject(CAR(parameters)); - value = eval(copyObject(CAR(CDR(parameters))), + value = Eval(copyObject(CAR(CDR(parameters))), currentEnv); if (TYPE(value) == errorObject) { @@ -420,7 +450,7 @@ object ifInt(object parameters, env currentEnv) switch (listLength(parameters)) { case 2: - predicate = eval(copyObject(CAR(parameters)), currentEnv); + predicate = Eval(copyObject(CAR(parameters)), currentEnv); if (TYPE(predicate) == errorObject) { CPYERR(ERR(predicate)); @@ -432,7 +462,7 @@ object ifInt(object parameters, env currentEnv) } else { - result = eval(copyObject(CAR(CDR(parameters))), + result = Eval(copyObject(CAR(CDR(parameters))), currentEnv); } @@ -442,7 +472,7 @@ object ifInt(object parameters, env currentEnv) } break; case 3: - predicate = eval(copyObject(CAR(parameters)), currentEnv); + predicate = Eval(copyObject(CAR(parameters)), currentEnv); if (TYPE(predicate) == errorObject) { CPYERR(ERR(predicate)); @@ -450,12 +480,12 @@ object ifInt(object parameters, env currentEnv) if (TYPE(predicate) == boolObject && BOOL(predicate) == 0) { - result = eval(copyObject(CAR(CDR(CDR(parameters)))), + result = Eval(copyObject(CAR(CDR(CDR(parameters)))), currentEnv); } else { - result = eval(copyObject(CAR(CDR(parameters))), + result = Eval(copyObject(CAR(CDR(parameters))), currentEnv); } @@ -498,6 +528,29 @@ object numberQInt(object parameters) return checkType(parameters, numberObject); } +object checkNumType(object parameters, numType type) +{ + if (listLength(parameters) != 1) + { + SIGERR(argumentNumberError); + } + object result; + TYPE(result) = boolObject; + BOOL(result) = TYPE(CAR(parameters)) == numberObject && + (NUM_TYPE(CAR(parameters)) == type ? 1 : 0); + return result; +} + +object fractionQInt(object parameters) +{ + return checkNumType(parameters, fractionNum); +} + +object realQInt(object parameters) +{ + return checkNumType(parameters, realNum); +} + object symbolQInt(object parameters) { return checkType(parameters, symbolObject); diff --git a/internals.h b/internals.h index 79d3af3..c45720a 100644 --- a/internals.h +++ b/internals.h @@ -7,6 +7,8 @@ object multiplyInt(object parameters); object divideInt(object parameters); object exactToInexactInt(object parameters); object inexactToExactInt(object parameters); +object numeratorInt(object parameters); +object denominatorInt(object parameters); object quoteInt(object parameters); object lambdaInt(object parameters, env currentEnv); object defineInt(object parameters, env currentEnv); @@ -18,6 +20,8 @@ object ifInt(object parameters, env currentEnv); object nilQInt(object parameters); object consQInt(object parameters); object numberQInt(object parameters); +object fractionQInt(object parameters); +object realQInt(object parameters); object symbolQInt(object parameters); object procedureQInt(object parameters); object boolQInt(object parameters); diff --git a/print.c b/print.c index 8831738..cf9d225 100644 --- a/print.c +++ b/print.c @@ -4,7 +4,7 @@ void printValue(object input); -int print(object input) +int Print(object input) { if (TYPE(input) == errorObject) { diff --git a/print.h b/print.h index 42bcb62..29c8f23 100644 --- a/print.h +++ b/print.h @@ -1,4 +1,4 @@ #pragma once -int print(object input); +int Print(object input); void printValue(object input); diff --git a/read.c b/read.c index 4299f1d..05a2874 100644 --- a/read.c +++ b/read.c @@ -19,7 +19,7 @@ wint_t unscanwc(wint_t c, FILE *stream); object getToken(); object macroFunction(wchar_t m, FILE *stream); -object read(char *prompt, FILE *stream) +object Read(char *prompt, FILE *stream) { printf("%s", prompt); @@ -48,7 +48,7 @@ object read(char *prompt, FILE *stream) if (TYPE(result) == unspecifiedObject) { - return read("", stream); + return Read("", stream); /* уколико улаз функције није прави објекат (на пример уколико је учитан * коментар) покушавамо прочитати опет */ } @@ -327,6 +327,16 @@ object dispatchedChar(wint_t c, FILE *stream) } TYPE(result) = unspecifiedObject; break; + case L'!': + for (;;) + { + if ((c = scanwc(stream)) == L'\n' || c == WEOF) + { + break; + } + } + TYPE(result) = unspecifiedObject; + break; case WEOF: SIGERR(unexpectedEOFError); default: @@ -351,7 +361,7 @@ object macroFunction(wchar_t m, FILE *stream) listCurrent = &result; for (;;) { - object currentObject = read("", stream); + object currentObject = Read("", stream); if (TYPE(currentObject) == errorObject && !strcmp(ERR(currentObject), commonErrs[unmatchedParenError])) @@ -441,7 +451,7 @@ object macroFunction(wchar_t m, FILE *stream) break; case L'\'': case L'`': - expression = read("", stream); + expression = Read("", stream); if (TYPE(expression) == errorObject) { CPYERR(ERR(expression)); diff --git a/read.h b/read.h index 36f7aa5..e9a09aa 100644 --- a/read.h +++ b/read.h @@ -2,4 +2,4 @@ #include "util.h" -object read(char *prompt, FILE *stream); +object Read(char *prompt, FILE *stream); diff --git a/инит.ћ b/инит.ћ index 2c22d5d..0efa7f3 100644 --- a/инит.ћ +++ b/инит.ћ @@ -13,6 +13,8 @@ (опиши нил ()) +(опиши (новиред) (прикажи #\новиред)) + (опиши (није предикат) (ако предикат #л #и)) @@ -58,3 +60,6 @@ (ако (нил? (сдр клаузе)) () (примени услов (сдр клаузе))))))) + +(опиши (цеоброј? џ) + (= (именилац (нетачно->тачно џ)) 1))