Skip to content
This repository has been archived by the owner on Aug 20, 2024. It is now read-only.

Commit

Permalink
Make return value of Serializer.lazily lazy (#2627)
Browse files Browse the repository at this point in the history
Directly subclassing Iterable is lazy-ish, but if you call any operation
on the resulting value (eg. map or ++) it will evaluate the Iterable and
return a List.
  • Loading branch information
jackkoenig committed Mar 21, 2023
1 parent d5dbf71 commit 57b8a39
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 1 deletion.
2 changes: 1 addition & 1 deletion src/main/scala/firrtl/ir/Serializer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ object Serializer {
case n: Circuit => sIt(n)(indent)
case other => Iterator(serialize(other, indent))
}
}
}.view // TODO replace .view with constructing a view directly above, but must drop 2.12 first.

/** Converts a `Constraint` into its string representation. */
def serialize(con: Constraint): String = {
Expand Down
44 changes: 44 additions & 0 deletions src/test/scala/firrtlTests/SerializerSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -136,4 +136,48 @@ class SerializerSpec extends AnyFlatSpec with Matchers {
val readNew = parseSerializeParse(SMemTestCircuit.src(" new"))
assert(SMemTestCircuit.findRuw(readNew) == ReadUnderWrite.New)
}

it should "support lazy serialization" in {
var stmtSerialized = false
case class HackStmt(stmt: Statement) extends Statement {
def serialize: String = {
stmtSerialized = true
stmt.serialize
}
def foreachExpr(f: Expression => Unit): Unit = stmt.foreachExpr(f)
def foreachInfo(f: Info => Unit): Unit = stmt.foreachInfo(f)
def foreachStmt(f: Statement => Unit): Unit = stmt.foreachStmt(f)
def foreachString(f: String => Unit): Unit = stmt.foreachString(f)
def foreachType(f: Type => Unit): Unit = stmt.foreachType(f)
def mapExpr(f: Expression => Expression): Statement = this.copy(stmt.mapExpr(f))
def mapInfo(f: Info => Info): Statement = this.copy(stmt.mapInfo(f))
def mapStmt(f: Statement => Statement): Statement = this.copy(stmt.mapStmt(f))
def mapString(f: String => String): Statement = this.copy(stmt.mapString(f))
def mapType(f: Type => Type): Statement = this.copy(stmt.mapType(f))
}

val stmt = HackStmt(DefNode(NoInfo, "foo", Reference("bar")))
val it: Iterable[String] = Serializer.lazily(stmt)
assert(!stmtSerialized, "We should be able to construct the serializer lazily")

var mapExecuted = false
val it2: Iterable[String] = it.map { x =>
mapExecuted = true
x + ","
}
assert(!stmtSerialized && !mapExecuted, "We should be able to map the serializer lazily")

var appendExecuted = false
val it3: Iterable[String] = it2 ++ Seq("hi").view.map { x =>
appendExecuted = true
x
}
assert(!stmtSerialized && !mapExecuted && !appendExecuted, "We should be able to append to the serializer lazily")

val result = it3.mkString
assert(
stmtSerialized && mapExecuted && appendExecuted,
"Once we traverse the serializer, everything should execute"
)
}
}

0 comments on commit 57b8a39

Please sign in to comment.