Skip to content

Commit

Permalink
JS-2186 Less Instruction default methods
Browse files Browse the repository at this point in the history
  • Loading branch information
Zschimmer committed Dec 12, 2024
1 parent 89c7596 commit 95510e9
Show file tree
Hide file tree
Showing 11 changed files with 95 additions and 69 deletions.
52 changes: 38 additions & 14 deletions js7-data/shared/src/main/scala/js7/data/workflow/Instruction.scala
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,11 @@ trait Instruction:

def withoutSourcePos: Instruction

def withPositions(position: Position): Instruction =
if branchWorkflows.nonEmpty then throw new AssertionError(
s"$instructionName.withPositions is not implemented")
this
def withPositions(position: Position): Instruction

def adopt(workflow: Workflow): Instruction =
this
def adopt(workflow: Workflow): Instruction

def reduceForAgent(agentPath: AgentPath, workflow: Workflow): Instruction =
this
def reduceForAgent(agentPath: AgentPath, workflow: Workflow): Instruction

def isVisibleForAgent(agentPath: AgentPath, workflow: Workflow): Boolean =
workflows.exists(_.isVisibleForAgent(agentPath))
Expand All @@ -44,8 +39,11 @@ trait Instruction:
def branchWorkflows: Seq[(BranchId, Workflow)]

// The instruction blocks of the instruction
def workflows: Seq[Workflow] =
branchWorkflows.map(_._2)
def workflows: Seq[Workflow]

protected final def unknownBlock(branchId: BranchId): Checked[Workflow] =
Left(Problem:
s"Instruction '$instructionName' does not have an instruction block '$branchId'")

final def flattenedWorkflows(parent: Position): View[(BranchPath, Workflow)] =
branchWorkflows.view
Expand All @@ -55,8 +53,7 @@ trait Instruction:
branchWorkflows.view
.flatMap { case (branchId, workflow) => workflow.flattenedInstructions(parent / branchId) }

def workflow(branchId: BranchId): Checked[Workflow] =
Problem(s"Instruction '$instructionName' does not have a nested workflow for branch '$branchId'")
def workflow(branchId: BranchId): Checked[Workflow]

def toCatchBranchId(branchId: BranchId): Option[BranchId] =
None
Expand All @@ -82,8 +79,10 @@ trait Instruction:


object Instruction:

object `@:`:
def unapply(labeled: Labeled): Some[(Option[Label], Instruction)] = Some((labeled.maybeLabel, labeled.instruction))
def unapply(labeled: Labeled): Some[(Option[Label], Instruction)] =
Some(labeled.maybeLabel -> labeled.instruction)

implicit def toLabeled(instruction: Instruction): Labeled =
Labeled(None, instruction)
Expand All @@ -101,6 +100,7 @@ object Instruction:
copy(
maybePosition = Some(position),
instruction = instruction.withPositions(position))

object Labeled:
implicit def jsonEncoder(implicit instrEncoder: Encoder.AsObject[Instruction]): Encoder.AsObject[Labeled] =
case Labeled(None, instruction, None) =>
Expand All @@ -125,12 +125,36 @@ object Instruction:
rightNode
yield Labeled(labels, instruction)

trait IsOrderBoundary extends Instruction

/** Instruction has no own instruction block (is not nesting). */
trait NoInstructionBlock extends Instruction:

final def withPositions(position: Position): Instruction =
this

final def withoutBlocks: NoInstructionBlock =
this

final def branchWorkflows: Seq[(BranchId, Workflow)] =
Nil

final def workflows: Seq[Workflow] =
Nil

final def workflow(branchId: BranchId): Checked[Workflow] =
unknownBlock(branchId)

final def adopt(workflow: Workflow): Instruction =
this

def reduceForAgent(agentPath: AgentPath, workflow: Workflow): Instruction =
this


trait WithInstructionBlock extends Instruction:

def workflows: Seq[Workflow] =
branchWorkflows.map(_._2)


trait IsOrderBoundary extends WithInstructionBlock
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ final case class ConsumeNotices(
whenNotAnnounced: WhenNotAnnounced = WhenNotAnnounced.Wait,
subworkflow: Workflow,
sourcePos: Option[SourcePos] = None)
extends ExpectOrConsumeNoticesInstruction:
extends ExpectOrConsumeNoticesInstruction, Instruction.WithInstructionBlock:

def withoutSourcePos: ConsumeNotices =
copy(sourcePos = None)
Expand All @@ -34,7 +34,7 @@ extends ExpectOrConsumeNoticesInstruction:
subworkflow = subworkflow.copy(
outer = Some(outer)))

override def reduceForAgent(agentPath: AgentPath, workflow: Workflow): Instruction =
def reduceForAgent(agentPath: AgentPath, workflow: Workflow): Instruction =
if isVisibleForAgent(agentPath, workflow) then
copy(
subworkflow = subworkflow.reduceForAgent(agentPath))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ final case class Cycle private(
cycleWorkflow: Workflow,
onlyOnePeriod: Boolean = false,
sourcePos: Option[SourcePos])
extends Instruction:
extends Instruction.WithInstructionBlock:

def withoutSourcePos: Cycle =
copy(
Expand All @@ -32,7 +32,7 @@ extends Instruction:
cycleWorkflow = cycleWorkflow.copy(
outer = Some(outer)))

override def reduceForAgent(agentPath: AgentPath, workflow: Workflow): Instruction =
def reduceForAgent(agentPath: AgentPath, workflow: Workflow): Instruction =
if isVisibleForAgent(agentPath, cycleWorkflow) then
copy(
cycleWorkflow = cycleWorkflow.reduceForAgent(agentPath))
Expand All @@ -52,7 +52,7 @@ extends Instruction:
branchId match
case BranchId.Cycle => Right(cycleWorkflow)
case BranchId.Named(string) if string.startsWith(BranchId.CyclePrefix) => Right(cycleWorkflow)
case _ => super.workflow(branchId)
case _ => unknownBlock(branchId)


object Cycle:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,15 @@ extends ForkInstruction:
sourcePos = None,
branches = branches.map(b => b.copy(workflow = b.workflow.withoutSourcePos)))

override def withPositions(position: Position): Fork =
def withPositions(position: Position): Fork =
copy(branches =
branches.map(branch => branch.copy(
workflow = branch.workflow.withPositions(position / branch.id.toBranchId))))

override def adopt(outer: Workflow): Fork = copy(
def adopt(outer: Workflow): Fork = copy(
branches = branches.map(o => o.copy(workflow = o.workflow.copy(outer = Some(outer)))))

override def reduceForAgent(agentPath: AgentPath, workflow: Workflow): Instruction =
def reduceForAgent(agentPath: AgentPath, workflow: Workflow): Instruction =
if this.agentPath.contains(agentPath) || isVisibleForAgent(agentPath, workflow) then
copy(
branches = for b <- branches yield
Expand All @@ -66,16 +66,16 @@ extends ForkInstruction:
branches = branches.map(_.copy(
workflow = Workflow.empty)))

override def workflow(branchId: BranchId): Checked[Workflow] =
def workflow(branchId: BranchId): Checked[Workflow] =
branchId match
case BranchId.Named(name) if name.startsWith(BranchId.ForkPrefix) =>
val id = ForkBranchId(name.drop(BranchId.ForkPrefix.length))
branches.collectFirst { case Fork.Branch(`id`, workflow) => workflow }
.fold(super.workflow(branchId))(Right.apply)
.fold(unknownBlock(branchId))(Right.apply)
case _ =>
super.workflow(branchId)
unknownBlock(branchId)

override def branchWorkflows: Seq[(BranchId, Workflow)] =
def branchWorkflows: Seq[(BranchId, Workflow)] =
branches.map(b => b.id.toBranchId -> b.workflow)

override def toString =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,14 @@ extends ForkInstruction:
sourcePos = None,
workflow = workflow.withoutSourcePos)

override def withPositions(position: Position): ForkList =
def withPositions(position: Position): ForkList =
copy(workflow =
workflow.withPositions(position / BranchId.ForkList))

override def adopt(outer: Workflow): ForkList = copy(
def adopt(outer: Workflow): ForkList = copy(
workflow = workflow.copy(outer = Some(outer)))

override def reduceForAgent(agentPath: AgentPath, outer: Workflow): Instruction =
def reduceForAgent(agentPath: AgentPath, outer: Workflow): Instruction =
if this.agentPath.contains(agentPath) || isVisibleForAgent(agentPath, outer) then
copy(
workflow = reuseIfEqual(workflow, workflow.reduceForAgent(agentPath)))
Expand All @@ -55,12 +55,12 @@ extends ForkInstruction:
def withoutBlocks: ForkList =
copy(workflow = Workflow.empty)

override def workflow(branchId: BranchId): Checked[Workflow] =
def workflow(branchId: BranchId): Checked[Workflow] =
branchId match
case BranchId.ForkList => Right(workflow)
case _ => super.workflow(branchId)
case _ => unknownBlock(branchId)

override def branchWorkflows: Seq[(BranchId, Workflow)] =
def branchWorkflows: Seq[(BranchId, Workflow)] =
Seq(BranchId.ForkList -> workflow)

override def toString = s"ForkList()$sourcePosToString"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,28 +21,28 @@ final case class If(
ifThens: NonEmptyVector[IfThen],
elseBlock: Option[Workflow] = None,
sourcePos: Option[SourcePos] = None)
extends Instruction:
extends Instruction.WithInstructionBlock:

def withoutSourcePos: If = copy(
sourcePos = None,
ifThens = ifThens.map(ifThen => ifThen.copy(
thenBlock = ifThen.thenBlock.withoutSourcePos)),
elseBlock = elseBlock.map(_.withoutSourcePos))

override def withPositions(position: Position): If =
def withPositions(position: Position): If =
copy(
ifThens = ifThens.map(ifThen => ifThen.copy(
thenBlock = ifThen.thenBlock.withPositions(position / BranchId.Then))),
elseBlock = elseBlock.map(_.withPositions(position / BranchId.Else)))

override def adopt(outer: Workflow): If = copy(
def adopt(outer: Workflow): If = copy(
ifThens = ifThens.map(ifThen => ifThen.copy(
thenBlock = ifThen.thenBlock.copy(
outer = Some(outer)))),
elseBlock = elseBlock.map(_.copy(
outer = Some(outer))))

override def reduceForAgent(agentPath: AgentPath, workflow: Workflow): Instruction =
def reduceForAgent(agentPath: AgentPath, workflow: Workflow): Instruction =
copy(
ifThens = ifThens.map(ifThen => ifThen.copy(
thenBlock = ifThen.thenBlock.reduceForAgent(agentPath))),
Expand All @@ -54,16 +54,16 @@ extends Instruction:
thenBlock = Workflow.empty)),
elseBlock = elseBlock.map(_ => Workflow.empty))

override def workflow(branchId: BranchId): Checked[Workflow] =
def workflow(branchId: BranchId): Checked[Workflow] =
NewBranchId.fromLegacy(branchId).flatMap:
case newBranchId @ NewBranchId.Then(i) =>
ifThens.get(i - 1).toRight(Problem(s"This if has no $newBranchId")).map(_.thenBlock)
case NewBranchId.Else =>
elseBlock.toChecked(Problem.pure("This If has no 'else' branch"))
case _ =>
super.workflow(branchId)
unknownBlock(branchId)

override def branchWorkflows: Seq[(BranchId, Workflow)] =
def branchWorkflows: Seq[(BranchId, Workflow)] =
ifThens.toVector.zipWithIndex.map: (ifThen, i) =>
BranchId.then_(1 + i) -> ifThen.thenBlock
.concat:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ final case class LockInstruction private(
demands: List[LockDemand],
lockedWorkflow: Workflow,
sourcePos: Option[SourcePos])
extends Instruction:
extends Instruction.WithInstructionBlock:

override def instructionName = "Lock"

Expand All @@ -28,15 +28,15 @@ extends Instruction:
sourcePos = None,
lockedWorkflow = lockedWorkflow.withoutSourcePos)

override def withPositions(position: Position): LockInstruction =
def withPositions(position: Position): LockInstruction =
copy(
lockedWorkflow = lockedWorkflow.withPositions(position / BranchId.Lock))

override def adopt(outer: Workflow): LockInstruction = copy(
def adopt(outer: Workflow): LockInstruction = copy(
lockedWorkflow = lockedWorkflow.copy(
outer = Some(outer)))

override def reduceForAgent(agentPath: AgentPath, workflow: Workflow): Instruction =
def reduceForAgent(agentPath: AgentPath, workflow: Workflow): Instruction =
if isVisibleForAgent(agentPath, workflow) then
copy(
lockedWorkflow = lockedWorkflow.reduceForAgent(agentPath))
Expand All @@ -46,15 +46,16 @@ extends Instruction:
def withoutBlocks: LockInstruction =
copy(lockedWorkflow = Workflow.empty)

override def workflows: Seq[Workflow] = lockedWorkflow :: Nil

override def branchWorkflows: Seq[(BranchId, Workflow)] =
def branchWorkflows: Seq[(BranchId, Workflow)] =
(BranchId.Lock -> lockedWorkflow) :: Nil

override def workflow(branchId: BranchId): Checked[Workflow] =
override def workflows: Seq[Workflow] =
lockedWorkflow :: Nil

def workflow(branchId: BranchId): Checked[Workflow] =
branchId match
case BranchId.Lock => Right(lockedWorkflow)
case _ => super.workflow(branchId)
case _ => unknownBlock(branchId)

def lockPaths: List[LockPath] =
demands.map(_.lockPath)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,29 +14,29 @@ final case class Options(
stopOnFailure: Option[Boolean],
block: Workflow,
sourcePos: Option[SourcePos])
extends Instruction:
extends Instruction.WithInstructionBlock:

def withoutSourcePos: Options =
copy(sourcePos = None)

override def withPositions(position: Position): Options =
def withPositions(position: Position): Options =
copy(
block = block.withPositions(position / BranchId.Options))

override def adopt(outer: Workflow): Options = copy(
def adopt(outer: Workflow): Options = copy(
block = block.copy(outer = Some(outer)))

override def reduceForAgent(agentPath: AgentPath, workflow: Workflow): Instruction =
def reduceForAgent(agentPath: AgentPath, workflow: Workflow): Instruction =
copy(
block = block.reduceForAgent(agentPath))

def withoutBlocks: Options =
copy(block = Workflow.empty)

override def workflow(branchId: BranchId): Checked[Workflow] =
def workflow(branchId: BranchId): Checked[Workflow] =
branchId match
case BranchId.Options => Right(block)
case _ => super.workflow(branchId)
case _ => unknownBlock(branchId)

override def branchWorkflows: Seq[(BranchId, Workflow)] =
(BranchId.Options -> block) :: Nil
Expand Down
Loading

0 comments on commit 95510e9

Please sign in to comment.