From: David Kerkeslager Date: Mon, 23 Aug 2021 21:15:33 +0000 (-0400) Subject: Add symbol and structure support X-Git-Url: https://code.kerkeslager.com/?a=commitdiff_plain;h=c9f3ff468993d92c3e32de627f1ac725859c8dd4;p=fur Add symbol and structure support --- diff --git a/interpreter.py b/interpreter.py index 5f71e3b..cbcfd4e 100644 --- a/interpreter.py +++ b/interpreter.py @@ -1,7 +1,17 @@ +import collections import sys import crossplatform_ir_generation +Symbol = collections.namedtuple( + 'Symbol', + ( + 'name', + ), +) + +SYMBOL_TABLE = {} + class Environment(object): def __init__(self, parent): self.symbols = {} @@ -140,6 +150,16 @@ def interpret(program): 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) @@ -182,6 +202,30 @@ def interpret(program): 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,