summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLi Haoyi <haoyi@dropbox.com>2014-11-04 00:03:13 -0800
committerLi Haoyi <haoyi@dropbox.com>2014-11-04 00:03:13 -0800
commit84d025280986302c0435a5910a6a3c9c34d8fc8c (patch)
treef194b1c44f7b48ecfc3a7252edf256a7da041f26
parent9d9cd46a6ccc5bbe8b22dc38f615b532e526774c (diff)
downloadhands-on-scala-js-84d025280986302c0435a5910a6a3c9c34d8fc8c.tar.gz
hands-on-scala-js-84d025280986302c0435a5910a6a3c9c34d8fc8c.tar.bz2
hands-on-scala-js-84d025280986302c0435a5910a6a3c9c34d8fc8c.zip
Inline definition-statements now work and are tested.
-rw-r--r--scalatexApi/src/main/scala/scalatex/stages/Compiler.scala23
-rw-r--r--scalatexApi/src/main/scala/scalatex/stages/Parser.scala19
-rw-r--r--scalatexApi/src/main/scala/torimatomeru/ScalaSyntax.scala2
-rw-r--r--scalatexApi/src/test/scala/scalatex/BasicTests.scala90
-rw-r--r--scalatexApi/src/test/scala/scalatex/ParserTests.scala45
5 files changed, 121 insertions, 58 deletions
diff --git a/scalatexApi/src/main/scala/scalatex/stages/Compiler.scala b/scalatexApi/src/main/scala/scalatex/stages/Compiler.scala
index 5704b2c..0ac9844 100644
--- a/scalatexApi/src/main/scala/scalatex/stages/Compiler.scala
+++ b/scalatexApi/src/main/scala/scalatex/stages/Compiler.scala
@@ -25,18 +25,29 @@ object Compiler{
case (curr, Ast.Chain.TypeArgs(str, offset2)) =>
val TypeApply(fun, args) = c.parse(s"omg$str")
TypeApply(curr, args)
- case (curr, Ast.Block(front, parts, offset)) =>
- q"$curr(..${compileBlock(front, parts, offset)})"
+ case (curr, Ast.Block(parts, offset)) =>
+ q"$curr(..${compileBlock(parts, offset)})"
+ case (curr, Ast.Header(header, block, offset)) =>
+ q"$curr(${compileHeader(header, block, offset)})"
+
}
}
- def compileBlock(front: Option[String], parts: Seq[Ast.Block.Sub], offset: Int): Seq[c.Tree] = {
+ def compileBlock(parts: Seq[Ast.Block.Sub], offset: Int): Seq[c.Tree] = {
parts.map{
- case Ast.Block.Text(str, offset2) => q"$str"
+ case Ast.Block.Text(str, _) => q"$str"
case Ast.Chain(code, parts, offset) => compileChain(code, parts, offset)
-
+ case Ast.Header(header, block, offset) => compileHeader(header, block, offset)
}
}
- val res = q"Seq[$fragType](..${compileBlock(None, template.parts, template.offset)})"
+ def compileHeader(header: String, block: Ast.Block, offset: Int): c.Tree = {
+ val Block(stmts, expr) = c.parse(s"{$header\n ()}")
+ Block(stmts, wrapBlock(compileBlock(block.parts, block.offset)))
+ }
+
+ def wrapBlock(items: Seq[c.Tree]) = {
+ q"Seq[$fragType](..$items)"
+ }
+ val res = wrapBlock(compileBlock(template.parts, template.offset))
println("::::::::::::::::::::::::::::::::::::::::::::::::")
println(res)
println("::::::::::::::::::::::::::::::::::::::::::::::::")
diff --git a/scalatexApi/src/main/scala/scalatex/stages/Parser.scala b/scalatexApi/src/main/scala/scalatex/stages/Parser.scala
index 91738a7..e54cb6b 100644
--- a/scalatexApi/src/main/scala/scalatex/stages/Parser.scala
+++ b/scalatexApi/src/main/scala/scalatex/stages/Parser.scala
@@ -44,9 +44,9 @@ class Parser(input: ParserInput, indent: Int = 0) extends ScalaSyntax(input) {
"@" ~ capture(Def | Import)
}
- def HeaderBlock: Rule1[Ast.Block] = rule{
- oneOrMore(Header ~ NewlineS) ~ runSubParser{new Parser(_, indent).Body0} ~> {
- (head: Seq[String], body: Ast.Block) => body.copy(front = Some(head.mkString("\n")))
+ def HeaderBlock: Rule1[Ast.Header] = rule{
+ Header ~ zeroOrMore(capture(NewlineS) ~ Header ~> (_ + _)) ~ runSubParser{new Parser(_, indent).Body0} ~> {
+ (start: String, heads: Seq[String], body: Ast.Block) => Ast.Header(start + heads.mkString, body)
}
}
@@ -92,12 +92,12 @@ class Parser(input: ParserInput, indent: Int = 0) extends ScalaSyntax(input) {
}
def Body = rule{
oneOrMore(BodyItem) ~> {x =>
- Ast.Block(None, x.flatten)
+ Ast.Block(x.flatten)
}
}
def Body0 = rule{
zeroOrMore(BodyItem) ~> {x =>
- Ast.Block(None, x.flatten)
+ Ast.Block(x.flatten)
}
}
}
@@ -108,21 +108,18 @@ trait Ast{
object Ast{
/**
- * @param front Any parameter lists (if it's a lambda), imports, val/def/lazy-val,
- * class/object/trait declarations that occur before the parts of this
- * block, and must be in scope within those parts
* @param parts The various bits of text and other things which make up this block
* @param offset
*/
- case class Block(front: Option[String],
- parts: Seq[Block.Sub],
+ case class Block(parts: Seq[Block.Sub],
offset: Int = 0)
extends Chain.Sub with Block.Sub
object Block{
trait Sub extends Ast
case class Text(txt: String, offset: Int = 0) extends Block.Sub
- }
+ }
+ case class Header(front: String, block: Block, offset: Int = 0) extends Block.Sub with Chain.Sub
/**
* @param lhs The first expression in this method-chain
* @param parts A list of follow-on items chained to the first
diff --git a/scalatexApi/src/main/scala/torimatomeru/ScalaSyntax.scala b/scalatexApi/src/main/scala/torimatomeru/ScalaSyntax.scala
index 5bbd0af..bf0e0e2 100644
--- a/scalatexApi/src/main/scala/torimatomeru/ScalaSyntax.scala
+++ b/scalatexApi/src/main/scala/torimatomeru/ScalaSyntax.scala
@@ -166,7 +166,7 @@ class ScalaSyntax(val input: ParserInput) extends Parser with Basic with Identif
def Params: Rule0 = rule { zeroOrMore(Param).separatedBy(',') }
def Param: Rule0 = rule { zeroOrMore(Annotation) ~ IdS ~ optional(':' ~ ParamType) ~ optional('=' ~ Expr) }
def ClassParamClauses: Rule0 = rule { zeroOrMore(ClassParamClause) ~ optional(optional(NewlineS) ~ '(' ~ "implicit" ~ ClassParam ~ ')') }
- def ClassParamClause: Rule0 = rule { optional(NewlineS) ~ '(' ~ optional(ClassParam) ~ ')' }
+ def ClassParamClause: Rule0 = rule { optional(NewlineS) ~ '(' ~ optional(ClassParams) ~ ')' }
def ClassParams: Rule0 = rule { oneOrMore(ClassParam).separatedBy(',') }
def ClassParam: Rule0 = rule { zeroOrMore(Annotation) ~ optional(zeroOrMore(Modifier) ~ ("val" | "var")) ~ IdS ~ ":" ~ ParamType ~ optional("=" ~ Expr) }
diff --git a/scalatexApi/src/test/scala/scalatex/BasicTests.scala b/scalatexApi/src/test/scala/scalatex/BasicTests.scala
index c7e2d6a..8acb9b7 100644
--- a/scalatexApi/src/test/scala/scalatex/BasicTests.scala
+++ b/scalatexApi/src/test/scala/scalatex/BasicTests.scala
@@ -48,28 +48,74 @@ object BasicTests extends TestSuite{
"""
)
}
-// 'imports{
-// object Whee{
-// def func(x: Int) = x * 2
-// }
-// check(
-// tw("""
-// @import math._
-// @import Whee.func
-// @abs(-10)
-// @p
-// @max(1, 2)
-// @func(2)
-// """),
-// """
-// 10
-// <p>
-// 2
-// 4
-// </p>
-// """
-// )
-// }
+ 'definitions{
+ 'imports{
+ object Whee{
+ def func(x: Int) = x * 2
+ }
+ check(
+ tw("""
+ @import math._
+ @import Whee.func
+ @abs(-10)
+ @p
+ @max(1, 2)
+ @func(2)
+ """),
+ """
+ 10
+ <p>
+ 2
+ 4
+ </p>
+ """
+ )
+ }
+ 'valDefVar{
+ check(
+ tw("""
+ Hello
+ @val x = 1
+ World @x
+ @def y = "omg"
+ mooo
+ @y
+ """),
+ """
+ Hello
+ World 1
+ mooo
+ omg
+ """
+ )
+ }
+ 'classObjectTrait{
+ check(
+ tw("""
+ @trait Trait{
+ def tt = 2
+ }
+ Hello
+ @case object moo extends Trait{
+ val omg = "wtf"
+ }
+
+ @moo.toString
+ @moo.omg
+ @case class Foo(i: Int, s: String, b: Boolean)
+ TT is @moo.tt
+ @Foo(10, "10", true).toString
+ """),
+ """
+ Hello
+ moo
+ wtf
+ TT is 2
+ Foo(10, 10, true)
+ """
+ )
+ }
+ }
'parenArgumentLists{
'attributes{
check(
diff --git a/scalatexApi/src/test/scala/scalatex/ParserTests.scala b/scalatexApi/src/test/scala/scalatex/ParserTests.scala
index f6d443f..9301755 100644
--- a/scalatexApi/src/test/scala/scalatex/ParserTests.scala
+++ b/scalatexApi/src/test/scala/scalatex/ParserTests.scala
@@ -12,8 +12,8 @@ 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))
- assert(parsed.get == expected)
+ val parsed = parse(new Parser(input)).get
+ assert(parsed == expected)
}
def tests = TestSuite{
'Trim{
@@ -100,18 +100,28 @@ object ParserTests extends utest.TestSuite{
|hello world
|""".stripMargin,
_.HeaderBlock.run(),
- Ast.Block(
- Some("import math.abs\nimport math.sin"),
- Seq(Text("\n"), Text("hello world"), Text("\n"))
+ Ast.Header(
+ "import math.abs\nimport math.sin",
+ Ast.Block(
+ Seq(Text("\n"), Text("\n"), Text("hello world"), Text("\n"))
+ )
)
)
}
+ 'caseclass{
+ check(
+ """@case class Foo(i: Int, s: String)
+ """.stripMargin,
+ _.Header.run(),
+ "case class Foo(i: Int, s: String)"
+ )
+ }
}
'Block{
- * - check("{i am a cow}", _.TBlock.run(), Block(None, Seq(Block.Text("i am a cow"))))
+ * - check("{i am a cow}", _.TBlock.run(), Block(Seq(Block.Text("i am a cow"))))
* - check("{i @am a @cow}", _.TBlock.run(),
- Block(None, Seq(
+ Block(Seq(
Block.Text("i "),
Chain("am",Seq()),
Block.Text(" a "),
@@ -131,10 +141,10 @@ object ParserTests extends utest.TestSuite{
)
* - check("@omg{bbq}.cow(moo){a @b}\n", _.ScalaChain.run(),
Chain("omg",Seq(
- Block(None, Seq(Block.Text("bbq"))),
+ Block(Seq(Block.Text("bbq"))),
Chain.Prop("cow"),
Chain.Args("(moo)"),
- Block(None, Seq(Block.Text("a "), Chain("b", Nil)))
+ Block(Seq(Block.Text("a "), Chain("b", Nil)))
))
)
}
@@ -146,13 +156,13 @@ object ParserTests extends utest.TestSuite{
| @bbq
| @lol""".stripMargin,
_.Body.run(),
- Block(None, Seq(
+ Block(Seq(
Text("\n"),
- Chain("omg",Seq(Block(None, Seq(
+ Chain("omg",Seq(Block(Seq(
Text("\n "),
- Chain("wtf",Seq(Block(None, Seq(
+ Chain("wtf",Seq(Block(Seq(
Text("\n "),
- Chain("bbq",Seq(Block(None, Seq(
+ Chain("bbq",Seq(Block(Seq(
Text("\n "),
Chain("lol",Seq())
))))
@@ -166,10 +176,9 @@ object ParserTests extends utest.TestSuite{
| @wtf
|@bbq""".stripMargin,
_.Body.run(),
- Block(None, Seq(
+ Block(Seq(
Text("\n"),
Chain("omg",Seq(Block(
- None,
Seq(
Text("\n "),
Chain("wtf",Seq()))
@@ -184,11 +193,11 @@ object ParserTests extends utest.TestSuite{
| @wtf
|bbq""".stripMargin,
_.Body.run(),
- Block(None, Seq(
+ Block(Seq(
Text("\n"),
Chain("omg",Seq(
Args("""("lol", 1, 2)"""),
- Block(None, Seq(
+ Block(Seq(
Text("\n "),
Chain("wtf",Seq())))
)),
@@ -224,7 +233,7 @@ object ParserTests extends utest.TestSuite{
| omg * 2
|}""".stripMargin,
_.Body.run(),
- Block(None, Seq(
+ Block(Seq(
Text("\n"),
Chain("{\"lol\" * 3}", Seq()),
Text("\n"),