Target Language Compiler    

Variable Scoping

This section discusses how the Target Language Compiler resolves references to variables (including records).

Scope, in this document, has two related meanings. First, scope is an attribute of a variable that defines its visibility and persistence. For example, a variable defined within the body of a function is visible only within that function, and it persists only as long as that function is executing. Such a variable has function (or local) scope. Each TLC variable has one (and only one) of the scopes described in Scopes below.

The term scope also refers to a collection, or pool, of variables that have the same scope. At any point in the execution of a TLC program, several scopes may exist. For example, during execution of a function, a function scope (the pool of variables local to the function) exists. In all cases, a global scope (the pool of global variables) would also exist.

To resolve variable references, TLC maintains a search list of current scopes and searches them in a well-defined sequence. The search sequence is described in How TLC Resolves Variable References.

Dynamic scoping refers to the process by which TLC creates and deallocates variables and the scopes in which they exist. For example, variables in a function scope exist only while the defining function executes.

Scopes

The following sections describe the possible scopes that a TLC variable can have.

Global Scope.   By default, TLC variables have global scope. Global variables are visible to, and can be referenced by, code anywhere in a TLC program. Global variables persist throughout the execution of the TLC program. Global variables are said to belong to the global pool.

Note in particular that the CompiledModel record of the model.rtw file has global scope. Therefore, you can access this structure from any of your TLC functions or files.

You can use the scope resolution operator (::) to explicitly reference or create global variables from within a function. See The Scope Resolution Operator for examples.

Note that you can use the %undef directive to free up memory used by global variables.

File Scope.   Variables with file scope are visible only within the file in which they are created. To limit the scope of variables in this way, use the %filescope directive anywhere in the defining file.

In the following code fragment, the variables fs1 and fs2 have file scope. Note that the %filescope directive does not have to be positioned before the statements that create the variables:

Variables whose scope is limited by %filescope go out of scope when execution of the file containing them completes. This lets you free up memory allocated to such variables.

Function (Local) Scope.   Variables defined within the body of a function have function scope. That is, they are visible within and local to the defining function. For example, in the following code fragment, the variable localv is local to the function foo. The variable x is global:

A local variable can have the same name as a global variable. To refer, within a function, to identically-named local and global variables, you must use the scope resolution operator (::) to disambiguate the variable references. See The Scope Resolution Operator for examples.

%with Scope.   The %with directive adds a new scope, referred to as a %with scope, to the current list of scopes. This directive makes it easier to refer to block-scoped variables.

The structure of the %with directive is

For example, the directive

adds the CompiledModel.System[sysidx] scope to the search list. This scope is searched before anything else. You can then refer to the system name simply by

instead of

Generate Scope.   Generate scope is a special scope used by certain built-in functions that are designed to support code generation. These functions dispatch function calls that are mapped to a specific record type. This capability supports a type of polymorphism in which different record types are associated with functions (analogous to methods) of the same name. Typically, this feature is used to map Block records to functions that implement the functionality of different block types.

Functions that employ generate scope include GENERATE, GENERATE_TYPE, GENERATE_FUNCTION_EXISTS, and GENERATE_TYPE_FUNCTION_EXISTS (See GENERATE and GENERATE_TYPE Functions). This section will discuss generate scope using the GENERATE built-in function as an example.

The syntax of the GENERATE function is

The first argument (blk) to GENERATE is a valid record name. The second argument (fn) is the name of a function to be dispatched. When a function is dispatched through a GENERATE call, TLC automatically adds blk to the list of scopes that is searched when resolving variable references. Thus the record (blk) is visible to the dispatched function, as if there were an implicit
%with <blk>... %endwith directive in the dispatched function.

In this context, the record (blk) is said to be in generate scope.

Three TLC files, demonstrating the use of generate scope, are listed below. The file polymorph.tlc creates two records representing two hypothetical block types, MyBlock and YourBlock. Each record type has an associated function named aFunc. The block-specific implementations of aFunc are contained in the files MyBlock.tlc and YourBlock.tlc.

Using GENERATE calls, polymorph.tlc dispatches to the appropriate function for each block type. Notice that the aFunc implementations can refer to the fields of MyBlock and YourBlock, because these records are in generate scope.

The invocation and output of polymorph.tlc, as displayed on the MATLAB console, are shown below:

The Scope Resolution Operator

The scope resolution operator (::) is used to indicate that the global scope should be searched when looking up a variable reference. The scope resolution operator is often used to change the value of global variables (or even create global variables) from within functions.

By using the scope resolution operator, you can resolve ambiguities that arise when a function references identically-named local and global variables. In the following example, a global variable foo is created. In addition, the function myfunc creates and initializes a local variable named foo. The function myfunc explicitly references the global variable foo by using the scope resolution operator.

You can also use the scope resolution operator, within a function, to create global variables. The following function creates and initializes a global variable:

How TLC Resolves Variable References

This section discusses how the Target Language Compiler searches the existing scopes to resolve variable references.

Global Scope.   In the simplest case, the Target Language Compiler resolves a variable reference by searching the global pool (including the CompiledModel structure).

%with Scope.   You can modify the search list and search sequence by using the %with directive. For example, when you add the following construct

the System[sysidx] scope is added to the search list. This scope is searched first, as shown by this picture.

Figure 6-1: %with Scope Added to Search Sequence

This technique makes it simpler to access embedded definitions. Using the %with construct (as in the previous example), you can refer to the system name simply by

instead of

Function Scope.   A function has its own scope. That scope is added to the previously described search list, as shown in this picture.

Figure 6-2: Scoping Rules Within Functions

For example, in the following code fragment:

If Name is not defined in foo, the assignment will use the value of Name from the previous scope, CompiledModel.System[SysIdx].Name.

In the case of nested functions, only the innermost nested function scope is searched. In the picture below, foo is called by callfoo. When resolving variable references in foo, only the scope of foo is searched (together with enclosing %with and global scopes.)

Figure 6-3: Nested File Scopes

File Scope.   File scopes are searched before the global scope, as shown in the following picture.

Figure 6-4: File Scopes Searched Before Global Scope

The rule for nested file scopes is similar to that for nested function scopes. In the case of nested file scopes, only the innermost nested file scope is searched.


  Identifier Definition Target Language Functions