in debugger/src/main/scala/org.apache.daffodil.debugger.dap/Parse.scala [774:870]
def debugee(args: Debugee.LaunchArgs.Manual): Resource[IO, DAPodil.Debugee] =
for {
data <- Channel.bounded[IO, DAPodil.Data](10).toResource
dapEvents <- Channel.bounded[IO, Events.DebugEvent](10).toResource
breakpoints <- Breakpoints().toResource
control <- Control.stopped().toResource
events <- Channel.bounded[IO, Event](10).toResource
debugger <- DaffodilDebugger
.resource(events, breakpoints, control, args.infosetFormat)
parse <-
args.data
.flatMap(in =>
Parse(
args.schemaPath,
in,
args.dataPath,
debugger,
args.infosetFormat,
args.rootName,
args.rootNamespace,
args.variables,
args.tunables,
dapEvents
)
)
.toResource
// run the parse, handling the final output (the infoset) in various ways
parsing = (args.infosetOutput match {
case Debugee.LaunchArgs.InfosetOutput.None =>
parse.run().drain
case Debugee.LaunchArgs.InfosetOutput.Console =>
parse
.run()
.through(text.utf8.decode)
.foldMonoid
.evalTap(xml =>
Logger[IO].debug("done collecting infoset XML output") *>
dapEvents.send(Events.OutputEvent.createConsoleOutput(xml))
)
case Debugee.LaunchArgs.InfosetOutput.File(path) =>
parse
.run()
.through(fs2.io.file.Files[IO].writeAll(fs2.io.file.Path.fromNioPath(path)))
}).onFinalizeCase {
// ensure dapEvents is terminated when the parse is terminated
case Resource.ExitCase.Errored(e: Parse.Exception) =>
// TODO: when Parse.Exception has source coordinates, include it into a more structured OutputEvent
dapEvents.send(Events.OutputEvent.createConsoleOutput(e.getMessage())) *>
dapEvents.close.void
case _ => dapEvents.close.void
}.onFinalizeCase(ec => Logger[IO].debug(s"parsing: $ec"))
latestData <- data.stream.holdResource(DAPodil.Data.empty)
debugee = new Debugee(
DAPodil.Source(args.schemaPath, None),
DAPodil.Source(args.dataPath, None),
latestData,
dapEvents.stream,
breakpoints,
control,
events
)
startup = dapEvents.send(ConfigEvent(args)) *>
(if (args.stopOnEntry)
control.step() *>
events.send(Parse.Event.Control(DAPodil.Debugee.State.Stopped.entry))
// don't use debugee.step as we need to send Stopped.entry, not Stopped.step
else debugee.continue())
delivery <- Delivery.to(data, dapEvents).toResource
deliverParseData =
events.stream
.through(delivery.deliver)
.onFinalize(data.close.void)
.onFinalizeCase {
case ec @ Resource.ExitCase.Errored(e) =>
Logger[IO].warn(e)(s"deliverParseData: $ec")
case ec => Logger[IO].debug(s"deliverParseData: $ec")
}
_ <- Stream
.emit(debugee)
.concurrently(
Stream(
Stream.eval(startup),
parsing,
deliverParseData
).parJoinUnbounded
)
.compile
.resource
.lastOrError
_ <- Resource.onFinalize(Logger[IO].debug("signalling a stop") *> parse.close())
} yield debugee