[Python-ideas] In call grammar, replace primary with possible_call? (was Re: ...quote followed by a left parenthesis...?)

Terry Reedy tjreedy at udel.edu
Fri Jul 17 00:27:34 CEST 2015

On 7/16/2015 7:32 AM, Andrew Barnert via Python-ideas wrote:
> On Jul 15, 2015, at 16:03, Terry Reedy <tjreedy at udel.edu> wrote:
>> So here is the proposal: in the call definition, change primary to
possible_call, where
>>   possible_call ::= identifier | parenth_form | yield_atom
>>                     | attributeref | subscription | slicing | call
> It would be fun to explain why [1,2]() is a syntax error but (1,2)() a runtime type error, and likewise for ""() vs ("")()...

Because parenthesis forms hide their contents from surrounding code. 
That is their purpose.  In the examples above, where the content is a 
single object, there is no effect on the resulting ast.

> Anyway, I honestly still don't get the motivation here.

Given that I switched from C to Python 18 years ago, I am obviously 
comfortable with runtime typing.  However, I consider the delay in error 
detection to be a cost, not a feature.  Unnoticed runtime errors 
sometimes sit for days to years. Earlier *is* better. The 
more-than-compensating benefit of dynamic typing is being able to write 
generic code and have user class instances participate in syntax on the 
same basic as with builtin classes.

 > What makes this kind of type error so special that it should be
 > caught at compile time?

'SyntaxError' is defined by the grammar + a few extra compile-time 
checks.  There are actually two versions of the grammar -- the one in 
the docs and the one actually used for the parser. If the grammars are 
tweaked to better define possibly_callable, then the invalid token 
sequences will be redefined as SyntaxErrors.

The boundary between SyntaxError and runtime errors is somewhat 
arbitrary. On the other hand, one might argue that once the boundary is 
set, it should not change lest code be broken.  Example of something 
that runs now and would not with the change.

print 1
if False: ''()

I am not sure that we have never moved the boundary, but it should be 
rare.  Since the disallowed forms are literals and displays, I cannot 
think of sensible running code that that would be broken by this 
proposal.  But the above might be enough to scuttle the idea.

We don't expect [1,2]['spam'] to fail to compile; what makes this different?

The compiler has a constant folder to optimize code.  I currently does 
tuple subscriptions.

 >>> from dis import dis
 >>> dis('(1,2)[0]')
   1           0 LOAD_CONST               4 (1)
               3 RETURN_VALUE
 >>> dis('(1,2)[1]')
   1           0 LOAD_CONST               3 (2)
               3 RETURN_VALUE
 >>> dis('(1,2)[2]')
   1           0 LOAD_CONST               2 ((1, 2))
               3 LOAD_CONST               1 (2)
               6 BINARY_SUBSCR
               7 RETURN_VALUE

It must be that the folder discovers the error, but rather than raise 
immediately, it puts the 'rotten fish' back in the stream to raise a 
stink when encountered. I started Python with -Wall and entered the code 
itself and no SyntaxWarning was issued.  Given that the error has been 
detected, but might sit silently for awhile, this seems like a shame.

'Constant' lists are not checked. They are too rare to bother checking 
for them.
 >>> dis('[1,2][0]')
   1           0 LOAD_CONST               0 (1)
               3 LOAD_CONST               1 (2)
               6 BUILD_LIST               2
               9 LOAD_CONST               2 (0)
              12 BINARY_SUBSCR
              13 RETURN_VALUE

It's a lot simpler to say you can try to call any primary,

'primary' is vague and to me way overly broad. When expanded to basic 
nonterminals, about half are never callable. Adding one production rule 
is a minor change. Leaving error detection aside, a benefit for readers 
would be to better define what is actually a possible callable.  Of 
course, this could be done with a new sentence in the doc without 
changing the grammer.  Maybe this should be the outcome of this issue.

Another arguments against the proposal is that code checkers should also 
be able to detect such non-callable primaries.

Terry Jan Reedy

More information about the Python-ideas mailing list