Ejemplo n.º 1
0
    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
Ejemplo n.º 2
0
    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
Ejemplo n.º 3
0
 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)
Ejemplo n.º 4
0
 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
Ejemplo n.º 5
0
 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
Ejemplo n.º 6
0
        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]
Ejemplo n.º 7
0
 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
Ejemplo n.º 8
0
    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