Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: m-labs/artiq
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 3485c834296d
Choose a base ref
...
head repository: m-labs/artiq
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 55ea68da7fd2
Choose a head ref
  • 3 commits
  • 10 files changed
  • 1 contributor

Commits on Nov 21, 2016

  1. inferencer: significantly improve the op-assignment diagnostic.

    Before this commit, it displayed incorrect output if an error
    appeared on 2nd run and beyond, and displayed messages for trying
    to do "num32 -= num64" that made very little sense.
    whitequark committed Nov 21, 2016
    Copy the full SHA
    35f4449 View commit details
  2. analyses.constness: fix false positive on x[...].

    whitequark committed Nov 21, 2016
    Copy the full SHA
    53b7d59 View commit details
  3. compiler: unbreak casts to int32/int64.

    whitequark committed Nov 21, 2016
    Copy the full SHA
    55ea68d View commit details
6 changes: 6 additions & 0 deletions artiq/compiler/analyses/constness.py
Original file line number Diff line number Diff line change
@@ -17,6 +17,12 @@ def visit_Assign(self, node):
self.visit(node.targets)
self.in_assign = False

def visit_SubscriptT(self, node):
old_in_assign, self.in_assign = self.in_assign, False
self.visit(node.value)
self.visit(node.slice)
self.in_assign = old_in_assign

def visit_AttributeT(self, node):
self.generic_visit(node)
if self.in_assign:
4 changes: 2 additions & 2 deletions artiq/compiler/builtins.py
Original file line number Diff line number Diff line change
@@ -126,10 +126,10 @@ def fn_int():
return types.TConstructor(TInt())

def fn_int32():
return types.TConstructor(TInt32())
return types.TBuiltinFunction("int32")

def fn_int64():
return types.TConstructor(TInt64())
return types.TBuiltinFunction("int64")

def fn_float():
return types.TConstructor(TFloat())
2 changes: 2 additions & 0 deletions artiq/compiler/prelude.py
Original file line number Diff line number Diff line change
@@ -14,6 +14,8 @@ def globals():
"list": builtins.fn_list(),
"array": builtins.fn_array(),
"range": builtins.fn_range(),
"int32": builtins.fn_int32(),
"int64": builtins.fn_int64(),

# Exception constructors
"Exception": builtins.fn_Exception(),
3 changes: 2 additions & 1 deletion artiq/compiler/transforms/artiq_ir_generator.py
Original file line number Diff line number Diff line change
@@ -1599,7 +1599,8 @@ def visit_builtin_call(self, node):
return self.coerce_to_bool(arg)
else:
assert False
elif types.is_builtin(typ, "int"):
elif types.is_builtin(typ, "int") or \
types.is_builtin(typ, "int32") or types.is_builtin(typ, "int64"):
if len(node.args) == 0 and len(node.keywords) == 0:
return ir.Constant(0, node.type)
elif len(node.args) == 1 and \
68 changes: 37 additions & 31 deletions artiq/compiler/transforms/inferencer.py
Original file line number Diff line number Diff line change
@@ -622,14 +622,28 @@ def simple_form(info, arg_types=[], return_type=builtins.TNone()):

self._unify(node.type, builtins.TBool(),
node.loc, None)
elif types.is_builtin(typ, "int"):
valid_forms = lambda: [
valid_form("int() -> numpy.int?"),
valid_form("int(x:'a) -> numpy.int?"),
valid_form("int(x:'a, width=?) -> numpy.int?")
]
elif types.is_builtin(typ, "int") or \
types.is_builtin(typ, "int32") or types.is_builtin(typ, "int64"):
if types.is_builtin(typ, "int"):
valid_forms = lambda: [
valid_form("int() -> numpy.int?"),
valid_form("int(x:'a) -> numpy.int? where 'a is numeric")
]
result_typ = builtins.TInt()
elif types.is_builtin(typ, "int32"):
valid_forms = lambda: [
valid_form("numpy.int32() -> numpy.int32"),
valid_form("numpy.int32(x:'a) -> numpy.int32 where 'a is numeric")
]
result_typ = builtins.TInt32()
elif types.is_builtin(typ, "int64"):
valid_forms = lambda: [
valid_form("numpy.int64() -> numpy.int64"),
valid_form("numpy.int64(x:'a) -> numpy.int64 where 'a is numeric")
]
result_typ = builtins.TInt64()

self._unify(node.type, builtins.TInt(),
self._unify(node.type, result_typ,
node.loc, None)

if len(node.args) == 0 and len(node.keywords) == 0:
@@ -639,20 +653,7 @@ def simple_form(info, arg_types=[], return_type=builtins.TNone()):
pass # undetermined yet
elif len(node.args) == 1 and len(node.keywords) == 0 and \
builtins.is_numeric(node.args[0].type):
self._unify(node.type, builtins.TInt(),
node.loc, None)
elif len(node.args) == 1 and len(node.keywords) == 1 and \
builtins.is_numeric(node.args[0].type) and \
node.keywords[0].arg == 'width':
width = node.keywords[0].value
if not (isinstance(width, asttyped.NumT) and isinstance(width.n, int)):
diag = diagnostic.Diagnostic("error",
"the width argument of int() must be an integer literal", {},
node.keywords[0].loc)
self.engine.process(diag)
return

self._unify(node.type, builtins.TInt(types.TValue(width.n)),
self._unify(node.type, result_typ,
node.loc, None)
else:
diagnose(valid_forms())
@@ -1043,36 +1044,41 @@ def visit_AugAssign(self, node):
if coerced:
return_type, target_type, value_type = coerced

if isinstance(node.value, asttyped.CoerceT):
orig_value_type = node.value.value.type
else:
orig_value_type = node.value.type

try:
node.target.type.unify(target_type)
node.target.type.unify(return_type)
except types.UnificationError as e:
printer = types.TypePrinter()
note = diagnostic.Diagnostic("note",
"expression of type {typec}",
{"typec": printer.name(node.value.type)},
{"typec": printer.name(orig_value_type)},
node.value.loc)
diag = diagnostic.Diagnostic("error",
"expression of type {typea} has to be coerced to {typeb}, "
"which makes assignment invalid",
"the result of this operation has type {typeb}, "
"which cannot be assigned to a left-hand side of type {typea}",
{"typea": printer.name(node.target.type),
"typeb": printer.name(target_type)},
"typeb": printer.name(return_type)},
node.op.loc, [node.target.loc], [note])
self.engine.process(diag)
return

try:
node.target.type.unify(return_type)
node.target.type.unify(target_type)
except types.UnificationError as e:
printer = types.TypePrinter()
note = diagnostic.Diagnostic("note",
"expression of type {typec}",
{"typec": printer.name(node.value.type)},
{"typec": printer.name(orig_value_type)},
node.value.loc)
diag = diagnostic.Diagnostic("error",
"the result of this operation has type {typeb}, "
"which makes assignment to a slot of type {typea} invalid",
"this operation requires the left-hand side of type {typea} "
"to be coerced to {typeb}, which cannot be done",
{"typea": printer.name(node.target.type),
"typeb": printer.name(return_type)},
"typeb": printer.name(target_type)},
node.op.loc, [node.target.loc], [note])
self.engine.process(diag)
return
4 changes: 2 additions & 2 deletions artiq/test/lit/inferencer/builtin_calls.py
Original file line number Diff line number Diff line change
@@ -13,8 +13,8 @@
# CHECK-L: int:<constructor int>(1.0:float):numpy.int?
int(1.0)

# CHECK-L: int:<constructor int>(1.0:float, width=64:numpy.int?):numpy.int64
int(1.0, width=64)
# CHECK-L: int64:<function int64>(1.0:float):numpy.int64
int64(1.0)

# CHECK-L: float:<constructor float {}>():float
float()
5 changes: 5 additions & 0 deletions artiq/test/lit/inferencer/cast.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# RUN: %python -m artiq.compiler.testbench.inferencer +mono %s >%t
# RUN: OutputCheck %s --file-to-check=%t

# CHECK-L: numpy.int64
int64(2)**32
4 changes: 0 additions & 4 deletions artiq/test/lit/inferencer/error_builtin_calls.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
# RUN: %python -m artiq.compiler.testbench.inferencer +diag %s >%t
# RUN: OutputCheck %s --file-to-check=%t

a = 1
# CHECK-L: ${LINE:+1}: error: the width argument of int() must be an integer literal
int(1.0, width=a)

# CHECK-L: ${LINE:+1}: error: the argument of len() must be of an iterable type
len(1)

4 changes: 2 additions & 2 deletions artiq/test/lit/inferencer/error_coerce.py
Original file line number Diff line number Diff line change
@@ -28,10 +28,10 @@
# CHECK-L: ${LINE:+1}: error: cannot coerce list(elt='a) to a numeric type
[] - 1.0

# CHECK-L: ${LINE:+2}: error: expression of type numpy.int? has to be coerced to float, which makes assignment invalid
# CHECK-L: ${LINE:+2}: error: the result of this operation has type float, which cannot be assigned to a left-hand side of type numpy.int?
# CHECK-L: ${LINE:+1}: note: expression of type float
a = 1; a += 1.0

# CHECK-L: ${LINE:+2}: error: the result of this operation has type (numpy.int?, float), which makes assignment to a slot of type (numpy.int?,) invalid
# CHECK-L: ${LINE:+2}: error: the result of this operation has type (numpy.int?, float), which cannot be assigned to a left-hand side of type (numpy.int?,)
# CHECK-L: ${LINE:+1}: note: expression of type (float,)
b = (1,); b += (1.0,)
2 changes: 1 addition & 1 deletion artiq/test/lit/integration/builtin.py
Original file line number Diff line number Diff line change
@@ -7,7 +7,7 @@

assert int() is 0
assert int(1.0) is 1
#ARTIQ#assert int(1, width=64) << 40 is 1099511627776
#ARTIQ#assert int64(1) << 40 is 1099511627776

#ARTIQ#assert float() is 0.0
#ARTIQ#assert float(1) is 1.0