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.