This article is under construction.
To use Miksilo effectively, we have to write some boilerplate. For each type of Node
, we need to define one NodeShape
object, and a NodeField
object for each field. Then, to make using the accessing fields of the new Node type easier, we need a subclass of NodeWrapper
. In the future, Scala macro’s might help us to generate this boilerplate, but currently they are not mature enough. For now we’ve written a generator instead. Here follows an example of the generator in action:
Given the following input:
object ClassFileDelta {
val input = new NodeShapeDefinition("ClassFile",
"classInfoIndex" -> "Int",
"interfaces" -> "Seq[Int]",
"methods" -> wrapSeq("Seq[MethodInfo]"),
"attributes" -> "Seq[Node]"
)
}
It outputs:
object ClassFileDelta {
val input = new NodeShapeDefinition("ClassFile",
"classInfoIndex" -> "Int",
"interfaces" -> "Seq[Int]",
"methods" -> wrapSeq("Seq[MethodInfo]"),
"attributes" -> "Seq[Node]"
)
//region Generated Node boilerplate
object Shape extends NodeShape
object Interfaces extends NodeField
object Methods extends NodeField
object Attributes extends NodeField
implicit class ClassFile[T <: NodeLike](val node: T) extends NodeWrapper {
assert(node.shape == Shape)
def interfaces: Seq[Int] = node(Interfaces).asInstanceOf[Seq[Int]]
def interfaces_(value: Seq[Int]): Unit = node(Interfaces) = value
def methods: Seq[MethodInfo[T]] = NodeWrapper.wrapSeq(node(Methods).asInstanceOf[Seq[T]])
def methods_(value: Seq[MethodInfo[T]]): Unit = node(Methods) = NodeWrapper.unwrapSeq(value)
def attributes: Seq[T] = node(Attributes).asInstanceOf[Seq[T]]
def attributes_(value: Seq[T]): Unit = node(Attributes) = value
}
//endregion
}
The generic type argument for the wrappers allows it to wrap around both Node
and Path
types. Wrapped fields can either wrap around regular types, other wrappers, or sequences of other wrappers.