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: 30ef6119e630
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: 4b0788d92c5b
Choose a head ref
  • 2 commits
  • 3 files changed
  • 1 contributor

Commits on Aug 17, 2014

  1. Copy the full SHA
    9e21ea5 View commit details
  2. Copy the full SHA
    4b0788d View commit details
Showing with 60 additions and 30 deletions.
  1. +21 −6 artiq/compiler/ir_ast_body.py
  2. +17 −24 artiq/compiler/ir_infer_types.py
  3. +22 −0 artiq/compiler/ir_values.py
27 changes: 21 additions & 6 deletions artiq/compiler/ir_ast_body.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import ast
from copy import copy

from llvm import core as lc

from artiq.compiler import ir_values

class Visitor:
def __init__(self, builder, ns):
self.builder = builder
def __init__(self, ns, builder=None):
self.ns = ns
self.builder = builder

# builder can be None for visit_expression
def visit_expression(self, node):
@@ -17,11 +20,23 @@ def visit_expression(self, node):
return visitor(node)

def _visit_expr_Name(self, node):
return self.ns.load(self.builder, node.id)
try:
r = self.ns[node.id]
except KeyError:
raise NameError("Name '{}' is not defined".format(node.id))
r = copy(r)
if self.builder is None:
r.llvm_value = None
else:
if isinstance(r.llvm_value, lc.AllocaInstruction):
r.llvm_value = self.builder.load(r.llvm_value)
return r

def _visit_expr_NameConstant(self, node):
v = node.value
if isinstance(v, bool):
if v is None:
r = ir_values.VNone()
elif isinstance(v, bool):
r = ir_values.VBool()
else:
raise NotImplementedError
@@ -112,14 +127,14 @@ def _visit_stmt_Assign(self, node):
val = self.visit_expression(node.value)
for target in node.targets:
if isinstance(target, ast.Name):
self.ns.store(self.builder, val, target.id)
self.builder.store(val, self.ns[target.id])
else:
raise NotImplementedError

def _visit_stmt_AugAssign(self, node):
val = self.visit_expression(ast.BinOp(op=node.op, left=node.target, right=node.value))
if isinstance(node.target, ast.Name):
self.ns.store(self.builder, val, node.target.id)
self.builder.store(val, self.ns[node.target.id])
else:
raise NotImplementedError

41 changes: 17 additions & 24 deletions artiq/compiler/ir_infer_types.py
Original file line number Diff line number Diff line change
@@ -4,51 +4,43 @@

from artiq.compiler.ir_ast_body import Visitor

class _Namespace:
def __init__(self, name_to_value):
self.name_to_value = name_to_value

def load(self, builder, name):
return self.name_to_value[name]

class _TypeScanner(ast.NodeVisitor):
def __init__(self, namespace):
self.exprv = Visitor(None, namespace)
def __init__(self, ns):
self.exprv = Visitor(ns)

def visit_Assign(self, node):
val = self.exprv.visit_expression(node.value)
n2v = self.exprv.ns.name_to_value
ns = self.exprv.ns
for target in node.targets:
if isinstance(target, ast.Name):
if target.id in n2v:
n2v[target.id].merge(val)
if target.id in ns:
ns[target.id].merge(val)
else:
n2v[target.id] = val
ns[target.id] = val
else:
raise NotImplementedError

def visit_AugAssign(self, node):
val = self.exprv.visit_expression(ast.BinOp(op=node.op, left=node.target, right=node.value))
n2v = self.exprv.ns.name_to_value
ns = self.exprv.ns
target = node.target
if isinstance(target, ast.Name):
if target.id in n2v:
n2v[target.id].merge(val)
if target.id in ns:
ns[target.id].merge(val)
else:
n2v[target.id] = val
ns[target.id] = val
else:
raise NotImplementedError

def infer_types(node):
name_to_value = dict()
ns = dict()
while True:
prev_name_to_value = deepcopy(name_to_value)
ns = _Namespace(name_to_value)
prev_ns = deepcopy(ns)
ts = _TypeScanner(ns)
ts.visit(node)
if prev_name_to_value and all(v.same_type(prev_name_to_value[k]) for k, v in name_to_value.items()):
if prev_ns and all(v.same_type(prev_ns[k]) for k, v in ns.items()):
# no more promotions - completed
return name_to_value
return ns

if __name__ == "__main__":
testcode = """
@@ -59,7 +51,8 @@ def infer_types(node):
x = int64(7)
a += x # promotes a to int64
foo = True
bar = None
"""
n2v = infer_types(ast.parse(testcode))
for k, v in sorted(n2v.items(), key=itemgetter(0)):
ns = infer_types(ast.parse(testcode))
for k, v in sorted(ns.items(), key=itemgetter(0)):
print("{:10}--> {}".format(k, str(v)))
22 changes: 22 additions & 0 deletions artiq/compiler/ir_values.py
Original file line number Diff line number Diff line change
@@ -2,6 +2,28 @@

from llvm import core as lc

# None type

class VNone:
def __repr__(self):
return "<VNone>"

def same_type(self, other):
return isinstance(other, VNone)

def merge(self, other):
if not isinstance(other, VNone):
raise TypeError

def create_alloca(self, builder, name):
pass

def o_bool(self, builder):
r = VBool()
if builder is not None:
r.create_constant(False)
return r

# Integer type

class VInt: