Scope

Scope refers to the visibility of declarations within the source code. That is, given a particular declaration, the scope of the declaration determines where it is legal to reference that declaration in code or not. With Firewing, there are three main levels of scope:

  • Block Scope - Available within the code block in which an item is declared
  • Subroutine and Function Scope - Available to all code within the subroutine or function in which an item is declared
  • Module Scope - Available to all code within the module in which an item is declared

Block Scope

A block is a set of statements which is enclosed within certain types of declaration statements. Examples of this type of statement include:

  • Do…Loop Until
  • For…Next
  • If…ElseIf…Else…End If
  • Select…End Select
  • While…End While
  • With…End With

An item declared inside one of above statements can be considered local to that statement block. For example,

If a = b Then
   Const varInit = 10
   Dim var As Byte = a * varInit
End If

In this example, varInit and var are local to the block that begins with "if a = b then" and ends with "end if". This means that varInit and var cannot be seen outside of the if…then statement block. For example,

If a = b Then
   Const varInit = 10
   Dim var As Byte = a * varInit
End If
Var = 100

Will generate a "variable not declared" compilation error when trying to assign 100 to var, because var does not exist outside of the if…then statement block.

Subroutine and Function Scope

An item declared within a subroutine or function is not available outside that procedure. Only the subroutine or function that contains the declaration can use it. Variables at the subroutine or function level are commonly referred to as local variables. If you declare an item at the subroutine or function level, it can be seen by all other block scope items within that routine. For example,

Imports USART
Sub Main()
   Dim found As Boolean = False
   If USART.DataAvailable Then
      found = True
   End If
End Sub

Because found is declared at the subroutine level, if can be referenced within the if…then statement block. Another way to think of subroutine or function scope is that of having a super block scope, in which all other block scopes live.

Module Scope

Any item declared inside a module but outside of a subroutine or function has module scope. By default, any declarations that have module scope are private. That is, only subroutine and functions within the module can access the private declaration item. Other modules or programs cannot access a declaration item that is private. If you want other programs or modules to see a declaration, it must be explicitly declared as public. The private and public keywords are often referred to as access modifiers, because they control the accessibility of declaration types.

A public declaration is therefore the interface to a module. Remember, all Firewing declarations are private by default. If you want other modules or programs to access them, they must be explicitly declared as public. For example,

Imports USART
Module MyUtils

' private helper
Function GetMax(ByRef array() As Byte) As Byte
   GetMax = 0
   For index As Byte = 0 To UBound(array)
      If array(index) > GetMax Then
         GetMax = array(index)
      End If
   Next
End Function    

' public interface 
Public Sub DisplayMax(ByRef array() As Byte)
   USART.Write("MAX = ", CStr(GetMax(array)), 13, 10)
End Sub
End Module

The module is named MyUtils, which declares a private helper function called GetMax() and a public interface subroutine called DisplayMax(). The DisplayMax() subroutine uses the private helper GetMax() to calculate the maximum array value, before outputting via the USART module's Write() subroutine. We can now use this module in a program, to output the maximum value of an array,

Imports USART
Imports MyUtils

Sub Main()
   Dim array(5) As Byte
   For index As Byte = 0 To UBound(array) 
      array(index) = USART.ReadByte
   Next      
   MyUtils.DisplayMax(array)
End Sub

However, if you try and make a call to the private helper function GetMax() from the program, an error is generated during compilation.

It's sometimes useful to understand how the compiler finds a declaration. For example, if your subroutine or function references a variable called Index, it will first look to see if a local variable or parameter called Index has been declared. If it cannot be found, then it will then look in the current module or program to see if the variable has been declared at the module level. If it has still not been found, it will then search all imported files referenced in the current module to see if any public variables called Index have been declared. If it still cannot be found, an error is generated.