This module defines types for a Ceylon Abstract Syntax Tree (AST), a hierarchical and immutable data structure that represents a Ceylon program.
There are two major ways to obtain an AST:
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")))
The ceylon.ast.redhat
module (module ceylon.ast.redhat
) allows you to
compile 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.
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.
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).
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 if
s 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.
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
.)
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 distinction between syntactical and semantical restrictions is sometimes
unclear or ambiguous; note especially that the RedHat compiler’s parser
(grammar) allows (for better error messages) some syntax that is refused
in ceylon.ast
(for example, empty resource lists for try
).
ceylon.ast
seeks to comply only with the Ceylon Language Specification,
not its implementation in the compiler.
Packages | |
ceylon.ast.core |
Dependencies | ||
ceylon.collection | 1.2.2 |
Aliases | |
AddingExpression | shared AddingExpression=> ScalingExpression|SumOperation|DifferenceOperation An expression on or above the precedence level of addition and subtraction. |
AssigningExpression | shared AssigningExpression=> ThenElseExpression|AssignmentOperation An expression on or above the precedence level of assignment. This contains all “Layer 4” operators, that is, all operators total. |
ComparingExpression | shared ComparingExpression=> ExistsNonemptyExpression|IsOperation|OfOperation|InOperation|ComparisonOperation|CompareOperation|WithinOperation An expression on or above the precedence level of comparison, containment, assignability and inheritance tests. |
ConjoiningExpression | shared ConjoiningExpression=> NegatingExpression|AndOperation An expression on or above the precedence level of logical conjunction. |
DisjoiningExpression | shared DisjoiningExpression=> ConjoiningExpression|OrOperation An expression on or above the precedence level of logical disjunction. This contains all “Layer 3” operators. |
EquatingExpression | shared EquatingExpression=> ComparingExpression|EqualityOperation An expression on or above the precedence level of equality tests. This contains all “Layer 2” operators. |
ExistsNonemptyExpression | shared ExistsNonemptyExpression=> SpanningExpression|ExistsOperation|NonemptyOperation An expression on or above the precedence level of existence and nonemptiness tests. |
ExponentiatingExpression | shared ExponentiatingExpression=> PrePostfixingExpression|ExponentiationOperation An expression on or above the precedence level of exponentiation. |
IntersectingExpression | shared IntersectingExpression=> InvertingExpression|IntersectionOperation An expression on or above the precedence level of intersection. |
InvertingExpression | shared 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 ( |
MemberName | shared MemberName=> LIdentifier |
MultiplyingExpression | shared MultiplyingExpression=> UnioningExpression|ProductOperation|QuotientOperation|RemainderOperation An expression on or above the precedence level of multiplication or division. |
NegatingExpression | shared 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 ( |
PackageName | shared PackageName=> LIdentifier |
PrePostfixingExpression | shared 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.) |
ScalingExpression | shared ScalingExpression=> MultiplyingExpression|ScaleOperation An expression on or above the precedence level of scaling. |
SpanningExpression | shared SpanningExpression=> AddingExpression|SpanOperation|MeasureOperation|EntryOperation An expression on or above the precedence level of range and entry construction. This contains all “Layer 1” operators. |
StructureExpression | shared StructureExpression=> DisjoiningExpression|IfElseExpression|SwitchCaseElseExpression|LetExpression An expression on or above the precedence level of “structural” expressions. |
ThenElseExpression | shared ThenElseExpression=> StructureExpression|ThenOperation|ElseOperation An expression on or above the precedence level of “ |
TypeName | shared TypeName=> UIdentifier |
UnioningExpression | shared UnioningExpression=> IntersectingExpression|UnionOperation|ComplementOperation An expression on or above the precedence level of union or complementation. |
Functions | |
annotation | shared Annotation annotation(String name) Shortcut helper function for an |
lidentifierNeedsPrefix | shared Boolean lidentifierNeedsPrefix(String name) Parameters:
|
uidentifierNeedsPrefix | shared Boolean uidentifierNeedsPrefix(String name) Parameters:
|
Interfaces | |
CascadingNarrowingTransformer | shared CascadingNarrowingTransformer<out Result> A 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 |
Editor | shared 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 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. |
ImmediateNarrowingTransformer | shared ImmediateNarrowingTransformer<out Result> A For example: shared actual default Result transformValueExpression(ValueExpression that) => that.transform(this); This interface should be functionally equivalent to |
NarrowingTransformer | shared NarrowingTransformer<out Result> A There are two ways to perform this narrowing:
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. |
Transformer | shared Transformer<out Result> Abstract interface to perform some operations on AST nodes and possibly get some result. For every subtype of
Be careful when mixing the two behaviors, lest you end up in an infinite recursion! |
Visitor | shared 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 Note: conceptually, a |
WideningTransformer | shared WideningTransformer<out Result> A |
Classes | |
AddAssignmentOperation | shared AddAssignmentOperation An add assignment operation ( Right-associative. Examples: index += step document.cursor.position += insertion.size |
AliasDec | shared AliasDec An alias reference expression, that is,
the Examples: `alias TypeName` `alias A.B.C |
AndAssignmentOperation | shared AndAssignmentOperation A logical conjunction assignment expression. Right-associative. Examples: valid &&= parsed exists legal &&= !globalLock |
AndOperation | shared AndOperation A logical conjunction expression. Left-associative. Examples: i%2 == 0 && j%2 == 1 attr1 == that.attr1 && attr2 == that.attr2 && attr3 == that.attr3 |
Annotation | shared Annotation An annotation. For the common case “no arguments”, the toplevel helper function Examples: shared formal by ("John Doe <john.doe@company.com>") see (`function print`) action { description = "Log in"; url = "/login"; } |
Annotations | shared 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 Annotations are not separated by any punctuation. Examples: shared formal "The number of elements in this list" see (`value List.lastIndex`) shared actual |
AnonymousArgument | shared AnonymousArgument An anonymous named argument, that is, an expression followed by a semicolon. Examples: name; width * height; |
AnyClass | shared 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); |
AnyCompilationUnit | shared 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 Every compilation unit starts with a (possibly empty) list of Examples (separated by blank lines): module tmp "1.0.0" {} package tmp; void run() { print("Hello, World!"); } |
AnyFunction | shared abstract AnyFunction A function declaration or definition. If the 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" ``!"); |
AnyInterface | shared abstract AnyInterface An interface definition or alias. Examples (multi-line): shared interface Printable { shared default void print() => package.print(this); } shared interface People => {Person*}; |
AnyInterfaceDefinition | shared 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; // ... } |
AnyMemberOperator | shared abstract AnyMemberOperator A member operator, used in a |
AnySpecifier | shared abstract AnySpecifier |
AnyValue | shared abstract AnyValue A value declaration or definition. If the Examples: shared String name; shared formal Comparison compare(Other that); shared default Boolean empty => iterator().next() is Finished; |
ArgumentList | shared 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 |
Arguments | shared abstract Arguments An argument list that can be used in an Not to be confused with Examples: (x, y, *messages) () (for (i in 1..10) i^2) { factor = 2.1; *actors } |
ArithmeticAssignmentOperation | shared abstract ArithmeticAssignmentOperation An arithmetic assignment operation,
a shortcut for an Right-associative. |
ArithmeticOperation | shared abstract ArithmeticOperation An arithmetic operation expression. |
Assertion | shared Assertion An assertion statement, that is,
an annotation list, followed by the keyword ‘ Examples: assert (exists num = parseFloat(numText)); "Weight cannot be negative" assert (weight >= 0); |
AssignOperation | shared AssignOperation An assignment expression. Right-associative. Examples: i = 1 text = "Hello, ``name else "World"``!" |
AssignmentOperation | shared abstract AssignmentOperation An assignment expression. Right-associative. This is the abstract superclass of all assignment operations, with operators like |
AssignmentStatement | shared AssignmentStatement An assignment expression statement, that is, an assignment terminated by a semicolon. In principle, a statement like Examples: text.length += added.length; ret.endToken = tokens.token(";", semicolon); |
Atom | shared 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 |
BaseExpression | shared BaseExpression An unqualified identifier with an optional list of type arguments. A base expression can refer to either:
Examples: null max<Integer,Nothing> |
BaseMeta | shared BaseMeta A base metamodel expression, that is,
a member name with optional type arguments,
optionally qualified with a ‘ (A type name with optional type arguments surrounded by backticks is a Examples: `sum<Float>` `system` `package.null` |
BaseType | shared BaseType A type name with optional type arguments. The type name may optionally be qualified by a ‘ Examples: String List<Character> package.Object |
BinaryOperation | shared abstract BinaryOperation A binary operator expression. Binary operations can be left-associative ( (Some binary operations have no precedence because they can’t be nested
(for example, |
Block | shared 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. 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 ""; } } |
Body | shared abstract Body A list of statements and declarations, surrounded by braces. Examples: {} { shared String name; string => name; } |
BooleanCondition | shared BooleanCondition A boolean condition, that is, an expression. The condition is satisfied when the expression evaluates to Examples: type in { type_ws, type_comment } literals.size == expressions.size + 1 |
Bound | shared abstract Bound A lower or upper bound of a bounded comparison operation. |
Break | shared Break A |
CallableConstructorDefinition | shared 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); } |
CallableParameter | shared CallableParameter A callable parameter. Examples: Comparison comparing(Element left, Element right) void onSuccess() |
CallableType | shared CallableType A callable type. Examples: Integer(Integer,Integer) String(Character*) Ret(*Args) |
CaseClause | shared CaseClause A ‘ Examples (multi-line): case (is String) { int = parseInteger(val); } case (null) { return; } |
CaseExpression | shared CaseExpression A ‘ The expression is parsed with a precedence just below
the Examples: case (is Integer) val / 2 case ('$') 2 |
CaseItem | shared abstract CaseItem A ‘ Examples: is String 0, 1 |
CaseTypes | shared CaseTypes A nonempty list of case types, separated by the union operator (‘ Examples: of String | Float | Integer of Other of empty | [Element+] |
CatchClause | shared CatchClause A ‘ Examples (multi-line): catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (e) { console.error(e); } |
CeylonExpressionTransformer | shared 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()); |
CharacterLiteral | shared CharacterLiteral A character literal consists of a single character or an escape sequence. |
ClassAliasDefinition | shared 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); |
ClassBody | shared ClassBody A list of statements and declarations, surrounded by braces. Logically, a class body is divided into two sections:
There is, however, no syntactical separation between these,
so syntactically a class body looks exactly like a 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) { ████ ███████ ██ █; } } |
ClassDec | shared ClassDec A class reference expression, that is,
the The value dec1 = `class null`; value dec2 = `value null`;
The Examples: `class String` `class A.B.C` `class` |
ClassDefinition | shared 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++; } |
ClassOrInterface | shared 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; } |
ClassSpecifier | shared ClassSpecifier A class specifier for a class alias,
that is, a lazy specification operator ‘ Examples: => String(characters) => Entry<String,Item>(name, item) => HomogenousCoordinates.Cartesian(x, y, z, 1.0) |
ClosedBound | shared ClosedBound A closed lower or upper bound of a bounded comparison operation. In a closed bound, the |
CompareOperation | shared CompareOperation A compare expression. No associativity. Examples: first <=> last n <=> 0 This is the concrete class for expressions like |
ComparisonOperation | shared abstract ComparisonOperation A comparison expression. No associativity. This is the abstract superclass of expressions like |
CompilationUnit | shared 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); |
ComplementAssignmentOperation | shared ComplementAssignmentOperation A complement assignment operation. Right-associative. Examples: people ~= kids elements ~= otherElements |
ComplementOperation | shared ComplementOperation A set complement expression. Defined via Examples: receivers~blocked primes ~ HashSet { 2 } |
Comprehension | shared Comprehension A comprehension, that is,
a chain of comprehension clauses,
beginning with an 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 |
ComprehensionClause | shared abstract ComprehensionClause A comprehension clause, one component of a Examples: for (person in people) if (person.age > 18) person.age if (isPrime(i)) i |
Condition | shared 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 |
ConditionalExpression | shared 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" |
Conditions | shared Conditions A comma-separated list of one or more Examples: (nonempty elems = that.elements, elems.first == expected) (is Integer num = obj.num, is Integer num2 = obj2.num, num == num2) |
Construction | shared Construction A construction, that is,
a member name with optional type arguments and (Note: the specification’s Examples: Point.cartesian(x, y, 0.0) withRGB(#FF, 0, 0) super.cartesian(x, y, 0.0) |
ConstructorDec | shared ConstructorDec A constructor reference expression, that is,
the Examples: `new Point.polar` `new Location.cartesian` |
ConstructorDefinition | shared 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; } |
Continue | shared Continue A |
ControlStructure | shared abstract ControlStructure A control structure statement, used to control normal execution flow. (An assertion failure is not considered as “normal” control flow;
therefore, an Examples: if (exists elem = queue.take) { process(elem); } for (i in 1:12) { print(month(i)); } |
Dec | shared abstract Dec A reference expression, that is, a detyped reference to a program element. Reference expressions may refer to:
Not to be confused with Reference expressions are often used in annotations, e. g. |
DecQualifier | shared DecQualifier A qualifier for a (The qualifier may also be completely empty.) Examples: process Entry package.Object |
Declaration | shared 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 Examples: shared actual String string => "``outer.string`` by ``step``"; shared class Person(shared String name) { string => name; } |
DefaultedCallableParameter | shared 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); |
DefaultedParameter | shared abstract DefaultedParameter A defaulted parameter. Examples: length = text.size Comparison comparing(Element x, Element y) => x.hash <=> y.hash |
DefaultedParameterReference | shared 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 |
DefaultedType | shared DefaultedType A defaulted type. Examples: String= Integer->String= |
DefaultedValueParameter | shared DefaultedValueParameter A value parameter, along with a default value for the parameter. Examples: Integer length = text.size Boolean discounted = false |
Destructure | shared Destructure A destructuring statement, that is,
a ‘ Examples: value name->[lat, lon] = observatories.first; value [x,y,z] = pos; |
DifferenceOperation | shared DifferenceOperation A difference expression. Defined via Examples: size - 1 lastIndex - firstIndex |
Directive | shared abstract Directive A control directive, terminated by a semicolon. There are four kinds of control directives:
Examples: return ret; throw AssertionError("Not implemented yet!"); // TODO implement break; continue; |
DivideAssignmentOperation | shared DivideAssignmentOperation A divide assignment operation ( Right-associative. Examples: width /= 2 amount /= exchangeRate |
DynamicBlock | shared DynamicBlock A 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 } |
DynamicInterfaceDefinition | shared 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()); } |
DynamicModifier | shared DynamicModifier A ‘ |
DynamicValue | shared DynamicValue A dynamic value expression, that is, the keyword ‘ Examples: dynamic [ error = 404; message = "not found"; ] dynamic [ ] |
ElementOrSubrangeExpression | shared ElementOrSubrangeExpression An element or subrange access expression, that is,
a target Examples: text[start...] map[key] |
ElseClause | shared ElseClause An Examples (multi-line): else { return "<null>"; } else if (exists div) { visit(div.paragraphs); } |
ElseOperation | shared ElseOperation An “else” operation. Left-associative. Examples: 0 <= val <= 10 then priority(val) else invalid parseInteger(input) else 0 |
EntryOperation | shared EntryOperation An entry expression. Defined via Examples: "1"->1 name->Person(name) |
EntryPattern | shared EntryPattern An entry pattern, that is,
a Examples: id->person name->[lat, lon] |
EntryType | shared EntryType An entry type, that is, a shortcut for Examples: String->Integer Printable&Persistent&Identifiable->Handle |
EqualOperation | shared EqualOperation An equals expression. Defined via Examples: length == 1 first == last parseInteger(input) == 0 |
EqualityOperation | shared abstract EqualityOperation An expression to test for identity or (in)equality of two objects. This is the abstract superclass of the nodes for |
ExistsCondition | shared ExistsCondition An existence condition, that is,
the keyword ‘ Examples: exists name exists firstItem = first?.item |
ExistsOperation | shared ExistsOperation A postfix existence test expression. No associativity. Examples: element exists parseInteger(text) exists |
ExistsOrNonemptyCondition | shared abstract ExistsOrNonemptyCondition An existence or nonemptiness condition, that is,
the keyword ‘ Examples: nonempty [employeeOfTheMonth, *others] = randomShuffle(employees) exists String name = person.name |
ExponentiationOperation | shared ExponentiationOperation An exponentiation expression. Defined via Examples: sideLength^dimension e^x |
Expression | shared 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 To ensure this, there is one type alias for each precedence level, specified as the union type of
For example, there is 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:
|
ExpressionComprehensionClause | shared ExpressionComprehensionClause An expression that terminates a comprehension. Examples: person.age i |
ExpressionStatement | shared 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 Examples: text.length += added.length; i++; print("Hello, World!"); |
ExtendedType | shared ExtendedType An ‘ Examples: extends Node() extends super.Entry<Key, Item>(key, item) extends HomogenousCoordinates.Cartesian(x, y, z, 1.0) |
Extension | shared Extension An extension, that is,
a type name with optional type arguments and optional (Note: the specification’s Examples: Object() package.Object super.Inner |
ExtensionOrConstruction | shared 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) |
FailClause | shared FailClause An ‘ Examples: else { print("Hello, World!"); } |
FinallyClause | shared FinallyClause A ‘ Examples: finally { print("END"); } finally { workers.collect(Worker.kill); } |
FloatLiteral | shared FloatLiteral A floating point literal is distinguished from an
integer literal ( |
ForClause | shared ForClause A ‘ (Not to be confused with a complete ‘ Examples: for (person in people) { print(person.name); } for (name->person in peopleByName) { print("``name``: ``person.age``"); } |
ForComprehensionClause | shared ForComprehensionClause A ‘ A ‘ Examples: for (person in people) "``person.firstName`` ``person.lastName``" for (people in peoples) for (person in people) if (person.age >= 18) person |
ForFail | shared ForFail A ‘ 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!"); } |
ForIterator | shared ForIterator An iterator for a ‘ Examples: (person in people) (name->person in peopleByName) ([x, y] in coordinates) |
FullPackageName | shared FullPackageName A full package name, that is, a period-separated list of lowercase identifiers. Examples: ceylon.language ceylon.ast.core |
FunctionArgument | shared FunctionArgument An inline function argument definition. Examples (multi-line): void onClick() { DialogBox { message = "Hello!"; parent = this; }.show(); } void onError(dynamic err) => console.error(err); |
FunctionDec | shared FunctionDec A function reference expression, that is,
the Examples: `function concatenate` `function Iterable.chain` |
FunctionDeclaration | shared FunctionDeclaration A function declaration. A function declaration declares the
In any case, the declaration must explicitly specify a type;
a ‘ |
FunctionDefinition | shared 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; } } |
FunctionExpression | shared 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...]]; } |
FunctionModifier | shared FunctionModifier A ‘ The ‘ |
FunctionShortcutDefinition | shared 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; |
GivenDec | shared GivenDec A type parameter reference expression, that is,
the name of a type parameter, prefixed by the type keyword Examples: `given Element` `given Key` |
GroupedExpression | shared GroupedExpression A grouped, or parenthesized expression. Examples: (1 + 2) * 3 "Hello, " + (process.arguments.first else "World") |
GroupedType | shared 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>[] |
IdenticalOperation | shared IdenticalOperation An identity test operation. Defined natively, on objects that satisfy Examples: node === rootNode this === zero |
Identifier | shared abstract Identifier |
IdentityOperation | shared IdentityOperation The expression This expression is defined to return (Not to be confused with |
IfClause | shared IfClause An Examples: if (15 <= estimatedAge <= 25) { askForID(); } if (exists elseClause = that.elseClause) { elseClause.visit(this); } |
IfComprehensionClause | shared IfComprehensionClause An ‘ An ‘ Examples: if (person.age >= 18) person if (exists typeArguments = that.typeArguments) for (typeArgument in typeArguments) typeArgument.type |
IfElse | shared IfElse An if/else conditional. The conditional begins with an 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; } |
IfElseExpression | shared IfElseExpression An if/then/else conditional expression, that is,
the keyword ‘ The 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 |
Import | shared Import An import statement, that is,
the keyword ‘ Examples: import ceylon.ast.core { ... } import java.lang { JString=String, System { sysout=\iout } } import ceylon.collection { ArrayList, MutableList } |
ImportAlias | shared abstract ImportAlias An import alias, that is, an identifier followed by an “equals” character. (Not to be confused with an alias declaration ( Examples: JString= sysout= |
ImportElement | shared abstract ImportElement A single import element, that is,
the name of an imported program element, Examples: HashMap ln=log System { sysout=out } |
ImportElements | shared ImportElements A comma-separated list of import elements, where the last element may optionally be a wildcard instead, surrounded by braces. Import elements may not be empty. ( Examples: MutableList, ArrayList JString=String, System { sysout=out } |
ImportFunctionValueAlias | shared ImportFunctionValueAlias A function or value import alias, that is, a lowercase identifier followed by an “equals” character. Examples: sysout= ln= |
ImportFunctionValueElement | shared ImportFunctionValueElement A single function or value import element, that is,
the name of an imported function or value,
optionally preceded by a type alias,
and (for Examples: ln=log sysout=out |
ImportTypeAlias | shared ImportTypeAlias A type import alias, that is, an uppercase identifier followed by an “equals” character. Examples: JString= Char= |
ImportTypeElement | shared ImportTypeElement A single type import element, that is, the name of an imported type, optionally preceded by a type alias and/or followed by nested import elements to import and rename members. Examples: HashMap System { sysout=out } |
ImportWildcard | shared ImportWildcard An import wildcard, that is, three colons (‘ Used to indicate that all elements from a package should be imported. |
InModifier | shared InModifier An ‘ |
InOperation | shared InOperation A containment test expression. Defined via 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,
rhs.contains(lhs) while e. g. lhs.times(rhs) (the qualifier and argument swapped places). |
InitialComprehensionClause | shared abstract InitialComprehensionClause A comprehension clause that can start a comprehension. Examples: for (person in people) “ if (exists typeArguments = that.typeArguments) for (typeArgument in typeArguments) typeArgument.type |
InlineDefinitionArgument | shared 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); } |
IntegerLiteral | shared 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. |
InterfaceAliasDefinition | shared 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); |
InterfaceBody | shared InterfaceBody A list of declarations, surrounded by braces. Unlike class bodies, interface bodies can’t immediately contain runnable code,
so the 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; } |
InterfaceDec | shared InterfaceDec An interface reference expression, that is,
the The Examples: `interface Iterable` `interface A.B.C` `interface` |
InterfaceDefinition | shared 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); } |
IntersectAssignmentOperation | shared IntersectAssignmentOperation An intersect assignment operation. Right-associative. Examples: people &= authorizedUsers commonElements &= elements |
IntersectionOperation | shared IntersectionOperation A set intersection expression. Defined via Examples: persistents&printables&identifiables x1&y1 |
IntersectionType | shared IntersectionType An intersection type. Examples: Element&Identifiable Persistent&Printable&Identifiable |
Invocation | shared Invocation An invocation, that is, an invoked expression with an argument list. Examples: print("Hello, World!") process.kill() ArrayList { initialCapacity = 100; 1, 1 } |
InvocationStatement | shared 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); |
IsCase | shared IsCase A ‘ Examples: is String is Persistent&Serializable is Integer|Float |
IsCondition | shared IsCondition An assignability condition, that is,
the keyword ‘ Examples: is Integer|Float num is Administrator user |
IsOperation | shared IsOperation A postfix assignability test expression. No associativity. Examples: element is String|Integer user is ExecutiveUser |
Iterable | shared Iterable An iterable object instantiation expression. Examples: {} { second, first, *rest.rest } |
IterableType | shared IterableType An iterable type, like |
Key | shared Key<Type> A key by which a |
KeySubscript | shared KeySubscript A key / index subscript expression,
to select an element from a Examples: key offset + i |
LIdentifier | shared LIdentifier An initial lowercase identifier. |
LargeAsOperation | shared LargeAsOperation A “large as” expression. No associativity. |
LargerOperation | shared LargerOperation A “larger than” expression. No associativity. |
LazySpecification | shared 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); |
LazySpecifier | shared LazySpecifier A lazy expression specifier, that is, an expression prefixed by a computation operator ‘ Examples: => text.uppercased => nothing |
LetExpression | shared LetExpression A The expression is parsed with a precedence
just below the 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) |
Literal | shared abstract Literal A literal is a single token that represents a Unicode character, a character string, or a numeric value. |
LocalModifier | shared abstract LocalModifier A modifier that indicates type inference. It can only be used on local definitions (not toplevel, not shared), hence the name. |
LogicalAssignmentOperation | shared abstract LogicalAssignmentOperation A logical assignment expression. Right-associative. |
LogicalOperation | shared abstract LogicalOperation A logical binary operation expression. |
MainType | shared abstract MainType “Main” types: the types that you normally use. This class is used as “Type, except EntryType” in |
MatchCase | shared MatchCase A ‘ Examples: null 0 | 1 null | smaller | larger |
MeasureOperation | shared MeasureOperation A measured range expression. Defined via Examples: 0:size today:14 |
MeasureSubscript | shared MeasureSubscript A measure subscript,
to select a (sub)range from a Examples: 0:30 match.start:match.size |
MemberDec | shared abstract MemberDec A member reference expression. Examples: `value null` `function Iterable.map` |
MemberMeta | shared 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 Examples: `Person.say` `system.milliseconds` `Iterable<String>.collect<Integer?>` |
MemberNameWithTypeArguments | shared MemberNameWithTypeArguments A member name and, optionally, type arguments. |
MemberOperator | shared MemberOperator A regular member operator, ‘ |
Meta | shared 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 (There is no |
Modifier | shared abstract Modifier A modifier keyword. Note: The Ceylon Language Specification also refers to certain annotations,
e. g.
|
ModuleBody | shared 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 Examples: {} { shared import ceylon.test "1.2.0"; } { import ceylon.collection "1.2.0"; } |
ModuleCompilationUnit | shared 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"; } |
ModuleDec | shared 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` |
ModuleDescriptor | shared ModuleDescriptor A module descriptor:
a list of annotations, followed by the keyword ‘ 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"; } |
ModuleImport | shared ModuleImport An import of another module within a module descriptor. Each module import consists of a list of Examples: shared import ceylon.test "1.2.0"; import ceylon.collection "1.2.0"; |
MultiplyAssignmentOperation | shared MultiplyAssignmentOperation A multiply assignment operation ( Right-associative. Examples: balance *= 1 + interestRate |
NameWithTypeArguments | shared abstract NameWithTypeArguments A name and, optionally, type arguments. |
NamedArgument | shared abstract NamedArgument A named argument. Examples: name; size = width * height; Color color(Integer x, Integer y) => red; |
NamedArguments | shared 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) } } |
NegationOperation | shared NegationOperation An arithmetic unary negation operation, that is, This operator is defined in terms of |
Node | shared abstract Node Abstract superclass of all AST nodes. Note that nodes are not Additional informationYou can attach additional information to individual AST nodes using typed keys.
Two sets of methods are available for this;
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[] |
NonemptyCondition | shared NonemptyCondition A nonemptiness condition, that is,
the keyword ‘ Examples: nonempty employees nonempty persons = people.sequence() |
NonemptyOperation | shared NonemptyOperation A nonempty postfix expression. No associativity. |
NotEqualOperation | shared NotEqualOperation A not equals expression. Defined via Examples: uid != 0 process.arguments.length != 7 |
NotOperation | shared NotOperation A logical not expression. Right-associative. Examples: !n in primes !predicate(element) |
ObjectArgument | shared 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(); } |
ObjectDefinition | shared 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"); } } |
ObjectExpression | shared ObjectExpression An object expression, that is,
the keyword ‘ Examples: object satisfies Iterator<Anything> { next() => finished; } |
OfOperation | shared 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? |
OpenBound | shared OpenBound An open lower or upper bound of a bounded comparison operation. In an open bound, the For example, in the interval |
Operation | shared 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 This class is called The specification also lists expressions like |
OptionalType | shared OptionalType An optional type, that is, a shortcut for Examples: String? <String->Integer>? |
OrAssignmentOperation | shared OrAssignmentOperation A logical disjunction assignment expression. Right-associative. Examples: permitted ||= backdoorTriggered canPrint ||= networkPrinterPresent |
OrOperation | shared OrOperation A logical disjunction expression. Left-associative. Examples: digit == 0 || digit == 1 element in errors || !element exists |
OutModifier | shared OutModifier An ’ |
Outer | shared 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. |
Package | shared Package
|
PackageCompilationUnit | shared PackageCompilationUnit A package descriptor compilation unit, containing a package descriptor. Examples: package tmp; shared package ceylon.ast.core; |
PackageDec | shared 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` |
PackageDescriptor | shared PackageDescriptor A package descriptor:
a list of annotations, followed by the keyword ‘ Examples: package tmp; "Test package" see (`package my.application`) package test.my.application; |
PackageQualifier | shared PackageQualifier A package qualifier, that is,
the keyword ‘ (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 |
Parameter | shared abstract Parameter A class, method, or function parameter. Examples: String name comparing Integer length = text.size Element+ elements |
ParameterReference | shared ParameterReference The name of a parameter, without type information. There are two possible interpretations of such a parameter:
Examples: comparing name |
Parameters | shared Parameters A parameter list. Examples: () (String text, Integer length = text.size) (Element+ elements) A note about this class’ parametersIt would seem reasonable to instead declare the parameters of this class like this: class Parameters(RequiredParameter[] required, DefaultedParameter[] defaulted, VariadicParameter|ParameterReference variadic) Note that (param) In this parameter list, is
To decide this, you need to look into the body of the function,
and check if the declaration of 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. |
Pattern | shared abstract Pattern A pattern declares one or multiple variables. The simplest and most common form is the Examples: e String line k->v [first, *rest] name->[lat, lon] |
PatternList | shared PatternList A comma-separated list of specified patterns, enclosed in parentheses. Used in Examples: (c = other.a, d = other.b) ([x,y] = loc, dist = sqrt(x^2 + y^2)) |
PositionalArguments | shared 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 Examples: (x, y, *messages) () (for (i in 1..10) i^2) |
PostfixDecrementOperation | shared PostfixDecrementOperation A postfix decrement expression ( |
PostfixIncrementOperation | shared PostfixIncrementOperation A postfix increment expression ( |
PostfixOperation | shared abstract PostfixOperation A postfix arithmetic expression, that is, |
PrefixDecrementOperation | shared PrefixDecrementOperation A prefix decrement expression ( |
PrefixIncrementOperation | shared PrefixIncrementOperation A prefix increment expression ( |
PrefixOperation | shared abstract PrefixOperation A prefix arithmetic expression, that is, |
PrefixPostfixStatement | shared PrefixPostfixStatement A prefix or postfix increment or decrement expression statement. Examples: i++; --size; |
Primary | shared abstract Primary A primary expression. Primaries can be combined using operations. |
PrimaryType | shared abstract PrimaryType A primary type; only intersection, union and entry types come before these. |
ProductOperation | shared ProductOperation A product expression. Defined via |
QualifiedExpression | shared QualifiedExpression A receiver expression,
followed by a member operator (usually ‘ Examples: ", ".join process.arguments.first people*.name sort(people, byAscending(Person.salary)).first?.salary |
QualifiedType | shared 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 |
QuotientOperation | shared QuotientOperation A quotient or division expression. Defined via |
RangeSubscript | shared abstract RangeSubscript A range subscript,
to select a (sub)range from a Examples: 1 .. text.size - 2 1... |
RemainderAssignmentOperation | shared RemainderAssignmentOperation A remainder assignment operation ( Right-associative. Examples: increment %= step |
RemainderOperation | shared RemainderOperation A remainder expression. Defined via |
RequiredParameter | shared abstract RequiredParameter A required parameter (neither defaulted nor variadic). Examples: String name comparing |
Resource | shared Resource A resource in a try-with-resources statement. Examples: lock writer = file.Writer() |
Resources | shared Resources A comma-separated list of Examples: (lock) (reader = inFile.Reader(), writer = outFile.Writer()) |
Return | shared Return A |
SafeMemberOperator | shared 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. |
SatisfiedTypes | shared SatisfiedTypes A nonempty list of satisfied types, separated by the intersection operator (‘ Examples: satisfies {Element+} satisfies Printable & Persistent |
ScaleOperation | shared ScaleOperation A scale expression. Defined via 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,
rhs.scale(lhs) while e. g. lhs.times(rhs) (the qualifier and argument swapped places). |
ScopedKey | shared ScopedKey<Type> A Usage example: shared Key<Token[]> tokensKey = ScopedKey<Token[]>(`class CeylonParser`, "tokens"); |
SelfReference | shared abstract SelfReference
|
SequentialType | shared SequentialType A sequential type, that is, a primary type, followed by an opening bracket,
optionally an integer If the length is absent, this is a shortcut for Examples: String[] <String->Integer>[] Boolean[2] // shortcut for [Boolean,Boolean] |
SetAssignmentOperation | shared abstract SetAssignmentOperation A set assignment operation. Right-associative. |
SetOperation | shared abstract SetOperation A set operation: intersection, union or complement. |
SimpleType | shared 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 |
SmallAsOperation | shared SmallAsOperation A “small as” expression. No associativity. |
SmallerOperation | shared SmallerOperation A “smaller than” expression. No associativity. |
SpanFromSubscript | shared SpanFromSubscript A span-from subscript,
to select a (sub)range from a Examples: 1... match.start ... |
SpanOperation | shared SpanOperation A spanned range expression. Defined via Examples: 0..9 monday..friday first.successor..last.predecessor |
SpanSubscript | shared SpanSubscript |
SpanToSubscript | shared SpanToSubscript A span-to subscript,
to select a (sub)range from a Examples: ... text.size - 1 ...count |
Specification | shared abstract Specification A specification statement. Examples: offset = preamble.size + title.size; debug(Anything a) => process.writeErrorLine(a); |
SpecifiedArgument | shared SpecifiedArgument A specified named argument, that is, a Examples: groupSeparators = false; initialCapacity = 256; |
SpecifiedPattern | shared SpecifiedPattern A Examples: [head, *tail] = elements.sequence() name = people.filter((p) => p.age < 18).first?.name?.uppercased |
SpecifiedVariable | shared SpecifiedVariable A specified inline variable declaration. Examples: num = parseFloat(numString) String name = person.name |
Specifier | shared Specifier An expression specifier, that is, an expression prefixed by a specification operator ‘ Examples: = 1 = nothing |
SpreadArgument | shared SpreadArgument A spread argument. Used in argument lists to “spread” a sequential value over multiple arguments. (The spread “operator” Examples: *args *values.collect(Object.string) *[] |
SpreadMemberOperator | shared 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. |
SpreadType | shared SpreadType |
Statement | shared abstract Statement A statement. Examples: value name = person.name else "<unnamed>"; print("Hello, World!"); |
StringLiteral | shared StringLiteral A string literal consists of a series of characters and/or, if it’s not verbatim, escape sequences. |
StringTemplate | shared 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 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``." |
Subscript | shared abstract Subscript A subscript used to access an element or subrange
in a In mathematical notations, these accessors are usually written as subscript, e. g. xi for the ith x element. Examples: index ... text.size - 2 |
SubtractAssignmentOperation | shared SubtractAssignmentOperation A subtract assignment operation ( Right-associative. Examples: countdown -= \iΔt |
SumOperation | shared SumOperation A sum expression. Defined via Examples: i + 1 firstIndex + size |
Super | shared 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. |
SwitchCaseElse | shared SwitchCaseElse A 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); } |
SwitchCaseElseExpression | shared SwitchCaseElseExpression A 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 |
SwitchCases | shared SwitchCases A list of ‘ 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); } |
SwitchClause | shared SwitchClause A ‘ Examples: switch (i.magnitude) switch (child) switch (arg = process.arguments.first) |
ThenOperation | shared ThenOperation A “then” operation. Left-associative. Examples: !name.empty then name age != -1 then age |
This | shared This The value of this expression is the current instance, and its type is the immediately containing type. |
Throw | shared Throw A |
TryCatchFinally | shared TryCatchFinally A try-cA try/catch/finally statement, that is,
a ‘ 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; } |
TryClause | shared TryClause A ‘ Examples (multi-line): try { value zombie = spawn { Zombie; center = player.location; spread = 50; }; zombie.aggro = player; } try (writer = file.Writer()) { that.serialize(writer); } |
Tuple | shared Tuple A tuple instantiation expression. Examples: [] [x, y] [father, mother, *children] |
TuplePattern | shared 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] |
TupleType | shared TupleType A tuple type. Examples: [String,Integer,Integer] [Float,Integer*] [] |
Type | shared abstract Type Representation of a type. |
TypeAliasDefinition | shared 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>; |
TypeArgument | shared TypeArgument A type argument, that is, a (Use-site variance is only rarely used; most of the time, Examples: String out T |
TypeArguments | shared TypeArguments A comma-separated list of type arguments, enclosed in angle brackets. Examples: <String,Nothing> <out Element> <> |
TypeConstraint | shared 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 |
TypeDec | shared abstract TypeDec A type reference expression. |
TypeDeclaration | shared abstract TypeDeclaration A type declaration. Examples (multi-line): shared interface Printable { shared default void print() { package.print(this); } } shared alias TypeName => UIdentifier; |
TypeIsh | shared abstract TypeIsh All node types in the type sub-hierarchy:
(For example, while |
TypeList | shared TypeList A list of types, with an optional trailing variadic type. Examples: String, String, String+ |
TypeMeta | shared TypeMeta A type metamodel expression, that is, a Examples: `List<String>` `Integer|Float` |
TypeModifier | shared abstract TypeModifier A modifier that can be used instead of a type in some places. This includes:
|
TypeNameWithTypeArguments | shared TypeNameWithTypeArguments A type name and, optionally, type arguments. |
TypeParameter | shared TypeParameter A type parameter of a class, method or function. The type parameter may optionally declare a type Examples: out Element out Absent=Null |
TypeParameters | shared TypeParameters A nonempty comma-separated list of type parameters, surrounded by angle brackets. Examples: <in Key, out Item> <out Element> |
TypeSpecifier | shared TypeSpecifier A type specifier, that is, a type prefixed by a computation operator ‘ Examples: => Map<String,Person> => Comparison(Value,Value) |
TypedDeclaration | shared abstract TypedDeclaration A declaration with a type. The type can either be explicitly specified ( Examples: shared String name; shared actual void visit(Node that) { print(that); that.visitChildren(this); } |
TypedVariable | shared TypedVariable A typed inline variable declaration. Examples: Integer|Float num String name |
UIdentifier | shared UIdentifier An initial uppercase identifier. |
UnaryArithmeticOperation | shared abstract UnaryArithmeticOperation A unary arithmetic expression, that is, |
UnaryIshOperation | shared abstract UnaryIshOperation An expression consisting of a These can be regular unary operations – either prefix or postfix – or unary type operations, which are always postfix, and include a type. |
UnaryOperation | shared abstract UnaryOperation A unary operator expression. |
UnaryTypeOperation | shared abstract UnaryTypeOperation A unary type operation. A subclass of |
UnionAssignmentOperation | shared UnionAssignmentOperation A union assignment operation. Right-associative. Examples: students |= course.students allElements |= elements |
UnionOperation | shared UnionOperation A set union expression. Defined via Examples: ints|floats x1&y1|x2&y2 |
UnionType | shared UnionType A union type. Examples: String|Integer|Float |
UnionableType | shared abstract UnionableType Types that can be children of a This class is only there to represent how types are parsed, not their semantics. |
UnspecifiedVariable | shared 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 |
ValueArgument | shared 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); |
ValueConstructorDefinition | shared 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; } |
ValueDec | shared ValueDec A value reference expression, that is,
the Examples: `value null` `value Iterable.first` |
ValueDeclaration | shared ValueDeclaration A value declaration. A value declaration declares the
In any case, the declaration must explicitly specify a type;
a |
ValueDefinition | shared ValueDefinition A value definition, using a specifier. Examples: shared actual String string => "``name`` from ``countryOfOrigin`` of age ``age``"; shared actual Null definition = null; |
ValueExpression | shared abstract ValueExpression An expression that returns an ordinary value. Value expressions return instances of classes, while function expressions return first-class functions. |
ValueGetterDefinition | shared ValueGetterDefinition A value definition, using a getter block. Examples: shared actual String string { value s = element.string; return ", ".join(Singleton(element).cycled.take(size)); } |
ValueModifier | shared ValueModifier A ‘ The ‘ |
ValueParameter | shared ValueParameter A value parameter. Examples: String name Integer length Boolean(Element) selecting shared Address privateAddress |
ValueSetterDefinition | shared ValueSetterDefinition A setter definition, that is,
the keyword ‘ Examples: assign diameter => radius = diameter / 2; assign diameter { throw AssertionError("Can’t set the diameter of the unit circle"); } |
ValueSpecification | shared ValueSpecification A value specification statement, that is, a member name followed by a Examples: size = 0; it = iterators.next(); |
Variable | shared abstract Variable An inline variable declaration. Assertions and some control structures allow inline declarations of variables. Examples: firstEmployee = employees.first Integer|Float num |
VariablePattern | shared VariablePattern A simple variable pattern. Examples: e String line |
VariadicParameter | shared VariadicParameter A variadic parameter. Examples: Element+ elements String* messages "The indexes" Integer+ indexes |
VariadicType | shared VariadicType A variadic type is a |
VariadicVariable | shared VariadicVariable |
Variance | shared abstract Variance A modifier that indicates type parameter / argument variance. Examples: in out |
VoidModifier | shared VoidModifier A ‘ |
While | shared While A Examples: while (i++ <= count) { lines.add(process.readLine()); } while (!((elem = it.next()) is Finished)) { expressions.add(elem); literals.add(it.next()); } |
WithinOperation | shared WithinOperation A bounded comparison operation, also known as “within” operation. Examples: 0 <= x < 10 1 <= x <= 31 |