2015年11月22日日曜日

開発環境

  • OS X El Capitan - Apple (OS)
  • Emacs(Text Editor)
  • Python 3.5 (プログラミング言語)

アンダースタンディング コンピュテーション (Tom Stuart (著)、 笹田 耕一(著)、笹井 崇司 (翻訳)、オライリージャパン)の第1部(プログラムと機械)、2章(プログラムの意味)、2.4(表示的意味論)、2.4.2(文)を Python (本書ではRuby) で取り組んでみる。

2.4.2(文)

コード(Emacs)

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

def merge(d1, d2):
    d = d1.copy()
    d.update(d2)
    return d

class Number:
    def __init__(self, value):
        self.value = value

    def __str__(self):
        return str(self.value)

    def __repr__(self):
        return '<<{0}>>'.format(self)

    def to_python(self):
        return 'lambda e: {0}'.format(self.value)

class Add:
    def __init__(self, left, right):
        self.left = left
        self.right = right

    def __str__(self):
        return '{0} + {1}'.format(self.left, self.right)

    def __repr__(self):
        return '<<{0}>>'.format(self)

    def to_python(self):
        return 'lambda e: ({0})(e) + ({1})(e)'.format(self.left.to_python(),
                                                      self.right.to_python())
    
class Multiply:
    def __init__(self, left, right):
        self.left = left
        self.right = right

    def __str__(self):
        return '{0} * {1}'.format(self.left, self.right)

    def __repr__(self):
        return '<<{0}>>'.format(self)

    def to_python(self):
        return 'lambda e: ({0})(e) * ({1})(e)'.format(self.left.to_python(),
                                                      self.right.to_python())

class Boolean:
    def __init__(self, value):
        self.value = value

    def __str__(self):
        return str(self.value)

    def __repr__(self):
        return '<<{}>>'.format(self)

    def __eq__(self, other):
        return type(self) == type(other) and self.value == other.value

    def to_python(self):
        return 'lambda e: False'
    
class LessThan:
    def __init__(self, left, right):
        self.left = left
        self.right = right

    def __str__(self):
        return '{0} < {1}'.format(self.left, self.right)

    def __repr__(self):
        return '<<{0}>>'.format(self)

    def to_python(self):
        return 'lambda e: ({0})(e) < ({1})(e)'.format(self.left.to_python(),
                                                      self.right.to_python())
        
class Variable:
    def __init__(self, name):
        self.name = name

    def __str__(self):
        return str(self.name)

    def __repr__(self):
        return '<<{}>>'.format(self)

    def to_python(self):
        return 'lambda e: e[\'{0}\']'.format(self.name)

class DoNothing:
    def __str__(self):
        return 'do-nothing'

    def __repr__(self):
        return '<<{}>>'.format(self)

    def __eq__(self, other):
        return type(other) == type(self)

    def to_python(self):
        return 'lambda e: e'

class Assign:
    def __init__(self, name, expression):
        self.name = name
        self.expression = expression

    def __str__(self):
        return '{0} = {1}'.format(self.name, self.expression)

    def __repr__(self):
        return '<<{}>>'.format(self)

    def to_python(self):
        return 'lambda e: merge(e, {{\'{0}\': ({1})(e)}})'.format(
            self.name, self.expression.to_python())
            
class If:
    def __init__(self, condition, consequence, alternative):
        self.condition = condition
        self.consequence = consequence
        self.alternative = alternative

    def __str__(self):
        return 'if ({0}) {{ {1} }}  else {{ {2} }}'.format(
            self.condition, self.consequence, self.alternative)

    def __repr__(self):
        return '<<{0}>>'.format(self)

    def to_python(self):
        return 'lambda e: ({0})(e) if ({1})(e) else ({2})(e)'.format(
            self.consequence.to_python(),
            self.consequence.to_python(),
            self.alternative.to_python())

class Sequence:
    def __init__(self, first, second):
        self.first = first
        self.second = second

    def __str__(self):
        return '{0}; {1}'.format(self.first, self.second)

    def __repr__(self):
        return '<<{}>>'.format(self)

    def to_python(self):
        return 'lambda e: ({0})(({1})(e))'.format(
            self.second.to_python(), self.first.to_python())


def while1(e, condition, bocy):
    while condition(e):
        e = bocy(e)
    return e

class While:
    def __init__(self, condition, body):
        self.condition = condition
        self.body = body

    def __str__(self):
        return 'while ({0}) {{ {1} }}'.format(self.condition, self.body)

    def __repr__(self):
        return '<<{}>>'.format(self)

    def to_python(self):
        return 'lambda e: while1(e, {0}, {1})'.format(
            self.condition.to_python(), self.body.to_python())
        
if __name__ == '__main__':
    statement = Assign('y', Add(Variable('x'), Number(1)))
    print(statement)
    print(statement.to_python())
    func = eval(statement.to_python())
    print(func({'x': 3}))
    print()

    statement = If(Boolean(True), Number(1), Number(0))
    print(statement)
    print(statement.to_python())
    func = eval(statement.to_python())
    print(func({}))
    print()

    statement = Sequence(Assign('x', Add(Number(1), Number(1))),
                         Assign('y', Add(Variable('x'), Number(3))))
    print(statement)
    print(statement.to_python())
    func = eval(statement.to_python())
    print(func({}))
    print()

    statement = While(LessThan(Variable('x'), Number(5)),
                      Assign('x', Multiply(Variable('x'), Number(3))))
    print(statement)
    print(statement.to_python())
    func = eval(statement.to_python())
    print(func)
    print(func({'x': 1}))

入出力結果(Terminal, IPython)

$ ./sample4_2.py
y = x + 1
lambda e: merge(e, {'y': (lambda e: (lambda e: e['x'])(e) + (lambda e: 1)(e))(e)})
{'y': 4, 'x': 3}

if (True) { 1 }  else { 0 }
lambda e: (lambda e: 1)(e) if (lambda e: 1)(e) else (lambda e: 0)(e)
1

x = 1 + 1; y = x + 3
lambda e: (lambda e: merge(e, {'y': (lambda e: (lambda e: e['x'])(e) + (lambda e: 3)(e))(e)}))((lambda e: merge(e, {'x': (lambda e: (lambda e: 1)(e) + (lambda e: 1)(e))(e)}))(e))
{'y': 5, 'x': 2}

while (x < 5) { x = x * 3 }
lambda e: while1(e, lambda e: (lambda e: e['x'])(e) < (lambda e: 5)(e), lambda e: merge(e, {'x': (lambda e: (lambda e: e['x'])(e) * (lambda e: 3)(e))(e)}))
<function <lambda> at 0x108ce6488>
{'x': 9}
$

0 コメント:

コメントを投稿