Skip to content

Commit 7ee14a6

Browse files
authored
[spectec] Formalise binding semantics for let premises (#2109)
1 parent 7d618b1 commit 7ee14a6

32 files changed

Lines changed: 327 additions & 164 deletions

‎spectec/Makefile‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,12 @@ sync%:
113113
(cd ../specification && make $@)
114114

115115

116+
# Semantics checks
117+
118+
sem:
119+
(cd doc/semantics/il && make check)
120+
121+
116122
# Cleanup
117123

118124
.PHONY: clean distclean
0 Bytes
Binary file not shown.

‎spectec/doc/semantics/il/1-syntax.spectec‎

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,9 @@ syntax deftyp =
3131
| VARIANT typcase*
3232

3333
syntax typbind = id `: typ
34-
syntax typfield = atom `: typ `- `{quant*} prem*
35-
syntax typcase = mixop `: typ `- `{quant*} prem*
34+
syntax typfield = atom `: typprems
35+
syntax typcase = mixop `: typprems
36+
syntax typprems = typ `- `{quant*} prem*
3637

3738

3839
;; Iterators
@@ -130,6 +131,8 @@ syntax exp =
130131

131132
syntax expfield = atom `= exp
132133
syntax exppull = id `: typ `<- exp
134+
syntax exppush = exp `-> id `: typ
135+
syntax expprems = exp `- prem*
133136

134137
syntax path =
135138
| ROOT ;;
@@ -174,8 +177,8 @@ syntax prem =
174177
| IF exp
175178
| ELSE
176179
| NOT prem
177-
| LET exp `= exp ;; TODO: variables/quantifiers?
178-
| ITER prem iter exppull*
180+
| LET `{quant*} exp `= exp
181+
| ITER prem iter exppull* exppush*
179182

180183
syntax dec =
181184
| TYP id param* `= inst*
@@ -185,9 +188,9 @@ syntax dec =
185188
| REC dec*
186189

187190
syntax inst = INST `{quant*} arg* `=> deftyp
188-
syntax rul = RULE `{quant*} exp `- prem*
189-
syntax clause = CLAUSE `{quant*} arg* `=> exp `- prem*
190-
syntax prod = PROD `{quant*} sym `=> exp `- prem*
191+
syntax rul = RULE `{quant*} expprems
192+
syntax clause = CLAUSE `{quant*} arg* `=> expprems
193+
syntax prod = PROD `{quant*} sym `=> expprems
191194

192195

193196
;; Scripts

‎spectec/doc/semantics/il/4-subst.spectec‎

Lines changed: 57 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -107,12 +107,38 @@ def $refresh_exppulls(ep*) = (ep', $composesubsts(s*))
107107
-- (if (ep', s) = $refresh_exppull(ep))*
108108

109109

110+
def $refresh_exppush(exppush) : (exppush, subst)
111+
def $refresh_exppushs(exppush*) : (exppush*, subst)
112+
113+
def $refresh_exppush(e `-> x `: t) = (e `-> x' `: t, s)
114+
-- if (x', s) = $refresh_expid(x)
115+
116+
def $refresh_exppushs(eq*) = (eq', $composesubsts(s*))
117+
-- (if (eq', s) = $refresh_exppush(eq))*
118+
119+
110120
def $refresh_iter(iter) : (iter, subst)
111121

112122
def $refresh_iter(QUEST) = (QUEST, {})
113123
def $refresh_iter(STAR) = (STAR, {})
114124
def $refresh_iter(PLUS) = (PLUS, {})
115-
def $refresh_iter(SUP x e) = (SUP x' e, s) -- if (x', s) = $refresh_expid(x)
125+
def $refresh_iter(SUP x e) = (SUP x' e, s)
126+
-- if (x', s) = $refresh_expid(x)
127+
128+
129+
def $refresh_prem(prem) : (prem, subst)
130+
def $refresh_prems(prem*) : (prem*, subst)
131+
132+
def $refresh_prem(REL x a* `: e) = (REL x a* `: e, {})
133+
def $refresh_prem(IF e) = (IF e, {})
134+
def $refresh_prem(ELSE) = (ELSE, {})
135+
def $refresh_prem(LET `{q*} e_1 `= e_2) = (LET `{q'*} $subst_exp(s, e_1) `= e_2, s)
136+
-- if (q'*, s) = $refresh_params(q*)
137+
def $refresh_prem(ITER pr it ep* eq*) = (ITER pr it ep* eq'*, s)
138+
-- if (eq'*, s) = $refresh_exppushs(eq*)
139+
140+
def $refresh_prems(pr*) =
141+
$refresh_list(prem, $refresh_prem, $subst_prem, pr*)
116142

117143

118144
;; Lists
@@ -142,12 +168,8 @@ def $subst_typ(s, MATCH x a* WITH inst*) = MATCH x $subst_arg(s, a)* WITH $subs
142168

143169
def $subst_deftyp(subst, deftyp) : deftyp
144170
def $subst_deftyp(s, ALIAS t) = ALIAS $subst_typ(s, t)
145-
def $subst_deftyp(s, STRUCT (a `: t `- `{q*} pr*)*) = STRUCT (a `: $subst_typ(s, t') `- `{$subst_param(s ++ s', q')*} $subst_prem(s ++ s' ++ s'', pr)*)*
146-
-- if (t', s') = $refresh_typ(t)
147-
-- if (q'*, s'') = $refresh_params(q*)
148-
def $subst_deftyp(s, VARIANT (m `: t `- `{q*} pr*)*) = VARIANT (m `: $subst_typ(s, t') `- `{$subst_param(s ++ s', q')*} $subst_prem(s ++ s' ++ s'', pr)*)*
149-
-- if (t', s') = $refresh_typ(t)
150-
-- if (q'*, s'') = $refresh_params(q*)
171+
def $subst_deftyp(s, STRUCT (a `: tpr)*) = STRUCT (a `: $subst_typprems(s, tpr))*
172+
def $subst_deftyp(s, VARIANT (m `: tpr)*) = VARIANT (m `: $subst_typprems(s, tpr))*
151173

152174
def $subst_typbind(subst, typbind) : typbind
153175
def $subst_typbind(s, x `: t) = x' `: $subst_typ(s, t)
@@ -164,6 +186,9 @@ def $subst_iter(s, SUP x e) = SUP x $subst_exp(s, e)
164186
def $subst_exppull(subst, exppull) : exppull
165187
def $subst_exppull(s, x `: t `<- e') = x `: $subst_typ(s, t) `<- $subst_exp(s, e')
166188

189+
def $subst_exppush(subst, exppush) : exppush
190+
def $subst_exppush(s, e' `-> x `: t) = $subst_exp(s, e') `-> x `: $subst_typ(s, t)
191+
167192

168193
;; Expressions
169194

@@ -223,7 +248,7 @@ def $subst_sym(s, ITER g it ep*) = ITER $subst_sym(s ++ s' ++ s'', g) $subst_ite
223248
-- if (ep'*, s'') = $refresh_exppulls(ep*)
224249

225250

226-
;; Definitions
251+
;; Arguments and Parameters
227252

228253
def $subst_arg(subst, arg) : arg
229254
def $subst_arg(s, TYP t) = TYP $subst_typ(s, t)
@@ -239,30 +264,49 @@ def $subst_param(s, FUN x `: p* `-> t) = FUN x `: $subst_param(s, p')* `-> $subs
239264
def $subst_param(s, GRAM x `: p* `-> t) = GRAM x `: $subst_param(s, p')* `-> $subst_typ(s ++ s', t)
240265
-- if (p'*, s') = $refresh_params(p*)
241266

267+
268+
;; Premises
269+
242270
def $subst_prem(subst, prem) : prem
243271
def $subst_prem(s, REL x a* `: e) = REL x $subst_arg(s, a)* `: $subst_exp(s, e)
244272
def $subst_prem(s, IF e) = IF $subst_exp(s, e)
245273
def $subst_prem(s, ELSE) = ELSE
246-
def $subst_prem(s, LET e_1 `= e_2) = LET $subst_exp(s, e_1) `= $subst_exp(s, e_2)
247-
def $subst_prem(s, ITER pr it ep*) = ITER $subst_prem(s ++ s' ++ s'', pr) $subst_iter(s, it') $subst_exppull(s, ep')*
274+
def $subst_prem(s, LET `{q*} e_1 `= e_2) = LET `{$subst_param(s, q)*} $subst_exp(s, e_1) `= $subst_exp(s, e_2)
275+
;; Assume: q* fresh (from caller $subst_typprems, $subst_expprems)
276+
def $subst_prem(s, ITER pr it ep* eq*) = ITER $subst_prem(s ++ s' ++ s'', pr') $subst_iter(s, it') $subst_exppull(s, ep')* $subst_exppush(s ++ s''', eq')*
277+
;; Assume: eq* fresh (from caller $subst_typprems, $subst_expprems)
248278
-- if (it', s') = $refresh_iter(it)
249279
-- if (ep'*, s'') = $refresh_exppulls(ep*)
280+
-- if (pr', s''') = $refresh_prem(pr)
281+
250282

283+
def $subst_typprems(subst, typprems) : typprems
284+
def $subst_typprems(s, t `- `{q*} pr*) = $subst_typ(s, t') `- `{$subst_param(s ++ s', q')*} $subst_prem(s ++ s' ++ s'', pr')*
285+
-- if (t', s') = $refresh_typ(t)
286+
-- if (q'*, s'') = $refresh_params(q*)
287+
-- if (pr'*, s''') = $refresh_prems(pr*)
288+
289+
def $subst_expprems(subst, expprems) : expprems
290+
def $subst_expprems(s, e `- pr*) = $subst_exp(s ++ s', e) `- $subst_prem(s, pr)*
291+
-- if (pr'*, s') = $refresh_prems(pr*)
292+
293+
294+
;; Definitions
251295

252296
def $subst_inst(subst, inst) : inst
253297
def $subst_inst(s, INST `{q*} a* `=> dt) = INST `{$subst_param(s, q')*} $subst_arg(s ++ s', a)* `=> $subst_deftyp(s ++ s', dt)
254298
-- if (q'*, s') = $refresh_params(q*)
255299

256300
def $subst_rule(subst, rul) : rul
257-
def $subst_rule(s, RULE `{q*} e `- pr*) = RULE `{$subst_param(s, q')*} $subst_exp(s ++ s', e) `- $subst_prem(s ++ s', pr)*
301+
def $subst_rule(s, RULE `{q*} epr) = RULE `{$subst_param(s, q')*} $subst_expprems(s ++ s', epr)
258302
-- if (q'*, s') = $refresh_params(q*)
259303

260304
def $subst_clause(subst, clause) : clause
261-
def $subst_clause(s, CLAUSE `{q*} a* `=> e `- pr*) = CLAUSE `{$subst_param(s, q')*} $subst_arg(s ++ s', a)* `=> $subst_exp(s ++ s', e) `- $subst_prem(s ++ s', pr)*
305+
def $subst_clause(s, CLAUSE `{q*} a* `=> epr) = CLAUSE `{$subst_param(s, q')*} $subst_arg(s ++ s', a)* `=> $subst_expprems(s ++ s', epr)
262306
-- if (q'*, s') = $refresh_params(q*)
263307

264308
def $subst_prod(subst, prod) : prod
265-
def $subst_prod(s, PROD `{q*} g `=> e `- pr*) = PROD `{$subst_param(s, q')*} $subst_sym(s ++ s', g) `=> $subst_exp(s ++ s', e) `- $subst_prem(s ++ s', pr)*
309+
def $subst_prod(s, PROD `{q*} g `=> epr) = PROD `{$subst_param(s, q')*} $subst_sym(s ++ s', g) `=> $subst_expprems(s ++ s', epr)
266310
-- if (q'*, s') = $refresh_params(q*)
267311

268312

‎spectec/doc/semantics/il/5-reduction.spectec‎

Lines changed: 64 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ rule Step_typ/ITER-ctx:
8080

8181
relation Step_iter: S |- iter ~> iter
8282
relation Step_exppull: S |- exppull ~> exppull
83+
relation Step_exppush: S |- exppush ~> exppush
8384

8485
rule Step_iter/SUP-ctx:
8586
S |- SUP x e ~> SUP x e'
@@ -94,6 +95,14 @@ rule Step_exppull/ctx2:
9495
S |- x `: t `<- e ~> x `: t `<- e'
9596
-- Step_exp: S |- e ~> e'
9697

98+
rule Step_exppush/ctx1:
99+
S |- e `-> x `: t ~> e' `-> x `: t
100+
-- Step_exp: S |- e ~> e'
101+
102+
rule Step_exppush/ctx2:
103+
S |- e `-> x `: t ~> e `-> x `: t'
104+
-- Step_typ: S |- t ~> t'
105+
97106

98107
;; Expressions
99108

@@ -442,9 +451,9 @@ rule Step_exp/MATCH-ctx2:
442451
-- Step_clause: S |- clause*[n] ~> clause'_n
443452

444453
rule Step_exp/MATCH-match:
445-
S |- MATCH a* WITH (CLAUSE `{q*} a'* `=> e `- pr*) clause* ~>
454+
S |- MATCH a* WITH (CLAUSE `{q*} a'* `=> epr) clause* ~>
446455
MATCH a''* WITH
447-
(CLAUSE `{q'*} a'''* `=> $subst_exp(s, e) `- $subst_prem(s, pr)*)
456+
(CLAUSE `{q'*} a'''* `=> $subst_expprems(s, epr))
448457
(CLAUSE `{} a''* `=> (MATCH a* WITH clause*) `- eps)
449458
-- Step_argmatch: S |- `{q*} (a / a')* ~>_s `{q'*} (a'' / a''')*
450459

@@ -695,6 +704,7 @@ rule Step_expmatch_plain/STR-fail:
695704
S |- STR ef* / STR ef'* ~> FAIL
696705
-- otherwise
697706

707+
698708
rule Step_expmatch_plain/ITER-PLUS:
699709
S |- LIST e* / ITER e' PLUS (x `: t `<- e_p)* ~>
700710
LIST e* / ITER e' STAR (x `: t `<- e_p)*
@@ -743,8 +753,8 @@ rule Step_clause/CLAUSE-ctx2:
743753
-- Step_exp: S |- e ~> e'
744754

745755
rule Step_clause/CLAUSE-ctx3:
746-
S |- CLAUSE `{q*} a* `=> e `- pr* ~> CLAUSE `{q*} a* `=> e `- pr'*
747-
-- Step_prems: S |- pr* ~> pr'*
756+
S |- CLAUSE `{q*} a* `=> e `- pr* ~> CLAUSE `{q*} a* `=> $subst_exp(s, e) `- pr'*
757+
-- Step_prems: S |- pr* ~>_s pr'*
748758

749759

750760
;; Arguments
@@ -782,7 +792,7 @@ rule Step_arg/TYP-ctx:
782792
;; Premises
783793

784794
relation Reduce_prems: S |- prem* ~>* prem*
785-
relation Step_prems: S |- prem* ~> prem*
795+
relation Step_prems: S |- prem* ~>_subst prem*
786796
relation Eq_prems: S |- prem* == prem*
787797

788798

@@ -798,74 +808,96 @@ rule Reduce_prems/refl:
798808

799809
rule Reduce_prems/step:
800810
S |- pr* ~>* pr''*
801-
-- Step_prems: S |- pr* ~> pr'*
811+
-- Step_prems: S |- pr* ~>_s pr'*
802812
-- Reduce_prems: S |- pr'* ~>* pr''*
803813

804814

805-
rule Step_prems/ctx:
806-
S |- pr* ~> pr*[0 : n] pr'_n* pr*[n : |pr*| - n]
807-
-- Step_prems: S |- pr*[n] ~> pr'_n*
815+
rule Step_prems/seq:
816+
S |- pr_1* pr pr_2* ~>_(s ++ s') pr_1* pr'* $subst_prem(s, pr'_2)*
817+
-- Step_prems: S |- pr ~>_s pr'*
818+
-- if (pr'_2*, s') = $refresh_prems(pr_2*)
808819

809820

810821
rule Step_prems/REL:
811-
S |- REL x a* `: e ~> $subst_prem(s, pr)* (IF (CMP EQ $subst_exp(s, e') e))
822+
S |- REL x a* `: e ~>_{} pr'* (IF (CMP EQ $subst_exp(s ++ s', e') e))
812823
-- if (x, p* `-> t `= rul*) <- S.REL
813-
-- if (RULE `{q*} e' `- pr*) <- $subst_rule($args_for_params(a*, p*), rul)*
824+
-- if (RULE `{q*} (e' `- pr*)) <- $subst_rule($args_for_params(a*, p*), rul)*
814825
-- Ok_subst: $storeenv(S) |- s : q*
826+
-- if (pr'*, s') = $refresh_prems(pr*)
815827
;; Note: non-computational rule
816828

817829
rule Step_prems/IF-ctx:
818-
S |- IF e ~> IF e'
830+
S |- IF e ~>_{} IF e'
819831
-- Step_exp: S |- e ~> e'
820832

821833
rule Step_prems/IF-true:
822-
S |- IF (BOOL true) ~> eps
834+
S |- IF (BOOL true) ~>_{} eps
823835

824836
rule Step_prems/ELSE:
825-
S |- ELSE ~> IF (BOOL true)
837+
S |- ELSE ~>_{} IF (BOOL true)
826838

827839
rule Step_prems/LET-ctx:
828-
S |- LET e_1 `= e_2 ~> LET e_1 `= e'_2
840+
S |- LET `{q*} e_1 `= e_2 ~>_{} LET `{q*} e_1 `= e'_2
829841
-- Step_exp: S |- e_2 ~> e'_2
830842

831843
rule Step_prems/LET:
832-
S |- LET e `= e ~> eps
844+
S |- LET `{(EXP x `: t)*} e_1 `= e_2 ~>_{EXP (x, e)*} eps
845+
-- (if e = MATCH (EXP e_2) WITH (CLAUSE `{(EXP x `: t)*} (EXP e_1) `=> (VAR x) `- eps))*
846+
;; TODO: Propagate false in case of match failure
833847

834848
rule Step_prems/NOT-ctx:
835-
S |- NOT pr ~> NOT pr'
836-
-- Step_prems: S |- pr ~> pr'
849+
S |- NOT pr ~>_{} NOT pr'
850+
-- Step_prems: S |- pr ~>_s pr'
837851

838852
rule Step_prems/NOT-true:
839-
S |- NOT (IF (BOOL true)) ~> IF (BOOL false)
853+
S |- NOT (IF (BOOL true)) ~>_{} IF (BOOL false)
840854

841855
rule Step_prems/NOT-false:
842-
S |- NOT (IF (BOOL false)) ~> IF (BOOL true)
856+
S |- NOT (IF (BOOL false)) ~>_{} IF (BOOL true)
857+
858+
var ep : exppull
859+
var eq : exppush
843860

844861
rule Step_prems/ITER-ctx1:
845-
S |- ITER pr it ep* ~> ITER pr' it ep*
846-
-- Step_prems: S |- pr ~> pr'
862+
S |- ITER pr it ep* eq* ~>_{} ITER pr' it ep* $subst_exppush(s, eq)*
863+
-- Step_prems: S |- pr ~>_s pr'
847864

848865
rule Step_prems/ITER-ctx2:
849-
S |- ITER pr it ep* ~> ITER pr it' ep*
866+
S |- ITER pr it ep* eq* ~>_{} ITER pr it' ep* eq*
850867
-- Step_iter: S |- it ~> it'
851868

852869
rule Step_prems/ITER-ctx3:
853-
S |- ITER pr it ep* ~> ITER pr it ep*[[n] = ep'_n]
870+
S |- ITER pr it ep* eq* ~>_{} ITER pr it ep*[[n] = ep'_n] eq*
854871
-- Step_exppull: S |- ep*[n] ~> ep'_n
855872

873+
rule Step_prems/ITER-ctx4:
874+
S |- ITER pr it ep* eq* ~>_{} ITER pr it ep* eq*[[n] = eq'_n]
875+
-- Step_exppush: S |- eq*[n] ~> eq'_n
876+
856877
rule Step_prems/ITER-QUEST:
857-
S |- ITER pr QUEST (x `: t `<- OPT e?)* ~> $subst_prem({EXP (x, e')*}, pr)?
858-
-- if e'*? = $transpose_(exp, e?*)
878+
S |- ITER pr QUEST (x_1 `: t_1 `<- OPT e_1?)* (e_2 `-> x_2 `: t_2)* ~>_({EXP (x_2, OPT $subst_exp(s', e''_2)?)*} ++ s')
879+
$subst_prem({EXP (x_1, e'_1)*}, pr')?
880+
-- if e'_1*? = $transpose_(exp, e_1?*)
881+
-- if e'_2*? = $transpose_(exp, e''_2?*)
882+
-- (if |e_1?| = |e''_2?|)*
883+
-- (if e'_2 = e_2)*?
884+
-- if (pr', s') = $refresh_prem(pr)
859885

860886
rule Step_prems/ITER-PLUS:
861-
S |- ITER pr PLUS (x `: t `<- LIST e*)* ~> ITER pr STAR (x `: t `<- LIST e*)*
862-
-- if |e**[0]| >= 1
887+
S |- ITER pr PLUS (x_1 `: t_1 `<- LIST e_1*)* (e_2 `-> x_2 `: t_2)* ~>_{}
888+
ITER pr STAR (x_1 `: t_1 `<- LIST e_1*)* (e_2 `-> x_2 `: t_2)*
889+
-- if |e_1**[0]| >= 1
863890

864891
rule Step_prems/ITER-STAR:
865-
S |- ITER pr STAR (x `: t `<- LIST e*)* ~> ITER pr (SUP y (NAT n)) (x `: t `<- LIST e*)*
866-
-- if |e**[0]| = n
892+
S |- ITER pr STAR (x_1 `: t_1 `<- LIST e_1*)* (e_2 `-> x_2 `: t_2)* ~>_{}
893+
ITER pr (SUP y (NAT n)) (x_1 `: t_1 `<- LIST e_1*)* (e_2 `-> x_2 `: t_2)*
894+
-- if |e_1**[0]| = n
867895
-- Fresh_id: y FRESH
868896

869897
rule Step_prems/ITER-SUP:
870-
S |- ITER pr (SUP y (NAT n)) (x `: t `<- LIST e^n)* ~> $subst_prem({EXP (x, e')* (y, NAT i)}, pr)^(i<n)
871-
-- if e'*^n = $transpose_(exp, e^n*)
898+
S |- ITER pr (SUP y (NAT n)) (x_1 `: t_1 `<- LIST e_1^n)* ~>_({EXP (x_2, LIST $subst_exp(s', e''_2)^n)*} ++ s')
899+
$subst_prem({EXP (x_1, e'_1)* (y, NAT i)}, pr')^(i<n)
900+
-- if e'_1*^n = $transpose_(exp, e_1^n*)
901+
-- if e'_2*^n = $transpose_(exp, e''_2^n*)
902+
-- (if e'_2 = e_2)*^n
903+
-- if (pr', s') = $refresh_prem(pr)

0 commit comments

Comments
 (0)