mirror of
https://github.com/uffejakobsen/acme.git
synced 2025-04-12 01:36:59 +00:00
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:
parent
72fc28e84c
commit
00d0462f74
@ -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;
|
||||
|
66
src/global.c
66
src/global.c
@ -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,
|
||||
|
@ -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.
|
||||
|
21
src/macro.c
21
src/macro.c
@ -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());
|
||||
|
@ -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)
|
||||
|
66
src/symbol.c
66
src/symbol.c
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user