Home My Page Projects Code Snippets Project Openings SML/NJ
Summary Activity Forums Tracker Lists Tasks Docs Surveys News SCM Files

SCM Repository

[smlnj] Annotation of /sml/trunk/src/ml-nlffi-lib/internals/c-int.sml
ViewVC logotype

Annotation of /sml/trunk/src/ml-nlffi-lib/internals/c-int.sml

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1152 - (view) (download)

1 : blume 828 (*
2 :     * The implementation of the interface that encodes C's type system
3 :     * in ML. This implementation includes its "private" extensions.
4 :     *
5 :     * (C) 2001, Lucent Technologies, Bell Laboratories
6 :     *
7 : blume 975 * author: Matthias Blume (blume@research.bell-labs.com)
8 : blume 828 *)
9 :     local
10 :     (* We play some games here with first calling C_Int simply C and then
11 :     * renaming it because they result in saner printing behavior. *)
12 :     structure C :> C_INT = struct
13 :    
14 : blume 1015 exception OutOfMemory = CMemory.OutOfMemory
15 :    
16 : blume 828 fun bug m = raise Fail ("impossible: " ^ m)
17 :    
18 :     type addr = CMemory.addr
19 :    
20 :     local
21 : blume 837 datatype objt =
22 : blume 828 BASE of word
23 : blume 837 | PTR of objt
24 :     | FPTR of Unsafe.Object.object (* == addr -> 'f *)
25 : blume 1096 | ARR of { typ: objt, n: word, esz: word, asz: word }
26 : blume 828
27 :     (* Bitfield: b bits wide, l bits from left corner, r bits from right.
28 :     * The word itself is CMemory.int_bits wide and located at address a.
29 :     *
30 :     * MSB LSB
31 :     * V |<---b--->| V
32 :     * |<---l---> ......... <---r--->|
33 :     * |<----------wordsize--------->|
34 :     *
35 :     * 0.......0 1.......1 0.......0 = m
36 :     * 1.......1 0.......0 1.......1 = im
37 :     *
38 :     * l + r = lr *)
39 : blume 1036 type cword = MLRep.Unsigned.word
40 : blume 828 type bf = { a: addr, l: word, r: word, lr: word, m: cword, im: cword }
41 :    
42 : blume 837 fun pair_type_addr (t: objt) (a: addr) = (a, t)
43 :     fun strip_type (a: addr, _: objt) = a
44 :     fun p_strip_type (a: addr, _: objt) = a
45 : blume 828 fun strip_fun (a: addr, _: 'f) = a
46 : blume 837 fun addr_type_id (x: addr * objt) = x
47 : blume 828 fun addr_id (x: addr) = x
48 :    
49 :     infix -- ++
50 :     val op -- = CMemory.--
51 :     val op ++ = CMemory.++
52 :    
53 :     infix << >> ~>> && || ^^
54 : blume 1036 val op << = MLRep.Unsigned.<<
55 :     val op >> = MLRep.Unsigned.>>
56 :     val op ~>> = MLRep.Unsigned.~>>
57 :     val op && = MLRep.Unsigned.andb
58 :     val op || = MLRep.Unsigned.orb
59 :     val op ^^ = MLRep.Unsigned.xorb
60 :     val ~~ = MLRep.Unsigned.notb
61 : blume 828 in
62 :    
63 : blume 975 type ('t, 'c) obj = addr * objt (* RTTI for stored value *)
64 : blume 837 type ('t, 'c) obj' = addr
65 : blume 828
66 :     type ro = unit
67 :     type rw = unit
68 :    
69 : blume 1078 type 'o ptr = addr * objt (* RTTI for target value *)
70 :     type 'o ptr' = addr
71 : blume 828
72 : blume 836 type ('t, 'n) arr = unit
73 : blume 828
74 :     type 'f fptr = addr * 'f
75 :     type 'f fptr' = addr (* does not carry function around *)
76 :    
77 : blume 1078 type void = unit
78 :     type voidptr = void ptr'
79 :    
80 : blume 828 type 'tag su = unit
81 :    
82 : blume 1096 type 'tag enum = MLRep.Signed.int
83 :    
84 : blume 1036 type schar = MLRep.Signed.int
85 :     type uchar = MLRep.Unsigned.word
86 :     type sint = MLRep.Signed.int
87 :     type uint = MLRep.Unsigned.word
88 :     type sshort = MLRep.Signed.int
89 :     type ushort = MLRep.Unsigned.word
90 :     type slong = MLRep.Signed.int
91 :     type ulong = MLRep.Unsigned.word
92 :     type float = MLRep.Real.real
93 :     type double = MLRep.Real.real
94 : blume 828
95 : blume 837 type 'c schar_obj = (schar, 'c) obj
96 :     type 'c uchar_obj = (uchar, 'c) obj
97 :     type 'c sint_obj = (sint, 'c) obj
98 :     type 'c uint_obj = (uint, 'c) obj
99 :     type 'c sshort_obj = (sshort, 'c) obj
100 :     type 'c ushort_obj = (ushort, 'c) obj
101 :     type 'c slong_obj = (slong, 'c) obj
102 :     type 'c ulong_obj = (ulong, 'c) obj
103 :     type 'c float_obj = (float, 'c) obj
104 :     type 'c double_obj = (double, 'c) obj
105 :     type 'c voidptr_obj = (voidptr, 'c) obj
106 : blume 1096 type ('e, 'c) enum_obj = ('e enum, 'c) obj
107 : blume 837 type ('f, 'c) fptr_obj = ('f fptr, 'c) obj
108 :     type ('s, 'c) su_obj = ('s su, 'c) obj
109 : blume 828
110 : blume 837 type 'c schar_obj' = (schar, 'c) obj'
111 :     type 'c uchar_obj' = (uchar, 'c) obj'
112 :     type 'c sint_obj' = (sint, 'c) obj'
113 :     type 'c uint_obj' = (uint, 'c) obj'
114 :     type 'c sshort_obj' = (sshort, 'c) obj'
115 :     type 'c ushort_obj' = (ushort, 'c) obj'
116 :     type 'c slong_obj' = (slong, 'c) obj'
117 :     type 'c ulong_obj' = (ulong, 'c) obj'
118 :     type 'c float_obj' = (float, 'c) obj'
119 :     type 'c double_obj' = (double, 'c) obj'
120 :     type 'c voidptr_obj' = (voidptr, 'c) obj'
121 : blume 1096 type ('e, 'c) enum_obj' = ('e enum, 'c) obj'
122 : blume 837 type ('f, 'c) fptr_obj' = ('f fptr, 'c) obj'
123 :     type ('s, 'c) su_obj' = ('s su, 'c) obj'
124 : blume 828
125 :     type 'c ubf = bf
126 :     type 'c sbf = bf
127 :    
128 : blume 1152 structure W = struct
129 :     type ('from, 'to) witness = unit
130 :    
131 :     val trivial = ()
132 :     fun pointer () = ()
133 :     fun object () = ()
134 :     fun arr () = ()
135 :     fun ro () = ()
136 :     fun rw () = ()
137 :     end
138 :    
139 :     fun convert w x = x
140 :     fun convert' w x = x
141 :    
142 : blume 828 (*
143 :     * A family of types and corresponding values representing natural numbers.
144 :     * (An encoding in SML without using dependent types.)
145 :     * This is the full implementation including an unsafe extension
146 :     * ("fromInt"). *)
147 :    
148 :     structure Dim = struct
149 :    
150 :     type ('a, 'z) dim0 = int
151 :     fun toInt d = d
152 :     fun fromInt d = d
153 :    
154 :     type dec = unit
155 :     type 'a dg0 = unit
156 :     type 'a dg1 = unit
157 :     type 'a dg2 = unit
158 :     type 'a dg3 = unit
159 :     type 'a dg4 = unit
160 :     type 'a dg5 = unit
161 :     type 'a dg6 = unit
162 :     type 'a dg7 = unit
163 :     type 'a dg8 = unit
164 :     type 'a dg9 = unit
165 :    
166 :     type zero = unit
167 :     type nonzero = unit
168 :    
169 :     type 'a dim = ('a, nonzero) dim0
170 :    
171 :     local
172 :     fun dg n d = 10 * d + n
173 :     in
174 :     val dec' = 0
175 : blume 840 val (dg0', dg1', dg2', dg3', dg4', dg5', dg6', dg7', dg8', dg9') =
176 :     (dg 0, dg 1, dg 2, dg 3, dg 4, dg 5, dg 6, dg 7, dg 8, dg 9)
177 : blume 828
178 :     fun dec k = k dec'
179 :     fun dg0 d k = k (dg0' d)
180 :     fun dg1 d k = k (dg1' d)
181 :     fun dg2 d k = k (dg2' d)
182 :     fun dg3 d k = k (dg3' d)
183 :     fun dg4 d k = k (dg4' d)
184 :     fun dg5 d k = k (dg5' d)
185 :     fun dg6 d k = k (dg6' d)
186 :     fun dg7 d k = k (dg7' d)
187 :     fun dg8 d k = k (dg8' d)
188 :     fun dg9 d k = k (dg9' d)
189 :     fun dim d = d
190 :     end
191 :     end
192 :    
193 :     structure S = struct
194 :    
195 :     type 't size = word
196 :    
197 :     fun toWord (s: 't size) = s
198 :    
199 :     val schar = CMemory.char_size
200 :     val uchar = CMemory.char_size
201 :     val sint = CMemory.int_size
202 :     val uint = CMemory.int_size
203 :     val sshort = CMemory.short_size
204 :     val ushort = CMemory.short_size
205 :     val slong = CMemory.long_size
206 :     val ulong = CMemory.long_size
207 :     val float = CMemory.float_size
208 :     val double = CMemory.double_size
209 :    
210 :     val voidptr = CMemory.addr_size
211 :     val ptr = CMemory.addr_size
212 :     val fptr = CMemory.addr_size
213 : blume 1096 val enum = CMemory.int_size
214 : blume 828 end
215 :    
216 :     structure T = struct
217 :    
218 : blume 837 type 't typ = objt
219 : blume 828
220 : blume 837 fun typeof (_: addr, t: objt) = t
221 : blume 828
222 :     fun sizeof (BASE b) = b
223 :     | sizeof (PTR _) = S.ptr
224 :     | sizeof (FPTR _) = S.fptr
225 :     | sizeof (ARR a) = #asz a
226 :    
227 :     (* use private (and unsafe) extension to Dim module here... *)
228 :     fun dim (ARR { n, ... }) = Dim.fromInt (Word.toInt n)
229 :     | dim _ = bug "T.dim (non-array type)"
230 :    
231 :     fun pointer t = PTR t
232 :     fun target (PTR t) = t
233 :     | target _ = bug "T.target (non-pointer type)"
234 :     fun arr (t, d) = let
235 :     val n = Word.fromInt (Dim.toInt d)
236 :     val s = sizeof t
237 :     in
238 : blume 1096 ARR { typ = t, n = n, esz = s, asz = n * s }
239 : blume 828 end
240 :     fun elem (ARR a) = #typ a
241 :     | elem _ = bug "T.elem (non-array type)"
242 : blume 837 fun ro (t: objt) = t
243 : blume 828
244 :     val schar = BASE S.schar
245 :     val uchar = BASE S.uchar
246 :     val sint = BASE S.sint
247 :     val uint = BASE S.uint
248 :     val sshort = BASE S.sshort
249 :     val ushort = BASE S.ushort
250 :     val slong = BASE S.slong
251 :     val ulong = BASE S.ulong
252 :     val float = BASE S.float
253 :     val double = BASE S.double
254 :    
255 :     val voidptr = BASE S.voidptr
256 : blume 1096
257 :     val enum = BASE S.sint
258 : blume 828 end
259 :    
260 :     structure Light = struct
261 :     val obj = p_strip_type
262 :     val ptr = p_strip_type
263 :     val fptr = strip_fun
264 :     end
265 :    
266 :     structure Heavy = struct
267 :     val obj = pair_type_addr
268 : blume 1078 fun ptr (PTR t) p = (p, t)
269 :     | ptr _ _ = bug "Heavy.ptr (non-object-pointer-type)"
270 : blume 837 fun fptr (FPTR mkf) p = (p, Unsafe.cast mkf p)
271 : blume 828 | fptr _ _ = bug "Heavy.fptr (non-function-pointer-type)"
272 :     end
273 :    
274 :     fun sizeof (_: addr, t) = T.sizeof t
275 :    
276 :     structure Cvt = struct
277 :     (* going between abstract and concrete; these are all identities *)
278 :     fun c_schar (c: schar) = c
279 :     fun c_uchar (c: uchar) = c
280 :     fun c_sint (i: sint) = i
281 :     fun c_uint (i: uint) = i
282 :     fun c_sshort (s: sshort) = s
283 :     fun c_ushort (s: ushort) = s
284 :     fun c_slong (l: slong) = l
285 :     fun c_ulong (l: ulong) = l
286 :     fun c_float (f: float) = f
287 :     fun c_double (d: double) = d
288 : blume 1096 fun i2c_enum (e: 'e enum) = e
289 : blume 828
290 :     val ml_schar = c_schar
291 :     val ml_uchar = c_uchar
292 :     val ml_sint = c_sint
293 :     val ml_uint = c_uint
294 :     val ml_sshort = c_sshort
295 :     val ml_ushort = c_ushort
296 :     val ml_slong = c_slong
297 :     val ml_ulong = c_ulong
298 :     val ml_float = c_float
299 :     val ml_double = c_double
300 : blume 1096 val c2i_enum = i2c_enum
301 : blume 828 end
302 :    
303 :     structure Get = struct
304 :     val uchar' = CMemory.load_uchar
305 :     val schar' = CMemory.load_schar
306 :     val uint' = CMemory.load_uint
307 :     val sint' = CMemory.load_sint
308 :     val ushort' = CMemory.load_ushort
309 :     val sshort' = CMemory.load_sshort
310 :     val ulong' = CMemory.load_ulong
311 :     val slong' = CMemory.load_slong
312 :     val float' = CMemory.load_float
313 :     val double' = CMemory.load_double
314 : blume 1096 val enum' = CMemory.load_sint
315 : blume 828
316 :     val ptr' = CMemory.load_addr
317 :     val fptr' = CMemory.load_addr
318 :     val voidptr' = CMemory.load_addr
319 :    
320 :     val uchar = uchar' o strip_type
321 :     val schar = schar' o strip_type
322 :     val uint = uint' o strip_type
323 :     val sint = sint' o strip_type
324 :     val ushort = ushort' o strip_type
325 :     val sshort = sshort' o strip_type
326 :     val ulong = ulong' o strip_type
327 :     val slong = slong' o strip_type
328 :     val float = float' o strip_type
329 :     val double = double' o strip_type
330 :     val voidptr = voidptr' o strip_type
331 : blume 1096 val enum = enum' o strip_type
332 : blume 828
333 :     fun ptr (a, PTR t) = (CMemory.load_addr a, t)
334 :     | ptr _ = bug "Get.ptr (non-pointer)"
335 :     fun fptr (a, FPTR mkf) =
336 : blume 837 let val fa = CMemory.load_addr a in (fa, Unsafe.cast mkf fa) end
337 : blume 828 | fptr _ = bug "Get.fptr (non-function-pointer)"
338 :    
339 :     local
340 : blume 1036 val u2s = MLRep.Signed.fromLarge o MLRep.Unsigned.toLargeIntX
341 : blume 828 in
342 :     fun ubf ({ a, l, r, lr, m, im } : bf) =
343 :     (CMemory.load_uint a << l) >> lr
344 :     fun sbf ({ a, l, r, lr, m, im } : bf) =
345 :     u2s ((CMemory.load_uint a << l) ~>> lr)
346 :     end
347 :     end
348 :    
349 :     structure Set = struct
350 :     val uchar' = CMemory.store_uchar
351 :     val schar' = CMemory.store_schar
352 :     val uint' = CMemory.store_uint
353 :     val sint' = CMemory.store_sint
354 :     val ushort' = CMemory.store_ushort
355 :     val sshort' = CMemory.store_sshort
356 :     val ulong' = CMemory.store_ulong
357 :     val slong' = CMemory.store_slong
358 :     val float' = CMemory.store_float
359 :     val double' = CMemory.store_double
360 : blume 1096 val enum' = CMemory.store_sint
361 : blume 828
362 :     val ptr' = CMemory.store_addr
363 :     val fptr' = CMemory.store_addr
364 :     val voidptr' = CMemory.store_addr
365 :     val ptr_voidptr' = CMemory.store_addr
366 :    
367 :     local
368 :     infix $
369 :     fun (f $ g) (x, y) = f (g x, y)
370 :     in
371 :     val uchar = uchar' $ strip_type
372 :     val schar = schar' $ strip_type
373 :     val uint = uint' $ strip_type
374 :     val sint = sint' $ strip_type
375 :     val ushort = ushort' $ strip_type
376 :     val sshort = sshort' $ strip_type
377 :     val ulong = ulong' $ strip_type
378 :     val slong = slong' $ strip_type
379 :     val float = float' $ strip_type
380 :     val double = double' $ strip_type
381 :     val voidptr = voidptr' $ strip_type
382 : blume 1096 val enum = enum' $ strip_type
383 : blume 828
384 :     fun ptr_voidptr (x, p) = ptr_voidptr' (p_strip_type x, p)
385 :    
386 :     fun ptr (x, p) = ptr' (p_strip_type x, p_strip_type p)
387 :     fun fptr (x, f) = fptr' (p_strip_type x, strip_fun f)
388 :     end
389 :    
390 :     fun ubf ({ a, l, r, lr, m, im }, x) =
391 :     CMemory.store_uint (a, (CMemory.load_uint a && im) ||
392 :     ((x << r) && m))
393 :    
394 :     local
395 : blume 1036 val s2u = MLRep.Unsigned.fromLargeInt o MLRep.Signed.toLarge
396 : blume 828 in
397 :     fun sbf (f, x) = ubf (f, s2u x)
398 :     end
399 :     end
400 :    
401 :     fun copy' bytes { from, to } =
402 :     CMemory.bcopy { from = from, to = to, bytes = bytes }
403 : blume 837 fun copy { from = (from, t), to = (to, _: objt) } =
404 : blume 828 copy' (T.sizeof t) { from = from, to = to }
405 :    
406 : blume 1021 val ro = addr_type_id
407 :     val rw = addr_type_id
408 :    
409 :     val ro' = addr_id
410 :     val rw' = addr_id
411 :    
412 : blume 828 structure Ptr = struct
413 :     val |&| = addr_type_id
414 :     val |*| = addr_type_id
415 :    
416 :     val |&! = addr_id
417 :     val |*! = addr_id
418 :    
419 :     fun compare (p, p') = CMemory.compare (p_strip_type p, p_strip_type p')
420 :    
421 :     val compare' = CMemory.compare
422 :    
423 :     val inject' = addr_id
424 : blume 1096 val cast' = addr_id
425 : blume 828
426 :     val inject = p_strip_type
427 : blume 837 fun cast (PTR t) (p : voidptr) = (p, t)
428 :     | cast _ _ = bug "Ptr.cast (non-pointer-type)"
429 : blume 828
430 :     val vNull = CMemory.null
431 : blume 837 fun null t = cast t vNull
432 : blume 828 val null' = CMemory.null
433 :    
434 : blume 1031 val fnull' = CMemory.null
435 :     fun fnull t = Heavy.fptr t fnull'
436 :    
437 : blume 828 val vIsNull = CMemory.isNull
438 :     fun isNull p = vIsNull (inject p)
439 :     val isNull' = CMemory.isNull
440 :    
441 : blume 1031 fun isFNull (p, _) = CMemory.isNull p
442 :     val isFNull' = CMemory.isNull
443 :    
444 : blume 828 fun |+! s (p, i) = p ++ (Word.toInt s * i)
445 :     fun |-! s (p, p') = (p -- p') div Word.toInt s
446 :    
447 :     fun |+| ((p, t), i) = (|+! (T.sizeof t) (p, i), t)
448 : blume 837 fun |-| ((p, t), (p', _: objt)) = |-! (T.sizeof t) (p, p')
449 : blume 828
450 :     fun sub (p, i) = |*| (|+| (p, i))
451 :    
452 :     fun sub' t (p, i) = |*! (|+! t (p, i))
453 :    
454 : blume 1021 val ro = addr_type_id
455 :     val rw = addr_type_id
456 : blume 828
457 : blume 1021 val ro' = addr_id
458 :     val rw' = addr_id
459 : blume 1152
460 :     fun convert w x = x
461 :     fun convert' w x = x
462 : blume 1021 end
463 : blume 828
464 :     structure Arr = struct
465 :     local
466 : blume 1096 fun asub (a, i, n, esz) =
467 : blume 828 (* take advantage of wrap-around to avoid the >= 0 test... *)
468 : blume 1096 if Word.fromInt i < n then a ++ (Word.toIntX esz * i)
469 : blume 828 else raise General.Subscript
470 :     in
471 : blume 1096 fun sub ((a, ARR { typ, n, esz, ... }), i) = (asub (a, i, n, esz), typ)
472 :     | sub _ = bug "Arr.sub (non-array)"
473 :     fun sub' (s, d) (a, i) = asub (a, i, Word.fromInt (Dim.toInt d), s)
474 : blume 828 end
475 :    
476 :     fun decay (a, ARR { typ, ... }) = (a, typ)
477 :     | decay _ = bug "Arr.decay (non-array)"
478 :    
479 :     val decay' = addr_id
480 :    
481 :     fun reconstruct ((a: addr, t), d) = (a, T.arr (t, d))
482 :    
483 :     fun reconstruct' (a: addr, d: 'n Dim.dim) = a
484 :    
485 :     fun dim (_: addr, t) = T.dim t
486 :     end
487 :    
488 : blume 837 fun new' s = CMemory.alloc s
489 : blume 1015 fun new t = (new' (T.sizeof t), t)
490 : blume 828
491 :     val discard' = CMemory.free
492 :     fun discard x = discard' (p_strip_type x)
493 :    
494 : blume 837 fun alloc' s i = CMemory.alloc (s * i)
495 : blume 1015 fun alloc t i = (alloc' (T.sizeof t) i, t)
496 : blume 828
497 :     val free' = CMemory.free
498 :     fun free x = free' (p_strip_type x)
499 :    
500 :     fun call ((_: addr, f), x) = f x
501 :    
502 : blume 837 fun call' (FPTR mkf) (a, x) = Unsafe.cast mkf a x
503 : blume 828 | call' _ _ = bug "call' (non-function-pointer-type)"
504 :    
505 : blume 1015 structure U = struct
506 :     fun fcast (f : 'a fptr') : 'b fptr' = f
507 : blume 1078 fun p2i (a : 'o ptr') : ulong = CMemory.p2i a
508 :     fun i2p (a : ulong) : 'o ptr' = CMemory.i2p a
509 : blume 1015 end
510 :    
511 : blume 828 (* ------------- internal stuff ------------- *)
512 :    
513 : blume 1096 fun mk_obj' (a : addr) = a
514 : blume 828 fun mk_voidptr (a : addr) = a
515 : blume 1011 fun mk_fptr (mkf, a) = (a, mkf a)
516 : blume 828
517 :     local
518 : blume 1011 fun mk_field (t: objt, i, (a, _: objt)) = (a ++ i, t)
519 : blume 828 in
520 :     val mk_rw_field = mk_field
521 :     val mk_ro_field = mk_field
522 : blume 1011 fun mk_field' (i, a) = a ++ i
523 : blume 828 end
524 :    
525 :     local
526 :     fun mk_bf' (offset, bits, shift) a = let
527 :     val a = a ++ offset
528 :     val l = shift
529 :     val lr = CMemory.int_bits - bits
530 :     val r = lr - l
531 :     val m = (~~0w0 << lr) >> l
532 :     val im = ~~ m
533 :     in
534 :     { a = a, l = l, r = r, lr = lr, m = m, im = im } : bf
535 :     end
536 : blume 837 fun mk_bf acc (a, _: objt) = mk_bf' acc a
537 : blume 828 in
538 :     val mk_rw_ubf = mk_bf
539 :     val mk_ro_ubf = mk_bf
540 :     val mk_rw_ubf' = mk_bf'
541 :     val mk_ro_ubf' = mk_bf'
542 :    
543 :     val mk_rw_sbf = mk_bf
544 :     val mk_ro_sbf = mk_bf
545 :     val mk_rw_sbf' = mk_bf'
546 :     val mk_ro_sbf' = mk_bf'
547 :     end
548 :    
549 :     fun mk_su_size sz = sz
550 :     fun mk_su_typ sz = BASE sz
551 : blume 837 fun mk_fptr_typ (mkf: addr -> 'a -> 'b) = FPTR (Unsafe.cast mkf)
552 : blume 828
553 :     val reveal = addr_id
554 :     val freveal = addr_id
555 :    
556 :     val vcast = addr_id
557 :     val pcast = addr_id
558 :     val fcast = addr_id
559 :    
560 :     fun unsafe_sub esz (a, i) = a ++ esz * i
561 :    
562 :     end (* local *)
563 :     end
564 :     in
565 :     structure C_Int = C
566 :     end

root@smlnj-gforge.cs.uchicago.edu
ViewVC Help
Powered by ViewVC 1.0.0