diff --git a/prover/strategies/core.md b/prover/strategies/core.md
index d9afd6e9e..8f46edf4e 100644
--- a/prover/strategies/core.md
+++ b/prover/strategies/core.md
@@ -23,8 +23,15 @@ module PROVER-CORE-SYNTAX
syntax SequenceStrategy ::= Strategy "." Strategy [right]
syntax ResultStrategy ::= "noop"
| TerminalStrategy
+ | IntroduceBranchStrategy
+ | ResolveBranchStrategy
| Strategy "&" Strategy [right, format(%1%n%2 %3)]
| Strategy "|" Strategy [right, format(%1%n%2 %3)]
+
+ syntax IntroduceBranchStrategy ::= Strategy "&>" Strategy [right, format(%1%n%2 %3)]
+
+ syntax ResolveBranchStrategy ::= Strategy "<|" Strategy [right, format(%1%n%2 %3)]
+
syntax Strategy ::= "or-split" | "and-split" | "or-split-rhs"
syntax Strategy ::= "prune" "(" Patterns ")"
@@ -53,10 +60,6 @@ module PROVER-CORE
`Strategy`s can be sequentially composed via the `.` operator.
-```k
- rule (S . T) . U => S . (T . U) ...
-```
-
Since strategies do not live in the K cell, we must manually heat and cool.
`ResultStrategy`s are strategies that can only be simplified when they are
cooled back into the sequence strategy.
@@ -65,7 +68,7 @@ cooled back into the sequence strategy.
syntax ResultStrategy ::= "#hole"
rule S1 . S2 => S1 ~> #hole . S2 ...
requires notBool(isResultStrategy(S1))
- andBool notBool(isSequenceStrategy(S1))
+
rule S1:ResultStrategy ~> #hole . S2 => S1 . S2 ...
```
@@ -185,6 +188,33 @@ approach succeeds:
andBool notBool(isTerminalStrategy(S2))
```
+The `<|` strategy allows us to choose different strategies
+for different subgoals.
+
+```k
+
+ rule S &> fail => fail ...
+ rule fail &> S => fail ...
+ rule S &> success => S ...
+ rule success &> S => S ...
+
+ // we could achieve the same result using &> on RHS
+ rule ((I1 &> Is) . (O1 <| Os)) => ((I1 . O1) & (Is . Os))
+
+ rule (I1 &> Is) . S => (I1 . S) &> (Is . S)
+ requires notBool isResolveBranchStrategy(S)
+
+ rule T:TerminalStrategy ~> #hole &> S2
+ => T &> S2
+ ...
+
+
+ rule ((S1 &> S2) => subgoal(GOAL, S1) ~> #hole &> S2)
+ GOAL:Pattern
+ requires notBool(isTerminalStrategy(S1))
+ andBool notBool(isTerminalStrategy(S2))
+```
+
The S { N } construct allows us to repeat a strategy S N times
```k
@@ -262,7 +292,7 @@ Internal strategy used to implement `or-split` and `and-split`.
syntax Strategy ::= "#andSplit" "(" Patterns ")" [function]
rule #andSplit(.Patterns) => noop
rule #andSplit(P:Pattern, .Patterns) => replace-goal(P)
- rule #andSplit(P:Pattern, Ps) => replace-goal(P) & #andSplit(Ps) [owise]
+ rule #andSplit(P:Pattern, Ps) => replace-goal(P) &> #andSplit(Ps) [owise]
```
If-then-else-fi strategy is useful for implementing other strategies:
diff --git a/prover/t/deterministic-choice.kore b/prover/t/deterministic-choice.kore
new file mode 100644
index 000000000..4c7fe8cca
--- /dev/null
+++ b/prover/t/deterministic-choice.kore
@@ -0,0 +1,16 @@
+symbol P() : Bool
+symbol Q() : Bool
+symbol R() : Bool
+symbol S() : Bool
+
+axiom p: P()
+axiom q: \equals(Q(), P())
+axiom r: \equals(R(), P())
+axiom s: \equals(S(), P())
+
+claim \and(Q(), R(), S())
+strategy (and-split
+ .( apply-equation -> q at 0 by []
+ <| apply-equation -> r at 0 by []
+ <| apply-equation -> s at 0 by []
+ )) . apply(p, fail)
diff --git a/prover/t/deterministic-choice.kore.expected b/prover/t/deterministic-choice.kore.expected
new file mode 100644
index 000000000..82c653b0a
--- /dev/null
+++ b/prover/t/deterministic-choice.kore.expected
@@ -0,0 +1,44 @@
+
+
+ 0
+
+
+
+ id: ., parent: .
+
+ \and ( .Patterns )
+
+
+ .
+ n
+ .
+
+
+ .LocalDeclCellSet
+
+
+ .
+
+
+
+
+ axiom ax0 : \and ( Q ( .Patterns ) , R ( .Patterns ) , S ( .Patterns ) , .Patterns )
+
+ axiom p : P ( .Patterns )
+
+ axiom q : \equals ( Q ( .Patterns ) , P ( .Patterns ) )
+
+ axiom r : \equals ( R ( .Patterns ) , P ( .Patterns ) )
+
+ axiom s : \equals ( S ( .Patterns ) , P ( .Patterns ) )
+
+ symbol P ( .Sorts ) : Bool
+
+ symbol Q ( .Sorts ) : Bool
+
+ symbol R ( .Sorts ) : Bool
+
+ symbol S ( .Sorts ) : Bool
+
+
+