January 01, 2009 Re: Non-nullable references, again | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Daniel Keep | On 2008-12-31 21:50:53 -0500, Daniel Keep <daniel.keep.lists@gmail.com> said: > Disclaimer: I'm not an expert on compilers. Plus, I just got up. :P > > The key is that the parser has to know what "MyClass" means before it can figure out what the "?" is for; that's why it's context-dependant. D avoids this dependency between compilation stages, because it complicates the compiler. When the parser sees "MyClass", it *doesn't know* that it's a type, so it can't distinguish between a nullable type and an invalid ?: expression. As far as I know, this can't be done with pointer declarations. Read this: a * b; Is it a multiplication or a declaration of a pointer to type "a"? You don't know until you resolve the identifiers. It's the exact same situation for using "?" to denote nullable. > At least, I think that's how it works; someone feel free to correct me if it's not. :P I belived the same for some time too, then found the above rebutal. -- Michel Fortin michel.fortin@michelf.com http://michelf.com/ | |||
January 01, 2009 Re: Non-nullable references, again | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Michel Fortin |
Michel Fortin wrote:
> On 2008-12-31 21:50:53 -0500, Daniel Keep <daniel.keep.lists@gmail.com> said:
>
>> Disclaimer: I'm not an expert on compilers. Plus, I just got up. :P
>>
>> The key is that the parser has to know what "MyClass" means before it can figure out what the "?" is for; that's why it's context-dependant. D avoids this dependency between compilation stages, because it complicates the compiler. When the parser sees "MyClass", it *doesn't know* that it's a type, so it can't distinguish between a nullable type and an invalid ?: expression.
>
> As far as I know, this can't be done with pointer declarations. Read this:
>
> a * b;
>
> Is it a multiplication or a declaration of a pointer to type "a"? You don't know until you resolve the identifiers. It's the exact same situation for using "?" to denote nullable.
>
>
>> At least, I think that's how it works; someone feel free to correct me if it's not. :P
>
> I belived the same for some time too, then found the above rebutal.
I don't think so; I believe that unary vs. binary operators are unambiguous. "a * b" is "a multiply b" because it's "(expr) * (expr)". It's pointer dereference when it's "* (expr)".
I keep in mind is that "(expr) < (expr) >" is ambiguous, but "* (expr)" isn't.
Like I said, I'm not an expert, so take what I say with a grain of salt.
-- Daniel
| |||
January 01, 2009 Re: Non-nullable references, again | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Daniel Keep | Daniel Keep wrote:
>
>
> Michel Fortin wrote:
>> On 2008-12-31 21:50:53 -0500, Daniel Keep <daniel.keep.lists@gmail.com> said:
>>
>>> Disclaimer: I'm not an expert on compilers. Plus, I just got up. :P
>>>
>>> The key is that the parser has to know what "MyClass" means before it can figure out what the "?" is for; that's why it's context-dependant. D avoids this dependency between compilation stages, because it complicates the compiler. When the parser sees "MyClass", it *doesn't know* that it's a type, so it can't distinguish between a nullable type and an invalid ?: expression.
>>
>> As far as I know, this can't be done with pointer declarations. Read this:
>>
>> a * b;
>>
>> Is it a multiplication or a declaration of a pointer to type "a"? You don't know until you resolve the identifiers. It's the exact same situation for using "?" to denote nullable.
>>
>>
>>> At least, I think that's how it works; someone feel free to correct me if it's not. :P
>>
>> I belived the same for some time too, then found the above rebutal.
>
> I don't think so; I believe that unary vs. binary operators are unambiguous. "a * b" is "a multiply b" because it's "(expr) * (expr)". It's pointer dereference when it's "* (expr)".
>
> I keep in mind is that "(expr) < (expr) >" is ambiguous, but "* (expr)" isn't.
>
> Like I said, I'm not an expert, so take what I say with a grain of salt.
>
> -- Daniel
>
It's about a pointer declaration, not a pointer dereference, a la "int * p;"
Happy New Year everyone!
Andrei
| |||
January 02, 2009 Re: Non-nullable references, again | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Daniel Keep | Daniel Keep wrote:
> Benji Smith wrote:
>> Don wrote:
>>> Denis Koroskin wrote:
>>>> Foo nonNull = new Foo();
>>>> Foo? possiblyNull = null;
>> >
>>> Wouldn't this cause ambiguity with the "?:" operator?
>>
>> At first, thought you might be right, and that there would some ambiguity calling constructors of nullable classes (especially given optional parentheses).
>>
>> But for the life of me, I couldn't come up with a truly ambiguous example, that couldn't be resolved with an extra token or two of lookahead.
>>
>> The '?' nullable-type operator is only used in type declarations, not in expressions, and the '?:' operator always consumes a few trailing expressions.
>>
>> Also (at least in C#) the null-coalesce operator (which converts nullable objects to either a non-null instance or a default value) looks like this:
>>
>> MyClass? myNullableObj = getNullableFromSomewhere();
>> MyClass myNonNullObj = myNullableObj ?? DEFAULT_VALUE;
>>
>> Since the double-hook is a single token, it's also unambiguous to parse.
>>
>> --benji
>
> Disclaimer: I'm not an expert on compilers. Plus, I just got up. :P
>
> The key is that the parser has to know what "MyClass" means before it can figure out what the "?" is for; that's why it's context-dependant. D avoids this dependency between compilation stages, because it complicates the compiler. When the parser sees "MyClass", it *doesn't know* that it's a type, so it can't distinguish between a nullable type and an invalid ?: expression.
>
> At least, I think that's how it works; someone feel free to correct me if it's not. :P
>
> -- Daniel
I could be wrong too. I've done a fair bit of this stuff, but I'm no expert either :)
Nevertheless, I still don't think there's any ambiguity, as long as the parser can perform syntactic lookahead predicates. The grammar would look something like this:
DECLARATION :=
IDENTIFIER // Type name
( HOOK )? // Is nullable?
IDENTIFIER // Var name
(
SEMICOLON // End of declaration
|
(
OP_ASSIGN // Assignment operator
EXPRESSION // Assigned value
)
)
Whereas the ternary expression grammar would look something like this:
TERNARY_EXPRESSION :=
IDENTIFIER // Type name
HOOK // Start of '?:' operator
EXPRESSION // Value if true
COLON // End of '?:' operator
EXPRESSION // Value if false
The only potential ambiguity arises because the "value if true" expression could also just be an identifier. But if the parser can construct syntactic predicates to perform LL(k) lookahead with arbitrary k, then it can just keep consuming tokens until it finds either a SEMICOLON, an OP_ASSIGN, or a COLON (potentially, recursively, if it encounters another identifier and hook within the expression).
Still, though, once it finds one of those tokens, the syntax has been successfully disambiguated, without resorting to a semantic predicate.
It requires arbitrary lookahead, but it can be done within a context-free grammar, and all within the syntax-processing portion of the parser.
Of course, I could be completely wrong too :)
--benji
| |||
January 02, 2009 Re: Non-nullable references, again | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Benji Smith | Benji Smith wrote:
> Daniel Keep wrote:
>> Benji Smith wrote:
>>> Don wrote:
>>>> Denis Koroskin wrote:
>>>>> Foo nonNull = new Foo();
>>>>> Foo? possiblyNull = null;
>>> >
>>>> Wouldn't this cause ambiguity with the "?:" operator?
>>>
>>> At first, thought you might be right, and that there would some ambiguity calling constructors of nullable classes (especially given optional parentheses).
>>>
>>> But for the life of me, I couldn't come up with a truly ambiguous example, that couldn't be resolved with an extra token or two of lookahead.
>>>
>>> The '?' nullable-type operator is only used in type declarations, not in expressions, and the '?:' operator always consumes a few trailing expressions.
>>>
>>> Also (at least in C#) the null-coalesce operator (which converts nullable objects to either a non-null instance or a default value) looks like this:
>>>
>>> MyClass? myNullableObj = getNullableFromSomewhere();
>>> MyClass myNonNullObj = myNullableObj ?? DEFAULT_VALUE;
>>>
>>> Since the double-hook is a single token, it's also unambiguous to parse.
>>>
>>> --benji
>>
>> Disclaimer: I'm not an expert on compilers. Plus, I just got up. :P
>>
>> The key is that the parser has to know what "MyClass" means before it can figure out what the "?" is for; that's why it's context-dependant. D avoids this dependency between compilation stages, because it complicates the compiler. When the parser sees "MyClass", it *doesn't know* that it's a type, so it can't distinguish between a nullable type and an invalid ?: expression.
>>
>> At least, I think that's how it works; someone feel free to correct me if it's not. :P
>>
>> -- Daniel
>
> I could be wrong too. I've done a fair bit of this stuff, but I'm no expert either :)
>
> Nevertheless, I still don't think there's any ambiguity, as long as the parser can perform syntactic lookahead predicates. The grammar would look something like this:
>
> DECLARATION :=
> IDENTIFIER // Type name
> ( HOOK )? // Is nullable?
> IDENTIFIER // Var name
> (
> SEMICOLON // End of declaration
> |
> (
> OP_ASSIGN // Assignment operator
> EXPRESSION // Assigned value
> )
> )
>
> Whereas the ternary expression grammar would look something like this:
>
> TERNARY_EXPRESSION :=
> IDENTIFIER // Type name
> HOOK // Start of '?:' operator
> EXPRESSION // Value if true
> COLON // End of '?:' operator
> EXPRESSION // Value if false
>
> The only potential ambiguity arises because the "value if true" expression could also just be an identifier. But if the parser can construct syntactic predicates to perform LL(k) lookahead with arbitrary k, then it can just keep consuming tokens until it finds either a SEMICOLON, an OP_ASSIGN, or a COLON (potentially, recursively, if it encounters another identifier and hook within the expression).
>
> Still, though, once it finds one of those tokens, the syntax has been successfully disambiguated, without resorting to a semantic predicate.
>
> It requires arbitrary lookahead, but it can be done within a context-free grammar, and all within the syntax-processing portion of the parser.
>
> Of course, I could be completely wrong too :)
>
> --benji
case a?.b:c:
break;
is this
case ((a?).b):
c:
break;
or is it
case (a ? b : c ) :
break;
| |||
January 02, 2009 Re: Non-nullable references, again | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Don | Don wrote:
> Benji Smith wrote:
>> Daniel Keep wrote:
>>> Benji Smith wrote:
>>>> Don wrote:
>>>>> Denis Koroskin wrote:
>>>>>> Foo nonNull = new Foo();
>>>>>> Foo? possiblyNull = null;
>>>> >
>>>>> Wouldn't this cause ambiguity with the "?:" operator?
>>>>
>>>> At first, thought you might be right, and that there would some ambiguity calling constructors of nullable classes (especially given optional parentheses).
>>>>
>>>> But for the life of me, I couldn't come up with a truly ambiguous example, that couldn't be resolved with an extra token or two of lookahead.
>>>>
>>>> The '?' nullable-type operator is only used in type declarations, not in expressions, and the '?:' operator always consumes a few trailing expressions.
>>>>
>>>> Also (at least in C#) the null-coalesce operator (which converts nullable objects to either a non-null instance or a default value) looks like this:
>>>>
>>>> MyClass? myNullableObj = getNullableFromSomewhere();
>>>> MyClass myNonNullObj = myNullableObj ?? DEFAULT_VALUE;
>>>>
>>>> Since the double-hook is a single token, it's also unambiguous to parse.
>>>>
>>>> --benji
>>>
>>> Disclaimer: I'm not an expert on compilers. Plus, I just got up. :P
>>>
>>> The key is that the parser has to know what "MyClass" means before it can figure out what the "?" is for; that's why it's context-dependant. D avoids this dependency between compilation stages, because it complicates the compiler. When the parser sees "MyClass", it *doesn't know* that it's a type, so it can't distinguish between a nullable type and an invalid ?: expression.
>>>
>>> At least, I think that's how it works; someone feel free to correct me if it's not. :P
>>>
>>> -- Daniel
>>
>> I could be wrong too. I've done a fair bit of this stuff, but I'm no expert either :)
>>
>> Nevertheless, I still don't think there's any ambiguity, as long as the parser can perform syntactic lookahead predicates. The grammar would look something like this:
>>
>> DECLARATION :=
>> IDENTIFIER // Type name
>> ( HOOK )? // Is nullable?
>> IDENTIFIER // Var name
>> (
>> SEMICOLON // End of declaration
>> |
>> (
>> OP_ASSIGN // Assignment operator
>> EXPRESSION // Assigned value
>> )
>> )
>>
>> Whereas the ternary expression grammar would look something like this:
>>
>> TERNARY_EXPRESSION :=
>> IDENTIFIER // Type name
>> HOOK // Start of '?:' operator
>> EXPRESSION // Value if true
>> COLON // End of '?:' operator
>> EXPRESSION // Value if false
>>
>> The only potential ambiguity arises because the "value if true" expression could also just be an identifier. But if the parser can construct syntactic predicates to perform LL(k) lookahead with arbitrary k, then it can just keep consuming tokens until it finds either a SEMICOLON, an OP_ASSIGN, or a COLON (potentially, recursively, if it encounters another identifier and hook within the expression).
>>
>> Still, though, once it finds one of those tokens, the syntax has been successfully disambiguated, without resorting to a semantic predicate.
>>
>> It requires arbitrary lookahead, but it can be done within a context-free grammar, and all within the syntax-processing portion of the parser.
>>
>> Of course, I could be completely wrong too :)
>>
>> --benji
>
> case a?.b:c:
> break;
>
> is this
>
> case ((a?).b):
> c:
> break;
>
> or is it
>
> case (a ? b : c ) :
> break;
>
Damn. I got so distracted with the ternary operator, I forgot about case statements.
--benji
| |||
January 03, 2009 Re: Non-nullable references, again | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Benji Smith | On 2009-01-02 10:37:50 -0500, Benji Smith <dlanguage@benjismith.net> said: >> case a?.b:c: >> break; >> >> is this >> >> case ((a?).b): >> c: >> break; >> >> or is it >> >> case (a ? b : c ) : >> break; How's this different from case a*.b: is this: case ((a*).b): or is it: case ((a) * (.b)): -- Michel Fortin michel.fortin@michelf.com http://michelf.com/ | |||
January 03, 2009 Re: Non-nullable references, again | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Michel Fortin | On Fri, Jan 2, 2009 at 8:35 PM, Michel Fortin <michel.fortin@michelf.com> wrote:
>
> How's this different from
>
> case a*.b:
>
> is this:
>
> case ((a*).b):
>
> or is it:
>
> case ((a) * (.b)):
What the heck is ((a*).b)? * is not a postfix operator.
| |||
January 03, 2009 Re: Non-nullable references, again | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Michel Fortin | Michel Fortin wrote:
> On 2009-01-02 10:37:50 -0500, Benji Smith <dlanguage@benjismith.net> said:
>
>>> case a?.b:c:
>>> break;
>>>
>>> is this
>>>
>>> case ((a?).b):
>>> c:
>>> break;
>>>
>>> or is it
>>>
>>> case (a ? b : c ) :
>>> break;
>
> How's this different from
>
> case a*.b:
>
> is this:
>
> case ((a*).b):
>
> or is it:
>
> case ((a) * (.b)):
>
>
Think of it like this:
MyClass?.myProperty
It's a static field of the nullable MyClass type.
--benji
| |||
January 03, 2009 Re: Non-nullable references, again | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Benji Smith | On 2009-01-02 21:39:52 -0500, Benji Smith <dlanguage@benjismith.net> said: > Think of it like this: > > MyClass?.myProperty > > It's a static field of the nullable MyClass type. Just like: MyStruct*.myProperty It's a static field of the struct for which you have a pointer to. Exact that for it to compile, you need to write: (MyStruct*).myProperty I propose we do things the same way for "?". -- Michel Fortin michel.fortin@michelf.com http://michelf.com/ | |||
Copyright © 1999-2021 by the D Language Foundation
Permalink
Reply