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