[SUGGESTION] Treat a keyword as an identifier #642
Replies: 26 comments 7 replies
-
I've actually found the Cpp2-specific keywords to be contextual, except for the
Including the |
Beta Was this translation helpful? Give feedback.
-
You're right 😬, that's very nice but it doesn't work in every situation, for example: type: type = {}
main: () = {
variable: type = 0;
} |
Beta Was this translation helpful? Give feedback.
-
I prefer |
Beta Was this translation helpful? Give feedback.
-
Also Cpp2 may have more keywords during language evolution in the future, therefore keywords such as |
Beta Was this translation helpful? Give feedback.
-
For |
Beta Was this translation helpful? Give feedback.
-
This are the sets of Cpp2-specific keywords: {i8, i16, i32, i64, u8,
u16, u32, u64, i8_fast, i16_fast,
i32_fast, i64_fast, u8_fast, u16_fast, u32_fast,
u64_fast, i8_least, i16_least, i32_least, i64_least,
u8_least, u16_least, u32_least, u64_least, inspect});
{next, copy, move, forward, pre, post, final,
in,
as, is, type,
assert, throws,
implicit, out,
inout}); I can't come up with another example like #392 (comment)'s. |
Beta Was this translation helpful? Give feedback.
-
Thanks. It's a good idea to use helper type main: () = {
type: type = {}
variable: ::type = ();
} |
Beta Was this translation helpful? Give feedback.
-
Well, the only reason to name it |
Beta Was this translation helpful? Give feedback.
-
Perhaps a backslash prefix would be a little more readable.
|
Beta Was this translation helpful? Give feedback.
-
Makes me think if raw string literals could just be backslash-escaped (see #302). |
Beta Was this translation helpful? Give feedback.
-
@MichaelCook, I like the idea to use backslash syntax Escape sequences in string literals start with a backslash to change the meaning of a character, why not just use it to change the meaning of a keyword and treat it as an identifier? @JohelEGP, Good idea but in my opinion, raw (non-interpolated) string literals break the general capture syntax |
Beta Was this translation helpful? Give feedback.
-
Because it only works on keywords, if Cpp2 has binary operator // Treats `type` keyword as identifier.
x: \type = ();
// binary operator \
y: = var0 \ var1; Also unary prefix and postfix operators |
Beta Was this translation helpful? Give feedback.
-
These are other use cases and reasons why it does matter in addition to C and Cpp1 language interop:
variable.\if(count < 10).\return(); |
Beta Was this translation helpful? Give feedback.
-
Could you give an example C++ API that would not be usable from Cpp2? Naming variables is not such a case. |
Beta Was this translation helpful? Give feedback.
-
How's this:
|
Beta Was this translation helpful? Give feedback.
-
See #392 (comment).
|
Beta Was this translation helpful? Give feedback.
-
Also Cpp1 type traits in standard library have a member type named std::is_integral<T>::type |
Beta Was this translation helpful? Give feedback.
-
Also const: type = {}
main: () = {
x: const = "";
} But it works with qualified name. By the way Cpp2 generates invalid Cpp1 code: const: type = {}
main: () = {
x: ::const = "";
} |
Beta Was this translation helpful? Give feedback.
-
According to @JohelEGP's helpful comment:
If Cpp2 accepts all keywords as identifiers with qualified names, and if Cpp2 would allow a way to have qualified names for local declarations (e.g. // `while` is not a keyword, because it's left-hand-side of `:`.
while: type = {
// `return` is not a keyword, because it's left-hand-side of `:`.
return: () = {}
}
main: () = {
// `do` is not a keyword, because it's left-hand-side of `:`.
// `do` is a local type.
do: type = { /* definition */ }
// `_::do` is a qualified name.
variable: _::do = /* definition */
// `for` is not a keyword, because it's left-hand-side of `:`.
// And `while` is an identifier.
for: ::while = ();
// `for` is an identifier becuase there is an operator dot.
// And `return` is an identifier too.
for.return();
// Also to clarify, `for` may be required to be quialified, but it's a little restrict.
_::for.return();
// `for` is a keyword, because there isn't any operator between `for` and `args`.
for args do (arg) { /* statements */ }
// `return` is not a keyword, because it's left-hand-side of `:`.
return: (param) -> ::while = ();
// AMBIGUOUS!
// When there is an ambiguous, they are keywords.
// So `return` is a keyword here.
return(/* something */);
// This `return` is not a keyword, because its name is qualified.
_::return(/* something */);
// `if` and `for` are not keywords, because there is an operator between them.
value: = if * for;
// `do` is not a keyword, because it's already a qualified name.
my_namespace::do();
} In this way, keywords would be fully contextual (except for EDITThis way has a problem if Cpp2 supports operator overloading for // This is AMBIGUOUS:
// Is `return` an object with `operator""`?
// Or is `return` a keyword and returns string `"something"`?
return "something";
// This is OK. `return` is an object with `operator""`.
_::return "something"; It is similar to how |
Beta Was this translation helpful? Give feedback.
-
To simplify the rule, maybe Cpp2 should require that every identifier to be qualified in which their name are equal to keywords: // `_::` must be omitted for naming declarations.
while: type = /* definition */
do: _::while = /* definition */
// `_::` must be omitted for accessing members with :: or dot.
// Because these are already qualified names.
_::do::type.as.forward;
_::return(args);
// OK. Keywords cannot be qualified names.
value: = _::if * _::for;
// `inspect` is not a keyword, because it's already a qualified name.
my_namespace::inspect(); So they must be always qualified either Instead of |
Beta Was this translation helpful? Give feedback.
-
Another option to consider is Types, functions and variables can be templates already. So if: (condition: bool, forward yes_value: int, forward no_value: int) -> forward int = {
/* Or force the template notation <> within declaration:
if: <> (condition: bool, forward yes_value: int, forward no_value: int) -> forward int = {
*/
if condition {
return yes_value;
}
else {
return no_value;
}
}
if: <T> (condition: bool, forward yes_value: T, forward no_value: T) -> forward T = {
if condition {
return yes_value;
}
else {
return no_value;
}
}
main: () = {
// if<> is not a keyword here.
x: = if<>(2 * 2 == 4, 1, 0);
// if<bool> is not a keyword here.
y: = if<bool>(2 * 2 == 4, true, false);
// if<> is not a keyword here.
z: = (2 * 2 == 4).if<>(1, 0);
} But keywords cannot be templates, so template arguments after keywords, mean they are not keywords. This requires empty template argument list as described in this bug. |
Beta Was this translation helpful? Give feedback.
-
Also it depends if Cpp2 would have similar Cpp1-style Or would Cpp2 have stand-alone if <something> { ... } That's suggested in this issue. |
Beta Was this translation helpful? Give feedback.
-
Well, I learned that I can treat a keyword as an identifier indirectly while reading Design note: Capture: if_name: = "if";
// Type "if"
if_name$: type = {
test: (this) = {
print("Something");
}
}
for_name: = "for";
// Function "for"
for_name$: () = {
print("Something");
}
// It creates an instance of type "if"
x: if_name$ = ();
// It creates an instance of type "if", and calls member function "test"
y: = if_name$().test();
// It calls function "for"
a: = for_name$(); But I don't know if the syntax is available outside code generation. |
Beta Was this translation helpful? Give feedback.
-
Why would this feature be desirable?
On 11 September 2023 14:33:53 Johel Ernesto Guerrero Peña ***@***.***> wrote:
I don't think that'll work.
It's the same as directly using the keyword as an identifier.
Because eventually the strings will be parsed as Cpp2.
—
Reply to this email directly, view it on GitHub<#642 (reply in thread)>, or unsubscribe<https://github.com/notifications/unsubscribe-auth/AALUZQOTS7DGWHJMSA7W5ATXZ4HLJANCNFSM6AAAAAA4S7N35I>.
You are receiving this because you are subscribed to this thread.Message ID: ***@***.***>
|
Beta Was this translation helpful? Give feedback.
-
The general language design technique is called stropping. Might be of interest to see how other languages have solved the problem. See link to wikipedia article. |
Beta Was this translation helpful? Give feedback.
-
tl;drThanks! Yes, I'll implement this... but not for Cpp1 compatibility (I don't think it's needed? Cpp2 is already 100% compatible with Cpp1 libraries), but rather from cross-language interop with other non-C++ languages. I don't think we need this feature for compatibility with Cpp1 code -- does anyone have counterexamples?Sorry if I missed it, but has anyone come up with an example of a need to turn a Cpp2 keyword into an identifier in order to use an existing Cpp1 library?
But I'm concerned about abuse of the proposed feature: It's not necessary, but would be actively harmful, to let people write Cpp1 reserved words like
But we do have prior art, that that prior art shows it's needed for compatibility with non-C++ codeAs I mentioned above, in C++/CLI we added this feature as The comparable use case will be to enable writing Cpp2 code that's compatible with libraries written in non-C++ languages, and I know that's coming, so I'll add the requested feature. For example, one of the planned uses of metafunctions is to use code generation to author a type in another language, say
SpellingMy current preference is to spell the escape hatch as Thanks! |
Beta Was this translation helpful? Give feedback.
-
Preface
I suggest to use
"keyword"$
syntax to treat keywords as identifiers in Cpp2.Suggestion Detail
Some identifiers in Cpp2 are keywords in Cpp1 such as
and
,or
, etc. These identifiers aren't valid identifiers in Cpp1. Therefore Cpp2 appendscpp2_
prefix to these identifiers during code generation for Cpp1 as discussed in this issue. For example identifiersand
,or
, etc in Cpp2 will respectively become identifierscpp2_and
,cpp2_or
, etc in generated Cpp1 code.On the other hand, some keywords in Cpp2 aren't keywords in Cpp1 such as
type
,next
, etc. These keywords are valid identifiers in Cpp1. Therefore it's not possible to use such identifiers in Cpp2 when dealing with Cpp1 API:I suggest to use a syntax such as
"keyword"$
to access identifiers from Cpp1 API in which they are keywords in Cpp2:I think syntax
"keyword"$
is good enough because Cpp2 will have similar syntax for reflections and code generations as described in this page of Wiki. And semantically this is related to them.Your Questions
Will your feature suggestion eliminate X% of security vulnerabilities of a given kind in current C++ code?
No.
Will your feature suggestion automate or eliminate X% of current C++ guidance literature?
No.
Considered Alternatives
I considered to use syntax
@keyword
but it would resemble meta-class functions. Another possible syntax is@"keyword"
, which doesn't resemble meta-class functions in addition to its difference from capture syntax.Also we can use a prefix such as
cpp1_
. For example:In this way,
cpp1_
prefix in addition tocpp2_
prefix should be reserved for Cpp2 compiler, and user-defined identifiers with those prefixes shouldn't be allowed.By the way, treating a keyword as an identifier, isn't frequency needed to dedicate a new symbol to it.
EDIT 1:
keyword<>
is another alternative solution as described in this comment.Beta Was this translation helpful? Give feedback.
All reactions