Add arithmetic for locations
Nearly all of the basic operations in eval.c have been implemented for values of type LOCATION. The behavior is generally modeled after typical vector arithmetic. For "<", as a particular case, every component must be less than or equal the corresponding component, and at least one must be strictly less (<= drops the latter condition, of course). Note "<" returns the number of strictly less coordinates, but 0 (false) if any coordinate is greater. Also implements a mechanism (string array Type_Names) for printing type information and slightly enhanced the error message for type mismatch in + Closes #16.
This commit is contained in:
parent
08b42bf424
commit
d24b8c5ead
146
eval.c
146
eval.c
@ -99,6 +99,8 @@ Token tadd(Token l, Token r)
|
||||
/* variables */ /*{{{*/
|
||||
Token result;
|
||||
const char *msg;
|
||||
char *buf;
|
||||
int len;
|
||||
/*}}}*/
|
||||
|
||||
if (l.type==EEK)
|
||||
@ -154,6 +156,14 @@ Token tadd(Token l, Token r)
|
||||
result.u.flt=l.u.flt+r.u.flt;
|
||||
}
|
||||
/*}}}*/
|
||||
else if (l.type == LOCATION && r.type == LOCATION)
|
||||
/* result is component-wise sum of locations */ /*{{{*/
|
||||
{
|
||||
result.type = LOCATION;
|
||||
for (len = 0; len < 3; ++len)
|
||||
result.u.location[len] = l.u.location[len] + r.u.location[len];
|
||||
}
|
||||
/*}}}*/
|
||||
else if (l.type==EMPTY && r.type==EMPTY)
|
||||
/* result is emty */ /*{{{*/
|
||||
{
|
||||
@ -164,7 +174,11 @@ Token tadd(Token l, Token r)
|
||||
/* result is type error */ /*{{{*/
|
||||
{
|
||||
result.type=EEK;
|
||||
result.u.err=strcpy(malloc(strlen(_("wrong types for + operator"))+1),_("wrong types for + operator"));
|
||||
len = strlen(_("wrong types for + operator"));
|
||||
buf = malloc(len + 128);
|
||||
strcpy(buf, _("wrong types for + operator"));
|
||||
snprintf(buf + len, 128, ": %s + %s", Type_Name[l.type], Type_Name[r.type]);
|
||||
result.u.err = buf;
|
||||
}
|
||||
/*}}}*/
|
||||
if (result.type==FLOAT && (msg=dblfinite(result.u.flt))!=(const char*)0)
|
||||
@ -185,6 +199,7 @@ Token tsub(Token l, Token r)
|
||||
/* variables */ /*{{{*/
|
||||
Token result;
|
||||
const char *msg;
|
||||
int len;
|
||||
/*}}}*/
|
||||
|
||||
if (l.type==EEK)
|
||||
@ -231,6 +246,14 @@ Token tsub(Token l, Token r)
|
||||
result.u.flt=l.u.flt-((double)r.u.integer);
|
||||
}
|
||||
/*}}}*/
|
||||
else if (l.type == LOCATION && r.type == LOCATION)
|
||||
/* result is component-wise difference of locations */ /*{{{*/
|
||||
{
|
||||
result.type = LOCATION;
|
||||
for (len = 0; len < 3; ++len)
|
||||
result.u.location[len] = l.u.location[len] - r.u.location[len];
|
||||
}
|
||||
/*}}}*/
|
||||
else
|
||||
/* result is difference type error */ /*{{{*/
|
||||
{
|
||||
@ -256,6 +279,7 @@ Token tdiv(Token l, Token r)
|
||||
/* variables */ /*{{{*/
|
||||
Token result;
|
||||
const char *msg;
|
||||
int len;
|
||||
/*}}}*/
|
||||
|
||||
if (l.type==EEK)
|
||||
@ -315,6 +339,14 @@ Token tdiv(Token l, Token r)
|
||||
result.u.flt=l.u.flt/((double)r.u.integer);
|
||||
}
|
||||
/*}}}*/
|
||||
else if (l.type == LOCATION && r.type == INT)
|
||||
/* result is divide each component of location by right */ /*{{{*/
|
||||
{
|
||||
result.type = LOCATION;
|
||||
for (len = 0; len < 3; ++len)
|
||||
result.u.location[len] = l.u.location[len] / r.u.integer;
|
||||
}
|
||||
/*}}}*/
|
||||
else
|
||||
/* result is quotient type error */ /*{{{*/
|
||||
{
|
||||
@ -340,6 +372,7 @@ Token tmod(Token l, Token r)
|
||||
/* variables */ /*{{{*/
|
||||
Token result;
|
||||
const char *msg;
|
||||
int len;
|
||||
/*}}}*/
|
||||
|
||||
if (l.type==EEK) /* return left error */ /*{{{*/
|
||||
@ -390,6 +423,22 @@ Token tmod(Token l, Token r)
|
||||
result.u.flt=fmod(l.u.flt,(double)r.u.integer);
|
||||
}
|
||||
/*}}}*/
|
||||
else if (l.type == LOCATION && r.type == LOCATION)
|
||||
/* result is component-wise mod of locations */ /*{{{*/
|
||||
{
|
||||
result.type = LOCATION;
|
||||
for (len = 0; len < 3; ++len)
|
||||
result.u.location[len] = l.u.location[len] % r.u.location[len];
|
||||
}
|
||||
/*}}}*/
|
||||
else if (l.type == LOCATION && r.type == INT)
|
||||
/* result is mod each component of location by right */ /*{{{*/
|
||||
{
|
||||
result.type = LOCATION;
|
||||
for (len = 0; len < 3; ++len)
|
||||
result.u.location[len] = l.u.location[len] % r.u.integer;
|
||||
}
|
||||
/*}}}*/
|
||||
else /* result is remainder type error */ /*{{{*/
|
||||
{
|
||||
result.type=EEK;
|
||||
@ -413,6 +462,7 @@ Token tmul(Token l, Token r)
|
||||
/* variables */ /*{{{*/
|
||||
Token result;
|
||||
const char *msg;
|
||||
int len;
|
||||
/*}}}*/
|
||||
|
||||
if (l.type==EEK)
|
||||
@ -471,6 +521,23 @@ Token tmul(Token l, Token r)
|
||||
result.type=EMPTY;
|
||||
}
|
||||
/*}}}*/
|
||||
else if (l.type == LOCATION && r.type == INT)
|
||||
/* result is each component of location times right */ /*{{{*/
|
||||
{
|
||||
result.type = LOCATION;
|
||||
for (len = 0; len < 3; ++len)
|
||||
result.u.location[len] = l.u.location[len] * r.u.integer;
|
||||
}
|
||||
/*}}}*/
|
||||
else if (l.type == LOCATION && r.type == LOCATION)
|
||||
/* result is dot product of locations */ /*{{{*/
|
||||
{
|
||||
result.type = INT;
|
||||
result.u.integer = 0;
|
||||
for (len = 0; len < 3; ++len)
|
||||
result.u.integer += l.u.location[len] * r.u.location[len];
|
||||
}
|
||||
/*}}}*/
|
||||
else
|
||||
/* result is product type error */ /*{{{*/
|
||||
{
|
||||
@ -495,6 +562,7 @@ Token tneg(Token x)
|
||||
{
|
||||
/* variables */ /*{{{*/
|
||||
Token result;
|
||||
int len;
|
||||
/*}}}*/
|
||||
|
||||
if (x.type==EEK)
|
||||
@ -521,6 +589,14 @@ Token tneg(Token x)
|
||||
result=tcopy(x);
|
||||
}
|
||||
/*}}}*/
|
||||
else if (x.type == LOCATION)
|
||||
/* result is component-wise negation of location */ /*{{{*/
|
||||
{
|
||||
result.type = LOCATION;
|
||||
for (len = 0; len < 3; ++len)
|
||||
result.u.location[len] = -x.u.location[len];
|
||||
}
|
||||
/*}}}*/
|
||||
else
|
||||
/* result is negation error */ /*{{{*/
|
||||
{
|
||||
@ -634,6 +710,7 @@ Token tlt(Token l, Token r)
|
||||
/* variables */ /*{{{*/
|
||||
Token result;
|
||||
static char empty[]="";
|
||||
int len;
|
||||
/*}}}*/
|
||||
|
||||
if (l.type==EEK) /* return left error argument */ /*{{{*/
|
||||
@ -696,6 +773,18 @@ Token tlt(Token l, Token r)
|
||||
result.u.integer=((double)l.u.integer)<r.u.flt;
|
||||
}
|
||||
/*}}}*/
|
||||
else if (l.type == LOCATION && r.type == LOCATION)
|
||||
/* result is true if l is strictly in rectangle from origin to r
|
||||
In addition the value tells how many coordinates were strictly less */ /*{{{*/
|
||||
{
|
||||
result.type = INT;
|
||||
result.u.integer = 0;
|
||||
for (len = 0; len < 3; ++len)
|
||||
if (l.u.location[len] > r.u.location[len]) break;
|
||||
else if (l.u.location[len] < r.u.location[len]) ++result.u.integer;
|
||||
if (len < 3) result.u.integer = 0;
|
||||
}
|
||||
/*}}}*/
|
||||
else /* return < type error */ /*{{{*/
|
||||
{
|
||||
result.type=EEK;
|
||||
@ -711,6 +800,7 @@ Token tle(Token l, Token r)
|
||||
/* variables */ /*{{{*/
|
||||
Token result;
|
||||
static char empty[]="";
|
||||
int len;
|
||||
/*}}}*/
|
||||
|
||||
if (l.type==EEK) /* return left error argument */ /*{{{*/
|
||||
@ -778,6 +868,16 @@ Token tle(Token l, Token r)
|
||||
result.type=INT;
|
||||
result.u.integer=1;
|
||||
}
|
||||
/*}}}*/
|
||||
else if (l.type == LOCATION && r.type == LOCATION)
|
||||
/* result is true if l is in rectangle from origin to r */ /*{{{*/
|
||||
{
|
||||
result.type = INT;
|
||||
result.u.integer = 1;
|
||||
for (len = 0; len < 3; ++len)
|
||||
if (l.u.location[len] > r.u.location[len]) break;
|
||||
if (len < 3) result.u.integer = 0;
|
||||
}
|
||||
/*}}}*/
|
||||
else /* result is <= type error */ /*{{{*/
|
||||
{
|
||||
@ -794,6 +894,7 @@ Token tge(Token l, Token r)
|
||||
/* variables */ /*{{{*/
|
||||
Token result;
|
||||
static char empty[]="";
|
||||
int len;
|
||||
/*}}}*/
|
||||
|
||||
if (l.type==EEK) /* return left error argument */ /*{{{*/
|
||||
@ -856,6 +957,16 @@ Token tge(Token l, Token r)
|
||||
result.u.integer=((double)l.u.integer)>=r.u.flt;
|
||||
}
|
||||
/*}}}*/
|
||||
else if (l.type == LOCATION && r.type == LOCATION)
|
||||
/* result is true if r is in rectangle from origin to l */ /*{{{*/
|
||||
{
|
||||
result.type = INT;
|
||||
result.u.integer = 1;
|
||||
for (len = 0; len < 3; ++len)
|
||||
if (r.u.location[len] > l.u.location[len]) break;
|
||||
if (len < 3) result.u.integer = 0;
|
||||
}
|
||||
/*}}}*/
|
||||
else /* return >= type error */ /*{{{*/
|
||||
{
|
||||
result.type=EEK;
|
||||
@ -871,6 +982,7 @@ Token tgt(Token l, Token r)
|
||||
/* variables */ /*{{{*/
|
||||
Token result;
|
||||
static char empty[]="";
|
||||
int len;
|
||||
/*}}}*/
|
||||
|
||||
if (l.type==EEK) /* return left error argument */ /*{{{*/
|
||||
@ -933,7 +1045,18 @@ Token tgt(Token l, Token r)
|
||||
result.u.integer=((double)l.u.integer)>r.u.flt;
|
||||
}
|
||||
/*}}}*/
|
||||
else /* result is relation op type error */ /*{{{*/
|
||||
else if (l.type == LOCATION && r.type == LOCATION)
|
||||
/* result is true if r is strictly in rectangle from origin to l
|
||||
In addition the value tells how many coordinates were strictly greater */ /*{{{*/
|
||||
{
|
||||
result.type = INT;
|
||||
result.u.integer = 0;
|
||||
for (len = 0; len < 3; ++len)
|
||||
if (r.u.location[len] > l.u.location[len]) break;
|
||||
else if (r.u.location[len] < l.u.location[len]) ++result.u.integer;
|
||||
if (len < 3) result.u.integer = 0;
|
||||
}
|
||||
/*}}}*/ else /* result is relation op type error */ /*{{{*/
|
||||
{
|
||||
result.type=EEK;
|
||||
result.u.err=mystrmalloc(_("type mismatch for relational operator"));
|
||||
@ -948,6 +1071,7 @@ Token teq(Token l, Token r)
|
||||
/* variables */ /*{{{*/
|
||||
Token result;
|
||||
static char empty[]="";
|
||||
int len;
|
||||
/*}}}*/
|
||||
|
||||
if (l.type==EEK) return tcopy(l);
|
||||
@ -1013,6 +1137,15 @@ Token teq(Token l, Token r)
|
||||
result.type=INT;
|
||||
result.u.integer=1;
|
||||
}
|
||||
else if (l.type == LOCATION)
|
||||
/* result is true if locations are component-wise equal */ /*{{{*/
|
||||
{
|
||||
result.type = INT;
|
||||
result.u.integer = 1;
|
||||
for (len = 0; len < 3 && l.u.location[len] == r.u.location[len]; ++len);
|
||||
if (len < 3) result.u.integer = 0;
|
||||
}
|
||||
/*}}}*/
|
||||
else
|
||||
{
|
||||
result.type=EEK;
|
||||
@ -1071,6 +1204,7 @@ Token tne(Token l, Token r)
|
||||
/* variables */ /*{{{*/
|
||||
Token result;
|
||||
static char empty[]="";
|
||||
int len;
|
||||
/*}}}*/
|
||||
|
||||
if (l.type==EEK) return tcopy(l);
|
||||
@ -1131,11 +1265,17 @@ Token tne(Token l, Token r)
|
||||
result.type=INT;
|
||||
result.u.integer=l.u.flt!=r.u.flt;
|
||||
}
|
||||
else if (l.type==EMPTY)
|
||||
else if (l.type==EMPTY) /* both empty, so equal, i.e. not inequal */
|
||||
{
|
||||
result.type=INT;
|
||||
result.u.integer=0;
|
||||
}
|
||||
else if (l.type == LOCATION) {
|
||||
result.type = INT;
|
||||
result.u.integer = 0;
|
||||
for (len = 0; len < 3 && l.u.location[len] == r.u.location[len]; ++len);
|
||||
if (len < 3) result.u.integer = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
result.type=EEK;
|
||||
|
@ -28,6 +28,12 @@ extern double strtod(const char *nptr, char **endptr); /* SunOS 4 hack */
|
||||
#include "scanner.h"
|
||||
/*}}}*/
|
||||
|
||||
const char *Type_Name[] =
|
||||
{ [EMPTY] = "EMPTY", [STRING] = "STRING", [FLOAT] = "FLOAT", [INT] = "INT",
|
||||
[OPERATOR] = "OPERATOR", [LIDENT] = "LABEL", [FIDENT] = "FUNCTION",
|
||||
[LOCATION] = "LOCATION", [EEK] = "ERROR"
|
||||
};
|
||||
|
||||
/* identcode -- return number of identifier */ /*{{{*/
|
||||
int identcode(const char *s, size_t len)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user