Parsing

File

Railroad diagram for file

While previously the smallest unit of code was the script, the new source format and compiler works on a basis of files. Each file contains a package declaration, and a single object definition.

Objects

Railroad diagram for object definitions

An object is a collection of features, functions and scripts. These may be defined in any order.

Features

Railroad diagram for features

A feature defines an attribute on the object being defined. Like a variable declaration, a function definition includes a type which should be respected by any functions on the object, and by any child objects. The default value for a feature should also match its type.

Functions

Railroad diagram for function

There are a few additional restrictions on function declarations that are not present in the current compiler:

Scripts

Railroad diagram for script

Script Body:

Railroad diagram for file

A script is composed of zero or more Statements, followed by zero or more Function Definitions. If there are any Statements outside of a formal function declaration, they will be wrapped in an implicit function that takes no arguments.

When a Script is invoked, either by another Script or by the executing environment, the first function (implicit or explicit) is called, with the parameters being passed to the Script being passed to the function.

Function Definition

Railroad diagram for function definitions

Function Arguments:

Railroad diagram for function arguments

Function Argument

Railroad diagram for function argument

A function definition optionally specifies the return type of the function. If none is provided, ’Dynamic‘ is assumed. The definition must provide a name for the function, followed by an open parenthesis, and the formal parameters to the function if any.

Each parameter may provide a type (dynamic if omitted), and a default value. This default value can be an arbitrary expression, which is evaluated on function entry. After a default value is provided for a parameter, all following parameters must also have default values. The parameter list may also end with an ellipsis, which indicates a variadic function. In this case, the complete list of parameters passed to the function can be accessed using the Parameters() built-in function.

Because OScript does not prevent variables from sharing names with types, one can easily have a function signature in a script that looks like
Function Void foo( Integer )
This looks like a function that takes one Integer parameter that lacks a name, but in fact is a function that takes one Dynamic parameter named Integer.

Statements

Railroad diagram for statements

Functions are composed of one or more statements, which are detailed here.

goto and Labels

Railroad diagram for labels Railroad diagram for goto

The goto command will cause program flow to jump to the specified label in the current function. Although jumping out of loops is legal, attempting to jump into a loop is illegal.

if statements

Railroad diagram for if statements

The if statement evaluates its argument. If the argument evaluates to a ‘true’ value (see Types for information on which values are considered ‘true’), it will evaluate the following block of statements. Otherwise, it will evaluate the next elseif statement, if any, or the else block, if present and there are no remaining elseif blocks. An elseif statement similar executes its contents if its argument evaluates to true, but will only execute if the arguments of all preceding if and elseif statements evaluated to false.

switch statements

Railroad diagram for Switch statements

The switch statement evaluates an expression, and chooses a case block to execute as a result of the expression's value. Case blocks are considered in order, with the value compared against the sequence of expressions associated with each case. Only integers and strings may be used in a case sub-statement.

If a case is matched, its contents are executed. There is no fall-through; when the end of the case statement is reached, program flow continues outside of the switch statement.

If no cases are matched, and the switch statement has a default block, this block will be executed. The default block must be the last block in the statement.

Long values will never match any cases, as cases must be constants, there are no Long literals, and no coercion is performed prior to comparison.

while statements

Railroad diagram for White loops

The while statement executes a block of code if the provided test expression evaluates to a true value. At the end of the block, the test expression is evaluated again. If it is still a true value, then the block is executed again. This process repeats until the end of the block is reached and the test expression evaluates to a false value. If the test expression is not true at the start, the block will never be executed.

If a continue statement is executed while inside of a while loop, execution passes to the test expression evaluation at the end of the loop. If a break statement is used, the while statement is exited with no further evaluation of the test expression.

repeat statements

Railroad diagram for Repeat loops

The repeat statement is similar to the while statement, except the block is executed once before the test expression is evaluated.

for loops

C-style for loops

Railroad diagram for C-Style for loops

The behaviour of this loop is similar, although not identical, to the while loop:

Init
while Test
    Body
    Increment
end

The differences lie in the behaviour of continue: it will always evaluate the Increment expression before the Test, unlike in the while-loop above, where it would be skipped.

Foreach loops

Railroad diagram for For-Each loops

This for loop takes an iterable value like a List, Record, RecArray or Assoc and binds its values sequentially to the given identifier. It is equivalent to the code:

Dynamic temporary = Expr
Integer i
Integer len = length( temporary )
for ( i = 1; i <= len; i += 1 )
    ID = temporary[ i ]
    Body
end

Structured for loops

Railroad diagram for structured for loops

This for loop assigns a sequence of values to an variable, either ascending (uses to), or descending (uses downto). If ascending, the loop assigns the begin value to the variable, and increments it by the value of the By expression, if given, or 1 otherwise, every iteration until the value of the variable is greater than the end value.

If descending, the value is decremented by the By expression, if given, or 1 otherwise, until the value is less than the end value.

If the value of the variable is modified in the body of the loop, the new value is the one that will be incremented or decremented by the loop.

If the value of the variable becomes Undefined, either because the begin value is Undefined, the By value is undefined, or an Undefined value is assigned to the variable in the body of the loop, the loop will never exit unless a non-Undefined value is later assigned to the variable.

End of Statement

OScript has two end-of-statement markers: a new line, or a semicolon. Either can be used in scripts or functions, which often makes writing strings to be passed to Compiler.Compile() easier, but only new lines can be used outside of scripts.

Expressions

Railroad diagram for expressions

Expressions evaluate to values. They may also have side effects, in the cases of variable assignment or function execution.

XLate

Railroad diagram for XLates

An XLate expression consists of a group name and an entry name. The XLate's value is computed at run-time, according to the language settings of Content Server. While they evaluate to strings, they are their own value. For more details, see XLates in the Types section.

Unary and binary expressions

Railroad diagram for unary expressions Railroad diagram for binary expressions

For more information on the behaviour of the unary and binary operators, see the section on operators in the Behaviour/Semantics section.

List literals

Railroad diagram for lists

List literals create a new List value when evaluated. The expressions that make up the elements of the list are evaluated in order.

Assoc literals

Railroad diagram for assocs

Assoc literals create a new Assoc value when evaluated. The key/value expression pairs that make up the elements of the list are evaluated in order.

Object names

Railroad diagram for object names

The object name is resolved at run time to an object reference value, pointing to the object with the given name.

Scoping

Functions and variables are limited in where they can be seen. Functions can only be seen by other functions within the same script, or by the implicit function created by having leading statements without an enclosing function. Variables can only be seen in the scope where they are declared, and any nested scopes. Each function definition is its own scope. The following also introduce new scopes:

If you declare a variable in a nested scope that shares the name of an already-declared variable, the new declaration will shadow the old variable inside of that scope: all reads and writes will refer to the new variable until the end of the scope where it was declared, or another variable declaration shadows it. This is true even if the new variable is of a different type.

Integer i = 3
echo( i ) // Outputs 3
if i > 2
    String i = "2"
    echo( i ) // Outputs 2
end
echo( i ) // Outputs 3