-
Notifications
You must be signed in to change notification settings - Fork 251
This issue was moved to a discussion.
You can continue the conversation there. Go to discussion →
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[SUGGESTION] Parameterized Meta Functions; A replacement for Attributes, Contracts, Coroutines and User-defined Language Constructs #523
Comments
This suggestion will bypass the following problems which are mentioned in @hsutter's P0707 paper.
On the other hand:
|
How to declare user-defined language constructs?User-defined language constructs are meta functions which may be applied before a null statement, block statement or parameterized block statement: // null statement
;
// block statement
{ /*statements...*/ }
// parameterized block statement
name (args) { /*statements...*/ } This is an example of what the declaration syntax may be look like. forr: (src: statement, arg: expr<every_op>) -> statement = {
d: every_op = arg.data();
// It's the new generated code.
-> {
(copy __t: timer = ()) while d.get_condition().to_string()$ {
src.to_string()$
__t.delay(d.get_time_interval().to_string()$);
}
}
}
every_op: type = {
condition: expr<bool>;
time_interval: expr<duration>;
operator=: (out this, arg1: expr<bool>, arg2: expr<duration>) = {
condition = arg1;
time_interval = arg2;
}
get_condition: (this) -> expr<bool> = condition;
get_time_interval: (this) -> expr<duration> = time_interval;
}
every: type = {
condition: expr<bool>;
operator=: (out this, arg: expr<bool>) = {
condition = arg;
}
operator(): (inout this, time_interval: expr<duration>) -> every_op = {
return (: every_op = (condition, time_interval));
}
} The above example, would be used like this: main: () = {
x: = random(1, 100);
// Its parameter is `(x < 10) every (1min)`.
@forr (x < 10) every (1min) {
// Its block statement
print(x);
x = random(1, 100);
}
} The parameter main: () = {
x: = random(1, 100);
(copy __t: timer = ()) while x < 10 {
print(x);
x = random(1, 100);
__t.delay(1min);
}
} When we call This example is a possible implementation, it may be like anything else. Its implementation syntax depends on Reflection which is not yet available in C++1. |
Meta Function OverloadingIt would be possible to overload meta functions. They are regular functions, therefore they can be overloaded: // first signature
forr: (src: statement, arg: expr<every_op>) -> statement = { ... }
// Here is the declaration of `every_op` and `every` type, similar to the previous example.
every_op: type = { /*...*/ }
every: type = { /*...*/ }
// second signature
forr: (src: statement, arg: expr<on_released_op>) -> statement = { ... }
// Here is the declaration of `on_released_op` and `on_released` type, similar to the previous example.
on_released_op: type = { /*...*/ }
on_released: type = { /*...*/ }
// It would call the first signature.
@forr (x < 10) every (1min) {
//statements...
}
// It would call the second signature.
@forr (x < 10) on_released (resource) {
//statements...
} |
This issue was moved to a discussion.
You can continue the conversation there. Go to discussion →
1. Preface
I'm looking for a feature to pass an expression itself like macro parameters instead of immediately calculate the result of an expression to pass its result to functions. To have this feature in Cpp2, the best condidate is Metaclass Functions with
@name
, because it generates code. So@name expr
will generate new code fromexpr
, and it can be applied to declarations, null statements, block statements or parameterized block statements. It's all about Reflections and Generations.2. Suggestion Detail
This suggestion heavely depends on @hsutter's P0707 paper about Metaclasses.
The idea is to allow Meta Functions to get a parameter, in addition to make its usage general. This suggestion requires chaining
(args)class
syntax for object construction as described in this suggestion (e.g.(args)type1(args)type2(args)type3(args)...
). It would have the following use cases:func: () @noreturn = { exit(); }
co_await
,co_yield
andco_return
):NOTE 1:
This suggestion is just a feature to explore, and I know that it isn't going to be implemented anytime soon as Reflection isn't ready yet in Cpp2.
The rules of the suggestion are that:
(x) less (y)
is an expression which creates an object with(x) less
and callsoperator()
on it with(y)
. It is the only one parameter.std::meta
is applied to a null statement:@std::meta "text";
Multiple parameters are not needed if we use reflections to parse that one parameter. After that we would generate new code based on that one parameter. Literally any expression are allowed to be that one parameter. Types look like they are keywords (althouth they are not) within chained object construction with
(args)class
syntax (as described in this suggestion):The point is that a parameterized meta function would generate new code from its parameter.
For example:
The above code would generate this new code:
Use Cases
2.1. User-defined Language Constructs
They are similar to macros in C and Cpp1, except:
@
prefix.User-defined Language Constructs are Meta Functions which would be applied to null statements, block statements or parameterized block statements. Cpp1 attributes in which they apply to null statements, are somehow language constructs. For example,
[[assume(expr)]];
and[[fallthrough]];
attributes in Cpp1, would be like this with the suggestion:Also when the resource have to be released, we can have a user-defined language construct for it:
2.2. Attributes
Parameterized meta functions are similar to attributes in Cpp1, except they are user-defined as library features.
This is how to use them to change the compiler behaviour or to inform the compiler to how generate code. For example, this is equal to
[[noreturn]]
in Cpp1:Compilers can implement their own attributes in Cpp2 as library features instead of how they have implementation-defined attributes in Cpp1. For example,
alias
extension attribute in GCC:In this case, they do not generate any statement, they only change the compiler behaviour.
The compiler could provide its options in
compiler
object:Meta functions can change the compiler behaviour with
compiler
object (reflections API).2.3 Contracts
Contracts
pre
andpost
are meta functions. They would add test conditions to the before and the after of function body. They generate new function body if that's necessary. For example:The above declaration will generate this declaration:
2.4 Coroutines
Coroutines could be a library feature in Cpp1 too (via
co_await
,co_yield
andco_return
). For example:The above examples are modified Cpp2 version from cppreference.com examples.
3. Your Questions
This suggestion won't eliminate X% of security vulnerabilities of a given kind in current C++ code.
But this suggestion will automate or eliminate X% of current C++ guidance literature. It would unify Contracts, Attributes, Coroutines and User-defined Language Constructs to a single concept Parameterized Meta Functions.
Also this suggestion would help compiler and library writers:
4. Considered Alternatives
I've considered to use named arguments instead of
(args)class1(args)class2(args)...
, but the problem of named arguments is that they don't look like built-in language constructs, also they need comma:The text was updated successfully, but these errors were encountered: