2022-04-12 07:49:12 +00:00
|
|
|
"""The instruction set for Shogoth."""
|
|
|
|
|
2022-07-16 01:33:32 +00:00
|
|
|
from abc import ABC
|
|
|
|
from dataclasses import dataclass
|
2022-04-12 07:49:12 +00:00
|
|
|
|
|
|
|
|
2022-07-16 01:33:32 +00:00
|
|
|
@dataclass
|
|
|
|
class Label(object):
|
|
|
|
name: str
|
|
|
|
|
|
|
|
def __hash__(self):
|
|
|
|
return hash(self.name)
|
|
|
|
|
|
|
|
|
|
|
|
class Opcode(ABC):
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
@dataclass
|
|
|
|
class GOTO(Opcode):
|
|
|
|
"""() -> ()
|
|
|
|
|
|
|
|
Branch to another point within the same bytecode segment. The target MUST be within the same module range as the
|
|
|
|
current function. Branching does NOT update the name or module of the current function.
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
target: int
|
|
|
|
|
|
|
|
####################################################################################################
|
|
|
|
# Stack manipulation
|
|
|
|
####################################################################################################
|
|
|
|
# https://wiki.laptop.org/go/Forth_stack_operators
|
|
|
|
# https://www.forth.com/starting-forth/2-stack-manipulation-operators-arithmetic/
|
|
|
|
# https://docs.oracle.com/javase/specs/jvms/se18/html/jvms-6.html#jvms-6.5.swap
|
|
|
|
|
|
|
|
@dataclass
|
|
|
|
class DUP(Opcode):
|
|
|
|
"""(A, B, ...) -> (A, B, ...)
|
|
|
|
|
|
|
|
Duplicate the top N items of the stack.
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
nargs: int = 1
|
|
|
|
|
2022-04-12 07:49:12 +00:00
|
|
|
|
2022-07-16 01:33:32 +00:00
|
|
|
@dataclass
|
|
|
|
class ROT(Opcode):
|
|
|
|
"""(A, B, ... Z) -> (Z, A, B, ...)
|
2022-06-11 06:28:24 +00:00
|
|
|
|
2022-07-16 01:33:32 +00:00
|
|
|
Rotate the top N elements of the stack.
|
2022-06-11 06:28:24 +00:00
|
|
|
|
2022-07-16 01:33:32 +00:00
|
|
|
"""
|
2022-06-11 06:28:24 +00:00
|
|
|
|
2022-07-16 01:33:32 +00:00
|
|
|
nargs: int = 2
|
2022-06-11 06:28:24 +00:00
|
|
|
|
2022-07-16 01:33:32 +00:00
|
|
|
@dataclass
|
|
|
|
class DROP(Opcode):
|
|
|
|
"""(*) -> ()
|
2022-06-11 06:28:24 +00:00
|
|
|
|
2022-07-16 01:33:32 +00:00
|
|
|
Drop the top N items of the stack.
|
2022-06-01 06:22:53 +00:00
|
|
|
|
2022-07-16 01:33:32 +00:00
|
|
|
"""
|
2022-06-01 06:22:53 +00:00
|
|
|
|
2022-07-16 01:33:32 +00:00
|
|
|
nargs: int = 1
|
2022-04-12 07:49:12 +00:00
|
|
|
|
|
|
|
|
2022-07-16 01:33:32 +00:00
|
|
|
@dataclass
|
|
|
|
class SLOT(Opcode):
|
|
|
|
"""(..., A) -> (A, ..., A)
|
2022-06-01 06:22:53 +00:00
|
|
|
|
2022-07-16 01:33:32 +00:00
|
|
|
Copy the Nth (counting up from 0 at the bottom of the stack) item to the top of the stack.
|
|
|
|
Intended to allow users to emulate (immutable) frame local slots for reused values.
|
2022-06-01 06:22:53 +00:00
|
|
|
|
2022-07-16 01:33:32 +00:00
|
|
|
"""
|
2022-04-12 07:49:12 +00:00
|
|
|
|
2022-07-16 01:33:32 +00:00
|
|
|
target: int
|
2022-04-12 07:49:12 +00:00
|
|
|
|
2022-07-16 01:33:32 +00:00
|
|
|
####################################################################################################
|
|
|
|
# Functional abstraction
|
|
|
|
####################################################################################################
|
2022-06-01 06:22:53 +00:00
|
|
|
|
2022-07-16 01:33:32 +00:00
|
|
|
@dataclass
|
|
|
|
class IDENTIFIERC(Opcode):
|
|
|
|
"""() -> (IDENTIFIER)
|
2022-06-01 06:22:53 +00:00
|
|
|
|
2022-07-16 01:33:32 +00:00
|
|
|
An inline constant which produces an identifier to the stack.
|
2022-04-12 07:49:12 +00:00
|
|
|
|
2022-07-16 01:33:32 +00:00
|
|
|
Identifiers name functions, fields and types but are not strings.
|
|
|
|
They are a VM-internal naming structure with reference to the module.
|
2022-04-12 07:49:12 +00:00
|
|
|
|
2022-07-16 01:33:32 +00:00
|
|
|
"""
|
2022-04-21 06:17:59 +00:00
|
|
|
|
2022-07-16 01:33:32 +00:00
|
|
|
val: str
|
2022-06-01 06:22:53 +00:00
|
|
|
|
2022-04-12 07:49:12 +00:00
|
|
|
|
2022-07-16 01:33:32 +00:00
|
|
|
@dataclass
|
|
|
|
class FUNREF(Opcode):
|
|
|
|
"""(IDENTIFIER) -> (`FUNREF<... A to ... B>`)
|
2022-06-01 06:22:53 +00:00
|
|
|
|
2022-07-16 01:33:32 +00:00
|
|
|
Construct a reference to a static codepoint.
|
2022-04-12 07:49:12 +00:00
|
|
|
|
2022-07-16 01:33:32 +00:00
|
|
|
"""
|
2022-04-12 07:49:12 +00:00
|
|
|
|
2022-07-16 01:33:32 +00:00
|
|
|
@dataclass
|
|
|
|
class CALLF(Opcode):
|
|
|
|
"""(`FUNREF<... A to ... B>`, ... A) -> (... B)
|
2022-06-01 06:22:53 +00:00
|
|
|
|
2022-07-16 01:33:32 +00:00
|
|
|
Call [funref]
|
2022-06-01 06:22:53 +00:00
|
|
|
|
2022-07-16 01:33:32 +00:00
|
|
|
Make a dynamic call to the function reference at the top of stack.
|
|
|
|
The callee will see a stack containg only the provided `nargs`.
|
|
|
|
A subsequent RETURN will return execution to the next point.
|
2022-04-12 07:49:12 +00:00
|
|
|
|
2022-07-16 01:33:32 +00:00
|
|
|
Executing a `CALL` pushes the name and module path of the current function.
|
2022-04-12 07:49:12 +00:00
|
|
|
|
2022-07-16 01:33:32 +00:00
|
|
|
"""
|
2022-06-01 06:22:53 +00:00
|
|
|
|
2022-07-16 01:33:32 +00:00
|
|
|
nargs: int = 0
|
2022-06-01 06:22:53 +00:00
|
|
|
|
2022-07-16 01:33:32 +00:00
|
|
|
@dataclass
|
|
|
|
class RETURN(Opcode):
|
|
|
|
"""(... A) -> ()
|
2022-04-21 06:17:59 +00:00
|
|
|
|
2022-07-16 01:33:32 +00:00
|
|
|
Return to the source of the last `CALL`. The returnee will see the top `nargs` values of the present stack
|
|
|
|
appended to theirs. All other values on the stack will be discarded.
|
2022-06-01 06:22:53 +00:00
|
|
|
|
2022-07-16 01:33:32 +00:00
|
|
|
Executing a `RETURN` pops (restores) the name and module path of the current function back to that of the caller.
|
2022-04-21 06:17:59 +00:00
|
|
|
|
2022-07-16 01:33:32 +00:00
|
|
|
If the call stack is empty, `RETURN` will exit the interpreter.
|
2022-04-21 06:17:59 +00:00
|
|
|
|
2022-07-16 01:33:32 +00:00
|
|
|
"""
|
2022-06-01 06:22:53 +00:00
|
|
|
|
2022-07-16 01:33:32 +00:00
|
|
|
nargs: int
|
2022-04-12 07:49:12 +00:00
|
|
|
|
2022-04-21 06:17:59 +00:00
|
|
|
|
2022-07-16 01:33:32 +00:00
|
|
|
@dataclass
|
|
|
|
class CLOSUREF(Opcode):
|
|
|
|
"""(`FUNREF<A, ... B to ... C>`, A) -> (`CLOSURE<... B to ... C>`)
|
2022-06-11 06:28:24 +00:00
|
|
|
|
2022-07-16 01:33:32 +00:00
|
|
|
Construct a closure over the function reference at the top of the stack. This may produce nullary closures.
|
2022-06-11 06:28:24 +00:00
|
|
|
|
2022-07-16 01:33:32 +00:00
|
|
|
"""
|
2022-06-11 06:28:24 +00:00
|
|
|
|
2022-07-16 01:33:32 +00:00
|
|
|
nargs: int = 0
|
2022-06-11 06:28:24 +00:00
|
|
|
|
|
|
|
|
2022-07-16 01:33:32 +00:00
|
|
|
@dataclass
|
|
|
|
class CLOSUREC(Opcode):
|
|
|
|
"""(`CLOSURE<A, ... B to ... C>`, A) -> (`CLOSURE<... B to ... C>`)
|
2022-06-11 06:28:24 +00:00
|
|
|
|
2022-07-16 01:33:32 +00:00
|
|
|
Further close over the closure at the top of the stack. This may produce nullary closures.
|
2022-06-11 06:28:24 +00:00
|
|
|
|
2022-07-16 01:33:32 +00:00
|
|
|
"""
|
2022-06-01 06:22:53 +00:00
|
|
|
|
2022-07-16 01:33:32 +00:00
|
|
|
nargs: int = 0
|
2022-06-01 06:22:53 +00:00
|
|
|
|
2022-06-01 06:11:14 +00:00
|
|
|
|
2022-07-16 01:33:32 +00:00
|
|
|
class CALLC(Opcode):
|
|
|
|
"""(`CLOSURE<... A to ... B>`, ... A) -> (... B)
|
2022-04-21 06:17:59 +00:00
|
|
|
|
2022-07-16 01:33:32 +00:00
|
|
|
Call [closure]
|
2022-06-01 06:22:53 +00:00
|
|
|
|
2022-07-16 01:33:32 +00:00
|
|
|
Make a dynamic call to the closure at the top of stack.
|
|
|
|
The callee will see a stack containg only the provided `nargs` and closed-overs.
|
|
|
|
A subsequent RETURN will return execution to the next point.
|
2022-06-01 06:22:53 +00:00
|
|
|
|
2022-07-16 01:33:32 +00:00
|
|
|
Executing a `CALL` pushes the name and module path of the current function.
|
2022-06-01 06:11:14 +00:00
|
|
|
|
2022-07-16 01:33:32 +00:00
|
|
|
"""
|
2022-04-21 06:17:59 +00:00
|
|
|
|
2022-07-16 01:33:32 +00:00
|
|
|
nargs: int = 0
|
2022-06-01 06:22:53 +00:00
|
|
|
|
2022-07-16 01:33:32 +00:00
|
|
|
####################################################################################################
|
|
|
|
# Structures
|
|
|
|
####################################################################################################
|
2022-04-21 06:17:59 +00:00
|
|
|
|
2022-07-16 01:33:32 +00:00
|
|
|
# FIXME: This lacks any sort of way to do dynamic type/field references
|
2022-04-21 06:17:59 +00:00
|
|
|
|
2022-07-16 01:33:32 +00:00
|
|
|
@dataclass
|
|
|
|
class TYPEREF(Opcode):
|
|
|
|
"""(IDENTIFIER) -> (TYPEREF)
|
2022-06-01 06:22:53 +00:00
|
|
|
|
2022-07-16 01:33:32 +00:00
|
|
|
Produces a TYPEREF to the type named by the provided IDENTIFIER.
|
2022-04-21 06:17:59 +00:00
|
|
|
|
2022-07-16 01:33:32 +00:00
|
|
|
"""
|
2022-04-21 06:17:59 +00:00
|
|
|
|
2022-06-07 16:32:15 +00:00
|
|
|
|
2022-07-16 01:33:32 +00:00
|
|
|
@dataclass
|
|
|
|
class VARIANTREF(Opcode):
|
|
|
|
"""(IDENTIFIER, TYPEREF) -> (VARIANTREF)
|
2022-06-07 16:32:15 +00:00
|
|
|
|
2022-07-16 01:33:32 +00:00
|
|
|
Produce a VARIANTREF to an 'arm' of the given variant type.
|
2022-06-07 16:32:15 +00:00
|
|
|
|
2022-07-16 01:33:32 +00:00
|
|
|
"""
|
2022-06-07 16:32:15 +00:00
|
|
|
|
|
|
|
|
2022-07-16 01:33:32 +00:00
|
|
|
@dataclass
|
|
|
|
class VARIANT(Opcode):
|
|
|
|
"""(VARIANTREF<a ⊢ A ⊂ B>, ...) -> (B)
|
2022-06-07 16:32:15 +00:00
|
|
|
|
2022-07-16 01:33:32 +00:00
|
|
|
Construct an instance of an 'arm' of a variant.
|
|
|
|
The type of the 'arm' is considered to be the type of the whole variant.
|
2022-06-07 16:32:15 +00:00
|
|
|
|
2022-07-16 01:33:32 +00:00
|
|
|
The name and module path of the current function MUST match the name and module path of `VARIANTREF`.
|
|
|
|
The arity of this opcode MUST match the arity of the arm.
|
|
|
|
The signature of the arm MUST match the signature fo the top N of the stack.
|
|
|
|
"""
|
2022-06-07 16:32:15 +00:00
|
|
|
|
2022-07-16 01:33:32 +00:00
|
|
|
nargs: int = 0
|
2022-06-07 16:32:15 +00:00
|
|
|
|
|
|
|
|
2022-07-16 01:33:32 +00:00
|
|
|
@dataclass
|
|
|
|
class VTEST(Opcode):
|
|
|
|
"""(VARIANTREF<a ⊢ A ⊂ B>, B) -> ()
|
2022-06-07 16:32:15 +00:00
|
|
|
|
2022-07-16 01:33:32 +00:00
|
|
|
Test whether B is a given arm of a variant A .
|
|
|
|
If it is, branch to the given target.
|
|
|
|
Otherwise fall through.
|
2022-06-07 16:32:15 +00:00
|
|
|
|
2022-07-16 01:33:32 +00:00
|
|
|
"""
|
2022-06-07 16:32:15 +00:00
|
|
|
|
2022-07-16 01:33:32 +00:00
|
|
|
target: int
|
2022-06-07 16:32:15 +00:00
|
|
|
|
|
|
|
|
2022-07-16 01:33:32 +00:00
|
|
|
@dataclass
|
|
|
|
class VLOAD(Opcode):
|
|
|
|
"""(VARIANTREF<a ⊢ A ⊂ B>, B) -> (A)
|
2022-06-16 05:10:54 +00:00
|
|
|
|
2022-07-16 01:33:32 +00:00
|
|
|
Load the value of the variant arm.
|
|
|
|
VLOAD errors (undefined) if B is not within the variant.
|
|
|
|
VLOAD errors (undefined) if the value in B is not an A - use VTEST as needed.
|
2022-06-07 16:32:15 +00:00
|
|
|
|
2022-07-16 01:33:32 +00:00
|
|
|
"""
|
2022-06-07 16:32:15 +00:00
|
|
|
|
|
|
|
|
2022-07-16 01:33:32 +00:00
|
|
|
@dataclass
|
|
|
|
class BREAK(Opcode):
|
|
|
|
"""Abort the interpreter."""
|