Last active
October 6, 2016 06:13
-
-
Save tomotaka/9d2e57295a81e2d853ca5b80f3f8fdd8 to your computer and use it in GitHub Desktop.
orelang python impl
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding: utf-8 -*- | |
# orelang: http://qiita.com/shuetsu@github/items/ac21e597265d6bb906dc | |
# dependency: click | |
import os | |
import os.path | |
import sys | |
import json | |
import click | |
_orelang_vars = dict() | |
class Expression(object): | |
@classmethod | |
def name(klass): | |
raise NotImplementedError() | |
def __init__(self, *args): | |
self.args = args | |
def eval(self): | |
raise NotImplementedError() | |
class Value(Expression): | |
@classmethod | |
def name(klass): | |
raise NotImplementedError() | |
def eval(self): | |
return self.args[0] | |
def __repr__(self): | |
return '<Value %s>' % self.args[0] | |
class Step(Expression): | |
@classmethod | |
def name(klass): | |
return "step" | |
def eval(self): | |
for expression in self.args: | |
last_result = expression.eval() | |
return last_result | |
class OpAdd(Expression): | |
@classmethod | |
def name(klass): | |
return "+" | |
def eval(self): | |
return sum([e.eval() for e in self.args]) | |
class OpMinus(Expression): | |
@classmethod | |
def name(klass): | |
return "-" | |
def eval(self): | |
return self.args[0].eval() + sum([-1 * (i.eval()) for i in self.args[1:]]) | |
class OpMultiply(Expression): | |
@classmethod | |
def name(klass): | |
return "*" | |
def eval(self): | |
r = self.args[0].eval() | |
for i in self.args[1:]: | |
r *= i.eval() | |
return r | |
class OpDevide(Expression): | |
@classmethod | |
def name(klass): | |
return "/" | |
def eval(self): | |
r = self.args[0].eval() | |
for i in self.args[1:]: | |
r /= i.eval() | |
return r | |
class OpEqual(Expression): | |
@classmethod | |
def name(klass): | |
return "=" | |
def eval(self): | |
return self.args[0].eval() == self.args[1].eval() | |
class OpSet(Expression): | |
@classmethod | |
def name(klass): | |
return "set" | |
def eval(self): | |
name = self.args[0].eval() | |
_orelang_vars[name] = self.args[1].eval() | |
return None | |
class OpGet(Expression): | |
@classmethod | |
def name(klass): | |
return "get" | |
def eval(self): | |
name = self.args[0].eval() | |
return _orelang_vars[name] | |
class OpUntil(Expression): | |
@classmethod | |
def name(klass): | |
return "until" | |
def eval(self): | |
condition = self.args[0] | |
expression = self.args[1] | |
while not condition.eval(): | |
expression.eval() | |
return None | |
expressions = ( | |
Step, | |
OpAdd, | |
OpMinus, | |
OpMultiply, | |
OpDevide, | |
OpEqual, | |
OpSet, | |
OpGet, | |
OpUntil | |
) | |
class ExpressionFactory(object): | |
def __init__(self, *args): | |
expression_classes = args | |
self._command_name_to_class = dict() | |
for klass in expression_classes: | |
self._command_name_to_class[klass.name()] = klass | |
def build(self, name, *args): | |
klass = self._command_name_to_class[name] | |
return klass(*args) | |
def compile(factory, code): | |
if isinstance(code, (list, tuple)): | |
name = code[0] | |
args = code[1:] | |
if 0 < len(args): | |
args = [ compile(factory, exp) for exp in args ] | |
return factory.build(name, *args) | |
else: | |
return Value(code) | |
def eval_orelang(factory, code): | |
expression = compile(factory, code) | |
return expression.eval() | |
@click.command() | |
@click.option('-f', '--file', help='orelang file') | |
def main(file): | |
if not file or not os.path.exists(file): | |
print 'no such file: %s' % file | |
sys.exit(-1) | |
with open(file, 'rb') as fh: | |
code = fh.read() | |
try: | |
code = json.loads(code) | |
except: | |
print 'json parse error' | |
sys.exit(-1) | |
factory = ExpressionFactory(*expressions) | |
print eval_orelang(factory, code) | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment