Skip to content

Commit 8657620

Browse files
committed
Move the concrete syntax of types to the beginning.
To align with the rest of the spec, which is syntax-first.
1 parent 6f21d93 commit 8657620

File tree

1 file changed

+146
-137
lines changed

1 file changed

+146
-137
lines changed

docs/_spec/03-types.md

Lines changed: 146 additions & 137 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,70 @@ chapter: 3
66

77
# Types
88

9-
In this specification, we specify and use types in terms of the following _abstract syntax_.
10-
The abstract syntax does not directly correspond to concrete syntax.
11-
It abstracts away irrelevant details such as precedence and grouping, and contains shapes of types that cannot be directly expressed using the concrete syntax.
9+
```ebnf
10+
Type ::= FunType
11+
| TypeLambda
12+
| InfixType
13+
FunType ::= FunctionArgTypes ‘=>’ Type
14+
| TypeLambdaParams '=>' Type
15+
FunctionArgTypes ::= InfixType
16+
| ‘(’ [ FunArgTypes ] ‘)’
17+
| FunParamClause
18+
FunParamClause ::= ‘(’ TypedFunParam {‘,’ TypedFunParam } ‘)’
19+
TypedFunParam ::= id ‘:’ Type
20+
TypeLambda ::= TypeLambdaParams ‘=>>’ Type
21+
TypeLambdaParams ::= ‘[’ TypeLambdaParam {‘,’ TypeLambdaParam} ‘]’
22+
TypeLambdaParam ::= {Annotation} (id | ‘_’) [TypeParamClause] TypeBounds
23+
InfixType ::= RefinedType
24+
| RefinedTypeOrWildcard id [nl] RefinedTypeOrWildcard {id [nl] RefinedTypeOrWildcard}
25+
RefinedType ::= AnnotType {[nl] Refinement}
26+
AnnotType ::= SimpleType {Annotation}
27+
SimpleType ::= SimpleLiteral
28+
| SimpleType1
29+
SimpleType1 ::= id
30+
| Singleton ‘.’ id
31+
| Singleton ‘.’ ‘type’
32+
| ‘(’ TypesOrWildcards ‘)’
33+
| Refinement
34+
| SimpleType1 TypeArgs
35+
| SimpleType1 ‘#’ id
36+
Singleton ::= SimpleRef
37+
| SimpleLiteral
38+
| Singleton ‘.’ id
39+
SimpleRef ::= id
40+
| [id ‘.’] ‘this’
41+
| [id ‘.’] ‘super’ [‘[’ id ‘]’] ‘.’ id
42+
FunArgTypes ::= FunArgType { ‘,’ FunArgType }
43+
FunArgType ::= Type
44+
| ‘=>’ Type
45+
ParamType ::= [‘=>’] ParamValueType
46+
ParamValueType ::= ParamValueType [‘*’]
47+
TypeArgs ::= ‘[’ TypesOrWildcards ‘]’
48+
Refinement ::= :<<< [RefineDcl] {semi [RefineDcl]} >>>
49+
50+
RefineDcl ::= ‘val’ ValDcl
51+
| ‘def’ DefDcl
52+
| ‘type’ {nl} TypeDcl
53+
54+
TypeBounds ::= [‘>:’ Type] [‘<:’ Type]
55+
56+
TypesOrWildcards ::= TypeOrWildcard {‘,’ TypeOrWildcard}
57+
TypeOrWildcard ::= Type
58+
| WildcardType
59+
RefinedTypeOrWildcard ::= RefinedType
60+
| WildcardType
61+
WildcardType ::= (‘?‘ | ‘_‘) TypeBounds
62+
```
63+
64+
The above grammer describes the concrete syntax of types that can be written in user code.
65+
Semantic operations on types in the Scala type system are better defined in terms of _internal types_, which are desugared from the concrete type syntax.
66+
67+
## Internal Types
68+
69+
The following _abstract grammar_ defines the shape of _internal types_.
70+
In this specification, unless otherwise noted, "types" refer to internal types.
71+
Internal types abstract away irrelevant details such as precedence and grouping, and contain shapes of types that cannot be directly expressed using the concrete syntax.
72+
They also contain simplified, decomposed shapes for complex concrete syntax types, such as refined types.
1273

1374
```ebnf
1475
Type ::= ‘AnyKind‘
@@ -84,8 +145,90 @@ TypeAlias ::= ‘=‘ Type
84145
TypeBounds ::= ‘<:‘ Type ‘>:‘ Type
85146
```
86147

148+
### Translation of Concrete Types into Internal Types
149+
150+
Concrete types are recursively translated, or desugared, into internal types.
151+
Most shapes of concrete types have a one-to-one translation to shapes of internal types.
152+
We elaborate hereafter on the translation of the other ones.
153+
154+
### Infix Types
155+
156+
```ebnf
157+
InfixType ::= CompoundType {id [nl] CompoundType}
158+
```
159+
160+
A concrete _infix type_ ´T_1´ `op` ´T_2´ consists of an infix operator `op` which gets applied to two type operands ´T_1´ and ´T_2´.
161+
The type is translated to the internal type application `op`´[T_1, T_2]´.
162+
The infix operator `op` may be an arbitrary identifier.
163+
164+
Type operators follow the same [precedence and associativity as term operators](06-expressions.html#prefix-infix-and-postfix-operations).
165+
For example, `A + B * C` parses as `A + (B * C)` and `A | B & C` parses as `A | (B & C)`.
166+
Type operators ending in a colon ‘:’ are right-associative; all other operators are left-associative.
167+
168+
In a sequence of consecutive type infix operations ´t_0 \, \mathit{op} \, t_1 \, \mathit{op_2} \, ... \, \mathit{op_n} \, t_n´, all operators ´\mathit{op}\_1, ..., \mathit{op}\_n´ must have the same associativity.
169+
If they are all left-associative, the sequence is interpreted as ´(... (t_0 \mathit{op_1} t_1) \mathit{op_2} ...) \mathit{op_n} t_n´, otherwise it is interpreted as ´t_0 \mathit{op_1} (t_1 \mathit{op_2} ( ... \mathit{op_n} t_n) ...)´.
170+
171+
The type operators `|` and `&` are not really special.
172+
Nevertheless, unless shadowed, they resolve to `scala.|` and `scala.&`, which represent [union and intersection types](#union-and-intersection-types), respectively.
173+
174+
### Function Types
175+
176+
```ebnf
177+
Type ::= FunctionArgTypes ‘=>’ Type
178+
FunctionArgTypes ::= InfixType
179+
| ‘(’ [ ParamType {‘,’ ParamType } ] ‘)’
180+
```
181+
182+
The concrete type ´(T_1, ..., T_n) \Rightarrow R´ represents the set of function values that take arguments of types ´T_1, ..., Tn´ and yield results of type ´R´.
183+
The case of exactly one argument type ´T \Rightarrow R´ is a shorthand for ´(T) \Rightarrow R´.
184+
An argument type of the form ´\Rightarrow T´ represents a [call-by-name parameter](04-basic-declarations-and-definitions.md#by-name-parameters) of type ´T´.
185+
186+
Function types associate to the right, e.g. ´S \Rightarrow T \Rightarrow R´ is the same as ´S \Rightarrow (T \Rightarrow R)´.
187+
188+
Function types are [covariant](04-basic-declarations-and-definitions.md#variance-annotations) in their result type and [contravariant](04-basic-declarations-and-definitions.md#variance-annotations) in their argument types.
189+
190+
Function types translate into internal class types that define an `apply` method.
191+
Specifically, the ´n´-ary function type ´(T_1, ..., T_n) \Rightarrow R´ translates to the internal class type `scala.Function´_n´[´T_1´, ..., ´T_n´, ´R´]`.
192+
In particular ´() \Rightarrow R´ is a shorthand for class type `scala.Function´_0´[´R´]`.
193+
194+
Such class types behave as if they were instances of the following trait:
195+
196+
```scala
197+
trait Function´_n´[-´T_1´, ..., -´T_n´, +´R´]:
198+
def apply(´x_1´: ´T_1´, ..., ´x_n´: ´T_n´): ´R´
199+
```
200+
201+
Their exact supertype and implementation can be consulted in the [function classes section](./12-the-scala-standard-library.md#the-function-classes) of the standard library page in this document.
202+
203+
### Concrete Refined Types
204+
205+
```ebnf
206+
RefinedType ::= AnnotType {[nl] Refinement}
207+
SimpleType1 ::= ...
208+
| Refinement
209+
Refinement ::= :<<< [RefineDcl] {semi [RefineDcl]} >>>
210+
211+
RefineDcl ::= ‘val’ ValDcl
212+
| ‘def’ DefDcl
213+
| ‘type’ {nl} TypeDcl
214+
```
215+
216+
In the concrete syntax of types, refinements can contain several refined declarations.
217+
Moreover, the refined declarations can refer to each other as well as to members of the parent type, i.e., they have access to `this`.
218+
219+
In the internal types, each refinement defines exactly one refined declaration, and references to `this` must be made explicit in a recursive type.
220+
221+
The conversion from the concrete syntax to the abstract syntax works as follows:
222+
223+
1. Create a fresh recursive this name ´\alpha´.
224+
2. Replace every implicit or explicit reference to `this` in the refinement declarations by ´\alpha´.
225+
3. Create nested [refined types](#refined-types), one for every refined declaration.
226+
4. Unless ´\alpha´ was never actually used, wrap the result in a [recursive type](#recursive-types) `{ ´\alpha´ => ´...´ }`.
227+
87228
## Definitions
88229

230+
From here onwards, we refer to internal types by default.
231+
89232
### Kinds
90233

91234
The Scala type system is fundamentally higher-kinded.
@@ -1047,137 +1190,3 @@ eglb(A, _) = A if A is not a trait
10471190
eglb(_, B) = B if B is not a trait
10481191
eglb(A, _) = A // use first
10491192
```
1050-
1051-
## Concrete syntax
1052-
1053-
```ebnf
1054-
Type ::= FunType
1055-
| TypeLambda
1056-
| InfixType
1057-
FunType ::= FunctionArgTypes ‘=>’ Type
1058-
| TypeLambdaParams '=>' Type
1059-
FunctionArgTypes ::= InfixType
1060-
| ‘(’ [ FunArgTypes ] ‘)’
1061-
| FunParamClause
1062-
FunParamClause ::= ‘(’ TypedFunParam {‘,’ TypedFunParam } ‘)’
1063-
TypedFunParam ::= id ‘:’ Type
1064-
TypeLambda ::= TypeLambdaParams ‘=>>’ Type
1065-
TypeLambdaParams ::= ‘[’ TypeLambdaParam {‘,’ TypeLambdaParam} ‘]’
1066-
TypeLambdaParam ::= {Annotation} (id | ‘_’) [TypeParamClause] TypeBounds
1067-
InfixType ::= RefinedType
1068-
| RefinedTypeOrWildcard id [nl] RefinedTypeOrWildcard {id [nl] RefinedTypeOrWildcard}
1069-
RefinedType ::= AnnotType {[nl] Refinement}
1070-
AnnotType ::= SimpleType {Annotation}
1071-
SimpleType ::= SimpleLiteral
1072-
| SimpleType1
1073-
SimpleType1 ::= id
1074-
| Singleton ‘.’ id
1075-
| Singleton ‘.’ ‘type’
1076-
| ‘(’ TypesOrWildcards ‘)’
1077-
| Refinement
1078-
| SimpleType1 TypeArgs
1079-
| SimpleType1 ‘#’ id
1080-
Singleton ::= SimpleRef
1081-
| SimpleLiteral
1082-
| Singleton ‘.’ id
1083-
SimpleRef ::= id
1084-
| [id ‘.’] ‘this’
1085-
| [id ‘.’] ‘super’ [‘[’ id ‘]’] ‘.’ id
1086-
FunArgTypes ::= FunArgType { ‘,’ FunArgType }
1087-
FunArgType ::= Type
1088-
| ‘=>’ Type
1089-
ParamType ::= [‘=>’] ParamValueType
1090-
ParamValueType ::= ParamValueType [‘*’]
1091-
TypeArgs ::= ‘[’ TypesOrWildcards ‘]’
1092-
Refinement ::= :<<< [RefineDcl] {semi [RefineDcl]} >>>
1093-
1094-
RefineDcl ::= ‘val’ ValDcl
1095-
| ‘def’ DefDcl
1096-
| ‘type’ {nl} TypeDcl
1097-
1098-
TypeBounds ::= [‘>:’ Type] [‘<:’ Type]
1099-
1100-
TypesOrWildcards ::= TypeOrWildcard {‘,’ TypeOrWildcard}
1101-
TypeOrWildcard ::= Type
1102-
| WildcardType
1103-
RefinedTypeOrWildcard ::= RefinedType
1104-
| WildcardType
1105-
WildcardType ::= (‘?‘ | ‘_‘) TypeBounds
1106-
```
1107-
1108-
Most types in the concrete syntax translate one to one to types in the abstract syntax.
1109-
We elaborate hereafter on the translation of the other ones.
1110-
1111-
### Infix Types
1112-
1113-
```ebnf
1114-
InfixType ::= CompoundType {id [nl] CompoundType}
1115-
```
1116-
1117-
An _infix type_ ´T_1´ `op` ´T_2´ consists of an infix operator `op` which gets applied to two type operands ´T_1´ and ´T_2´.
1118-
The type is equivalent to the type application `op`´[T_1, T_2]´.
1119-
The infix operator `op` may be an arbitrary identifier.
1120-
1121-
Type operators follow the same [precedence and associativity as term operators](06-expressions.html#prefix-infix-and-postfix-operations).
1122-
For example, `A + B * C` parses as `A + (B * C)` and `A | B & C` parses as `A | (B & C)`.
1123-
Type operators ending in a colon ‘:’ are right-associative; all other operators are left-associative.
1124-
1125-
In a sequence of consecutive type infix operations ´t_0 \, \mathit{op} \, t_1 \, \mathit{op_2} \, ... \, \mathit{op_n} \, t_n´, all operators ´\mathit{op}\_1, ..., \mathit{op}\_n´ must have the same associativity.
1126-
If they are all left-associative, the sequence is interpreted as ´(... (t_0 \mathit{op_1} t_1) \mathit{op_2} ...) \mathit{op_n} t_n´, otherwise it is interpreted as ´t_0 \mathit{op_1} (t_1 \mathit{op_2} ( ... \mathit{op_n} t_n) ...)´.
1127-
1128-
The type operators `|` and `&` are not really special.
1129-
Nevertheless, unless shadowed, they resolve to `scala.|` and `scala.&`, which represent [union and intersection types](#union-and-intersection-types), respectively.
1130-
1131-
### Function Types
1132-
1133-
```ebnf
1134-
Type ::= FunctionArgTypes ‘=>’ Type
1135-
FunctionArgTypes ::= InfixType
1136-
| ‘(’ [ ParamType {‘,’ ParamType } ] ‘)’
1137-
```
1138-
1139-
The type ´(T_1, ..., T_n) \Rightarrow R´ represents the set of function values that take arguments of types ´T_1, ..., Tn´ and yield results of type ´R´.
1140-
The case of exactly one argument type ´T \Rightarrow R´ is a shorthand for ´(T) \Rightarrow R´.
1141-
An argument type of the form ´\Rightarrow T´ represents a [call-by-name parameter](04-basic-declarations-and-definitions.md#by-name-parameters) of type ´T´.
1142-
1143-
Function types associate to the right, e.g. ´S \Rightarrow T \Rightarrow R´ is the same as ´S \Rightarrow (T \Rightarrow R)´.
1144-
1145-
Function types are [covariant](04-basic-declarations-and-definitions.md#variance-annotations) in their result type and [contravariant](04-basic-declarations-and-definitions.md#variance-annotations) in their argument types.
1146-
1147-
Function types are shorthands for class types that define an `apply` method.
1148-
Specifically, the ´n´-ary function type ´(T_1, ..., T_n) \Rightarrow R´ is a shorthand for the class type `Function´_n´[´T_1´, ..., ´T_n´, ´R´]`.
1149-
In particular ´() \Rightarrow R´ is a shorthand for class type `Function´_0´[´R´]`.
1150-
1151-
Such class types behave as if they were instances of the following trait:
1152-
1153-
```scala
1154-
trait Function´_n´[-´T_1´, ..., -´T_n´, +´R´]:
1155-
def apply(´x_1´: ´T_1´, ..., ´x_n´: ´T_n´): ´R´
1156-
```
1157-
1158-
Their exact supertype and implementation can be consulted in the [function classes section](./12-the-scala-standard-library.md#the-function-classes) of the standard library page in this document.
1159-
1160-
### Concrete Refined Types
1161-
1162-
```ebnf
1163-
RefinedType ::= AnnotType {[nl] Refinement}
1164-
SimpleType1 ::= ...
1165-
| Refinement
1166-
Refinement ::= :<<< [RefineDcl] {semi [RefineDcl]} >>>
1167-
1168-
RefineDcl ::= ‘val’ ValDcl
1169-
| ‘def’ DefDcl
1170-
| ‘type’ {nl} TypeDcl
1171-
```
1172-
1173-
In the concrete syntax of types, refinements can contain several refined declarations.
1174-
Moreover, the refined declarations can refer to each other as well as to members of the parent type, i.e., they have access to `this`.
1175-
1176-
In the abstract syntax of types, each refinement defines exactly one refined declaration, and references to `this` must be made explicit in a recursive type.
1177-
1178-
The conversion from the concrete syntax to the abstract syntax works as follows:
1179-
1180-
1. Create a fresh recursive this name ´\alpha´.
1181-
2. Replace every implicit or explicit reference to `this` in the refinement declarations by ´\alpha´.
1182-
3. Create nested [refined types](#refined-types), one for every refined declaration.
1183-
4. Unless ´\alpha´ was never actually used, wrap the result in a [recursive type](#recursive-types) `{ ´\alpha´ => ´...´ }`.

0 commit comments

Comments
 (0)