def get_order(module: ast.Module, type_info: type_info_mod.TypeInfo, imports: Dict[ast.Import, ImportedInfo], traverse_tests: bool = False) -> List[ConversionRecord]: """Returns (topological) order for functions to be converted to IR. Args: module: Module to convert the (non-parametric) functions for. type_info: Mapping from node to type. imports: Transitive imports that are required by "module". traverse_tests: Whether to traverse DSLX test constructs. This flag should be set if we intend to run functions only called from test constructs through the JIT. """ ready = [] # type: List[ConversionRecord] # Functions in the module should become ready in dependency order (they # referred to each other's names). for quickcheck in module.get_quickchecks(): function = quickcheck.f assert not function.is_parametric(), function _add_to_ready(ready, imports, function, module, type_info, bindings=SymbolicBindings()) for function in module.get_functions(): if function.is_parametric(): continue _add_to_ready(ready, imports, function, module, type_info, bindings=SymbolicBindings()) if traverse_tests: for test in module.get_tests(): _add_to_ready(ready, imports, test, module, type_info, bindings=SymbolicBindings()) return ready
def test_transitive_parametric(self): program = """ fn g<M: u32>(x: bits[M]) -> u32 { M } fn f<N: u32>(x: bits[N]) -> u32 { g(x) } fn main() -> u32 { f(u2:0) } """ m, type_info = self._get_module(program) order = extract_conversion_order.get_order(m, type_info, imports={}) self.assertLen(order, 3) self.assertEqual(order[0].f.identifier, 'g') self.assertEqual(order[0].bindings, SymbolicBindings([('M', 2)])) self.assertEqual(order[1].f.identifier, 'f') self.assertEqual(order[1].bindings, SymbolicBindings([('N', 2)])) self.assertEqual(order[2].f.identifier, 'main') self.assertEqual(order[2].bindings, SymbolicBindings())
def test_get_callees(self): program = """ fn f() -> u32 { u32:42 } fn main() -> u32 { f() } """ m, type_info = self._get_module(program) callee = extract_conversion_order.Callee(m.get_function('f'), m, type_info, SymbolicBindings()) self.assertEqual( (callee, ), extract_conversion_order.get_callees(m.get_function('main'), m, type_info, imports={}, bindings=SymbolicBindings()))
def test_parametric(self): program = """ fn f<N: u32>(x: bits[N]) -> u32 { N } fn main() -> u32 { f(u2:0) } """ m, type_info = self._get_module(program) order = extract_conversion_order.get_order(m, type_info, imports={}) self.assertLen(order, 2) self.assertEqual(order[0].f.identifier, 'f') self.assertEqual(order[0].bindings, SymbolicBindings([('N', 2)])) self.assertEqual(order[0].callees, ()) self.assertEqual(order[1].f.identifier, 'main') self.assertEqual(order[1].bindings, SymbolicBindings()) f = m.get_function('f') self.assertEqual( tuple((c.f, c.m, c.sym_bindings) for c in order[1].callees), ((f, m, SymbolicBindings([('N', 2)])), ))
def test_builtin_is_elided(self): program = """ fn main() -> u32 { fail!(u32:0) } """ m, type_info = self._get_module(program) order = extract_conversion_order.get_order(m, type_info, imports={}) self.assertLen(order, 1) self.assertEqual(order[0].f.identifier, 'main') self.assertEqual(order[0].bindings, SymbolicBindings())
def wrapper( arg_types: ArgTypes, name: Text, span: Span, ctx: DeduceCtx, parametric_bindings: Optional[ParametricBindings] ) -> Tuple[ConcreteType, SymbolicBindings]: result = f(arg_types, name, span, ctx, parametric_bindings) if isinstance(result, tuple): return result assert isinstance(result, ConcreteType), result return result, SymbolicBindings()