Skip to content

Commit 8c5e58f

Browse files
author
whitequark
committedJun 15, 2015
Implement Call.
1 parent 7a00a4a commit 8c5e58f

File tree

4 files changed

+121
-2
lines changed

4 files changed

+121
-2
lines changed
 

Diff for: ‎artiq/py2llvm/types.py

+6
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,9 @@ class TFunction(Type):
152152
def __init__(self, args, optargs, ret):
153153
self.args, self.optargs, self.ret = args, optargs, ret
154154

155+
def arity(self):
156+
return len(self.args) + len(self.optargs)
157+
155158
def find(self):
156159
return self
157160

@@ -229,6 +232,9 @@ def is_tuple(typ, elts=None):
229232
else:
230233
return isinstance(typ, TTuple)
231234

235+
def is_function(typ):
236+
return isinstance(typ.find(), TFunction)
237+
232238
def get_value(typ):
233239
typ = typ.find()
234240
if isinstance(typ, TVar):

Diff for: ‎artiq/py2llvm/typing.py

+83-2
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,15 @@ def visit_ListComp(self, node):
303303
finally:
304304
self.env_stack.pop()
305305

306+
def visit_Call(self, node):
307+
node = self.generic_visit(node)
308+
node = asttyped.CallT(type=types.TVar(),
309+
func=node.func, args=node.args, keywords=node.keywords,
310+
starargs=node.starargs, kwargs=node.kwargs,
311+
star_loc=node.star_loc, dstar_loc=node.dstar_loc,
312+
begin_loc=node.begin_loc, end_loc=node.end_loc, loc=node.loc)
313+
return node
314+
306315
def visit_Lambda(self, node):
307316
extractor = LocalExtractor(env_stack=self.env_stack, engine=self.engine)
308317
extractor.visit(node)
@@ -337,7 +346,6 @@ def visit_unsupported(self, node):
337346
self.engine.process(diag)
338347

339348
# expr
340-
visit_Call = visit_unsupported
341349
visit_Dict = visit_unsupported
342350
visit_DictComp = visit_unsupported
343351
visit_Ellipsis = visit_unsupported
@@ -707,6 +715,79 @@ def visit_comprehension(self, node):
707715
self.generic_visit(node)
708716
self._unify_collection(element=node.target, collection=node.iter)
709717

718+
def visit_CallT(self, node):
719+
self.generic_visit(node)
720+
721+
for (sigil_loc, vararg) in ((node.star_loc, node.starargs),
722+
(node.dstar_loc, node.kwargs)):
723+
if vararg:
724+
diag = diagnostic.Diagnostic("error",
725+
"variadic arguments are not supported", {},
726+
sigil_loc, [vararg.loc])
727+
self.engine.process(diag)
728+
return
729+
730+
if types.is_var(node.func.type):
731+
return # not enough info yet
732+
elif not types.is_function(node.func.type):
733+
diag = diagnostic.Diagnostic("error",
734+
"cannot call this expression of type {type}",
735+
{"type": types.TypePrinter().name(node.func.type)},
736+
node.func.loc, [])
737+
self.engine.process(diag)
738+
return
739+
740+
typ = node.func.type.find()
741+
passed_args = set()
742+
743+
if len(node.args) > typ.arity():
744+
note = diagnostic.Diagnostic("note",
745+
"extraneous argument(s)", {},
746+
node.args[typ.arity()].loc.join(node.args[-1].loc))
747+
diag = diagnostic.Diagnostic("error",
748+
"this function of type {type} accepts at most {num} arguments",
749+
{"type": types.TypePrinter().name(node.func.type),
750+
"num": typ.arity()},
751+
node.func.loc, [], [note])
752+
self.engine.process(diag)
753+
return
754+
755+
for actualarg, (formalname, formaltyp) in \
756+
zip(node.args, list(typ.args.items()) + list(typ.optargs.items())):
757+
self._unify(actualarg.type, formaltyp,
758+
actualarg.loc, None)
759+
passed_args.add(formalname)
760+
761+
for keyword in node.keywords:
762+
if keyword.arg in passed_args:
763+
diag = diagnostic.Diagnostic("error",
764+
"the argument '{name}' is already passed",
765+
{"name": keyword.arg},
766+
keyword.arg_loc)
767+
self.engine.process(diag)
768+
return
769+
770+
if keyword.arg in typ.args:
771+
self._unify(keyword.value.type, typ.args[keyword.arg],
772+
keyword.value.loc, None)
773+
elif keyword.arg in typ.optargs:
774+
self._unify(keyword.value.type, typ.optargs[keyword.arg],
775+
keyword.value.loc, None)
776+
passed_args.add(keyword.arg)
777+
778+
for formalname in typ.args:
779+
if formalname not in passed_args:
780+
note = diagnostic.Diagnostic("note",
781+
"the called function is of type {type}",
782+
{"type": types.TypePrinter().name(node.func.type)},
783+
node.func.loc)
784+
diag = diagnostic.Diagnostic("error",
785+
"mandatory argument '{name}' is not passed",
786+
{"name": formalname},
787+
node.begin_loc.join(node.end_loc), [], [note])
788+
self.engine.process(diag)
789+
return
790+
710791
def visit_LambdaT(self, node):
711792
self.generic_visit(node)
712793
signature_type = self._type_from_arguments(node.args, node.body.type)
@@ -818,7 +899,7 @@ def extract_args(arg_nodes):
818899
return OrderedDict(args)
819900

820901
return types.TFunction(extract_args(node.args[:len(node.args) - len(node.defaults)]),
821-
extract_args(node.args[len(node.defaults):]),
902+
extract_args(node.args[len(node.args) - len(node.defaults):]),
822903
ret)
823904

824905
def visit_arguments(self, node):

Diff for: ‎lit-test/py2llvm/typing/error_call.py

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# RUN: %python -m artiq.py2llvm.typing +diag %s >%t
2+
# RUN: OutputCheck %s --file-to-check=%t
3+
4+
# CHECK-L: ${LINE:+1}: error: cannot call this expression of type int
5+
(1)()
6+
7+
def f(x, y, z=1):
8+
pass
9+
10+
# CHECK-L: ${LINE:+1}: error: variadic arguments are not supported
11+
f(*[])
12+
13+
# CHECK-L: ${LINE:+1}: error: variadic arguments are not supported
14+
f(**[])
15+
16+
# CHECK-L: ${LINE:+1}: error: the argument 'x' is already passed
17+
f(1, x=1)
18+
19+
# CHECK-L: ${LINE:+1}: error: mandatory argument 'x' is not passed
20+
f()

Diff for: ‎lit-test/py2llvm/typing/gcd.py

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# RUN: %python -m artiq.py2llvm.typing %s >%t
2+
3+
def _gcd(a, b):
4+
if a < 0:
5+
a = -a
6+
while a:
7+
c = a
8+
a = b % a
9+
b = c
10+
return b
11+
12+
_gcd(10, 25)

0 commit comments

Comments
 (0)
Please sign in to comment.