Boost logo

Proto :

Subject: Re: [proto] grammars, domains and subdomains
From: Eric Niebler (eric_at_[hidden])
Date: 2010-12-10 10:12:33

On 12/9/2010 10:51 AM, Thomas Heller wrote:
> Eric Niebler wrote:
>> On 12/8/2010 5:30 PM, Thomas Heller wrote:
>>> I don't really now how to do it otherwise with the current design.
>>> There is really only this part of the puzzle missing. If it is done, we
>>> have a working and clean Phoenix V3.
>>> For the time being, I can live with the workaround I did.
>>> However, I will focus my efforts of the next days on working out a patch
>>> for this to work properly.
>> I made a simple fix to proto::matches on trunk that should get you
>> moving. The overloads can still be smarter about sub-domains, but for
>> now you can easily work around that by explicitly allowing expressions
>> in sub-domains in your super-domain's grammar. See the attached solution
>> to your original problem.
> It solves the problem as it succeeds to compile.
> However, there are two problems with that solution:
> 1) t2 is matched by grammar1
> 2) I have to add the plus rule in grammar2 (this could be solved with the
> grammar parametrisation from my earlier post)
> 3) The expression in a subdomain is matched in grammar1 on the pure fact
> that it is a subdomain of domain1, it should be matched against the
> subdomains grammar as well.
> Right now, i am questioning the whole deduce_domain domain part and
> selection of the resulting domains in proto's operator overload.
> Here is what i think should happen (Without the loss of genericity I
> restrict myself to binary expressions):
> If the two operands are in the same domain, the situation is clear:
> The operands need to match the grammar belonging to the domain, and the
> result has to as well.
> If one of the operands is in a different domain the situation gets
> complicated. IMHO, the domain of the resulting expression should be
> selected differently.
> Given is a domain (domain1) which has a certain grammar (grammar1) and
> sub-domain (domain2) with another grammar (grammar2).
> When combining two expressions from these domains with a binary op, the
> resulting expression should be in domain2.
> Why? Because there is no way that when writing grammar1 to account the
> expressions which should be valid grammar2. With the current deduce_domain,
> this is determined to fail always. Additionally, conceptionally, it makes
> no sense that a expression containing t1 and t2 be in domain1.

Why not? What about this:

class D1 {};
class D2 : public D1 {};

D1 d1;
D2 d2;

D1 *p1 = &d1; // OK
D1 *p2 = &d2; // ok
D2 *p3 = &d1; // ERROR

You're suggesting an analogous behavior for expressions and domains.
What happens when you have a situation where ...

D1 is a sub-domain of B
D2 is a sub-domain of B

E1 is an expression in D1
E2 is an expression in D2

E1 + E2; // What domain is this in?

The current implementation gives an unambiguous answer -- B -- and
nicely mirrors the implicit conversions of C++ inheritance. Your
solution leads to ambiguities.

> When the domains are not compatible (meaning they have no domain - sub
> domain relationship), the resulting domain should be common_domain.

No, that should be an error.

> These considerations are based on the assumption that a expression in a
> sub-domain should not be matched by the grammar of the super domain.

That /may/ be the case or it may not.

> Which makes sense, given the context of the local variables in phoenix.
> Remember, local variables shall only be valid when embedded in a let or
> lambda expression.
> Maybe, the sub-domain idea is not suited at all for that task.


> OK ... thinking along ... The stuff which is already in place, and your
> suggested fix, makes sense when seeing sub-domains really as extensions to
> the super domain, and the grammar of these ...
> Thoughts?

I really don't think sub-domains are what you're looking for. Why can't
you just give locals like _a a tag type that is unrecognized by the main
Phoenix grammar, but recognized by the grammar of let expressions? That
seems simplest.

Aside: I've given more thought to the problem of grammar-checking in the
presence of sub-domains, and here's my current thinking (and note that
this doesn't address your problem):

The common domain is calculated as always. The existing solution has the
operator overloads building a new expression type and then checking it
against the grammar of the common domain. Let's say Left is already in
the common domain and Right is in a sub-domain. E.g. operator+ builds
proto::plus<Left, Right>::type and checks against common_domain<Left,

What if instead we build a dummy expression type like this: proto::plus<
Left, proto::_ >::type and match THAT against the common domain's
grammar? It's currently undefined what happens when you use the wildcard
as an expression type when doing pattern matching, but we can say that
it's an expression that trivially matches any grammar. (It's already a
grammar that matches any expression.)

Why this is a good thing: expressions that are sub-domains of the common
domain are grandfathered in. That is, they are automatically treated as
valid expressions in the common domain. Without this rule, we end up in
the odd situation where we have valid expression in a sub-domain that
cannot be combined in any way with expression in the super-domain.

Eric Niebler
BoostPro Computing

Proto list run by eric at