From a8972540348a98fddee6b9fba9cb0db924322ce5 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Thu, 17 Nov 2022 09:52:15 +0100 Subject: [PATCH 1/2] Upgrade implicits in Interpreter * Use `using` for `Env` parameters and arguments * Remove unnecessary `Env` parameters --- .../dotty/tools/dotc/quoted/Interpreter.scala | 35 ++++++++++--------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/quoted/Interpreter.scala b/compiler/src/dotty/tools/dotc/quoted/Interpreter.scala index 6c3d03fad4ca..3b226cd08a39 100644 --- a/compiler/src/dotty/tools/dotc/quoted/Interpreter.scala +++ b/compiler/src/dotty/tools/dotc/quoted/Interpreter.scala @@ -36,14 +36,17 @@ abstract class Interpreter(pos: SrcPos, classLoader: ClassLoader)(using Context) import Interpreter._ import tpd._ + /** Local variable environment */ type Env = Map[Symbol, Object] + def emptyEnv: Env = Map.empty + inline def env(using e: Env): e.type = e /** Returns the result of interpreting the code in the tree. * Return Some of the result or None if the result type is not consistent with the expected type. * Throws a StopInterpretation if the tree could not be interpreted or a runtime exception ocurred. */ - final def interpret[T](tree: Tree)(implicit ct: ClassTag[T]): Option[T] = - interpretTree(tree)(Map.empty) match { + final def interpret[T](tree: Tree)(using ct: ClassTag[T]): Option[T] = + interpretTree(tree)(using emptyEnv) match { case obj: T => Some(obj) case obj => // TODO upgrade to a full type tag check or something similar @@ -54,7 +57,7 @@ abstract class Interpreter(pos: SrcPos, classLoader: ClassLoader)(using Context) /** Returns the result of interpreting the code in the tree. * Throws a StopInterpretation if the tree could not be interpreted or a runtime exception ocurred. */ - protected def interpretTree(tree: Tree)(implicit env: Env): Object = tree match { + protected def interpretTree(tree: Tree)(using Env): Object = tree match { case Literal(Constant(value)) => interpretLiteral(value) @@ -136,26 +139,26 @@ abstract class Interpreter(pos: SrcPos, classLoader: ClassLoader)(using Context) Nil } - private def interpretBlock(stats: List[Tree], expr: Tree)(implicit env: Env) = { + private def interpretBlock(stats: List[Tree], expr: Tree)(using Env) = { var unexpected: Option[Object] = None - val newEnv = stats.foldLeft(env)((accEnv, stat) => stat match { + val newEnv = stats.foldLeft(env)((accEnv, stat) => stat match case stat: ValDef => - accEnv.updated(stat.symbol, interpretTree(stat.rhs)(accEnv)) + accEnv.updated(stat.symbol, interpretTree(stat.rhs)(using accEnv)) case stat => if (unexpected.isEmpty) unexpected = Some(unexpectedTree(stat)) accEnv - }) - unexpected.getOrElse(interpretTree(expr)(newEnv)) + ) + unexpected.getOrElse(interpretTree(expr)(using newEnv)) } - private def interpretLiteral(value: Any)(implicit env: Env): Object = + private def interpretLiteral(value: Any): Object = value.asInstanceOf[Object] - private def interpretVarargs(args: List[Object])(implicit env: Env): Object = + private def interpretVarargs(args: List[Object]): Object = args.toSeq - private def interpretedStaticMethodCall(moduleClass: Symbol, fn: Symbol)(implicit env: Env): List[Object] => Object = { + private def interpretedStaticMethodCall(moduleClass: Symbol, fn: Symbol): List[Object] => Object = { val (inst, clazz) = try if (moduleClass.name.startsWith(str.REPL_SESSION_LINE)) @@ -175,22 +178,22 @@ abstract class Interpreter(pos: SrcPos, classLoader: ClassLoader)(using Context) (args: List[Object]) => stopIfRuntimeException(method.invoke(inst, args: _*), method) } - private def interpretedStaticFieldAccess(sym: Symbol)(implicit env: Env): Object = { + private def interpretedStaticFieldAccess(sym: Symbol): Object = { val clazz = loadClass(sym.owner.fullName.toString) val field = clazz.getField(sym.name.toString) field.get(null) } - private def interpretModuleAccess(fn: Symbol)(implicit env: Env): Object = + private def interpretModuleAccess(fn: Symbol): Object = loadModule(fn.moduleClass) - private def interpretNew(fn: Symbol, args: => List[Object])(implicit env: Env): Object = { + private def interpretNew(fn: Symbol, args: => List[Object]): Object = { val clazz = loadClass(fn.owner.fullName.toString) val constr = clazz.getConstructor(paramsSig(fn): _*) constr.newInstance(args: _*).asInstanceOf[Object] } - private def unexpectedTree(tree: Tree)(implicit env: Env): Object = + private def unexpectedTree(tree: Tree): Object = throw new StopInterpretation(em"Unexpected tree could not be interpreted: ${tree.toString}", tree.srcPos) private def loadModule(sym: Symbol): Object = @@ -210,7 +213,7 @@ abstract class Interpreter(pos: SrcPos, classLoader: ClassLoader)(using Context) clazz.getConstructor().newInstance().asInstanceOf[Object] } - private def loadReplLineClass(moduleClass: Symbol)(implicit env: Env): Class[?] = { + private def loadReplLineClass(moduleClass: Symbol): Class[?] = { val lineClassloader = new AbstractFileClassLoader(ctx.settings.outputDir.value, classLoader) lineClassloader.loadClass(moduleClass.name.firstPart.toString) } From 16488eb6e35be42c211334fb248773f2a7194df7 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Thu, 17 Nov 2022 09:56:16 +0100 Subject: [PATCH 2/2] Remove unnecessary lambda from Interpreter --- compiler/src/dotty/tools/dotc/quoted/Interpreter.scala | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/quoted/Interpreter.scala b/compiler/src/dotty/tools/dotc/quoted/Interpreter.scala index 3b226cd08a39..8fb59c8d9df8 100644 --- a/compiler/src/dotty/tools/dotc/quoted/Interpreter.scala +++ b/compiler/src/dotty/tools/dotc/quoted/Interpreter.scala @@ -73,8 +73,7 @@ abstract class Interpreter(pos: SrcPos, classLoader: ClassLoader)(using Context) else if (fn.symbol.is(Module)) interpretModuleAccess(fn.symbol) else if (fn.symbol.is(Method) && fn.symbol.isStatic) { - val staticMethodCall = interpretedStaticMethodCall(fn.symbol.owner, fn.symbol) - staticMethodCall(interpretArgs(args, fn.symbol.info)) + interpretedStaticMethodCall(fn.symbol.owner, fn.symbol, interpretArgs(args, fn.symbol.info)) } else if fn.symbol.isStatic then assert(args.isEmpty) @@ -83,8 +82,7 @@ abstract class Interpreter(pos: SrcPos, classLoader: ClassLoader)(using Context) if (fn.name == nme.asInstanceOfPM) interpretModuleAccess(fn.qualifier.symbol) else { - val staticMethodCall = interpretedStaticMethodCall(fn.qualifier.symbol.moduleClass, fn.symbol) - staticMethodCall(interpretArgs(args, fn.symbol.info)) + interpretedStaticMethodCall(fn.qualifier.symbol.moduleClass, fn.symbol, interpretArgs(args, fn.symbol.info)) } else if (env.contains(fn.symbol)) env(fn.symbol) @@ -158,7 +156,7 @@ abstract class Interpreter(pos: SrcPos, classLoader: ClassLoader)(using Context) private def interpretVarargs(args: List[Object]): Object = args.toSeq - private def interpretedStaticMethodCall(moduleClass: Symbol, fn: Symbol): List[Object] => Object = { + private def interpretedStaticMethodCall(moduleClass: Symbol, fn: Symbol, args: List[Object]): Object = { val (inst, clazz) = try if (moduleClass.name.startsWith(str.REPL_SESSION_LINE)) @@ -175,7 +173,7 @@ abstract class Interpreter(pos: SrcPos, classLoader: ClassLoader)(using Context) val name = fn.name.asTermName val method = getMethod(clazz, name, paramsSig(fn)) - (args: List[Object]) => stopIfRuntimeException(method.invoke(inst, args: _*), method) + stopIfRuntimeException(method.invoke(inst, args: _*), method) } private def interpretedStaticFieldAccess(sym: Symbol): Object = {