mirror of
https://github.com/curioustorvald/tsvm.git
synced 2026-06-13 08:04:03 +09:00
working goto but ^C doesnt work
This commit is contained in:
@@ -253,6 +253,21 @@ basicInterpreterStatus.builtin = {
|
|||||||
if (isNaN(lh) || isNaN(rh)) throw lang.illegalType(lnum);
|
if (isNaN(lh) || isNaN(rh)) throw lang.illegalType(lnum);
|
||||||
|
|
||||||
sys.poke(lh, rh);
|
sys.poke(lh, rh);
|
||||||
|
},
|
||||||
|
"GOTO" : function(lnum, args) {
|
||||||
|
if (args.length != 1) throw lang.syntaxfehler(lnum);
|
||||||
|
var lh = resolve(args[0]);
|
||||||
|
if (lh === undefined) throw lang.refError(lnum);
|
||||||
|
if (isNaN(lh)) throw lang.illegalType(lnum);
|
||||||
|
return lh;
|
||||||
|
},
|
||||||
|
"GOSUB" : function(lnum, args) {
|
||||||
|
if (args.length != 1) throw lang.syntaxfehler(lnum);
|
||||||
|
var lh = resolve(args[0]);
|
||||||
|
if (lh === undefined || rh === undefined) throw lang.refError(lnum);
|
||||||
|
if (isNaN(lh)) throw lang.illegalType(lnum);
|
||||||
|
basicInterpreterStatus.gosubStack.push(lnum + 1);
|
||||||
|
return lh;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Object.freeze(basicInterpreterStatus.builtin);
|
Object.freeze(basicInterpreterStatus.builtin);
|
||||||
@@ -757,7 +772,7 @@ for input "DEFUN sinc(x) = sin(x) / x"
|
|||||||
"quote" == state || "number" == state || "bool" == state || "literal" == state;
|
"quote" == state || "number" == state || "bool" == state || "literal" == state;
|
||||||
}
|
}
|
||||||
|
|
||||||
var _debugSyntaxAnalysis = true;
|
var _debugSyntaxAnalysis = false;
|
||||||
|
|
||||||
if (_debugSyntaxAnalysis) println("@@ SYNTAX ANALYSIS @@");
|
if (_debugSyntaxAnalysis) println("@@ SYNTAX ANALYSIS @@");
|
||||||
|
|
||||||
@@ -1012,8 +1027,14 @@ function JStoBASICtype(object) {
|
|||||||
else if (object === undefined) return "null";
|
else if (object === undefined) return "null";
|
||||||
else throw "InternalError: un-translatable object with typeof "+(typeof object)+"\n"+object;
|
else throw "InternalError: un-translatable object with typeof "+(typeof object)+"\n"+object;
|
||||||
}
|
}
|
||||||
|
function SyntaxTreeReturnObj(type, value, nextLine) {
|
||||||
|
this.type = type;
|
||||||
|
this.value = value;
|
||||||
|
this.nextLine = nextLine;
|
||||||
|
}
|
||||||
|
basicFunctions._gotoCmds = { GOTO:1, GOSUB:1 };
|
||||||
basicFunctions._executeSyntaxTree = function(lnum, syntaxTree, recDepth) {
|
basicFunctions._executeSyntaxTree = function(lnum, syntaxTree, recDepth) {
|
||||||
var _debugExec = true;
|
var _debugExec = false;
|
||||||
var recWedge = "> ".repeat(recDepth);
|
var recWedge = "> ".repeat(recDepth);
|
||||||
|
|
||||||
if (_debugExec) serial.println(recWedge+"@@ EXECUTE @@");
|
if (_debugExec) serial.println(recWedge+"@@ EXECUTE @@");
|
||||||
@@ -1023,26 +1044,32 @@ basicFunctions._executeSyntaxTree = function(lnum, syntaxTree, recDepth) {
|
|||||||
else if (syntaxTree.type == "function" || syntaxTree.type == "operator") {
|
else if (syntaxTree.type == "function" || syntaxTree.type == "operator") {
|
||||||
if (_debugExec) serial.println(recWedge+"function|operator");
|
if (_debugExec) serial.println(recWedge+"function|operator");
|
||||||
if (_debugExec) serial.println(recWedge+syntaxTree.toString());
|
if (_debugExec) serial.println(recWedge+syntaxTree.toString());
|
||||||
var func = basicInterpreterStatus.builtin[syntaxTree.value.toUpperCase()];
|
var funcName = syntaxTree.value.toUpperCase();
|
||||||
|
var func = basicInterpreterStatus.builtin[funcName];
|
||||||
var args = syntaxTree.leaves.map(function(it) { return basicFunctions._executeSyntaxTree(lnum, it, recDepth + 1); });
|
var args = syntaxTree.leaves.map(function(it) { return basicFunctions._executeSyntaxTree(lnum, it, recDepth + 1); });
|
||||||
if (_debugExec) {
|
if (_debugExec) {
|
||||||
serial.println(recWedge+"fn call name: "+syntaxTree.value.toUpperCase());
|
serial.println(recWedge+"fn call name: "+funcName);
|
||||||
serial.println(recWedge+"fn call args: "+(args.map(function(it) { return it.type+" "+it.value; })).join(", "));
|
serial.println(recWedge+"fn call args: "+(args.map(function(it) { return it.type+" "+it.value; })).join(", "));
|
||||||
}
|
}
|
||||||
|
|
||||||
var funcCallResult = func(lnum, args);
|
var funcCallResult = func(lnum, args);
|
||||||
return { type:JStoBASICtype(funcCallResult), value:funcCallResult };
|
|
||||||
|
return new SyntaxTreeReturnObj(
|
||||||
|
JStoBASICtype(funcCallResult),
|
||||||
|
funcCallResult,
|
||||||
|
(basicFunctions._gotoCmds[funcName] !== undefined) ? funcCallResult : lnum + 1
|
||||||
|
);
|
||||||
}
|
}
|
||||||
else if (syntaxTree.type == "number") {
|
else if (syntaxTree.type == "number") {
|
||||||
if (_debugExec) serial.println(recWedge+"number");
|
if (_debugExec) serial.println(recWedge+"number");
|
||||||
return { type:syntaxTree.type, value:+(syntaxTree.value) };
|
return new SyntaxTreeReturnObj(syntaxTree.type, +(syntaxTree.value), lnum + 1);
|
||||||
}
|
}
|
||||||
else if (syntaxTree.type == "string" || syntaxTree.type == "literal") {
|
else if (syntaxTree.type == "string" || syntaxTree.type == "literal") {
|
||||||
if (_debugExec) serial.println(recWedge+"string|operator");
|
if (_debugExec) serial.println(recWedge+"string|literal");
|
||||||
return { type:syntaxTree.type, value:syntaxTree.value };
|
return new SyntaxTreeReturnObj(syntaxTree.type, syntaxTree.value, lnum + 1);
|
||||||
}
|
}
|
||||||
else if (syntaxTree.type == "null") {
|
else if (syntaxTree.type == "null") {
|
||||||
return basicFunctions._executeSyntaxTree(lnum, syntaxTree.leaves[0], recDepth + 1);
|
return new basicFunctions._executeSyntaxTree(lnum, syntaxTree.leaves[0], recDepth + 1);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
serial.println(recWedge+"Parse error in "+lnum);
|
serial.println(recWedge+"Parse error in "+lnum);
|
||||||
@@ -1052,7 +1079,7 @@ basicFunctions._executeSyntaxTree = function(lnum, syntaxTree, recDepth) {
|
|||||||
};
|
};
|
||||||
// @returns: line number for the next command, normally (lnum + 1); if GOTO or GOSUB was met, returns its line number
|
// @returns: line number for the next command, normally (lnum + 1); if GOTO or GOSUB was met, returns its line number
|
||||||
basicFunctions._interpretLine = function(lnum, cmd) {
|
basicFunctions._interpretLine = function(lnum, cmd) {
|
||||||
var _debugprintHighestLevel = true;
|
var _debugprintHighestLevel = false;
|
||||||
|
|
||||||
// TOKENISE
|
// TOKENISE
|
||||||
var tokenisedObject = basicFunctions._tokenise(lnum, cmd);
|
var tokenisedObject = basicFunctions._tokenise(lnum, cmd);
|
||||||
@@ -1068,12 +1095,12 @@ basicFunctions._interpretLine = function(lnum, cmd) {
|
|||||||
if (_debugprintHighestLevel) serial.println("Final syntax tree:");
|
if (_debugprintHighestLevel) serial.println("Final syntax tree:");
|
||||||
if (_debugprintHighestLevel) serial.println(syntaxTree.toString());
|
if (_debugprintHighestLevel) serial.println(syntaxTree.toString());
|
||||||
|
|
||||||
basicFunctions._executeSyntaxTree(lnum, syntaxTree, 0);
|
var execResult = basicFunctions._executeSyntaxTree(lnum, syntaxTree, 0);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// EXECUTE
|
// EXECUTE
|
||||||
return lnum + 1;
|
return execResult.nextLine;
|
||||||
|
|
||||||
|
|
||||||
}; // end INTERPRETLINE
|
}; // end INTERPRETLINE
|
||||||
@@ -1143,6 +1170,9 @@ basicFunctions.fre = function(args) {
|
|||||||
basicFunctions.run = function(args) { // RUN function
|
basicFunctions.run = function(args) { // RUN function
|
||||||
var linenumber = 1;
|
var linenumber = 1;
|
||||||
var oldnum = 1;
|
var oldnum = 1;
|
||||||
|
|
||||||
|
var countup = 0;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if (cmdbuf[linenumber] !== undefined) {
|
if (cmdbuf[linenumber] !== undefined) {
|
||||||
oldnum = linenumber;
|
oldnum = linenumber;
|
||||||
@@ -1151,7 +1181,8 @@ basicFunctions.run = function(args) { // RUN function
|
|||||||
else {
|
else {
|
||||||
linenumber += 1;
|
linenumber += 1;
|
||||||
}
|
}
|
||||||
if (con.hitterminate()) {
|
countup += 1;
|
||||||
|
if (con.hitterminate() || countup >= 100) {
|
||||||
println("Break in "+oldnum);
|
println("Break in "+oldnum);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
BIN
guicursor.kra
LFS
BIN
guicursor.kra
LFS
Binary file not shown.
245
src/net/torvald/tsvm/peripheral/TTY.kt
Normal file
245
src/net/torvald/tsvm/peripheral/TTY.kt
Normal file
@@ -0,0 +1,245 @@
|
|||||||
|
package net.torvald.tsvm.peripheral
|
||||||
|
|
||||||
|
import com.badlogic.gdx.graphics.Texture
|
||||||
|
import net.torvald.UnsafeHelper
|
||||||
|
import net.torvald.tsvm.VM
|
||||||
|
import java.io.InputStream
|
||||||
|
import java.io.OutputStream
|
||||||
|
|
||||||
|
class TTY(val vm: VM) : GlassTty(TEXT_ROWS, TEXT_COLS), PeriBase {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val TEXT_ROWS = 25
|
||||||
|
const val TEXT_COLS = 80
|
||||||
|
}
|
||||||
|
|
||||||
|
private val chrrom = Texture("./tty.png")
|
||||||
|
private val textBuffer = UnsafeHelper.allocate(TEXT_ROWS * TEXT_COLS * 2L)
|
||||||
|
override var rawCursorPos = 0
|
||||||
|
|
||||||
|
private val TEXT_AREA_SIZE = TEXT_COLS * TEXT_ROWS
|
||||||
|
private val memTextOffset = 0L
|
||||||
|
private val memTextAttrOffset = TEXT_AREA_SIZE.toLong()
|
||||||
|
|
||||||
|
override var ttyFore = 0 // 0: normal, 1: intense, 2: dim
|
||||||
|
override var ttyBack: Int
|
||||||
|
get() = 0
|
||||||
|
set(value) {}
|
||||||
|
var ttyInv = false
|
||||||
|
override var blinkCursor = true
|
||||||
|
override var ttyRawMode = false
|
||||||
|
|
||||||
|
override fun getCursorPos() = rawCursorPos % TEXT_COLS to rawCursorPos / TEXT_COLS
|
||||||
|
/**
|
||||||
|
* Think of it as a real paper tty;
|
||||||
|
* setCursorPos must "wrap" the cursor properly when x-value goes out of screen bound.
|
||||||
|
* For y-value, only when y < 0, set y to zero and don't care about the y-value goes out of bound.
|
||||||
|
*/
|
||||||
|
override fun setCursorPos(x: Int, y: Int) {
|
||||||
|
var newx = x
|
||||||
|
var newy = y
|
||||||
|
|
||||||
|
if (newx >= TEXT_COLS) {
|
||||||
|
newx = 0
|
||||||
|
newy += 1
|
||||||
|
}
|
||||||
|
else if (newx < 0) {
|
||||||
|
newx = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newy < 0) {
|
||||||
|
newy = 0 // DON'T SCROLL when cursor goes ABOVE the screen
|
||||||
|
}
|
||||||
|
|
||||||
|
rawCursorPos = toTtyTextOffset(newx, newy)
|
||||||
|
}
|
||||||
|
private fun toTtyTextOffset(x: Int, y: Int) = y * TEXT_COLS + x
|
||||||
|
|
||||||
|
|
||||||
|
override fun peek(addr: Long): Byte? {
|
||||||
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun poke(addr: Long, byte: Byte) {
|
||||||
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun mmio_read(addr: Long): Byte? {
|
||||||
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun mmio_write(addr: Long, byte: Byte) {
|
||||||
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getVM() = vm
|
||||||
|
|
||||||
|
override fun putChar(x: Int, y: Int, text: Byte, foreColour: Byte, backColour: Byte) {
|
||||||
|
val textOff = toTtyTextOffset(x, y)
|
||||||
|
textBuffer[memTextAttrOffset + textOff] = 0
|
||||||
|
textBuffer[memTextOffset + textOff] = text
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun resetTtyStatus() {
|
||||||
|
ttyFore = 0
|
||||||
|
ttyInv = false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun cursorUp(arg: Int) {
|
||||||
|
val (x, y) = getCursorPos()
|
||||||
|
setCursorPos(x, y - arg)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun cursorDown(arg: Int) {
|
||||||
|
val (x, y) = getCursorPos()
|
||||||
|
val newy = y + arg
|
||||||
|
setCursorPos(x, if (newy >= TEXT_ROWS) TEXT_ROWS - 1 else newy)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun cursorFwd(arg: Int) {
|
||||||
|
val (x, y) = getCursorPos()
|
||||||
|
setCursorPos(x + arg, y)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun cursorBack(arg: Int) {
|
||||||
|
val (x, y) = getCursorPos()
|
||||||
|
setCursorPos(x - arg, y)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun cursorNextLine(arg: Int) {
|
||||||
|
val (_, y) = getCursorPos()
|
||||||
|
val newy = y + arg
|
||||||
|
setCursorPos(0, if (newy >= TEXT_ROWS) TEXT_ROWS - 1 else newy)
|
||||||
|
if (newy >= TEXT_ROWS) {
|
||||||
|
scrollUp(newy - TEXT_ROWS + 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun cursorPrevLine(arg: Int) {
|
||||||
|
val (_, y) = getCursorPos()
|
||||||
|
setCursorPos(0, y - arg)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun cursorX(arg: Int) {
|
||||||
|
val (_, y) = getCursorPos()
|
||||||
|
setCursorPos(arg, y)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun eraseInDisp(arg: Int) {
|
||||||
|
when (arg) {
|
||||||
|
else -> TODO()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun eraseInLine(arg: Int) {
|
||||||
|
when (arg) {
|
||||||
|
else -> TODO()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun sgrOneArg(arg: Int) {
|
||||||
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun sgrTwoArg(arg1: Int, arg2: Int) {
|
||||||
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun sgrThreeArg(arg1: Int, arg2: Int, arg3: Int) {
|
||||||
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun cursorXY(arg1: Int, arg2: Int) {
|
||||||
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun ringBell() {
|
||||||
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun insertTab() {
|
||||||
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun crlf() {
|
||||||
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun backspace() {
|
||||||
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun privateSeqH(arg: Int) {
|
||||||
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun privateSeqL(arg: Int) {
|
||||||
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getPrintStream(): OutputStream {
|
||||||
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getErrorStream(): OutputStream {
|
||||||
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getInputStream(): InputStream {
|
||||||
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun putKey(key: Int) {
|
||||||
|
vm.poke(-39, key.toByte())
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return key code in 0..255 (TODO: JInput Keycode or ASCII-Code?)
|
||||||
|
*/
|
||||||
|
override fun takeKey(): Int {
|
||||||
|
return vm.peek(-38)!!.toInt().and(255)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** New lines are added at the bottom */
|
||||||
|
override fun scrollUp(arg: Int) {
|
||||||
|
val displacement = arg.toLong() * TEXT_COLS
|
||||||
|
UnsafeHelper.memcpy(
|
||||||
|
textBuffer.ptr + memTextOffset + displacement,
|
||||||
|
textBuffer.ptr + memTextOffset,
|
||||||
|
TEXT_AREA_SIZE - displacement
|
||||||
|
)
|
||||||
|
UnsafeHelper.memcpy(
|
||||||
|
textBuffer.ptr + memTextAttrOffset + displacement,
|
||||||
|
textBuffer.ptr + memTextAttrOffset,
|
||||||
|
TEXT_AREA_SIZE - displacement
|
||||||
|
)
|
||||||
|
for (i in 0 until displacement) {
|
||||||
|
textBuffer[memTextOffset + TEXT_AREA_SIZE - displacement + i] = 0
|
||||||
|
textBuffer[memTextAttrOffset + TEXT_AREA_SIZE - displacement + i] = ttyFore.toByte()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** New lines are added at the top */
|
||||||
|
override fun scrollDown(arg: Int) {
|
||||||
|
val displacement = arg.toLong() * TEXT_COLS
|
||||||
|
UnsafeHelper.memcpy(
|
||||||
|
textBuffer.ptr + memTextOffset,
|
||||||
|
textBuffer.ptr + memTextOffset + displacement,
|
||||||
|
TEXT_AREA_SIZE - displacement
|
||||||
|
)
|
||||||
|
UnsafeHelper.memcpy(
|
||||||
|
textBuffer.ptr + memTextAttrOffset,
|
||||||
|
textBuffer.ptr + memTextAttrOffset + displacement,
|
||||||
|
TEXT_AREA_SIZE - displacement
|
||||||
|
)
|
||||||
|
for (i in 0 until displacement) {
|
||||||
|
textBuffer[memTextOffset + TEXT_AREA_SIZE + i] = 0
|
||||||
|
textBuffer[memTextAttrOffset + TEXT_AREA_SIZE + i] = ttyFore.toByte()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
override fun dispose() {
|
||||||
|
chrrom.dispose()
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user