From 3cbf9cf597d3ac09a9d64bdb077456a129a24b7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonathan=20Immanuel=20Brachth=C3=A4user?= Date: Wed, 8 Jan 2025 23:45:19 +0100 Subject: [PATCH] Drop Select from core and add Run to CPS (#765) --- .../src/test/scala/effekt/core/VMTests.scala | 40 +++--------------- .../src/main/scala/effekt/core/Parser.scala | 7 ---- .../effekt/core/PolymorphismBoxing.scala | 41 ++----------------- .../scala/effekt/core/PrettyPrinter.scala | 2 - .../main/scala/effekt/core/Recursive.scala | 1 - .../main/scala/effekt/core/Transformer.scala | 29 ++++++++++++- .../src/main/scala/effekt/core/Tree.scala | 10 ----- .../src/main/scala/effekt/core/Type.scala | 1 - .../core/optimizer/BindSubexpressions.scala | 1 - .../effekt/core/optimizer/Normalizer.scala | 14 +++---- .../effekt/core/optimizer/Reachable.scala | 1 - .../core/optimizer/StaticArguments.scala | 1 - .../effekt/core/vm/Instrumentation.scala | 4 -- .../src/main/scala/effekt/core/vm/VM.scala | 21 ---------- .../main/scala/effekt/cps/Transformer.scala | 6 ++- .../src/main/scala/effekt/cps/Tree.scala | 6 --- .../effekt/generator/chez/Transformer.scala | 3 -- .../effekt/generator/js/TransformerCps.scala | 12 +++--- .../scala/effekt/machine/Transformer.scala | 11 ----- 19 files changed, 53 insertions(+), 158 deletions(-) diff --git a/effekt/jvm/src/test/scala/effekt/core/VMTests.scala b/effekt/jvm/src/test/scala/effekt/core/VMTests.scala index b7c316ddb..3fb2fd110 100644 --- a/effekt/jvm/src/test/scala/effekt/core/VMTests.scala +++ b/effekt/jvm/src/test/scala/effekt/core/VMTests.scala @@ -74,7 +74,6 @@ class VMTests extends munit.FunSuite { poppedFrames = counting.poppedFrames, allocations = counting.allocations, closures = counting.closures, - fieldLookups = counting.fieldLookups, variableReads = counting.variableReads, variableWrites = counting.variableWrites, resets = counting.resets, @@ -100,7 +99,6 @@ class VMTests extends munit.FunSuite { poppedFrames: Int, allocations: Int, closures: Int, - fieldLookups: Int, variableReads: Int, variableWrites: Int, resets: Int, @@ -247,7 +245,6 @@ class VMTests extends munit.FunSuite { poppedFrames = 34010, allocations = 0, closures = 100, - fieldLookups = 0, variableReads = 7132, variableWrites = 3157, resets = 0, @@ -264,7 +261,6 @@ class VMTests extends munit.FunSuite { poppedFrames = 4961, allocations = 34, closures = 0, - fieldLookups = 0, variableReads = 0, variableWrites = 0, resets = 0, @@ -281,7 +277,6 @@ class VMTests extends munit.FunSuite { poppedFrames = 117, allocations = 0, closures = 0, - fieldLookups = 0, variableReads = 70, variableWrites = 32, resets = 0, @@ -292,13 +287,12 @@ class VMTests extends munit.FunSuite { examplesDir / "benchmarks" / "are_we_fast_yet" / "nbody.effekt" -> Some(Summary( staticDispatches = 56, dynamicDispatches = 0, - patternMatches = 0, + patternMatches = 455, branches = 56, pushedFrames = 80, poppedFrames = 80, allocations = 31, closures = 0, - fieldLookups = 455, variableReads = 34, variableWrites = 30, resets = 0, @@ -315,7 +309,6 @@ class VMTests extends munit.FunSuite { poppedFrames = 3060, allocations = 0, closures = 0, - fieldLookups = 0, variableReads = 0, variableWrites = 0, resets = 113, @@ -332,7 +325,6 @@ class VMTests extends munit.FunSuite { poppedFrames = 51284, allocations = 0, closures = 0, - fieldLookups = 0, variableReads = 34546, variableWrites = 11738, resets = 0, @@ -349,7 +341,6 @@ class VMTests extends munit.FunSuite { poppedFrames = 65630, allocations = 8206, closures = 0, - fieldLookups = 0, variableReads = 41027, variableWrites = 8205, resets = 0, @@ -366,7 +357,6 @@ class VMTests extends munit.FunSuite { poppedFrames = 54797, allocations = 0, closures = 0, - fieldLookups = 0, variableReads = 32437, variableWrites = 13699, resets = 0, @@ -383,7 +373,6 @@ class VMTests extends munit.FunSuite { poppedFrames = 28674, allocations = 5461, closures = 0, - fieldLookups = 0, variableReads = 13654, variableWrites = 9557, resets = 0, @@ -402,7 +391,6 @@ class VMTests extends munit.FunSuite { poppedFrames = 6, allocations = 16, closures = 0, - fieldLookups = 0, variableReads = 0, variableWrites = 0, resets = 0, @@ -419,7 +407,6 @@ class VMTests extends munit.FunSuite { poppedFrames = 1, allocations = 0, closures = 0, - fieldLookups = 0, variableReads = 0, variableWrites = 0, resets = 0, @@ -436,7 +423,6 @@ class VMTests extends munit.FunSuite { poppedFrames = 15, allocations = 0, closures = 0, - fieldLookups = 0, variableReads = 0, variableWrites = 0, resets = 0, @@ -453,7 +439,6 @@ class VMTests extends munit.FunSuite { poppedFrames = 1, allocations = 0, closures = 0, - fieldLookups = 0, variableReads = 0, variableWrites = 0, resets = 0, @@ -470,7 +455,6 @@ class VMTests extends munit.FunSuite { poppedFrames = 7, allocations = 6, closures = 0, - fieldLookups = 0, variableReads = 0, variableWrites = 0, resets = 0, @@ -487,7 +471,6 @@ class VMTests extends munit.FunSuite { poppedFrames = 7, allocations = 6, closures = 0, - fieldLookups = 0, variableReads = 0, variableWrites = 0, resets = 0, @@ -504,7 +487,6 @@ class VMTests extends munit.FunSuite { poppedFrames = 12, allocations = 6, closures = 0, - fieldLookups = 0, variableReads = 0, variableWrites = 0, resets = 0, @@ -523,7 +505,6 @@ class VMTests extends munit.FunSuite { poppedFrames = 12, allocations = 0, closures = 0, - fieldLookups = 0, variableReads = 6, variableWrites = 5, resets = 0, @@ -540,7 +521,6 @@ class VMTests extends munit.FunSuite { poppedFrames = 14, allocations = 0, closures = 0, - fieldLookups = 0, variableReads = 7, variableWrites = 6, resets = 0, @@ -557,7 +537,6 @@ class VMTests extends munit.FunSuite { poppedFrames = 1409, allocations = 54, closures = 0, - fieldLookups = 0, variableReads = 0, variableWrites = 0, resets = 1, @@ -574,7 +553,6 @@ class VMTests extends munit.FunSuite { poppedFrames = 377, allocations = 0, closures = 0, - fieldLookups = 0, variableReads = 222, variableWrites = 88, resets = 1, @@ -591,7 +569,6 @@ class VMTests extends munit.FunSuite { poppedFrames = 1008, allocations = 1002, closures = 0, - fieldLookups = 0, variableReads = 0, variableWrites = 0, resets = 5, @@ -608,7 +585,6 @@ class VMTests extends munit.FunSuite { poppedFrames = 16001, allocations = 0, closures = 0, - fieldLookups = 0, variableReads = 0, variableWrites = 0, resets = 1000, @@ -625,7 +601,6 @@ class VMTests extends munit.FunSuite { poppedFrames = 9807, allocations = 2556, closures = 0, - fieldLookups = 0, variableReads = 2051, variableWrites = 1430, resets = 10, @@ -642,7 +617,6 @@ class VMTests extends munit.FunSuite { poppedFrames = 880, allocations = 4, closures = 0, - fieldLookups = 0, variableReads = 0, variableWrites = 0, resets = 1, @@ -655,13 +629,12 @@ class VMTests extends munit.FunSuite { examplesDir / "casestudies" / "ad.effekt.md" -> Some(Summary( staticDispatches = 19, dynamicDispatches = 335, - patternMatches = 0, + patternMatches = 706, branches = 285, pushedFrames = 453, poppedFrames = 453, allocations = 174, closures = 39, - fieldLookups = 706, variableReads = 0, variableWrites = 0, resets = 8, @@ -678,7 +651,6 @@ class VMTests extends munit.FunSuite { poppedFrames = 30, allocations = 15, closures = 36, - fieldLookups = 0, variableReads = 7, variableWrites = 3, resets = 9, @@ -695,7 +667,6 @@ class VMTests extends munit.FunSuite { poppedFrames = 106, allocations = 73, closures = 8, - fieldLookups = 0, variableReads = 29, variableWrites = 18, resets = 1, @@ -706,13 +677,12 @@ class VMTests extends munit.FunSuite { examplesDir / "casestudies" / "inference.effekt.md" -> Some(Summary( staticDispatches = 1457444, dynamicDispatches = 3201452, - patternMatches = 1474376, + patternMatches = 1474290, branches = 303298, - pushedFrames = 7574572, - poppedFrames = 6709277, + pushedFrames = 7574480, + poppedFrames = 6709185, allocations = 4626007, closures = 865541, - fieldLookups = 0, variableReads = 2908620, variableWrites = 1453663, resets = 288559, diff --git a/effekt/shared/src/main/scala/effekt/core/Parser.scala b/effekt/shared/src/main/scala/effekt/core/Parser.scala index 1c77732e0..b83fcd22f 100644 --- a/effekt/shared/src/main/scala/effekt/core/Parser.scala +++ b/effekt/shared/src/main/scala/effekt/core/Parser.scala @@ -165,13 +165,6 @@ class CoreParsers(positions: Positions, names: Names) extends EffektLexers(posit // Pure Expressions // ---------------- lazy val pure: P[Pure] = - pureNonAccess ~ many((`.` ~> id) ~ (`:` ~> valueType)) ^^ { - case firstTarget ~ accesses => accesses.foldLeft(firstTarget){ - case (target, field ~ tpe) => Pure.Select(target, field, tpe) - } - } - - lazy val pureNonAccess: P[Pure] = ( literal | id ~ (`:` ~> valueType) ^^ Pure.ValueVar.apply | `box` ~> captures ~ block ^^ { case capt ~ block => Pure.Box(block, capt) } diff --git a/effekt/shared/src/main/scala/effekt/core/PolymorphismBoxing.scala b/effekt/shared/src/main/scala/effekt/core/PolymorphismBoxing.scala index ee052bf1e..47daa1f58 100644 --- a/effekt/shared/src/main/scala/effekt/core/PolymorphismBoxing.scala +++ b/effekt/shared/src/main/scala/effekt/core/PolymorphismBoxing.scala @@ -48,19 +48,6 @@ object PolymorphismBoxing extends Phase[CoreTransformed, CoreTransformed] { def unbox(p: Pure) = Pure.PureApp(unboxFn, Nil, List(p)) } - /** - * Describes how to box/unbox values using records - * - * @param boxTpe The type BoxedT - * @param constructor The constructor to use for boxing - * @param field The field to access for unboxing - */ - case class RecordBoxer(boxTpe: ValueType.Data, constructor: Constructor, field: Field) extends Boxer { - def tpe = boxTpe - def box(p: Pure) = Pure.Make(boxTpe, constructor.id, List(p)) - def unbox(p: Pure) = Pure.Select(p, field.id, field.tpe) - } - /** * Partial function to describe which values to box and how. * Is defined iff values of the given type should be boxed. @@ -124,18 +111,10 @@ object PolymorphismBoxing extends Phase[CoreTransformed, CoreTransformed] { } Some(ExternFnBoxer(boxRet, box, unbox)) } - /** Try to find a `BoxedT` type */ - def findRecordBoxer() = boundary { - findRecord("Boxed" ++ name) match { - case Some(Declaration.Data(tpe, List(), List(cns@Constructor(id, List(field))))) => - Some(RecordBoxer(ValueType.Data(tpe, Nil), cns, field)) - case _ => None - } - } - findExternFnBoxer() orElse findRecordBoxer() getOrElse { + + findExternFnBoxer() getOrElse { Context.abort(s"Type ${name}, which needs to be boxed, is used as a type argument but no " + - s"corresponding pure externs box${name} and unbox${name} were defined in the prelude, " + - s"and also no record type Boxed${name}.") + s"corresponding pure externs box${name} and unbox${name} were defined in the prelude.") } } } @@ -379,20 +358,6 @@ object PolymorphismBoxing extends Phase[CoreTransformed, CoreTransformed] { val coercedArgs = (vargs zip paramTypes).map { case (arg, paramTpe) => coerce(transform(arg), paramTpe) } Pure.Make(transform(data), tag, coercedArgs) - case Pure.Select(target, field, annotatedType) => { - val (symbol, targs) = target.tpe match { - case ValueType.Data(symbol, targs) => (symbol, targs) - case t => Context.abort(s"Select on value of type ${PrettyPrinter.format(t)} is not supported.") - } - PContext.getData(symbol) match { - case Declaration.Data(id, tparams, List(Constructor(cns, fields))) => - val f = fields.find(_.id == field).getOrElse{ - Context.abort(s"${id} has no field ${field}.") - } - coerce(Pure.Select(target, field, transform(annotatedType)), Type.substitute(f.tpe, (tparams zip targs).toMap, Map())) - case t => Context.abort(s"Select on data type ${t.id} is not supported.") - } - } case Pure.Box(b, annotatedCapture) => Pure.Box(transform(b), annotatedCapture) } diff --git a/effekt/shared/src/main/scala/effekt/core/PrettyPrinter.scala b/effekt/shared/src/main/scala/effekt/core/PrettyPrinter.scala index 5d79369fd..8af77e6ea 100644 --- a/effekt/shared/src/main/scala/effekt/core/PrettyPrinter.scala +++ b/effekt/shared/src/main/scala/effekt/core/PrettyPrinter.scala @@ -102,8 +102,6 @@ object PrettyPrinter extends ParenPrettyPrinter { case Make(data, tag, vargs) => "make" <+> toDoc(data) <+> toDoc(tag) <> argsToDoc(Nil, vargs, Nil) case DirectApp(b, targs, vargs, bargs) => toDoc(b) <> argsToDoc(targs, vargs, bargs) - case Select(b, field, tpe) => toDoc(b) <> "." <> toDoc(field) - case Box(b, capt) => parens("box" <+> toDoc(b)) } diff --git a/effekt/shared/src/main/scala/effekt/core/Recursive.scala b/effekt/shared/src/main/scala/effekt/core/Recursive.scala index 898d84073..db0440581 100644 --- a/effekt/shared/src/main/scala/effekt/core/Recursive.scala +++ b/effekt/shared/src/main/scala/effekt/core/Recursive.scala @@ -92,7 +92,6 @@ class Recursive( case Pure.Literal(value, annotatedType) => () case Pure.PureApp(b, targs, vargs) => process(b); vargs.foreach(process) case Pure.Make(data, tag, vargs) => vargs.foreach(process) - case Pure.Select(target, field, annotatedType) => process(target) case Pure.Box(b, annotatedCapture) => process(b) } diff --git a/effekt/shared/src/main/scala/effekt/core/Transformer.scala b/effekt/shared/src/main/scala/effekt/core/Transformer.scala index 8b77feaf7..54c95ceed 100644 --- a/effekt/shared/src/main/scala/effekt/core/Transformer.scala +++ b/effekt/shared/src/main/scala/effekt/core/Transformer.scala @@ -337,8 +337,35 @@ object Transformer extends Phase[Typechecked, CoreTransformed] { case source.Literal(value, tpe) => Literal(value, transform(tpe)) + // [[ sc.field ]] = val x = sc match { tag: { (_, _, x, _) => return x } }; ... case s @ source.Select(receiver, selector) => - Select(transformAsPure(receiver), s.definition, transform(Context.inferredTypeOf(s))) + val field: Field = s.definition + + val constructor = field.constructor + val dataType: symbols.TypeConstructor = constructor.tpe + val universals: List[symbols.TypeParam] = dataType.tparams + + // allTypeParams = universals ++ existentials + val allTypeParams: List[symbols.TypeParam] = constructor.tparams + + assert(allTypeParams.length == universals.length, "Existentials on record selection not supported, yet.") + + val scrutineeTypeArgs = Context.inferredTypeOf(receiver) match { + case effekt.symbols.ValueType.ValueTypeApp(constructor, args) => args + case _ => Context.panic("Should not happen: selection from non ValueTypeApp") + } + + val substitution = Substitutions((universals zip scrutineeTypeArgs).toMap, Map.empty) + + val selected = Id("x") + val tpe = transform(Context.inferredTypeOf(s)) + val params = constructor.fields.map { + case f: Field => + val tpe = transform(substitution.substitute(f.returnType)) + core.ValueParam(if f == field then selected else Id("_"), tpe) + } + Context.bind(Stmt.Match(transformAsPure(receiver), + List((constructor, BlockLit(Nil, Nil, params, Nil, Stmt.Return(Pure.ValueVar(selected, tpe))))), None)) case source.Box(capt, block) => transformBox(block) diff --git a/effekt/shared/src/main/scala/effekt/core/Tree.scala b/effekt/shared/src/main/scala/effekt/core/Tree.scala index d413e11bf..bde32e984 100644 --- a/effekt/shared/src/main/scala/effekt/core/Tree.scala +++ b/effekt/shared/src/main/scala/effekt/core/Tree.scala @@ -171,7 +171,6 @@ case class DirectApp(b: Block.BlockVar, targs: List[ValueType], vargs: List[Pure * │─ [[ Literal ]] * │─ [[ PureApp ]] * │─ [[ Make ]] - * │─ [[ Select ]] * │─ [[ Box ]] * * ------------------------------------------- @@ -194,11 +193,6 @@ enum Pure extends Expr { */ case Make(data: ValueType.Data, tag: Id, vargs: List[Pure]) - /** - * Record Selection - */ - case Select(target: Pure, field: Id, annotatedType: ValueType) - case Box(b: Block, annotatedCapture: Captures) } export Pure.* @@ -581,7 +575,6 @@ object Variables { case Pure.Literal(value, annotatedType) => Variables.empty case Pure.PureApp(b, targs, vargs) => free(b) ++ all(vargs, free) case Pure.Make(data, tag, vargs) => all(vargs, free) - case Pure.Select(target, field, annotatedType) => free(target) case Pure.Box(b, annotatedCapture) => free(b) } @@ -782,9 +775,6 @@ object substitutions { case _ => INTERNAL_ERROR("Should never substitute a concrete block for an FFI function.") } - case Select(target, field, annotatedType) => - Select(substitute(target), field, substitute(annotatedType)) - case Box(b, annotatedCapture) => Box(substitute(b), substitute(annotatedCapture)) } diff --git a/effekt/shared/src/main/scala/effekt/core/Type.scala b/effekt/shared/src/main/scala/effekt/core/Type.scala index c03d72330..7f942e0b1 100644 --- a/effekt/shared/src/main/scala/effekt/core/Type.scala +++ b/effekt/shared/src/main/scala/effekt/core/Type.scala @@ -247,7 +247,6 @@ object Type { case Pure.Literal(value, tpe) => tpe case Pure.PureApp(callee, targs, args) => instantiate(callee.functionType, targs, Nil).result case Pure.Make(tpe, tag, args) => tpe - case Pure.Select(target, field, annotatedType) => annotatedType case Pure.Box(block, capt) => ValueType.Boxed(block.tpe, capt) } diff --git a/effekt/shared/src/main/scala/effekt/core/optimizer/BindSubexpressions.scala b/effekt/shared/src/main/scala/effekt/core/optimizer/BindSubexpressions.scala index e4964677d..6d14f51cc 100644 --- a/effekt/shared/src/main/scala/effekt/core/optimizer/BindSubexpressions.scala +++ b/effekt/shared/src/main/scala/effekt/core/optimizer/BindSubexpressions.scala @@ -138,7 +138,6 @@ object BindSubexpressions { vs <- transformExprs(vargs); res <- bind(Pure.PureApp(f, targs.map(transform), vs)) } yield res - case Pure.Select(target, field, tpe) => transform(target) { v => bind(Pure.Select(v, field, transform(tpe))) } case Pure.Box(block, capt) => transform(block) { b => bind(Pure.Box(b, transform(capt))) } } diff --git a/effekt/shared/src/main/scala/effekt/core/optimizer/Normalizer.scala b/effekt/shared/src/main/scala/effekt/core/optimizer/Normalizer.scala index 02f23c3c6..9855b9446 100644 --- a/effekt/shared/src/main/scala/effekt/core/optimizer/Normalizer.scala +++ b/effekt/shared/src/main/scala/effekt/core/optimizer/Normalizer.scala @@ -211,6 +211,11 @@ object Normalizer { normal => def normalizeVal(id: Id, tpe: ValueType, binding: Stmt, body: Stmt): Stmt = binding match { + // [[ val x = sc match { case id(ps) => body2 }; body ]] = sc match { case id(ps) => val x = body2; body } + case Stmt.Match(sc, List((id2, BlockLit(tparams2, cparams2, vparams2, bparams2, body2))), None) => + Stmt.Match(sc, List((id2, BlockLit(tparams2, cparams2, vparams2, bparams2, + normalizeVal(id, tpe, body2, body)))), None) + // [[ val x = return e; s ]] = let x = [[ e ]]; [[ s ]] case Stmt.Return(expr2) => Stmt.Let(id, tpe, expr2, normalize(body)(using C.bind(id, expr2))) @@ -283,15 +288,6 @@ object Normalizer { normal => } def normalize(p: Pure)(using ctx: Context): Pure = p match { - // [[ Constructor(f = v).f ]] = [[ v ]] - case Pure.Select(target, field, annotatedType) => active(target) match { - case Pure.Make(datatype, tag, fields) => - val constructor = ctx.decls.findConstructor(tag).get - val expr = (constructor.fields zip fields).collectFirst { case (f, expr) if f.id == field => expr }.get - normalize(expr) - case _ => Pure.Select(normalize(target), field, annotatedType) - } - // [[ box (unbox e) ]] = [[ e ]] case Pure.Box(b, annotatedCapture) => active(b) match { case NormalizedBlock.Known(Unbox(p), boundBy) => p diff --git a/effekt/shared/src/main/scala/effekt/core/optimizer/Reachable.scala b/effekt/shared/src/main/scala/effekt/core/optimizer/Reachable.scala index dc5aab2f6..fb5c753f8 100644 --- a/effekt/shared/src/main/scala/effekt/core/optimizer/Reachable.scala +++ b/effekt/shared/src/main/scala/effekt/core/optimizer/Reachable.scala @@ -110,7 +110,6 @@ class Reachable( case Pure.Literal(value, annotatedType) => () case Pure.PureApp(b, targs, vargs) => process(b); vargs.foreach(process) case Pure.Make(data, tag, vargs) => process(tag); vargs.foreach(process) - case Pure.Select(target, field, annotatedType) => process(field); process(target) case Pure.Box(b, annotatedCapture) => process(b) } diff --git a/effekt/shared/src/main/scala/effekt/core/optimizer/StaticArguments.scala b/effekt/shared/src/main/scala/effekt/core/optimizer/StaticArguments.scala index c6729192b..9e3e0ce06 100644 --- a/effekt/shared/src/main/scala/effekt/core/optimizer/StaticArguments.scala +++ b/effekt/shared/src/main/scala/effekt/core/optimizer/StaticArguments.scala @@ -190,7 +190,6 @@ object StaticArguments { // congruences case Pure.Literal(value, annotatedType) => p - case Pure.Select(target, field, annotatedType) => Pure.Select(rewrite(target), field, annotatedType) case Pure.Box(b, annotatedCapture) => Pure.Box(rewrite(b), annotatedCapture) } diff --git a/effekt/shared/src/main/scala/effekt/core/vm/Instrumentation.scala b/effekt/shared/src/main/scala/effekt/core/vm/Instrumentation.scala index 31f89ab3e..341a503e3 100644 --- a/effekt/shared/src/main/scala/effekt/core/vm/Instrumentation.scala +++ b/effekt/shared/src/main/scala/effekt/core/vm/Instrumentation.scala @@ -11,7 +11,6 @@ trait Instrumentation { def popFrame(): Unit = () def allocate(v: Value.Data): Unit = () def closure(): Unit = () - def fieldLookup(id: Id): Unit = () def step(state: State): Unit = () def readMutableVariable(id: Id): Unit = () def writeMutableVariable(id: Id): Unit = () @@ -34,7 +33,6 @@ class Counting extends Instrumentation { var poppedFrames = 0 var allocations = 0 var closures = 0 - var fieldLookups = 0 var variableReads = 0 var variableWrites = 0 @@ -50,7 +48,6 @@ class Counting extends Instrumentation { override def popFrame(): Unit = poppedFrames += 1 override def allocate(v: Value.Data): Unit = allocations += 1 override def closure(): Unit = closures += 1 - override def fieldLookup(id: Id): Unit = fieldLookups += 1 override def readMutableVariable(id: Id): Unit = variableReads += 1 override def writeMutableVariable(id: Id): Unit = variableWrites += 1 override def reset(): Unit = resets += 1 @@ -65,7 +62,6 @@ class Counting extends Instrumentation { println(s"Frames (pushed: ${pushedFrames}, popped: ${poppedFrames})") println(s"Allocations: ${allocations}") println(s"Closures: ${closures}") - println(s"Field lookups: ${fieldLookups}") println(s"Variable reads: ${variableReads}") println(s"Variable writes: ${variableWrites}") println(s"Installed delimiters: ${resets}") diff --git a/effekt/shared/src/main/scala/effekt/core/vm/VM.scala b/effekt/shared/src/main/scala/effekt/core/vm/VM.scala index 60e32311b..82f7799ae 100644 --- a/effekt/shared/src/main/scala/effekt/core/vm/VM.scala +++ b/effekt/shared/src/main/scala/effekt/core/vm/VM.scala @@ -511,27 +511,6 @@ class Interpreter(instrumentation: Instrumentation, runtime: Runtime) { val result: Value.Data = Value.Data(data, tag, vargs.map(a => eval(a, env))) instrumentation.allocate(result) result - case Pure.Select(target, field, annotatedType) => - @tailrec - def declarations(env: Env): List[Declaration] = env match { - case Env.Top(functions, builtins, toplevel, declarations) => declarations - case Env.Static(id, block, rest) => declarations(rest) - case Env.Dynamic(id, block, rest) => declarations(rest) - case Env.Let(id, value, rest) => declarations(rest) - } - val decls = DeclarationContext(declarations(env), Nil) - - // TODO clean this mess up! - val fieldSymbol = decls.findField(field).getOrElse(???) - val constrSymbol = decls.findConstructor(fieldSymbol).getOrElse(???) - val index = constrSymbol.fields.indexOf(fieldSymbol) - - instrumentation.fieldLookup(field) - - eval(target, env) match { - case Value.Data(data, tag, fields) => fields(index) - case _ => ??? - } case Pure.Box(b, annotatedCapture) => Value.Boxed(eval(b, env)) } diff --git a/effekt/shared/src/main/scala/effekt/cps/Transformer.scala b/effekt/shared/src/main/scala/effekt/cps/Transformer.scala index 3f2422fe5..95ac72ae9 100644 --- a/effekt/shared/src/main/scala/effekt/cps/Transformer.scala +++ b/effekt/shared/src/main/scala/effekt/cps/Transformer.scala @@ -89,6 +89,11 @@ object Transformer { If(transform(cond), transform(thn, ks, k2), transform(els, ks, k2)) } + case core.Stmt.Match(scrutinee, List((id, rhs)), None) => + Match( + transform(scrutinee), + List((id, transformClause(rhs, ks, k))), None) + case core.Stmt.Match(scrutinee, clauses, default) => withJoinpoint(k) { k => Match( @@ -179,7 +184,6 @@ object Transformer { case _ => sys error "Should not happen" } case core.Pure.Make(data, tag, vargs) => Make(data, tag, vargs.map(transform)) - case core.Pure.Select(target, field, annotatedType) => Select(transform(target), field) case core.Pure.Box(b, annotatedCapture) => Box(transform(b)) } diff --git a/effekt/shared/src/main/scala/effekt/cps/Tree.scala b/effekt/shared/src/main/scala/effekt/cps/Tree.scala index 774a6a4f2..8fa44c7dd 100644 --- a/effekt/shared/src/main/scala/effekt/cps/Tree.scala +++ b/effekt/shared/src/main/scala/effekt/cps/Tree.scala @@ -81,11 +81,6 @@ enum Pure extends Expr { case Make(data: ValueType.Data, tag: Id, vargs: List[Pure]) - /** - * Record Selection - */ - case Select(target: Pure, field: Id) - case Box(b: Block) } export Pure.* @@ -182,7 +177,6 @@ object Variables { case Pure.Literal(value) => empty case Pure.PureApp(id, vargs) => block(id) ++ all(vargs, free) case Pure.Make(data, tag, vargs) => all(vargs, free) - case Pure.Select(target, field) => free(target) case Pure.Box(b) => free(b) } diff --git a/effekt/shared/src/main/scala/effekt/generator/chez/Transformer.scala b/effekt/shared/src/main/scala/effekt/generator/chez/Transformer.scala index f72d6d35e..bbf30582b 100644 --- a/effekt/shared/src/main/scala/effekt/generator/chez/Transformer.scala +++ b/effekt/shared/src/main/scala/effekt/generator/chez/Transformer.scala @@ -217,9 +217,6 @@ trait Transformer { case PureApp(b, targs, args) => chez.Call(toChez(b), args map toChez) case Make(data, tag, args) => chez.Call(chez.Variable(nameRef(tag)), args map toChez) - case Select(b, field, _) => - chez.Call(nameRef(field), toChez(b)) - case Box(b, _) => toChez(b) } diff --git a/effekt/shared/src/main/scala/effekt/generator/js/TransformerCps.scala b/effekt/shared/src/main/scala/effekt/generator/js/TransformerCps.scala index a796cd5bb..7f1d7e09b 100644 --- a/effekt/shared/src/main/scala/effekt/generator/js/TransformerCps.scala +++ b/effekt/shared/src/main/scala/effekt/generator/js/TransformerCps.scala @@ -161,7 +161,6 @@ object TransformerCps extends Transformer { case DirectApp(id, vargs, bargs) => js.Call(nameRef(id), vargs.map(toJS) ++ bargs.map(toJS)) case Pure.PureApp(id, vargs) => inlineExtern(id, vargs) case Pure.Make(data, tag, vargs) => js.New(nameRef(tag), vargs map toJS) - case Pure.Select(target, field) => js.Member(toJS(target), memberNameRef(field)) case Pure.Box(b) => toJS(b) } @@ -190,14 +189,17 @@ object TransformerCps extends Transformer { case cps.Stmt.Match(sc, List((tag, clause)), None) => val scrutinee = toJS(sc) val (_, stmts) = toJS(scrutinee, tag, clause) - pure(js.MaybeBlock(stmts)) + stmts // (function () { switch (sc.tag) { case 0: return f17.apply(null, sc.data) } case cps.Stmt.Match(sc, clauses, default) => val scrutinee = toJS(sc) pure(js.Switch(js.Member(scrutinee, `tag`), - clauses.map { case (tag, clause) => toJS(scrutinee, tag, clause) }, + clauses.map { case (tag, clause) => + val (e, binding) = toJS(scrutinee, tag, clause); + (e, binding.stmts) + }, default.map { s => toJS(s).stmts })) case cps.Stmt.Jump(k, arg, ks) => @@ -265,7 +267,7 @@ object TransformerCps extends Transformer { pure(js.Return($effekt.call("hole"))) } - def toJS(scrutinee: js.Expr, variant: Id, clause: cps.Clause)(using C: TransformerContext): (js.Expr, List[js.Stmt]) = + def toJS(scrutinee: js.Expr, variant: Id, clause: cps.Clause)(using C: TransformerContext): (js.Expr, Binding[js.Stmt]) = clause match { case cps.Clause(vparams, body) => val fields = C.declarations.getConstructor(variant).fields.map(_.id) @@ -278,7 +280,7 @@ object TransformerCps extends Transformer { js.Const(nameDef(p), js.Member(scrutinee, memberNameRef(f))) } - (tag, extractedFields ++ toJS(body).stmts) + (tag, Binding { k => extractedFields ++ toJS(body).run(k) }) } def toJS(d: cps.Def)(using T: TransformerContext): js.Stmt = d match { diff --git a/effekt/shared/src/main/scala/effekt/machine/Transformer.scala b/effekt/shared/src/main/scala/effekt/machine/Transformer.scala index 798d6ced2..1002896c9 100644 --- a/effekt/shared/src/main/scala/effekt/machine/Transformer.scala +++ b/effekt/shared/src/main/scala/effekt/machine/Transformer.scala @@ -425,17 +425,6 @@ object Transformer { } } - case core.Select(target, field, tpe) if DeclarationContext.findField(field).isDefined => - // TODO all of this can go away, if we desugar records in the translation to core! - val fields = DeclarationContext.getField(field).constructor.fields - val fieldIndex = fields.indexWhere(_.id == field) - val variables = fields.map { f => Variable(freshName("select"), transform(f.tpe)) } - transform(target).flatMap { value => - Binding { k => - Switch(value, List(0 -> Clause(variables, k(variables(fieldIndex)))), None) - } - } - case core.Box(block, annot) => transformBlockArg(block).flatMap { unboxed => Binding { k =>