Имплементиране командно-линијске опције, додате функције за препознавање типова бројева

This commit is contained in:
kappa 2019-02-19 09:49:55 +01:00
parent 4dc9a4e888
commit d24fa3945d
11 changed files with 158 additions and 27 deletions

View file

@ -8,7 +8,8 @@ PREFIX = /usr/local
LIBPREFIX = $(PREFIX)/lib LIBPREFIX = $(PREFIX)/lib
# флегови за C компајлер и линкер # флегови за 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 = -g -std=c99 -pedantic -Wall -O0
# CFLAGS = -std=c99 -pedantic -Wall -O3 # CFLAGS = -std=c99 -pedantic -Wall -O3
LDFLAGS = -lm -lc LDFLAGS = -lm -lc
@ -25,7 +26,7 @@ all: cirilisp $(L_SRC)
.c.o: .c.o:
$(CC) -c $(CPPFLAGS) $(CFLAGS) $< $(CC) -c $(CPPFLAGS) $(CFLAGS) $<
$(OBJ): $(INC) $(L_SRC) $(OBJ): $(INC)
cirilisp: $(OBJ) cirilisp: $(OBJ)
$(CC) -o $@ $(OBJ) $(LDFLAGS) $(CC) -o $@ $(OBJ) $(LDFLAGS)

View file

@ -1,4 +1,5 @@
#include <locale.h> #include <locale.h>
#include <unistd.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -16,14 +17,17 @@ int load(char *pathname)
return 0; return 0;
} }
object exp; object exp;
while (TYPE(exp = eval(read("", stream), globalEnv)) != EOFObject) while (TYPE(exp = Eval(Read("", stream), globalEnv)) != EOFObject)
{ {
if (TYPE(exp) == errorObject) if (TYPE(exp) == errorObject)
{ {
print(exp); Print(exp);
} }
else
{
deleteObject(exp); deleteObject(exp);
} }
}
eofStatus = 0; eofStatus = 0;
fclose(stream); fclose(stream);
return 1; return 1;
@ -45,6 +49,8 @@ void init()
addSymbolInternal("-", &subtractInt, 0); addSymbolInternal("-", &subtractInt, 0);
addSymbolInternal("*", &multiplyInt, 0); addSymbolInternal("*", &multiplyInt, 0);
addSymbolInternal("/", &divideInt, 0); addSymbolInternal("/", &divideInt, 0);
addSymbolInternal("бројилац", &numeratorInt, 0);
addSymbolInternal("именилац", &denominatorInt, 0);
addSymbolInternal("навод", &quoteInt, 1); addSymbolInternal("навод", &quoteInt, 1);
addSymbolInternal("опиши", &defineInt, 1); addSymbolInternal("опиши", &defineInt, 1);
addSymbolInternal("опиши-складњу", &defineMacroInt, 1); addSymbolInternal("опиши-складњу", &defineMacroInt, 1);
@ -58,6 +64,8 @@ void init()
addSymbolInternal("нил?", &nilQInt, 0); addSymbolInternal("нил?", &nilQInt, 0);
addSymbolInternal("конс?", &consQInt, 0); addSymbolInternal("конс?", &consQInt, 0);
addSymbolInternal("број?", &numberQInt, 0); addSymbolInternal("број?", &numberQInt, 0);
addSymbolInternal("разломак?", &fractionQInt, 0);
addSymbolInternal("реалан?", &realQInt, 0);
addSymbolInternal("симбол?", &symbolQInt, 0); addSymbolInternal("симбол?", &symbolQInt, 0);
addSymbolInternal("процедура?", &procedureQInt, 0); addSymbolInternal("процедура?", &procedureQInt, 0);
addSymbolInternal("булски?", &boolQInt, 0); addSymbolInternal("булски?", &boolQInt, 0);
@ -81,14 +89,64 @@ void init()
{ {
fprintf(stderr, "Није пронађена стандардна ЋИРЛИСП библиотека\ 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) int main(int argc, char **argv)
{ {
init(); 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"); printf("\nДостигнут крај улазног тока.\nЗбогом и дођите нам опет!\n");

10
eval.c
View file

@ -11,7 +11,7 @@ int maxRecursionDepth = 10000;
object apply(object function, object parameters, env currentEnv); object apply(object function, object parameters, env currentEnv);
object eval(object input, env currentEnv) object Eval(object input, env currentEnv)
{ {
object result; object result;
@ -29,7 +29,7 @@ object eval(object input, env currentEnv)
else else
{ {
int regularEvalOrder = 1; int regularEvalOrder = 1;
CAR(input) = eval(CAR(input), currentEnv); CAR(input) = Eval(CAR(input), currentEnv);
if (TYPE(CAR(input)) == errorObject) if (TYPE(CAR(input)) == errorObject)
{ {
result = copyObject(CAR(input)); result = copyObject(CAR(input));
@ -50,7 +50,7 @@ object eval(object input, env currentEnv)
while (TYPE(*currentCell) != nilObject) while (TYPE(*currentCell) != nilObject)
{ {
CAR(*currentCell) = CAR(*currentCell) =
eval(CAR(*currentCell), Eval(CAR(*currentCell),
currentEnv); currentEnv);
if (TYPE(CAR(*currentCell)) == if (TYPE(CAR(*currentCell)) ==
@ -77,7 +77,7 @@ object eval(object input, env currentEnv)
PROC_SPECIAL(CAR(input)) && PROC_SPECIAL(CAR(input)) &&
PROC_TYPE(CAR(input)) == compoundProc) 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; object *currentSubProc = &body;
while (TYPE(*currentSubProc) != nilObject) while (TYPE(*currentSubProc) != nilObject)
{ {
CAR(*currentSubProc) = eval(CAR(*currentSubProc), procEnv); CAR(*currentSubProc) = Eval(CAR(*currentSubProc), procEnv);
if (TYPE(CDR(*currentSubProc)) == nilObject) if (TYPE(CDR(*currentSubProc)) == nilObject)
{ {
result = copyObject(CAR(*currentSubProc)); result = copyObject(CAR(*currentSubProc));

2
eval.h
View file

@ -1,4 +1,4 @@
#pragma once #pragma once
object eval(object input, env currentEnv); object Eval(object input, env currentEnv);
object apply(object function, object parameters, env currentEnv); object apply(object function, object parameters, env currentEnv);

View file

@ -198,6 +198,36 @@ object inexactToExactInt(object parameters)
return result; 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 quoteInt(object parameters)
{ {
object result; object result;
@ -286,7 +316,7 @@ object defineInt(object parameters, env currentEnv)
if (listLength(parameters) == 2) if (listLength(parameters) == 2)
{ {
result = copyObject(CAR(parameters)); result = copyObject(CAR(parameters));
value = eval(copyObject(CAR(CDR(parameters))), value = Eval(copyObject(CAR(CDR(parameters))),
currentEnv); currentEnv);
if (TYPE(value) == errorObject) if (TYPE(value) == errorObject)
{ {
@ -420,7 +450,7 @@ object ifInt(object parameters, env currentEnv)
switch (listLength(parameters)) switch (listLength(parameters))
{ {
case 2: case 2:
predicate = eval(copyObject(CAR(parameters)), currentEnv); predicate = Eval(copyObject(CAR(parameters)), currentEnv);
if (TYPE(predicate) == errorObject) if (TYPE(predicate) == errorObject)
{ {
CPYERR(ERR(predicate)); CPYERR(ERR(predicate));
@ -432,7 +462,7 @@ object ifInt(object parameters, env currentEnv)
} }
else else
{ {
result = eval(copyObject(CAR(CDR(parameters))), result = Eval(copyObject(CAR(CDR(parameters))),
currentEnv); currentEnv);
} }
@ -442,7 +472,7 @@ object ifInt(object parameters, env currentEnv)
} }
break; break;
case 3: case 3:
predicate = eval(copyObject(CAR(parameters)), currentEnv); predicate = Eval(copyObject(CAR(parameters)), currentEnv);
if (TYPE(predicate) == errorObject) if (TYPE(predicate) == errorObject)
{ {
CPYERR(ERR(predicate)); CPYERR(ERR(predicate));
@ -450,12 +480,12 @@ object ifInt(object parameters, env currentEnv)
if (TYPE(predicate) == boolObject && BOOL(predicate) == 0) if (TYPE(predicate) == boolObject && BOOL(predicate) == 0)
{ {
result = eval(copyObject(CAR(CDR(CDR(parameters)))), result = Eval(copyObject(CAR(CDR(CDR(parameters)))),
currentEnv); currentEnv);
} }
else else
{ {
result = eval(copyObject(CAR(CDR(parameters))), result = Eval(copyObject(CAR(CDR(parameters))),
currentEnv); currentEnv);
} }
@ -498,6 +528,29 @@ object numberQInt(object parameters)
return checkType(parameters, numberObject); 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) object symbolQInt(object parameters)
{ {
return checkType(parameters, symbolObject); return checkType(parameters, symbolObject);

View file

@ -7,6 +7,8 @@ object multiplyInt(object parameters);
object divideInt(object parameters); object divideInt(object parameters);
object exactToInexactInt(object parameters); object exactToInexactInt(object parameters);
object inexactToExactInt(object parameters); object inexactToExactInt(object parameters);
object numeratorInt(object parameters);
object denominatorInt(object parameters);
object quoteInt(object parameters); object quoteInt(object parameters);
object lambdaInt(object parameters, env currentEnv); object lambdaInt(object parameters, env currentEnv);
object defineInt(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 nilQInt(object parameters);
object consQInt(object parameters); object consQInt(object parameters);
object numberQInt(object parameters); object numberQInt(object parameters);
object fractionQInt(object parameters);
object realQInt(object parameters);
object symbolQInt(object parameters); object symbolQInt(object parameters);
object procedureQInt(object parameters); object procedureQInt(object parameters);
object boolQInt(object parameters); object boolQInt(object parameters);

View file

@ -4,7 +4,7 @@
void printValue(object input); void printValue(object input);
int print(object input) int Print(object input)
{ {
if (TYPE(input) == errorObject) if (TYPE(input) == errorObject)
{ {

View file

@ -1,4 +1,4 @@
#pragma once #pragma once
int print(object input); int Print(object input);
void printValue(object input); void printValue(object input);

18
read.c
View file

@ -19,7 +19,7 @@ wint_t unscanwc(wint_t c, FILE *stream);
object getToken(); object getToken();
object macroFunction(wchar_t m, FILE *stream); object macroFunction(wchar_t m, FILE *stream);
object read(char *prompt, FILE *stream) object Read(char *prompt, FILE *stream)
{ {
printf("%s", prompt); printf("%s", prompt);
@ -48,7 +48,7 @@ object read(char *prompt, FILE *stream)
if (TYPE(result) == unspecifiedObject) if (TYPE(result) == unspecifiedObject)
{ {
return read("", stream); return Read("", stream);
/* уколико улаз функције није прави објекат (на пример уколико је учитан /* уколико улаз функције није прави објекат (на пример уколико је учитан
* коментар) покушавамо прочитати опет */ * коментар) покушавамо прочитати опет */
} }
@ -327,6 +327,16 @@ object dispatchedChar(wint_t c, FILE *stream)
} }
TYPE(result) = unspecifiedObject; TYPE(result) = unspecifiedObject;
break; break;
case L'!':
for (;;)
{
if ((c = scanwc(stream)) == L'\n' || c == WEOF)
{
break;
}
}
TYPE(result) = unspecifiedObject;
break;
case WEOF: case WEOF:
SIGERR(unexpectedEOFError); SIGERR(unexpectedEOFError);
default: default:
@ -351,7 +361,7 @@ object macroFunction(wchar_t m, FILE *stream)
listCurrent = &result; listCurrent = &result;
for (;;) for (;;)
{ {
object currentObject = read("", stream); object currentObject = Read("", stream);
if (TYPE(currentObject) == errorObject && if (TYPE(currentObject) == errorObject &&
!strcmp(ERR(currentObject), !strcmp(ERR(currentObject),
commonErrs[unmatchedParenError])) commonErrs[unmatchedParenError]))
@ -441,7 +451,7 @@ object macroFunction(wchar_t m, FILE *stream)
break; break;
case L'\'': case L'\'':
case L'`': case L'`':
expression = read("", stream); expression = Read("", stream);
if (TYPE(expression) == errorObject) if (TYPE(expression) == errorObject)
{ {
CPYERR(ERR(expression)); CPYERR(ERR(expression));

2
read.h
View file

@ -2,4 +2,4 @@
#include "util.h" #include "util.h"
object read(char *prompt, FILE *stream); object Read(char *prompt, FILE *stream);

View file

@ -13,6 +13,8 @@
(опиши нил ()) (опиши нил ())
(опиши (новиред) (прикажи #\новиред))
(опиши (није предикат) (опиши (није предикат)
(ако предикат #л #и)) (ако предикат #л #и))
@ -58,3 +60,6 @@
(ако (нил? (сдр клаузе)) (ако (нил? (сдр клаузе))
() ()
(примени услов (сдр клаузе))))))) (примени услов (сдр клаузе)))))))
(опиши (цеоброј? џ)
(= (именилац (нетачно->тачно џ)) 1))