Esempio n. 1
0
 def provider():
     all_providers = (
         tuple(def_provider_builders) + self.external_def_providers
     )
     return Transformer.first_of(
         *(p(provider) for p in all_providers)
     )
Esempio n. 2
0
        def provide_subprogram_access(inner_provider):
            # This provider is composed of several providers in the following
            # manner:
            # 1. A first transformer (get_subprogram_access_signature)
            #    constructs dynamically the Signature object of the subprogram
            #    being accessed and returns the pair (access_sig, subp_sig)
            #    where access_sig is the signature of the function which
            #    creates the subprogram access, and subp_sig is the signature
            #    of the subprogram being accessed.
            #
            # 2. A second transformer (inner_provider) transforms the second
            #    element of this pair in order to retrieve the forward and
            #    backward implementations of the subprogram being accessed.
            #
            # 3. A third transformer (subprogram_access_provider) creates the
            #    definition of the subprogram access is finally constructed
            #    using the pair (access_sig, subp_defs).

            @Transformer.as_transformer
            def get_subprogram_access_signature(sig):
                if isinstance(sig.name, access_paths.Subprogram):
                    if sig.output_domain == ptr_dom:
                        if sig.name.interface.does_return:
                            input_domains = sig.userdata[:-1]
                            output_domain = sig.userdata[-1]
                        else:
                            input_domains = sig.userdata
                            output_domain = None

                        subp_signature = Signature(
                            sig.name.subp_obj,
                            tuple(input_domains), output_domain,
                            tuple(sig.name.interface.out_indices))

                        return sig, subp_signature

            @def_provider
            def subprogram_access_provider(args):
                access_sig, subp_defs = args
                subp = access_sig.name.subp_obj
                interface = access_sig.name.interface
                return (access_paths_ops.subp_address(ptr_dom, subp, interface,
                                                      subp_defs),
                        access_paths_ops.inv_subp_address())

            return (get_subprogram_access_signature >>
                    (Transformer.identity() & inner_provider) >>
                    subprogram_access_provider)
Esempio n. 3
0
def subp_ret_typer(inner):
    """
    :param types.Typer[lal.AdaNode] inner: Typer for return type components.
    :rtype: types.Typer[lal.AdaNode]
    """
    @Transformer.as_transformer
    def get_components(hint):
        if hint.is_a(ExtendedCallReturnType):
            return (hint.out_indices, hint.out_types if hint.ret_type is None
                    else hint.out_types + (hint.ret_type, ))

    @Transformer.as_transformer
    def to_output(x):
        out_indices, out_types = x
        return types.FunOutput(tuple(out_indices), out_types)

    return (get_components >>
            (Transformer.identity() & inner.lifted()) >> to_output)
Esempio n. 4
0
def record_typer(comp_typer):
    """
    :param types.Typer[lal.ComponentDecl | lal.DiscriminantSpec] comp_typer:
        A typer for components of products.

    :return: A typer for record types.

    :rtype: types.Typer[lal.AdaNode]
    """
    @Transformer.as_transformer
    def get_elements(hint):
        """
        :param lal.AdaNode hint: the lal type.
        :return: The components of the record type, if relevant.
        :rtype: list[lal.AdaNode]
        """
        if hint.is_a(lal.TypeDecl):
            if hint.f_type_def.is_a(lal.RecordTypeDef):
                return [field.decl for field in record_fields(hint)]

    to_product = Transformer.as_transformer(types.Product)

    # Get the elements -> type them all -> generate the product type.
    return get_elements >> comp_typer.lifted() >> to_product
Esempio n. 5
0
def name_typer(inner_typer):
    """
    :param types.Typer[lal.AdaNode] inner_typer: A typer for elements
        being referred by identifiers.

    :return: A typer for names.

    :rtype: types.Typer[lal.AdaNode]
    """

    # Create a simple placeholder object for when there are no constraint.
    # (object() is called because None would mean that we failed to fetch the
    # constraint).
    no_constraint = object()

    @Transformer.as_transformer
    def resolved_name_and_constraint(hint):
        """
        :param lal.AdaNode hint: the lal type expression.
        :return: The type declaration associated to the name, if relevant,
            as well as the optional constraint.
        :rtype: (lal.BaseTypeDecl, lal.AdaNode)
        """
        if hint.is_a(lal.SubtypeIndication):
            try:
                return (
                    hint.p_designated_type_decl,
                    hint.f_constraint if hint.f_constraint is not None
                    else no_constraint
                )
            except lal.PropertyError:
                pass

    def identity_if_is_a(tpe):
        """
        Given a type tpe, returns a transformer which fails if its element
        to transform is not of type tpe, or else leaves it untouched.
        """
        @Transformer.as_transformer
        def f(x):
            if x.is_a(tpe):
                return x
        return f

    @Transformer.as_transformer
    def get_range(constraint):
        """
        If the given constraint is a range constraint, returns the expressions
        for its left and right hand side in a pair.
        """
        if constraint is not no_constraint:
            if constraint.is_a(lal.RangeConstraint):
                rng = constraint.f_range.f_range
                if rng.is_a(lal.BinOp) and rng.f_op.is_a(lal.OpDoubleDot):
                    return rng.f_left, rng.f_right

    @Transformer.as_transformer
    def refined_int_range(args):
        """
        From the given pair containing an IntRange type on the left and an
        evaluated range constraint on the right (a pair of integers), return
        a new IntRange instance with the constraint applied.
        """
        tpe, (c_left, c_right) = args
        assert (tpe.frm <= c_left and tpe.to >= c_right)
        return type(tpe)(c_left, c_right)

    # Transforms a lal.RangeConstraint into a pair of int ('First and 'Last)
    get_range_constraint = get_range >> (_eval_as_int & _eval_as_int)

    # Transforms a pair (types.IntRange, lal.RangeConstraint) into a new,
    # refined types.IntRange instance.
    when_constrained_range = (
        (identity_if_is_a(types.IntRange) & get_range_constraint) >>
        refined_int_range
    )

    # 1. Resolve the name reference and the optional constraint into a pair.
    # 2. Type the left (0th) element of the tuple (which contains the referred
    #    declaration).
    # 3. If the computed type is an IntRange and the constraint is a range
    #    constraint, refine the IntRange. Else ignore the constraint and simply
    #    return the previously computed type which is in the left (0th) element
    #    of the tuple.
    return (resolved_name_and_constraint >>
            inner_typer.for_index(0) >>
            (when_constrained_range | Transformer.project(0)))
Esempio n. 6
0
@Transformer.as_transformer
def _eval_as_int(x):
    """
    Given an arbitrary Ada node, tries to evaluate it to an integer.

    :param lal.AdaNode x: The node to evaluate
    :rtype: int | None
    """
    try:
        return x.p_eval_as_int
    except (lal.PropertyError, lal.NativeException, OSError):
        return None


_eval_as_real = (
    Transformer.as_transformer(eval_as_real).catch(NotImplementedError)
)


@types.delegating_typer
def int_range_typer():
    """
    :return: A typer for int ranges.
    :rtype: types.Typer[lal.AdaNode]
    """

    @Transformer.as_transformer
    def get_operands(hint):
        if hint.is_a(lal.TypeDecl):
            if hint.f_type_def.is_a(lal.SignedIntTypeDef):
                rng = hint.f_type_def.f_range.f_range
Esempio n. 7
0
 def provider():
     return (
         original_signature >>
         (Transformer.identity() & actual_interp.def_provider_builder)
         >> transform_implementation) | model_provider
Esempio n. 8
0
 def provider():
     aggregate_provider = Transformer.first_of(
         *(p(provider) for p in def_provider_builders))
     return (aggregate_provider if self.external_def_provider is None
             else (aggregate_provider
                   | self.external_def_provider(provider)))