-
-
Notifications
You must be signed in to change notification settings - Fork 41
Conversation
src/printer/index.js
Outdated
return concat(path.map(printElseBody, "orelse")); | ||
} | ||
return concat([ | ||
hardline, | ||
"else:", | ||
concat(path.map(printElseBody, "orelse")) | ||
indent(concat(path.map(printElseBody, "orelse"))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just don't use printElseBody
here and you should be good. You only need special-case handling for the elif
case.
I will say that both this and the multi- The Python AST has a much looser mapping to the tokens than the JS AST does. The following pieces of code are not just equivalent – they're actually syntactically identical: if foo:
foo()
elif bar:
bar()
else:
baz()
if foo:
foo()
else:
if bar:
bar()
else:
baz() The same is not true of the analogous code in JS. Fortunately asttokens means we do actually have the token information available here. |
Calling it "fucked up" is a bit much, though. It's an AST. It doesn't have to reflect all the syntactic sugar used in the code. |
@taion thanks for that I noticed it as well, anyway, before seeing your comment I've tried a different approach, can you have a look at the code now? :) I've tested with your example code and it prints always the same: if foo:
foo()
elif bar:
bar()
else:
baz() I'm not sure if we should change this :) |
@@ -189,10 +150,29 @@ function printIf(path, print) { | |||
indent(concat([hardline, printBody(path, print)])) | |||
]; | |||
|
|||
const orElse = printOrElse(path); | |||
while (n.orelse && n.orelse.length === 1 && n.orelse[0].ast_type === "If") { | |||
n = n.orelse[0]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe just something like:
parts.push(concat(path.map(printElif, 'orelse')));
and then have printElif
deal with this if
clause, or even like a printIfBodyAndOrElse
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure I'm understanding what you mean here
if (n.orelse && n.orelse.length > 0) { | ||
parts.push(hardline, "else:"); | ||
|
||
for (let i = 0; i < n.orelse.length; i++) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can't you just do
parts.push(indent(concat(path.map(print, 'orelse'))));
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
for some reason it doesn't work, it is like it is missing the indent
call:
if foo:
foo()
elif bar:
bar()
else:baz()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you need the hardline
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are we doing a manual for
loop here rather than just re-using our printBody
function, like we do the other times in this function?
I opened #22 to track some of these ambiguities. I don't think I've ever intentionally written an |
@taion thanks for that, pretty helpful! I'll have a look at your comments soon (I'm running out of battery) |
@FuegoFro would mind having a look at this one? I think your input will be super helpful :) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree that this is a super interesting problem and a look at how Python's AST handles this! I made some suggestions inline :) The main concern I have is that this is going to morph the code into something that's syntactically different but parses/desugars to the same AST.
if bar: | ||
bar() | ||
if baz: | ||
baz() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It'd be great to see some tests that have elif
in them! Maybe something like
if foo:
foo()
elif bar:
bar()
else:
if baz:
baz()
elif garply:
garply()
else:
qux()
Maybe also a simple case like:
if a:
a()
else:
if b:
b()
My guess is that to make the above cases work (and not, for instance, collapse the end of the second case into elif b
) we're going to need to modify the printer function to use n.source
(probably looking at what it starts with) to determine if the orelse
is an else
or elif
.
if (n.orelse && n.orelse.length > 0) { | ||
parts.push(hardline, "else:"); | ||
|
||
for (let i = 0; i < n.orelse.length; i++) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are we doing a manual for
loop here rather than just re-using our printBody
function, like we do the other times in this function?
@@ -189,10 +150,29 @@ function printIf(path, print) { | |||
indent(concat([hardline, printBody(path, print)])) | |||
]; | |||
|
|||
const orElse = printOrElse(path); | |||
while (n.orelse && n.orelse.length === 1 && n.orelse[0].ast_type === "If") { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: wouldn't hurt to have a comment or two in here :) Maybe something along the lines of this?
# "Handle the nested `elif`, which are represented as `else: if...` in the AST."
Up to you though :)
@@ -189,10 +150,29 @@ function printIf(path, print) { | |||
indent(concat([hardline, printBody(path, print)])) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: If you wanted, you could update this function to use the indentConcat
function, which reduces the number of parens you need :D
Closing in favour of #85 |
Currently transforms this:
to this, which is broken:
Almost there :)