fixes for nested DO/IF/ELSE/FIN

This commit is contained in:
marketideas 2019-11-21 19:20:59 -08:00
parent d86bd06e8e
commit b154efff36
5 changed files with 120 additions and 68 deletions

153
asm.cpp
View File

@ -2030,13 +2030,38 @@ restart:
return (res);
}
bool CLASS::doOFF(void)
{
bool res=curDO.doskip;
std::stack<TDOstruct> tmpstack;
TDOstruct doitem;
uint32_t ct=DOstack.size();
if (ct>0)
{
tmpstack=DOstack;
}
while(ct>0)
{
doitem=tmpstack.top();
tmpstack.pop();
if (doitem.doskip)
{
res=true;
}
ct--;
}
return(res);
}
// this function determines if code generation is turned off (IF,DO,LUP,MAC, etc
bool CLASS::codeSkipped(void)
{
bool res = false;
res = (curLUP.lupskip) ? true : res;
res = (curDO.doskip) ? true : res;
res = doOFF() ? true : res;
res = currentmacro.running ? true : res;
//printf("codeskip: %d\n",res);
@ -2062,7 +2087,7 @@ void CLASS::process(void)
char c;
char buff[256];
MerlinLine errLine;
std::string op, operand, ls;
std::string op, realop, operand, ls;
pass = 0;
while (pass < 2)
@ -2116,6 +2141,7 @@ void CLASS::process(void)
//printf("lineno: %d %d |%s|\n",lineno,l,line.operand.c_str());
op = Poco::toLower(line.opcode);
realop = line.opcode;
operand = Poco::toLower(line.operand);
line.startpc = PC.currentpc;
line.linemx = mx;
@ -2194,74 +2220,85 @@ void CLASS::process(void)
x = 0;
if (op.length() > 0)
{
TMacro *mac = NULL;
bool inoperand = false;
mac = findMacro(op);
if (mac == NULL)
bool skipop = false;
if (doOFF())
{
if (op == ">>>") // specal merlin way of calling a macro
skipop = true;
if ((op == "fin") || (op == "else") || (op == "do") || (op == "if"))
{
Poco::StringTokenizer tok(operand, ", ", Poco::StringTokenizer::TOK_TRIM |
Poco::StringTokenizer::TOK_IGNORE_EMPTY);
std::string s="";
if (tok.count()>0)
{
s=tok[0];
}
mac = findMacro(s);
inoperand = true;
skipop = false;
}
}
if (mac == NULL)
if (!skipop)
{
x = callOpCode(op, line);
}
if (mac != NULL)
{
expand_macrostack.push(expand_macro);
expand_macro = *mac;
expand_macro.lines.clear();
//printf("mac start=%u end=%u\n", expand_macro.start, expand_macro.end);
for (uint32_t lc = expand_macro.start; lc < expand_macro.end; lc++)
TMacro *mac = NULL;
bool inoperand = false;
mac = findMacro(realop);
if (mac == NULL)
{
//printf("pushing %s\n", lines[lc].wholetext.c_str());
MerlinLine nl(lines[lc].wholetext); // create a new clean line (without errors,data)
expand_macro.lines.push_back(nl);
}
expand_macro.running = true;
expand_macro.sourceline = lineno;
expand_macro.variables.vars.clear();
// set the variables for the macro here SGQ
std::string parms = line.operand;
if (inoperand)
{
Poco::StringTokenizer tok(parms, ", ", Poco::StringTokenizer::TOK_TRIM |
Poco::StringTokenizer::TOK_IGNORE_EMPTY);
parms = "";
if (tok.count() > 1)
if (op == ">>>") // specal merlin way of calling a macro
{
parms = tok[1];
Poco::StringTokenizer tok(operand, ", ", Poco::StringTokenizer::TOK_TRIM |
Poco::StringTokenizer::TOK_IGNORE_EMPTY);
std::string s = "";
if (tok.count() > 0)
{
s = tok[0];
}
mac = findMacro(s);
inoperand = true;
}
}
Poco::StringTokenizer tok(parms, ",;", Poco::StringTokenizer::TOK_TRIM |
Poco::StringTokenizer::TOK_IGNORE_EMPTY);
uint32_t ct = 0;
for (auto itr = tok.begin(); itr != tok.end(); ++itr)
if (mac == NULL)
{
//evaluate each of these strings, check for errors on pass 2
std::string expr = *itr;
std::string v = "]" + Poco::NumberFormatter::format(ct + 1);
//printf("var: %s %s\n", v.c_str(), expr.c_str());
addVariable(v, expr, expand_macro.variables, true);
ct++;
x = callOpCode(op, line);
}
if (mac != NULL)
{
expand_macrostack.push(expand_macro);
expand_macro = *mac;
expand_macro.lines.clear();
//printf("mac start=%u end=%u\n", expand_macro.start, expand_macro.end);
for (uint32_t lc = expand_macro.start; lc < expand_macro.end; lc++)
{
//printf("pushing %s\n", lines[lc].wholetext.c_str());
MerlinLine nl(lines[lc].wholetext); // create a new clean line (without errors,data)
expand_macro.lines.push_back(nl);
}
expand_macro.running = true;
expand_macro.sourceline = lineno;
expand_macro.variables.vars.clear();
// set the variables for the macro here SGQ
std::string parms = line.operand;
if (inoperand)
{
Poco::StringTokenizer tok(parms, ", ", Poco::StringTokenizer::TOK_TRIM |
Poco::StringTokenizer::TOK_IGNORE_EMPTY);
parms = "";
if (tok.count() > 1)
{
parms = tok[1];
}
}
Poco::StringTokenizer tok(parms, ",;", Poco::StringTokenizer::TOK_TRIM |
Poco::StringTokenizer::TOK_IGNORE_EMPTY);
uint32_t ct = 0;
for (auto itr = tok.begin(); itr != tok.end(); ++itr)
{
//evaluate each of these strings, check for errors on pass 2
std::string expr = *itr;
std::string v = "]" + Poco::NumberFormatter::format(ct + 1);
//printf("var: %s %s\n", v.c_str(), expr.c_str());
addVariable(v, expr, expand_macro.variables, true);
ct++;
}
x = 0;
expand_macro.currentline = 0;
}
x = 0;
expand_macro.currentline = 0;
}
//}
}
if ((x > 0) && (codeSkipped())) // has a psuedo-op turned off code generation? (LUP, IF, etc)

2
asm.h
View File

@ -473,6 +473,8 @@ public:
int substituteVariables(MerlinLine & line, std::string &outop);
bool codeSkipped(void);
bool doOFF(void);
int parseOperand(MerlinLine &line);
int getAddrMode(MerlinLine &line);

View File

@ -15,6 +15,7 @@ std::ostream& operator<<(std::ostream& os, const Token& token)
CLASS::CLASS(T65816Asm &_asm) : assembler(_asm)
{
allowMX = false;
}
CLASS::~CLASS()
@ -232,20 +233,30 @@ std::deque<Token> CLASS::shuntingYard(const std::deque<Token>& tokens)
}
else
{
sym = assembler.findSymbol(token.str);
//printf("symbol find |%s| %p\n",token.str.c_str(),sym);
if (sym != NULL)
std::string tok = Poco::toUpper(token.str);
if ((tok == "MX") && (allowMX))
{
sym->used = true;
sprintf(buff, "$%X", sym->value);
token.str = buff;
//printf("MX EVAL\n");
sprintf(buff,"$%02X",assembler.mx&0x03);
token.str=buff;;
}
else
{
setError(Token::unknownSymbolErr);
badsymbol = token.str;
token.str = "0";
sym = assembler.findSymbol(token.str);
//printf("symbol find |%s| %p\n",token.str.c_str(),sym);
if (sym != NULL)
{
sym->used = true;
sprintf(buff, "$%X", sym->value);
token.str = buff;
}
else
{
setError(Token::unknownSymbolErr);
badsymbol = token.str;
token.str = "0";
}
}
}
queue.push_back(token);

1
eval.h
View File

@ -68,6 +68,7 @@ protected:
public:
CLASS(T65816Asm &_asm);
~CLASS();
bool allowMX;
std::string badsymbol;
std::deque<Token> shuntingYard(const std::deque<Token>& tokens);
std::deque<Token> exprToTokens(const std::string& expr);

View File

@ -36,6 +36,7 @@ int CLASS::doDO(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
UNUSED(opinfo);
TEvaluator eval(a);
eval.allowMX=true; // allow the built in MX symbol
int64_t eval_value = 0;
uint8_t shift;