Date: Sun, 11 Apr 2021 14:32:57 +0200
Martin,
I am opening a new thread, since I don't really like our discussion
to fan out under the same thread in infinite directions. Otherwise it is
later impossible to track the different aspects that we want to resolve.
The thread to which you were replying was meant to talk about the
primary syntactic problem with the combination of lambdas and
attributes, and there is no need to complicate that discussion with
`auto` paramenters and the lookahead that this might incur. (but see
below)
on Sun, 11 Apr 2021 11:15:22 +0000 you ("Uecker, Martin"
<Martin.Uecker_at_[hidden]>) wrote:
> My main concern with all this is less about some finite look ahead
> but something else:
>
> In C is is possible to do type checking during parsing and directly
> produce an intermediate code (or in theory even machine code).
> There is no need to have an AST and some compiler do not have this.
> Without goto we could go more or less directly to SSA.
>
> With type generic lambdas this is not possible anymore. You then
> need to be able to parse arbitrary code without type information
> and perform the type checking later when the lambda is specialized.
>
> [](auto x){ ... arbitrary c code with unknown types ... }
>
> What is an ICE may also depends on type and folding then also
> needs to be delayed.
>
> At the moment only the preprocessor moves tokens around and
> parsing, type checking, and ICE folding can be done in one pass
> with limited look ahead.
>
> Note, that this is a superficious issue introduced by the lambda
> syntax.
No it isn't, this is only for tg lambdas with `auto` parameters, which
even in C++ is a relatively new feature.
> As the use case for type-generic lambdas is that they
> are produced by a macro are instantiated directly, this could
> be done differenty, i.e. the statement expressions of GCC do
> not have this problem:
>
> #define foo(x) \
> ({ \
> auto y = (x); // type generic argument
> ... arbitrary code using y ... \
> })
>
> After expnading the macro the code can be parsed with full type
> information because the argument is inserted by the preprocessor
> at a position where it can be parsed frst.
Your example is a bit misleading. The natural C++ replacement for your
macro above is
#define foo(x) \
[&, y = (x)] mutable { /* type generic argument */ \
... arbitrary code using y ... \
}()
No `auto` parameters are need for such a thing. For the proposed C
feature (without `mutable`) this would be
#define foo(x) \
[&, yy = (x)] { /* type generic argument */ \
auto y = yy; \
... arbitrary code using y ... \
}()
This may not be pretty, but here also no `auto` parameters are needed
and the full functionality is already there.
The only real and new purpose of type-generic macros with `auto`
parameters is the second usage for them, namely the conversion into
function pointers. A type-generic lambda macro
#define mysin [](auto x){ \
/* implement a tg formula for the sinus function */ \
return val; \
}
double (*sin)(double) = mysin;
is not so easily emulated by gcc's compound statement plus nested
functions, if at all.
> In contrast, with type-generic lambdas:
>
> #define foo [](auto y){ \
> ... arbitrary code using y ... \
> }
>
> the code needs to be parsed without knowing the type of 'y'
> and only then is the argument is parsed which yields this
> information.
If used in a call expression, yes, in a sense.
But that problem can also be solved with lookahead for a ballanced
token sequence, finding the arguments to the call (if this is a call),
doing the type inference for the parameters, and then scanning the
body of the lambda for real.
So yes, this has a cost, but I think that this cost is limited.
The big advantage is that this would bring us feature-complete
type-generic math library (or similar) that enables us to provide
function pointers where they are needed.
Jens
I am opening a new thread, since I don't really like our discussion
to fan out under the same thread in infinite directions. Otherwise it is
later impossible to track the different aspects that we want to resolve.
The thread to which you were replying was meant to talk about the
primary syntactic problem with the combination of lambdas and
attributes, and there is no need to complicate that discussion with
`auto` paramenters and the lookahead that this might incur. (but see
below)
on Sun, 11 Apr 2021 11:15:22 +0000 you ("Uecker, Martin"
<Martin.Uecker_at_[hidden]>) wrote:
> My main concern with all this is less about some finite look ahead
> but something else:
>
> In C is is possible to do type checking during parsing and directly
> produce an intermediate code (or in theory even machine code).
> There is no need to have an AST and some compiler do not have this.
> Without goto we could go more or less directly to SSA.
>
> With type generic lambdas this is not possible anymore. You then
> need to be able to parse arbitrary code without type information
> and perform the type checking later when the lambda is specialized.
>
> [](auto x){ ... arbitrary c code with unknown types ... }
>
> What is an ICE may also depends on type and folding then also
> needs to be delayed.
>
> At the moment only the preprocessor moves tokens around and
> parsing, type checking, and ICE folding can be done in one pass
> with limited look ahead.
>
> Note, that this is a superficious issue introduced by the lambda
> syntax.
No it isn't, this is only for tg lambdas with `auto` parameters, which
even in C++ is a relatively new feature.
> As the use case for type-generic lambdas is that they
> are produced by a macro are instantiated directly, this could
> be done differenty, i.e. the statement expressions of GCC do
> not have this problem:
>
> #define foo(x) \
> ({ \
> auto y = (x); // type generic argument
> ... arbitrary code using y ... \
> })
>
> After expnading the macro the code can be parsed with full type
> information because the argument is inserted by the preprocessor
> at a position where it can be parsed frst.
Your example is a bit misleading. The natural C++ replacement for your
macro above is
#define foo(x) \
[&, y = (x)] mutable { /* type generic argument */ \
... arbitrary code using y ... \
}()
No `auto` parameters are need for such a thing. For the proposed C
feature (without `mutable`) this would be
#define foo(x) \
[&, yy = (x)] { /* type generic argument */ \
auto y = yy; \
... arbitrary code using y ... \
}()
This may not be pretty, but here also no `auto` parameters are needed
and the full functionality is already there.
The only real and new purpose of type-generic macros with `auto`
parameters is the second usage for them, namely the conversion into
function pointers. A type-generic lambda macro
#define mysin [](auto x){ \
/* implement a tg formula for the sinus function */ \
return val; \
}
double (*sin)(double) = mysin;
is not so easily emulated by gcc's compound statement plus nested
functions, if at all.
> In contrast, with type-generic lambdas:
>
> #define foo [](auto y){ \
> ... arbitrary code using y ... \
> }
>
> the code needs to be parsed without knowing the type of 'y'
> and only then is the argument is parsed which yields this
> information.
If used in a call expression, yes, in a sense.
But that problem can also be solved with lookahead for a ballanced
token sequence, finding the arguments to the call (if this is a call),
doing the type inference for the parameters, and then scanning the
body of the lambda for real.
So yes, this has a cost, but I think that this cost is limited.
The big advantage is that this would bring us feature-complete
type-generic math library (or similar) that enables us to provide
function pointers where they are needed.
Jens
-- :: INRIA Nancy Grand Est ::: Camus ::::::: ICube/ICPS ::: :: ::::::::::::::: office Strasbourg : +33 368854536 :: :: :::::::::::::::::::::: gsm France : +33 651400183 :: :: ::::::::::::::: gsm international : +49 15737185122 :: :: http://icube-icps.unistra.fr/index.php/Jens_Gustedt ::
Received on 2021-04-11 07:33:03