one more restriction for from __future__ import ...

I would like to add another restriction: A future_statement must appear on a line by itself. It is not legal to combine a future_statement without any other statement using a semicolon. It would be a bear to implement error handling for cases like this: from __future__ import a; import b; from __future__ import c Jeremy

Really?!? Why? Isn't it straightforward to check that everything you encounter in a left-to-right leaf scan of the parse tree is either a future statement or a docstring until you encounter a non-future? --Guido van Rossum (home page: http://www.python.org/~guido/)

"GvR" == Guido van Rossum <guido@digicool.com> writes:
GvR> Really?!? Why? Isn't it straightforward to check that GvR> everything you encounter in a left-to-right leaf scan of the GvR> parse tree is either a future statement or a docstring until GvR> you encounter a non-future? It's not hard to find legal future statements. It's hard to find illegal ones. The pass to find future statements exits as soon as it finds something that isn't a doc string or a future. The symbol table pass detects illegal future statements by comparing the current line number against the line number of the last legal futre statement. If a mixture of legal and illegal future statements occurs on the same line, that test fails. If I want to be more precise, I can think of a couple of ways to figure out if a particular future statement occurs after the first non-import statement. Neither is particularly pretty because the parse tree is so deep by the time you get to the import statement. One possibility is to record the index of each small_stmt that occurs as a child of a simple_stmt in the symbol table. The future statement pass can record the offset of the first non-legal small_stmt when it occurs as part of an extend simple_stmt. The symbol table would also need to record the current index of each small_stmt. To implement this, I've got to touch a lot of code. The other possibility is to record the address for the first statement following the last legal future statement. The symbol table pass could test each node it visits and set a flag when this node is visited a second time. Any future statement found when the flag is set is an error. I'm concerned that it will be difficult to guarantee that this node is always checked, because the loop that walks the tree frequently dispatches to helper functions. I think each helper function would need to test. Do you have any other ideas? I haven't though about this for more than 20 minutes and was hoping to avoid more time invested on the matter. If it's a problem for Jython, though, we'll need to figure something out. Perhaps the effect of multiple future statements on a single line could be undefined, which would allow Python to raise an error and Jython to ignore the error. Not ideal, but expedient. Jeremy

Jeremy> The symbol table pass detects illegal future statements by Jeremy> comparing the current line number against the line number of the Jeremy> last legal futre statement. Why not just add a flag (default false at the start of the compilation) to the compiling struct that tells you if you've seen a future-killer statement already? Then if you see a future statement the compiler can whine. Skip

"SM" == Skip Montanaro <skip@mojam.com> writes:
Jeremy> The symbol table pass detects illegal future statements by Jeremy> comparing the current line number against the line number of Jeremy> the last legal futre statement. SM> Why not just add a flag (default false at the start of the SM> compilation) to the compiling struct that tells you if you've SM> seen a future-killer statement already? Then if you see a SM> future statement the compiler can whine. Almost everything is a future-killer statement, only doc strings and other future statements are allowed. I would have to add a st->st_future_killed = 1 for almost every node type. There are also a number of nodes (about ten) that can contain future statements or doc strings or future killers. As a result, I'd have to add special cases for them, too. Jeremy

The pass to find future statements exits as soon as it finds something that isn't a doc string or a future.
Well, don't do that, then. Have the find_future_statements pass keep going and look for *illegal* future statements as well. Then, subsequent passes can just ignore any import that looks like a future statement, because it will already have been either processed or reported as an error. Greg Ewing, Computer Science Dept, +--------------------------------------+ University of Canterbury, | A citizen of NewZealandCorp, a | Christchurch, New Zealand | wholly-owned subsidiary of USA Inc. | greg@cosc.canterbury.ac.nz +--------------------------------------+

"GE" == Greg Ewing <greg@cosc.canterbury.ac.nz> writes:
The pass to find future statements exits as soon as it finds something that isn't a doc string or a future.
GE> Well, don't do that, then. Have the find_future_statements pass GE> keep going and look for *illegal* future statements as well. GE> Then, subsequent passes can just ignore any import that looks GE> like a future statement, because it will already have been GE> either processed or reported as an error. I like this idea best so far. Jeremy

Aha. That's what I missed -- comparison by line number. One thing you could do would simply be check the entire current simple_statement, which would catch the above example; the possibilities are limited at that level (no blocks can start on the same line after an import). --Guido van Rossum (home page: http://www.python.org/~guido/)

Really?!? Why? Isn't it straightforward to check that everything you encounter in a left-to-right leaf scan of the parse tree is either a future statement or a docstring until you encounter a non-future? --Guido van Rossum (home page: http://www.python.org/~guido/)

"GvR" == Guido van Rossum <guido@digicool.com> writes:
GvR> Really?!? Why? Isn't it straightforward to check that GvR> everything you encounter in a left-to-right leaf scan of the GvR> parse tree is either a future statement or a docstring until GvR> you encounter a non-future? It's not hard to find legal future statements. It's hard to find illegal ones. The pass to find future statements exits as soon as it finds something that isn't a doc string or a future. The symbol table pass detects illegal future statements by comparing the current line number against the line number of the last legal futre statement. If a mixture of legal and illegal future statements occurs on the same line, that test fails. If I want to be more precise, I can think of a couple of ways to figure out if a particular future statement occurs after the first non-import statement. Neither is particularly pretty because the parse tree is so deep by the time you get to the import statement. One possibility is to record the index of each small_stmt that occurs as a child of a simple_stmt in the symbol table. The future statement pass can record the offset of the first non-legal small_stmt when it occurs as part of an extend simple_stmt. The symbol table would also need to record the current index of each small_stmt. To implement this, I've got to touch a lot of code. The other possibility is to record the address for the first statement following the last legal future statement. The symbol table pass could test each node it visits and set a flag when this node is visited a second time. Any future statement found when the flag is set is an error. I'm concerned that it will be difficult to guarantee that this node is always checked, because the loop that walks the tree frequently dispatches to helper functions. I think each helper function would need to test. Do you have any other ideas? I haven't though about this for more than 20 minutes and was hoping to avoid more time invested on the matter. If it's a problem for Jython, though, we'll need to figure something out. Perhaps the effect of multiple future statements on a single line could be undefined, which would allow Python to raise an error and Jython to ignore the error. Not ideal, but expedient. Jeremy

Jeremy> The symbol table pass detects illegal future statements by Jeremy> comparing the current line number against the line number of the Jeremy> last legal futre statement. Why not just add a flag (default false at the start of the compilation) to the compiling struct that tells you if you've seen a future-killer statement already? Then if you see a future statement the compiler can whine. Skip

"SM" == Skip Montanaro <skip@mojam.com> writes:
Jeremy> The symbol table pass detects illegal future statements by Jeremy> comparing the current line number against the line number of Jeremy> the last legal futre statement. SM> Why not just add a flag (default false at the start of the SM> compilation) to the compiling struct that tells you if you've SM> seen a future-killer statement already? Then if you see a SM> future statement the compiler can whine. Almost everything is a future-killer statement, only doc strings and other future statements are allowed. I would have to add a st->st_future_killed = 1 for almost every node type. There are also a number of nodes (about ten) that can contain future statements or doc strings or future killers. As a result, I'd have to add special cases for them, too. Jeremy

The pass to find future statements exits as soon as it finds something that isn't a doc string or a future.
Well, don't do that, then. Have the find_future_statements pass keep going and look for *illegal* future statements as well. Then, subsequent passes can just ignore any import that looks like a future statement, because it will already have been either processed or reported as an error. Greg Ewing, Computer Science Dept, +--------------------------------------+ University of Canterbury, | A citizen of NewZealandCorp, a | Christchurch, New Zealand | wholly-owned subsidiary of USA Inc. | greg@cosc.canterbury.ac.nz +--------------------------------------+

"GE" == Greg Ewing <greg@cosc.canterbury.ac.nz> writes:
The pass to find future statements exits as soon as it finds something that isn't a doc string or a future.
GE> Well, don't do that, then. Have the find_future_statements pass GE> keep going and look for *illegal* future statements as well. GE> Then, subsequent passes can just ignore any import that looks GE> like a future statement, because it will already have been GE> either processed or reported as an error. I like this idea best so far. Jeremy

Aha. That's what I missed -- comparison by line number. One thing you could do would simply be check the entire current simple_statement, which would catch the above example; the possibilities are limited at that level (no blocks can start on the same line after an import). --Guido van Rossum (home page: http://www.python.org/~guido/)
participants (4)
-
Greg Ewing
-
Guido van Rossum
-
Jeremy Hylton
-
Skip Montanaro