1 [DRAFT] AerScript Specification Aer#19 standard
Rafal Kupiec edited this page 2019-06-14 21:02:58 +02:00
This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

1. Introduction

The AerScript language specification is the definitive source for the language syntax and usage. This specification contains detailed information about all aspects of the language. AerScript has its roots in the C family of languages and will be immediately familiar to C, C++, C#, Java and PHP programmers. AerScript is standardized by CodingWorkshop as the Aer#19 standard. The Aer Interpreter is a conforming implementation of this standard.

AerScript is a simple, modern, general-purpose, object-oriented scripting language. Several AerScript features aid in the construction of web sites and robust scripts in any, inluding embedded environments: Garbage collection automatically reclaims memory occupied by unused objects; exception handling provides a structured and extensible approach to error detection and recovery; and strong type checking presents errors and enhances reliability.

2. Scope

This specification describes the form and establishes the interpretation of programs written in the AerScript language. It describes:

  • The representation of AerScript programs;
  • The syntax and constraints of the AerScript language;
  • The semantic rules for interpreting AerScript programs;
  • The restrictions and limits imposed by a conforming implementation of Aer Interpreter;

3. Terms and Definitions

  • Argument: an expression in the comma-separated list bounded by the parentheses in a method or instance constructor call expression. It is also known as an actual argument.
  • Behavior: external appearance or action.
  • Constraint: restriction, either syntactic or semantic, on how language elements can be used.
  • Deprecated: an informational message reported, that is intended to identify a use of deprecated language construct or feature.
  • Error: a condition in which the engine cannot continue executing the script and must terminate.
  • Exception: an error that is outside the ordinary expected behavior and can be caught by a user-defined handler.
  • Notice: an informational message informing user of the code that may not work as intended.
  • Parameter: a variable declared as part of a method, instance constructor, or indexer definition, which6acquires a value on entry to that method. It is also known as formal parameter.
  • PH7 Engine: the software including Virtual Machine, that executes an AerScript program.
  • Script: refers to one or more source files that are presented to the interpreter. Essentially, a script is the input to the interpreter.
  • Warning: an informational message reported, that is intended to identify a potentially questionable usage of a program element.
  • Value: a primitive unit of data operated by the Engine having a type and potentially other content depending on the type.

4. Notational conventions

Lexical and syntactic grammars for AerScript are interspersed throughout this specification. The lexical grammar defines how characters can be combined to form tokens, that is the minimal lexical elements of the language. The syntactic grammar defines how tokens can be combined to make valid AerScript programs.

4.1. Scripts

A script is an ordered sequence of UTF-8 characters. Typically, a script has a one-to-one correspondence with a file in a file system, but this correspondence is not required. AerScript scripts are parsed as a series of 8-bit bytes, rather than code points from Unicode or any other character repertoire. Within this specification, bytes are represented by their ASCII interpretations where these are printable characters. Conceptually speaking, a script is translated using the following steps:

  • Lexical analysis, which translates a stream of input characters into a stream of tokens.
  • Syntactic analysis, which translates the stream of tokens into executable code.

Conforming implementations must accept scripts encoded with the UTF-8 encoding form (as defined by the Unicode standard), and transform them into a sequence of characters. This means that any UTF-8 encoded natural language (i.e: Japanese, Chinese, Arabic, etc.) can be used for writing scripts. Implementations can choose to accept and transform additional character encoding schemes.

4.2. Lexical analysis

The input production defines the lexical structure of an AerScript source file. Each source file in an AerScript application must conform to this lexical grammar production.

Four basic elements make up the lexical structure of an AerScript source file: Line terminators, white space, comments, and tokens. Of these basic elements, only tokens are significant in the syntactic grammar of an AerScript program.

4.2.1. Comments

Two forms of comments are supported:

  • delimited comments,
  • single-line comments.

Single-line comments start with the characters // or # and extend to the end of the source line. The trailing new line can be ommitted. Delimited comments start with the characters /* and end with the characters */. Delimited comments may span multiple lines. Example:

# This is a single line comment
// This is another single line comment
/* This is a 
   multi-line comment block */

A delimited comment can occur in any place in a script in which white space can occur. During tokenizing, an implementation can treat a delimited comment as though it was a white space.

4.2.2. White space

White space is defined as any character with Unicode class Zs (which includes the space character) as well as the horizontal tab character, the vertical tab character, and the form feed character. White space in AerScript is used to separate tokens in the source file. It is used to improve the readability of the source code. The amount of space put between tokens is irrelevant for the Aer Interpreter. It is based on the preferences and the style of a programmer. Two statements can be put into one line, as well as one statement into several lines. Source code should be readable for humans and makes no difference to the Interpreter.

4.2.3. Tokens

There are several kinds of tokens: identifiers, keywords, literals, operators, and punctuators. White space and comments are not tokens, though they act as separators for tokens.

token
    : identifier
    | keyword
    | NULL_literal
    | boolean_literal
    | integer_literal
    | real_literal
    | character_literal
    | string_literal
    | interpolated_string_literal
    | operator_or_punctuator
    ;

3.3.1 Literals

A literal is any notation for representing a value within the Aer source code. Technically, a literal is assigned a value at compile time, while a variable is assigned at runtime. Aer supports:

  • boolean literal (can be true or false),
  • integer literal (can be decimal and hexadecimal),
  • real literal (used to write values of float type),
  • character literal (represents a single character),
  • string literal (zero or more characters enclosed in single or double quotes),
  • NULL literal (represents a null value)

3.3.2 Operators and punctators

There are several kinds of operators and punctuators. Operators are used in expressions to describe operations involving one or more operands. Punctuators are for grouping and separating.

      • / % ++ -- = += -= *= /= .= %= == != >< > < >= <= && || ! & ^ ^^ | ~ . << >> , :: ( ) [ ] { } -> : ? =>

X.Y.Z Identifiers

3.3.3 Keywords

A keyword is a reserved word in the Aer language. Keywords are used to perform a specific task in a computer program; for example, print a value, do repetitive tasks, or perform logical operations. A programmer cannot use a keyword as an ordinary variable.

Available keywords: break, case, catch, class, clone, const, continue, default, do, else, elseif, extends, final, finally, for, foreach, if, implements, in, interface, instanceof, namespace, new, private, protected, public, static, switch, throw, try, using, virtual, while

Next we have other language constructs: define() empty(), exit(), eval(), import(), include(), isset(), list(), require(), return(), print()

3.3.4 Semicolon

A semicolon is used to mark the end of a statement in Aer language. It is mandatory.

3.3.5 Aer Variables

A variable is an identifier, which holds a value. In programming we say that we assign a value to a variable. Technically speaking, a variable is a reference to a computer memory, where the value is stored. In Aer language, a variable can hold a string, a number, or various objects like a function or a class. Variables can be assigned different values over time. Variables in Aer consist of the $ character, called a sigil, and a label. A label can be created from alphanumeric characters and an underscore _ character. A variable cannot begin with a number.

3.3.6 Aer Constants

A constant is an identifier for a value which cannot change during the execution of the script. Constants are created with the define() function. Constants differ from variables; is is impossible to assign a different value to an existing constant.

4. Basic concept

4.1. Script startup

Aer is an interpreted language, thus a program or script does not have to be compiled as an application that may be started. An interpreted program shall contain exactly one method qualifying as an entry point by satisfying the following requirements:

  • It has to be a method called main() of class named Program,
  • The return type shall be void or int,
  • It shall not be a partial method without an implementation,
  • The formal parameter list shall either be empty, or have a single value parameter of type string[], Additionally, if Program class implements a constructor, it will be optionally called before main() method.

4.2. Script termination

If the return type of the script's entry point method is int, the value returned serves as the scripts's termination status code. The purpose of this code is to allow communication of success or failure to the execution environment. If the return type of the entry point method is void, reaching the right brace (}) that terminates that method, or executing a return statement that has no expression, results in a termination status code of 0.

4.3. Console Output

Output from Aer scripts is sent to the console is CLI SAPI is being used. If same script is launched when using CGI or FastCGI SAPIs, the output will be sent to the browser.

print('Hello world from Aer');

The print keyword does not add a new line to the output, script author has to put it manually.

4.4. Command-line Arguments

Aer scripts can receive command line arguments. They follow the name of the program. To access them, the main class constructor has to take a string[] argument. It is an array holding all arguments of a script to provide the program some values at the moment of execution. To check the number of parameters passed, sizeof() builtin function should be used.

4.5. Declarations

Declarations in a Aer script define the constituent elements of the program. Type declarations are used to define classes, structs, interfaces and enums. The kinds of members permitted in a type declaration depend on the form of the type declaration. For instance, class declarations can contain declarations for constants, properties, methods, instance constructors and destructors. A declaration defines a name in the declaration space to which the declaration belongs. It is a compile-time error to have two or more declarations that introduce members with the same name in a declaration space, except in the following cases:

  • Two or more namespace declarations with the same name are allowed in the same declaration space. Such namespace declarations are aggregated to form a single logical namespace and share a single declaration space.
  • Two or more methods with the same name but distinct signatures are allowed in the same declaration space.

4.6. Aer Types

Aer provides a set of predefined types called the simple types. The simple types are identified through keywords:

  • bool
  • callback
  • char
  • float
  • int
  • mixed
  • object
  • resource
  • string
  • void

4.7. Variable Interpolation

Variable interpolation is replacing variables with their values inside string literals. Another names for variable interpolation are: variable substitution or variable expansion.

int $age = 20;
print("I'm $age years old.");

In above example, the $age variable is replaced with the value 20 in the string enclosed by double quotes. However, this does not work if single quotes are used. In this case, no interpolation happens and no special characters are working.

4.8. Including Files

Aer code can be split in multiple files for bigger scripts. There are two statements in Aer, which allows to join various Aer files:

  • include()
  • require()

The include() function includes and evaluates the specified file during the execution of the script. Files are included based on the file path given or, if none is given the include_path specified. If the file isn't found in the include_path include() will finally check in the calling script's own directory and the current working directory before failing. The include() construct will emit a warning if it cannot find a file.

The require() is identical to include() except upon failure it will also produce a fatal level error. In other words, it will halt the script whereas include() only emits a warning which allowsthe script to continue.

Both of above listed builtin functions can be called only from methods.

4.9. Loading modules

AerScript is divided into dynamically loadable modules. Each module can be loaded on runtime by using an import() builtin function. It returns TRUE on success or if the given module is already loaded. FALSE is returned on failure.

5. Data Types & Pseudo Types

5.1. Boolean Values

The bool type represents Boolean logical quantities. The possible values of type bool are TRUE and FALSE. In Aer, a zero integral or floating-point value, or a null pointer can be converted to the Boolean value FALSE, and a non-zero integral or floating-point value, or a non-null pointer can be converted to the Boolean value TRUE.

5.2. Callback Values

Callbacks can be denoted in Aer language by callback type hint. This pseudo-type is used mostly for anonymous functions.

callback $callme = int() {
    return 7;
}
int $var = $callme(); // value is 7

What is more, Aer allows a language constructs in the context of a function call:

callback $echo = 'print';
$echo('Hello world'); // Calls the print function on the fly

5.3. Character Values

The char type holds a single character. The first 128 code points (0127) of Unicode correspond to the letters and symbols on a standard U.S. keyboard. These first 128 code points are the same as those the ASCII character set defines. The second 128 code points (128255) represent special characters, such as Latin-based alphabet letters, accents, currency symbols, and fractions.

5.4. Floating-point Values

Aer supports one floating-point type. The float type is represented using the 64-bit double-precision. It can represent values ranging from approximately 5.0 × 10324 to 1.7 × 10308 with a precision of 1516 digits.

5.5. Integer Values

Aer have standardized integers, which are stored in 8 bytes (64 bits) regardless of the host environment. Because there is no cross-platform way to specify 64-bit integer types Aer includes typedefs for 64-bit signed integers. In Aer, the int type can store integer values between -9223372036854775808 and +9223372036854775807 inclusive.

5.6. Mixed Values

Mixed pseudo-type indicates that a variable might accept multiple (but not necessarily all) types. It is not a primitive, and thus it cannot be used as typehints.

mixed $var;
$var = NULL;
var_dump($var); // NULL
$var = 'Test';
var_dump($var); // string(4) "Test"
$var = 7;
var_dump($var); // int(7)

5.7. Object Values

An object pseudo type is used for storing a pointer to the object.

object $system;
$system = new System();

5.8. Resource Values

A resource is a special variable, holding a reference to an external resource, like special handle to opened file, or database connection. Resources are created and used by special functions.

5.9. String Values

A string is series of characters. The simplest way to specify a string is to enclose it in single quotes. To specify a literal single quote, escape it with a backslash. To specify a literal backslash, double it. All other instances of backslash will be treated as a literal backslash: this means that the other escape sequences you might be used to, such as \r or \n, will be output literally as specified rather than having any special meaning. If the string is enclosed in double-quotes, Aer will interpret the following escape sequences for special characters:

  • ' - single quote
  • " - double quote
  • \ - backslash
  • $ - dollar sign
  • \0 - NULL
  • \a - alert
  • \b - backspace
  • \e - escape
  • \f - form feed
  • \n - new line
  • \r - carriage return
  • \t - hortizontal tab
  • \v - vertical tab
  • 0-7]{1,3} - the sequence of characters matching the regular expression is a character in octal notation, which silently overflows to fit in a byte (e.g. "\400" === "\000")
    
  • \x[0-9A-Fa-f]{1,2} - the sequence of characters matching the regular expression is a character in hexadecimal notation

When a string is specified in double quotes, variables are also parsed within it.

5.10. Void Values

Void is an empty data type and it is used as a return type of functions and methods that return no value. It is possible to declare a variable of void type, but it cannot store any value.

5.11. Null Values

Null is a special data type. Basically, the data type means non existent, not known or empty. In Aer, a variable is NULL in three cases:

  • it was not assigned a value
  • it was assigned a special NULL constant
  • it was unset with the unset() function

5.12. Arrays

Array is a complex data type which handles a collection of elements. Each of the elements can be accessed by an index. In Aer, just like in PHP, arrays are more complex. An array in Aer is actually an ordered map. A map is a type that associates values to keys. This type is optimized for several different uses; it can be treated as an array, list (vector), hash table (an implementation of a map), dictionary, collection, stack, queue, and probably more.

int[] $arr1;
int[] $arr2 = {0, 0}
$arr1 = {1, 2, 3, 4, 5};
$arr1[] = 6;
$arr1[] = {7};
$arr1[] = {'test' => 8};
$arr1[] = $arr2;
var_dump($arr1);

Above example will create a multi-dimensional associative array containing integers. The output of var_dump() function should return the following output:

array(9) {
    [0] => int(1),
    [1] => int(2),
    [2] => int(3),
    [3] => int(4),
    [4] => int(5),
    [5] => int(6),
    [6] => int(7),
    ["test"] => int(8),
    [7] => array(2) {
        [0] =>int(0),
        [1] => int(0),
    }
}

5.13. Type Casting

Type casting in Aer works much as it does in C/C++ - the name of the desired type is written in parentheses before the variable which is to be cast:

  • (bool) - casts to Boolean
  • (float) casts to Float
  • (int) - casts to Integer
  • (object) - casts to Object
  • (string) - casts to String

An example:

string $str = "45";
int $integer = 7 + (int) $str; // contains value: 52

5.14. References

References in Aer are a means to access the same variable content by different names. They are not like C pointers; for instance, they does not allow to perform pointer arithmetic using them, they are not actual memory addresses, and so on. Instead, they are symbol table aliases. There are two basic operations performed using references: passing by reference and returning by reference.

5.14.1. Return Reference

When a function returns a reference, it returns an implicit pointer to its return value. This way, a function can be used on the left side of an assignment statement.

int[] $table = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0};

int &refFunc(int $i) {
    return $table[$i];  // returns a reference to the ith element
}

5.14.2. Pass By Reference

This is done by making a local variable in a function and a variable in the calling scope referencing the same content.

int func(int &$val) {
    $val++;
}
int $var = 5;
func($var);
print("\$var = $var"); // outputs "$var = 6"

6. Operators

Expressions are constructed from operands and operators. The operators of an expression indicate which operations to apply to the operands. There are three kinds of operators:

  • Unary operators - the unary operators take one operand and use either prefix notation (such as $x) or postfix notation (such as $x++),
  • Binary operators - the binary operators take two operands and all use infix notation (such as $x + $y),
  • Ternary operator. Only one ternary operator, ?:, exists; it takes three operands and uses infix notation (c ? x : y). The order of evaluation of operators in an expression is determined by the precedence of the operators.

6.1. Operator Precedence

When an expression contains multiple operators, the precedence of the operators controls the order in which the individual operators are evaluated. The precedence of an operator is established by the definition of its associated grammar production. The following list shows common AerScript operators ordered by precedence (highest precedence first):

Precedence Description Operator Associativity
1 object-related clone new non-associative
2 postfix operators -> :: [ left-associative
3 increment / decrement ++ -- non-associative
4 unary operators - + ~ ! right-associative
4 cast operators (typedef) right-associative
7 object-related instanceof non-associative
7 arithmetic operators * / % left-associative
8 arithmetic operators + - left-associative
9 bitwise operators << >> left-associative
10 comparison < <= > >= non-associative
11 comparison == != === !== non-associative
12 bitwise and & left-associative
12 reference operator =& left-associative
13 bitwise xor ^ left-associative
14 bitwise or | left-associative
15 logical and && left-associative
16 logical xor ^^ left-associative
17 logical or || left-associative
18 ternary operator ? : left-associative
19 assignment operators = += -= *= /= %= right-associative
23 comma operator , left-associative

6.2. Associativity Rule

Sometimes the precedence is not satisfactory to determine the outcome of an expression. There is another rule called associativity. The associativity of operators determines the order of evaluation of operators with the same precedence level.

9 / 3 * 3

What is the outcome of this expression, 9 or 1? The multiplication, deletion, and the modulo operator are left to right associated. So the expression is evaluated this way: (9 / 3) * 3 and the result is 9. Arithmetic, boolean, relational, and bitwise operators are all left to right associated. On the other hand, the assignment operator is right associated.

6.3. Assignment Operator

The assignment operator = assigns a value to a variable. A variable is a placeholder for a value. In Aer, like in PHP or Perl, a variable begins with a $ character.

$x = 1;

6.4. Arithmetic Operators

Aer offers the following arithmetic operators:

  • Addition: +
  • Subtraction: -
  • Multiplication: *
  • Division: /
  • Modulo: %

6.5. Concatenating Strings

In Aer concatenating strings is nothing more than adding strings to each other with the addition operator.

string $str = "Hello" + ' ' + 'World!';

6.6. Boolean Operators

In Aer, there are and (&&), or (||), xor (^^) and negation (!) boolean operators. With boolean operators logical operations are performed. These are often used with if and while keywords.

6.7. Relational Operators

Relational operators are used to compare values. These operators always result in boolean value. Aer implements the following ones:

  • strictly less than: <
  • less than or equal to: <=
  • strictly greater than: >
  • greater than or equal to: >=
  • equal to: ==
  • not equal to: !=
  • identical: ===
  • not identical: !==

6.8. Bitwise Operators

Decimal numbers are natural to humans. Binary numbers are native to computers. Binary, octal, decimal or hexadecimal symbols are only notations of a number. Bitwise operators work with bits of a binary number. Aer also have binary logical operators and shift operators:

  • bitwise negation: ~
  • bitwise exclusive or (xor): ^
  • bitwise and: &
  • bitwise or: |
  • left shift: <<
  • right shift: >>

6.9. Compound Assignment Operators

The compound assignment operators consist of two operators. They are shorthand operators. The ccompound operators are: += -= *= /= %= &= |= ^= >>= <<=

6.10. Ternary Operator

Unlike the standard PHP engine, the ternary operator under Aer evaluates left-to-right, associates right-to-left. That is, there is no need for parenthesis for nested ternary operators.

string $var = true ? 'true' : false? 't' : 'f';
print($var);

The above expression in PHP will output 't' and this is an unexpected result, but if the same code run using the Aer will output 'true' as expected.

7. Flow Control

7.1. If Statement

The if statement has the following general form:

if (expression)
    statement

The if keyword is used to check if an expression is true. If it is true, a statement is then executed. The statement can be a single statement or a compound statement. A compound statement consists of multiple statements enclosed by curly brackets.

Often there is a need to execute a statement if a certain condition is met, and a different statement if the condition is not met. This is what else is for. Else extends an if statement to execute a statement in case the expression in the if statement evaluates to FALSE. For example, the following code would display a is greater than b if $a is greater than $b, and a is NOT greater than b otherwise:

if ($a > $b) {
    print("a is greater than b");
} else {
    print("a is NOT greater than b");
}

7.2. Switch Statement

The switch statement is a selection control flow statement. It allows the value of a variable or expression to control the flow of program execution via a multiway branch. It creates multiple branches in a simpler way than using the if, elseif statements. The switch statement works with two other keywords: case and break. The case keyword is used to test a label against a value from the round brackets. If the label equals to the value, the statement following the case is executed. The break keyword is used to jump out of the switch statement. There is an optional default statement. If none of the labels equals the value, the default statement is executed.

$domain = 'de';
switch ($domain) {
    case 'us':
        print("United States\n");
        break;
    case 'de':
        print("Germany\n");
        break;
    case 'sk':
        print("Slovakia\n");
        break;
    case 'pl':
        print("Poland\n");
        break;
    default:
        print("Other\n");
        break;
}

7.3. While Loop

The while is a control flow statement that allows code to be executed repeatedly based on a given boolean condition. This is the general form of the while loop:

while (expression):
    statement

The while loop executes the statement when the expression is evaluated to true. The statement is a simple statement terminated by a semicolon or a compound statement enclosed in curly brackets.

int $i = 0;
while ($i < 5) {
    print("Aer Language\n");
    $i++;
}

7.4. Do-While Loop

The do while loop is a version of the while loop. The difference is that this version is guaranteed to run at least once.

int $count = 0;
do {
    print("$count\n");
} while ($count != 0) 

In above example, first the iteration is executed and then the truth expression is evaluated.

7.5. For Loop

The for loop does the same thing as the while loop. Only it puts all three phases, initialization, testing and updating into one place, between the round brackets. It is mainly used when the number of iteration is know before entering the loop.

string[] $days = { "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", 
      "Saturday", "Sunday" };
int $len = sizeof($days);

for (int $i = 0; $i < $len; $i++) {
    print("$days[$i]\n");
}

The three phases are divided by semicolons. First, the $i counter is initiated. The initiation part takes place only once. Next, the test is conducted. If the result of the test is true, the statement is executed. Finally, the counter is incremented. This is one cycle. The for loop iterates until the test expression is false.

7.6. Foreach Loop

The foreach construct simplifies traversing over collections of data. It has no explicit counter. The foreach statement goes through the array one by one and the current value is copied to a variable defined in the construct. In Aer, it can be used to traverse over an array.

string[] $days = { "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", 
      "Saturday", "Sunday" };
string $day;
foreach ($day in $days) {
    print("$day\n");
}

The usage of the foreach statement is straightforward. The $days is the array that gets iterated through. The $day is the temporary variable that has the current value from the array. The foreach statement goes through all the days and prints them to the console.

There is another syntax of the foreach statement. Below form will additionally assign the current element's key to the $key variable on each iteration.

string[] $benelux =  { 'be' => 'Belgium', 'lu' => 'Luxembourgh', 'nl' => 'Netherlands' };
string $key, $value;
foreach ($key => $value in $benelux) {
    print("$key is $value\n");
}

7.7. Break & Continue Statements

The break statement is used to terminate the loop. The continue statement is used to skip a part of the loop and continue with the next iteration of the loop.

int $val;
while (true) {
    $val = rand(1, 30);
    print("$val ");
    if ($val == 22) {
        break;
    }
}

In above example, endless loop has been defined. There is only one way to jump out of a such loop—using the break statement. Above code assigns a random value from 1 to 30 and prints it. If the value equals to 22, script finishes the endless while loop.

int $num = 0;
while ($num < 1000) {
    $num++;
    if (($num % 2) == 0)
        continue;
    print("$num ");
}

Above example prints a list of numbers that cannot be divided by 2 without a remainder, during a while loop, which iterates through numbers from 1 to 999.

8. Functions

Aer is fully object-oriented programming language. However, it has a support for built-in functions. The built-in functions are part of the Aer language.

8.1. Anonymous Functions

Anonymous functions, also known as closures, allow the creation of functions which have no specified name. In Aer, anonymous function arguments can take a default value exactly like standard function arguments. The default value associated with the function argument can be any complex expression including function calls.

callback $anon = void(string $msg = 'Hello' + ' ' + 'World!' /* Complex expression */){
    print($msg + PS_EOL);
}; // semicolon is required here
$anon(); // You should see 'Hello World!'
$anon('Welcome guest!'); //You should see 'Welcome guest!'

Anonymous function can be defined in a method body. Unlike methods, a closures are limited to return only a primitive data types listed in chapter 4.6.

9. Static Variables & Constant

Aer lets use any complex expressions including method calls as an initialization values for your static variables and constants.

public void test() {
    /* Random number between 0 and 1023 as the initialization value for the static variable  */
    static int $salt = rand() & 0x3FF;
    /* Echo the random number and increment it's value by 1*/
    print($salt++ + "\n");
}

public void __construct() {
    /* Random string of length 6 for our test constant */
    const string MY_CONST = rand_str(6);
    $this->test(); /* a random number between 0 and 1023 [ex: 596 ] */
    $this->test(); /* 597 */
    $this->test(); /* 598 */
    print("MY_CONST value = " + MY_CONST);
}

In above example, the static variable $salt takes as its initialization value a random number between 0 and 1023 inclusive generated by the built-in rand() function while the constant MY_CONST takes at its initialization value a random string generated by the built-in rand_str() function. Also note that the 'const' construct can be used outside a class definition.

10. Object-Oriented Programming

There are three widely used programming paradigms there: procedural programming, functional programming, and object-oriented programming. Aer supports only object-oriented programming (OOP). This is a programming paradigm that uses objects and their interactions to design applications and computer programs. The basic programming concepts in OOP are:

  • Abstraction
  • Polymorphism
  • Encapsulation
  • Inheritance

10.1. Objects in AerScript

Objects are basic building blocks of a Aer script. An object is a combination of data and methods. In a OOP program, we create objects. These objects communicate together through methods. Each object can receive messages, send messages, and process data. There are two steps in creating an object. First, a class needs to be defined. A class is a template for an object. It is a blueprint which describes the state and behavior that the objects of the class all share. A class can be used to create many objects. Objects created at runtime from a class are called instances of that particular class.

class Demo { }
object $demo_object = new Demo();

10.2. Object Attributes

Object attributes are the data bundled in an instance of a class. The object attributes are called instance variables or member fields. An instance variable is a variable defined in a class, for which each object in the class has a separate copy.

class Person {
    public string $name = '';
}

class Program {
    public void main() {
        object $person1, $person2;

        $person1 = new Person();
        $person2 = new Person();
        $person1->name = "John";
        $person2->name = "Olivier";

        print("Hello $person1->name and $person2->name");
    }
}

In example above Person class contains one attribute - $name. This class has been instantiated twice and both objects contains different data stored.

10.3. Methods

Methods are functions defined inside the body of a class. They are used to perform operations with the attributes of objects. Methods are essential in encapsulation concept of the OOP paradigm.

class Circle {
    private float $radius;

    public void setRadius($radius) {
        $this->radius = $radius;
    }

    public float area() {
        return $this->radius * $this->radius * 3.14;
    }
}

class Program {
    public void main() {
        object $c = new Circle();
        $c->setRadius(5);
        print('Area is: ' . $c->area());
    }
}

Example above shows a Circle class. It contains one member field. It is the radius of the circle. The private keyword is an access specifier. It tells that the variable is accessible only from inside of the class. There are also 2 methods definition: area() and setRadius(). The $this keyword is a special variable which is used to access the member fields from methods. The area() method returns the area of a circle.

10.3.1 Return Keyword

The return keyword is used to return a value from the method. A method may or may not return a value.

10.3.2 Method Arguments

Most methods accept arguments. Arguments are values that are sent to the method. The methods process the values and possibly return some outcome.

void myFunc(string $who) {
    print('Hello ' + $who + ' from my first function!');
}

10.3.3 Implicit Values

The arguments in Aer methods may have implicit values. An implicit value is used if no value is provided. Aer lets use any complex expressions including built-in function or method calls, math or string expressions and so on as a default values for function arguments.

void test(string $name = 'Aer ' + rand_str(4), int $age = 10 * 2 + 5) {
    print("Name = $name\n");
    print("Age = $age\n");
}

10.4. Access Modifiers

Access modifiers set the visibility of methods and member fields. Aer implements three access modifiers: public, protected, and private. The public members can be accessed from anywhere. The protected members can be accessed only within the class itself and by inherited and parent classes. The private members may only be accessed by the class that defines the member. Access modifiers protect data against accidental modifications. They make the programs more robust.

class DemoClass {
    public float $real;
    protected string $text;
    private int $age;
}

class Demo extends DemoClass {}

In the above script, there are three member fields; one is declared public, second protected and the last as private. Public visible attribute can be modified from anywhere. Protected argument, from DemoClass and Demo classes. Private argument can be modified only from DemoClass. If there is no access modifier specified, public is assumed.

10.5. Method Overloading

Method overloading allows the creation of several methods with the same name which differ from each other in the type of the input. Aer implements a method overloading, well-known from languages like C#, Java or C++.

virtual class Test {
    virtual void function test();
    virtual void function test(int $var);
}

10.6. Constructors & Destructors

A constructor and destructor are a special kind of methods. Copnstructor is automatically called when the object is created. The purpose of the constructor is to initiate the state of the object. Destructor is automatically called when object is destroyed. The purpose of destructor is to close open handles (eg. close database connection).

class Demo {
    public void __construct() {
    }

    public void __destruct() {
    }
}

Both constructor and destructor methods cannot return any value. Declaring a constructor with access modifier other to public will make the class uninstantiable, as it will be unable call private or protected method from outside this class. Solution to this can be some additional method that will return instantiate the object and return it:

class Demo {
    private void __construct() {
    }

    public object instance() {
        return new Demo();
    }
}

10.7. Constructor Overloading

Aer supports constructor overloading like any other method.

10.8. Scope Resolution Operator

In computer programming, scope is an enclosing context where values and expressions are associated. The scope resolution operator helps to identify and specify the context to which an identifier refers, particularly by specifying a namespace. The specific uses vary across different programming languages with the notions of scoping. In Aer language the scope resolution operator is written "::".

10.9. Inheritance

The inheritance is a way to form new classes using classes that have already been defined. The newly formed classes are called derived classes, the classes that we derive from are called base classes. Important benefits of inheritance are code reuse and reduction of complexity of a program. The derived classes (descendants) override or extend the functionality of base classes (ancestors).

class Base {
    void __construct() {
        print('World!');
    }
}

class Derived extends Base {
    void __construct() {
        print('Hello ');
        parent::__construct();
    }
}

In this script, there are two classes: a Base class and a Derived class. The Derived class inherits from the Base class. In Aer, the extends keyword is used to create inheritance relations. In the constructor of the Derived class, we call the parent constructor. We use the parent keyword, followed by two colons and a method name. The constructors of the parent classes must be called explicitly. Output od the above example is "Hello World!'.

10.10. Multiple inheritance

When one class extends more than one classes then this is called multiple inheritance. For example if class Derived extends classes Base1 and Base2 then this type of inheritance is known as multiple inheritance:

class Base1 {}
class Base2 {}
class Derived extends Base1, Base2 {}

Multiple inheritance can lead to ambiguity. One of the example of such problem is the diamond problem that occurs in multiple inheritance. Aer tries to address this problem, thus supporting multiple inheritance only partially.

class Base1 {
    void funcA() {
        print('funcA from Base1');
    }
}

class Base2 {
    void funcB() {
        print('funcB from Base2');
    }
}

class Derived extends Base1, Base2 {
}

In above situation, class Derived inherits method funcA() from Base1 class, and method funcB() from Base2 class. However, only class Base1 is registered as direct base class. This means that only methods from class Base1 can be accessed by using parent operator. Because both method names are different, in this specific case both of them are accessible by using $this operator.

class Base1 {
    void funcA() {
        print('funcA from Base1. ');
    }
}

class Base2 {
    void funcA() {
        print('funcA from Base2. ');
    }
}

class Derived1 extends Base1, Base2 {
}

class Derived2 extends Base2, Base1 {
}

class Program {
    public void main() {
        object $a = new Derived1();
        object $b = new Derived2();
        $a->funcA();
        $b->funcA();
    }
}

The ordering occurrences of classes after the extends keyword has a major importance. Above example will "funcA from Base1. funcA from Base2.". This is because an instantiated object cannot inherit 2 methods with the same name. While, the first one is always valid, the second gets omited. It is also impossible to overload methods between derived classes.

10.11. Virtual Classes & Methods

Virtual classes cannot be instantiated. If a class contains at least one virtual method, it must be declared virtual too. Virtual methods cannot be implemented, they merely declare the methods' signatures. When a class inherits from a virtual class, all virtual methods must be implemented by the derived class. Furthermore, these methods must be declared with the same or with a less restricted visibility. Unlike interfaces, virtual classes may have methods with full implementation and may also have defined member fields. So virtual classes may provide a partial implementation.

virtual class Drawing {
    protected int $x = 0;
    protected int $y = 0;

    public abstract float area();

    public void getCoordinates() {
        print("\$x is $this->x\n");
        print("\$y is $this->y\n");
    }
}

class Circle extends Drawing {
    private int $radius;

    public void __construct(int $x, int $y, int $r) {
        $this->radius = $r;
        $this->x = $x;
        $this->y = $y;
    }

    public float area() {
        return $this->radius * $this->radius * 3.14;
    }
}

10.12. Magic Methods

When the print keyword is used with the object instance, the __toString() magic method is called.

10.13. Class Constants

Aer enables to create class constants. These constants do not belong to a concrete object. They belong to the class.

class Math {
    public const float PI = 3.14159265359;

    public float getPI() {
        print(self::PI);
    }
}

In above example, the const keyword is used to define a constant. Class constants are accessed from within methods using the self keyword followed by two colons.

10.14. Static Keyword

Aer allows to declare class properties and methods to be static. The static properties and methods do not belong to the instance of the class. They belong to the class itself. They are accessible through the scope resolution operator.

10.15. Final Keyword

Final methods cannot be overridden and final classes cannot be extended. The final keyword is a matter of design of the application. Some classes should not be extended and some methods should not be overridden. This behaviour is enforced by the final keyword.

10.16. Instanceof Keyword

The instanceof keyword is used to determine whether a variable is an instantiated object of a certain class.

object $obj = new MyClass();
if($obj instanceof MyClass) {
    print("\$obj is instance of MyClass");
}

10.17. Interfaces

Object interfaces allow to create code which specifies which methods a class must implement, without having to define how these methods are implemented. Interfaces are defined in the same way as a class, but with the interface keyword replacing the class keyword and without any of the methods having their contents defined. All methods declared in an interface must be public; this is the nature of an interface. Note that it is possible to declare a constructor in an interface, what can be useful in some contexts, e.g. for use by factories.

interface MyInterface {
    public void myFunction();
}

class MyClass implements MyInterface {
    public void myFunction() {
    }
}

10.18. Exceptions

Exceptions are designed to handle the occurrence of exceptions, special conditions that change the normal flow of program execution. Exceptions are raised or thrown and initiated. During the execution of script, many things might go wrong. A disk might get full and it might be unable to save a file. An Internet connection might go down while script tries to connect to a site. All these might result in a crash. To prevent happening this, script must cope with all possible errors that might occur. For this, thee exception handling can be used.

try {
    // some code to execute
} catch(Exception $e) {
    // code to execute when Exception is thrown
} finally {
    // code to execute regardless of whether an exception has been thrown
}

10.18.1. Catch Block

Multiple catch blocks can be used to catch different classes of exceptions. Normal execution (when no exception is thrown within the try block) will continue after that last catch block defined in sequence. Exceptions can be thrown (or re-thrown) within a catch block.

10.18.2 Finally Block

A finally block may also be specified after or instead of catch blocks. Code within the finally block will always be executed after the try and catch blocks, regardless of whether an exception has been thrown, and before normal execution resumes.