diff --git a/compiler/src/dotty/tools/dotc/tastyreflect/SymbolOpsImpl.scala b/compiler/src/dotty/tools/dotc/tastyreflect/SymbolOpsImpl.scala new file mode 100644 index 000000000000..ae87bcc16b25 --- /dev/null +++ b/compiler/src/dotty/tools/dotc/tastyreflect/SymbolOpsImpl.scala @@ -0,0 +1,14 @@ +package dotty.tools.dotc.tastyreflect + +import dotty.tools.dotc.core.Symbols._ + +trait SymbolOpsImpl extends scala.tasty.reflect.SymbolOps with TastyCoreImpl { + + def SymbolDeco(symbol: Symbol): SymbolAPI = new SymbolAPI { + def isEmpty: Boolean = symbol eq NoSymbol + def localContext(implicit ctx: Context): Context = ctx.withOwner(symbol) + def tree(implicit ctx: Context): Option[Definition] = + if (isEmpty) None else Some(FromSymbol.definitionFromSym(symbol)) + } + +} diff --git a/compiler/src/dotty/tools/dotc/tastyreflect/TastyCoreImpl.scala b/compiler/src/dotty/tools/dotc/tastyreflect/TastyCoreImpl.scala index 38e2533ae9b6..1db73141ad25 100644 --- a/compiler/src/dotty/tools/dotc/tastyreflect/TastyCoreImpl.scala +++ b/compiler/src/dotty/tools/dotc/tastyreflect/TastyCoreImpl.scala @@ -50,5 +50,7 @@ trait TastyCoreImpl extends scala.tasty.reflect.TastyCore { type Position = util.SourcePosition type Constant = Constants.Constant - + + type Symbol = core.Symbols.Symbol + } diff --git a/compiler/src/dotty/tools/dotc/tastyreflect/TastyImpl.scala b/compiler/src/dotty/tools/dotc/tastyreflect/TastyImpl.scala index 454208329706..3ceb2f4fb086 100644 --- a/compiler/src/dotty/tools/dotc/tastyreflect/TastyImpl.scala +++ b/compiler/src/dotty/tools/dotc/tastyreflect/TastyImpl.scala @@ -2,4 +2,21 @@ package dotty.tools.dotc.tastyreflect import dotty.tools.dotc.core._ -class TastyImpl(val rootContext: Contexts.Context) extends scala.tasty.Tasty with TastyCoreImpl with CaseDefOpsImpl with ConstantOpsImpl with ContextOpsImpl with IdOpsImpl with ImportSelectorOpsImpl with QuotedOpsImpl with PatternOpsImpl with PositionOpsImpl with PrintersImpl with SignatureOpsImpl with StandardDefinitions with TreeOpsImpl with TypeOrBoundsTreesOpsImpl with TypeOrBoundsOpsImpl +class TastyImpl(val rootContext: Contexts.Context) + extends scala.tasty.Tasty + with TastyCoreImpl + with CaseDefOpsImpl + with ConstantOpsImpl + with ContextOpsImpl + with IdOpsImpl + with ImportSelectorOpsImpl + with QuotedOpsImpl + with PatternOpsImpl + with PositionOpsImpl + with PrintersImpl + with SignatureOpsImpl + with StandardDefinitions + with SymbolOpsImpl + with TreeOpsImpl + with TypeOrBoundsTreesOpsImpl + with TypeOrBoundsOpsImpl diff --git a/compiler/src/dotty/tools/dotc/tastyreflect/TreeOpsImpl.scala b/compiler/src/dotty/tools/dotc/tastyreflect/TreeOpsImpl.scala index 7ff0fe7d86f7..d0ec292aec85 100644 --- a/compiler/src/dotty/tools/dotc/tastyreflect/TreeOpsImpl.scala +++ b/compiler/src/dotty/tools/dotc/tastyreflect/TreeOpsImpl.scala @@ -13,6 +13,8 @@ trait TreeOpsImpl extends scala.tasty.reflect.TreeOps with TastyCoreImpl with He def TreeDeco(tree: Tree): TreeAPI = new TreeAPI { def pos(implicit ctx: Context): Position = tree.pos + def symbol(implicit ctx: Context): Symbol = tree.symbol + } object IsPackageClause extends IsPackageClauseExtractor { @@ -30,7 +32,7 @@ trait TreeOpsImpl extends scala.tasty.reflect.TreeOps with TastyCoreImpl with He } def PackageClauseDeco(pack: PackageClause): PackageClauseAPI = new PackageClauseAPI { - def definition(implicit ctx: Context): Definition = packageDefFromSym(pack.symbol) + } // ----- Statements ----------------------------------------------- diff --git a/library/src/scala/tasty/Tasty.scala b/library/src/scala/tasty/Tasty.scala index 44da7b06be38..ab5a0047ddf7 100644 --- a/library/src/scala/tasty/Tasty.scala +++ b/library/src/scala/tasty/Tasty.scala @@ -2,4 +2,20 @@ package scala.tasty import scala.tasty.reflect._ -abstract class Tasty extends TastyCore with CaseDefOps with ConstantOps with ContextOps with IdOps with ImportSelectorOps with QuotedOps with PatternOps with PositionOps with Printers with SignatureOps with StandardDefinitions with TreeOps with TypeOrBoundsTreeOps with TypeOrBoundsOps +abstract class Tasty + extends TastyCore + with CaseDefOps + with ConstantOps + with ContextOps + with IdOps + with ImportSelectorOps + with QuotedOps + with PatternOps + with PositionOps + with Printers + with SignatureOps + with StandardDefinitions + with SymbolOps + with TreeOps + with TypeOrBoundsTreeOps + with TypeOrBoundsOps diff --git a/library/src/scala/tasty/reflect/SymbolOps.scala b/library/src/scala/tasty/reflect/SymbolOps.scala new file mode 100644 index 000000000000..0ddbd73ba8b1 --- /dev/null +++ b/library/src/scala/tasty/reflect/SymbolOps.scala @@ -0,0 +1,14 @@ +package scala.tasty +package reflect + +/** Tasty reflect symbol */ +trait SymbolOps extends TastyCore { + + trait SymbolAPI { + def isEmpty: Boolean + def localContext(implicit ctx: Context): Context + def tree(implicit ctx: Context): Option[Definition] + } + implicit def SymbolDeco(symbol: Symbol): SymbolAPI + +} diff --git a/library/src/scala/tasty/reflect/TastyCore.scala b/library/src/scala/tasty/reflect/TastyCore.scala index 7cecaf235e77..27391693506b 100644 --- a/library/src/scala/tasty/reflect/TastyCore.scala +++ b/library/src/scala/tasty/reflect/TastyCore.scala @@ -96,6 +96,8 @@ package scala.tasty.reflect * * +- Constant * + * +- Symbol + * * ``` */ trait TastyCore { @@ -158,4 +160,9 @@ trait TastyCore { /** Constant value represented as the constant itself */ type Constant + /** Symbol of a definition. + * Then can be compared with == to know if the definition is the same. + */ + type Symbol + } diff --git a/library/src/scala/tasty/reflect/TreeOps.scala b/library/src/scala/tasty/reflect/TreeOps.scala index 28668323cfe5..253c134859a3 100644 --- a/library/src/scala/tasty/reflect/TreeOps.scala +++ b/library/src/scala/tasty/reflect/TreeOps.scala @@ -5,6 +5,7 @@ trait TreeOps extends TastyCore { trait TreeAPI { def pos(implicit ctx: Context): Position + def symbol(implicit ctx: Context): Symbol } implicit def TreeDeco(tree: Tree): TreeAPI @@ -19,7 +20,7 @@ trait TreeOps extends TastyCore { } trait PackageClauseAPI { - def definition(implicit ctx: Context): Definition + } implicit def PackageClauseDeco(pack: PackageClause): PackageClauseAPI diff --git a/library/src/scala/tasty/util/TreeAccumulator.scala b/library/src/scala/tasty/util/TreeAccumulator.scala index 975efbca9230..a2648d9daa69 100644 --- a/library/src/scala/tasty/util/TreeAccumulator.scala +++ b/library/src/scala/tasty/util/TreeAccumulator.scala @@ -18,7 +18,7 @@ abstract class TreeAccumulator[X, T <: Tasty with Singleton](val tasty: T) { private def foldParents(x: X, trees: Iterable[Parent])(implicit ctx: Context): X = (x /: trees)(foldOverParent) def foldOverTree(x: X, tree: Tree)(implicit ctx: Context): X = { - def localCtx(definition: Definition): Context = definition.localContext + def localCtx(definition: Definition): Context = definition.symbol.localContext tree match { case Term.Ident(_) => x @@ -74,7 +74,7 @@ abstract class TreeAccumulator[X, T <: Tasty with Singleton](val tasty: T) { case Import(expr, selectors) => foldTree(x, expr) case IsPackageClause(clause @ PackageClause(pid, stats)) => - foldTrees(foldTree(x, pid), stats)(localCtx(clause.definition)) + foldTrees(foldTree(x, pid), stats)(clause.symbol.localContext) } } diff --git a/project/scripts/cmdTests b/project/scripts/cmdTests index 1933812f2c17..21473b2c3c7b 100755 --- a/project/scripts/cmdTests +++ b/project/scripts/cmdTests @@ -50,7 +50,7 @@ clear_out "$OUT" grep -qe "def main(args: scala.Array\[scala.Predef.String\]): scala.Unit =" "$tmp" echo "testing scala.quoted.Expr.run from sbt dotr" -"$SBT" ";dotty-compiler-bootstrapped/dotc -with-compiler tests/run-with-compiler/quote-run.scala; dotty-compiler-bootstrapped/dotr -with-compiler Test" > "$tmp" +"$SBT" ";dotty-compiler-bootstrapped/dotc tests/run-with-compiler/quote-run.scala; dotty-compiler-bootstrapped/dotr -with-compiler Test" > "$tmp" grep -qe "val a: scala.Int = 3" "$tmp" diff --git a/tests/run/tasty-definitions.check b/tests/run/tasty-definitions-1.check similarity index 100% rename from tests/run/tasty-definitions.check rename to tests/run/tasty-definitions-1.check diff --git a/tests/run/tasty-definitions/quoted_1.scala b/tests/run/tasty-definitions-1/quoted_1.scala similarity index 100% rename from tests/run/tasty-definitions/quoted_1.scala rename to tests/run/tasty-definitions-1/quoted_1.scala diff --git a/tests/run/tasty-definitions/quoted_2.scala b/tests/run/tasty-definitions-1/quoted_2.scala similarity index 100% rename from tests/run/tasty-definitions/quoted_2.scala rename to tests/run/tasty-definitions-1/quoted_2.scala diff --git a/tests/run/tasty-definitions-2.check b/tests/run/tasty-definitions-2.check new file mode 100644 index 000000000000..e92423eea1ca --- /dev/null +++ b/tests/run/tasty-definitions-2.check @@ -0,0 +1,2 @@ +DefDef("foo", Nil, Nil, TypeTree.Synthetic(), None) +ValDef("bar", TypeTree.Synthetic(), None) diff --git a/tests/run/tasty-definitions-2/Macro_1.scala b/tests/run/tasty-definitions-2/Macro_1.scala new file mode 100644 index 000000000000..cc4870d39e62 --- /dev/null +++ b/tests/run/tasty-definitions-2/Macro_1.scala @@ -0,0 +1,23 @@ +import scala.quoted._ +import scala.tasty._ + +object Foo { + + transparent def inspectBody(i: => Int): String = + ~inspectBodyImpl('(i))(TopLevelSplice.tastyContext) // FIXME infer TopLevelSplice.tastyContext within top level ~ + + def inspectBodyImpl(x: Expr[Int])(implicit tasty: Tasty): Expr[String] = { + import tasty._ + def definitionString(tree: Tree): Expr[String] = tree.symbol.tree match { + case Some(definition) => definition.show.toExpr + case None => '("NO DEFINTION") + } + x.toTasty match { + case Term.Inlined(None, Nil, arg) => definitionString(arg) + case arg => definitionString(arg) // TODO should all by name parameters be in an inline node? + } + } + + def foo: Int = 1 + 2 + val bar: Int = 2 + 3 +} diff --git a/tests/run/tasty-definitions-2/Test_2.scala b/tests/run/tasty-definitions-2/Test_2.scala new file mode 100644 index 000000000000..323560068029 --- /dev/null +++ b/tests/run/tasty-definitions-2/Test_2.scala @@ -0,0 +1,6 @@ +object Test { + def main(args: Array[String]): Unit = { + println(Foo.inspectBody(Foo.foo)) + println(Foo.inspectBody(Foo.bar)) + } +} diff --git a/tests/run/tasty-definitions-3.check b/tests/run/tasty-definitions-3.check new file mode 100644 index 000000000000..e92423eea1ca --- /dev/null +++ b/tests/run/tasty-definitions-3.check @@ -0,0 +1,2 @@ +DefDef("foo", Nil, Nil, TypeTree.Synthetic(), None) +ValDef("bar", TypeTree.Synthetic(), None) diff --git a/tests/run/tasty-definitions-3/Macro_1.scala b/tests/run/tasty-definitions-3/Macro_1.scala new file mode 100644 index 000000000000..02bbd8a351db --- /dev/null +++ b/tests/run/tasty-definitions-3/Macro_1.scala @@ -0,0 +1,20 @@ +import scala.quoted._ +import scala.tasty._ + +object Foo { + + transparent def inspectBody(i: => Int): String = + ~inspectBodyImpl('(i))(TopLevelSplice.tastyContext) // FIXME infer TopLevelSplice.tastyContext within top level ~ + + def inspectBodyImpl(x: Expr[Int])(implicit tasty: Tasty): Expr[String] = { + import tasty._ + def definitionString(tree: Tree): Expr[String] = tree.symbol.tree match { + case Some(definition) => definition.show.toExpr + case None => '("NO DEFINTION") + } + x.toTasty match { + case Term.Inlined(None, Nil, arg) => definitionString(arg) + case arg => definitionString(arg) // TODO should all by name parameters be in an inline node? + } + } +} diff --git a/tests/run/tasty-definitions-3/Test_2.scala b/tests/run/tasty-definitions-3/Test_2.scala new file mode 100644 index 000000000000..9df0c7c1bfe5 --- /dev/null +++ b/tests/run/tasty-definitions-3/Test_2.scala @@ -0,0 +1,10 @@ +object Test { + + def main(args: Array[String]): Unit = { + println(Foo.inspectBody(foo)) + println(Foo.inspectBody(bar)) + } + + def foo: Int = 1 + 2 + val bar: Int = 2 + 3 +}