Skip to content

Commit

Permalink
Support length-based abbreviation for tuple types
Browse files Browse the repository at this point in the history
A SequencedType can now optionally have an IntegerLiteral type to form a
tuple of the given length.

The syntax Boolean[8] has been around for a while (even before the
Ceylon 1.1 release), but was only recently declared an officially
supported feature of the language, part of the specification. See
ceylon/ceylon-spec#1041.
  • Loading branch information
lucaswerkmeister committed Jun 1, 2015
1 parent a09aca6 commit c4329c1
Show file tree
Hide file tree
Showing 9 changed files with 47 additions and 14 deletions.
5 changes: 4 additions & 1 deletion source/ceylon/ast/core/CeylonExpressionTransformer.ceylon
Original file line number Diff line number Diff line change
Expand Up @@ -754,7 +754,10 @@ shared class CeylonExpressionTransformer(String indentLevel = " ") satisfies
`` indent + indentLevel ``factor = ``transformWithIndent(that.factor)``;
`` indent + indentLevel ``scalable = ``transformWithIndent(that.scalable)``;
``indent``}";
transformSequentialType(SequentialType that) => "SequentialType(``transformWithIndent(that.elementType)``)";
transformSequentialType(SequentialType that)
=> that.length exists
then "SequentialType(``transformWithIndent(that.elementType)``, ``transformWithIndent(that.length)``)"
else "SequentialType(``transformWithIndent(that.elementType)``)";
transformSmallAsOperation(SmallAsOperation that)
=> "SmallAsOperation {
`` indent + indentLevel ``leftOperand = ``transformWithIndent(that.leftOperand)``;
Expand Down
2 changes: 1 addition & 1 deletion source/ceylon/ast/core/Editor.ceylon
Original file line number Diff line number Diff line change
Expand Up @@ -733,7 +733,7 @@ shared interface Editor satisfies ImmediateNarrowingTransformer<Node> {
return ret;
}
shared actual default SequentialType transformSequentialType(SequentialType that)
=> that.copy(transformPrimaryType(that.elementType));
=> that.copy(transformPrimaryType(that.elementType), nullsafeInvoke(that.length, transformIntegerLiteral));
shared actual default SetAssignmentOperation transformSetAssignmentOperation(SetAssignmentOperation that) {
assert (is SetAssignmentOperation ret = super.transformSetAssignmentOperation(that));
return ret;
Expand Down
35 changes: 29 additions & 6 deletions source/ceylon/ast/core/SequentialType.ceylon
Original file line number Diff line number Diff line change
@@ -1,22 +1,45 @@
"A sequential type, that is, a shortcut for `TypeNameWithTypeArguments(UIdentifier(\"Sequential\"), [elementType])`.
"A sequential type, that is, a [[primary type|elementType]], followed by an opening bracket,
optionally an integer [[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>[]"
shared class SequentialType(elementType)
<String->Integer>[]
Boolean[2] // shortcut for [Boolean,Boolean]"
shared class SequentialType(elementType, length = null)
extends PrimaryType() {

"The element type."
shared PrimaryType elementType;

shared actual [PrimaryType] children = [elementType];
shared IntegerLiteral? length;

shared actual [PrimaryType, IntegerLiteral=] children;
if (exists length) {
children = [elementType, length];
} else {
children = [elementType];
}

shared actual Result transform<out Result>(Transformer<Result> transformer)
=> transformer.transformSequentialType(this);

shared actual Boolean equals(Object that) {
if (is SequentialType that) {
if (exists length) {
if (exists length_ = that.length) {
if (length != length_) {
return false;
}
} else {
return false;
}
} else if (that.length exists) {
return false;
}
return elementType == that.elementType;
} else {
return false;
Expand All @@ -26,8 +49,8 @@ shared class SequentialType(elementType)
shared actual Integer hash
=> 31 * elementType.hash;

shared SequentialType copy(PrimaryType elementType = this.elementType) {
value ret = SequentialType(elementType);
shared SequentialType copy(PrimaryType elementType = this.elementType, IntegerLiteral? length = this.length) {
value ret = SequentialType(elementType, length);
copyExtraInfoTo(ret);
return ret;
}
Expand Down
4 changes: 2 additions & 2 deletions source/ceylon/ast/core/Type.ceylon
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@
shared abstract class TypeIsh()
of Type | NameWithTypeArguments | VariadicType | DefaultedType | TypeList | SpreadType | TypeArgument | TypeArguments | PackageQualifier
extends Node() {
shared actual formal <TypeIsh|Identifier|Variance>[] children;
shared actual formal <TypeIsh|Identifier|Variance|IntegerLiteral>[] children;
}

"Representation of a type."
shared abstract class Type()
of MainType | EntryType
extends TypeIsh() {

shared actual formal TypeIsh[] children;
shared actual formal <TypeIsh|IntegerLiteral>[] children;

"Tests for equality of two type nodes.
Expand Down
3 changes: 3 additions & 0 deletions source/ceylon/ast/redhat/RedHatTransformer.ceylon
Original file line number Diff line number Diff line change
Expand Up @@ -2776,6 +2776,9 @@ shared class RedHatTransformer(TokenFactory tokens) satisfies ImmediateNarrowing
JSequenceType ret = JSequenceType(null);
ret.elementType = transformPrimaryType(that.elementType);
ret.endToken = tokens.token("[", lbracket); // unreachable, but we need to have it in the token stream
if (exists length = that.length) {
ret.length = transformIntegerLiteral(length);
}
ret.endToken = tokens.token("]", rbracket);
return ret;
}
Expand Down
2 changes: 1 addition & 1 deletion source/ceylon/ast/redhat/SequentialType.ceylon
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import com.redhat.ceylon.compiler.typechecker.tree {
"Converts a RedHat AST [[SequenceType|JSequenceType]] to a `ceylon.ast` [[SequentialType]]."
shared SequentialType sequentialTypeToCeylon(JSequenceType sequentialType) {
assert (is PrimaryType element = typeToCeylon(sequentialType.elementType));
return SequentialType(element);
return SequentialType(element, if (exists jLength = sequentialType.length) then integerLiteralToCeylon(jLength) else null);
}

"Compiles the given [[code]] for a Sequential Type
Expand Down
1 change: 1 addition & 0 deletions source/test/ceylon/ast/redhat/BaseType.ceylon
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ shared object baseType satisfies ConcreteTest<BaseType,JBaseType> {
shared String->BaseType retType = construct("Ret");
shared String->BaseType argsType = construct("Args");
shared String->BaseType systemObjectType = constructO("system");
shared String->BaseType booleanType = construct("Boolean");

compile = compileBaseType;
fromCeylon = RedHatTransformer.transformBaseType;
Expand Down
1 change: 1 addition & 0 deletions source/test/ceylon/ast/redhat/IntegerLiteral.ceylon
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ shared object integerLiteral satisfies ConcreteTest<IntegerLiteral,JNaturalLiter
shared String->IntegerLiteral oneIntegerLiteral = construct("1");
shared String->IntegerLiteral _0IntegerLiteral = construct("0");
shared String->IntegerLiteral _2IntegerLiteral = construct("2");
shared String->IntegerLiteral _8IntegerLiteral = construct("8");

compile = compileIntegerLiteral;
fromCeylon = RedHatTransformer.transformIntegerLiteral;
Expand Down
8 changes: 5 additions & 3 deletions source/test/ceylon/ast/redhat/SequentialType.ceylon
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import ceylon.ast.core {
IntegerLiteral,
PrimaryType,
SequentialType
}
Expand All @@ -15,14 +16,15 @@ import com.redhat.ceylon.compiler.typechecker.tree {

shared object sequentialType satisfies ConcreteTest<SequentialType,JSequenceType> {

String->SequentialType construct(String->PrimaryType elem)
=> "``elem.key``[]"->SequentialType(elem.item);
String->SequentialType construct(String->PrimaryType elem, <String->IntegerLiteral>? length = null)
=> "``elem.key``[`` length?.key else "" ``]"->SequentialType(elem.item, length?.item);

shared String->SequentialType stringSequentialType = construct(baseType.stringType);
shared String->SequentialType iterableOfStringSequentialType = construct(baseType.iterableOfStringType);
shared String->SequentialType byteSequentialType = construct(baseType.booleanType, integerLiteral._8IntegerLiteral);

compile = compileSequentialType;
fromCeylon = RedHatTransformer.transformSequentialType;
toCeylon = sequentialTypeToCeylon;
codes = [stringSequentialType, iterableOfStringSequentialType];
codes = [stringSequentialType, iterableOfStringSequentialType, byteSequentialType];
}

0 comments on commit c4329c1

Please sign in to comment.