MorphoDocsSupport.kt
src/jvmMain/kotlin/afield/tools/docs/MorphoDocsSupport.kt · 69 lines
package afield.tools.docs
import afield.document.graph.Box
import afield.lang.morpho.MorphoCircuit
import afield.lang.morpho.MorphoExecution
import afield.lang.morpho.MorphoRuntime
import afield.lang.morpho.flines
import afield.lang.morpho.morphoPlaneWindow
import afield.lang.morpho.planeBounds
import afield.geometry.spatial.showPlaneGrid
Lets a documentation page hold MorphoHDL itself, rather than Kotlin that mentions it.
A fence written as data-lang=morpho shows its body as MorphoHDL, and public/docs_hooks.py
wraps that body in a call into this file before the docs runner evaluates it, the same way it
already wraps a nano or a forth fence. What the reader sees under the fence is that program
compiled, grown out in full with its layout relaxing between expansions, and drawn.
The snippet is handled as a morpho box would handle it, down to using MorphoExecution's own
directive parsing, so a program on the page and the same text pasted into a box behave alike.
That includes the refusal: without a # main line there is no design to build and no width to
build it at, so the snippet fails rather than guessing. A snippet that defines no cells of its
own is given morpho's standard library, which is what makes a one-line program publishable.
morpho_examples.md is the page that uses this.
fun Box.renderMorphoDocsSnippet(source: String)
Render a MorphoHDL snippet the way a morpho box would, for a data-lang=morpho docs fence.
The point is that the code shown on the page is MorphoHDL, not Kotlin that happens to mention
it. docs_hooks.py wraps a morpho fence's body into a call to this, exactly as it already does
for nano and forth — so the reader sees the language and the figure below it is that language
having been compiled, grown, laid out and drawn.
Directive handling matches MorphoExecution rather than reimplementing it, so a snippet on the
page and the same text pasted into a box behave identically. That includes the refusal: no
# main line is an error here too, because a size-agnostic cell has no defensible default width.
fun Box.renderMorphoDocsSnippet(source: String) {
val directive = MorphoExecution.parseDirective(source)
?: throw IllegalStateException(
"no '# main …' directive — a MorphoHDL docs snippet has to say which design to build " +
"and how wide, e.g. # main ripple_adder(8, 8, 1)"
)
// A snippet that defines no cells of its own still gets morpho's standard library, so a page can
// show a one-line program. Same rule as a morpho box.
val defines = runCatching { MorphoRuntime.cellNames(source) }.getOrDefault(emptyList())
val full = if (defines.isEmpty()) MorphoRuntime.standardLibrary + "\n" + source else source
MorphoCircuit.compile(
source = full,
design = directive.design,
signature = directive.signature,
optimize = directive.optimize,
).use { circuit ->
circuit.growFully(relaxSteps = 240)
println(circuit.summary())
showPlaneGrid(
circuit.summary() to circuit.flines(),
columns = 1,
cellWidth = 560,
cellHeight = 560,
window = morphoPlaneWindow(circuit.planeBounds()),
)
}
}