Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add regression test for tasty reflect case study #5797

Merged
merged 45 commits into from
Jan 29, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
9ff84c6
Add basic structure
biboudis Nov 19, 2018
55dd7fc
Update tasty-interpreter.check
biboudis Nov 20, 2018
fe86dd6
LF endings
biboudis Nov 27, 2018
7e75c43
Handle simple method calls
biboudis Nov 27, 2018
b65b1b0
Update extractor
biboudis Nov 27, 2018
6c11c9d
Move interpreter
biboudis Dec 7, 2018
a5fd508
Add JVM reflect
biboudis Dec 7, 2018
5fe6446
Add JVM reflect for static methods without params
biboudis Dec 7, 2018
13ff866
Decouple static val from static meth reflection
biboudis Dec 10, 2018
6ffa3b0
wip
biboudis Dec 12, 2018
663adba
Handle static methods with parameter
biboudis Dec 13, 2018
32c0805
Handles multiple args
biboudis Dec 13, 2018
9cf5c4d
Adding reflective proxies
biboudis Dec 14, 2018
8b076ba
Cleanup
biboudis Dec 17, 2018
6d96ba2
Move classes into packages
nicolasstucki Jan 4, 2019
642c29f
Move Ref and subclasses to to their own files
nicolasstucki Jan 4, 2019
c05a971
Remove unnecessary ctx
nicolasstucki Jan 4, 2019
a5ae022
Split tree interreter from jvm interpreter
nicolasstucki Jan 4, 2019
2fdd5dc
Move logic out of eval
nicolasstucki Jan 4, 2019
5d7f940
Implement isInstanceOf and asInstanceOf
nicolasstucki Jan 4, 2019
7e3b36e
Abstract over interpreted object representation
nicolasstucki Jan 4, 2019
4b1c8cd
Pass evaluated prefix
nicolasstucki Jan 4, 2019
e7e39f1
Refactor Ref (now LocalValue)
nicolasstucki Jan 4, 2019
61de0fa
Remove deadcode
nicolasstucki Jan 4, 2019
4c5b39d
Abstract over ==
nicolasstucki Jan 4, 2019
f64013d
Abstract over primitive numeric operations
nicolasstucki Jan 4, 2019
5b30f9d
Implement primitive divition
nicolasstucki Jan 4, 2019
93ac8cd
Add <= and =>
nicolasstucki Jan 4, 2019
73584ac
Use custom output check as compileDir does use the checkfile
nicolasstucki Jan 8, 2019
74ffc6e
Remove code added by mistake
nicolasstucki Jan 8, 2019
467d9af
Add eval log
nicolasstucki Jan 8, 2019
0cfaefd
Interpret method calls (not only static ones)
nicolasstucki Jan 8, 2019
0cf9d10
Add log to proxy calls
nicolasstucki Jan 8, 2019
3f57db5
Cleanup calls to Object proxy methods
nicolasstucki Jan 8, 2019
b7b101c
Use implicit function types
nicolasstucki Jan 8, 2019
fbc2ca2
Create enviroment abtractions
nicolasstucki Jan 8, 2019
e4d8092
Create interpretValGet
nicolasstucki Jan 8, 2019
b06850a
Reuse interpretCall in proxies
nicolasstucki Jan 8, 2019
ace99d9
Add notes
nicolasstucki Jan 8, 2019
8443112
Move TastyInterpreter
nicolasstucki Jan 8, 2019
ab9a607
Add infrastructure to interpret `run` test
nicolasstucki Jan 8, 2019
18d4ca8
Make HelloWorld pass the tests
nicolasstucki Jan 8, 2019
085e1dd
Interpret varargs
nicolasstucki Jan 9, 2019
4098c43
Add a list of interesting tests
nicolasstucki Jan 9, 2019
9a9bbbc
Rebased
biboudis Jan 25, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ trait FlagsOpsImpl extends scala.tasty.reflect.FlagsOps with CoreImpl {
def Contravariant: Flags = core.Flags.Contravariant
def Scala2X: Flags = core.Flags.Scala2x
def DefaultParameterized: Flags = core.Flags.DefaultParameterized
def Stable: Flags = core.Flags.StableRealizable
def StableRealizable: Flags = core.Flags.StableRealizable
def Param: Flags = core.Flags.Param
def ParamAccessor: Flags = core.Flags.ParamAccessor
}
Expand Down
13 changes: 13 additions & 0 deletions compiler/src/dotty/tools/dotc/tastyreflect/SymbolOpsImpl.scala
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,10 @@ trait SymbolOpsImpl extends scala.tasty.reflect.SymbolOps with CoreImpl {
}
}

def isDefinedInCurrentRun(implicit ctx: Context): Boolean = {
symbol.topLevelClass.asClass.isDefinedInCurrentRun
}

}

object IsPackageSymbol extends IsPackageSymbolModule {
Expand Down Expand Up @@ -171,6 +175,10 @@ trait SymbolOpsImpl extends scala.tasty.reflect.SymbolOps with CoreImpl {

def DefSymbolDeco(symbol: DefSymbol): DefSymbolAPI = new DefSymbolAPI {
def tree(implicit ctx: Context): DefDef = FromSymbol.defDefFromSym(symbol)

def signature(implicit ctx: Context): Signature = {
symbol.signature
}
}

object IsValSymbol extends IsValSymbolModule {
Expand All @@ -181,6 +189,11 @@ trait SymbolOpsImpl extends scala.tasty.reflect.SymbolOps with CoreImpl {
def ValSymbolDeco(symbol: ValSymbol): ValSymbolAPI = new ValSymbolAPI {
def tree(implicit ctx: Context): ValDef = FromSymbol.valDefFromSym(symbol)

def moduleClass(implicit ctx: Context): Option[ClassSymbol] = {
val sym = symbol.moduleClass
if (sym.exists) Some(sym.asClass) else None
}

def companionClass(implicit ctx: Context): Option[ClassSymbol] = {
val sym = symbol.companionClass
if (sym.exists) Some(sym.asClass) else None
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ trait TypeOrBoundsOpsImpl extends scala.tasty.reflect.TypeOrBoundsOps with CoreI
*/
def widen(implicit ctx: Context): Type = tpe.widen

def classSymbol(implicit ctx: Context): Option[ClassSymbol] =
if (tpe.classSymbol.exists) Some(tpe.classSymbol.asClass) else None
}

def ConstantTypeDeco(x: ConstantType): Type.ConstantTypeAPI = new Type.ConstantTypeAPI {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ class BootstrappedOnlyCompilationTests extends ParallelTesting {
@Test def runWithCompiler: Unit = {
implicit val testGroup: TestGroup = TestGroup("runWithCompiler")
compileFilesInDir("tests/run-with-compiler", withCompilerOptions) +
compileDir("tests/run-with-compiler-custom-args/tasty-interpreter", withCompilerOptions) +
compileFile("tests/run-with-compiler-custom-args/staged-streams_1.scala", withCompilerOptions without "-Yno-deep-subtypes")
}.checkRuns()

Expand Down
4 changes: 2 additions & 2 deletions library/src/scala/tasty/reflect/FlagsOps.scala
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,8 @@ trait FlagsOps extends Core {
/** Is this symbol a method with default parameters */
def DefaultParameterized: Flags

/** Is this symbol member that is assumed to be stable */
def Stable: Flags
/** Is this symbol member that is assumed to be stable and realizable */
def StableRealizable: Flags

/** Is this symbol a parameter */
def Param: Flags
Expand Down
4 changes: 2 additions & 2 deletions library/src/scala/tasty/reflect/Printers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ trait Printers
if (flags.is(Flags.Contravariant)) flagList += "Flags.Contravariant"
if (flags.is(Flags.Scala2X)) flagList += "Flags.Scala2X"
if (flags.is(Flags.DefaultParameterized)) flagList += "Flags.DefaultParameterized"
if (flags.is(Flags.Stable)) flagList += "Flags.Stable"
if (flags.is(Flags.StableRealizable)) flagList += "Flags.StableRealizable"
if (flags.is(Flags.Param)) flagList += "Flags.Param"
if (flags.is(Flags.ParamAccessor)) flagList += "Flags.ParamAccessor"
flagList.result().mkString(" | ")
Expand Down Expand Up @@ -501,7 +501,7 @@ trait Printers
if (flags.is(Flags.Contravariant)) flagList += "contravariant"
if (flags.is(Flags.Scala2X)) flagList += "scala2x"
if (flags.is(Flags.DefaultParameterized)) flagList += "defaultParameterized"
if (flags.is(Flags.Stable)) flagList += "stable"
if (flags.is(Flags.StableRealizable)) flagList += "stableRealizable"
if (flags.is(Flags.Param)) flagList += "param"
if (flags.is(Flags.ParamAccessor)) flagList += "paramAccessor"
flagList.result().mkString("/*", " ", "*/")
Expand Down
8 changes: 6 additions & 2 deletions library/src/scala/tasty/reflect/SymbolOps.scala
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ trait SymbolOps extends Core {
/** Annotations attached to this symbol */
def annots(implicit ctx: Context): List[Term]

def isDefinedInCurrentRun(implicit ctx: Context): Boolean
}
implicit def SymbolDeco(symbol: Symbol): SymbolAPI

Expand Down Expand Up @@ -121,7 +122,7 @@ trait SymbolOps extends Core {
}

trait TypeSymbolAPI {
/** TypeDef tree of this defintion. */
/** TypeDef tree of this definition. */
def tree(implicit ctx: Context): TypeDef
}
implicit def TypeSymbolDeco(symbol: TypeSymbol): TypeSymbolAPI
Expand All @@ -136,6 +137,8 @@ trait SymbolOps extends Core {
trait DefSymbolAPI {
/** DefDef tree of this defintion. */
def tree(implicit ctx: Context): DefDef

def signature(implicit ctx: Context): Signature
}
implicit def DefSymbolDeco(symbol: DefSymbol): DefSymbolAPI

Expand All @@ -151,8 +154,9 @@ trait SymbolOps extends Core {
def tree(implicit ctx: Context): ValDef

/** The class symbol of the companion module class */
def companionClass(implicit ctx: Context): Option[ClassSymbol]
def moduleClass(implicit ctx: Context): Option[ClassSymbol]

def companionClass(implicit ctx: Context): Option[ClassSymbol]
}
implicit def ValSymbolDeco(symbol: ValSymbol): ValSymbolAPI

Expand Down
3 changes: 2 additions & 1 deletion library/src/scala/tasty/reflect/TypeOrBoundsOps.scala
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ trait TypeOrBoundsOps extends Core {
implicit def TypeLambdaDeco(x: TypeLambda): Type.TypeLambdaAPI

implicit def TypeBoundsDeco(bounds: TypeBounds): TypeBoundsAPI

// ----- Types ----------------------------------------------------

def typeOf[T: scala.quoted.Type]: Type
Expand All @@ -53,6 +53,7 @@ trait TypeOrBoundsOps extends Core {
def =:=(other: Type)(implicit ctx: Context): Boolean
def <:<(other: Type)(implicit ctx: Context): Boolean
def widen(implicit ctx: Context): Type
def classSymbol(implicit ctx: Context): Option[ClassSymbol]
}

val IsType: IsTypeModule
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
object IntepretedMain {
def main(args: Array[String]): Unit = {
val x1 = 42
println(x1)
println()

lazy val x2 = println("Hello")
x2
x2
println()

def x3 = 42
println(x3)
println()

var x4: Int = 42
x4 = 43
println(x4)
println()

if(x1 == 42)
println("if")
else
println("else")
println()

var x5 = 5
while(x5 > 0){
println(x5)
x5 = x5 - 1
}
println()

def meth() = 42
println(meth())
println()

def methP(i: Int) = i
println(methP(55))

println(Precompiled)
println(Precompiled.staticMeth)
println(Precompiled.staticVal)
println(Precompiled.staticMeth1())
println(Precompiled.staticMeth2(58))
println(Precompiled.staticMeth3(new Object))
println(Precompiled.staticMeth4(new Bar))
println(Precompiled.staticMeth5(new Bar, 61))
println(Precompiled.staticMeth4(new InterpretedBar))
println(Precompiled.staticMeth5(new InterpretedBar, 62))

val x6: Any = 64
println(x6.isInstanceOf[Int])
println(x6.isInstanceOf[Long])
println(x6.asInstanceOf[Int])


val bar = new Bar
println(bar.meth() + 5)
println(bar.methA(66))

val ibar = new InterpretedBar
println(ibar.meth() + 5)
println(ibar.methA(67))
}

def foo(x: Int): Unit = println(x)
}

class InterpretedBar extends IFace {
def meth(): Int = 62
def methA(x: Int): Int = x + 1
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@

class Bar extends IFace {
def meth(): Int = 60
def methA(x: Int): Int = x
}

trait IFace {
def meth(): Int
def methA(x: Int): Int
}

object Precompiled {
def staticMeth = 55
val staticVal = 56

// Todo
def staticMeth1() = 57
def staticMeth2(arg: Int) = arg
def staticMeth3(arg: Object): Int = 59
def staticMeth4(arg: IFace): Int = arg.meth()
def staticMeth5(arg: IFace, x: Int): Int = arg.methA(x)

override def toString() = "precompiledModule"
}
113 changes: 113 additions & 0 deletions tests/run-with-compiler-custom-args/tasty-interpreter/Test.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
import java.io.{ByteArrayOutputStream, File, PrintStream}

import dotty.tools.dotc.core.Contexts
import dotty.tools.dotc.reporting.Reporter
import dotty.tools.dotc.reporting.diagnostic.MessageContainer
import dotty.tools.dotc.util.DiffUtil
import dotty.tools.io.Path

import scala.io.Source
import scala.tasty.file._
import scala.tasty.interpreter.TastyInterpreter
import scala.tasty.Reflection

object Test {
def main(args: Array[String]): Unit = {

val actualOutput = interpret("")("IntepretedMain", "InterpretedBar")
val expectedOutput =
"""42
|
|Hello
|
|42
|
|43
|
|if
|
|5
|4
|3
|2
|1
|
|42
|
|55
|precompiledModule
|55
|56
|57
|58
|59
|60
|61
|62
|63
|true
|false
|64
|65
|66
|67
|68
|""".stripMargin

assert(expectedOutput == actualOutput,
"\n>>>>>>>>>>>>>>>>>>\n" +
DiffUtil.mkColoredCodeDiff(actualOutput, expectedOutput, true) +
"<<<<<<<<<<<<<<<<<<"
)

compileAndInterpret("HelloWorld.scala")
compileAndInterpret("nullInstanceEval.scala")
compileAndInterpret("t3327.scala")
// compileAndInterpret("t5614.scala")
// compileAndInterpret("t4054.scala")
// compileAndInterpret("sort.scala")
// compileAndInterpret("t0607.scala")
// compileAndInterpret("i4073b.scala")
// compileAndInterpret("i4430.scala")
// compileAndInterpret("nullAsInstanceOf.scala")
// compileAndInterpret("classof.scala")
// compileAndInterpret("null-hash.scala")
// compileAndInterpret("i3518.scala")
// compileAndInterpret("withIndex.scala")
// compileAndInterpret("unboxingBug.scala")
// compileAndInterpret("traitInit.scala")
}

def compileAndInterpret(testFileName: String) = {
val reproter = new Reporter {
def doReport(m: MessageContainer)(implicit ctx: Contexts.Context): Unit = println(m)
}
val out = java.nio.file.Paths.get("out/interpreted")
if (!java.nio.file.Files.exists(out))
java.nio.file.Files.createDirectory(out)
dotty.tools.dotc.Main.process(Array("-classpath", System.getProperty("java.class.path"), "-d", out.toString, "tests/run/" + testFileName), reproter)

val actualOutput = interpret(out.toString)("Test")

val checkFile = java.nio.file.Paths.get("tests/run/" + testFileName.stripSuffix(".scala") + ".check")
if (java.nio.file.Files.exists(checkFile)) {
val expectedOutput = Source.fromFile(checkFile.toFile).getLines().mkString("", "\n", "\n")

assert(expectedOutput == actualOutput,
"\n>>>>>>>>>>>>>>>>>>\n" +
DiffUtil.mkColoredCodeDiff(actualOutput, expectedOutput, true) +
"<<<<<<<<<<<<<<<<<<"
)
}
}

def interpret(classpath: String*)(interpretedClasses: String*): String = {
val ps = new ByteArrayOutputStream()
try scala.Console.withOut(ps) {
ConsumeTasty(classpath.mkString(java.io.File.pathSeparatorChar.toString), interpretedClasses.toList, new TastyInterpreter)
} catch {
case e: Throwable => throw new Exception(ps.toString, e)
}
ps.toString
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package scala.tasty.interpreter

import scala.tasty.Reflection
import scala.tasty.file.TastyConsumer

class TastyInterpreter extends TastyConsumer {

final def apply(reflect: Reflection)(root: reflect.Tree): Unit = {
import reflect._
object Traverser extends TreeTraverser {

override def traverseTree(tree: Tree)(implicit ctx: Context): Unit = tree match {
// TODO: check the correct sig and object enclosement for main
case DefDef("main", _, _, _, Some(rhs)) =>
val interpreter = new jvm.Interpreter(reflect)

interpreter.eval(rhs)(Map.empty)
// TODO: recurse only for PackageDef, ClassDef
case tree =>
super.traverseTree(tree)
}
}
Traverser.traverseTree(root)(reflect.rootContext)
}
}
Loading