Skip to content

Commit

Permalink
Allow type annotations on remotely called functions.
Browse files Browse the repository at this point in the history
  • Loading branch information
whitequark committed Aug 10, 2015
1 parent b28a874 commit 435559f
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 8 deletions.
42 changes: 35 additions & 7 deletions artiq/compiler/embedding.py
Expand Up @@ -232,22 +232,44 @@ def _quote_embedded_function(self, function):
quote_function=self._quote_function)
return asttyped_rewriter.visit(function_node)

def _function_def_note(self, function):
def _function_loc(self, function):
filename = function.__code__.co_filename
line = function.__code__.co_firstlineno
name = function.__code__.co_name

source_line = linecache.getline(filename, line)
column = re.search("def", source_line).start(0)
source_buffer = source.Buffer(source_line, filename, line)
loc = source.Range(source_buffer, column, column)
return source.Range(source_buffer, column, column)

def _function_def_note(self, function):
return diagnostic.Diagnostic("note",
"definition of function '{function}'",
{"function": name},
loc)
{"function": function.__name__},
self._function_loc(function))

def _extract_annot(self, function, annot, kind, call_loc):
if not isinstance(annot, types.Type):
note = diagnostic.Diagnostic("note",
"in function called remotely here", {},
call_loc)
diag = diagnostic.Diagnostic("error",
"type annotation for {kind}, '{annot}', is not an ARTIQ type",
{"kind": kind, "annot": repr(annot)},
self._function_loc(function),
notes=[note])
self.engine.process(diag)

return types.TVar()
else:
return annot

def _type_of_param(self, function, loc, param):
if param.default is not inspect.Parameter.empty:
if param.annotation is not inspect.Parameter.empty:
# Type specified explicitly.
return self._extract_annot(function, param.annotation,
"argument {}".format(param.name), loc)
elif param.default is not inspect.Parameter.empty:
# Try and infer the type from the default value.
# This is tricky, because the default value might not have
# a well-defined type in APython.
Expand Down Expand Up @@ -300,8 +322,14 @@ def _quote_rpc_function(self, function, loc):
else:
optarg_types[param.name] = self._type_of_param(function, loc, param)

# Fixed for now.
ret_type = builtins.TInt(types.TValue(32))
if signature.return_annotation is not inspect.Signature.empty:
ret_type = self._extract_annot(function, signature.return_annotation,
"return type", loc)
else:
diag = diagnostic.Diagnostic("fatal",
"function must have a return type specified to be called remotely", {},
self._function_loc(function))
self.engine.process(diag)

rpc_type = types.TRPCFunction(arg_types, optarg_types, ret_type,
service=self._map(function))
Expand Down
4 changes: 3 additions & 1 deletion artiq/language/__init__.py
@@ -1,12 +1,14 @@
from artiq.language import core, environment, units, scan
from artiq.language import core, types, environment, units, scan
from artiq.language.core import *
from artiq.language.types import *
from artiq.language.environment import *
from artiq.language.units import *
from artiq.language.scan import *


__all__ = []
__all__.extend(core.__all__)
__all__.extend(types.__all__)
__all__.extend(environment.__all__)
__all__.extend(units.__all__)
__all__.extend(scan.__all__)
19 changes: 19 additions & 0 deletions artiq/language/types.py
@@ -0,0 +1,19 @@
"""
Values representing ARTIQ types, to be used in function type
annotations.
"""

from artiq.compiler import types, builtins

__all__ = ["TNone", "TBool", "TInt32", "TInt64", "TFloat",
"TStr", "TList", "TRange32", "TRange64"]

TNone = builtins.TNone()
TBool = builtins.TBool()
TInt32 = builtins.TInt(types.TValue(32))
TInt64 = builtins.TInt(types.TValue(64))
TFloat = builtins.TFloat()
TStr = builtins.TStr()
TList = builtins.TList
TRange32 = builtins.TRange(builtins.TInt(types.TValue(32)))
TRange64 = builtins.TRange(builtins.TInt(types.TValue(64)))

0 comments on commit 435559f

Please sign in to comment.