diff --git a/basic.js b/basic.js index 0debd3c..7f4c982 100644 --- a/basic.js +++ b/basic.js @@ -489,6 +489,15 @@ this.basic = (function() { }, 0xFC9C: function() { // Clear from cursor to right if (env.tty.clearEOL) { env.tty.clearEOL(); } + }, + 0xFD0C: function() { // Wait for key press + throw new BlockingInput(env.tty.readChar, function(_){}); + }, + 0xFE84: function() { // Normal + if (env.tty.setTextStyle) { env.tty.setTextStyle(env.tty.TEXT_STYLE_NORMAL); } + }, + 0xFE80: function() { // Inverse + if (env.tty.setTextStyle) { env.tty.setTextStyle(env.tty.TEXT_STYLE_INVERSE); } } }; @@ -731,20 +740,15 @@ this.basic = (function() { }, 'get': function GET(lvalue) { - var im = env.tty.readChar, - ih = function(entry) { - lvalue(entry); - }; - throw new BlockingInput(im, ih); + throw new BlockingInput(env.tty.readChar, function(entry) { lvalue(entry); }); }, 'input': function INPUT(prompt /* , ...varlist */) { var varlist = Array.prototype.slice.call(arguments, 1); // copy for closure - var im, ih; - im = function(cb) { return env.tty.readLine(cb, prompt); }; - ih = function(entry) { + var im = function(cb) { return env.tty.readLine(cb, prompt); }; + var ih = function(entry) { var parts = [], - stream = new Stream(entry); + stream = new Stream(entry); parseDataInput(stream, parts); @@ -753,7 +757,7 @@ this.basic = (function() { varlist.shift()(parts.shift()); } catch (e) { if (e instanceof basic.RuntimeError && - e.code === ERRORS.TYPE_MISMATCH[0]) { + e.code === ERRORS.TYPE_MISMATCH[0]) { e.code = ERRORS.REENTER[0]; e.message = ERRORS.REENTER[1]; } @@ -964,7 +968,7 @@ this.basic = (function() { if (!hires) { runtime_error('Hires graphics not supported'); } var coords = Array.prototype.slice.call(arguments), - size = hires.getScreenSize(), x, y; + size = hires.getScreenSize(), x, y; while (coords.length) { x = coords.shift() >> 0; @@ -1181,8 +1185,8 @@ this.basic = (function() { ////////////////////////////////////////////////////////////////////// var match, test, endOfStatement, endOfProgram, - currLine = 0, currColumn = 0, - currLineNumber = 0; + currLine = 0, currColumn = 0, + currLineNumber = 0; function parse_error(msg) { return new basic.ParseError(msg + " in line " + currLineNumber, @@ -1253,7 +1257,7 @@ this.basic = (function() { // data - DATA blah,"blah",blah var start = true, - stream = new Stream(source); + stream = new Stream(source); function nextToken() { var token = {}, newline = start, ws; @@ -1375,25 +1379,9 @@ this.basic = (function() { ////////////////////////////////////////////////////////////////////// function quote(string) { - // From json2.js (http://www.json.org/js.html) - var escapable = /[\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, - meta = { // table of character substitutions - '\b': '\\b', - '\t': '\\t', - '\n': '\\n', - '\f': '\\f', - '\r': '\\r', - '"': '\\"', - '\\': '\\\\' - }; - - return '"' + string.replace(escapable, function(a) { - var c = meta[a]; - return c ? c : '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); - }) + '"'; + return JSON.stringify(string); } - ////////////////////////////////////////////////////////////////////// // // Recursive Descent Parser @@ -1453,7 +1441,7 @@ this.basic = (function() { function parsePValue() { var name = match('identifier'), - subscripts = parseSubscripts(); + subscripts = parseSubscripts(); if (subscripts) { identifiers.arrays[name] = true; @@ -1476,8 +1464,8 @@ this.basic = (function() { function parseUserfunction() { var name = match('identifier'), - type = vartype(name) === 'string' ? 'string' : 'number', - expr; + type = vartype(name) === 'string' ? 'string' : 'number', + expr; // FUTURE: Allow differing argument type and return type // (may require runtime type checks) @@ -1499,10 +1487,10 @@ this.basic = (function() { match("operator", "("); var func = funlib[name], - funcdesc = func.signature.slice(), - rtype = funcdesc.shift(), - args = [], - atype; + funcdesc = func.signature.slice(), + rtype = funcdesc.shift(), + args = [], + atype; while (funcdesc.length) { atype = funcdesc.shift(); @@ -1543,8 +1531,8 @@ this.basic = (function() { return parsefunction(match('reserved')); } else if (test('identifier')) { var name = match('identifier'), - type = vartype(name) === 'string' ? 'string' : 'number', - subscripts = parseSubscripts(); + type = vartype(name) === 'string' ? 'string' : 'number', + subscripts = parseSubscripts(); if (subscripts) { identifiers.arrays[name] = true; return { source: 'state.arrays[' + quote(name) + '].get([' + subscripts + '])', type: type }; @@ -1709,7 +1697,7 @@ this.basic = (function() { } var keyword = test('identifier') ? kws.LET : match('reserved'), - name, type, subscripts, is_to, expr, param, args, prompt, trailing, js; + name, type, subscripts, is_to, expr, param, args, prompt, trailing, js; switch (keyword) { ////////////////////////////////////////////////////////////////////// diff --git a/index.html b/index.html index c4bb736..596d246 100644 --- a/index.html +++ b/index.html @@ -149,9 +149,9 @@ By Joshua Bell
  • 6502asm.com - a 6502 assembler/emulator in JavaScript
  • Quite BASIC - a similar project aimed at teaching programming -
  • NG-BASIC for Javascript Navaho Gunleg's interpreter +
    diff --git a/reference.html b/reference.html index 28c996b..5695d0a 100644 --- a/reference.html +++ b/reference.html @@ -38,7 +38,7 @@ This is intended as a quick reference for the Applesoft BASIC in Ja
  • Apple II Programmer's Reference: Applesoft Commands
  • Applesoft BASIC Frequently Asked Questions (FAQ)
  • Beagle Bros. Peeks, Pokes & Pointers Chart (Colors, ASCII values, etc) -
  • More Beagle Bros. Posters - including Apple Commands Chart, in PDF format +
  • More Beagle Bros. Posters — including Apple Commands Chart, in PDF format
  • Applesoft Basic Programming Reference Manual @@ -186,48 +186,51 @@ can be literals (unquoted strings), strings, or numbers

    Compatibility Shims

    -
    SPEED= aexpr
    Set character output delay - has no effect +
    SPEED= aexpr
    Set character output delay — has no effect
    POKE aexpr, aexpr
    Set memory location to value
      -
    • POKE 32,n - Text window left edge -
    • POKE 33,n - Text window width -
    • POKE 34,n - Text window top edge -
    • POKE 35,n - Text window bottom -
    • POKE 36,n - Text cursor x -
    • POKE 37,n - Text cursor y -
    • POKE 216,n - ONERR flag (n < 128 disables ONERR handler) -
    • POKE 230,n - Hi-Res plotting page (32 = page 1, 64 = page 2) -
    • POKE 49168,0 - clear keyboard strobe -
    • POKE 49200,0 - toggle speaker (no-op) -
    • POKE 49232,0 - graphics mode -
    • POKE 49233,0 - text mode -
    • POKE 49234,0 - full graphics mode -
    • POKE 49235,0 - mixed text/graphics mode -
    • POKE 49236,0 - display page 1 -
    • POKE 49237,0 - display page 2 -
    • POKE 49238,0 - lores graphics mode -
    • POKE 49239,0 - hires graphics mode +
    • POKE 32,n — Text window left edge +
    • POKE 33,n — Text window width +
    • POKE 34,n — Text window top edge +
    • POKE 35,n — Text window bottom +
    • POKE 36,n — Text cursor x +
    • POKE 37,n — Text cursor y +
    • POKE 216,n — ONERR flag (n < 128 disables ONERR handler) +
    • POKE 230,n — Hi-Res plotting page (32 = page 1, 64 = page 2) +
    • POKE 49168,0 — clear keyboard strobe +
    • POKE 49200,0 — toggle speaker (no-op) +
    • POKE 49232,0 — graphics mode +
    • POKE 49233,0 — text mode +
    • POKE 49234,0 — full graphics mode +
    • POKE 49235,0 — mixed text/graphics mode +
    • POKE 49236,0 — display page 1 +
    • POKE 49237,0 — display page 2 +
    • POKE 49238,0 — lores graphics mode +
    • POKE 49239,0 — hires graphics mode
    CALL aexpr
    Call native routine
      -
    • CALL -3288 - pop ONERR/RESUME entry from stack -
    • CALL -3100 - reveal hi-res page 1 -
    • CALL -3086 - clear current hi-res page to black -
    • CALL -3082 - clear current hi-res page to current color -
    • CALL 54951 - clear stack (pop all FOR/NEXT, GOSUB/RETURN, and ONERR/RESUME entries) -
    • CALL -1036 - move cursor right -
    • CALL -1008 - move cursor left -
    • CALL -998 - move cursor up -
    • CALL -958 - clear text from cursor to bottom of window -
    • CALL -922 - move cursor down -
    • CALL -868 - clear text from cursor to end of line +
    • CALL 54915 or CALL -10621 — clear stack (pop all FOR/NEXT, GOSUB/RETURN, and ONERR/RESUME entries) +
    • CALL 62248 or CALL -3288 — pop ONERR/RESUME entry from stack +
    • CALL 62436 or CALL -3100 — reveal hi-res page 1 +
    • CALL 62450 or CALL -3086 — clear current hi-res page to black +
    • CALL 62454 or CALL -3082 — clear current hi-res page to current color +
    • CALL 64500 or CALL -1036 — move cursor right +
    • CALL 64528 or CALL -1008 — move cursor left +
    • CALL 64538 or CALL -998 — move cursor up +
    • CALL 64578 or CALL -958 — clear text from cursor to bottom of window +
    • CALL 64614 or CALL -922 — move cursor down +
    • CALL 64668 or CALL -868 — clear text from cursor to end of line +
    • CALL 64780 or CALL -756 — wait for keypress +
    • CALL 65152 or CALL -384 — set inverse text mode +
    • CALL 65156 or CALL -380 — set normal text mode
    PR# aexpr
    Direct output to slot
      -
    • PR#0 - set 40 column mode -
    • PR#3 - set 80 column mode +
    • PR#0 — set 40 column mode +
    • PR#3 — set 80 column mode
    @@ -287,22 +290,22 @@ can be literals (unquoted strings), strings, or numbers
    PEEK( aexpr )
    Value at memory location
      -
    • PEEK(32) - Text window left edge -
    • PEEK(33) - Text window width -
    • PEEK(34) - Text window top edge -
    • PEEK(35) - Text window bottom -
    • PEEK(36) - Text cursor x -
    • PEEK(37) - Text cursor y -
    • PEEK(78) & PEEK(79) - Random-Number Field -
    • PEEK(222) - Last error code -
    • PEEK(230) - Hi-Res plotting page (32 = page 1, 64 = page 2) -
    • PEEK(49152) - Read Keyboard -
    • PEEK(49168) - Clear Keyboard strobe -
    • PEEK(49200) - Click Speaker (no-op) -
    • PEEK(49248) - Read Paddle Button #3 - Use the PageDown key -
    • PEEK(49249) - Read Paddle Button #0 - Use the Home key -
    • PEEK(49250) - Read Paddle Button #1 - Use the End key -
    • PEEK(49251) - Read Paddle Button #2 - Use the PageUp or Shift key +
    • PEEK(32) — Text window left edge +
    • PEEK(33) — Text window width +
    • PEEK(34) — Text window top edge +
    • PEEK(35) — Text window bottom +
    • PEEK(36) — Text cursor x +
    • PEEK(37) — Text cursor y +
    • PEEK(78) & PEEK(79) — Random-Number Field +
    • PEEK(222) — Last error code +
    • PEEK(230) — Hi-Res plotting page (32 = page 1, 64 = page 2) +
    • PEEK(49152) — Read Keyboard +
    • PEEK(49168) — Clear Keyboard strobe +
    • PEEK(49200) — Click Speaker (no-op) +
    • PEEK(49248) — Read Paddle Button #3 — Use the PageDown key +
    • PEEK(49249) — Read Paddle Button #0 — Use the Home key +
    • PEEK(49250) — Read Paddle Button #1 — Use the End key +
    • PEEK(49251) — Read Paddle Button #2 — Use the PageUp or Shift key
    @@ -350,19 +353,19 @@ can be literals (unquoted strings), strings, or numbers
    0
    Next without for -
    16
    Syntax error - Not generated +
    16
    Syntax error — Not generated
    22
    Return without gosub
    42
    Out of data
    53
    Illegal quantity
    69
    Overflow -
    77
    Out of memory - Not generated by all browsers +
    77
    Out of memory — Not generated by all browsers
    90
    Undefined statement
    107
    Bad subscript
    120
    Redimensioned array
    133
    Division by zero
    163
    Type mismatch -
    176
    String too long - Not generated -
    191
    Formula too complex - Not generated by all browsers +
    176
    String too long — Not generated +
    191
    Formula too complex — Not generated by all browsers
    224
    Undefined function
    254
    Re-enter
    255
    Break @@ -404,20 +407,20 @@ can be literals (unquoted strings), strings, or numbers PEEK(222) in an ONERR handler.

    -
    1
    Language not available - Not generated -
    2
    Range error - Not generated -
    4
    Write protected - Not generated +
    1
    Language not available — Not generated +
    2
    Range error — Not generated +
    4
    Write protected — Not generated
    5
    End of data
    6
    File not found -
    7
    Volume mismatch - Not generated -
    8
    I/O error - Not generated -
    9
    Disk full - Not generated -
    10
    File locked - Not generated +
    7
    Volume mismatch — Not generated +
    8
    I/O error — Not generated +
    9
    Disk full — Not generated +
    10
    File locked — Not generated
    11
    Invalid option -
    12
    No buffers available - Not generated -
    13
    File type mismatch - Not generated -
    14
    Program too large - Not generated -
    15
    Not direct command - Not generated +
    12
    No buffers available — Not generated +
    13
    File type mismatch — Not generated +
    14
    Program too large — Not generated +
    15
    Not direct command — Not generated
    @@ -528,7 +531,7 @@ object representing the program.

    separator, remark, data-declaration - - take a peek at the code if you want the gruesome details. Source lines may + — take a peek at the code if you want the gruesome details. Source lines may only start with line numbers or (as an extension) separators. Special statement parsing is done while lexing: REM consumes anything to the next line break, and DATA statements yield an array of strings @@ -588,7 +591,7 @@ function which implements the logic for walking over the array.

  • DEF FN supports string and integer functions e.g. DEF FN IN$(X$) = " " + X$ - - the return type must match the argument type, so string-to-number or number-to-string functions + — the return type must match the argument type, so string-to-number or number-to-string functions can not be implemented.
  • "Double equals" == is supported for equality comparisons, with the same meaning as "single equals" = diff --git a/styles.css b/styles.css index 14c48f0..6faf77d 100644 --- a/styles.css +++ b/styles.css @@ -9,14 +9,13 @@ h1, h2, h3, p, ul { margin-bottom: 0; margin-top: 0; } /* "Paper" (for copying output) */ #paper { - display: none; margin: 0; position: fixed; z-index: 100; left: 0; right: 0; bottom: 0; - top: 560px; + height: 0; overflow-x: hidden; overflow-y: scroll; font-family: Courier, Monospace; @@ -28,10 +27,10 @@ h1, h2, h3, p, ul { margin-bottom: 0; margin-top: 0; } padding-left: 50px; white-space: pre; box-shadow: inset 0 5px 10px black; + transition: height 0.5s ease; } -body.printout #paper { display: block; } -#show_paper { display: inline-block; } -#hide_paper { display: none; } +body.printout #paper, #paper-spacer { height: 200px; } + +body:not(.printout) #hide_paper { display: none; } body.printout #show_paper { display: none; } -body.printout #hide_paper { display: inline-block; }