Tapping towards structs and variants

This commit is contained in:
Reid D. 'arrdem' McKenzie 2022-06-07 10:32:15 -06:00
parent 6bc9bb9b59
commit 34c550ba7f
3 changed files with 107 additions and 11 deletions

View file

@ -236,7 +236,7 @@ class Interpreter(object):
if n + len(c.frag) != len(c.funref.args):
_error("CALLC target vionation; argument count missmatch")
if n > len(stack):
_error("Stack size vionation")
_error("Stack size violation")
# Extract the function signature
sig = c.funref
@ -253,6 +253,23 @@ class Interpreter(object):
stack = stack.call(sig, ip)
continue
case Opcode.STRUCT(structref, n):
if not (t := module.types.get(structref)):
_error(f"STRUCT must reference a known type, {structref!r} is undefined")
if n > len(stack):
_error("Stack size violation")
args = stack[:n]
stack.drop(n)
# FIXME: typecheck
for arg, ftype in zip(args, t.children):
pass
inst = Struct(structref, [], dict(zip(t.field_names, args)))
stack.push(inst)
case _:
raise Exception(f"Unhandled interpreter state {op}")

View file

@ -175,19 +175,58 @@ class Opcode:
####################################################################################################
# Structures
####################################################################################################
# FIXME: This lacks any sort of way to do dynamic field references
class IDENTIFIERC(t.NamedTuple):
"""() -> (CONST)
An inline constant which produces an identifier to the stack.
Identifiers name functions, fields and types but are not strings.
They are a VM-internal naming structure with reference to the module.
"""
val: str
class TYPEREF(t.NamedTuple):
"""(IDENTIFIER) -> (TYPEREF)
Produces a TYPEREF to the type named by the provided IDENTIFIER.
"""
class FIELDREF(t.NamedTuple):
"""(IDENTIFIER, TYPEREF) -> (FIELDREF)
Produces a FIELDREF to the field named by the provided IDENTIFIER.
The FIELDREF must be within and with reference to a sum type.
"""
class VARIANTREF(t.NamedTuple):
"""(IDENTIFIER, TYPEREF) -> (VARIANTREF)
Produce a VARIANTREF to an 'arm' of the given variant type.
"""
class STRUCT(t.NamedTuple):
"""(*) -> (T)
"""(STRUCTREF<S>, ...) -> (S)
Consume the top N items of the stack, producing a struct of the type `structref`.
The name and module path of the current function MUST match the name and module path of `structref`.
The arity of this opcode MUST match the arity of the struct.
The signature of the struct MUST match the signature fo the top N of the stack.
"""
structref: str
nargs: int
nargs: int = 0
class FLOAD(t.NamedTuple):
"""(A) -> (B)
"""(FIELDREF<f ⊢ T ∈ S>, S) -> (T)
Consume the struct reference at the top of the stack, producing the value of the referenced field.
@ -196,7 +235,7 @@ class Opcode:
fieldref: str
class FSTORE(t.NamedTuple):
"""(A, B) -> (A)
"""(FIELDREF<f ⊢ T ∈ S>, S, T) -> (S)
Consume the struct reference at the top of the stack and a value, producing a new copy of the struct in which
that field has been updated to the new value.
@ -205,6 +244,35 @@ class Opcode:
fieldref: str
class VARIANT(t.NamedTuple):
"""(VARIANTREF<a ⊢ A ⊂ B>, ...) -> (B)
Construct an instance of an 'arm' of a variant.
The type of the 'arm' is considered to be the type of the whole variant.
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.
"""
nargs: int = 0
class VTEST(t.NamedTuple):
"""(VARIANTREF<a ⊢ A ⊂ B>, B) -> (bool)
Test whether B is a given arm of a variant A .
"""
class VLOAD(t.NamedTuple):
"""(VARIANTREF<a ⊢ A ⊂ B>, B) -> (A)
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.
"""
####################################################################################################
# Arrays
####################################################################################################

View file

@ -22,6 +22,14 @@ class ProductExpr(t.NamedTuple):
children: t.Mapping[str, t.Any]
# FIXME: How exactly
class StructExpr(t.NamedTuple):
name: str
type_params: list
field_names: t.List[str]
children: t.List[t.Any]
####################################################################################################
####################################################################################################
####################################################################################################
@ -50,8 +58,10 @@ class FunctionRef(t.NamedTuple):
class Closure(t.NamedTuple):
target: t.Union["Closure", FunctionRef]
args: t.List[t.Any]
# Note that a closure over a closure is equivalent to a single closure which extends the captured stack fragment, so
# there's no need for a union here as we can simply convert nested closures.
funref: FunctionRef
frag: t.List[t.Any]
class FunctionSignature(t.NamedTuple):
@ -77,6 +87,7 @@ class FunctionSignature(t.NamedTuple):
)
class Closure(t.NamedTuple):
funref: FunctionRef
frag: t.List[t.Any]
class Struct(t.NamedTuple):
name: str
type_params: list
children: t.Mapping[str, t.Any]