ooc-lang / rock

:ocean: self-hosted ooc compiler that generates c99
http://ooc-lang.org/
MIT License
401 stars 40 forks source link

Multiple '+' or '-' prefix operators in a row should be disallowed #982

Open alexnask opened 8 years ago

alexnask commented 8 years ago

Currently, using two '+'s or '-'s in a row causes rock to produce a postfix increment/decrement operator in the resulting C code.

Semantically, there is no reason in particular why it should be allowed anyways, it just causes confusion since ooc is a C family language but we have no increment/decrement operators.

marcusnaslund commented 8 years ago

I agree. If I remember correctly, ++variable works, but variable++ does not, which always confused me.

alexnask commented 8 years ago

Yeah, it works accidentally, it shouldn't.

I would highly advise you to go through your code and replace all instances it appears in, I will make it an error soon.

vendethiel commented 8 years ago

++variable is just semantically +(+(variable)), but is generating C code "++variable" because of no special-casing. Whereas I gather "variable++" simply doesn't parse?

marcusnaslund commented 8 years ago

I would highly advise you to go through your code and replace all instances it appears in, I will make it an error soon.

I was just about to. :)

alexnask commented 8 years ago

@vendethiel
Exactly, but I do think disallowing multiple prefix + and - operators is the way to go, as I said it would be really confusing otherwise, even if the generated code did not result in C's increment/decrement operators.

horasal commented 8 years ago

change the rule of unary operator to '+' !'+' works for me.

https://github.com/zhaihj/nagaqueen/commit/d14f181111f41481bc24c18470a99b78cf75db44

I'm trying to make the error message more clear

alexnask commented 8 years ago

Could be done with something like:

UNARY_PLUS  = '+' ('+' {  rewindWhiteSpace; throwError(...); })?
horasal commented 8 years ago

@shamanas I'm wondering why this doesn't work:

UNARY_PLUS = '+' (!'+') ~{ throwError( ); }
alexnask commented 8 years ago

I'm not too sure how ~ is implemented in greg, perhaps it can only be used after a match, so the ! here makes it useless?

I don't know, so I'm probably wrong though :)

fasterthanlime commented 8 years ago

I think @shamanas is right: (!'+') doesn't mean "Match something that isn't a plus", it means "stop matching if the character ahead is a plus" - so the rule probably doesn't match at all.

I think this was the right idea:

UNARY_PLUS = '+' ('+' { rewindWhiteSpace; throwError(...); })?

..except why can't it live in a separate PRE_INCREMENT / POST_INCREMENT rule? It might feel silly to actively look out for an operator we don't support, but that's the price to pay for having clear error messages, I guess.

alexnask commented 8 years ago

If it lived in a PRE_INCREMENT rule, we should do something like:

UnaryOp = (UNARY_PLUS | PRE_INCREMENT | .... ) expr: Access

Anyways right?
So we still actively look for the operator we don't support, just in the child rule.

To me, UNARY_PLUS = '+' ('+' { rewindWhiteSpace; throwError(...); })? reads like: match unary + operator exactly one time and error out if we find it more than once, feels natural.

Anyway, it's just a little trick for better error reporting, this can be fixed in better ways (but with bad error reporting :P)

fasterthanlime commented 8 years ago

If it lived in a PRE_INCREMENT rule, we should do something like (...)

not necessarily, you can have several rules that start with '+', as long as unary plus has a !'+' after the first plus is matches, the double-plus rules should kick in next.

(then again I haven't touched nagaqueen in a while)

alexnask commented 8 years ago

Sure, I don't disagree.
The point is, at some point or another, you will need to 'call' the double-plus rule so that error checking is done.
That means that no matter what you do, you will have some weird looking rule.
I personally prefer having the error checking in the UNARY_PLUS rule because I feel it makes it explicit that a chain of +s is not legal.
Another way would be to have a separate DISALLOW_PREFIX_INCREMENT, that is fine too imo.

Anyway, I think it's just a question of style, I don't lean in any direction too much :P