Make the handle_* methods user-visible

This commit is contained in:
Reid 'arrdem' McKenzie 2022-08-13 00:09:55 -06:00
parent edd237f0be
commit 4ac9de366b

View file

@ -181,23 +181,23 @@ class Interpreter(BaseInterpreter):
def step(self, state: InterpreterState, opcode: isa.Opcode) -> InterpreterState: def step(self, state: InterpreterState, opcode: isa.Opcode) -> InterpreterState:
"""Execute an instruction, producing the next state of the VM.""" """Execute an instruction, producing the next state of the VM."""
return self._handle_opcode(state, opcode) return self.handle_opcode(state, opcode)
#################################################################################################################### ####################################################################################################################
# BEGIN INSTRUCTION IMPLEMENTATIONS AT LENGTH # BEGIN INSTRUCTION IMPLEMENTATIONS AT LENGTH
#################################################################################################################### ####################################################################################################################
@opcode_dispatch @opcode_dispatch
def _handle_opcode(self, state: InterpreterState, opcode: isa.Opcode) -> InterpreterState: def handle_opcode(self, state: InterpreterState, opcode: isa.Opcode) -> InterpreterState:
"""Generic entrypoint. Exists to establish a type signature and provide singledispatch handling.""" """Generic entrypoint. Exists to establish a type signature and provide singledispatch handling."""
return self.handle_unknown(state, opcode) return self.handle_unknown(state, opcode)
@_handle_opcode.register(object) @handle_opcode.register(object)
def _handle_unknown(self, state: InterpreterState, opcode: isa.Opcode) -> InterpreterState: def handle_unknown(self, state: InterpreterState, opcode: isa.Opcode) -> InterpreterState:
return self.handle_unknown(state, opcode) return self.handle_unknown(state, opcode)
@_handle_opcode.register(isa.IDENTIFIERC) @handle_opcode.register(isa.IDENTIFIERC)
def _handle_identifierc(self, state: InterpreterState, opcode: isa.IDENTIFIERC) -> InterpreterState: def handle_identifierc(self, state: InterpreterState, opcode: isa.IDENTIFIERC) -> InterpreterState:
name = opcode.val name = opcode.val
if not (name in state.module.functions if not (name in state.module.functions
or name in state.module.types or name in state.module.types
@ -208,8 +208,8 @@ class Interpreter(BaseInterpreter):
state.stackframe._ip += 1 state.stackframe._ip += 1
return state return state
@_handle_opcode.register(isa.TYPEREF) @handle_opcode.register(isa.TYPEREF)
def _handle_typeref(self, state, opcode) -> InterpreterState: def handle_typeref(self, state, opcode) -> InterpreterState:
id = state.stackframe.pop() id = state.stackframe.pop()
if not isinstance(id, Identifier): if not isinstance(id, Identifier):
return self.handle_fault(state, opcode, "TYPEREF consumes an identifier") return self.handle_fault(state, opcode, "TYPEREF consumes an identifier")
@ -221,8 +221,8 @@ class Interpreter(BaseInterpreter):
state.stackframe._ip += 1 state.stackframe._ip += 1
return state return state
@_handle_opcode.register(isa.ARMREF) @handle_opcode.register(isa.ARMREF)
def _handle_armref(self, state, opcode) -> InterpreterState: def handle_armref(self, state, opcode) -> InterpreterState:
id: Identifier = state.stackframe.pop() id: Identifier = state.stackframe.pop()
if not isinstance(id, Identifier): if not isinstance(id, Identifier):
return self.handle_fault(state, opcode, "VARIANTREF consumes an identifier and a typeref") return self.handle_fault(state, opcode, "VARIANTREF consumes an identifier and a typeref")
@ -239,8 +239,8 @@ class Interpreter(BaseInterpreter):
state.stackframe._ip += 1 state.stackframe._ip += 1
return state return state
@_handle_opcode.register(isa.ARM) @handle_opcode.register(isa.ARM)
def _handle_arm(self, state: InterpreterState, opcode: isa.ARM) -> InterpreterState: def handle_arm(self, state: InterpreterState, opcode: isa.ARM) -> InterpreterState:
armref: VariantRef = state.stackframe.pop() armref: VariantRef = state.stackframe.pop()
if not isinstance(armref, VariantRef): if not isinstance(armref, VariantRef):
return self.handle_fault(state, opcode, "VARIANT must be given a valid constructor reference") return self.handle_fault(state, opcode, "VARIANT must be given a valid constructor reference")
@ -260,8 +260,8 @@ class Interpreter(BaseInterpreter):
state.stackframe._ip += 1 state.stackframe._ip += 1
return state return state
@_handle_opcode.register(isa.ATEST) @handle_opcode.register(isa.ATEST)
def _handle_atest(self, state: InterpreterState, opcode: isa.ATEST) -> InterpreterState: def handle_atest(self, state: InterpreterState, opcode: isa.ATEST) -> InterpreterState:
armref: VariantRef = state.stackframe.pop() armref: VariantRef = state.stackframe.pop()
if not isinstance(armref, VariantRef): if not isinstance(armref, VariantRef):
return self.handle_fault(state, opcode, "VTEST must be given a variant reference") return self.handle_fault(state, opcode, "VTEST must be given a variant reference")
@ -277,15 +277,15 @@ class Interpreter(BaseInterpreter):
return state return state
@_handle_opcode.register(isa.GOTO) @handle_opcode.register(isa.GOTO)
def _handle_goto(self, state, opcode: isa.GOTO) -> InterpreterState: def handle_goto(self, state, opcode: isa.GOTO) -> InterpreterState:
if (opcode.target < 0): if (opcode.target < 0):
return self.handle_fault(state, opcode, "Illegal branch target") return self.handle_fault(state, opcode, "Illegal branch target")
state.stackframe.goto(opcode.target) state.stackframe.goto(opcode.target)
return state return state
@_handle_opcode.register(isa.DUP) @handle_opcode.register(isa.DUP)
def _handle_dupe(self, state, opcode: isa.DUP) -> InterpreterState: def handle_dupe(self, state, opcode: isa.DUP) -> InterpreterState:
if (opcode.nargs > len(state.stackframe)): if (opcode.nargs > len(state.stackframe)):
return self.handle_fault(state, opcode, "Stack size violation") return self.handle_fault(state, opcode, "Stack size violation")
@ -293,8 +293,8 @@ class Interpreter(BaseInterpreter):
state.stackframe._ip += 1 state.stackframe._ip += 1
return state return state
@_handle_opcode.register(isa.ROT) @handle_opcode.register(isa.ROT)
def _handle_rot(self, state, opcode: isa.DUP) -> InterpreterState: def handle_rot(self, state, opcode: isa.DUP) -> InterpreterState:
if (opcode.nargs > len(state.stackframe)): if (opcode.nargs > len(state.stackframe)):
return self.handle_fault(state, opcode, "Stack size violation") return self.handle_fault(state, opcode, "Stack size violation")
@ -302,8 +302,8 @@ class Interpreter(BaseInterpreter):
state.stackframe._ip += 1 state.stackframe._ip += 1
return state return state
@_handle_opcode.register(isa.DROP) @handle_opcode.register(isa.DROP)
def _handle_drop(self, state, opcode: isa.DROP) -> InterpreterState: def handle_drop(self, state, opcode: isa.DROP) -> InterpreterState:
if (opcode.nargs > len(state.stackframe)): if (opcode.nargs > len(state.stackframe)):
return self.handle_fault(state, opcode, "Stack size violation") return self.handle_fault(state, opcode, "Stack size violation")
@ -311,8 +311,8 @@ class Interpreter(BaseInterpreter):
state.stackframe._ip += 1 state.stackframe._ip += 1
return state return state
@_handle_opcode.register(isa.SLOT) @handle_opcode.register(isa.SLOT)
def _handle_slot(self, state, opcode: isa.SLOT) -> InterpreterState: def handle_slot(self, state, opcode: isa.SLOT) -> InterpreterState:
if (opcode.target < 0): if (opcode.target < 0):
return self.handle_fault(state, opcode, "SLOT must have a positive reference") return self.handle_fault(state, opcode, "SLOT must have a positive reference")
@ -323,8 +323,8 @@ class Interpreter(BaseInterpreter):
state.stackframe._ip += 1 state.stackframe._ip += 1
return state return state
@_handle_opcode.register(isa.FUNREF) @handle_opcode.register(isa.FUNREF)
def _handle_funref(self, state, opcode) -> InterpreterState: def handle_funref(self, state, opcode) -> InterpreterState:
id = state.stackframe.pop() id = state.stackframe.pop()
if not isinstance(id, Identifier): if not isinstance(id, Identifier):
return self.handle_fault(state, opcode, "FUNREF consumes an IDENTIFIER") return self.handle_fault(state, opcode, "FUNREF consumes an IDENTIFIER")
@ -337,8 +337,8 @@ class Interpreter(BaseInterpreter):
state.stackframe._ip += 1 state.stackframe._ip += 1
return state return state
@_handle_opcode.register(isa.CALLF) @handle_opcode.register(isa.CALLF)
def _handle_callf(self, state, opcode: isa.CALLF) -> InterpreterState: def handle_callf(self, state, opcode: isa.CALLF) -> InterpreterState:
sig = state.stackframe.pop() sig = state.stackframe.pop()
if not isinstance(sig, FunctionRef): if not isinstance(sig, FunctionRef):
return self.handle_fault(state, opcode, "CALLF requires a funref at top of stack") return self.handle_fault(state, opcode, "CALLF requires a funref at top of stack")
@ -358,8 +358,8 @@ class Interpreter(BaseInterpreter):
return state return state
@_handle_opcode.register(isa.RETURN) @handle_opcode.register(isa.RETURN)
def _handle_return(self, state, opcode: isa.RETURN) -> InterpreterState: def handle_return(self, state, opcode: isa.RETURN) -> InterpreterState:
n = 1 # FIXME: clean this up n = 1 # FIXME: clean this up
if (n > len(state.stackframe)): if (n > len(state.stackframe)):
return self.handle_fault(state, opcode, "Stack size violation") return self.handle_fault(state, opcode, "Stack size violation")
@ -373,8 +373,8 @@ class Interpreter(BaseInterpreter):
state.stackframe = state.stackframe.ret(n) state.stackframe = state.stackframe.ret(n)
return state return state
@_handle_opcode.register(isa.CLOSUREF) @handle_opcode.register(isa.CLOSUREF)
def _handle_closuref(self, state: InterpreterState, opcode: isa.CLOSUREF) -> InterpreterState: def handle_closuref(self, state: InterpreterState, opcode: isa.CLOSUREF) -> InterpreterState:
n = opcode.nargs n = opcode.nargs
sig = state.stackframe.pop() sig = state.stackframe.pop()
@ -397,8 +397,8 @@ class Interpreter(BaseInterpreter):
state.stackframe._ip += 1 state.stackframe._ip += 1
return state return state
@_handle_opcode.register(isa.CLOSUREC) @handle_opcode.register(isa.CLOSUREC)
def _handle_closurec(self, state, opcode: isa.CLOSUREC) -> InterpreterState: def handle_closurec(self, state, opcode: isa.CLOSUREC) -> InterpreterState:
n = opcode.nargs n = opcode.nargs
c = state.stackframe.pop() c = state.stackframe.pop()
@ -421,8 +421,8 @@ class Interpreter(BaseInterpreter):
state.stackframe._ip += 1 state.stackframe._ip += 1
return state return state
@_handle_opcode.register(isa.CALLC) @handle_opcode.register(isa.CALLC)
def _handle_callc(self, state, opcode: isa.CALLC) -> InterpreterState: def handle_callc(self, state, opcode: isa.CALLC) -> InterpreterState:
n = opcode.nargs n = opcode.nargs
c = state.stackframe.pop() c = state.stackframe.pop()
if not isinstance(c, Closure): if not isinstance(c, Closure):
@ -445,6 +445,6 @@ class Interpreter(BaseInterpreter):
state.stackframe = state.stackframe.call(fun, ip) state.stackframe = state.stackframe.call(fun, ip)
return state return state
@_handle_opcode.register(isa.BREAK) @handle_opcode.register(isa.BREAK)
def _handle_break(self, state, _) -> InterpreterState: def handle_break(self, state, _) -> InterpreterState:
raise InterpreterReturn(state.stackframe._stack) raise InterpreterReturn(state.stackframe._stack)