Author Topic: [Email suggestion No. 3] type casts in C2 + bugs  (Read 8137 times)

magnusi

  • Newbie
  • *
  • Posts: 17
    • View Profile
[Email suggestion No. 3] type casts in C2 + bugs
« on: July 19, 2016, 10:26:37 AM »
The current cast<type>(what); does not really fit into C2 syntax wise, since it implies generics and that is not something that fits in C2 as it is now. Bas proposed this syntax in an email a few months ago:

Code: [Select]
(->type)what
This could be much better and due to the arrow, more understandable to those who don't know how casts work beforehand.

casting bug 1: C2C parser completely ignores invalid C-style casts and interprets statements that use it as ones using implicit conversion

example:

Code: [Select]
int32 i = 10;
char c = (char)i;

I think that this syntax should result in an error or at-least warning about C-style casts. Frankly, I know that C-style casts are hard to parse, so I am not sure how easy or hard that is to implement

casting bug 2: C2C does not work properly when I do intentionally a bad thing like this:

Code: [Select]
int32 i = 10;
char d = cast<char>(d); //undeclared identifier error

I think that the proper behavior should be issuing a message/error/warning about using uninitialized variable or casting to itself.

admin

  • Administrator
  • Newbie
  • *****
  • Posts: 11
    • View Profile
Re: [Email suggestion No. 3] type casts in C2 + bugs
« Reply #1 on: July 21, 2016, 08:03:47 AM »
I couldn't agree more. The <> syntax just looks like C++ templates is is just plain ugly..

However ugly, it does have the advantage of requiring parentheses around the thing being
cast. With the c-style cast, it's not always obvious what exactly is cast. This has to do with
operator precendence (and could be a source of bugs).

C-style cast are currently not working on purpose. Casts need to be fixed first.

The 2nd 'bug' is also done on purpose for now, since we don't have to check circular initializations now ;)
So the declaration is only added to the scope after it's been done, so after the initialization. But for better
error messages, it might be needed to change this

magnusi

  • Newbie
  • *
  • Posts: 17
    • View Profile
Re: [Email suggestion No. 3] type casts in C2 + bugs
« Reply #2 on: July 21, 2016, 02:34:16 PM »
I couldn't agree more. The <> syntax just looks like C++ templates is is just plain ugly..

However ugly, it does have the advantage of requiring parentheses around the thing being
cast. With the c-style cast, it's not always obvious what exactly is cast. This has to do with
operator precendence (and could be a source of bugs).

C-style cast are currently not working on purpose. Casts need to be fixed first.


The 2nd 'bug' is also done on purpose for now, since we don't have to check circular initializations now ;)
So the declaration is only added to the scope after it's been done, so after the initialization. But for better
error messages, it might be needed to change this

Yes, I understand it, what I mean is that the compiler is ignoring them, rather than issuing a proper warning about C-style casts or throwing an error.

admin

  • Administrator
  • Newbie
  • *****
  • Posts: 11
    • View Profile
Re: [Email suggestion No. 3] type casts in C2 + bugs
« Reply #3 on: July 22, 2016, 09:22:47 AM »
Yes, the parser ignores them currently, I'll put a task on my backlog to fix this properly

lerno

  • Full Member
  • ***
  • Posts: 247
    • View Profile
Re: [Email suggestion No. 3] type casts in C2 + bugs
« Reply #4 on: June 22, 2018, 11:16:09 AM »
C/C++/Java style casts of the form (Bar)foo is notoriously hard to visually parse because the precedence rules are rarely clear. The cast<Bar>(foo) is easier to visually parse since the object of the cast is clear. Another way is to introduce a post-fix notation with an "AS" operator or similar, e.g. foo as Bar where as binds directly to the object to the left:

Code: [Select]
foo as Bar // == cast<Bar>(foo)
foo.baz as Buz // == cast<Buz>(foo.baz)
(foo as Bar).fooBar // == cast<Bar>(foo).fooBar
i as u8 // == cast<u8>(i)
cc = ((c << 2) & 0xFF) as u8 // == cast<u8>((c << 2) & 0xFF)

magnusi

  • Newbie
  • *
  • Posts: 17
    • View Profile
Re: [Email suggestion No. 3] type casts in C2 + bugs
« Reply #5 on: November 09, 2018, 10:56:47 PM »
Back when I first started debating this, I was young and inexperienced.
Now, after two years of Rust, I can say that I agree with @lerno that value as Type might be the best solution. It is clear, readable and not as out of place as cast<Type>(val) is.

Moreover, if C2 was ever to introduce any form of generics, cast<Type>(val) would be as deceiving in appearance as sizeof(val) is for newcomers (they both look like functions).

bas

  • Full Member
  • ***
  • Posts: 220
    • View Profile
Re: [Email suggestion No. 3] type casts in C2 + bugs
« Reply #6 on: November 13, 2018, 08:49:24 AM »
I think the expr as type idea is also nice. The only nasty thing I can think of is during parsing.
The type after as, like: (fabricated example)

Code: [Select]
x = y as u32* * 10;
So the parser sees to asterixes, so is it a pointer to a pointer to u32 or a multiplication?

lerno

  • Full Member
  • ***
  • Posts: 247
    • View Profile
Re: [Email suggestion No. 3] type casts in C2 + bugs
« Reply #7 on: November 13, 2018, 08:39:28 PM »
Look at the examples here: http://www.c2lang.org/forum/index.php?topic=108.0

I ended up with these possibilities:

a. cast(foo as i32)
b. cast(foo, i32)
c. foo->i32
d. (foo:i32) alt. cast(foo:i32)
e. (foo::i32) alt. cast(foo::i32)
f. foo.as(i32)
g. foo :> i32

Exactly because we want to avoid the difficulty of parsing the suffix there. That's my main reason for abandoning my suggestion of "foo as i32"

I think (foo:i32) is pretty radical but nicely terse. The only objection for me is that the parsing might be iffy.

Any "cast" version is very old fashioned but safe as alternatives.

Let's consider 2 common situations:

Code: [Select]
double f = (double)(3 + (unsigned)foo());
Bar bar = bars[(size_t)i];

Here's what they'd look like:

Code: [Select]
d64 f = cast((3 + cast(foo() as u32)) as d64);
Bar bar = bars[cast(i as size_t)];

Code: [Select]
d64 f = cast(3 + cast(foo(), u32), d64);
Bar bar = bars[cast(i, usize)];

Code: [Select]
d64 f = (3 + foo()->u32)->d64;
Bar bar = bars[i->usize];


Code: [Select]
d64 f = (3 + (foo():u32)):d64);
Bar bar = bars[(i:usize)];

Code: [Select]
d64 f = cast(3 + cast(foo():u32)):d64);
Bar bar = bars[cast(i:usize)];

Code: [Select]
d64 f = (3 + (foo()::u32))::d64);
Bar bar = bars[(i::usize)];

Code: [Select]
d64 f = cast(3 + cast(foo()::u32))::d64);
Bar bar = bars[cast(i::usize)];

Code: [Select]
d64 f = (3 + foo().as(u32)).as(d64);
Bar bar = bars[i.as(usize)];

Code: [Select]
d64 f = cast((3 + (foo() :> u32)) :> d64);
Bar bar = bars[(i :> size_t)];