-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathutbp.py
102 lines (83 loc) · 3.2 KB
/
utbp.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import parser
import inspect
from function_repository import FunctionRepository
import lis
import tree
frep = FunctionRepository('defs.exh')
class UTBP(object):
def __init__(self, f):
self.f = f
self.name = f.__name__
#self.fname = inspect.getfile(f)
self.ready = False
def _prepare(self):
f = self.f
self.arg_names = tuple(inspect.getargspec(f).args)
self.n_args = len(self.arg_names)
self.use_cases = self._parse_use_cases(f.__doc__)
self.arg_types = tuple([self._type_signature([use_case[0][i]
for use_case in
self.use_cases])
for i in range(self.n_args)])
self.return_type = self._type_signature([use_case[1] for use_case
in self.use_cases])
lisp_use_cases = tuple([self._lisp_use_case(use_case)
for use_case in self.use_cases])
frep.fit(self.name, self.arg_names, self.arg_types,
self.return_type, lisp_use_cases, debug=True)
frep.consider(self.name)
self.ready = True
def _parse_use_cases(self, docstring):
examples = [[e.strip() for e in l.split('==')]
for l in docstring.strip().split('\n')]
use_cases = []
for exp, outcome_exp in examples:
name, args = parser.parse_call(exp)
assert name == self.name
assert len(args) == self.n_args
outcome = parser.parse_expression(outcome_exp)
use_cases.append((args, outcome))
return use_cases
def _lisp_use_case(self, use_case):
args, outcome = use_case
res_arg = []
for arg in args:
res_arg.append(self._to_lisp_syntax(arg, quote=True))
# Arguments as tuples, outcome value as ints and tuples
return (tuple(res_arg), outcome)
def _to_lisp_syntax(self, a, quote=False):
if type(a).__name__ == 'int':
return a
elif type(a).__name__ == 'tuple':
res = tuple(self._to_lisp_syntax(e) for e in a)
if quote:
res = ('quote', res)
return res
else:
assert False
def _type_signature(self, values):
types = [type(v).__name__ for v in values]
d = {'int':'number', 'tuple':'list'}
assert types[0] in ('int', 'tuple')
if len(set(types)) == 1:
return d[types[0]]
else:
return 'S-expression'
def __str__(self):
if not self.ready:
self._prepare()
t = tree.Tree.from_code(frep.derived[self.name][2])
return str(t)
def __call__(self, *args):
if not self.ready:
self._prepare()
res_arg = []
for arg in args:
res_arg.append(self._to_lisp_syntax(arg, quote=True))
# TODO: arguments could also be symbols in the case of functions as
# first-class objects
q = (lis.Symbol(self.name),) + tuple(res_arg)
res = frep.interpreter.interpret(q)
return res