Lots of MACRO-10 improvements, DAKAM now assembles (but does not pass)

This commit is contained in:
Jeff 2017-04-03 16:10:08 -07:00 committed by Jeff Parsons
commit 09dc4dcb9a
13 changed files with 22047 additions and 1758 deletions

View file

@ -109,19 +109,6 @@ class Debugger extends Component
*/
this.nBits = 32;
/*
* sUndefined is set to the last unknown variable that parseExpression() encounters, if if
* is called in "quiet mode"; the value used for the variable is zero. This mode was added
* for components that need to support expressions containing "fixups" (ie, values that
* must be determined later).
*
* TODO: Only one unknown (fixup) per expression is supported, and we don't indicate what
* operation was performed with the value (callers generally assume addition). If a call
* encounters more than one undefined value, it will revert to normal error reporting and
* return an undefined value for the entire expression.
*/
this.sUndefined = null;
this.achGroup = ['{','}'];
this.achAddress = ['[',']'];
@ -594,6 +581,9 @@ class Debugger extends Component
case '||':
valNew = (val1 || val2? 1 : 0);
break;
case ',,':
valNew = this.truncate(val1, 18, true) * Math.pow(2, 18) + this.truncate(val2, 18, true);
break;
case '_':
case '^_':
valNew = val1;
@ -625,7 +615,7 @@ class Debugger extends Component
}
/**
* parseArray(asValues, iValue, iLimit, nBase, fQuiet)
* parseArray(asValues, iValue, iLimit, nBase, aUndefined)
*
* parseExpression() takes a complete expression and divides it into array elements, where even elements
* are values (which may be empty if two or more operators appear consecutively) and odd elements are operators.
@ -643,10 +633,10 @@ class Debugger extends Component
* @param {number} iValue
* @param {number} iLimit
* @param {number} nBase
* @param {boolean} [fQuiet]
* @param {Array|undefined} [aUndefined]
* @return {number|undefined}
*/
parseArray(asValues, iValue, iLimit, nBase, fQuiet)
parseArray(asValues, iValue, iLimit, nBase, aUndefined)
{
var value;
var sValue, sOp;
@ -663,7 +653,7 @@ class Debugger extends Component
sOp = (iValue < iLimit? asValues[iValue++] : "");
if (sValue) {
v = this.parseValue(sValue, null, fQuiet, nUnary);
v = this.parseValue(sValue, null, aUndefined, nUnary);
} else {
if (sOp == '{') {
var cOpen = 1;
@ -677,7 +667,7 @@ class Debugger extends Component
if (!--cOpen) break;
}
}
v = this.parseArray(asValues, iStart, iValue-1, this.nBase, fQuiet);
v = this.parseArray(asValues, iStart, iValue-1, this.nBase, aUndefined);
if (v != null && nUnary) {
v = this.parseUnary(v, nUnary);
}
@ -730,12 +720,12 @@ class Debugger extends Component
}
if (v === undefined) {
if (this.sUndefined == null && fQuiet) {
this.sUndefined = sValue;
if (aUndefined) {
aUndefined.push(sValue);
v = 0;
} else {
fError = true;
fQuiet = !fQuiet;
aUndefined = [];
break;
}
}
@ -786,7 +776,7 @@ class Debugger extends Component
if (!fError) {
value = aVals.pop();
this.assert(!aVals.length);
} else if (fQuiet === false) {
} else if (!aUndefined) {
this.println("parse error (" + (sValue || sOp) + ")");
}
@ -795,17 +785,16 @@ class Debugger extends Component
}
/**
* parseASCII(sExp, chDelim, nBits, cchMax, fQuiet)
* parseASCII(sExp, chDelim, nBits, cchMax)
*
* @this {Debugger}
* @param {string} sExp
* @param {string} chDelim
* @param {number} nBits
* @param {number} cchMax
* @param {boolean} [fQuiet] (true for quiet parsing)
* @return {string}
*/
parseASCII(sExp, chDelim, nBits, cchMax, fQuiet)
parseASCII(sExp, chDelim, nBits, cchMax)
{
var i;
while ((i = sExp.indexOf(chDelim)) >= 0) {
@ -829,7 +818,7 @@ class Debugger extends Component
v = this.truncate(v * Math.pow(2, nBits) + c, nBits * cchMax, true);
}
if (cch >= 0) {
if (fQuiet === false) this.println("parse error (" + sExp + ")");
this.println("parse error (" + chDelim + sExp + chDelim + ")");
break;
} else {
sExp = sExp.substr(0, i) + this.toStrBase(v, -1) + sExp.substr(j);
@ -858,15 +847,20 @@ class Debugger extends Component
* predecessor is encountered, evaluate, and push the result back onto aVals. Only selected unary
* operators are supported (eg, negate and complement); no ternary operators like '?:' are supported.
*
* fQuiet can be used to pass an array that collects any undefined variables that parseExpression()
* encounters; the value of an undefined variable is zero. This mode was added for components that need
* to support expressions containing "fixups" (ie, values that must be determined later).
*
* @this {Debugger}
* @param {string|undefined} sExp
* @param {boolean} [fQuiet] (true for quiet parsing)
* @param {Array|undefined|boolean} [fQuiet]
* @return {number|undefined} numeric value, or undefined if sExp contains any undefined or invalid values
*/
parseExpression(sExp, fQuiet)
{
var value = undefined;
this.sUndefined = null;
var fPrint = (fQuiet === false);
var aUndefined = Array.isArray(fQuiet)? fQuiet : undefined;
if (sExp) {
@ -888,9 +882,9 @@ class Debugger extends Component
* Quoted ASCII characters can have a numeric value, too, which must be converted now, to avoid any
* conflicts with the operators below.
*/
sExp = this.parseASCII(sExp, '"', 7, 5, fQuiet); // MACRO-10 packs up to 5 7-bit ASCII codes into a value
sExp = this.parseASCII(sExp, '"', 7, 5); // MACRO-10 packs up to 5 7-bit ASCII codes into a value
if (!sExp) return value;
sExp = this.parseASCII(sExp, "'", 6, 6, fQuiet); // MACRO-10 packs up to 6 6-bit ASCII (SIXBIT) codes into a value
sExp = this.parseASCII(sExp, "'", 6, 6); // MACRO-10 packs up to 6 6-bit ASCII (SIXBIT) codes into a value
if (!sExp) return value;
/*
@ -928,11 +922,11 @@ class Debugger extends Component
* to remove spaces entirely, because if an operator-less expression like "A B" was passed in, we would want
* that to generate an error; if we converted it to "AB", evaluation might inadvertently succeed.
*/
var regExp = /({|}|\|\||&&|\||\^!|\^B|\^O|\^D|\^L|\^-|~|\^_|_|&|!=|!|==|>=|>>>|>>|>|<=|<<|<|-|\+|\^\/|\/|\*| )/;
var regExp = /({|}|\|\||&&|\||\^!|\^B|\^O|\^D|\^L|\^-|~|\^_|_|&|!=|!|==|>=|>>>|>>|>|<=|<<|<|-|\+|\^\/|\/|\*|,,| )/;
sExp = sExp.replace(/(^|[^A-Z0-9$%.])([0-9]+)B/, "$1$2^_").replace(/\s+/g, ' ');
var asValues = sExp.split(regExp);
value = this.parseArray(asValues, 0, asValues.length, this.nBase, fQuiet);
if (value !== undefined && fQuiet === false) {
value = this.parseArray(asValues, 0, asValues.length, this.nBase, aUndefined);
if (value !== undefined && fPrint) {
this.printValue(null, value);
}
}
@ -1060,13 +1054,15 @@ class Debugger extends Component
* @this {Debugger}
* @param {string|undefined} sValue
* @param {string|null} [sName] is the name of the value, if any
* @param {boolean} [fQuiet]
* @param {Array|undefined|boolean} [fQuiet]
* @param {number} [nUnary] (0 for none, 1 for negate, 2 for complement, 3 for leading zeros)
* @return {number|undefined} numeric value, or undefined if sValue is either undefined or invalid
*/
parseValue(sValue, sName, fQuiet, nUnary = 0)
{
var value;
var aUndefined = Array.isArray(fQuiet)? fQuiet : undefined;
if (sValue != null) {
var iReg = this.getRegIndex(sValue);
if (iReg >= 0) {
@ -1076,13 +1072,10 @@ class Debugger extends Component
if (value != null) {
var sUndefined = this.getVariableFixup(sValue);
if (sUndefined) {
if (!this.sUndefined) {
this.sUndefined = sUndefined;
if (aUndefined) {
aUndefined.push(sUndefined);
} else {
if (!fQuiet) {
this.println(sValue + " has too many undefined values (" + sUndefined + ',' + this.sUndefined + ")");
fQuiet = true;
}
this.println(sValue + " is undefined (" + sUndefined + ")");
value = undefined;
}
}
@ -1169,13 +1162,17 @@ class Debugger extends Component
*/
printVariable(sVar)
{
if (sVar) {
return this.printValue(sVar, this.aVariables[sVar].value);
}
var cVariables = 0;
for (sVar in this.aVariables) {
this.printValue(sVar, this.aVariables[sVar].value);
cVariables++;
if (this.aVariables) {
if (sVar) {
return this.printValue(sVar, this.aVariables[sVar] && this.aVariables[sVar].value);
}
var aVars = Object.keys(this.aVariables);
aVars.sort();
for (var i = 0; i < aVars.length; i++) {
this.printValue(aVars[i], this.aVariables[aVars[i]].value);
cVariables++;
}
}
return cVariables > 0;
}
@ -1200,6 +1197,10 @@ class Debugger extends Component
*/
getVariable(sVar)
{
if (this.aVariables[sVar]) {
return this.aVariables[sVar].value;
}
sVar = sVar.substr(0, 6);
return this.aVariables[sVar] && this.aVariables[sVar].value;
}
@ -1233,7 +1234,7 @@ class Debugger extends Component
* @this {Debugger}
* @param {string} sVar
* @param {number} value
* @param {string|null} [sUndefined]
* @param {string|undefined} [sUndefined]
*/
setVariable(sVar, value, sUndefined)
{
@ -1317,6 +1318,7 @@ if (DEBUGGER) {
'}': 20 // close grouped expression (converted from achGroup[1])
};
Debugger.aDECOpPrecedence = {
',,': 1, // high-word,,low-word
'||': 5, // logical OR
'&&': 6, // logical AND
'!=': 10, // inequality