Boost logo

Proto :

Subject: Re: [proto] Problems with unary function node
From: Eric Niebler (eric_at_[hidden])
Date: 2011-10-29 00:37:58

On 10/28/2011 6:29 AM, Mathias Gaunard wrote:
> On 28/10/2011 07:30, Eric Niebler wrote:
>> Regardless, I'm convinced that a complete fix is possible, and I have it
>> mostly coded. It would require you (the user) to disable unary function
>> and assign in your domain via a grammar. But. It's expensive at compile
>> time, and everybody pays. I need to be convinced before I proceed.
> I think it would also be fine to just document the issue, and let people
> special-case the generator if needed.
> I wouldn't want all Proto-based code to become slower just because of this.
> I would be quite interested to see what the fix is, though.

I opened a trac issue, and attached the patch.

I don't think this solves your problem, though. See below.

>> Your
>> example code was very contrived. (Certainly you don't need to ask a
>> Proto expression extension type whether it is a proto expression. The
>> answer will always be yes.)
>> So what is your realistic usage scenario?
>> What type categorization do you want to do on the extension type that
>> you can't do on the raw passed-in expression?
> The call goes through generic components that don't necessarily deal
> with Proto expressions, but some of them may have special
> specializations for Proto expressions.
> The categorization of non-raw expressions is of course richer, because
> each of those went through their own generators and attached special
> semantic information to each node type.
> In NT2, we generate expressions that look like this
> template<class Expr, class ResultType>
> struct expression
> : proto::extends< expression<Expr, ResultType> >
> {
> typedef typename extent_type<ResultType>::type extent_type;
> expression(Expr const& expr, extent_type const& extent_)
> : proto::extends< expression<Expr, ResultType> >(expr)
> , extent(extent_)
> {
> }
> extent_type const& extent() const { return extent; }
> private:
> extent_type extent;
> };
> It not only wraps the naked Proto expression, but it also contains what
> the expression represents from a logical point of view (at some point we
> wanted to use domains for this, but it's just not practical).
> The expression also contains its logical size, which is computed at
> runtime by the generator, and is tightly coupled with what the
> expression represents.
> So we categorize a naked tag(a0, a1) expression as
> expr_< unspecified_<Expr>, domain, tag >
> The same expression with the result type information of int32_t is
> expr_< scalar_< int32_<Expr> >, domain, tag >
> In certain situations, I ended up with a category of unspecified_<Expr>
> on some of my expression types because the categorization meta-function
> was instantiated on an incomplete type (the expression type for the
> terminal).
> This way quite unexepcted and hard to debug.
> Regardless, we like to have to ability to inject specializations *after*
> the expression type has been defined, which only works if instantiation
> is delayed until the function is actually called.

It could be that I'm stupid, or that I'm tired, or that your explanation
is insufficient ... but I don't get it. Regardless, it seems to me that
you still want your expressions to have a unary function operator, but
that you don't want to compute its return type eagerly. And as you said,
that's just not possible in today's language. My patch solves the
problem only for those people who want to turn off unary function
completely. Ditto for assign.

What should you do? Avoid calling those generic categorization
metafunctions in your generator. The generator has to assume the type it
computes is incomplete. Don't pass it to anything that tries to
introspect it. You have to find another way to get the information you need.

Sorry I can't be more helpful.

Eric Niebler
BoostPro Computing

Proto list run by eric at