6.15 Static

Static qualifiers allocate the memory address of a variable in a higher enclosing level.

For a function body, the variable is allocated in the block where the function is defined; so in the code

struct s {
  int count() {
    static int c=0;
    ++c;
    return c;
  }
}

there is one instance of the variable c for each object s (as opposed to each call of count).

Similarly, in

int factorial(int n) {
  int helper(int k) {
    static int x=1;
    x *= k;
    return k == 1 ? x : helper(k-1);
  }
  return helper(n);
}

there is one instance of x for every call to factorial (and not for every call to helper), so this is a correct, but ugly, implementation of factorial.

Similarly, a static variable declared within a structure is allocated in the block where the structure is defined. Thus,

struct A {
  struct B {
    static pair z;
  }
}

creates one object z for each object of type A created.

In this example,

int pow(int n, int k) {
  struct A {
    static int x=1;
    void helper() {
      x *= n;
    }
  }
  for(int i=0; i < k; ++i) {
    A a;
    a.helper();
  }
  return A.x;
}

there is one instance of x for each call to pow, so this is an ugly implementation of exponentiation.

Loop constructs allocate a new frame in every iteration. This is so that higher-order functions can refer to variables of a specific iteration of a loop:

void f();
for(int i=0; i < 10; ++i) {
  int x=i;
  if(x==5) {
    f=new void() {write(x);};
  }
}
f();

Here, every iteration of the loop has its own variable x, so f() will write 5. If a variable in a loop is declared static, it will be allocated where the enclosing function or structure was defined (just as if it were declared static outside of the loop). For instance, in:

void f() {
  static int x;
  for(int i=0; i < 10; ++i) {
    static int y;
  }
}

both x and y will be allocated in the same place, which is also where f is allocated.

Statements may also be declared static, in which case they are run at the place where the enclosing function or structure is defined. Declarations or statements not enclosed in a function or structure definition are already at the top level, so static modifiers are meaningless. A warning is given in such a case.

Since structures can have static fields, it is not always clear for a qualified name whether the qualifier is a variable or a type. For instance, in:

struct A {
  static int x;
}
pair A;

int y=A.x;

does the A in A.x refer to the structure or to the pair variable. It is the convention in Asymptote that, if there is a non-function variable with the same name as the qualifier, the qualifier refers to that variable, and not to the type. This is regardless of what fields the variable actually possesses.