Skip to content

Commit 54d0097

Browse files
committed
add dynamic RSX commands defined by addRsx (needed for speech.rsx example)
1 parent 30ca9c6 commit 54d0097

9 files changed

Lines changed: 97 additions & 9 deletions

File tree

CodeGeneratorJs.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -457,9 +457,9 @@ CodeGeneratorJs.prototype = {
457457
sLabel = that.iLine + "s" + that.iStopCount; // we use stopCount
458458
that.iStopCount += 1;
459459

460-
if (!bRsxAvailable) { // if RSX not available, we delay the error until it is executed (or catched by on error goto)
460+
if (!bRsxAvailable) { // if RSX not available at compile time, delay error until execution (supports dynamic/temporary RSX)
461461
aNodeArgs.unshift('"' + sRsxName + '"'); // put as first arg
462-
sRsxName = "rsxExec"; // and call special handler which triggers error if not available
462+
sRsxName = "rsxExec"; // and call dispatcher which handles both temporary and permanent RSX
463463
}
464464

465465
node.pv = "o.rsx." + sRsxName + "(" + aNodeArgs.join(", ") + "); o.goto(\"" + sLabel + "\"); break;\ncase \"" + sLabel + "\":"; // most RSX commands need goto (era, ren,...)

Controller.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,23 @@ Controller.prototype = {
216216
return sKey;
217217
},
218218

219+
addRsx(sKey, oRsxConstructor) {
220+
var oExample;
221+
222+
if (!sKey) { // maybe ""
223+
sKey = (document.currentScript && document.currentScript.getAttribute("data-key")) || this.model.getProperty("example");
224+
// on IE we can just get the current example
225+
}
226+
227+
oExample = this.model.getExample(sKey);
228+
oExample.key = sKey; // maybe changed
229+
oExample.rsx = true; // mark that example has RSX
230+
oExample.rsxConstructor = oRsxConstructor; // store constructor for later registration
231+
oExample.loaded = true;
232+
Utils.console.log("addRsx:", sKey);
233+
return sKey;
234+
},
235+
219236
setDatabaseSelectOptions: function () {
220237
var sSelect = "databaseSelect",
221238
aItems = [],
@@ -987,6 +1004,13 @@ Controller.prototype = {
9871004
if (!bSuppressLog) {
9881005
Utils.console.log("Example", sUrl, oExample.meta || "", "loaded");
9891006
}
1007+
1008+
// Reset and register temporary RSX if available
1009+
that.oVm.rsx.rsxReset();
1010+
if (oExample.rsxConstructor) {
1011+
that.oVm.rsx.rsxRegister(oExample.rsxConstructor);
1012+
}
1013+
9901014
sInput = oExample.script;
9911015
that.model.setProperty("example", oInFile.sMemorizedExample);
9921016
that.oVm.vmStop("", 0, true);

CpcVm.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,10 @@ CpcVm.prototype = {
353353
return this.oVariables.getAllVariables();
354354
},
355355

356+
vmGetVariableByIndex(index) { // also called from JS script
357+
return this.oVariables.getVariableByIndex(index);
358+
},
359+
356360
vmSetStartLine: function (iLine) {
357361
this.iStartLine = iLine;
358362
},
@@ -737,6 +741,10 @@ CpcVm.prototype = {
737741
return this.oInFile;
738742
},
739743

744+
vmGetKeyboard: function () {
745+
return this.oKeyboard;
746+
},
747+
740748
vmGetOutFileObject: function () {
741749
return this.oOutFile;
742750
},

CpcVmRsx.js

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,18 +18,48 @@ function CpcVmRsx(oVm) {
1818
CpcVmRsx.prototype = {
1919
rsxInit: function (oVm) {
2020
this.oVm = oVm;
21+
this.rsxTemporary = {}; // temporary/dynamic RSX registered at runtime
2122
},
2223

2324
rsxIsAvailable: function (sName) {
24-
return sName in this;
25+
return (sName in this.rsxTemporary) || (sName in this); // check temporary first, then permanent
26+
},
27+
28+
rsxRegister: function (oRsxConstructor) {
29+
// Register temporary RSX from constructor
30+
// Constructor should be a function that returns an object with getRsxCommands() method
31+
var oRsxModule, oRsxCommands, sCommand;
32+
33+
oRsxModule = new oRsxConstructor();
34+
if (oRsxModule.getRsxCommands) {
35+
oRsxCommands = oRsxModule.getRsxCommands();
36+
for (sCommand in oRsxCommands) {
37+
if (oRsxCommands.hasOwnProperty(sCommand)) {
38+
this.rsxTemporary[sCommand] = oRsxCommands[sCommand];
39+
}
40+
}
41+
}
42+
},
43+
44+
rsxReset: function () {
45+
// Clear temporary RSX (called when loading new example)
46+
this.rsxTemporary = {};
2547
},
2648

2749
rsxExec: function (sName) { // varargs
28-
var aArgs;
50+
var aArgs, fnRsx;
2951

30-
if (this.rsxIsAvailable(sName)) {
52+
// Check temporary RSX first, then permanent
53+
if (sName in this.rsxTemporary) {
54+
// Temporary RSX: call with this = CpcVm (the VM instance)
55+
fnRsx = this.rsxTemporary[sName];
56+
aArgs = Array.prototype.slice.call(arguments, 1);
57+
fnRsx.apply(this.oVm, aArgs);
58+
} else if (typeof this[sName] === "function") {
59+
// Permanent RSX: call with this = CpcVmRsx
60+
fnRsx = this[sName];
3161
aArgs = Array.prototype.slice.call(arguments, 1);
32-
this[sName].apply(this, aArgs);
62+
fnRsx.apply(this, aArgs);
3363
} else {
3464
throw this.oVm.vmComposeError(Error(), 28, "|" + sName); // Unknown command
3565
}

Keyboard.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -502,8 +502,12 @@ Keyboard.prototype = {
502502
return sKey;
503503
},
504504

505-
putKeyInBuffer: function (sKey) {
505+
putKeyInBuffer: function (sKey, bTriggerOnKeyDown) {
506506
this.aKeyBuffer.push(sKey);
507+
508+
if (bTriggerOnKeyDown && this.fnOnKeyDown) { // trigger handler for async events (e.g., speech synthesis)
509+
this.fnOnKeyDown(this.aKeyBuffer);
510+
}
507511
},
508512

509513
putKeysInBuffer: function (sInput) {

cpcbasic.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,10 @@ cpcBasic = {
6060
return cpcBasic.controller.addItem(sKey, input);
6161
},
6262

63+
addRsx(sKey, oRsxConstructor) {
64+
return cpcBasic.controller.addRsx(sKey, oRsxConstructor);
65+
},
66+
6367
// https://stackoverflow.com/questions/901115/how-can-i-get-query-string-values-in-javascript
6468
fnParseUri: function (oConfig) {
6569
var aMatch,

index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
55
<meta name="viewport" content="width=device-width, initial-scale=1.0">
66
<link rel="stylesheet" href="cpcbasic.css" />
7-
<title id="title">CPC Basic v0.10.18</title>
7+
<title id="title">CPC Basic v0.10.19</title>
88
</head>
99

1010
<body id="pageBody">

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "cpcbasic",
3-
"version": "0.10.18",
3+
"version": "0.10.19",
44
"description": "# CPCBasic - Run CPC BASIC in a Browser",
55
"main": "cpcbasic.js",
66
"directories": {

test/testParseExamples.qunit.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,20 @@ cpcBasic = {
208208
return sKey;
209209
},
210210

211+
addRsx2(sKey, oRsxConstructor) {
212+
var oExample;
213+
214+
if (!sKey) {
215+
sKey = this.model.getProperty("example");
216+
}
217+
218+
oExample = this.model.getExample(sKey);
219+
oExample.key = sKey; // maybe changed
220+
oExample.rsx = new oRsxConstructor();
221+
oExample.loaded = true;
222+
return sKey;
223+
},
224+
211225
fnHereDoc: function (fn) {
212226
return String(fn).
213227
replace(/^[^/]+\/\*\S*/, "").
@@ -229,6 +243,10 @@ cpcBasic = {
229243
input = this.fnHereDoc(input);
230244
}
231245
return this.addItem2(sKey, input);
246+
},
247+
248+
addRsx(sKey, oRsxConstructor) {
249+
return this.addRsx2(sKey, oRsxConstructor);
232250
}
233251
};
234252

0 commit comments

Comments
 (0)