summaryrefslogtreecommitdiff
path: root/scalaParser/src/test
diff options
context:
space:
mode:
Diffstat (limited to 'scalaParser/src/test')
-rw-r--r--scalaParser/src/test/resources/test.scala751
-rw-r--r--scalaParser/src/test/scala/scalaParser/SyntaxTest.scala956
2 files changed, 542 insertions, 1165 deletions
diff --git a/scalaParser/src/test/resources/test.scala b/scalaParser/src/test/resources/test.scala
index d560736..a0e847e 100644
--- a/scalaParser/src/test/resources/test.scala
+++ b/scalaParser/src/test/resources/test.scala
@@ -1,751 +1,4 @@
-/* Scala.js compiler
- * Copyright 2013 LAMP/EPFL
- * @author Sébastien Doeraene
- */
-
-package scala.scalajs.compiler
-
-import scala.collection.mutable
-
-import scala.tools.nsc._
-import scala.math.PartialOrdering
-import scala.reflect.internal.Flags
-
-import scala.scalajs.ir
-import ir.{Trees => js, Types => jstpe}
-
-import util.ScopedVar
-import ScopedVar.withScopedVars
-
-/** Generation of exports for JavaScript
- *
- * @author Sébastien Doeraene
- */
-trait GenJSExports extends SubComponent { self: GenJSCode =>
- import global._
- import jsAddons._
- import definitions._
- import jsDefinitions._
-
- trait JSExportsPhase { this: JSCodePhase =>
-
- /**
- * Generate exporter methods for a class
- * @param classSym symbol of class we export for
- * @param decldExports symbols exporter methods that have been encountered in
- * the class' tree. This is not the same as classSym.info.delcs since
- * inherited concrete methods from traits should be in this param, too
- */
- def genMemberExports(
- classSym: Symbol,
- decldExports: List[Symbol]): List[js.Tree] = {
-
- val newlyDecldExports = decldExports.filterNot { isOverridingExport _ }
- val newlyDecldExportNames =
- newlyDecldExports.map(_.name.toTermName).toList.distinct
-
- newlyDecldExportNames map { genMemberExport(classSym, _) }
- }
-
- def genConstructorExports(classSym: Symbol): List[js.ConstructorExportDef] = {
- val constructors = classSym.tpe.member(nme.CONSTRUCTOR).alternatives
-
- // Generate exports from constructors and their annotations
- val ctorExports = for {
- ctor <- constructors
- exp <- jsInterop.exportsOf(ctor)
- } yield (exp, ctor)
-
- val exports = for {
- (jsName, specs) <- ctorExports.groupBy(_._1.jsName) // group by exported name
- } yield {
- val (namedExports, normalExports) = specs.partition(_._1.isNamed)
-
- val normalCtors = normalExports.map(s => ExportedSymbol(s._2))
- val namedCtors = for {
- (exp, ctor) <- namedExports
- } yield {
- implicit val pos = exp.pos
- ExportedBody(List(JSAnyTpe),
- genNamedExporterBody(ctor, genFormalArg(1).ref),
- nme.CONSTRUCTOR.toString, pos)
- }
-
- val ctors = normalCtors ++ namedCtors
-
- implicit val pos = ctors.head.pos
-
- val js.MethodDef(_, args, _, body) =
- withNewLocalNameScope(genExportMethod(ctors, jsName))
-
- js.ConstructorExportDef(jsName, args, body)
- }
-
- exports.toList
- }
-
- def genModuleAccessorExports(classSym: Symbol): List[js.ModuleExportDef] = {
- for {
- exp <- jsInterop.exportsOf(classSym)
- } yield {
- implicit val pos = exp.pos
-
- if (exp.isNamed)
- reporter.error(pos, "You may not use @JSNamedExport on an object")
-
- js.ModuleExportDef(exp.jsName)
- }
- }
-
- /** Generate the exporter proxy for a named export */
- def genNamedExporterDef(dd: DefDef): js.MethodDef = {
- implicit val pos = dd.pos
-
- val sym = dd.symbol
-
- val Block(Apply(fun, _) :: Nil, _) = dd.rhs
- val trgSym = fun.symbol
-
- val inArg =
- js.ParamDef(js.Ident("namedParams"), jstpe.AnyType, mutable = false)
- val inArgRef = inArg.ref
-
- val methodIdent = encodeMethodSym(sym)
-
- withScopedVars(
- currentMethodInfoBuilder :=
- currentClassInfoBuilder.addMethod(methodIdent.name)
- ) {
- js.MethodDef(methodIdent, List(inArg), toIRType(sym.tpe.resultType),
- genNamedExporterBody(trgSym, inArg.ref))(None)
- }
- }
-
- private def genNamedExporterBody(trgSym: Symbol, inArg: js.Tree)(
- implicit pos: Position) = {
-
- if (hasRepeatedParam(trgSym)) {
- reporter.error(pos,
- "You may not name-export a method with a *-parameter")
- }
-
- val jsArgs = for {
- (pSym, index) <- trgSym.info.params.zipWithIndex
- } yield {
- val rhs = js.JSBracketSelect(inArg,
- js.StringLiteral(pSym.name.decoded))
- js.VarDef(js.Ident("namedArg$" + index), jstpe.AnyType,
- mutable = false, rhs = rhs)
- }
-
- val jsArgRefs = jsArgs.map(_.ref)
-
- // Generate JS code to prepare arguments (default getters and unboxes)
- val jsArgPrep = genPrepareArgs(jsArgRefs, trgSym)
- val jsResult = genResult(trgSym, jsArgPrep.map(_.ref))
-
- js.Block(jsArgs ++ jsArgPrep :+ jsResult)
- }
-
- private def genMemberExport(classSym: Symbol, name: TermName): js.Tree = {
- val alts = classSym.info.member(name).alternatives
-
- assert(!alts.isEmpty,
- s"Ended up with no alternatives for ${classSym.fullName}::$name. " +
- s"Original set was ${alts} with types ${alts.map(_.tpe)}")
-
- val (jsName, isProp) = jsInterop.jsExportInfo(name)
-
- // Check if we have a conflicting export of the other kind
- val conflicting =
- classSym.info.member(jsInterop.scalaExportName(jsName, !isProp))
-
- if (conflicting != NoSymbol) {
- val kind = if (isProp) "property" else "method"
- val alts = conflicting.alternatives
-
- reporter.error(alts.head.pos,
- s"Exported $kind $jsName conflicts with ${alts.head.fullName}")
- }
-
- withNewLocalNameScope {
- if (isProp)
- genExportProperty(alts, jsName)
- else
- genExportMethod(alts.map(ExportedSymbol), jsName)
- }
- }
-
- private def genExportProperty(alts: List[Symbol], jsName: String) = {
- assert(!alts.isEmpty)
- implicit val pos = alts.head.pos
-
- // Separate getters and setters. Somehow isJSGetter doesn't work here. Hence
- // we just check the parameter list length.
- val (getter, setters) = alts.partition(_.tpe.params.isEmpty)
-
- // if we have more than one getter, something went horribly wrong
- assert(getter.size <= 1,
- s"Found more than one getter to export for name ${jsName}.")
-
- val getTree =
- if (getter.isEmpty) js.EmptyTree
- else genApplyForSym(getter.head)
-
- val setTree =
- if (setters.isEmpty) js.EmptyTree
- else genExportSameArgc(setters.map(ExportedSymbol), 0) // we only have 1 argument
-
- js.PropertyDef(js.StringLiteral(jsName), getTree, genFormalArg(1), setTree)
- }
-
- /** generates the exporter function (i.e. exporter for non-properties) for
- * a given name */
- private def genExportMethod(alts0: List[Exported], jsName: String) = {
- assert(alts0.nonEmpty,
- "need at least one alternative to generate exporter method")
-
- implicit val pos = alts0.head.pos
-
- val alts = {
- // toString() is always exported. We might need to add it here
- // to get correct overloading.
- if (jsName == "toString" && alts0.forall(_.params.nonEmpty))
- ExportedSymbol(Object_toString) :: alts0
- else
- alts0
- }
-
- // Factor out methods with variable argument lists. Note that they can
- // only be at the end of the lists as enforced by PrepJSExports
- val (varArgMeths, normalMeths) = alts.partition(_.hasRepeatedParam)
-
- // Highest non-repeated argument count
- val maxArgc = (
- // We have argc - 1, since a repeated parameter list may also be empty
- // (unlike a normal parameter)
- varArgMeths.map(_.params.size - 1) ++
- normalMeths.map(_.params.size)
- ).max
-
- val formalArgs = genFormalArgs(maxArgc)
-
- // Calculates possible arg counts for normal method
- def argCounts(ex: Exported) = ex match {
- case ExportedSymbol(sym) =>
- val params = sym.tpe.params
- // Find default param
- val dParam = params.indexWhere { _.hasFlag(Flags.DEFAULTPARAM) }
- if (dParam == -1) Seq(params.size)
- else dParam to params.size
- case ex: ExportedBody =>
- List(ex.params.size)
- }
-
- // Generate tuples (argc, method)
- val methodArgCounts = {
- // Normal methods
- for {
- method <- normalMeths
- argc <- argCounts(method)
- } yield (argc, method)
- } ++ {
- // Repeated parameter methods
- for {
- method <- varArgMeths
- argc <- method.params.size - 1 to maxArgc
- } yield (argc, method)
- }
-
- // Create a map: argCount -> methods (methods may appear multiple times)
- val methodByArgCount =
- methodArgCounts.groupBy(_._1).mapValues(_.map(_._2).toSet)
-
- // Create tuples: (methods, argCounts). This will be the cases we generate
- val caseDefinitions =
- methodByArgCount.groupBy(_._2).mapValues(_.keySet)
-
- // Verify stuff about caseDefinitions
- assert({
- val argcs = caseDefinitions.values.flatten.toList
- argcs == argcs.distinct &&
- argcs.forall(_ <= maxArgc)
- }, "every argc should appear only once and be lower than max")
-
- // Generate a case block for each (methods, argCounts) tuple
- val cases = for {
- (methods, argcs) <- caseDefinitions
- if methods.nonEmpty && argcs.nonEmpty
-
- // exclude default case we're generating anyways for varargs
- if methods != varArgMeths.toSet
-
- // body of case to disambiguates methods with current count
- caseBody =
- genExportSameArgc(methods.toList, 0, Some(argcs.min))
-
- // argc in reverse order
- argcList = argcs.toList.sortBy(- _)
- } yield (argcList.map(js.IntLiteral(_)), caseBody)
-
- val hasVarArg = varArgMeths.nonEmpty
-
- def defaultCase = {
- if (!hasVarArg)
- genThrowTypeError()
- else
- genExportSameArgc(varArgMeths, 0)
- }
-
- val body = {
- if (cases.isEmpty)
- defaultCase
- else if (cases.size == 1 && !hasVarArg)
- cases.head._2
- else {
- js.Match(
- js.Unbox(js.JSBracketSelect(
- js.VarRef(js.Ident("arguments"), false)(jstpe.AnyType),
- js.StringLiteral("length")),
- 'I'),
- cases.toList, defaultCase)(jstpe.AnyType)
- }
- }
-
- js.MethodDef(js.StringLiteral(jsName), formalArgs, jstpe.AnyType, body)(None)
- }
-
- /**
- * Resolve method calls to [[alts]] while assuming they have the same
- * parameter count.
- * @param alts Alternative methods
- * @param paramIndex Index where to start disambiguation
- * @param maxArgc only use that many arguments
- */
- private def genExportSameArgc(alts: List[Exported],
- paramIndex: Int, maxArgc: Option[Int] = None): js.Tree = {
-
- implicit val pos = alts.head.pos
-
- if (alts.size == 1)
- alts.head.body
- else if (maxArgc.exists(_ <= paramIndex) ||
- !alts.exists(_.params.size > paramIndex)) {
- // We reach here in three cases:
- // 1. The parameter list has been exhausted
- // 2. The optional argument count restriction has triggered
- // 3. We only have (more than once) repeated parameters left
- // Therefore, we should fail
- reporter.error(pos,
- s"""Cannot disambiguate overloads for exported method ${alts.head.name} with types
- | ${alts.map(_.typeInfo).mkString("\n ")}""".stripMargin)
- js.Undefined()
- } else {
-
- val altsByTypeTest = groupByWithoutHashCode(alts) {
- case ExportedSymbol(alt) =>
- // get parameter type while resolving repeated params
- val tpe = enteringPhase(currentRun.uncurryPhase) {
- val ps = alt.paramss.flatten
- if (ps.size <= paramIndex || isRepeated(ps(paramIndex))) {
- assert(isRepeated(ps.last))
- repeatedToSingle(ps.last.tpe)
- } else {
- enteringPhase(currentRun.posterasurePhase) {
- ps(paramIndex).tpe
- }
- }
- }
-
- typeTestForTpe(tpe)
-
- case ex: ExportedBody =>
- typeTestForTpe(ex.params(paramIndex))
- }
-
- if (altsByTypeTest.size == 1) {
- // Testing this parameter is not doing any us good
- genExportSameArgc(alts, paramIndex+1, maxArgc)
- } else {
- // Sort them so that, e.g., isInstanceOf[String]
- // comes before isInstanceOf[Object]
- val sortedAltsByTypeTest = topoSortDistinctsBy(
- altsByTypeTest)(_._1)(RTTypeTest.Ordering)
-
- val defaultCase = genThrowTypeError()
-
- sortedAltsByTypeTest.foldRight[js.Tree](defaultCase) { (elem, elsep) =>
- val (typeTest, subAlts) = elem
- implicit val pos = subAlts.head.pos
-
- val param = genFormalArg(paramIndex+1)
- val genSubAlts = genExportSameArgc(subAlts, paramIndex+1, maxArgc)
-
- def hasDefaultParam = subAlts.exists {
- case ExportedSymbol(p) =>
- val params = p.tpe.params
- params.size > paramIndex &&
- params(paramIndex).hasFlag(Flags.DEFAULTPARAM)
- case _: ExportedBody => false
- }
-
- val optCond = typeTest match {
- case HijackedTypeTest(boxedClassName, _) =>
- Some(js.IsInstanceOf(param.ref, jstpe.ClassType(boxedClassName)))
-
- case InstanceOfTypeTest(tpe) =>
- Some(genIsInstanceOf(param.ref, tpe))
-
- case NoTypeTest =>
- None
- }
-
- optCond.fold[js.Tree] {
- genSubAlts // note: elsep is discarded, obviously
- } { cond =>
- val condOrUndef = if (!hasDefaultParam) cond else {
- js.If(cond, js.BooleanLiteral(true),
- js.BinaryOp(js.BinaryOp.===, param.ref, js.Undefined()))(
- jstpe.BooleanType)
- }
- js.If(condOrUndef, genSubAlts, elsep)(jstpe.AnyType)
- }
- }
- }
- }
- }
-
- /**
- * Generate a call to the method [[sym]] while using the formalArguments
- * and potentially the argument array. Also inserts default parameters if
- * required.
- */
- private def genApplyForSym(sym: Symbol): js.Tree = {
- implicit val pos = sym.pos
-
- // the (single) type of the repeated parameter if any
- val repeatedTpe = enteringPhase(currentRun.uncurryPhase) {
- for {
- param <- sym.paramss.flatten.lastOption
- if isRepeated(param)
- } yield repeatedToSingle(param.tpe)
- }
-
- val normalArgc = sym.tpe.params.size -
- (if (repeatedTpe.isDefined) 1 else 0)
-
- // optional repeated parameter list
- val jsVarArg = repeatedTpe map { tpe =>
- // Copy arguments that go to vararg into an array, put it in a wrapper
-
- val countIdent = freshLocalIdent("count")
- val count = js.VarRef(countIdent, mutable = false)(jstpe.IntType)
-
- val counterIdent = freshLocalIdent("i")
- val counter = js.VarRef(counterIdent, mutable = true)(jstpe.IntType)
-
- val arrayIdent = freshLocalIdent("varargs")
- val array = js.VarRef(arrayIdent, mutable = false)(jstpe.AnyType)
-
- val arguments = js.VarRef(js.Ident("arguments"),
- mutable = false)(jstpe.AnyType)
- val argLen = js.Unbox(
- js.JSBracketSelect(arguments, js.StringLiteral("length")), 'I')
- val argOffset = js.IntLiteral(normalArgc)
-
- val jsArrayCtor =
- js.JSBracketSelect(
- js.JSBracketSelect(js.JSEnvInfo(), js.StringLiteral("global")),
- js.StringLiteral("Array"))
-
- js.Block(
- // var i = 0
- js.VarDef(counterIdent, jstpe.IntType, mutable = true,
- rhs = js.IntLiteral(0)),
- // val count = arguments.length - <normalArgc>
- js.VarDef(countIdent, jstpe.IntType, mutable = false,
- rhs = js.BinaryOp(js.BinaryOp.Int_-, argLen, argOffset)),
- // val varargs = new Array(count)
- js.VarDef(arrayIdent, jstpe.AnyType, mutable = false,
- rhs = js.JSNew(jsArrayCtor, List(count))),
- // while (i < count)
- js.While(js.BinaryOp(js.BinaryOp.Num_<, counter, count), js.Block(
- // varargs[i] = arguments[<normalArgc> + i];
- js.Assign(
- js.JSBracketSelect(array, counter),
- js.JSBracketSelect(arguments,
- js.BinaryOp(js.BinaryOp.Int_+, argOffset, counter))),
- // i = i + 1 (++i won't work, desugar eliminates it)
- js.Assign(counter, js.BinaryOp(js.BinaryOp.Int_+,
- counter, js.IntLiteral(1)))
- )),
- // new WrappedArray(varargs)
- genNew(WrappedArrayClass, WrappedArray_ctor, List(array))
- )
- }
-
- // normal arguments
- val jsArgs = genFormalArgs(normalArgc)
- val jsArgRefs = jsArgs.map(_.ref)
-
- // Generate JS code to prepare arguments (default getters and unboxes)
- val jsArgPrep = genPrepareArgs(jsArgRefs, sym)
- val jsResult = genResult(sym, jsArgPrep.map(_.ref) ++ jsVarArg)
-
- js.Block(jsArgPrep :+ jsResult)
- }
-
- /** Generate the necessary JavaScript code to prepare the arguments of an
- * exported method (unboxing and default parameter handling)
- */
- private def genPrepareArgs(jsArgs: List[js.VarRef], sym: Symbol)(
- implicit pos: Position): List[js.VarDef] = {
-
- val result = new mutable.ListBuffer[js.VarDef]
-
- val funTpe = enteringPhase(currentRun.posterasurePhase)(sym.tpe)
- for {
- (jsArg, (param, i)) <- jsArgs zip funTpe.params.zipWithIndex
- } yield {
- // Code to verify the type of the argument (if it is defined)
- val verifiedArg = {
- val tpePosterasure =
- enteringPhase(currentRun.posterasurePhase)(param.tpe)
- tpePosterasure match {
- case tpe if isPrimitiveValueType(tpe) =>
- val unboxed = makePrimitiveUnbox(jsArg, tpe)
- // Ensure we don't convert null to a primitive value type
- js.If(js.BinaryOp(js.BinaryOp.===, jsArg, js.Null()),
- genThrowTypeError(s"Found null, expected $tpe"),
- unboxed)(unboxed.tpe)
- case tpe: ErasedValueType =>
- val boxedClass = tpe.valueClazz
- val unboxMethod = boxedClass.derivedValueClassUnbox
- genApplyMethod(
- genAsInstanceOf(jsArg, tpe),
- boxedClass, unboxMethod, Nil)
- case tpe =>
- genAsInstanceOf(jsArg, tpe)
- }
- }
-
- // If argument is undefined and there is a default getter, call it
- val verifiedOrDefault = if (param.hasFlag(Flags.DEFAULTPARAM)) {
- js.If(js.BinaryOp(js.BinaryOp.===, jsArg, js.Undefined()), {
- val trgSym = {
- if (sym.isClassConstructor) sym.owner.companionModule.moduleClass
- else sym.owner
- }
- val defaultGetter = trgSym.tpe.member(
- nme.defaultGetterName(sym.name, i+1))
-
- assert(defaultGetter.exists,
- s"need default getter for method ${sym.fullName}")
- assert(!defaultGetter.isOverloaded)
-
- val trgTree = {
- if (sym.isClassConstructor) genLoadModule(trgSym)
- else js.This()(encodeClassType(trgSym))
- }
-
- // Pass previous arguments to defaultGetter
- genApplyMethod(trgTree, trgSym, defaultGetter,
- result.take(defaultGetter.tpe.params.size).toList.map(_.ref))
- }, {
- // Otherwise, unbox the argument
- verifiedArg
- })(verifiedArg.tpe)
- } else {
- // Otherwise, it is always the unboxed argument
- verifiedArg
- }
-
- result +=
- js.VarDef(js.Ident("prep"+jsArg.ident.name, jsArg.ident.originalName),
- verifiedOrDefault.tpe, mutable = false, verifiedOrDefault)
- }
-
- result.toList
- }
-
- /** Generate the final forwarding call to the exported method.
- * Attention: This method casts the arguments to the right type. The IR
- * checker will not detect if you pass in a wrongly typed argument.
- */
- private def genResult(sym: Symbol,
- args: List[js.Tree])(implicit pos: Position) = {
- val thisType =
- if (sym.owner == ObjectClass) jstpe.ClassType(ir.Definitions.ObjectClass)
- else encodeClassType(sym.owner)
- val call = genApplyMethod(js.This()(thisType), sym.owner, sym, args)
- ensureBoxed(call,
- enteringPhase(currentRun.posterasurePhase)(sym.tpe.resultType))
- }
-
- private sealed abstract class Exported {
- def pos: Position
- def params: List[Type]
- def body: js.Tree
- def name: String
- def typeInfo: String
- def hasRepeatedParam: Boolean
- }
-
- private case class ExportedSymbol(sym: Symbol) extends Exported {
- def pos: Position = sym.pos
- def params: List[Type] = sym.tpe.params.map(_.tpe)
- def body: js.Tree = genApplyForSym(sym)
- def name: String = sym.name.toString
- def typeInfo: String = sym.tpe.toString
- def hasRepeatedParam: Boolean = GenJSExports.this.hasRepeatedParam(sym)
- }
-
- private case class ExportedBody(params: List[Type], body: js.Tree,
- name: String, pos: Position) extends Exported {
- def typeInfo: String = params.mkString("(", ", ", ")")
- val hasRepeatedParam: Boolean = false
- }
- }
-
- private def isOverridingExport(sym: Symbol): Boolean = {
- lazy val osym = sym.nextOverriddenSymbol
- sym.isOverridingSymbol && !osym.owner.isInterface
- }
-
- private sealed abstract class RTTypeTest
-
- private final case class HijackedTypeTest(
- boxedClassName: String, rank: Int) extends RTTypeTest
-
- private final case class InstanceOfTypeTest(tpe: Type) extends RTTypeTest {
- override def equals(that: Any): Boolean = {
- that match {
- case InstanceOfTypeTest(thatTpe) => tpe =:= thatTpe
- case _ => false
- }
- }
- }
-
- private case object NoTypeTest extends RTTypeTest
-
- private object RTTypeTest {
- implicit object Ordering extends PartialOrdering[RTTypeTest] {
- override def tryCompare(lhs: RTTypeTest, rhs: RTTypeTest): Option[Int] = {
- if (lteq(lhs, rhs)) if (lteq(rhs, lhs)) Some(0) else Some(-1)
- else if (lteq(rhs, lhs)) Some(1) else None
- }
-
- override def lteq(lhs: RTTypeTest, rhs: RTTypeTest): Boolean = {
- (lhs, rhs) match {
- // NoTypeTest is always last
- case (_, NoTypeTest) => true
- case (NoTypeTest, _) => false
-
- case (HijackedTypeTest(_, rank1), HijackedTypeTest(_, rank2)) =>
- rank1 <= rank2
-
- case (InstanceOfTypeTest(t1), InstanceOfTypeTest(t2)) =>
- t1 <:< t2
-
- case (_:HijackedTypeTest, _:InstanceOfTypeTest) => true
- case (_:InstanceOfTypeTest, _:HijackedTypeTest) => false
- }
- }
-
- override def equiv(lhs: RTTypeTest, rhs: RTTypeTest): Boolean = {
- lhs == rhs
- }
- }
- }
-
- // Very simple O(n²) topological sort for elements assumed to be distinct
- private def topoSortDistinctsBy[A <: AnyRef, B](coll: List[A])(f: A => B)(
- implicit ord: PartialOrdering[B]): List[A] = {
-
- @scala.annotation.tailrec
- def loop(coll: List[A], acc: List[A]): List[A] = {
- if (coll.isEmpty) acc
- else if (coll.tail.isEmpty) coll.head :: acc
- else {
- val (lhs, rhs) = coll.span(x => !coll.forall(
- y => (x eq y) || !ord.lteq(f(x), f(y))))
- assert(!rhs.isEmpty, s"cycle while ordering $coll")
- loop(lhs ::: rhs.tail, rhs.head :: acc)
- }
- }
-
- loop(coll, Nil)
- }
-
- private def typeTestForTpe(tpe: Type): RTTypeTest = {
- tpe match {
- case tpe: ErasedValueType =>
- InstanceOfTypeTest(tpe.valueClazz.typeConstructor)
-
- case _ =>
- import ir.{Definitions => Defs}
- (toTypeKind(tpe): @unchecked) match {
- case VoidKind => HijackedTypeTest(Defs.BoxedUnitClass, 0)
- case BooleanKind => HijackedTypeTest(Defs.BoxedBooleanClass, 1)
- case ByteKind => HijackedTypeTest(Defs.BoxedByteClass, 2)
- case ShortKind => HijackedTypeTest(Defs.BoxedShortClass, 3)
- case IntKind => HijackedTypeTest(Defs.BoxedIntegerClass, 4)
- case FloatKind => HijackedTypeTest(Defs.BoxedFloatClass, 5)
- case DoubleKind => HijackedTypeTest(Defs.BoxedDoubleClass, 6)
-
- case CharKind => InstanceOfTypeTest(boxedClass(CharClass).tpe)
- case LongKind => InstanceOfTypeTest(boxedClass(LongClass).tpe)
-
- case REFERENCE(cls) =>
- if (cls == StringClass) HijackedTypeTest(Defs.StringClass, 7)
- else if (cls == ObjectClass) NoTypeTest
- else if (isRawJSType(tpe)) {
- cls match {
- case JSUndefinedClass => HijackedTypeTest(Defs.BoxedUnitClass, 0)
- case JSBooleanClass => HijackedTypeTest(Defs.BoxedBooleanClass, 1)
- case JSNumberClass => HijackedTypeTest(Defs.BoxedDoubleClass, 6)
- case JSStringClass => HijackedTypeTest(Defs.StringClass, 7)
- case _ => NoTypeTest
- }
- } else InstanceOfTypeTest(tpe)
-
- case ARRAY(_) => InstanceOfTypeTest(tpe)
- }
- }
- }
-
- // Group-by that does not rely on hashCode(), only equals() - O(n²)
- private def groupByWithoutHashCode[A, B](
- coll: List[A])(f: A => B): List[(B, List[A])] = {
-
- import scala.collection.mutable.ArrayBuffer
- val m = new ArrayBuffer[(B, List[A])]
- m.sizeHint(coll.length)
-
- for (elem <- coll) {
- val key = f(elem)
- val index = m.indexWhere(_._1 == key)
- if (index < 0) m += ((key, List(elem)))
- else m(index) = (key, elem :: m(index)._2)
- }
-
- m.toList
- }
-
- private def genThrowTypeError(msg: String = "No matching overload")(
- implicit pos: Position): js.Tree = {
- js.Throw(js.StringLiteral(msg))
- }
-
- private def genFormalArgs(count: Int)(implicit pos: Position): List[js.ParamDef] =
- (1 to count map genFormalArg).toList
-
- private def genFormalArg(index: Int)(implicit pos: Position): js.ParamDef =
- js.ParamDef(js.Ident("arg$" + index), jstpe.AnyType, mutable = false)
-
- private def hasRepeatedParam(sym: Symbol) =
- enteringPhase(currentRun.uncurryPhase) {
- sym.paramss.flatten.lastOption.exists(isRepeated _)
- }
+object System {
+ def a[@b T] = 1
}
diff --git a/scalaParser/src/test/scala/scalaParser/SyntaxTest.scala b/scalaParser/src/test/scala/scalaParser/SyntaxTest.scala
index 45f86b2..0f9b734 100644
--- a/scalaParser/src/test/scala/scalaParser/SyntaxTest.scala
+++ b/scalaParser/src/test/scala/scalaParser/SyntaxTest.scala
@@ -8,6 +8,13 @@ import utest.util.Tree
import scala.util.{Failure, Success}
object SyntaxTest extends TestSuite{
+ def checkNeg[T](input: String) = {
+ println("Checking...")
+ new ScalaSyntax(input).CompilationUnit.run() match{
+ case Failure(f: ParseError) => () // yay
+ case Success(parsed) => assert(parsed.length != input.length)
+ }
+ }
def check[T](input: String) = {
println("Checking...")
new ScalaSyntax(input).CompilationUnit.run() match{
@@ -27,429 +34,546 @@ object SyntaxTest extends TestSuite{
println("running")
def tests = TestSuite{
'unit {
- * - check(
- "package torimatomeru"
-
- )
- * - check(
- """package torimatomeru
- |
- |package lols
- """.stripMargin
- )
- * - check(
- """package torimatomeru
- |import a
- |import b
- """.stripMargin
- )
- * - check(
- """
- |package torimatomeru
- |
- |import org.parboiled2.ParseError
- |import utest._
- |import utest.framework.Test
- |import utest.util.Tree
- |
- |import scala.util.{Failure, Success}
- |
- |object SyntaxTest extends TestSuite
- """.stripMargin
- )
- * - check(
- """
- |object SyntaxTest extends TestSuite{
- | def check[T](input: String) = {
- |
- | }
- |}
- """.stripMargin
- )
- * - check(
- """
- |object SyntaxTest{
- | a()
- | throw 1
- |}
- """.stripMargin
- )
- * - check(
- """
- |object SyntaxTest extends TestSuite{
- | {
- | println
- | throw 1
- | }
- |}
- """.stripMargin
- )
- * - check(
- """package scalatex
- |
- |
- |import org.parboiled2._
- |import torimatomeru.ScalaSyntax
- |
- |import scalatex.stages.{Trim, Parser, Ast}
- |import scalatex.stages.Ast.Block.{IfElse, For, Text}
- |import Ast.Chain.Args
- |
- |object ParserTests extends utest.TestSuite{
- | import Ast._
- | import utest._
- | def check[T](input: String, parse: Parser => scala.util.Try[T], expected: T) = {
- | val parsed = parse(new Parser(input)).get
- | assert(parsed == expected)
- | }
- | def tests = TestSuite{}
- |}
- """.stripMargin
- )
- * - check(
- """
- |object Moo{
- | a
- | .b
- |
- | c
- |}
- """.stripMargin
- )
- * - check(
- """
- |object Moo{
- | filename
- | .asInstanceOf[Literal]
- |10
- |}
- """.stripMargin
- )
- * - check(
- """
- |object Cow{
- | ().mkString
- |
- | 1
- |}
- """.stripMargin
- )
- * - check(
- """
- |object O{
- | private[this] val applyMacroFull = 1
- |}
- """.stripMargin
- )
- * - check(
- """
- |object O{
- | private[this] def applyMacroFull(c: Context)
- | (expr: c.Expr[String],
- | runtimeErrors: Boolean,
- | debug: Boolean)
- | : c.Expr[Frag] = {
- | }
- |}
- """.stripMargin
- )
- * - check(
- """
- |object O{
- | class DebugFailure extends Exception
- |
- | 1
- |}
- """.stripMargin
- )
- * - check(
- """
- |package torimatomeru
- |
- |package syntax
- |
- |import org.parboiled2._
- |
- """.stripMargin
- )
- * - check(
- """
- |object Foo{
- | 0 match {
- | case A | B => 0
- | }
- |}
- """.stripMargin
- )
- * - check(
- """
- |object Compiler{
- |
- | def apply = {
- | def rec = t match {
- | case 0 => 0
- | }
- |
- | rec(tree)
- | }
- |}
- |
- """.stripMargin
- )
- * - check(
- """
- |object O {
- | A(A(A(A(A(A(A(A())))))))
- |}
- |
- """.stripMargin
- )
- * - check(
- """
- |object O{
- | A(A(A(A(A(A(A(A(A(A(A(A(A(A(A(A())))))))))))))))
- |}
- """.stripMargin
- )
- * - check(
- """
- |object L{
- | a.b = c
- | a().b = c
- |}
- """.stripMargin
- )
- * - check(
- """
- |object L{
- | a b c
- | d = 1
- |}
- """.stripMargin
- )
+ 'pos {
+ * - check(
+ "package torimatomeru"
- * - check(
- """/* __ *\
- |** ________ ___ / / ___ __ ____ Scala.js CLI **
- |** / __/ __// _ | / / / _ | __ / // __/ (c) 2013-2014, LAMP/EPFL **
- |** __\ \/ /__/ __ |/ /__/ __ |/_// /_\ \ http://scala-js.org/ **
- |** /____/\___/_/ |_/____/_/ | |__/ /____/ **
- |** |/____/ **
- |\* */
+ )
+ * - check(
+ """package torimatomeru
+ |
+ |package lols
+ """.stripMargin
+ )
+ * - check(
+ """package torimatomeru
+ |import a
+ |import b
+ """.stripMargin
+ )
+ * - check(
+ """
+ |package torimatomeru
+ |
+ |import org.parboiled2.ParseError
+ |import utest._
+ |import utest.framework.Test
+ |import utest.util.Tree
+ |
+ |import scala.util.{Failure, Success}
+ |
+ |object SyntaxTest extends TestSuite
+ """.stripMargin
+ )
+ * - check(
+ """
+ |object SyntaxTest extends TestSuite{
+ | def check[T](input: String) = {
+ |
+ | }
+ |}
+ """.stripMargin
+ )
+ * - check(
+ """
+ |object SyntaxTest{
+ | a()
+ | throw 1
+ |}
+ """.stripMargin
+ )
+ * - check(
+ """
+ |object SyntaxTest extends TestSuite{
+ | {
+ | println
+ | throw 1
+ | }
+ |}
+ """.stripMargin
+ )
+ * - check(
+ """package scalatex
+ |
+ |
+ |import org.parboiled2._
+ |import torimatomeru.ScalaSyntax
+ |
+ |import scalatex.stages.{Trim, Parser, Ast}
+ |import scalatex.stages.Ast.Block.{IfElse, For, Text}
+ |import Ast.Chain.Args
+ |
+ |object ParserTests extends utest.TestSuite{
+ | import Ast._
+ | import utest._
+ | def check[T](input: String, parse: Parser => scala.util.Try[T], expected: T) = {
+ | val parsed = parse(new Parser(input)).get
+ | assert(parsed == expected)
+ | }
+ | def tests = TestSuite{}
+ |}
+ """.stripMargin
+ )
+ * - check(
+ """
+ |object Moo{
+ | a
+ | .b
+ |
+ | c
+ |}
+ """.stripMargin
+ )
+ * - check(
+ """
+ |object Moo{
+ | filename
+ | .asInstanceOf[Literal]
+ |10
+ |}
+ """.stripMargin
+ )
+ * - check(
+ """
+ |object Cow{
+ | ().mkString
+ |
+ | 1
+ |}
+ """.stripMargin
+ )
+ * - check(
+ """
+ |object O{
+ | private[this] val applyMacroFull = 1
+ |}
+ """.stripMargin
+ )
+ * - check(
+ """
+ |object O{
+ | private[this] def applyMacroFull(c: Context)
+ | (expr: c.Expr[String],
+ | runtimeErrors: Boolean,
+ | debug: Boolean)
+ | : c.Expr[Frag] = {
+ | }
+ |}
+ """.stripMargin
+ )
+ * - check(
+ """
+ |object O{
+ | class DebugFailure extends Exception
+ |
+ | 1
+ |}
+ """.stripMargin
+ )
+ * - check(
+ """
+ |package torimatomeru
+ |
+ |package syntax
+ |
+ |import org.parboiled2._
+ |
+ """.stripMargin
+ )
+ * - check(
+ """
+ |object Foo{
+ | 0 match {
+ | case A | B => 0
+ | }
+ |}
+ """.stripMargin
+ )
+ * - check(
+ """
+ |object Compiler{
|
- |package scala.scalajs.cli
+ | def apply = {
+ | def rec = t match {
+ | case 0 => 0
+ | }
|
- """.stripMargin
- )
- * - check(
- """
- |object O{
- | for {
- | a <- b
- | c <- d
- | } {
- | 1
+ | rec(tree)
| }
|}
- """.stripMargin
- )
- * - check(
- """
- |object O{
- | val jarFile =
- | try { 1 }
- | catch { case _: F => G }
- |}
- """.stripMargin
- )
- * - check(
- """
- |object F{
- | func{ case _: F => fail }
- |}
- """.stripMargin
- )
- * - check(
- """
- |object Foo{
- | val a = d // g
- | val b = e // h
- | val c = f
- |}
- """.stripMargin
- )
- * - check(
- """
- |object L{
- | x match{
- | case y.Y(z) => z
- | }
- |}
- """.stripMargin
- )
- * - check(
- """object K{
- | val a: B {
- | val c: D
- | }
- |
- | 1
- |}
- """.stripMargin
- )
- * - check(
- """
- |object LOLS{
- | def run() {}
- |
- | def apply() {}
- |}
- """.stripMargin
- )
- * - check(
- """
- |object O{
- | a =:= b.c
- |}
- """.stripMargin
- )
- * - check(
- """
- |object K{
- | a(
- | 1: _*
- | )
- |}
- """.stripMargin
- )
- * - check(
- """
- |object P{
- | tree match {
- | case stats :+ expr => 1
- | }
- |}
- """.stripMargin
- )
- * - check(
- """
- |object K{
- | val trueA = 1
- |}
- """.stripMargin
- )
- * - check(
- """
- |object K{
- | val nullo :: cow = 1
- |}
- """.stripMargin
- )
- * - check(
- """
- |object K{
- | val omg_+ = 1
- |}
- """.stripMargin
- )
- * - check(
- """
- |object K{
- | val + = 1
- | var * = 2
- |}
- """.stripMargin
- )
- * - check(
- """
- |object O{
- | c match {
- | case b_ => 1
- | }
- |}
- """.stripMargin
- )
- * - check(
- """
- |trait Basic {
- | b match {
- | case C => true; case _ => false
- | }
- |}
- """.stripMargin
- )
- * - check(
- """trait Basic {
- | !a.b
- |}
- """.stripMargin
- )
- * - check(
- """
- |class Parser {
- | {() => }
- |}
- |
- """.stripMargin
- )
- * - check(
- """
- |
- |
- |
- |package omg
- |;
- |
- |;
- |
- |;
- |class Parser
- |;
- |
- |;
|
- |;
- """.stripMargin
- )
- * - check(
- """
- |
- |object GenJSCode {
- | code: @switch
- |}
- """.stripMargin
- )
- * - check(
- """object B {
- | { a: L => }
- |}
- """.stripMargin
- )
- * - check(
- """object O{
- | {
- | val index = 0
- | i: Int => 10
- | 0
- | }
- |}
- """.stripMargin
- )
- * - check(
- """object GenJSCode{
- | val g: G.this.g.type
- |}
- |
- """.stripMargin
- )
- * - check(
- """object K{
- | class RTTypeTest
- | private object O
- |}
- """.stripMargin
- )
+ """.
+ stripMargin
+ )
+ * - check(
+ """
+ |object O {
+ | A(A(A(A(A(A(A(A())))))))
+ |}
+ |
+ """.stripMargin
+ )
+ * - check(
+ """
+ |object O{
+ | A(A(A(A(A(A(A(A(A(A(A(A(A(A(A(A())))))))))))))))
+ |}
+ """.stripMargin
+ )
+ * - check(
+ """
+ |object L{
+ | a.b = c
+ | a().b = c
+ |}
+ """.stripMargin
+ )
+ * - check(
+ """
+ |object L{
+ | a b c
+ | d = 1
+ |}
+ """.stripMargin
+ )
+ * - check(
+ """/* __ *\
+ |** ________ ___ / / ___ __ ____ Scala.js CLI **
+ |** / __/ __// _ | / / / _ | __ / // __/ (c) 2013-2014, LAMP/EPFL **
+ |** __\ \/ /__/ __ |/ /__/ __ |/_// /_\ \ http://scala-js.org/ **
+ |** /____/\___/_/ |_/____/_/ | |__/ /____/ **
+ |** |/____/ **
+ |\* */
+ |
+ |package scala.scalajs.cli
+ |
+ """.stripMargin
+ )
+ * - check(
+ """
+ |object O{
+ | for {
+ | a <- b
+ | c <- d
+ | } {
+ | 1
+ | }
+ |}
+ """.stripMargin
+ )
+ * - check(
+ """
+ |object O{
+ | val jarFile =
+ | try { 1 }
+ | catch { case _: F => G }
+ |}
+ """.stripMargin
+ )
+ * - check(
+ """
+ |object F{
+ | func{ case _: F => fail }
+ |}
+ """.stripMargin
+ )
+ * - check(
+ """
+ |object Foo{
+ | val a = d // g
+ | val b = e // h
+ | val c = f
+ |}
+ """.stripMargin
+ )
+ * - check(
+ """
+ |object L{
+ | x match{
+ | case y.Y(z) => z
+ | }
+ |}
+ """.stripMargin
+ )
+ * - check(
+ """object K{
+ | val a: B {
+ | val c: D
+ | }
+ |
+ | 1
+ |}
+ """.stripMargin
+ )
+ * - check(
+ """
+ |object LOLS{
+ | def run() {}
+ |
+ | def apply() {}
+ |}
+ """.stripMargin
+ )
+ * - check(
+ """
+ |object O{
+ | a =:= b.c
+ |}
+ """.stripMargin
+ )
+ * - check(
+ """
+ |object K{
+ | a(
+ | 1: _*
+ | )
+ |}
+ """.stripMargin
+ )
+ * - check(
+ """
+ |object P{
+ | tree match {
+ | case stats :+ expr => 1
+ | }
+ |}
+ """.stripMargin
+ )
+ * - check(
+ """
+ |object K{
+ | val trueA = 1
+ |}
+ """.stripMargin
+ )
+ * - check(
+ """
+ |object K{
+ | val nullo :: cow = 1
+ |}
+ """.stripMargin
+ )
+ * - check(
+ """
+ |object K{
+ | val omg_+ = 1
+ |}
+ """.stripMargin
+ )
+ * - check(
+ """
+ |object K{
+ | val + = 1
+ | var * = 2
+ |}
+ """.stripMargin
+ )
+ * - check(
+ """
+ |object O{
+ | c match {
+ | case b_ => 1
+ | }
+ |}
+ """.stripMargin
+ )
+ * - check(
+ """
+ |trait Basic {
+ | b match {
+ | case C => true; case _ => false
+ | }
+ |}
+ """.stripMargin
+ )
+ * - check(
+ """trait Basic {
+ | !a.b
+ |}
+ """.stripMargin
+ )
+ * - check(
+ """
+ |class Parser {
+ | {() => }
+ |}
+ |
+ """.stripMargin
+ )
+ * - check(
+ """
+ |
+ |
+ |
+ |package omg
+ |;
+ |
+ |;
+ |
+ |;
+ |class Parser
+ |;
+ |
+ |;
+ |
+ |;
+ """.stripMargin
+ )
+ * - check(
+ """
+ |
+ |object GenJSCode {
+ | code: @switch
+ |}
+ """.stripMargin
+ )
+ * - check(
+ """object B {
+ | { a: L => }
+ |}
+ """.stripMargin
+ )
+ * - check(
+ """object O{
+ | {
+ | val index = 0
+ | i: Int => 10
+ | 0
+ | }
+ |}
+ """.stripMargin
+ )
+ * - check(
+ """object GenJSCode{
+ | val g: G.this.g.type
+ |}
+ |
+ """.stripMargin
+ )
+ * - check(
+ """object K{
+ | class RTTypeTest
+ | private object O
+ |}
+ """.stripMargin
+ )
+ * - check(
+ """object O{
+ | if (eqeq &&
+ |
+ | false) 1
+ |}
+ """.stripMargin
+ )
+ * - check(
+ """
+ |object O{
+ | for(
+ | x <- Nil map
+ |
+ | (x => x)
+ | ) yield x
+ |}
+ """.stripMargin
+ )
+ * - check(
+ """
+ |object O{
+ | for{
+ | x <- Nil
+ | if
+ |
+ | 1 == 2
+ | } yield x
+ |}
+ """.stripMargin
+ )
+ * - check(
+ """
+ |object ScopedVar {
+ | def withScopedVars(ass: Seq[_]) = 1
+ |}
+ |
+ """.stripMargin
+ )
+ * - check(
+ """
+ |abstract class JSASTTest extends DirectTest {
+ | def show: this.type = ()
+ |}
+ |
+ """.stripMargin
+ )
+ * - check(
+ """object Traversers {
+ | {
+ | 1
+ | cases foreach nil
+ | }
+ |}
+ """.stripMargin
+ )
+ * - check(
+ """object Utils {
+ | "\\"
+ |}
+ |
+ """.stripMargin
+ )
+ * - check(
+ """object F{
+ | this eq that.asInstanceOf[AnyRef]
+ |}
+ """.stripMargin
+ )
+ * - check(
+ """class C{
+ | 0x00 <= 2 && 1
+ |}
+ |
+ """.stripMargin
+ )
+ * - check(
+ """class Runtime private
+ """.stripMargin
+ )
+ }
+ 'neg{
+ * - checkNeg(
+ """
+ |object O{
+ | for{
+ | x <- Nil map
+ |
+ | (x => x)
+ | } yield x
+ |}
+ """.stripMargin
+ )
+ * - checkNeg(
+ """object O{
+ | for{
+ | x <- Nil
+ | if 1 ==
+ |
+ | 2
+ | } yield x
+ |}
+ """.stripMargin
+ )
+ * - checkNeg(
+ """object O{
+ | for{
+ | x <- Nil
+ | _ = 1 ==
+ |
+ | 2
+ | } yield x
+ |}
+ """.stripMargin
+ )
+ }
}
def checkFile(path: String) = check(io.Source.fromFile(path).mkString)
'file{