refactored symbol assignment (unfinished)

git-svn-id: https://svn.code.sf.net/p/acme-crossass/code-0/trunk@214 4df02467-bbd4-4a76-a152-e7ce94205b78
This commit is contained in:
marcobaye 2020-06-05 01:11:51 +00:00
parent 72fc28e84c
commit 00d0462f74
8 changed files with 114 additions and 98 deletions

View File

@ -351,7 +351,14 @@ static void get_symbol_value(scope_t scope, char optional_prefix_char, size_t na
struct object *arg;
// if the symbol gets created now, mark it as unsure
symbol = symbol_find(scope, NUMBER_EVER_UNDEFINED); // TODO - split into "find" and "if NULL object, make into undefined int"
symbol = symbol_find(scope);
if (symbol->object.type == NULL) {
// finish symbol item by making it an undefined int
symbol->object.type = &type_int;
symbol->object.u.number.flags = NUMBER_EVER_UNDEFINED;
symbol->object.u.number.addr_refs = 0;
symbol->object.u.number.val.intval = 0;
}
// first push on arg stack, so we have a local copy we can "unpseudopc"
arg = &arg_stack[arg_sp++];
*arg = symbol->object;

View File

@ -168,16 +168,17 @@ static void set_label(scope_t scope, int stat_flags, int force_bit, boolean chan
struct object result;
struct symbol *symbol;
symbol = symbol_find(scope, force_bit); // TODO - split into "find", "forcebit handling", "if NULL object, make int" and "if not int, complain"
// label definition
if ((stat_flags & SF_FOUND_BLANK) && config.warn_on_indented_labels)
Throw_first_pass_warning("Label name not in leftmost column.");
symbol = symbol_find(scope);
// label definition
vcpu_read_pc(&pc);
// FIXME - if undefined, check pass.complain_about_undefined and maybe throw "value not defined"!
result.type = &type_int;
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_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"!
symbol->pseudopc = pseudopc_get_context();
// global labels must open new scope for cheap locals
@ -186,29 +187,55 @@ 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)
{
struct symbol *symbol;
struct object result;
GetByte(); // eat '='
symbol = symbol_find(scope);
ALU_any_result(&result);
// if wanted, mark as address reference
if (typesystem_says_address()) {
// FIXME - checking types explicitly is ugly...
if ((result.type == &type_int)
|| (result.type == &type_float))
result.u.number.addr_refs = 1;
}
// 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))) {
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!
}
symbol_set_object(symbol, &result, po_set);
}
// parse symbol definition (can be either global or local, may turn out to be a label).
// name must be held in GlobalDynaBuf.
static void parse_symbol_definition(scope_t scope, int stat_flags)
{
struct object result;
struct symbol *symbol;
int force_bit = Input_get_force_bit(); // skips spaces after
// FIXME - force bit is allowed for label definitions?!
int force_bit;
force_bit = Input_get_force_bit(); // skips spaces after (yes, force bit is allowed for label definitions)
if (GotByte == '=') {
// explicit symbol definition (symbol = <something>)
symbol = symbol_find(scope, force_bit); // FIXME - split into "find", "forcebit handling", "if not NULL object, types must be equal"...
// symbol = parsed value
GetByte(); // skip '='
ALU_any_result(&result);
// if wanted, mark as address reference
if (typesystem_says_address()) {
// FIXME - checking types explicitly is ugly...
if ((result.type == &type_int)
|| (result.type == &type_float))
result.u.number.addr_refs = 1;
}
symbol_set_object(symbol, &result, FALSE);
parse_assignment(scope, force_bit, FALSE);
Input_ensure_EOS();
} else {
// implicit symbol definition (label)
@ -220,8 +247,11 @@ static void parse_symbol_definition(scope_t scope, int stat_flags)
// Parse global symbol definition or assembler mnemonic
static void parse_mnemo_or_global_symbol_def(int *statement_flags)
{
boolean is_mnemonic;
is_mnemonic = CPU_state.type->keyword_is_mnemonic(Input_read_keyword());
// It is only a label if it isn't a mnemonic
if ((CPU_state.type->keyword_is_mnemonic(Input_read_keyword()) == FALSE)
if ((!is_mnemonic)
&& first_label_of_statement(statement_flags)) {
// Now GotByte = illegal char
// 04 Jun 2005: this fix should help to explain "strange" error messages.
@ -297,7 +327,7 @@ void Parse_until_eob_or_eof(void)
statement_flags = 0; // no "label = pc" definition yet
typesystem_force_address_statement(FALSE);
// Parse until end of statement. Only loops if statement
// contains "label = pc" definition and something else; or
// contains implicit label definition (=pc) and something else; or
// if "!ifdef/ifndef" is true/false, or if "!addr" is used without block.
do {
// check for pseudo opcodes was moved out of switch,

View File

@ -134,6 +134,9 @@ do { \
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);
// 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.

View File

@ -250,8 +250,8 @@ void Macro_parse_call(void) // Now GotByte = dot or first char of macro name
// internal_name = MacroTitle ARG_SEPARATOR (grows to signature)
// Accept n>=0 comma-separated arguments before CHAR_EOS.
// Valid argument formats are:
// EXPRESSION (everything that does NOT start with '~'
// ~SYMBOL
// ~SYMBOL call by ref
// EXPRESSION call by value (everything that does NOT start with '~')
// now GotByte = non-space
if (GotByte != CHAR_EOS) { // any at all?
do {
@ -263,10 +263,10 @@ void Macro_parse_call(void) // Now GotByte = dot or first char of macro name
if (GotByte == REFERENCE_CHAR) {
// read call-by-reference arg
DynaBuf_append(internal_name, ARGTYPE_REF);
GetByte(); // skip '~' character
GetByte(); // eat '~'
Input_read_scope_and_keyword(&symbol_scope);
// GotByte = illegal char
arg_table[arg_count].symbol = symbol_find(symbol_scope, 0); // FIXME - do not default to undefined int!
arg_table[arg_count].symbol = symbol_find(symbol_scope); // CAUTION, object type may be NULL!
} else {
// read call-by-value arg
DynaBuf_append(internal_name, ARGTYPE_VALUE);
@ -317,22 +317,21 @@ void Macro_parse_call(void) // Now GotByte = dot or first char of macro name
// In both cases, GlobalDynaBuf may be used.
if (GotByte == REFERENCE_CHAR) {
// assign call-by-reference arg
GetByte(); // skip '~' character
GetByte(); // eat '~'
Input_read_scope_and_keyword(&symbol_scope);
// create new tree node and link existing symbol struct from arg list to it
if ((Tree_hard_scan(&symbol_node, symbols_forest, symbol_scope, TRUE) == FALSE)
&& (FIRST_PASS))
Throw_error("Macro parameter twice.");
symbol_node->body = arg_table[arg_count].symbol;
symbol_node->body = arg_table[arg_count].symbol; // CAUTION, object type may be NULL
} else {
// assign call-by-value arg
Input_read_scope_and_keyword(&symbol_scope);
symbol = symbol_find(symbol_scope, 0); // FIXME - split into "find", "ensure freshly created"
// FIXME - add a possibility to symbol_find to make it possible to find out
// whether symbol was just created. Then check for the same error message here
// as above ("Macro parameter twice.").
symbol = symbol_find(symbol_scope);
// FIXME - find out if symbol was just created.
// Then check for the same error message here as above ("Macro parameter twice.").
// TODO - on the other hand, this would rule out globals as args (stupid anyway, but not illegal yet!)
symbol->object = arg_table[arg_count].result; // FIXME - this assignment redefines globals without throwing errors!
symbol->object = arg_table[arg_count].result; // FIXME - this assignment redefines globals/whatever without throwing errors!
}
++arg_count;
} while (Input_accept_comma());

View File

@ -739,37 +739,19 @@ Throw_serious_error("Not yet"); // FIXME
// (re)set symbol
static enum eos po_set(void) // now GotByte = illegal char
{
struct object result;
int force_bit;
struct symbol *symbol;
scope_t scope;
scope_t scope;
int force_bit;
if (Input_read_scope_and_keyword(&scope) == 0) // skips spaces before
// now GotByte = illegal char
return SKIP_REMAINDER;
return SKIP_REMAINDER; // zero length
force_bit = Input_get_force_bit(); // skips spaces after
symbol = symbol_find(scope, force_bit); // FIXME - split into "find" and "handle forcebits", remove the "default to undefined int" part!
if (GotByte != '=') {
Throw_error(exception_syntax);
return SKIP_REMAINDER;
}
// symbol = parsed value
GetByte(); // proceed with next char
ALU_any_result(&result);
// 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))) {
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!
symbol_set_object(symbol, &result, TRUE);
parse_assignment(scope, force_bit, TRUE);
return ENSURE_EOS;
}
@ -1053,11 +1035,12 @@ static enum eos po_for(void) // now GotByte = illegal char
struct for_loop loop;
if (Input_read_scope_and_keyword(&scope) == 0) // skips spaces before
return SKIP_REMAINDER;
return SKIP_REMAINDER; // zero length
// now GotByte = illegal char
force_bit = Input_get_force_bit(); // skips spaces after
loop.symbol = symbol_find(scope, force_bit); // FIXME - split into "find" and "handle force bit". if type is not NULL, complain if not number!
loop.symbol = symbol_find(scope); // FIXME - if type is not NULL, complain if not number!
symbol_forcebit(loop.symbol, force_bit);
if (!Input_accept_comma()) {
Throw_error(exception_syntax);
return SKIP_REMAINDER;
@ -1066,7 +1049,8 @@ static enum eos po_for(void) // now GotByte = illegal char
ALU_defined_int(&intresult); // read first argument
loop.counter.addr_refs = intresult.addr_refs;
if (Input_accept_comma()) {
loop.use_old_algo = FALSE; // new format - yay!
// new format - yay!
loop.use_old_algo = FALSE;
if (config.wanted_version < VER_NEWFORSYNTAX)
Throw_first_pass_warning("Found new \"!for\" syntax.");
loop.counter.first = intresult.val.intval; // use first argument
@ -1079,7 +1063,8 @@ static enum eos po_for(void) // now GotByte = illegal char
}
loop.counter.increment = (loop.counter.last < loop.counter.first) ? -1 : 1;
} else {
loop.use_old_algo = TRUE; // old format - booo!
// old format - booo!
loop.use_old_algo = TRUE;
if (config.wanted_version >= VER_NEWFORSYNTAX)
Throw_first_pass_warning("Found old \"!for\" syntax.");
if (intresult.val.intval < 0)

View File

@ -107,8 +107,9 @@ static void dump_vice_unusednonaddress(struct rwnode *node, FILE *fd)
}
// temporary helper function to properly refactor this mess
static struct symbol *temp_find(scope_t scope)
// search for symbol. if it does not exist, create with NULL object (CAUTION!).
// the symbol name must be held in GlobalDynaBuf.
struct symbol *symbol_find(scope_t scope)
{
struct rwnode *node;
struct symbol *symbol;
@ -132,51 +133,27 @@ static struct symbol *temp_find(scope_t scope)
return symbol; // now symbol->object.type can be tested to see if this was freshly created.
// CAUTION: this only works if caller always sets a type pointer after checking! if NULL is kept, the struct still looks new later on...
}
// search for symbol. create if nonexistant. if created, give it flags "flags".
// the symbol name must be held in GlobalDynaBuf.
/*
FIXME - to get lists/strings to work, this can no longer create an int by default!
maybe get rid of "int flags" and use some "struct object *default" instead?
called by;
alu.c
get_symbol_value (here it's okay to create an undefined int)
global.c
set_label implicit symbol definition (gets assigned pc, so int is ok)
parse_symbol_definition explicit symbol definition
macro.c
Macro_parse_call early to build array of outer refs in case of call-by-ref
Macro_parse_call later to lookup inner symbols in case of call-by-value
symbol.c
symbol_define
symbol_fix_forward_anon_name
*/
struct symbol *symbol_find(scope_t scope, int flags) // FIXME - "flags" is either 0 or UNDEFINED or a forcebit, right? move UNDEFINED and forcebit stuff elsewhere!
{
struct symbol *symbol;
int new_force_bits;
symbol = temp_find(scope);
// FIXME - merge with function below!
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 = flags;
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)) {
new_force_bits = flags & NUMBER_FORCEBITS;
if (new_force_bits)
if ((symbol->object.u.number.flags & NUMBER_FORCEBITS) != new_force_bits)
Throw_error("Too late for postfix.");
if ((symbol->object.u.number.flags & NUMBER_FORCEBITS) != force_bit)
Throw_error("Too late for postfix.");
}
}
return symbol;
}
// assign value 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
@ -237,8 +214,8 @@ void symbol_define(intval_t value)
result.type = &type_int;
result.u.number.flags = NUMBER_IS_DEFINED;
result.u.number.val.intval = value;
symbol = symbol_find(SCOPE_GLOBAL, 0);
symbol_set_object(symbol, &result, TRUE);
symbol = symbol_find(SCOPE_GLOBAL);
symbol->object = result;
}
@ -268,6 +245,12 @@ void symbols_vicelabels(FILE *fd)
// references the *next* anonymous forward label definition. The tricky bit is,
// each name length would need its own counter. But hey, ACME's real quick in
// finding symbols, so I'll just abuse the symbol system to store those counters.
// example:
// forward anon name is "+++"
// we look up that symbol's value in the current local scope -> $12
// we attach hex digits to name -> "+++21"
// that's the name of the symbol that _actually_ contains the address
// caller sets "increment" to TRUE for writing, FALSE for reading
void symbol_fix_forward_anon_name(boolean increment)
{
struct symbol *counter_symbol;
@ -275,10 +258,17 @@ void symbol_fix_forward_anon_name(boolean increment)
// terminate name, find "counter" symbol and read value
DynaBuf_append(GlobalDynaBuf, '\0');
counter_symbol = symbol_find(section_now->local_scope, 0);
// sanity check: it must be an int!
if (counter_symbol->object.type != &type_int)
counter_symbol = symbol_find(section_now->local_scope);
if (counter_symbol->object.type == NULL) {
// finish freshly created symbol item
counter_symbol->object.type = &type_int;
counter_symbol->object.u.number.flags = NUMBER_IS_DEFINED;
counter_symbol->object.u.number.addr_refs = 0;
counter_symbol->object.u.number.val.intval = 0;
} else if (counter_symbol->object.type != &type_int) {
// sanity check: it must be an int!
Bug_found("ForwardAnonCounterNotInt", 0);
}
// make sure it gets reset to zero in each new pass
if (counter_symbol->pass != pass.number) {
counter_symbol->pass = pass.number;

View File

@ -31,9 +31,11 @@ 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);
// search for symbol. create if nonexistant. if created, assign flags.
// name must be held in GlobalDynaBuf.
extern struct symbol *symbol_find(scope_t, int flags);
// search for symbol. if it does not exist, create with NULL object (CAUTION!).
// the symbol name must be held in GlobalDynaBuf.
extern struct symbol *symbol_find(scope_t scope);
// FIXME
extern void symbol_forcebit(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);

View File

@ -9,7 +9,7 @@
#define RELEASE "0.96.5" // update before release FIXME
#define CODENAME "Fenchurch" // update before release
#define CHANGE_DATE "3 June" // update before release FIXME
#define CHANGE_DATE "5 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