JacquelineCasey / Nom

0 stars 0 forks source link

Return #14

Closed JacquelineCasey closed 11 months ago

JacquelineCasey commented 1 year ago

Allow the return keyword in functions. I am not sure if return should be a statement or an expression.

One concern is type checking - ideally a branch that returns should have some sort of diverges type, which can coerce to any other type. Does this only work if we use return as a statement? Should using return as an expression statement be allowed in this case? I guess dead code is ok if it is being actively worked on or the live code is just a test, but it might necessitate some sort of analysis that says that a branch yields the bottom type if it is guaranteed to always hit a return...

JacquelineCasey commented 12 months ago

Trying to decide if return should be an expression or a statement.

In Rust, it's an expression, although of course you almost always use it in a context where it could easily be turned into a statement by the addition of a semicolon.

The only benefit of expressional return that I understand is that you can omit the wrapping block if you are early returning from a match statement. To be fair, that is a nice ergonomic thing.

I am actually going to make it an expresssion, for a weird reason. We want return to have a type, and expressions have types while statements do not. The type might be called "diverging," "never," or "bottom." It actually exhibits some special rules:

Is allowed, even though it is kinda weird code. Something more sane is:

val a: i32 = if b == c {
    1000
}
else {
    return "hello world"
}

Actually, annoyingly, that should compile even if the return has a semicolon, or if it is nested deep in some other set of branches that are guaranteed to diverge. We really need to do some sort of reachability analysis... the second rule is something like - if a block contains a never type, then the type of the block decays to never.

JacquelineCasey commented 12 months ago

We are going to want to do this analysis at some point, and I think the never type is very interesting actually! Zig has some information on what it can be used for, though they call it noreturn.

For instance, we could then add unreachable as a keyword. Zig's @panic is a builtin function, but it also returns noreturn, which seems like the right behavior.

JacquelineCasey commented 12 months ago

Be aware of how never interacts with the short circuit boolean operators...

JacquelineCasey commented 12 months ago

We could special case while true to be never as well.

Another interesting use of never: Result<i32, never> for those weird generic situations when you need a result (perhaps a callback is supposed to give a result but you know for a fact that the error part never happens). Rust does this, but it calls this special type Infallible. Interestingly, it is implemented as the zero variant enum.

Huh, I never noticed that the zero field tuple (product type) was the unit type and the zero variant enum (sum type) was the bottom type.