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

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
# флегови за 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)

View file

@ -1,4 +1,5 @@
#include <locale.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
@ -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("/", &divideInt, 0);
addSymbolInternal("бројилац", &numeratorInt, 0);
addSymbolInternal("именилац", &denominatorInt, 0);
addSymbolInternal("навод", &quoteInt, 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");
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");

10
eval.c
View file

@ -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));

2
eval.h
View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

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

View file

@ -1,4 +1,4 @@
#pragma once
int print(object input);
int Print(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 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));

2
read.h
View file

@ -2,4 +2,4 @@
#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))