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

[BUG] Arithmetic operation fails #319

Closed
msadeqhe opened this issue Apr 4, 2023 · 6 comments
Closed

[BUG] Arithmetic operation fails #319

msadeqhe opened this issue Apr 4, 2023 · 6 comments
Labels
bug Something isn't working

Comments

@msadeqhe
Copy link

msadeqhe commented Apr 4, 2023

It is the example code:

main: () = {
    x := 2*2;
}

It should generate the following C++1 code:

auto main() -> int{
    auto x {2 * 2}; 
}

But C++2 compiler outputs the following error message:

error: postfix unary * (dereference) cannot be immediately followed by a (, identifier, or literal - add whitespace before * here if you meant binary * (multiplication)

On the other hand, 2+2 works, also 2 * 2 (with white-spaces around * operator) works. The reason of this bug seems to be that * operator can be both unary postfix and binary. I think it's related to this issue.

@msadeqhe msadeqhe added the bug Something isn't working label Apr 4, 2023
@JohelEGP
Copy link
Contributor

JohelEGP commented Apr 4, 2023

According to https://github.com/hsutter/cppfront/wiki/Design-note%3A-Postfix-operators, it should work:

additionally, as a convenience, cases like x**y mean the same as x* * y since they can't mean anything else, which is convenient so we can still write things like a*b and a*2 conveniently with the obvious meaning.

@msadeqhe
Copy link
Author

msadeqhe commented Apr 4, 2023

I think that's because the behaviour is changed after this commit.

@AbhinavK00
Copy link

One way could be to completely rethink the operator symbols (it's a very small space) and come up with something unambigious. Something that'd solve both this issue and #304 .

@msadeqhe
Copy link
Author

msadeqhe commented Apr 4, 2023

Using and, or and not keywords instead of &&, || and !, seems reasonable to solve the issue with & operator, but it doesn't solve the issue with * operator.

To solve this issue, if there is unary postfix operators side-by-side a binary operator, and if the last unary postfix operator's symbol is the same as the binary operator's symbol, then there should be a white-space between them, otherwise white-space is not necessary. Also this can be true for unary prefix operators, therefore imagine if C++2 had unary prefix * in addition to unary postfix * and binary *, then:

a0 := x***y; // ERROR!
b0 := x* * *y; // OK, but if C++2 had unary prefix `*`.
c0 := x-- - -y; // OK.

// Here whitespace isn't required.
// := (x--)*(-y);
a1 := x--*-y; // OK.
b1 := 2*2; // It will work too.

@AbhinavK00
Copy link

AbhinavK00 commented Apr 4, 2023

I was thinking using keywords like and, or and xor instead of &, | and ^ and then using ^ for pointer deref. There was some issue where I proposed a function addr for taking address of a variable as it's not as common as derefs. That'd leave us with something like this

// unary operations except dereferencing
+a;
-a;
a++;
b++;
b~;
!a;

//arithmetic operations
a+b;   
a-b;
a*b;
a/b;
a%b;

//bitwise operations
a and b;
a or b;
a xor b;
a shl b;
a shr b;

//logical operations
a&&b;
a||b;
!a;

//taking address
a.addr();  //similar to ssize()

//pointer deref
a^;
b^^;
c : ^_ = k.addr();

I don't really like spelling-out bitwise operators but that's one feasible approach.

But I have a question, isn't this a problem with transpiler because other compilers can tell the difference somehow? Or is this because of context-free grammar?

Edit: Added shift operators to example code
Edit: Added unary operators too
Edit: Another option

//will only write things that change here

//bitwise operators
a&&b;
a||b;
a%%b; //this is xor

//logical operators
a and b;
b or a;
not a;
//how to write "not equal to" ?

//taking address
a.addr();  //similar to ssize()

//pointer deref
a^;
b^^;
c : ^_ = k.addr();

This approach throws familiarity out of window but solves #304 simultaneously

Personally, I DON'T completely like any of these but maybe they'll inspire a better approach. But I think reserving a unique symbol for derefs would be the way (and if that symbol matches with any current one, then do something about it).

@hsutter
Copy link
Owner

hsutter commented Mar 21, 2024

Thanks! Finally fixed -- see longer note in #989.

The example

main: () = {
    x := 2*2;
}

obviously should just work, and now it Just Works again.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

4 participants