def type_expr(expr): """Types an expression""" if not isinstance(expr, ast.Operation): return False def get_type(scheme): """Get the type of an operation argument.""" if isinstance(scheme, int): return expr.var_types[scheme] return scheme work_done = False schema = operations.OPERATIONS[expr.operation] if expr.var_types is None: expr.var_types = [None] * schema.ty_vars typ_scheme_res = get_type(schema.result) if expr.type is None: if typ_scheme_res is not None: expr.type = typ_scheme_res work_done = True else: if typ_scheme_res is None: expr.var_types[schema.result] = expr.type work_done = True else: if typ_scheme_res != expr.type: raise base.Z3TypeError( "Type error expresion {} has type {} not {}".format( expr, typ_scheme_res, expr.type)) for i in moves.range(len(expr.args)): arg = expr.args[i] if type_expr(arg): work_done = True typ_schema_arg = get_type(schema.args[i]) if arg.type is None: if typ_schema_arg is not None: arg.type = typ_schema_arg work_done = True else: if typ_schema_arg is None: expr.var_types[schema.args[i]] = arg.type work_done = True else: if typ_schema_arg != arg.type: raise base.Z3TypeError( "Type error: arg {} has type {} not {}".format( arg, typ_schema_arg, arg.type)) return work_done
def get_table_types(self, table, fields): """Return the types of the fields for a given table :param table: the table name :param fields: a list of field names :return: a list of the type names of the fiels """ if table in self.datasources: prim = self.datasources[table].fields else: raise base.Z3TypeError("Unknown extensible table {}".format(table)) try: args = [prim[field][0] for field in fields] except KeyError as exc: raise base.Z3TypeError("Unknown field {} in table {}".format( exc.args[0], table)) return args
def get_field(field): """Get a field compilation functions for cloud access""" try: type_name, access = accessor.fields[field] except KeyError: raise base.Z3TypeError('Unknown field {} in {}'.format( field, table_name)) type_field = self.types[type_name] return (type_field.to_z3, access, type_field.marshall)
def type_atom(atom): """Types an atom""" params = atom.types work_done = False for i in moves.range(len(params)): param_type = params[i] arg = atom.args[i] if param_type is None: if arg.type is not None: params[i] = arg.type work_done = True else: if arg.type is None: arg.type = param_type work_done = True else: if arg.type != param_type: raise base.Z3TypeError( "Type error {}:{} not {} in {}".format( arg, arg.type, param_type, atom)) if operations.is_primitive(atom): param0 = atom.types[0] param1 = atom.types[1] if param0 is None: if param1 is not None: atom.types[0] = atom.types[1] atom.args[0].type = atom.types[1] work_done = True else: if param1 is None: atom.types[1] = atom.types[0] atom.args[1].type = atom.types[0] work_done = True else: if param0 != param1: raise base.Z3TypeError( "Type error on equality {} not {} != {}".format( atom, param0, param1)) for arg in atom.args: if type_expr(arg): work_done = True return work_done
def build_relations(self): """Builds the compiled relations""" for name, arg_types in six.iteritems(self.compiler.typed_tables): try: param_types = [ self.datasource.types[typename].type() for typename in arg_types] except KeyError as exc: raise base.Z3TypeError( "Unknown type {} found for {}: {}".format( exc.args[0], name, arg_types )) param_types.append(z3.BoolSort()) relation = z3.Function(name, *param_types) self.context.register_relation(relation) self.relations[name] = relation
def prepare_atom(atom): """Makes atom typable Sustitute table name with a unique table description and make var instances unique in arguments. Comparison are a particular case, due to polymorphism. """ if operations.is_primitive(atom): atom.types = [None, None] elif atom.table in dict_tables: atom.types = dict_tables[atom.table] if len(atom.types) != len(atom.args): raise base.Z3TypeError( "Arity problem for symbol {} in {}".format( atom.table, atom)) else: params = [None for _ in atom.args] dict_tables[atom.table] = params atom.types = params atom.args = [subst_var(arg) for arg in atom.args]
def subst_var(arg): """Makes var instances unique""" if isinstance(arg, ast.Variable): if arg.full_id() in dict_vars: var_inst = dict_vars[arg.full_id()] if arg.type is not None: if var_inst.type is None: var_inst.type = arg.type else: if var_inst.type != arg.type: raise base.Z3TypeError( "Incompatible constraint on {}: {} != {}". format(arg.id, var_inst.type, arg.type)) return var_inst else: dict_vars[arg.full_id()] = arg return arg elif isinstance(arg, ast.Operation): arg.args = [subst_var(a) for a in arg.args] return arg else: return arg
def retrieve_table(self, table_name, fields, mk_relation): """Get the facts on the cloud or in the csv cache. :param table_name: the name of the table to retrieve :param fields: the list of field names of the table used :param mk_relation: a callback called on each row an taking a row value as a list of Z3 objects associated to each field and creating a fact in the Z3 context for the row. :param extract: an optional list of integer indexes defining the args to give back as a result (used by unfolding) :returns: None or a list of tuples for the columns requested in extract. """ use_cache = self.backup is not None if table_name in self.datasources: accessor = self.datasources[table_name] if use_cache: (index, objs) = self.backup.get(table_name, ([], [])) else: index = None objs = accessor.access(accessor.session) else: raise base.Z3TypeError( 'Unknown primitive relation {}'.format(table_name)) def get_field(field): """Get a field compilation functions for cloud access""" try: type_name, access = accessor.fields[field] except KeyError: raise base.Z3TypeError('Unknown field {} in {}'.format( field, table_name)) type_field = self.types[type_name] return (type_field.to_z3, access, type_field.marshall) def get_field_from_cache(field): """Get a field compilation functions for csv access""" type_name, _ = accessor.fields[field] type_field = self.types[type_name] try: pos = index.index(field) except ValueError: raise base.Z3NotWellFormed( "Field {} was not saved for table {}".format( field, table_name)) return (type_field.to_z3, lambda row: type_field.unmarshall(row[pos]), type_field.marshall) if use_cache: access_fields = [get_field_from_cache(field) for field in fields] else: access_fields = [get_field(field) for field in fields] if self.csv_writer is not None: self.csv_writer.writerow([table_name] + fields) for obj in objs: try: extracted = [(typ, acc(obj), marshall) for (typ, acc, marshall) in access_fields] if self.csv_writer is not None: self.csv_writer.writerow( [table_name] + [marshall(raw) for (_, raw, marshall) in extracted]) args = [typ(raw) for (typ, raw, _) in extracted] mk_relation(args) except Exception as exc: print("Error while retrieving table {} on {}".format( table_name, obj)) raise exc