mirror of
https://github.com/sehugg/8bitworkshop.git
synced 2024-12-21 21:29:17 +00:00
basic: testInitialFor, staticArrays, token crunching, bell, more OPTIONs (17, 54, 68)
This commit is contained in:
parent
ac4b6a86ce
commit
e962404c2f
3
Makefile
3
Makefile
@ -32,6 +32,9 @@ dist:
|
|||||||
|
|
||||||
package: dist darwin.dist win32.dist linux.dist
|
package: dist darwin.dist win32.dist linux.dist
|
||||||
|
|
||||||
|
meta/electron.diff: index.html electron.html
|
||||||
|
-diff -u index.html electron.html > $@
|
||||||
|
|
||||||
web:
|
web:
|
||||||
(ip addr || ifconfig) | grep inet
|
(ip addr || ifconfig) | grep inet
|
||||||
python3 scripts/serveit.py 2>> /dev/null #http.out
|
python3 scripts/serveit.py 2>> /dev/null #http.out
|
||||||
|
257
electron.diff
Normal file
257
electron.diff
Normal file
@ -0,0 +1,257 @@
|
|||||||
|
--- index.html 2020-08-11 11:10:30.000000000 -0500
|
||||||
|
+++ electron.html 2020-08-11 14:45:27.000000000 -0500
|
||||||
|
@@ -3,16 +3,6 @@
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<title>8bitworkshop IDE</title>
|
||||||
|
-<link rel="manifest" href="manifest.json">
|
||||||
|
-<meta name="googlebot" content="nosnippet" />
|
||||||
|
-<meta name="mobile-web-app-capable" content="yes">
|
||||||
|
-<meta name="apple-mobile-web-app-capable" content="yes">
|
||||||
|
-<meta name="application-name" content="8bitworkshop">
|
||||||
|
-<meta name="apple-mobile-web-app-title" content="8bitworkshop">
|
||||||
|
-<meta name="theme-color" content="#ffffff">
|
||||||
|
-<meta name="msapplication-navbutton-color" content="#ffffff">
|
||||||
|
-<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
|
||||||
|
-<meta name="msapplication-starturl" content="/redir.html">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=yes">
|
||||||
|
<style type="text/css" media="screen">
|
||||||
|
body {
|
||||||
|
@@ -21,46 +11,6 @@
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<link rel="stylesheet" href="css/ui.css">
|
||||||
|
-
|
||||||
|
-<!-- google analytics -->
|
||||||
|
-<script>
|
||||||
|
-window.ga=window.ga||function(){(ga.q=ga.q||[]).push(arguments)};ga.l=+new Date;
|
||||||
|
-if (window.location.host.endsWith('8bitworkshop.com')) {
|
||||||
|
- ga('create', 'UA-54497476-9', 'auto');
|
||||||
|
- ga('set', 'anonymizeIp', true);
|
||||||
|
-}
|
||||||
|
-</script>
|
||||||
|
-<script async src='https://www.google-analytics.com/analytics.js'></script>
|
||||||
|
-
|
||||||
|
-<!-- firebase libs -->
|
||||||
|
-<script defer src="https://www.gstatic.com/firebasejs/5.11.1/firebase-app.js"></script>
|
||||||
|
-<script defer src="https://www.gstatic.com/firebasejs/5.11.1/firebase-auth.js"></script>
|
||||||
|
-<script defer src="config.js"></script>
|
||||||
|
-
|
||||||
|
-<!-- Sentry error reporting -->
|
||||||
|
-<script
|
||||||
|
- src="https://browser.sentry-cdn.com/5.20.1/bundle.min.js"
|
||||||
|
- integrity="sha384-O8HdAJg1h8RARFowXd2J/r5fIWuinSBtjhwQoPesfVILeXzGpJxvyY/77OaPPXUo"
|
||||||
|
- crossorigin="anonymous"></script>
|
||||||
|
-<script>
|
||||||
|
-if (window.location.host.endsWith('8bitworkshop.com')) {
|
||||||
|
- Sentry.init({
|
||||||
|
- dsn: 'https://bf329df3d1b34afa9f5b5e8ecd80ad11@sentry.io/1813925',
|
||||||
|
- beforeBreadcrumb(breadcrumb, hint) {
|
||||||
|
- if (breadcrumb.category === 'xhr' && typeof breadcrumb.data.url === 'string') {
|
||||||
|
- if (breadcrumb.data.url.startsWith('http')) return null; // discard external scripts
|
||||||
|
- }
|
||||||
|
- return breadcrumb;
|
||||||
|
- },
|
||||||
|
- beforeSend(event, hint) {
|
||||||
|
- const error = hint.originalException;
|
||||||
|
- if (error instanceof EmuHalt) return null; // ignore EmuHalt
|
||||||
|
- return event;
|
||||||
|
- },
|
||||||
|
- });
|
||||||
|
-}
|
||||||
|
-</script>
|
||||||
|
-
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
@@ -88,26 +38,6 @@
|
||||||
|
<hr>
|
||||||
|
<li><a class="dropdown-item" href="#" id="item_addfile_include">Add Include File...</a></li>
|
||||||
|
<li><a class="dropdown-item" href="#" id="item_addfile_link">Add Linked File...</a></li>
|
||||||
|
- <hr>
|
||||||
|
- <!--
|
||||||
|
- <li><a class="dropdown-item" href="#" id="item_switch_https" style="display:none">Switch to HTTPS...</a></li>
|
||||||
|
- -->
|
||||||
|
- <li><a class="dropdown-item" href="#" id="item_request_persist">Request Local Storage Permissions</a></li>
|
||||||
|
- </ul>
|
||||||
|
- </li>
|
||||||
|
- <li class="dropdown dropdown-submenu">
|
||||||
|
- <a tabindex="-1" href="#">Sync</a>
|
||||||
|
- <ul class="dropdown-menu">
|
||||||
|
- <li><a class="dropdown-item" href="#" id="item_github_login">Sign in to Github...</a></li>
|
||||||
|
- <li><a class="dropdown-item" href="#" id="item_github_logout">Log out</a></li>
|
||||||
|
- <hr>
|
||||||
|
- <li><a class="dropdown-item" href="#" id="item_github_import">Import Project from GitHub...</a></li>
|
||||||
|
- <li><a class="dropdown-item" href="#" id="item_github_pull">Pull Latest from Repository</a></li>
|
||||||
|
- <hr>
|
||||||
|
- <li><a class="dropdown-item" href="#" id="item_github_publish">Publish Project on GitHub...</a></li>
|
||||||
|
- <li><a class="dropdown-item" href="#" id="item_github_push">Push Changes to Repository...</a></li>
|
||||||
|
- <hr>
|
||||||
|
- <li><a class="dropdown-item" href="#" id="item_repo_delete">Delete Local Repository...</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li class="dropdown dropdown-submenu">
|
||||||
|
@@ -133,36 +63,6 @@
|
||||||
|
<li><a class="dropdown-item" href="#" id="item_debug_expr">Break Expression...</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
- <li class="dropdown dropdown-submenu">
|
||||||
|
- <a tabindex="-1" href="#">Tools</a>
|
||||||
|
- <ul class="dropdown-menu">
|
||||||
|
- <li><a class="dropdown-item" target="_8bws_tools" href="https://8bitworkshop.com/dithertron/">Dithertron Image Converter</a></li>
|
||||||
|
- <li><a class="dropdown-item" target="_8bws_tools" href="https://8bitworkshop.com/bitmapfontgenerator/">Bitmap Font Generator</a></li>
|
||||||
|
- <li><a class="dropdown-item" target="_8bws_tools" href="http://tomeko.net/online_tools/file_to_hex.php?lang=en">Binary File to Hex Converter</a></li>
|
||||||
|
- <li class="dropdown dropdown-submenu">
|
||||||
|
- <a tabindex="-1" href="#">Atari 2600</a>
|
||||||
|
- <ul class="dropdown-menu">
|
||||||
|
- <li><a class="dropdown-item" target="_8bws_tools" href="https://alienbill.com/2600/playerpalnext.html">playerpal 2600</a></li>
|
||||||
|
- <li><a class="dropdown-item" target="_8bws_tools" href="https://alienbill.com/2600/playfieldpal.html">playfieldpal 2600</a></li>
|
||||||
|
- </ul>
|
||||||
|
- </li>
|
||||||
|
- </ul>
|
||||||
|
- </li>
|
||||||
|
- <hr>
|
||||||
|
- <li class="dropdown dropdown-submenu">
|
||||||
|
- <a tabindex="-1" href="#">About</a>
|
||||||
|
- <ul class="dropdown-menu">
|
||||||
|
- <li><a class="dropdown-item" target="_8bws_about" href="https://8bitworkshop.com/blog">Latest News</a></li>
|
||||||
|
- <li><a class="dropdown-item" target="_8bws_about" href="https://8bitworkshop.com/projects">Projects</a></li>
|
||||||
|
- <li><a class="dropdown-item" target="_8bws_about" href="https://twitter.com/8bitworkshop">Twitter</a></li>
|
||||||
|
- <li><a class="dropdown-item" target="_8bws_about" href="https://github.com/sehugg/8bitworkshop">GitHub</a></li>
|
||||||
|
- <li><a class="dropdown-item" target="_8bws_about" href="https://github.com/sehugg/8bitworkshop/issues/new">Report an Issue</a></li>
|
||||||
|
- <li><a class="dropdown-item" target="_8bws_about" href="https://8bitworkshop.com/blog/docs/ide.md.html">IDE Help</a></li>
|
||||||
|
- </ul>
|
||||||
|
- </li>
|
||||||
|
- <!--
|
||||||
|
- <hr><li><a class="dropdown-item" href="/redir.html">Use Latest Version</a></li>
|
||||||
|
- -->
|
||||||
|
</ul>
|
||||||
|
</span>
|
||||||
|
|
||||||
|
@@ -258,39 +158,6 @@
|
||||||
|
<span class="label"><span id="settle_label"></span> evals/clk</span>
|
||||||
|
</span>
|
||||||
|
|
||||||
|
- <!-- BOOKS menu -->
|
||||||
|
- <span class="dropdown pull-right">
|
||||||
|
- <a class="btn dropdown-toggle hidden-xs toolbarMenuButton" id="booksMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||||
|
- <span class="glyphicon glyphicon-book" aria-hidden="true"></span>
|
||||||
|
- Get Books <span class="caret"></span>
|
||||||
|
- </a>
|
||||||
|
- <ul class="dropdown-menu dropdown-menu-right" aria-labelledby="booksMenuButton">
|
||||||
|
- <li>
|
||||||
|
- <a class="dropdown-item dropdown-link book-vcs" target="_book_a2600" href="https://www.amazon.com/gp/product/1541021304/ref=as_li_qf_sp_asin_il_tl?ie=UTF8&tag=pzp-20&camp=1789&creative=9325&linkCode=as2&creativeASIN=B01N4DSRIZ&linkId=04d39e274c06e6c93b93d20a9a977111">
|
||||||
|
- <img src="images/book_a2600.png"/>
|
||||||
|
- <span class="book-title">Making Games For The Atari 2600</span>
|
||||||
|
- </a>
|
||||||
|
- </li>
|
||||||
|
- <li>
|
||||||
|
- <a class="dropdown-item dropdown-link book-arcade" target="_book_arcade" href="https://www.amazon.com/gp/product/1545484759/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1545484759&linkCode=as2&tag=pzp-20&linkId=b27709c022d2ebe639e90316d9f4fd5b">
|
||||||
|
- <img src="images/book_arcade.png"/>
|
||||||
|
- <span class="book-title">Making 8-bit Arcade Games in C</span>
|
||||||
|
- </a>
|
||||||
|
- </li>
|
||||||
|
- <li>
|
||||||
|
- <a class="dropdown-item dropdown-link book-verilog" target="_book_verilog" href="https://www.amazon.com/gp/product/1728619440/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1728619440&linkCode=as2&tag=pzp-20&linkId=7237a25861cb6b49a4128ba53d84c3e2">
|
||||||
|
- <img src="images/book_verilog.png"/>
|
||||||
|
- <span class="book-title">Designing Video Game Hardware in Verilog</span>
|
||||||
|
- </a>
|
||||||
|
- </li>
|
||||||
|
- <li>
|
||||||
|
- <a class="dropdown-item dropdown-link book-nes" target="_book_nes" href="https://www.amazon.com/gp/product/1075952727/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1075952727&linkCode=as2&tag=pzp-20&linkId=633176e8b36fea7f927020e2c322d80a">
|
||||||
|
- <img src="images/book_nes.png"/>
|
||||||
|
- <span class="book-title">Making Games For The NES</span>
|
||||||
|
- </a>
|
||||||
|
- </li>
|
||||||
|
- </ul>
|
||||||
|
- </span>
|
||||||
|
<!-- 8bitworkshop logo -->
|
||||||
|
<span class="logo-gradient hidden-xs hidden-sm hidden-md pull-right" style="margin-left:auto" onclick="window.open('/','_8bitws');">8bitworkshop</span>
|
||||||
|
|
||||||
|
@@ -477,73 +344,6 @@
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
-<div id="importGithubModal" class="modal fade">
|
||||||
|
- <div class="modal-dialog modal-md" role="document">
|
||||||
|
- <div class="modal-content">
|
||||||
|
- <div class="modal-header">
|
||||||
|
- <h3 class="modal-title">Import Project from GitHub</h3>
|
||||||
|
- </div>
|
||||||
|
- <div class="modal-body">
|
||||||
|
- <p>Enter the GitHub repository URL:</p>
|
||||||
|
- <p><input id="importGithubURL" size="60" placeholder="https://github.com/user/repo"></input></p>
|
||||||
|
- <p>If the project is compatible with 8bitworkshop, it should build automatically.</p>
|
||||||
|
- <p>Otherwise, some work may be required -- make sure you've selected the correct platform.</p>
|
||||||
|
- <p>Source files must be in the root folder of the repository.</p>
|
||||||
|
- <p><button type="button" class="btn btn-primary" id="importGithubButton">Import Project</button></p>
|
||||||
|
- </div>
|
||||||
|
- <div class="modal-footer">
|
||||||
|
- <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
|
||||||
|
- </div>
|
||||||
|
- </div>
|
||||||
|
- </div>
|
||||||
|
-</div>
|
||||||
|
-<div id="publishGithubModal" class="modal fade">
|
||||||
|
- <div class="modal-dialog modal-md" role="document">
|
||||||
|
- <div class="modal-content">
|
||||||
|
- <div class="modal-header">
|
||||||
|
- <h3 class="modal-title">Publish Project on GitHub</h3>
|
||||||
|
- </div>
|
||||||
|
- <div class="modal-body">
|
||||||
|
- <p>This will migrate your existing project to a new GitHub repository.</p>
|
||||||
|
- <p>https://github.com/username/ <input id="githubRepoName" size="35" placeholder="Enter a project name"></input></p>
|
||||||
|
- <p><input id="githubRepoDesc" size="60" placeholder="Enter a project description"></input></p>
|
||||||
|
- <p>Your repository will be <select id="githubRepoPrivate">
|
||||||
|
- <option value="public">Public</option>
|
||||||
|
- <option value="private">Private</option>
|
||||||
|
- </select></p>
|
||||||
|
- <p>License: <select id="githubRepoLicense">
|
||||||
|
- <option value="">Will decide later / all rights reserved</option>
|
||||||
|
- <option value="cc0-1.0">CC Zero (public domain, remix-friendly)</option>
|
||||||
|
- <option value="mit">MIT (must preserve notices)</option>
|
||||||
|
- <option value="cc-by-4.0">CC BY (must attribute)</option>
|
||||||
|
- <option value="cc-by-sa-4.0">CC BY-SA (must attribute, use same license)</option>
|
||||||
|
- <option value="gpl-3.0">GPL v3 (must publish source)</option>
|
||||||
|
- </select></p>
|
||||||
|
- <p><button type="button" class="btn btn-primary" id="publishGithubButton">Upload Project</button></p>
|
||||||
|
- <p>Your existing file will be moved to a new folder in the IDE.</p>
|
||||||
|
- </div>
|
||||||
|
- <div class="modal-footer">
|
||||||
|
- <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
|
||||||
|
- </div>
|
||||||
|
- </div>
|
||||||
|
- </div>
|
||||||
|
-</div>
|
||||||
|
-<div id="pushGithubModal" class="modal fade">
|
||||||
|
- <div class="modal-dialog modal-md" role="document">
|
||||||
|
- <div class="modal-content">
|
||||||
|
- <div class="modal-header">
|
||||||
|
- <h3 class="modal-title">Push Project Changes to GitHub</h3>
|
||||||
|
- </div>
|
||||||
|
- <div class="modal-body">
|
||||||
|
- <p><input id="githubCommitMsg" size="50" placeholder="Enter a commit message"></input></p>
|
||||||
|
- <p><button type="button" class="btn btn-primary" id="pushGithubButton">Push Changes</button></p>
|
||||||
|
- </div>
|
||||||
|
- <div class="modal-footer">
|
||||||
|
- <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
|
||||||
|
- </div>
|
||||||
|
- </div>
|
||||||
|
- </div>
|
||||||
|
-</div>
|
||||||
|
|
||||||
|
<script src="jquery/jquery.min.js"></script>
|
||||||
|
|
||||||
|
@@ -635,12 +435,5 @@
|
||||||
|
startUI();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
-<script>
|
||||||
|
-/*
|
||||||
|
- var isFirefox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1;
|
||||||
|
- if (!isFirefox && platform_id != 'vcs') { $("#best_in_firefox").show(); }
|
||||||
|
-*/
|
||||||
|
-</script>
|
||||||
|
-
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -96,6 +96,7 @@ body {
|
|||||||
<li><a class="dropdown-item" href="?platform=msx-libcv">MSX (libCV)</a></li>
|
<li><a class="dropdown-item" href="?platform=msx-libcv">MSX (libCV)</a></li>
|
||||||
<li><a class="dropdown-item" href="?platform=apple2">Apple ][+</a></li>
|
<li><a class="dropdown-item" href="?platform=apple2">Apple ][+</a></li>
|
||||||
<li><a class="dropdown-item" href="?platform=zx">ZX Spectrum</a></li>
|
<li><a class="dropdown-item" href="?platform=zx">ZX Spectrum</a></li>
|
||||||
|
<li><a class="dropdown-item" href="?platform=x86">x86 (FreeDOS)</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li class="dropdown dropdown-submenu">
|
<li class="dropdown dropdown-submenu">
|
||||||
@ -105,6 +106,7 @@ body {
|
|||||||
<li><a class="dropdown-item" href="?platform=mw8080bw">Midway 8080</a></li>
|
<li><a class="dropdown-item" href="?platform=mw8080bw">Midway 8080</a></li>
|
||||||
<li><a class="dropdown-item" href="?platform=galaxian-scramble">Galaxian/Scramble</a></li>
|
<li><a class="dropdown-item" href="?platform=galaxian-scramble">Galaxian/Scramble</a></li>
|
||||||
<li><a class="dropdown-item" href="?platform=vector-z80color">Atari Color Vector (Z80)</a></li>
|
<li><a class="dropdown-item" href="?platform=vector-z80color">Atari Color Vector (Z80)</a></li>
|
||||||
|
<li><a class="dropdown-item" href="?platform=vector-ataricolor">Atari Color Vector (6502)</a></li>
|
||||||
<li><a class="dropdown-item" href="?platform=williams-z80">Williams (Z80)</a></li>
|
<li><a class="dropdown-item" href="?platform=williams-z80">Williams (Z80)</a></li>
|
||||||
<li><a class="dropdown-item" href="?platform=sound_williams-z80">Williams Sound (Z80)</a></li>
|
<li><a class="dropdown-item" href="?platform=sound_williams-z80">Williams Sound (Z80)</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
@ -116,26 +118,25 @@ body {
|
|||||||
<li><a class="dropdown-item" href="?platform=verilog-vga">Verilog (VGA @ 25 Mhz)</a></li>
|
<li><a class="dropdown-item" href="?platform=verilog-vga">Verilog (VGA @ 25 Mhz)</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li class="dropdown dropdown-submenu">
|
|
||||||
<a tabindex="-1" href="#">MAME Emulators</a>
|
|
||||||
<ul class="dropdown-menu">
|
|
||||||
<li><a class="dropdown-item" href="?platform=atari8-800xl.mame">Atari 800XL (MAME)</a></li>
|
|
||||||
<li><a class="dropdown-item" href="?platform=atari8-5200.mame">Atari 5200 (MAME)</a></li>
|
|
||||||
<hr>
|
|
||||||
<li><a class="dropdown-item" href="?platform=vcs.mame">Atari 2600 (MAME)</a></li>
|
|
||||||
<li><a class="dropdown-item" href="?platform=coleco.mame">ColecoVision (MAME)</a></li>
|
|
||||||
<li><a class="dropdown-item" href="?platform=nes.mame">NES (MAME)</a></li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
<li class="dropdown dropdown-submenu">
|
<li class="dropdown dropdown-submenu">
|
||||||
<a tabindex="-1" href="#">Other</a>
|
<a tabindex="-1" href="#">Interpreters</a>
|
||||||
<ul class="dropdown-menu">
|
<ul class="dropdown-menu">
|
||||||
<li><a class="dropdown-item" href="?platform=vector-ataricolor">Atari Color Vector (6502)</a></li>
|
<li><a class="dropdown-item" href="?platform=basic">BASIC</a></li>
|
||||||
<li><a class="dropdown-item" href="?platform=x86">x86 (FreeDOS)</a></li>
|
<li><a class="dropdown-item" href="?platform=zmachine">Z-Machine</a></li>
|
||||||
<li><a class="dropdown-item" href="?platform=zmachine">Z-Machine</a></li>
|
<li><a class="dropdown-item" href="?platform=markdown">Markdown Text Editor</a></li>
|
||||||
<li><a class="dropdown-item" href="?platform=markdown">Markdown Text Editor</a></li>
|
</ul>
|
||||||
</ul>
|
</li>
|
||||||
</li>
|
<li class="dropdown dropdown-submenu">
|
||||||
|
<a tabindex="-1" href="#">MAME Emulators</a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a class="dropdown-item" href="?platform=atari8-800xl.mame">Atari 800XL (MAME)</a></li>
|
||||||
|
<li><a class="dropdown-item" href="?platform=atari8-5200.mame">Atari 5200 (MAME)</a></li>
|
||||||
|
<hr>
|
||||||
|
<li><a class="dropdown-item" href="?platform=vcs.mame">Atari 2600 (MAME)</a></li>
|
||||||
|
<li><a class="dropdown-item" href="?platform=coleco.mame">ColecoVision (MAME)</a></li>
|
||||||
|
<li><a class="dropdown-item" href="?platform=nes.mame">NES (MAME)</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
|
@ -1,266 +1,257 @@
|
|||||||
*** index.html 2020-07-30 21:15:48.000000000 -0500
|
--- index.html 2020-08-11 11:10:30.000000000 -0500
|
||||||
--- electron.html 2020-07-30 21:16:00.000000000 -0500
|
+++ electron.html 2020-08-11 14:47:38.000000000 -0500
|
||||||
***************
|
@@ -3,16 +3,6 @@
|
||||||
*** 3,18 ****
|
|
||||||
|
<head>
|
||||||
<head>
|
<title>8bitworkshop IDE</title>
|
||||||
<title>8bitworkshop IDE</title>
|
-<link rel="manifest" href="manifest.json">
|
||||||
- <link rel="manifest" href="manifest.json">
|
-<meta name="googlebot" content="nosnippet" />
|
||||||
- <meta name="googlebot" content="nosnippet" />
|
-<meta name="mobile-web-app-capable" content="yes">
|
||||||
- <meta name="mobile-web-app-capable" content="yes">
|
-<meta name="apple-mobile-web-app-capable" content="yes">
|
||||||
- <meta name="apple-mobile-web-app-capable" content="yes">
|
-<meta name="application-name" content="8bitworkshop">
|
||||||
- <meta name="application-name" content="8bitworkshop">
|
-<meta name="apple-mobile-web-app-title" content="8bitworkshop">
|
||||||
- <meta name="apple-mobile-web-app-title" content="8bitworkshop">
|
-<meta name="theme-color" content="#ffffff">
|
||||||
- <meta name="theme-color" content="#ffffff">
|
-<meta name="msapplication-navbutton-color" content="#ffffff">
|
||||||
- <meta name="msapplication-navbutton-color" content="#ffffff">
|
-<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
|
||||||
- <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
|
-<meta name="msapplication-starturl" content="/redir.html">
|
||||||
- <meta name="msapplication-starturl" content="/redir.html">
|
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=yes">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=yes">
|
<style type="text/css" media="screen">
|
||||||
<style type="text/css" media="screen">
|
body {
|
||||||
body {
|
@@ -21,46 +11,6 @@
|
||||||
--- 3,8 ----
|
}
|
||||||
*************** body {
|
</style>
|
||||||
*** 21,61 ****
|
<link rel="stylesheet" href="css/ui.css">
|
||||||
}
|
-
|
||||||
</style>
|
-<!-- google analytics -->
|
||||||
<link rel="stylesheet" href="css/ui.css">
|
-<script>
|
||||||
-
|
-window.ga=window.ga||function(){(ga.q=ga.q||[]).push(arguments)};ga.l=+new Date;
|
||||||
- <!-- google analytics -->
|
-if (window.location.host.endsWith('8bitworkshop.com')) {
|
||||||
- <script>
|
- ga('create', 'UA-54497476-9', 'auto');
|
||||||
- window.ga=window.ga||function(){(ga.q=ga.q||[]).push(arguments)};ga.l=+new Date;
|
- ga('set', 'anonymizeIp', true);
|
||||||
- if (window.location.host.endsWith('8bitworkshop.com')) {
|
-}
|
||||||
- ga('create', 'UA-54497476-9', 'auto');
|
-</script>
|
||||||
- ga('set', 'anonymizeIp', true);
|
-<script async src='https://www.google-analytics.com/analytics.js'></script>
|
||||||
- }
|
-
|
||||||
- </script>
|
-<!-- firebase libs -->
|
||||||
- <script async src='https://www.google-analytics.com/analytics.js'></script>
|
-<script defer src="https://www.gstatic.com/firebasejs/5.11.1/firebase-app.js"></script>
|
||||||
-
|
-<script defer src="https://www.gstatic.com/firebasejs/5.11.1/firebase-auth.js"></script>
|
||||||
- <!-- firebase libs -->
|
-<script defer src="config.js"></script>
|
||||||
- <script defer src="https://www.gstatic.com/firebasejs/5.11.1/firebase-app.js"></script>
|
-
|
||||||
- <script defer src="https://www.gstatic.com/firebasejs/5.11.1/firebase-auth.js"></script>
|
-<!-- Sentry error reporting -->
|
||||||
- <script defer src="config.js"></script>
|
-<script
|
||||||
-
|
- src="https://browser.sentry-cdn.com/5.20.1/bundle.min.js"
|
||||||
- <!-- Sentry error reporting -->
|
- integrity="sha384-O8HdAJg1h8RARFowXd2J/r5fIWuinSBtjhwQoPesfVILeXzGpJxvyY/77OaPPXUo"
|
||||||
- <script
|
- crossorigin="anonymous"></script>
|
||||||
- src="https://browser.sentry-cdn.com/5.10.2/bundle.min.js"
|
-<script>
|
||||||
- integrity="sha384-ssBfXiBvlVC7bdA/VX03S88B5MwXQWdnpJRbUYFPgswlOBwETwTp6F3SMUNpo9M9"
|
-if (window.location.host.endsWith('8bitworkshop.com')) {
|
||||||
- crossorigin="anonymous"></script>
|
- Sentry.init({
|
||||||
- <script>
|
- dsn: 'https://bf329df3d1b34afa9f5b5e8ecd80ad11@sentry.io/1813925',
|
||||||
- if (window.location.host.endsWith('8bitworkshop.com')) {
|
- beforeBreadcrumb(breadcrumb, hint) {
|
||||||
- Sentry.init({
|
- if (breadcrumb.category === 'xhr' && typeof breadcrumb.data.url === 'string') {
|
||||||
- dsn: 'https://bf329df3d1b34afa9f5b5e8ecd80ad11@sentry.io/1813925',
|
- if (breadcrumb.data.url.startsWith('http')) return null; // discard external scripts
|
||||||
- beforeBreadcrumb(breadcrumb, hint) {
|
- }
|
||||||
- if (breadcrumb.category === 'xhr' && typeof breadcrumb.data.url === 'string') {
|
- return breadcrumb;
|
||||||
- if (breadcrumb.data.url.startsWith('http')) return null; // discard external scripts
|
- },
|
||||||
- }
|
- beforeSend(event, hint) {
|
||||||
- return breadcrumb;
|
- const error = hint.originalException;
|
||||||
- },
|
- if (error instanceof EmuHalt) return null; // ignore EmuHalt
|
||||||
- });
|
- return event;
|
||||||
- }
|
- },
|
||||||
- </script>
|
- });
|
||||||
-
|
-}
|
||||||
</head>
|
-</script>
|
||||||
<body>
|
-
|
||||||
|
</head>
|
||||||
--- 11,16 ----
|
<body>
|
||||||
*************** if (window.location.host.endsWith('8bitw
|
|
||||||
*** 83,108 ****
|
@@ -88,26 +38,6 @@
|
||||||
<hr>
|
<hr>
|
||||||
<li><a class="dropdown-item" href="#" id="item_addfile_include">Add Include File...</a></li>
|
<li><a class="dropdown-item" href="#" id="item_addfile_include">Add Include File...</a></li>
|
||||||
<li><a class="dropdown-item" href="#" id="item_addfile_link">Add Linked File...</a></li>
|
<li><a class="dropdown-item" href="#" id="item_addfile_link">Add Linked File...</a></li>
|
||||||
- <hr>
|
- <hr>
|
||||||
- <!--
|
- <!--
|
||||||
- <li><a class="dropdown-item" href="#" id="item_switch_https" style="display:none">Switch to HTTPS...</a></li>
|
- <li><a class="dropdown-item" href="#" id="item_switch_https" style="display:none">Switch to HTTPS...</a></li>
|
||||||
- -->
|
- -->
|
||||||
- <li><a class="dropdown-item" href="#" id="item_request_persist">Request Local Storage Permissions</a></li>
|
- <li><a class="dropdown-item" href="#" id="item_request_persist">Request Local Storage Permissions</a></li>
|
||||||
- </ul>
|
- </ul>
|
||||||
- </li>
|
- </li>
|
||||||
- <li class="dropdown dropdown-submenu">
|
- <li class="dropdown dropdown-submenu">
|
||||||
- <a tabindex="-1" href="#">Sync</a>
|
- <a tabindex="-1" href="#">Sync</a>
|
||||||
- <ul class="dropdown-menu">
|
- <ul class="dropdown-menu">
|
||||||
- <li><a class="dropdown-item" href="#" id="item_github_login">Sign in to Github...</a></li>
|
- <li><a class="dropdown-item" href="#" id="item_github_login">Sign in to Github...</a></li>
|
||||||
- <li><a class="dropdown-item" href="#" id="item_github_logout">Log out</a></li>
|
- <li><a class="dropdown-item" href="#" id="item_github_logout">Log out</a></li>
|
||||||
- <hr>
|
- <hr>
|
||||||
- <li><a class="dropdown-item" href="#" id="item_github_import">Import Project from GitHub...</a></li>
|
- <li><a class="dropdown-item" href="#" id="item_github_import">Import Project from GitHub...</a></li>
|
||||||
- <li><a class="dropdown-item" href="#" id="item_github_pull">Pull Latest from Repository</a></li>
|
- <li><a class="dropdown-item" href="#" id="item_github_pull">Pull Latest from Repository</a></li>
|
||||||
- <hr>
|
- <hr>
|
||||||
- <li><a class="dropdown-item" href="#" id="item_github_publish">Publish Project on GitHub...</a></li>
|
- <li><a class="dropdown-item" href="#" id="item_github_publish">Publish Project on GitHub...</a></li>
|
||||||
- <li><a class="dropdown-item" href="#" id="item_github_push">Push Changes to Repository...</a></li>
|
- <li><a class="dropdown-item" href="#" id="item_github_push">Push Changes to Repository...</a></li>
|
||||||
- <hr>
|
- <hr>
|
||||||
- <li><a class="dropdown-item" href="#" id="item_repo_delete">Delete Local Repository...</a></li>
|
- <li><a class="dropdown-item" href="#" id="item_repo_delete">Delete Local Repository...</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li class="dropdown dropdown-submenu">
|
<li class="dropdown dropdown-submenu">
|
||||||
--- 38,43 ----
|
@@ -133,36 +63,6 @@
|
||||||
*************** if (window.location.host.endsWith('8bitw
|
<li><a class="dropdown-item" href="#" id="item_debug_expr">Break Expression...</a></li>
|
||||||
*** 128,163 ****
|
</ul>
|
||||||
<li><a class="dropdown-item" href="#" id="item_debug_expr">Break Expression...</a></li>
|
</li>
|
||||||
</ul>
|
- <li class="dropdown dropdown-submenu">
|
||||||
</li>
|
- <a tabindex="-1" href="#">Tools</a>
|
||||||
- <li class="dropdown dropdown-submenu">
|
- <ul class="dropdown-menu">
|
||||||
- <a tabindex="-1" href="#">Tools</a>
|
- <li><a class="dropdown-item" target="_8bws_tools" href="https://8bitworkshop.com/dithertron/">Dithertron Image Converter</a></li>
|
||||||
- <ul class="dropdown-menu">
|
- <li><a class="dropdown-item" target="_8bws_tools" href="https://8bitworkshop.com/bitmapfontgenerator/">Bitmap Font Generator</a></li>
|
||||||
- <li><a class="dropdown-item" target="_8bws_tools" href="https://8bitworkshop.com/dithertron/">Dithertron Image Converter</a></li>
|
- <li><a class="dropdown-item" target="_8bws_tools" href="http://tomeko.net/online_tools/file_to_hex.php?lang=en">Binary File to Hex Converter</a></li>
|
||||||
- <li><a class="dropdown-item" target="_8bws_tools" href="https://8bitworkshop.com/bitmapfontgenerator/">Bitmap Font Generator</a></li>
|
- <li class="dropdown dropdown-submenu">
|
||||||
- <li><a class="dropdown-item" target="_8bws_tools" href="http://tomeko.net/online_tools/file_to_hex.php?lang=en">Binary File to Hex Converter</a></li>
|
- <a tabindex="-1" href="#">Atari 2600</a>
|
||||||
- <li class="dropdown dropdown-submenu">
|
- <ul class="dropdown-menu">
|
||||||
- <a tabindex="-1" href="#">Atari 2600</a>
|
- <li><a class="dropdown-item" target="_8bws_tools" href="https://alienbill.com/2600/playerpalnext.html">playerpal 2600</a></li>
|
||||||
- <ul class="dropdown-menu">
|
- <li><a class="dropdown-item" target="_8bws_tools" href="https://alienbill.com/2600/playfieldpal.html">playfieldpal 2600</a></li>
|
||||||
- <li><a class="dropdown-item" target="_8bws_tools" href="https://alienbill.com/2600/playerpalnext.html">playerpal 2600</a></li>
|
- </ul>
|
||||||
- <li><a class="dropdown-item" target="_8bws_tools" href="https://alienbill.com/2600/playfieldpal.html">playfieldpal 2600</a></li>
|
- </li>
|
||||||
- </ul>
|
- </ul>
|
||||||
- </li>
|
- </li>
|
||||||
- </ul>
|
- <hr>
|
||||||
- </li>
|
- <li class="dropdown dropdown-submenu">
|
||||||
- <hr>
|
- <a tabindex="-1" href="#">About</a>
|
||||||
- <li class="dropdown dropdown-submenu">
|
- <ul class="dropdown-menu">
|
||||||
- <a tabindex="-1" href="#">About</a>
|
- <li><a class="dropdown-item" target="_8bws_about" href="https://8bitworkshop.com/blog">Latest News</a></li>
|
||||||
- <ul class="dropdown-menu">
|
- <li><a class="dropdown-item" target="_8bws_about" href="https://8bitworkshop.com/projects">Projects</a></li>
|
||||||
- <li><a class="dropdown-item" target="_8bws_about" href="https://8bitworkshop.com/blog">Latest News</a></li>
|
- <li><a class="dropdown-item" target="_8bws_about" href="https://twitter.com/8bitworkshop">Twitter</a></li>
|
||||||
- <li><a class="dropdown-item" target="_8bws_about" href="https://8bitworkshop.com/projects">Projects</a></li>
|
- <li><a class="dropdown-item" target="_8bws_about" href="https://github.com/sehugg/8bitworkshop">GitHub</a></li>
|
||||||
- <li><a class="dropdown-item" target="_8bws_about" href="https://twitter.com/8bitworkshop">Twitter</a></li>
|
- <li><a class="dropdown-item" target="_8bws_about" href="https://github.com/sehugg/8bitworkshop/issues/new">Report an Issue</a></li>
|
||||||
- <li><a class="dropdown-item" target="_8bws_about" href="https://github.com/sehugg/8bitworkshop">GitHub</a></li>
|
- <li><a class="dropdown-item" target="_8bws_about" href="https://8bitworkshop.com/blog/docs/ide.md.html">IDE Help</a></li>
|
||||||
- <li><a class="dropdown-item" target="_8bws_about" href="https://github.com/sehugg/8bitworkshop/issues/new">Report an Issue</a></li>
|
- </ul>
|
||||||
- <li><a class="dropdown-item" target="_8bws_about" href="https://8bitworkshop.com/blog/docs/ide.md.html">IDE Help</a></li>
|
- </li>
|
||||||
- </ul>
|
- <!--
|
||||||
- </li>
|
- <hr><li><a class="dropdown-item" href="/redir.html">Use Latest Version</a></li>
|
||||||
- <!--
|
- -->
|
||||||
- <hr><li><a class="dropdown-item" href="/redir.html">Use Latest Version</a></li>
|
</ul>
|
||||||
- -->
|
</span>
|
||||||
</ul>
|
|
||||||
</span>
|
@@ -258,39 +158,6 @@
|
||||||
|
<span class="label"><span id="settle_label"></span> evals/clk</span>
|
||||||
--- 63,68 ----
|
</span>
|
||||||
*************** if (window.location.host.endsWith('8bitw
|
|
||||||
*** 252,290 ****
|
- <!-- BOOKS menu -->
|
||||||
<span class="label"><span id="settle_label"></span> evals/clk</span>
|
- <span class="dropdown pull-right">
|
||||||
</span>
|
- <a class="btn dropdown-toggle hidden-xs toolbarMenuButton" id="booksMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||||
|
- <span class="glyphicon glyphicon-book" aria-hidden="true"></span>
|
||||||
- <!-- BOOKS menu -->
|
- Get Books <span class="caret"></span>
|
||||||
- <span class="dropdown pull-right">
|
- </a>
|
||||||
- <a class="btn dropdown-toggle hidden-xs toolbarMenuButton" id="booksMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
- <ul class="dropdown-menu dropdown-menu-right" aria-labelledby="booksMenuButton">
|
||||||
- <span class="glyphicon glyphicon-book" aria-hidden="true"></span>
|
- <li>
|
||||||
- Get Books <span class="caret"></span>
|
- <a class="dropdown-item dropdown-link book-vcs" target="_book_a2600" href="https://www.amazon.com/gp/product/1541021304/ref=as_li_qf_sp_asin_il_tl?ie=UTF8&tag=pzp-20&camp=1789&creative=9325&linkCode=as2&creativeASIN=B01N4DSRIZ&linkId=04d39e274c06e6c93b93d20a9a977111">
|
||||||
- </a>
|
- <img src="images/book_a2600.png"/>
|
||||||
- <ul class="dropdown-menu dropdown-menu-right" aria-labelledby="booksMenuButton">
|
- <span class="book-title">Making Games For The Atari 2600</span>
|
||||||
- <li>
|
- </a>
|
||||||
- <a class="dropdown-item dropdown-link book-vcs" target="_book_a2600" href="https://www.amazon.com/gp/product/1541021304/ref=as_li_qf_sp_asin_il_tl?ie=UTF8&tag=pzp-20&camp=1789&creative=9325&linkCode=as2&creativeASIN=B01N4DSRIZ&linkId=04d39e274c06e6c93b93d20a9a977111">
|
- </li>
|
||||||
- <img src="images/book_a2600.png"/>
|
- <li>
|
||||||
- <span class="book-title">Making Games For The Atari 2600</span>
|
- <a class="dropdown-item dropdown-link book-arcade" target="_book_arcade" href="https://www.amazon.com/gp/product/1545484759/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1545484759&linkCode=as2&tag=pzp-20&linkId=b27709c022d2ebe639e90316d9f4fd5b">
|
||||||
- </a>
|
- <img src="images/book_arcade.png"/>
|
||||||
- </li>
|
- <span class="book-title">Making 8-bit Arcade Games in C</span>
|
||||||
- <li>
|
- </a>
|
||||||
- <a class="dropdown-item dropdown-link book-arcade" target="_book_arcade" href="https://www.amazon.com/gp/product/1545484759/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1545484759&linkCode=as2&tag=pzp-20&linkId=b27709c022d2ebe639e90316d9f4fd5b">
|
- </li>
|
||||||
- <img src="images/book_arcade.png"/>
|
- <li>
|
||||||
- <span class="book-title">Making 8-bit Arcade Games in C</span>
|
- <a class="dropdown-item dropdown-link book-verilog" target="_book_verilog" href="https://www.amazon.com/gp/product/1728619440/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1728619440&linkCode=as2&tag=pzp-20&linkId=7237a25861cb6b49a4128ba53d84c3e2">
|
||||||
- </a>
|
- <img src="images/book_verilog.png"/>
|
||||||
- </li>
|
- <span class="book-title">Designing Video Game Hardware in Verilog</span>
|
||||||
- <li>
|
- </a>
|
||||||
- <a class="dropdown-item dropdown-link book-verilog" target="_book_verilog" href="https://www.amazon.com/gp/product/1728619440/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1728619440&linkCode=as2&tag=pzp-20&linkId=7237a25861cb6b49a4128ba53d84c3e2">
|
- </li>
|
||||||
- <img src="images/book_verilog.png"/>
|
- <li>
|
||||||
- <span class="book-title">Designing Video Game Hardware in Verilog</span>
|
- <a class="dropdown-item dropdown-link book-nes" target="_book_nes" href="https://www.amazon.com/gp/product/1075952727/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1075952727&linkCode=as2&tag=pzp-20&linkId=633176e8b36fea7f927020e2c322d80a">
|
||||||
- </a>
|
- <img src="images/book_nes.png"/>
|
||||||
- </li>
|
- <span class="book-title">Making Games For The NES</span>
|
||||||
- <li>
|
- </a>
|
||||||
- <a class="dropdown-item dropdown-link book-nes" target="_book_nes" href="https://www.amazon.com/gp/product/1075952727/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1075952727&linkCode=as2&tag=pzp-20&linkId=633176e8b36fea7f927020e2c322d80a">
|
- </li>
|
||||||
- <img src="images/book_nes.png"/>
|
- </ul>
|
||||||
- <span class="book-title">Making Games For The NES</span>
|
- </span>
|
||||||
- </a>
|
<!-- 8bitworkshop logo -->
|
||||||
- </li>
|
<span class="logo-gradient hidden-xs hidden-sm hidden-md pull-right" style="margin-left:auto" onclick="window.open('/','_8bitws');">8bitworkshop</span>
|
||||||
- </ul>
|
|
||||||
- </span>
|
@@ -477,73 +344,6 @@
|
||||||
<!-- 8bitworkshop logo -->
|
</div>
|
||||||
<span class="logo-gradient hidden-xs hidden-sm hidden-md pull-right" style="margin-left:auto" onclick="window.open('/','_8bitws');">8bitworkshop</span>
|
</div>
|
||||||
|
</div>
|
||||||
--- 157,162 ----
|
-<div id="importGithubModal" class="modal fade">
|
||||||
*************** if (window.location.host.endsWith('8bitw
|
- <div class="modal-dialog modal-md" role="document">
|
||||||
*** 471,543 ****
|
- <div class="modal-content">
|
||||||
</div>
|
- <div class="modal-header">
|
||||||
</div>
|
- <h3 class="modal-title">Import Project from GitHub</h3>
|
||||||
</div>
|
- </div>
|
||||||
- <div id="importGithubModal" class="modal fade">
|
- <div class="modal-body">
|
||||||
- <div class="modal-dialog modal-md" role="document">
|
- <p>Enter the GitHub repository URL:</p>
|
||||||
- <div class="modal-content">
|
- <p><input id="importGithubURL" size="60" placeholder="https://github.com/user/repo"></input></p>
|
||||||
- <div class="modal-header">
|
- <p>If the project is compatible with 8bitworkshop, it should build automatically.</p>
|
||||||
- <h3 class="modal-title">Import Project from GitHub</h3>
|
- <p>Otherwise, some work may be required -- make sure you've selected the correct platform.</p>
|
||||||
- </div>
|
- <p>Source files must be in the root folder of the repository.</p>
|
||||||
- <div class="modal-body">
|
- <p><button type="button" class="btn btn-primary" id="importGithubButton">Import Project</button></p>
|
||||||
- <p>Enter the GitHub repository URL:</p>
|
- </div>
|
||||||
- <p><input id="importGithubURL" size="60" placeholder="https://github.com/user/repo"></input></p>
|
- <div class="modal-footer">
|
||||||
- <p>If the project is compatible with 8bitworkshop, it should build automatically.</p>
|
- <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
|
||||||
- <p>Otherwise, some work may be required -- make sure you've selected the correct platform.</p>
|
- </div>
|
||||||
- <p>Source files must be in the root folder of the repository.</p>
|
- </div>
|
||||||
- <p><button type="button" class="btn btn-primary" id="importGithubButton">Import Project</button></p>
|
- </div>
|
||||||
- </div>
|
-</div>
|
||||||
- <div class="modal-footer">
|
-<div id="publishGithubModal" class="modal fade">
|
||||||
- <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
|
- <div class="modal-dialog modal-md" role="document">
|
||||||
- </div>
|
- <div class="modal-content">
|
||||||
- </div>
|
- <div class="modal-header">
|
||||||
- </div>
|
- <h3 class="modal-title">Publish Project on GitHub</h3>
|
||||||
- </div>
|
- </div>
|
||||||
- <div id="publishGithubModal" class="modal fade">
|
- <div class="modal-body">
|
||||||
- <div class="modal-dialog modal-md" role="document">
|
- <p>This will migrate your existing project to a new GitHub repository.</p>
|
||||||
- <div class="modal-content">
|
- <p>https://github.com/username/ <input id="githubRepoName" size="35" placeholder="Enter a project name"></input></p>
|
||||||
- <div class="modal-header">
|
- <p><input id="githubRepoDesc" size="60" placeholder="Enter a project description"></input></p>
|
||||||
- <h3 class="modal-title">Publish Project on GitHub</h3>
|
- <p>Your repository will be <select id="githubRepoPrivate">
|
||||||
- </div>
|
- <option value="public">Public</option>
|
||||||
- <div class="modal-body">
|
- <option value="private">Private</option>
|
||||||
- <p>This will migrate your existing project to a new GitHub repository.</p>
|
- </select></p>
|
||||||
- <p>https://github.com/username/ <input id="githubRepoName" size="35" placeholder="Enter a project name"></input></p>
|
- <p>License: <select id="githubRepoLicense">
|
||||||
- <p><input id="githubRepoDesc" size="60" placeholder="Enter a project description"></input></p>
|
- <option value="">Will decide later / all rights reserved</option>
|
||||||
- <p>Your repository will be <select id="githubRepoPrivate">
|
- <option value="cc0-1.0">CC Zero (public domain, remix-friendly)</option>
|
||||||
- <option value="public">Public</option>
|
- <option value="mit">MIT (must preserve notices)</option>
|
||||||
- <option value="private">Private</option>
|
- <option value="cc-by-4.0">CC BY (must attribute)</option>
|
||||||
- </select></p>
|
- <option value="cc-by-sa-4.0">CC BY-SA (must attribute, use same license)</option>
|
||||||
- <p>License: <select id="githubRepoLicense">
|
- <option value="gpl-3.0">GPL v3 (must publish source)</option>
|
||||||
- <option value="">Will decide later / all rights reserved</option>
|
- </select></p>
|
||||||
- <option value="cc0-1.0">CC Zero (public domain, remix-friendly)</option>
|
- <p><button type="button" class="btn btn-primary" id="publishGithubButton">Upload Project</button></p>
|
||||||
- <option value="mit">MIT (must preserve notices)</option>
|
- <p>Your existing file will be moved to a new folder in the IDE.</p>
|
||||||
- <option value="cc-by-4.0">CC BY (must attribute)</option>
|
- </div>
|
||||||
- <option value="cc-by-sa-4.0">CC BY-SA (must attribute, use same license)</option>
|
- <div class="modal-footer">
|
||||||
- <option value="gpl-3.0">GPL v3 (must publish source)</option>
|
- <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
|
||||||
- </select></p>
|
- </div>
|
||||||
- <p><button type="button" class="btn btn-primary" id="publishGithubButton">Upload Project</button></p>
|
- </div>
|
||||||
- <p>Your existing file will be moved to a new folder in the IDE.</p>
|
- </div>
|
||||||
- </div>
|
-</div>
|
||||||
- <div class="modal-footer">
|
-<div id="pushGithubModal" class="modal fade">
|
||||||
- <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
|
- <div class="modal-dialog modal-md" role="document">
|
||||||
- </div>
|
- <div class="modal-content">
|
||||||
- </div>
|
- <div class="modal-header">
|
||||||
- </div>
|
- <h3 class="modal-title">Push Project Changes to GitHub</h3>
|
||||||
- </div>
|
- </div>
|
||||||
- <div id="pushGithubModal" class="modal fade">
|
- <div class="modal-body">
|
||||||
- <div class="modal-dialog modal-md" role="document">
|
- <p><input id="githubCommitMsg" size="50" placeholder="Enter a commit message"></input></p>
|
||||||
- <div class="modal-content">
|
- <p><button type="button" class="btn btn-primary" id="pushGithubButton">Push Changes</button></p>
|
||||||
- <div class="modal-header">
|
- </div>
|
||||||
- <h3 class="modal-title">Push Project Changes to GitHub</h3>
|
- <div class="modal-footer">
|
||||||
- </div>
|
- <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
|
||||||
- <div class="modal-body">
|
- </div>
|
||||||
- <p><input id="githubCommitMsg" size="50" placeholder="Enter a commit message"></input></p>
|
- </div>
|
||||||
- <p><button type="button" class="btn btn-primary" id="pushGithubButton">Push Changes</button></p>
|
- </div>
|
||||||
- </div>
|
-</div>
|
||||||
- <div class="modal-footer">
|
|
||||||
- <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
|
<script src="jquery/jquery.min.js"></script>
|
||||||
- </div>
|
|
||||||
- </div>
|
@@ -635,12 +435,5 @@
|
||||||
- </div>
|
startUI();
|
||||||
- </div>
|
</script>
|
||||||
|
|
||||||
<script src="jquery/jquery.min.js"></script>
|
-<script>
|
||||||
|
-/*
|
||||||
--- 343,348 ----
|
- var isFirefox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1;
|
||||||
*************** $( ".dropdown-submenu" ).click(function(
|
- if (!isFirefox && platform_id != 'vcs') { $("#best_in_firefox").show(); }
|
||||||
*** 629,640 ****
|
-*/
|
||||||
startUI();
|
-</script>
|
||||||
</script>
|
-
|
||||||
|
</body>
|
||||||
- <script>
|
</html>
|
||||||
- /*
|
|
||||||
- var isFirefox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1;
|
|
||||||
- if (!isFirefox && platform_id != 'vcs') { $("#best_in_firefox").show(); }
|
|
||||||
- */
|
|
||||||
- </script>
|
|
||||||
-
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
--- 434,438 ----
|
|
||||||
|
@ -8,3 +8,4 @@
|
|||||||
45 PRINT
|
45 PRINT
|
||||||
50 PRINT "THAT'S A GOOD ONE! I LIKE";N^2;"MYSELF."
|
50 PRINT "THAT'S A GOOD ONE! I LIKE";N^2;"MYSELF."
|
||||||
60 PRINT "NICE MEETING YOU, ";A$;"."
|
60 PRINT "NICE MEETING YOU, ";A$;"."
|
||||||
|
999 END
|
||||||
|
BIN
res/ttybell.mp3
Normal file
BIN
res/ttybell.mp3
Normal file
Binary file not shown.
@ -14,8 +14,9 @@
|
|||||||
CodeMirror.defineMode("basic", function(conf, parserConf) {
|
CodeMirror.defineMode("basic", function(conf, parserConf) {
|
||||||
var ERRORCLASS = 'error';
|
var ERRORCLASS = 'error';
|
||||||
|
|
||||||
function wordRegexp(words) {
|
function wordRegexp(words, crunch) {
|
||||||
return new RegExp("^((" + words.join(")|(") + "))\\b", "i");
|
return new RegExp("^((" + words.join(")|(") + "))", "i");
|
||||||
|
//return new RegExp("^((" + words.join(")|(") + "))\\b", "i");
|
||||||
}
|
}
|
||||||
|
|
||||||
var singleOperators = new RegExp("^[\\+\\-\\*/%&\\\\|\\^~<>!]");
|
var singleOperators = new RegExp("^[\\+\\-\\*/%&\\\\|\\^~<>!]");
|
||||||
|
@ -1,10 +1,46 @@
|
|||||||
import { WorkerError, CodeListingMap, SourceLocation, SourceLine } from "../workertypes";
|
import { WorkerError, CodeListingMap, SourceLocation, SourceLine } from "../workertypes";
|
||||||
|
|
||||||
|
export interface BASICOptions {
|
||||||
|
dialectName : string; // use this to select the dialect
|
||||||
|
// SYNTAX AND PARSING
|
||||||
|
asciiOnly : boolean; // reject non-ASCII chars?
|
||||||
|
uppercaseOnly : boolean; // convert everything to uppercase?
|
||||||
|
optionalLabels : boolean; // can omit line numbers and use labels?
|
||||||
|
optionalWhitespace : boolean; // can "crunch" keywords?
|
||||||
|
varNaming : 'A1'|'AA'|'*'; // only allow A0-9 for numerics, single letter for arrays/strings
|
||||||
|
tickComments : boolean; // support 'comments?
|
||||||
|
validKeywords : string[]; // valid keywords (or null for accept all)
|
||||||
|
validFunctions : string[]; // valid functions (or null for accept all)
|
||||||
|
validOperators : string[]; // valid operators (or null for accept all)
|
||||||
|
// VALUES AND OPERATORS
|
||||||
|
defaultValues : boolean; // initialize unset variables to default value? (0 or "")
|
||||||
|
stringConcat : boolean; // can concat strings with "+" operator?
|
||||||
|
typeConvert : boolean; // type convert strings <-> numbers?
|
||||||
|
checkOverflow : boolean; // check for overflow of numerics?
|
||||||
|
bitwiseLogic : boolean; // -1 = TRUE, 0 = FALSE, AND/OR/NOT done with bitwise ops
|
||||||
|
maxStringLength : number; // maximum string length in chars
|
||||||
|
maxDefArgs : number; // maximum # of arguments for user-defined functions
|
||||||
|
// ARRAYS
|
||||||
|
staticArrays : boolean; // can only DIM with constant value? (and never redim)
|
||||||
|
sharedArrayNamespace : boolean; // arrays and variables have same namespace? (TODO)
|
||||||
|
defaultArrayBase : number; // arrays start at this number (0 or 1)
|
||||||
|
defaultArraySize : number; // arrays are allocated w/ this size (starting @ 0)
|
||||||
|
maxDimensions : number; // max number of dimensions for arrays
|
||||||
|
// PRINTING
|
||||||
|
printZoneLength : number; // print zone length
|
||||||
|
numericPadding : boolean; // " " or "-" before and " " after numbers?
|
||||||
|
// CONTROL FLOW
|
||||||
|
testInitialFor : boolean; // can we skip a NEXT statement? (can't interleave tho)
|
||||||
|
ifElse : boolean; // IF...ELSE construct
|
||||||
|
// MISC
|
||||||
|
commandsPerSec? : number; // how many commands per second?
|
||||||
|
}
|
||||||
|
|
||||||
export interface SourceLocated {
|
export interface SourceLocated {
|
||||||
$loc?: SourceLine;
|
$loc?: SourceLine;
|
||||||
}
|
}
|
||||||
|
|
||||||
class CompileError extends Error {
|
export class CompileError extends Error {
|
||||||
constructor(msg: string) {
|
constructor(msg: string) {
|
||||||
super(msg);
|
super(msg);
|
||||||
Object.setPrototypeOf(this, CompileError.prototype);
|
Object.setPrototypeOf(this, CompileError.prototype);
|
||||||
@ -179,8 +215,10 @@ const OPERATORS = {
|
|||||||
'IMP': {f:'bimp',p:4},
|
'IMP': {f:'bimp',p:4},
|
||||||
'EQV': {f:'beqv',p:5},
|
'EQV': {f:'beqv',p:5},
|
||||||
'XOR': {f:'bxor',p:6},
|
'XOR': {f:'bxor',p:6},
|
||||||
'OR': {f:'lor',p:7}, // or "bor"
|
'OR': {f:'bor',p:7}, // or "lor" for logical
|
||||||
'AND': {f:'land',p:8}, // or "band"
|
'AND': {f:'band',p:8}, // or "land" for logical
|
||||||
|
'||': {f:'lor',p:17}, // not used
|
||||||
|
'&&': {f:'land',p:18}, // not used
|
||||||
'=': {f:'eq',p:50},
|
'=': {f:'eq',p:50},
|
||||||
'<>': {f:'ne',p:50},
|
'<>': {f:'ne',p:50},
|
||||||
'<': {f:'lt',p:50},
|
'<': {f:'lt',p:50},
|
||||||
@ -222,41 +260,10 @@ function stripQuotes(s: string) {
|
|||||||
return s.substr(1, s.length-2);
|
return s.substr(1, s.length-2);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: implement these
|
|
||||||
export interface BASICOptions {
|
|
||||||
dialectName : string; // use this to select the dialect
|
|
||||||
asciiOnly : boolean; // reject non-ASCII chars?
|
|
||||||
uppercaseOnly : boolean; // convert everything to uppercase?
|
|
||||||
optionalLabels : boolean; // can omit line numbers and use labels?
|
|
||||||
strictVarNames : boolean; // only allow A0-9 for numerics, single letter for arrays/strings
|
|
||||||
tickComments : boolean; // support 'comments?
|
|
||||||
defaultValues : boolean; // initialize unset variables to default value? (0 or "")
|
|
||||||
sharedArrayNamespace : boolean; // arrays and variables have same namespace? (conflict)
|
|
||||||
defaultArrayBase : number; // arrays start at this number (0 or 1) (TODO: check)
|
|
||||||
defaultArraySize : number; // arrays are allocated w/ this size (starting @ 0)
|
|
||||||
stringConcat : boolean; // can concat strings with "+" operator?
|
|
||||||
typeConvert : boolean; // type convert strings <-> numbers? (TODO)
|
|
||||||
checkOverflow : boolean; // check for overflow of numerics?
|
|
||||||
sparseArrays : boolean; // true == don't require DIM for arrays (TODO)
|
|
||||||
printZoneLength : number; // print zone length
|
|
||||||
numericPadding : boolean; // " " or "-" before and " " after numbers?
|
|
||||||
outOfOrderNext : boolean; // can we skip a NEXT statement? (can't interleave tho)
|
|
||||||
multipleNextVars : boolean; // NEXT Y,X (TODO)
|
|
||||||
ifElse : boolean; // IF...ELSE construct
|
|
||||||
bitwiseLogic : boolean; // -1 = TRUE, 0 = FALSE, AND/OR/NOT done with bitwise ops
|
|
||||||
maxDimensions : number; // max number of dimensions for arrays
|
|
||||||
maxDefArgs : number; // maximum # of arguments for user-defined functions
|
|
||||||
maxStringLength : number; // maximum string length in chars
|
|
||||||
validKeywords : string[]; // valid keywords (or null for accept all)
|
|
||||||
validFunctions : string[]; // valid functions (or null for accept all)
|
|
||||||
validOperators : string[]; // valid operators (or null for accept all)
|
|
||||||
commandsPerSec? : number; // how many commands per second?
|
|
||||||
}
|
|
||||||
|
|
||||||
///// BASIC PARSER
|
///// BASIC PARSER
|
||||||
|
|
||||||
export class BASICParser {
|
export class BASICParser {
|
||||||
opts : BASICOptions = ALTAIR_BASIC40;
|
opts : BASICOptions = ALTAIR_BASIC41;
|
||||||
errors: WorkerError[];
|
errors: WorkerError[];
|
||||||
listings: CodeListingMap;
|
listings: CodeListingMap;
|
||||||
labels: { [label: string]: BASICLine };
|
labels: { [label: string]: BASICLine };
|
||||||
@ -283,8 +290,7 @@ export class BASICParser {
|
|||||||
}
|
}
|
||||||
compileError(msg: string, loc?: SourceLocation) {
|
compileError(msg: string, loc?: SourceLocation) {
|
||||||
if (!loc) loc = this.peekToken().$loc;
|
if (!loc) loc = this.peekToken().$loc;
|
||||||
// TODO: pass SourceLocation to errors
|
this.errors.push({path:loc.path, line:loc.line, label:loc.label, start:loc.start, end:loc.end, msg:msg});
|
||||||
this.errors.push({path:loc.path, line:loc.line, label:loc.label, msg:msg});
|
|
||||||
throw new CompileError(`${msg} (line ${loc.line})`); // TODO: label too?
|
throw new CompileError(`${msg} (line ${loc.line})`); // TODO: label too?
|
||||||
}
|
}
|
||||||
dialectError(what: string, loc?: SourceLocation) {
|
dialectError(what: string, loc?: SourceLocation) {
|
||||||
@ -358,23 +364,33 @@ export class BASICParser {
|
|||||||
tokenize(line: string) : void {
|
tokenize(line: string) : void {
|
||||||
this.lineno++;
|
this.lineno++;
|
||||||
this.tokens = [];
|
this.tokens = [];
|
||||||
|
let splitre = this.opts.optionalWhitespace && new RegExp(this.opts.validKeywords.map(s => `^${s}`).join('|'));
|
||||||
var m : RegExpMatchArray;
|
var m : RegExpMatchArray;
|
||||||
while (m = re_toks.exec(line)) {
|
while (m = re_toks.exec(line)) {
|
||||||
for (var i = 1; i < TokenType._LAST; i++) {
|
for (var i = 1; i < TokenType._LAST; i++) {
|
||||||
let s : string = m[i];
|
let s : string = m[i];
|
||||||
if (s != null) {
|
if (s != null) {
|
||||||
|
let loc = { path: this.path, line: this.lineno, start: m.index, end: m.index+s.length, label: this.curlabel };
|
||||||
// maybe we don't support unicode in 1975?
|
// maybe we don't support unicode in 1975?
|
||||||
if (this.opts.asciiOnly && !/^[\x00-\x7F]*$/.test(s))
|
if (this.opts.asciiOnly && !/^[\x00-\x7F]*$/.test(s))
|
||||||
this.dialectError(`non-ASCII characters`);
|
this.dialectError(`non-ASCII characters`);
|
||||||
// uppercase all identifiers, and maybe more
|
// uppercase all identifiers, and maybe more
|
||||||
if (i == TokenType.Ident || this.opts.uppercaseOnly)
|
if (i == TokenType.Ident || this.opts.uppercaseOnly)
|
||||||
s = s.toUpperCase();
|
s = s.toUpperCase();
|
||||||
|
// un-crunch tokens?
|
||||||
|
if (splitre) {
|
||||||
|
while (i == TokenType.Ident) {
|
||||||
|
let m2 = splitre.exec(s);
|
||||||
|
if (m2 && s.length > m2[0].length) {
|
||||||
|
this.tokens.push({str:m2[0], type:TokenType.Ident, $loc:loc});
|
||||||
|
s = s.substring(m2[0].length);
|
||||||
|
} else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (/^[0-9]+$/.test(s)) i = TokenType.Int;
|
||||||
|
}
|
||||||
// add token to list
|
// add token to list
|
||||||
this.tokens.push({
|
this.tokens.push({str: s, type: i, $loc:loc});
|
||||||
str: s,
|
|
||||||
type: i,
|
|
||||||
$loc: { path: this.path, line: this.lineno, start: m.index, end: m.index+s.length, label: this.curlabel }
|
|
||||||
});
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -473,6 +489,12 @@ export class BASICParser {
|
|||||||
this.validateVarName(lexpr);
|
this.validateVarName(lexpr);
|
||||||
return lexpr;
|
return lexpr;
|
||||||
}
|
}
|
||||||
|
parseForNextLexpr() : IndOp {
|
||||||
|
var lexpr = this.parseLexpr();
|
||||||
|
if (lexpr.args || lexpr.name.endsWith('$'))
|
||||||
|
this.compileError(`A FOR ... NEXT loop can only use numeric variables.`);
|
||||||
|
return lexpr;
|
||||||
|
}
|
||||||
parseList<T>(parseFunc:()=>T, delim:string): T[] {
|
parseList<T>(parseFunc:()=>T, delim:string): T[] {
|
||||||
var sep;
|
var sep;
|
||||||
var list = [];
|
var list = [];
|
||||||
@ -564,8 +586,9 @@ export class BASICParser {
|
|||||||
look = this.peekToken();
|
look = this.peekToken();
|
||||||
}
|
}
|
||||||
var opfn = getOperator(op.str).f;
|
var opfn = getOperator(op.str).f;
|
||||||
if (this.opts.bitwiseLogic && opfn == 'land') opfn = 'band';
|
// use logical operators instead of bitwise?
|
||||||
if (this.opts.bitwiseLogic && opfn == 'lor') opfn = 'bor';
|
if (!this.opts.bitwiseLogic && op.str == 'AND') opfn = 'land';
|
||||||
|
if (!this.opts.bitwiseLogic && op.str == 'OR') opfn = 'lor';
|
||||||
left = { op:opfn, left: left, right: right };
|
left = { op:opfn, left: left, right: right };
|
||||||
}
|
}
|
||||||
return left;
|
return left;
|
||||||
@ -574,11 +597,17 @@ export class BASICParser {
|
|||||||
return this.parseExpr1(this.parsePrimary(), 0);
|
return this.parseExpr1(this.parsePrimary(), 0);
|
||||||
}
|
}
|
||||||
validateVarName(lexpr: IndOp) {
|
validateVarName(lexpr: IndOp) {
|
||||||
if (this.opts.strictVarNames) {
|
switch (this.opts.varNaming) {
|
||||||
if (lexpr.args == null && !/^[A-Z][0-9]?[$]?$/.test(lexpr.name))
|
case 'A1':
|
||||||
this.dialectError(`variable names other than a letter followed by an optional digit`);
|
if (lexpr.args == null && !/^[A-Z][0-9]?[$]?$/i.test(lexpr.name))
|
||||||
if (lexpr.args != null && !/^[A-Z]?[$]?$/.test(lexpr.name))
|
this.dialectError(`variable names other than a letter followed by an optional digit`);
|
||||||
this.dialectError(`array names other than a single letter`);
|
if (lexpr.args != null && !/^[A-Z]?[$]?$/i.test(lexpr.name))
|
||||||
|
this.dialectError(`array names other than a single letter`);
|
||||||
|
break;
|
||||||
|
case 'AA':
|
||||||
|
if (lexpr.args == null && !/^[A-Z][A-Z0-9]?[$]?$/i.test(lexpr.name))
|
||||||
|
this.dialectError(`variable names other than a letter followed by an optional letter or digit`);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -648,7 +677,7 @@ export class BASICParser {
|
|||||||
return { command: "ELSE" };
|
return { command: "ELSE" };
|
||||||
}
|
}
|
||||||
stmt__FOR() : FOR_Statement {
|
stmt__FOR() : FOR_Statement {
|
||||||
var lexpr = this.parseLexpr(); // TODO: parseNumVar()
|
var lexpr = this.parseForNextLexpr();
|
||||||
this.expectToken('=');
|
this.expectToken('=');
|
||||||
var init = this.parseExpr();
|
var init = this.parseExpr();
|
||||||
this.expectToken('TO');
|
this.expectToken('TO');
|
||||||
@ -662,7 +691,7 @@ export class BASICParser {
|
|||||||
stmt__NEXT() : NEXT_Statement {
|
stmt__NEXT() : NEXT_Statement {
|
||||||
var lexpr = null;
|
var lexpr = null;
|
||||||
if (!isEOS(this.peekToken())) {
|
if (!isEOS(this.peekToken())) {
|
||||||
lexpr = this.parseExpr();
|
lexpr = this.parseForNextLexpr();
|
||||||
}
|
}
|
||||||
return { command:'NEXT', lexpr:lexpr };
|
return { command:'NEXT', lexpr:lexpr };
|
||||||
}
|
}
|
||||||
@ -770,6 +799,18 @@ export class BASICParser {
|
|||||||
this.compileError(`OPTION CPUSPEED takes a positive number or MAX.`);
|
this.compileError(`OPTION CPUSPEED takes a positive number or MAX.`);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
// maybe it's one of the options?
|
||||||
|
var name = Object.getOwnPropertyNames(this.opts).find((n) => n.toUpperCase() == stmt.optname);
|
||||||
|
if (name != null) switch (typeof this.opts[name]) {
|
||||||
|
case 'boolean' : this.opts[name] = arg ? true : false; return;
|
||||||
|
case 'number' : this.opts[name] = parseFloat(arg); return;
|
||||||
|
case 'string' : this.opts[name] = arg; return;
|
||||||
|
case 'object' :
|
||||||
|
if (Array.isArray(this.opts[name]) && arg == 'ALL') {
|
||||||
|
this.opts[name] = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
this.compileError(`OPTION ${stmt.optname} is not supported by this compiler.`);
|
this.compileError(`OPTION ${stmt.optname} is not supported by this compiler.`);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -814,13 +855,15 @@ export class BASICParser {
|
|||||||
|
|
||||||
///// BASIC DIALECTS
|
///// BASIC DIALECTS
|
||||||
|
|
||||||
// TODO: require END statement, check FOR condition at start of loop
|
// TODO: require END statement
|
||||||
export const ECMA55_MINIMAL : BASICOptions = {
|
export const ECMA55_MINIMAL : BASICOptions = {
|
||||||
dialectName: "ECMA55",
|
dialectName: "ECMA55",
|
||||||
asciiOnly : true,
|
asciiOnly : true,
|
||||||
uppercaseOnly : true,
|
uppercaseOnly : true,
|
||||||
optionalLabels : false,
|
optionalLabels : false,
|
||||||
strictVarNames : true,
|
optionalWhitespace : false,
|
||||||
|
varNaming : "A1",
|
||||||
|
staticArrays : true,
|
||||||
sharedArrayNamespace : true,
|
sharedArrayNamespace : true,
|
||||||
defaultArrayBase : 0,
|
defaultArrayBase : 0,
|
||||||
defaultArraySize : 11,
|
defaultArraySize : 11,
|
||||||
@ -830,29 +873,62 @@ export const ECMA55_MINIMAL : BASICOptions = {
|
|||||||
maxDimensions : 2,
|
maxDimensions : 2,
|
||||||
maxDefArgs : 255,
|
maxDefArgs : 255,
|
||||||
maxStringLength : 255,
|
maxStringLength : 255,
|
||||||
sparseArrays : false,
|
|
||||||
tickComments : false,
|
tickComments : false,
|
||||||
validKeywords : ['BASE','DATA','DEF','DIM','END',
|
validKeywords : ['BASE','DATA','DEF','DIM','END',
|
||||||
'FOR','GO','GOSUB','GOTO','IF','INPUT','LET','NEXT','ON','OPTION','PRINT',
|
'FOR','GO','GOSUB','GOTO','IF','INPUT','LET','NEXT','ON','OPTION','PRINT',
|
||||||
'RANDOMIZE','READ','REM','RESTORE','RETURN','STEP','STOP','SUB','THEN','TO'
|
'RANDOMIZE','READ','REM','RESTORE','RETURN','STEP','STOP','SUB','THEN','TO'
|
||||||
], // TODO: no ON...GOSUB
|
],
|
||||||
validFunctions : ['ABS','ATN','COS','EXP','INT','LOG','RND','SGN','SIN','SQR','TAB','TAN'],
|
validFunctions : ['ABS','ATN','COS','EXP','INT','LOG','RND','SGN','SIN','SQR','TAB','TAN'],
|
||||||
validOperators : ['=', '<>', '<', '>', '<=', '>=', '+', '-', '*', '/', '^'],
|
validOperators : ['=', '<>', '<', '>', '<=', '>=', '+', '-', '*', '/', '^'],
|
||||||
printZoneLength : 15,
|
printZoneLength : 15,
|
||||||
numericPadding : true,
|
numericPadding : true,
|
||||||
checkOverflow : true,
|
checkOverflow : true,
|
||||||
outOfOrderNext : false,
|
testInitialFor : true,
|
||||||
multipleNextVars : false,
|
|
||||||
ifElse : false,
|
ifElse : false,
|
||||||
bitwiseLogic : false,
|
bitwiseLogic : false,
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ALTAIR_BASIC40 : BASICOptions = {
|
export const BASICODE : BASICOptions = {
|
||||||
dialectName: "ALTAIR40",
|
dialectName: "BASICODE",
|
||||||
asciiOnly : true,
|
asciiOnly : true,
|
||||||
uppercaseOnly : true,
|
uppercaseOnly : true,
|
||||||
optionalLabels : false,
|
optionalLabels : false,
|
||||||
strictVarNames : false,
|
optionalWhitespace : true,
|
||||||
|
varNaming : "AA",
|
||||||
|
staticArrays : true,
|
||||||
|
sharedArrayNamespace : false,
|
||||||
|
defaultArrayBase : 0,
|
||||||
|
defaultArraySize : 11,
|
||||||
|
defaultValues : false,
|
||||||
|
stringConcat : true,
|
||||||
|
typeConvert : false,
|
||||||
|
maxDimensions : 2,
|
||||||
|
maxDefArgs : 255,
|
||||||
|
maxStringLength : 255,
|
||||||
|
tickComments : false,
|
||||||
|
validKeywords : ['BASE','DATA','DEF','DIM','END',
|
||||||
|
'FOR','GO','GOSUB','GOTO','IF','INPUT','LET','NEXT','ON','OPTION','PRINT',
|
||||||
|
'READ','REM','RESTORE','RETURN','STEP','STOP','SUB','THEN','TO'
|
||||||
|
],
|
||||||
|
validFunctions : ['ABS','ASC','ATN','CHR$','COS','EXP','INT','LEFT$','LEN','LOG',
|
||||||
|
'MID$','RIGHT$','SGN','SIN','SQR','TAB','TAN','VAL'],
|
||||||
|
validOperators : ['=', '<>', '<', '>', '<=', '>=', '+', '-', '*', '/', '^', 'AND', 'NOT', 'OR'],
|
||||||
|
printZoneLength : 15,
|
||||||
|
numericPadding : true,
|
||||||
|
checkOverflow : true,
|
||||||
|
testInitialFor : true,
|
||||||
|
ifElse : false,
|
||||||
|
bitwiseLogic : false,
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ALTAIR_BASIC41 : BASICOptions = {
|
||||||
|
dialectName: "ALTAIR41",
|
||||||
|
asciiOnly : true,
|
||||||
|
uppercaseOnly : true,
|
||||||
|
optionalLabels : false,
|
||||||
|
optionalWhitespace : true,
|
||||||
|
varNaming : "*", // or AA
|
||||||
|
staticArrays : false,
|
||||||
sharedArrayNamespace : true,
|
sharedArrayNamespace : true,
|
||||||
defaultArrayBase : 0,
|
defaultArrayBase : 0,
|
||||||
defaultArraySize : 11,
|
defaultArraySize : 11,
|
||||||
@ -862,16 +938,21 @@ export const ALTAIR_BASIC40 : BASICOptions = {
|
|||||||
maxDimensions : 128, // "as many as will fit on a single line" ... ?
|
maxDimensions : 128, // "as many as will fit on a single line" ... ?
|
||||||
maxDefArgs : 255,
|
maxDefArgs : 255,
|
||||||
maxStringLength : 255,
|
maxStringLength : 255,
|
||||||
sparseArrays : false,
|
|
||||||
tickComments : false,
|
tickComments : false,
|
||||||
validKeywords : null, // all
|
validKeywords : [
|
||||||
|
'OPTION',
|
||||||
|
'CONSOLE','DATA','DEF','DEFUSR','DIM','END','ERASE','ERROR',
|
||||||
|
'FOR','GOTO','GOSUB','IF','THEN','ELSE','INPUT','LET','LINE',
|
||||||
|
'PRINT','LPRINT','USING','NEXT','ON','OUT','POKE',
|
||||||
|
'READ','REM','RESTORE','RESUME','RETURN','STOP','SWAP',
|
||||||
|
'TROFF','TRON','WAIT'],
|
||||||
validFunctions : null, // all
|
validFunctions : null, // all
|
||||||
validOperators : null, // all
|
validOperators : null, // all
|
||||||
printZoneLength : 15,
|
printZoneLength : 15,
|
||||||
numericPadding : true,
|
numericPadding : true,
|
||||||
checkOverflow : true,
|
checkOverflow : true,
|
||||||
outOfOrderNext : true,
|
testInitialFor : false,
|
||||||
multipleNextVars : true, // TODO: not supported
|
//multipleNextVars : true, // TODO: not supported
|
||||||
ifElse : true,
|
ifElse : true,
|
||||||
bitwiseLogic : true,
|
bitwiseLogic : true,
|
||||||
}
|
}
|
||||||
@ -881,21 +962,22 @@ export const APPLESOFT_BASIC : BASICOptions = {
|
|||||||
asciiOnly : true,
|
asciiOnly : true,
|
||||||
uppercaseOnly : false,
|
uppercaseOnly : false,
|
||||||
optionalLabels : false,
|
optionalLabels : false,
|
||||||
strictVarNames : false, // TODO: first two alphanum chars
|
optionalWhitespace : true,
|
||||||
|
varNaming : "*", // or AA
|
||||||
|
staticArrays : false,
|
||||||
sharedArrayNamespace : false,
|
sharedArrayNamespace : false,
|
||||||
defaultArrayBase : 0,
|
defaultArrayBase : 0,
|
||||||
defaultArraySize : 9, // A(0) to A(8)
|
defaultArraySize : 11,
|
||||||
defaultValues : true,
|
defaultValues : true,
|
||||||
stringConcat : true,
|
stringConcat : true,
|
||||||
typeConvert : false,
|
typeConvert : false,
|
||||||
maxDimensions : 88,
|
maxDimensions : 88,
|
||||||
maxDefArgs : 1, // TODO: no string FNs
|
maxDefArgs : 1, // TODO: no string FNs
|
||||||
maxStringLength : 255,
|
maxStringLength : 255,
|
||||||
sparseArrays : false,
|
|
||||||
tickComments : false,
|
tickComments : false,
|
||||||
validKeywords : [
|
validKeywords : [
|
||||||
'OPTION',
|
'OPTION',
|
||||||
'CLEAR','LET','DIM','DEF','FN','GOTO','GOSUB','RETURN','ON','POP',
|
'CLEAR','LET','DIM','DEF','GOTO','GOSUB','RETURN','ON','POP',
|
||||||
'FOR','TO','NEXT','IF','THEN','END','STOP','ONERR','RESUME',
|
'FOR','TO','NEXT','IF','THEN','END','STOP','ONERR','RESUME',
|
||||||
'PRINT','INPUT','GET','HOME','HTAB','VTAB',
|
'PRINT','INPUT','GET','HOME','HTAB','VTAB',
|
||||||
'INVERSE','FLASH','NORMAL','TEXT',
|
'INVERSE','FLASH','NORMAL','TEXT',
|
||||||
@ -911,8 +993,7 @@ export const APPLESOFT_BASIC : BASICOptions = {
|
|||||||
printZoneLength : 16,
|
printZoneLength : 16,
|
||||||
numericPadding : false,
|
numericPadding : false,
|
||||||
checkOverflow : true,
|
checkOverflow : true,
|
||||||
outOfOrderNext : true,
|
testInitialFor : false,
|
||||||
multipleNextVars : false,
|
|
||||||
ifElse : false,
|
ifElse : false,
|
||||||
bitwiseLogic : false,
|
bitwiseLogic : false,
|
||||||
}
|
}
|
||||||
@ -922,39 +1003,40 @@ export const MODERN_BASIC : BASICOptions = {
|
|||||||
asciiOnly : false,
|
asciiOnly : false,
|
||||||
uppercaseOnly : false,
|
uppercaseOnly : false,
|
||||||
optionalLabels : true,
|
optionalLabels : true,
|
||||||
strictVarNames : false,
|
optionalWhitespace : false,
|
||||||
|
varNaming : "*",
|
||||||
|
staticArrays : false,
|
||||||
sharedArrayNamespace : false,
|
sharedArrayNamespace : false,
|
||||||
defaultArrayBase : 0,
|
defaultArrayBase : 0,
|
||||||
defaultArraySize : 11,
|
defaultArraySize : 0, // DIM required
|
||||||
defaultValues : false,
|
defaultValues : false,
|
||||||
stringConcat : true,
|
stringConcat : true,
|
||||||
typeConvert : true,
|
typeConvert : true,
|
||||||
maxDimensions : 255,
|
maxDimensions : 255,
|
||||||
maxDefArgs : 255,
|
maxDefArgs : 255,
|
||||||
maxStringLength : 1024, // TODO?
|
maxStringLength : 2048, // TODO?
|
||||||
sparseArrays : false,
|
|
||||||
tickComments : true,
|
tickComments : true,
|
||||||
validKeywords : null, // all
|
validKeywords : null, // all
|
||||||
validFunctions : null, // all
|
validFunctions : null, // all
|
||||||
validOperators : null, // all
|
validOperators : null, // all
|
||||||
printZoneLength : 15,
|
printZoneLength : 16,
|
||||||
numericPadding : false,
|
numericPadding : false,
|
||||||
checkOverflow : true,
|
checkOverflow : true,
|
||||||
outOfOrderNext : true,
|
testInitialFor : true,
|
||||||
multipleNextVars : true,
|
|
||||||
ifElse : true,
|
ifElse : true,
|
||||||
bitwiseLogic : true,
|
bitwiseLogic : true,
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: integer vars
|
// TODO: integer vars
|
||||||
// TODO: short-circuit FOR loop
|
// TODO: DEFINT/DEFSTR
|
||||||
|
|
||||||
export const DIALECTS = {
|
export const DIALECTS = {
|
||||||
"DEFAULT": ALTAIR_BASIC40,
|
"DEFAULT": ALTAIR_BASIC41,
|
||||||
"ALTAIR": ALTAIR_BASIC40,
|
"ALTAIR": ALTAIR_BASIC41,
|
||||||
"ALTAIR40": ALTAIR_BASIC40,
|
"ALTAIR41": ALTAIR_BASIC41,
|
||||||
"ECMA55": ECMA55_MINIMAL,
|
"ECMA55": ECMA55_MINIMAL,
|
||||||
"MINIMAL": ECMA55_MINIMAL,
|
"MINIMAL": ECMA55_MINIMAL,
|
||||||
|
"BASICODE": BASICODE,
|
||||||
"APPLESOFT": APPLESOFT_BASIC,
|
"APPLESOFT": APPLESOFT_BASIC,
|
||||||
"MODERN": MODERN_BASIC,
|
"MODERN": MODERN_BASIC,
|
||||||
};
|
};
|
||||||
|
@ -48,7 +48,8 @@ export class BASICRuntime {
|
|||||||
vars : {};
|
vars : {};
|
||||||
arrays : {};
|
arrays : {};
|
||||||
defs : {};
|
defs : {};
|
||||||
forLoops : {varname:string, next:(name:string) => void}[];
|
forLoops : { [varname:string] : { $next:(name:string) => void, inner:string } };
|
||||||
|
topForLoopName : string;
|
||||||
returnStack : number[];
|
returnStack : number[];
|
||||||
column : number;
|
column : number;
|
||||||
|
|
||||||
@ -70,23 +71,26 @@ export class BASICRuntime {
|
|||||||
// TODO: lines start @ 1?
|
// TODO: lines start @ 1?
|
||||||
program.lines.forEach((line, idx) => {
|
program.lines.forEach((line, idx) => {
|
||||||
// make lookup tables
|
// make lookup tables
|
||||||
this.curpc = this.allstmts.length + 1; // set for error reporting
|
|
||||||
if (line.label != null) this.label2lineidx[line.label] = idx;
|
if (line.label != null) this.label2lineidx[line.label] = idx;
|
||||||
if (line.label != null) this.label2pc[line.label] = this.allstmts.length;
|
if (line.label != null) this.label2pc[line.label] = this.allstmts.length;
|
||||||
this.line2pc.push(this.allstmts.length);
|
this.line2pc.push(this.allstmts.length);
|
||||||
this.pc2line.set(this.allstmts.length, idx);
|
this.pc2line.set(this.allstmts.length, idx);
|
||||||
// combine all statements into single list
|
// combine all statements into single list
|
||||||
line.stmts.forEach((stmt) => this.allstmts.push(stmt));
|
line.stmts.forEach((stmt) => this.allstmts.push(stmt));
|
||||||
// parse DATA literals
|
});
|
||||||
line.stmts.filter((stmt) => stmt.command == 'DATA').forEach((datastmt) => {
|
// compile statements ahead of time
|
||||||
(datastmt as basic.DATA_Statement).datums.forEach(d => {
|
this.allstmts.forEach((stmt, pc) => {
|
||||||
var functext = this.expr2js(d, {isconst:true});
|
this.curpc = pc + 1; // for error reporting
|
||||||
var value = new Function(`return ${functext};`).bind(this)();
|
this.compileStatement(stmt);
|
||||||
this.datums.push({value:value});
|
});
|
||||||
});
|
// parse DATA literals
|
||||||
|
this.allstmts.filter((stmt) => stmt.command == 'DATA').forEach((datastmt) => {
|
||||||
|
(datastmt as basic.DATA_Statement).datums.forEach(d => {
|
||||||
|
//this.curpc = datastmt.$loc.offset; // for error reporting
|
||||||
|
var functext = this.expr2js(d, {isconst:true});
|
||||||
|
var value = new Function(`return ${functext};`).bind(this)();
|
||||||
|
this.datums.push({value:value});
|
||||||
});
|
});
|
||||||
// compile statements ahead of time
|
|
||||||
line.stmts.forEach((stmt) => this.compileStatement(stmt));
|
|
||||||
});
|
});
|
||||||
// try to resume where we left off after loading
|
// try to resume where we left off after loading
|
||||||
this.curpc = this.label2pc[prevlabel] || 0;
|
this.curpc = this.label2pc[prevlabel] || 0;
|
||||||
@ -97,7 +101,6 @@ export class BASICRuntime {
|
|||||||
this.curpc = 0;
|
this.curpc = 0;
|
||||||
this.dataptr = 0;
|
this.dataptr = 0;
|
||||||
this.clearVars();
|
this.clearVars();
|
||||||
this.forLoops = [];
|
|
||||||
this.returnStack = [];
|
this.returnStack = [];
|
||||||
this.column = 0;
|
this.column = 0;
|
||||||
this.running = true;
|
this.running = true;
|
||||||
@ -107,6 +110,14 @@ export class BASICRuntime {
|
|||||||
this.vars = {};
|
this.vars = {};
|
||||||
this.arrays = {};
|
this.arrays = {};
|
||||||
this.defs = {}; // TODO? only in interpreters
|
this.defs = {}; // TODO? only in interpreters
|
||||||
|
this.forLoops = {};
|
||||||
|
this.topForLoopName = null;
|
||||||
|
// initialize arrays?
|
||||||
|
if (this.opts && this.opts.staticArrays) {
|
||||||
|
this.allstmts.filter((stmt) => stmt.command == 'DIM').forEach((dimstmt: basic.DIM_Statement) => {
|
||||||
|
dimstmt.args.forEach( (arg) => this.compileJS(this._DIM(arg))() );
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getBuiltinFunctions() {
|
getBuiltinFunctions() {
|
||||||
@ -175,13 +186,16 @@ export class BASICRuntime {
|
|||||||
if (stmtfn == null) this.runtimeError(`I don't know how to "${stmt.command}".`);
|
if (stmtfn == null) this.runtimeError(`I don't know how to "${stmt.command}".`);
|
||||||
var functext = stmtfn.bind(this)(stmt);
|
var functext = stmtfn.bind(this)(stmt);
|
||||||
if (this.trace) console.log(functext);
|
if (this.trace) console.log(functext);
|
||||||
stmt.$run = new Function(functext).bind(this);
|
stmt.$run = this.compileJS(functext);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(functext);
|
console.log(functext);
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
compileJS(functext: string) : () => void {
|
||||||
|
return new Function(functext).bind(this);
|
||||||
|
}
|
||||||
executeStatement(stmt: basic.Statement & CompiledStatement) {
|
executeStatement(stmt: basic.Statement & CompiledStatement) {
|
||||||
// compile (unless cached)
|
// compile (unless cached)
|
||||||
this.compileStatement(stmt);
|
this.compileStatement(stmt);
|
||||||
@ -212,6 +226,22 @@ export class BASICRuntime {
|
|||||||
this.curpc = this.allstmts.length;
|
this.curpc = this.allstmts.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
skipToAfterNext(forname: string) : void {
|
||||||
|
var pc = this.curpc;
|
||||||
|
while (pc < this.allstmts.length) {
|
||||||
|
var stmt = this.allstmts[pc];
|
||||||
|
if (stmt.command == 'NEXT') {
|
||||||
|
var nextlexpr = (stmt as basic.NEXT_Statement).lexpr;
|
||||||
|
if (nextlexpr && nextlexpr.name == forname) {
|
||||||
|
this.curpc = pc + 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pc++;
|
||||||
|
}
|
||||||
|
this.runtimeError(`I couldn't find a matching NEXT ${forname} to skip this for loop.`);
|
||||||
|
}
|
||||||
|
|
||||||
gotoLabel(label) {
|
gotoLabel(label) {
|
||||||
var pc = this.label2pc[label];
|
var pc = this.label2pc[label];
|
||||||
if (pc >= 0) {
|
if (pc >= 0) {
|
||||||
@ -300,9 +330,11 @@ export class BASICRuntime {
|
|||||||
if (!expr.args && opts.locals && opts.locals.indexOf(expr.name) >= 0) {
|
if (!expr.args && opts.locals && opts.locals.indexOf(expr.name) >= 0) {
|
||||||
return expr.name; // local arg in DEF
|
return expr.name; // local arg in DEF
|
||||||
} else {
|
} else {
|
||||||
|
if (opts.isconst)
|
||||||
|
this.runtimeError(`I expected a constant value here.`); // TODO: check at compile-time?
|
||||||
var s = '';
|
var s = '';
|
||||||
var qname = JSON.stringify(expr.name);
|
var qname = JSON.stringify(expr.name);
|
||||||
let jsargs = expr.args && expr.args.map((arg) => this.expr2js(arg, opts)).join(', ');
|
let jsargs = expr.args ? expr.args.map((arg) => this.expr2js(arg, opts)).join(', ') : [];
|
||||||
if (expr.name.startsWith("FN")) { // is it a user-defined function?
|
if (expr.name.startsWith("FN")) { // is it a user-defined function?
|
||||||
// TODO: check argument count?
|
// TODO: check argument count?
|
||||||
s += `this.getDef(${qname})(${jsargs})`;
|
s += `this.getDef(${qname})(${jsargs})`;
|
||||||
@ -347,6 +379,8 @@ export class BASICRuntime {
|
|||||||
checkFuncArgs(expr: basic.IndOp, fn: Function) {
|
checkFuncArgs(expr: basic.IndOp, fn: Function) {
|
||||||
// TODO: check types?
|
// TODO: check types?
|
||||||
var nargs = expr.args ? expr.args.length : 0;
|
var nargs = expr.args ? expr.args.length : 0;
|
||||||
|
// exceptions
|
||||||
|
if (expr.name == 'RND' && nargs == 0) return;
|
||||||
if (expr.name == 'MID$' && nargs == 2) return;
|
if (expr.name == 'MID$' && nargs == 2) return;
|
||||||
if (expr.name == 'INSTR' && nargs == 2) return;
|
if (expr.name == 'INSTR' && nargs == 2) return;
|
||||||
if (fn.length != nargs)
|
if (fn.length != nargs)
|
||||||
@ -354,40 +388,44 @@ export class BASICRuntime {
|
|||||||
}
|
}
|
||||||
|
|
||||||
startForLoop(forname, init, targ, step) {
|
startForLoop(forname, init, targ, step) {
|
||||||
// TODO: support 0-iteration loops
|
|
||||||
var pc = this.curpc;
|
var pc = this.curpc;
|
||||||
if (!step) step = 1;
|
if (!step) step = 1;
|
||||||
this.vars[forname] = init;
|
this.vars[forname] = init;
|
||||||
if (this.trace) console.log(`FOR ${forname} = ${init} TO ${targ} STEP ${step}`);
|
if (this.trace) console.log(`FOR ${forname} = ${init} TO ${targ} STEP ${step}`);
|
||||||
this.forLoops.unshift({
|
// create done function
|
||||||
varname: forname,
|
var loopdone = () => {
|
||||||
next: (nextname:string) => {
|
return step >= 0 ? this.vars[forname] > targ : this.vars[forname] < targ;
|
||||||
|
}
|
||||||
|
// skip entire for loop before first iteration? (Minimal BASIC)
|
||||||
|
if (this.opts.testInitialFor && loopdone())
|
||||||
|
return this.skipToAfterNext(forname);
|
||||||
|
// save for var name on top of linked-list stack
|
||||||
|
var inner = this.topForLoopName;
|
||||||
|
this.topForLoopName = forname;
|
||||||
|
// create for loop record
|
||||||
|
this.forLoops[forname] = {
|
||||||
|
inner: inner,
|
||||||
|
$next: (nextname:string) => {
|
||||||
if (nextname && forname != nextname)
|
if (nextname && forname != nextname)
|
||||||
this.runtimeError(`I executed NEXT "${nextname}", but the last FOR was for "${forname}".`)
|
this.runtimeError(`I executed NEXT "${nextname}", but the last FOR was for "${forname}".`)
|
||||||
this.vars[forname] += step;
|
this.vars[forname] += step;
|
||||||
var done = step >= 0 ? this.vars[forname] > targ : this.vars[forname] < targ;
|
var done = loopdone();
|
||||||
if (done) {
|
if (done) {
|
||||||
this.forLoops.shift(); // pop FOR off the stack and continue
|
// pop FOR off the stack and continue
|
||||||
|
this.topForLoopName = inner;
|
||||||
|
delete this.forLoops[forname];
|
||||||
} else {
|
} else {
|
||||||
this.curpc = pc; // go back to FOR location
|
this.curpc = pc; // go back to FOR location
|
||||||
}
|
}
|
||||||
if (this.trace) console.log(`NEXT ${forname}: ${this.vars[forname]} TO ${targ} STEP ${step} DONE=${done}`);
|
if (this.trace) console.log(`NEXT ${forname}: ${this.vars[forname]} TO ${targ} STEP ${step} DONE=${done}`);
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
nextForLoop(name) {
|
nextForLoop(name) {
|
||||||
var fl = this.forLoops[0];
|
var fl = this.forLoops[name];
|
||||||
if (fl != null && name != null && fl.varname != name) {
|
|
||||||
if (!this.opts.outOfOrderNext) this.dialectError(`execute out-of-order NEXT statements`);
|
|
||||||
while (fl) {
|
|
||||||
if (fl.varname == name) break;
|
|
||||||
this.forLoops.shift();
|
|
||||||
fl = this.forLoops[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!fl) this.runtimeError(`I couldn't find a FOR for this NEXT.`)
|
if (!fl) this.runtimeError(`I couldn't find a FOR for this NEXT.`)
|
||||||
fl.next(name);
|
fl.$next(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
// converts a variable to string/number based on var name
|
// converts a variable to string/number based on var name
|
||||||
@ -425,11 +463,13 @@ export class BASICRuntime {
|
|||||||
// dimension array
|
// dimension array
|
||||||
dimArray(name: string, ...dims:number[]) {
|
dimArray(name: string, ...dims:number[]) {
|
||||||
// TODO: maybe do this check at compile-time?
|
// TODO: maybe do this check at compile-time?
|
||||||
if (this.arrays[name]) this.runtimeError(`I already dimensioned this array (${name}) earlier.`)
|
if (this.arrays[name] != null) {
|
||||||
|
if (this.opts.staticArrays) return;
|
||||||
|
else this.runtimeError(`I already dimensioned this array (${name}) earlier.`)
|
||||||
|
}
|
||||||
var isstring = name.endsWith('$');
|
var isstring = name.endsWith('$');
|
||||||
// if defaultValues is true, we use Float64Array which inits to 0
|
// if numeric value, we use Float64Array which inits to 0
|
||||||
var arrcons = isstring || !this.opts.defaultValues ? Array : Float64Array;
|
var arrcons = isstring ? Array : Float64Array;
|
||||||
// TODO? var ab = this.opts.defaultArrayBase;
|
|
||||||
if (dims.length == 1) {
|
if (dims.length == 1) {
|
||||||
this.arrays[name] = new arrcons(dims[0]+1);
|
this.arrays[name] = new arrcons(dims[0]+1);
|
||||||
} else if (dims.length == 2) {
|
} else if (dims.length == 2) {
|
||||||
@ -444,10 +484,12 @@ export class BASICRuntime {
|
|||||||
|
|
||||||
getArray(name: string, order: number) : [] {
|
getArray(name: string, order: number) : [] {
|
||||||
if (!this.arrays[name]) {
|
if (!this.arrays[name]) {
|
||||||
|
if (this.opts.defaultArraySize == 0)
|
||||||
|
this.dialectError(`automatically declare arrays without a DIM statement`);
|
||||||
if (order == 1)
|
if (order == 1)
|
||||||
this.dimArray(name, this.opts.defaultArraySize);
|
this.dimArray(name, this.opts.defaultArraySize-1);
|
||||||
else if (order == 2)
|
else if (order == 2)
|
||||||
this.dimArray(name, this.opts.defaultArraySize, this.opts.defaultArraySize);
|
this.dimArray(name, this.opts.defaultArraySize-1, this.opts.defaultArraySize-1);
|
||||||
else
|
else
|
||||||
this.runtimeError(`I only support arrays of one or two dimensions.`); // TODO
|
this.runtimeError(`I only support arrays of one or two dimensions.`); // TODO
|
||||||
}
|
}
|
||||||
@ -464,7 +506,7 @@ export class BASICRuntime {
|
|||||||
this.runtimeError(`I tried to lookup ${name}(${indices}) but used too many dimensions.`);
|
this.runtimeError(`I tried to lookup ${name}(${indices}) but used too many dimensions.`);
|
||||||
if (idx < this.opts.defaultArrayBase)
|
if (idx < this.opts.defaultArrayBase)
|
||||||
this.runtimeError(`I tried to lookup ${name}(${indices}) but an index was less than ${this.opts.defaultArrayBase}.`);
|
this.runtimeError(`I tried to lookup ${name}(${indices}) but an index was less than ${this.opts.defaultArrayBase}.`);
|
||||||
if (idx >= v.length)
|
if (idx >= v.length) // TODO: also can happen when mispelling function name
|
||||||
this.runtimeError(`I tried to lookup ${name}(${indices}) but it exceeded the dimensions of the array.`);
|
this.runtimeError(`I tried to lookup ${name}(${indices}) but it exceeded the dimensions of the array.`);
|
||||||
v = v[indices[i]];
|
v = v[indices[i]];
|
||||||
}
|
}
|
||||||
@ -572,12 +614,13 @@ export class BASICRuntime {
|
|||||||
var argsstr = '';
|
var argsstr = '';
|
||||||
for (var arg of dim.args) {
|
for (var arg of dim.args) {
|
||||||
// TODO: check for float (or at compile time)
|
// TODO: check for float (or at compile time)
|
||||||
argsstr += ', ' + this.expr2js(arg);
|
argsstr += ', ' + this.expr2js(arg, {isconst: this.opts.staticArrays});
|
||||||
}
|
}
|
||||||
return `this.dimArray(${JSON.stringify(dim.name)}${argsstr});`;
|
return `this.dimArray(${JSON.stringify(dim.name)}${argsstr});`;
|
||||||
}
|
}
|
||||||
|
|
||||||
do__DIM(stmt : basic.DIM_Statement) {
|
do__DIM(stmt : basic.DIM_Statement) {
|
||||||
|
if (this.opts.staticArrays) return; // DIM at reset()
|
||||||
var s = '';
|
var s = '';
|
||||||
stmt.args.forEach((dim) => s += this._DIM(dim));
|
stmt.args.forEach((dim) => s += this._DIM(dim));
|
||||||
return s;
|
return s;
|
||||||
|
@ -2,7 +2,9 @@
|
|||||||
export class TeleType {
|
export class TeleType {
|
||||||
page: HTMLElement;
|
page: HTMLElement;
|
||||||
fixed: boolean;
|
fixed: boolean;
|
||||||
|
ncols: number = 80;
|
||||||
scrolldiv: HTMLElement;
|
scrolldiv: HTMLElement;
|
||||||
|
bell; // Audio
|
||||||
|
|
||||||
curline: HTMLElement;
|
curline: HTMLElement;
|
||||||
curstyle: number;
|
curstyle: number;
|
||||||
@ -52,6 +54,17 @@ export class TeleType {
|
|||||||
this.addtext(line[i], style);
|
this.addtext(line[i], style);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// process control codes
|
||||||
|
if (line.length == 1) {
|
||||||
|
var ch = line.charCodeAt(0);
|
||||||
|
switch (ch) {
|
||||||
|
case 7: if (this.bell) this.bell.play(); break;
|
||||||
|
case 8: if (this.col > 0) this.col--; break;
|
||||||
|
case 12: this.formfeed(); break;
|
||||||
|
case 13: this.col = 0; break;
|
||||||
|
}
|
||||||
|
if (ch < 32) return; // ignore non-printables
|
||||||
|
}
|
||||||
var span = $("<span/>").text(line);
|
var span = $("<span/>").text(line);
|
||||||
for (var i = 0; i < 8; i++) {
|
for (var i = 0; i < 8; i++) {
|
||||||
if (style & (1 << i))
|
if (style & (1 << i))
|
||||||
@ -66,7 +79,8 @@ export class TeleType {
|
|||||||
span.appendTo(this.curline);
|
span.appendTo(this.curline);
|
||||||
}
|
}
|
||||||
this.col += line.length;
|
this.col += line.length;
|
||||||
// TODO: wrap @ 80 columns
|
// wrap @ 80 columns (TODO: const)
|
||||||
|
if (this.fixed && this.col >= this.ncols) this.newline();
|
||||||
this.ncharsout += line.length;
|
this.ncharsout += line.length;
|
||||||
this.movePrintHead(true);
|
this.movePrintHead(true);
|
||||||
}
|
}
|
||||||
@ -117,7 +131,7 @@ export class TeleType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
formfeed() {
|
formfeed() {
|
||||||
this.newline();
|
for (var i=0; i<60; i++) { this.newline(); this.ensureline(); }
|
||||||
}
|
}
|
||||||
scrollToBottom() {
|
scrollToBottom() {
|
||||||
this.curline.scrollIntoView();
|
this.curline.scrollIntoView();
|
||||||
|
@ -1098,6 +1098,17 @@ function showErrorAlert(errors : WorkerError[]) {
|
|||||||
$("#error_alert").show();
|
$("#error_alert").show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function showExceptionAsError(err, msg:string) {
|
||||||
|
var werr : WorkerError = {msg:msg, line:0};
|
||||||
|
if (err instanceof EmuHalt && err.$loc) {
|
||||||
|
werr = Object.create(err.$loc);
|
||||||
|
werr.msg = msg;
|
||||||
|
console.log(werr);
|
||||||
|
projectWindows.refresh(false);
|
||||||
|
}
|
||||||
|
showErrorAlert([werr]);
|
||||||
|
}
|
||||||
|
|
||||||
var measureTimeStart : Date = new Date();
|
var measureTimeStart : Date = new Date();
|
||||||
var measureTimeLoad : Date;
|
var measureTimeLoad : Date;
|
||||||
function measureBuildTime() {
|
function measureBuildTime() {
|
||||||
@ -1133,7 +1144,7 @@ function setCompileOutput(data: WorkerResult) {
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(e);
|
console.log(e);
|
||||||
toolbar.addClass("has-errors");
|
toolbar.addClass("has-errors");
|
||||||
showErrorAlert([{msg:e+"",line:0}]);
|
showExceptionAsError(e, e+"");
|
||||||
current_output = null;
|
current_output = null;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1885,14 +1896,7 @@ function globalErrorHandler(msgevent) {
|
|||||||
requestPersistPermission(false, false);
|
requestPersistPermission(false, false);
|
||||||
} else {
|
} else {
|
||||||
var err = msgevent.error;
|
var err = msgevent.error;
|
||||||
var werr : WorkerError = {msg:msg, line:0};
|
showExceptionAsError(err, msg);
|
||||||
if (err instanceof EmuHalt && err.$loc) {
|
|
||||||
werr = Object.create(err.$loc);
|
|
||||||
werr.msg = msg;
|
|
||||||
console.log(werr);
|
|
||||||
projectWindows.refresh(false);
|
|
||||||
}
|
|
||||||
showErrorAlert([werr]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -379,6 +379,7 @@ export class SourceEditor implements ProjectView {
|
|||||||
|
|
||||||
refreshDebugState(moveCursor:boolean) {
|
refreshDebugState(moveCursor:boolean) {
|
||||||
// TODO: only if line changed
|
// TODO: only if line changed
|
||||||
|
// TODO: remove after compilation restarts platform
|
||||||
this.clearCurrentLine(moveCursor);
|
this.clearCurrentLine(moveCursor);
|
||||||
var line = this.getActiveLine();
|
var line = this.getActiveLine();
|
||||||
if (line) {
|
if (line) {
|
||||||
|
@ -48,6 +48,7 @@ class BASICPlatform implements Platform {
|
|||||||
//var printshield = $('<div id="printhead" class="transcript-print-shield"/>').appendTo(parent);
|
//var printshield = $('<div id="printhead" class="transcript-print-shield"/>').appendTo(parent);
|
||||||
this.tty = new TeleTypeWithKeyboard(windowport[0], true, inputline[0] as HTMLInputElement);
|
this.tty = new TeleTypeWithKeyboard(windowport[0], true, inputline[0] as HTMLInputElement);
|
||||||
this.tty.scrolldiv = parent;
|
this.tty.scrolldiv = parent;
|
||||||
|
this.tty.bell = new Audio('res/ttybell.mp3');
|
||||||
this.runtime.input = async (prompt:string, nargs:number) => {
|
this.runtime.input = async (prompt:string, nargs:number) => {
|
||||||
return new Promise( (resolve, reject) => {
|
return new Promise( (resolve, reject) => {
|
||||||
if (prompt != null) {
|
if (prompt != null) {
|
||||||
|
Loading…
Reference in New Issue
Block a user