def debugee()

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