more internal cleanup

git-svn-id: https://svn.code.sf.net/p/acme-crossass/code-0/trunk@124 4df02467-bbd4-4a76-a152-e7ce94205b78
This commit is contained in:
marcobaye 2020-04-26 18:53:14 +00:00
parent a4afd81f42
commit 41f9534b99
4 changed files with 82 additions and 61 deletions

View File

@ -158,7 +158,7 @@ static int operator_sp; // operator stack pointer
static struct result *operand_stack = NULL; // flags and value
static int operand_stk_size = HALF_INITIAL_STACK_SIZE;
static int operand_sp; // value stack pointer
static int indirect_flag; // Flag for indirect addressing
static int indirect_flag; // Flag for indirect addressing TODO - get rid of extra var
// (indicated by useless parentheses)
// Contains either 0 or MVALUE_INDIRECT
enum alu_state {
@ -1423,17 +1423,19 @@ RNTLObutDontTouchIndirectFlag:
}
// The core of it. Returns number of parentheses left open.
// The core of it.
// FIXME - make state machine using function pointers? or too slow?
static int parse_expression(struct result *result)
static void parse_expression(struct expression *expression)
{
int open_parentheses = 0;
struct result *result = &expression->number;
expression->open_parentheses = 0;
operator_sp = 0; // operator stack pointer
operand_sp = 0; // value stack pointer
// begin by reading value (or monadic operator)
alu_state = STATE_EXPECT_OPERAND_OR_MONADIC_OPERATOR;
indirect_flag = 0; // Contains either 0 or MVALUE_INDIRECT
indirect_flag = 0; // Contains either 0 or MVALUE_INDIRECT // FIXME
PUSH_OPERATOR(&ops_exprstart);
do {
// check stack sizes. enlarge if needed
@ -1450,7 +1452,7 @@ static int parse_expression(struct result *result)
break; // no fallthrough; state might
// have been changed to END or ERROR
case STATE_TRY_TO_REDUCE_STACKS:
try_to_reduce_stacks(&open_parentheses);
try_to_reduce_stacks(&expression->open_parentheses);
break;
case STATE_MAX_GO_ON: // suppress
case STATE_ERROR: // compiler
@ -1467,7 +1469,7 @@ static int parse_expression(struct result *result)
Bug_found("OperatorStackNotEmpty", operator_sp);
// copy result
*result = operand_stack[0];
result->flags |= indirect_flag; // OR indirect flag
expression->number.flags |= indirect_flag; // OR indirect flag FIXME - get rid of "indirect"
// only allow *one* force bit
if (result->flags & MVALUE_FORCE24)
result->flags &= ~(MVALUE_FORCE16 | MVALUE_FORCE08);
@ -1475,7 +1477,7 @@ static int parse_expression(struct result *result)
result->flags &= ~MVALUE_FORCE08;
// if there was nothing to parse, mark as undefined
// (so ALU_defined_int() can react)
if ((result->flags & MVALUE_EXISTS) == 0)
if ((expression->number.flags & MVALUE_EXISTS) == 0)
result->flags &= ~MVALUE_DEFINED;
// do some checks depending on int/float
if (result->flags & MVALUE_IS_FP) {
@ -1509,8 +1511,6 @@ static int parse_expression(struct result *result)
// callers must decide for themselves what to do when expression parser returns error
// (currently LDA'' results in both "no string given" AND "illegal combination of command and addressing mode"!)
}
// return number of open (unmatched) parentheses
return open_parentheses; // FIXME - move this into "expression struct flags", together with indirect flag and EXISTS flag
}
@ -1525,22 +1525,23 @@ static int parse_expression(struct result *result)
// FLOAT: convert to int
int ALU_optional_defined_int(intval_t *target) // ACCEPT_EMPTY
{
struct result result;
struct expression expression;
if (parse_expression(&result))
parse_expression(&expression);
if (expression.open_parentheses)
Throw_error(exception_paren_open);
// do not combine the next two checks, they were separated because EXISTS should move from result flags to expression flags...
if ((result.flags & MVALUE_EXISTS)
&& ((result.flags & MVALUE_DEFINED) == 0))
if ((expression.number.flags & MVALUE_EXISTS)
&& ((expression.number.flags & MVALUE_DEFINED) == 0))
Throw_serious_error(value_not_defined());
if ((result.flags & MVALUE_EXISTS) == 0)
if ((expression.number.flags & MVALUE_EXISTS) == 0)
return 0;
// something was given, so store
if (result.flags & MVALUE_IS_FP)
*target = result.val.fpval;
if (expression.number.flags & MVALUE_IS_FP)
*target = expression.number.val.fpval;
else
*target = result.val.intval;
*target = expression.number.val.intval;
return 1;
}
@ -1555,14 +1556,18 @@ int ALU_optional_defined_int(intval_t *target) // ACCEPT_EMPTY
// FLOAT: convert to int
void ALU_int_result(struct result *intresult) // ACCEPT_UNDEFINED
{
if (parse_expression(intresult))
struct expression expression;
parse_expression(&expression);
*intresult = expression.number;
if (expression.open_parentheses)
Throw_error(exception_paren_open);
// make sure result is not float
if (intresult->flags & MVALUE_IS_FP) {
intresult->val.intval = intresult->val.fpval;
intresult->flags &= ~MVALUE_IS_FP;
}
if ((intresult->flags & MVALUE_EXISTS) == 0)
if ((expression.number.flags & MVALUE_EXISTS) == 0)
Throw_error(exception_no_value);
else if ((intresult->flags & MVALUE_DEFINED) == 0)
result_is_undefined();
@ -1580,18 +1585,19 @@ void ALU_int_result(struct result *intresult) // ACCEPT_UNDEFINED
intval_t ALU_any_int(void) // ACCEPT_UNDEFINED
{
// FIXME - replace this fn with a call to ALU_int_result() above!
struct result result;
struct expression expression;
if (parse_expression(&result))
parse_expression(&expression);
if (expression.open_parentheses)
Throw_error(exception_paren_open);
if ((result.flags & MVALUE_EXISTS) == 0)
if ((expression.number.flags & MVALUE_EXISTS) == 0)
Throw_error(exception_no_value);
else if ((result.flags & MVALUE_DEFINED) == 0)
else if ((expression.number.flags & MVALUE_DEFINED) == 0)
result_is_undefined();
if (result.flags & MVALUE_IS_FP)
return result.val.fpval;
if (expression.number.flags & MVALUE_IS_FP)
return expression.number.val.fpval;
else
return result.val.intval;
return expression.number.val.intval;
}
@ -1601,9 +1607,13 @@ intval_t ALU_any_int(void) // ACCEPT_UNDEFINED
// EMPTY: treat as UNDEFINED <= this is a problem - maybe use a wrapper fn for this use case?
// UNDEFINED: complain _seriously_
// FLOAT: convert to int
extern void ALU_defined_int(struct result *intresult) // no ACCEPT constants?
void ALU_defined_int(struct result *intresult) // no ACCEPT constants?
{
if (parse_expression(intresult))
struct expression expression;
parse_expression(&expression);
*intresult = expression.number;
if (expression.open_parentheses)
Throw_error(exception_paren_open);
if ((intresult->flags & MVALUE_DEFINED) == 0)
Throw_serious_error(value_not_defined());
@ -1616,34 +1626,32 @@ extern void ALU_defined_int(struct result *intresult) // no ACCEPT constants?
// Store int value and flags.
// This function allows for one '(' too many. Needed when parsing indirect
// addressing modes where internal indices have to be possible. Returns number
// of parentheses still open (either 0 or 1).
// addressing modes where internal indices have to be possible.
// If the result's "exists" flag is clear (=empty expression), it throws an
// error.
// OPEN_PARENTHESIS: allow
// UNDEFINED: allow
// EMPTY: complain
// FLOAT: convert to int
int ALU_liberal_int(struct result *intresult) // ACCEPT_UNDEFINED | ACCEPT_OPENPARENTHESIS
void ALU_liberal_int(struct expression *expression) // ACCEPT_UNDEFINED | ACCEPT_OPENPARENTHESIS
{
int parentheses_still_open;
struct result *intresult = &expression->number;
parentheses_still_open = parse_expression(intresult);
parse_expression(expression);
// make sure result is not float
if (intresult->flags & MVALUE_IS_FP) {
intresult->val.intval = intresult->val.fpval;
intresult->flags &= ~MVALUE_IS_FP;
}
if (parentheses_still_open > 1) {
parentheses_still_open = 0;
if (expression->open_parentheses > 1) {
expression->open_parentheses = 0;
Throw_error(exception_paren_open);
}
if ((intresult->flags & MVALUE_EXISTS) == 0)
if ((expression->number.flags & MVALUE_EXISTS) == 0)
Throw_error(exception_no_value);
if ((intresult->flags & MVALUE_EXISTS)
if ((expression->number.flags & MVALUE_EXISTS)
&& ((intresult->flags & MVALUE_DEFINED) == 0))
result_is_undefined();
return parentheses_still_open;
}
@ -1657,9 +1665,13 @@ int ALU_liberal_int(struct result *intresult) // ACCEPT_UNDEFINED | ACCEPT_OPENP
// FLOAT: keep
void ALU_any_result(struct result *result) // ACCEPT_UNDEFINED | ACCEPT_FLOAT
{
if (parse_expression(result))
struct expression expression;
parse_expression(&expression);
*result = expression.number;
if (expression.open_parentheses)
Throw_error(exception_paren_open);
if ((result->flags & MVALUE_EXISTS) == 0)
if ((expression.number.flags & MVALUE_EXISTS) == 0)
Throw_error(exception_no_value);
else if ((result->flags & MVALUE_DEFINED) == 0)
result_is_undefined();

View File

@ -10,6 +10,24 @@
#include "config.h"
// types
/*
enum expression_type {
EXTY_EMPTY, // next char after space was comma or end-of-statement
EXTY_NUMBER, // int or float (what is returned by the current functions)
EXTY_STRING, // TODO
EXTY_REGISTER, // reserved cpu constant (register names), TODO
EXTY_LIST // TODO
};
*/
struct expression {
//enum expression_type type;
struct result number;
//int flags; // TODO: move EXISTS and INDIRECT here
int open_parentheses; // number of parentheses still open
};
// constants
// TODO - move EXISTS and INDIRECT to a new "expression flags" struct! make "nothing" its own result type?
@ -38,15 +56,7 @@ extern void (*ALU_optional_notdef_handler)(const char *);
// FIXME - replace all the functions below with a single one using a "flags" arg!
/* its return value would then be:
enum expression_result {
EXRE_ERROR, // error (has been reported, so skip remainder of statement)
EXRE_NOTHING, // next char after space was comma or end-of-statement
EXRE_NUMBER, // int or float (what is returned by the current functions)
EXRE_STRING, // TODO
EXRE_RESERVED, // reserved cpu constant (register names), TODO
EXRE_LIST // TODO
};
/* its return value would then be "error"/"ok".
// input flags:
#define ACCEPT_EMPTY (1u << 0) // if not given, throws error
#define ACCEPT_UNDEFINED (1u << 1) // if not given, undefined throws serious error
@ -67,8 +77,7 @@ extern void ALU_int_result(struct result *intresult);
// if result was undefined, serious error is thrown
extern void ALU_defined_int(struct result *intresult);
// stores int value and flags, allowing for one '(' too many (x-indirect addr).
// returns number of additional '(' (1 or 0).
extern int ALU_liberal_int(struct result *intresult);
extern void ALU_liberal_int(struct expression *expression);
// stores value and flags (result may be either int or float)
extern void ALU_any_result(struct result *result);

View File

@ -1,5 +1,5 @@
// ACME - a crossassembler for producing 6502/65c02/65816/65ce02 code.
// Copyright (C) 1998-2016 Marco Baye
// Copyright (C) 1998-2020 Marco Baye
// Have a look at "acme.c" for further info
//
// Configuration
@ -12,9 +12,8 @@ typedef unsigned int scope_t;
typedef signed long intval_t; // at least 32 bits
typedef unsigned long uintval_t; // just for logical shift right
// result structure type definition with support for floating point
// future result types: EMPTY, UNDEFINED, INT, FLOAT (, STRING)
struct result { // either int or float
int flags; // expression flags
struct result { // either int or float (TODO - rename to "number"?)
int flags; // result flags (see alu.h, one if these tells ints and floats apart)
union {
intval_t intval; // integer value
double fpval; // floating point value

View File

@ -523,8 +523,8 @@ static int get_index(int next)
// structure (using the valueparser). The addressing mode is returned.
static int get_argument(struct result *result)
{
int open_paren,
address_mode_bits = 0;
struct expression expression;
int address_mode_bits = 0;
SKIPSPACE();
switch (GotByte) {
@ -548,13 +548,14 @@ static int get_argument(struct result *result)
break;
default:
// liberal, to allow for "(...,"
open_paren = ALU_liberal_int(result);
ALU_liberal_int(&expression);
*result = expression.number;
typesystem_want_addr(result);
// check for indirect addressing
if (result->flags & MVALUE_INDIRECT)
if (expression.number.flags & MVALUE_INDIRECT)
address_mode_bits |= AMB_INDIRECT;
// check for internal index (before closing parenthesis)
if (open_paren) {
if (expression.open_parentheses) {
// in case there are still open parentheses,
// read internal index
address_mode_bits |= AMB_PREINDEX(get_index(FALSE));