Skip to content

Commit 26d79cb

Browse files
jbertholdPetarMax
andauthored
Hotfix check/adjust subsorting for substitutions based on ==K terms (#4076)
When a constraint of shape `VAR:VarSort ~> .K ==K term:TermSort ~> .K` is externalised, the prior code just rendered a `VAR:VarSort #Equals term:TermSort`. This is wrong when `TermSort /= VarSort`, however `TermSort` will be a subsort of `VarSort`, otherwise the rule that introduced this `==K` term is ill-sorted. * Externalisation code now inserts the missing injection into the `#Equals` expression. * A test was added which demonstrates the use case and behaviour (failed before, succeeds now). * A pretty-printer option was added to show the injections in the printed terms (off by default). --------- Co-authored-by: Petar Maksimović <[email protected]>
1 parent 74322a5 commit 26d79cb

13 files changed

+331
-136
lines changed

booster/library/Booster/CLOptions.hs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ parseLogOptions =
184184
( metavar "PRETTY_PRINT"
185185
<> value [Decoded, Truncated]
186186
<> long "pretty-print"
187-
<> help "Prety print options for kore terms: decode, infix, truncated"
187+
<> help "Pretty print options for kore terms: decoded, infix, truncated, with-injections"
188188
<> showDefault
189189
)
190190
where
@@ -210,7 +210,8 @@ parseLogOptions =
210210
"truncated" -> Right Truncated
211211
"infix" -> Right Infix
212212
"decoded" -> Right Decoded
213-
other -> Left $ other <> ": Unsupported prettry printer option"
213+
"with-injections" -> Right WithInjections
214+
other -> Left $ other <> ": Unsupported pretty printer option"
214215

215216
readTimeStampFormat :: String -> Either String TimestampFormat
216217
readTimeStampFormat = \case

booster/library/Booster/Pattern/Pretty.hs

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,18 +23,21 @@ import Data.Data (Proxy (..))
2323
import Data.Set qualified as Set
2424
import Data.Text qualified as Text
2525

26-
data ModifierT = Truncated | Infix | Decoded deriving (Show)
26+
data ModifierT = WithInjections | Truncated | Infix | Decoded deriving (Show)
2727

2828
data Modifiers = Modifiers
29-
{ isTruncated, isInfix, isDecoded :: Bool
29+
{ isWithInjections, isTruncated, isInfix, isDecoded :: Bool
3030
}
3131

3232
defaultModifiers :: Modifiers
33-
defaultModifiers = Modifiers False False False
33+
defaultModifiers = Modifiers False False False False
3434

3535
class FromModifierT (m :: ModifierT) where
3636
modifiers' :: Modifiers -> Modifiers
3737

38+
instance FromModifierT 'WithInjections where
39+
modifiers' m = m{isWithInjections = True}
40+
3841
instance FromModifierT 'Truncated where
3942
modifiers' m = m{isTruncated = True}
4043

@@ -60,6 +63,7 @@ toModifiersRep = go (ModifiersRep @'[] Proxy)
6063
where
6164
go rep@(ModifiersRep (Proxy :: Proxy mods)) = \case
6265
[] -> rep
66+
(WithInjections : xs) -> go (ModifiersRep @('WithInjections ': mods) Proxy) xs
6367
(Truncated : xs) -> go (ModifiersRep @('Truncated ': mods) Proxy) xs
6468
(Infix : xs) -> go (ModifiersRep @('Infix ': mods) Proxy) xs
6569
(Decoded : xs) -> go (ModifiersRep @('Decoded ': mods) Proxy) xs
@@ -89,7 +93,13 @@ instance Pretty (PrettyWithModifiers mods Term) where
8993
DotDotDot -> "..."
9094
DomainValue _sort bs -> pretty . show . Text.decodeLatin1 . shortenBS $ bs
9195
Var var -> pretty' @mods var
92-
Injection _source _target t' -> pretty' @mods t'
96+
Injection source target t'
97+
| isWithInjections ->
98+
"inj"
99+
<> Pretty.braces
100+
(Pretty.hsep $ Pretty.punctuate Pretty.comma [pretty' @mods source, pretty' @mods target])
101+
<> KPretty.arguments' [pretty' @mods t']
102+
| otherwise -> pretty' @mods t'
93103
KMap _attrs keyVals rest ->
94104
Pretty.braces . Pretty.hsep . Pretty.punctuate Pretty.comma $
95105
[pretty' @mods k <+> "->" <+> pretty' @mods v | (k, v) <- keyVals]
@@ -110,7 +120,8 @@ instance Pretty (PrettyWithModifiers mods Term) where
110120
Pretty.<+> maybe mempty ((" ++ " <>) . pretty' @mods) rest
111121
where
112122
Modifiers
113-
{ isTruncated
123+
{ isWithInjections
124+
, isTruncated
114125
, isInfix
115126
, isDecoded
116127
} = modifiers @mods defaultModifiers

booster/library/Booster/Syntax/Json/Externalise.hs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ externaliseExistTerm vars t = exist vars
9999
externalisePredicate :: Syntax.Sort -> Internal.Predicate -> Syntax.KorePattern
100100
externalisePredicate sort (Internal.Predicate t) =
101101
Syntax.KJEquals
102-
{ argSort = externaliseSort $ sortOfTerm t
102+
{ argSort = externaliseSort $ sortOfTerm t -- must actually be SortBool
103103
, sort
104104
, first = externaliseTerm Internal.TrueBool
105105
, second = externaliseTerm t
@@ -116,11 +116,20 @@ externaliseCeil sort (Internal.Ceil term) =
116116
externaliseSubstitution :: Syntax.Sort -> Internal.Variable -> Internal.Term -> Syntax.KorePattern
117117
externaliseSubstitution sort Internal.Variable{variableSort = iSort, variableName = iName} t =
118118
Syntax.KJEquals
119-
{ argSort = externaliseSort $ sortOfTerm t
119+
{ argSort = extISort
120120
, sort
121-
, first = Syntax.KJEVar (varNameToId iName) (externaliseSort iSort)
122-
, second = externaliseTerm t
121+
, first = Syntax.KJEVar (varNameToId iName) extISort
122+
, second = target
123123
}
124+
where
125+
extISort = externaliseSort iSort
126+
-- The sort of the term not be iSort but must be a subsort of it.
127+
-- We assume termSort < iSort but cannot check it.
128+
termSort = sortOfTerm t
129+
target
130+
| termSort == iSort = externaliseTerm t
131+
| otherwise =
132+
externaliseTerm $ Internal.Injection termSort iSort t
124133

125134
varNameToId :: Internal.VarName -> Syntax.Id
126135
varNameToId = Syntax.Id . Text.decodeLatin1

booster/test/rpc-integration/resources/subk.k

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ module SUBK
22
imports BOOL
33
imports K-EQUAL
44

5-
syntax State ::= "ping" [token]
6-
| "pong" [token]
7-
| "peng" [token]
5+
syntax State ::= "ping" [symbol("ping")]
6+
| "pong" [symbol("pong")]
7+
| "peng" [symbol("peng")]
88

99
configuration <k> $PGM:State ~> .K </k>
1010
<x> .K </x>
@@ -27,4 +27,12 @@ module SUBK
2727
<x> X </x>
2828
requires notBool (X ==K inK(pong))
2929

30+
syntax State ::= Substate
31+
32+
syntax Substate ::= "bong" [symbol("bong")]
33+
34+
syntax Bool ::= isBong ( State ) [function, total, symbol("isBong")]
35+
36+
rule isBong(S) => S ==K bong
37+
3038
endmodule

0 commit comments

Comments
 (0)