From 752031147dba22b6ede2c762becfde2091c11d55 Mon Sep 17 00:00:00 2001 From: whitequark Date: Wed, 24 Jun 2015 12:16:17 +0300 Subject: [PATCH] Add valid forms for builtin calls. --- artiq/py2llvm/prelude.py | 2 +- artiq/py2llvm/types.py | 3 ++ artiq/py2llvm/typing.py | 62 ++++++++++++++++++++++++ lit-test/py2llvm/typing/builtin_calls.py | 2 + 4 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 lit-test/py2llvm/typing/builtin_calls.py diff --git a/artiq/py2llvm/prelude.py b/artiq/py2llvm/prelude.py index 4e4d93fe7..4f603c05a 100644 --- a/artiq/py2llvm/prelude.py +++ b/artiq/py2llvm/prelude.py @@ -10,8 +10,8 @@ def globals(): "bool": builtins.TBool(), "int": builtins.TInt(), "float": builtins.TFloat(), - "round": builtins.fn_round(), "len": builtins.fn_len(), + "round": builtins.fn_round(), "range": builtins.fn_range(), "syscall": builtins.fn_syscall(), } diff --git a/artiq/py2llvm/types.py b/artiq/py2llvm/types.py index 029744ef8..60e09f2e3 100644 --- a/artiq/py2llvm/types.py +++ b/artiq/py2llvm/types.py @@ -262,6 +262,9 @@ def is_tuple(typ, elts=None): def is_function(typ): return isinstance(typ.find(), TFunction) +def is_builtin(typ): + return isinstance(typ.find(), TBuiltin) + def get_value(typ): typ = typ.find() if isinstance(typ, TVar): diff --git a/artiq/py2llvm/typing.py b/artiq/py2llvm/typing.py index 676dce879..bd7145e09 100644 --- a/artiq/py2llvm/typing.py +++ b/artiq/py2llvm/typing.py @@ -715,6 +715,66 @@ class Inferencer(algorithm.Visitor): self.generic_visit(node) self._unify_collection(element=node.target, collection=node.iter) + def visit_builtin_call(self, node): + if types.is_mono(node.func.type): + func_name = "function " + node.func.type.find().name + elif builtins.is_function(node.func.type): + func_name = node.func.type.find().name + + def valid_form(signature): + return diagnostic.Diagnostic("note", + "{func} can be invoked as: {signature}", + {"func": func_name}, + node.func.loc) + + def diagnose(valid_forms): + diag = diagnostic.Diagnostic("error", + "{func} cannot be invoked with these arguments", + {"func": func_name}, + node.func.loc, notes=valid_forms) + + if builtins.is_bool(node.type): + valid_forms = lambda: [ + valid_form("bool() -> bool"), + valid_form("bool(x:'a) -> bool where 'a is numeric") + ] + elif builtins.is_int(node.type): + valid_forms = lambda: [ + valid_form("int() -> int(width='a)"), + valid_form("int(x:'a) -> int(width='b) where 'a is numeric"), + valid_form("int(x:'a, width='b ) -> int(width='b) where 'a is numeric") + ] + elif builtins.is_float(node.type): + valid_forms = lambda: [ + valid_form("float() -> float"), + valid_form("float(x:'a) -> float where 'a is numeric") + ] + elif builtins.is_list(node.type): + valid_forms = lambda: [ + valid_form("list() -> list(elt='a)"), + # TODO: add this form when adding iterators + # valid_form("list(x) -> list(elt='a)") + ] + elif builtins.is_function(node.type, "len"): + valid_forms = lambda: [ + valid_form("len(x:list(elt='a)) -> int(width='b)"), + ] + elif builtins.is_function(node.type, "round"): + valid_forms = lambda: [ + valid_form("round(x:float) -> int(width='a)"), + ] + # TODO: add when there are range types + # elif builtins.is_function(node.type, "range"): + # valid_forms = lambda: [ + # valid_form("range(max:'a) -> range(elt='a)"), + # valid_form("range(min:'a, max:'a) -> range(elt='a)"), + # valid_form("range(min:'a, max:'a, step:'a) -> range(elt='a)"), + # ] + # TODO: add when it is clear what interface syscall() has + # elif builtins.is_function(node.type, "syscall"): + # valid_Forms = lambda: [ + # ] + def visit_CallT(self, node): self.generic_visit(node) @@ -729,6 +789,8 @@ class Inferencer(algorithm.Visitor): if types.is_var(node.func.type): return # not enough info yet + elif types.is_mono(node.func.type) or types.is_builtin(node.func.type): + return self.visit_builtin_call(self, node) elif not types.is_function(node.func.type): diag = diagnostic.Diagnostic("error", "cannot call this expression of type {type}", diff --git a/lit-test/py2llvm/typing/builtin_calls.py b/lit-test/py2llvm/typing/builtin_calls.py new file mode 100644 index 000000000..fb6ac38c0 --- /dev/null +++ b/lit-test/py2llvm/typing/builtin_calls.py @@ -0,0 +1,2 @@ +# RUN: %python -m artiq.py2llvm.typing %s >%t +# RUN: OutputCheck %s --file-to-check=%t