Newer
Older
NewLang / interp.py
# SPDX-License-Identifier: MIT
# Copyright 2021 Jookia <contact@jookia.org>

import ast_types

class Text:
    def __init__(self, value):
        self._value = value

    def __repr__(self):
        return "Text('%s')" % (self._value)

    def value(self):
        return self._value

    def verb_Append(self, args):
        appendix = args[0]
        return Text(self.value() + " " + appendix.value())

class Module_System:
    def verb_Print(self, args):
        print(args[0].value())

    def verb_Read(self, args):
        return Text(input())

class InterpreterError(BaseException):
    def __init__(self, error):
        self.error = error

    def __repr__(self):
        return "InterpreterError(error '%s')" % (self.error)

class Interpreter:
    def __init__(self, env):
        self.env = env

    def resolve_value(self, value):
        if value.__class__ == ast_types.Reference:
            return self.env[value.value]
        elif value.__class__ == ast_types.Text:
            return Text(value.value)
        else:
            raise InterpreterError("Unknown value type %s" % (value.__class__.__name__))

    def run_statement(self, ast):
        subject = self.resolve_value(ast.subject)
        if ast.verb == None:
            return subject
        args = []
        for arg in ast.arguments:
            args.append(self.resolve_value(arg))
        return getattr(subject, "verb_" + ast.verb)(args)

    def run_set(self, ast):
        self.env[ast.subject] = self.run_statement(ast.statement)
        return self.env[ast.subject]

    def run_conditional(self, ast):
        raise InterpreterError("Conditionals are unimplemented")

    def run_command(self, ast):
        if ast.__class__ == ast_types.Statement:
            return self.run_statement(ast)
        elif ast.__class__ == ast_types.Set:
            return self.run_set(ast)
        elif ast.__class__ == ast_types.Conditional:
            return self.run_conditional(ast)
        else:
            raise InterpreterError("Unknown command type %s" % (ast.__class__.__name__))

    def run(self, ast):
        ret = None
        for command in ast:
            ret = self.run_command(command)
        return ret

def run_ast(ast):
    env = {
        "System": Module_System(),
    }
    try:
        return Interpreter(env).run(ast)
    except InterpreterError as e:
        print("Interpreter error: %s" % (e))
        return None