diff options
author | Li Haoyi <haoyi@dropbox.com> | 2014-12-28 09:15:07 +0100 |
---|---|---|
committer | Li Haoyi <haoyi@dropbox.com> | 2014-12-28 09:15:07 +0100 |
commit | 8eba9de819131993fd056a8833fb384de0904a8c (patch) | |
tree | 6defbb256def036644167b3f77e7e1814c103ada /scalatex/api/src/main | |
parent | a84c09efcb2d843ee04ee3299ceb592a00a42267 (diff) | |
download | hands-on-scala-js-8eba9de819131993fd056a8833fb384de0904a8c.tar.gz hands-on-scala-js-8eba9de819131993fd056a8833fb384de0904a8c.tar.bz2 hands-on-scala-js-8eba9de819131993fd056a8833fb384de0904a8c.zip |
Remove Scalatex from source tree (it's now in a separate project)
Diffstat (limited to 'scalatex/api/src/main')
4 files changed, 0 insertions, 400 deletions
diff --git a/scalatex/api/src/main/scala/scalatex/package.scala b/scalatex/api/src/main/scala/scalatex/package.scala deleted file mode 100644 index 1f13e63..0000000 --- a/scalatex/api/src/main/scala/scalatex/package.scala +++ /dev/null @@ -1,98 +0,0 @@ -import scala.reflect.internal.util.{BatchSourceFile, SourceFile, OffsetPosition} -import scala.reflect.io.{PlainFile, AbstractFile} -import scala.reflect.macros.{TypecheckException, Context} -import scalatags.Text.all._ -import scalatex.stages.{Parser, Compiler} -import scala.language.experimental.macros -import acyclic.file - -package object scalatex { - /** - * Wraps the given string as a twist fragment. - */ - def tw(expr: String): Frag = macro Internals.applyMacro - def twf(filename: String): Frag = macro Internals.applyMacroFile - object Internals { - - def twRuntimeErrors(expr: String): Frag = macro applyMacroRuntimeErrors - def twDebug(expr: String): Frag = macro applyMacroDebug - - def applyMacro(c: Context)(expr: c.Expr[String]): c.Expr[Frag] = applyMacroFull(c)(expr, false, false) - def applyMacroDebug(c: Context)(expr: c.Expr[String]): c.Expr[Frag] = applyMacroFull(c)(expr, false, true) - - def applyMacroRuntimeErrors(c: Context)(expr: c.Expr[String]): c.Expr[Frag] = applyMacroFull(c)(expr, true, false) - - def applyMacroFile(c: Context)(filename: c.Expr[String]): c.Expr[Frag] = { - import c.universe._ - val fileName = filename.tree - .asInstanceOf[Literal] - .value - .value - .asInstanceOf[String] - val txt = io.Source.fromFile(fileName).mkString - val sourceFile = new BatchSourceFile( - new PlainFile(fileName), - txt.toCharArray - ) - - compileThing(c)(txt, sourceFile, 0, false, false) - } - - case class DebugFailure(msg: String, pos: String) extends Exception(msg) - - private[this] def applyMacroFull(c: Context) - (expr: c.Expr[String], - runtimeErrors: Boolean, - debug: Boolean) - : c.Expr[Frag] = { - import c.universe._ - val scalatexFragment = expr.tree - .asInstanceOf[Literal] - .value - .value - .asInstanceOf[String] - val stringStart = - expr.tree - .pos - .lineContent - .drop(expr.tree.pos.column) - .take(2) - compileThing(c)( - scalatexFragment, - expr.tree.pos.source, - expr.tree.pos.point + (if (stringStart == "\"\"") 1 else -1), - runtimeErrors, - debug - ) - } - } - - def compileThing(c: Context) - (scalatexSource: String, - source: SourceFile, - point: Int, - runtimeErrors: Boolean, - debug: Boolean) = { - import c.universe._ - def compile(s: String): c.Tree = { - val realPos = new OffsetPosition(source, point).asInstanceOf[c.universe.Position] - - Compiler(c)(realPos, Parser.tupled(stages.Trim(s))) - } - - - import c.Position - try { - val compiled = compile(scalatexSource) - if (debug) println(compiled) - c.Expr[Frag](c.typeCheck(compiled)) - } catch { - case e@TypecheckException(pos: Position, msg) => - if (!runtimeErrors) c.abort(pos, msg) - else { - val posMsg = pos.lineContent + "\n" + (" " * pos.column) + "^" - c.Expr( q"""throw scalatex.Internals.DebugFailure($msg, $posMsg)""") - } - } - } -} diff --git a/scalatex/api/src/main/scala/scalatex/stages/Compiler.scala b/scalatex/api/src/main/scala/scalatex/stages/Compiler.scala deleted file mode 100644 index 3df8da7..0000000 --- a/scalatex/api/src/main/scala/scalatex/stages/Compiler.scala +++ /dev/null @@ -1,103 +0,0 @@ -package scalatex -package stages - -import acyclic.file - -import scala.reflect.macros.whitebox.Context -import scala.reflect.internal.util.{Position, OffsetPosition} - -/** - * Walks the parsed AST, converting it into a structured Scala c.Tree - */ -object Compiler{ - - def apply(c: Context)(fragPos: c.Position, template: Ast.Block): c.Tree = { - - import c.universe._ - def fragType = tq"scalatags.Text.all.Frag" - - def incPosRec(trees: c.Tree, offset: Int): trees.type = { - - trees.foreach(incPos(_, offset)) - trees - } - def incPos(tree: c.Tree, offset: Int): tree.type = { - - val current = if (tree.pos == NoPosition) 0 else tree.pos.point - c.internal.setPos(tree, - new OffsetPosition( - fragPos.source, - offset + current + fragPos.point - ).asInstanceOf[c.universe.Position] - ) - tree - } - - def compileChain(code: String, parts: Seq[Ast.Chain.Sub], offset: Int): c.Tree = { - - val out = parts.foldLeft(incPosRec(c.parse(code), offset + 1)){ - case (curr, Ast.Chain.Prop(str, offset2)) => - incPos(q"$curr.${TermName(str)}", offset2 + 1) - case (curr, Ast.Chain.Args(str, offset2)) => - val Apply(fun, args) = c.parse(s"omg$str") - incPos(Apply(curr, args.map(incPosRec(_, offset2 - 2))), offset2) - case (curr, Ast.Chain.TypeArgs(str, offset2)) => - val TypeApply(fun, args) = c.parse(s"omg$str") - incPos(TypeApply(curr, args.map(incPosRec(_, offset2 - 2))), offset2) - case (curr, Ast.Block(parts, offset1)) => - incPos(q"$curr(..${compileBlock(parts, offset1)})", offset1) - case (curr, Ast.Header(header, block, offset1)) => - incPos(q"$curr(${compileHeader(header, block, offset1)})", offset1) - } - - out - } - def compileBlock(parts: Seq[Ast.Block.Sub], offset: Int): Seq[c.Tree] = { - val res = parts.map{ - case Ast.Block.Text(str, offset1) => - incPos(q"$str", offset1) - case Ast.Chain(code, parts, offset1) => - compileChain(code, parts, offset1) - case Ast.Header(header, block, offset1) => - compileHeader(header, block, offset1) - case Ast.Block.IfElse(condString, Ast.Block(parts2, offset2), elseBlock, offset1) => - val If(cond, _, _) = c.parse(condString + "{}") - val elseCompiled = elseBlock match{ - case Some(Ast.Block(parts3, offset3)) => compileBlockWrapped(parts3, offset3) - case None => EmptyTree - } - - val res = If(incPosRec(cond, offset1 + 2), compileBlockWrapped(parts2, offset2), elseCompiled) - - incPos(res, offset1) - res - case Ast.Block.For(generators, Ast.Block(parts2, offset2), offset1) => - val fresh = c.fresh() - - val tree = incPosRec(c.parse(s"$generators yield $fresh"), offset1 + 2) - - def rec(t: Tree): Tree = t match { - case a @ Apply(fun, List(f @ Function(vparams, body))) => - val f2 = Function(vparams, rec(body)) - val a2 = Apply(fun, List(f2)) - a2 - case Ident(x: TermName) if x.decoded == fresh => - compileBlockWrapped(parts2, offset2) - } - - rec(tree) - } - res - } - def compileBlockWrapped(parts: Seq[Ast.Block.Sub], offset: Int): c.Tree = { - incPos(q"Seq[$fragType](..${compileBlock(parts, offset)})", offset) - } - def compileHeader(header: String, block: Ast.Block, offset: Int): c.Tree = { - val Block(stmts, expr) = c.parse(s"{$header\n ()}") - Block(stmts, compileBlockWrapped(block.parts, block.offset)) - } - - val res = compileBlockWrapped(template.parts, template.offset) - res - } -}
\ No newline at end of file diff --git a/scalatex/api/src/main/scala/scalatex/stages/Parser.scala b/scalatex/api/src/main/scala/scalatex/stages/Parser.scala deleted file mode 100644 index 0b87d97..0000000 --- a/scalatex/api/src/main/scala/scalatex/stages/Parser.scala +++ /dev/null @@ -1,170 +0,0 @@ -package scalatex -package stages -import acyclic.file -import org.parboiled2._ -import scalaParser.ScalaSyntax - -/** - * Parses the input text into a roughly-structured AST. This AST - * is much simpler than the real Scala AST, but serves us well - * enough until we stuff the code-strings into the real Scala - * parser later - */ -object Parser extends ((String, Int) => Ast.Block){ - def apply(input: String, offset: Int = 0): Ast.Block = { - new Parser(input, offset).Body.run().get - } -} -class Parser(input: ParserInput, indent: Int = 0, offset: Int = 0) extends scalaParser.ScalaSyntax(input) { - def offsetCursor = offset + cursor - val txt = input.sliceString(0, input.length) - val indentTable = txt.split('\n').map{ s => - if (s.trim == "") -1 - else s.takeWhile(_ == ' ').length - } - val nextIndentTable = (0 until indentTable.length).map { i => - val index = indentTable.indexWhere(_ != -1, i + 1) - if (index == -1) 100000 - else indentTable(index) - } - def cursorNextIndent() = { - nextIndentTable(txt.take(cursor).count(_ == '\n')) - } - - def TextNot(chars: String) = rule { - push(offsetCursor) ~ capture(oneOrMore(noneOf(chars + "\n") | "@@")) ~> { - (i, x) => Ast.Block.Text(x.replace("@@", "@"), i) - } - } - def Text = TextNot("@") - def Code = rule { - "@" ~ capture(Identifiers.Id | BlockExpr2 | ('(' ~ optional(Exprs) ~ ')')) - } - def Header = rule { - "@" ~ capture(Def | Import) - } - - def HeaderBlock: Rule1[Ast.Header] = rule{ - Header ~ zeroOrMore(capture(WL) ~ Header ~> (_ + _)) ~ runSubParser{new Parser(_, indent, cursor).Body0} ~> { - (start: String, heads: Seq[String], body: Ast.Block) => Ast.Header(start + heads.mkString, body) - } - } - - def BlankLine = rule{ '\n' ~ zeroOrMore(' ') ~ &('\n') } - def IndentSpaces = rule{ indent.times(' ') ~ zeroOrMore(' ') } - def Indent = rule{ '\n' ~ IndentSpaces } - def LoneScalaChain: Rule2[Ast.Block.Text, Ast.Chain] = rule { - (push(offsetCursor) ~ capture(Indent) ~> ((i, x) => Ast.Block.Text(x, i))) ~ - ScalaChain ~ - IndentBlock ~> { - (chain: Ast.Chain, body: Ast.Block) => chain.copy(parts = chain.parts :+ body) - } - } - def IndentBlock = rule{ - &("\n") ~ - test(cursorNextIndent() > indent) ~ - runSubParser(new Parser(_, cursorNextIndent(), cursor).Body) - } - def IfHead = rule{ "@" ~ capture("if" ~ "(" ~ Expr ~ ")") } - def IfElse1 = rule{ - push(offsetCursor) ~ IfHead ~ BraceBlock ~ optional("else" ~ (BraceBlock | IndentBlock)) - } - def IfElse2 = rule{ - Indent ~ push(offsetCursor) ~ IfHead ~ IndentBlock ~ optional(Indent ~ "@else" ~ (BraceBlock | IndentBlock)) - } - def IfElse = rule{ - (IfElse1 | IfElse2) ~> ((a, b, c, d) => Ast.Block.IfElse(b, c, d, a)) - } - - def ForHead = rule{ - push(offsetCursor) ~ "@" ~ capture("for" ~ '(' ~ Enumerators ~ ')') - } - def ForLoop = rule{ - ForHead ~ - BraceBlock ~> ((a, b, c) => Ast.Block.For(b, c, a)) - } - def LoneForLoop = rule{ - (push(offsetCursor) ~ capture(Indent) ~> ((i, t) => Ast.Block.Text(t, i))) ~ - ForHead ~ - IndentBlock ~> - ((a, b, c) => Ast.Block.For(b, c, a)) - } - - def ScalaChain = rule { - push(offsetCursor) ~ Code ~ zeroOrMore(Extension) ~> { (a, b, c) => Ast.Chain(b, c, a)} - } - def Extension: Rule1[Ast.Chain.Sub] = rule { - (push(offsetCursor) ~ '.' ~ capture(Identifiers.Id) ~> ((x, y) => Ast.Chain.Prop(y, x))) | - (push(offsetCursor) ~ capture(TypeArgs2) ~> ((x, y) => Ast.Chain.TypeArgs(y, x))) | - (push(offsetCursor) ~ capture(ArgumentExprs2) ~> ((x, y) => Ast.Chain.Args(y, x))) | - BraceBlock - } - def Ws = WL - // clones of the version in ScalaSyntax, but without tailing whitespace or newlines - def TypeArgs2 = rule { '[' ~ Ws ~ Types ~ ']' } - def ArgumentExprs2 = rule { - '(' ~ Ws ~ - (optional(Exprs ~ ',' ~ Ws) ~ PostfixExpr ~ ':' ~ Ws ~ '_' ~ Ws ~ '*' ~ Ws | optional(Exprs) ) ~ - ')' - } - def BlockExpr2: Rule0 = rule { '{' ~ Ws ~ (CaseClauses | Block) ~ Ws ~ '}' } - def BraceBlock: Rule1[Ast.Block] = rule{ '{' ~ BodyNoBrace ~ '}' } - - def BodyItem(exclusions: String): Rule1[Seq[Ast.Block.Sub]] = rule{ - ForLoop ~> (Seq(_)) | - LoneForLoop ~> (Seq(_, _)) | - IfElse ~> (Seq(_)) | - LoneScalaChain ~> (Seq(_, _)) | - HeaderBlock ~> (Seq(_)) | - TextNot("@" + exclusions) ~> (Seq(_)) | - (push(offsetCursor) ~ capture(Indent) ~> ((i, x) => Seq(Ast.Block.Text(x, i)))) | - (push(offsetCursor) ~ capture(BlankLine) ~> ((i, x) => Seq(Ast.Block.Text(x, i)))) | - ScalaChain ~> (Seq(_: Ast.Block.Sub)) - } - def Body = rule{ BodyEx() } - def BodyNoBrace = rule{ BodyEx("}") } - def BodyEx(exclusions: String = "") = rule{ - push(offsetCursor) ~ oneOrMore(BodyItem(exclusions)) ~> {(i, x) => - Ast.Block(x.flatten, i) - } - } - def Body0 = rule{ - push(offsetCursor) ~ zeroOrMore(BodyItem("")) ~> {(i, x) => - Ast.Block(x.flatten, i) - } - } -} - -trait Ast{ - def offset: Int -} -object Ast{ - - /** - * @param parts The various bits of text and other things which make up this block - * @param offset - */ - 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 For(generators: String, block: Block, offset: Int = 0) extends Block.Sub - case class IfElse(condition: String, block: Block, elseBlock: Option[Block], 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 - * @param offset - */ - case class Chain(lhs: String, parts: Seq[Chain.Sub], offset: Int = 0) extends Block.Sub - object Chain{ - trait Sub extends Ast - case class Prop(str: String, offset: Int = 0) extends Sub - case class TypeArgs(str: String, offset: Int = 0) extends Sub - case class Args(str: String, offset: Int = 0) extends Sub - } -} diff --git a/scalatex/api/src/main/scala/scalatex/stages/Trim.scala b/scalatex/api/src/main/scala/scalatex/stages/Trim.scala deleted file mode 100644 index 8993734..0000000 --- a/scalatex/api/src/main/scala/scalatex/stages/Trim.scala +++ /dev/null @@ -1,29 +0,0 @@ -package scalatex.stages -import acyclic.file - -/** - * Preprocesses the input string to normalize things related to whitespace - * - * Find the "first" non-whitespace-line of the text and remove the front - * of every line to align that first line with the left margin. - * - * Remove all trailing whitespace from each line. - */ -object Trim extends (String => (String, Int)){ - def apply(str: String) = { - val lines = str.split("\n", -1) - val offset = lines.iterator - .filter(_.length > 0) - .next() - .takeWhile(_ == ' ') - .length - val res = lines.iterator - .map(_.replaceFirst("\\s+$", "")) - .mkString("\n") - (res, offset) - } - def old(str: String) = { - val (res, offset) = this.apply(str) - res.split("\n", -1).map(_.drop(offset)).mkString("\n") - } -} |