Topic: Compile-time generated abstract-syntax-trees
Author: Miro Knejp <miro.knejp@gmail.com>
Date: Thu, 25 Feb 2016 20:29:11 +0100
Raw View
This is a multi-part message in MIME format.
--------------000808020807050509030803
Content-Type: text/plain; charset=UTF-8; format=flowed
Sorry to break it to you, but you might have wanted to do a bit more
research.
The premise for your problem statement is factually wrong. See below.
Am 25.02.2016 um 19:06 schrieb Paul:
> *_Compile-time generated abstract-syntax-trees using generalized
> concepts_*
>
> *Problem:*
>
> A major issue in generic programming with C++ is the increase of
> compile-time
> when compiling a complex code base (Boost, Hana, ...). Compilers like
> Clang
> or GCC usually only cache the tokens from the source code, this is
> already a
> good thing to do, to improve compile-time but the Lexer of a compiler
> isn't the most time wasting part of the compile chain.
> The Parser and Semantic-Analysis takes up the most time because every
> time a
> template gets instantiated, the compiler basically re-runs the Parser &
> Semantic-Analysis.
This is wrong. The parser is not involved in template instantiation at
all, at least not in Clang (which is the only compiler I have at least
some knowledge of its source code so I'll use it as reference here).
When Clang dumps the processed source code into a file it actually
serialized the fully parsed AST, not just lexed tokens.
> Another problem which arises when using templates is the misguided
> diagnostic
> but with the use of the concepts extension for C++, this issue can be
> partially
> seen as solved.
> *
> *
> *Approach using AST-Injection:*
>
> The idea is to generate an abstract-syntax-tree (AST) which can be
> injected into
> an appropriate context. This seems simple as it completely eliminates
> the need
> of re-parsing and requires minimal semantic analysis in context of the
> place to
> inject the AST.
Again, there is no "re-parsing" happening in template instantiation.
Clang generates an AST for the entire translation unit and that includes
function, class and variable templates. These are represented as special
AST nodes and serve as as basis for specialization, which does not
consume lexer tokens but AST nodes. The problem you're trying to solve
here doesn't exist.
> *
> *
> *Problem with AST-Injection:*
>
> Lets say we have this template code:
>
> template <typename T, typename Z>
> auto Foo(T a, Z b) {
> return T.getConstant(z);
> }
>
> How can the compiler know what T is when Foo hasn't been instantiated?
> The compiler simply cannot create an AST because it doesn't know the
> signature
> of getConstant and the class in general.
Again, wrong. The compiler creates an AST for the entire Foo function,
marking "T" and "Z" as dependent names, and all statements and
expressions in the function's body are parsed into child nodes. Because
it knows that "T" is a dependent name it defers this part of Sema until
specialization (any independent statements/expressions have to be
checked by Sema beforehand).
> To create an independent AST which can be merged later within the context
> to be inject, we have to at least constrain the type T, like we do
> with Concepts
> just with another purpose to get better diagnostics.
>
> *Problem with Concepts:*
>
> As a result from the above conclusions it seems that replacing
> 'typename' with a
> concept should solve the 'signature' problem.
>
> Lets see:
>
> template<typename T, typename U>
> concept bool SameTy() {
> return std::is_same<T, U>::value;
> }
> template <typename T>
> concept bool TConcept =
> requires () {
> { &T::getConstant } -> SameTy<int (T::*) (int)>;
> } ||
> requires () {
> { &T::getConstant } -> SameTy<int (T::*) (short)>;
> };
>
> template <TConcept T, typename Z>
> auto Foo(T a, Z b) {
> return T.getConstant(z);
> }
>
> We are basically checking the non-static member function's signature
> by using
> concepts but there is a flaw in that. You are not supposed to do type
> signature
> in that way, it seems more like a hack and has lots of limitations
> (overloads?),
> because of the expression based constraining.
You're needlessly overconstraining your concept. Foo does not require
"getConstant()" to have the exact signature of "int(T::*)(int)" or
"int(T::*)(short)". It only requires that the expression
"a.getConstant(b)" is well-formed with "a" being an lvalue of type "T"
and "b" being an lvalue of type "Z". The return type does not matter
since Foo returns "auto". That simplifies your concept *significantly*:
template<class T, class Z>
concept bool TConcept = requires (T a, Z b) { a.getConstant(b); };
template <class T, class Z> requires TConcept<T, Z>
auto Foo(T a, Z b) {
return a.getConstant(b);
}
If you want to restrict "Z" to "int" and "short" only, then provide only
the appropriate overloads. If the function must return "int", declare it
so and don't use "auto".
>
> *Generalizing Concepts:*
>
> "Concepts are not a general purpose, compile-time introspection tool.
> Nor are they a general purpose template metaprogramming tool." -
> Andrew Sutton [1]
>
> I would say that if the current Concepts proposal would be designed to
> be a
> general purpose compile-time introspection tool, it would mainly give
> us the
> ability to get this whole idea to reality.
There's a reason it's called Concepts *Lite*.
>
> Features like in-built signature checking is mostly needed to created
> an useful
> AST. A way which tells the compiler the approximate semantics/syntax
> of the type.
That is *exactly* what concepts tell the compiler: "Make sure the
expression 'a.getConstant(b)' is well-formed otherwise reject the
template." You're telling the compiler the syntax requirements and it
enforces them. And once again, please stop with the AST argumentation
until you have improved your understanding of how template instantiation
works.
>
> *Syntax for injection an AST:*
>
> This is an example of how code might look like when using the
> AST-Injection
> approach.
>
> // I found this "old" concepts syntax somewhere which fits the
> "generalized"
> // concepts approach
> concept TConcept<typename T> {
> int T::getConstant(int);
> int T::getConstant(short);
> }
> constast <TConcept T, typename Z>
> auto Foo(T a, Z b) {
> return T.getConstant(z);
> }
>
> I know this isn't a proposal and this may contain tons of flaws but I
> just would
> like to share what I had in mind regards the still consisting issues with
> templates and ideas how to solve it.
>
Next time simply ditch the whole technical AST stuff (which is factually
wrong and irrelevant to your actual point) and just focus on the actual
problems you have with the concept definition and associated
diagnostics. Oh, and maybe make sure your code examples actually compile
to save us the hassle of figuring out what you've actually meant to show.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/56CF5607.1040406%40gmail.com.
--------------000808020807050509030803
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<html>
<head>
<meta content=3D"text/html; charset=3Dutf-8" http-equiv=3D"Content-Type=
">
</head>
<body bgcolor=3D"#FFFFFF" text=3D"#000000">
Sorry to break it to you, but you might have wanted to do a bit more
research.<br>
The premise for your problem statement is factually wrong. See
below.<br>
<br>
<div class=3D"moz-cite-prefix">Am 25.02.2016 um 19:06 schrieb Paul:<br>
</div>
<blockquote
cite=3D"mid:4550eac8-4009-455b-bfa1-d96278466c1b@isocpp.org"
type=3D"cite">
<div dir=3D"ltr">
<div><b><u>Compile-time generated abstract-syntax-trees using
generalized concepts</u></b></div>
<div><br>
</div>
<div><b>Problem:</b></div>
<div><br>
</div>
<div>A major issue in generic programming with C++ is the
increase of compile-time</div>
<div>when compiling a complex code base (Boost, Hana, ...).
Compilers like Clang</div>
<div>or GCC usually only cache the tokens from the source code,
this is already a</div>
<div>good thing to do, to improve compile-time but the Lexer of
a compiler</div>
<div>isn't the most time wasting part of the compile chain.</div>
<div>The Parser and Semantic-Analysis takes up the most time
because every time a</div>
<div>template gets instantiated, the compiler basically re-runs
the Parser &</div>
<div>Semantic-Analysis.</div>
</div>
</blockquote>
This is wrong. The parser is not involved in template instantiation
at all, at least not in Clang (which is the only compiler I have at
least some knowledge of its source code so I'll use it as reference
here). When Clang dumps the processed source code into a file it
actually serialized the fully parsed AST, not just lexed tokens.<br>
<blockquote
cite=3D"mid:4550eac8-4009-455b-bfa1-d96278466c1b@isocpp.org"
type=3D"cite">
<div dir=3D"ltr">
<div>Another problem which arises when using templates is the
misguided diagnostic</div>
<div>but with the use of the concepts extension for C++, this
issue can be partially</div>
<div>seen as solved.</div>
<div><b><br>
</b></div>
<div><b>Approach using AST-Injection:</b></div>
<div><br>
</div>
<div>The idea is to generate an abstract-syntax-tree (AST) which
can be injected into</div>
<div>an appropriate context. This seems simple as it completely
eliminates the need</div>
<div>of re-parsing and requires minimal semantic analysis in
context of the place to</div>
<div>inject the AST.</div>
</div>
</blockquote>
Again, there is no "re-parsing" happening in template instantiation.
Clang generates an AST for the entire translation unit and that
includes function, class and variable templates. These are
represented as special AST nodes and serve as as basis for
specialization, which does not consume lexer tokens but AST nodes.
The problem you're trying to solve here doesn't exist.<br>
<blockquote
cite=3D"mid:4550eac8-4009-455b-bfa1-d96278466c1b@isocpp.org"
type=3D"cite">
<div dir=3D"ltr">
<div><b><br>
</b></div>
<div><b>Problem with AST-Injection:</b></div>
<div><br>
</div>
<div>Lets say we have this template code:</div>
<div><br>
</div>
<div>=C2=A0 =C2=A0 template <typename T, typename Z></div>
<div>=C2=A0 =C2=A0 auto Foo(T a, Z b) {</div>
<div>=C2=A0 =C2=A0 =C2=A0 return T.getConstant(z);</div>
<div>=C2=A0 =C2=A0 }</div>
<div><br>
</div>
<div>How can the compiler know what T is when Foo hasn't been
instantiated?</div>
<div>The compiler simply cannot create an AST because it doesn't
know the signature</div>
<div>of getConstant and the class in general.</div>
</div>
</blockquote>
Again, wrong. The compiler creates an AST for the entire Foo
function, marking "T" and "Z" as dependent names, and all statements
and expressions in the function's body are parsed into child nodes.
Because it knows that "T" is a dependent name it defers this part of
Sema until specialization (any independent statements/expressions
have to be checked by Sema beforehand).<br>
<blockquote
cite=3D"mid:4550eac8-4009-455b-bfa1-d96278466c1b@isocpp.org"
type=3D"cite">
<div dir=3D"ltr">
<div>To create an independent AST which can be merged later
within the context</div>
<div>to be inject, we have to at least constrain the type T,
like we do with Concepts</div>
<div>just with another purpose to get better diagnostics.</div>
<div><br>
</div>
<div><b>Problem with Concepts:</b></div>
<div><br>
</div>
<div>As a result from the above conclusions it seems that
replacing 'typename' with a</div>
<div>concept should solve the 'signature' problem.</div>
<div><br>
</div>
<div>Lets see:</div>
<div><br>
</div>
<div>=C2=A0 =C2=A0 template<typename T, typename U></div>
<div>=C2=A0 =C2=A0 concept bool SameTy() {</div>
<div>=C2=A0 =C2=A0 =C2=A0 return std::is_same<T, U>::value;</=
div>
<div>=C2=A0 =C2=A0 }</div>
<div>=C2=A0 =C2=A0=C2=A0</div>
<div>=C2=A0 =C2=A0 template <typename T></div>
<div>=C2=A0 =C2=A0 concept bool TConcept =3D</div>
<div>=C2=A0 =C2=A0 =C2=A0 requires () {</div>
<div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 { &T::getConstant } -> Same=
Ty<int (T::*)
(int)>;</div>
<div>=C2=A0 =C2=A0 =C2=A0 } ||</div>
<div>=C2=A0 =C2=A0 =C2=A0 requires () {</div>
<div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 { &T::getConstant } -> Same=
Ty<int (T::*)
(short)>;</div>
<div>=C2=A0 =C2=A0 =C2=A0 };</div>
<div><br>
</div>
<div>=C2=A0 =C2=A0 template <TConcept T, typename Z></div>
<div>=C2=A0 =C2=A0 auto Foo(T a, Z b) {</div>
<div>=C2=A0 =C2=A0 =C2=A0 return T.getConstant(z);</div>
<div>=C2=A0 =C2=A0 }</div>
<div><br>
</div>
<div>We are basically checking the non-static member function's
signature by using</div>
<div>concepts but there is a flaw in that. You are not supposed
to do type signature</div>
<div>in that way, it seems more like a hack and has lots of
limitations (overloads?),</div>
<div>because of the expression based constraining.</div>
</div>
</blockquote>
You're needlessly overconstraining your concept. Foo does not
require=C2=A0 "getConstant()" to have the exact signature of
"int(T::*)(int)" or "int(T::*)(short)". It only requires that the
expression "a.getConstant(b)" is well-formed with "a" being an
lvalue of type "T" and "b" being an lvalue of type "Z". The return
type does not matter since Foo returns "auto". That simplifies your
concept *significantly*:<br>
<br>
template<class T, class Z><br>
concept bool TConcept =3D requires (T a, Z b) { a.getConstant(b); };<br=
>
<br>
template <class T, class Z> requires TConcept<T, Z><br>
<div>auto Foo(T a, Z b) {</div>
<div>=C2=A0=C2=A0=C2=A0 return a.getConstant(b);</div>
<div>}<br>
<br>
If you want to restrict "Z" to "int" and "short" only, then
provide only the appropriate overloads. If the function must
return "int", declare it so and don't use "auto".<br>
</div>
<br>
<blockquote
cite=3D"mid:4550eac8-4009-455b-bfa1-d96278466c1b@isocpp.org"
type=3D"cite">
<div dir=3D"ltr">
<div><br>
</div>
<div><b>Generalizing Concepts:</b></div>
<div><br>
</div>
<div>"Concepts are not a general purpose, compile-time
introspection tool.</div>
<div>Nor are they a general purpose template metaprogramming
tool." - Andrew Sutton [1]</div>
<div><br>
</div>
<div>I would say that if the current Concepts proposal would be
designed to be a</div>
<div>general purpose compile-time introspection tool, it would
mainly give us the</div>
<div>ability to get this whole idea to reality.</div>
</div>
</blockquote>
There's a reason it's called Concepts *Lite*.<br>
<blockquote
cite=3D"mid:4550eac8-4009-455b-bfa1-d96278466c1b@isocpp.org"
type=3D"cite">
<div dir=3D"ltr">
<div><br>
</div>
<div>Features like in-built signature checking is mostly needed
to created an useful</div>
<div>AST. A way which tells the compiler the approximate
semantics/syntax of the type.</div>
</div>
</blockquote>
That is *exactly* what concepts tell the compiler: "Make sure the
expression 'a.getConstant(b)' is well-formed otherwise reject the
template." You're telling the compiler the syntax requirements and
it enforces them. And once again, please stop with the AST
argumentation until you have improved your understanding of how
template instantiation works.<br>
<blockquote
cite=3D"mid:4550eac8-4009-455b-bfa1-d96278466c1b@isocpp.org"
type=3D"cite">
<div dir=3D"ltr">
<div><br>
</div>
<div><b>Syntax for injection an AST:</b></div>
<div><br>
</div>
<div>This is an example of how code might look like when using
the AST-Injection</div>
<div>approach.</div>
<div><br>
</div>
<div>=C2=A0 =C2=A0 // I found this "old" concepts syntax somewhere =
which
fits the "generalized"</div>
<div>=C2=A0 =C2=A0 // concepts approach</div>
<div>=C2=A0 =C2=A0 concept TConcept<typename T> {</div>
<div>=C2=A0 =C2=A0 =C2=A0 int T::getConstant(int);</div>
<div>=C2=A0 =C2=A0 =C2=A0 int T::getConstant(short);</div>
<div>=C2=A0 =C2=A0 }</div>
<div>=C2=A0 =C2=A0=C2=A0</div>
<div>=C2=A0 =C2=A0 constast <TConcept T, typename Z>=C2=A0</d=
iv>
<div>=C2=A0 =C2=A0 auto Foo(T a, Z b) {</div>
<div>=C2=A0 =C2=A0 =C2=A0 return T.getConstant(z);</div>
<div>=C2=A0 =C2=A0 }</div>
<div><br>
</div>
<div>I know this isn't a proposal and this may contain tons of
flaws but I just would</div>
<div>like to share what I had in mind regards the still
consisting issues with</div>
<div>templates and ideas how to solve it.</div>
<div><br>
</div>
</div>
</blockquote>
Next time simply ditch the whole technical AST stuff (which is
factually wrong and irrelevant to your actual point) and just focus
on the actual problems you have with the concept definition and
associated diagnostics. Oh, and maybe make sure your code examples
actually compile to save us the hassle of figuring out what you've
actually meant to show.<br>
<br>
</body>
</html>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/56CF5607.1040406%40gmail.com?utm_medi=
um=3Demail&utm_source=3Dfooter">https://groups.google.com/a/isocpp.org/d/ms=
gid/std-proposals/56CF5607.1040406%40gmail.com</a>.<br />
--------------000808020807050509030803--
.
Author: Paul <peetpaul69@gmail.com>
Date: Thu, 25 Feb 2016 12:03:45 -0800 (PST)
Raw View
------=_Part_1218_809316738.1456430625245
Content-Type: multipart/alternative;
boundary="----=_Part_1219_1236187259.1456430625245"
------=_Part_1219_1236187259.1456430625245
Content-Type: text/plain; charset=UTF-8
Well, I actually did research it and the code I included were just
"pseudocode" with no intention to actually compile. Yes, I just realized
that I completely misunderstood the code (I am not familiar with the code
so I assumed a lot, especially the stuff with CachedToken
and LexTemplateFunctionForLateParsing (which actually refers to ms delayed
template prasing)).
My apologies.
On Thursday, February 25, 2016 at 8:27:09 PM UTC+1, Miro Knejp wrote:
>
> Sorry to break it to you, but you might have wanted to do a bit more
> research.
> The premise for your problem statement is factually wrong. See below.
>
> Am 25.02.2016 um 19:06 schrieb Paul:
>
> *Compile-time generated abstract-syntax-trees using generalized concepts*
>
> *Problem:*
>
> A major issue in generic programming with C++ is the increase of
> compile-time
> when compiling a complex code base (Boost, Hana, ...). Compilers like Clang
> or GCC usually only cache the tokens from the source code, this is already
> a
> good thing to do, to improve compile-time but the Lexer of a compiler
> isn't the most time wasting part of the compile chain.
> The Parser and Semantic-Analysis takes up the most time because every time
> a
> template gets instantiated, the compiler basically re-runs the Parser &
> Semantic-Analysis.
>
> This is wrong. The parser is not involved in template instantiation at
> all, at least not in Clang (which is the only compiler I have at least some
> knowledge of its source code so I'll use it as reference here). When Clang
> dumps the processed source code into a file it actually serialized the
> fully parsed AST, not just lexed tokens.
>
> Another problem which arises when using templates is the misguided
> diagnostic
> but with the use of the concepts extension for C++, this issue can be
> partially
> seen as solved.
>
> *Approach using AST-Injection:*
>
> The idea is to generate an abstract-syntax-tree (AST) which can be
> injected into
> an appropriate context. This seems simple as it completely eliminates the
> need
> of re-parsing and requires minimal semantic analysis in context of the
> place to
> inject the AST.
>
> Again, there is no "re-parsing" happening in template instantiation. Clang
> generates an AST for the entire translation unit and that includes
> function, class and variable templates. These are represented as special
> AST nodes and serve as as basis for specialization, which does not consume
> lexer tokens but AST nodes. The problem you're trying to solve here doesn't
> exist.
>
>
> *Problem with AST-Injection:*
>
> Lets say we have this template code:
>
> template <typename T, typename Z>
> auto Foo(T a, Z b) {
> return T.getConstant(z);
> }
>
> How can the compiler know what T is when Foo hasn't been instantiated?
> The compiler simply cannot create an AST because it doesn't know the
> signature
> of getConstant and the class in general.
>
> Again, wrong. The compiler creates an AST for the entire Foo function,
> marking "T" and "Z" as dependent names, and all statements and expressions
> in the function's body are parsed into child nodes. Because it knows that
> "T" is a dependent name it defers this part of Sema until specialization
> (any independent statements/expressions have to be checked by Sema
> beforehand).
>
> To create an independent AST which can be merged later within the context
> to be inject, we have to at least constrain the type T, like we do with
> Concepts
> just with another purpose to get better diagnostics.
>
> *Problem with Concepts:*
>
> As a result from the above conclusions it seems that replacing 'typename'
> with a
> concept should solve the 'signature' problem.
>
> Lets see:
>
> template<typename T, typename U>
> concept bool SameTy() {
> return std::is_same<T, U>::value;
> }
>
> template <typename T>
> concept bool TConcept =
> requires () {
> { &T::getConstant } -> SameTy<int (T::*) (int)>;
> } ||
> requires () {
> { &T::getConstant } -> SameTy<int (T::*) (short)>;
> };
>
> template <TConcept T, typename Z>
> auto Foo(T a, Z b) {
> return T.getConstant(z);
> }
>
> We are basically checking the non-static member function's signature by
> using
> concepts but there is a flaw in that. You are not supposed to do type
> signature
> in that way, it seems more like a hack and has lots of limitations
> (overloads?),
> because of the expression based constraining.
>
> You're needlessly overconstraining your concept. Foo does not require
> "getConstant()" to have the exact signature of "int(T::*)(int)" or
> "int(T::*)(short)". It only requires that the expression "a.getConstant(b)"
> is well-formed with "a" being an lvalue of type "T" and "b" being an lvalue
> of type "Z". The return type does not matter since Foo returns "auto". That
> simplifies your concept *significantly*:
>
> template<class T, class Z>
> concept bool TConcept = requires (T a, Z b) { a.getConstant(b); };
>
> template <class T, class Z> requires TConcept<T, Z>
> auto Foo(T a, Z b) {
> return a.getConstant(b);
> }
>
> If you want to restrict "Z" to "int" and "short" only, then provide only
> the appropriate overloads. If the function must return "int", declare it so
> and don't use "auto".
>
>
> *Generalizing Concepts:*
>
> "Concepts are not a general purpose, compile-time introspection tool.
> Nor are they a general purpose template metaprogramming tool." - Andrew
> Sutton [1]
>
> I would say that if the current Concepts proposal would be designed to be a
> general purpose compile-time introspection tool, it would mainly give us
> the
> ability to get this whole idea to reality.
>
> There's a reason it's called Concepts *Lite*.
>
>
> Features like in-built signature checking is mostly needed to created an
> useful
> AST. A way which tells the compiler the approximate semantics/syntax of
> the type.
>
> That is *exactly* what concepts tell the compiler: "Make sure the
> expression 'a.getConstant(b)' is well-formed otherwise reject the
> template." You're telling the compiler the syntax requirements and it
> enforces them. And once again, please stop with the AST argumentation until
> you have improved your understanding of how template instantiation works.
>
>
> *Syntax for injection an AST:*
>
> This is an example of how code might look like when using the AST-Injection
> approach.
>
> // I found this "old" concepts syntax somewhere which fits the
> "generalized"
> // concepts approach
> concept TConcept<typename T> {
> int T::getConstant(int);
> int T::getConstant(short);
> }
>
> constast <TConcept T, typename Z>
> auto Foo(T a, Z b) {
> return T.getConstant(z);
> }
>
> I know this isn't a proposal and this may contain tons of flaws but I just
> would
> like to share what I had in mind regards the still consisting issues with
> templates and ideas how to solve it.
>
> Next time simply ditch the whole technical AST stuff (which is factually
> wrong and irrelevant to your actual point) and just focus on the actual
> problems you have with the concept definition and associated diagnostics.
> Oh, and maybe make sure your code examples actually compile to save us the
> hassle of figuring out what you've actually meant to show.
>
>
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/9739aca1-8000-41cf-8647-2f22f063d05a%40isocpp.org.
------=_Part_1219_1236187259.1456430625245
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">Well, I actually did research it and the code I included w=
ere just "pseudocode" with no intention to actually compile. Yes,=
I just realized that I completely misunderstood the code (I am not familia=
r with the code so I assumed a lot, especially the stuff with CachedToken a=
nd=C2=A0LexTemplateFunctionForLateParsing (which actually refers to ms dela=
yed template prasing)).<div>My apologies.<div><br>On Thursday, February 25,=
2016 at 8:27:09 PM UTC+1, Miro Knejp wrote:<blockquote class=3D"gmail_quot=
e" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;paddin=
g-left: 1ex;">
=20
=20
=20
<div bgcolor=3D"#FFFFFF" text=3D"#000000">
Sorry to break it to you, but you might have wanted to do a bit more
research.<br>
The premise for your problem statement is factually wrong. See
below.<br>
<br>
<div>Am 25.02.2016 um 19:06 schrieb Paul:<br>
</div>
<blockquote type=3D"cite">
<div dir=3D"ltr">
<div><b><u>Compile-time generated abstract-syntax-trees using
generalized concepts</u></b></div>
<div><br>
</div>
<div><b>Problem:</b></div>
<div><br>
</div>
<div>A major issue in generic programming with C++ is the
increase of compile-time</div>
<div>when compiling a complex code base (Boost, Hana, ...).
Compilers like Clang</div>
<div>or GCC usually only cache the tokens from the source code,
this is already a</div>
<div>good thing to do, to improve compile-time but the Lexer of
a compiler</div>
<div>isn't the most time wasting part of the compile chain.</di=
v>
<div>The Parser and Semantic-Analysis takes up the most time
because every time a</div>
<div>template gets instantiated, the compiler basically re-runs
the Parser &</div>
<div>Semantic-Analysis.</div>
</div>
</blockquote>
This is wrong. The parser is not involved in template instantiation
at all, at least not in Clang (which is the only compiler I have at
least some knowledge of its source code so I'll use it as reference
here). When Clang dumps the processed source code into a file it
actually serialized the fully parsed AST, not just lexed tokens.<br>
<blockquote type=3D"cite">
<div dir=3D"ltr">
<div>Another problem which arises when using templates is the
misguided diagnostic</div>
<div>but with the use of the concepts extension for C++, this
issue can be partially</div>
<div>seen as solved.</div>
<div><b><br>
</b></div>
<div><b>Approach using AST-Injection:</b></div>
<div><br>
</div>
<div>The idea is to generate an abstract-syntax-tree (AST) which
can be injected into</div>
<div>an appropriate context. This seems simple as it completely
eliminates the need</div>
<div>of re-parsing and requires minimal semantic analysis in
context of the place to</div>
<div>inject the AST.</div>
</div>
</blockquote>
Again, there is no "re-parsing" happening in template instant=
iation.
Clang generates an AST for the entire translation unit and that
includes function, class and variable templates. These are
represented as special AST nodes and serve as as basis for
specialization, which does not consume lexer tokens but AST nodes.
The problem you're trying to solve here doesn't exist.<br>
<blockquote type=3D"cite">
<div dir=3D"ltr">
<div><b><br>
</b></div>
<div><b>Problem with AST-Injection:</b></div>
<div><br>
</div>
<div>Lets say we have this template code:</div>
<div><br>
</div>
<div>=C2=A0 =C2=A0 template <typename T, typename Z></div>
<div>=C2=A0 =C2=A0 auto Foo(T a, Z b) {</div>
<div>=C2=A0 =C2=A0 =C2=A0 return T.getConstant(z);</div>
<div>=C2=A0 =C2=A0 }</div>
<div><br>
</div>
<div>How can the compiler know what T is when Foo hasn't been
instantiated?</div>
<div>The compiler simply cannot create an AST because it doesn'=
t
know the signature</div>
<div>of getConstant and the class in general.</div>
</div>
</blockquote>
Again, wrong. The compiler creates an AST for the entire Foo
function, marking "T" and "Z" as dependent names, a=
nd all statements
and expressions in the function's body are parsed into child nodes.
Because it knows that "T" is a dependent name it defers this =
part of
Sema until specialization (any independent statements/expressions
have to be checked by Sema beforehand).<br>
<blockquote type=3D"cite">
<div dir=3D"ltr">
<div>To create an independent AST which can be merged later
within the context</div>
<div>to be inject, we have to at least constrain the type T,
like we do with Concepts</div>
<div>just with another purpose to get better diagnostics.</div>
<div><br>
</div>
<div><b>Problem with Concepts:</b></div>
<div><br>
</div>
<div>As a result from the above conclusions it seems that
replacing 'typename' with a</div>
<div>concept should solve the 'signature' problem.</div>
<div><br>
</div>
<div>Lets see:</div>
<div><br>
</div>
<div>=C2=A0 =C2=A0 template<typename T, typename U></div>
<div>=C2=A0 =C2=A0 concept bool SameTy() {</div>
<div>=C2=A0 =C2=A0 =C2=A0 return std::is_same<T, U>::value;</=
div>
<div>=C2=A0 =C2=A0 }</div>
<div>=C2=A0 =C2=A0=C2=A0</div>
<div>=C2=A0 =C2=A0 template <typename T></div>
<div>=C2=A0 =C2=A0 concept bool TConcept =3D</div>
<div>=C2=A0 =C2=A0 =C2=A0 requires () {</div>
<div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 { &T::getConstant } -> Same=
Ty<int (T::*)
(int)>;</div>
<div>=C2=A0 =C2=A0 =C2=A0 } ||</div>
<div>=C2=A0 =C2=A0 =C2=A0 requires () {</div>
<div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 { &T::getConstant } -> Same=
Ty<int (T::*)
(short)>;</div>
<div>=C2=A0 =C2=A0 =C2=A0 };</div>
<div><br>
</div>
<div>=C2=A0 =C2=A0 template <TConcept T, typename Z></div>
<div>=C2=A0 =C2=A0 auto Foo(T a, Z b) {</div>
<div>=C2=A0 =C2=A0 =C2=A0 return T.getConstant(z);</div>
<div>=C2=A0 =C2=A0 }</div>
<div><br>
</div>
<div>We are basically checking the non-static member function's
signature by using</div>
<div>concepts but there is a flaw in that. You are not supposed
to do type signature</div>
<div>in that way, it seems more like a hack and has lots of
limitations (overloads?),</div>
<div>because of the expression based constraining.</div>
</div>
</blockquote>
You're needlessly overconstraining your concept. Foo does not
require=C2=A0 "getConstant()" to have the exact signature of
"int(T::*)(int)" or "int(T::*)(short)". It only req=
uires that the
expression "a.getConstant(b)" is well-formed with "a&quo=
t; being an
lvalue of type "T" and "b" being an lvalue of type =
"Z". The return
type does not matter since Foo returns "auto". That simplifie=
s your
concept *significantly*:<br>
<br>
template<class T, class Z><br>
concept bool TConcept =3D requires (T a, Z b) { a.getConstant(b); };<br=
>
<br>
template <class T, class Z> requires TConcept<T, Z><br>
<div>auto Foo(T a, Z b) {</div>
<div>=C2=A0=C2=A0=C2=A0 return a.getConstant(b);</div>
<div>}<br>
<br>
If you want to restrict "Z" to "int" and "sh=
ort" only, then
provide only the appropriate overloads. If the function must
return "int", declare it so and don't use "auto&qu=
ot;.<br>
</div>
<br>
<blockquote type=3D"cite">
<div dir=3D"ltr">
<div><br>
</div>
<div><b>Generalizing Concepts:</b></div>
<div><br>
</div>
<div>"Concepts are not a general purpose, compile-time
introspection tool.</div>
<div>Nor are they a general purpose template metaprogramming
tool." - Andrew Sutton [1]</div>
<div><br>
</div>
<div>I would say that if the current Concepts proposal would be
designed to be a</div>
<div>general purpose compile-time introspection tool, it would
mainly give us the</div>
<div>ability to get this whole idea to reality.</div>
</div>
</blockquote>
There's a reason it's called Concepts *Lite*.<br>
<blockquote type=3D"cite">
<div dir=3D"ltr">
<div><br>
</div>
<div>Features like in-built signature checking is mostly needed
to created an useful</div>
<div>AST. A way which tells the compiler the approximate
semantics/syntax of the type.</div>
</div>
</blockquote>
That is *exactly* what concepts tell the compiler: "Make sure the
expression 'a.getConstant(b)' is well-formed otherwise reject t=
he
template." You're telling the compiler the syntax requirements=
and
it enforces them. And once again, please stop with the AST
argumentation until you have improved your understanding of how
template instantiation works.<br>
<blockquote type=3D"cite">
<div dir=3D"ltr">
<div><br>
</div>
<div><b>Syntax for injection an AST:</b></div>
<div><br>
</div>
<div>This is an example of how code might look like when using
the AST-Injection</div>
<div>approach.</div>
<div><br>
</div>
<div>=C2=A0 =C2=A0 // I found this "old" concepts syntax =
somewhere which
fits the "generalized"</div>
<div>=C2=A0 =C2=A0 // concepts approach</div>
<div>=C2=A0 =C2=A0 concept TConcept<typename T> {</div>
<div>=C2=A0 =C2=A0 =C2=A0 int T::getConstant(int);</div>
<div>=C2=A0 =C2=A0 =C2=A0 int T::getConstant(short);</div>
<div>=C2=A0 =C2=A0 }</div>
<div>=C2=A0 =C2=A0=C2=A0</div>
<div>=C2=A0 =C2=A0 constast <TConcept T, typename Z>=C2=A0</d=
iv>
<div>=C2=A0 =C2=A0 auto Foo(T a, Z b) {</div>
<div>=C2=A0 =C2=A0 =C2=A0 return T.getConstant(z);</div>
<div>=C2=A0 =C2=A0 }</div>
<div><br>
</div>
<div>I know this isn't a proposal and this may contain tons of
flaws but I just would</div>
<div>like to share what I had in mind regards the still
consisting issues with</div>
<div>templates and ideas how to solve it.</div>
<div><br>
</div>
</div>
</blockquote>
Next time simply ditch the whole technical AST stuff (which is
factually wrong and irrelevant to your actual point) and just focus
on the actual problems you have with the concept definition and
associated diagnostics. Oh, and maybe make sure your code examples
actually compile to save us the hassle of figuring out what you've
actually meant to show.<br>
<br>
</div>
</blockquote></div></div></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/9739aca1-8000-41cf-8647-2f22f063d05a%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/9739aca1-8000-41cf-8647-2f22f063d05a=
%40isocpp.org</a>.<br />
------=_Part_1219_1236187259.1456430625245--
------=_Part_1218_809316738.1456430625245--
.
Author: Thiago Macieira <thiago@macieira.org>
Date: Fri, 26 Feb 2016 23:47:01 -0800
Raw View
On quinta-feira, 25 de fevereiro de 2016 20:29:11 PST Miro Knejp wrote:
> Next time simply ditch the whole technical AST stuff (which is factually
> wrong and irrelevant to your actual point) and just focus on the actual
> problems you have with the concept definition and associated
> diagnostics. Oh, and maybe make sure your code examples actually compile
> to save us the hassle of figuring out what you've actually meant to show.
I second Miro's statement here.
Please don't make a proposal based on how a compiler works, ought to work or
used to work. You may be wrong about the compiler, compilers are allowed to
change and there is more than one compiler. In all of the proposals that have
so far talked about AST, we can always point to a compiler that doesn't use an
AST and how that proposal would be implemented.
Instead, tell us how this improves the programmers' lives: be either the
producers of the code in question or the consumers of it.
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/9056791.9NaC6bedIU%40tjmaciei-mobl4.
.