1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 """Encapsulates functions used in osh commands such as C{f} and C{select}.
19
20 osh function syntax::
21
22 [[lambda] ARGS:] EXPRESSION
23
24 C{ARGS}: Comma-separated list of function arguments, optionally preceded by keyword
25 C{lambda}. C{ARGS} may be omitted only for a function with no arguments.
26
27 C{EXPRESSION}: A Python expression written in terms of the function arguments.
28
29 Example::
30
31 x: max(x, 10)
32 """
33
34 import copy
35 import sys
36 import types
37
38 import core
39
40 _LAMBDA = 'lambda '
41 _LAMBDA_COLON = 'lambda:'
42
43
45 """Represents a function for use by osh commands with function arguments,
46 e.g., select.
47 """
48
49 _function_spec = None
50 _function = None
51 _function_id = None
52
53 - def __init__(self, function_spec, namespace = core.__dict__):
54 """Creates a Function.
55 - function_spec: String specification of a function. Uses lambda notation,
56 but the 'lambda' keyword is optional.
57 - namespace: The default is reasonable; there's been no need to
58 override it so far.
59 """
60 if type(function_spec) in (types.FunctionType, types.BuiltinFunctionType):
61 self._function = function_spec
62 else:
63 self._function_spec = function_spec
64 lambda_expression = self.parse(function_spec.strip())
65
66 namespace = copy.copy(namespace)
67 namespace.update(core.namespace())
68 self._function = eval(lambda_expression, namespace)
69
71 return 'function(%s)' % self._function_spec
72
74 return self._function(*args)
75
76 - def parse(self, function_spec):
77
78
79
80
81
82
83
84 if function_spec.startswith(_LAMBDA) or function_spec.startswith(_LAMBDA_COLON):
85
86 pass
87 else:
88 fixed_function_spec = '%s: %s' % (_LAMBDA, function_spec)
89 try:
90 eval(fixed_function_spec)
91 function_spec = fixed_function_spec
92 except:
93 fixed_function_spec = '%s %s' % (_LAMBDA, function_spec)
94 try:
95 eval(fixed_function_spec)
96 function_spec = fixed_function_spec
97 except:
98 raise NotAFunctionException('Illegal function spec: %s' % function_spec)
99 return function_spec
100
105
107 if op == '+':
108 f = lambda x, y: x + y
109 elif op == '*':
110 f = lambda x, y: x * y
111 elif op == '^':
112 f = lambda x, y: x ^ y
113 elif op == '&':
114 f = lambda x, y: x & y
115 elif op == '|':
116 f = lambda x, y: x | y
117 elif op == 'and':
118 f = lambda x, y: x and y
119 elif op == 'or':
120 f = lambda x, y: x or y
121 elif op == 'max':
122 f = lambda x, y: max(x, y)
123 elif op == 'min':
124 f = lambda x, y: min(x, y)
125 else:
126 f = None
127 return f
128
130 f = None
131 if type(x) in [types.FunctionType, types.BuiltinFunctionType]:
132 f = _Function(x)
133 elif isinstance(x, str):
134 op = _operator_to_function(x)
135 if op:
136 f = _Function(op)
137 else:
138 f = _Function(x)
139 return f
140