orelangをPythonで実装してみた

http://qiita.com/shuetsu@github/items/ac21e597265d6bb906dc

いろんな人がいろんな言語で実装してた。 Python版が載ってなかったので参戦。

一応、引き算にも対応した。

class Engine:
    def __init__(self):
        self.operators = {}
        self.variables = {}
        
        self.operators["+"] = AddOperator()
        self.operators["-"] = SubOperator()
        self.operators["*"] = MultiplyOperator()
        self.operators["="] = EqualOperator()
        self.operators["set"] = SetOperator()
        self.operators["get"] = GetOperator()
        self.operators["until"] = UntilOperator()
        self.operators["step"] = StepOperator()

    def eval(self, script):
        return self._get_expression(script).eval(self)
    
    def _get_expression(self, script):
        if isinstance(script, list):
            script_list = script
            return CallOperator(self.operators[script_list[0]], script_list[1:])
        else:
            return ImmediateValue(script)


class CallOperator:
    def __init__(self, operator, args):
        self.operator = operator
        self.args = args
    
    def eval(self, engine):
        return self.operator.call(engine, self.args)


class ImmediateValue:
    def __init__(self, value):
        self.value = value
        
    def eval(self, engine):
        return self.value


class SubOperator:
    def call(self, engine, args):
        retval = engine.eval(args[0])
        for arg in args[1:]:
            v = engine.eval(arg)
            retval -= v
        return retval
        

class AddOperator:
    def call(self, engine, args):
        retval = 0
        for arg in args:
            v = engine.eval(arg)
            retval += v
        return retval


class MultiplyOperator:
    def call(self, engine, args):
        retval = 1
        for arg in args:
            v = engine.eval(arg)
            retval *= v
        return retval


class EqualOperator:
    def call(self, engine, args):
        return engine.eval(args[0]) == engine.eval(args[1])
    
    
class SetOperator:
    def call(self, engine, args):
        value = engine.eval(args[1])
        engine.variables[str(engine.eval(args[0]))] = value
        return value
    
    
class GetOperator:
    def call(self, engine, args):
        return engine.variables[engine.eval(args[0])]
    

class UntilOperator:
    def call(self, engine, args):
        retval = None
        while not engine.eval(args[0]):
            retval = engine.eval(args[1])
        return retval
    
    
class StepOperator:
    def call(self, engine, args):
        retval = None
        for arg in args:
            retval = engine.eval(arg)
        return retval

言語を作るのは、どうやるのか想像がしにくかったので面白かった