ЋИРИЛИСП-0,8: имплементирана контрола тока и основни предикати поређивања

This commit is contained in:
kappa 2019-02-07 23:07:02 +01:00
parent 075669842b
commit b7f3124302
8 changed files with 188 additions and 13 deletions

View file

@ -1,14 +1,15 @@
# cirilisp - компајлер за ћирилични дијалекат лиспа # cirilisp - компајлер за ћирилични дијалекат лиспа
# ћирилисп верзија # ћирилисп верзија
VERSION = 0.7 VERSION = 0,8
# локација за инсталацију # локација за инсталацију
PREFIX = /usr/local PREFIX = /usr/local
# флегови за C компајлер и линкер # флегови за C компајлер и линкер
# CFLAGS = -g -std=c99 -pedantic -Wall -O0 CPPFLAGS = -D_POSIX_C_SOURCE=200200L
CFLAGS = -std=c99 -pedantic -Wall -O3 CFLAGS = -g -std=c99 -pedantic -Wall -O0
# CFLAGS = -std=c99 -pedantic -Wall -O3
LDFLAGS = -lm -lc LDFLAGS = -lm -lc
CC = cc CC = cc

2
eval.c
View file

@ -88,7 +88,7 @@ object apply(object procedure, object parameters, env currentEnv)
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) if (f == define || f == lambda || f == ifStatement)
{ {
result = f(parameters, currentEnv); result = f(parameters, currentEnv);
} }

3
init.c
View file

@ -25,4 +25,7 @@ void init()
addSymbolInternal("тачно->нетачно", &exactToInexact); addSymbolInternal("тачно->нетачно", &exactToInexact);
addSymbolInternal("нетачно->тачно", &inexactToExact); addSymbolInternal("нетачно->тачно", &inexactToExact);
addSymbolInternal("ламбда", &lambda); addSymbolInternal("ламбда", &lambda);
addSymbolInternal("<", &less);
addSymbolInternal(">", &greater);
addSymbolInternal("ако", &ifStatement);
} }

View file

@ -32,10 +32,6 @@ int allSyms(object list)
} }
/*
object ifStatement(object parameters)
{
*/
object add(object parameters) object add(object parameters)
{ {
@ -328,3 +324,102 @@ object define(object parameters, env currentEnv)
return result; return result;
} }
object less(object parameters)
{
if (!allNums(parameters))
{
SIGERR(typeError);
}
if (listLength(parameters) == 0 || listLength(parameters) == 1)
{
return intToBool(1);
}
int resultInt = 1;
object *current = &parameters;
while (TYPE(CDR(*current)) != nilObject)
{
if (cmp(CAR(*current), CAR(CDR(*current))) >= 0)
{
resultInt = 0;
break;
}
current = &CDR(*current);
}
object result;
TYPE(result) = boolObject;
BOOL(result) = resultInt;
return result;
}
object greater(object parameters)
{
if (!allNums(parameters))
{
SIGERR(typeError);
}
if (listLength(parameters) == 0 || listLength(parameters) == 1)
{
return intToBool(1);
}
int resultInt = 1;
object *current = &parameters;
while (TYPE(CDR(*current)) != nilObject)
{
if (cmp(CAR(*current), CAR(CDR(*current))) <= 0)
{
resultInt = 0;
break;
}
current = &CDR(*current);
}
object result;
TYPE(result) = boolObject;
BOOL(result) = resultInt;
return result;
}
object ifStatement(object parameters, env currentEnv)
{
object predicate, result;
switch (listLength(parameters))
{
case 2:
predicate = eval(CAR(parameters), currentEnv);
if (TYPE(predicate) == boolObject && BOOL(predicate) == 0)
{
TYPE(result) = unspecifiedObject;
}
else
{
result = eval(copyObject(CAR(CDR(parameters))),
currentEnv);
}
break;
case 3:
predicate = eval(CAR(parameters), currentEnv);
if (TYPE(predicate) == boolObject && BOOL(predicate) == 0)
{
result = eval(copyObject(CAR(CDR(CDR(parameters)))),
currentEnv);
}
else
{
result = eval(copyObject(CAR(CDR(parameters))),
currentEnv);
}
break;
default:
SIGERR(argumentNumberError);
}
return result;
}

View file

@ -8,5 +8,8 @@ object divide(object parameters);
object exactToInexact(object parameters); object exactToInexact(object parameters);
object inexactToExact(object parameters); object inexactToExact(object parameters);
object quote(object parameters); object quote(object parameters);
object define(object parameters);
object lambda(object parameters); object lambda(object parameters);
object define(object parameters);
object less(object parameters);
object greater(object parameters);
object ifStatement(object parameters);

15
read.c
View file

@ -4,6 +4,7 @@
#include <wctype.h> #include <wctype.h>
#include <ctype.h> #include <ctype.h>
#include <string.h> #include <string.h>
#include <regex.h>
#include "util.h" #include "util.h"
#include "read.h" #include "read.h"
@ -234,7 +235,15 @@ object getToken()
char *s = malloc(n * sizeof(char)); char *s = malloc(n * sizeof(char));
wcstombs(s, buffer, n); wcstombs(s, buffer, n);
if (isFracNumToken(s)) regex_t regNumberFrac, regNumberReal;
regcomp(&regNumberFrac, "^[-+]?[[:digit:]]+(/[[:digit:]]+)?$",
REG_EXTENDED);
regcomp(&regNumberReal, "^[-+]?[[:digit:]]*,[[:digit:]]+$",
REG_EXTENDED);
const int nmatches = 1;
regmatch_t a[nmatches];
if (!regexec(&regNumberFrac, s, nmatches, a, 0))
{ {
TYPE(result) = numberObject; TYPE(result) = numberObject;
NUM_TYPE(result) = fractionNum; NUM_TYPE(result) = fractionNum;
@ -244,7 +253,7 @@ object getToken()
1 : atoll(tmp + 1); 1 : atoll(tmp + 1);
result = shortenFractionNum(result); result = shortenFractionNum(result);
} }
else if (isRealNumToken(s)) else if (!regexec(&regNumberReal, s, nmatches, a, 0))
{ {
TYPE(result) = numberObject; TYPE(result) = numberObject;
NUM_TYPE(result) = realNum; NUM_TYPE(result) = realNum;
@ -256,6 +265,8 @@ object getToken()
SYM(result) = malloc((strlen(s) + 1) * sizeof(char)); SYM(result) = malloc((strlen(s) + 1) * sizeof(char));
strcpy(SYM(result), s); strcpy(SYM(result), s);
} }
regfree(&regNumberFrac);
regfree(&regNumberReal);
return result; return result;
} }

61
util.c
View file

@ -123,7 +123,7 @@ object referVariable(char *symbol,env currentEnv)
} }
} }
#define SPECIALFORMSNUM 3 #define SPECIALFORMSNUM 4
int isSpecialForm(char *symbol) int isSpecialForm(char *symbol)
{ {
int result = 0; int result = 0;
@ -131,7 +131,8 @@ int isSpecialForm(char *symbol)
{ {
"навод", "навод",
"дефиниши", "дефиниши",
"ламбда" "ламбда",
"ако"
}; };
for (int i = 0; i < SPECIALFORMSNUM; ++i) for (int i = 0; i < SPECIALFORMSNUM; ++i)
@ -352,6 +353,11 @@ object shortenFractionNum(object a)
gcd(NUM_NUMER(result), NUM_DENOM(result)); gcd(NUM_NUMER(result), NUM_DENOM(result));
NUM_NUMER(result) /= divisor; NUM_NUMER(result) /= divisor;
NUM_DENOM(result) /= divisor; NUM_DENOM(result) /= divisor;
if (NUM_DENOM(result) < 0)
{
NUM_DENOM(result) = -NUM_DENOM(result);
NUM_NUMER(result) = -NUM_NUMER(result);
}
} }
} }
@ -453,6 +459,57 @@ object inverseNum(object a)
return result; return result;
} }
int cmp(object a, object b)
{
object aCmp = copyObject(a), bCmp = copyObject(b);
if (NUM_TYPE(aCmp) == realNum || NUM_TYPE(bCmp) == realNum)
{
aCmp = exactToInexactNum(aCmp);
bCmp = exactToInexactNum(bCmp);
if (NUM_REAL(aCmp) > NUM_REAL(bCmp))
{
return 1;
}
else if (NUM_REAL(aCmp) < NUM_REAL(bCmp))
{
return -1;
}
else
{
return 0;
}
}
else
{
long long int denom = lcm(NUM_DENOM(aCmp), NUM_DENOM(bCmp));
NUM_NUMER(aCmp) = NUM_NUMER(aCmp) * (denom / NUM_DENOM(aCmp));
NUM_NUMER(bCmp) = NUM_NUMER(bCmp) * (denom / NUM_DENOM(bCmp));
NUM_DENOM(aCmp) = NUM_DENOM(bCmp) = denom;
if (NUM_NUMER(aCmp) > NUM_NUMER(bCmp))
{
return 1;
}
else if (NUM_NUMER(aCmp) < NUM_NUMER(bCmp))
{
return -1;
}
else
{
return 0;
}
}
}
object intToBool(int boolean)
{
object result;
TYPE(result) = boolObject;
BOOL(result) = boolean == 0 ? 0 : 1;
return result;
}
procedure *createProcedure() procedure *createProcedure()
{ {
return malloc(sizeof(procedure)); return malloc(sizeof(procedure));

5
util.h
View file

@ -185,5 +185,10 @@ object plusNum(object a, object b);
object minusNum(object a); object minusNum(object a);
object timesNum(object a, object b); object timesNum(object a, object b);
object inverseNum(object a); object inverseNum(object a);
int cmp(object a, object b);
/* пореди два броја и враћа -1, 0, 1 у зависности од односа истих, претпоставља
* да су објекти бројеви */
object intToBool(int boolean);
procedure *createProcedure(); procedure *createProcedure();