Next: Typed identifiers
Up: Types and type identifiers
Previous: Class and interface types
Array types
Array types cannot be declared or named; every use of an array type is
represented by its denotation.
Two array type denotations are equivalent if they have the same element
type and the same number of dimensions.
This is a restricted form of structural equivalence, which requires that
the StructEquiv module be instantiated:
Instantiate required modules[26]
:
$/Type/StructEquiv.fw
This macro is defined in definitions 15, 26, 38, and 44.
This macro is invoked in definition 1.
StructEquiv defines a partition on the set of types such that types
that could be equivalent on the basis of their construction rule lie in
the same block of the partition.
After all type denotations have been examined, StructEquiv refines the
partition on the basis of the component types of each type.
The blocks of the refined partitions are the type equivalence classes.
We therefore use AddTypeToBlock to assign each array denotation to the
ArrayTypes block with the element type as a singleton component type
list:
Property definitions[27]
:
ArrayTypes;
This macro is defined in definitions 18, 24, 27, and 29.
This macro is invoked in definition 3.
TREE SYMBOL ArrayType: ElementType: DefTableKey;
TREE SYMBOL ArrayType INHERITS TypeDenotation COMPUTE
SYNT.GotType=
AddTypeToBlock(
THIS.Type,
ArrayTypes,
SingleDefTableKeyList(THIS.ElementType));
END;
RULE: ArrayType ::= PrimitiveType '[' ']' COMPUTE
ArrayType.ElementType=PrimitiveType.Type;
END;
RULE: ArrayType ::= Name $pTypeName '[' ']' COMPUTE
ArrayType.ElementType=pTypeName.Type;
END;
RULE: ArrayType ::= ArrayType '[' ']' COMPUTE
ArrayType[1].ElementType=ArrayType[2].Type;
END;
This macro is defined in definitions 28, 30, 31, 32, and 33.
This macro is invoked in definition 14.
Each array type has an associated set of operators that must be
added to the operator database.
Those operators should only be instantiated once for each unique array
type.
The Ops property of the final array type is set to indicate that the
operators for that array type have been entered into the database.
Property definitions[29]
:
Ops: int [Has, KReset];
This macro is defined in definitions 18, 24, 27, and 29.
This macro is invoked in definition 3.
TREE SYMBOL ArrayType INHERITS OperatorDefs COMPUTE
SYNT.GotOper=
IF(NOT(HasOps(THIS.Type)),
InstClass1(
arrayOps,
KResetOps(FinalType(THIS.Type),1),
THIS.ElementType));
END;
This macro is defined in definitions 28, 30, 31, 32, and 33.
This macro is invoked in definition 14.
Every array access is also an array type denotation, but with some
subscripts specified.
The processing of these denotations is basically the same as the processing
specified above.
The only difference is that there is no direct access to the element type.
We therefore use a chain, started in the context of the array access,
to carry the element type from one dimension to the next:
CHAIN ArrTyp: DefTableKey;
SYMBOL Dimension INHERITS TypeDenotation, OperatorDefs COMPUTE
SYNT.GotType=
AddTypeToBlock(THIS.Type,ArrayTypes,SingleDefTableKeyList(THIS.ArrTyp));
SYNT.GotOper=
IF(NOT(HasOps(THIS.Type)),
InstClass1(
arrayOps,
KResetOps(FinalType(THIS.Type),1),
THIS.ArrTyp));
THIS.ArrTyp=THIS.Type;
END;
This macro is defined in definitions 28, 30, 31, 32, and 33.
This macro is invoked in definition 14.
As discussed in Section 5.3, Java allows identifiers to be declared
with trailing dimensions.
This requires operations like those above, associated with the particular
context in which the trailing dimensions occur.
If there is no trailing dimension, do nothing:
TREE SYMBOL VariableDeclaratorId INHERITS TypeDenotation, OperatorDefs
COMPUTE
SYNT.GotType="yes";
SYNT.GotOper="yes";
END;
RULE: VariableDeclaratorId ::= VariableDeclaratorId '[' ']' COMPUTE
VariableDeclaratorId[1].GotType=
AddTypeToBlock(
VariableDeclaratorId[1].Type,
ArrayTypes,
SingleDefTableKeyList(
INCLUDING (VariableDeclaratorId.Type,TypedDefinition.Type)));
VariableDeclaratorId[1].GotOper=
IF(NOT(HasOps(VariableDeclaratorId[1].Type)),
InstClass1(
arrayOps,
KResetOps(FinalType(VariableDeclaratorId[1].Type),1),
INCLUDING (VariableDeclaratorId.Type,TypedDefinition.Type)));
END;
This macro is defined in definitions 28, 30, 31, 32, and 33.
This macro is invoked in definition 14.
For compatibility with older versions of the Java platform, a declaration
form for a method that returns an array is allowed to place (some or all of)
the empty bracket pairs that form the declaration of the array type after
the parameter list.
By now, the operations should be familiar:
TREE SYMBOL MethodDeclarator INHERITS TypeDenotation, OperatorDefs
COMPUTE
SYNT.GotType="yes";
SYNT.GotOper="yes";
END;
RULE: MethodDeclarator ::= MethodDeclarator '[' ']' COMPUTE
MethodDeclarator[1].GotType=
AddTypeToBlock(
MethodDeclarator[1].Type,
ArrayTypes,
SingleDefTableKeyList(
INCLUDING (MethodDeclarator.Type,MethodHeader.Type)));
MethodDeclarator[1].GotOper=
IF(NOT(HasOps(MethodDeclarator[1].Type)),
InstClass1(
arrayOps,
KResetOps(FinalType(MethodDeclarator[1].Type),1),
INCLUDING (MethodDeclarator.Type,MethodHeader.Type)));
END;
This macro is defined in definitions 28, 30, 31, 32, and 33.
This macro is invoked in definition 14.
See Section 5.4.2 for the context of this computation.
Next: Typed identifiers
Up: Types and type identifiers
Previous: Class and interface types
2008-09-11