diff --git a/_posts/2017-03-21-the-macro-10-assembler-50-years-later.md b/_posts/2017-03-21-the-macro-10-assembler-50-years-later.md index c7662cd5a..fcc2cd23c 100644 --- a/_posts/2017-03-21-the-macro-10-assembler-50-years-later.md +++ b/_posts/2017-03-21-the-macro-10-assembler-50-years-later.md @@ -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 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 complement operator (^-, aliased to ~) - Unary base overrides (^D, ^O, and ^B) +- Unary zero-bit-count operator (^L) - Binary shifting (B) and underscore shifting (_) operators - Logical binary operations (! for OR, ^! for XOR, and & for AND) - Multiplication and division (* and /) - Addition and subtraction (+ 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 useful in assembling the following tests: diff --git a/modules/shared/lib/debugger.js b/modules/shared/lib/debugger.js index 446128d73..ee90393c1 100644 --- a/modules/shared/lib/debugger.js +++ b/modules/shared/lib/debugger.js @@ -684,6 +684,10 @@ class Debugger extends Component nUnary = (nUnary << 2) | 2; continue; } + if (sOp == '^L') { + nUnary = (nUnary << 2) | 3; + continue; + } } fError = true; 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. */ - var regExp = /(\{|}|\|\||&&|\||\^!|\^B|\^O|\^D|\^-|~|\^_|_|&|!=|!|==|>=|>>>|>>|>|<=|<<|<|-|\+|%|\/|\*)/; + var regExp = /(\{|}|\|\||&&|\||\^!|\^B|\^O|\^D|\^L|\^-|~|\^_|_|&|!=|!|==|>=|>>>|>>|>|<=|<<|<|-|\+|%|\/|\*)/; sExp = sExp.replace(/(^|[^A-Z0-9$%.])([0-9]+)B/, "$1$2^_"); var asValues = sExp.split(regExp); value = this.parseArray(asValues, 0, asValues.length, this.nBase, fQuiet); @@ -965,7 +969,7 @@ class Debugger extends Component * @param {string|undefined} sValue * @param {string|null} [sName] is the name of the value, if any * @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 */ parseValue(sValue, sName, fQuiet, nUnary = 0) @@ -986,11 +990,18 @@ class Debugger extends Component } if (value != null) { while (nUnary) { - if (nUnary & 1) { + switch(nUnary & 0o3) { + case 1: value = -this.truncate(value); - } - else if (nUnary & 2) { + break; + case 2: 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; }