forked from M-Labs/artiq
compiler/inferencer: Detect rectangular array()s
Still needs support through all the rest of the compiler, and support for higher-dimensional arrays. Alternatively, we could always assume ndarrays of ndarrays are rectangular (i.e. ban array/list element types), and detect mismatch at runtime. This might turn out to be preferrable to be able to construct matrices from rows/columns. `array()` is disallowed for no particularly good reason but numpy API compatibility.
This commit is contained in:
parent
6ea836183d
commit
56010c49fb
|
@ -7,6 +7,21 @@ from pythonparser import algorithm, diagnostic, ast
|
|||
from .. import asttyped, types, builtins
|
||||
from .typedtree_printer import TypedtreePrinter
|
||||
|
||||
|
||||
def is_rectangular_2d_list(node):
|
||||
if not isinstance(node, asttyped.ListT):
|
||||
return False
|
||||
num_elts = None
|
||||
for e in node.elts:
|
||||
if not isinstance(e, asttyped.ListT):
|
||||
return False
|
||||
if num_elts is None:
|
||||
num_elts = len(e.elts)
|
||||
elif num_elts != len(e.elts):
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
class Inferencer(algorithm.Visitor):
|
||||
"""
|
||||
:class:`Inferencer` infers types by recursively applying the unification
|
||||
|
@ -706,7 +721,6 @@ class Inferencer(algorithm.Visitor):
|
|||
node.loc, None)
|
||||
elif types.is_builtin(typ, "array"):
|
||||
valid_forms = lambda: [
|
||||
valid_form("array() -> array(elt='a)"),
|
||||
valid_form("array(x:'a) -> array(elt='b) where 'a is iterable")
|
||||
]
|
||||
|
||||
|
@ -715,8 +729,10 @@ class Inferencer(algorithm.Visitor):
|
|||
else:
|
||||
assert False
|
||||
|
||||
if len(node.args) == 0 and len(node.keywords) == 0:
|
||||
pass # []
|
||||
if (types.is_builtin(typ, "list") and len(node.args) == 0 and
|
||||
len(node.keywords) == 0):
|
||||
# Mimic numpy and don't allow array() (but []).
|
||||
pass
|
||||
elif len(node.args) == 1 and len(node.keywords) == 0:
|
||||
arg, = node.args
|
||||
|
||||
|
@ -732,8 +748,14 @@ class Inferencer(algorithm.Visitor):
|
|||
{"typeb": printer.name(typeb)},
|
||||
locb)
|
||||
]
|
||||
elt = arg.type.find().params["elt"]
|
||||
if types.is_builtin(typ, "array") and builtins.is_listish(elt):
|
||||
# KLUDGE: Support 2D arary creation if lexically specified
|
||||
# as a rectangular array of lists.
|
||||
if is_rectangular_2d_list(arg):
|
||||
elt = elt.find().params["elt"]
|
||||
self._unify(node.type.find().params["elt"],
|
||||
arg.type.find().params["elt"],
|
||||
elt,
|
||||
node.loc, arg.loc, makenotes=makenotes)
|
||||
elif types.is_var(arg.type):
|
||||
pass # undetermined yet
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
# RUN: %python -m artiq.compiler.testbench.inferencer %s >%t
|
||||
# RUN: OutputCheck %s --file-to-check=%t
|
||||
|
||||
# CHECK-L: numpy.array(elt='a)
|
||||
array([])
|
||||
|
||||
# CHECK-L: numpy.array(elt=numpy.int?)
|
||||
array([1, 2, 3])
|
||||
# CHECK-L: numpy.array(elt=numpy.int?)
|
||||
array([[1, 2, 3], [4, 5, 6]])
|
||||
|
||||
# CHECK-L: numpy.array(elt=list(elt=numpy.int?))
|
||||
array([[1, 2, 3], [4, 5]])
|
|
@ -0,0 +1,5 @@
|
|||
# RUN: %python -m artiq.compiler.testbench.inferencer +diag %s >%t
|
||||
# RUN: OutputCheck %s --file-to-check=%t
|
||||
|
||||
# CHECK-L: ${LINE:+1}: error: array cannot be invoked with the arguments ()
|
||||
a = array()
|
Loading…
Reference in New Issue