diff --git a/projects/shoggoth/src/python/ichor/__main__.py b/projects/shoggoth/src/python/ichor/__main__.py
index 7aa87ad..8ba9303 100644
--- a/projects/shoggoth/src/python/ichor/__main__.py
+++ b/projects/shoggoth/src/python/ichor/__main__.py
@@ -17,7 +17,7 @@ def main():
             Opcode.CALLC(1),
             Opcode.RETURN(1),
         ],
-        stack = [True, True, False]
+        stackframe = [True, True, False]
     )
     print(ret)
 
diff --git a/projects/shoggoth/src/python/ichor/impl.py b/projects/shoggoth/src/python/ichor/impl.py
index 832e757..7569bb3 100644
--- a/projects/shoggoth/src/python/ichor/impl.py
+++ b/projects/shoggoth/src/python/ichor/impl.py
@@ -12,7 +12,7 @@ context (a virtual machine) which DOES have an easily introspected and serialize
 from copy import deepcopy
 
 from ichor.isa import Opcode
-from ichor.typing import Closure, FunctionRef, Identifier
+from ichor.state import Closure, FunctionRef, Identifier, Module
 
 
 def rotate(l):
@@ -76,7 +76,7 @@ class InterpreterError(Exception):
 
 class Interpreter(object):
     """A shit simple instruction pointer based interpreter."""
-    def __init__(self, bootstrap_module):
+    def __init__(self, bootstrap_module: Module):
         self.bootstrap = bootstrap_module
 
     def run(self, opcodes, stack=[]):
@@ -94,7 +94,7 @@ class Interpreter(object):
             raise InterpreterError(mod, deepcopy(stackframe), msg)
 
         while True:
-            op = mod.opcodes[stackframe.ip]
+            op = mod.codepage[stackframe.ip]
             print("{0}{1: <50} {2}: {3}".format("  " * stackframe.depth, str(stackframe.stack), stackframe.ip, op))
 
             match op:
diff --git a/projects/shoggoth/src/python/ichor/state.py b/projects/shoggoth/src/python/ichor/state.py
new file mode 100644
index 0000000..deb30a9
--- /dev/null
+++ b/projects/shoggoth/src/python/ichor/state.py
@@ -0,0 +1,139 @@
+#!/usr/bin/env python3
+
+"""The core VM/interpreter model."""
+
+
+import typing as t
+
+from ichor.isa import Opcode
+
+
+class Identifier(t.NamedTuple):
+    name: str
+
+
+class FunctionSignature(t.NamedTuple):
+    raw: str
+    type_params: list
+    name: str
+    args: list
+    ret: list
+
+    @staticmethod
+    def parse_list(l):
+        return [e for e in l.split(",") if e]
+
+    @classmethod
+    def parse(cls, raw: str):
+        vars, name, args, ret = raw.split(";")
+        return cls(
+            raw,
+            cls.parse_list(vars),
+            name,
+            cls.parse_list(args),
+            cls.parse_list(ret)
+        )
+
+
+class FunctionRef(t.NamedTuple):
+    raw: str
+    type_params: list
+    name: str
+    args: list
+    ret: list
+
+    @staticmethod
+    def parse_list(l):
+        return [e for e in l.split(",") if e]
+
+    @classmethod
+    def parse(cls, raw: str):
+        vars, name, args, ret = raw.split(";")
+        return cls(
+            raw,
+            cls.parse_list(vars),
+            name,
+            cls.parse_list(args),
+            cls.parse_list(ret)
+        )
+
+
+class Function(t.NamedTuple):
+    name: str
+
+
+class Closure(t.NamedTuple):
+    # 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 Struct(t.NamedTuple):
+    name: str
+    type_params: list
+    children: t.Mapping[str, t.Any]
+
+
+class Module(t.NamedTuple):
+    codepage: list = []
+    functions: dict = {}
+    types: dict = {}
+    constants: dict = {}
+
+    def copy(self) -> "Module":
+        return Module(
+            self.codepage.copy(),
+            self.functions.copy(),
+            self.types.copy(),
+            self.constants.copy(),
+        )
+
+    @staticmethod
+    def translate(start: int, end: int, i: Opcode):
+        # FIXME: Consolidate bounds checks somehow
+        match i:
+            case Opcode.IF(t):
+                d = t + start
+                assert start <= d < end
+                return Opcode.IF(d)
+
+            case Opcode.GOTO(t):
+                d = t + start
+                assert start <= d < end
+                return Opcode.GOTO(d)
+
+            case _:
+                return i
+
+    def define_function(self, name, opcodes):
+        """Enter a function into module.
+
+        Side-effects the codepage and name table.
+
+        """
+
+        try:
+            sig = FunctionRef.parse(name)
+            assert sig.name
+        except:
+            raise ValueError("Illegal name provided")
+
+        start = len(self.codepage)
+        self.functions[name] = start
+        for op in opcodes:
+            self.codepage.append(self.translate(start, start + len(opcodes), op))
+        return name
+
+    def define_type(self, name, signature):
+        self.types[name] = signature
+        return name
+
+    def __str__(self):
+        b = []
+        marks = {v: k for k, v in self.functions.items()}
+        for i, o in zip(range(1<<64), self.codepage):
+            if(i in marks):
+                b.append(f"{marks[i]}:")
+                b.append(f"{i: >10}: {o}")
+        return "\n".join(b)
diff --git a/projects/shoggoth/src/python/ichor/typing.py b/projects/shoggoth/src/python/ichor/typing.py
index 40516fa..6cd48fe 100644
--- a/projects/shoggoth/src/python/ichor/typing.py
+++ b/projects/shoggoth/src/python/ichor/typing.py
@@ -1,3 +1,5 @@
+#!/usr/bin/env python3
+
 """The public interface for shoggoth's baked-in types."""
 
 
@@ -20,78 +22,3 @@ class SumExpr(t.NamedTuple):
 
 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]
-
-
-####################################################################################################
-####################################################################################################
-####################################################################################################
-
-class FunctionRef(t.NamedTuple):
-    raw: str
-    type_params: list
-    name: str
-    args: list
-    ret: list
-
-    @staticmethod
-    def parse_list(l):
-        return [e for e in l.split(",") if e]
-
-    @classmethod
-    def parse(cls, raw: str):
-        vars, name, args, ret = raw.split(";")
-        return cls(
-            raw,
-            cls.parse_list(vars),
-            name,
-            cls.parse_list(args),
-            cls.parse_list(ret)
-        )
-
-
-class Closure(t.NamedTuple):
-    # 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):
-    raw: str
-    type_params: list
-    name: str
-    args: list
-    ret: list
-
-    @staticmethod
-    def parse_list(l):
-        return [e for e in l.split(",") if e]
-
-    @classmethod
-    def parse(cls, raw: str):
-        vars, name, args, ret = raw.split(";")
-        return cls(
-            raw,
-            cls.parse_list(vars),
-            name,
-            cls.parse_list(args),
-            cls.parse_list(ret)
-        )
-
-
-class Struct(t.NamedTuple):
-    name: str
-    type_params: list
-    children: t.Mapping[str, t.Any]
-
-
-class Identifier(t.NamedTuple):
-    name: str
diff --git a/projects/shoggoth/test/python/ichor/fixtures.py b/projects/shoggoth/test/python/ichor/fixtures.py
index 5257a3d..1f973b4 100644
--- a/projects/shoggoth/test/python/ichor/fixtures.py
+++ b/projects/shoggoth/test/python/ichor/fixtures.py
@@ -1,6 +1,7 @@
 #!/usr/bin/env python3
 
 from ichor import Interpreter, BOOTSTRAP
+
 import pytest