Skip to content

Commit

Permalink
Move macro code to src-2 (#268)
Browse files Browse the repository at this point in the history
  • Loading branch information
lolgab authored Dec 27, 2022
1 parent 8927803 commit af4b47f
Show file tree
Hide file tree
Showing 4 changed files with 142 additions and 141 deletions.
11 changes: 5 additions & 6 deletions build.sc
Original file line number Diff line number Diff line change
Expand Up @@ -195,12 +195,11 @@ trait CommonCrossModule extends CrossScalaModule with PublishModule with Mima{

def platformSegment: String
def millSourcePath = super.millSourcePath / os.up
def sources = T.sources(
millSourcePath / "src",
millSourcePath / s"src-$platformSegment"
)


def sources = T.sources { super.sources() ++
Seq(
millSourcePath / s"src-$platformSegment"
).map(PathRef(_))
}
}
trait CommonTestModule extends ScalaModule with TestModule.Utest{

Expand Down
137 changes: 137 additions & 0 deletions fastparse/src-2/fastparse/internal/MacroRepImpls.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
package fastparse.internal

import scala.reflect.macros.blackbox.Context
import language.experimental.macros

/**
* Implementations of the various `.rep`/`.repX` overloads. The most common
* and simple overloads are implemented as macros for performance, while the
* more complex/general cases are left as normal methods to avoid code bloat
* and allow the use of default/named arguments (which don't work in macros
* due to https://github.com/scala/bug/issues/5920).
*
* Even the normal method overloads are manually-specialized to some extent
* for various sorts of inputs as a best-effort attempt ot minimize branching
* in the hot paths.
*/
object MacroRepImpls{
def repXMacro0[T: c.WeakTypeTag, V: c.WeakTypeTag](c: Context)
(whitespace: Option[c.Tree], min: Option[c.Tree])
(repeater: c.Tree,
ctx: c.Tree): c.Tree = {
import c.universe._
val repeater1 = TermName(c.freshName("repeater"))
val ctx1 = TermName(c.freshName("repeater"))
val acc = TermName(c.freshName("acc"))
val startIndex = TermName(c.freshName("startIndex"))
val count = TermName(c.freshName("count"))
val beforeSepIndex = TermName(c.freshName("beforeSepIndex"))
val rec = TermName(c.freshName("rec"))
val originalCut = TermName(c.freshName("originalCut"))
val parsedMsg = TermName(c.freshName("parsedMsg"))
val lastAgg = TermName(c.freshName("lastAgg"))
val parsedAgg = TermName(c.freshName("parsedAgg"))
val ((endSnippet, aggregateSnippet), minCut) = min match{
case None =>
q"""
$ctx1.freshSuccess($repeater1.result($acc), $startIndex, $originalCut)
""" ->
q""" "" """ ->
q"""false"""
case Some(min1) =>
q"""
if ($count < $min1) $ctx1.augmentFailure($startIndex, $originalCut)
else $ctx1.freshSuccess($repeater1.result($acc), $startIndex, $originalCut)
""" ->
q"""if($min1 == 0) "" else "(" + $min1 + ")"""" ->
q"""$originalCut && ($count < $min1)"""
}

val wsSnippet = whitespace match{
case None => q"$rec($beforeSepIndex, $count + 1, $parsedAgg)"
case Some(ws) =>
q"""
if ($ws ne _root_.fastparse.NoWhitespace.noWhitespaceImplicit) {
_root_.fastparse.internal.Util.consumeWhitespace($ws, $ctx1)
}
if (!$ctx1.isSuccess && $ctx1.cut) $ctx1.asInstanceOf[_root_.fastparse.ParsingRun[scala.Nothing]]
else{
$ctx1.cut = false
$rec($beforeSepIndex, $count + 1, $parsedAgg)
}
"""
}

q"""
$ctx match{ case $ctx1 =>
$repeater match {case $repeater1 =>
var $originalCut = $ctx1.cut
val $acc = $repeater1.initial
@_root_.scala.annotation.tailrec
def $rec($startIndex: _root_.scala.Int,
$count: _root_.scala.Int,
$lastAgg: _root_.fastparse.internal.Msgs): _root_.fastparse.P[${c.weakTypeOf[V]}] = {
$ctx1.cut = $minCut
${c.prefix}.parse0()

val $parsedMsg = $ctx1.shortParserMsg
val $parsedAgg = $ctx1.failureGroupAggregate
$originalCut |= $ctx1.cut
if (!$ctx1.isSuccess) {
val res =
if ($ctx1.cut) $ctx1.asInstanceOf[_root_.fastparse.P[${c.weakTypeOf[V]}]]
else $endSnippet
if ($ctx1.verboseFailures) {
$ctx1.aggregateMsg(
$startIndex,
() => $parsedMsg.render + s".rep" + $aggregateSnippet,
if ($lastAgg == null) $ctx1.failureGroupAggregate
else $ctx1.failureGroupAggregate ::: $lastAgg
)
}
res
}else {
val $beforeSepIndex = $ctx1.index
$repeater1.accumulate($ctx1.successValue.asInstanceOf[${c.weakTypeOf[T]}], $acc)
$ctx1.cut = false
$wsSnippet
}
}
$rec($ctx1.index, 0, null)
}
}
"""
}

def repXMacro1[T: c.WeakTypeTag, V: c.WeakTypeTag](c: Context)
(repeater: c.Tree,
ctx: c.Tree): c.Tree = {
import c.universe._
MacroRepImpls.repXMacro0[T, V](c)(None, None)(repeater, ctx)
}

def repXMacro2[T: c.WeakTypeTag, V: c.WeakTypeTag](c: Context)
(min: c.Tree)
(repeater: c.Tree,
ctx: c.Tree): c.Tree = {
import c.universe._
MacroRepImpls.repXMacro0[T, V](c)(None, Some(min))(repeater, ctx)
}

def repXMacro1ws[T: c.WeakTypeTag, V: c.WeakTypeTag](c: Context)
(repeater: c.Tree,
whitespace: c.Tree,
ctx: c.Tree): c.Tree = {
import c.universe._
MacroRepImpls.repXMacro0[T, V](c)(Some(whitespace), None)(repeater, ctx)
}

def repXMacro2ws[T: c.WeakTypeTag, V: c.WeakTypeTag](c: Context)
(min: c.Tree)
(repeater: c.Tree,
whitespace: c.Tree,
ctx: c.Tree): c.Tree = {
import c.universe._
MacroRepImpls.repXMacro0[T, V](c)(Some(whitespace), Some(min))(repeater, ctx)
}
}
135 changes: 0 additions & 135 deletions fastparse/src/fastparse/internal/RepImpls.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,141 +3,6 @@ package fastparse.internal
import fastparse.{Implicits, NoWhitespace, ParsingRun}

import scala.annotation.tailrec
import scala.reflect.macros.blackbox.Context
import language.experimental.macros

/**
* Implementations of the various `.rep`/`.repX` overloads. The most common
* and simple overloads are implemented as macros for performance, while the
* more complex/general cases are left as normal methods to avoid code bloat
* and allow the use of default/named arguments (which don't work in macros
* due to https://github.com/scala/bug/issues/5920).
*
* Even the normal method overloads are manually-specialized to some extent
* for various sorts of inputs as a best-effort attempt ot minimize branching
* in the hot paths.
*/
object MacroRepImpls{
def repXMacro0[T: c.WeakTypeTag, V: c.WeakTypeTag](c: Context)
(whitespace: Option[c.Tree], min: Option[c.Tree])
(repeater: c.Tree,
ctx: c.Tree): c.Tree = {
import c.universe._
val repeater1 = TermName(c.freshName("repeater"))
val ctx1 = TermName(c.freshName("repeater"))
val acc = TermName(c.freshName("acc"))
val startIndex = TermName(c.freshName("startIndex"))
val count = TermName(c.freshName("count"))
val beforeSepIndex = TermName(c.freshName("beforeSepIndex"))
val rec = TermName(c.freshName("rec"))
val originalCut = TermName(c.freshName("originalCut"))
val parsedMsg = TermName(c.freshName("parsedMsg"))
val lastAgg = TermName(c.freshName("lastAgg"))
val parsedAgg = TermName(c.freshName("parsedAgg"))
val ((endSnippet, aggregateSnippet), minCut) = min match{
case None =>
q"""
$ctx1.freshSuccess($repeater1.result($acc), $startIndex, $originalCut)
""" ->
q""" "" """ ->
q"""false"""
case Some(min1) =>
q"""
if ($count < $min1) $ctx1.augmentFailure($startIndex, $originalCut)
else $ctx1.freshSuccess($repeater1.result($acc), $startIndex, $originalCut)
""" ->
q"""if($min1 == 0) "" else "(" + $min1 + ")"""" ->
q"""$originalCut && ($count < $min1)"""
}

val wsSnippet = whitespace match{
case None => q"$rec($beforeSepIndex, $count + 1, $parsedAgg)"
case Some(ws) =>
q"""
if ($ws ne _root_.fastparse.NoWhitespace.noWhitespaceImplicit) {
_root_.fastparse.internal.Util.consumeWhitespace($ws, $ctx1)
}
if (!$ctx1.isSuccess && $ctx1.cut) $ctx1.asInstanceOf[_root_.fastparse.ParsingRun[scala.Nothing]]
else{
$ctx1.cut = false
$rec($beforeSepIndex, $count + 1, $parsedAgg)
}
"""
}

q"""
$ctx match{ case $ctx1 =>
$repeater match {case $repeater1 =>
var $originalCut = $ctx1.cut
val $acc = $repeater1.initial
@_root_.scala.annotation.tailrec
def $rec($startIndex: _root_.scala.Int,
$count: _root_.scala.Int,
$lastAgg: _root_.fastparse.internal.Msgs): _root_.fastparse.P[${c.weakTypeOf[V]}] = {
$ctx1.cut = $minCut
${c.prefix}.parse0()

val $parsedMsg = $ctx1.shortParserMsg
val $parsedAgg = $ctx1.failureGroupAggregate
$originalCut |= $ctx1.cut
if (!$ctx1.isSuccess) {
val res =
if ($ctx1.cut) $ctx1.asInstanceOf[_root_.fastparse.P[${c.weakTypeOf[V]}]]
else $endSnippet
if ($ctx1.verboseFailures) {
$ctx1.aggregateMsg(
$startIndex,
() => $parsedMsg.render + s".rep" + $aggregateSnippet,
if ($lastAgg == null) $ctx1.failureGroupAggregate
else $ctx1.failureGroupAggregate ::: $lastAgg
)
}
res
}else {
val $beforeSepIndex = $ctx1.index
$repeater1.accumulate($ctx1.successValue.asInstanceOf[${c.weakTypeOf[T]}], $acc)
$ctx1.cut = false
$wsSnippet
}
}
$rec($ctx1.index, 0, null)
}
}
"""
}

def repXMacro1[T: c.WeakTypeTag, V: c.WeakTypeTag](c: Context)
(repeater: c.Tree,
ctx: c.Tree): c.Tree = {
import c.universe._
MacroRepImpls.repXMacro0[T, V](c)(None, None)(repeater, ctx)
}

def repXMacro2[T: c.WeakTypeTag, V: c.WeakTypeTag](c: Context)
(min: c.Tree)
(repeater: c.Tree,
ctx: c.Tree): c.Tree = {
import c.universe._
MacroRepImpls.repXMacro0[T, V](c)(None, Some(min))(repeater, ctx)
}

def repXMacro1ws[T: c.WeakTypeTag, V: c.WeakTypeTag](c: Context)
(repeater: c.Tree,
whitespace: c.Tree,
ctx: c.Tree): c.Tree = {
import c.universe._
MacroRepImpls.repXMacro0[T, V](c)(Some(whitespace), None)(repeater, ctx)
}

def repXMacro2ws[T: c.WeakTypeTag, V: c.WeakTypeTag](c: Context)
(min: c.Tree)
(repeater: c.Tree,
whitespace: c.Tree,
ctx: c.Tree): c.Tree = {
import c.universe._
MacroRepImpls.repXMacro0[T, V](c)(Some(whitespace), Some(min))(repeater, ctx)
}
}

class RepImpls[T](val parse0: () => ParsingRun[T]) extends AnyVal{
def repX[V](min: Int = 0,
Expand Down

0 comments on commit af4b47f

Please sign in to comment.