Scope state object Proposal

The _Context keyword can be used to bind the entire local state of the following scope block or declaration to struct fields, this shall be refered to as a context scope. This is done by turning all local declarations into aliases to a field in a struct, see semantics for what that means. In addition to this, a _Continuation keyword is defined, labels can now be referenced using &&, and the result has the _Label type, and it is possible to jump to those using a computed goto*.

Example

The folowing shows how this can be used for a simple generator which returns numbers.

int mycounter(struct state*const state);

struct mycounter {
  int variable;
  _Continuation typeof(mycounter)* next;
};


int mycounter(struct state*const state) _Context(state) {
  int variable = 1;
  while(true){
    variable += 1;
    state->next = &&next;
    return variable; next:;
  }
}

int main(){
  struct mycounter counter_state = {.next=mycounter;};
  printf("%d\n", counter_state.next(&counter_state)); // 1
  printf("%d\n", counter_state.next(&counter_state)); // 2
  printf("%d\n", counter_state.next(&counter_state)); // 3
}

Semantics

Any scope inside a context scope is a context scope too.

The exact type of a referenced label is implementation defined, but it is to be available only inside functions and usable using the _Label keyword, which can be used to refer to that type, and the type may depend on the function type. A label reference can be jumped to using goto*. It bahaves exactly like a goto to the label directly. A label reference can be stored in a variable with _Label type. A label reference can be implicitly converted into the _Continuation function type of the enclosing function if the function block has context scope. The _Continuation keyword is a function-specifier. It can be called like a regular function, but it can not be jumped to using goto. When a _Continuation function is called, and it refers to a function label, the function is called normally, except that it starts at that label. A function pointer can also be implicitly converted into a compatible _Continuation function type, but not the other way around. If the resulting _Continuation function pointer is called, it behaves no different from a regular function call.

A context scope may have one or more pointers to structs associated with it, which shall be refered to as context objects. These are provided using an assignment-expression of the _Context specifier. Those assignment-expression are always reevaluated when the associated context scope is entered, even if this happens by calling goto, or by calling a function or a _Continuation (This does not include other scopes or context scopes contained within that scope). The assignment expression is never reevaluated inside of the context scope. If any context object pointer is invalid or null, the bahaviour is undefined.

Local variables with automatic storage duration in a context scope have different semantics from regular variables. Each variable declaration in context scope must match, and is then associated to, a field of one of the context objects, with the last added / closest context object being checked first. Both, the name and the type of the declaration, must match, if they don’t, an error must be generated, even if there are no context objects at all. It is allowed to use the const version of the type in the declaration. The lifetime af the variable will be the same as the object it references. Accessing the variable is semantically exactly equivalent to dereferencing and accessing the field of the referenced struct associated_struct_ptr->field. It is an error to declare a variable shadowing another variable if both reference the same field of the same struct in the same context scope.

In a context scope, at the point where a local variable with automatic storage duration would normally be initialised, that still happens, except that it is now technically an assignment to the associated struct field.

Skipping over the declaration of variables in a context scope by goto or other means behaves as follows. They still just refer to pre existing variables rather than defining a new one, and accessing them must still behave es expected of accessing that object. The variables are are not initialised again in this case, no assignment to the associated struct field takes place.

Syntax

context-specifier:
  _Context( assignment-expressionopt )

(6.7) declaration-specifiers:
  storage-class-specifier declaration-specifiersopt
  type-specifier declaration-specifiersopt
  type-qualifier declaration-specifiersopt
  function-specifier declaration-specifiersopt
  alignment-specifier declaration-specifiersopt
  context-specifier declaration-specifiersopt

(6.7.4) function-specifier:
  inline
  _Noreturn
  _Continuation

(6.8.2) compound-statement:
  context-specifieropt { block-item-listopt }

(6.8.5) iteration-statement:
  while ( expression ) statement
  do statement while ( expression ) ;
  context-specifieropt for ( expressionopt ; expressionopt ; expressionopt ) statement
  context-specifieropt for ( declaration expressionopt ; expressionopt ) statement