Add valid forms for builtin calls.

This commit is contained in:
whitequark 2015-06-24 12:16:17 +03:00
parent 4d407ace4b
commit 752031147d
4 changed files with 68 additions and 1 deletions

View File

@ -10,8 +10,8 @@ def globals():
"bool": builtins.TBool(), "bool": builtins.TBool(),
"int": builtins.TInt(), "int": builtins.TInt(),
"float": builtins.TFloat(), "float": builtins.TFloat(),
"round": builtins.fn_round(),
"len": builtins.fn_len(), "len": builtins.fn_len(),
"round": builtins.fn_round(),
"range": builtins.fn_range(), "range": builtins.fn_range(),
"syscall": builtins.fn_syscall(), "syscall": builtins.fn_syscall(),
} }

View File

@ -262,6 +262,9 @@ def is_tuple(typ, elts=None):
def is_function(typ): def is_function(typ):
return isinstance(typ.find(), TFunction) return isinstance(typ.find(), TFunction)
def is_builtin(typ):
return isinstance(typ.find(), TBuiltin)
def get_value(typ): def get_value(typ):
typ = typ.find() typ = typ.find()
if isinstance(typ, TVar): if isinstance(typ, TVar):

View File

@ -715,6 +715,66 @@ class Inferencer(algorithm.Visitor):
self.generic_visit(node) self.generic_visit(node)
self._unify_collection(element=node.target, collection=node.iter) 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 literal>) -> 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): def visit_CallT(self, node):
self.generic_visit(node) self.generic_visit(node)
@ -729,6 +789,8 @@ class Inferencer(algorithm.Visitor):
if types.is_var(node.func.type): if types.is_var(node.func.type):
return # not enough info yet 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): elif not types.is_function(node.func.type):
diag = diagnostic.Diagnostic("error", diag = diagnostic.Diagnostic("error",
"cannot call this expression of type {type}", "cannot call this expression of type {type}",

View File

@ -0,0 +1,2 @@
# RUN: %python -m artiq.py2llvm.typing %s >%t
# RUN: OutputCheck %s --file-to-check=%t