haskell-te: 98de8d74c47c8601f0fedc6d329ddee6a0fc3524

     1: #!/usr/bin/env python
     2: # -*- coding: utf-8 -*-
     3: from json import loads
     4: from sys  import stdin
     5: 
     6: def dedupe(l):
     7:     result = []
     8:     for x in l:
     9:         if x not in result:
    10:             result += [x]
    11:     return result
    12: 
    13: def names(expr):
    14:     def go(x):
    15:         return {
    16:             'constant'    : lambda: [x['symbol']],
    17:             'variable'    : lambda: [],
    18:             'application' : lambda: go(x['lhs']) + go(x['rhs']),
    19:             'lambda'      : lambda: go(x['body'])
    20:         }[x['role']]()
    21:     return go(expr)
    22: 
    23: def varsOf(lhs, rhs):
    24:     def go(x):
    25:         return {
    26:             'constant'    : lambda: [],
    27:             'variable'    : lambda: [x],
    28:             'application' : lambda: go(x['lhs']) + go(x['rhs']),
    29:             'lambda'      : lambda: go(x['body'])
    30:         }[x['role']]()
    31:     return dedupe(go(lhs) + go(rhs))
    32: 
    33: def wrap(vs, expr):
    34:     '''Wraps the given expression in parentheses if it's an application.'''
    35:     return (u'({0})' if expr['role'] in ['application', 'lambda'] \
    36:                      else u'{0}').format(render(vs, expr))
    37: 
    38: # Read in all equations
    39: eqs = loads(stdin.read())
    40: 
    41: # Pick a symbol for variables which doesn't clash with any constant name
    42: syms   = dedupe(reduce(lambda r, eq: r + names(eq['lhs']) + names(eq['rhs']),
    43:                        eqs,
    44:                        []))
    45: varPre = 'v'
    46: while any([s.startswith(varPre) for s in syms]):
    47:     varPre += 'v'
    48: 
    49: def render(vs, expr):
    50:     '''Render an expression to a string, numbering variables based on vs.'''
    51:     return {
    52:         'constant'    : lambda: expr['symbol'],
    53:         'variable'    : lambda: varPre + str(vs.index(expr)),
    54:         'application' : lambda: u'{0} {1}'.format(wrap(vs, expr['lhs']),
    55:                                                   wrap(vs, expr['rhs'])),
    56:         'lambda'      : lambda: u'\u03bb{0}. {1}'.format('' if expr['arg'] is None \
    57:                                                             else expr['arg'],
    58:                                                          wrap(vs, expr['body']))
    59:     }[expr['role']]()
    60: 
    61: for eq in eqs:
    62:     vs = varsOf(eq['lhs'], eq['rhs'])
    63:     print(u'{0} ~= {1}'.format(render(vs, eq['lhs']), render(vs, eq['rhs']))
    64:                        .encode('utf-8', 'replace'))

Generated by git2html.