mirror of
https://github.com/irmen/prog8.git
synced 2025-01-11 13:29:45 +00:00
vm tweaks
This commit is contained in:
parent
0603b93f47
commit
27e6749533
15
testvm.txt
15
testvm.txt
@ -1,19 +1,14 @@
|
||||
; source code for a tinyvm program
|
||||
%block b1
|
||||
%vardefs
|
||||
var byte teller 1
|
||||
var byte teller 0
|
||||
var byte numbertoprint 0
|
||||
const byte one 1
|
||||
const byte thousand 100000
|
||||
var array_byte newlinestr 2 [32 32]
|
||||
const byte thousand 1000
|
||||
const byte space_chr 32
|
||||
%end_vardefs
|
||||
|
||||
%instructions
|
||||
push teller
|
||||
syscall decimalstr_signed
|
||||
syscall printstr
|
||||
push newlinestr
|
||||
syscall printstr
|
||||
back:
|
||||
push teller
|
||||
push one
|
||||
@ -29,8 +24,8 @@ back:
|
||||
printnumber:
|
||||
syscall decimalstr_signed
|
||||
syscall printstr
|
||||
push newlinestr
|
||||
syscall printstr
|
||||
push space_chr
|
||||
syscall printchr
|
||||
return 0
|
||||
%end_instructions
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import sys
|
||||
from .parse import Parser
|
||||
from .core import Program, Opcode, Block, Instruction
|
||||
from .program import Program, Opcode, Block, Instruction
|
||||
from .vm import VM
|
||||
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import array
|
||||
from typing import Optional, List, Tuple, Dict
|
||||
from .core import DataType, Opcode, Program, Block, Variable, Instruction
|
||||
from typing import Optional, List, Tuple, Dict, Any
|
||||
from .program import DataType, Opcode, Program, Block, Variable, Instruction
|
||||
from .vm import StackValueType
|
||||
|
||||
|
||||
@ -112,6 +112,7 @@ class Parser:
|
||||
def parse_instruction(ln: str) -> Instruction:
|
||||
parts = ln.split(maxsplit=1)
|
||||
opcode = Opcode[parts[0].upper()]
|
||||
args = [] # type: List[Any]
|
||||
if len(parts) == 2:
|
||||
args = parts[1].split()
|
||||
else:
|
||||
|
@ -65,7 +65,7 @@ class Variable:
|
||||
class Instruction:
|
||||
__slots__ = ["opcode", "args", "next", "alt_next"]
|
||||
|
||||
def __init__(self, opcode: Opcode, args: List[Any], nxt: Optional['Instruction'], alt_next: Optional['Instruction']) -> None:
|
||||
def __init__(self, opcode: Opcode, args: List[Any], nxt: Optional['Instruction']=None, alt_next: Optional['Instruction']=None) -> None:
|
||||
self.opcode = opcode
|
||||
self.args = args
|
||||
self.next = nxt # regular next statement, None=end
|
||||
@ -77,16 +77,16 @@ class Instruction:
|
||||
|
||||
class Block:
|
||||
def __init__(self, name: str, parent: 'Block',
|
||||
variables: List[Variable],
|
||||
instructions: List[Instruction],
|
||||
labels: Dict[str, Instruction], # named entry points
|
||||
blocks: List['Block']) -> None:
|
||||
variables: List[Variable] = None,
|
||||
instructions: List[Instruction] = None,
|
||||
labels: Dict[str, Instruction] = None, # named entry points
|
||||
subblocks: List['Block'] = None) -> None:
|
||||
self.name = name
|
||||
self.parent = parent
|
||||
self.variables = variables
|
||||
self.blocks = blocks
|
||||
self.instructions = instructions
|
||||
self.labels = labels
|
||||
self.variables = variables or []
|
||||
self.blocks = subblocks or []
|
||||
self.instructions = instructions or []
|
||||
self.labels = labels or {}
|
||||
|
||||
def __str__(self) -> str:
|
||||
if self.parent:
|
55
tinyvm/vm.py
55
tinyvm/vm.py
@ -16,11 +16,11 @@
|
||||
# or in one of the dynamic variables.
|
||||
#
|
||||
# I/O: either via programmed I/O routines:
|
||||
# write [byte to text output/screen],
|
||||
# read [byte from keyboard],
|
||||
# wait [till any input comes available],
|
||||
# check [if input is available)
|
||||
# or via memory-mapped I/O (text screen matrix, keyboard scan register)
|
||||
# write [byte/bytearray to text output/screen],
|
||||
# read [byte/bytearray from keyboard],
|
||||
# wait [till any input comes available], @todo
|
||||
# check [if input is available) @todo
|
||||
# or via memory-mapped I/O (text screen matrix, keyboard scan register) @todo
|
||||
#
|
||||
# CPU: stack based execution, no registers.
|
||||
# unlimited dynamic variables (v0, v1, ...) that have a value and a type.
|
||||
@ -63,9 +63,9 @@ import collections
|
||||
import array
|
||||
import threading
|
||||
import pprint
|
||||
from .core import Instruction, Variable, Block, Program, Opcode
|
||||
from typing import Dict, List, Tuple, Union
|
||||
from il65.emit import mflpt5_to_float, to_mflpt5
|
||||
from .program import Instruction, Variable, Block, Program, Opcode
|
||||
|
||||
|
||||
class ExecutionError(Exception):
|
||||
@ -522,7 +522,7 @@ class VM:
|
||||
|
||||
def opcode_RETURN(self, instruction: Instruction) -> bool:
|
||||
callframe = self.stack.pop_under(instruction.args[0])
|
||||
assert isinstance(callframe, CallFrameMarker)
|
||||
assert isinstance(callframe, CallFrameMarker), callframe
|
||||
self.pc = callframe.returninstruction
|
||||
return False
|
||||
|
||||
@ -591,8 +591,8 @@ class System:
|
||||
def _encodestr(self, string: str, alt: bool=False) -> bytearray:
|
||||
return bytearray(string, self.vm.str_alt_encoding if alt else self.vm.str_encoding)
|
||||
|
||||
def _decodestr(self, bb: bytearray, alt: bool=False) -> str:
|
||||
return str(bb, self.vm.str_alt_encoding if alt else self.vm.str_encoding)
|
||||
def _decodestr(self, bb: Union[bytearray, array.array], alt: bool=False) -> str:
|
||||
return str(bb, self.vm.str_alt_encoding if alt else self.vm.str_encoding) # type: ignore
|
||||
|
||||
def syscall_printstr(self) -> bool:
|
||||
value = self.vm.stack.pop()
|
||||
@ -602,6 +602,22 @@ class System:
|
||||
else:
|
||||
raise TypeError("printstr expects bytearray", value)
|
||||
|
||||
def syscall_printchr(self) -> bool:
|
||||
character = self.vm.stack.pop()
|
||||
if isinstance(character, int):
|
||||
print(self._decodestr(bytearray([character])), end="")
|
||||
return True
|
||||
else:
|
||||
raise TypeError("printchr expects integer (1 char)", character)
|
||||
|
||||
def syscall_input(self) -> bool:
|
||||
self.vm.stack.push(self._encodestr(input()))
|
||||
return True
|
||||
|
||||
def syscall_getchr(self) -> bool:
|
||||
self.vm.stack.push(self._encodestr(input() + '\n')[0])
|
||||
return True
|
||||
|
||||
def syscall_decimalstr_signed(self) -> bool:
|
||||
value = self.vm.stack.pop()
|
||||
if type(value) is int:
|
||||
@ -631,3 +647,24 @@ class System:
|
||||
value, address = self.vm.stack.pop2()
|
||||
self.vm.memory.set_sbyte(address, value) # type: ignore
|
||||
return True
|
||||
|
||||
def syscall_memwrite_word(self) -> bool:
|
||||
value, address = self.vm.stack.pop2()
|
||||
self.vm.memory.set_word(address, value) # type: ignore
|
||||
return True
|
||||
|
||||
def syscall_memwrite_sword(self) -> bool:
|
||||
value, address = self.vm.stack.pop2()
|
||||
self.vm.memory.set_sword(address, value) # type: ignore
|
||||
return True
|
||||
|
||||
def syscall_memwrite_float(self) -> bool:
|
||||
value, address = self.vm.stack.pop2()
|
||||
self.vm.memory.set_float(address, value) # type: ignore
|
||||
return True
|
||||
|
||||
def syscall_memwrite_str(self) -> bool:
|
||||
strbytes, address = self.vm.stack.pop2()
|
||||
for i, b in enumerate(strbytes): # type: ignore
|
||||
self.vm.memory.set_byte(address+i, b) # type: ignore
|
||||
return True
|
||||
|
Loading…
x
Reference in New Issue
Block a user