mirror of
https://github.com/uffejakobsen/acme.git
synced 2025-01-10 05:30:29 +00:00
symbol assignment refactoring seems to be finished now
git-svn-id: https://svn.code.sf.net/p/acme-crossass/code-0/trunk@228 4df02467-bbd4-4a76-a152-e7ce94205b78
This commit is contained in:
parent
395dcf55f3
commit
4643e841f9
122
src/alu.c
122
src/alu.c
@ -1161,6 +1161,112 @@ static boolean object_return_true(struct object *self)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// int/float:
|
||||
// helper function to check two values for equality
|
||||
// in case of undefined value(s), "fallback" is returned
|
||||
static inline boolean num_different(struct object *self, struct object *other, boolean fallback)
|
||||
{
|
||||
if ((self->u.number.flags & NUMBER_IS_DEFINED) == 0)
|
||||
return fallback;
|
||||
|
||||
if ((other->u.number.flags & NUMBER_IS_DEFINED) == 0)
|
||||
return fallback;
|
||||
|
||||
if (self->type == &type_int) {
|
||||
if (other->type == &type_int)
|
||||
return self->u.number.val.intval != other->u.number.val.intval;
|
||||
else
|
||||
return self->u.number.val.intval != other->u.number.val.fpval;
|
||||
} else {
|
||||
if (other->type == &type_int)
|
||||
return self->u.number.val.fpval != other->u.number.val.intval;
|
||||
else
|
||||
return self->u.number.val.fpval != other->u.number.val.fpval;
|
||||
}
|
||||
}
|
||||
|
||||
// int/float:
|
||||
// assign new value
|
||||
static void number_assign(struct object *self, struct object *new_value, boolean accept_change)
|
||||
{
|
||||
int own_flags = self->u.number.flags,
|
||||
other_flags = new_value->u.number.flags;
|
||||
// local copies of the flags are used because
|
||||
// self->...flags might get overwritten when copying struct over, and
|
||||
// new_value-> is const so shouldn't be touched.
|
||||
|
||||
// accepting a different value is easily done by just forgetting the old one:
|
||||
if (accept_change) {
|
||||
own_flags &= ~(NUMBER_IS_DEFINED | NUMBER_FITS_BYTE);
|
||||
}
|
||||
|
||||
// copy struct over?
|
||||
if (!(own_flags & NUMBER_IS_DEFINED)) {
|
||||
// symbol is undefined OR redefinitions are allowed, so use new value:
|
||||
*self = *new_value; // copy type and flags/value/addr_refs
|
||||
// flags will be fixed, see below
|
||||
} else {
|
||||
// symbol is already defined, so compare new and old values
|
||||
// if values differ, complain and return
|
||||
if (num_different(self, new_value, FALSE)) {
|
||||
Throw_error(exception_symbol_defined);
|
||||
return;
|
||||
}
|
||||
// values are the same, so only fiddle with flags
|
||||
}
|
||||
|
||||
// if symbol has no force bits of its own, use the ones from new value:
|
||||
if ((own_flags & NUMBER_FORCEBITS) == 0)
|
||||
own_flags = (own_flags & ~NUMBER_FORCEBITS) | (other_flags & NUMBER_FORCEBITS);
|
||||
|
||||
// tainted symbols without "fits byte" flag must never get that flag
|
||||
if ((own_flags & (NUMBER_EVER_UNDEFINED | NUMBER_FITS_BYTE)) == NUMBER_EVER_UNDEFINED)
|
||||
other_flags &= ~NUMBER_FITS_BYTE;
|
||||
// now OR together "fits byte", "defined" and "tainted"
|
||||
// (any hypothetical problems about "new value is later found out to
|
||||
// _not_ fit byte" would be detected when assigning a different value
|
||||
// raises an error in a later pass)
|
||||
own_flags |= other_flags & (NUMBER_FITS_BYTE | NUMBER_IS_DEFINED | NUMBER_EVER_UNDEFINED);
|
||||
|
||||
self->u.number.flags = own_flags;
|
||||
}
|
||||
|
||||
|
||||
// list:
|
||||
// assign new value
|
||||
static void list_assign(struct object *self, struct object *new_value, boolean accept_change)
|
||||
{
|
||||
if (!accept_change) {
|
||||
if (0/* TODO - compare old and new lists? */) {
|
||||
Throw_error(exception_symbol_defined);
|
||||
return;
|
||||
}
|
||||
}
|
||||
*self = *new_value;
|
||||
}
|
||||
|
||||
// string:
|
||||
// helper function, returns whether equal
|
||||
static boolean string_equal(struct string *arthur, struct string *ford)
|
||||
{
|
||||
if (arthur->length != ford->length)
|
||||
return FALSE;
|
||||
|
||||
return !memcmp(arthur->payload, ford->payload, arthur->length);
|
||||
}
|
||||
// string:
|
||||
// assign new value
|
||||
static void string_assign(struct object *self, struct object *new_value, boolean accept_change)
|
||||
{
|
||||
if (!accept_change) {
|
||||
if (!string_equal(self->u.string, new_value->u.string)) {
|
||||
Throw_error(exception_symbol_defined);
|
||||
return;
|
||||
}
|
||||
}
|
||||
*self = *new_value;
|
||||
}
|
||||
|
||||
// this gets called for LSR, AND, OR, XOR with float args
|
||||
// FIXME - warning is never seen if arguments are undefined in first pass!
|
||||
static void warn_float_to_int(void)
|
||||
@ -1762,11 +1868,7 @@ static void string_handle_dyadic_operator(struct object *self, struct op *op, st
|
||||
break; // complain
|
||||
arthur = self->u.string;
|
||||
ford = other->u.string;
|
||||
if (arthur->length != ford->length) {
|
||||
int_create_byte(self, FALSE);
|
||||
} else {
|
||||
int_create_byte(self, !memcmp(arthur->payload, ford->payload, arthur->length));
|
||||
}
|
||||
int_create_byte(self, string_equal(arthur, ford));
|
||||
arthur->refs--; // FIXME - call a function for this...
|
||||
ford->refs--; // FIXME - call a function for this...
|
||||
return;
|
||||
@ -1776,11 +1878,7 @@ static void string_handle_dyadic_operator(struct object *self, struct op *op, st
|
||||
break; // complain
|
||||
arthur = self->u.string;
|
||||
ford = other->u.string;
|
||||
if (arthur->length != ford->length) {
|
||||
int_create_byte(self, TRUE);
|
||||
} else {
|
||||
int_create_byte(self, !!memcmp(arthur->payload, ford->payload, arthur->length));
|
||||
}
|
||||
int_create_byte(self, !string_equal(arthur, ford));
|
||||
arthur->refs--; // FIXME - call a function for this...
|
||||
ford->refs--; // FIXME - call a function for this...
|
||||
return;
|
||||
@ -1902,6 +2000,7 @@ static void string_print(struct object *self, struct dynabuf *db)
|
||||
struct type type_int = {
|
||||
"integer",
|
||||
number_is_defined,
|
||||
number_assign,
|
||||
int_handle_monadic_operator,
|
||||
int_handle_dyadic_operator,
|
||||
int_fix_result,
|
||||
@ -1910,6 +2009,7 @@ struct type type_int = {
|
||||
struct type type_float = {
|
||||
"float",
|
||||
number_is_defined,
|
||||
number_assign,
|
||||
float_handle_monadic_operator,
|
||||
float_handle_dyadic_operator,
|
||||
float_fix_result,
|
||||
@ -1918,6 +2018,7 @@ struct type type_float = {
|
||||
struct type type_list = {
|
||||
"list",
|
||||
object_return_true, // lists are always considered to be defined (even though they can hold undefined numbers...)
|
||||
list_assign,
|
||||
list_handle_monadic_operator,
|
||||
list_handle_dyadic_operator,
|
||||
object_no_op, // no need to fix list results
|
||||
@ -1926,6 +2027,7 @@ struct type type_list = {
|
||||
struct type type_string = {
|
||||
"string",
|
||||
object_return_true, // strings are always defined
|
||||
string_assign,
|
||||
string_handle_monadic_operator,
|
||||
string_handle_dyadic_operator,
|
||||
object_no_op, // no need to fix string results
|
||||
|
@ -15,6 +15,7 @@ struct dynabuf;
|
||||
struct type {
|
||||
const char *name;
|
||||
boolean (*is_defined)(struct object *self);
|
||||
void (*assign)(struct object *self, struct object *new_value, boolean accept_change);
|
||||
void (*monadic_op)(struct object *self, struct op *op);
|
||||
void (*dyadic_op)(struct object *self, struct op *op, struct object *other);
|
||||
void (*fix_result)(struct object *self);
|
||||
|
15
src/flow.c
15
src/flow.c
@ -61,8 +61,21 @@ void flow_forloop(struct for_loop *loop)
|
||||
loop_counter.u.number.flags = NUMBER_IS_DEFINED;
|
||||
loop_counter.u.number.val.intval = loop->counter.first;
|
||||
loop_counter.u.number.addr_refs = loop->counter.addr_refs;
|
||||
symbol_set_object2(loop->symbol, &loop_counter, loop->force_bit, TRUE);
|
||||
// CAUTION: next line does not have power to change symbol type, but if
|
||||
// "symbol already defined" error is thrown, the type will still have
|
||||
// been changed. this was done so the code below has a counter var.
|
||||
symbol_set_object(loop->symbol, &loop_counter, POWER_CHANGE_VALUE);
|
||||
// TODO: in versions before 0.97, force bit handling was broken
|
||||
// in both "!set" and "!for":
|
||||
// trying to change a force bit correctly raised an error, but
|
||||
// in any case, ALL FORCE BITS WERE CLEARED in symbol. only
|
||||
// cases like !set N=N+1 worked, because the force bit was
|
||||
// taken from result.
|
||||
// maybe support this behaviour via --dialect?
|
||||
if (loop->force_bit)
|
||||
symbol_set_force_bit(loop->symbol, loop->force_bit);
|
||||
loop_counter = loop->symbol->object; // update local copy with force bit
|
||||
loop->symbol->has_been_read = TRUE; // lock force bit
|
||||
if (loop->use_old_algo) {
|
||||
// old algo for old syntax:
|
||||
// if count == 0, skip loop
|
||||
|
26
src/global.c
26
src/global.c
@ -54,6 +54,7 @@ const char exception_no_right_brace[] = "Found end-of-file instead of '}'.";
|
||||
//const char exception_not_yet[] = "Sorry, feature not yet implemented.";
|
||||
const char exception_number_out_of_range[] = "Number out of range.";
|
||||
const char exception_pc_undefined[] = "Program counter undefined.";
|
||||
const char exception_symbol_defined[] = "Symbol already defined.";
|
||||
const char exception_syntax[] = "Syntax error.";
|
||||
const char exception_value_not_defined[] = "Value not defined.";
|
||||
// default value for number of errors before exiting
|
||||
@ -162,7 +163,8 @@ static int first_label_of_statement(int *statement_flags)
|
||||
// parse label definition (can be either global or local).
|
||||
// name must be held in GlobalDynaBuf.
|
||||
// called by parse_symbol_definition, parse_backward_anon_def, parse_forward_anon_def
|
||||
static void set_label(scope_t scope, int stat_flags, int force_bit, boolean change_allowed) // "change_allowed" is used by backward anons!
|
||||
// "powers" is used by backward anons to allow changes
|
||||
static void set_label(scope_t scope, int stat_flags, int force_bit, int powers)
|
||||
{
|
||||
struct symbol *symbol;
|
||||
struct number pc;
|
||||
@ -176,7 +178,9 @@ static void set_label(scope_t scope, int stat_flags, int force_bit, boolean chan
|
||||
result.u.number.flags = pc.flags & NUMBER_IS_DEFINED;
|
||||
result.u.number.val.intval = pc.val.intval;
|
||||
result.u.number.addr_refs = pc.addr_refs;
|
||||
symbol_set_object2(symbol, &result, force_bit, change_allowed);
|
||||
symbol_set_object(symbol, &result, powers);
|
||||
if (force_bit)
|
||||
symbol_set_force_bit(symbol, force_bit);
|
||||
symbol->pseudopc = pseudopc_get_context();
|
||||
// global labels must open new scope for cheap locals
|
||||
if (scope == SCOPE_GLOBAL)
|
||||
@ -185,8 +189,8 @@ static void set_label(scope_t scope, int stat_flags, int force_bit, boolean chan
|
||||
|
||||
|
||||
// call with symbol name in GlobalDynaBuf and GotByte == '='
|
||||
// "po_set" is for "!set" pseudo opcode, so changes are allowed
|
||||
void parse_assignment(scope_t scope, int force_bit, boolean po_set)
|
||||
// "powers" is for "!set" pseudo opcode so changes are allowed (see symbol.h for powers)
|
||||
void parse_assignment(scope_t scope, int force_bit, int powers)
|
||||
{
|
||||
struct symbol *symbol;
|
||||
struct object result;
|
||||
@ -201,7 +205,9 @@ void parse_assignment(scope_t scope, int force_bit, boolean po_set)
|
||||
|| (result.type == &type_float))
|
||||
result.u.number.addr_refs = 1;
|
||||
}
|
||||
symbol_set_object3(symbol, &result, force_bit, po_set);
|
||||
symbol_set_object(symbol, &result, powers);
|
||||
if (force_bit)
|
||||
symbol_set_force_bit(symbol, force_bit);
|
||||
}
|
||||
|
||||
|
||||
@ -214,11 +220,11 @@ static void parse_symbol_definition(scope_t scope, int stat_flags)
|
||||
force_bit = Input_get_force_bit(); // skips spaces after (yes, force bit is allowed for label definitions)
|
||||
if (GotByte == '=') {
|
||||
// explicit symbol definition (symbol = <something>)
|
||||
parse_assignment(scope, force_bit, FALSE);
|
||||
parse_assignment(scope, force_bit, POWER_NONE);
|
||||
Input_ensure_EOS();
|
||||
} else {
|
||||
// implicit symbol definition (label)
|
||||
set_label(scope, stat_flags, force_bit, FALSE);
|
||||
set_label(scope, stat_flags, force_bit, POWER_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -266,7 +272,8 @@ static void parse_backward_anon_def(int *statement_flags)
|
||||
DYNABUF_APPEND(GlobalDynaBuf, '-');
|
||||
while (GetByte() == '-');
|
||||
DynaBuf_append(GlobalDynaBuf, '\0');
|
||||
set_label(section_now->local_scope, *statement_flags, 0, TRUE); // this "TRUE" is the whole secret
|
||||
// 0 = no force bit, power = backward anons change their value!
|
||||
set_label(section_now->local_scope, *statement_flags, 0, POWER_CHANGE_VALUE);
|
||||
}
|
||||
|
||||
|
||||
@ -285,7 +292,8 @@ static void parse_forward_anon_def(int *statement_flags)
|
||||
symbol_fix_forward_anon_name(TRUE); // TRUE: increment counter
|
||||
DynaBuf_append(GlobalDynaBuf, '\0');
|
||||
//printf("[%d, %s]\n", section_now->local_scope, GlobalDynaBuf->buffer);
|
||||
set_label(section_now->local_scope, *statement_flags, 0, FALSE);
|
||||
// 0 = no force bit
|
||||
set_label(section_now->local_scope, *statement_flags, 0, POWER_NONE);
|
||||
}
|
||||
|
||||
|
||||
|
@ -44,6 +44,7 @@ extern const char exception_no_right_brace[];
|
||||
//extern const char exception_not_yet[];
|
||||
extern const char exception_number_out_of_range[];
|
||||
extern const char exception_pc_undefined[];
|
||||
extern const char exception_symbol_defined[];
|
||||
extern const char exception_syntax[];
|
||||
extern const char exception_value_not_defined[];
|
||||
// byte flags table
|
||||
@ -135,8 +136,8 @@ extern void config_default(struct config *conf);
|
||||
// allocate memory and die if not available
|
||||
extern void *safe_malloc(size_t amount);
|
||||
// call with symbol name in GlobalDynaBuf and GotByte == '='
|
||||
// "po_set" is for "!set" pseudo opcode, so changes are allowed
|
||||
extern void parse_assignment(scope_t scope, int force_bit, boolean po_set);
|
||||
// "powers" is for "!set" pseudo opcode so changes are allowed (see symbol.h for powers)
|
||||
extern void parse_assignment(scope_t scope, int force_bit, int powers);
|
||||
// Parse block, beginning with next byte.
|
||||
// End reason (either CHAR_EOB or CHAR_EOF) can be found in GotByte afterwards
|
||||
// Has to be re-entrant.
|
||||
|
@ -751,7 +751,14 @@ static enum eos po_set(void) // now GotByte = illegal char
|
||||
return SKIP_REMAINDER;
|
||||
}
|
||||
|
||||
parse_assignment(scope, force_bit, TRUE);
|
||||
// TODO: in versions before 0.97, force bit handling was broken
|
||||
// in both "!set" and "!for":
|
||||
// trying to change a force bit correctly raised an error, but
|
||||
// in any case, ALL FORCE BITS WERE CLEARED in symbol. only
|
||||
// cases like !set N=N+1 worked, because the force bit was
|
||||
// taken from result.
|
||||
// maybe support this behaviour via --dialect?
|
||||
parse_assignment(scope, force_bit, POWER_CHANGE_VALUE | POWER_CHANGE_OBJTYPE);
|
||||
return ENSURE_EOS;
|
||||
}
|
||||
|
||||
|
160
src/symbol.c
160
src/symbol.c
@ -135,119 +135,77 @@ struct symbol *symbol_find(scope_t scope)
|
||||
}
|
||||
|
||||
|
||||
// FIXME - temporary helper function during refactoring
|
||||
static void symbol_forcebit(struct symbol *symbol, int force_bit)
|
||||
{
|
||||
// if symbol has no object assigned to it, make it an int
|
||||
if (symbol->object.type == NULL) {
|
||||
// finish empty symbol item
|
||||
symbol->object.type = &type_int;
|
||||
symbol->object.u.number.flags = force_bit;
|
||||
symbol->object.u.number.addr_refs = 0;
|
||||
symbol->object.u.number.val.intval = 0;
|
||||
} else {
|
||||
// make sure the force bits don't clash
|
||||
if ((symbol->object.type == &type_int)
|
||||
|| (symbol->object.type == &type_float)) {
|
||||
if (force_bit
|
||||
&& force_bit != (symbol->object.u.number.flags & NUMBER_FORCEBITS))
|
||||
Throw_error("Too late for postfix.");
|
||||
}
|
||||
}
|
||||
}
|
||||
// assign value to symbol. the function acts upon the symbol's flag bits and
|
||||
// assign object to symbol. the function acts upon the symbol's flag bits and
|
||||
// produces an error if needed.
|
||||
// TODO - split checks into two parts: first deal with object type. in case of number, then check value/flags/whatever
|
||||
static void symbol_set_object(struct symbol *symbol, struct object *new_value, boolean change_allowed) // FIXME - does "change_allowed" refer to type change or number value change?
|
||||
// using "power" bits, caller can state which changes are ok.
|
||||
// called by:
|
||||
// implicit label definitions (including anons, backward anons have POWER_CHANGE_VALUE)
|
||||
// explicit symbol assignments
|
||||
// explicit symbol assignments via "!set" (has all powers)
|
||||
// loop counter var init via "!for" (has POWER_CHANGE_VALUE and POWER_CHANGE_NUMTYPE)
|
||||
// CAUTION: actual incrementing of counter is then done directly without calls here!
|
||||
void symbol_set_object(struct symbol *symbol, struct object *new_value, int powers)
|
||||
{
|
||||
int flags; // for int/float re-definitions
|
||||
struct type *symbol_class, // helper vars to group
|
||||
*newval_class; // ints and floats
|
||||
|
||||
// any new type?
|
||||
if (((symbol->object.type != &type_int) && (symbol->object.type != &type_float))
|
||||
|| ((new_value->type != &type_int) && (new_value->type != &type_float))) {
|
||||
// changing value is ok, changing type needs extra flag:
|
||||
if (change_allowed || (symbol->object.type == new_value->type))
|
||||
symbol->object = *new_value;
|
||||
else
|
||||
Throw_error("Symbol already defined.");
|
||||
// if symbol has no object assigned to it yet, fine:
|
||||
if (symbol->object.type == NULL) {
|
||||
symbol->object = *new_value; // copy whole struct including type
|
||||
// as long as the symbol has not been read, the force bits can
|
||||
// be changed, so the caller still has a chance to do that.
|
||||
return;
|
||||
}
|
||||
|
||||
// FIXME - force bits assigned via !for or !set are lost, because due to "change_allowed", the new object struct is copied and that's it!
|
||||
// now we know symbol already has a type
|
||||
|
||||
// both old and new are either int or float, so keep old algo:
|
||||
|
||||
// value stuff
|
||||
flags = symbol->object.u.number.flags;
|
||||
if (change_allowed || !(flags & NUMBER_IS_DEFINED)) {
|
||||
// symbol is not defined yet OR redefinitions are allowed
|
||||
symbol->object = *new_value;
|
||||
} else {
|
||||
// symbol is already defined, so compare new and old values
|
||||
// if different type OR same type but different value, complain
|
||||
if ((symbol->object.type != new_value->type)
|
||||
|| ((symbol->object.type == &type_float) ? (symbol->object.u.number.val.fpval != new_value->u.number.val.fpval) : (symbol->object.u.number.val.intval != new_value->u.number.val.intval)))
|
||||
Throw_error("Symbol already defined.");
|
||||
// compare types (CAUTION, ints and floats are grouped!)
|
||||
symbol_class = symbol->object.type;
|
||||
if (symbol_class == &type_float)
|
||||
symbol_class = &type_int;
|
||||
newval_class = new_value->type;
|
||||
if (newval_class == &type_float)
|
||||
newval_class = &type_int;
|
||||
// if too different, needs power (or complains)
|
||||
if (symbol_class != newval_class) {
|
||||
if (!(powers & POWER_CHANGE_OBJTYPE))
|
||||
Throw_error(exception_symbol_defined);
|
||||
// CAUTION: if above line throws error, we still go ahead and change type!
|
||||
// this is to keep "!for" working, where the counter var is accessed.
|
||||
symbol->object = *new_value; // copy whole struct including type
|
||||
// clear flag so caller can adjust force bits:
|
||||
symbol->has_been_read = FALSE; // it's basically a new symbol now
|
||||
return;
|
||||
}
|
||||
// flags stuff
|
||||
// Ensure that "unsure" symbols without "isByte" state don't get that
|
||||
if ((flags & (NUMBER_EVER_UNDEFINED | NUMBER_FITS_BYTE)) == NUMBER_EVER_UNDEFINED)
|
||||
new_value->u.number.flags &= ~NUMBER_FITS_BYTE;
|
||||
|
||||
if (change_allowed) {
|
||||
// take flags from new value, then OR EVER_UNDEFINED from old value
|
||||
flags = (flags & NUMBER_EVER_UNDEFINED) | new_value->u.number.flags;
|
||||
} else {
|
||||
if ((flags & NUMBER_FORCEBITS) == 0) {
|
||||
if ((flags & (NUMBER_EVER_UNDEFINED | NUMBER_IS_DEFINED)) == 0) {
|
||||
// FIXME - this can't happen!? Yes, it can!
|
||||
// if the symbol was created just now to be assigned a value,
|
||||
// then both flags are clear before the assignment takes place.
|
||||
// in future this should no longer happen, because creating a
|
||||
// symbol will give it the NULL type, and flags will only
|
||||
// matter if it then gets assigned an int or float value.
|
||||
flags |= new_value->u.number.flags & NUMBER_FORCEBITS;
|
||||
}
|
||||
}
|
||||
flags |= new_value->u.number.flags & ~NUMBER_FORCEBITS;
|
||||
}
|
||||
symbol->object.u.number.flags = flags;
|
||||
// now we know symbol and new value have compatible types, so call handler:
|
||||
symbol->object.type->assign(&symbol->object, new_value, !!(powers & POWER_CHANGE_VALUE));
|
||||
}
|
||||
// FIXME - temporary helper function during refactoring
|
||||
// used for:
|
||||
// (implicit!) label definitions, including anons (FIXME - anons cannot have force bits. handle them elsewhere? change backward anons directly, no questions asked?)
|
||||
// setting up loop counter for "!for" (CAUTION: actual incrementing is then done directly without calling this function!)
|
||||
// "change_allowed" is used by backward anons, but then force_bit is 0
|
||||
// "change_allowed" is also used by "!for", then force_bit may be nonzero
|
||||
void symbol_set_object2(struct symbol *symbol, struct object *result, int force_bit, boolean change_allowed)
|
||||
|
||||
|
||||
// set force bit of symbol. trying to change to a different one will raise error.
|
||||
void symbol_set_force_bit(struct symbol *symbol, int force_bit)
|
||||
{
|
||||
symbol_forcebit(symbol, force_bit); // TODO - "if NULL object, make int" and "if not int, complain"
|
||||
symbol_set_object(symbol, result, change_allowed); // FIXME - "backward anon allows number redef" is different from "!set allows object redef"!
|
||||
}
|
||||
// FIXME - temporary helper function during refactoring
|
||||
// used for:
|
||||
// explicit assignments, including "!set"
|
||||
// "po_set" means "!set", so changes are allowed
|
||||
void symbol_set_object3(struct symbol *symbol, struct object *result, int force_bit, boolean po_set)
|
||||
{
|
||||
// FIXME - force bit can only be used if result is number! check!
|
||||
symbol_forcebit(symbol, force_bit);
|
||||
// if this was called by !set, new force bit replaces old one:
|
||||
if (po_set) {
|
||||
// clear symbol's force bits and set new ones
|
||||
// (but only do this for numbers!)
|
||||
if (((symbol->object.type == &type_int) || (symbol->object.type == &type_float))
|
||||
&& ((result->type == &type_int) || (result->type == &type_float))) {
|
||||
// clear symbol's size flags, set new one, clear result's size flags
|
||||
symbol->object.u.number.flags &= ~(NUMBER_FORCEBITS | NUMBER_FITS_BYTE);
|
||||
if (force_bit) {
|
||||
symbol->object.u.number.flags |= force_bit;
|
||||
result->u.number.flags &= ~(NUMBER_FORCEBITS | NUMBER_FITS_BYTE);
|
||||
}
|
||||
}
|
||||
// FIXME - take a good look at the flags handling above and in the fn called below and clean this up!
|
||||
if (!force_bit)
|
||||
Bug_found("ForceBitZero", 0); // FIXME - add to docs!
|
||||
if (symbol->object.type == NULL)
|
||||
Bug_found("NullObject", 0); // FIXME - add to docs!
|
||||
|
||||
if ((symbol->object.type != &type_int) && (symbol->object.type != &type_float)) {
|
||||
Throw_error("Force bits can only be given to numbers."); // FIXME - add to docs!
|
||||
return;
|
||||
}
|
||||
symbol_set_object(symbol, result, po_set);
|
||||
|
||||
// if change is ok, change
|
||||
if (!symbol->has_been_read) {
|
||||
symbol->object.u.number.flags &= ~NUMBER_FORCEBITS;
|
||||
symbol->object.u.number.flags |= force_bit;
|
||||
return; // and be done with it
|
||||
}
|
||||
|
||||
// it's too late to change, so check if the wanted bit is actually different
|
||||
if ((symbol->object.u.number.flags & NUMBER_FORCEBITS) != force_bit)
|
||||
Throw_error("Too late for postfix.");
|
||||
}
|
||||
|
||||
|
||||
|
15
src/symbol.h
15
src/symbol.h
@ -29,15 +29,18 @@ struct symbol {
|
||||
extern struct rwnode *symbols_forest[]; // trees (because of 8-bit hash)
|
||||
|
||||
|
||||
// function acts upon the symbol's flag bits and produces an error if needed.
|
||||
//extern void symbol_set_object(struct symbol *symbol, struct object *new_obj, boolean change_allowed);
|
||||
// FIXME - temporary helper function during refactoring
|
||||
extern void symbol_set_object2(struct symbol *symbol, struct object *new_obj, int force_bit, boolean change_allowed);
|
||||
// FIXME - temporary helper function during refactoring
|
||||
extern void symbol_set_object3(struct symbol *symbol, struct object *new_obj, int force_bit, boolean change_allowed);
|
||||
// search for symbol. if it does not exist, create with NULL type object (CAUTION!).
|
||||
// the symbol name must be held in GlobalDynaBuf.
|
||||
extern struct symbol *symbol_find(scope_t scope);
|
||||
// assign object to symbol. function acts upon the symbol's flag bits and
|
||||
// produces an error if needed.
|
||||
// using "power" bits, caller can state which changes are ok.
|
||||
#define POWER_NONE 0
|
||||
#define POWER_CHANGE_VALUE (1u << 0) // e.g. change 3 to 5 or 2.71
|
||||
#define POWER_CHANGE_OBJTYPE (1u << 1) // e.g. change 3 to "somestring"
|
||||
extern void symbol_set_object(struct symbol *symbol, struct object *new_obj, int powers);
|
||||
// set force bit of symbol. trying to change to a different one will raise error.
|
||||
extern void symbol_set_force_bit(struct symbol *symbol, int force_bit);
|
||||
// set global symbol to value, no questions asked (for "-D" switch)
|
||||
// name must be held in GlobalDynaBuf.
|
||||
extern void symbol_define(intval_t value);
|
||||
|
@ -9,7 +9,7 @@
|
||||
|
||||
#define RELEASE "0.96.5" // update before release FIXME
|
||||
#define CODENAME "Fenchurch" // update before release
|
||||
#define CHANGE_DATE "13 June" // update before release FIXME
|
||||
#define CHANGE_DATE "14 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
|
||||
|
Loading…
x
Reference in New Issue
Block a user