![]() | ![]() | |||||||||||||||
|
Block Statements and SubprogramsSparForte scripts can be organized using declare blocks, procedures and functions. This enables pieces of a program to be easily reused. A procedure is a routine that can be called but returns no value. For example, put_line is a procedure. A function always returns a value so it can be used as part of an expression. strings.length is an example of a function which responds with the length of a string. Overall StructureAn AdaScript script consists of a sequence of executable statements. These statements can appear as a simple list or can be enclosed in a "library" unit. The basic library unit is a main procedure (or sometimes called a main program or main subprogram). Other library units may be introduced in the future (such as packages). If pragma ada_95 is used, the statements must be enclosed in a library unit. Some features may not be available with a simple list of statements. Declare BlockDeclare blocks (also called block statements) contains a sequence of statements or commands that can include locally declared variables. Declare blocks are located in the executable part of a script. Between declare and begin, declarations can be made. Between begin and end are executable statements. The declarations are visible to these executable statements. A new block can be created without declaration any
variables by using begin...end without the declare section.
declare
Example: The Declare Block Statement
Procedure and Function BlocksRepeatable blocks of a series of instructions (like Perl sub or Python def) can be created with the word procedure or function. A procedure is a set of instructions with a name. A function is a set of instructions with a name that computes and returns a value and can be used in an expression. Like a declare block, local variables can be declared before the word begin. Procedure and function subprograms must finish with end and the name of the subprogram: this is to clarify the structure of the program. Ada: In Ada, the name of the subprogram is optional after end. In AdaScript, the name is required.
procedure print_title is
Example: The Procedure Subprogram Statement
Procedures and functions may be nested: you can declare them in the declaration parts of another procedure, function or declare block. These nested subprograms only exist for the scope of this parent block. A procedure may be terminated early using a return statement. A function uses return to return back a value. Ada: AdaScript doesn't support creating new arithmetic operators by defining functions with operator symbols. Procedure and Function ParametersBoth procedures and functions can have parameters. If a procedure or function has no parameters, do not include any parantheses. If there are parameters, they are listed with a name, a mode and a type. By default, all parameters are "in" mode parameters: they give additional information to a subprogram and are treated as constants. The word "in" is optional before the type of parameter.
function add_two( number : integer ) return integer is
Example: The Function Subprogram Statement
Besides in mode parameters, parameters may also be out or in out mode. Out parameters return values, and in out read, modify and return values. These parameters may refer to arrays, records, array elements or record fields, in addition to the scalar types. Functions are not allowed to use out parameters. Ada: Ada does not permit functions to use in out mode parameters. Procedures and functions can only declared inside the declaration section of a script's main procedure block (or declared nested inside other subprograms or declare blocks). procedure my_script is
Example: A Main Program Procedure
That is, they must be in a script that has a main procedure block.
i : integer; The built-in procedures and functions found in the SparForte packages may include parameters with other modes. in out mode means the value of the parameter is used by the subprogram and may be changed. out mode means the parameter is not read by the subprogram but a value will be returned using the parameter. Functions may only use in mode. The modes are described on the front page of the Packages section of this documentation. Ada: access mode parameters are not supported for user-defined subprograms. Named parameters are not supported. Default values are not supported. Forward Subprograms and RecursionForward declarations and recursion are planned but not yet implemented. Separate SubprogramsProcedures and functions maybe loaded from a separate file. (This is referred to as a "subunit": a feature of a script stored in a separate file). Copy your subprogram (or create a new one) and put it in a file with the name of the subprogram. For example, if you have a separate procedure called "t2", put it in a file called "t2.sp". The filename must match the name of the subprogram. Separate subprograms must begin with a separate statement as the first line in the file. This indicates that the file is not an executable script. The separate statement should include the name of the parent script. Each separate subprogram belongs to a single, specific parent script.
-- t2.sp is a separate procedure
Example: t2.sp is a loadable by a script named t.sp
In the parent script (the one that will load the subprogram), declare the subprogram but replace the body of the subprogram with the word separate.
procedure t is
Example: t.sp loads t2.sp and executes t2
SparForte will search for the separate subprogram using the SparForte library path. The path is specified using the -L command option or using the environment variable SPAR_LIBRARY_PATH. By default, SparForte will search the current directory. The separate subprogram must exist and be readable in order to load it. In SparForte, procedures and functions can be nested. Support for separate nested subprograms is planned but not yet implemented. Separate subprogram blocks are similar to include files in other languages except that the separate block is a part of a specific main script. Ada: GCC Ada also has separate subunits. They are implemented in the same way. Separate DeclarationsA separate declaration file is the SparForte equivalent of an include file. It is an set of declaration statements stored in a separate file. The file can include variables, constants, types, functions, procedures, pragmas, etc. A declaration file is used to share common declarations across many scripts. The separate declaration file is inserted into another script using "with separate". Since the declaration file is inserted, they have the same scope as the declaration block they are used in. Any subscript pragmas will also affect the file loading the declaration file. The with separate statement can occur in a declaration section of any block (a main procedure, procedures, functions or a declare block).
procedure main is
Example: Loading a separate declaration file
Unlike separate procedures / functions, declaration files are not tied to a particular script. The subscript fragment must have "separate" as its first statement. This identifies it as a separate declaration file.
-- This is the file named globals.sp
Example: A very short separate declaration file containing one constant
Like separate subprograms, SparForte will search for the declaration file using the SparForte library path. The path is specified using the -L command option or using the environment variable SPAR_LIBRARY_PATH. By default, SparForte will search the current directory. The declaration file must exist and be readable in order to load it. The separate declaration file may contain more "with separate" statements. If the same file is included twice in the same scope, duplicate declaration errors will occur. Having a file include itself, or having a nested with separate include the file, will result in a loop and SparForte will report an error. Subscripts are loaded before a script starts execution. If you do something unusual such as to create a for loop containing a declare block with a "with separate", the with separate only executes once. However, the subprograms contained in the separate declaration file will access the new variable values as the for loop iterates, just as if they were declared without the with separate. Subscripts are permitted with pragma ada_95, even though they are not a part of the Ada 95 standard, to allow large scripts to be broken up. Subscripts are permitted in a restricted shell to allow large scripts to be broken up. Implementation Note: with separate has a string literal as a parameter. Because the separate file is loaded before the program is running, any variables that might contain the file path cannot exist when the file is loaded. So you're stuck with a string literal. Rationale: Subscripts are intended as a simple mechanism to break up large scripts until loadable user-defined packages are completed. ExceptionsProcedures, functions, declare blocks or main programs can have an exception handler. If an error or exception occurs, you can detect it and perform remedial action in the handler. Declaring ExceptionsExceptions can be declared by creating variables with the type of exception. They are not intended for reporting all errors, but errors that are rare or inconvenient to test for in the middle of a routine.
file_load_error : exception;
Example: An exception declaration
The execption type name may be followed with a "with/use". with specifies a default message to accompany the exception error message. use specifies a status code to return if the exception is raised to the main program and is not handled.
file_load_error : exception with "unable to load the file" use 15;
Example: An exception declaration with a with/use clause
The with/use clause is not available with pragma ada_95. Unlike other variables, two exceptions with the same name declared in overlapping scopes are not allowed. This is to make it easier to identify which exception was raised. For example, if you had a global exception named "disk_space_error" you cannot declare another "disk_space_error" in a procedure. Ada: Ada permits exceptions with the same name in overlapping scopes. It differentiates between them with dotted notation. Exception HandlersException handlers are created using an exception section. Once an exception handle runs, control is not returned to the block where the exception occurred: the exception handler replaces the remainder of the executable statements in the block. An exception handler is similar to a case statement. when sections contain the executble code to run in the case of a specific exception. If there is a when others section, it will run if none of the preceeding sections applied. when others will also handle most run-time errors.
procedure divide( x : integer; y : integer ) is
Example: Math errors like dividing by zero display "undefined"
Errors that occur during the syntax check when a program starts cannot be handled as the program is not running yet. A small number of errors, such as exceeding the number of variables the language can declare, cannot be handled, mainly because the run-time system is in a corrupted or uncertain state. If an exception handler occurs in a function, a function return can be placed in the handler. If a block has no exception handler, the enclosing blocks will be searched for a handler. (That is, the exception will propogate.) An exception handler can contain a declare/begin block with its own exception handlers. Re-raising ExceptionsThe raise command will propogate the exception after handling. That is, it will reinstate the exception to exception handlers in the surrounding blocks, just as if the exception was not handled.
procedure main_prog is
Example: Both exception handlers will run
Raising New ExceptionsThe raise command will raise user-declared exceptions. An alternate message can be given with a with clause.
raise file_load_error with "the customer file did not load";
Example: Raising and handling a user exception
raise can be used within an exception handler to raise a different exception. The with clause is not allowed with pragma ada_95. Profile FilesWhen SparForte is used as a login shell, it checks for the existence of two files: "/etc/sparforte_profile" and ".sparforte_profile" in the user's home directory. The first is a system-wide initialization file. The second is for initializing personal preferences. The personal file always run after the system-wide file. These are only read on login, or if SparForte simulates a login when it is started with --login. SparForte checks these files before opening them. They must meet the following conditions:
If a profile exists but doesn't meet these conditions, an error is reported and the profile file will not be run. The login session will be aborted. Policies and the Global Policy FileA policy is a special block. It contains a collection of pragmas that apply to a project. It may also contain static if or case statements (that is, with expressions that can be evaluated before the program is run) so that different pragmas can be applied in different situations. They are intended for use by architects. Policy blocks are named so that each block can be applied only once. An identifier already declared error will occur if the same block is applied twice. A policy block should appear before the main program. policy web_app_policy is
Example: A Simple Policy Block
There can also be a global policy file. When SparForte runs a script, it searches for a file called /etc/sparforte_policy. This is a system-wide initialization file, similar to a profile file. It's purpose is to setup any architectural pragmas common to all scripts on a server. The policy file is not executed for interactive sessions. The file is indended to be used by architects who maintain the standards and integration of different computer systems, separating their concerns from those of the programmers. SparForte checks this file before opening it. It must meet the following conditions:
If a policy file exists but doesn't meet these conditions, an error is reported and the file will not be run. The script will be aborted. A policy file may only contain pragma's. It cannot contain include files. Configuration Blocks and Global Configuration FileA configuration block is a special block. It contains a collection of declarations and pragmas at apply to a project. These are for describing environment settings such as server names, login credentials for services (such as databases) and so forth. The block is intended for use by system administrators. Configuration blocks are named so that each block can be applied only once. An identifier already declared error will occur if the same block is applied twice. A configuration block should appear before the main program. There can also be a global configuration file. After running any global policy file, SparForte searches for a file called . This is a system-wide initialization file containing a configuration block. The configuration file is not executed for interactive sessions. The file is intended to be used by system administrators who must maintain different enviroments, separating their concerns from those of the programmers. SparForte checks this file before opening it. It must meet the following conditions:
If a configuration file exists but doesn't meet these conditions, an error is reported and the file will not be run. The script will be aborted. A configuration file may only contain declarations. That is, it may contain variable declarations, constant declarations, type declarations, pragmas, function declarations or procedure declarations—anything which can be created in the declaration section of a subprogram. However, the content is mostly likely to be a group of constants. It cannot contain include files. -- Database settings for this server
Example: A Simple /etc/sparforte_config File
SparForte will not report an error if there are any unused variables from the configuration file. It is assumed that some declarations will not be used in some scripts. |
![]() Block Statements and Subprograms |
![]() |
![]() |