@@ -702,11 +702,11 @@ class RecursiveDescent(positions: Positions, tokens: Seq[Token], source: Source)
702
702
def implementation (): Implementation =
703
703
nonterminal :
704
704
// Interface[...] {}
705
- def emptyImplementation () = backtrack { Implementation (interfaceType (), `{` ~> Nil <~ `}`) }
705
+ def emptyImplementation () = backtrack { Implementation (blockTypeRef (), `{` ~> Nil <~ `}`) }
706
706
707
707
// Interface[...] { def <NAME> = ... }
708
708
def interfaceImplementation () = backtrack {
709
- val tpe = interfaceType ()
709
+ val tpe = blockTypeRef ()
710
710
consume(`{`)
711
711
if ! peek(`def`) then fail(" Expected at least one operation definition to implement this interface." )
712
712
tpe
@@ -719,7 +719,7 @@ class RecursiveDescent(positions: Positions, tokens: Seq[Token], source: Source)
719
719
def operationImplementation () = idRef() ~ maybeTypeArgs() ~ implicitResume ~ functionArg() match {
720
720
case (id ~ tps ~ k ~ BlockLiteral (_, vps, bps, body)) =>
721
721
val synthesizedId = IdRef (Nil , id.name).withPositionOf(id)
722
- val interface = BlockTypeRef (id, tps).withPositionOf(id): BlockTypeRef
722
+ val interface = TypeRef (id, tps).withPositionOf(id)
723
723
val operation = OpClause (synthesizedId, Nil , vps, bps, None , body, k).withRangeOf(id, body)
724
724
Implementation (interface, List (operation))
725
725
}
@@ -866,9 +866,8 @@ class RecursiveDescent(positions: Positions, tokens: Seq[Token], source: Source)
866
866
case _ => sys.error(s " Internal compiler error: not a valid operator ${op}" )
867
867
}
868
868
869
- private def TupleTypeTree (tps : List [ValueType ]): ValueType =
870
- ValueTypeRef (IdRef (List (" effekt" ), s " Tuple ${tps.size}" ), tps)
871
- // TODO positions!
869
+ def TypeTuple (tps : List [Type ]): Type =
870
+ TypeRef (IdRef (List (" effekt" ), s " Tuple ${tps.size}" ), tps)
872
871
873
872
/**
874
873
* This is a compound production for
@@ -1100,78 +1099,109 @@ class RecursiveDescent(positions: Positions, tokens: Seq[Token], source: Source)
1100
1099
case _ => fail(s " Expected identifier " )
1101
1100
}
1102
1101
1103
-
1104
- /**
1105
- * Types
1106
- */
1107
-
1108
- def valueType (): ValueType = valueType2(true )
1109
-
1110
- /**
1111
- * Uses backtracking!
1102
+ /*
1103
+ * Type grammar by precedence:
1104
+ *
1105
+ * Type ::= Id ('[' Type ',' ... ']')? refType
1106
+ *
1107
+ * | '(' Type ',' ... ')' atomicType
1108
+ * | '(' Type ')'
1112
1109
*
1113
- * This is not very efficient. To parse a value type, we first parse a block type,
1114
- * just to see that it either is no blocktype or it is not followed by an `at`
1115
- * and just "looked" like a block type...
1110
+ * | Type '=>' Type ('/' SetType)? functionType
1111
+ * | '(' Type ',' ... ')' ('{' Type '}')* '=>' Type ('/' SetType)?
1116
1112
*
1117
- * The parameter [[boxedAllowed ]] controls whether on the right a dangling `at`
1118
- * can occur. This way we prevent parsing `() => S at {} at {}` and force users
1119
- * to manually parenthesize.
1113
+ * | Type 'at' Id boxedType
1114
+ * | Type 'at' '{' Id ',' ... '}'
1115
+ * | Type ('/' SetType)?
1116
+ *
1117
+ * SetType ::= Type
1118
+ * | '{' Type ',' ... '}'
1120
1119
*/
1121
- private def valueType2 (boxedAllowed : Boolean ): ValueType = nonterminal {
1122
- def boxedBlock = backtrack {
1123
- BoxedType (blockType2(false ), `at` ~> captureSet())
1124
- }
1125
- if (boxedAllowed) { boxedBlock getOrElse atomicValueType() }
1126
- else atomicValueType()
1120
+ def effects (): Effects =
1121
+ nonterminal :
1122
+ if peek(`{`) then Effects (many(refType, `{`, `,`, `}`))
1123
+ else Effects (refType())
1124
+
1125
+ def maybeEffects (): Effects = {
1126
+ nonterminal :
1127
+ when(`/`) {
1128
+ effects()
1129
+ } {
1130
+ Effects .Pure
1131
+ }
1127
1132
}
1128
1133
1129
- def atomicValueType (): ValueType =
1134
+ def refType (): TypeRef =
1135
+ nonterminal :
1136
+ TypeRef (idRef(), maybeTypeArgs())
1137
+
1138
+ // Parse atomic types: Tuples, parenthesized types, type references (highest precedence)
1139
+ private def atomicType (): Type =
1130
1140
nonterminal :
1131
1141
peek.kind match {
1132
- case `(` => some(valueType, `(`, `,`, `)`) match {
1133
- case tpe :: Nil => tpe
1134
- case tpes => TupleTypeTree (tpes)
1135
- }
1136
- case _ => ValueTypeRef (idRef(), maybeTypeArgs())
1142
+ case `(` =>
1143
+ some(boxedType, `(`, `,`, `)`) match {
1144
+ case tpe :: Nil => tpe
1145
+ case tpes => TypeTuple (tpes)
1146
+ }
1147
+ case _ => refType()
1148
+ }
1149
+
1150
+ // Parse function types (middle precedence)
1151
+ private def functionType (): Type = {
1152
+ // Complex function type: [T]*(Int, String)*{Exc} => Int / {Effect}
1153
+ def functionTypeComplex = backtrack {
1154
+ maybeTypeParams() ~ maybeValueTypes() ~ (maybeBlockTypeParams() <~ `=>`) ~ atomicType() ~ maybeEffects() match {
1155
+ case tparams ~ vparams ~ bparams ~ t ~ effs => FunctionType (tparams, vparams, bparams, t, effs)
1137
1156
}
1157
+ }
1138
1158
1159
+ // Simple function type: Int => Int
1160
+ def functionTypeSimple = backtrack {
1161
+ refType() <~ `=>`
1162
+ } map { tpe =>
1163
+ FunctionType (Nil , List (tpe), Nil , atomicType(), maybeEffects())
1164
+ }
1139
1165
1140
- /**
1141
- * Uses backtracking!
1142
- *
1143
- * TODO improve errors
1144
- * i.e. fail("Expected either a function type (e.g., (A) => B / {E} or => B) or an interface type (e.g., State[T]).")
1145
- */
1146
- def blockType (): BlockType = blockType2(true )
1147
- private def blockType2 (boxedAllowed : Boolean ): BlockType =
1166
+ // Try to parse each function type variant, fall back to basic type if none match
1148
1167
nonterminal :
1168
+ functionTypeSimple orElse functionTypeComplex getOrElse atomicType()
1169
+ }
1149
1170
1150
- def simpleFunType = backtrack {
1151
- ValueTypeRef (idRef(), maybeTypeArgs()) <~ `=>`
1152
- } map { tpe =>
1153
- FunctionType (Nil , List (tpe), Nil , valueType2(boxedAllowed), maybeEffects())
1171
+ // Parse boxed types and effectfuls (lowest precedence)
1172
+ // "Top-level" parser for a generic type.
1173
+ private def boxedType (): Type = {
1174
+ nonterminal :
1175
+ // Parse the function type first
1176
+ val tpe = functionType()
1177
+
1178
+ // TODO: these should probably be in a loop to parse as many `at`s and `\`s as possible?
1179
+ val boxed = when(`at`) {
1180
+ BoxedType (tpe, captureSet())
1181
+ } {
1182
+ tpe
1154
1183
}
1155
1184
1156
- def funType = backtrack {
1157
- maybeTypeParams() ~ maybeValueTypes() ~ (maybeBlockTypeParams() <~ `=>`) ~ valueType2(boxedAllowed) ~ maybeEffects() match {
1158
- case tparams ~ vparams ~ bparams ~ t ~ effs => FunctionType (tparams, vparams, bparams, t, effs)
1159
- }
1185
+ if (peek(`/`)) {
1186
+ Effectful (boxed, maybeEffects())
1187
+ } else {
1188
+ boxed
1160
1189
}
1161
- def parenthesized = backtrack { parens { blockType() } }
1190
+ }
1162
1191
1163
- def interface () =
1164
- val res = interfaceType()
1165
- if peek(`/`) then
1166
- fail(" Effects not allowed here. Maybe you mean to use a function type `() => T / E`?" )
1167
- else res
1192
+ // NOTE: ValueType, BlockType are just aliases for Type.
1193
+ def blockType (): BlockType = boxedType()
1194
+ def valueType (): ValueType = boxedType()
1168
1195
1169
- simpleFunType orElse funType orElse parenthesized getOrElse interface()
1196
+ // Completely specialized for TypeRef: we only parse `refType` here, we don't go through the whole hierarchy.
1197
+ // This results in slightly worse errors, but massively simplifies the design.
1198
+ inline def blockTypeRef (): TypeRef = refType()
1170
1199
1171
- def interfaceType (): BlockTypeRef =
1172
- nonterminal :
1173
- BlockTypeRef (idRef(), maybeTypeArgs()): BlockTypeRef
1174
- // TODO error "Expected an interface type"
1200
+ // Somewhat specialized: we parse a normal type, if it's not a ${tpe} / ${effs},
1201
+ // then pretend the effect set is empty. This seems to work out fine :)
1202
+ def effectful (): Effectful = boxedType() match
1203
+ case eff : Effectful => eff
1204
+ case tpe => Effectful (tpe, Effects .Pure )
1175
1205
1176
1206
def maybeTypeParams (): List [Id ] =
1177
1207
nonterminal :
@@ -1181,15 +1211,15 @@ class RecursiveDescent(positions: Positions, tokens: Seq[Token], source: Source)
1181
1211
nonterminal :
1182
1212
some(idDef, `[`, `,`, `]`)
1183
1213
1184
- def maybeBlockTypeParams (): List [(Option [IdDef ], BlockType )] =
1214
+ def maybeBlockTypeParams (): List [(Option [IdDef ], Type )] =
1185
1215
nonterminal :
1186
1216
if peek(`{`) then blockTypeParams() else Nil
1187
1217
1188
- def blockTypeParams (): List [(Option [IdDef ], BlockType )] =
1218
+ def blockTypeParams (): List [(Option [IdDef ], Type )] =
1189
1219
nonterminal :
1190
1220
someWhile(blockTypeParam(), `{`)
1191
1221
1192
- def blockTypeParam (): (Option [IdDef ], BlockType ) =
1222
+ def blockTypeParam (): (Option [IdDef ], Type ) =
1193
1223
nonterminal :
1194
1224
braces { (backtrack { idDef() <~ `:` }, blockType()) }
1195
1225
@@ -1259,34 +1289,18 @@ class RecursiveDescent(positions: Positions, tokens: Seq[Token], source: Source)
1259
1289
nonterminal :
1260
1290
BlockParam (idDef(), when(`:`)(Some (blockType()))(None ))
1261
1291
1262
-
1263
- def maybeValueTypes (): List [ValueType ] =
1292
+ def maybeValueTypes (): List [Type ] =
1264
1293
nonterminal :
1265
1294
if peek(`(`) then valueTypes() else Nil
1266
1295
1267
- def valueTypes (): List [ValueType ] =
1296
+ def valueTypes (): List [Type ] =
1268
1297
nonterminal :
1269
1298
many(valueType, `(`, `,`, `)`)
1270
1299
1271
1300
def captureSet (): CaptureSet =
1272
1301
nonterminal :
1273
1302
CaptureSet (many(idRef, `{`, `,` , `}`))
1274
1303
1275
- def effectful (): Effectful =
1276
- nonterminal :
1277
- Effectful (valueType(), maybeEffects())
1278
-
1279
- def maybeEffects (): Effects =
1280
- nonterminal :
1281
- when(`/`) { effects() } { Effects .Pure }
1282
-
1283
- // TODO error "Expected an effect set"
1284
- def effects (): Effects =
1285
- nonterminal :
1286
- if peek(`{`) then Effects (many(interfaceType, `{`, `,`, `}`))
1287
- else Effects (interfaceType())
1288
-
1289
-
1290
1304
// Generic utility functions
1291
1305
// -------------------------
1292
1306
// ... for writing parsers.
0 commit comments