Added the ^L MACRO-10 unary zero-bit-counting operator, and updated the last blog post with expression parser differences (eg, interpretation of numbers with a decimal point)
This commit is contained in:
parent
3ae81730d8
commit
6ad35d2d17
2 changed files with 24 additions and 6 deletions
|
|
@ -183,17 +183,24 @@ Use double-quotes for ASCII constants and single-quotes for SIXBIT constants:
|
||||||
NOTE: When using the PCjs debugger, the constant must be preceded by an arithmetic operator (eg, '+'), otherwise it interprets
|
NOTE: When using the PCjs debugger, the constant must be preceded by an arithmetic operator (eg, '+'), otherwise it interprets
|
||||||
the quoted argument as a string. This is an idiosyncrasy of the "print" command, not the expression parser.
|
the quoted argument as a string. This is an idiosyncrasy of the "print" command, not the expression parser.
|
||||||
|
|
||||||
All MACRO-10 logical and arithmetic operators are supported, including:
|
Most MACRO-10 logical and arithmetic operators are supported, including:
|
||||||
|
|
||||||
- Unary arithmetic operators (+ and -)
|
- Unary arithmetic operators (+ and -)
|
||||||
- Unary complement operator (^-, aliased to ~)
|
- Unary complement operator (^-, aliased to ~)
|
||||||
- Unary base overrides (^D, ^O, and ^B)
|
- Unary base overrides (^D, ^O, and ^B)
|
||||||
|
- Unary zero-bit-count operator (^L)
|
||||||
- Binary shifting (B) and underscore shifting (_) operators
|
- Binary shifting (B) and underscore shifting (_) operators
|
||||||
- Logical binary operations (! for OR, ^! for XOR, and & for AND)
|
- Logical binary operations (! for OR, ^! for XOR, and & for AND)
|
||||||
- Multiplication and division (* and /)
|
- Multiplication and division (* and /)
|
||||||
- Addition and subtraction (+ and -)
|
- Addition and subtraction (+ and -)
|
||||||
- Angle brackets for expression grouping (< and >)
|
- Angle brackets for expression grouping (< and >)
|
||||||
|
|
||||||
|
Unfortunately, since the PCjs expression parser predates MACRO-10 support, there are bound to be differences that I
|
||||||
|
haven't ironed out yet. One known difference involves numeric constants with a trailing period (decimal point): PCjs
|
||||||
|
historically treats such constants as decimal *integers*, whereas MACRO-10 treats numeric constants with either a
|
||||||
|
leading, embedded, or trailing period as a decimal *floating-point* number. I've chosen to ignore this difference for
|
||||||
|
now, since I'm holding off on all floating-point support for as long as possible.
|
||||||
|
|
||||||
Much more work is needed to make the MACRO-10 "Mini-Assembler" a general-purpose assembler, but it's already proved itself
|
Much more work is needed to make the MACRO-10 "Mini-Assembler" a general-purpose assembler, but it's already proved itself
|
||||||
useful in assembling the following tests:
|
useful in assembling the following tests:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -684,6 +684,10 @@ class Debugger extends Component
|
||||||
nUnary = (nUnary << 2) | 2;
|
nUnary = (nUnary << 2) | 2;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (sOp == '^L') {
|
||||||
|
nUnary = (nUnary << 2) | 3;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
fError = true;
|
fError = true;
|
||||||
break;
|
break;
|
||||||
|
|
@ -861,7 +865,7 @@ class Debugger extends Component
|
||||||
*
|
*
|
||||||
* WARNING: Whenever you make changes to this RegExp, make sure you update aBinOpPrecedence as needed, too.
|
* WARNING: Whenever you make changes to this RegExp, make sure you update aBinOpPrecedence as needed, too.
|
||||||
*/
|
*/
|
||||||
var regExp = /(\{|}|\|\||&&|\||\^!|\^B|\^O|\^D|\^-|~|\^_|_|&|!=|!|==|>=|>>>|>>|>|<=|<<|<|-|\+|%|\/|\*)/;
|
var regExp = /(\{|}|\|\||&&|\||\^!|\^B|\^O|\^D|\^L|\^-|~|\^_|_|&|!=|!|==|>=|>>>|>>|>|<=|<<|<|-|\+|%|\/|\*)/;
|
||||||
sExp = sExp.replace(/(^|[^A-Z0-9$%.])([0-9]+)B/, "$1$2^_");
|
sExp = sExp.replace(/(^|[^A-Z0-9$%.])([0-9]+)B/, "$1$2^_");
|
||||||
var asValues = sExp.split(regExp);
|
var asValues = sExp.split(regExp);
|
||||||
value = this.parseArray(asValues, 0, asValues.length, this.nBase, fQuiet);
|
value = this.parseArray(asValues, 0, asValues.length, this.nBase, fQuiet);
|
||||||
|
|
@ -965,7 +969,7 @@ class Debugger extends Component
|
||||||
* @param {string|undefined} sValue
|
* @param {string|undefined} sValue
|
||||||
* @param {string|null} [sName] is the name of the value, if any
|
* @param {string|null} [sName] is the name of the value, if any
|
||||||
* @param {boolean} [fQuiet]
|
* @param {boolean} [fQuiet]
|
||||||
* @param {number} [nUnary] (0 for none, 1 for negate, 2 for complement)
|
* @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
|
* @return {number|undefined} numeric value, or undefined if sValue is either undefined or invalid
|
||||||
*/
|
*/
|
||||||
parseValue(sValue, sName, fQuiet, nUnary = 0)
|
parseValue(sValue, sName, fQuiet, nUnary = 0)
|
||||||
|
|
@ -986,11 +990,18 @@ class Debugger extends Component
|
||||||
}
|
}
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
while (nUnary) {
|
while (nUnary) {
|
||||||
if (nUnary & 1) {
|
switch(nUnary & 0o3) {
|
||||||
|
case 1:
|
||||||
value = -this.truncate(value);
|
value = -this.truncate(value);
|
||||||
}
|
break;
|
||||||
else if (nUnary & 2) {
|
case 2:
|
||||||
value = this.evalXOR(value, -1); // this is easier than adding an evalNOT()...
|
value = this.evalXOR(value, -1); // this is easier than adding an evalNOT()...
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
var bit = 35; // simple left-to-right zero-bit-counting loop...
|
||||||
|
while (bit >= 0 && !this.evalAND(value, Math.pow(2, bit))) bit--;
|
||||||
|
value = 35 - bit;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
nUnary >>>= 2;
|
nUnary >>>= 2;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue