summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLi Haoyi <haoyi@dropbox.com>2014-11-28 04:56:22 -0800
committerLi Haoyi <haoyi@dropbox.com>2014-11-28 04:56:22 -0800
commit5ef6a1dd630764a1ffa6c3b68fff1649c9d89934 (patch)
treeca39750b6d421c99bc320b356dd8babadb2b917b
parent142fdb8404a95b6d587766b7820b56e121337c7d (diff)
downloadhands-on-scala-js-5ef6a1dd630764a1ffa6c3b68fff1649c9d89934.tar.gz
hands-on-scala-js-5ef6a1dd630764a1ffa6c3b68fff1649c9d89934.tar.bz2
hands-on-scala-js-5ef6a1dd630764a1ffa6c3b68fff1649c9d89934.zip
Removed a bunch of unnecessary `WL`s
-rw-r--r--scalaParser/src/main/scala/scalaParser/ScalaSyntax.scala158
-rw-r--r--scalaParser/src/main/scala/scalaParser/syntax/Literals.scala7
-rw-r--r--scalaParser/src/test/resources/test.scala751
-rw-r--r--scalaParser/src/test/scala/scalaParser/SyntaxTest.scala956
4 files changed, 631 insertions, 1241 deletions
diff --git a/scalaParser/src/main/scala/scalaParser/ScalaSyntax.scala b/scalaParser/src/main/scala/scalaParser/ScalaSyntax.scala
index 8dfe6e7..fe30606 100644
--- a/scalaParser/src/main/scala/scalaParser/ScalaSyntax.scala
+++ b/scalaParser/src/main/scala/scalaParser/ScalaSyntax.scala
@@ -78,24 +78,27 @@ class ScalaSyntax(val input: ParserInput) extends Parser with Basic with Identif
def StableId: R0 = {
def ClassQualifier = rule { '[' ~ Id ~ ']' }
rule {
- zeroOrMore(Id ~ '.') ~ (K.W("this") | K.W("super") ~ optional(ClassQualifier)) ~ '.' ~ oneOrMore(Id).separatedBy('.') |
- Id ~ zeroOrMore(WL ~ '.' ~ WL ~ Id)
+ zeroOrMore(Id ~ '.') ~ (K.W("this") | K.W("super") ~ optional(ClassQualifier)) ~ zeroOrMore('.' ~ Id) |
+ Id ~ zeroOrMore('.' ~ Id)
}
}
def Type: R0 = {
+ def WildcardType: R0 = rule{ K.W("_") }
def ExistentialDcl = rule { K.W("type") ~ TypeDcl | K.W("val") ~ ValDcl }
def ExistentialClause = rule { "forSome" ~ '{' ~ oneOrMore(ExistentialDcl).separatedBy(Semi) }
def FunctionArgTypes = rule {
InfixType | '(' ~ optional(oneOrMore(ParamType) separatedBy ',') ~ ')'
}
rule {
- FunctionArgTypes ~ K.O("=>") ~ Type | InfixType ~ optional(WL ~ ExistentialClause)
+ (WildcardType |
+ FunctionArgTypes ~ K.O("=>") ~ Type |
+ InfixType ~ optional(ExistentialClause)) ~ TypeBounds
}
}
def InfixType = rule {
- CompoundType ~ zeroOrMore(WL ~ Id ~ OneNewlineMax ~ CompoundType)
+ CompoundType ~ zeroOrMore(Id ~ OneNewlineMax ~ CompoundType)
}
def CompoundType = {
def RefineStat = rule { "type" ~ TypeDef | Dcl | MATCH }
@@ -103,11 +106,11 @@ class ScalaSyntax(val input: ParserInput) extends Parser with Basic with Identif
OneNewlineMax ~ '{' ~ oneOrMore(RefineStat).separatedBy(Semi) ~ "}"
}
rule {
- oneOrMore(AnnotType).separatedBy(WL ~ K.W("with")) ~ optional(Refinement)
+ oneOrMore(AnnotType).separatedBy(K.W("with")) ~ optional(Refinement)
}
}
def AnnotType = rule {
- SimpleType ~ zeroOrMore(WL ~ Annotation)
+ SimpleType ~ zeroOrMore(Annotation)
}
def SimpleType: R0 = {
def BasicType: R0 = rule {
@@ -117,8 +120,8 @@ class ScalaSyntax(val input: ParserInput) extends Parser with Basic with Identif
}
rule {
BasicType ~
- optional(WL ~ '#' ~ Id) ~
- optional(WL ~ TypeArgs)
+ optional('#' ~ Id) ~
+ optional(TypeArgs)
}
}
@@ -147,53 +150,56 @@ class ScalaSyntax(val input: ParserInput) extends Parser with Basic with Identif
K.O("=>")
}
}
- def Enumerators: R0 = {
- def Generator: R0 = rule { Pattern1 ~ K.O("<-") ~ Expr ~ optional(WL ~ Guard) }
- def Enumerator: R0 = rule { Generator | Guard | Pattern1 ~ K.O("=") ~ Expr }
- rule { Generator ~ zeroOrMore(Semi ~ Enumerator) ~ WL }
+ def Enumerators(G: Boolean = false): R0 = {
+ def Generator: R0 = rule { Pattern1 ~ K.O("<-") ~ Expr0(G) ~ optional(Guard(G)) }
+ def Enumerator: R0 = rule { Generator | Guard(G) | Pattern1 ~ K.O("=") ~ Expr0(G) }
+ rule { Generator ~ zeroOrMore(Semis ~ Enumerator) ~ WL }
}
- def Expr: R0 = {
- def IfCFlow = rule { "if" ~ '(' ~ Expr ~ ')' ~ Expr ~ optional(optional(Semi) ~ K.W("else") ~ Expr) }
- def WhileCFlow = rule { "while" ~ '(' ~ Expr ~ ')' ~ Expr }
+ def Expr = Expr0()
+ def ExprSensitive = Expr0(true)
+ def Expr0(G: Boolean = false): R0 = {
+ def IfCFlow = rule { "if" ~ '(' ~ Expr ~ ')' ~ Expr0(G) ~ optional(optional(Semi) ~ K.W("else") ~ Expr0(G)) }
+ def WhileCFlow = rule { "while" ~ '(' ~ Expr ~ ')' ~ Expr0(G) }
def TryCFlow = rule {
- K.W("try") ~ Expr ~
- optional(WL ~ K.W("catch") ~ Expr) ~
- optional(WL ~ K.W("finally") ~ Expr)
+ K.W("try") ~ Expr0(G) ~
+ optional(K.W("catch") ~ Expr0(G)) ~
+ optional(K.W("finally") ~ Expr0(G))
}
- def DoWhileCFlow = rule { K.W("do") ~ Expr ~ optional(Semi) ~ "while" ~ '(' ~ Expr ~ ")" }
+ def DoWhileCFlow = rule { K.W("do") ~ Expr0(G) ~ optional(Semi) ~ "while" ~ '(' ~ Expr ~ ")" }
def ForCFlow = {
rule {
"for" ~
- ('(' ~ Enumerators ~ ')' | '{' ~ Enumerators ~ '}') ~
+ ('(' ~ Enumerators() ~ ')' | '{' ~ Enumerators(G = true) ~ '}') ~
optional(K.W("yield")) ~
- Expr
+ Expr0(G)
}
}
rule {
zeroOrMore(LambdaHead) ~ (
IfCFlow |
- WhileCFlow |
- TryCFlow |
- DoWhileCFlow |
- ForCFlow |
- K.W("throw") ~ Expr |
- K.W("return") ~ optional(Expr) |
- SimpleExpr ~ K.O("=") ~ Expr |
- PostfixExpr ~ optional("match" ~ '{' ~ CaseClauses ~ "}" | Ascription)
- )
+ WhileCFlow |
+ TryCFlow |
+ DoWhileCFlow |
+ ForCFlow |
+ K.W("throw") ~ Expr0(G) |
+ K.W("return") ~ optional(Expr0(G)) |
+ SimpleExpr ~ K.O("=") ~ Expr0(G) |
+ PostfixExpr(G) ~ optional("match" ~ '{' ~ CaseClauses ~ "}" | Ascription)
+ )
}
}
- def PostfixExpr: R0 = {
+ def PostfixExpr(G: Boolean = false): R0 = {
def PrefixExpr = rule { optional(WL ~ anyOf("-+~!")) ~ SimpleExpr }
+ def Check = if (G) OneNewlineMax else MATCH
def InfixExpr: R0 = rule {
PrefixExpr ~
zeroOrMore(
NotNewline ~
Id ~
- OneNewlineMax ~
+ Check ~
PrefixExpr
)
}
@@ -202,21 +208,21 @@ class ScalaSyntax(val input: ParserInput) extends Parser with Basic with Identif
def SimpleExpr: R0 = {
def Path: R0 = rule {
- zeroOrMore(Id ~ '.') ~ K.W("this") ~ zeroOrMore(Id).separatedBy('.') |
- StableId
+ zeroOrMore(Id ~ '.') ~ K.W("this") ~ zeroOrMore('.' ~ Id) |
+ StableId
}
def SimpleExpr1 = rule{
K.W("new") ~ (ClassTemplate | TemplateBody) |
- BlockExpr |
- Literal |
- Path |
- K.W("_") |
- '(' ~ optional(Exprs) ~ ")"
+ BlockExpr |
+ Literal |
+ Path |
+ K.W("_") |
+ '(' ~ optional(Exprs) ~ ")"
}
rule {
SimpleExpr1 ~
- zeroOrMore(WL ~ ('.' ~ Id | TypeArgs | ArgumentExprs)) ~
- optional(WL ~ "_")
+ zeroOrMore('.' ~ Id | TypeArgs | ArgumentExprs) ~
+ optional( "_")
}
}
@@ -232,14 +238,15 @@ class ScalaSyntax(val input: ParserInput) extends Parser with Basic with Identif
def BlockStat: R0 = rule {
Import |
- zeroOrMore(Annotation) ~ (optional(K.W("implicit") | K.W("lazy")) ~ Def | zeroOrMore(LocalModifier) ~ TmplDef) |
- Expr
+ zeroOrMore(Annotation) ~ (optional(K.W("implicit") | K.W("lazy")) ~ Def | zeroOrMore(LocalModifier) ~ TmplDef) |
+ Expr0(true)
}
rule{ oneOrMore(BlockStat).separatedBy(Semis) }
}
def Block: R0 = {
- def BlockEnd: R0 = rule{ optional(Semis) ~ &("}" | "case") }
+ def BlockEnd: R0 = rule{ optional(Semis) ~ &("}" | K.W("case")) }
+ def ResultExpr: R0 = Expr0(true)
rule {
zeroOrMore(LambdaHead) ~
optional(Semis) ~
@@ -251,14 +258,14 @@ class ScalaSyntax(val input: ParserInput) extends Parser with Basic with Identif
}
}
- def ResultExpr: R0 = Expr
+
def CaseClauses: R0 = {
- def CaseClause: R0 = rule { K.W("case") ~ Pattern ~ optional(Guard) ~ K.O("=>") ~ Block }
+ def CaseClause: R0 = rule { K.W("case") ~ Pattern ~ optional(Guard()) ~ K.O("=>") ~ Block }
rule { oneOrMore(CaseClause) }
}
- def Guard: R0 = rule { K.W("if") ~ PostfixExpr }
+ def Guard(G: Boolean = false): R0 = rule { K.W("if") ~ PostfixExpr(G) }
def Pattern: R0 = rule {
oneOrMore(Pattern1).separatedBy('|')
}
@@ -296,14 +303,16 @@ class ScalaSyntax(val input: ParserInput) extends Parser with Basic with Identif
rule { '[' ~ oneOrMore(VariantTypeParam).separatedBy(',') ~ ']' }
}
def FunTypeParamClause: R0 = rule { '[' ~ oneOrMore(TypeParam).separatedBy(',') ~ ']' }
-
+ def TypeBounds: R0 = rule{
+ optional(K.O(">:") ~ Type) ~
+ optional(K.O("<:") ~ Type)
+ }
def TypeParam: R0 = rule {
(Id | K.W("_")) ~
- optional(TypeParamClause) ~
- optional(K.O(">:") ~ Type) ~
- optional(K.O("<:") ~ Type) ~
- zeroOrMore(K.O("<%") ~ Type) ~
- zeroOrMore(K.O(":") ~ Type)
+ optional(TypeParamClause) ~
+ TypeBounds ~
+ zeroOrMore(K.O("<%") ~ Type) ~
+ zeroOrMore(K.O(":") ~ Type)
}
def ParamClauses: R0 = rule {
zeroOrMore(ParamClause) ~ optional(OneNewlineMax ~ '(' ~ K.W("implicit") ~ Params ~ ')')
@@ -330,7 +339,7 @@ class ScalaSyntax(val input: ParserInput) extends Parser with Basic with Identif
rule { (K.W("private") | K.W("protected")) ~ optional(AccessQualifier) }
}
- def Annotation: R0 = rule { '@' ~ SimpleType ~ zeroOrMore(WL ~ ArgumentExprs) }
+ def Annotation: R0 = rule { '@' ~ SimpleType ~ zeroOrMore(ArgumentExprs) }
def TemplateBody: R0 = rule {
'{' ~
@@ -358,7 +367,7 @@ class ScalaSyntax(val input: ParserInput) extends Parser with Basic with Identif
def Dcl: R0 = {
def VarDcl: R0 = rule { Ids ~ K.O(":") ~ Type }
- def FunDcl: R0 = rule { FunSig ~ optional(WL ~ K.O(":") ~ Type) }
+ def FunDcl: R0 = rule { FunSig ~ optional(K.O(":") ~ Type) }
rule {
K.W("val") ~ ValDcl |
@@ -371,9 +380,8 @@ class ScalaSyntax(val input: ParserInput) extends Parser with Basic with Identif
def ValDcl: R0 = rule { Ids ~ K.O(":") ~ Type }
def TypeDcl: R0 = rule {
Id ~
- optional(WL ~ TypeParamClause) ~
- optional(WL ~ K.O(">:") ~ Type) ~
- optional(WL ~ K.O("<:") ~ Type)
+ optional(TypeParamClause) ~
+ TypeBounds
}
def PatVarDef: R0 = {
@@ -399,7 +407,7 @@ class ScalaSyntax(val input: ParserInput) extends Parser with Basic with Identif
def TmplDef: R0 = {
def TraitTemplate: R0 = {
def TraitParents: R0 = rule {
- AnnotType ~ zeroOrMore(WL ~ K.W("with") ~ AnnotType)
+ AnnotType ~ zeroOrMore(K.W("with") ~ AnnotType)
}
rule{ optional(EarlyDefs) ~ TraitParents ~ optional(TemplateBody) }
}
@@ -411,24 +419,28 @@ class ScalaSyntax(val input: ParserInput) extends Parser with Basic with Identif
ClassParam ~
")"
}
- def ConstrPrelude: R0 = {
- def Annot: R0 = rule { '@' ~ SimpleType ~ ArgumentExprs }
- rule{ zeroOrMore(Annot) ~ optional(AccessModifier) }
- }
+
def ClassParamClause: R0 = {
def ClassParams: R0 = rule { oneOrMore(ClassParam).separatedBy(',') }
rule { OneNewlineMax ~'(' ~ optional(ClassParams) ~ ")" }
}
rule {
- ConstrPrelude ~ (
- oneOrMore(ClassParamClause) ~ optional(Implicit) |
- Implicit
- )
+ oneOrMore(ClassParamClause) ~ optional(Implicit) | Implicit
+ }
+ }
+ def ConstrPrelude: R0 = {
+ def Annot: R0 = rule { '@' ~ SimpleType ~ ArgumentExprs }
+ rule{
+ NotNewline ~ (
+ oneOrMore(Annot) ~ optional(AccessModifier) |
+ zeroOrMore(Annot) ~ AccessModifier
+ )
}
}
def ClassDef: R0 = rule {
Id ~
optional(TypeParamClause) ~
+ optional(ConstrPrelude) ~
optional(ClassParamClauses) ~
ClassTemplateOpt
}
@@ -448,16 +460,16 @@ class ScalaSyntax(val input: ParserInput) extends Parser with Basic with Identif
def ObjectDef: R0 = rule { Id ~ ClassTemplateOpt }
def ClassTemplateOpt: R0 = rule {
- WL ~ K.W("extends") ~ ClassTemplate |
- optional(WL ~ optional(K.W("extends")) ~ TemplateBody)
+ K.W("extends") ~ ClassTemplate |
+ optional(optional(K.W("extends")) ~ TemplateBody)
}
def ClassTemplate: R0 = {
def ClassParents: R0 = {
- def Constr: R0 = rule{ AnnotType ~ zeroOrMore(WL ~ ArgumentExprs) }
- rule{ Constr ~ zeroOrMore(WL ~ K.W("with") ~ AnnotType) }
+ def Constr: R0 = rule{ AnnotType ~ zeroOrMore(ArgumentExprs) }
+ rule{ Constr ~ zeroOrMore(K.W("with") ~ AnnotType) }
}
- rule{ optional(EarlyDefs) ~ ClassParents ~ optional(WL ~ TemplateBody) }
+ rule{ optional(EarlyDefs) ~ ClassParents ~ optional(TemplateBody) }
}
def EarlyDefs: R0 = {
@@ -491,7 +503,7 @@ class ScalaSyntax(val input: ParserInput) extends Parser with Basic with Identif
optional(Semis) ~
(TopPackageSeq ~ optional(Semis ~ TopStatSeq) | TopStatSeq) ~
optional(Semis) ~
- WL ~ EOI
+ WL
)
}
}
diff --git a/scalaParser/src/main/scala/scalaParser/syntax/Literals.scala b/scalaParser/src/main/scala/scalaParser/syntax/Literals.scala
index 9fd9d5b..4e3d119 100644
--- a/scalaParser/src/main/scala/scalaParser/syntax/Literals.scala
+++ b/scalaParser/src/main/scala/scalaParser/syntax/Literals.scala
@@ -16,7 +16,7 @@ trait Literals { self: Parser with Basic with Identifiers =>
)
}
- def IntegerLiteral = rule { (DecimalNumeral | HexNumeral) ~ optional(anyOf("Ll")) }
+ def IntegerLiteral = rule { (HexNumeral | DecimalNumeral) ~ optional(anyOf("Ll")) }
def BooleanLiteral = rule { Key.W("true") | Key.W("false") }
@@ -36,7 +36,7 @@ trait Literals { self: Parser with Basic with Identifiers =>
}
- def EscapedChars = rule { '\\' ~ anyOf("rnt\\\"") }
+ def EscapedChars = rule { '\\' ~ anyOf("rnt\\\"") }
// Note that symbols can take on the same values as keywords!
def SymbolLiteral = rule { ''' ~ (Identifiers.PlainId | Identifiers.Keywords) }
@@ -44,9 +44,10 @@ trait Literals { self: Parser with Basic with Identifiers =>
def CharacterLiteral = rule { ''' ~ (UnicodeExcape | EscapedChars | !'\\' ~ CharPredicate.from(isPrintableChar)) ~ ''' }
def MultiLineChars = rule { zeroOrMore(optional('"') ~ optional('"') ~ noneOf("\"")) }
+ def pr(s: String) = rule { run(println(s"LOGGING $cursor: $s")) }
def StringLiteral = rule {
(optional(Identifiers.Id) ~ "\"\"\"" ~ MultiLineChars ~ ("\"\"\"" ~ zeroOrMore('"'))) |
- (optional(Identifiers.Id) ~ '"' ~ zeroOrMore("\\\"" | noneOf("\n\"")) ~ '"')
+ (optional(Identifiers.Id) ~ '"' ~ zeroOrMore("\\\"" | "\\\\" | noneOf("\n\"")) ~ '"')
}
def isPrintableChar(c: Char): Boolean = {
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{