Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Same-depth blocks don't work #208

Closed
pjeby opened this issue May 24, 2013 · 13 comments
Closed

Same-depth blocks don't work #208

pjeby opened this issue May 24, 2013 · 13 comments

Comments

@pjeby
Copy link

pjeby commented May 24, 2013

In CoffeeScript 1.6.2, the following is valid code, compiling to an AMD module definition:

define 'aModule', ['dep1', 'dep2'], \
                   (dep1,   dep2) -> (``

foo = bar baz
if x
    y()
return spim()

)

In Redux 2.0.0.-beta5 (on the demo site), the above gives an error, even though the following compiles (albeit incorrectly):

define 'aModule', ['dep1', 'dep2'], (dep1, dep2) -> (\
foo = bar baz;
if x then y();
return spim();
)

Notice the added ';' terminators, the removed continuation line, the change from `` (as a null statement) to a continuation line, and the flattened if block.

Current CoffeeScript doesn't require each statement in a block like this to be explicitly delimited with semicolons, and doesn't treat continuation lines' leading whitespace as indentation.

Fiddling around with this, I found that various bits of syntax in 2.0.0-beta5 work strangely or not at all. For example, this:

if x then y();
spim()

correctly translates to:

if (x) {
  y();
}

spim();

in 1.6.2, but in 2.0.0-beta5, it translates to the (rather non-obvious):

// Generated by CoffeeScript 2.0.0-beta5
if (x) {
  y();
  spim();
}

CSR seems to be treating semicolon as a line continuation character, or really, a block continuation character.

Don't know if these changes are intentional, and the original behavior of CS 1.6 could be considered quirky as well, but it doesn't seem as though CSR is less quirky about these things, just quirky in a different way.

In particular, the treatment of backslash-continued lines as affecting the indent level is unexpected, as is the peculiar handling of ';'.

Any thoughts? "Don't do that" might be a reasonable response, except that IIUC one of the refactoring goals is to make it so you get compiler messages instead of having to just know what not to do. ;-)

@vendethiel
Copy link
Contributor

Blah, blah, whitespace significant isn't so tolerant in redux, and what have been said in all the other issues :p

@michaelficarra
Copy link
Owner

The line continuations with \ is a duplicate of #20.

The semicolon is being treated as a sequence operator internally in CSR, as it should have been in the original compiler. The only difference should be trailing semicolons in files. Semicolons were never meant to be stuck on the end of every line. Are you suggesting we shouldn't allow newlines to follow semicolons? I would be for that, but it may make some people unhappy. Though I guess it'd only affect those stick-a-semicolon-at-the-end-of-every-line-for-no-semantic-reason people.

@pjeby
Copy link
Author

pjeby commented May 25, 2013

The semicolon is being treated as a sequence operator internally in CSR, as it should have been in the original compiler.

Really? The CS docs say it's an optional statement terminator, not a sequence operator.

Are you suggesting we shouldn't allow newlines to follow semicolons?

Personally, I don't care about the semicolons part at all; that was just an attempt to see if there was a workaround for the semicolon-free syntax of my first example, that avoids having to have an entire module definition (i.e. an entire file) indented an extra level. (This is an pain in .litcoffee especially, since there's already an extra indent level.)

I also can't use a define( ... ) wrapper, because CSR evals JS literals instead of placing them inline... which seems like a nasty misfeature to me. If I didn't want to inject raw javascript, what good is `` syntax? (For example, I don't think eval'ing a yield statement is going to do much good.)

Of course, if CS and CSR ever implement <- syntax, that would be the obvious correct way to do what I'm trying to do, i.e.

(dep1, dep2) <- define ['dep1', 'dep2']
# rest of file goes here

But lacking that, I'm wondering if there is any other way of doing this available. Will CSR have any sort of non-indent block syntax?

Also, is there any document anywhere that summarizes all (or even some) of the backwards incompatible changes, such as backquote->eval, semicolon as sequence operator, etc.? Thanks!

@epidemian
Copy link

@pjeby, if you're interested, the change regarding the semicolon as an operator instead of a statement delimiter was discussed in #174. As it can be inferred from that discussion, i'm not in favour of that change either.

That being said, i think the first code snippet in this issue is quite a obscure hack. I wouldn't use that unless it's the last resort, and it would need to have an explanatory comment so readers of the code can understand what the hell is going on there (which would be so painful that i'd rather consider using other module system, like CommonJS, or adding a pre-processing step to the compilation 😝). So yeah, i don't think that example makes a good point for retaining that particular behaviour of the original compiler.

Now, the bit about the:

if x then y();
spim()

is very confusing IMO. I personally would expect that in order to have more than one statement in an in-line if one would need to use parentheses (i.e. if x then (y(); z()). But it kinda follows the same reasoning about the meaning of the semicolon.

There's however, an inconsistency with post-if form it seems. The normal if will eat all the semicolon-separated statements after it:

if isFriday() then haveCerelal(); catchBus()
# Compiles to:
# if (isFriday()) { haveCerelal(); catchBus(); }

But the post-if does not eat all semicolon-separated statements before it:

haveCerelal(); catchBus() if isFriday()
# Compiles to:
# haveCerelal(); if (isFriday()) catchBus();
# And i don't have enough money to have cereal every day...

Is this by design or is it a bug?

@michaelficarra
Copy link
Owner

@epidemian:

Is this by design or is it a bug?

I doubt the original compiler's precedence was by design. A lot of the precedence rules seem to have occurred simply by accident, and only the most egregious mistakes were later corrected. Try searching for "precedence" in the issues.

Implementing the same precedence rules in CSR was entirely by design. I wish we could change them now. Function application needs to be above infix operators.

@epidemian
Copy link

@michaelficarra, the discussion about precedence of infix operators vs function application is outside the scope of this issue i think.

However, i was asking about the behaviour in Redux. The difference i mentioned between normal if and post-if seems pretty unintuitive to me. In the original compiler the semicolon behaves as a statement delimiter, semantically equivalent to a newline, so the behaviour if a then b; c and a; b if c is pretty consistent IMO (the semicolon can be replaced by a newline and the meaning is preserved).

@michaelficarra
Copy link
Owner

@epidemian: Sorry, I wasn't trying to derail the issue, just lamenting. The CSR compilation of your examples is the same as jashkenas/coffee-script. Are you saying postfix and prefix if should have the same precedence relative to ;? I don't see why that would be expected.

@epidemian
Copy link

The CSR compilation of your examples is the same as jashkenas/coffee-script.

Ho, snap. That was a total brain fart from my part. I was under the impression that if a then b(); c() compiled to if (a) b(); c(); in the original compiler 😓

Well, i'll leave my comment there just to avoid rewriting the past, but it was totally wrong hehe.

@pjeby
Copy link
Author

pjeby commented May 25, 2013

I was under the impression that if a then b(); c() compiled to if (a) b(); c(); in the original compiler

No, but:

if a then b();
c();

does, unlike in CSR. CSR actually fails on this input, complaining about an unexpected end-of-input unless you either add more code or get rid of the semicolon.

CSR is treating ';' like a binary operator rather than an optional statement terminator. This strikes me as just plain wrong, if one goes by the CS docs, or an intuitive "CS is just JavaScript" reading of one's code.

But I see this has been raised already in the other issue. What worries me about the process there is that ISTM CSR is not really going to be CoffeeScript at all, but rather just another opinionated fork like all the other CS variants, with its own set of unique parsing quirks, rather than a CS with fewer parsing quirks.

Alas, maybe this is unavoidable due to CS's grammar being underspecified.

@michaelficarra
Copy link
Owner

CSR is not really going to be CoffeeScript at all, but rather just another opinionated fork like all the other CS variants

Not even close. Only the most underspecified and edge-case features have been changed/corrected (depending on your opinion of the change). I'll try to get together an exhaustive list of differences on the wiki soon.

Regarding the trailing semicolons: you've read the previous issues and are familiar with my stance on the issue. Let me remind you that the vim-coffee-script syntax file highlights trailing/unnecessary semicolons as errors. It did not do this without reason. Unnecessary semicolons have always been highly discouraged, to the point of being considered errors.

@pjeby
Copy link
Author

pjeby commented May 25, 2013

I'll try to get together an exhaustive list of differences on the wiki soon.

Thank you. That will help a lot with reducing my vague worries that CSR will quietly change semantics of existing code or barf on stuff that looks valid to the inexperienced and non-vim-using eye. ;-) (At one point I also saw a difference of interpretation of whitespace removal in multi-line strings between CS and CSR, so it'd be good to know how those are changing, too.)

It also occurred to me later that I might be worrying too much about upgrading anyway; I can always pin my projects to older versions of CS until there's a reason to upgrade them. I probably didn't think of that sooner, due to being still too accustomed to my toolsets for other languages... where tools are installed globally by default and upgraded whether you like the changes or not. ;-)

@michaelficarra
Copy link
Owner

At one point I also saw a difference of interpretation of whitespace removal in multi-line strings between CS and CS

Yeah, sorry about that. That bug re-appeared a couple of times due to insufficient tests. Single- and double-quoted strings, single- and double-quoted heredocs, and strings with interpolations all have distinct parse rules, so the bug kept getting half-fixed. It should be all good now.

@michaelficarra
Copy link
Owner

@pjeby: See https://github.com/michaelficarra/CoffeeScriptRedux/wiki/Intentional-Deviations-From-jashkenas-coffee-script. It's obviously not yet exhaustive, but it's a start.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants