Add symbol and structure support master
authorDavid Kerkeslager <kerkeslager@gmail.com>
Mon, 23 Aug 2021 21:15:33 +0000 (17:15 -0400)
committerDavid Kerkeslager <kerkeslager@gmail.com>
Mon, 23 Aug 2021 21:15:33 +0000 (17:15 -0400)
interpreter.py

index 5f71e3b..cbcfd4e 100644 (file)
@@ -1,7 +1,17 @@
+import collections
 import sys
 
 import crossplatform_ir_generation
 
 import sys
 
 import crossplatform_ir_generation
 
+Symbol = collections.namedtuple(
+    'Symbol',
+    (
+        'name',
+    ),
+)
+
+SYMBOL_TABLE = {}
+
 class Environment(object):
     def __init__(self, parent):
         self.symbols = {}
 class Environment(object):
     def __init__(self, parent):
         self.symbols = {}
@@ -140,6 +150,16 @@ def interpret(program):
             assert argument is None
             sys.exit(0)
 
             assert argument is None
             sys.exit(0)
 
+        elif instruction == 'field':
+            key = stack.pop()
+            structure = stack.pop()
+            sentinel = object()
+            result = getattr(structure, key.name, sentinel)
+
+            assert result is not sentinel
+
+            stack.append(result)
+
         elif instruction == 'get':
             index = stack.pop()
             assert isinstance(argument, int)
         elif instruction == 'get':
             index = stack.pop()
             assert isinstance(argument, int)
@@ -182,6 +202,30 @@ def interpret(program):
             assert argument.endswith('"')
             stack.append(argument[1:-1].encode('utf-8').decode('unicode_escape'))
 
             assert argument.endswith('"')
             stack.append(argument[1:-1].encode('utf-8').decode('unicode_escape'))
 
+        elif instruction == 'push_symbol':
+            assert argument.startswith('sym(')
+            assert argument.endswith(')')
+
+            result = SYMBOL_TABLE.get(argument)
+            if not result:
+                result = Symbol(name=argument[4:-1])
+                SYMBOL_TABLE[argument] = result
+
+            stack.append(result)
+
+        elif instruction == 'structure':
+            kvps = []
+
+            for i in range(argument):
+                key = stack.pop()
+                value = stack.pop()
+                kvps.append((key.name, value))
+
+            keys = tuple(reversed(list(k for k,v in kvps)))
+            result = collections.namedtuple('Structure', keys)(**dict(kvps))
+
+            stack.append(result)
+
         else:
             raise Exception('Instruction "{}" not supported (argument {}).'.format(
                 instruction,
         else:
             raise Exception('Instruction "{}" not supported (argument {}).'.format(
                 instruction,