changing a list now needs !set

git-svn-id: https://svn.code.sf.net/p/acme-crossass/code-0/trunk@243 4df02467-bbd4-4a76-a152-e7ce94205b78
This commit is contained in:
marcobaye 2020-06-20 14:54:43 +00:00
parent fc913eefb6
commit 562ce98f75
4 changed files with 69 additions and 39 deletions

102
src/alu.c
View File

@ -370,10 +370,8 @@ static void get_symbol_value(scope_t scope, char optional_prefix_char, size_t na
if (unpseudo_count) { if (unpseudo_count) {
if (arg->type == &type_number) { if (arg->type == &type_number) {
pseudopc_unpseudo(&arg->u.number, symbol->pseudopc, unpseudo_count); pseudopc_unpseudo(&arg->u.number, symbol->pseudopc, unpseudo_count);
// TODO - check return value and enter error state if nonzero?
} else { } else {
Throw_error("Un-pseudopc operator '&' can only be applied to labels."); Throw_error("Un-pseudopc operator '&' can only be applied to labels.");
// TODO - enter error state?
} }
} }
// if needed, output "value not defined" error // if needed, output "value not defined" error
@ -1164,28 +1162,66 @@ static boolean object_return_true(const struct object *self)
} }
// int/float: // int/float:
// helper function to check two values for equality // check if new value differs from old
// in case of undefined value(s), "fallback" is returned // returns FALSE in case of undefined value(s), because undefined is not necessarily different!
static inline boolean num_different(const struct number *self, const struct number *other, boolean fallback) static boolean number_differs(const struct object *self, const struct object *other)
{ {
if (self->ntype == NUMTYPE_UNDEFINED) if (self->u.number.ntype == NUMTYPE_UNDEFINED)
return fallback; return FALSE;
if (other->ntype == NUMTYPE_UNDEFINED) if (other->u.number.ntype == NUMTYPE_UNDEFINED)
return fallback; return FALSE;
if (self->ntype == NUMTYPE_INT) { if (self->u.number.ntype == NUMTYPE_INT) {
if (other->ntype == NUMTYPE_INT) if (other->u.number.ntype == NUMTYPE_INT)
return self->val.intval != other->val.intval; return self->u.number.val.intval != other->u.number.val.intval;
else else
return self->val.intval != other->val.fpval; return self->u.number.val.intval != other->u.number.val.fpval;
} else { } else {
if (other->ntype == NUMTYPE_INT) if (other->u.number.ntype == NUMTYPE_INT)
return self->val.fpval != other->val.intval; return self->u.number.val.fpval != other->u.number.val.intval;
else else
return self->val.fpval != other->val.fpval; return self->u.number.val.fpval != other->u.number.val.fpval;
} }
} }
// list:
// check if new value differs from old
static boolean list_differs(const struct object *self, const struct object *other)
{
struct listitem *arthur,
*ford;
if (self->u.listhead->length != other->u.listhead->length)
return TRUE; // lengths differ
// same length, so iterate over lists and check items
arthur = self->u.listhead->next;
ford = other->u.listhead->next;
while (arthur != self->u.listhead) {
if (ford == other->u.listhead)
Bug_found("ListLengthError", 0);
if (arthur->payload.type != ford->payload.type)
return TRUE; // item types differ
if (arthur->payload.type->differs(&arthur->payload, &ford->payload))
return TRUE; // item values differ
arthur = arthur->next;
ford = ford->next;
}
if (ford != other->u.listhead)
Bug_found("ListLengthError", 1);
return FALSE; // no difference found
}
// string:
// check if new value differs from old
static boolean string_differs(const struct object *self, const struct object *other)
{
if (self->u.string->length != other->u.string->length)
return TRUE;
return !!memcmp(self->u.string->payload, other->u.string->payload, self->u.string->length);
}
// int/float: // int/float:
// assign new value // assign new value
@ -1211,7 +1247,7 @@ static void number_assign(struct object *self, const struct object *new_value, b
} else { } else {
// symbol is already defined, so compare new and old values // symbol is already defined, so compare new and old values
// if values differ, complain and return // if values differ, complain and return
if (num_different(&self->u.number, &new_value->u.number, FALSE)) { if (number_differs(self, new_value)) {
Throw_error(exception_symbol_defined); Throw_error(exception_symbol_defined);
return; return;
} }
@ -1239,33 +1275,20 @@ static void number_assign(struct object *self, const struct object *new_value, b
// assign new value // assign new value
static void list_assign(struct object *self, const struct object *new_value, boolean accept_change) static void list_assign(struct object *self, const struct object *new_value, boolean accept_change)
{ {
if (!accept_change) { if ((!accept_change) && list_differs(self, new_value)) {
if (0/* TODO - compare old and new lists? */) { Throw_error(exception_symbol_defined);
Throw_error(exception_symbol_defined); return;
return;
}
} }
*self = *new_value; *self = *new_value;
} }
// string:
// helper function, returns whether equal
static boolean string_equal(const struct string *arthur, const struct string *ford)
{
if (arthur->length != ford->length)
return FALSE;
return !memcmp(arthur->payload, ford->payload, arthur->length);
}
// string: // string:
// assign new value // assign new value
static void string_assign(struct object *self, const struct object *new_value, boolean accept_change) static void string_assign(struct object *self, const struct object *new_value, boolean accept_change)
{ {
if (!accept_change) { if ((!accept_change) && string_differs(self, new_value)) {
if (!string_equal(self->u.string, new_value->u.string)) { Throw_error(exception_symbol_defined);
Throw_error(exception_symbol_defined); return;
return;
}
} }
*self = *new_value; *self = *new_value;
} }
@ -2013,7 +2036,7 @@ static void string_handle_dyadic_operator(struct object *self, const struct op *
break; // complain break; // complain
arthur = self->u.string; arthur = self->u.string;
ford = other->u.string; ford = other->u.string;
int_create_byte(self, string_equal(arthur, ford)); int_create_byte(self, !string_differs(self, other));
arthur->refs--; // FIXME - call a function for this... arthur->refs--; // FIXME - call a function for this...
ford->refs--; // FIXME - call a function for this... ford->refs--; // FIXME - call a function for this...
return; return;
@ -2023,7 +2046,7 @@ static void string_handle_dyadic_operator(struct object *self, const struct op *
break; // complain break; // complain
arthur = self->u.string; arthur = self->u.string;
ford = other->u.string; ford = other->u.string;
int_create_byte(self, !string_equal(arthur, ford)); int_create_byte(self, string_differs(self, other));
arthur->refs--; // FIXME - call a function for this... arthur->refs--; // FIXME - call a function for this...
ford->refs--; // FIXME - call a function for this... ford->refs--; // FIXME - call a function for this...
return; return;
@ -2124,6 +2147,7 @@ static void string_print(const struct object *self, struct dynabuf *db)
struct type type_number = { struct type type_number = {
"number", "number",
number_is_defined, number_is_defined,
number_differs,
number_assign, number_assign,
number_handle_monadic_operator, number_handle_monadic_operator,
number_handle_dyadic_operator, number_handle_dyadic_operator,
@ -2133,6 +2157,7 @@ struct type type_number = {
struct type type_list = { struct type type_list = {
"list", "list",
object_return_true, // lists are always considered to be defined (even though they can hold undefined numbers...) object_return_true, // lists are always considered to be defined (even though they can hold undefined numbers...)
list_differs,
list_assign, list_assign,
list_handle_monadic_operator, list_handle_monadic_operator,
list_handle_dyadic_operator, list_handle_dyadic_operator,
@ -2142,6 +2167,7 @@ struct type type_list = {
struct type type_string = { struct type type_string = {
"string", "string",
object_return_true, // strings are always defined object_return_true, // strings are always defined
string_differs,
string_assign, string_assign,
string_handle_monadic_operator, string_handle_monadic_operator,
string_handle_dyadic_operator, string_handle_dyadic_operator,

View File

@ -15,6 +15,7 @@ struct dynabuf;
struct type { struct type {
const char *name; const char *name;
boolean (*is_defined)(const struct object *self); boolean (*is_defined)(const struct object *self);
boolean (*differs)(const struct object *self, const struct object *other);
void (*assign)(struct object *self, const struct object *new_value, boolean accept_change); void (*assign)(struct object *self, const struct object *new_value, boolean accept_change);
void (*monadic_op)(struct object *self, const struct op *op); void (*monadic_op)(struct object *self, const struct op *op);
void (*dyadic_op)(struct object *self, const struct op *op, struct object *other); void (*dyadic_op)(struct object *self, const struct op *op, struct object *other);

View File

@ -9,7 +9,7 @@
#define RELEASE "0.96.5" // update before release FIXME #define RELEASE "0.96.5" // update before release FIXME
#define CODENAME "Fenchurch" // update before release #define CODENAME "Fenchurch" // update before release
#define CHANGE_DATE "19 June" // update before release FIXME #define CHANGE_DATE "20 June" // update before release FIXME
#define CHANGE_YEAR "2020" // update before release #define CHANGE_YEAR "2020" // update before release
//#define HOME_PAGE "http://home.pages.de/~mac_bacon/smorbrod/acme/" //#define HOME_PAGE "http://home.pages.de/~mac_bacon/smorbrod/acme/"
#define HOME_PAGE "http://sourceforge.net/p/acme-crossass/" // FIXME #define HOME_PAGE "http://sourceforge.net/p/acme-crossass/" // FIXME

View File

@ -0,0 +1,3 @@
;ACME 0.96.5
a = [1, 2]
a = [1, 3] ; -> "already defined" (value has changed)