1structure intSyntax :> intSyntax =
2struct
3
4open HolKernel boolLib Parse integerTheory;
5
6val ERR = mk_HOL_ERR "intSyntax";
7
8val num_ty = numSyntax.num
9val int_ty = mk_thy_type{Tyop = "int", Thy="integer", Args = []}
10
11fun Const s = prim_mk_const{Name=s, Thy="integer"};
12
13val negate_tm = Const "int_neg"
14val plus_tm =  Const "int_add"
15val minus_tm = Const "int_sub"
16val mult_tm =  Const "int_mul"
17val exp_tm =   Const "int_exp"
18val div_tm =   Const "int_div"
19val mod_tm =   Const "int_mod"
20val quot_tm =  Const "int_quot"
21val rem_tm =   Const "int_rem"
22val less_tm =  Const "int_lt"
23val leq_tm =   Const "int_le"
24val greater_tm = Const "int_gt"
25val geq_tm =   Const "int_ge"
26val min_tm =   Const "int_min"
27val max_tm =   Const "int_max";
28val absval_tm =  Const "ABS"
29val divides_tm = Const "int_divides"
30val LEAST_INT_tm = Const "LEAST_INT"
31val int_injection = Const "int_of_num"
32val Num_tm = Const "Num"
33
34val int_eq_tm = inst [alpha |-> int_ty] boolSyntax.equality
35
36fun dest_binop t (srcf,msg) tm = let
37  val (farg1, arg2) = dest_comb tm
38  val (f, arg1) = dest_comb farg1
39in
40  if f !~ t then raise ERR srcf msg
41  else (arg1, arg2)
42end
43
44val dest_plus = dest_binop plus_tm ("dest_plus", "Term not a plus")
45val is_plus = can dest_plus
46fun mk_plus (arg1, arg2) = list_mk_comb(plus_tm, [arg1, arg2])
47
48fun list_mk_plus summands = let
49  fun recurse acc [] = acc
50    | recurse acc (x::xs) = recurse (mk_plus(acc, x)) xs
51in
52  recurse (hd summands) (tl summands)
53  handle List.Empty => raise ERR "list_mk_plus" "empty summand list"
54end
55
56fun strip_plus tm = let
57  fun recurse acc tm = let
58    val (l,r) = dest_plus tm
59  in
60    recurse (recurse acc r) l
61  end handle HOL_ERR _ => tm::acc
62in
63  recurse [] tm
64end
65
66val dest_minus = dest_binop minus_tm ("dest_minus", "Term not a minus")
67val is_minus = can dest_minus
68fun mk_minus (tm1, tm2) = list_mk_comb(minus_tm, [tm1, tm2])
69
70val dest_mult = dest_binop mult_tm ("dest_mult", "Term not a multiplication")
71val is_mult = can dest_mult
72fun mk_mult (tm1, tm2) = list_mk_comb(mult_tm, [tm1, tm2]);
73
74fun list_mk_mult multiplicands = let
75  fun recurse acc [] = acc
76    | recurse acc (x::xs) = recurse (mk_mult(acc, x)) xs
77in
78  recurse (hd multiplicands) (tl multiplicands)
79  handle List.Empty => raise ERR "list_mk_mult" "empty multiplicand list"
80end
81fun strip_mult tm = let
82  fun recurse acc tm = let
83    val (l,r) = dest_mult tm
84  in
85    recurse (recurse acc r) l
86  end handle HOL_ERR _ => tm::acc
87in
88  recurse [] tm
89end
90
91val dest_exp = dest_binop exp_tm ("dest_exp", "Term not an exp")
92val is_exp = can dest_exp
93fun mk_exp (arg1, arg2) = list_mk_comb(exp_tm, [arg1, arg2])
94
95val dest_div = dest_binop div_tm ("dest_div", "Term not a division")
96val is_div = can dest_div
97fun mk_div (t1, t2) = list_mk_comb(div_tm, [t1, t2])
98
99val dest_mod = dest_binop mod_tm ("dest_mod", "Term not a modulo")
100val is_mod = can dest_mod
101fun mk_mod (t1, t2) = list_mk_comb(mod_tm, [t1, t2])
102
103val dest_quot = dest_binop quot_tm ("dest_quot", "Term not a quotient")
104val is_quot = can dest_quot
105fun mk_quot (t1, t2) = list_mk_comb(quot_tm, [t1, t2])
106
107val dest_rem = dest_binop rem_tm ("dest_rem", "Term not a remainder")
108val is_rem = can dest_rem
109fun mk_rem (t1, t2) = list_mk_comb(rem_tm, [t1, t2])
110
111fun mk_absval tm = mk_comb(absval_tm, tm)
112fun dest_absval tm = let
113  val (f,x) = dest_comb tm
114      handle HOL_ERR _ => raise ERR "dest_absval" "term not an absolute value"
115in
116  if same_const f absval_tm then x
117  else raise ERR "dest_absval" "term not an absolute value"
118end
119val is_absval = can dest_absval
120
121fun mk_Num t = mk_comb(Num_tm, t)
122fun dest_Num t = let
123  val (f,x) = dest_comb t
124      handle HOL_ERR _ => raise ERR "dest_Num" "term not a Num coercion"
125in
126  if same_const f Num_tm then x
127  else raise ERR "dest_Num" "term not a Num coercion"
128end
129val is_Num = can dest_Num
130
131
132
133val dest_less = dest_binop less_tm ("dest_less", "Term not a less-than")
134val is_less = can dest_less
135fun mk_less (tm1, tm2) = list_mk_comb(less_tm, [tm1, tm2])
136
137val dest_leq = dest_binop leq_tm ("dest_leq", "Term not a less-than-or-equal")
138val is_leq = can dest_leq
139fun mk_leq (tm1, tm2) = list_mk_comb(leq_tm, [tm1, tm2])
140
141val dest_greater = dest_binop greater_tm ("dest_greater", "Term not a greater-than")
142val is_greater = can dest_greater
143fun mk_greater (tm1, tm2) = list_mk_comb(greater_tm, [tm1, tm2])
144
145val dest_geq = dest_binop geq_tm ("dest_geq",
146                                  "Term not a greater-than-or-equal")
147val is_geq = can dest_geq
148fun mk_geq (tm1, tm2) = list_mk_comb(geq_tm, [tm1, tm2])
149
150
151val dest_divides = dest_binop divides_tm ("dest_divides", "Term not a divides")
152val is_divides = can dest_divides
153fun mk_divides (tm1, tm2) = list_mk_comb(divides_tm, [tm1, tm2])
154
155val dest_min = dest_binop min_tm ("dest_min", "Term not a min")
156val is_min = can dest_min
157fun mk_min (tm1, tm2) = list_mk_comb(min_tm, [tm1, tm2])
158
159val dest_max = dest_binop max_tm ("dest_max", "Term not a max")
160val is_max = can dest_max
161fun mk_max (tm1, tm2) = list_mk_comb(max_tm, [tm1, tm2])
162
163fun dest_LEAST_INT t =
164  let
165    val (f, x) = dest_comb t
166    val _ = assert (same_const LEAST_INT_tm) f
167  in
168    x
169  end handle HOL_ERR _ =>
170    raise ERR "dest_LEAST_INT" "term not a LEAST_INT"
171
172val is_LEAST_INT = can dest_LEAST_INT
173fun mk_LEAST_INT t = mk_comb (LEAST_INT_tm, t)
174
175fun dest_injected tm = let
176  val (f,x) = dest_comb tm
177    handle HOL_ERR _ => raise ERR "dest_injected" "term not an injection"
178in
179  if f ~~ int_injection then x
180  else raise ERR "dest_injected" "term not an injection"
181end
182val is_injected = can dest_injected
183fun mk_injected tm = mk_comb(int_injection, tm)
184
185
186fun dest_negated tm = let
187  val (l,r) = dest_comb tm
188    handle HOL_ERR _ => raise ERR "dest_negated" "term not a negation"
189in
190  if l ~~ negate_tm then r
191  else raise ERR "dest_negated" "term not a negation"
192end
193val is_negated = can dest_negated
194fun mk_negated tm = mk_comb(negate_tm, tm)
195
196fun is_int_literal t =
197  (rator t ~~ int_injection andalso numSyntax.is_numeral (rand t)) orelse
198  (rator t ~~ negate_tm andalso is_int_literal (rand t))
199  handle HOL_ERR _ => false
200
201fun int_of_term tm = let
202  val _ =
203    is_int_literal tm orelse
204    raise ERR "int_of_term" "applied to non-literal"
205  val (l,r) = dest_comb tm
206in
207  if l ~~ negate_tm then Arbint.~(int_of_term r)
208  else Arbint.fromNat (numSyntax.dest_numeral r)
209end
210
211fun term_of_int i = let
212  open Arbint
213in
214  if i < zero then
215    mk_negated (term_of_int (~i))
216  else
217    mk_comb(int_injection, numSyntax.mk_numeral (toNat i))
218end
219
220val zero_tm = term_of_int Arbint.zero
221val one_tm  = term_of_int Arbint.one
222
223end
224