Skip to content

Cascaded invocations

Nick Schrader requested to merge nschrader/vala:327-wip into master

Final proposal for an implementation of #327 (closed).

Work done

  • Change scope inside of with
  • Declare local variable explicitly: with (var x = y ())
  • Assign the given expression to a local variable implicitly if needed: with (y ())
  • Perform semantic checks
  • Support for --enable-experimental-non-null
  • 30 test cases for all of these points
  • Linted code

Tests

All tests are passing, the compiler can compile itself and run tests

Syntax

The follwing formal grammar has been implemented:

statement ::= block | ";" | if_statement | switch_statement | while_statement | for_statement | foreach_statement |
              break_statement | continue_statement | return_statement | yield_statement | throw_statement |
              try_statement | lock_statement | WITH_STATEMENT | delete_statement | local_variable_declarations | expression_statement
              
with_statement ::= "with" "(" [ ("var" | type) identifier "=" ] expression ")" embedded_statement

It must comply with the following semantic:

  • Eventually, the explicit local variable declaration must have compatible types
  • The expression must refer to an object or basic type
  • It can be a dereferenced pointer
  • In experimental non-null mode it mustn't be nullable

A special effort was made to provide meaningful error messages.

Behavior

  • Within the with-block the expression's members can be directly accessed without the member access operator
  • Members may hide local, class and instance varibales with the same name
  • Instance variables are still accessible through this
  • A local variable can be directly declared in the with statement header
  • Hidden local and class variables are currently not directly accessible (using this for class members generates a warning, just as it always does)

Examples

class Foo {
    public int field;
    
    public static Foo.factory () { }    
    public void method () { }
}
void function () {
    with (var f = new Foo ()) {
        field = 100;
        method ();
        log (f);
    }
}
void function (Foo f) {
    with (f) {
        field = 100;
        method ();
    }
}
class Bar {
    public int field;
    
    void m () {
        Foo f;
        with (f = Foo.factory ()) {
            field = 100;
            this.field = 200;
            method ();
        }
        log (f);
    }
}
Edited by Nick Schrader

Merge request reports

Loading