This module defines types for a Ceylon Abstract Syntax Tree (AST), a hierarchical and immutable data structure that represents a Ceylon program.

Obtaining an AST

There are two major ways to obtain an AST:

Create it yourself

You can of course construct the AST yourself. To reduce the amount of boilerplate code necessary, we strongly recommend using the ceylon.ast.create module (module ceylon.ast.create); this will, for example, allow you to write

baseExpression("null")

instead of

BaseExpression(MemberNameWithTypeArguments(LIdentifier("null")))

Parse it

The ceylon.ast.redhat module (module ceylon.ast.redhat) allows you to parse any AST node from a corresponding code string (internally using the RedHat Ceylon compiler).

If you have a node from the RedHat AST, you can also convert it using that module.

Operating on an AST

Analyze it

You can analyze an AST node (and its child nodes) using the Visitor interface. For example, you can count the amount of else if snippets like this:

variable Integer elseIfCount = 0;
that.visit {
    object visitor satisfies Visitor {
        shared actual void visitElseClause(ElseClause that) {
            if (that.child is IfElse) {
                elseIfCount++;
            }
            super.visitElseClause(that);
        }
    }
};

Visitor takes care of the AST traversal for you; you only need to override the functions that correspond to the nodes that concern you.

Attaching additional information

You can also attach your analysis results to the AST nodes. To do this, you first need to create a Key:

shared Key<Token[]> tokensKey
    = ScopedKey<Token[]>(`module my.parser`, "tokens");

(We recommend the use of ScopedKey to avoid naming collisions.)

Then, you can attach information using Node.put()

node.put(tokensKey, tokens)

and later retrieve it with Node.get() (perhaps in a different module):

assert (exists tokens = node.get(tokensKey));

The key is typed, so you don’t lose typing information (except about the presence of the attached information).

Edit it

Since the AST is immutable, you can’t edit it directly. However, you can easily obtain an edited copy using the Editor interface. For example, you can replace else ifs with else { if … }s like this:

that.transform {
    object transformer satisfies Editor {
        shared actual ElseClause transformElseClause(ElseClause that) {
            if (is IfElse ifElse = that.child) {
                return that.copy {
                    child = Block([ifElse]);
                };
            } else {
                return super.transformElseClause(that);
            }
        }
    }
};

Editor performs a deep copy by default; again, you only need to override the functions that correspond to the nodes that concern you.

Consuming an AST

You can also transform your AST into something completely different using the Transformer interface.

A Transformer<Something> transforms an AST into an instance of Something. Here are a few examples:

CeylonExpressionTransformer

CeylonExpressionTransformer is a Transformer<String> and transforms individual nodes like this:

transformSumOperation(SumOperation that)
        => "SumOperation {
                leftSummand = ``that.leftSummand.transform(this)``;
                rightSummand = ``that.rightSummand.transform(this)``;
            }";

(In reality it’s a bit more complicated because we need to deal with indentation.)

While the traversal doesn’t happen automatically, it’s mostly taken care of by the ceylon.ast infrastructure, at least if your resulting representation retains the node hierarchy (here: direct use of child.transform(this)).

RedHatTransformer

RedHatTransformer, in the ceylon.ast.redhat module (module ceylon.ast.redhat), is a Transformer<JNode> (where JNode is an import alias for RedHat AST nodes). It can be used to transform a ceylon.ast node to a RedHat AST node. This node can then, for example, be fed into the RedHat Ceylon compiler to compile it, or into the ceylon.formatter (module ceylon.formatter) to generate code for it (format function).

Editor

Editor is a Transformer<Node>, that is, a transformer from ceylon.ast to ceylon.ast. (That’s why the methods it uses are called transform and not edit.)

Meaning of an AST

An AST node represents a syntactically valid Ceylon program. It doesn’t necessarily have to be semantically valid; for example, the following expression

null.wrdlbrmpfd(nothing.attr)

will not compile, but has a perfectly valid AST representation. On the other hand, you cannot create an

LIdentifier("My Identifier")

(it will throw an AssertionError at runtime), because My Identifier is not a syntactically valid lowercase identifier.

Likewise, equality of nodes (equals) only means syntactic equality: Even though the following two types are equal

String|Integer
Integer|String

their AST nodes are not.

The standard for a syntactically valid Ceylon program is the reference implementation of the typechecker. This includes some programs that are not covered by the specification, which the typechecker accepts for better interoperation; within reason, and where this does not appear to be a bug in the typechecker, ceylon.ast permits such programs as well. However, this is restricted to programs that do not cause any typechecker errors: programs which the typechecker can parse merely so that it can report proper errors instead of parse errors (for example, try (/* empty resource list */)) are not accepted by ceylon.ast.

By: Lucas Werkmeister
License: http://www.apache.org/licenses/LICENSE-2.0.html
Packages
ceylon.ast.core
Dependencies
ceylon.collection1.3.1
Aliases
AddingExpressionshared AddingExpression=> ScalingExpression|SumOperation|DifferenceOperation

An expression on or above the precedence level of addition and subtraction.

AssigningExpressionshared AssigningExpression=> ThenElseExpression|AssignmentOperation

An expression on or above the precedence level of assignment.

This contains all “Layer 4” operators, that is, all operators total.

ComparingExpressionshared ComparingExpression=> ExistsNonemptyExpression|IsOperation|OfOperation|InOperation|ComparisonOperation|CompareOperation|WithinOperation

An expression on or above the precedence level of comparison, containment, assignability and inheritance tests.

ConjoiningExpressionshared ConjoiningExpression=> NegatingExpression|AndOperation

An expression on or above the precedence level of logical conjunction.

DisjoiningExpressionshared DisjoiningExpression=> ConjoiningExpression|OrOperation

An expression on or above the precedence level of logical disjunction.

This contains all “Layer 3” operators.

EquatingExpressionshared EquatingExpression=> ComparingExpression|EqualityOperation

An expression on or above the precedence level of equality tests.

This contains all “Layer 2” operators.

ExistsNonemptyExpressionshared ExistsNonemptyExpression=> SpanningExpression|ExistsOperation|NonemptyOperation

An expression on or above the precedence level of existence and nonemptiness tests.

ExponentiatingExpressionshared ExponentiatingExpression=> PrePostfixingExpression|ExponentiationOperation

An expression on or above the precedence level of exponentiation.

IntersectingExpressionshared IntersectingExpression=> InvertingExpression|IntersectionOperation

An expression on or above the precedence level of intersection.

InvertingExpressionshared InvertingExpression=> ExponentiatingExpression|UnaryArithmeticOperation

An expression on or above the precedence level of arithmetic inversion or identity.

Not to be confused with the precedence level of logical negation (NegatingExpression).

MemberNameshared MemberName=> LIdentifier
MultiplyingExpressionshared MultiplyingExpression=> UnioningExpression|ProductOperation|QuotientOperation|RemainderOperation

An expression on or above the precedence level of multiplication or division.

NegatingExpressionshared NegatingExpression=> EquatingExpression|NotOperation

An expression on or above the precedence level of logical negation.

Not to be confused with the precedence level of arithmetic inversion (InvertingExpression).

PackageNameshared PackageName=> LIdentifier
PrePostfixingExpressionshared PrePostfixingExpression=> Primary|PrefixOperation|PostfixOperation

An expression on or above the precedence level of arithmetic pre- or postfix expressions.

(This is the highest precedence level for operators; only primary expressions rank higher.)

RepositoryTypeshared RepositoryType=> LIdentifier
ScalingExpressionshared ScalingExpression=> MultiplyingExpression|ScaleOperation

An expression on or above the precedence level of scaling.

SpanningExpressionshared SpanningExpression=> AddingExpression|SpanOperation|MeasureOperation|EntryOperation

An expression on or above the precedence level of range and entry construction.

This contains all “Layer 1” operators.

StructureExpressionshared StructureExpression=> DisjoiningExpression|IfElseExpression|SwitchCaseElseExpression|LetExpression

An expression on or above the precedence level of “structural” expressions.

ThenElseExpressionshared ThenElseExpression=> StructureExpression|ThenOperation|ElseOperation

An expression on or above the precedence level of “then” and “else” expressions.

TypeNameshared TypeName=> UIdentifier
UnioningExpressionshared UnioningExpression=> IntersectingExpression|UnionOperation|ComplementOperation

An expression on or above the precedence level of union or complementation.

Functions
annotationshared Annotation annotation(String name)

Shortcut helper function for an Annotation with the specified name and no arguments.

lidentifierNeedsPrefixshared Boolean lidentifierNeedsPrefix(String name)
Parameters:
  • name
    • Name must not be empty

matchCaseAcceptableshared Boolean matchCaseAcceptable(Expression expression)

Determines whether an expression is acceptable for a match case.

  • An integer, character or string literal is known at compile time and therefore accepted. (Float literals are not accepted because due to rounding errors, exact comparison with a float literal value is rarely the correct thing to do.)
  • A negated integer literal is known at compile time and therefore accepted.
  • A base expression referring to a toplevel object is known at compile time and acceptable if the object satisfies Identifiable|Null.
  • A qualified expression referring to a value constructor of a toplevel class is known at compile time and acceptable if the class satisfies Identifiable|Null.
  • A qualified expression referring to a package-qualified toplevel object is known at compile time and accepted if the object satisfies Identifiable|Null.
  • A tuple is accepted if all of its listed expressions are accepted and it does not have a sequence argument.
  • No other expressions are accepted.

These conditions are slightly relaxed for ceylon.ast; without typechecker information, it is impossible to know what an expression refers to, so any base expression is accepted, and a qualified expression is accepted iff its receiver expression is accepted, permitting arbitrarily nested qualifier expressions.

See also MatchCase.expressions
uidentifierNeedsPrefixshared Boolean uidentifierNeedsPrefix(String name)
Parameters:
  • name
    • Name must not be empty

Interfaces
CascadingNarrowingTransformershared CascadingNarrowingTransformer<out Result>

A NarrowingTransformer that narrows cascadingly to the “less abstract” type of the visited subject by switching on the case types and invoking the proper transformX method.

For example:

// ValueExample has the case types Primary | Operation
shared actual default Result transformValueExpression(ValueExpression that) {
    switch (that)
    case (is Primary) { return transformPrimary(that); }
    case (is Operation) { return transformOperation(that); }
}

I honestly don’t know when you’d want to use this instead of ImmediateNarrowingTransformer; perhaps the strongest argument for its existence is that it was trivial to generate along with other generated code while ceylon.ast was originally written, but would be significantly more painful to create (by hand or automatically) afterwards.

Editorshared Editor

An AST editor. There is one method per AST node; override the methods for which you need to change the AST, and leave the others untouched.

The default operation for “bottom“ non-leaf node types’ methods is to check Editor.editNode() for that node; if it returns true, the node is copied, editing the children, and if it returns false, the same node is returned without changes (shortcut). The default operation for leaf node types’ methods (nodes with no children) is to return the same node. (The default operation for non-“bottom” node types’ methods is inherited from ImmediateNarrowingTransformer, see there.) By itself, an Editor will not actually edit the AST – it’s only scaffolding that allows you to easily edit parts of the AST without having to bother with the deep nesting of the nodes.

For example:

class TraceFunctionEditor() satisfies Editor {
    shared actual FunctionDefinition transformFunctionDefinition(FunctionDefinition that) {
        value print = BaseExpression(MemberNameWithTypeArguments(LIdentifier("print")));
        value enterArgs = PositionalArguments(ArgumentList([StringLiteral("enter ``that.name.name``")]));
        value leaveArgs = PositionalArguments(ArgumentList([StringLiteral("leave ``that.name.name``")]));
        value enter = InvocationStatement(Invocation(print.copy(), enterArgs));
        value leave = InvocationStatement(Invocation(print.copy(), leaveArgs));
        return that.copy {
            definition = Block(concatenate([enter], that.definition.content, [leave]));
        };
    }
}

will insert a print statement at the beginning and end of every function block in the AST.

ImmediateNarrowingTransformershared ImmediateNarrowingTransformer<out Result>

A NarrowingTransformer that narrows immediately to the type of the visited subject by invoking its transform (Node.transform) method.

For example:

shared actual default Result transformValueExpression(ValueExpression that)
        => that.transform(this);

This interface should be functionally equivalent to CascadingNarrowingTransformer, but is likely a lot faster because it uses only a single virtual method lookup instead of a series of type checks and calls.

NarrowingTransformershared NarrowingTransformer<out Result>

A Transformer with the default operation to narrow the type of the visited subject; all methods for abstract node types have a default implementation while those for concrete node types remain formal.

There are two ways to perform this narrowing:

  • immediately, by invoking the transform (Node.transform) method on the subject, or
  • cascadingly, where each method switches on the enumerated subtypes of the node type and narrows only by one layer by invoking the corresponding transformX method on the transformer.

It should be possible to use them interchangeably (swap out the satisfying type of your implementing class without any effect), and since the immediate version is faster (it’s only a virtual method lookup instead of a series of calls and type checks), you should probably use that.

Transformershared Transformer<out Result>

Abstract interface to perform some operations on AST nodes and possibly get some result.

For every subtype of Node, there is one transform method, each returning Result. These are all formal, as there are two sensible default behaviors:

Be careful when mixing the two behaviors, lest you end up in an infinite recursion!

Visitorshared Visitor

An AST visitor. There is one method per AST node; override the methods for which you need to do something, and leave the others untouched.

The default operation for most node types is to pass the visit up to the node’s supertype; for example, if you override only Visitor.visitIdentifier(), you will receive calls to both LIdentifier.visit() and UIdentifier.visit(), as the default operation for Visitor.visitLIdentifier() and Visitor.visitUIdentifier() is to delegate to Visitor.visitIdentifier(). Visitor.visitNode() is different: As the root of the AST class hierarchy, it has no superclass; instead, it visits all the children of the node. Thus, the default visitor will already traverse the AST fully, and if you need to perform some operation only for some node type that might appear anywhere in the AST, you can simply override that particular method and leave the rest as it is.

Note: conceptually, a Visitor is a WideningTransformer<Anything>, that is, a WideningTransformer without any result. However, for performance reasons, this notion was dropped in the 1.2.1 release, and Visitor is now an independent, unparameterized interface. See #109 for more information.

WideningTransformershared WideningTransformer<out Result>

A Transformer with the default operation to widen the type of the visited subject: WideningTransformer.transformLIdentifier() delegates to WideningTransformer.transformIdentifier(), which in turn delegates to Transformer.transformNode(), which (Node being without a superclass) is the only formal method left.

Classes
AddAssignmentOperationshared AddAssignmentOperation

An add assignment operation (+=).

Right-associative. Any expression may appear on the right-hand side, regardless of precedence.

Examples:

index += step
document.cursor.position += insertion.size
AliasDecshared AliasDec

An alias reference expression, that is, the AliasDec.name of an alias, optionally qualified by a AliasDec.qualifier (separated from it by a member operator ‘.’), prefixed by the type keyword alias and surrounded by backticks.

Examples:

`alias TypeName`
`alias A.B.C
AndAssignmentOperationshared AndAssignmentOperation

A logical conjunction assignment expression.

Right-associative. Any expression may appear on the right-hand side, regardless of precedence.

Examples:

valid &&= parsed exists
legal &&= !globalLock
AndOperationshared AndOperation

A logical conjunction expression.

Left-associative.

Examples:

i%2 == 0 && j%2 == 1
attr1 == that.attr1 && attr2 == that.attr2 && attr3 == that.attr3
Annotationshared Annotation

An annotation.

For the common case “no arguments”, the toplevel helper function annotation() may be used.

Examples:

shared
formal
by ("John Doe <john.doe@company.com>")
see (`function print`)
action { description = "Log in"; url = "/login"; }
Annotationsshared Annotations

A list of annotations.

The first annotation may optionally be an anonymous annotation, that is, a string literal interpreted as the argument of a doc annotation.

Annotations are not separated by any punctuation.

Examples:

shared formal
"The number of elements in this list" see (`value List.lastIndex`) shared actual
AnonymousArgumentshared AnonymousArgument

An anonymous named argument, that is, an expression followed by a semicolon.

Examples:

name;
width * height;
AnyClassshared abstract AnyClass

A class definition or alias.

Examples (multi-line):

shared class PrintableWrapper<T>(shared T wrapped)
        satisfies Printable {
    shared actual void print() {
        package.print(wrapped else "<null>");
    }
}

shared class VariadicString(Character* characters) => String(characters);
AnyCompilationUnitshared abstract AnyCompilationUnit

A compilation unit.

There are three kinds of compilation unit:

(Because it is the most commonly used, and also what most people associate with a “compilation unit”, the first kind is simply called CompilationUnit and this abstract class is called AnyCompilationUnit, rather than calling this CompilationUnit and using RegularCompilationUnit or CodeCompilationUnit for regular compilation units.)

Every compilation unit starts with a (possibly empty) list of AnyCompilationUnit.imports.

Examples (separated by blank lines):

module tmp "1.0.0" {}

package tmp;

void run() {
    print("Hello, World!");
}
AnyFunctionshared abstract AnyFunction

A function declaration or definition.

If the AnyFunction.definition is missing or a specifier, then the statement must be terminated by a semicolon; if it’s a Block, the semicolon is not necessary.

Examples:

shared formal Boolean equals(Object that);
function compareByLength({Anything*} first, {Anything*} second) => first.length.compare(second.length);
shared void run() {
    print("Hello, `` process.arguments.first else "World" ``!");
AnyInterfaceshared abstract AnyInterface

An interface definition or alias.

Examples (multi-line):

shared interface Printable {
    shared default void print() => package.print(this);
}

shared interface People => {Person*};
AnyInterfaceDefinitionshared abstract AnyInterfaceDefinition

A regular or dynamic interface definition.

Examples (multi-line):

shared interface Printable {
    shared default void print() => package.print(this);
}

shared dynamic Document {
    shared formal String xmlVersion;
    shared formal StyleSheetList styleSheets;
    shared formal String documentURI;
    // ...
}
AnyMemberOperatorshared abstract AnyMemberOperator

A member operator, used in a QualifiedExpression.

AnySpecifiershared abstract AnySpecifier

An eager or lazy expression specifier.

Examples:

= 1
=> text.uppercased
AnyValueshared abstract AnyValue

A value declaration or definition.

If the TypedDeclaration.definition is missing or a specifier, then the statement must be terminated by a semicolon; if it’s a Block, the semicolon is not necesary.

Examples:

shared String name;
shared formal Comparison compare(Other that);
shared default Boolean empty => iterator().next() is Finished;
ArgumentListshared ArgumentList

An argument list.

A list of expressions, here called listed arguments, optionally followed by a spread argument or a comprehension.

Examples:

width, height
*args
/* empty parameter list is also allowed */
this, *others
Argumentsshared abstract Arguments

An argument list that can be used in an Invocation.

Not to be confused with ArgumentList. An ArgumentList is just a comma-separated list of arguments with an optional trailing sequential argument. Arguments either simply wrap an ArgumentList in parentheses (PositionalArguments), or can also add named arguments (NamedArguments).

Examples:

(x, y, *messages)
()
(for (i in 1..10) i^2)
{ factor = 2.1; *actors }
ArithmeticAssignmentOperationshared abstract ArithmeticAssignmentOperation

An arithmetic assignment operation, a shortcut for an ArithmeticOperation combined with an AssignmentOperation.

Right-associative. Any expression may appear on the right-hand side, regardless of precedence.

ArithmeticOperationshared abstract ArithmeticOperation

An arithmetic operation expression.

Assertionshared Assertion

An assertion statement, that is, an annotation list, followed by the keyword ‘assert’, a condition list, and terminated by a semicolon.

Examples:

assert (exists num = parseFloat(numText));
"Weight cannot be negative" assert (weight >= 0);
AssignOperationshared AssignOperation

An assignment expression.

Right-associative. Any expression may appear on the right-hand side, regardless of precedence.

Examples:

i = 1
text = "Hello, ``name else "World"``!"
AssignmentOperationshared abstract AssignmentOperation

An assignment expression.

Right-associative. Any expression may appear on the right-hand side, regardless of precedence.

This is the abstract superclass of all assignment operations, with operators like =, +=, &=, etc. Not to be confused with AssignOperation, the concrete class for = expressions!

AssignmentStatementshared AssignmentStatement

An assignment expression statement, that is, an assignment terminated by a semicolon.

In principle, a statement like i = 0; could be parsed ambigously, either as an assignment statement or as a specification. When possible, the Ceylon language favors the latter interpretation, which means that an assignment statement where the target is a BaseExpression is invalid. (This is only true for simple AssignOperations; other assignment operations, e. g. i += size;, are still valid assignment expression statements.)

Examples:

text.length += added.length;
ret.endToken = tokens.token(";", semicolon);
Atomshared abstract Atom

An “atomic” expression.

While atoms can wrap and contain other expressions, they never consist of several expressions chained together without any wrapping. For example, in [1, 2, 3], the child expressions are wrapped in the surrounding brackets; in 1.add, however, the child expressions are not wrapped. Therefore, a Tuple is an atom, while a QualifiedExpression isn’t.

BaseExpressionshared BaseExpression

An unqualified identifier with an optional list of type arguments.

A base expression can refer to either:

  • a toplevel function, value, or class,
  • a function, value, or class in the current scope, or
  • a function, value, or class in the current block.

Examples:

null
max<Integer,Nothing>
BaseMetashared BaseMeta

A base metamodel expression, that is, a member name with optional type arguments, optionally qualified with a package’ qualifier (packageQualifier), surrounded by backticks.

(A type name with optional type arguments surrounded by backticks is a TypeMeta.)

Examples:

`sum<Float>`
`system`
`package.null`
BaseTypeshared BaseType

A type name with optional type arguments.

The type name may optionally be qualified by a package’ qualifier (qualifier).

Examples:

String
List<Character>
package.Object
BinaryOperationshared abstract BinaryOperation

A binary operator expression.

Binary operations can be left-associative (a X b X c means (a X b) X c) or right-associative (a X b X c means a X (b X c)). To represent this in the type system, the left and right children of concrete classes usually have different types: One has the type of the current precedence level (see the PrecedenceXOperation aliases), one has the type of the precedence level below.

(Some binary operations have no precedence because they can’t be nested (for example, a == b == c is never allowed); in this case, both children have the type of the precedence level below.)

Blockshared Block

A list of statements and declarations, surrounded by braces.

A block contains imperative code, a series of statements that is executed sequentially each time the block is entered (declarations can’t be executed). It may also return a value.

A block may also include a list of Block.imports that is local to this block only.

Examples (multi-line):

{
    print("``indent``BEGIN ``that``");
    value origIndent = indent;
    indent += indentLevel;
    that.visit(this);
    indent = origIndent;
    print("``indent``END ``that``");
}
{
    throw AssertionError("Not yet implemented!");
}
{
    if (exists first = s.first) {
        return String { first.lowercased, *s.rest };
    } else {
        return "";
    }
}
{
    import java.lang { System }
    System.arraycopy(src, srcPos, dest, destPos, length);
}
Bodyshared abstract Body

A list of statements and declarations, surrounded by braces.

A body may also include a list of Body.imports that is local to this body only.

Examples:

{}
{ shared String name; string => name; }
BooleanConditionshared BooleanCondition

A boolean condition, that is, an expression.

The condition is satisfied when the expression evaluates to true.

Examples:

type in { type_ws, type_comment }
literals.size == expressions.size + 1
Boundshared abstract Bound

A lower or upper bound of a bounded comparison operation.

Breakshared Break

A break directive.

CallableConstructorDefinitionshared CallableConstructorDefinition

A callable constructor definition.

A callable constructor definition has the following components:

Examples (multi-line):

// 2D point
shared new polar(r, φ) {
    Float r;
    Float φ;
    this.x = r * cos(φ);
    this.y = r * sin(φ);
    this.r = r;
    this.φ = φ;
}

// 3D location in homogenous coordinates
shared new cartesian(Float x, Float y, Float z)
        extends super.cartesian(x, y, z, 1.0) {}

// default constructor
shared new(String name, Date|String dateOfBirth) {
    this.name = name;
    this.dateOfBirth
            = switch (dateOfBirth)
              case (is Date) dateOfBirth
              case (is String) parseDate(dateOfBirth);
}
CallableParametershared CallableParameter

A callable parameter.

Examples:

Comparison comparing(Element left, Element right)
void onSuccess()
CallableTypeshared CallableType

A callable type.

Examples:

Integer(Integer,Integer)
String(Character*)
Ret(*Args)
CaseClauseshared CaseClause

A ‘case’ clause of a switch’ statement (SwitchCaseElse), that is, the keyword ‘case’, followed by a case item enclosed in parentheses and a CaseClause.block.

Examples (multi-line):

case (is String) {
    int = parseInteger(val);
}

case (null) { return; }
CaseExpressionshared CaseExpression

A ‘case’ expression clause of a switch’ expression (SwitchCaseElseExpression), that is, the keyword ‘case’, followed by a case item enclosed in parentheses and an expression.

The expression is parsed with a precedence just below the then (ThenOperation) and else (ElseOperation) operations, to avoid ambiguity with these. Alternatively, it may be an if/then/else expression (IfElseExpression) or let expression (LetExpression).

Examples:

case (is Integer) val / 2
case ('$') 2
CaseItemshared abstract CaseItem

A ‘case’ item from a case’ clause (CaseClause).

Examples:

is String
0, 1
CaseTypesshared CaseTypes

A nonempty list of case types, separated by the union operator (‘|’).

Examples:

of String | Float | Integer
of Other
of empty | [Element+]
CatchClauseshared CatchClause

A ‘catch’ clause, that is, the keyword ‘catch’, followed by a CatchClause.variable (enclosed in parentheses) and a CatchClause.block.

Examples (multi-line):

catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}

catch (e) {
    console.error(e);
}
CeylonExpressionTransformershared CeylonExpressionTransformer

Builds a Ceylon expression string for an AST node; compiling and evaluating the resulting string will yield a copy of the transformed node.

Usage:

myNode.transform(CeylonExpressionTransformer());
CharacterLiteralshared CharacterLiteral

A character literal consists of a single character or an escape sequence.

ClassAliasDefinitionshared ClassAliasDefinition

A class alias definition.

A class alias definition has the following components:

(While semantically, a class alias may never have case types or extend or satisfy other types, these nodes may syntactically still be present.)

Examples:

shared class VariadicString(Character* characters) => String(characters);
shared class MemberName(String name) => LIdentifier(name);
ClassBodyshared ClassBody

A list of statements and declarations, surrounded by braces.

Logically, a class body is divided into two sections:

  • An initializer section, mixing statements and declarations, and
  • a declaration section, containing only declarations.

There is, however, no syntactical separation between these, so syntactically a class body looks exactly like a Block.

A class body may also include a list of ClassBody.imports that is local to this class body only.

Examples (multi-line):

{
    shared formal Float x;
    shared formal Float y;
    shared actual default Float distance(Point other) => ((x-other.x)^2 + (y-other.y)^2)^0.5;
}

{
    if (token != secret) {
        throw AssertionError("You may not instantiate this class!");
    }
    shared void hack(Anything victim) {
        ████ ███████ ██ █;
    }
}
ClassDecshared ClassDec

A class reference expression, that is, the ClassDec.name of a class or anonymous class, qualified by a (possibly empty) ClassDec.qualifier (separated from it by a member operator ‘.’), or empty for the current class, prefixed by the type keyword class and surrounded by backticks.

The ClassDec.name may be an LIdentifier to refer to the class declaration of an anonymous class. For example, in

value dec1 = `class null`;
value dec2 = `value null`;

dec1 refers to the anonymous class of the null object, while dec2 refers to the only instance of that class, the null object itself.

The ClassDec.qualifier may only be null if the ClassDec.name is also null. If the name exists, the qualifier must exist as well (but may of course be empty).

Examples:

`class String`
`class A.B.C`
`class`
ClassDefinitionshared ClassDefinition

A class definition.

A class definition has the following components:

Examples (multi-line):

shared class PrintableWrapper<T>(shared T wrapped)
        satisfies Printable {
    shared actual void print() {
        package.print(wrapped else "<null>");
    }
}

shared class Counter(Integer initialCount=0) {

    variable Integer n = initialCount;

    shared Integer count => n;

    shared void increment() => n++;
}
ClassOrInterfaceshared abstract ClassOrInterface

A class or interface declaration.

Examples (multi-line):

shared class PrintableWrapper<T>(shared T wrapped)
        satisfies Printable {
    shared actual void print() {
        package.print(wrapped else "<null>");
    }
}

shared interface 3DSized<Unit>
        given Unit satisfies Numeric<Unit> {
    shared formal Unit width;
    shared formal Unit length;
    shared formal Unit height;
}
ClassSpecifiershared ClassSpecifier

A class specifier for a class alias, that is, a lazy specification operator ‘=>’ followed by an extension or construction.

Examples:

=> String(characters)
=> Entry<String,Item>(name, item)
=> HomogenousCoordinates.Cartesian(x, y, z, 1.0)
ClosedBoundshared ClosedBound

A closed lower or upper bound of a bounded comparison operation.

In a closed bound, the ClosedBound.endpoint is a part of the designated interval; therefore, the minimum / maximum value of the interval is the endpoint.

CompareOperationshared CompareOperation

A compare expression.

No associativity.

Examples:

first <=> last
n <=> 0

This is the concrete class for expressions like first <=> last; not to be confused with ComparisonOperation, the abstract superclass of expressions like a <= b and x > 3!

ComparisonOperationshared abstract ComparisonOperation

A comparison expression.

No associativity.

This is the abstract superclass of expressions like a <= b and x > 3; not to be confused with CompareOperation, the concrete class representing expressions like first <=> second!

CompilationUnitshared CompilationUnit

A regular compilation unit, containing toplevel type, value, or function definitions.

This is the most commonly used type of compilation unit, and the basic “container” for your declarations.

Examples:

void run() {
    print("Hello, World!");
}

// end of example, start of next example

import ceylon.collection {
    SetMutator
}

MyPlugin myPlugin = MyPlugin(); // only instance

register
shared void registerMyPlugin(SetMutator<Plugin> registry)
    => registry.put(myPlugin);
ComplementAssignmentOperationshared ComplementAssignmentOperation

A complement assignment operation.

Right-associative. Any expression may appear on the right-hand side, regardless of precedence.

Examples:

people ~= kids
elements ~= otherElements
ComplementOperationshared ComplementOperation

A set complement expression.

Defined via complement. Left-associative.

Examples:

receivers~blocked
primes ~ HashSet { 2 }
Comprehensionshared Comprehension

A comprehension, that is, a chain of comprehension clauses, beginning with an InitialComprehensionClause and terminated by an ExpressionComprehensionClause.

Examples:

for (people in peoples) for (person in people) if (person.age >= age) person
if (exists typeArguments = that.typeArguments) for (typeArgument in typeArguments) typeArgument.type
ComprehensionClauseshared abstract ComprehensionClause

A comprehension clause, one component of a Comprehension.

Examples:

for (person in people) if (person.age > 18) person.age
if (isPrime(i)) i
Conditionshared abstract Condition

A condition.

There are four kinds of conditions:

Examples:

exists first = string.first
type in { type_ws, type_comment }
is Float number
nonempty members
ConditionalExpressionshared abstract ConditionalExpression

A conditional expression.

Conditional expressions resemble control structures, but are part of the expression syntax and evaluate to values.

Examples (multi-line):

if (is Box<Type> that)
    then this.content == that.content
    else false

switch (first.age <=> second.age)
case (smaller) "younger"
case (equal) "of the same age as"
case (larger) "older than"
Conditionsshared Conditions

A comma-separated list of one or more Conditions.conditions, enclosed in parentheses.

Examples:

(nonempty elems = that.elements, elems.first == expected)
(is Integer num = obj.num, is Integer num2 = obj2.num, num == num2)
Constructionshared Construction

A construction, that is, a member name with optional type arguments and Construction.arguments, optionally qualified with a base type or a super qualifier.

(Note: the specification’s BaseConstruction and SuperConstruction have been inlined into this node.)

Examples:

Point.cartesian(x, y, 0.0)
withRGB(#FF, 0, 0)
super.cartesian(x, y, 0.0)
ConstructorDecshared ConstructorDec

A constructor reference expression, that is, the ConstructorDec.name of a constructor, qualified by a ConstructorDec.qualifier (separated from it by a member operator ‘.’), prefixed by the constructor keyword class and surrounded by backticks.

Examples:

`new Point.polar`
`new Location.cartesian`
ConstructorDefinitionshared abstract ConstructorDefinition

A constructor definition.

A constructor may be either a callable constructor or a value constructor.

Examples (multi-line):

// 2D point
shared new polar(r, φ) {
    Float r;
    Float φ;
    this.x = r * cos(φ);
    this.y = r * sin(φ);
    this.r = r;
    this.φ = φ;
}

shared new origin {
    x = 0.0; y = 0.0;
    r = 0.0; φ = 0.0;
}
Continueshared Continue

A continue directive.

ControlStructureshared abstract ControlStructure

A control structure statement, used to control normal execution flow.

(An assertion failure is not considered as “normal” control flow; therefore, an Assertion is not a control structure.)

Examples:

if (exists elem = queue.take) { process(elem); }
for (i in 1:12) { print(month(i)); }
Decshared abstract Dec

A reference expression, that is, a detyped reference to a program element.

Reference expressions may refer to:

Not to be confused with Meta, which represents a typed reference. Simply speaking, if there’s a keyword (`class String`, `value system`), then it’s a Dec, otherwise it’s a Meta.

Reference expressions are often used in annotations, e. g. see.

DecQualifiershared DecQualifier

A qualifier for a Dec, that is, a period-separated sequence of identifiers, possibly itself qualified by a package’ qualifier (packageQualifier).

(The qualifier may also be completely empty.)

Examples:

process
Entry
package.Object
Declarationshared abstract Declaration

A declaration.

Most declarations either define or have a type.

The general order of the children of a declaration is as follows:

Annotations
(Modifier | Type) Identifier TypeParameters? Parameters*
CaseTypes? ExtendedType? SatisfiedTypes?
TypeConstraints?
(Body | AnySpecifier? ";")

However, the only children common to all declarations are the Declaration.name of the declared program element and its Declaration.annotations.

Examples:

shared actual String string => "``outer.string`` by ``step``";
shared class Person(shared String name) { string => name; }
DefaultedCallableParametershared DefaultedCallableParameter

A callable parameter, along with a default implementation for the parameter.

Examples:

Float weight(Item item) => item.cost
void log(String message) => process.writeErrorLine(message);
DefaultedParametershared abstract DefaultedParameter

A defaulted parameter.

Examples:

length = text.size
Comparison comparing(Element x, Element y) => x.hash <=> y.hash
DefaultedParameterReferenceshared DefaultedParameterReference

The name of a parameter declared in the body of the function or class, along with a default value for the parameter.

Examples:

length = text.size
status = ok
DefaultedTypeshared DefaultedType

A defaulted type.

Examples:

String=
Integer->String=
DefaultedValueParametershared DefaultedValueParameter

A value parameter, along with a default value for the parameter.

Examples:

Integer length = text.size
Boolean discounted = false
Destructureshared Destructure

A destructuring statement, that is, a value’ modifier (valueModifier), followed by a Destructure.pattern and a Destructure.specifier, and terminated by a semicolon.

Examples:

value name->[lat, lon] = observatories.first;
value [x,y,z] = pos;
DifferenceOperationshared DifferenceOperation

A difference expression.

Defined via minus. Left-associative.

Examples:

size - 1
lastIndex - firstIndex
Directiveshared abstract Directive

A control directive, terminated by a semicolon.

There are four kinds of control directives:

  • the return (Return) directive, to return a value or terminate execution,
  • the throw (Throw) directive, to raise an exception,
  • the break (Break) directive, to terminate a loop, and
  • the continue (Continue) directive, to jump to the next iteration of a loop.

Examples:

return ret;
throw AssertionError("Not implemented yet!"); // TODO implement
break;
continue;
DivideAssignmentOperationshared DivideAssignmentOperation

A divide assignment operation (/=).

Right-associative. Any expression may appear on the right-hand side, regardless of precedence.

Examples:

width /= 2
amount /= exchangeRate
DynamicBlockshared DynamicBlock

A dynamic block, that is, a DynamicBlock.block prefixed by the keyword ‘dynamic’.

Examples (multi-line):

dynamic {
    setTimeout(\iMath.random() * 1000, () => print("A message from the past"));
}

dynamic {
    console.log("Direct console access");
    console.dir(this); // I wonder what this looks like
}
DynamicInterfaceDefinitionshared DynamicInterfaceDefinition

A dynamic interface definition.

A dynamic interface definition has the following components:

Examples (multi-line):

shared dynamic Document {
    shared formal String xmlVersion;
    shared formal StyleSheetList styleSheets;
    shared formal String documentURI;
    // ...
}

shared dynamic Promise {
    shared formal Promise \ithen(void onFulfilled(dynamic result) => noop(), void onRejected(dynamic error) => noop());
    shared formal Promise catch(void onRejected(dynamic error) => noop());
}
DynamicModifiershared DynamicModifier

A ‘dynamic’ modifier keyword.

DynamicValueshared DynamicValue

A dynamic value expression, that is, the keyword ‘dynamic’ followed by any number of named arguments and a (possibly empty) argument list, enclosed in brackets.

Examples:

dynamic [ error = 404; message = "not found"; ]
dynamic [ ]
ElementOrSubrangeExpressionshared ElementOrSubrangeExpression

An element or subrange access expression, that is, a target ElementOrSubrangeExpression.primary followed by a ElementOrSubrangeExpression.subscript surrounded with brackets.

Examples:

text[start...]
map[key]
ElseClauseshared ElseClause

An else clause, that is, the keyword ‘else’, followed by a block or another if/else conditional.

Examples (multi-line):

else {
    return "<null>";
}

else if (exists div) {
    visit(div.paragraphs);
}
ElseOperationshared ElseOperation

An “else” operation.

Left-associative.

Examples:

0 <= val <= 10 then priority(val) else invalid
parseInteger(input) else 0
EntryOperationshared EntryOperation

An entry expression.

Defined via Entry. No associativity.

Examples:

"1"->1
name->Person(name)
EntryPatternshared EntryPattern

An entry pattern, that is, a EntryPattern.key pattern and an EntryPattern.item pattern, separated by an entry operator.

Examples:

id->person
name->[lat, lon]
EntryTypeshared EntryType

An entry type, that is, a shortcut for TypeNameWithTypeArguments(TypeName(UIdentifier("Entry")), [left, right]).

Examples:

String->Integer
Printable&Persistent&Identifiable->Handle
EqualOperationshared EqualOperation

An equals expression.

Defined via equals. No associativity.

Examples:

length == 1
first == last
parseInteger(input) == 0
EqualityOperationshared abstract EqualityOperation

An expression to test for identity or (in)equality of two objects.

This is the abstract superclass of the nodes for ==, !=, ===; not to be confused with EqualOperation, the concrete class for ==!

ExistsConditionshared ExistsCondition

An existence condition, that is, the keyword ‘exists’, followed by either a specified pattern or a member name referencing an existing value.

Examples:

exists name
exists firstItem = first?.item
ExistsOperationshared ExistsOperation

A postfix existence test expression.

No associativity.

Examples:

element exists
parseInteger(text) exists
ExistsOrNonemptyConditionshared abstract ExistsOrNonemptyCondition

An existence or nonemptiness condition, that is, the keyword ‘exists’ or ‘nonempty’, followed by either a specified pattern or a member name referencing an existing value.

Examples:

nonempty [employeeOfTheMonth, *others] = randomShuffle(employees)
exists String name = person.name
ExponentiationOperationshared ExponentiationOperation

An exponentiation expression.

Defined via power. Right-associative.

Examples:

sideLength^dimension
e^x
Expressionshared abstract Expression

Abstract superclass of all expression nodes.

Correct operator precedence and associativity is enforced by the parameter types of the various child classes. For example, consider the following simple expression:

1 + 2 * 3

Because multiplication has higher precedence than addition, the correct syntax tree for this expression is:

SumOperation {
    leftOperand = IntegerLiteral("1");
    rightOperand = ProductOperation {
        leftOperand = IntegerLiteral("2");
        rightOperand = IntegerLiteral("3");
    };
}

A very simple, strictly left-associative parser that doesn’t respect operator precedence might instead try to produce:

ProductOperation {
    leftFactor = SumOperation {
        leftSummand = IntegerLiteral("1");
        rightSummand = IntegerLiteral("2");
    };
    rightFactor = IntegerLiteral("3");
}

However, this is not well-typed (the parser would likely have an assertion failure at runtime), because the types of ProductOperation’s child nodes are crafted such that only nodes with correct precedence and associativity can be created.

To ensure this, there is one type alias for each precedence level, specified as the union type of

  • the next higher level’s alias, and
  • all operator types on this level.

For example, there is MultiplyingExpression for multiplicative expressions and AddingExpression for summative expressions. ProductOperation.leftFactor then has type MultiplyingExpression, which does not include SumOperation. ProductOperation.rightFactor has the next higher level’s type UnioningExpression, reflecting the left-associativity of product operations: Instead of

ProductOperation {
    leftFactor = IntegerLiteral("1");
    rightFactor = ProductOperation {
        leftFactor = IntegerLiteral("2");
        rightFactor = IntegerLiteral("3");
    };
}

you should have

ProductOperation {
    leftFactor = ProductOperation {
        leftFactor = IntegerLiteral("1");
        rightFactor = IntegerLiteral("2");
    };
    rightFactor = IntegerLiteral("3");
}

These aliases are, from highest to lowest precedence:

ExpressionComprehensionClauseshared ExpressionComprehensionClause

An expression that terminates a comprehension.

Examples:

person.age
i
ExpressionStatementshared abstract ExpressionStatement

An expression statement, that is, an expression terminated by a semicolon.

Only certain expressions are valid statements:

Be aware that very simple assignments are specifications; an AssignmentStatement where the target of the AssignOperation is a BaseExpression is invalid.

Examples:

text.length += added.length;
i++;
print("Hello, World!");
ExtendedTypeshared ExtendedType

An ‘extends’ clause for a class definition, that is, the keyword ‘extends’, followed by an extension or construction.

Examples:

extends Node()
extends super.Entry<Key, Item>(key, item)
extends HomogenousCoordinates.Cartesian(x, y, z, 1.0)
Extensionshared Extension

An extension, that is, a type name with optional type arguments and optional Extension.arguments, optionally qualified with a package or super qualifier.

(Note: the specification’s BaseExtension and SuperExtension have been inlined into this node.)

Examples:

Object()
package.Object
super.Inner
ExtensionOrConstructionshared abstract ExtensionOrConstruction

An extension or construction, that is, anything that can go in an extended type or class specifier.

Examples:

Object()
Point.cartesian(x, y, 0.0)
FailClauseshared FailClause

An ‘else’ failure clause for a for’ loop (ForFail), that is, the keyword ‘else’ followed by a FailClause.block.

Examples:

else { print("Hello, World!"); }
FinallyClauseshared FinallyClause

A ‘finally’ clause, that is, the keyword ‘finally’ followed by a FinallyClause.block.

Examples:

finally { print("END"); }
finally { workers.collect(Worker.kill); }
FloatLiteralshared FloatLiteral

A floating point literal is distinguished from an integer literal (IntegerLiteral) by the presence of fractional digits or a fractional magnitude.

ForClauseshared ForClause

A ‘for’ clause, that is, the keyword ‘for’ followed by an ForClause.iterator and a ForClause.block.

(Not to be confused with a complete for’ loop (ForFail), which also includes an optional failure clause.)

Examples:

for (person in people) { print(person.name); }
for (name->person in peopleByName) { print("``name``: ``person.age``"); }
ForComprehensionClauseshared ForComprehensionClause

A ‘for’ comprehension clause, also known as a quantifier clause.

A ‘for’ comprehension clause consists of the keyword ‘for’, an ForComprehensionClause.iterator and a following ForComprehensionClause.clause.

Examples:

for (person in people) "``person.firstName`` ``person.lastName``"
for (people in peoples) for (person in people) if (person.age >= 18) person
ForFailshared ForFail

A ‘for’ loop with an optional failure clause, that is, a for’ clause (forClause), optionally followed by an else’ failure clause (failClause).

Examples (multi-line):

for (i in 1:12) {
    print(month(i));
}

for (person in people) {                                  
    if (!person.greeted) {
        print("Hello, ``person.name``!");
        break;
    }
} else {
    print("Hello, World!");
}
ForIteratorshared ForIterator

An iterator for a ‘for’ loop, enclosed in parentheses.

Examples:

(person in people)
(name->person in peopleByName)
([x, y] in coordinates)
FullPackageNameshared FullPackageName

A full package name, that is, a period-separated list of lowercase identifiers.

Examples:

ceylon.language
ceylon.ast.core
FunctionArgumentshared FunctionArgument

An inline function argument definition.

Examples (multi-line):

void onClick() {
    DialogBox { message = "Hello!"; parent = this; }.show();
}

void onError(dynamic err)
        => console.error(err);
FunctionDecshared FunctionDec

A function reference expression, that is, the FunctionDec.name of a function or method, qualified by a (possibly empty) FunctionDec.qualifier (separated from it by a member operator ‘.’), prefixed by the member keyword function and surrounded by backticks.

Examples:

`function concatenate`
`function Iterable.chain`
FunctionDeclarationshared FunctionDeclaration

A function declaration.

A function declaration declares the FunctionDeclaration.name, FunctionDeclaration.type, parameters,
type parameters and type constraints of the value, but doesn’t provide a FunctionDeclaration.definition for it. There are several possible reasons for this:

  • The function can be a formal method of an abstract class or an interface, and subtypes have to provide the definition.
  • The function can be the declaration of a class or function parameter that only listed the name.
  • The function can be forward-declared, and the definition will be provided later.

In any case, the declaration must explicitly specify a type; a function’ modifier (FunctionModifier) indicating type inference cannot be used. (The ’dynamic’ modifier counts as a “type” here, indicating not the inference, but rather the absense of typing information.)

FunctionDefinitionshared FunctionDefinition

A function definition, using a block.

Exampes (multi-line):

shared void run() {
    print("Hello, `` process.arguments.first else "World" ``!");
}
shared actual Boolean equals(Object that) {
    if (is Color that) {
        return red == that.red && green == that.green && blue == that.blue;
    } else {
        return false;
    }
}
FunctionExpressionshared FunctionExpression

An expression that returns a callable function.

Unlike value expressions, function expressions don’t return instances of classes.

Examples (multi-line):

(String? name) => name else "John Doe"

(String string) {
    value mid = string.size / 2;
    return [string[...mid], [string[mid+1...]];
}
FunctionModifiershared FunctionModifier

A ‘function’ modifier keyword.

The ‘function’ modifier keyword indicates that the type of a function is inferred.

FunctionShortcutDefinitionshared FunctionShortcutDefinition

A function shortcut definition, using a lazy specifier and terminated by a semicolon.

Examples:

shared void run() => print("Hello, `` process.arguments.first else "World" ``!");
shared actual Boolean equals(Object that) => that is This;
GivenDecshared GivenDec

A type parameter reference expression, that is, the name of a type parameter, prefixed by the type keyword given and surrounded by backticks.

Examples:

`given Element`
`given Key`
GroupedExpressionshared GroupedExpression

A grouped, or parenthesized expression.

Examples:

(1 + 2) * 3
"Hello, " + (process.arguments.first else "World")
GroupedTypeshared GroupedType

A type, grouped in angle brackets to resolve lexical ambiguity:

String->String[]

is parsed as

Entry<String,String[]>

To get

Entry<String,String>[]

you need to write

<String->String>[]
IdenticalOperationshared IdenticalOperation

An identity test operation.

Defined natively, on objects that satisfy Identifiable. No associativity.

Examples:

node === rootNode
this === zero
Identifiershared abstract Identifier
IdentityOperationshared IdentityOperation

The expression +i.

This expression is defined to return i for any i of Invertible type.

(Not to be confused with IdenticalOperation, i === i.)

IfClauseshared IfClause

An if clause, that is, the keyword ‘if’, followed by a condition list and a IfClause.block.

Examples:

if (15 <= estimatedAge <= 25) { askForID(); }
if (exists elseClause = that.elseClause) { elseClause.visit(this); }
IfComprehensionClauseshared IfComprehensionClause

An ‘if’ comprehension clause, also knows as a filter clause.

An ‘if’ comprehension clause consists of the keyword ‘if’, a condition list and a following IfComprehensionClause.clause.

Examples:

if (person.age >= 18) person
if (exists typeArguments = that.typeArguments) for (typeArgument in typeArguments) typeArgument.type
IfElseshared IfElse

An if/else conditional.

The conditional begins with an if clause (ifClause) and may then optionally be followed by a chain of if/else clauses, optionally terminated by an else clause.

Examples (multi-line):

if (exists p = paragraphs.first) {
    setupAnchor(p);
    paragraphs.collect(output);
} else if (exists div) {
    visit(div.paragraphs);
} else {
    outputEmpty();
}

if (text.size >= terminalWidth) {
    print(text);
} else if (text.size >= remainingWidth) {
    wrap();
    print(text);
    remainingWidth = terminalWidth - text.size;
} else {
    print(text);
    remainingWidth -= text.size;
}
IfElseExpressionshared IfElseExpression

An if/then/else conditional expression, that is, the keyword ‘if’, followed by a condition list, the keyword ‘then’, followed by an expression, and the keyword ‘else’, followed by another expression.

The then and else expressions are both parsed with a precedence just below the then (ThenOperation) and else (ElseOperation) operations, to avoid ambiguity with these. Alternatively, they may be if/then/else expressions (IfElseExpression) or let expressions (LetExpression).

Examples (multi-line):

if (is Person p)
then p.name
else p.string

if (exists youngest = peopleSortedByAge.first, youngest.age >= 18)
then true
else false
Importshared Import

An import statement, that is, the keyword ‘import’ followed by the package name and the imported Import.elements from the package.

Examples:

import ceylon.ast.core { ... }
import java.lang { JString=String, System { sysout=\iout } }
import ceylon.collection { ArrayList, MutableList }
ImportAliasshared ImportAlias

An import alias, that is, an identifier followed by an “equals” character.

(Not to be confused with an alias declaration (TypeAliasDefinition) like alias TypeName => UIdentifier;.)

The specification distinguishes between TypeAliases and FunctionValueAliases, which differ in the kinds of identifiers they specify. However, the compiler does not actually enforce this distinction (mainly for improved interoperation with Java), and in ceylon.ast they are both merged into this one class.

Examples:

JString=
sysout=
ImportElementshared ImportElement

A single import element, that is, the name of an imported program element,
optionally preceded by an alias and/or followed by nested import elements to import and rename members.

The specification distinguishes between ImportTypeElements, ImportObjectElements and ImportFunctionValueElements, which differ in the kinds of identifiers they specify and in whether or not they may contain nested imports. However, the compiler does not actually enforce this distinction (mainly for improved interoperation with Java), and in ceylon.ast they are all merged into this one class.

Examples:

HashMap
ln=log
System { sysout=\iout }
ImportElementsshared ImportElements

A comma-separated list of import elements, where the last element may optionally be a wildcard instead, surrounded by braces.

(ceylon.ast ImportElements are slightly different from the specification’s ImportElements; in the specification, the surrounding braces are always part of the “parent” node (Import, ImportTypeElement), while in ceylon.ast, they are part of the ImportElements.)

Examples:

MutableList, ArrayList
JString=String, System { sysout=out }
ImportWildcardshared ImportWildcard

An import wildcard, that is, three colons (‘...’).

Used to indicate that all elements from a package should be imported.

InModifiershared InModifier

An ‘in’ modifier, indicating a contravariant type parameter or argument.

InOperationshared InOperation

A containment test expression.

Defined via contains.

Examples:

digit in (0..9).by(2)
user in authorizedUsers
input in { "yes", "no" }

The containment operation is special because the receiver of the method invocation by which it is defined is the right-hand side, not the left-hand side. In other words, lhs in rhs corresponds to

rhs.contains(lhs)

while e. g. lhs * rhs corresponds to

lhs.times(rhs)

(the qualifier and argument swapped places).

InitialComprehensionClauseshared abstract InitialComprehensionClause

A comprehension clause that can start a comprehension. Examples: for (person in people) “person.firstName person.lastName

if (exists typeArguments = that.typeArguments) for (typeArgument in typeArguments) typeArgument.type
InlineDefinitionArgumentshared abstract InlineDefinitionArgument

A named argument that defines a getter, function, or anonymous class, and assigns it to a parameter.

Examples (multi-line):

void onSuccess(Result result) {
    print(result);
    logger.end(currentTask, result);
}

object destroyable satisfies Destroyable {
    shared actual void destroy(Anything error) => process.exit(1);
}
IntegerLiteralshared IntegerLiteral

An integer literal may be expressed in decimal (no prefix), hexadecimal (prefix ‘#’) or binary (prefix ‘$’) notation. Integer literals may be grouped with underscores, and may contain a magnitude.

InterfaceAliasDefinitionshared InterfaceAliasDefinition

An interface alias definition.

An interface alias definition has the following components:

(While semantically, an interface alias may never have case types or satisfy other types, these nodes may syntactically still be present.)

Examples:

shared interface People => {Person*};
shared interface Compare<Value> => Comparison(Value,Value);
InterfaceBodyshared InterfaceBody

A list of declarations, surrounded by braces.

Unlike class bodies, interface bodies can’t immediately contain runnable code, so the InterfaceBody.content is just declarations, no statements. An exception from this are specifications, which, while technically statements, are allowed (shortcut refinement).

An interface body may also include a list of InterfaceBody.imports that is local to this interface body only.

Examples (multi-line):

{
    shared formal Other plus(Other other);
}
{
    shared default void writeString(String string) => print(string);
    shared default void write(Anything that) => writeString(that?.string else "<null>");
}
{
    shared formal String name;
    string => name;
}
InterfaceDecshared InterfaceDec

An interface reference expression, that is, the InterfaceDec.name of an interface, optionally qualified by a InterfaceDec.qualifier (separated from it by a member operator ‘.’), or empty for the current interface, prefixed by the type keyword interface and surrounded by backticks.

The InterfaceDec.qualifier may only be null if the InterfaceDec.name is also null. If the name exists, the qualifier must exist as well (but may of course be empty).

Examples:

`interface Iterable`
`interface A.B.C`
`interface`
InterfaceDefinitionshared InterfaceDefinition

A regular interface definition.

An interface definition has the following components:

Examples (multi-line):

shared interface Printable {
    shared default void print() => package.print(this);
}

shared interface Numeric<Other> of Other
        satisfies Invertible<Other>
        given Other satisfies Numeric<Other> {
    shared formal Other times(other);
    shared formal Other divided(other);
}
IntersectAssignmentOperationshared IntersectAssignmentOperation

An intersect assignment operation.

Right-associative. Any expression may appear on the right-hand side, regardless of precedence.

Examples:

people &= authorizedUsers
commonElements &= elements
IntersectionOperationshared IntersectionOperation

A set intersection expression.

Defined via intersection. Left-associative.

Examples:

persistents&printables&identifiables
x1&y1
IntersectionTypeshared IntersectionType

An intersection type.

Examples:

Element&Identifiable
Persistent&Printable&Identifiable
Invocationshared Invocation

An invocation, that is, an invoked expression with an argument list.

Examples:

print("Hello, World!")
process.kill()
ArrayList { initialCapacity = 100; 1, 1 }
InvocationStatementshared InvocationStatement

An invocation statement, that is, an invocation terminated by a semicolon.

(The invocation can also be an instantiation invocation.)

Examples:

print("Hello, World!");
that.visitChildren(this);
IsCaseshared IsCase

A ‘case’ item to test the type of the switch expression.

Examples:

is String
is Persistent&Serializable
is Integer|Float
IsConditionshared IsCondition

An assignability condition, that is, the keyword ‘is’, followed by an (optionally specified) typed variable and optionally prefixed by a negation operator ‘!’.

Examples:

is Integer|Float num
is Administrator user
IsOperationshared IsOperation

A postfix assignability test expression.

No associativity.

Examples:

element is String|Integer
user is ExecutiveUser
Iterableshared Iterable

An iterable object instantiation expression.

Examples:

{}
{ second, first, *rest.rest }
IterableTypeshared IterableType

An iterable type, like {String*} or {Integer+}.

Keyshared Key<Type>
given Type satisfies Object

A key by which a Node’s additional information can be accessed.

KeySubscriptshared KeySubscript

A key / index subscript expression, to select an element from a Correspondence expression.

The KeySubscript.key may be any expression except for a SpanOperation or MeasureOperation, which would be ambiguous with a SpanSubscript or MeasureSubscript.

Examples:

key
offset + i
LIdentifiershared LIdentifier

An initial lowercase identifier.

LargeAsOperationshared LargeAsOperation

A “large as” expression.

No associativity.

LargerOperationshared LargerOperation

A “larger than” expression.

No associativity.

LazySpecificationshared LazySpecification

A lazy specification statement, that is, a member name, optionally followed by one or more parameter lists, and specified by a lazy specifier.

Examples:

string => counter.string;
visitIdentifier(Identifier that) => names.put((names[that.name] else 0) + 1);
LazySpecifiershared LazySpecifier

A lazy expression specifier, that is, an expression prefixed by a computation operator ‘=>’.

Examples:

=> text.uppercased
=> nothing
LetExpressionshared LetExpression

A let expression, that is, the keyword ‘let’, followed by a list of patterns and an LetExpression.expression that can involve these patterns’ variables.

The expression is parsed with a precedence just below the then (ThenOperation) and else (ElseOperation) operations, to avoid ambiguity with these. Alternatively, it may be an if/then/else expression (IfElseExpression) or a let expression (LetExpression).

Examples:

let ([x,y] = loc, dist = sqrt(x^2 + y^2)) [x / dist, y / dist]
let (c = other.a, d = other.b) Complex(a*c - b*d, a*d + b*c)
Literalshared abstract Literal

A literal is a single token that represents a Unicode character, a character string, or a numeric value.

LocalModifiershared abstract LocalModifier

A modifier that indicates type inference.

It can only be used on local definitions (not toplevel, not shared), hence the name.

LogicalAssignmentOperationshared abstract LogicalAssignmentOperation

A logical assignment expression.

Right-associative. Any expression may appear on the right-hand side, regardless of precedence.

LogicalOperationshared abstract LogicalOperation

A logical binary operation expression.

MainTypeshared abstract MainType

“Main” types: the types that you normally use.

This class is used as “Type, except EntryType” in EntryType and VariadicType, since both of these can’t have entry types as children. In other words, this class is only there to represent how types are parsed, not their semantics.

MatchCaseshared MatchCase

A ‘case’ item to test if the switch expression matches one or more expressions.

Examples:

null
0 | 1
null | smaller | larger
MeasureOperationshared MeasureOperation

A measured range expression.

Defined via measure. No associativity.

Examples:

0:size
today:14
MeasureSubscriptshared MeasureSubscript

A measure subscript, to select a (sub)range from a Ranged expression using the first index and MeasureSubscript.length.

Examples:

0:30
match.start:match.size
MemberDecshared abstract MemberDec

A member reference expression.

Examples:

`value null`
`function Iterable.map`
MemberMetashared MemberMeta

A member metamodel expression, that is, a qualifying type, followed by a member name with optional type arguments, surrounded by backticks.

(A qualifier followed by a type name with optional type arguments surrounded by backticks is a TypeMeta.)

Examples:

`Person.say`
`system.milliseconds`
`Iterable<String>.collect<Integer?>`
MemberNameWithTypeArgumentsshared MemberNameWithTypeArguments

A member name and, optionally, type arguments.

MemberOperatorshared MemberOperator

A regular member operator, ‘.’.

Metashared abstract Meta

A metamodel expression, that is, a typed reference to a type, class, function or value.

Examples:

`List<String>`
`sum<Float>`
`system.milliseconds`

Not to be confused with Dec, which represents a detyped reference. Simply speaking, if there’s a keyword (`class String`, `value system`), then it’s a Dec, otherwise it’s a Meta.

(There is no ConstructorMeta class because the ConstructorMeta syntax from the specification is a strict subset of the TypeMeta syntax – every ConstructorMeta is parsed as a TypeMeta with a QualifiedType type.

Modifiershared abstract Modifier

A modifier keyword.

Note: The Ceylon Language Specification also refers to certain annotations, e. g. shared, abstract, variable, etc., as “modifiers” – see §7.4.1, Declaration Modifiers. In ceylon.ast, however, Modifier refers only to the reserved keywords that can be used on a function or value:

ModuleBodyshared ModuleBody

A module descriptor body, that is, any number of module imports surrounded by braces.

(Because a module body can’t contain procedural code, this is not a subclass of Body. If a future version of Ceylon allows procedural code in a module body, then this may change.)

Examples:

{}
{ shared import ceylon.test "1.2.0"; }
{ import ceylon.collection "1.2.0"; }
ModuleCompilationUnitshared ModuleCompilationUnit

A module descriptor compilation unit, containing a module descriptor.

Examples (separated by blank lines):

module tmp "1.0.0" {}

"Representation of a Ceylon AST in Ceylon."
by ("Lucas Werkmeister <mail@lucaswerkmeister.de>")
license ("http://www.apache.org/licenses/LICENSE-2.0.html")
module ceylon.ast.core "1.2.0" {
    import ceylon.collection "1.2.0";
}
ModuleDecshared ModuleDec

A module reference expression, that is, the name of a module (or empty for the current module), prefixed by the keyword “module” and surrounded by backticks.

Examples:

`module ceylon.language`
`module ceylon.ast.core`
`module`
ModuleDescriptorshared ModuleDescriptor

A module descriptor: a list of annotations, followed by the keyword ‘module’, and then the module ModuleDescriptor.name, ModuleDescriptor.version and ModuleDescriptor.body.

Examples (multi-line):

module tmp "1.0.0" {}

"Tests for the [[ceylon.ast.core module|module ceylon.ast.core]]"
by ("Lucas Werkmeister <mail@lucaswerkmeister.de>")
license ("http://www.apache.org/licenses/LICENSE-2.0.html")
module test.ceylon.ast.core "1.2.0" {
    shared import ceylon.test "1.2.0";
    import ceylon.ast.core "1.2.0";
}
ModuleImportshared ModuleImport

An import of another module within a module descriptor.

Each module import consists of a list of ModuleImport.annotations, followed by the keyword ‘import’, an optional repository type and colon, the ModuleImport.name of the imported module, and the ModuleImport.version of the imported module, terminated by a semicolon.

Examples:

shared import ceylon.test "1.2.0";
import ceylon.collection "1.2.0";
import maven:"commons-codec:commons-codec" "1.4";
MultiplyAssignmentOperationshared MultiplyAssignmentOperation

A multiply assignment operation (*=).

Right-associative. Any expression may appear on the right-hand side, regardless of precedence.

Examples:

balance *= 1 + interestRate
NameWithTypeArgumentsshared abstract NameWithTypeArguments

A name and, optionally, type arguments.

NamedArgumentshared abstract NamedArgument

A named argument.

Examples:

name;
size = width * height;
Color color(Integer x, Integer y) => red;
NamedArgumentsshared NamedArguments

A named argument list.

Any number of named arguments, followed by a (possibly empty) ordinary list of arguments.

Examples:

{}
{ name; size = width * height; }
{
    Head { title = pageTitle; }
    Body {
        for (paragraph in paragraphs)
            P(paragraph)
    }
}
NegationOperationshared NegationOperation

An arithmetic unary negation operation, that is, -i.

This operator is defined in terms of negated.

Nodeshared abstract Node

Abstract superclass of all AST nodes.

Note that nodes are not Identifiable: as they are immutable, the identity of a particular instance is meaningless.

Additional information

You can attach additional information to individual AST nodes using typed keys. Two sets of methods are available for this; Node.get(), Node.put() and Node.remove() offer more type safety and information, while Node.getObject(), Node.set() and Node.delete() can be slightly faster.

Usage example:

// toplevel
shared Key<Token[]> tokensKey
    = ScopedKey<Token[]>(`module my.parser`, "tokens");

// in the parser
node.put(tokensKey, tokens);

// somewhere else
assert (exists tokens = node.get(tokensKey)); // tokens has type Token[]
NonemptyConditionshared NonemptyCondition

A nonemptiness condition, that is, the keyword ‘nonempty’, followed by either a specified pattern or a member name referencing an existing value.

Examples:

nonempty employees
nonempty persons = people.sequence()
NonemptyOperationshared NonemptyOperation

A nonempty postfix expression.

No associativity.

NotEqualOperationshared NotEqualOperation

A not equals expression.

Defined via equals. No associativity.

Examples:

uid != 0
process.arguments.length != 7
NotOperationshared NotOperation

A logical not expression.

Right-associative.

Examples:

!n in primes
!predicate(element)
ObjectArgumentshared ObjectArgument

An object argument definition.

Examples (multi-line):

object destroyable satisfies Destroyable {
    shared actual void destroy(Anything error) => process.exit(1);
}

object items satisfies Iterable<Integer> {
    variable Integer accesses = 0;
    shared actual Iterator<Integer> iterator() => (0..(++accesses)).iterator();
}
ObjectDefinitionshared ObjectDefinition

An object definition.

Examples (multi-line):

shared object red extends Color(255, 0, 0) {
    string => "Red";
}

object stdoutWriter satisfies Writer {
    shared actual void close() => flush();
    shared actual void flush() {}
    shared actual void write(String string) {
        process.write(string);
    }
    shared actual void writeLine(String line) {
        process.writeLine(line);
    }
    shared actual void writeBytes({Byte*} bytes) {
        throw AssertionError("Can’t write bytes");
    }
}
ObjectExpressionshared ObjectExpression

An object expression, that is, the keyword ‘object’, followed by an optional extended type and optional satisfied types, and then a ObjectExpression.body.

Examples:

object satisfies Iterator<Anything> { next() => finished; }
OfOperationshared OfOperation

A coverage expression.

Narrows or widens the type of an expression to another type that covers the expression type.

Defined natively. No associativity.

Examples:

thing of Object?
component.parent of Container?
OpenBoundshared OpenBound

An open lower or upper bound of a bounded comparison operation.

In an open bound, the OpenBound.endpoint is not a part of the designated interval; therefore, when dealing with real numbers, the interval has no minimum / maximum value, as you can get infinitely close to the endpoint without reaching it.

For example, in the interval 0 < x < 1, the values 0.9, 0.99, 0.999, etc. for x are all within the interval.

Operationshared abstract Operation

An operator expression.

Operations combine Primaries, as well as other operations, depending on precedence. Operator precedence and associativity is represented in the AST through the child types of the nodes; an AST that would violate associativity (for example, using a sum expression as the direct child of a product expression – without wrapping it in a GroupedExpression) isn’t well-typed.

This class is called Operation rather than OperatorExpression to avoid overly long names of the subtypes; for the same reason, subtypes are only suffixed -Operation rather than -BinaryOperation or -UnaryOperation.

The specification also lists expressions like "Hello"[...3] under operators; in ceylon.ast, they are called ElementOrSubrangeExpression, and primaries.

OptionalTypeshared OptionalType

An optional type, that is, a shortcut for UnionType(definiteType, nullType).

Examples:

String?
<String->Integer>?
OrAssignmentOperationshared OrAssignmentOperation

A logical disjunction assignment expression.

Right-associative. Any expression may appear on the right-hand side, regardless of precedence.

Examples:

permitted ||= backdoorTriggered
canPrint ||= networkPrinterPresent
OrOperationshared OrOperation

A logical disjunction expression.

Left-associative.

Examples:

digit == 0 || digit == 1
element in errors || !element exists
OutModifiershared OutModifier

An ’out’ modifier, indicating a covariant type parameter or argument.

Outershared Outer

The value of this expression is the current instance of the type which immediately contains the immediately containing type, and its type is assignable to that type.

Packageshared Package

package isn’t actually an expression; it can be used to qualify and disambiguate a value or callable reference.

PackageCompilationUnitshared PackageCompilationUnit

A package descriptor compilation unit, containing a package descriptor.

Examples:

package tmp;
shared package ceylon.ast.core;
PackageDecshared PackageDec

A package reference expression, that is, the name of a package (or empty for the current package), prefixed by the keyword “package” and surrounded by backticks.

Examples:

`package ceylon.language`
`package ceylon.ast.core`
`package`
PackageDescriptorshared PackageDescriptor

A package descriptor: a list of annotations, followed by the keyword ‘package’, the package name, and terminated by a semicolon.

Examples:

package tmp;
"Test package" see (`package my.application`) package test.my.application;
PackageQualifiershared PackageQualifier

A package qualifier, that is, the keyword ‘package’ followed by a member operator.

(The member operator is implicit and not an actual child node.)

This node is used in types and meta expressions and not to be confused with Package, which is used in regular expressions.

Parametershared abstract Parameter

A class, method, or function parameter.

Examples:

String name
comparing
Integer length = text.size
Element+ elements
ParameterReferenceshared ParameterReference

The name of a parameter, without type information.

There are two possible interpretations of such a parameter:

  1. The parameter is later declared in the body of the function or class. This is frequently used for class parameters, where having the documentation in the parameter list would clutter the parameter list.
  2. The type of the parameter is inferred. This is only legal for anonymous functions, and intended for small one-line arguments to functions like map or filter (with a LazySpecifier rather than a Block).

Examples:

comparing
name
Parametersshared Parameters

A parameter list.

Examples:

()
(String text, Integer length = text.size)
(Element+ elements)

A note about this class’ parameters

It would seem reasonable to instead declare the parameters of this class like this:

class Parameters(RequiredParameter[] required,
    DefaultedParameter[] defaulted,
    VariadicParameter|ParameterReference variadic)

Note that variadic must have the type VariadicParameter|ParameterReference, not just VariadicParameter, because a variadic parameter can also be just a reference, and declared in the body of the function or class. And this is where the problem comes in:

(param)

In this parameter list, is param a required or a defaulted parameter? In other words, is this

  • a Parameters { required = [param]; }, or
  • a Parameters { variadic = param; }?

To decide this, you need to look into the body of the function, and check if the declaration of param has a regular or a variadic type. This is a semantical distinction, not a syntactical one, and in general we can’t expect tools that operate on an AST to be able to make this distinction.

Instead, we have just one list of parameters; the separation into required, defaulted, and variadic ones may then be done in later stages of AST processing.

Patternshared abstract Pattern

A pattern declares one or multiple variables.
Destructuring statements, assertions, and some control structures can instantiate the pattern, possibly destructuring the original value in the process.

The simplest and most common form is the VariablePattern.

Examples:

e
String line
k->v
[first, *rest]
name->[lat, lon]
PatternListshared PatternList

A comma-separated list of specified patterns, enclosed in parentheses.

Used in let expressions (LetExpression).

Examples:

(c = other.a, d = other.b)
([x,y] = loc, dist = sqrt(x^2 + y^2))
PositionalArgumentsshared PositionalArguments

A positional argument list.

A list of arguments where the mapping from an argument to its parameter is based only on the position of the argument. Syntactically, this is just a wrapper for an ArgumentList, enclosed in parentheses.

Examples:

(x, y, *messages)
()
(for (i in 1..10) i^2)
PostfixDecrementOperationshared PostfixDecrementOperation

A postfix decrement expression (i--).

PostfixIncrementOperationshared PostfixIncrementOperation

A postfix increment expression (i++).

PostfixOperationshared abstract PostfixOperation

A postfix arithmetic expression, that is, i++ or i-- for any Primary i.

PrefixDecrementOperationshared PrefixDecrementOperation

A prefix decrement expression (--i).

PrefixIncrementOperationshared PrefixIncrementOperation

A prefix increment expression (++i).

PrefixOperationshared abstract PrefixOperation

A prefix arithmetic expression, that is, ++i or --i for any Primary i.

PrefixPostfixStatementshared PrefixPostfixStatement

A prefix or postfix increment or decrement expression statement.

Examples:

i++;
--size;
Primaryshared abstract Primary

A primary expression.

Primaries can be combined using operations.

PrimaryTypeshared abstract PrimaryType

A primary type; only intersection, union and entry types come before these.

ProductOperationshared ProductOperation

A product expression.

Defined via times. Left-associative.

QualifiedExpressionshared QualifiedExpression

A receiver expression, followed by a member operator (usually ‘.’) and an (unqualified) identifier with optional type arguments.

Examples:

", ".join
process.arguments.first
people*.name
sort(people, byAscending(Person.salary)).first?.salary
QualifiedTypeshared QualifiedType

A qualified type, consisting of a qualifying type and a type name with arguments, separated by a member operator.

Foo.Bar // Foo is the qualifying type, Bar the type name
X<A>.Y<B>.Z<C> // X<A>.Y<B> is the qualifying type – another qualified type –, Z the type name and C the type arguments
QuotientOperationshared QuotientOperation

A quotient or division expression.

Defined via divided. Left-associative.

RangeSubscriptshared abstract RangeSubscript

A range subscript, to select a (sub)range from a Ranged expression.

Examples:

1 .. text.size - 2
1...
RemainderAssignmentOperationshared RemainderAssignmentOperation

A remainder assignment operation (%=).

Right-associative. Any expression may appear on the right-hand side, regardless of precedence.

Examples:

increment %= step
RemainderOperationshared RemainderOperation

A remainder expression.

Defined via remainder. Left-associative.

RequiredParametershared abstract RequiredParameter

A required parameter (neither defaulted nor variadic).

Examples:

String name
comparing
Resourceshared Resource

A resource in a try-with-resources statement.

Examples:

lock
writer = file.Writer()
Resourcesshared Resources

A comma-separated list of Resources.resources, surrounded by parentheses.

Examples:

(lock)
(reader = inFile.Reader(), writer = outFile.Writer())
Returnshared Return

A return directive, with an optional returned expression.

SafeMemberOperatorshared SafeMemberOperator

A nullsafe member operator, ‘?.’.

Technically, the nullsafe attribute operator and the nullsafe method operator are two different operators, since a nullsafe invocation is not the same as an invocation of a nullsafely accessed method attribute; however, that distinction is only semantical, not syntactical, and therefore does not belong in the AST.

SatisfiedTypesshared SatisfiedTypes

A nonempty list of satisfied types, separated by the intersection operator (‘&’).

Examples:

satisfies {Element+}
satisfies Printable & Persistent
ScaleOperationshared ScaleOperation

A scale expression.

Defined via scale. Right-associative.

Examples:

2 ** vector
brakeFactor ** velocity

The scale operation is special because the receiver of the method invocation by which it is defined is the right-hand side, not the left-hand side. In other words, lhs ** rhs corresponds to

rhs.scale(lhs)

while e. g. lhs * rhs corresponds to

lhs.times(rhs)

(the qualifier and argument swapped places).

ScopedKeyshared ScopedKey<Type>
given Type satisfies Object

A Key with an explicitly provided scope, to avoid name collisions.

Usage example:

shared Key<Token[]> tokensKey
        = ScopedKey<Token[]>(`class CeylonParser`, "tokens");
SelfReferenceshared abstract SelfReference

this, super, outer and package are self reference expressions. The type of these expressions depends on the context in which they appear.

SequentialTypeshared SequentialType

A sequential type, that is, a primary type, followed by an opening bracket, optionally an integer SequentialType.length, and a closing bracket.

If the length is absent, this is a shortcut for Sequential<ElementType>; with the length present, it is a shortcut for a tuple of length elements of the element type.

Examples:

String[]
<String->Integer>[]
Boolean[2] // shortcut for [Boolean,Boolean]
SetAssignmentOperationshared abstract SetAssignmentOperation

A set assignment operation.

Right-associative. Any expression may appear on the right-hand side, regardless of precedence.

SetOperationshared abstract SetOperation

A set operation: intersection, union or complement.

SimpleTypeshared abstract SimpleType

A simple type: One or more TypeNamesWithArguments, separated by member operators.

String
Iterable<String,Nothing>
Outer.Inner

The type of every instance can be written as a SimpleType.

SmallAsOperationshared SmallAsOperation

A “small as” expression.

No associativity.

SmallerOperationshared SmallerOperation

A “smaller than” expression.

No associativity.

SpanFromSubscriptshared SpanFromSubscript

A span-from subscript, to select a (sub)range from a Ranged expression using the first index.

Examples:

1...
match.start ...
SpanOperationshared SpanOperation

A spanned range expression.

Defined via span. No associativity.

Examples:

0..9 monday..friday first.successor..last.predecessor

SpanSubscriptshared SpanSubscript

A span subscript, to select a (sub)range from a Ranged expression using the first and last index.

Examples:

1 .. text.size - 2
text.size - 1 .. 0
SpanToSubscriptshared SpanToSubscript

A span-to subscript, to select a (sub)range from a Ranged expression using the last index.

Examples:

... text.size - 1
...count
Specificationshared abstract Specification

A specification statement.

Examples:

offset = preamble.size + title.size;
debug(Anything a) => process.writeErrorLine(a);
SpecifiedArgumentshared SpecifiedArgument

A specified named argument, that is, a Specification.

Examples:

groupSeparators = false;
initialCapacity = 256;
SpecifiedPatternshared SpecifiedPattern

A SpecifiedPattern.pattern followed by a SpecifiedPattern.specifier that is assigned to the pattern.

Examples:

[head, *tail] = elements.sequence()
name = people.filter((p) => p.age < 18).first?.name?.uppercased
SpecifiedVariableshared SpecifiedVariable

A specified inline variable declaration.

Examples:

num = parseFloat(numString)
String name = person.name
Specifiershared Specifier

An expression specifier, that is, an expression prefixed by a specification operator ‘=’.

Examples:

= 1
= nothing
SpreadArgumentshared SpreadArgument

A spread argument.

Used in argument lists to “spread” a sequential value over multiple arguments.

(The spread “operator” * looks like a prefix unary operator, but because it produces multiple values, not just one, a spread argument is not an expression.)

Examples:

*args
*values.collect(Object.string)
*[]
SpreadMemberOperatorshared SpreadMemberOperator

A spread member operator, ‘*.’.

Technically, the spread attribute operator and the spread method operator are two different operators, since a spread invocation is not the same as an invocation of a spread accessed method attribute; however, that distinction is only semantical, not syntactical, and therefore does not belong in the AST.

SpreadTypeshared SpreadType

A spread type.

Used in a CallableType.

Examples:

*Args
*[String,Integer]
Statementshared abstract Statement

A statement.

Examples:

value name = person.name else "<unnamed>";
print("Hello, World!");
StringLiteralshared StringLiteral

A string literal consists of a series of characters and/or, if it’s not verbatim, escape sequences.

StringTemplateshared StringTemplate

A string template, that is, a string start, followed by any number of value expression and string mid pairs, followed by a value expression and a string end.

(The distinction between string starts, mids, and ends is a purely lexical one, and not covered in ceylon.ast.)

There must be at least one expression in a string template, and the number of string literals must be exactly the number of expressions plus one.

Examples:

"Elapsed: `` tEnd - tStart ``ms"
"Hello, ``person.firstName`` ``person.lastName``. How nice to see you back in ``person.homeTown``."
Subscriptshared abstract Subscript

A subscript used to access an element or subrange in a ElementOrSubrangeExpression (where it is surrounded by brackets).

In mathematical notations, these accessors are usually written as subscript, e. g. xi for the ith x element.

Examples:

index
... text.size - 2
SubtractAssignmentOperationshared SubtractAssignmentOperation

A subtract assignment operation (-=).

Right-associative. Any expression may appear on the right-hand side, regardless of precedence.

Examples:

countdown -= \iΔt
SumOperationshared SumOperation

A sum expression.

Defined via plus. Left-associative.

Examples:

i + 1
firstIndex + size
Supershared Super

The value of this expression is the current instance, and its type is the intersection of the immediate superclass and all immediate superinterfaces of the current class.

SwitchCaseElseshared SwitchCaseElse

A switch/case/else statement, that is, a switch clause (clause), followed by SwitchCaseElse.cases.

Examples (multi-line):

switch (i.magnitude)
case (0 | 1) { return false; }
case (2) { return true; }
else {
    return i % 2 == 1 && expensivePrimeTest(i);
}

switch (that)
case (is Block) { return transformBlock(that); }
case (is IfElse) { return transformIfElse(that); }
SwitchCaseElseExpressionshared SwitchCaseElseExpression

A switch/case/else expression, that is, a switch clause (switchClause), followed by one or more case expressions (caseExpressions) and optionally an else expression (elseExpression) preceded by an ‘else’ keyword.

Examples:

switch (seq) case (null) "null" case (is []) "empty" else "nonempty"
switch (text.first) case ('$') 2 case ('#') 16 case ('0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9') 10 else nothing
SwitchCasesshared SwitchCases

A list of ‘case’ clauses (with an optional trailing ‘else’ clause) for a switch statement (SwitchCaseElse).

Examples (multi-line):

case (is Block) { return transformBlock(that); }
case (is IfElse) { return transformIfElse(that); }

case (0 | 1) { return false; }
case (2) { return true; }
else {
    return i % 2 == 1 && expensivePrimeTest(i);
}
SwitchClauseshared SwitchClause

A ‘switch’ clause of a switch statement (SwitchCaseElse), that is, the keyword ‘switch’, followed by an expression or variable definition.

Examples:

switch (i.magnitude)
switch (child)
switch (arg = process.arguments.first)
ThenOperationshared ThenOperation

A “then” operation.

Left-associative.

Examples:

!name.empty then name
age != -1 then age
Thisshared This

The value of this expression is the current instance, and its type is the immediately containing type.

Throwshared Throw

A throw directive, with an optional thrown exception.

TryCatchFinallyshared TryCatchFinally

A try-cA try/catch/finally statement, that is, a try’ clause (tryClause), followed by any amount of catch’ clauses (catchClauses), and optionally terminated by a finally’ clause (finallyClause).

Examples (multi-line):

// removing a non-critical entity, e. g. when running low on resources
try (writer = file.Writer()) {
    that.serialize(writer);
} finally {
    despawn(that);
}

// a compilation controller
try (lock) {
    compilationUnit.compile(this);
} catch (CancellationException e) {
    // ignore
} catch (otherException) {
    log(otherException);
    compilationUnit.compiled = false;
}
TryClauseshared TryClause

A ‘try’ clause, that is, the keyword ‘try’, followed optionally by TryClause.resources and then by a TryClause.block (required).

Examples (multi-line):

try {
    value zombie = spawn { Zombie; center = player.location; spread = 50; };
    zombie.aggro = player;
}

try (writer = file.Writer()) {
    that.serialize(writer);
}
Tupleshared Tuple

A tuple instantiation expression.

Examples:

[]     
[x, y]
[father, mother, *children]
TuplePatternshared TuplePattern

A tuple pattern, that is, several patterns, including optionally a trailing variadic one, separated by commas and enclosed in brackets.

(There must be at least one total pattern, i. e., the element patterns may only be empty if the variadic element pattern is present.)

Examples:

[x, y, z]
[first, *rest]
TupleTypeshared TupleType

A tuple type.

Examples:

[String,Integer,Integer]
[Float,Integer*]
[]
Typeshared abstract Type

Representation of a type.

TypeAliasDefinitionshared TypeAliasDefinition

A type alias definition.

A type alias definition has the following components:

Examples:

alias Primitive => Boolean|Integer|Float|Character|String|Null;
alias AnyMutableSet<Element> given Element satisfies Object => Set<Element>&SetMutator<Element>;
TypeArgumentshared TypeArgument

A type argument, that is, a TypeArgument.type with optional TypeArgument.variance (use-site variance).

(Use-site variance is only rarely used; most of the time, TypeArgument.variance should be null.)

Examples:

String
out T
TypeArgumentsshared TypeArguments

A comma-separated list of type arguments, enclosed in angle brackets.

Examples:

<String,Nothing>
<out Element>
<>
TypeConstraintshared TypeConstraint

A constraint upon a type parameter.

Examples:

given Key satisfies Object
given Printable of String | Integer | Float
given T of T1|T2|T3 satisfies U
TypeDecshared abstract TypeDec

A type reference expression.

TypeDeclarationshared abstract TypeDeclaration

A type declaration.

Examples (multi-line):

shared interface Printable {
    shared default void print() {
        package.print(this);
    }
}

shared alias TypeName => UIdentifier;
TypeIshshared abstract TypeIsh

All node types in the type sub-hierarchy: Type and some auxiliary node types that aren’t proper Types.

(For example, while String* is part of the valid type {String*}, it’s not a valid type by itself.)

TypeListshared TypeList

A list of types, with an optional trailing variadic type.

Examples:

String, String, String+
TypeMetashared TypeMeta

A type metamodel expression, that is, a Type surrounded by backticks.

Examples:

`List<String>`
`Integer|Float`
TypeModifiershared abstract TypeModifier

A modifier that can be used instead of a type in some places.

This includes:

  • the local modifiers ‘value’ and ‘function’, indicating type inference;
  • the ‘void’ modifier, indicating that a function doesn’t return a value; and
  • the ‘dynamic’ modifier, indicating absense of any typing information.
TypeNameWithTypeArgumentsshared TypeNameWithTypeArguments

A type name and, optionally, type arguments.

TypeParametershared TypeParameter

A type parameter of a class, method or function.

The type parameter may optionally declare a type TypeParameter.variance (without one, it is invariant) and/or a default type argument (used when the use-site declares some but not all type arguments).

Examples:

out Element
out Absent=Null
TypeParametersshared TypeParameters

A nonempty comma-separated list of type parameters, surrounded by angle brackets.

Examples:

<in Key, out Item>
<out Element>
TypeSpecifiershared TypeSpecifier

A type specifier, that is, a type prefixed by a computation operator ‘=>’.

Examples:

=> Map<String,Person>
=> Comparison(Value,Value)
TypedDeclarationshared abstract TypedDeclaration

A declaration with a type.

The type can either be explicitly specified (TypedDeclaration.type is a Type) or inferred (TypedDeclaration.type is a Modifier that indicates type inference).

Examples:

shared String name;
shared actual void visit(Node that) { print(that); that.visitChildren(this); }
TypedVariableshared TypedVariable

A typed inline variable declaration.

Examples:

Integer|Float num
String name
UIdentifiershared UIdentifier

An initial uppercase identifier.

UnaryArithmeticOperationshared abstract UnaryArithmeticOperation

A unary arithmetic expression, that is, +i or -i.

UnaryIshOperationshared abstract UnaryIshOperation

An expression consisting of a ValueExpression, an operator, and possibly a Type.

These can be regular unary operations – either prefix or postfix – or unary type operations, which are always postfix, and include a type.

UnaryOperationshared abstract UnaryOperation

A unary operator expression.

UnaryTypeOperationshared abstract UnaryTypeOperation

A unary type operation.

A subclass of UnaryIshOperation, not BinaryOperation, because the second child is a UnaryTypeOperation.type rather than a ValueExpression.

UnionAssignmentOperationshared UnionAssignmentOperation

A union assignment operation.

Right-associative. Any expression may appear on the right-hand side, regardless of precedence.

Examples:

students |= course.students
allElements |= elements
UnionOperationshared UnionOperation

A set union expression.

Defined via union. Left-associative.

Examples:

ints|floats
x1&y1|x2&y2
UnionTypeshared UnionType

A union type.

Examples:

String|Integer|Float
UnionableTypeshared abstract UnionableType

Types that can be children of a UnionType.

This class is only there to represent how types are parsed, not their semantics.

UnspecifiedVariableshared UnspecifiedVariable

An unspecified inline variable declaration.

The value of the variable is assigned by the surrounding construct, e. g. the current iteration result, or the caught exception.

Examples:

element
AssertionError ae
ValueArgumentshared ValueArgument

An inline getter argument definition.

Examples (multi-line):

String val {
    StringBuilder sb = StringBuilder();
    for (person in people) {
        sb.append("``person.firstName`` ``person.lastName``");
        if (exists age = person.age) {
            sb.append(", ``age`` year`` age != 1 then "s" else "" ``");
        }
        sb.appendNewline();
    }
    return sb.string;
}

value elements = people.collect(Person.age);
ValueConstructorDefinitionshared ValueConstructorDefinition

A value constructor definition.

A value constructor definition has the following components:

Examples (multi-line):

shared new origin {
    x = 0.0; y = 0.0;
    r = 0.0; φ = 0.0;
}

shared new red {
    rgb = #FF0000;
}
ValueDecshared ValueDec

A value reference expression, that is, the ValueDec.name of a value, qualified by a (possibly empty) ValueDec.qualifier (separated from it by a member operator ‘.’), prefixed by the member keyword value and surrounded by backticks.

Examples:

`value null`
`value Iterable.first`
ValueDeclarationshared ValueDeclaration

A value declaration.

A value declaration declares the ValueDeclaration.name and ValueDeclaration.type of the value, but doesn’t provide a ValueDeclaration.definition for it. There are several possible reasons for this:

  • The value can be a formal attribute and be a member of an abstract class
    or an interface, and subtypes have to provide the definition.
  • The value can be the declaration of a class or function parameter that only listed the name (and potentially a default value).
  • The value can be forward-declared, and the definition will be provided later.

In any case, the declaration must explicitly specify a type; a Modifier indicating type inference cannot be used. (The ’dynamic’ modifier counts as a “type” here, indicating not the inference, but rather the absense of typing information.)

ValueDefinitionshared ValueDefinition

A value definition, using a specifier.

Examples:

shared actual String string => "``name`` from ``countryOfOrigin`` of age ``age``";
shared actual Null definition = null;
ValueExpressionshared abstract ValueExpression

An expression that returns an ordinary value.

Value expressions return instances of classes, while function expressions return first-class functions.

ValueGetterDefinitionshared ValueGetterDefinition

A value definition, using a getter block.

Examples:

shared actual String string { value s = element.string; return ", ".join(Singleton(element).cycled.take(size)); }
ValueModifiershared ValueModifier

A ‘value’ modifier keyword.

The ‘value’ modifier keyword indicates that the type of a value is inferred.

ValueParametershared ValueParameter

A value parameter.

Examples:

String name
Integer length
Boolean(Element) selecting
shared Address privateAddress
ValueSetterDefinitionshared ValueSetterDefinition

A setter definition, that is, the keyword ‘assign’, followed by the ValueSetterDefinition.name of the value and the ValueSetterDefinition.definition (either a block or a lazy specifier terminated by a semicolon), preceded by ValueSetterDefinition.annotations.

Examples:

assign diameter => radius = diameter / 2;
assign diameter {
    throw AssertionError("Can’t set the diameter of the unit circle");
}
ValueSpecificationshared ValueSpecification

A value specification statement, that is, a member name followed by a Specifier.

Examples:

size = 0;
it = iterators.next();
Variableshared abstract Variable

An inline variable declaration.

Assertions and some control structures allow inline declarations of variables.

Examples:

firstEmployee = employees.first
Integer|Float num
VariablePatternshared VariablePattern

A simple variable pattern.

Examples:

e
String line
VariadicParametershared VariadicParameter

A variadic parameter.

Examples:

Element+ elements
String* messages
"The indexes" Integer+ indexes
VariadicTypeshared VariadicType

A variadic type is a MainType followed by a “*” (possibly-empty) or a “+” (nonempty).

VariadicVariableshared VariadicVariable

A variadic pattern variable.

These only occur within tuple patterns.

Examples:

*others
String *rest
Varianceshared abstract Variance

A modifier that indicates type parameter / argument variance.

Examples:

in
out
VoidModifiershared VoidModifier

A ‘void’ modifier keyword.

Whileshared While

A while loop, that is, the keyword ‘while’, followed by While.conditions and a While.block.

Examples:

while (i++ <= count) { lines.add(process.readLine()); }
while (!((elem = it.next()) is Finished)) { expressions.add(elem); literals.add(it.next()); }
WithinOperationshared WithinOperation

A bounded comparison operation, also known as “within” operation.

Examples:

0 <= x < 10
1 <= x <= 31