migration to graal

This commit is contained in:
minjaesong
2020-12-01 14:16:48 +09:00
parent f4c67fee30
commit 6403a84af3
54 changed files with 182 additions and 326 deletions

View File

@@ -0,0 +1,20 @@
<component name="libraryTable">
<library name="org.graalvm.js:js:20.3.0" type="repository">
<properties maven-id="org.graalvm.js:js:20.3.0" />
<CLASSES>
<root url="jar://$PROJECT_DIR$/lib/js-20.3.0.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/regex-20.3.0.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/truffle-api-20.3.0.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/graal-sdk-20.3.0.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/icu4j-67.1.jar!/" />
</CLASSES>
<JAVADOC>
<root url="jar://$PROJECT_DIR$/lib/js-20.3.0-javadoc.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/regex-20.3.0-javadoc.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/truffle-api-20.3.0-javadoc.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/graal-sdk-20.3.0-javadoc.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/icu4j-67.1-javadoc.jar!/" />
</JAVADOC>
<SOURCES />
</library>
</component>

View File

@@ -0,0 +1,14 @@
<component name="libraryTable">
<library name="org.graalvm.js:js-scriptengine:20.3.0" type="repository">
<properties maven-id="org.graalvm.js:js-scriptengine:20.3.0" />
<CLASSES>
<root url="jar://$PROJECT_DIR$/lib/js-scriptengine-20.3.0.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/graal-sdk-20.3.0.jar!/" />
</CLASSES>
<JAVADOC>
<root url="jar://$PROJECT_DIR$/lib/js-scriptengine-20.3.0-javadoc.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/graal-sdk-20.3.0-javadoc.jar!/" />
</JAVADOC>
<SOURCES />
</library>
</component>

View File

@@ -1,26 +0,0 @@
<component name="libraryTable">
<library name="org.jetbrains.kotlin:kotlin-scripting-jsr223:1.3.71" type="repository">
<properties maven-id="org.jetbrains.kotlin:kotlin-scripting-jsr223:1.3.71" />
<CLASSES>
<root url="jar://$PROJECT_DIR$/lib/kotlin-scripting-jsr223-1.3.71.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/kotlin-script-runtime-1.3.71.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/kotlin-stdlib-1.3.71.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/kotlin-stdlib-common-1.3.71.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/annotations-13.0.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/kotlin-scripting-common-1.3.71.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/kotlinx-coroutines-core-1.2.1.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/kotlin-scripting-jvm-1.3.71.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/kotlin-scripting-jvm-host-1.3.71.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/trove4j-1.0.20181211.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/kotlin-scripting-compiler-1.3.71.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/kotlin-scripting-js-1.3.71.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/kotlin-util-klib-1.3.71.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/kotlin-util-io-1.3.71.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/kotlin-scripting-compiler-impl-1.3.71.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/kotlin-compiler-1.3.71.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/kotlin-reflect-1.3.71.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

View File

@@ -0,0 +1,18 @@
<component name="libraryTable">
<library name="org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.1" type="repository">
<properties maven-id="org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.1" />
<CLASSES>
<root url="jar://$PROJECT_DIR$/lib/kotlinx-coroutines-core-1.4.1.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/kotlin-stdlib-1.4.0.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/annotations-13.0.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/kotlin-stdlib-common-1.4.0.jar!/" />
</CLASSES>
<JAVADOC>
<root url="jar://$PROJECT_DIR$/lib/kotlinx-coroutines-core-1.4.1-javadoc.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/kotlin-stdlib-1.4.0-javadoc.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/annotations-13.0-javadoc.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/kotlin-stdlib-common-1.4.0-javadoc.jar!/" />
</JAVADOC>
<SOURCES />
</library>
</component>

View File

@@ -1 +1 @@
let p=_BIOS.FIRST_BOOTABLE_PORT;com.sendMessage(p[0],"DEVRST\x17");com.sendMessage(p[0],'OPENR"tvdos/TVDOS.SYS",'+p[1]);let r=com.getStatusCode(p[0]);if(0==r)if(com.sendMessage(p[0],"READ"),r=com.getStatusCode([0]),0==r){let g=com.pullMessage(p[0]);eval(g)}else println("I/O Error");else println("TVDOS.SYS not found");println("Shutting down...");println("It is now safe to turn off the power"); let p=_BIOS.FIRST_BOOTABLE_PORT;com.sendMessage(p[0],"DEVRST\x17");com.sendMessage(p[0],'OPENR"tvdos/TVDOS.SYS",'+p[1]);let r=com.getStatusCode(p[0]);if(0==r)if(com.sendMessage(p[0],"READ"),r=com.getStatusCode(p[0]),0==r){let g=com.pullMessage(p[0]);eval(g)}else println("I/O Error");else println("TVDOS.SYS not found");println("Shutting down...");println("It is now safe to turn off the power");

View File

@@ -80,11 +80,11 @@ fs._flush = function(portNo) {
// - java.lang.NullPointerException if path is null // - java.lang.NullPointerException if path is null
// - Error if operation mode is not "R", "W" nor "A" // - Error if operation mode is not "R", "W" nor "A"
fs.open = function(path, operationMode) { fs.open = function(path, operationMode) {
let port = _BIOS.FIRST_BOOTABLE_PORT; var port = _BIOS.FIRST_BOOTABLE_PORT;
fs._flush(port[0]); fs._close(port[0]); fs._flush(port[0]); fs._close(port[0]);
let mode = operationMode.toUpperCase(); var mode = operationMode.toUpperCase();
if (mode != "R" && mode != "W" && mode != "A") { if (mode != "R" && mode != "W" && mode != "A") {
throw Error("Unknown file opening mode: " + mode); throw Error("Unknown file opening mode: " + mode);
} }
@@ -95,9 +95,9 @@ fs.open = function(path, operationMode) {
}; };
// @return the entire contents of the file in String // @return the entire contents of the file in String
fs.readAll = function() { fs.readAll = function() {
let port = _BIOS.FIRST_BOOTABLE_PORT; var port = _BIOS.FIRST_BOOTABLE_PORT;
com.sendMessage(port[0], "READ"); com.sendMessage(port[0], "READ");
let response = com.getStatusCode(port[0]); var response = com.getStatusCode(port[0]);
if (135 == response) { if (135 == response) {
throw Error("File not opened"); throw Error("File not opened");
} }
@@ -107,9 +107,9 @@ fs.readAll = function() {
return com.pullMessage(port[0]); return com.pullMessage(port[0]);
}; };
fs.write = function(string) { fs.write = function(string) {
let port = _BIOS.FIRST_BOOTABLE_PORT; var port = _BIOS.FIRST_BOOTABLE_PORT;
com.sendMessage(port[0], "WRITE"+string.length); com.sendMessage(port[0], "WRITE"+string.length);
let response = com.getStatusCode(port[0]); var response = com.getStatusCode(port[0]);
if (135 == response) { if (135 == response) {
throw Error("File not opened"); throw Error("File not opened");
} }
@@ -125,10 +125,10 @@ Object.freeze(fs);
// requirements: reset_graphics(), getch(), curs_set(int), hitterminate(), resetkeybuf(), addch(int) // requirements: reset_graphics(), getch(), curs_set(int), hitterminate(), resetkeybuf(), addch(int)
let getUsedMemSize = function() { let getUsedMemSize = function() {
let varsMemSize = 0; var varsMemSize = 0;
Object.entries(bStatus.vars).forEach(function(pair,i) { Object.entries(bStatus.vars).forEach(function(pair,i) {
let object = pair[1]; var object = pair[1];
if (Array.isArray(object)) { if (Array.isArray(object)) {
// TODO test 1-D array // TODO test 1-D array
@@ -441,14 +441,14 @@ if no arg text were given (e.g. "10 NEXT"), args will have zero length
}, },
"TO" : function(lnum, args) { "TO" : function(lnum, args) {
return twoArgNum(lnum, args, function(from, to) { return twoArgNum(lnum, args, function(from, to) {
let a = []; var a = [];
if (from <= to) { if (from <= to) {
for (let k = from; k <= to; k++) { for (var k = from; k <= to; k++) {
a.push(k); a.push(k);
} }
} }
else { else {
for (let k = -from; k <= -to; k++) { for (var k = -from; k <= -to; k++) {
a.push(-k); a.push(-k);
} }
} }
@@ -464,7 +464,7 @@ if no arg text were given (e.g. "10 NEXT"), args will have zero length
var rsvArg1 = resolve(args[1]); var rsvArg1 = resolve(args[1]);
if (rsvArg1 === undefined) throw lang.refError(lnum, rsvArg1); if (rsvArg1 === undefined) throw lang.refError(lnum, rsvArg1);
if (isNaN(rsvArg1)) throw lang.illegalType(lnum, rsvArg1); if (isNaN(rsvArg1)) throw lang.illegalType(lnum, rsvArg1);
let a = []; let stepcnt = 0; var a = []; var stepcnt = 0;
rsvArg0.forEach(function(v,i) { rsvArg0.forEach(function(v,i) {
if (stepcnt == 0) a.push(v); if (stepcnt == 0) a.push(v);
stepcnt = (stepcnt + 1) % rsvArg1; stepcnt = (stepcnt + 1) % rsvArg1;
@@ -474,8 +474,8 @@ if no arg text were given (e.g. "10 NEXT"), args will have zero length
"DIM" : function(lnum, args) { "DIM" : function(lnum, args) {
return oneArgNum(lnum, args, function(size) { return oneArgNum(lnum, args, function(size) {
if (size <= 0) throw lang.syntaxfehler(lnum, size); if (size <= 0) throw lang.syntaxfehler(lnum, size);
let a = []; var a = [];
for (let k = 0; k < size; k++) a.push(0); for (var k = 0; k < size; k++) a.push(0);
return a; return a;
}); });
}, },
@@ -601,12 +601,12 @@ if no arg text were given (e.g. "10 NEXT"), args will have zero length
return resolve(args[0]); return resolve(args[0]);
}, },
"FOR" : function(lnum, args) { "FOR" : function(lnum, args) {
let asgnObj = resolve(args[0]); var asgnObj = resolve(args[0]);
// type check // type check
if (asgnObj === undefined) throw lang.syntaxfehler(lnum); if (asgnObj === undefined) throw lang.syntaxfehler(lnum);
if (!Array.isArray(asgnObj.asgnValue)) throw lang.illegalType(lnum, asgnObj); if (!Array.isArray(asgnObj.asgnValue)) throw lang.illegalType(lnum, asgnObj);
let varname = asgnObj.asgnVarName; var varname = asgnObj.asgnVarName;
// assign new variable // assign new variable
// the var itself will have head of the array, and the head itself will be removed from the array // the var itself will have head of the array, and the head itself will be removed from the array
@@ -621,7 +621,7 @@ if no arg text were given (e.g. "10 NEXT"), args will have zero length
// if no args were given // if no args were given
if (args.length == 0 || (args.length == 1 && args.troType == "null")) { if (args.length == 0 || (args.length == 1 && args.troType == "null")) {
// go to most recent FOR // go to most recent FOR
let forVarname = bStatus.forStack.pop(); var forVarname = bStatus.forStack.pop();
//serial.println(lnum+" NEXT > forVarname = "+forVarname); //serial.println(lnum+" NEXT > forVarname = "+forVarname);
if (forVarname === undefined) { if (forVarname === undefined) {
throw lang.nextWithoutFor(lnum); throw lang.nextWithoutFor(lnum);
@@ -680,7 +680,7 @@ if no arg text were given (e.g. "10 NEXT"), args will have zero length
*/ */
"INPUT" : function(lnum, args) { "INPUT" : function(lnum, args) {
// just use tail-end arg as an input variable // just use tail-end arg as an input variable
let endArg = args.pop(); var endArg = args.pop();
if (endArg === undefined) { if (endArg === undefined) {
system.printerr("INPUT called with no arguments"); system.printerr("INPUT called with no arguments");
return undefined; return undefined;
@@ -689,7 +689,7 @@ if no arg text were given (e.g. "10 NEXT"), args will have zero length
// print out prompt text // print out prompt text
print("? "); print("? ");
let inputstr = sys.read().trim(); var inputstr = sys.read().trim();
// screw with the comma-separating because shrug // screw with the comma-separating because shrug
bStatus.vars[endArg.troValue] = new BasicVar(inputstr, JStoBASICtype(inputstr)); bStatus.vars[endArg.troValue] = new BasicVar(inputstr, JStoBASICtype(inputstr));
@@ -767,12 +767,12 @@ bF._keywords = {
}; };
bF._tokenise = function(lnum, cmd) { bF._tokenise = function(lnum, cmd) {
let _debugprintStateTransition = false; var _debugprintStateTransition = false;
let k; var k;
let tokens = []; var tokens = [];
let states = []; var states = [];
let sb = ""; var sb = "";
let mode = "lit"; // literal, quote, paren, sep, operator, number; operator2, numbersep, number2, limbo, escape, quote_end var mode = "lit"; // literal, quote, paren, sep, operator, number; operator2, numbersep, number2, limbo, escape, quote_end
// NOTE: malformed numbers (e.g. "_b3", "_", "__") must be re-marked as literal or syntax error in the second pass // NOTE: malformed numbers (e.g. "_b3", "_", "__") must be re-marked as literal or syntax error in the second pass
@@ -1245,9 +1245,9 @@ bF._parseTokens = function(lnum, tokens, states, recDepth) {
return retTreeHead; return retTreeHead;
} }
let k; var k;
let headWord = tokens[0].toLowerCase(); var headWord = tokens[0].toLowerCase();
let treeHead = new BasicAST(); var treeHead = new BasicAST();
treeHead.astDepth = recDepth; treeHead.astDepth = recDepth;
treeHead.astLnum = lnum; treeHead.astLnum = lnum;
@@ -1583,7 +1583,7 @@ bF._executeSyntaxTree = function(lnum, syntaxTree, recDepth) {
// func not in builtins (e.g. array access, user-defined function defuns) // func not in builtins (e.g. array access, user-defined function defuns)
if (func === undefined) { if (func === undefined) {
let someVar = bStatus.vars[funcName]; var someVar = bStatus.vars[funcName];
if (someVar === undefined) { if (someVar === undefined) {
throw lang.syntaxfehler(lnum, funcName + " is undefined"); throw lang.syntaxfehler(lnum, funcName + " is undefined");
} }
@@ -1741,18 +1741,18 @@ bF.run = function(args) { // RUN function
bF.save = function(args) { // SAVE function bF.save = function(args) { // SAVE function
if (args[1] === undefined) throw lang.missingOperand; if (args[1] === undefined) throw lang.missingOperand;
fs.open(args[1], "W"); fs.open(args[1], "W");
let sb = ""; var sb = "";
cmdbuf.forEach(function(v,i) { sb += i+" "+v+"\n"; }); cmdbuf.forEach(function(v,i) { sb += i+" "+v+"\n"; });
fs.write(sb); fs.write(sb);
}; };
bF.load = function(args) { // LOAD function bF.load = function(args) { // LOAD function
if (args[1] === undefined) throw lang.missingOperand; if (args[1] === undefined) throw lang.missingOperand;
let fileOpened = fs.open(args[1], "R"); var fileOpened = fs.open(args[1], "R");
if (!fileOpened) { if (!fileOpened) {
throw lang.noSuchFile; throw lang.noSuchFile;
return; return;
} }
let prg = fs.readAll(); var prg = fs.readAll();
// reset the environment // reset the environment
cmdbuf = []; cmdbuf = [];
@@ -1760,36 +1760,36 @@ bF.load = function(args) { // LOAD function
// read the source // read the source
prg.split('\n').forEach(function(line) { prg.split('\n').forEach(function(line) {
let i = line.indexOf(" "); var i = line.indexOf(" ");
let lnum = line.slice(0, i); var lnum = line.slice(0, i);
if (isNaN(lnum)) throw lang.illegalType(); if (isNaN(lnum)) throw lang.illegalType();
cmdbuf[lnum] = line.slice(i + 1, line.length); cmdbuf[lnum] = line.slice(i + 1, line.length);
}); });
}; };
bF.catalog = function(args) { // CATALOG function bF.catalog = function(args) { // CATALOG function
if (args[1] === undefined) args[1] = "\\"; if (args[1] === undefined) args[1] = "\\";
let pathOpened = fs.open(args[1], 'R'); var pathOpened = fs.open(args[1], 'R');
if (!pathOpened) { if (!pathOpened) {
throw lang.noSuchFile; throw lang.noSuchFile;
return; return;
} }
let port = _BIOS.FIRST_BOOTABLE_PORT[0]; var port = _BIOS.FIRST_BOOTABLE_PORT[0];
com.sendMessage(port, "LIST"); com.sendMessage(port, "LIST");
println(com.pullMessage(port)); println(com.pullMessage(port));
}; };
Object.freeze(bF); Object.freeze(bF);
while (!tbasexit) { while (!tbasexit) {
let line = sys.read().trim(); var line = sys.read().trim();
cmdbufMemFootPrint += line.length; cmdbufMemFootPrint += line.length;
if (reLineNum.test(line)) { if (reLineNum.test(line)) {
let i = line.indexOf(" "); var i = line.indexOf(" ");
cmdbuf[line.slice(0, i)] = line.slice(i + 1, line.length); cmdbuf[line.slice(0, i)] = line.slice(i + 1, line.length);
} }
else if (line.length > 0) { else if (line.length > 0) {
cmdbufMemFootPrint -= line.length; cmdbufMemFootPrint -= line.length;
let cmd = line.split(" "); var cmd = line.split(" ");
if (bF[cmd[0].toLowerCase()] === undefined) { if (bF[cmd[0].toLowerCase()] === undefined) {
serial.printerr("Unknown command: "+cmd[0].toLowerCase()); serial.printerr("Unknown command: "+cmd[0].toLowerCase());
println(lang.syntaxfehler()); println(lang.syntaxfehler());

View File

@@ -5,7 +5,7 @@ com.sendMessage(p[0], 'OPENR"tvdos/TVDOS.SYS",'+p[1]);
let r = com.getStatusCode(p[0]); let r = com.getStatusCode(p[0]);
if (r == 0){ if (r == 0){
com.sendMessage(p[0], "READ"); com.sendMessage(p[0], "READ");
r = com.getStatusCode([0]); r = com.getStatusCode(p[0]);
if (r == 0) { if (r == 0) {
let g=com.pullMessage(p[0]); let g=com.pullMessage(p[0]);
eval(g); eval(g);

View File

@@ -1,72 +0,0 @@
println("JS Console");
let _cmdHistory = []; // zeroth element is the oldest
let _cmdHistoryScroll = 0; // 0 for outside-of-buffer, 1 for most recent
while (true) {
print("JS> ");
let _cmdbuf = "";
while (true) {
let key = con.getch();
// printable chars
if (key >= 32 && key <= 126) {
let __sss = String.fromCharCode(key);
_cmdbuf += __sss;
print(__sss);
}
// backspace
else if (key === 8 && _cmdbuf.length > 0) {
_cmdbuf = _cmdbuf.substring(0, _cmdbuf.length - 1);
print(String.fromCharCode(key));
}
// enter
else if (key === 10 || key === 13) {
println();
try {
let prg = eval("let _appStub=function(){"+_cmdbuf+"};_appStub;"); // making 'exec_args' a app-level global
println(prg());
}
catch (e) {
printerrln(e);
}
finally {
if (_cmdbuf.trim().length > 0)
_cmdHistory.push(_cmdbuf);
_cmdHistoryScroll = 0;
break;
}
}
// up arrow
else if (key === 19 && _cmdHistory.length > 0 && _cmdHistoryScroll < _cmdHistory.length) {
_cmdHistoryScroll += 1;
// back the cursor in order to type new cmd
let __xx = 0;
for (__xx = 0; __xx < _cmdbuf.length; __xx++) print(String.fromCharCode(8));
_cmdbuf = _cmdHistory[_cmdHistory.length - _cmdHistoryScroll];
// re-type the new command
print(_cmdbuf);
}
// down arrow
else if (key === 20) {
if (_cmdHistoryScroll > 0) {
// back the cursor in order to type new cmd
let __xx = 0;
for (__xx = 0; __xx < _cmdbuf.length; __xx++) print(String.fromCharCode(8));
_cmdbuf = _cmdHistory[_cmdHistory.length - _cmdHistoryScroll];
// re-type the new command
print(_cmdbuf);
_cmdHistoryScroll -= 1;
}
else {
// back the cursor in order to type new cmd
for (__xx = 0; __xx < _cmdbuf.length; __xx++) print(String.fromCharCode(8));
_cmdbuf = "";
}
}
}
}

View File

@@ -30,7 +30,7 @@ filesystem._toPorts = function(driveLetter) {
if (driveLetter.toUpperCase === undefined) { if (driveLetter.toUpperCase === undefined) {
throw Error("'"+driveLetter+"' (type: "+typeof driveLetter+") is not a valid drive letter"); throw Error("'"+driveLetter+"' (type: "+typeof driveLetter+") is not a valid drive letter");
} }
let port = _TVDOS.DRIVES[driveLetter.toUpperCase()]; var port = _TVDOS.DRIVES[driveLetter.toUpperCase()];
if (port === undefined) { if (port === undefined) {
throw Error("Drive letter '" + driveLetter.toUpperCase() + "' does not exist"); throw Error("Drive letter '" + driveLetter.toUpperCase() + "' does not exist");
} }
@@ -48,24 +48,24 @@ filesystem._flush = function(portNo) {
// - java.lang.NullPointerException if path is null // - java.lang.NullPointerException if path is null
// - Error if operation mode is not "R", "W" nor "A" // - Error if operation mode is not "R", "W" nor "A"
filesystem.open = function(driveLetter, path, operationMode) { filesystem.open = function(driveLetter, path, operationMode) {
let port = filesystem._toPorts(driveLetter); var port = filesystem._toPorts(driveLetter);
filesystem._flush(port[0]); filesystem._close(port[0]); filesystem._flush(port[0]); filesystem._close(port[0]);
let mode = operationMode.toUpperCase(); var mode = operationMode.toUpperCase();
if (mode != "R" && mode != "W" && mode != "A") { if (mode != "R" && mode != "W" && mode != "A") {
throw Error("Unknown file opening mode: " + mode); throw Error("Unknown file opening mode: " + mode);
} }
com.sendMessage(port[0], "OPEN"+mode+'"'+path+'",'+port[1]); com.sendMessage(port[0], "OPEN"+mode+'"'+path+'",'+port[1]);
let response = com.getStatusCode(port[0]); var response = com.getStatusCode(port[0]);
return (response == 0); return (response == 0);
}; };
// @return the entire contents of the file in String // @return the entire contents of the file in String
filesystem.readAll = function(driveLetter) { filesystem.readAll = function(driveLetter) {
let port = filesystem._toPorts(driveLetter); var port = filesystem._toPorts(driveLetter);
com.sendMessage(port[0], "READ"); com.sendMessage(port[0], "READ");
let response = com.getStatusCode(port[0]); var response = com.getStatusCode(port[0]);
if (135 == response) { if (135 == response) {
throw Error("File not opened"); throw Error("File not opened");
} }
@@ -75,9 +75,9 @@ filesystem.readAll = function(driveLetter) {
return com.pullMessage(port[0]); return com.pullMessage(port[0]);
}; };
filesystem.write = function(driveLetter, string) { filesystem.write = function(driveLetter, string) {
let port = filesystem._toPorts(driveLetter); var port = filesystem._toPorts(driveLetter);
com.sendMessage(port[0], "WRITE"+string.length); com.sendMessage(port[0], "WRITE"+string.length);
let response = com.getStatusCode(port[0]); var response = com.getStatusCode(port[0]);
if (135 == response) { if (135 == response) {
throw Error("File not opened"); throw Error("File not opened");
} }
@@ -88,32 +88,32 @@ filesystem.write = function(driveLetter, string) {
filesystem._flush(port[0]); filesystem._close(port[0]); filesystem._flush(port[0]); filesystem._close(port[0]);
}; };
filesystem.isDirectory = function(driveLetter) { filesystem.isDirectory = function(driveLetter) {
let port = filesystem._toPorts(driveLetter); var port = filesystem._toPorts(driveLetter);
com.sendMessage(port[0], "LISTFILES"); com.sendMessage(port[0], "LISTFILES");
let response = com.getStatusCode(port[0]); var response = com.getStatusCode(port[0]);
return (response === 0); return (response === 0);
}; };
filesystem.mkDir = function(driveLetter) { filesystem.mkDir = function(driveLetter) {
let port = filesystem._toPorts(driveLetter); var port = filesystem._toPorts(driveLetter);
com.sendMessage(port[0], "MKDIR"); com.sendMessage(port[0], "MKDIR");
let response = com.getStatusCode(port[0]); var response = com.getStatusCode(port[0]);
if (response < 0 || response >= 128) { if (response < 0 || response >= 128) {
let status = com.getDeviceStatus(port[0]); var status = com.getDeviceStatus(port[0]);
throw Error("Creating a directory failed with ("+response+"): "+status.message+"\n"); throw Error("Creating a directory failed with ("+response+"): "+status.message+"\n");
} }
return (response === 0); // possible status codes: 0 (success), 1 (fail) return (response === 0); // possible status codes: 0 (success), 1 (fail)
}; };
filesystem.touch = function(driveLetter) { filesystem.touch = function(driveLetter) {
let port = filesystem._toPorts(driveLetter); var port = filesystem._toPorts(driveLetter);
com.sendMessage(port[0], "TOUCH"); com.sendMessage(port[0], "TOUCH");
let response = com.getStatusCode(port[0]); var response = com.getStatusCode(port[0]);
return (response === 0); return (response === 0);
}; };
filesystem.mkFile = function(driveLetter) { filesystem.mkFile = function(driveLetter) {
let port = filesystem._toPorts(driveLetter); var port = filesystem._toPorts(driveLetter);
com.sendMessage(port[0], "MKFILE"); com.sendMessage(port[0], "MKFILE");
let response = com.getStatusCode(port[0]); var response = com.getStatusCode(port[0]);
return (response === 0); return (response === 0);
}; };
Object.freeze(filesystem); Object.freeze(filesystem);
@@ -128,8 +128,8 @@ var GL = eval(filesystem.readAll("A"));
// @param args arguments for the program, must be Array, and args[0] is always the name of the program, e.g. // @param args arguments for the program, must be Array, and args[0] is always the name of the program, e.g.
// for command line 'echo foo bar', args[0] must be 'echo' // for command line 'echo foo bar', args[0] must be 'echo'
var execApp = function(cmdsrc, args) { var execApp = function(cmdsrc, args) {
let prg = eval("let _appStub=function(exec_args){"+cmdsrc+"};_appStub;"); // making 'exec_args' a app-level global var execAppPrg = eval("var _appStub=function(exec_args){"+cmdsrc+"};_appStub;"); // making 'exec_args' a app-level global
return prg(args); return execAppPrg(args);
} }
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////

View File

@@ -49,9 +49,9 @@ function greet() {
} }
function trimStartRevSlash(s) { function trimStartRevSlash(s) {
let cnt = 0; var cnt = 0;
while (cnt < s.length) { while (cnt < s.length) {
let chr = s[cnt]; var chr = s[cnt];
if (chr != '\\') break; if (chr != '\\') break;
@@ -66,10 +66,10 @@ shell.getPwd = function() { return shell_pwd; }
shell.getCurrentDrive = function() { return CURRENT_DRIVE; } shell.getCurrentDrive = function() { return CURRENT_DRIVE; }
// example input: echo "the string" > subdir\test.txt // example input: echo "the string" > subdir\test.txt
shell.parse = function(input) { shell.parse = function(input) {
let tokens = []; var tokens = [];
let stringBuffer = ""; var stringBuffer = "";
let mode = "LITERAL"; // LITERAL, QUOTE, ESCAPE, LIMBO var mode = "LITERAL"; // LITERAL, QUOTE, ESCAPE, LIMBO
let i = 0 var i = 0
while (i < input.length) { while (i < input.length) {
const c = input[i]; const c = input[i];
/*digraph g { /*digraph g {
@@ -136,12 +136,12 @@ shell.parse = function(input) {
} }
shell.resolvePathInput = function(input) { shell.resolvePathInput = function(input) {
// replace slashes into revslashes // replace slashes into revslashes
let pathstr = input.replaceAll('/','\\\\'); var pathstr = input.replaceAll('/','\\\\');
let startsWithSlash = input.startsWith('\\'); var startsWithSlash = input.startsWith('\\');
let newPwd = []; var newPwd = [];
// split them into an array while filtering empty elements except for the root 'head' // split them into an array while filtering empty elements except for the root 'head'
let ipwd = (startsWithSlash ? [""] : shell_pwd).concat(pathstr.split("\\").filter(function(it) { return (it.length > 0); })); var ipwd = (startsWithSlash ? [""] : shell_pwd).concat(pathstr.split("\\").filter(function(it) { return (it.length > 0); }));
serial.println("command.js > resolvePathInput > ipwd = "+ipwd); serial.println("command.js > resolvePathInput > ipwd = "+ipwd);
serial.println("command.js > resolvePathInput > newPwd = "+newPwd); serial.println("command.js > resolvePathInput > newPwd = "+newPwd);
@@ -177,12 +177,12 @@ shell.coreutils = {
println(CURRENT_DRIVE+":"+shell_pwd.join("\\")); println(CURRENT_DRIVE+":"+shell_pwd.join("\\"));
return return
} }
let path = shell.resolvePathInput(args[1]) var path = shell.resolvePathInput(args[1])
if (DEBUG_PRINT) serial.println("command.js > cd > pathstr = "+path.string); if (DEBUG_PRINT) serial.println("command.js > cd > pathstr = "+path.string);
// check if path is valid // check if path is valid
filesystem.open(CURRENT_DRIVE, path.string, 'R'); filesystem.open(CURRENT_DRIVE, path.string, 'R');
let dirOpened = filesystem.isDirectory(CURRENT_DRIVE); // open a dir; if path is nonexistent, file won't actually be opened var dirOpened = filesystem.isDirectory(CURRENT_DRIVE); // open a dir; if path is nonexistent, file won't actually be opened
if (!dirOpened) { printerrln("CHDIR failed for '"+path.string+"'"); return; } // if file is not opened, FALSE will be returned if (!dirOpened) { printerrln("CHDIR failed for '"+path.string+"'"); return; } // if file is not opened, FALSE will be returned
shell_pwd = path.pwd; shell_pwd = path.pwd;
@@ -192,12 +192,12 @@ shell.coreutils = {
printerrln("Syntax error"); printerrln("Syntax error");
return return
} }
let path = shell.resolvePathInput(args[1]) var path = shell.resolvePathInput(args[1])
if (DEBUG_PRINT) serial.println("command.js > mkdir > pathstr = "+path.string); if (DEBUG_PRINT) serial.println("command.js > mkdir > pathstr = "+path.string);
// check if path is valid // check if path is valid
let dirOpened = filesystem.open(CURRENT_DRIVE, path.string, 'W'); var dirOpened = filesystem.open(CURRENT_DRIVE, path.string, 'W');
let mkdird = filesystem.mkDir(CURRENT_DRIVE); var mkdird = filesystem.mkDir(CURRENT_DRIVE);
if (!mkdird) { printerrln("MKDIR failed for '"+path.string+"'"); return; } if (!mkdird) { printerrln("MKDIR failed for '"+path.string+"'"); return; }
}, },
cls: function(args) { cls: function(args) {
@@ -225,13 +225,13 @@ shell.coreutils = {
} }
else { else {
// parse key-value pair with splitter '=' // parse key-value pair with splitter '='
let key = undefined; let value = undefined; var key = undefined; var value = undefined;
// if syntax "<key> = <value>" is used? // if syntax "<key> = <value>" is used?
if ('=' == args[2]) { if ('=' == args[2]) {
key = args[1].toUpperCase(); value = args[3]; key = args[1].toUpperCase(); value = args[3];
} }
else if (args[2] === undefined) { else if (args[2] === undefined) {
let pair = args[1].split('='); var pair = args[1].split('=');
key = pair[0].toUpperCase(); value = pair[1]; key = pair[0].toUpperCase(); value = pair[1];
} }
@@ -251,13 +251,13 @@ shell.coreutils = {
} }
}, },
dir: function(args) { dir: function(args) {
let pathstr = (args[1] !== undefined) ? args[1] : "\\"+shell_pwd.join("\\"); var pathstr = (args[1] !== undefined) ? args[1] : "\\"+shell_pwd.join("\\");
// check if path is valid // check if path is valid
let pathOpened = filesystem.open(CURRENT_DRIVE, pathstr, 'R'); var pathOpened = filesystem.open(CURRENT_DRIVE, pathstr, 'R');
if (!pathOpened) { printerrln("File not found"); return; } if (!pathOpened) { printerrln("File not found"); return; }
let port = filesystem._toPorts(CURRENT_DRIVE)[0] var port = filesystem._toPorts(CURRENT_DRIVE)[0]
com.sendMessage(port, "LIST"); com.sendMessage(port, "LIST");
println(com.pullMessage(port)); println(com.pullMessage(port));
} }
@@ -266,24 +266,24 @@ shell.coreutils.chdir = shell.coreutils.cd;
Object.freeze(shell.coreutils); Object.freeze(shell.coreutils);
shell.execute = function(line) { shell.execute = function(line) {
if (0 == line.size) return; if (0 == line.size) return;
let tokens = shell.parse(line); var tokens = shell.parse(line);
let cmd = tokens[0]; var cmd = tokens[0];
if (cmd === undefined || cmd === '') return 0; if (cmd === undefined || cmd === '') return 0;
// handle Ctrl-C // handle Ctrl-C
if (con.hitterminate()) return 1; if (con.hitterminate()) return 1;
if (shell.coreutils[cmd.toLowerCase()] !== undefined) { if (shell.coreutils[cmd.toLowerCase()] !== undefined) {
let retval = shell.coreutils[cmd.toLowerCase()](tokens); var retval = shell.coreutils[cmd.toLowerCase()](tokens);
return retval|0; // return value of undefined will cast into 0 return retval|0; // return value of undefined will cast into 0
} }
else { else {
// search through PATH for execution // search through PATH for execution
let fileExists = false; var fileExists = false;
let searchDir = (cmd.startsWith("\\")) ? [""] : ["\\"+shell_pwd.join("\\")].concat(_TVDOS.getPath()); var searchDir = (cmd.startsWith("\\")) ? [""] : ["\\"+shell_pwd.join("\\")].concat(_TVDOS.getPath());
let pathExt = []; var pathExt = []; // it seems Nashorn does not like 'let' too much? this line gets ignored sometimes
// fill pathExt using %PATHEXT% but also capitalise them // fill pathExt using %PATHEXT% but also capitalise them
if (cmd.split(".")[1] === undefined) if (cmd.split(".")[1] === undefined)
_TVDOS.variables.PATHEXT.split(';').forEach(function(it) { pathExt.push(it); pathExt.push(it.toUpperCase()); }); _TVDOS.variables.PATHEXT.split(';').forEach(function(it) { pathExt.push(it); pathExt.push(it.toUpperCase()); });
@@ -291,10 +291,10 @@ shell.execute = function(line) {
pathExt.push(""); // final empty extension pathExt.push(""); // final empty extension
searchLoop: searchLoop:
for (let i = 0; i < searchDir.length; i++) { for (var i = 0; i < searchDir.length; i++) {
for (let j = 0; j < pathExt.length; j++) { for (var j = 0; j < pathExt.length; j++) {
let search = searchDir[i]; if (!search.endsWith('\\')) search += '\\'; var search = searchDir[i]; if (!search.endsWith('\\')) search += '\\';
let path = trimStartRevSlash(search + cmd + pathExt[j]); var path = trimStartRevSlash(search + cmd + pathExt[j]);
if (DEBUG_PRINT) { if (DEBUG_PRINT) {
serial.println("[command.js > shell.execute] file search path: "+path); serial.println("[command.js > shell.execute] file search path: "+path);
@@ -312,21 +312,21 @@ shell.execute = function(line) {
return 127; return 127;
} }
else { else {
let prg = filesystem.readAll(CURRENT_DRIVE); var programCode = filesystem.readAll(CURRENT_DRIVE);
let extension = undefined; var extension = undefined;
// get proper extension // get proper extension
let dotSepTokens = cmd.split('.'); var dotSepTokens = cmd.split('.');
if (dotSepTokens.length > 1) extension = dotSepTokens[dotSepTokens.length - 1].toUpperCase(); if (dotSepTokens.length > 1) extension = dotSepTokens[dotSepTokens.length - 1].toUpperCase();
if ("BAT" == extension) { if ("BAT" == extension) {
// parse and run as batch file // parse and run as batch file
let lines = prg.split('\n').filter(function(it) { return it.length > 0; }); var lines = programCode.split('\n').filter(function(it) { return it.length > 0; });
lines.forEach(function(line) { lines.forEach(function(line) {
shell.execute(line); shell.execute(line);
}); });
} }
else { else {
return execApp(prg, tokens)|0; // return value of undefined will cast into 0 return execApp(programCode, tokens)|0; // return value of undefined will cast into 0
} }
} }
} }
@@ -339,7 +339,7 @@ _G.shell = shell;
if (exec_args[1] !== undefined) { if (exec_args[1] !== undefined) {
// only meaningful switches would be either /c or /k anyway // only meaningful switches would be either /c or /k anyway
let firstSwitch = exec_args[1].toLowerCase(); var firstSwitch = exec_args[1].toLowerCase();
// command /c <commands> // command /c <commands>
// ^[0] ^[1] ^[2] // ^[0] ^[1] ^[2]
@@ -376,14 +376,14 @@ if (goInteractive) {
con.reset_graphics(); con.reset_graphics();
print_prompt_text(); print_prompt_text();
let cmdbuf = ""; var cmdbuf = "";
while (true) { while (true) {
let key = con.getch(); var key = con.getch();
// printable chars // printable chars
if (key >= 32 && key <= 126) { if (key >= 32 && key <= 126) {
let s = String.fromCharCode(key); var s = String.fromCharCode(key);
cmdbuf += s; cmdbuf += s;
print(s); print(s);
} }
@@ -421,7 +421,7 @@ if (goInteractive) {
cmdHistoryScroll += 1; cmdHistoryScroll += 1;
// back the cursor in order to type new cmd // back the cursor in order to type new cmd
let x = 0; var x = 0;
for (x = 0; x < cmdbuf.length; x++) print(String.fromCharCode(8)); for (x = 0; x < cmdbuf.length; x++) print(String.fromCharCode(8));
cmdbuf = cmdHistory[cmdHistory.length - cmdHistoryScroll]; cmdbuf = cmdHistory[cmdHistory.length - cmdHistoryScroll];
// re-type the new command // re-type the new command
@@ -432,7 +432,7 @@ if (goInteractive) {
else if (key === 20) { else if (key === 20) {
if (cmdHistoryScroll > 0) { if (cmdHistoryScroll > 0) {
// back the cursor in order to type new cmd // back the cursor in order to type new cmd
let x = 0; var x = 0;
for (x = 0; x < cmdbuf.length; x++) print(String.fromCharCode(8)); for (x = 0; x < cmdbuf.length; x++) print(String.fromCharCode(8));
cmdbuf = cmdHistory[cmdHistory.length - cmdHistoryScroll]; cmdbuf = cmdHistory[cmdHistory.length - cmdHistoryScroll];
// re-type the new command // re-type the new command
@@ -442,7 +442,7 @@ if (goInteractive) {
} }
else { else {
// back the cursor in order to type new cmd // back the cursor in order to type new cmd
let x = 0; var x = 0;
for (x = 0; x < cmdbuf.length; x++) print(String.fromCharCode(8)); for (x = 0; x < cmdbuf.length; x++) print(String.fromCharCode(8));
cmdbuf = ""; cmdbuf = "";
} }

Binary file not shown.

Binary file not shown.

BIN
lib/graal-sdk-20.3.0.jar Normal file

Binary file not shown.

BIN
lib/icu4j-67.1-javadoc.jar Normal file

Binary file not shown.

BIN
lib/icu4j-67.1.jar Normal file

Binary file not shown.

BIN
lib/js-20.3.0-javadoc.jar Normal file

Binary file not shown.

BIN
lib/js-20.3.0.jar Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
lib/kotlin-stdlib-1.4.0.jar Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
lib/regex-20.3.0.jar Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
lib/truffle-api-20.3.0.jar Normal file

Binary file not shown.

View File

@@ -39,10 +39,10 @@ class GraphicsJSR223Delegate(val vm: VM) {
} }
} }
fun plotPixel(x: Int, y: Int, color: Byte) { fun plotPixel(x: Int, y: Int, color: Int) {
getFirstGPU()?.let { getFirstGPU()?.let {
if (x in 0 until it.config.width && y in 0 until it.config.height) { if (x in 0 until it.config.width && y in 0 until it.config.height) {
it.poke(y.toLong() * it.config.width + x, color) it.poke(y.toLong() * it.config.width + x, color.toByte())
} }
} }
} }
@@ -82,12 +82,12 @@ class GraphicsJSR223Delegate(val vm: VM) {
/** /**
* prints a char as-is; won't interpret them as an escape sequence * prints a char as-is; won't interpret them as an escape sequence
*/ */
fun putSymbol(char: Byte) { fun putSymbol(c: Int) {
getFirstGPU()?.let { getFirstGPU()?.let {
val (cx, cy) = it.getCursorPos() val (cx, cy) = it.getCursorPos()
it.putChar(cx, cy, char) it.putChar(cx, cy, c.toByte())
it.setCursorPos(cx + 1, cy) it.setCursorPos(cx + 1, cy)
} }
} }

View File

@@ -2,7 +2,6 @@ package net.torvald.tsvm
import net.torvald.UnsafeHelper import net.torvald.UnsafeHelper
import net.torvald.UnsafePtr import net.torvald.UnsafePtr
import net.torvald.tsvm.firmware.Firmware
import net.torvald.tsvm.peripheral.IOSpace import net.torvald.tsvm.peripheral.IOSpace
import net.torvald.tsvm.peripheral.PeriBase import net.torvald.tsvm.peripheral.PeriBase
import net.torvald.tsvm.peripheral.VMProgramRom import net.torvald.tsvm.peripheral.VMProgramRom
@@ -21,6 +20,9 @@ class VM(
val roms: Array<VMProgramRom?> // first ROM must contain the BIOS val roms: Array<VMProgramRom?> // first ROM must contain the BIOS
) { ) {
class ErrorIllegalAccess(val addr: Long) : RuntimeException("Segmentation fault at 0x${addr.toString(16).padStart(8, '0')}")
val id = java.util.Random().nextInt() val id = java.util.Random().nextInt()
val memsize = minOf(USER_SPACE_SIZE, _memsize.toLong()) val memsize = minOf(USER_SPACE_SIZE, _memsize.toLong())
@@ -115,10 +117,10 @@ class VM(
internal fun poke(addr: Long, value: Byte) { internal fun poke(addr: Long, value: Byte) {
val (memspace, offset) = translateAddr(addr) val (memspace, offset) = translateAddr(addr)
if (memspace == null) if (memspace == null)
throw Firmware.ErrorIllegalAccess(addr) throw ErrorIllegalAccess(addr)
else if (memspace is UnsafePtr) { else if (memspace is UnsafePtr) {
if (addr >= memspace.size) if (addr >= memspace.size)
throw Firmware.ErrorIllegalAccess(addr) throw ErrorIllegalAccess(addr)
else else
memspace.set(offset, value) memspace.set(offset, value)
} }
@@ -132,7 +134,7 @@ class VM(
null null
else if (memspace is UnsafePtr) { else if (memspace is UnsafePtr) {
if (addr >= memspace.size) if (addr >= memspace.size)
throw Firmware.ErrorIllegalAccess(addr) throw ErrorIllegalAccess(addr)
else else
memspace.get(offset) memspace.get(offset)
} }

View File

@@ -38,15 +38,14 @@ class VMJSR223Delegate(val vm: VM) {
return r return r
} }
fun print(s: String) { fun print(s: Any) {
//System.out.print("[Nashorn] $s") //System.out.print("[Nashorn] $s")
vm.getPrintStream().write(s.toByteArray(VM.CHARSET)) vm.getPrintStream().write("$s".toByteArray(VM.CHARSET))
} }
fun println(s: String) { fun println(s: Any = "") {
System.out.println("[Nashorn] $s") System.out.println("[Graal] $s")
vm.getPrintStream().write((s + '\n').toByteArray(VM.CHARSET)) vm.getPrintStream().write(("$s\n").toByteArray(VM.CHARSET))
} }
fun println() = print('\n')
/** /**
* @return key being hit, of which: * @return key being hit, of which:
@@ -112,7 +111,7 @@ class VMJSR223Delegate(val vm: VM) {
} }
class VMSerialDebugger(val vm: VM) { class VMSerialDebugger(val vm: VM) {
fun print(s: String) = System.out.print(s) fun print(s: Any) = System.out.print("$s")
fun println(s: String) = System.out.println(s) fun println(s: Any) = System.out.println("$s")
fun printerr(s: String) = System.err.println(s) fun printerr(s: Any) = System.err.println("$s")
} }

View File

@@ -1,18 +0,0 @@
package net.torvald.tsvm
import net.torvald.tsvm.firmware.Firmware
import org.luaj.vm2.LuaTable
import org.luaj.vm2.LuaValue
import org.luaj.vm2.lib.ZeroArgFunction
import org.luaj.vm2.lib.jse.JsePlatform
class VMLuaAdapter(val vm: VM) {
val lua = JsePlatform.standardGlobals()
init {
lua.load(Firmware(vm))
lua.load("_G.int = function(n) if n > 0 then return math.floor(n) else return math.ceil(n) end end").call()
}
}

View File

@@ -31,20 +31,6 @@ object VMRunnerFactory {
} }
return when (extension) { return when (extension) {
"lua" -> {
object : VMRunner(extension) {
private val vmLua = VMLuaAdapter(vm)
override suspend fun executeCommand(command: String) {
vmLua.lua.load(command).call()
}
override suspend fun evalGlobal(command: String) {
TODO("Not yet implemented")
}
}
}
"vt2" -> { "vt2" -> {
object : VMRunner(extension) { object : VMRunner(extension) {
@@ -62,18 +48,13 @@ object VMRunnerFactory {
} }
"js" -> { "js" -> {
object : VMRunner(extension) { object : VMRunner(extension) {
private val engine: ScriptEngine// = ScriptEngineManager().getEngineByExtension(extension) private val engine: ScriptEngine = ScriptEngineManager().getEngineByName("Graal.js")
private val bind = engine.getBindings(ScriptContext.ENGINE_SCOPE)
init { init {
val engineFactory = NashornScriptEngineFactory() // see https://github.com/graalvm/graaljs/blob/master/docs/user/ScriptEngine.md
engine = engineFactory.getScriptEngine("--no-java", "--no-syntax-extensions", "--language=es6") bind.put("polyglot.js.allowHostAccess", true)
assertNotNull(engine, "Script engine for extension $extension not found")
}
private val context = SimpleScriptContext()
private val bind = context.getBindings(ScriptContext.ENGINE_SCOPE)
init {
bind.put("sys", VMJSR223Delegate(vm)) // TODO use delegator class to access peripheral (do not expose VM itself) bind.put("sys", VMJSR223Delegate(vm)) // TODO use delegator class to access peripheral (do not expose VM itself)
bind.put("graphics", GraphicsJSR223Delegate(vm)) bind.put("graphics", GraphicsJSR223Delegate(vm))
bind.put("serial", VMSerialDebugger(vm)) bind.put("serial", VMSerialDebugger(vm))
@@ -84,12 +65,12 @@ object VMRunnerFactory {
val fr = FileReader("./assets/JS_INIT.js") val fr = FileReader("./assets/JS_INIT.js")
val prg = fr.readText() val prg = fr.readText()
fr.close() fr.close()
engine.eval(sanitiseJS(prg), context) engine.eval(sanitiseJS(prg))
} }
override suspend fun executeCommand(command: String) { override suspend fun executeCommand(command: String) {
try { try {
engine.eval(encapsulateJS(sanitiseJS(command)), context) engine.eval(encapsulateJS(sanitiseJS(command)))
} }
catch (e: javax.script.ScriptException) { catch (e: javax.script.ScriptException) {
System.err.println("ScriptException from the script:") System.err.println("ScriptException from the script:")
@@ -99,7 +80,7 @@ object VMRunnerFactory {
} }
override suspend fun evalGlobal(command: String) { override suspend fun evalGlobal(command: String) {
engine.eval("\"use strict\";" + sanitiseJS(command), context) engine.eval("\"use strict\";" + sanitiseJS(command))
} }
} }
} }

View File

@@ -1,64 +0,0 @@
package net.torvald.tsvm.firmware
import net.torvald.tsvm.VM
import net.torvald.tsvm.kB
import org.luaj.vm2.LuaTable
import org.luaj.vm2.LuaValue
import org.luaj.vm2.lib.OneArgFunction
import org.luaj.vm2.lib.TwoArgFunction
import org.luaj.vm2.lib.ZeroArgFunction
import java.lang.RuntimeException
internal class Firmware(val vm: VM) : TwoArgFunction() {
class ErrorIllegalAccess(val addr: Long) : RuntimeException("Segmentation fault at 0x${addr.toString(16).padStart(8, '0')}")
companion object {
internal fun translateAddr(vm : VM, addr: LuaValue): Pair<Any?, Long> {
val addr = addr.checklong()
return when (addr) {
// DO note that numbers in Lua are double precision floats (ignore Lua 5.3 for now)
in 0..8192.kB() - 1 -> vm.usermem to addr
in -1024.kB()..-1 -> vm.peripheralTable[0].peripheral to (-addr - 1)
in -2048.kB()..-1024.kB() - 1 -> vm.peripheralTable[1].peripheral to (-addr - 1 - 1024.kB())
in -3072.kB()..-2048.kB() - 1 -> vm.peripheralTable[2].peripheral to (-addr - 1 - 2048.kB())
in -4096.kB()..-3072.kB() - 1 -> vm.peripheralTable[3].peripheral to (-addr - 1 - 3072.kB())
in -5120.kB()..-4096.kB() - 1 -> vm.peripheralTable[4].peripheral to (-addr - 1 - 4096.kB())
in -6144.kB()..-5120.kB() - 1 -> vm.peripheralTable[5].peripheral to (-addr - 1 - 5120.kB())
in -7168.kB()..-6144.kB() - 1 -> vm.peripheralTable[6].peripheral to (-addr - 1 - 6144.kB())
in -8192.kB()..-7168.kB() - 1 -> vm.peripheralTable[7].peripheral to (-addr - 1 - 7168.kB())
else -> null to addr
}
}
fun Byte.toLuaValue() = LuaValue.valueOf(this.toInt())
}
class Poke(private val vm: VM) : TwoArgFunction() {
override fun call(addr: LuaValue, value: LuaValue): LuaValue {
vm.poke(addr.checklong(), value.checkint().toByte())
return LuaValue.NIL
}
}
class Peek(private val vm: VM) : OneArgFunction() {
override fun call(addr: LuaValue): LuaValue {
return vm.peek(addr.checklong())?.toLuaValue() ?: LuaValue.NIL
}
}
override fun call(modname: LuaValue, env: LuaValue): LuaValue {
println("[Firmware] Loading package 'rawamem'")
val t = LuaTable()
t["poke"] = Poke(vm)
t["peek"] = Peek(vm)
t["nanoTime"] = object : ZeroArgFunction() {
override fun call(): LuaValue {
return LuaValue.valueOf(System.nanoTime().toDouble())
}
}
if (!env["package"].isnil()) env["package"]["loaded"]["rawmem"] = t
return t
}
}

View File

@@ -8,6 +8,8 @@
<orderEntry type="inheritedJdk" /> <orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" /> <orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="KotlinJavaRuntime" level="project" /> <orderEntry type="library" name="KotlinJavaRuntime" level="project" />
<orderEntry type="library" name="org.jetbrains.kotlin:kotlin-scripting-jsr223:1.3.71" level="project" /> <orderEntry type="library" name="org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.1" level="project" />
<orderEntry type="library" name="org.graalvm.js:js-scriptengine:20.3.0" level="project" />
<orderEntry type="library" name="org.graalvm.js:js:20.3.0" level="project" />
</component> </component>
</module> </module>