PMzone logo

Book cover

Project Guides


User Manuals

UNDER CONSTRUCTION

A programming language reference manual is one form of documentation that is associated with most mainstream programming languages. A reference manual is ordinarily separate and distinct from a programming language specification, which is usually more detailed and intended for use by implementors of the language itself, rather than those who simply use the language to accomplish some processing task. Jump to: navigation, search

Programming language documentation describes a single programming language. It's aimed at users of the language (opposite to Programming language specification which is more formal and targets implementers). Usually it is written by it's authors or developers or active participants during language development. Programming language documentation may exist in form of the websites, books (Programming language reference), etc.

In computing, a programming language specification (or standard or definition) is a documentation artifact that defines a programming language so that users and implementors can agree on what programs in that language mean. Specifications are typically detailed and formal, and primarily used by implementors, with users referring to them in case of ambiguity; the C++ specification is frequently cited by users, for instance, due to the complexity.

Related documentation includes a programming language reference, which is intended expressly for users, and a programming language rationale, which explains why the specification is written as it is; these are typically more informal than a specification.

A reference implementation is a single implementation of a programming language that is designated as authoritative. The behavior of this implementation is held to define the proper behavior of a program written in the language. This approach has several attractive properties. First, it is precise, and requires no human interpretation: disputes as to the meaning of a program can be settled simply by executing the program on the reference implementation (provided that the implementation behaves deterministically for that program).

On the other hand, defining language semantics through a reference implementation also has several potential drawbacks. Chief among them is that it conflates limitations of the reference implementation with properties of the language. For example, if the reference implementation has a bug, then that bug must be considered to be an authoritative behavior. Another drawback is that programs written in this language may rely on quirks in the reference implementation, hindering portability across different implementations.

Nevertheless, several languages have successfully used the reference implementation approach. For example, the Perl interpreter is considered to define the authoritative behavior of Perl programs. In the case of Perl, the Open Source model of software distribution has contributed to the fact that nobody has ever produced another implementation of the language, so the issues involved in using a reference implementation to define the language semantics are moot.

certificate

Adagé for Programmers

Project 3: Learn How to Write 64-Bit Windows Applications

This project is a hands-on introduction to the Ada programming language. Ada is a creative programming language developed as an experiment in overcoming the shortcomings inherent in currently available languages. As a practical software tool, Ada combines inline assembly language instructions with high-level source code to provide a readable, writable, and reliable programming language. Excerpts in the accompanying project guides are taken from the book, Adagé for Programmers, Volume 1, First Edition.

NOTE Adagé for Programmers and accompanying project guides are currently being written and tested. They are not yet available for release.

Adagé for Programmers

Good programming languages are concise. This means they include only the fundamental constructs to make programs work. To expand the functionality of the language, extensive component libraries should be provided. Useful libraries should (1) include text, numeric, and file input/output functions; (2) contain extensive math and text manipulation functions; (3) be reliable and efficient; (4) come with great documentation, and (5) be simple to implement.

An outstanding programming language gives users what they want; a language they will love. It is just as easy to design a good language as it is a bad one. The fundamental language itself should be concise, but include adequate library functions to expand its power. The manual should be short as well. A well-designed language does not need lengthy clarifications, numerous warnings, or lots of special case examples.

Overview

One hallmark of a cogent programming language is its user's manual. Adagé for Programmers is designed to assist users in learning how to build practical applications using the Adagé programming language. This straightforward guide covers the many detailed features of the Adagé programming language. It incorporates example programs accompanied by programming tips, recommended practices, and learning exercises to ensure a complete understanding of Adagé's range of features.

Page Top

Adagé Overview

This section provides an overview of the basic syntax used by Adagé. It provides a sense of the features expressed in the Adagé programming language with sufficient perspective necessary to understand the details in later sections of this web page.

Adagé is a 64-bit bi-level, general-purpose programming language with built-in verification capabilities. Adagé provides a structured programming environment with strong typing, program encapsulation, data abstraction, and high reliability. To facilitate these fundamental goals, Adagé employs a highly standardized, syntactically simple grammar designed to enhance readability and facilitate compiler development.

As with any imperative programming language, Adagé is focused on storing program instructions, declaring typed objects, elaborating and storing the objects as data, and then manipulating those data using type-specific operations. Adagé operations are further strengthened by the use of packages that separate interfaces from the implementation code and by employing contracts between software components to verify code correctness.

Adagé's bi-level structure offers two levels of program development. At the high level, Adagé's expressive syntax is specifically designed to free users from the intricate details of the underlying system architecture. At the low level, Adagé provides extensive features explicitly designed to allow direct access to system hardware and external libraries using native inline assembly language instructions.

Most importantly, Adagé is primary focused on producing correct, error-free code containing no user surprises. To this end, Adagé relies on ample quantities of memory space for key language structures to ensure accuracy, contextual language compliance, and program security. The following code stub depicts a simple program demonstrating some of Adagé's high-level syntax.

Listing 1. Sample High-Level Syntax
 1. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 2. ~ Simple program demonstrating Adagé syntax
 3. ~ Prints "Hello, World!" and 12345 to stdout
 4. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 5. import "text_io"                     ~ Import support routines
 6. procedure Greetings
 7.   var str : string = "Hello, world!" ~ Create string object
 8. begin
 9.   put (str); new_line                ~ Subprogram statements
10.   put (12345); new_line
11. end procedure
12. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Going through Listing 1 provides a quick look at the structure of an Adagé program. Lines 1 through 4 represent comments. Comments begin with the tilde (~) symbol. Line 5 informs the compiler that the program will be importing external code from a file named text_io. The imported code provides the program with routines to print text to the standard output device. Line 6 tells the compiler about a procedure called Greetings.

Line 7 creates a string type object in memory named str. By default, it sets aside memory space for up to 255 characters. The section between lines 8 and 11 is called the procedure body, or executable statements section of the procedure. This example program depicts four subprogram statements, two on line 9 and two on line 10. Multiple statements contained on the same line are separated by semi-colons. The four statements all call for output actions to the standard output device, which happens to be the screen.

Adagé programs are built out of declarations, statements, and comments, which consist of sequences of identifiers, symbols, and keywords. Notice that Adagé formats each line similar to the formatting found in most natural languages such as English. Semi-colons separate multiple statements written on the same line. Colons are used to separate identifiers from their type definitions. Colons and semi-colons are typically placed right after the clauses they offset, just as in natural languages.

White space such as tabs, spaces, and blank lines are used to improve readability. Note that spaces are required between identifiers, keywords, symbols, and number series. Spaces may be included within strings, but are not allowed within identifiers and keywords.

NOTE - With the exception of inline assembly language instructions and blank lines, every new line in Adagé begins with an identifier or comment.

Listing 2 shows Adagé's approach to low-level programming features. These features provide access to the underlying system hardware and to external library functions.

Listing 2. Sample Low-Level Syntax
 1. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 2. ~ Demonstrate how to incorporate inline assembly language code
 3. ~ Prints  "Hello, World!" to stdout
 4. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 5. asm
 6.   section .data
 7.   str db "Hello, world!\n",0
 8.
 9.   section .text
10.   extern _printf        ~ Make external library function visible
11.   text_io:              ~ Label denotes start of procedure
12.     mov rcx, str        ~ Address of str
13.     call _printf        ~ Execute library print routine
14.   ret                   ~ Return to caller
15. end asm
16. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Listing 2 shows an example of how assembly language instructions are employed in Adagé source code. Note that comments are stripped out of inline assembly language blocks during the scanning process while the remaining code is passed directly to the NASM assembler unchanged. Assembly language programming is the subject of another publication titled: Inline Assembly Language Programming. Therefore, inline assembly techniques will not be discussed here.

Page Top

Lexical Elements

The syntax of Adagé is described using a modified version of Backus-Naur Form commonly called BNF. Details concerning Adagé's syntax is covered in the Compiler Design and Development guide. We will use BNF syntax in discussing Adagé's lexical elements.

Character Set

Adagé programs are written as a sequence of lines composed of strings of text characters that form lexical elements called lexemes. The only characters allowed in Adagé programs are those corresponding to the basic ASCII character set, which comprises the 128 seven-bit ASCII characters. All Adagé programs can be written using this basic character set.

ASCII characters 0 to 31 and character 127 are non-printing and mostly obsolete control characters. With the exception of string and character literals, upper and lower case characters are generally considered the same in Adagé programs.

Figure 1. Adagé's 95 Printable ASCII Characters
upper case letters ::= A .. Z
lower case letters ::= a .. z
digits ::= 0 1 2 3 4 5 6 7 8 9
special characters ::= ~ ` ! @ # $ % ^ & * ( ) - _ + = { } [ ] | \ : ; " ' < > , . ? /
space characters ::= space tab blank_line

Adagé's syntax rules specify which lexemes are part of the language. Adagé's lexemes include: (1) user-defined identifiers, (2) special words, (3) literals, (4) white space, (5) special characters, and (6) comments.

Identifiers

Names, called identifiers, are used to identify variables, constants, subprograms, packages, and so forth. These are user-defined and must start with a letter and may be followed by zero, one, or more upper or lower case letters, single underlines, and digits. Punctuation characters such as %, @, $, and & are not allowed to be used as part of a name. An identifier name cannot end with an underline nor can an underline be the only character. Identifiers must be separated by spaces and cannot contain any spaces within their names.

Figure 2. Examples of Legal and Illegal Identifiers
  LEGAL IDENTIFIERS       ILLEGAL IDENTIFIERS
  Add_Two_Numbers         Add__Two__Numbers    ~ Cannot use two adjacent underlines
  P25_Units               25_Units             ~ Cannot use a digit as the first character
  ReturnVal               RETURN               ~ Cannot use stand-alone reserved words
  My_3_Variables          My#3Variables:       ~ Cannot use symbols other than underlines
  x_1                     _                    ~ Cannot use single stand-alone underlines
  Div_by_Two              _Div_by_Two          ~ Cannot use an underline as the first character
  Big_Definition          Big_Definition_      ~ Cannot use an underline as the last character
  A315_Vectors            A315 Vectors         ~ Cannot use spaces within a name

Special Words

Adagé has a number of named identifiers that convey special meaning and are used as part of its syntax to make programs more readable by naming actions to be performed. Adagé has two kinds of special words: (1) reserved words and (2) keywords.

Reserved Words

Reserved words cannot be used by programmers as user-defined identifiers, names of packages, or names of subprograms.

Figure 3. Adagé's 53 Reserved Words
abort and array asm begin case const declare do else elsif end exit for function goto if in import interface is loop mutex new next not of or others out package pointer pragma private procedure record return step subtype then this thread to type until use when while with xor choose redim var at body bool character exception enum export float generic iif (select) integer limited method null protected raise range rem reverse select separate some static string tagged terminate vector
Keywords

Adagé's syntax also contains a number of keywords that have special meaning only in certain contexts. Generally, predefined keywords can be used as user-defined identifiers unless a program unit in which they are defined is made visible. This is done using the IMPORT reserved word. Once imported, Adagé keywords cannot be redefined.

Figure 4. Adagé's Keywords
abs acos asc asin atan atod atof atoi atou bsearch ceil chr close cls color com copy cos cosh create date dictionary directory dtoa eof eol exp exp2 exp10 extleft extright file find floor flt free ftoa get hex int isalpha isctrl isdigit iseof iseol islower ispunct isspace istab isupper itoa leaf len loc locate log log2 log10 ltrim node open play pos printer put qsort rand read redim seed seek remove restore rtrim sgn sin sinh split sqrt strcat strchr strcmp strcpy strlen strig system tan tanh time timer tolower toupper trim utoa val variant verify wait window write
Case Sensitivity

THIS SECTION IS UNDER CONSTRUCTION

Adagé identifiers, including reserved words and keywords, are case-insensitive. This means named objects may contain a mix of upper and lower case characters. Names differing only in the upper and lower case letters, in corresponding positions, are considered identical. That is, Adagé treats MyString the same as mystring.

Literals

THIS SECTION IS UNDER CONSTRUCTION

A literal is a syntax format for representing a fixed value in source code. When defined, literals become constant values of the type being represented and cannot be redefined during program execution. Adagé defines four literal types: (1) numeric, (2) character, (3) string, and (4) Boolean.

Numeric Literals

THIS SECTION IS UNDER CONSTRUCTION

Adagé uses two classes of numeric literals to represent numbers. They are (1) discrete and (2) real. All numeric literals begin with a digit or alternatively with a plus or minus sign followed by one or more digits. Isolated commas may be inserted between adjacent digits to facilitate ease of reading. Real literals include a decimal point while integers do not. Numeric literals cannot contain symbols or spaces other than decimals, commas, and exponential notations.

Numeric literals may contain an exponent indicating a power of ten by which the value of the literal is to be multiplied to obtain a value without the exponent. Base 10 exponents are denoted by the use of either the "e" or "E" character followed by the integer value of the exponent. Regular exponents are denoted using the carat ^ symbol. Note that integer values cannot contain a negative exponent because that would infer a floating point number. The exponent part of a numeric literal cannot contain any commas. The following numeric literals are permitted by Adagé.

Figure 5. Numeric Literal Examples
-15             ~ Negative integer type
123e5           ~ Integer value with base 10 exponent of 5
10,525,697,134  ~ Integer value with commas
1.923,756E+305  ~ Floating point type with commas
125,505.99      ~ Decimal type with commas
4^2             ~ Integer value to the power of 2
5.0 + 0.0j      ~ Complex number expression
NOTE - Adagé allows commas to be used as separators in numeric literals to enhance readability. For this reason, a series of individual numbers must be separated by white space.
Figure 6. Numbers with Commas versus a List of Numbers
123,456,789    ~ Nine-digit number
123, 456, 789  ~ Series of three separate numbers
Character Literals

THIS SECTION IS UNDER CONSTRUCTION

Character literals are formed by enclosing a character within single quotes ('). Examples of character literals are shown here.

Figure 7. Character Literal Examples
'A'  ~ ASCII character A
' '  ~ ASCII space character
'&'  ~ ASCII ampersand &
String Literals

THIS SECTION IS UNDER CONSTRUCTION

Strings represent arrays of printable characters including spaces enclosed in double quotes "". They may also contain just one character or may be null. All Adagé strings must fit onto a single line. Concatenation, denoted by the & symbol, is used to represent strings longer then one line.

Figure 8. String Literal Examples
"A typical string enclosed in double quotes."        ~ Typical string format
"This is a very big and very long string that" &     ~ String concatenation
" only shows how to combine two lines of strings."
" "  ~ Space
""   ~ Null string
"A quoted phrase \"index\" and a newline \n"         ~ Embedded escape sequences

Adagé allows control characters to be embedded in strings through the use of escape sequences. Escape sequences begin with the backslash \ symbol.

Figure 9. Adagé's Escape Sequences
Sequence  Meaning              Sequence  Meaning
   \b     Backspace               \\     Backslash
   \f     Form feed               \'     Single quote
   \n     Newline                 \"     Double quote
   \r     Carriage return         \0     End of string
   \t     Horizontal tab          \xnn   Hex value nn 
Boolean Literals

THIS SECTION IS UNDER CONSTRUCTION

The values FALSE and TRUE are also treated as literals in Adagé programs. Examples of Boolean literals are shown here.

Figure 10. Boolean Literal Examples
finished : bool = true  ~ Assign true to finished
on_off : bool = false   ~ Assign false to on_off

White Space

THIS SECTION IS UNDER CONSTRUCTION

White Space consists of spaces, horizontal tabs, vertical tabs, blank lines, and end of line (EOL) markers. The compiler is insensitive to white space and except for spaces contained in quoted strings, generally ignores white space. White space is used to improve program readability and delineate identifiers and symbols.

Figure 11. Example Uses of White Space
index : integer       ~ White space between colon and expressions
index: integer        ~ Same as above; note colon position
put (100) ; new_line  ~ White space between semi-colon and expressions
put (100); new_line   ~ Same as above; note semi-colon position
BigArray [100]        ~ White space between identifier and bracket symbol
BigArray[100]         ~ Same as above; note bracket position
                      ~ Blank lines are ignored by the compiler
put ("Hello world!")  ~ White space in quoted strings are meaningful
    x = index + rate  ~ Tabs that begin new lines are ignored by the compiler
a = b * c             ~ Note white space around the equal and multiplication signs
NOTE - Adagé allows semi-colons, colons, parentheses, and brackets to be placed next to the left-hand clause. This is perfectly acceptable and is allowed so that programmers used to coding in this style can do so without causing exceptions.

Special Characters

THIS SECTION IS UNDER CONSTRUCTION

Special characters are sequences of one or more characters used to separate independent parts of statements. Adagé's special characters are referred to as delimiters. Adagé utilizes two forms of delimiters: (1) single-character and (2) compound.

Single-Character Delimiters

THIS SECTION IS UNDER CONSTRUCTION

Single-character delimiters are composed of a single character. Single-character delimiters with their names are shown in the following figure.

Figure 12. Single-Character Delimiters
Symbol  Name                      Symbol  Name               Symbol  Name
  ~     tilde, comment               )     rparen               :     colon
  `     grave, backquote             _     underline            ;     semicolon
  !     exclamation, bitwise_not     -     hyphen, minus        "     quote, double_quote
  @     at_sign                      +     plus                 '     apostrophe, single_quote
  #     sharp                        =     equal, assignment    <     langle, less_than
  $     dollar                       {     lbrace               >     rangle, greater_than
  %     percent, modulus, remainder  }     rbrace               ,     comma
  ^     circumflex, exponent         [     lbracket             .     period, decimal, dot
  &     ampersand, concatenate       ]     rbracket             ?     question
  *     asterisk, multiply ×         |     bar, bitwise_or      /     slash, divide ÷
  (     lparen                       \     backslash, escape          

The following examples show how single-character delimiters are used.

Figure 13. Examples of Single-Character Delimiters in Use
var x, y, z : float = 0.0      ~ Commas followed by white space separate variable fields
const pi : float = 3.14        ~ Colons separate object names from their type-definitions
put (12345); new_line          ~ Semi-colons separate multiple program statements
MyChr : char = 'A'             ~ Single quotes contain character types
type BigArray is array [10]    ~ Brackets contain array indices
type WeekEnd is {Sat, Sun}     ~ Braces contain aggregate names separated by commas and white space
procedure AddNum (x : integer) ~ Parentheses contain subprogram parameter information
index = rate / 100             ~ Arithmetic and assignment symbols separated by white space
Compound Delimiters

THIS SECTION IS UNDER CONSTRUCTION

Compound delimiters are composed of two adjacent special characters. Adagé's compound delimiters are shown here with their names.

Figure 14. Compound Delimiters
Symbol  Name                   Symbol  Name
  =>    arrow, choose            <=    less_than_or_equal ≤
  ..    range                    >=    greater_than_or_equal ≥
  ~#    aspect_clause            <<    bit_shift_left
  ==    equal_to                 >>    bit_shift_right
  !=    not_equal_to ≠           <>    box
  &&    bitwise_and              ||    bitwise_xor

Compound delimiters are typically used as shown here.

Figure 15. Examples of Compound Delimiters in Use
if x >= y then statement                        ~ Greater_than_or_equal ≥
while index != false do                         ~ Not_equal_to ≠
procedure Area (x => in length, y => in width)  ~ Arrow =>
~# global big_number                            ~ Aspect clause ~#
x = y && z                                      ~ Bitwise_and &&

Comments

THIS SECTION IS UNDER CONSTRUCTION

Comments begin with the tilde (~) symbol and can contain zero or more characters. Adagé uses the tilde symbol in order to avoid overloading other symbols such as the asterisk (*), forward slash (/), reverse slash (\), double slash (//), grave (`), and double hyphens (--), which are often used by other languages. Since comments terminate at the end of the line, they cannot extend over multiple lines.

Figure 16. Examples of Comments
~~~~~~~~~~~~~~~~~~~~~~~~~ Comment forming a line
~ Line containing a standalone comment
index : integer = 100  ~ Comment following a statement
~ constant pi : float = 3.14159 is a standalone comment and not a declaration
Page Top

Data Type System

THIS SECTION IS UNDER CONSTRUCTION

Adagé data types define the format and size of data stored in computer memory and are characterized by a set of values and a set of operations. This allows programmers to create powerful abstractions that represent real world problems. Adagé provides a standard syntax for defining types and associating them with objects. Strict type checking is implemented to ensure prohibited language implementations of data types are reported as early as possible.

Adagé's data type system adheres to the following contextual rules:

  1. All objects must belong to a defined type or subtype
  2. All objects are either variables or constants
  3. Every type and subtype must have a name; anonymous composite types are not allowed
  4. Predefined types belong to hypothetical system base types and need not be explicitly declared
  5. User-defined types must be explicitly declared before they can be elaborated
  6. Every type must be elaborated before an object representing that type can be placed into memory, initialized, and used in a program
  7. Constraints are not allowed in the declarations of objects
  8. Types with different names are incompatible with one another and cannot be mixed
  9. Variables of different types are incompatible with one another and cannot be mixed
  10. Subtypes are compatible with their base types and other subtypes of the same base type
  11. Variables of subtypes of the same base type are compatible with one another

Adagé implements two kinds of data types: (1) predefined and (2) user-defined. Predefined types represent a set of primitive data types that are essentially built into the Adagé programming language. They are reflective of the hardware architecture and include scalar and text types. The benefit of predefined data types is that they do not need to be explicitly declared before they are elaborated and used in a program. Predefined types are defined in Adagé's standard library package.

User-defined types represent more complex data types that are built up from predefined data types. They must be explicitly declared before they can be elaborated and used in a program. User-defined types include composite, structure, and reference types. The next figure portrays Adagé's data types.

Figure 17. Adagé Types

Data Objects

THIS SECTION IS UNDER CONSTRUCTION

The data that takes up actual storage locations in memory are called objects. Every object has a name called an identifier that references its computer memory address. Every object has an associated type that determines the range of values the object can store in memory and the set of operations explicitly defined for values of the type. Every object has a related storage class that establishes its lifetime. Finally, every object has a scope defined by where in the program the object is declared and depending on its storage class.

The rules governing Adagé's type system specify that every object:

Adagé provides two fundamental kinds of objects: (1) variables and (2) constants. Objects are created (elaborated) by means of declarations. When declared, objects are assigned a memory location of a specific size based on its type. Objects are initialized with a value constrained by its range of allowable values. Variable objects may be assigned different values at different times during program execution. The values of constant objects are set when defined and cannot be changed during program execution.

Variables and constants both store data. The difference between them is that the data stored in a variable can be changed during program execution, whereas the data stored in a constant cannot. Both must be declared as a specific type, but only the constant requires a value (the data) to be assigned (initialized) when it is declared. In Ada, variables and constants are actually called objects. This has nothing to do with object oriented programming. A variable in Ada is an object that has been declared as a given type and with an optional initial value. A constant is the same, except the declaration now contains the reserved word constant and the initial value is no longer optional, but required. Both variables and constants are declared in the declarative part of a block. More can be read about the structure of an Ada program here.

Note that Adagé objects must be declared, elaborated, and initialized before they can be used. Variable and constant declarations must be declared in the declaration section of a program unit.

Variables

THIS SECTION IS UNDER CONSTRUCTION

Variables represent abstractions of computer memory and are declared using the VAR reserved word. Values consistent with the variable's type may be assigned to it in the body of a program. New values assigned to variables simply replace whatever value was previously assigned. A variable is declared like this:

var name: type = value

Variable_Name : Variable_Type [:=Optional Value]

The reserved word VAR declares the object to be a variable. NAME is an identifier that names the object and links it to the memory location of the stored data. TYPE defines the type that the variable will have during program execution. VALUE represents an optional initial value assigned to the object. Here are examples of variable object declarations.

var x : integer = 500  ~ Declare single initialized variable object
var x, y, z : float    ~ Declare multiple uninitialized variable objects
Variable Storage Class

THIS SECTION IS UNDER CONSTRUCTION

Variables come into existence only when the program reaches the line of code where they are declared. Depending on their type, appropriate storage space is set aside in memory. Variables go out of existence when the program leaves the scope of the variable; i.e., they are no longer accessible to a program unit. Variables become initialized when values are explicitly assigned.

Note that Adagé does not automatically initialize variables to zero or any other value. Evidence seems to indicate that automatically initializing variables often results in the unintentional use of invalid values in computations. This could cause hard-to-trace program errors or errors to occur that are never detected. For this reason, Adagé prefers to report uninitialized variables as early as possible instead of automatically initializing them.

Adagé employs four storage classes: (1) stack, (2) heap, (3) register, and (4) static. Variables declared within subprograms are usually stored on the stack. These are considered local variables that exist only during subprogram execution. Variables declared dynamically such as pointers, trees, dictionaries, temporary strings, etc., are generally placed on the heap. The heap is a managed section of memory used to store dynamic objects. Heap variables only exist as long as the structures such as procedures and functions that define them exist. Variables used for such things as indexes and counters are typically placed in a CPU register. Register variables exist only as long as the flow structures such as loops execute. Static variables persist throughout the lifetime of the program.

Constants and Static Expressions

THIS SECTION IS UNDER CONSTRUCTION

The reserved word CONST declares the object to be a constant. A constant is an object that has an assigned value that cannot be changed during program execution. Constant declarations look just like variable declarations except that the reserved word CONST is used in the declaration instead of VAR. Objects declared as constants must be initialized with a static expression whose value is known at compile time. The syntax of a constant declaration is

Constants are an important tool to help make your programs more reliable and maintainable. A constant is, just like a variable, a reference to a specific type of data, but where they differ from variables is in their constant nature. Variables vary, constants are constant. When declared and initialized, the data they reference is static and can no longer be altered. If you try to alter a constant, the compiler will complain, loudly.

const name : type = static_expression

The reserved word CONST declares the object to be a constant. NAME is an identifier that refers to the memory location of the stored data object. TYPE defines the type that the constant represents. STATIC_EXPRESSION represents a mandatory assignment of a static value. Example constant object declarations look like the following

const index : integer = 500                ~ Constant object of type integer
const pi : float = 3.1416                  ~ Constant object of type float
const prompt : string = "Type a number: "  ~ Constant object of type string
const P : integer = index + 1              ~ Constant object using a static expression
const CR : char = '\n'                     ~ Constant object of type char

Note that it makes sense that constants can represent only predefined scalar and string types such as integer, float, string, and char. All constants are static. This means all Adagé constant expressions must evaluate to a constant value during compilation. During program execution, they become read-only. A constant expression cannot contain the name of a variable, a function call other than a call of a predefined operator or attribute, an indexed component, or a composite data type.

Constant Storage Class

THIS SECTION IS UNDER CONSTRUCTION

Note that all constants have a static storage class and persist throughout the lifetime of the program. An error will be reported for any constant that is not assigned a static value or expression when declared. An error will also result if an attempt is made to alter the value of a constant during program execution. Adagé treats constant declarations similar to preprocessor commands such as #define used by other languages.

Data Operations

THIS SECTION IS UNDER CONSTRUCTION

The operations that can be performed on different kinds of objects depends on their type definition. Scalar data types can be used with the relational operators ==, !=, <, <=, >, and >= and the arithmetic operators +, -, *, /, and ^. Discrete types can be used with the additional arithmetic operators % and REM. The following example shows how Adagé employs operators.

z = 250  ~ Assignment operator
a + b    ~ Plus arithmetic operator
x != y   ~ Not_equal_to relational operator
m^n      ~ Exponential operator
x % y    ~ Integer modulo operator

Data Attributes

THIS SECTION IS UNDER CONSTRUCTION

Attributes are predefined characteristics of named types and objects. Some attributes are functions and play an important role in the manipulation of scalar and discrete data types. Attributes are formed by appending an attribute designator to the object separated by a grave symbol (`). The grave symbol is used so as not to overload other symbols such as the quote ('), dot (.), or colon (:) and to make attribute definitions look different from dot notation. There are a number of built-in attributes defined in Adagé, the following are some examples:

name`first  ~ Yields the value of the lower bound of an array or enumeration list
name`last   ~ Yields the value of the upper bound of an array or enumeration list
name`len    ~ Yields the length of a string not including the terminating zero
name`size   ~ Yields the size in bytes of an object's reserved memory space
name`pos    ~ Yields the position of an enumeration identifier in a list
name`val    ~ Yields the value of an enumeration identifier in a list
name`pred   ~ Yields the identifier preceding the named identifier
name`succ   ~ Yields the identifier succeeding the named identifier

Adagé Type Declarations

THIS SECTION IS UNDER CONSTRUCTION

Every built-in type defined by Adagé syntax is considered to be declared in the package STANDARD, which is imported into every Adagé program. In Adagé, every type declaration introduces a new type, which is distinct from any other type. The set of values belonging to two distinct types are also distinct from each other. By design, values of different types cannot be assigned to variables of another type. Adagé's strong typing ensures that assignment of incompatible types is reported.

Adagé provides two built-in types: (1) primitive and (2) composite. Primitive types include integer, modular, enum, float, decimal, and pointer. Composite types include records and arrays. Adagé's type declaration syntax takes the form

type name is type-definition

Adagé uses a different format for declaring types than it uses for declaring objects. This is to emphasize the conceptual difference between the two declarations. The reserved word TYPE is followed by the identifier name to be associated with the type, the reserved word IS, and then the TYPE-DEFINITION. Type declarations can be written like

type aircraft is {Beechcraft, Cessna, Cirrus, Mooney, Piper}
type count is integer {0 to 100}
type sales is array [count] of aircraft

Notice that the information after the reserved word IS gives a list of literal values belonging to each type. Also, the first declaration states that there are five values belonging to the type aircraft. The second declaration introduces a completely new type, which contains 100 values belonging to the type count. As discussed previously, objects of both types can be declared in the following way.

var A : aircraft  ~ Declare object A as type aircraft
var C : count     ~ Declare object C as type count

Since both declarations introduce completely different types, values of one type cannot be assigned to variables of another type. Therefore, they cannot be mixed as shown in the following example.

var I    : integer
var A, B : aircraft
var C    : count
...
~ Illegal assignment of incompatible types
I = C
C = A
A = I
...
~ Legal assignment of compatible types
I = 1000
A = Cessna
B = A       ~ A and B have values of Cessna
C = C`last  ~ Assigns 100 to C

Adagé will report an error when it detects any attempt at assigning incompatible types during compilation. Strong typing used in the manner shown in the last example is designed to ensure that only similar types can be mixed in order to avoid incorrect programs.


Adagé Subtype Declarations

THIS SECTION IS UNDER CONSTRUCTION

Adagé subtypes represent subsets of values of base types. Although a subtype can represent a complete set of a base type, they are normally used to form constraints of base types. Constraints take various forms according the category of the base type. Although subtypes can constrain the range base type values, they cannot restrict the set of operations of base types. Subtypes assumes all the operations allowed by base types because subtyping only applies to the values of the base type. The following template shows how subtypes are declared.

subtype name is type-definition

For instance, the following example employs a subtype declaration of a base type.

type planets is {Mercury, Venus, earth, Mars, Jupiter, Saturn, Uranus, Neptune}  ~ Base type
subtype gas_planet is {Jupiter, Saturn}  ~ Subtype with constraints
var G : gas_planet                       ~ Variable elaboration of subtype

The compiler will now ensure that only Jupiter or Saturn can be assigned to variable G. If, as an example, a program attempts to assign Venus to G, a CONSTRAINT_ERROR will be raised.

Note that subtype declarations do not introduce new distinct types. As depicted in the next example, an object such as X, which is of type integer, can be assigned a value of another type that is of type integer.

subtype days_of_the_year is integer {1 to 365}
var D : days_of_the_year
var I : integer = 10
var J : integer = 500
...
D = I  ~ Perfectly legal assignment
D = J  ~ Raises a constraint error, D only accepts values in the range 1 to 365

Type Equivalence

THIS SECTION IS UNDER CONSTRUCTION

Name equivalence.

Adagé contains two classes of data: (1) primitive data types consisting of scalar and discrete data types and (2) composite data types. These types are built in as part of the language and need not be defined by the user.

Scalar Data Types

THIS SECTION IS UNDER CONSTRUCTION

Scalar types describe ordered values. Two predefined attributes, called FIRST and LAST, return the lowest and highest values respectively for the named object. Adagé provides two kinds of scalar types: (1) float and (2) decimal.

Float Types

THIS SECTION IS UNDER CONSTRUCTION

Adagé's predefined FLOAT type is a subset of real numbers and is represented using floating point notation. All Adagé floating point types must contain a decimal point, at least one digit to the left and right of the decimal, and an optional exponential integer value denoted with an exponent symbol e | E. Commas may be used in the significand to enhance readability. The purpose of floating point types is to extend the range of values that can be represented in computations.

Floats are stored using 64-bits where bits 0 through 51 contain the significand value, bits 52 through 62 hold the exponent, and bit 63 contains the sign value where 0 denotes a positive value and 1 denotes a negative value. As a result, type float has 53 bits of precision expressed in 16 digits of accuracy. The definition of the predefined type float is shown here:

type float is {float`first to float`last}
  where: float`first = ±2.225073858507201e-308
         float`last  = ±1.797693134862316e+308

Examples of a float type declaration and elaborated variables are shown here:

type flt is float {0 to 1.234567890e308}  ~ Constrained float type declaration
  var width: flt = 1.123e45               ~ Initialized variable of type flt
  var length: flt                         ~ Uninitialized variable of type flt
var height: float = 123,456,789e15        ~ Anonymous float type

Note that variables width and length are of the same type. This means width = length is a legal assignment. However, width = height is not legal because variables width and height are not of the same type even though they both represent floating point values.

Floating point values that underflow or overflow the allowable minimum and maximum values for float types will cause program execution to halt and an underflow/overflow error message to be reported. Likewise, any values that exceed user-defined range specifiers such as {-1.5 to 1.5}, will cause program execution to halt and a bounds error to be reported. Finally, any attempt to divide by zero will result in program execution being halted and a divide by zero error message to be reported. However, underflow/overflow and divide_by_zero pragmas can be set so that instead of halting program execution, the compiler substitutes float`first or float`last when an underflow or overflow condition exists or cause a zero to be returned in the case of a divide by zero condition.

Decimal Types

THIS SECTION IS UNDER CONSTRUCTION

Adagé's predefined DECIMAL type is a subset of real numbers and is represented using fixed-point notation. All Adagé decimal types must contain a decimal point, at least one digit to the left of the decimal, and exactly two digits to the right of the decimal. Decimal types do not contain exponents like the float type. Commas may be used in the significand to enhance readability. The purpose of decimal types is to provide accurate financial calculations.

Fixed-point types consist of two components: (1) significand and (2) fractional part. The significand is stored as a 64-bit signed integer type where the most significant bit (bit 63) represents the sign of the number. This means that the significand part provides 63 bits of precision expressed in up to 19 digits of accuracy. The fractional part has a range of 0 to 99 and does not suffer from loss of accuracy due to rounding. The definition of the predefined decimal type is shown here:

type decimal is {decimal`first to decimal`last}
  where: decimal`first = -9,223,372,036,854,775,808.99 
         decimal`last  = +9,223,372,036,854,775,807.99

Examples of a decimal type declaration and elaborated variables are shown here:

type dec is decimal {-100.00 to 125,696,781.25}  ~ Constrained decimal type
  var a : dec = 15.25                            ~ Initialized decimal variable of type dec
  var b : dec                                    ~ Uninitialized decimal variable of type dec
var big_decimal : decimal = 715,884,105,727.18   ~ Anonymous decimal type

Decimal values that underflow or overflow the allowable minimum and maximum values for decimal types will cause program execution to halt and an underflow/overflow error message to be reported. Likewise, any values that exceed user-defined range specifiers such as {-100.0 to 125676781.25}, will cause program execution to halt and a bounds error to be reported. Finally, any attempt to divide by zero will result in program execution being halted and a divide by zero error message to be reported. However, the underflow/overflow and divide_by_zero pragmas can be set so that instead of halting program execution, the compiler substitutes decimal`first or decimal`last when an underflow or overflow condition exists or return a zero in the case of a divide by zero condition.

Discrete Data Types

THIS SECTION IS UNDER CONSTRUCTION

In addition to being ordered, discrete data types provide a finite set of unique predecessor and successor identifiers. This gives discrete types an explicit first and last value in each set of identifiers. Each value other than the first has a unique predecessor, and each value other than the last has a unique successor. A value is greater than its predecessor and less than its successor. Identifier names in an enumerated list are called aggregates or aggregate elements. Adagé discrete types include: (1) ENUM, (2) BOOL, (3) CHAR, (4) INTEGER, and (5) modular types.

Enumeration Types

Adagé's ENUM type represents an ordered list of user-defined integer constants taking the form of literal identifiers or characters. The set of permissible values are known as enumerators. The order relationship among the literals of an enumeration type is fixed when the type is declared.

The purpose of enumeration types is to provide a means for defining a type by listing identifiers for all the values in a defined set. This improves readability and reliability because identifier names are easily recognized. Basically, enumeration identifiers act like type-safe constants. The definition of the predefined enumeration type is shown here.

type name is {literala, ..., literaln}
where: name`first = literala  ~ Value of left-most position in a list
       name`last  = literaln  ~ Value of right-most position in a list
Enumeration Aggregates

THIS SECTION IS UNDER CONSTRUCTION

Positional lists of enumerated literals are called aggregates. Aggregates represent a collection of one or more identifiers or characters. Inclusive literals are enclosed in braces and separated by commas. The individual literals of an aggregate list are ordinal in that they are positional in nature. This means the left-most literal, in position 0, is lower in value than its successor values to the right. The right-most literal, in position n, has the highest value. A typical declaration of an enumeration type and elaborated variables are shown here:

type weekdays is {Mon, Tue, Wed, Thr, Fri}  ~ Mon = 0, Tue = 1, Wed = 2, Thr = 3, Fri = 4
var today: weekdays = Mon                   ~ Initialized enum variable of type weekdays
var workday: weekdays                       ~ Uninitialized enum variable of type weekdays
workday = today                             ~ Legal assignment, both are of the same type

Note that enumerated identifiers are case insensitive so that "mon" has the same meaning as "Mon". Literal names in any given list may not be repeated. Technically, there is no upper limit on the number of literals that can be included in a list, but there must be at least one. An empty enumeration type is not allowed. User-defined enumeration types typically contain only a small number of identifiers.

Adagé also allows the internal codes used to represent enumeration literals to be specified using aggregate assignments. Internal codes must be integer values declared in the same order as they appear in the aggregate list, and they must be in ascending order. Aggregate assignment is shown in the following example:

type engine_hp is {           ~ Enumeration type with explicitly assigned values
  model_10 = 100
  model_20 = 205
  model_30 = 308 }
var hp: engine_hp = model_20  ~ hp`val = model_20; hp`pos = 205

Adagé does not allow overloading of enumeration literals within the same scope. The following example shows that the literal Saturn is used in two different declarations in the same scope.

type automobile is {Focus, Impala, Saturn, Buick}
type planets is {Mercury, Venus, earth, Mars, Jupiter, Saturn, Uranus, Neptune}
var gas_planet : planets = Saturn  ~ Illegal declaration because Saturn is ambiguous

In order to use duplicate literal names like Saturn belonging to different types in the same scope, they must both appear using fully qualified names like as shown next.

var gmc: automobile = automobile.Staturn  ~ Fully qualified name
var gas_planet: planets                   ~ Declare variable of type planets
  gas_planet = planets.Saturn             ~ Fully qualified name
var color: enum = blue, green, red, yellow  ~ Anonymous enum type
Boolean Types

THIS SECTION IS UNDER CONSTRUCTION

Adagé provides two predefined enumeration types: BOOL and CHAR. The predefined BOOL type can only have one of two possible values: FALSE or TRUE. Boolean 0 typically refers to logical false while true is always a non-zero value. The purpose of Boolean types is to represent flags that can be used to provide flow control within programs. Boolean types also enhance readability because they convey better meaning than do integer alternatives. Here is the definition of the predefined bool type:

type bool is {FALSE, TRUE}  ~ Predefined enumeration type
  where: bool`first = false
         bool`last  = true
Character Types

THIS SECTION IS UNDER CONSTRUCTION

Adagé's predefined CHAR type reflects the sequence of characters enumerated in the ASCII character set. Characters are enclosed in single quotes and are stored in memory as single bytes. The purpose of character types is to provide a flexible means of processing single character codes that can be converted to numeric values when needed. Here is the definition of the predefined char type:

type char is {ASCII_char`first to ASCII_char`last}  ~ Predefined enumeration type
  where: ASCII_char`first = chr (0)
         ASCII_char`last  = chr (127)

Examples of a char type declaration and elaboration are shown here:

type ch is char {'a', 'e', 'i', 'o', 'u'}  ~ Constrained char type declaration
  var vowel: ch = 'e'                      ~ Initialized ch variable
  var vow: ch                              ~ Uninitialized ch variable
Integer Types

THIS SECTION IS UNDER CONSTRUCTION

Adagé's INTEGER type represents a subset of whole numbers. Integers are 64-bit signed data types stored in twos complement format where the most significant bit (bit 63) represents the sign of the number. This allows Adagé integers to provide 63 bits of precision expressed in up to 19 digits of accuracy. Additionally, integer types can be used with the arithmetic operators +, -, *, /, %, ^, and rem. The main purpose for integer types is to provide finite subscript indices in arrays, precise counters in iterative routines, clear-cut relational decisions in expressions, and accurate memory addressing and allocation. The definition of the predefined integer type is shown here.

type integer is {integer`first to integer`last}
  where: integer`first = -9,223,372,036,854,775,808
         integer`last  = +9,223,372,036,854,775,807

Examples of integer type declarations and elaboration are shown here:

type int_val is integer {-4^3 to 10,000}  ~ Constrained integer type declaration
  var x: int_val = 50                     ~ Initialized variable object
  var y: int_val                          ~ Uninitialized variable object
var natural: integer {0 to integer`last}  ~ Constrained integer variable

Integer values that underflow or overflow the allowable minimum and maximum values for integer types will cause program execution to halt and an underflow/overflow error message to be reported. Likewise, any values that exceed user-defined range specifiers such as {1 to 10000}, will cause program execution to halt and a bounds error to be reported. Finally, any attempt to divide by zero will cause program execution to halt and a divide by zero error message to be reported. However, the underflow/overflow and divide_by_zero pragmas can be set so that instead of halting program execution, the compiler substitutes integer`first or integer`last when an underflow or overflow condition exists or return a zero in the case of a divide by zero condition. The purpose of these pragmas are to keep the program from halting during critical operations.

Note that the type declaration in the previous set of examples defines a range constraint. For instance, the declaration for int_val defines it as type integer with values constrained to the range -4^3 to 10000. The next line elaborates a variable named "x" as an int_val type, which means it is allocated 8 bytes of memory space and is assigned an initial value of 50. The compiler will verify that any assignment to variable "x" is in the specified range -4^3 to 10000. Finally, notice that the natural represents an anonymous type. Anonymous types are definitions only and do not set aside memory space. Type definitions must be elaborated before they become useful in a program.

Modular Types

THIS SECTION IS UNDER CONSTRUCTION

Adagé's modular types are unsigned integer types that provide for cyclic computations. Although modular types represent unsigned integer types, they possess a special wrap-around property. That is, when a modular value reaches a maximum defined upper limit, the value wraps around to the lower limit. Conversely, when a modular value reaches a minimum defined lower limit, the value wraps around to the upper limit. The purpose of modular types is for use in hash tables, queues, indexes, compass bearings, time calculations, trigonometric functions, and so forth. The definition of the predefined modular type is shown here.

type modular is {modular`first to modular`last}
  where: modular`first = 0
         modular`last  = 18,446,744,073,709,551,615

A good example implementation of the modular type would be in computing compass bearings. Most compasses use a system of degrees that range from 0 degrees (North) to 359 degrees. It is useful that when a calculation reaches a heading of 359 degrees that it wrap back around to 0 degrees. Similarly, when a clock reaches 2400 hours, it should wrap back around to 0 hours and start over. Examples of modular type declarations and elaboration are shown here.

type time_val is modular {0 to 24}       ~ Constrained modular type declaration
  var x : time_val = 10                  ~ Initialized variable object
  var y : time_val                       ~ Uninitialized variable object
var index : modular {0 to modular`last}  ~ Constrained modular variable
var z : time_val = 26                    ~ z is assigned a value of 2 (26 % 24)
var z : time_val = -5                    ~ z is assigned a value of 19 (24 - (abs(-5) % 24))

Modular values have a second unique property in that they cannot underflow or overflow defined minimum and maximum values. However, any values that exceed user-defined range specifiers will cause program execution to halt and a bounds error to be reported. Finally, any attempt to divide by zero will cause program execution to halt and a divide by zero error message to be reported. However, the divide_by_zero pragma can be set so that instead of halting program execution, the compiler returns a zero in the case of a divide by zero condition. The purpose of the divide_by_zero pragma is to keep the program from halting during critical operations.

Base Notation

THIS SECTION IS UNDER CONSTRUCTION

Numeric literals also can be written in base 2 (binary), base 8 (octal), and base 16 (hexadecimal). Numbers using a base other than 10 must begin with a zero. Following the zero, binary numbers are represented using the "b" infix symbol, octal numbers use the "o" infix symbol while hexadecimal numbers use the "x" infix symbol. Underscores can be interspersed within adjacent digits to make reading easier. Number representations A through F can be in upper or lower case. Here are some examples of base representations:

0b10111001          ~ Base 2 (binary) representation
0o15.0              ~ Base 8 (octal) representation
0xFF23_A3B4         ~ Base 16 (hexadecimal) representation
0xff23_a3b4         ~ Same as previous representation
0x8000000000000000  ~ Integer`first in hexadecimal
0x7fffffffffffffff  ~ Integer`last in hexadecimal
0b10000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000  ~ Integer`first in binary
0b01111111_11111111_11111111_11111111_11111111_11111111_11111111_11111111  ~ Integer`last in binary

Composite Data Types

THIS SECTION IS UNDER CONSTRUCTION

Composite data types are variable constructs comprised of one or more primary data types grouped together in a single structure. The purpose of composite data types is to provide a method for managing multiple elements of related data using a single construct. Composite data objects are created (instantiated) by means of declarations similar to other variable objects. Adagé offers two kinds of composite data types: (1) arrays and (2) records.

Array Types

THIS SECTION IS UNDER CONSTRUCTION

Adagé array types represent simple data structures that hold multiple homogeneous data elements. Homogeneous means equally sized data elements of the same data type. Elements within an array are accessed using discrete (ordinal) indices. The lower bounds of Adagé arrays start at 0 by default. Adagé allows multi-dimensional arrays, although one and two dimensional arrays are the most common.

Adagé provides only constrained arrays. Constrained arrays require explicit static ranges to be assigned. Dynamic, or unconstrained, arrays are not allowed in Adagé because they are inherently unsecure and can't be validated during compilation. However, all arrays may be explicitly redimensioned (resized) during program execution. Definitions of the predefined array type are shown here:

type name is array [size] of type                        ~ Default lower bounds starts at 0
type name is array [lower_bound to upper_bound] of type  ~ Array with user-defined bounds
type name is array [index, index] of type                ~ Two-dimensional array

The reserved word ARRAY declares this composite data structure to be of type array. SIZE defines the number of individual elements that can be assigned to the array. Array sizes and bounds must be ordinal type values. TYPE defines the type of variable elements that will be contained within the array during program execution. Here are some examples of array types:

type small_array is array [9] of integer  ~ Array of 9 integer elements
type buffer is array [32767] of char      ~ Array of 32,767 char elements
type work_hrs is array [5] of week_days   ~ Array of an enumeration type containing 5 identifiers
Array Aggregates

THIS SECTION IS UNDER CONSTRUCTION

Array aggregates are used to initialize array objects and are represented by a collection of elements enclosed in braces. Braces are used so as not to overload other symbols such as brackets and parentheses. Braces also allow aggregate lists to span multiple lines. Here are some examples of array aggregates:

type tiny_array is array [5] of integer = {25, 10, 1, 0, 100}  ~ Five initialization values
type big_array is array [5000] of float = {=> 0.0}             ~ Initialize all array elements to 0.0
String Types

THIS SECTION IS UNDER CONSTRUCTION

Adagé strings are predefined homogeneous types representing an array of zero or more characters. A string array of zero characters is defined as the NULL string. Individual characters within a string are accessed using standard array indices. The default size of string arrays is 255 characters. User-defined ranges may be assigned. Unconstrained string arrays are not allowed by Adagé for security and validation reasons. Definitions of the predefined string type are shown here:

type name is string                               ~ Constrained string array of 255 characters
type name is string = "string"                    ~ String constant where size = number of characters
type name is string [size]                        ~ Constrained string array of size characters
type name is string [lower_bound to upper_bound]  ~ Constrained string array with a user-defined range

The reserved word STRING declares this composite data structure to be of type string. SIZE is a size specifier that sets the size of memory to be reserved for the string. Users may define the lower and upper bounds of a string, which allows for string slicing. String size specifiers and bounds must be ordinal type values. String declarations that do not contain any size specifier or initialization string in quotes defaults to a size of 255 characters.

String Aggregates

THIS SECTION IS UNDER CONSTRUCTION

String aggregates are used to initialize string objects and are represented by a sequence of zero or more characters enclosed in quotes " ". Quotes are used so as not to overload other symbols such as braces, brackets, parentheses, or apostrophes. Strings must fit on one line. The ampersand (&) may be used to catenate strings on multiple lines. Here are some examples of string aggregates:

var str1: string = "Adagé is fun!"       ~ Constant string with a size of 13 characters
var str2: string [20] = "Doe, John"      ~ Initialized string of up to 20 characters
var str3: string                         ~ Uninitialized string with default size of 255 characters
var empty: string = ""                   ~ Null string of zero size
type new_string is string [128]          ~ String type declaration
var s: new_string = "This is a string."  ~ Elaboration of s as a new_string type of up to 128 characters

The null string is often used to check if a string has been initialized. A string given in quotes with no size specifier defaults to a constant with a size equal to the number of characters. A variable defined as a string type with no size specifier or initializing string in quotes automatically sets aside 255 bytes of memory space. Non-constant strings with large size specifiers are designed to be flexible so that the characters in the string may be altered and the size of the string can shrink or grow as necessary within the range specified by size specifier.

Record Types

THIS SECTION IS UNDER CONSTRUCTION

Updating Gehani p18. heterogeneous types. A struct declaration consists of a list of fields, each of which can have any type. The total storage required for a struct object is the sum of the storage requirements of all the fields, plus any internal padding.

Discriminants => Spark2014 p56.

Record aggregates => Spark2014 p55.

Pointer Types

THIS SECTION IS UNDER CONSTRUCTION

Updating Gehani p21, Ada2012 p189.

Subtypes

THIS SECTION IS UNDER CONSTRUCTION

Updating Spark2014 p45.

Coersion and Conversion

THIS SECTION IS UNDER CONSTRUCTION

Updating Spark p120.

Page Top

Declarations

THIS SECTION IS UNDER CONSTRUCTION

Lexical elements are formed into declarations and expressions using Adagé's [EDIT...ADD SOME RELEVANT TEXT HERE].

Object Declarations

THIS SECTION IS UNDER CONSTRUCTION

Updating Gehani p5, Spark2014 p32.

Type Declarations

THIS SECTION IS UNDER CONSTRUCTION

Updating Gehani p8.

Page Top

Expressions

THIS SECTION IS UNDER CONSTRUCTION

TEXT

Static Expressions

THIS SECTION IS UNDER CONSTRUCTION

Updating Gehani p23, Spark p116.

Arithmetic Operators

THIS SECTION IS UNDER CONSTRUCTION

Updating Gehani p24, Spark p119.

Logical and Bitwise Operators

THIS SECTION IS UNDER CONSTRUCTION

Relational Operators

THIS SECTION IS UNDER CONSTRUCTION

Updating Gehani p26, Spark p118. Relational operators, also known as comparison operators, etc.

Page Top

Statements

THIS SECTION IS UNDER CONSTRUCTION

TEXT

Null Statement

THIS SECTION IS UNDER CONSTRUCTION

Updating Gehani p28, Ada95 p121.

Assignment

THIS SECTION IS UNDER CONSTRUCTION

Updating Gehani p28, Spark p126.

If-Then Statement

THIS SECTION IS UNDER CONSTRUCTION

Updating Gehani p29, Spark p128.

Loops

THIS SECTION IS UNDER CONSTRUCTION

Updating Gehani p30, Spark p129.

Case Statement

THIS SECTION IS UNDER CONSTRUCTION

Updating Gehani p29.

Blocks

THIS SECTION IS UNDER CONSTRUCTION

Updating Gehani p32.

Exit

THIS SECTION IS UNDER CONSTRUCTION

Updating Gehani p33.

Return

THIS SECTION IS UNDER CONSTRUCTION

Updating Gehani p33, Spark p133.

Goto

THIS SECTION IS UNDER CONSTRUCTION

Updating Gehani p33.

Page Top

Subprograms

THIS SECTION IS UNDER CONSTRUCTION

Gehani p51, Ada2012 p161, Spark p33, 134, Spark2014 p27.

Variables

THIS SECTION IS UNDER CONSTRUCTION

[EDIT--NEED SOME SOLID EXPLAINING]. In contrast to literals, variables or constants are symbols that can take on one of a class of fixed values, the constant being constrained not to change. Literals are often used to initialize variables, for example, in the following, 1 is an integer literal and the three letter string in "cat" is a string literal.

Functions

THIS SECTION IS UNDER CONSTRUCTION

Updating Ada2012 p161, Spark p144, Spark2014 p31.

Procedures

THIS SECTION IS UNDER CONSTRUCTION

Ada2012 p171, Spark2014 p28.

Parameter Modes

THIS SECTION IS UNDER CONSTRUCTION

In Out In-Out Spark p35, Spark2014 p29.

Page Top

Exceptions

THIS SECTION IS UNDER CONSTRUCTION

Gehani p201.

Handling Exceptions

THIS SECTION IS UNDER CONSTRUCTION

Updating Ada2012 p361.

Declaring Exceptions

THIS SECTION IS UNDER CONSTRUCTION

class="magic"Updating Gehani p203, Ada2012 p364.

Raising Exceptions

THIS SECTION IS UNDER CONSTRUCTION

Updating Gehani p204.

Page Top

Packages

THIS SECTION IS UNDER CONSTRUCTION

Packages are the basic building blocks of Adagé programs. A package is a name space consisting of a collection of declarations including annotations, constants, variables, types, procedures, and functions. A package can makes its facilities available to other packages, called clients.

Packages are program units composed of two parts: (1) a public section and (2) a private section. The public section is called an interface and provides the specifications of the types and subprogram interfaces needed for clients to use the package. The private section, called a package body, contains the implementation details of the types, procedures, and functions that are hidden from clients. The term package refers to the interface specification and package body collectively.

Notice that the interface and package are two physically separate and vitally distinct sections. Together they provide modularity and extensibility. Unlike subprograms, packages do not exist primarily to be executed. Instead, they exist primarily for the facilities they provide for clients. Separate package files have the name of the package with an .lib extension. As an example, a package called Greetings would be stored in a file labeled greetings.lib. All package files are stored in the adage/library/ directory.

Spark p151.

Example of a Package

Interface

THIS SECTION IS UNDER CONSTRUCTION

The interface is the public section of the package. All declarations in the interface are visible to clients of the package. Interfaces use the following syntax:

interfaces package-name  -- Public section
  [imported packages]  -- Zero or more imported packages
  {declarations}       -- One or more declarations
end interface

Interfaces must start with the keyword INTERFACE and end with the keywords END INTERFACE>. Interfaces contain import and declaration (see Declarations) parts. Import statements must appear right after the INTERFACE keyword and before any declarations.

Listing 2 shows an example of an interface specification for a package called Add_Numbers:

-------------------------------------------------------
-- Listing 2. Interface for Package Add_Numbers
-- Make declarations visible to clients
-- Build as executable
-------------------------------------------------------
interface Add_Numbers
  import text_io, float_io
  function Add_2_Numbers (x, y: in float) return float
  procedure Print_Result (str: string)
end interface
-------------------------------------------------------

Notice how the interface in Listing 2 imports two support packages and defines a function and a procedure. Add_Numbers is the client of the two import packages text_io and float_io. The declarations in text_io and float_io are now visible to and directly usable by the package Add_Numbers.

Import Clause

THIS SECTION IS UNDER CONSTRUCTION

Adagé programs are written and compiled in a certain context. The context of a program determines what external elements are available to the program for its use. Clients can gain access to declarations in other packages by using the IMPORT context clause. For example, a main program unit cannot use the types, variables, functions, or procedures in another package such as the text_io and float_io packages previously shown until those packages are implicitly imported.

More than one package may be named on the same line by separating each package-name with a comma. It is mandatory to name imported packages in the package interface. However, Adagé rules state that if a package is imported into a named interface, by extension it is also imported into the associated named package whether or not the named package also imports the other package. Adagé rules also state that the effect of importing a package or library unit more than once is the same as importing it once. Therefore, it is not necessary to repeat the IMPORT statement in the package body when it is included in the package interface. Import statements use the following syntax to make packages visible to clients:

import package-name [, package-name]              -- Default location
or
import c:/documents/package-name [, package-name] -- User location

The compiler will search in the default directory for the imported package file. The default directory is adage/library/file-name. Alternatively, programmers can include a different directory for the compiler to search in by including a full search path. Once a package's declarations are imported, they are referenced by prefixing their names with the name of the imported package and a period. This is called dot notation or more formally, fully qualified reference. Examples of fully qualified reference conventions are shown here:

import text_io, integer_io         -- Imported packages
...
text_io.put ("This is a string.")  -- Fully qualified references must be used
integer_io.put (12345)

Use Clause [NOT USING THE USE CLAUSE

THIS SECTION IS UNDER CONSTRUCTION

[EDIT--ADAGE DOESN'T ALLOW THE USE CLAUSE]. Notice that when using declarations imported from another package, nonlocal declaration names must be qualified with the name of the package from which it was imported. To avoid having to use qualified references, the USE clause can be added to the context. If the USE clause is used, it is placed immediately after the IMPORT statement. The purpose of the USE clause is to make the names of declared elements in imported packages visible to the compiler. The format of the USE statement is shown here:

import package-name; use declaration-name

This form allows unqualified references to be used. An example of using this form is shown here:

import text_io; use put    -- Imported package and declaration
...
put ("This is a string.")  -- Unqualified references can be used

Notice that a when the USE statement is used, fully qualified references are not needed. However, unqualified references should be avoided whenever possible due to their propensity to obscure the origin of entities.

Implementation

THIS SECTION IS UNDER CONSTRUCTION

Updating. The syntax for interfaces and packages are written as follows:

package package-name    -- Private section
  declarations
  begin
    sequence of statements
end package

Packages must begin with the keyword package and end with the keywords end package.

-------------------------------------------------------
-- Listing 3. Package for Add_Numbers
-- Example Package Syntax
-- Build as executable
-------------------------------------------------------
package Add_Numbers
  var str: string "The answer is: "
  var temp: in out float
   
  function Add_2_Numbers (x, y: in float) return float
  begin
    temp = x + y
    return temp
  end function
    
  procedure Print_Result (str: string)
  begin
    text_io.put (str)
    float_io.put (temp)
    text_io.new_line
  end procedure
end package
-------------------------------------------------------

Annotations

THIS SECTION IS UNDER CONSTRUCTION

[Ada2012 p385].

Adagé's verification tools add contract type interfaces in the form of annotated comments. Annotations employ aspect clauses designed to support abstraction and static source code analysis. When fully implemented, Adagé tools will supersede the debugger as the primary provision for validating and verifying source code against the Adagé language standard. Annotated comments are denoted using the --# symbol. This way, annotated comments appear to be normal comments to the compiler. When the verification and validation tool, called Inspector, is executed, it recognizes annotated comments as contract type instructions.

Spark2014 p76 => Introduction to Contracts.

Aspect Specifications

THIS SECTION IS UNDER CONSTRUCTION

Ada2012 p385.

Global Clause

THIS SECTION IS UNDER CONSTRUCTION

Spark p138, OWN Spark p161.

Pre and Post Clause

THIS SECTION IS UNDER CONSTRUCTION

Ada2012 p388.

The following code snippet shows how annotated comments are used in an Adagé program.

 1. ----------------------------------------------------------------------------
 2. -- Listing 3. Adagé Annotated Comment Syntax
 3. -- Calculates total by adding tax to price
 4. ----------------------------------------------------------------------------
 5. interface Total_Cost                    -- Specification for the package
 6. --# global total: float                 -- Make package variables visible
 7.
 8.   procedure Compute_Cost (price: in float)
 9.   --# global out total                  -- total is write only
10.   --# pre in price > 0.0                -- Pre-condition check
11.   --# post out total > 0.0              -- Post-condition check
12. end interface
13.
14. package Total_Cost
15.   var total: float
16.
17.   procedure Compute_Cost (price: in float)
18.     var tax: float
18.   begin
20.     tax = price * 0.05                  -- Compute tax
21.     total = price + tax                 -- Compute total
22.   end procedure
23. end package
24. -----------------------------------------------------------------------------

Listing 3 demonstrates how annotated comments are employed in an Adagé program. Notice that annotations are applied in the interface and not in the package. However, related refinement annotations may be placed in corresponding packages as necessary. Use of the GLOBAL clause means that the listed objects are located in the package. The PRE clause is a pre-condition that explicitly tells Inspector to check that input prices are greater than 0.0. The POST clause is a post-condition that explicitly tells Inspector to check that the final value of total is greater than 0.0.

Page Top

Object Oriented Programming

THIS SECTION IS UNDER CONSTRUCTION

Text.

Type Extension

THIS SECTION IS UNDER CONSTRUCTION

Updating Ada2012 p301.

Page Top

Pragmas

THIS SECTION IS UNDER CONSTRUCTION

More discussion to come as the Ada user's manual project progresses.

Page Top

© 1997-2017 Transtar Management Services, Inc. All rights reserved. Terms of Use