Skip to content

Instantly share code, notes, and snippets.

@tomotaka
Last active October 6, 2016 06:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tomotaka/9d2e57295a81e2d853ca5b80f3f8fdd8 to your computer and use it in GitHub Desktop.
Save tomotaka/9d2e57295a81e2d853ca5b80f3f8fdd8 to your computer and use it in GitHub Desktop.
orelang python impl
# -*- 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