Skip to content

Commit

Permalink
Experiment: else ifs in serializer code
Browse files Browse the repository at this point in the history
Use scalameta to transform lists of mutually exclusive ifs into else ifs, to potentially save a miniscule amount of performance.
  • Loading branch information
Ostrzyciel committed Jul 16, 2024
1 parent c7b841d commit cbd4b33
Show file tree
Hide file tree
Showing 7 changed files with 249 additions and 195 deletions.
4 changes: 2 additions & 2 deletions project/Generator.scala
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ object Generator {
println(s" Processing ${inputFile.getName}")
val inputStr = IO.read(inputFile)
val outputFile = outputDir / inputFile.name
// Apply transformations: 1, 2
val outputStr = ProtoTransformer2.transform(ProtoTransformer1.transform(inputStr))
// Apply transformations
val outputStr = ProtoTransformer.transform(inputStr)
IO.write(outputFile, outputStr)
outputFile
}
Expand Down
23 changes: 23 additions & 0 deletions project/ProtoTransformer.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import scala.meta._

object ProtoTransformer {
val transformations: Seq[Transformer] = Seq(
Transform1.transformer,
Transform2.transformer,
Transform3.transformer,
)

def transform(input: String): String = {
val tree = input.parse[Source].get

val transformer = new Transformer {
override def apply(tree: Tree): Tree = {
transformations.foldLeft(tree) { (t, transformer) =>
transformer(t)
}
}
}

transformer(tree).syntax
}
}
86 changes: 0 additions & 86 deletions project/ProtoTransformer1.scala

This file was deleted.

107 changes: 0 additions & 107 deletions project/ProtoTransformer2.scala

This file was deleted.

80 changes: 80 additions & 0 deletions project/Transform1.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import scala.meta._

/**
* Source code transformer that for oneof protos:
* - Unifies naming of is[S/P/O/G]Something methods to isSomething
* - Removes with[S/P/O/G]Something methods
* - Unifies naming of [S/P/O/G]Something classes to Something
* - Unifies naming of [s/p/o/g]Something fields to something
* - Adds base traits (RdfTerm, RdfTermCompanion)
*
* All this must be done before ProtoTransformer2 is executed.
*/
object Transform1 {
val isMethodNamePattern = "^is[SPOG](Iri|Bnode|Literal|TripleTerm|DefaultGraph)$".r
val withMethodNamePattern = "^with[SPOG](Iri|Bnode|Literal|TripleTerm|DefaultGraph)$".r
val classNamePattern = "^[SPOG](Iri|Bnode|Literal|TripleTerm|DefaultGraph)".r
val fieldNamePattern = "^[spog](Iri|Bnode|Literal|TripleTerm|DefaultGraph)".r
val traitNamePattern = "^(Subject|Predicate|Object|Graph)$".r

val transformer = new Transformer {
override def apply(tree: Tree): Tree = tree match {
// Transform method and class names in references
case Term.Name(name) => name match {
case isMethodNamePattern(t) => Term.Name(f"is$t")
case classNamePattern(t) => Term.Name(t)
case fieldNamePattern(t) => Term.Name(f"${t.head.toLower}${t.tail}")
case _ => super.apply(tree)
}

// Transform class names in definitions
case Type.Name(classNamePattern(t)) => Type.Name(t)

// Remove with[S/P/O/G]Something methods
case Template.After_4_4_0(_, _, _, stats, _) => tree.asInstanceOf[Template].copy(
stats = stats.flatMap { stat => stat match {
case Defn.Def.After_4_7_3(_, Term.Name(withMethodNamePattern(t)), _, _, _) => None
case t => Some(apply(t).asInstanceOf[Stat])
}}
)

// Transform traits for RDF terms
case Defn.Trait.After_4_6_0(_, Type.Name(traitNamePattern(name)), _, _, templ) =>
val adapterName = if (name == "Graph") "GraphTerm" else s"SpoTerm"
tree.asInstanceOf[Defn.Trait].copy(
templ = apply(templ.copy(
inits = templ.inits :+ Init.After_4_6_0(
Type.Select(q"eu.ostrzyciel.jelly.core.proto_adapters", Type.Name(adapterName)),
Name.Anonymous(), Nil
)
)).asInstanceOf[Template]
)

// Transform companion objects for RDF terms
case Defn.Object(_, Term.Name(traitNamePattern(name)), templ) =>
val adapterName = if (name == "Graph") "GraphTermCompanion" else s"SpoTermCompanion"
val lastMethod = if (name == "Graph")
q"val makeDefaultGraph: DefaultGraph = DefaultGraph(RdfDefaultGraph.defaultInstance)"
else q"def makeTripleTerm(t: eu.ostrzyciel.jelly.core.proto.v1.RdfTriple): TripleTerm = TripleTerm(t)"
tree.asInstanceOf[Defn.Object].copy(
templ = apply(templ.copy(
inits = templ.inits :+ Init.After_4_6_0(
Type.Apply(
Type.Select(q"eu.ostrzyciel.jelly.core.proto_adapters", Type.Name(adapterName)),
Type.ArgClause(Type.Name(name) :: Nil)
),
Name.Anonymous(), Nil
),
stats = templ.stats ++ Seq(
q"val makeEmpty: Empty.type = Empty",
q"def makeIri(iri: eu.ostrzyciel.jelly.core.proto.v1.RdfIri): Iri = Iri(iri)",
q"def makeBnode(bnode: String): Bnode = Bnode(bnode)",
q"def makeLiteral(literal: eu.ostrzyciel.jelly.core.proto.v1.RdfLiteral): Literal = Literal(literal)"
) ++ Seq(lastMethod),
)).asInstanceOf[Template]
)

case node => super.apply(node)
}
}
}
Loading

0 comments on commit cbd4b33

Please sign in to comment.