I prefer option #3, just according to taste.

froy

On Tue, Nov 23, 2010 at 2:58 PM, David Herman <[email protected]> wrote:

> Two afterthoughts:
>
> - IINM, the different syntax for blocks between option #2 and option #3 is
> not that drastic, so if we choose one and decide we prefer the other, it
> might not be too hard to change.
>
> - In option #4, we can't completely *turn off* typechecking -- that's
> unsound. (For example, inside the unchecked part you could assign the wrong
> type to a variable or data structure.) But we could avoid certain checks
> (like comparing the result type of the two arms of an if). Not that I'm
> advocating option #4. :)
>
> Dave
>
> On Nov 23, 2010, at 2:53 PM, David Herman wrote:
>
> > Of these, I like option #3 the most.
> >
> > I should say, I think anywhere that we have statements in the grammar, we
> could actually allow them to be expressions of type (), and ISTM that would
> be equally workable for option #2 or option #3. I'd be open to that
> alternative, since in *surface* syntax you still have the look and feel of
> C, but you get higher refactoring flexibility.
> >
> > Dave
> >
> > On Nov 23, 2010, at 2:34 PM, Graydon Hoare wrote:
> >
> >> Hi,
> >>
> >> Some of you may have noticed that in the rewrite from rustboot to rustc
> we're becoming substantially more expression-language-ish. This is mostly a
> result of me yielding to the preferences of other developers (and LLVM's
> semantics), as well as some hint that things get much easier in syntax
> extensions and calculating compile-time-constants if we permit more
> "statement-ish" forms as expressions. Particularly conditionals.
> >>
> >> We've run into a (common, seen in many other languages) sort of problem
> along the way here, which is that some expressions are implicitly ignored
> (or must be, due to being in an ignored context) whereas others are not. We
> have a nil-type (), but we don't always have sensible rules for forcing
> things to have the nil type by context.
> >>
> >> This email is a poll of alternative solutions. I'll give two example
> cases and ask people for their input on which modification of the rules
> feels best.
> >>
> >> Example case that does compile:
> >>
> >> A:  auto x = if (foo()) { 10; } else { 11; };
> >>
> >> Example case that does not compile:
> >>
> >> B:  if (foo()) { 10; } else { "hello"; }
> >>
> >> We can write this in rust at the moment, but in the rustc typechecking
> rules it will fail to compile, because 'if' is an expression-statement,
> expressions have types, and the types of the two branches (judged as the
> last statement's expression value, if it's an expression, or else nil) are
> of different types.
> >>
> >> Here are some approaches to solving this example. Please pick the one
> you like the most:
> >>
> >> (1) Kick all branchy expressions out of the expression grammar, put them
> back in the statement grammar. Case B will compile, and case A must be
> rewritten like so:
> >>
> >> A:  auto x = { auto t = 11; if (foo()) { t = 10; }; t; };
> >>
> >> This is the C-with-GNU-extensions model.
> >>
> >> (2) Hoist all statements up into the expression language and make
> semicolon into a sequencing operator, with a trailing-semi ignored by the
> parser. Then we need to rewrite only the second case to force unit types in
> the to-be-ignored differing branches.
> >>
> >> B:  if (foo()) { 10; () } else { "hello"; () }
> >>
> >> Though we'd also be *allowed* to rewrite the first case to drop the
> semicolons:
> >>
> >> A:  auto x = if (foo() { 10 } else { 11 };
> >>
> >> This is the Ocaml approach.
> >>
> >> (3) A slightly weaker form of (2), which is to reformulate blocks with
> the following grammar:
> >>
> >>   block ::=  { [ stmt ; ]* expr? }
> >>
> >> In other words, every block becomes a brace-enclosed sequence of
> semicolon-terminated statements, followed by an optional expr. If the expr
> is missing, it is implied as (). In this case we'd be rewriting only the
> first case:
> >>
> >> A:  auto x = if (foo()) { 10 } else { 11 };
> >>
> >> This is similar to the Ocaml rule in practice, except that it makes the
> presence or absence of the final semicolon in a block equivalent to ending
> the block with the nil type. This is a possible hazard (especially during
> refactoring or editing) to users who want to write a value-producing block
> but accidentally semicolon-terminate the last expression; but it's not a
> huge hazard since the typechecker will tell them the value they produced is
> of nil type. It just might be hit a lot.
> >>
> >> (4) Statically determine the contexts in which an expression's value
> "will be used" in an outer expression, and only typecheck those contexts.
> This permits both of the examples to compile as-is, but it's the most
> unorthodox approach, and poses a refactoring hazard as code may become
> type-invalid when nested into an expression context that "uses" its
> previously-ignored result. Again, as in (3) the typechecker will catch these
> cases, but they might happen more or less often than those in (3).
> >>
> >> We can't think of any other options. Significant whitespace is not an
> option :)
> >>
> >> Personally my knee-jerk reaction is to embrace (1) since I like
> statements anyway, but I can see plausible arguments for the other 3. Can I
> get a show of hands? We have to pick something.
> >>
> >> -Graydon
> >> _______________________________________________
> >> Rust-dev mailing list
> >> [email protected]
> >> https://mail.mozilla.org/listinfo/rust-dev
> >
> > _______________________________________________
> > Rust-dev mailing list
> > [email protected]
> > https://mail.mozilla.org/listinfo/rust-dev
>
> _______________________________________________
> Rust-dev mailing list
> [email protected]
> https://mail.mozilla.org/listinfo/rust-dev
>
_______________________________________________
Rust-dev mailing list
[email protected]
https://mail.mozilla.org/listinfo/rust-dev

Reply via email to