Variable Scopes

Variable scopes, like function scopes, control how visible a variable is to code in the project. There are four scopes:

Global Variables
Visible to code in all files in the project.
Internal Variables
In a circuit code file, visible to code in all other circuit code files, and in a device file or additional code file, visible to code in the same device file and its associated additional code files.
Local Variables
Visible to code in the same file.
Function Variables
Visible to code in the same function.

Variables are only visible from the point at which they are defined, and not before. This means:

  • Variables defined inside a function can only be used from their declaration until the end of the function.
  • GLOBAL, INTERNAL and LOCAL variables are visible in the file in which they are declared from their declaration onwards.
  • GLOBAL and INTERNAL variables declared in a circuit code file are only visible in other circuit code files that appear later in the list of circuit code files.
  • INTERNAL variables declared in a test device file are visible in all the additional code files added to that device file.
  • INTERNAL variables declared in an additional code file are only visible in the additional code files that appear later in the list of additional code files for the device file.

Variables defined outside a function and without an explicit scope will default to GLOBAL in a circuit code file and INTERNAL in a device file or additional code file.


Global Variables

Global variables are declared using the GLOBAL scope modifier when declaring a variable and can only be declared in a circuit code file. Any variable in a circuit code file without an explicit scope is in fact global in scope, but it is better to always be explicit when declaring global variables and use the GLOBAL modifier. Global variables are visible from anywhere within the code, across all files.

Variables can be declared as global in a device file or one of its additional code files, but it is the equivalent of internal in this situation and cannot be accessed from outside the device file.

Global variables can be used for values such as debug settings, or any globally applicable settings. This means that, rather than have to pass a 'debug' variable into every function, the global variable can be accessed from anywhere in the system to decide whether to output debug information.

Example

The following example is split into two sections, a circuit code file and one of the device files which is called (through the CALL line) from the Test function.

GLOBAL INT DEBUG;

GLOBAL Test()(INT result)
  // Set the debug variable.
  DEBUG := TRUE;

  // Call a function in another file.
  CALL("IC1", "Test")()(result);
END;

The device file:

GLOBAL Test()(INT result)
  IF DEBUG THEN
    // The global variable is set, so the system should output debugging.
    PRINT("Enter Function Test for device ", UNIQUE_DEVICE_REF, "\n");
  END;
END;

Overriding global variables

The initial value of global variables can be overridden on the Run Tests screen in XJDeveloper or XJInvestigator and in XJRunner if enhanced testing is enabled for the current user.

Initial values can also be overridden on the command-line when running with XJRun:

xjrun -set DEBUG=1 main.xje

Internal Variables

Internal variables are declared with the INTERNAL scope modified. Internal variables defined in a circuit code file are visible in that file and all other circuit code files, but not in any device files. Internal variables defined in a device file or any of its additional code files are visible to just those files. In addition, each device using that device file has its own copy of each variable. Any variable declared without an explicit scope in a device file or one of its additional code files, is implicitly internal.

Example

The first snippet is a device file with the internal variable:

INTERNAL INT internalVariable;

// Function to write to the variable
GLOBAL WriteValue(INT x)()
  internalVariable := x;
END;

// Function to read from the variable
GLOBAL ReadValue()(INT x)
  x := internalVariable;
END;

The next code snippet indicates the operation of the internal variables. The same device file is assigned to two devices, IC1 and IC2. The internal variable is set inside the code by a call to WriteValue as defined above. The two devices are set to different values to show the independence of the two internal variables.

Test()()
  INT val1, val2;

  // Write a value to IC1's static variable
  CALL("IC1", "WriteValue")(10)();
  CALL("IC2", "WriteValue")(20)();

  // Read the values back
  CALL("IC1", "ReadValue")()(val1);
  CALL("IC2", "ReadValue")()(val2);

  PRINT("IC1 value: ", val1, "\n");
  PRINT("IC2 value: ", val2, "\n");
END;

The output will be:

IC1 value: 10
IC2 value: 20

Local Variables

Local variables are only valid within a single file whether that be an additional code file, a circuit code file or a device file. They are declared using the LOCAL scope modifier. If two local variables are declared with the same name but in different files, they are different variables.

Example

There follows two code snippets, one from a circuit code file and one from a device file. Each declares a local variable with the same name but they are distinct variables.

Circuit code file:

// The variable is only accessible within this file
LOCAL INT localVar := 10;

GLOBAL Test()()
  // The following line will print '10'
  PRINT("Local var is ", localVar, "\n");
END;

Device file:

// This variable is only accessible within this file
// but is distinct from the previous declaration of 'localVar'
LOCAL INT localVar := 20;

GLOBAL Test()()
  // The following line will print '20'
  PRINT("Local var is ", localVar, "\n");
END;

Function Parameters and Variables

Function parameters and variables have a scope that extends from their declaration to the end of the current function. All variables must be declared before any statements in the function.

Example

GLOBAL Test(INT a, INT b, STRING c)(INT d)
  INT x := a;
  INT y := b;

  IF (x < y) THEN
    d := x;
  ELSE
    d := y;
  END;
END;