diff --git a/src/alu.c b/src/alu.c index 9bc8a4f..9678d9d 100644 --- a/src/alu.c +++ b/src/alu.c @@ -442,7 +442,7 @@ static void parse_quoted(char closing_quote) Throw_error("There's more than one character."); // parse character value = (intval_t) (unsigned char) encoding_encode_char(GLOBALDYNABUF_CURRENT[0]); - PUSH_INT_ARG(value, NUMBER_IS_DEFINED | NUMBER_FITS_BYTE, 0); + PUSH_INT_ARG(value, NUMBER_IS_DEFINED | NUMBER_FITS_BYTE, 0); // FIXME - why set FITS_BYTE? it's only really useful for undefined values! } // Now GotByte = char following closing quote (or CHAR_EOS on error) return; @@ -1126,7 +1126,7 @@ static void unsupported_operation(struct object *optional, struct op *op, struct static void int_create_byte(struct object *self, intval_t byte) { self->type = &type_int; - self->u.number.flags = NUMBER_IS_DEFINED | NUMBER_FITS_BYTE; + self->u.number.flags = NUMBER_IS_DEFINED | NUMBER_FITS_BYTE; // FIXME - if DEFINED anyway, what use is there for FITS_BYTE? self->u.number.val.intval = byte; self->u.number.addr_refs = 0; } @@ -1259,21 +1259,27 @@ static void float_handle_monadic_operator(struct object *self, struct op *op) break; case OPID_SIN: self->u.number.val.fpval = sin(self->u.number.val.fpval); + self->u.number.flags &= ~NUMBER_FITS_BYTE; break; case OPID_COS: self->u.number.val.fpval = cos(self->u.number.val.fpval); + self->u.number.flags &= ~NUMBER_FITS_BYTE; break; case OPID_TAN: self->u.number.val.fpval = tan(self->u.number.val.fpval); + self->u.number.flags &= ~NUMBER_FITS_BYTE; break; case OPID_ARCSIN: float_ranged_fn(asin, self); + self->u.number.flags &= ~NUMBER_FITS_BYTE; break; case OPID_ARCCOS: float_ranged_fn(acos, self); + self->u.number.flags &= ~NUMBER_FITS_BYTE; break; case OPID_ARCTAN: self->u.number.val.fpval = atan(self->u.number.val.fpval); + self->u.number.flags &= ~NUMBER_FITS_BYTE; break; case OPID_NEGATE: self->u.number.val.fpval = -(self->u.number.val.fpval); @@ -1336,15 +1342,26 @@ static void string_handle_monadic_operator(struct object *self, struct op *op) // int/float: // merge result flags -// (used by both int and float handlers for dyadic operators) +// (used by both int and float handlers for comparison operators) +static void number_fix_result_after_comparison(struct object *self, struct object *other, intval_t result) +{ + int flags; + + self->type = &type_int; + self->u.number.val.intval = result; + self->u.number.addr_refs = 0; + flags = (self->u.number.flags & other->u.number.flags) & NUMBER_IS_DEFINED; // DEFINED flags are ANDed together + flags |= (self->u.number.flags | other->u.number.flags) & NUMBER_EVER_UNDEFINED; // EVER_UNDEFINED flags are ORd together + flags |= NUMBER_FITS_BYTE; // FITS_BYTE gets set + // (FORCEBITS are cleared) + self->u.number.flags = flags; +} +// (used by both int and float handlers for all other dyadic operators) static void number_fix_result_after_dyadic(struct object *self, struct object *other) { - // EVER_UNDEFINED and FORCEBIT flags are ORd together - self->u.number.flags |= other->u.number.flags & (NUMBER_EVER_UNDEFINED | NUMBER_FORCEBITS); - // DEFINED flags are ANDed together - self->u.number.flags &= (other->u.number.flags | ~NUMBER_IS_DEFINED); - // FITS_BYTE is cleared - self->u.number.flags &= ~NUMBER_FITS_BYTE; + self->u.number.flags |= other->u.number.flags & (NUMBER_EVER_UNDEFINED | NUMBER_FORCEBITS); // EVER_UNDEFINED and FORCEBITs are ORd together + self->u.number.flags &= (other->u.number.flags | ~NUMBER_IS_DEFINED); // DEFINED flags are ANDed together + self->u.number.flags &= ~NUMBER_FITS_BYTE; // FITS_BYTE is cleared } @@ -1460,24 +1477,17 @@ static void int_handle_dyadic_operator(struct object *self, struct op *op, struc self->u.number.val.intval = ((uintval_t) (self->u.number.val.intval)) >> other->u.number.val.intval; break; case OPID_LESSOREQUAL: -// FIXME - all comparison results should clear all force bits and set fits_byte! also for floats! - self->u.number.val.intval = (self->u.number.val.intval <= other->u.number.val.intval); - break; + return number_fix_result_after_comparison(self, other, self->u.number.val.intval <= other->u.number.val.intval); case OPID_LESSTHAN: - self->u.number.val.intval = (self->u.number.val.intval < other->u.number.val.intval); - break; + return number_fix_result_after_comparison(self, other, self->u.number.val.intval < other->u.number.val.intval); case OPID_GREATEROREQUAL: - self->u.number.val.intval = (self->u.number.val.intval >= other->u.number.val.intval); - break; + return number_fix_result_after_comparison(self, other, self->u.number.val.intval >= other->u.number.val.intval); case OPID_GREATERTHAN: - self->u.number.val.intval = (self->u.number.val.intval > other->u.number.val.intval); - break; + return number_fix_result_after_comparison(self, other, self->u.number.val.intval > other->u.number.val.intval); case OPID_NOTEQUAL: - self->u.number.val.intval = (self->u.number.val.intval != other->u.number.val.intval); - break; + return number_fix_result_after_comparison(self, other, self->u.number.val.intval != other->u.number.val.intval); case OPID_EQUALS: - self->u.number.val.intval = (self->u.number.val.intval == other->u.number.val.intval); - break; + return number_fix_result_after_comparison(self, other, self->u.number.val.intval == other->u.number.val.intval); case OPID_AND: self->u.number.val.intval &= other->u.number.val.intval; refs = self->u.number.addr_refs + other->u.number.addr_refs; // add address references @@ -1500,6 +1510,7 @@ static void int_handle_dyadic_operator(struct object *self, struct op *op, struc unsupported_operation(self, op, other); return; } + // CAUTION: comparisons call number_fix_result_after_comparison instead of jumping here self->u.number.addr_refs = refs; // update address refs with local copy number_fix_result_after_dyadic(self, other); // fix result flags } @@ -1616,29 +1627,17 @@ static void float_handle_dyadic_operator(struct object *self, struct op *op, str self->u.number.val.fpval /= (1 << other->u.number.val.intval); // FIXME - why not use pow() as in SL above? break; case OPID_LESSOREQUAL: - self->u.number.val.intval = (self->u.number.val.fpval <= other->u.number.val.fpval); - self->type = &type_int; // result is int - break; + return number_fix_result_after_comparison(self, other, self->u.number.val.fpval <= other->u.number.val.fpval); case OPID_LESSTHAN: - self->u.number.val.intval = (self->u.number.val.fpval < other->u.number.val.fpval); - self->type = &type_int; // result is int - break; + return number_fix_result_after_comparison(self, other, self->u.number.val.fpval < other->u.number.val.fpval); case OPID_GREATEROREQUAL: - self->u.number.val.intval = (self->u.number.val.fpval >= other->u.number.val.fpval); - self->type = &type_int; // result is int - break; + return number_fix_result_after_comparison(self, other, self->u.number.val.fpval >= other->u.number.val.fpval); case OPID_GREATERTHAN: - self->u.number.val.intval = (self->u.number.val.fpval > other->u.number.val.fpval); - self->type = &type_int; // result is int - break; + return number_fix_result_after_comparison(self, other, self->u.number.val.fpval > other->u.number.val.fpval); case OPID_NOTEQUAL: - self->u.number.val.intval = (self->u.number.val.fpval != other->u.number.val.fpval); - self->type = &type_int; // result is int - break; + return number_fix_result_after_comparison(self, other, self->u.number.val.fpval != other->u.number.val.fpval); case OPID_EQUALS: - self->u.number.val.intval = (self->u.number.val.fpval == other->u.number.val.fpval); - self->type = &type_int; // result is int - break; + return number_fix_result_after_comparison(self, other, self->u.number.val.fpval == other->u.number.val.fpval); // add new dyadic operators here // case OPID_: // break; @@ -1646,6 +1645,7 @@ static void float_handle_dyadic_operator(struct object *self, struct op *op, str unsupported_operation(self, op, other); return; } + // CAUTION: comparisons call number_fix_result_after_comparison instead of jumping here self->u.number.addr_refs = refs; // update address refs with local copy number_fix_result_after_dyadic(self, other); // fix result flags } diff --git a/src/version.h b/src/version.h index ea96d60..0c1d626 100644 --- a/src/version.h +++ b/src/version.h @@ -9,7 +9,7 @@ #define RELEASE "0.96.5" // update before release FIXME #define CODENAME "Fenchurch" // update before release -#define CHANGE_DATE "9 June" // update before release FIXME +#define CHANGE_DATE "10 June" // update before release FIXME #define CHANGE_YEAR "2020" // update before release //#define HOME_PAGE "http://home.pages.de/~mac_bacon/smorbrod/acme/" #define HOME_PAGE "http://sourceforge.net/p/acme-crossass/" // FIXME diff --git a/testing/errors/alreadydefined1.a b/testing/errors/alreadydefined1.a index 28583ab..06a8bbe 100644 --- a/testing/errors/alreadydefined1.a +++ b/testing/errors/alreadydefined1.a @@ -1,2 +1,3 @@ +;ACME 0.96.5 a = 3 a = 3.0 ; -> "already defined" (type has changed) diff --git a/testing/errors/alreadydefined2.a b/testing/errors/alreadydefined2.a index 23123de..672f5bc 100644 --- a/testing/errors/alreadydefined2.a +++ b/testing/errors/alreadydefined2.a @@ -1,2 +1,3 @@ +;ACME 0.96.5 a = 3 a = 4 ; -> "already defined" (value has changed) diff --git a/testing/errors/alreadydefined3.a b/testing/errors/alreadydefined3.a index 6daccf4..02873d5 100644 --- a/testing/errors/alreadydefined3.a +++ b/testing/errors/alreadydefined3.a @@ -1,3 +1,4 @@ +;ACME 0.96.5 *=$1000 label nop diff --git a/testing/errors/toolateforpostfix1.a b/testing/errors/toolateforpostfix1.a index 62a4ab1..5b63143 100644 --- a/testing/errors/toolateforpostfix1.a +++ b/testing/errors/toolateforpostfix1.a @@ -1,3 +1,4 @@ +;ACME 0.96.5 a = 3 b = a ; read a a+2 = 3 ; -> "too late for postfix" diff --git a/testing/errors/toolateforpostfix2.a b/testing/errors/toolateforpostfix2.a index 0ba2f8e..554327d 100644 --- a/testing/errors/toolateforpostfix2.a +++ b/testing/errors/toolateforpostfix2.a @@ -1,3 +1,4 @@ +;ACME 0.96.5 *=$1000 label b = label ; read symbol diff --git a/testing/math1.a b/testing/math1.a index 5580d13..f9e2fbc 100644 --- a/testing/math1.a +++ b/testing/math1.a @@ -1,3 +1,4 @@ +;ACME 0.96.5 ; "assert" macro !macro a @r { !if @r != 1 { diff --git a/testing/numberflags.a b/testing/numberflags.a new file mode 100644 index 0000000..4436188 --- /dev/null +++ b/testing/numberflags.a @@ -0,0 +1,152 @@ +;ACME 0.96.5 + *=$1000 + !cpu 65816 ; we need 24-bit addressing + !macro fitsbyte .arg { +.b + lda .arg + !if * - .b != 2 { + !error "argument wasn't flagged as 'fits byte'" + } + } + !macro defaultsto16b .arg { +.b + lda .arg + !if * - .b != 3 { + !error "argument wasn't flagged as '16 bit size'" + } + } + !macro defaultsto24b .arg { +.b + lda .arg + !if * - .b != 4 { + !error "argument wasn't flagged as '24 bit size'" + } + } + + byte = < (label&0) ; now byte should have FITS_BYTE flag + bigger = label & 0 ; and bigger shouldn't + enforce8+1 = label&0 ; enforce8 should enforce 8-bit addressing + enforce16+2 = label&0 ; enforce16 should enforce 16-bit addressing + enforce24+3 = label&0 ; enforce24 should enforce 24-bit addressing + ; check all monadics + +fitsbyte byte + +defaultsto16b bigger + +fitsbyte enforce8 + +defaultsto16b enforce16 + +defaultsto24b enforce24 + + +defaultsto16b NOT byte + +defaultsto16b NOT bigger + +fitsbyte NOT enforce8 + +defaultsto16b NOT enforce16 + +defaultsto24b NOT enforce24 + + +defaultsto16b -byte + +defaultsto16b -bigger + +fitsbyte -enforce8 + +defaultsto16b -enforce16 + +defaultsto24b -enforce24 + + +fitsbyte byte + +fitsbyte >bigger + +fitsbyte >enforce8 + +fitsbyte >enforce16 + +fitsbyte >enforce24 + + +fitsbyte ^byte + +fitsbyte ^bigger + +fitsbyte ^enforce8 + +fitsbyte ^enforce16 + +fitsbyte ^enforce24 + + +fitsbyte address(byte) + +defaultsto16b address(bigger) + +fitsbyte address(enforce8) + +defaultsto16b address(enforce16) + +defaultsto24b address(enforce24) + + +fitsbyte int(byte) + +defaultsto16b int(bigger) + +fitsbyte int(enforce8) + +defaultsto16b int(enforce16) + +defaultsto24b int(enforce24) + + +fitsbyte float(byte) + +defaultsto16b float(bigger) + +fitsbyte float(enforce8) + +defaultsto16b float(enforce16) + +defaultsto24b float(enforce24) + + +defaultsto16b sin(byte) + +defaultsto16b sin(bigger) + +fitsbyte sin(enforce8) + +defaultsto16b sin(enforce16) + +defaultsto24b sin(enforce24) + + +defaultsto16b cos(byte) + +defaultsto16b cos(bigger) + +fitsbyte cos(enforce8) + +defaultsto16b cos(enforce16) + +defaultsto24b cos(enforce24) + + +defaultsto16b tan(byte) + +defaultsto16b tan(bigger) + +fitsbyte tan(enforce8) + +defaultsto16b tan(enforce16) + +defaultsto24b tan(enforce24) + + +defaultsto16b arcsin(byte) + +defaultsto16b arcsin(bigger) + +fitsbyte arcsin(enforce8) + +defaultsto16b arcsin(enforce16) + +defaultsto24b arcsin(enforce24) + + +defaultsto16b arccos(byte) + +defaultsto16b arccos(bigger) + +fitsbyte arccos(enforce8) + +defaultsto16b arccos(enforce16) + +defaultsto24b arccos(enforce24) + + +defaultsto16b arctan(byte) + +defaultsto16b arctan(bigger) + +fitsbyte arctan(enforce8) + +defaultsto16b arctan(enforce16) + +defaultsto24b arctan(enforce24) + + +fitsbyte 'a' + +fitsbyte