break;
case FCONST:
ptk.u32 = tok;
- *evalTokenBuffer.u32++ = CONST;
+ *evalTokenBuffer.u32++ = FCONST;
*evalTokenBuffer.u64++ = *ptk.u64++;
tok = ptk.u32;
break;
}
if (sy->sattr & DEFINED)
- {
*++sval = sy->svalue; // Push symbol's value
- }
else
- {
*++sval = 0; // 0 for undefined symbols
- }
*++sattr = (WORD)(sy->sattr & ~GLOBAL); // Push attribs
sym_seg = (WORD)(sy->sattr & TDB);
break;
+
case CONST:
*++sval = *tk.u64++;
//printf("evexpr(): CONST = %lX\n", *sval);
*++sattr = ABS | DEFINED; // Push simple attribs
break;
+
case FCONST:
-//printf("evexpr(): FCONST = %i\n", *tk.u32);
- *((double *)sval) = *((double *)tk.u32);
- tk.u32 += 2;
+//printf("evexpr(): FCONST = %lf\n", *tk.dp);
+ // Even though it's a double, we can treat it like a uint64_t since
+ // we're just moving the bits around.
+ *++sval = *tk.u64++;
*++sattr = ABS | DEFINED | FLOAT; // Push simple attribs
break;
+
case ACONST:
//printf("evexpr(): ACONST = %i\n", *tk.u32);
*++sval = *tk.u32++; // Push value
//
// [1] + : Error
// - : ABS
+
case '+':
//printf("evexpr(): +\n");
--sval; // Pop value
--sattr; // Pop attrib
//printf("--> N+N: %i + %i = ", *sval, sval[1]);
- // Extract float attributes from both terms and pack them
- // into a single value
- attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) >> 1);
- attr2 = sattr[0] | sattr[1] & FLOAT; // Returns FLOAT if either of the two numbers are FLOAT
+ // Get FLOAT attribute, if any
+ attr = (sattr[0] | sattr[1]) & FLOAT;
- if (attr == (FLOAT | (FLOAT >> 1)))
- {
- // Float + Float
- double * dst = (double *)sval;
- double * src = (double *)(sval + 1);
- *dst += *src;
- }
- else if (attr == FLOAT)
- {
- // Float + Int
- double * dst = (double *)sval;
- uint64_t * src = (uint64_t *)(sval + 1);
- *dst += *src;
- }
- else if (attr == FLOAT >> 1)
+ // Since adding an int to a fp value promotes it to a fp value, we
+ // don't care whether it's first or second; we cast to to a double
+ // regardless.
+ if (attr == FLOAT)
{
- // Int + Float
- uint64_t * dst = (uint64_t *)sval;
- double * src = (double *)(sval + 1);
- *(double *)dst = *src + *dst;
+ PTR p;
+ p.u64 = sval;
+ double fpval1 = (sattr[0] & FLOAT ? *p.dp : (double)*p.i64);
+ p.u64++;
+ double fpval2 = (sattr[1] & FLOAT ? *p.dp : (double)*p.i64);
+ *(double *)sval = fpval1 + fpval2;
}
else
{
//printf("%i\n", *sval);
if (!(*sattr & TDB))
- *sattr = sattr[1] | attr2;
+ *sattr = sattr[1] | attr;
else if (sattr[1] & TDB)
return error(seg_error);
break;
+
case '-':
//printf("evexpr(): -\n");
--sval; // Pop value
--sattr; // Pop attrib
//printf("--> N-N: %i - %i = ", *sval, sval[1]);
- // Extract float attributes from both terms and pack them
- // into a single value
- attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) >> 1);
- attr2 = sattr[0] | sattr[1] & FLOAT; // Returns FLOAT if either of the two numbers are FLOAT
+ // Get FLOAT attribute, if any
+ attr = (sattr[0] | sattr[1]) & FLOAT;
- if (attr == (FLOAT | (FLOAT >> 1)))
- {
- // Float - Float
- double * dst = (double *)sval;
- double * src = (double *)(sval + 1);
- *dst -= *src;
- }
- else if (attr == FLOAT)
+ // Since subtracting an int to a fp value promotes it to a fp
+ // value, we don't care whether it's first or second; we cast to to
+ // a double regardless.
+ if (attr == FLOAT)
{
- // Float - Int
- double * dst = (double *)sval;
- uint64_t * src = (uint64_t *)(sval + 1);
- *dst -= *src;
- }
- else if (attr == FLOAT >> 1)
- {
- // Int - Float
- uint64_t * dst = (uint64_t *)sval;
- double * src = (double *)(sval + 1);
- *(double *)dst = *dst - *src;
+ PTR p;
+ p.u64 = sval;
+ double fpval1 = (sattr[0] & FLOAT ? *p.dp : (double)*p.i64);
+ p.u64++;
+ double fpval2 = (sattr[1] & FLOAT ? *p.dp : (double)*p.i64);
+ *(double *)sval = fpval1 - fpval2;
}
else
{
- *sval -= sval[1]; // Compute value
+ *sval -= sval[1];
}
-
//printf("%i\n", *sval);
+ *sattr |= attr; // Inherit FLOAT attribute
attr = (WORD)(*sattr & TDB);
#if 0
printf("EVEXPR (-): sym1 = %X, sym2 = %X\n", attr, sattr[1]);
#endif
- *sattr |= attr2; // Inherit FLOAT attribute
// If symbol1 is ABS, take attributes from symbol2
if (!attr)
*sattr = sattr[1];
*sattr &= ~TDB;
break;
+
// Unary operators only work on ABS items
case UNMINUS:
//printf("evexpr(): UNMINUS\n");
if (*sattr & FLOAT)
{
- double *dst = (double *)sval;
+ double * dst = (double *)sval;
*dst = -*dst;
*sattr = ABS | DEFINED | FLOAT; // Expr becomes absolute
}
else
{
- *sval = -(int)*sval;
+ *sval = -(int64_t)*sval;
*sattr = ABS | DEFINED; // Expr becomes absolute
}
+
break;
+
case '!':
//printf("evexpr(): !\n");
if (*sattr & TDB)
*sval = !*sval;
*sattr = ABS | DEFINED; // Expr becomes absolute
break;
+
case '~':
//printf("evexpr(): ~\n");
if (*sattr & TDB)
*sval = ~*sval;
*sattr = ABS | DEFINED; // Expr becomes absolute
break;
+
// Comparison operators must have two values that
// are in the same segment, but that's the only requirement.
case LE:
if ((*sattr & TDB) != (sattr[1] & TDB))
return error(seg_error);
- // Extract float attributes from both terms and pack them
- // into a single value
- attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) >> 1);
+ // Get FLOAT attribute, if any
+ attr = (sattr[0] | sattr[1]) & FLOAT;
- if (attr == (FLOAT | (FLOAT >> 1)))
- {
- // Float <= Float
- double * dst = (double *)sval;
- double * src = (double *)(sval + 1);
- *sval = *dst <= *src;
- }
- else if (attr == FLOAT)
- {
- // Float <= Int
- double * dst = (double *)sval;
- uint64_t * src = (uint64_t *)(sval + 1);
- *sval = *dst <= *src;
- }
- else if (attr == FLOAT >> 1)
+ // Cast any ints in the comparison to double, if there's at least
+ // one double in the comparison.
+ if (attr == FLOAT)
{
- // Int <= Float
- uint64_t * dst = (uint64_t *)sval;
- double * src = (double *)(sval + 1);
- *sval = *dst <= *src;
+ PTR p;
+ p.u64 = sval;
+ double fpval1 = (sattr[0] & FLOAT ? *p.dp : (double)*p.i64);
+ p.u64++;
+ double fpval2 = (sattr[1] & FLOAT ? *p.dp : (double)*p.i64);
+ *sval = (fpval1 <= fpval2);
}
else
{
- *sval = *sval <= sval[1];
+ *sval = (*sval <= sval[1]);
}
*sattr = ABS | DEFINED;
break;
+
case GE:
//printf("evexpr(): GE\n");
sattr--;
if ((*sattr & TDB) != (sattr[1] & TDB))
return error(seg_error);
- // Extract float attributes from both terms and pack them
- // into a single value
- attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) >> 1);
+ // Get FLOAT attribute, if any
+ attr = (sattr[0] | sattr[1]) & FLOAT;
- if (attr == (FLOAT | (FLOAT >> 1)))
- {
- // Float >= Float
- double * dst = (double *)sval;
- double * src = (double *)(sval + 1);
- *sval = *dst >= *src;
- }
- else if (attr == FLOAT)
+ // Cast any ints in the comparison to double, if there's at least
+ // one double in the comparison.
+ if (attr == FLOAT)
{
- // Float >= Int
- double * dst = (double *)sval;
- uint64_t * src = (uint64_t *)(sval + 1);
- *sval = *dst >= *src;
- }
- else if (attr == FLOAT >> 1)
- {
- // Int >= Float
- uint64_t * dst = (uint64_t *)sval;
- double * src = (double *)(sval + 1);
- *sval = *dst >= *src;
+ PTR p;
+ p.u64 = sval;
+ double fpval1 = (sattr[0] & FLOAT ? *p.dp : (double)*p.i64);
+ p.u64++;
+ double fpval2 = (sattr[1] & FLOAT ? *p.dp : (double)*p.i64);
+ *sval = (fpval1 >= fpval2);
}
- else if (attr == 0)
+ else
{
- *sval = *sval >= sval[1];
+ *sval = (*sval >= sval[1]);
}
- else
- *sattr = ABS | DEFINED;
+ *sattr = ABS | DEFINED;
break;
+
case '>':
//printf("evexpr(): >\n");
sattr--;
if ((*sattr & TDB) != (sattr[1] & TDB))
return error(seg_error);
- // Extract float attributes from both terms and pack them
- // into a single value
- attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) >> 1);
+ // Get FLOAT attribute, if any
+ attr = (sattr[0] | sattr[1]) & FLOAT;
- if (attr == (FLOAT | (FLOAT >> 1)))
- {
- // Float > Float
- double * dst = (double *)sval;
- double * src = (double *)(sval + 1);
- *sval = *dst > *src;
- }
- else if (attr == FLOAT)
- {
- // Float > Int
- double * dst = (double *)sval;
- uint64_t * src = (uint64_t *)(sval + 1);
- *sval = *dst > *src;
- }
- else if (attr == FLOAT >> 1)
+ // Cast any ints in the comparison to double, if there's at least
+ // one double in the comparison.
+ if (attr == FLOAT)
{
- // Int > Float
- uint64_t * dst = (uint64_t *)sval;
- double * src = (double *)(sval + 1);
- *sval = *dst > *src;
+ PTR p;
+ p.u64 = sval;
+ double fpval1 = (sattr[0] & FLOAT ? *p.dp : (double)*p.i64);
+ p.u64++;
+ double fpval2 = (sattr[1] & FLOAT ? *p.dp : (double)*p.i64);
+ *sval = (fpval1 > fpval2);
}
else
{
- *sval = *sval > sval[1];
+ *sval = (*sval > sval[1]);
}
*sattr = ABS | DEFINED;
-
break;
+
case '<':
//printf("evexpr(): <\n");
sattr--;
if ((*sattr & TDB) != (sattr[1] & TDB))
return error(seg_error);
- // Extract float attributes from both terms and pack them
- // into a single value
- attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) >> 1);
+ // Get FLOAT attribute, if any
+ attr = (sattr[0] | sattr[1]) & FLOAT;
- if (attr == (FLOAT | (FLOAT >> 1)))
- {
- // Float < Float
- double * dst = (double *)sval;
- double * src = (double *)(sval + 1);
- *sval = *dst < *src;
- }
- else if (attr == FLOAT)
- {
- // Float < Int
- double * dst = (double *)sval;
- uint64_t * src = (uint64_t *)(sval + 1);
- *sval = *dst < *src;
- }
- else if (attr == FLOAT >> 1)
+ // Cast any ints in the comparison to double, if there's at least
+ // one double in the comparison.
+ if (attr == FLOAT)
{
- // Int < Float
- uint64_t * dst = (uint64_t *)sval;
- double * src = (double *)(sval + 1);
- *sval = *dst < *src;
+ PTR p;
+ p.u64 = sval;
+ double fpval1 = (sattr[0] & FLOAT ? *p.dp : (double)*p.i64);
+ p.u64++;
+ double fpval2 = (sattr[1] & FLOAT ? *p.dp : (double)*p.i64);
+ *sval = (fpval1 < fpval2);
}
else
{
- *sval = *sval < sval[1];
+ *sval = (*sval < sval[1]);
}
- *sattr = ABS | DEFINED;
-
+ *sattr = ABS | DEFINED; // Expr forced to ABS
break;
+
case NE:
//printf("evexpr(): NE\n");
sattr--;
if ((*sattr & TDB) != (sattr[1] & TDB))
return error(seg_error);
- // Extract float attributes from both terms and pack them
- // into a single value
- attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) >> 1);
+ // Get FLOAT attribute, if any
+ attr = (sattr[0] | sattr[1]) & FLOAT;
- if (attr == (FLOAT | (FLOAT >> 1)))
+ // Cast any ints in the comparison to double, if there's at least
+ // one double in the comparison.
+ if (attr == FLOAT)
{
- // Float <> Float
- return error("comparison for equality with float types not allowed.");
- }
- else if (attr == FLOAT)
- {
- // Float <> Int
- return error("comparison for equality with float types not allowed.");
- }
- else if (attr == FLOAT >> 1)
- {
- // Int != Float
- return error("comparison for equality with float types not allowed.");
+ PTR p;
+ p.u64 = sval;
+ double fpval1 = (sattr[0] & FLOAT ? *p.dp : (double)*p.i64);
+ p.u64++;
+ double fpval2 = (sattr[1] & FLOAT ? *p.dp : (double)*p.i64);
+ *sval = (fpval1 != fpval2);
}
else
{
- *sval = *sval != sval[1];
+ *sval = (*sval != sval[1]);
}
- *sattr = ABS | DEFINED;
-
+ *sattr = ABS | DEFINED; // Expr forced to ABS
break;
+
case '=':
//printf("evexpr(): =\n");
sattr--;
if ((*sattr & TDB) != (sattr[1] & TDB))
return error(seg_error);
- // Extract float attributes from both terms and pack them
- // into a single value
- attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) >> 1);
+ // Get FLOAT attribute, if any
+ attr = (sattr[0] | sattr[1]) & FLOAT;
- if (attr == (FLOAT | (FLOAT >> 1)))
- {
- // Float = Float
- double * dst = (double *)sval;
- double * src = (double *)(sval + 1);
- *sval = *src == *dst;
- }
- else if (attr == FLOAT)
- {
- // Float = Int
- return error("equality with float ");
- }
- else if (attr == FLOAT >> 1)
+ // Cast any ints in the comparison to double, if there's at least
+ // one double in the comparison.
+ if (attr == FLOAT)
{
- // Int == Float
- uint64_t * dst = (uint64_t *)sval;
- double * src = (double *)(sval + 1);
- *sval = *src == *dst;
+ PTR p;
+ p.u64 = sval;
+ double fpval1 = (sattr[0] & FLOAT ? *p.dp : (double)*p.i64);
+ p.u64++;
+ double fpval2 = (sattr[1] & FLOAT ? *p.dp : (double)*p.i64);
+ *sval = (fpval1 == fpval2);
}
else
{
- *sval = *sval == sval[1];
+ *sval = (*sval == sval[1]);
}
- *sattr = ABS | DEFINED;
+ *sattr = ABS | DEFINED; // Expr forced to ABS
break;
+
// All other binary operators must have two ABS items to work with.
// They all produce an ABS value.
default:
{
case '*':
sval--;
- sattr--; // Pop attrib
+ sattr--;
//printf("--> NxN: %i x %i = ", *sval, sval[1]);
- // Extract float attributes from both terms and pack them
- // into a single value
- attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) >> 1);
- attr2 = sattr[0] | sattr[1] & FLOAT; // Returns FLOAT if either of the two numbers are FLOAT
+ // Get FLOAT attribute, if any
+ attr = (sattr[0] | sattr[1]) & FLOAT;
- if (attr == (FLOAT | (FLOAT >> 1)))
- {
- // Float * Float
- double * dst = (double *)sval;
- double * src = (double *)(sval + 1);
- *dst *= *src;
- }
- else if (attr == FLOAT)
- {
- // Float * Int
- double * dst = (double *)sval;
- uint64_t * src = (uint64_t *)(sval + 1);
- *dst *= *src;
- }
- else if (attr == FLOAT >> 1)
+ // Since multiplying an int to a fp value promotes it to a fp
+ // value, we don't care whether it's first or second; it will
+ // be cast to a double regardless.
+/*
+An open question here is do we promote ints to floats as signed or unsigned? It makes a difference if, say, the int is put in as -1 but is promoted to a double as $FFFFFFFFFFFFFFFF--you get very different results that way! For now, we promote as signed until proven detrimental otherwise.
+*/
+ if (attr == FLOAT)
{
- // Int * Float
- uint64_t * dst = (uint64_t *)sval;
- double * src = (double *)(sval + 1);
- *(double *)dst = *src * *dst;
+ PTR p;
+ p.u64 = sval;
+ double fpval1 = (sattr[0] & FLOAT ? *p.dp : (double)*p.i64);
+ p.u64++;
+ double fpval2 = (sattr[1] & FLOAT ? *p.dp : (double)*p.i64);
+ *(double *)sval = fpval1 * fpval2;
}
else
{
}
//printf("%i\n", *sval);
- *sattr = ABS | DEFINED; // Expr becomes absolute
- *sattr |= attr2;
-
+ *sattr = ABS | DEFINED | attr; // Expr becomes absolute
break;
+
case '/':
sval--;
- sattr--; // Pop attrib
-
-
+ sattr--;
//printf("--> N/N: %i / %i = ", sval[0], sval[1]);
- // Extract float attributes from both terms and pack them
- // into a single value
- attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) >> 1);
- attr2 = sattr[0] | sattr[1] & FLOAT; // Returns FLOAT if either of the two numbers are FLOAT
-
- if (attr == (FLOAT | (FLOAT >> 1)))
- {
- // Float / Float
- double * dst = (double *)sval;
- double * src = (double *)(sval + 1);
-
- if (*src == 0)
- return error("divide by zero");
+ // Get FLOAT attribute, if any
+ attr = (sattr[0] | sattr[1]) & FLOAT;
- *dst = *dst / *src;
- }
- else if (attr == FLOAT)
+ if (attr == FLOAT)
{
- // Float / Int
- double * dst = (double *)sval;
- uint64_t * src = (uint64_t *)(sval + 1);
+ PTR p;
+ p.u64 = sval;
+ double fpval1 = (sattr[0] & FLOAT ? *p.dp : (double)*p.i64);
+ p.u64++;
+ double fpval2 = (sattr[1] & FLOAT ? *p.dp : (double)*p.i64);
- if (*src == 0)
+ if (fpval2 == 0)
return error("divide by zero");
- *dst = *dst / *src;
- }
- else if (attr == FLOAT >> 1)
- {
- // Int / Float
- uint64_t * dst=(uint64_t *)sval;
- double * src=(double *)(sval + 1);
-
- if (*src == 0)
- return error("divide by zero");
-
- *(double *)dst = *dst / *src;
+ *(double *)sval = fpval1 / fpval2;
}
else
{
// ints.
*sval = (int32_t)sval[0] / (int32_t)sval[1];
}
-
- *sattr = ABS | DEFINED; // Expr becomes absolute
- *sattr |= attr2;
-
//printf("%i\n", *sval);
+
+ *sattr = ABS | DEFINED | attr; // Expr becomes absolute
break;
+
case '%':
sval--;
- sattr--; // Pop attrib
+ sattr--;
if ((*sattr | sattr[1]) & FLOAT)
return error("floating point numbers not allowed with operator '%'.");
if (sval[1] == 0)
return error("mod (%) by zero");
- *sattr = ABS | DEFINED; // Expr becomes absolute
*sval %= sval[1];
+ *sattr = ABS | DEFINED; // Expr becomes absolute
break;
+
case SHL:
sval--;
sattr--; // Pop attrib
if ((*sattr | sattr[1]) & FLOAT)
return error("floating point numbers not allowed with operator '<<'.");
- *sattr = ABS | DEFINED; // Expr becomes absolute
*sval <<= sval[1];
+ *sattr = ABS | DEFINED; // Expr becomes absolute
break;
+
case SHR:
sval--;
sattr--; // Pop attrib
if ((*sattr | sattr[1]) & FLOAT)
return error("floating point numbers not allowed with operator '>>'.");
- *sattr = ABS | DEFINED; // Expr becomes absolute
*sval >>= sval[1];
+ *sattr = ABS | DEFINED; // Expr becomes absolute
break;
+
case '&':
sval--;
sattr--; // Pop attrib
if ((*sattr | sattr[1]) & FLOAT)
return error("floating point numbers not allowed with operator '&'.");
- *sattr = ABS | DEFINED; // Expr becomes absolute
*sval &= sval[1];
+ *sattr = ABS | DEFINED; // Expr becomes absolute
break;
+
case '^':
sval--;
sattr--; // Pop attrib
if ((*sattr | sattr[1]) & FLOAT)
return error("floating point numbers not allowed with operator '^'.");
- *sattr = ABS | DEFINED; // Expr becomes absolute
*sval ^= sval[1];
+ *sattr = ABS | DEFINED; // Expr becomes absolute
break;
+
case '|':
sval--;
- sattr--; // Pop attrib
+ sattr--;
if ((*sattr | sattr[1]) & FLOAT)
return error("floating point numbers not allowed with operator '|'.");
- *sattr = ABS | DEFINED; // Expr becomes absolute
*sval |= sval[1];
+ *sattr = ABS | DEFINED; // Expr becomes absolute
break;
+
default:
- interror(5); // Bad operator in expression stream
+ // Bad operator in expression stream (this should never happen!)
+ interror(5);
}
}
}
if (a_esym != NULL)
*a_esym = esym;
- // sym_seg added in 1.0.16 to solve a problem with forward symbols in
- // expressions where absolute values also existed. The absolutes were
- // overiding the symbol segments and not being included :(
- //*a_attr = *sattr | sym_seg; // Copy value + attrib
-
- *a_attr = *sattr; // Copy value + attrib
+ // Copy value + attrib into return variables
*a_value = *sval;
+ *a_attr = *sattr;
return OK;
}