1from __future__ import division, print_function, unicode_literals
2
3from ..common.utility import isString
4
5from .expression import Variable
6
7class BuiltInFunction:
8    def __init__(self, header, cppType, name, namespace='std', targs=None, args=None):
9        self.header = header
10        self.cppType = cppType
11        self.name = name
12        self.namespace = namespace
13        self.tarts = None if targs is None else [a.strip() for a in targs]
14        self.args = [] if args is None else [a.strip() if isString(a) else a for a in args]
15
16        if len(self.args) > 0:
17            arg = self.args[len(self.args)-1]
18            self.variadic = (isinstance(arg, Variable) and arg.cppType.endswith('...'))
19        else:
20            self.variadic = False
21
22    def __call__(self, *args):
23        if (len(args) != len(self.args)) and not self.variadic:
24            raise Exception('Wrong number of Arguments: ' + str(len(args)) + ' (should be ' + str(len(self.args)) + ').')
25        from .expression import Application, makeExpression
26        return Application(self, args=[makeExpression(arg) for arg in args])
27
28    def __eq__(self, other):
29        if not isinstance(other, BuiltInFunction):
30            return False
31        if (other.namespace == self.namespace) and (other.name == self.name):
32            assert (other.header == self.header)
33            return True
34        else:
35            return False
36
37    def __hash__(self):
38        return hash(("BuildInFunction", self.namespace, self.cppType, self.name))
39
40    def __str__(self):
41        if self.namespace is None:
42            return self.name
43        else:
44            return self.namespace + '::' + self.name
45
46    def __repr__(self):
47        return "built-in(" + str(self) + ")"
48
49
50and_ = BuiltInFunction('algorithm', 'X', 'std::logical_and', targs=['class X'], args=['const X &x', 'const X &y'])
51max_ = BuiltInFunction('algorithm', 'X', 'max', targs=['class X'], args=['const X &x', 'const X &y'])
52min_ = BuiltInFunction('algorithm', 'X', 'min', targs=['class X'], args=['const X &x', 'const X &y'])
53
54abs_ = BuiltInFunction('cmath', 'X', 'abs', targs=['class X'], args=['const X &x'])
55atan = BuiltInFunction('cmath', 'X', 'atan', targs=['class X'], args=['const X &x'])
56atan2 = BuiltInFunction('cmath', 'X', 'atan2', targs=['class X'], args=['const X &x', 'const X &y'])
57exp = BuiltInFunction('cmath', 'X', 'exp', targs=['class X'], args=['const X &x'])
58cos = BuiltInFunction('cmath', 'X', 'cos', targs=['class X'], args=['const X &x'])
59cosh = BuiltInFunction('cmath', 'X', 'cosh', targs=['class X'], args=['const X &x'])
60log = BuiltInFunction('cmath', 'X', 'log', targs=['class X'], args=['const X &x'])
61pow_ = BuiltInFunction('cmath', 'X', 'pow', targs=['class X'], args=['const X &x', 'const X &y'])
62sin = BuiltInFunction('cmath', 'X', 'sin', targs=['class X'], args=['const X &x'])
63sinh = BuiltInFunction('cmath', 'X', 'sinh', targs=['class X'], args=['const X &x'])
64sqrt = BuiltInFunction('cmath', 'X', 'sqrt', targs=['class X'], args=['const X &x'])
65tan = BuiltInFunction('cmath', 'X', 'tan', targs=['class X'], args=['const X &x'])
66tanh = BuiltInFunction('cmath', 'X', 'tanh', targs=['class X'], args=['const X &x'])
67
68def get(i):
69    return BuiltInFunction('tuple', 'auto', 'get< ' + str(i) + ' >', targs=['class T'], args=['const T &arg'])
70
71make_pair = BuiltInFunction('utility', 'std::pair< U, V >', 'make_pair', targs=['class U', 'class V'], args=['const U &left', 'const V &right'])
72
73def make_index_sequence(n):
74    return BuiltInFunction('utility', 'auto', 'make_index_sequence< ' + str(n) + ' >')
75
76def make_shared(T):
77    return BuiltInFunction('memory', 'std::shared_ptr< T >', 'make_shared< ' + T + ' >', targs=['class... Args'], args=[Variable('Args &&...', 'args')])
78
79hybridForEach = BuiltInFunction('dune/common/hybridutilities.hh', 'void', 'forEach', namespace='Dune::Hybrid', targs=['class Range', 'class F'], args=['Range &&range', 'F &&f'])
80
81coordinate = BuiltInFunction('dune/fem/common/coordinate.hh', 'X', 'coordinate', namespace='Dune::Fem', targs=['class X'], args=['const X &x'])
82
83maxEdgeLength = BuiltInFunction('dune/fempy/geometry/edgelength.hh', 'typename Geometry::ctype', 'maxEdgeLength', namespace='Dune::FemPy', targs=['class Geometry'], args=['const Geometry &geometry'])
84minEdgeLength = BuiltInFunction('dune/fempy/geometry/edgelength.hh', 'typename Geometry::ctype', 'minEdgeLength', namespace='Dune::FemPy', targs=['class Geometry'], args=['const Geometry &geometry'])
85