Skip to content

References

Moises Aguirre edited this page Dec 13, 2024 · 5 revisions

NOTE: At this time, due to lack of support for non-function references in the game engine, references to arrays and structure variables (in the default address space, that is, when not using world/global references/pointers) have the following restrictions:

  • Only references to internal arrays and structure variables can be assigned to variables and passed to functions.
  • References to arrays and structure variables cannot be shared between libraries. That means you cannot pass an array reference to another library, and you cannot use an array reference in, or returned from, another library.

Array references

element-type [] & var = reference ;

In C, when you specify an array, it "decays" into a pointer to the first element of the array. In BCS, something similar happens: when you specify an array, what you actually get is a reference to the array. You can then save that reference into a reference variable, or pass it to a function:

#library "reftest"

// Only references to internal variables can be passed around to functions.
internal int a[] = { 1, 2, 3 };
internal int b[] = { 6, 5, 4 };

script "Main" enter {
   PrintArray( a );
   PrintArray( b );
}

void PrintArray( int[]& array ) {
   foreach ( let int element; array ) {
      Print( d: element );
   }
}

Structure variable references

structure & var = reference ;

Similar to arrays, when you specify a structure variable, what you get is a reference to the structure variable:

#library "reftest"

struct NumberT {
   int value;
};

// Only references to internal variables can be assigned to reference variables
// and passed around to functions.
internal NumberT someNumber = { 123 };

script "Main" enter {
   NumberT& number = someNumber;
   Print( d: number.value ); // Output: 123
   ChangeNumber( number );
   Print( d: number.value ); // Output: 321
}

void ChangeNumber( NumberT& number ) {
   number.value = 321;
}

Function references

return-type function( [parameters] ) [qualifiers] & var = reference ;

Similar to arrays and structure variables, when you specify a function, what you get is a reference to the function:

#library "reftest"

void F1() { Print( s: "F1() called" ); }
void F2() { Print( s: "F2() called" ); }

script "Main" enter {
   void function()& f = F1;
   f(); // Output: F1() called
   f = F2;
   f(); // Output: F2() called
}

Nullable references

The null reference is an invalid reference. A nullable reference is a reference that can either be a valid reference or the null reference. Nullable references can only be assigned to variables of nullable reference type. A nullable reference type is marked with a question mark (?) instead of an ampersand (&):

script "Main" enter {
   int[]? r = null;
   struct S { int a; }? r2 = null;
   void function()? r3 = null;
}
Null check

The null reference cannot be dereferenced. Everytime you use a nullable reference, the game will check the reference. If it is the null reference, an error will be reported in the console and the current script will be terminated:

script "Main" enter {
   int[]? r = null;
   r[ 0 ] = 123; // Prints error and terminates script.
}
From nullable to non-nullable

A nullable reference cannot be assigned to a non-nullable reference variable. The !! operator confirms that a nullable reference is not the null reference by performing the above null check and returns the nullable reference as a non-nullable reference:

script "Main" enter {
   static int a[] = { 1, 2, 3 };
   int[]? r = a;
   // `r` refers to a valid reference, so will succeed.
   int[]& r2 = r!!;
   r = null;
   // `r` no longer refers to a valid reference, so an error will be printed
   // and the script will be terminated.
   r2 = r!!;
}

Pointers

zt-bcc introduces a pointer type, which is specified by using `*` in place of `?`/`&`, primarily for interoperability with other compilers and extreme performance requirements. Unlike reference types, array length is **not** passed around, and null checks aren't done. Pointers are exchangeable with nullable references to structures and functions of the same type, but pointers to arrays cannot be implicitly cast to nullable references to arrays.

Address spaces

zt-bcc introduces the ability to have references and pointers into any world/global array. The syntax is as follows:
struct foo world:0* bar;
void[] global:0? baz;

That is, world/global:index after the type but before ?/*, where index is the index of the global array to be pointed to.

Void array references

Much like void pointers in C, void array references in zt-bcc are the generic reference/pointer type. They cannot be dereferenced, but they can be implicitly converted to and from any other structure/array reference/pointer type.