def substitute_and_reinfer(self): """ Try substituting resolved parts of promotions and reinfer the types. """ from numba import symtab if not self.variable.type.is_unresolved: return False # Find substitutions and save original variables old_vars = [] for node in self.dependences: sub_type = self.substitution_candidate(node.variable) if sub_type: old_vars.append((node, node.variable)) node.variable = symtab.Variable(sub_type, name='<substitute>') if old_vars: # We have some substitutions, retry type inference result = self._reinfer() # Reset our original variables! for node, old_var in old_vars: node.variable = old_var return result # We cannot substitute any promotion candidates, see if we can resolve # anyhow (this should be a cheap operation anyway if it fails) new_type = self.retry_infer() if not new_type.is_unresolved: self.variable.type = new_type return True return False
def inherit_attributes(ext_type, class_dict): cls = ext_type.py_class if not is_numba_class(cls): # superclass is not a numba class return struct_type = cls.__numba_struct_type vtab_type = cls.__numba_vtab_type verify_base_class_compatibility(cls, struct_type, vtab_type) # Inherit attributes ext_type.attribute_struct = numba.struct(struct_type.fields) for field_name, field_type in ext_type.attribute_struct.fields: ext_type.symtab[field_name] = symtab.Variable(field_type, promotable_type=False) # Inherit methods for method_name, method_type in vtab_type.fields: func_signature = method_type.base_type args = list(func_signature.args) if not (func_signature.is_class or func_signature.is_static): args[0] = ext_type func_signature = func_signature.return_type(*args) ext_type.add_method(method_name, func_signature) ext_type.parent_attr_struct = struct_type ext_type.parent_vtab_type = vtab_type
def build_extension_symtab(ext_type): """ Create symbol table for all attributes of the extension type. These are Variables which are used by the type inferencer and used to type check attribute assignments. New attribute assignments create new ExtensionAttributeVariable variables in the symtab. These variables update the attribute table during type inference: class Foo(object): value1 = double def __init__(self, value2): self.value2 = int_(value2) Before type inference of __init__ we have: symtab = { 'value1': Variable(double) } and after type inference of __init__ we have: symtab = { 'value1': Variable(double), # type is fixed 'value2': ExtensionAttributeVariable(int_), # type is inferred } """ table = ext_type.attribute_table for attr_name, attr_type in table.attributedict.iteritems(): ext_type.symtab[attr_name] = symtab.Variable(attr_type, promotable_type=False)
def promote(typesystem, type1, type2, assignment=False): promote_ = partial(promote, typesystem) if type1.is_unresolved or type2.is_unresolved: if type1.is_unresolved: type1 = type1.resolve() if type2.is_unresolved: type2 = type2.resolve() if type1.is_unresolved or type2.is_unresolved: # The Variable is really only important for ast.Name, fabricate # one from numba import symtab var = symtab.Variable(None) return PromotionType(var, promote_, [type1, type2]) else: return typesystem.promote(type1, type2) return typesystem.promote(type1, type2)
def promote_types(self, type1, type2, assignment=False): have = lambda p1, p2: have_properties(type1, type2, p1, p2) if (type1.is_array or type2.is_array) and not \ (type1.is_array and type2.is_array): if type1.is_array: array_type = type1 other_type = type2 else: array_type = type2 other_type = type1 type = copy.copy(array_type) type.dtype = self.promote_types(array_type.dtype, other_type) if type.dtype.is_object and not array_type.dtype.is_object: # Make sure that (double[:], object_) -> object_ type = object_ return type elif type1.is_unresolved or type2.is_unresolved: if type1.is_unresolved: type1 = type1.resolve() if type2.is_unresolved: type2 = type2.resolve() if type1.is_unresolved or type2.is_unresolved: # The Variable is really only important for ast.Name, fabricate # one from numba import symtab var = symtab.Variable(None) return PromotionType(var, self.context, [type1, type2]) else: return self.promote_types(type1, type2) elif have("is_pointer", "is_null"): return [type1, type2][type1.is_null] # return the pointer type elif have("is_pointer", "is_int"): return [type1, type2][type1.is_int] # return the pointer type return super(NumbaTypeMapper, self).promote_types(type1, type2)
def initialize_symtab(self, allow_rebind_args): """ Populate the symbol table with variables and set their renaming status. Variables appearing in locals, or arguments typed through the 'jit' decorator are not renameable. """ symbols = symtab.Symtab(self.symtab) for var_name in self.local_names: variable = symtab.Variable(None, name=var_name, is_local=True) # Set cellvar status. Free variables are not assignments, and # are caught in the type inferencer variable.is_cellvar = var_name in self.cellvars # variable.is_freevar = var_name in self.freevars variable.renameable = ( var_name not in self.locals and not (variable.is_cellvar or variable.is_freevar) and (var_name not in self.argnames or allow_rebind_args)) symbols[var_name] = variable return symbols