2014-09-06 19:03:08 +08:00
|
|
|
import unittest
|
|
|
|
import ast
|
|
|
|
import inspect
|
2014-09-07 15:26:05 +08:00
|
|
|
from fractions import Fraction
|
2014-09-06 19:03:08 +08:00
|
|
|
|
|
|
|
from llvm import ee as le
|
|
|
|
|
2014-09-07 14:07:07 +08:00
|
|
|
from artiq.language.core import int64
|
2014-09-06 19:03:08 +08:00
|
|
|
from artiq.py2llvm.infer_types import infer_function_types
|
2014-09-07 14:09:03 +08:00
|
|
|
from artiq.py2llvm import base_types
|
|
|
|
from artiq.py2llvm.module import Module
|
2014-09-06 19:03:08 +08:00
|
|
|
|
|
|
|
|
|
|
|
def test_types(choice):
|
|
|
|
a = 2 # promoted later to int64
|
|
|
|
b = a + 1 # initially int32, becomes int64 after a is promoted
|
|
|
|
c = b//2 # initially int32, becomes int64 after b is promoted
|
|
|
|
d = 4 # stays int32
|
|
|
|
x = int64(7)
|
|
|
|
a += x # promotes a to int64
|
|
|
|
foo = True
|
|
|
|
bar = None
|
|
|
|
|
2014-09-07 14:07:07 +08:00
|
|
|
if choice and foo and not bar:
|
|
|
|
return d
|
2014-09-06 19:03:08 +08:00
|
|
|
else:
|
2014-09-07 14:07:07 +08:00
|
|
|
return x + c
|
2014-09-06 19:03:08 +08:00
|
|
|
|
|
|
|
class FunctionTypesCase(unittest.TestCase):
|
|
|
|
def setUp(self):
|
|
|
|
self.ns = infer_function_types(
|
|
|
|
None, ast.parse(inspect.getsource(test_types)),
|
|
|
|
dict())
|
|
|
|
|
|
|
|
def test_base_types(self):
|
2014-09-07 14:09:03 +08:00
|
|
|
self.assertIsInstance(self.ns["foo"], base_types.VBool)
|
|
|
|
self.assertIsInstance(self.ns["bar"], base_types.VNone)
|
|
|
|
self.assertIsInstance(self.ns["d"], base_types.VInt)
|
2014-09-06 19:03:08 +08:00
|
|
|
self.assertEqual(self.ns["d"].nbits, 32)
|
2014-09-07 14:09:03 +08:00
|
|
|
self.assertIsInstance(self.ns["x"], base_types.VInt)
|
2014-09-06 19:03:08 +08:00
|
|
|
self.assertEqual(self.ns["x"].nbits, 64)
|
|
|
|
|
|
|
|
def test_promotion(self):
|
|
|
|
for v in "abc":
|
2014-09-07 14:09:03 +08:00
|
|
|
self.assertIsInstance(self.ns[v], base_types.VInt)
|
2014-09-06 19:03:08 +08:00
|
|
|
self.assertEqual(self.ns[v].nbits, 64)
|
|
|
|
|
|
|
|
def test_return(self):
|
2014-09-07 14:09:03 +08:00
|
|
|
self.assertIsInstance(self.ns["return"], base_types.VInt)
|
2014-09-06 19:03:08 +08:00
|
|
|
self.assertEqual(self.ns["return"].nbits, 64)
|
|
|
|
|
|
|
|
|
|
|
|
class CompiledFunction:
|
|
|
|
def __init__(self, function, param_types):
|
2014-09-07 14:09:03 +08:00
|
|
|
module = Module()
|
2014-09-06 19:03:08 +08:00
|
|
|
funcdef = ast.parse(inspect.getsource(function)).body[0]
|
2014-09-07 14:09:03 +08:00
|
|
|
self.function, self.retval = module.compile_function(
|
|
|
|
funcdef, param_types)
|
2014-09-06 19:03:08 +08:00
|
|
|
self.argval = [param_types[arg.arg] for arg in funcdef.args.args]
|
2014-09-07 14:09:03 +08:00
|
|
|
self.ee = module.get_ee()
|
2014-09-06 19:03:08 +08:00
|
|
|
|
|
|
|
def __call__(self, *args):
|
|
|
|
args_llvm = [
|
|
|
|
le.GenericValue.int(av.get_llvm_type(), a)
|
|
|
|
for av, a in zip(self.argval, args)]
|
2014-09-07 14:09:03 +08:00
|
|
|
result = self.ee.run_function(self.function, args_llvm)
|
|
|
|
if isinstance(self.retval, base_types.VBool):
|
2014-09-06 19:03:08 +08:00
|
|
|
return bool(result.as_int())
|
2014-09-07 14:09:03 +08:00
|
|
|
elif isinstance(self.retval, base_types.VInt):
|
2014-09-06 19:03:08 +08:00
|
|
|
return result.as_int_signed()
|
|
|
|
else:
|
|
|
|
raise NotImplementedError
|
|
|
|
|
|
|
|
|
|
|
|
def is_prime(x):
|
|
|
|
d = 2
|
|
|
|
while d*d <= x:
|
|
|
|
if not x % d:
|
|
|
|
return False
|
|
|
|
d += 1
|
|
|
|
return True
|
|
|
|
|
2014-09-07 15:26:05 +08:00
|
|
|
def simplify_encode(n, d):
|
|
|
|
f = Fraction(n, d)
|
|
|
|
return f.numerator*1000 + f.denominator
|
|
|
|
|
2014-09-06 19:03:08 +08:00
|
|
|
class CodeGenCase(unittest.TestCase):
|
|
|
|
def test_is_prime(self):
|
2014-09-07 15:26:05 +08:00
|
|
|
is_prime_c = CompiledFunction(is_prime, {"x": base_types.VInt()})
|
2014-09-06 19:03:08 +08:00
|
|
|
for i in range(200):
|
|
|
|
self.assertEqual(is_prime_c(i), is_prime(i))
|
2014-09-07 15:26:05 +08:00
|
|
|
|
|
|
|
def test_frac_simplify(self):
|
|
|
|
simplify_encode_c = CompiledFunction(
|
|
|
|
simplify_encode, {"n": base_types.VInt(), "d": base_types.VInt()})
|
|
|
|
for n in range(5, 20):
|
|
|
|
for d in range(5, 20):
|
|
|
|
self.assertEqual(simplify_encode_c(n, d), simplify_encode(n, d))
|