Skip to content

Commit 9b9266c

Browse files
phischub-studios
authored andcommitted
Properly represent existentials in core (effekt-lang#880)
Co-authored-by: Jonathan Brachthäuser <[email protected]>
1 parent 1a71751 commit 9b9266c

18 files changed

+83
-66
lines changed

effekt/jvm/src/test/scala/effekt/core/PatternMatchingTests.scala

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,10 @@ class PatternMatchingTests extends CoreTests {
3838
List(
3939
Condition.Patterns(Map(x -> Pattern.Any(y.id))),
4040
Condition.Patterns(Map(y -> Pattern.Any(z.id)))),
41-
f, List(z)))
41+
f, Nil, List(z)))
4242

4343
// case => f(z)
44-
val expected = Clause(Nil, f, List(x))
44+
val expected = Clause(Nil, f, Nil, List(x))
4545

4646
assertEquals(normalized, expected)
4747
}
@@ -73,11 +73,11 @@ class PatternMatchingTests extends CoreTests {
7373
Condition.Patterns(Map(sc -> Pattern.Any(x.id))),
7474
Condition.Val(p.id, TBoolean, trivalPredicate),
7575
Condition.Predicate(p)),
76-
b1, List(x)),
76+
b1, Nil, List(x)),
7777
Clause(
7878
List(
7979
Condition.Patterns(Map(sc -> Pattern.Ignore()))),
80-
b2, List())))
80+
b2, Nil, List())))
8181

8282
val expected =
8383
Val(p.id, TBoolean, trivalPredicate,
@@ -124,14 +124,14 @@ class PatternMatchingTests extends CoreTests {
124124
val result = compile(List(
125125
Clause(
126126
List(
127-
Condition.Patterns(Map(opt -> Pattern.Tag(SomeC, List(Pattern.Any(v.id) -> TInt)))),
127+
Condition.Patterns(Map(opt -> Pattern.Tag(SomeC, List(), List(Pattern.Any(v.id) -> TInt)))),
128128
Condition.Val(p.id, TBoolean, trivalPredicate),
129129
Condition.Predicate(p)),
130-
b1, List(v)),
130+
b1, Nil, List(v)),
131131
Clause(
132132
List(
133133
Condition.Patterns(Map(opt -> Pattern.Ignore()))),
134-
b2, List())))
134+
b2, Nil, List())))
135135

136136
// opt match {
137137
// case Some(tmp) => val p = return v > 0; if (p) { b1(tmp) } else { b2() }

effekt/shared/src/main/scala/effekt/core/Parser.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ class CoreParsers(positions: Positions, names: Names) extends EffektLexers(posit
168168
( literal
169169
| id ~ (`:` ~> valueType) ^^ Pure.ValueVar.apply
170170
| `box` ~> captures ~ block ^^ { case capt ~ block => Pure.Box(block, capt) }
171-
| `make` ~> dataType ~ id ~ valueArgs ^^ Pure.Make.apply
171+
| `make` ~> dataType ~ id ~ maybeTypeArgs ~ valueArgs ^^ Pure.Make.apply
172172
| maybeParens(blockVar) ~ maybeTypeArgs ~ valueArgs ^^ Pure.PureApp.apply
173173
| failure("Expected a pure expression.")
174174
)

effekt/shared/src/main/scala/effekt/core/PatternMatchingCompiler.scala

Lines changed: 31 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
package effekt
22
package core
33

4-
import effekt.context.Context
54
import effekt.core.substitutions.Substitution
6-
import effekt.symbols.TmpValue
75

86
import scala.collection.mutable
97

@@ -54,9 +52,9 @@ import scala.collection.mutable
5452
object PatternMatchingCompiler {
5553

5654
/**
57-
* The conditions need to be met in sequence before the block at [[label]] can be evaluated with given [[args]].
55+
* The conditions need to be met in sequence before the block at [[label]] can be evaluated with given [[targs]] and [[args]].
5856
*/
59-
case class Clause(conditions: List[Condition], label: BlockVar, args: List[ValueVar])
57+
case class Clause(conditions: List[Condition], label: BlockVar, targs: List[ValueType], args: List[ValueVar])
6058

6159
enum Condition {
6260
// all of the patterns need to match for this condition to be met
@@ -71,7 +69,7 @@ object PatternMatchingCompiler {
7169
enum Pattern {
7270
// sub-patterns are annotated with the inferred type of the scrutinee at this point
7371
// i.e. Cons(Some(x : TInt): Option[Int], xs: List[Option[Int]])
74-
case Tag(id: Id, patterns: List[(Pattern, ValueType)])
72+
case Tag(id: Id, tparams: List[Id], patterns: List[(Pattern, ValueType)])
7573
case Ignore()
7674
case Any(id: Id)
7775
case Or(patterns: List[Pattern])
@@ -93,21 +91,21 @@ object PatternMatchingCompiler {
9391
// (1) Check the first clause to be matched (we can immediately handle non-pattern cases)
9492
val patterns = headClause match {
9593
// - The top-most clause already matches successfully
96-
case Clause(Nil, target, args) =>
97-
return core.App(target, Nil, args, Nil)
94+
case Clause(Nil, target, targs, args) =>
95+
return core.App(target, targs, args, Nil)
9896
// - We need to perform a computation
99-
case Clause(Condition.Val(x, tpe, binding) :: rest, target, args) =>
100-
return core.Val(x, tpe, binding, compile(Clause(rest, target, args) :: remainingClauses))
97+
case Clause(Condition.Val(x, tpe, binding) :: rest, target, targs, args) =>
98+
return core.Val(x, tpe, binding, compile(Clause(rest, target, targs, args) :: remainingClauses))
10199
// - We need to perform a computation
102-
case Clause(Condition.Let(x, tpe, binding) :: rest, target, args) =>
103-
return core.Let(x, tpe, binding, compile(Clause(rest, target, args) :: remainingClauses))
100+
case Clause(Condition.Let(x, tpe, binding) :: rest, target, targs, args) =>
101+
return core.Let(x, tpe, binding, compile(Clause(rest, target, targs, args) :: remainingClauses))
104102
// - We need to check a predicate
105-
case Clause(Condition.Predicate(pred) :: rest, target, args) =>
103+
case Clause(Condition.Predicate(pred) :: rest, target, targs, args) =>
106104
return core.If(pred,
107-
compile(Clause(rest, target, args) :: remainingClauses),
105+
compile(Clause(rest, target, targs, args) :: remainingClauses),
108106
compile(remainingClauses)
109107
)
110-
case Clause(Condition.Patterns(patterns) :: rest, target, args) =>
108+
case Clause(Condition.Patterns(patterns) :: rest, target, targs, args) =>
111109
patterns
112110
}
113111

@@ -127,7 +125,7 @@ object PatternMatchingCompiler {
127125
def splitOnLiteral(lit: Literal, equals: (Pure, Pure) => Pure): core.Stmt = {
128126
// the different literal values that we match on
129127
val variants: List[core.Literal] = normalized.collect {
130-
case Clause(Split(Pattern.Literal(lit, _), _, _), _, _) => lit
128+
case Clause(Split(Pattern.Literal(lit, _), _, _), _, _, _) => lit
131129
}.distinct
132130

133131
// for each literal, we collect the clauses that match it correctly
@@ -141,8 +139,8 @@ object PatternMatchingCompiler {
141139
defaults = defaults :+ cl
142140

143141
normalized.foreach {
144-
case Clause(Split(Pattern.Literal(lit, _), restPatterns, restConds), label, args) =>
145-
addClause(lit, Clause(Condition.Patterns(restPatterns) :: restConds, label, args))
142+
case Clause(Split(Pattern.Literal(lit, _), restPatterns, restConds), label, targs, args) =>
143+
addClause(lit, Clause(Condition.Patterns(restPatterns) :: restConds, label, targs, args))
146144
case c =>
147145
addDefault(c)
148146
variants.foreach { v => addClause(v, c) }
@@ -164,7 +162,7 @@ object PatternMatchingCompiler {
164162
def splitOnTag() = {
165163
// collect all variants that are mentioned in the clauses
166164
val variants: List[Id] = normalized.collect {
167-
case Clause(Split(p: Pattern.Tag, _, _), _, _) => p.id
165+
case Clause(Split(p: Pattern.Tag, _, _), _, _, _) => p.id
168166
}.distinct
169167

170168
// for each tag, we collect the clauses that match it correctly
@@ -179,7 +177,9 @@ object PatternMatchingCompiler {
179177

180178
// used to make up new scrutinees
181179
val varsFor = mutable.Map.empty[Id, List[ValueVar]]
182-
def fieldVarsFor(constructor: Id, fieldInfo: List[((Pattern, ValueType), String)]): List[ValueVar] =
180+
val tvarsFor = mutable.Map.empty[Id, List[Id]]
181+
def fieldVarsFor(constructor: Id, tparams: List[Id], fieldInfo: List[((Pattern, ValueType), String)]): List[ValueVar] =
182+
tvarsFor.getOrElseUpdate(constructor, tparams)
183183
varsFor.getOrElseUpdate(
184184
constructor,
185185
fieldInfo.map {
@@ -191,17 +191,17 @@ object PatternMatchingCompiler {
191191
)
192192

193193
normalized.foreach {
194-
case Clause(Split(Pattern.Tag(constructor, patternsAndTypes), restPatterns, restConds), label, args) =>
194+
case Clause(Split(Pattern.Tag(constructor, tparams, patternsAndTypes), restPatterns, restConds), label, targs, args) =>
195195
// NOTE: Ideally, we would use a `DeclarationContext` here, but we cannot: we're currently in the Source->Core transformer, so we do not have all of the details yet.
196196
val fieldNames: List[String] = constructor match {
197197
case c: symbols.Constructor => c.fields.map(_.name.name)
198198
case _ => List.fill(patternsAndTypes.size) { "y" } // NOTE: Only reached in PatternMatchingTests
199199
}
200-
val fieldVars = fieldVarsFor(constructor, patternsAndTypes.zip(fieldNames))
200+
val fieldVars = fieldVarsFor(constructor, tparams, patternsAndTypes.zip(fieldNames))
201201
val nestedMatches = fieldVars.zip(patternsAndTypes.map { case (pat, tpe) => pat }).toMap
202202
addClause(constructor,
203203
// it is important to add nested matches first, since they might include substitutions for the rest.
204-
Clause(Condition.Patterns(nestedMatches) :: Condition.Patterns(restPatterns) :: restConds, label, args))
204+
Clause(Condition.Patterns(nestedMatches) :: Condition.Patterns(restPatterns) :: restConds, label, targs, args))
205205

206206
case c =>
207207
// Clauses that don't match on that var are duplicated.
@@ -214,8 +214,9 @@ object PatternMatchingCompiler {
214214
// (4) assemble syntax tree for the pattern match
215215
val branches = variants.map { v =>
216216
val body = compile(clausesFor.getOrElse(v, Nil))
217+
val tparams = tvarsFor(v)
217218
val params = varsFor(v).map { case ValueVar(id, tpe) => core.ValueParam(id, tpe): core.ValueParam }
218-
val blockLit: BlockLit = BlockLit(Nil, Nil, params, Nil, body)
219+
val blockLit: BlockLit = BlockLit(tparams, Nil, params, Nil, body)
219220
(v, blockLit)
220221
}
221222

@@ -232,16 +233,17 @@ object PatternMatchingCompiler {
232233

233234
def branchingHeuristic(patterns: Map[ValueVar, Pattern], clauses: List[Clause]): ValueVar =
234235
patterns.keys.maxBy(v => clauses.count {
235-
case Clause(ps, _, _) => ps.contains(v)
236+
case Clause(ps, _, _, _) => ps.contains(v)
236237
})
237238

238239
/**
239240
* Substitutes AnyPattern and removes wildcards.
240241
*/
241242
def normalize(clause: Clause): Clause = clause match {
242-
case Clause(conditions, label, args) =>
243+
case Clause(conditions, label, targs, args) =>
243244
val (normalized, substitution) = normalize(Map.empty, conditions, Map.empty)
244-
Clause(normalized, label, args.map(v => substitution.getOrElse(v.id, v)))
245+
// TODO also substitute types?
246+
Clause(normalized, label, targs, args.map(v => substitution.getOrElse(v.id, v)))
245247
}
246248

247249

@@ -309,8 +311,8 @@ object PatternMatchingCompiler {
309311
// -----------------------------
310312

311313
def show(cl: Clause): String = cl match {
312-
case Clause(conditions, label, args) =>
313-
s"case ${conditions.map(show).mkString("; ")} => ${util.show(label.id)}${args.map(x => util.show(x)).mkString("(", ", ", ")")}"
314+
case Clause(conditions, label, targs, args) =>
315+
s"case ${conditions.map(show).mkString("; ")} => ${util.show(label.id)}${targs.map(x => util.show(x))}${args.map(x => util.show(x)).mkString("(", ", ", ")")}"
314316
}
315317

316318
def show(c: Condition): String = c match {
@@ -321,7 +323,7 @@ object PatternMatchingCompiler {
321323
}
322324

323325
def show(p: Pattern): String = p match {
324-
case Pattern.Tag(id, patterns) => util.show(id) + patterns.map { case (p, tpe) => show(p) }.mkString("(", ", ", ")")
326+
case Pattern.Tag(id, tparams, patterns) => util.show(id) + tparams.map(util.show).mkString("[", ",", "]") + patterns.map { case (p, tpe) => show(p) }.mkString("(", ", ", ")")
325327
case Pattern.Ignore() => "_"
326328
case Pattern.Any(id) => util.show(id)
327329
case Pattern.Or(patterns) => patterns.map(show).mkString(" | ")

effekt/shared/src/main/scala/effekt/core/PolymorphismBoxing.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -349,15 +349,15 @@ object PolymorphismBoxing extends Phase[CoreTransformed, CoreTransformed] {
349349
val vCoerced = (vargs zip tpe.vparams).map { (a, tpe) => coerce(transform(a), tpe) }
350350
coerce(PureApp(callee, targs.map(transformArg), vCoerced), itpe.result)
351351

352-
case Pure.Make(data, tag, vargs) =>
352+
case Pure.Make(data, tag, targs, vargs) =>
353353
val dataDecl = PContext.getData(data.name)
354354
val ctorDecl = dataDecl.constructors.find(_.id == tag).getOrElse {
355355
Context.panic(pp"No constructor found for tag ${tag} in data type: ${data}")
356356
}
357357
val paramTypes = ctorDecl.fields.map(_.tpe)
358358

359359
val coercedArgs = (vargs zip paramTypes).map { case (arg, paramTpe) => coerce(transform(arg), paramTpe) }
360-
Pure.Make(transform(data), tag, coercedArgs)
360+
Pure.Make(transform(data), tag, targs.map(transformArg), coercedArgs)
361361

362362
case Pure.Box(b, annotatedCapture) =>
363363
Pure.Box(transform(b), annotatedCapture)

effekt/shared/src/main/scala/effekt/core/PrettyPrinter.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ object PrettyPrinter extends ParenPrettyPrinter {
100100
case ValueVar(id, _) => toDoc(id)
101101

102102
case PureApp(b, targs, vargs) => toDoc(b) <> argsToDoc(targs, vargs, Nil)
103-
case Make(data, tag, vargs) => "make" <+> toDoc(data) <+> toDoc(tag) <> argsToDoc(Nil, vargs, Nil)
103+
case Make(data, tag, targs, vargs) => "make" <+> toDoc(data) <+> toDoc(tag) <> argsToDoc(targs, vargs, Nil)
104104
case DirectApp(b, targs, vargs, bargs) => toDoc(b) <> argsToDoc(targs, vargs, bargs)
105105

106106
case Box(b, capt) => parens("box" <+> toDoc(b))

effekt/shared/src/main/scala/effekt/core/Recursive.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ class Recursive(
9494
case Pure.ValueVar(id, annotatedType) => ()
9595
case Pure.Literal(value, annotatedType) => ()
9696
case Pure.PureApp(b, targs, vargs) => process(b); vargs.foreach(process)
97-
case Pure.Make(data, tag, vargs) => vargs.foreach(process)
97+
case Pure.Make(data, tag, targs, vargs) => vargs.foreach(process)
9898
case Pure.Box(b, annotatedCapture) => process(b)
9999
}
100100

effekt/shared/src/main/scala/effekt/core/Transformer.scala

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -273,13 +273,13 @@ object Transformer extends Phase[Typechecked, CoreTransformed] {
273273
Stmt.Return(PureApp(BlockVar(b), targs, vargs)))
274274
}
275275

276-
// [[ f ]] = { (x) => make f(x) }
276+
// [[ f ]] = { [A](x) => make f[A](x) }
277277
def etaExpandConstructor(b: Constructor): BlockLit = {
278278
assert(bparamtps.isEmpty)
279279
assert(effects.isEmpty)
280280
assert(cparams.isEmpty)
281281
BlockLit(tparams, Nil, vparams, Nil,
282-
Stmt.Return(Make(core.ValueType.Data(b.tpe, targs), b, vargs)))
282+
Stmt.Return(Make(core.ValueType.Data(b.tpe, targs), b, targs, vargs)))
283283
}
284284

285285
// [[ f ]] = { (x){g} => let r = f(x){g}; return r }
@@ -668,6 +668,15 @@ object Transformer extends Phase[Typechecked, CoreTransformed] {
668668
case MatchGuard.BooleanGuard(condition) => Nil
669669
case MatchGuard.PatternGuard(scrutinee, pattern) => boundInPattern(pattern)
670670
}
671+
def boundTypesInPattern(p: source.MatchPattern): List[Id] = p match {
672+
case source.AnyPattern(id) => List()
673+
case p @ source.TagPattern(id, patterns) => Context.annotation(Annotations.TypeParameters, p) ++ patterns.flatMap(boundTypesInPattern)
674+
case _: source.LiteralPattern | _: source.IgnorePattern => Nil
675+
}
676+
def boundTypesInGuard(g: source.MatchGuard): List[Id] = g match {
677+
case MatchGuard.BooleanGuard(condition) => Nil
678+
case MatchGuard.PatternGuard(scrutinee, pattern) => boundTypesInPattern(pattern)
679+
}
671680
def equalsFor(tpe: symbols.ValueType): (Pure, Pure) => Pure =
672681
val prelude = Context.module.findDependency(QualifiedName(Nil, "effekt")).getOrElse {
673682
Context.panic(pp"${Context.module.name.name}: Cannot find 'effekt' in prelude, which is necessary to compile pattern matching.")
@@ -685,14 +694,16 @@ object Transformer extends Phase[Typechecked, CoreTransformed] {
685694
} getOrElse { Context.panic(pp"Cannot find == for type ${tpe} in prelude!") }
686695

687696
// create joinpoint
697+
val tparams = patterns.flatMap { case (sc, p) => boundTypesInPattern(p) } ++ guards.flatMap(boundTypesInGuard)
688698
val params = patterns.flatMap { case (sc, p) => boundInPattern(p) } ++ guards.flatMap(boundInGuard)
689-
val joinpoint = Context.bind(TmpBlock(label), BlockLit(Nil, Nil, params, Nil, body))
699+
val joinpoint = Context.bind(TmpBlock(label), BlockLit(tparams, Nil, params, Nil, body))
690700

691701
def transformPattern(p: source.MatchPattern): Pattern = p match {
692702
case source.AnyPattern(id) =>
693703
Pattern.Any(id.symbol)
694-
case source.TagPattern(id, patterns) =>
695-
Pattern.Tag(id.symbol, patterns.map { p => (transformPattern(p), transform(Context.inferredTypeOf(p))) })
704+
case p @ source.TagPattern(id, patterns) =>
705+
val tparams = Context.annotation(Annotations.TypeParameters, p)
706+
Pattern.Tag(id.symbol, tparams, patterns.map { p => (transformPattern(p), transform(Context.inferredTypeOf(p))) })
696707
case source.IgnorePattern() =>
697708
Pattern.Ignore()
698709
case source.LiteralPattern(source.Literal(value, tpe)) =>
@@ -719,7 +730,7 @@ object Transformer extends Phase[Typechecked, CoreTransformed] {
719730
val transformedGuards = guards.flatMap(transformGuard)
720731
val conditions = if transformedPatterns.isEmpty then transformedGuards else Condition.Patterns(transformedPatterns) :: guards.flatMap(transformGuard)
721732

722-
Clause(conditions, joinpoint, params.map(p => core.ValueVar(p.id, p.tpe)))
733+
Clause(conditions, joinpoint, tparams.map(x => core.ValueType.Var(x)), params.map(p => core.ValueVar(p.id, p.tpe)))
723734
}
724735

725736
/**
@@ -785,7 +796,9 @@ object Transformer extends Phase[Typechecked, CoreTransformed] {
785796
DirectApp(BlockVar(f), targs, vargsT, bargsT)
786797
case r: Constructor =>
787798
if (bargs.nonEmpty) Context.abort("Constructors cannot take block arguments.")
788-
Make(core.ValueType.Data(r.tpe, targs), r, vargsT)
799+
val universals = targs.take(r.tpe.tparams.length)
800+
val existentials = targs.drop(r.tpe.tparams.length)
801+
Make(core.ValueType.Data(r.tpe, universals), r, existentials, vargsT)
789802
case f: Operation =>
790803
Context.panic("Should have been translated to a method call!")
791804
case f: Field =>

effekt/shared/src/main/scala/effekt/core/Tree.scala

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ enum Pure extends Expr {
191191
*
192192
* Note: the structure mirrors interface implementation
193193
*/
194-
case Make(data: ValueType.Data, tag: Id, vargs: List[Pure])
194+
case Make(data: ValueType.Data, tag: Id, targs: List[ValueType], vargs: List[Pure])
195195

196196
case Box(b: Block, annotatedCapture: Captures)
197197
}
@@ -578,7 +578,7 @@ object Variables {
578578
case Pure.ValueVar(id, annotatedType) => Variables.value(id, annotatedType)
579579
case Pure.Literal(value, annotatedType) => Variables.empty
580580
case Pure.PureApp(b, targs, vargs) => free(b) ++ all(vargs, free)
581-
case Pure.Make(data, tag, vargs) => all(vargs, free)
581+
case Pure.Make(data, tag, targs, vargs) => all(vargs, free)
582582
case Pure.Box(b, annotatedCapture) => free(b)
583583
}
584584

@@ -772,8 +772,8 @@ object substitutions {
772772
case Literal(value, annotatedType) =>
773773
Literal(value, substitute(annotatedType))
774774

775-
case Make(tpe, tag, vargs) =>
776-
Make(substitute(tpe).asInstanceOf, tag, vargs.map(substitute))
775+
case Make(tpe, tag, targs, vargs) =>
776+
Make(substitute(tpe).asInstanceOf, tag, targs.map(substitute), vargs.map(substitute))
777777

778778
case PureApp(f, targs, vargs) => substitute(f) match {
779779
case g : Block.BlockVar => PureApp(g, targs.map(substitute), vargs.map(substitute))

effekt/shared/src/main/scala/effekt/core/Type.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,7 @@ object Type {
252252
case Pure.ValueVar(id, tpe) => tpe
253253
case Pure.Literal(value, tpe) => tpe
254254
case Pure.PureApp(callee, targs, args) => instantiate(callee.functionType, targs, Nil).result
255-
case Pure.Make(tpe, tag, args) => tpe
255+
case Pure.Make(tpe, tag, targs, args) => tpe // TODO instantiate?
256256
case Pure.Box(block, capt) => ValueType.Boxed(block.tpe, capt)
257257
}
258258

effekt/shared/src/main/scala/effekt/core/optimizer/BindSubexpressions.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,8 +126,8 @@ object BindSubexpressions {
126126
case Pure.ValueVar(id, tpe) => pure(ValueVar(transform(id), transform(tpe)))
127127
case Pure.Literal(value, tpe) => pure(Pure.Literal(value, transform(tpe)))
128128

129-
case Pure.Make(data, tag, vargs) => transformExprs(vargs) { vs =>
130-
bind(Pure.Make(data, tag, vs))
129+
case Pure.Make(data, tag, targs, vargs) => transformExprs(vargs) { vs =>
130+
bind(Pure.Make(data, tag, targs, vs))
131131
}
132132
case DirectApp(f, targs, vargs, bargs) => for {
133133
vs <- transformExprs(vargs);

0 commit comments

Comments
 (0)