Skip to content

Commit ce31761

Browse files
committed
using Proposition instead of StateSpace for wp calculation
1 parent 34249e7 commit ce31761

File tree

4 files changed

+76
-103
lines changed

4 files changed

+76
-103
lines changed

Prover/Inspect.fs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ let printCalculationError (calc: CheckedCalculation) =
8686
match calc.Error with
8787
| Some(FailedSteps xs) -> error "failed steps" "" :: (xs |> List.map (fun (i, p, r) -> $"{i}: {p} | {r}"))
8888
| Some(WrongEvidence(counterExample, premise, conclusion)) ->
89-
let implication = premise |> List.map (_.ToString()) |> String.concat ", "
89+
let implication = premise |> List.map string |> String.concat ", "
9090

9191
[ error "invalid evidence" ""
9292
$"❌ counter-example found: {counterExample}"

Prover/LanguageServices/FSharp/FsDefinitions.fs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,7 @@ let parseAndTypeCheckSingleFile (file, input) =
278278

279279
// Wait until type checking succeeds (or 100 attempts)
280280
match checkFileResults with
281-
| FSharpCheckFileAnswer.Succeeded(res) -> parseFileResults, res
281+
| FSharpCheckFileAnswer.Succeeded res -> parseFileResults, res
282282
| res -> failwithf "Parsing did not finish... (%A)" res
283283

284284

Prover/LanguageServices/Wybe/Semantics.fs

Lines changed: 58 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -409,39 +409,20 @@ let semanticExprToWExpr (e: SemanticTree) : DomainWExpr =
409409
let domain = e.SemanticResult.Domain |> Option.map typedToWExpr
410410
DomainWExpr(domain, typedToWExpr e)
411411

412-
type StateSpace =
413-
| StateSpace of Map<string, Type> * Proposition
414-
415-
override this.ToString() : string =
416-
let p = this.Proposition.ToString()
417-
418-
let vars =
419-
this.Vars
420-
|> Map.toList
421-
|> List.map (fun (k, v) -> $"{k}: {v}")
422-
|> String.concat "\n"
423-
424-
$"\n{vars}\n{p}"
425-
426-
member this.Proposition =
427-
let (StateSpace(_, prop)) = this
428-
prop
429-
430-
member this.Vars =
431-
let (StateSpace(vars, _)) = this
432-
vars
412+
let varsToString (vars: Map<string, Type>) =
413+
vars |> Map.toList |> List.map (fun (k, v) -> $"{k}: {v}") |> String.concat "\n"
433414

434415
let makeWExpr vars (expected: Type) (expr: Expr) =
435416
match checkChildrenFixedType vars (expr, expected) (expected, [ expr ]) with
436417
| e when e.SemanticResult.Type.IsSome -> Ok(semanticExprToWExpr e)
437418
| e -> Error e.SemanticResult
438419

439-
let makeStateSpace vars (predicate: Expr) =
420+
let makePredicate vars (predicate: Expr) =
440421
match checkChildrenFixedType vars (predicate, Type.Boolean) (Type.Boolean, [ predicate ]) with
441422
| pred when pred.SemanticResult.Type.IsSome ->
442423
match semanticExprToWExpr pred with
443-
| wexpr when wexpr.Domain.IsSome -> Ok(StateSpace(vars, wexpr.Domain.Value <&&> wexpr.Expr))
444-
| wexpr -> Ok(StateSpace(vars, wexpr.Expr :?> Proposition))
424+
| wexpr when wexpr.Domain.IsSome -> Ok(wexpr.Domain.Value <&&> wexpr.Expr)
425+
| wexpr -> Ok(wexpr.Expr :?> Proposition)
445426
| r -> Error r
446427

447428
type Guard =
@@ -456,73 +437,68 @@ type Guard =
456437
body
457438

458439
and Statement =
459-
| VarDecl of SameTypeDecl list
460440
| Becomes of (string * DomainWExpr) list
461441
| If of Guard list
462442
| Do of Guard list
463-
| Assert of WExpr
443+
| Assert of Proposition
464444
| Compose of Statement * Statement
465445
| Skip
466446
| Abort
467447

468448
// weakest precondition of assignemt
469449
// wp.(x := E).P = defined.E ∧ P[x := E]
470-
let wpAssignment (becomes: (string * DomainWExpr) list) (space: StateSpace) =
450+
let wpAssignment (becomes: (string * DomainWExpr) list) (postcondition: Proposition) =
471451
let rec substitute (target: WExpr) ((var, expr): string * DomainWExpr) =
472452
target.TextualSubstitution var expr.Expr
473453

474-
let expr = becomes |> List.fold substitute space.Proposition
454+
let expr = becomes |> List.fold substitute postcondition
475455

476456
match becomes |> List.choose (snd >> _.Domain) with
477-
| [] -> StateSpace(space.Vars, expr :?> Proposition)
457+
| [] -> expr :?> Proposition
478458
| x :: xs ->
479459
let domain = xs |> List.fold (fun acc x -> acc <&&> x) (x :?> Proposition)
480-
StateSpace(space.Vars, domain <&&> expr)
460+
domain <&&> expr
481461

482-
let wpVarDecls (xs: SameTypeDecl list) (space: StateSpace) =
483-
let addVarType t (acc: Map<string, Type>) name = Map.add name t acc
484-
let addSameType vars t map = vars |> List.fold (addVarType t) map
485-
486-
let newVars =
487-
xs |> List.fold (fun acc (vars, t) -> addSameType vars t acc) space.Vars
488-
489-
StateSpace(newVars, space.Proposition)
490-
491-
let rec wpComposition (s: Statement, t: Statement) (space: StateSpace) = wpStatement s (wpStatement t space)
462+
let rec wpComposition (s: Statement, t: Statement) (postcondition: Proposition) =
463+
wpStatement s (wpStatement t postcondition)
492464
// wp.(if cond0 -> body0 | cond1 -> body1 fi).P = (cond0 ∨ cond1) ∧ (cond0 ⇒ wp.body0.P) ∧ (cond1 ⇒ wp.body1.P)
493-
and wpAlternative (guards: Guard list) (space: StateSpace) =
465+
and wpAlternative (guards: Guard list) (postcondition: Proposition) =
494466
let conds, bodies =
495467
guards
496-
|> List.map (fun g -> g.Condition, g.Condition ==> (wpStatement g.Body space).Proposition)
468+
|> List.map (fun g -> g.Condition, g.Condition ==> wpStatement g.Body postcondition)
497469
|> List.unzip
498470

499471
let orConds =
500472
conds.Tail |> List.fold (fun acc c -> acc <||> c) (conds.Head :?> Proposition)
501473

502474
let andBodies = bodies.Tail |> List.fold (fun acc c -> acc <&&> c) bodies.Head
503-
StateSpace(space.Vars, orConds <&&> andBodies)
475+
orConds <&&> andBodies
504476

505477
// wlp.(do cond0 → body0 | cond1 → body1 od).P = (cond0 ∧ P ⇒ wp.body0.P) ∧ (cond1 ∧ P ⇒ wp.body1.P)
506-
and wlpRepetition (guards: Guard list) (space: StateSpace) =
478+
and wlpRepetition (guards: Guard list) (postcondition: Proposition) =
507479
let bodies =
508480
guards
509-
|> List.map (fun g -> g.Condition <&&> space.Proposition ==> (wpStatement g.Body space).Proposition)
481+
|> List.map (fun g -> g.Condition <&&> postcondition ==> wpStatement g.Body postcondition)
510482

511483
let andBodies = bodies.Tail |> List.fold (fun acc c -> acc <&&> c) bodies.Head
512-
StateSpace(space.Vars, andBodies)
484+
andBodies
513485

514-
and wpStatement (s: Statement) (space: StateSpace) =
486+
and wpStatement (s: Statement) (postcondition: Proposition) =
515487
match s with
516-
| VarDecl xs -> wpVarDecls xs space
517-
| Becomes becomes -> wpAssignment becomes space
518-
| Compose(s, t) -> wpComposition (s, t) space
519-
| If guards -> wpAlternative guards space
520-
| Do guards -> wlpRepetition guards space
521-
| Assert expr -> StateSpace(space.Vars, expr ==> space.Proposition)
522-
| Skip -> space // wp.skip.P = P
523-
| Abort -> StateSpace(Map.empty, False)
524-
525-
let rec astStatementToSemantic (vars: Map<string, Type>) (s: AST.Statement) =
488+
| Becomes becomes -> wpAssignment becomes postcondition
489+
| Compose(s, t) -> wpComposition (s, t) postcondition
490+
| If guards -> wpAlternative guards postcondition
491+
| Do guards -> wlpRepetition guards postcondition
492+
| Assert expr -> expr ==> postcondition
493+
| Skip -> postcondition // wp.skip.P = P
494+
| Abort -> False
495+
496+
type AstSemanticResult =
497+
| NewVars of Map<string, Type>
498+
| NewStatement of Statement
499+
| FailedSemantic of SemanticResult
500+
501+
let rec astStatementToSemantic (vars: Map<string, Type>) (s: AST.Statement) : AstSemanticResult =
526502
let splitResult (rs: Result<'a, 'b> list) =
527503
let oks, errs = rs |> List.partition Result.isOk
528504

@@ -540,33 +516,36 @@ let rec astStatementToSemantic (vars: Map<string, Type>) (s: AST.Statement) =
540516

541517
oks, errs
542518

543-
let guardedBlock (guards: AST.Guard list) =
519+
let guardedBlock (constructor: Guard list -> Statement) (guards: AST.Guard list) =
544520
let oks, errs =
545521
guards
546522
|> List.map (fun g ->
547-
match makeStateSpace vars g.Condition with
523+
match makePredicate vars g.Condition with
548524
| Ok e ->
549525
match astStatementToSemantic vars g.Body with
550-
| Ok body -> Ok(Guard(e.Proposition, body))
551-
| Error m -> Error m
552-
| Error m -> Error m)
526+
| NewStatement body -> Ok(Guard(e, body))
527+
| FailedSemantic m -> Error m
528+
| NewVars _ -> failwith "not implemented"
529+
| Error m -> Error m.SemanticResult)
553530
|> splitResult
554531

555532
match errs with
556-
| [] -> Ok oks
557-
| errs ->
558-
let r = errs |> List.map _.SemanticResult |> MultipleResults
559-
Error(ST((r, Lit(Str "")), []))
560-
533+
| [] -> constructor oks |> NewStatement
534+
| errs -> errs |> MultipleResults |> FailedSemantic
561535

562536
match s with
563-
| AST.VarDecl xs -> Ok(VarDecl xs)
564-
| AST.Abort -> Ok Abort
565-
| AST.Skip -> Ok Skip
537+
| AST.VarDecl xs ->
538+
let addVarType t (acc: Map<string, Type>) name = Map.add name t acc
539+
let addSameType vars t map = vars |> List.fold (addVarType t) map
540+
541+
let newVars = xs |> List.fold (fun acc (vars, t) -> addSameType vars t acc) vars
542+
NewVars newVars
543+
| AST.Abort -> NewStatement Abort
544+
| AST.Skip -> NewStatement Skip
566545
| AST.Assert expr ->
567-
match makeStateSpace vars expr with
568-
| Ok s -> Ok(Assert s.Proposition)
569-
| Error e -> Error e
546+
match makePredicate vars expr with
547+
| Ok s -> NewStatement(Assert s)
548+
| Error e -> FailedSemantic e.SemanticResult
570549
| AST.Becomes(vs, exprs) when vs.Length.Equals exprs.Length ->
571550
let oks, errs =
572551
exprs
@@ -578,9 +557,9 @@ let rec astStatementToSemantic (vars: Map<string, Type>) (s: AST.Statement) =
578557
|> splitResult
579558

580559
match errs with
581-
| [] -> Ok(Becomes oks)
582-
| [ e ] -> Error(ST((e, Lit(Str "")), []))
583-
| _ -> Error(ST((MultipleResults errs, Lit(Str "")), []))
584-
| AST.Becomes _ -> Error(ST((MalformedAssignment, Lit(Str "")), []))
585-
| AST.Do guards -> guardedBlock guards |> Result.map Do
586-
| AST.If guards -> guardedBlock guards |> Result.map If
560+
| [] -> NewStatement(Becomes oks)
561+
| [ e ] -> FailedSemantic e
562+
| _ -> FailedSemantic(MultipleResults errs)
563+
| AST.Becomes _ -> FailedSemantic MalformedAssignment
564+
| AST.Do guards -> guardedBlock Do guards
565+
| AST.If guards -> guardedBlock If guards

Test/WybeLangTest.fs

Lines changed: 16 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -110,15 +110,12 @@ let ``wp assignment`` () =
110110
[ "n", DomainWExpr(None, n + 1), nExceeds0, n + 1 > zero
111111
"n", DomainWExpr(Some(m != zero), n / m), nExceeds0, m != zero <&&> (n / m > zero) ]
112112
|> List.iter (fun (var, expr, postcondition, wp) ->
113-
let r = wpAssignment [ var, expr ] (StateSpace(vars, postcondition))
114-
shouldEqual wp r.Proposition)
113+
let r = wpAssignment [ var, expr ] postcondition
114+
shouldEqual wp r)
115115

116116
[<Fact>]
117117
let ``wp composition`` () =
118-
[ Becomes [ "n", DomainWExpr(None, n + 1) ],
119-
Becomes [ "n", DomainWExpr(None, n * 2) ],
120-
StateSpace(vars, n > zero),
121-
StateSpace(vars, (n + 1) * 2 > zero) ]
118+
[ Becomes [ "n", DomainWExpr(None, n + 1) ], Becomes [ "n", DomainWExpr(None, n * 2) ], n > zero, (n + 1) * 2 > zero ]
122119
|> List.iter (fun (s, t, postcondition, expected) ->
123120
let wp = wpComposition (s, t) postcondition
124121
shouldEqual expected wp)
@@ -128,23 +125,20 @@ let ``wp alternative`` () =
128125
[ [ Guard(Core.Equals(n, zero), Becomes [ "n", DomainWExpr(None, n + 1) ])
129126
Guard(n > zero, Skip)
130127
Guard(n < zero, Becomes [ "n", DomainWExpr(None, n * -1) ]) ],
131-
StateSpace(vars, n > zero),
132-
StateSpace(
133-
vars,
134-
(n = zero <||> (n > zero) <||> (n < zero))
135-
<&&> (n = zero ==> (n + 1 > zero))
136-
<&&> (n > zero ==> (n > zero))
137-
<&&> (n < zero ==> (n * -1 > zero))
138-
) ]
139-
|> List.iter (fun (guards, space, expected) ->
140-
let r = wpAlternative guards space
141-
shouldEqual $"{expected}" $"{r}")
128+
n > zero,
129+
(n = zero <||> (n > zero) <||> (n < zero))
130+
<&&> (n = zero ==> (n + 1 > zero))
131+
<&&> (n > zero ==> (n > zero))
132+
<&&> (n < zero ==> (n * -1 > zero)) ]
133+
|> List.iter (fun (guards, postcondition, expected) ->
134+
let wp = wpAlternative guards postcondition
135+
shouldEqual $"{expected}" $"{wp}")
142136

143137
[<Fact>]
144138
let ``wlp repetition`` () =
145139
[ [ Guard(n > zero, Becomes [ "n", DomainWExpr(None, n - 1) ]) ],
146-
StateSpace(vars, n >= zero),
147-
StateSpace(vars, (n > zero <&&> (n >= zero) ==> (n - 1 >= zero))) ]
148-
|> List.iter (fun (guards, space, expected) ->
149-
let r = wlpRepetition guards space
150-
shouldEqual expected r)
140+
n >= zero,
141+
(n > zero <&&> (n >= zero) ==> (n - 1 >= zero)) ]
142+
|> List.iter (fun (guards, postcondition, expected) ->
143+
let wp = wlpRepetition guards postcondition
144+
shouldEqual expected wp)

0 commit comments

Comments
 (0)