|
|
1.1 root 1: (* Copyright 1989 by AT&T Bell Laboratories *)
2: (* notes:
3: OFFSET should not be generated by this module
4: RECORD fields should contain only empty paths (pure variables)
5: *)
6:
7: (* xgrep '[^a-z]n[^a-z]' cps/convert.sml *)
8: structure Convert =
9: struct
10:
11: open CPS Access
12: fun sublist test =
13: let fun subl(a::r) = if test a then a::(subl r) else subl r
14: | subl x = x
15: in subl
16: end
17:
18: local open Lambda Basics
19: in
20: fun translatepath [v] = VAR v
21: | translatepath (x::p) = SELECT(x,translatepath p)
22: | translatepath nil = ErrorMsg.impossible "convert.translatepath nil"
23:
24: fun isboxedRep(CONSTANT _) = false
25: | isboxedRep(TRANSU) = false
26: | isboxedRep(_) = true
27:
28: fun isboxed (DATAcon(DATACON{rep,...})) = isboxedRep(rep)
29: | isboxed (REALcon _) = true
30: | isboxed (STRINGcon s) = (size s <> 1)
31: | isboxed _ = false
32: end
33:
34: fun mk f = f (mkLvar())
35:
36: val sortcases = Sort.sort (fn ((i:int,_),(j,_)) => i>j)
37:
38: val calling =
39: fn P.boxed => (1,0,2)
40: | P.< => (2,0,2)
41: | P.<= => (2,0,2)
42: | P.> => (2,0,2)
43: | P.>= => (2,0,2)
44: | P.ieql => (2,0,2)
45: | P.ineq => (2,0,2)
46: | P.feql => (2,0,2)
47: | P.fge => (2,0,2)
48: | P.fgt => (2,0,2)
49: | P.fle => (2,0,2)
50: | P.flt => (2,0,2)
51: | P.fneq => (2,0,2)
52: | P.gethdlr => (0,1,1)
53: | P.* => (2,1,1)
54: | P.+ => (2,1,1)
55: | P.- => (2,1,1)
56: | P.div => (2,1,1)
57: | P.orb => (2,1,1)
58: | P.andb => (2,1,1)
59: | P.xorb => (2,1,1)
60: | P.rshift => (2,1,1)
61: | P.lshift => (2,1,1)
62: | P.fadd => (2,1,1)
63: | P.fdiv => (2,1,1)
64: | P.fmul => (2,1,1)
65: | P.fsub => (2,1,1)
66: | P.subscript => (2,1,1)
67: | P.ordof => (2,1,1)
68: | P.! => (1,1,1)
69: | P.alength => (1,1,1)
70: | P.fneg => (1,1,1)
71: | P.makeref => (1,1,1)
72: | P.delay => (2,1,1)
73: | P.slength => (1,1,1)
74: | P.~ => (1,1,1)
75: | P.notb => (1,1,1)
76: | P.sethdlr => (1,0,1)
77: | P.:= => (2,0,1)
78: | P.unboxedassign => (2,0,1)
79: | P.store => (3,0,1)
80: | P.unboxedupdate => (3,0,1)
81: | P.update => (3,0,1)
82: | _ => ErrorMsg.impossible "calling with bad primop"
83:
84: fun nthcdr(l, 0) = l
85: | nthcdr(a::r, n) = nthcdr(r, n-1)
86: | nthcdr _ = ErrorMsg.impossible "nthcdr in convert"
87:
88: fun count test =
89: let fun subl acc (a::r) = subl(if test a then 1+acc else acc) r
90: | subl acc nil = acc
91: in subl 0
92: end
93:
94: fun convert lexp =
95: let
96: local open Intmap
97: val m : const intmap = new(32, Ctable)
98: val enter = add m
99: in fun bindconst(c,cont) = mk(fn v => (enter(v,c); cont v))
100: val ctable = m
101: end
102:
103: local open Intmap
104: exception Rename
105: val m : lvar intmap = new(32, Rename)
106: val rename = map m
107: in fun ren v = rename v handle Rename => v
108: val newname = add m
109: end
110:
111: fun switch1(e : lvar, cases : (int*cexp) list, d : lvar, (lo,hi)) =
112: let val delta = 2
113: fun collapse (l as (li,ui,ni,xi)::(lj,uj,nj,xj)::r ) =
114: if ((ni+nj) * delta > ui-lj)
115: then collapse((lj,ui,ni+nj,xj)::r)
116: else l
117: | collapse l = l
118: fun f (z, x as (i,_)::r) = f(collapse((i,i,1,x)::z), r)
119: | f (z, nil) = z
120: fun tackon (stuff as (l,u,n,x)::r) =
121: if n*delta > u-l andalso n>4 andalso hi>u
122: then tackon((l,u+1,n+1,x@[(u+1,APP(d,nil))])::r)
123: else stuff
124: fun separate((z as (l,u,n,x))::r) =
125: if n<4 andalso n>1
126: then let val ix as (i,_) = nth(x, (n-1))
127: in (i,i,1,[ix])::separate((l,l,n-1,x)::r)
128: end
129: else z :: separate r
130: | separate nil = nil
131: val chunks = rev (separate (tackon (f (nil,cases))))
132: fun g(1,(l,h,1,(i,b)::_)::_,(lo,hi)) =
133: if lo=i andalso hi=i then b
134: else bindconst(INTconst i, fn i' =>
135: PRIMOP(P.ineq,[e, i'], nil, [APP(d,nil), b]))
136: | g(1,(l,h,n,x)::_,(lo,hi)) =
137: let fun f(0,_,_) = nil
138: | f(n,i,l as (j,b)::r) =
139: if i+lo = j then b::f(n-1,i+1,r)
140: else (APP(d,nil))::f(n,i+1,l)
141: val list = f(n,0,x)
142: val body = if lo=0 then SWITCH(e,list)
143: else bindconst(INTconst lo, fn lo' =>
144: mk(fn e' =>
145: PRIMOP(P.-,[e, lo'], [e'],
146: [SWITCH(e', list)])))
147: val a = if (lo<l)
148: then bindconst(INTconst l, fn l' =>
149: PRIMOP(P.<,[e, l'], nil, [APP(d,nil), body]))
150: else body
151: val b = if (hi > h)
152: then bindconst(INTconst h, fn h' =>
153: PRIMOP(P.>,[e, h'], nil, [APP(d,nil), a]))
154: else a
155: in b
156: end
157: | g(n,cases,(lo,hi)) =
158: let val n2 = n div 2
159: val c2 as (l,_,_,_)::r = nthcdr(cases, n2)
160: in bindconst(INTconst l, fn l' =>
161: PRIMOP(P.<,[e,l'],nil, [g(n2,cases,(lo,l-1)),
162: g(n-n2,c2,(l,hi))]))
163: end
164: in g (length chunks, chunks, (lo, hi))
165: end
166:
167: fun switch(e, l, d, inrange) =
168: let val len = List.length l
169: val d' = case d of SOME d' => d' | NONE => mkLvar()
170: fun ifelse nil = APP(d',nil)
171: | ifelse ((i,b)::r) =
172: bindconst(INTconst i, fn v =>
173: PRIMOP(P.ineq,[v, e], nil, [ifelse r, b]))
174: fun ifelseN [(i,b)] = b
175: | ifelseN ((i,b)::r) =
176: bindconst(INTconst i, fn v =>
177: PRIMOP(P.ineq,[v, e], nil, [ifelseN r, b]))
178: | ifelseN _ = ErrorMsg.impossible "convert.224"
179: val l = sortcases l
180: in case (len<4, inrange)
181: of (true, NONE) => ifelse l
182: | (true, SOME n) => if n+1=len then ifelseN l else ifelse l
183: | (false, NONE) =>
184: let fun last [x] = x | last (_::r) = last r
185: val (hi,_) = last l and (low,_)::r = l
186: in bindconst(INTconst low, fn low' =>
187: bindconst(INTconst hi, fn hi' =>
188: PRIMOP(P.>,[low', e], nil, [APP(d',[]),
189: PRIMOP(P.<,[hi', e], nil, [APP(d',[]),
190: switch1(e, l, d', (low,hi))])])))
191: end
192: | (false, SOME n) => switch1(e, l, d', (0,n))
193: end
194:
195: val zero = bindconst(INTconst 0, fn x => x)
196: val one = bindconst(INTconst 1, fn x => x)
197: val neg1 = bindconst(INTconst ~1, fn x => x)
198: val unevaled = bindconst(INTconst (System.Tags.tag_suspension div 2), fn x => x)
199: val evaled = bindconst(INTconst((System.Tags.tag_suspension
200: +System.Tags.power_tags)div 2), fn x => x)
201:
202: fun convlist (el,c) =
203: let fun f(le::r, vl) = conv(le, fn v => f(r,v::vl))
204: | f(nil, vl) = c (rev vl)
205: in f (el,nil)
206: end
207:
208: and getargs(1,a,g) = conv(a, fn z => g[z])
209: | getargs(n,Lambda.RECORD l,g) = convlist(l,g)
210: | getargs(n, a, g) = conv(a, fn v =>
211: let fun f (j,wl) = if j=n
212: then g(rev wl)
213: else mk(fn w => SELECT(j,v,w,f(j+1,w::wl)))
214: in f(0,nil)
215: end)
216:
217: and conv (le, c) =
218: case le of
219: Lambda.APP(Lambda.PRIM P.callcc, f) =>
220: let val k = mkLvar() and k' = mkLvar() and k'' = mkLvar()
221: and x = mkLvar() and y = mkLvar() and h = mkLvar()
222: in FIX([(k,[x],c x)],
223: PRIMOP(P.gethdlr,[],[h],
224: [FIX([(k',[y,k''],PRIMOP(P.sethdlr,[h],[],[APP(k,[y])]))],
225: conv(f, fn vf => APP(vf,[k',k])))]))
226: end
227: | Lambda.APP(Lambda.PRIM P.throw, k) => conv(k,c)
228: | Lambda.APP(Lambda.PRIM P.cast, k) => conv(k,c)
229: | Lambda.APP(Lambda.PRIM P.force, k) =>
230: let val c0=mkLvar() and c0v=mkLvar() and w=mkLvar() and x=mkLvar()
231: and y=mkLvar() and c1=mkLvar() and c1v=mkLvar()
232: in conv(k, fn v =>
233: FIX([(c0,[c0v],c c0v)],
234: PRIMOP(P.boxed,[v],[],[PRIMOP(P.subscript,[v,neg1],[w],[
235: PRIMOP(P.ieql,[w,evaled],[],[PRIMOP(P.!,[v],[x],[APP(c0,[x])]),
236: PRIMOP(P.ineq,[w,unevaled],[],[APP(c0,[v]),
237: FIX([(c1,[c1v],
238: PRIMOP(P.:=,[v,c1v],[],[
239: PRIMOP(P.update,[v,neg1,evaled],[],[
240: APP(c0,[c1v])])]))],
241: PRIMOP(P.!,[v],[y],[APP(y,[zero,c1])]))])])]),
242: APP(c0,[v])])))
243: end
244: | Lambda.APP(Lambda.PRIM i, a) =>
245: (case calling i of
246: (n,1,1) => getargs(n,a,fn vl => mk(fn w => PRIMOP(i,vl,[w],[c w])))
247: | (n,0,1) => getargs(n,a,fn vl => PRIMOP(i,vl,[],[c zero]))
248: | (n,0,2) => getargs(n,a,fn vl =>
249: let val cv = mkLvar() and v = mkLvar()
250: in FIX([(cv,[v],c v)],PRIMOP(i,vl,[],[APP(cv,[one]),APP(cv,[zero])]))
251: end))
252: | Lambda.PRIM i => mk(fn v => conv(Lambda.FN(v,Lambda.APP(le,Lambda.VAR v)),c))
253: | Lambda.VAR v => c (ren v)
254: | Lambda.APP(Lambda.FN(v,e),a) =>
255: conv(a, fn w => (newname(v,w);Access.sameName(v,w); conv(e, c)))
256: | Lambda.FN (v,e) => let val f = mkLvar() and w = mkLvar()
257: in FIX([(f,[v,w],conv(e, fn z => APP(w,[z])))], c f)
258: end
259: | Lambda.APP (f,a) =>
260: let val fc = mkLvar() and x = mkLvar()
261: in FIX([(fc,[x],c x)], conv(f,fn vf => conv(a,fn va => APP(vf,[va,fc]))))
262: end
263: | Lambda.FIX (fl, el, body) =>
264: let fun g(f::fl, Lambda.FN(v,b)::el) =
265: mk(fn w => (f,[v,w], conv(b, fn z => APP(w,[z])))) :: g(fl,el)
266: | g(nil,nil) = nil
267: in FIX(g(fl,el), conv(body,c))
268: end
269: | Lambda.INT i =>
270: ((i+i; bindconst(INTconst i, c))
271: handle Overflow =>
272: let open Lambda
273: in conv(APP(PRIM P.+, RECORD[INT(i div 2), INT(i - i div 2)]),c)
274: end)
275: | Lambda.REAL i => bindconst(REALconst i, c)
276: | Lambda.STRING i => (case size i
277: of 1 => bindconst(INTconst(ord i),c)
278: | _ => bindconst(STRINGconst i, c))
279: | Lambda.RECORD nil => c zero
280: | Lambda.RECORD l => convlist(l,fn vl => mk(fn x => RECORD(recordpath vl,x,c x)))
281: | Lambda.SELECT(i, e) => mk(fn w => conv(e, fn v => SELECT(i, v, w, c w)))
282: | Lambda.SWITCH(e,l as (Lambda.DATAcon(Basics.DATACON{
283: rep=Basics.VARIABLE _,...}), _)::_, SOME d) =>
284: let val cf = mkLvar() and vf = mkLvar()
285: in FIX([(cf, [vf], c vf)],
286: conv(Lambda.SELECT(1,e), fn w =>
287: let fun g((Lambda.DATAcon(Basics.DATACON{
288: rep=Basics.VARIABLE(Access.PATH p),const=true,...}), x)::r) =
289: conv(translatepath(1::p), fn v =>
290: PRIMOP(P.ineq, [w,v], [], [g r, conv(x, fn z => APP(cf,[z]))]))
291: | g((Lambda.DATAcon(Basics.DATACON{
292: rep=Basics.VARIABLE(Access.PATH p),...}), x)::r) =
293: conv(translatepath p, fn v =>
294: PRIMOP(P.ineq, [w,v], [], [g r, conv(x, fn z => APP(cf,[z]))]))
295: | g nil = conv(d, fn z => APP(cf,[z]))
296: | g _ = ErrorMsg.impossible "convert.21"
297: in g l
298: end))
299: end
300: | Lambda.SWITCH(e,l as (Lambda.REALcon _, _)::_, SOME d) =>
301: let val cf = mkLvar() and vf = mkLvar()
302: in FIX([(cf, [vf], c vf)],
303: conv(e, fn w =>
304: let fun g((Lambda.REALcon rval, x)::r) =
305: bindconst(REALconst rval, fn v =>
306: PRIMOP(P.fneq, [w,v],[], [g r, conv(x,fn z => APP(cf,[z]))]))
307: | g nil = conv(d, fn z => APP(cf,[z]))
308: | g _ = ErrorMsg.impossible "convert.81"
309: in g l
310: end))
311: end
312: | Lambda.SWITCH(e,l as (Lambda.INTcon _, _)::_, SOME d) =>
313: let val cf = mkLvar() and vf = mkLvar() and df = mkLvar()
314: in FIX([(cf, [vf], c vf), (df, [], conv(d, fn z => APP(cf,[z])))],
315: conv(e, fn w =>
316: let fun g (Lambda.INTcon j, a) = (j,conv(a, fn z => APP(cf,[z])))
317: in switch(w, map g l, SOME df, NONE)
318: end))
319: end
320: | Lambda.SWITCH(e,l as (Lambda.STRINGcon _, _)::_, SOME d) =>
321: let val cf = mkLvar() and vf = mkLvar() and df = mkLvar() and vd = mkLvar()
322: val cont = fn z => APP(cf,[z])
323: fun isboxed (Lambda.STRINGcon s, _) = size s <> 1
324: val b = sublist isboxed l
325: val u = sublist (not o isboxed) l
326: fun g(Lambda.STRINGcon j, e) = (ord j, conv(e,cont))
327: val z = map g u
328: val [p1,p2] = !CoreInfo.stringequalPath
329: in FIX([(cf, [vf], c vf), (df, [], conv(d, cont))],
330: conv(e, fn w =>
331: let val genu = switch(w, z, SOME df, NONE)
332: fun genb [] = APP(df,[])
333: | genb cases =
334: let val len1 = mkLvar()
335: fun g((Lambda.STRINGcon s, x)::r) =
336: let val ssize = size s
337: val k = mkLvar() and seq = mkLvar() and pair = mkLvar()
338: and c2 = mkLvar() and ans = mkLvar()
339: in FIX((k,[], g r)::
340: if ssize=0 then []
341: else [(c2,[ans],PRIMOP(P.ieql,[ans,zero],[],
342: [APP(k,[]), conv(x,cont)]))],
343: bindconst(STRINGconst s, fn v =>
344: bindconst(INTconst ssize, fn len0 =>
345: bindconst(INTconst((ssize + 3) div 4 - 1), fn len0' =>
346: PRIMOP(P.ineq,[len0,len1],[],
347: [APP(k,[]),
348: if ssize=0 then conv(x,cont)
349: else SELECT(p1,ren p2,seq,
350: RECORD([(w,OFFp 0),(v,OFFp 0)],
351: pair, APP(seq,[pair,c2])))])))))
352: end
353: | g nil = APP(df, [])
354: in PRIMOP(P.slength,[w],[len1], [g cases])
355: end
356: in PRIMOP(P.boxed,[w],[],[genb b, genu])
357: end))
358: end
359: | Lambda.SWITCH
360: (x as (Lambda.APP(Lambda.PRIM i, args),
361: [(Lambda.DATAcon(Basics.DATACON{rep=(Basics.CONSTANT c1),...}),e1),
362: (Lambda.DATAcon(Basics.DATACON{rep=(Basics.CONSTANT c2),...}),e2)],
363: NONE)) =>
364: let fun g(n,a,b) =
365: let val cf = mkLvar() and v = mkLvar()
366: val cont = (fn w => APP(cf,[w]))
367: in FIX([(cf,[v],c v)],
368: getargs(n,args,fn vl => PRIMOP(i,vl,[],[conv(a,cont),conv(b,cont)])))
369: end
370: in case (calling i, c1, c2) of
371: ((n,0,2), 1, 0) => g(n,e1,e2)
372: | ((n,0,2), 0, 1) => g(n,e2,e1)
373: | _ => genswitch(x,c)
374: end
375: | Lambda.SWITCH x => genswitch(x,c)
376: | Lambda.RAISE(e) =>
377: conv(e,fn w => mk(fn h => PRIMOP(P.gethdlr,[],[h],[APP(h,[w])])))
378: | Lambda.HANDLE(a,b) =>
379: let val h = mkLvar() and vb = mkLvar() and vc = mkLvar()
380: and x = mkLvar() and v = mkLvar ()
381: in FIX([(vc,[x],c x)],
382: PRIMOP(P.gethdlr,[],[h],
383: [FIX([(vb,[v],PRIMOP(P.sethdlr,[h],[],[conv(b,fn f => APP(f,[v,vc]))]))],
384: PRIMOP(P.sethdlr,[vb],[],
385: [conv(a, fn va => PRIMOP(P.sethdlr,[h],[], [APP(vc,[va])]))]))]))
386: end
387:
388: and genswitch ((e, l as (Lambda.DATAcon(Basics.DATACON{sign,...}),_)::_, d),c) =
389: let val cf = mkLvar() and cv = mkLvar() and df = mkLvar()
390: val cont = fn z => APP(cf,[z])
391: val boxed = sublist (isboxed o #1) l
392: val unboxed = sublist (not o isboxed o #1) l
393: val w = mkLvar() and t = mkLvar()
394: fun tag (Lambda.DATAcon(Basics.DATACON{rep=Basics.CONSTANT i,...}), e) =
395: (i, conv(e,cont))
396: | tag (Lambda.DATAcon(Basics.DATACON{rep=Basics.TAGGED i,...}), e) =
397: (i, conv(e,cont))
398: | tag (c,e) = (0, conv(e,cont))
399: in FIX((cf,[cv],c cv) ::
400: case d of NONE => [] | SOME d' => [(df,[],conv(d',cont))],
401: conv(e, fn w =>
402: case (count isboxedRep sign, count (not o isboxedRep) sign)
403: of (0, n) => switch(w, map tag l, SOME df, SOME(n-1))
404: | (n, 0) => SELECT(1, w, t, switch(t, map tag l, SOME df, SOME(n-1)))
405: | (1, nu) =>
406: PRIMOP(P.boxed, [w], [],
407: [switch(zero, map tag boxed, SOME df, SOME 0),
408: switch(w, map tag unboxed, SOME df, SOME(nu-1))])
409: | (nb,nu) =>
410: PRIMOP(P.boxed, [w], [],
411: [SELECT(1,w,t, switch(t, map tag boxed, SOME df, SOME(nb-1))),
412: switch(w, map tag unboxed, SOME df, SOME(nu-1))])))
413: end
414: val v = mkLvar() and x = mkLvar() and f = mkLvar()
415: in ((f, [v,x], conv(lexp, fn w => APP(w,[v,x]))), ctable)
416: end
417:
418: end
419:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.