Skip to content

Patmat #172

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

Closed
wants to merge 23 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
2e40898
Allow converting junit test to scalameter benchmark
DarkDimius Jul 23, 2014
38f335d
Definitions used by pattern matcher
DarkDimius Sep 5, 2014
ff9455e
initValue helper method
DarkDimius Sep 9, 2014
9b78066
Making all case classes implement Product. Requires adding Product0
DarkDimius Sep 9, 2014
45b67a4
Unapply doc update
DarkDimius Sep 9, 2014
7ebc55c
More complicated patterns.
DarkDimius Sep 9, 2014
09d8aa6
Definitions used by patmat
DarkDimius Sep 9, 2014
7c13ea8
Common functionality to be shared between patmat and typer
DarkDimius Sep 9, 2014
2946689
CommonCodegen for patMat
DarkDimius Sep 9, 2014
c6473bd
Optimized codegen for patmat
DarkDimius Sep 9, 2014
b790f83
TreeMakers for patmat
DarkDimius Sep 9, 2014
55fd952
add Substitution to patmat.
DarkDimius Sep 9, 2014
9530230
Match translator for patmat
DarkDimius Sep 9, 2014
073d3e6
Pattern expanders for patmat
DarkDimius Sep 9, 2014
4b2626e
Helper methods for patmat
DarkDimius Sep 9, 2014
4f8ffe0
Adapting patmat for dotty
DarkDimius Sep 9, 2014
435a50a
more of adapting patmat for dotty
DarkDimius Sep 9, 2014
f96c175
More fixes, added _id for internal tracking of failures
DarkDimius Sep 9, 2014
fb3e44a
Most of tests succeed now.
DarkDimius Sep 9, 2014
ba038e5
Everything except unapplySeq doesn't explode.
DarkDimius Sep 9, 2014
0748229
Fixed unapplySeq. Patmat passes all test suite but typer itself break…
DarkDimius Sep 9, 2014
2e23251
Remaining definitions for patmat.
DarkDimius Sep 9, 2014
dd732c2
Remove dead code and add todo about outer tests not being generated
DarkDimius Sep 9, 2014
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
61 changes: 61 additions & 0 deletions bench/src/test/scala/TestsAsBenchmarks.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package dotty.tools.benchmarks

import java.lang.annotation.Annotation
import java.lang.reflect.Method

import org.junit.runner.Request
import org.junit.runner.notification.RunNotifier
import org.scalameter.PerformanceTest.OnlineRegressionReport
import org.scalameter.api._
import org.scalameter.reporting.RegressionReporter.Tester

import scala.collection.mutable.ListBuffer


abstract class TestsToBenchmarkConverter
(targetClass: Class[_],
filterAnnot: Class[_ <: java.lang.annotation.Annotation] = classOf[org.junit.Test].asInstanceOf[Class[_ <: java.lang.annotation.Annotation]])
extends OnlineRegressionReport {

// accept all the results, do not fail
override def tester: Tester = new Tester.Accepter

override def executor: Executor = LocalExecutor(warmer, aggregator, measurer)
val testNames = getMethodsAnnotatedWith(targetClass, filterAnnot).map(_.getName).sorted


val tests = testNames.map{name =>
val runner = Request.method(targetClass, name).getRunner
(name, Gen.single("test")(name).map(Request.method(targetClass, _).getRunner))}.toMap
//Gen.enumeration("test")(testNames:_*)

performance of targetClass.getSimpleName config (Context(reports.resultDir -> "./tmp")) in {
for (test <- testNames)
measure.method(test) in {
using(tests(test)) curve test in {
r =>
val dummy = new RunNotifier()
r.run(dummy)
}
}
}

def getMethodsAnnotatedWith(clazz: Class[_], annotation: Class[_ <: java.lang.annotation.Annotation]): List[Method] = {
val methods = ListBuffer[Method]()
var klass: Class[_] = clazz
while (klass ne classOf[AnyRef]) {
val allMethods = klass.getDeclaredMethods
import scala.collection.JavaConversions._
for (method <- allMethods) {
if (annotation == null || method.isAnnotationPresent(annotation)) {
val annotInstance: Annotation = method.getAnnotation(annotation)
methods.add(method)
}
}
klass = klass.getSuperclass
}
methods.toList
}
}

object dotcTests extends TestsToBenchmarkConverter(classOf[dotc.tests])
50 changes: 48 additions & 2 deletions project/Build.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import sbt.Keys._
import sbt._
import Keys._
import Process._

object DottyBuild extends Build {

Expand Down Expand Up @@ -71,4 +70,51 @@ object DottyBuild extends Build {
)

lazy val dotty = Project(id = "dotty", base = file("."), settings = defaults)

lazy val benchmarkSettings = Defaults.defaultSettings ++ Seq(

// to get Scala 2.11
resolvers += Resolver.sonatypeRepo("releases"),

baseDirectory in (Test,run) := (baseDirectory in dotty).value,


libraryDependencies ++= Seq("com.storm-enroute" %% "scalameter" % "0.6" % Test,
"com.novocode" % "junit-interface" % "0.11-RC1"),
testFrameworks += new TestFramework("org.scalameter.ScalaMeterFramework"),

// scalac options
scalacOptions in Global ++= Seq("-feature", "-deprecation", "-language:_"),

javacOptions ++= Seq("-Xlint:unchecked", "-Xlint:deprecation"),

fork in Test := true,
parallelExecution in Test := false,

// http://grokbase.com/t/gg/simple-build-tool/135ke5y90p/sbt-setting-jvm-boot-paramaters-for-scala
javaOptions <++= (dependencyClasspath in Runtime, packageBin in Compile) map { (attList, bin) =>
// put the Scala {library, reflect, compiler} in the classpath
val path = for {
file <- attList.map(_.data)
path = file.getAbsolutePath
prefix = if(path.endsWith(".jar")) "p" else "a"
} yield "-Xbootclasspath/"+ prefix +":" + path
// dotty itself needs to be in the bootclasspath
val fullpath = ("-Xbootclasspath/a:" + bin) :: path.toList
// System.err.println("BOOTPATH: " + fullpath)

val travis_build = // propagate if this is a travis build
if (sys.props.isDefinedAt(TRAVIS_BUILD))
List(s"-D$TRAVIS_BUILD=${sys.props(TRAVIS_BUILD)}")
else
List()
val res = agentOptions ::: travis_build ::: fullpath
println("Running with javaOptions: " +res)
res
}
)


lazy val benchmarks = Project(id = "dotty-bench", settings = benchmarkSettings,
base = file("bench")) dependsOn(dotty % "compile->test")
}
2 changes: 1 addition & 1 deletion src/dotty/tools/dotc/Run.scala
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ class Run(comp: Compiler)(implicit ctx: Context) {
private def printTree(ctx: Context) = {
val unit = ctx.compilationUnit
println(s"result of $unit after ${ctx.phase.prev}:")
println(unit.tpdTree.show(ctx))
println(unit.tpdTree)
}

def compile(sourceCode: String): Unit = {
Expand Down
9 changes: 6 additions & 3 deletions src/dotty/tools/dotc/ast/Desugar.scala
Original file line number Diff line number Diff line change
Expand Up @@ -302,13 +302,16 @@ object desugar {
def anyRef = ref(defn.AnyRefAlias.typeRef)
def productConstr(n: Int) = {
val tycon = ref(defn.ProductNClass(n).typeRef)
val targs = constrVparamss.head map (_.tpt)
AppliedTypeTree(tycon, targs)
if(n > 0) {
val targs = constrVparamss.head map (_.tpt)
AppliedTypeTree(tycon, targs)
}
else tycon
}

// Case classes get a ProductN parent
var parents1 = parents
if ((mods is Case) && 2 <= arity && arity <= Definitions.MaxTupleArity)
if ((mods is Case) && arity <= Definitions.MaxTupleArity)
parents1 = parents1 :+ productConstr(arity)

// The thicket which is the desugared version of the companion object
Expand Down
4 changes: 3 additions & 1 deletion src/dotty/tools/dotc/ast/Trees.scala
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,8 @@ object Trees {
* an UnAssignedTypeException is thrown. (Overridden by empty trees)
*/
def tpe: T @uncheckedVariance = {
if (myTpe == null) throw new UnAssignedTypeException(this)
if (myTpe == null)
throw new UnAssignedTypeException(this)
myTpe
}

Expand Down Expand Up @@ -683,6 +684,7 @@ object Trees {
* @param implicits Any implicit parameters passed to the unapply after the selector
* @param patterns The argument patterns in the pattern match.
*
* It is typed with same type as first `fun` argument
* Given a match selector `sel` a pattern UnApply(fun, implicits, patterns) is roughly translated as follows
*
* val result = fun(sel)(implicits)
Expand Down
18 changes: 17 additions & 1 deletion src/dotty/tools/dotc/ast/tpd.scala
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,20 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
Thicket(valdef, clsdef)
}

def initValue(tpe: Types.Type)(implicit ctx: Context) = {
val tpw = tpe.widen

if (tpw =:= defn.IntType) Literal(Constant(0))
else if (tpw =:= defn.LongType) Literal(Constant(0L))
else if (tpw =:= defn.BooleanType) Literal(Constant(false))
else if (tpw =:= defn.CharType) Literal(Constant('\u0000'))
else if (tpw =:= defn.FloatType) Literal(Constant(0f))
else if (tpw =:= defn.DoubleType) Literal(Constant(0d))
else if (tpw =:= defn.ByteType) Literal(Constant(0.toByte))
else if (tpw =:= defn.ShortType) Literal(Constant(0.toShort))
else Literal(Constant(null)).select(defn.Any_asInstanceOf).appliedToType(tpe)
}

private class FindLocalDummyAccumulator(cls: ClassSymbol)(implicit ctx: Context) extends TreeAccumulator[Symbol] {
def apply(sym: Symbol, tree: Tree) =
if (sym.exists) sym
Expand Down Expand Up @@ -523,7 +537,9 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
}
}

def runtimeCall(name: TermName, args: List[Tree])(implicit ctx: Context): Tree = ???
def runtimeCall(name: TermName, args: List[Tree])(implicit ctx: Context): Tree = {
Ident(defn.ScalaRuntimeModule.requiredMethod(name).termRef).appliedToArgs(args)
}

def mkAnd(tree1: Tree, tree2: Tree)(implicit ctx: Context) =
tree1.select(defn.Boolean_and).appliedTo(tree2)
Expand Down
23 changes: 22 additions & 1 deletion src/dotty/tools/dotc/core/Definitions.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ package core

import Types._, Contexts._, Symbols._, Denotations._, SymDenotations._, StdNames._, Names._
import Flags._, Scopes._, Decorators._, NameOps._, util.Positions._
import TypeApplications._
import pickling.UnPickler.ensureConstructor
import scala.annotation.{ switch, meta }
import scala.collection.{ mutable, immutable }
Expand Down Expand Up @@ -103,6 +104,7 @@ class Definitions {
lazy val EmptyPackageVal = EmptyPackageClass.sourceModule.entered

lazy val ScalaPackageVal = ctx.requiredPackage("scala")
lazy val ScalaMathPackageVal = ctx.requiredPackage("scala.math")
lazy val ScalaPackageClass = ScalaPackageVal.moduleClass.asClass
lazy val JavaPackageVal = ctx.requiredPackage("java")
lazy val JavaLangPackageVal = ctx.requiredPackage("java.lang")
Expand Down Expand Up @@ -177,7 +179,9 @@ class Definitions {

lazy val ScalaPredefModule = ctx.requiredModule("scala.Predef")
lazy val ScalaRuntimeModule = ctx.requiredModule("scala.runtime.ScalaRunTime")
lazy val ScalaRuntimeModuleClass = ScalaRuntimeModule.moduleClass.asClass
lazy val BoxesRunTimeModule = ctx.requiredModule("scala.runtime.BoxesRunTime")

lazy val BoxesRunTimeClass = BoxesRunTimeModule.moduleClass
lazy val DottyPredefModule = ctx.requiredModule("dotty.DottyPredef")
lazy val NilModule = ctx.requiredModule("scala.collection.immutable.Nil")
Expand All @@ -191,11 +195,15 @@ class Definitions {
ScalaPackageClass, tpnme.Singleton, Trait | Interface | Final,
List(AnyClass.typeRef), EmptyScope)
lazy val SeqClass: ClassSymbol = ctx.requiredClass("scala.collection.Seq")
lazy val Seq_apply = ctx.requiredMethod(SeqClass, nme.apply)
lazy val Seq_head = ctx.requiredMethod(SeqClass, nme.head)
lazy val ArrayClass: ClassSymbol = ctx.requiredClass("scala.Array")
lazy val Array_apply = ctx.requiredMethod(ArrayClass, nme.apply)
lazy val Array_update = ctx.requiredMethod(ArrayClass, nme.update)
lazy val Array_length = ctx.requiredMethod(ArrayClass, nme.length)
lazy val Array_clone = ctx.requiredMethod(ArrayClass, nme.clone_)

lazy val traversableDropMethod = ctx.requiredMethod(ScalaRuntimeModuleClass, nme.drop)
lazy val uncheckedStableClass: ClassSymbol = ctx.requiredClass("scala.annotation.unchecked.uncheckedStable")

lazy val UnitClass = valueClassSymbol("scala.Unit", BoxedUnitClass, java.lang.Void.TYPE, UnitEnc)
Expand All @@ -208,6 +216,13 @@ class Definitions {
lazy val ShortClass = valueClassSymbol("scala.Short", BoxedShortClass, java.lang.Short.TYPE, ShortEnc)
lazy val CharClass = valueClassSymbol("scala.Char", BoxedCharClass, java.lang.Character.TYPE, CharEnc)
lazy val IntClass = valueClassSymbol("scala.Int", BoxedIntClass, java.lang.Integer.TYPE, IntEnc)
lazy val Int_- = IntClass.requiredMethod(nme.MINUS, List(IntType))
lazy val Int_+ = IntClass.requiredMethod(nme.PLUS, List(IntType))
lazy val Int_/ = IntClass.requiredMethod(nme.DIV, List(IntType))
lazy val Int_* = IntClass.requiredMethod(nme.MUL, List(IntType))
lazy val Int_== = IntClass.requiredMethod(nme.EQ, List(IntType))
lazy val Int_>= = IntClass.requiredMethod(nme.GE, List(IntType))
lazy val Int_<= = IntClass.requiredMethod(nme.LE, List(IntType))
lazy val LongClass = valueClassSymbol("scala.Long", BoxedLongClass, java.lang.Long.TYPE, LongEnc)
lazy val Long_XOR_Long = LongClass.info.member(nme.XOR).requiredSymbol(
x => (x is Method) && (x.info.firstParamTypes.head isRef defn.LongClass)
Expand Down Expand Up @@ -253,6 +268,8 @@ class Definitions {
lazy val JavaCloneableClass = ctx.requiredClass("java.lang.Cloneable")
lazy val StringBuilderClass = ctx.requiredClass("scala.collection.mutable.StringBuilder")
lazy val NullPointerExceptionClass = ctx.requiredClass(jnme.NPException)
lazy val MatchErrorClass = ctx.requiredClass("scala.MatchError")
lazy val MatchErrorType = MatchErrorClass.typeRef

lazy val StringAddClass = ctx.requiredClass("scala.runtime.StringAdd")

Expand Down Expand Up @@ -390,7 +407,7 @@ class Definitions {
lazy val Function0_apply = FunctionClass(0).requiredMethod(nme.apply)

lazy val TupleClass = mkArityArray("scala.Tuple", MaxTupleArity, 2)
lazy val ProductNClass = mkArityArray("scala.Product", MaxTupleArity, 2)
lazy val ProductNClass = mkArityArray("scala.Product", MaxTupleArity, 0)

lazy val FunctionClasses: Set[Symbol] = FunctionClass.toSet
lazy val TupleClasses: Set[Symbol] = TupleClass.toSet
Expand All @@ -414,6 +431,10 @@ class Definitions {
arity <= MaxTupleArity && (tp isRef TupleClass(arity))
}

def tupleType(elems: List[Type]) = {
TupleClass(elems.size).typeRef.appliedTo(elems)
}

def isProductSubType(tp: Type)(implicit ctx: Context) =
(tp derivesFrom ProductClass) && tp.baseClasses.exists(ProductClasses contains _)

Expand Down
5 changes: 5 additions & 0 deletions src/dotty/tools/dotc/core/Denotations.scala
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,11 @@ object Denotations {
def requiredMethod(name: PreName)(implicit ctx: Context): TermSymbol =
info.member(name.toTermName).requiredSymbol(_ is Method).asTerm

def requiredMethod(name: PreName, argTypes: List[Type])(implicit ctx: Context): TermSymbol =
info.member(name.toTermName).requiredSymbol(x=>
(x is Method) && x.info.paramTypess == List(argTypes)
).asTerm

def requiredValue(name: PreName)(implicit ctx: Context): TermSymbol =
info.member(name.toTermName).requiredSymbol(_.info.isParameterless).asTerm

Expand Down
2 changes: 2 additions & 0 deletions src/dotty/tools/dotc/core/Names.scala
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,8 @@ object Names {
i < length
}

def firstChar = chrs(start)

// ----- Collections integration -------------------------------------

override protected[this] def thisCollection: WrappedString = new WrappedString(repr.toString)
Expand Down
59 changes: 59 additions & 0 deletions src/dotty/tools/dotc/core/StdNames.scala
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,29 @@ object StdNames {
val x_8 : N = "x$8"
val x_9 : N = "x$9"

val _1 : N = "_1"
val _2 : N = "_2"
val _3 : N = "_3"
val _4 : N = "_4"
val _5 : N = "_5"
val _6 : N = "_6"
val _7 : N = "_7"
val _8 : N = "_8"
val _9 : N = "_9"
val _10 : N = "_10"
val _11 : N = "_11"
val _12 : N = "_12"
val _13 : N = "_13"
val _14 : N = "_14"
val _15 : N = "_15"
val _16 : N = "_16"
val _17 : N = "_17"
val _18 : N = "_18"
val _19 : N = "_19"
val _20 : N = "_20"
val _21 : N = "_21"
val _22 : N = "_22"

val ??? = encode("???")

val genericWrapArray: N = "genericWrapArray"
Expand Down Expand Up @@ -627,6 +650,32 @@ object StdNames {
case _ => termName("x$" + i)
}

@switch def productAccessorName(j: Int): TermName = j match {
case 1 => nme._1
case 2 => nme._2
case 3 => nme._3
case 4 => nme._4
case 5 => nme._5
case 6 => nme._6
case 7 => nme._7
case 8 => nme._8
case 9 => nme._9
case 10 => nme._10
case 11 => nme._11
case 12 => nme._12
case 13 => nme._13
case 14 => nme._14
case 15 => nme._15
case 16 => nme._16
case 17 => nme._17
case 18 => nme._18
case 19 => nme._19
case 20 => nme._20
case 21 => nme._21
case 22 => nme._22
case _ => termName("_" + j)
}

def syntheticParamNames(num: Int): List[TermName] =
(0 until num).map(syntheticParamName)(breakOut)

Expand All @@ -636,6 +685,16 @@ object StdNames {
def newBitmapName(bitmapPrefix: TermName, n: Int): TermName = bitmapPrefix ++ n.toString

def selectorName(n: Int): TermName = "_" + (n + 1)

/** Is name a variable name? */
def isVariableName(name: Name): Boolean = {
val first = name.firstChar
( ((first.isLower && first.isLetter) || first == '_')
&& (name != nme.false_)
&& (name != nme.true_)
&& (name != nme.null_)
)
}
}

class ScalaTypeNames extends ScalaNames[TypeName] {
Expand Down
Loading