Positron Compiler Documentation

Return Variable

Source: Positron16 Compiler User Manual, PDF page 451

A procedure can return a variable of any type, making it useful for inclusion within expressions. The variable type to return is added to the end of the procedure's template. For example:

Proc MyProc(), SByte
   Result = 10
EndProc

All variable types are allowed as return parameters and follow the same syntax rules as Dim. Note that a return name is not required, only a type. For example:

Proc MyProc(), [12] as Byte
                                ' Procedure returns a 12 element byte array
Proc MyProc(), [12] as Word
                                ' Procedure returns a 12 element word array
Proc MyProc(), [12] as Dword  ' Procedure returns a 12 element dword array
Proc MyProc(), [12] as Float  ' Procedure returns a 12 element float array
Proc MyProc(), String * 12
                                ' Procedure returns a 12 character string

In order to return a value, the text “Result” is used. Internally, the text Result will be mapped to the procedure’s return variable. For example:

Proc MyProc(pBytein as Byte), Byte
   Result = pBytein ' Transfer the parameter directly to the return variable
EndProc

The Result variable is mapped internally to a variable of the type given as the return parameter, therefore it is possible to use it the same as any other local variable, and upon return from the procedure, its value will be passed. For example:

Proc MyProc(pBytein as Byte), Byte
   Result = pBytein
                         ' Transfer the parameter to the return variable
   Result = Result + 1  ' Add one to it
EndProc

Returning early from a procedure is the same as returning from a subroutine. i.e. using the ExitProc directive.

Proc MyProc(pBytein as Byte), Byte
   Result = pBytein
                                   ' Transfer the parameter to the return variable
   If pBytein = 0 Then ExitProc  ' Perform a test and return early if required
   Result = Result + 1
                                   ' Otherwise… Add one to it
EndProc

A return parameter can also be aliased to an SFR (Special Function Register). For example:

Proc MyProc(), WREG0

As with standard variables, the aliased return parameter can also be casted to a type that has fewer bytes. For example, a Word variable can be casted to a Byte type, or a Dword can be casted to a Word or Byte type etc…

Proc MyProc(), WREG2.Byte0

Below is an example procedure that mimics the compiler’s 16-bit Dig command.

         Device = 24EP128MC202
         Declare Xtal = 140.03
         Declare Hserial_Baud = 9600
                                            ' UART1 Baud rate
         Declare Hrsout1_Pin = PORTB.11  ' Select pin to be used for USART1 TX
         Dim MyWord As Word = 12345
      '--------------------------------------------------
      ' Emulate the 16-bit Dig command's operation
      ' Input     : pWordin holds the value to extract from
      '           : pDigit holds which digit to extract (1 To 5)
      ' Output    : Result holds the extracted value
      ' Notes     : None
      '
      Proc DoDig16(pWordin As Word, pDigit As Byte), Byte
      Dim DigitLoop As Byte
         pWordin = Abs(pWordin)
         If pDigit > 0 Then
           For DigitLoop = (pDigit - 1) To 0 Step -1
              pWordin = pWordin / 10
           Next
         EndIf
         Result = pWordin // 10
      EndProc
'--------------------------------------------------
Main:
' Setup the Oscillator to operate the device at 140.03MHz
' Fosc = (7.37 * 76) / (2 * 2) = 140.03MHz
  PLL_Setup(76, 2, 2, $0300)
  RPOR4.Byte1 = 1                         ' Make PPS Pin RB11 U1TX
  HRSOut Dec DoDig16(MyWord, 0)
  HRSOut Dec DoDig16(MyWord, 1)
  HRSOut Dec DoDig16(MyWord, 2)
  HRSOut Dec DoDig16(MyWord, 3)
  HRSOutLn Dec DoDig16(MyWord, 4)
'--------------------------------------------------------------------------
' Configure for internal 7.37MHz oscillator with PLL
' OSC pins are general purpose I/O
'
    Config FGS = GWRP_OFF, GCP_OFF
    Config FOSCSEL = FNOSC_FRCPLL, IESO_ON, PWMLOCK_OFF
    Config FOSC = POSCMD_NONE, OSCIOFNC_ON, IOL1WAY_OFF, FCKSM_CSDCMD
    Config FWDT = WDTPOST_PS256, WINDIS_OFF, PLLKEN_ON, FWDTEN_OFF
    Config FPOR = ALTI2C1_ON, ALTI2C2_OFF
    Config FICD = ICS_PGD1, JTAGEN_OFF

Notes

The compiler’s implementation of procedures is not as thorough as a true procedural language such as C or Pascal because they have had to be added to an already flat language. However, they are still a powerful feature of the language when used appropriately. Procedures are not supported in every instance of the compiler and if one is not supported within a particular command, a syntax error will be produced. In which case, an intermediate variable will need to be created to hold the procedure’s return result:

MyTemp = MyProc()

The compiler does not re-cycle RAM for parameters or local variables. A parameter that is passed ByRef can only ever be a Byte, Word or Dword type, because it will hold the address of the variable passed to it and not its value. This is then used by either Ptr8, Ptr16, Ptr32 and Ptr64 in order to manipulate the address indirectly. An example of this mechanism is shown below:

' Demonstrate a procedure for finding the length of a word array
' given a particular terminator value
'
  Device = 24FJ64GA002
  Declare Xtal = 16
'
' USART1 declares
'
  Declare Hserial_Baud = 9600      ' UART1 Baud rate
  Declare Hrsout1_Pin = PORTB.14
                                     ' Select the pin for TX with USART1
  Dim MyLength As Word
  Dim MyArray[20] As Word = 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,0
'---------------------------------------------------------------------------
' Find the length of a word array with a user defined terminator
' Input     : pArrayIn holds the address of the word array
'           : pTerminator holds the terminator value
' Output    : Returns the length of the word array up to the terminator
' Notes     : Uses indirect addressing using ByRef and Ptr16
'
Proc LengthOf(ByRef pInAddress As Word, pTerminator As Word), Word
   Result = 0                   ' Clear the result of the procedure
   While                       ' Create an infinite loop
     '
     ' Increment up the array and exit the loop when the terminator is found
     '
     If Ptr16(pInAddress++) = pTerminator Then Break
     Inc Result                      ' Increment the count
  Wend
EndProc
'---------------------------------------------------------------------------
Main:
  RPOR7 = 3                        ' Make PPS Pin RP14 U1TX
'
' Find the length of a null terminated word array
'
  MyLength = LengthOf(MyArray, 0)
  HRSOutLn Dec MyLength
                                     ' Display the result on a serial terminal

See Also: Gosub, Sub…EndSub