Skip to content

Commit f00a33a

Browse files
tnelsonshoujohnny
andauthored
Modify the cores pipeline to get cores info to Sterling (#312)
* fix: join parsing, regression test, note on 2nd issue * add: semantics test * add: tests, no-op change to parser for readability * add: revisions to get core (strings, for the moment) to sterling * fix: unsat but no core * stop sending core in place of source * Froglet Error Message Changes (#306) * update: error messages --------- Co-authored-by: shoujohnny <johnson_shou@brown.edu>
1 parent 3ebbf83 commit f00a33a

File tree

8 files changed

+161
-105
lines changed

8 files changed

+161
-105
lines changed

forge/froglet/lang/bsl-lang-specific-checks.rkt

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -140,22 +140,22 @@
140140
(define (check-node-expr-op-+ expr-node node-type child-types)
141141
(when (eq? (nodeinfo-lang (node-info expr-node)) LANG_ID)
142142
(define loc (nodeinfo-loc (node-info expr-node)))
143-
(raise-bsl-relational-error "+" expr-node loc "You may have meant to use the `add` predicate instead.")))
143+
(raise-bsl-relational-error "+" expr-node loc "The `+` operator is not used in Froglet, but is reserved for use in other Forge languages. If you meant addition, use the `add` predicate instead.")))
144144

145145
(define (check-node-expr-op-- expr-node node-type child-types)
146146
(when (eq? (nodeinfo-lang (node-info expr-node)) LANG_ID)
147147
(define loc (nodeinfo-loc (node-info expr-node)))
148-
(raise-bsl-relational-error "-" expr-node loc "You may have meant to use the `subtract` predicate instead.")))
148+
(raise-bsl-relational-error "-" expr-node loc "The `-` operator is not used in Froglet, but is reserved for use in other Forge languages. If you meant subtraction, use the `subtract` predicate instead.")))
149149

150150
(define (check-node-expr-op-& expr-node node-type child-types)
151151
(when (eq? (nodeinfo-lang (node-info expr-node)) LANG_ID)
152152
(define loc (nodeinfo-loc (node-info expr-node)))
153-
(raise-bsl-relational-error "&" expr-node loc)))
153+
(raise-bsl-relational-error "&" expr-node loc "The `&` operator is not used in Froglet, but is reserved for use in other Forge languages. If you meant logical-and, use `and` or `&&` instead.")))
154154

155155
(define (check-node-expr-op--> expr-node node-type child-types)
156156
(when (eq? (nodeinfo-lang (node-info expr-node)) LANG_ID)
157157
(define loc (nodeinfo-loc (node-info expr-node)))
158-
(raise-bsl-error "Use of -> in expressions is not allowed in forge/bsl" expr-node loc)))
158+
(raise-bsl-error "The `->` operator is only used for field declaration in Froglet." expr-node loc)))
159159

160160
(define (check-node-expr-op-join expr-node node-type child-types)
161161
(when (eq? (nodeinfo-lang (node-info expr-node)) LANG_ID)
@@ -170,17 +170,17 @@
170170
(define (check-node-expr-op-^ expr-node node-type child-types)
171171
(when (eq? (nodeinfo-lang (node-info expr-node)) LANG_ID)
172172
(define loc (nodeinfo-loc (node-info expr-node)))
173-
(raise-bsl-relational-error "^" expr-node loc)))
173+
(raise-bsl-relational-error "^" expr-node loc "The `^` operator is not used in Froglet, but is reserved for use in other Forge languages. If you meant exclusive-or, use the `xor` operator instead.")))
174174

175175
(define (check-node-expr-op-* expr-node node-type child-types)
176176
(when (eq? (nodeinfo-lang (node-info expr-node)) LANG_ID)
177177
(define loc (nodeinfo-loc (node-info expr-node)))
178-
(raise-bsl-relational-error "*" expr-node loc)))
178+
(raise-bsl-relational-error "*" expr-node loc "The `*` operator is not used in Froglet, but is reserved for use in other Forge languages. If you meant multiplication, use the `multiply` predicate instead.")))
179179

180180
(define (check-node-expr-op-~ expr-node node-type child-types)
181181
(when (eq? (nodeinfo-lang (node-info expr-node)) LANG_ID)
182182
(define loc (nodeinfo-loc (node-info expr-node)))
183-
(raise-bsl-relational-error "~~" expr-node loc)))
183+
(raise-bsl-relational-error "~~" expr-node loc "The `~` operator is not used in Froglet, but is reserved for use in other Forge languages. If you meant logical-negation, use `not` or '!' instead.")))
184184

185185
(define bsl-checker-hash (make-hash))
186186
(hash-set! bsl-checker-hash node/formula/multiplicity check-formula-mult)
@@ -259,38 +259,38 @@
259259
(define (check-args-node-expr-op--> expr-args info)
260260
(when (eq? (nodeinfo-lang info) LANG_ID)
261261
(define loc (nodeinfo-loc info))
262-
(raise-bsl-error-deparsed-str "Direct use of -> in a formula is not allowed in Froglet" (format "(~a->~a)" (deparse (first expr-args)) (deparse (second expr-args))) loc)))
262+
(raise-bsl-error-deparsed-str "The `->` operator is only used for field declaration in Froglet." (format "(~a->~a)" (deparse (first expr-args)) (deparse (second expr-args))) loc)))
263263

264264
(define (check-args-node-expr-op-+ expr-args info)
265265
(when (eq? (nodeinfo-lang info) LANG_ID)
266266
(define loc (nodeinfo-loc info))
267-
(raise-bsl-relational-error-expr-args "+" expr-args loc "You may have meant to use the `add` predicate instead.")))
267+
(raise-bsl-relational-error-expr-args "+" expr-args loc "The `+` operator is not used in Froglet, but is reserved for use in other Forge languages. If you meant addition, use the `add` predicate instead.")))
268268

269269

270270
(define (check-args-node-expr-op-- expr-args info)
271271
(when (eq? (nodeinfo-lang info) LANG_ID)
272272
(define loc (nodeinfo-loc info))
273-
(raise-bsl-relational-error-expr-args "-" expr-args loc "You may have meant to use the `subtract` predicate instead.")))
273+
(raise-bsl-relational-error-expr-args "-" expr-args loc "The `-` operator is not used in Froglet, but is reserved for use in other Forge languages. If you meant subtraction, use the `subtract` predicate instead.")))
274274

275275
(define (check-args-node-expr-op-& expr-args info)
276276
(when (eq? (nodeinfo-lang info) LANG_ID)
277277
(define loc (nodeinfo-loc info))
278-
(raise-bsl-relational-error-expr-args "&" expr-args loc)))
278+
(raise-bsl-relational-error-expr-args "&" expr-args loc "The `&` operator is not used in Froglet, but is reserved for use in other Forge languages. If you meant logical-and, use `and` or `&&` instead.")))
279279

280280
(define (check-args-node-expr-op-^ expr-args info)
281281
(when (eq? (nodeinfo-lang info) LANG_ID)
282282
(define loc (nodeinfo-loc info))
283-
(raise-bsl-relational-error-expr-args "^" expr-args loc)))
283+
(raise-bsl-relational-error-expr-args "^" expr-args loc "The `^` operator is not used in Froglet, but is reserved for use in other Forge languages. If you meant exclusive-or, use the `xor` operator instead.")))
284284

285285
(define (check-args-node-expr-op-* expr-args info)
286286
(when (eq? (nodeinfo-lang info) LANG_ID)
287287
(define loc (nodeinfo-loc info))
288-
(raise-bsl-relational-error-expr-args "*" expr-args loc)))
288+
(raise-bsl-relational-error-expr-args "*" expr-args loc "The `*` operator is not used in Froglet, but is reserved for use in other Forge languages. If you meant multiplication, use the `multiply` predicate instead.")))
289289

290290
(define (check-args-node-expr-op-~ expr-args info)
291291
(when (eq? (nodeinfo-lang info) LANG_ID)
292292
(define loc (nodeinfo-loc info))
293-
(raise-bsl-relational-error-expr-args "~" expr-args loc)))
293+
(raise-bsl-relational-error-expr-args "~" expr-args loc "The `~` operator is not used in Froglet, but is reserved for use in other Forge languages. If you meant logical-negation, use `not` or '!' instead.")))
294294

295295
; Prevent the forge/core arity error from appearing, since it breaks closure
296296
(define (check-args-node-formula-op-= expr-args info)

forge/server/forgeserver.rkt

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
; should be called for any context where a menu of commands doesn't fit (such as a
1515
; failing test, perhaps).
1616

17-
(require (only-in forge/lang/ast relation-name raise-forge-error)
17+
(require (only-in forge/lang/ast relation-name raise-forge-error deparse node?)
1818
forge/server/modelToXML
1919
forge/evaluator
2020
xml
@@ -130,7 +130,7 @@
130130
[else
131131
(printf "Sterling: unexpected 'next' request type: ~a~n" json-m)]))
132132
(define xml (get-xml inst))
133-
(define response (make-sterling-data xml datum-id name temporal? (Sat? inst) old-datum-id))
133+
(define response (make-sterling-data xml datum-id name temporal? inst old-datum-id))
134134
(send-to-sterling response #:connection connection)]
135135
[else
136136
(printf "Sterling: unexpected onClick: ~a~n" json-m)])
@@ -143,7 +143,7 @@
143143
(define inst (get-current-instance))
144144
(define id curr-datum-id)
145145
(define xml (get-xml inst))
146-
(define response (make-sterling-data xml id name temporal? (Sat? inst)))
146+
(define response (make-sterling-data xml id name temporal? inst))
147147
(send-to-sterling response #:connection connection)
148148
]
149149
[(equal? (hash-ref json-m 'type) "eval")
@@ -199,7 +199,22 @@
199199
(unless (equal? 'off (get-option state-for-run 'run_sterling))
200200
(serve-sterling-static #:provider-port port)))
201201

202-
(define (make-sterling-data xml id run-name temporal? not-done? [old-id #f])
202+
(define (make-status-value inst)
203+
(cond [(Sat? inst) "sat"]
204+
[(Unsat? inst) "unsat"]
205+
[(Unknown? inst) "unknown"]
206+
[else "error"]))
207+
(define (make-core-value inst)
208+
(if (and (Unsat? inst) (Unsat-core inst))
209+
(map (lambda (cr) (cond [(node? cr) (deparse cr)]
210+
[(string? cr) cr]
211+
[else (raise-forge-error #:msg (format "Unexpected core value sending to Sterling: ~a" cr)
212+
#:context #f)]))
213+
(Unsat-core inst))
214+
#f))
215+
216+
(define (make-sterling-data xml id run-name temporal? inst [old-id #f])
217+
(define not-done? (Sat? inst))
203218
(jsexpr->string
204219
(hash
205220
'type "data"
@@ -210,6 +225,8 @@
210225
'generatorName (->string run-name)
211226
'format "alloy"
212227
'data xml
228+
'status (make-status-value inst)
229+
'core (make-core-value inst)
213230
'buttons (cond [(not not-done?) (list)]
214231
[temporal?
215232
(list (hash 'text "Next Trace"
@@ -407,7 +424,7 @@
407424
; is-run-closed? is about whether this specific run has been terminated
408425
; Sat? is about whether the solution we have is Sat.
409426
(define response (make-sterling-data xml datum-id name temporal?
410-
(and (is-running? the-run) (not (is-run-closed? the-run)) (Sat? inst))
427+
(and (is-running? the-run) (not (is-run-closed? the-run)) inst)
411428
old-datum-id))
412429
(send-to-sterling response #:connection connection)]
413430
[else

forge/server/modelToXML.rkt

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -110,12 +110,16 @@
110110
[(list? rs-opt) (apply string-append (map single-path-to-xml rs-opt))]
111111
[else ""]))
112112

113-
(define (clean str)
114-
(string-replace
115-
(string-replace
116-
(string-replace
113+
(define (clean ele)
114+
(cond
115+
[(string? ele)
117116
(string-replace
118-
(string-replace str "\"" "&quot;") ">" "&gt;") "<" "&lt;") "&" "&amp;") "\n" "&#xA;"))
117+
(string-replace
118+
(string-replace
119+
(string-replace
120+
(string-replace ele "\"" "&quot;") ">" "&gt;") "<" "&lt;") "&" "&amp;") "\n" "&#xA;")]
121+
[(node? ele) (deparse ele)]
122+
[else ele]))
119123

120124
(define (agg-lines lines)
121125
(if (empty? lines)
@@ -221,11 +225,11 @@ here-string-delimiter
221225
"<atom label=\"Unsatisfiable\"/>"
222226
"</sig>\n"
223227
"\n</instance>\n"
224-
(if data
225-
(string-append "<source filename=\"Unsat Core\" content=\""
226-
(agg-lines
227-
(map clean data))
228-
"\"></source>\n") "")
228+
"<source filename=\"" filepath "\" content=\""
229+
(with-handlers ([exn:fail:filesystem:errno?
230+
(λ (exn) (format "// Couldn't open source file (~a) (info: ~a). Is the file saved?" filepath (exn:fail:filesystem:errno-errno exn)))])
231+
(clean (agg-lines (port->lines (open-input-file filepath)))))
232+
"\"></source>\n"
229233
"</alloy>")]
230234

231235
; ** Special display for "out of instances" vs. "unsat" **

forge/sigs-structs.rkt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,11 @@
3838
) #:transparent)
3939

4040
(struct/contract Unsat (
41-
[core (or/c #f (listof any/c))]; list-of-Formula-string-or-formulaID)]
41+
;[core (or/c #f (listof any/c))]; list-of-Formula-string-or-formulaID)]
42+
; If there's a core, there are two cases per component:
43+
; (1) a node: a known formula
44+
; (2) a string: an unknown formula (Kodkod couldn't map back this part of the core)
45+
[core (or/c #f (listof (or/c node? string?)))]
4246
[stats any/c] ; association list
4347
[kind symbol?] ; symbol
4448
) #:transparent)
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
#lang racket/base
2+
3+
(require forge/lang/ast)
4+
(require racket/string
5+
(only-in racket first empty? rest)
6+
(except-in racket/contract ->)
7+
(prefix-in @ (only-in racket/contract ->))
8+
9+
(prefix-in @ (only-in racket +))
10+
(only-in forge/shared get-verbosity VERBOSITY_HIGH))
11+
(provide pretty-print-core-formula process-core-formula pretty-format-core-formula)
12+
13+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
14+
; Note on cores: if core granularity is high, Kodkod may return a formula we do not have an ID for.
15+
; In these cases, the engine should be passing something like "f:0,0" which indexes _child_ formulas.
16+
; (In *very* rare cases, Kodkod may not be able to blame a subformula, and just give us a string.)
17+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
18+
(define (traverse-path-list path core-map [fmla #f])
19+
;; Cannot use for/fold or fold here, because we need to _not_ move down the list for
20+
;; a node/fmla/pred-spacer node (and any other node that is invisible to Pardinus).
21+
(cond
22+
; Base case: no more indexes to process
23+
[(empty? path) fmla]
24+
; We have an index, descend as appropriate
25+
[else
26+
(define idx-str (first path))
27+
(define idx (string->number idx-str))
28+
(cond [(not fmla)
29+
(traverse-path-list (rest path)
30+
core-map
31+
(hash-ref core-map idx))]
32+
[(node/formula/quantified? fmla)
33+
; Quantified: decls formulas first, then sub-formula last
34+
(cond [(>= idx (length (node/formula/quantified-decls fmla)))
35+
(traverse-path-list (rest path)
36+
core-map
37+
(node/formula/quantified-formula fmla))]
38+
[else
39+
(define decl (list-ref (node/formula/quantified-decls fmla) idx))
40+
(traverse-path-list (rest path)
41+
core-map
42+
(car decl))])]
43+
[(node/formula/op? fmla)
44+
; Operator formula: sub-formulas in order. Note that this layer isn't shown
45+
; to Pardinus, so we cannot move down the path index list for this.
46+
(traverse-path-list (rest path)
47+
core-map
48+
(list-ref (node/formula/op-children fmla) idx))]
49+
[(node/fmla/pred-spacer? fmla)
50+
; Predicate spacer, just use internal formula, and don't move forward in the path
51+
(traverse-path-list path
52+
core-map
53+
(node/fmla/pred-spacer-expanded fmla))]
54+
[else
55+
(raise-user-error (format "Unsupported formula type in core: ~a" fmla))])]))
56+
57+
(define (find-core-formula id core-map)
58+
(unless (string-prefix? id "f:")
59+
(raise-user-error (format "Unexpected error: invalid formula path ID: ~a" id)))
60+
(define path (string-split (first (string-split id "f:")) ","))
61+
(when (>= (get-verbosity) VERBOSITY_HIGH)
62+
(printf "core path: ~a~n" path))
63+
(unless (and (> (length path) 0) (member (string->number (first path)) (hash-keys core-map)))
64+
(raise-user-error (format "Unexpected error: solver path ID prefix was invalid: ~a; valid prefixes: ~a" id (hash-keys core-map))))
65+
(traverse-path-list path core-map #f))
66+
67+
; A processed core formula will hopefully be a node, but it might also be a string
68+
; describing a formula that Kodkod couldn't map back. (This happens sometimes when using
69+
; temporal operators, but it's rare.)
70+
(define/contract (process-core-formula fmla-or-id core-map)
71+
(@-> (or/c node? string?) hash? (or/c string? node?))
72+
; (printf "***~n*** process-core-formula ~a ~a~n" fmla-or-id core-map)
73+
;(define fmla-num (if (string-prefix? id "f:") (string->number (substring id 2)) #f)]
74+
(cond [(and (string? fmla-or-id) (string-prefix? fmla-or-id "f:"))
75+
(find-core-formula fmla-or-id core-map)]
76+
; Otherwise, it might be a node already, or else a string with a formula
77+
; Kodkod couldn't find a blame path for.
78+
[else fmla-or-id]))
79+
80+
(define (pretty-format-core-formula idx max fmla-or-id core-map)
81+
(define fmla-or-string (process-core-formula fmla-or-id core-map))
82+
(cond [(node? fmla-or-string)
83+
(format "Core(part ~a/~a): [~a] ~a~n" (@+ idx 1) max
84+
(pretty-loc fmla-or-string) (deparse fmla-or-string))]
85+
[else
86+
(format "Core(part ~a/~a): [UNKNOWN] ~a~n" (@+ idx 1) max
87+
fmla-or-string)]))
88+
89+
(define (pretty-print-core-formula idx max fmla-or-id core-map)
90+
(fprintf (current-error-port) (pretty-format-core-formula idx max fmla-or-id core-map)))
91+

0 commit comments

Comments
 (0)