|
|
1.1 ! root 1: (* Copyright 1989 by AT&T Bell Laboratories *) ! 2: structure Initial = ! 3: struct ! 4: ! 5: structure Inside : sig structure System : SYSTEM ! 6: structure List : LIST ! 7: structure ByteArray : BYTEARRAY ! 8: structure IO : IO ! 9: structure Bool : BOOL ! 10: structure String : STRING ! 11: end = ! 12: struct ! 13: ! 14: open Core ! 15: ! 16: (* create a type-safe version of the InLine structure while preserving ! 17: the inline property of the functions. *) ! 18: structure InLine = ! 19: struct ! 20: infix 7 * div ! 21: infix 6 + - ! 22: infix 4 < > <= >= ! 23: infix 3 := ! 24: val callcc : ('a cont -> 'a) -> 'a = InLine.callcc ! 25: val throw : 'a cont -> 'a -> 'b = InLine.throw ! 26: val ! : 'a ref -> 'a = InLine.! ! 27: val op * : int * int -> int = InLine.* ! 28: val op + : int * int -> int = InLine.+ ! 29: val op - : int * int -> int = InLine.- ! 30: val op := : 'a ref * 'a -> unit = InLine.:= ! 31: val op < : int * int -> bool = InLine.< ! 32: val op <= : int * int -> bool = InLine.<= ! 33: val op > : int * int -> bool = InLine.> ! 34: val op >= : int * int -> bool = InLine.>= ! 35: val alength : 'a array -> int = InLine.alength ! 36: val boxed : 'a -> bool = InLine.boxed ! 37: val cast : 'a -> 'b = InLine.cast ! 38: val op div : int * int -> int = InLine.div ! 39: val fadd : real * real -> real = InLine.fadd ! 40: val fdiv : real * real -> real = InLine.fdiv ! 41: val feql : real * real -> bool = InLine.feql ! 42: val fge : real * real -> bool = InLine.fge ! 43: val fgt : real * real -> bool = InLine.fgt ! 44: val fle : real * real -> bool = InLine.fle ! 45: val flt : real * real -> bool = InLine.flt ! 46: val fmul : real * real -> real = InLine.fmul ! 47: val fneg : real -> real = InLine.fneg ! 48: val fneq : real * real -> bool = InLine.fneq ! 49: val fsub : real * real -> real = InLine.fsub ! 50: val ieql : int * int -> bool = InLine.ieql ! 51: val ineq : int * int -> bool = InLine.ineq ! 52: val makeref : 'a -> 'a ref = InLine.makeref ! 53: val ordof : string * int -> int = InLine.ordof ! 54: val slength : string -> int = InLine.slength ! 55: val store : string * int * int -> unit = InLine.store ! 56: val subscript : 'a array * int -> 'a = InLine.subscript ! 57: val update : 'a array * int * 'a -> unit = InLine.update ! 58: val ~ : int -> int = InLine.~ ! 59: val reql : 'a ref * 'a ref -> bool = InLine.ieql ! 60: val aeql : 'a array * 'a array -> bool = InLine.ieql ! 61: val andb : int * int -> int = InLine.andb ! 62: val orb : int * int -> int = InLine.orb ! 63: val xorb : int * int -> int = InLine.xorb ! 64: val rshift : int * int -> int = InLine.rshift ! 65: val lshift : int * int -> int = InLine.lshift ! 66: val notb : int -> int = InLine.notb ! 67: end (* structure InLine *) ! 68: ! 69: fun c_function s = ! 70: let exception C_function_not_found of string ! 71: fun f (Assembly.FUNC(p,t,rest)) = ! 72: if stringequal(s,t) then p ! 73: else if stringequal(t,"xxxx") then raise (C_function_not_found s) ! 74: else f rest ! 75: val cfun = f Assembly.external ! 76: in fn x => Assembly.A.callc(cfun,x) ! 77: end ! 78: ! 79: val isV9 = InLine.ieql(Assembly.opsys,3) ! 80: ! 81: val bigEndian = ! 82: case InLine.!(InLine.cast "\001\003\005\007") ! 83: of 8487555 => true ! 84: | 58884480 => false ! 85: ! 86: ! 87: (* The datatype ref is defined in the built-in structure PrimTypes. ! 88: It is not mention here because it has a unique representation; an ! 89: explicit datatype declaration would destroy this representation. ! 90: Similarly, there is no datatype specification in the REF signature ! 91: itself. *) ! 92: structure Ref = ! 93: struct ! 94: infix 3 := ! 95: val ! = InLine.! ! 96: val op := = InLine.:= ! 97: fun inc r = r := InLine.+(!r,1) ! 98: fun dec r = r := InLine.-(!r,1) ! 99: end (* structure Ref *) ! 100: ! 101: structure List : LIST = ! 102: struct ! 103: infixr 5 :: @ ! 104: open PrimTypes InLine ! 105: exception Hd ! 106: exception Tl ! 107: exception Nth ! 108: exception NthTail ! 109: fun hd (a::r) = a | hd nil = raise Hd ! 110: fun tl (a::r) = r | tl nil = raise Tl ! 111: fun null nil = true | null _ = false ! 112: fun length l = ! 113: let fun j(k,nil) = k ! 114: | j(k, a::x) = j(k+1,x) ! 115: in j(0,l) ! 116: end ! 117: fun op @ (nil,l) = l ! 118: | op @ (a::r, l) = a :: (r@l) ! 119: fun rev l = ! 120: let fun f (nil, h) = h ! 121: | f (a::r, h) = f(r, a::h) ! 122: in f(l,nil) ! 123: end ! 124: fun map f = ! 125: let fun m nil = nil ! 126: | m (a::r) = f a :: m r ! 127: in m ! 128: end ! 129: fun fold f [] = (fn b => b) ! 130: | fold f (a::r) = (fn b => let fun f2(e,[]) = f(e,b) ! 131: | f2(e,a::r) = f(e,f2(a,r)) ! 132: in f2(a,r) ! 133: end) ! 134: fun revfold f [] = (fn b => b) ! 135: | revfold f (a::r) = (fn b => let fun f2(e,[],b) = f(e,b) ! 136: | f2(e,a::r,b) = f2(a,r,f(e,b)) ! 137: in f2(a,r,b) ! 138: end) ! 139: fun app f = let fun a2 (e::r) = (f e; a2 r) | a2 nil = () in a2 end ! 140: fun revapp f = let fun a2 (e::r) = (a2 r; f e; ()) | a2 nil = () in a2 end ! 141: fun nthtail(e,0) = e ! 142: | nthtail(e::r,n) = nthtail(r,n-1) ! 143: | nthtail _ = raise NthTail ! 144: fun nth x = hd(nthtail x) handle NthTail => raise Nth | Hd => raise Nth ! 145: fun exists pred = ! 146: let fun f nil = false ! 147: | f (hd::tl) = pred hd orelse f tl ! 148: in f ! 149: end ! 150: end (* structure List *) ! 151: ! 152: structure PreString : sig exception Substring ! 153: infix 6 ^ ! 154: val substring : string * int * int -> string ! 155: val ^ : string * string -> string ! 156: val imakestring : int -> string ! 157: end = ! 158: struct ! 159: open InLine ! 160: exception Substring ! 161: fun substring("",0,0) = "" (* never call create_s with 0 *) ! 162: | substring("",_,_) = raise Substring ! 163: | substring(s,i,0) = if i>=0 ! 164: then if boxed s then if i <= slength s ! 165: then "" else raise Substring ! 166: else if i<=1 ! 167: then "" else raise Substring ! 168: else raise Substring ! 169: | substring(s,0,1) = if boxed s then cast(ordof(s,0)) else s ! 170: | substring(s,i,1) = ! 171: if boxed s then if i>=0 andalso i < slength s ! 172: then cast(ordof(s,i)) ! 173: else raise Substring ! 174: else if ieql(i,0) then s else raise Substring ! 175: | substring(s,i,len) = ! 176: if boxed s andalso i>=0 andalso i+len <= slength s ! 177: andalso len >= 0 ! 178: then let val a = Assembly.A.create_s(len) ! 179: fun copy j = if ieql(j,len) then () ! 180: else (store(a,j,ordof(s,i+j)); copy(j+1)) ! 181: in copy 0; a ! 182: end ! 183: else raise Substring ! 184: ! 185: infix 6 ^ ! 186: fun op ^ ("",s) = s ! 187: | op ^ (s,"") = s ! 188: | op ^ (x,y) = ! 189: if boxed x ! 190: then if boxed y ! 191: then let val xl = slength x and yl = slength y ! 192: val a = Assembly.A.create_s(xl+yl) ! 193: fun copyx n = if ieql(n,xl) then () ! 194: else (store(a,n,ordof(x,n)); copyx(n+1)) ! 195: fun copyy n = if ieql(n,yl) then () ! 196: else (store(a,xl+n,ordof(y,n)); copyy(n+1)) ! 197: in copyx 0; copyy 0; a ! 198: end ! 199: else let val xl = slength x ! 200: val a = Assembly.A.create_s(xl+1) ! 201: fun copyx n = if ieql(n,xl) then () ! 202: else (store(a,n,ordof(x,n)); copyx(n+1)) ! 203: in copyx 0; store(a,xl,cast y); a ! 204: end ! 205: else if boxed y ! 206: then let val yl = slength y ! 207: val a = Assembly.A.create_s(1+yl) ! 208: fun copyy n = if ieql(n,yl) then () ! 209: else (store(a,1+n,ordof(y,n)); copyy(n+1)) ! 210: in store(a,0,cast x); copyy 0; a ! 211: end ! 212: else let val a = Assembly.A.create_s 2 ! 213: in store(a,0,cast x); store(a,1,cast y); a ! 214: end ! 215: fun imakestring i = ! 216: if i<0 then "~" ^ imakestring(~i) ! 217: else if i<10 then InLine.cast(InLine.cast "0" + i) ! 218: else let val j = i div 10 ! 219: in imakestring j ^ imakestring(i-j*10) ! 220: end ! 221: ! 222: end (* structure PreString *) ! 223: ! 224: abstraction ByteArray : BYTEARRAY = ! 225: struct ! 226: open InLine PreString ! 227: infix 3 sub ! 228: type bytearray = string ! 229: exception Subscript ! 230: exception Range ! 231: fun array(len,v) = ! 232: if len<0 then raise Subscript ! 233: else if v<0 orelse v>=256 then raise Range ! 234: else if ieql(len,0) then Assembly.bytearray0 ! 235: else let val a = Assembly.A.create_b len ! 236: fun init i = if ieql(i,len) then () ! 237: else (store(a,i,v); init(i+1)) ! 238: in init 0; a ! 239: end ! 240: val length = cast slength ! 241: fun update(arg as (s,i,c)) = ! 242: if i<0 orelse i >= slength s then raise Subscript ! 243: else if c<0 orelse c>255 then raise Range ! 244: else store arg ! 245: val op sub = fn (s,i) => if i<0 orelse i>= slength s then raise Subscript ! 246: else ordof(s,i) ! 247: fun extract(ba,i,1) = if i<0 orelse i >= slength ba then raise Subscript ! 248: else cast(ordof(ba,i)) ! 249: | extract(s,i,len) = ! 250: if i<0 orelse i+len > slength s orelse len<0 then raise Subscript ! 251: else if ieql(len,0) then "" ! 252: else let val a = Assembly.A.create_s len ! 253: fun copy j = if ieql(j,len) then () ! 254: else (store(a,j,ordof(s,i+j)); copy(j+1)) ! 255: in copy 0; a ! 256: end ! 257: fun app f ba = ! 258: let val len = slength ba ! 259: fun app' i = if i >= len then () ! 260: else (f(ba sub i); app'(i+1)) ! 261: in app' 0 ! 262: end ! 263: fun revapp f ba = ! 264: let fun revapp' i = if i < 0 then () ! 265: else (f(ba sub i); revapp'(i-1)) ! 266: in revapp'(slength ba - 1) ! 267: end ! 268: fun fold f ba x = ! 269: let fun fold'(i,x) = if i < 0 then x else fold'(i-1, f(ordof(ba,i),x)) ! 270: in fold'(slength ba - 1, x) ! 271: end ! 272: fun revfold f ba x = ! 273: let val len = slength ba ! 274: fun revfold'(i,x) = if i >= len then x ! 275: else revfold'(i+1,f(ordof(ba,i),x)) ! 276: in revfold'(0,x) ! 277: end ! 278: end (* abstraction ByteArray *) ! 279: ! 280: structure PreLim = ! 281: struct ! 282: val exn_name : exn -> string = InLine.cast(fn(_,ref s) => s) ! 283: val interactive = Core.Refs.interactive ! 284: val prLambda = Core.Refs.prLambda ! 285: fun getargs s = ! 286: let val f : int -> string = c_function s ! 287: fun strlen(s,i) = ! 288: if InLine.ieql(InLine.ordof(s,i),0) then i ! 289: else strlen(s,InLine.+(i,1)) ! 290: fun mlstr x = ! 291: let val len = strlen(x,0) ! 292: val ba = Assembly.A.create_s len ! 293: fun copy ~1 = () ! 294: | copy i = (InLine.store(ba,i,InLine.ordof(x,i)); ! 295: copy(InLine.-(i,1))) ! 296: in copy (InLine.-(len,1)); ! 297: ba ! 298: end ! 299: fun g i = ! 300: let val x = f i ! 301: in if InLine.ineq(InLine.cast x,0) ! 302: then mlstr x :: g (InLine.+(i,1)) ! 303: else nil ! 304: end ! 305: in fn () => g 0 ! 306: end ! 307: val argv : unit -> string list = getargs "argv" ! 308: val environ : unit -> string list = getargs "envi" ! 309: end (* structure PreLim *) ! 310: ! 311: structure PreStats = ! 312: struct ! 313: datatype time = TIME of {sec : int, usec : int} ! 314: local open Assembly.A Ref ! 315: in ! 316: val zerotime = TIME{sec=0,usec=0} ! 317: val lines = Core.Refs.lines ! 318: val parse = InLine.cast Core.Refs.parse ! 319: val translate = InLine.cast Core.Refs.translate ! 320: val codeopt = InLine.cast Core.Refs.codeopt ! 321: val convert = InLine.cast Core.Refs.convert ! 322: val hoist = InLine.cast Core.Refs.hoistx ! 323: val cpsopt = InLine.cast Core.Refs.cpsopt ! 324: val closure = InLine.cast Core.Refs.closure ! 325: val globalfix = InLine.cast Core.Refs.globalfix ! 326: val spill = InLine.cast Core.Refs.spill ! 327: val codegen = InLine.cast Core.Refs.codegen ! 328: val freemap = InLine.cast Core.Refs.freemap ! 329: val execution = InLine.cast Core.Refs.execution ! 330: fun reset() = ! 331: (lines := 0; ! 332: parse := zerotime; ! 333: translate := zerotime; ! 334: codeopt := zerotime; ! 335: convert := zerotime; ! 336: cpsopt := zerotime; ! 337: closure := zerotime; ! 338: globalfix := zerotime; ! 339: spill := zerotime; ! 340: codegen := zerotime; ! 341: freemap := zerotime; ! 342: execution := zerotime) ! 343: end ! 344: end ! 345: ! 346: val errn = c_function "errn" ! 347: ! 348: fun syserror s = ! 349: let val n = errn() ! 350: open PreString ! 351: val m = InLine.alength Assembly.errorstrings ! 352: val w = if InLine.>=(n,m) orelse InLine.<(n,0) ! 353: then "Error " ^ imakestring n ! 354: else InLine.subscript(Assembly.errorstrings,n) ! 355: in raise Assembly.SystemCall (s ^ " failed, " ^ w) ! 356: end ! 357: ! 358: structure IOx = ! 359: struct ! 360: local open InLine Ref PreString PrimTypes in ! 361: type bytearray = string ! 362: exception Io of string ! 363: type instream = {filid : int, pos : int ref, len : int ref, name : string, ! 364: closed : bool ref, buf : bytearray, tty : bool ref} ! 365: type outstream = {filid : int, pos : int ref, name : string, ! 366: closed : bool ref, buf : bytearray, tty : bool ref} ! 367: ! 368: val isatty = c_function "isat" ! 369: ! 370: val bufsize = Core.bufsize ! 371: ! 372: val std_in = Core.std_in ! 373: val std_out = Core.std_out ! 374: val _ = (#tty std_in := isatty 0; #tty std_out := isatty 1) ! 375: ! 376: (* should be flushed on exportML, flushed and closed on exportFn *) ! 377: val outstreams = Core.Refs.outstreams ! 378: (* should be closed on exportFn *) ! 379: val instreams = Core.Refs.instreams ! 380: fun add_in s = instreams := s :: !instreams ! 381: fun add_out s = outstreams := s :: !outstreams ! 382: fun init_streams() = ! 383: let val {pos=pos_in,tty=tty_in,closed=closed_in,len,...} = std_in ! 384: val {pos=pos_out,tty=tty_out,closed=closed_out,...} = std_out ! 385: in pos_in := 0; tty_in := isatty 0; closed_in := false; len := 0; ! 386: pos_out := 0; tty_out := isatty 1; closed_out := false; ! 387: PreLim.interactive := !tty_in; ! 388: instreams := [std_in]; ! 389: outstreams := [std_out] ! 390: end ! 391: ! 392: (* the filename passed to Assembly.A.openf must be zero-padded; ! 393: you need 2 zeros in case padding a null string. *) ! 394: val c00 = "\000\000" ! 395: ! 396: fun close filid = case Assembly.A.syscall(6,[cast filid],1) ! 397: of ~1 => syserror "close" ! 398: | _ => () ! 399: ! 400: datatype mode = READ | WRITE | APPEND ! 401: ! 402: val openf = ! 403: if isV9 ! 404: then fn(name,mode) => ! 405: let open Assembly.A ! 406: in case mode ! 407: of READ => ! 408: (case syscall(5,[name,cast 0],2) ! 409: of ~1 => syserror "open" ! 410: | n => n) ! 411: | WRITE => ! 412: (case syscall(8,[name, cast 438],2) ! 413: of ~1 => syserror "creat" ! 414: | n => n) ! 415: | APPEND => ! 416: (case syscall(5,[name,cast 1],2) ! 417: of ~1 => (case syscall(8,[name, cast 438],2) ! 418: of ~1 => syserror "creat" ! 419: | n => n) ! 420: | n => (case syscall(19,[cast n,cast 0,cast 2],3) ! 421: of ~1 => (close n; syserror "lseek") ! 422: | _ => n)) ! 423: end ! 424: else fn (name,mode) => ! 425: let open Assembly.A ! 426: val flag = case mode of READ => 0 | WRITE => 1537 | APPEND => 521 ! 427: in case syscall(5,[name, cast flag, cast 438],3) ! 428: of ~1 => syserror "open" ! 429: | n => n ! 430: end ! 431: ! 432: fun open_in s = ! 433: let val f = openf(s ^ c00,READ) ! 434: handle Assembly.SystemCall message => ! 435: raise Io("open_in \"" ^ s ^ "\": " ^ message) ! 436: val s = {filid = f, pos = ref 0, closed = ref false, ! 437: len = ref 0, name = s, ! 438: buf = Assembly.A.create_b bufsize, tty = ref(isatty f)} ! 439: in add_in s; s ! 440: end ! 441: fun open_o mode = fn s => ! 442: let val f = openf(s ^ c00,mode) ! 443: val s = {filid = f, pos = ref 0, closed = ref false, name=s, ! 444: buf = Assembly.A.create_b bufsize, tty = ref(isatty f)} ! 445: in add_out s; s ! 446: end ! 447: ! 448: fun open_out name = open_o WRITE name ! 449: handle Assembly.SystemCall message => ! 450: raise Io("open_out \"" ^ name ^ "\": " ^ message) ! 451: ! 452: fun open_append name = open_o APPEND name ! 453: handle Assembly.SystemCall message => ! 454: raise Io("open_append \"" ^ name ^ "\": " ^ message) ! 455: ! 456: ! 457: fun open_string s = ! 458: if boxed s ! 459: then {filid = ~1, pos = ref 0, len = ref (slength s), ! 460: closed = ref false, tty = ref false, name="<string>", ! 461: buf = s} ! 462: else {filid = ~1, pos = ref 0, len = ref 1, ! 463: closed = ref false, tty = ref false, name="<string>", ! 464: buf =let val a = Assembly.A.create_s 1 ! 465: in store(a,0,cast s); a ! 466: end} ! 467: ! 468: fun read(filid, buf) = ! 469: case Assembly.A.syscall(3,[cast filid, buf, cast(slength buf)],3) ! 470: of ~1 => syserror "read" ! 471: | n => n ! 472: ! 473: fun filbuf ({closed = ref true,...} : instream) = ! 474: raise Assembly.SystemCall "closed instream" ! 475: | filbuf {filid = ~1,pos,len,...} = (len := 0; pos := 0) ! 476: | filbuf {filid,pos,buf,len,...} = ! 477: (pos := 0; len := read(filid,buf)) ! 478: ! 479: fun write(filid,s,l) = ! 480: case Assembly.A.syscall(4,[cast filid, s, cast l],3) ! 481: of ~1 => syserror "write" ! 482: | n => n ! 483: ! 484: fun write_sure(filid,s,l) = ! 485: let val k = write(filid,s,l) ! 486: in if ieql(k,l) then () ! 487: else let val subs = PreString.substring ! 488: fun f i = if i+k<l ! 489: then (write_sure(filid,subs(s,i,k),k); f(i+k)) ! 490: else write_sure(filid,subs(s,i,l-i),l-i) ! 491: in f k ! 492: end ! 493: end ! 494: ! 495: fun flush_out ({closed = ref true,name,...} : outstream) = ! 496: raise Io ("flush_out \"" ^ name ^ "\": closed stream") ! 497: | flush_out {pos = ref 0,...} = () ! 498: | flush_out {filid,pos,buf,name,...} = ! 499: (write_sure(filid,buf,!pos); ! 500: pos := 0) ! 501: handle Assembly.SystemCall s => ! 502: raise Io("flush_out \"" ^ name ^ "\": " ^ s) ! 503: ! 504: val flsbuf = flush_out ! 505: ! 506: fun close_in ({closed = ref true,name,...} : instream) = ! 507: raise Io("close_in \"" ^ name ^ "\": closed stream") ! 508: | close_in {filid = ~1,closed,len,pos,...} = ! 509: (closed := true; len := 0; pos := 1) ! 510: | close_in {filid,pos,len,closed,name,...} = ! 511: (closed := true; len := 0; pos := 1; ! 512: instreams := List.fold ! 513: (fn(s as {pos=p,...}:instream, tl) => ! 514: if ieql(cast pos, cast p) then tl else s::tl) ! 515: (!instreams) ! 516: nil; ! 517: close filid handle Assembly.SystemCall s => ! 518: raise Io("close_in \"" ^ name ^ "\": " ^ s)) ! 519: ! 520: fun close_out ({closed = ref true,name,...} : outstream) = ! 521: raise(Io("close_out \"" ^ name ^ "\": closed stream")) ! 522: | close_out (f as {filid,pos,closed,name,...}) = ! 523: (flsbuf f; pos := 0; closed := true; ! 524: outstreams := List.fold ! 525: (fn(s as {filid=f,...}:outstream,tl) => ! 526: if ieql(filid,f) then tl else s::tl) ! 527: (!outstreams) ! 528: nil; ! 529: close filid) ! 530: handle Assembly.SystemCall s => ! 531: raise Io("close_out \"" ^ name ^ "\": " ^ s) ! 532: ! 533: fun look ({closed = ref true,...} : instream) = ! 534: raise Assembly.SystemCall "closed stream" ! 535: | look (f as {len,pos,buf,...}) = ! 536: if !len > !pos ! 537: then cast(ordof(buf,!pos)) ! 538: else (filbuf f; if ieql(!len,0) then "" else look f) ! 539: ! 540: fun lookahead f = look f handle Assembly.SystemCall s => ! 541: raise Io("lookahead \"" ^ #name f ^ "\": " ^ s) ! 542: ! 543: fun end_of_stream ({closed = ref true,name,...} : instream) = ! 544: raise Io("end_of_stream \"" ^ name ^ "\": closed stream") ! 545: | end_of_stream f = case look f of "" => true | _ => false ! 546: handle Assembly.SystemCall s => ! 547: raise Io("end_of_stream \"" ^ #name f ^ "\": " ^ s) ! 548: ! 549: fun biginput(filid,k) = (* k must be larger than 1 *) ! 550: let val a = Assembly.A.create_s k ! 551: val len = read(filid,a) ! 552: in if ieql(len,k) then a ! 553: else PreString.substring(a,0,len) ! 554: end ! 555: ! 556: local ! 557: val mtim: int -> int = c_function "mtim" (* "mtim" gives ~1 on error *) ! 558: in ! 559: fun mtime({filid, closed,name, ...}: instream): int = ! 560: if !closed then ! 561: raise Io("mtime \"" ^ name ^ "\": closed stream") ! 562: else ! 563: let val tim = mtim filid ! 564: in if InLine.ieql(tim, ~1) then raise Io("mtime \"" ^ name ^ "\"") ! 565: else tim ! 566: end ! 567: end ! 568: ! 569: val fionread : int -> int = c_function "fion" ! 570: ! 571: fun input(f as {filid,pos,len,buf,closed,name,...} : instream) = ! 572: let val filbuf = fn f => (filbuf f ! 573: handle Assembly.SystemCall s => ! 574: raise Io("input \"" ^ name ^ "\": " ^ s)) ! 575: fun get i = ! 576: if (!len - !pos) >= i then ! 577: if ieql(i,1) then ! 578: let val p = !pos ! 579: in pos := p+1; cast(ordof(buf,p)) ! 580: end ! 581: else if i < 0 then ! 582: raise Io("input \"" ^ name ^ "\": negative character count") ! 583: else let val s = substring(buf,!pos,i) ! 584: in pos := !pos+i; s ! 585: end ! 586: else if !closed then raise Io("input \"" ^ name ^ "\": closed stream") ! 587: else let val remaining = !len - !pos ! 588: val s = substring(buf,!pos, remaining) ! 589: val j = i - remaining ! 590: val avail = if filid < 0 then 0 ! 591: else if j<=bufsize then j ! 592: else let val c = fionread filid ! 593: in if j<c then j else c ! 594: end ! 595: in if avail >= bufsize ! 596: then let val s' = biginput(filid,avail) ! 597: handle Assembly.SystemCall s => ! 598: raise Io("input \"" ^ name ^ "\": " ^ s) ! 599: in if boxed s' ! 600: then if ieql(slength s',0) ! 601: then s ! 602: else s ^ s' ^ get(j-slength s') ! 603: else s ^ s' ^ get(j-1) ! 604: end ! 605: else (filbuf f; ! 606: if ieql(!len,0) then s ! 607: else s ^ get j) ! 608: end ! 609: in get ! 610: end ! 611: ! 612: fun input_line({closed = ref true,name,...} : instream) = ! 613: raise Io ("input_line \"" ^ name ^ "\": closed stream") ! 614: | input_line(f as {pos,len,buf,name,...}) = ! 615: let val l = !len ! 616: val filbuf = fn f => (filbuf f ! 617: handle Assembly.SystemCall s => ! 618: raise Io("input_line \"" ^ name ^ "\": " ^ s)) ! 619: fun next j = if ieql(j,l) then ! 620: let val s = substring(buf, !pos, l - !pos) ! 621: in filbuf f; ! 622: if ieql(!len,0) then s ! 623: else s ^ input_line f ! 624: end ! 625: else if ieql(ordof(buf,j),10) then input f (j+1 - !pos) ! 626: else next(j+1) ! 627: in next (!pos) ! 628: end ! 629: ! 630: fun output(f as {filid,buf,pos,tty,closed,name,...} : outstream) = ! 631: let fun put s = ! 632: if !closed then raise Assembly.SystemCall "closed outstream" ! 633: else if boxed s then ! 634: let val l = slength s ! 635: in if l > 4 * bufsize ! 636: then (flsbuf f; write_sure(filid,s,l)) ! 637: handle Assembly.SystemCall s => ! 638: raise Io("output \"" ^ name ^ "\": " ^ s) ! 639: else let val i = ref 0 ! 640: in while !i < l ! 641: do let val c = ordof(s,!i) ! 642: in store(buf,!pos,c); ! 643: pos := !pos + 1; i := !i + 1; ! 644: if ieql(!pos,bufsize) ! 645: orelse (!tty andalso ieql(c,10)) ! 646: then flsbuf f ! 647: handle Assembly.SystemCall s => ! 648: raise Io("output \"" ^ name ^ "\": " ^ s) ! 649: else () ! 650: end ! 651: end ! 652: end ! 653: else (store(buf,!pos,cast s); ! 654: pos := !pos + 1; ! 655: if ieql(!pos,bufsize) ! 656: orelse (!tty andalso ieql(cast s,10)) ! 657: then flsbuf f ! 658: handle Assembly.SystemCall s => ! 659: raise Io("output \"" ^ name ^ "\": " ^ s) ! 660: else ()) ! 661: in put ! 662: end ! 663: ! 664: fun can_input ({closed = ref true,name,...} : instream) = ! 665: raise Io("can_input \"" ^ name ^ "\": closed stream") ! 666: | can_input {filid = ~1,pos,len,...} = !len - !pos ! 667: | can_input {filid,pos,len,name,...} = ! 668: !len - !pos + fionread filid ! 669: handle Assembly.SystemCall s => raise Io("can_input \"" ^ name ^ "\": " ^ s) ! 670: ! 671: local val buf = Assembly.A.create_b 8 ! 672: in fun pipe() = (* won't work for more than 256 file descriptors! *) ! 673: (case Assembly.A.syscall(42,[buf],1) ! 674: of ~1 => syserror "pipe" ! 675: | _ => if bigEndian then (InLine.ordof(buf,3),InLine.ordof(buf,7)) ! 676: else (InLine.ordof(buf,0),InLine.ordof(buf,4))) ! 677: end ! 678: ! 679: val exec : (string * int ref * int ref) -> int = c_function "exec" ! 680: ! 681: fun execute s = ! 682: let val fdin=ref 0 and fdout = ref 0 ! 683: in case exec(s^c00,fdin,fdout) ! 684: of ~1 => raise Io("Cannot execute "^s) ! 685: | _ => ! 686: let val r = {filid = !fdin, pos = ref 0, len = ref 0, ! 687: closed = ref false, name="<pipe_in>", ! 688: buf = Assembly.A.create_b bufsize, ! 689: tty = ref false} ! 690: val w = {filid = !fdout, pos = ref 0, ! 691: closed = ref false, name="<pipe_out>", ! 692: buf = Assembly.A.create_b bufsize, ! 693: tty = ref false} ! 694: in add_in r; ! 695: add_out w; ! 696: (r,w) ! 697: end ! 698: end ! 699: ! 700: fun is_term_in ({closed = ref true,name,...} : instream) = ! 701: raise Io("is_term_in \"" ^ name ^ "\": closed stream") ! 702: | is_term_in {tty=ref x,...} = x ! 703: ! 704: fun is_term_out ({closed = ref true,name,...} : outstream) = ! 705: raise Io("is_term_out \"" ^ name ^ "\": closed stream") ! 706: | is_term_out {tty=ref x,...} = x ! 707: ! 708: fun set_term_in ({closed = ref true,name,...} : instream,_) = ! 709: raise Io("set_term_in \"" ^ name ^ "\": closed stream") ! 710: | set_term_in ({tty,...},t) = tty := t ! 711: ! 712: fun set_term_out ({closed = ref true,name,...} : outstream,_) = ! 713: raise Io("set_term_out \"" ^ name ^ "\": closed stream") ! 714: | set_term_out ({tty,...},t) = tty := t ! 715: ! 716: val expo = c_function "expo" ! 717: fun exportML filename = ! 718: let val filid = openf(filename ^ c00,WRITE) ! 719: handle Assembly.SystemCall s => raise Io("exportML \"" ^ filename ^ "\": " ^ s) ! 720: in List.app flush_out (!outstreams); ! 721: if expo filid ! 722: then ((* mark previously opened streams as closed ! 723: without flushing them *) ! 724: List.app (fn {closed,...} : outstream => closed := true) ! 725: (!outstreams); ! 726: List.app (fn {closed,...} : instream => closed := true) ! 727: (!instreams); ! 728: (* restore std_in and std_out *) ! 729: init_streams(); ! 730: (* reset timing statistics *) ! 731: PreStats.reset(); ! 732: true) ! 733: else (close filid; false) ! 734: end ! 735: ! 736: val use_f = Core.Refs.use_f ! 737: val use_s : (instream -> unit) ref = cast Core.Refs.use_s ! 738: fun use f = !use_f f ! 739: fun use_stream s = !use_s s ! 740: val reduce_r = Core.Refs.reduce_r ! 741: val reduce : ('a -> 'b) -> ('a -> 'b) = fn x => cast(!reduce_r) x ! 742: ! 743: (* close/flush all streams; watch out, some may be damaged. *) ! 744: fun cleanup () = ! 745: let fun c_out s = close_out s handle _ => () ! 746: fun c_in s = close_in s handle _ => () ! 747: in List.app c_out (!outstreams); ! 748: List.app c_in (!instreams) ! 749: end ! 750: ! 751: fun quit _ = (Assembly.A.syscall(1,[cast 0],1); ()) ! 752: ! 753: fun exportFn (filename,func) = ! 754: let val filid=openf(filename ^ c00,WRITE) ! 755: handle Assembly.SystemCall s => raise Io("exportFn \"" ^ filename ^ "\": " ^ s) ! 756: val pr = output std_out ! 757: in cleanup(); ! 758: use_f := (fn (_ : string) => ()); ! 759: use_s := (fn (_ : instream) => ()); ! 760: reduce_r := (fn (x:unit->unit) => x); ! 761: Core.Refs.lookup_r := cast(fn ()=>()); ! 762: Core.Refs.compreturn := ! 763: [cast(quit, fn e => (pr "uncaught exception "; ! 764: pr (PreLim.exn_name e); ! 765: pr "\n"; cleanup(); quit()))]; ! 766: PreLim.prLambda := (fn () => ()); ! 767: if expo filid ! 768: then (init_streams(); ! 769: func(PreLim.argv(),PreLim.environ()); ! 770: cleanup(); ! 771: quit()) ! 772: handle exn => ! 773: (pr "uncaught exception "; ! 774: pr (PreLim.exn_name exn); ! 775: pr "\n"; ! 776: cleanup()) ! 777: else () ! 778: end ! 779: ! 780: val blas : int * 'a -> 'a = c_function "blas" ! 781: val salb : string -> 'a = c_function "salb" ! 782: fun blast_write((s as {filid,...}) : outstream, obj) = ! 783: (flush_out s; blas(filid,obj); ()) ! 784: fun blast_read f = salb (input f (can_input f)) ! 785: ! 786: end (* local open ... *) ! 787: end (* structure IOx *) ! 788: ! 789: abstraction IO : IO = IOx; ! 790: ! 791: ! 792: structure Bool : BOOL = ! 793: struct ! 794: open PrimTypes (* for datatype bool *) ! 795: fun not true = false ! 796: | not false = true ! 797: fun makestring true = "true" ! 798: | makestring false = "false" ! 799: local val pr = IO.output IO.std_out in ! 800: fun print b = pr(makestring b) ! 801: end ! 802: end (* structure Bool *) ! 803: ! 804: ! 805: structure String : STRING = ! 806: struct ! 807: open PrimTypes InLine ! 808: infix 4 > < >= <= ! 809: infix 6 ^ ! 810: type string = string ! 811: fun length s = if boxed s then slength s else 1 ! 812: val size = length ! 813: exception Substring = PreString.Substring ! 814: val substring = PreString.substring ! 815: fun explode s = ! 816: if boxed s ! 817: then let fun f(l,~1) = l ! 818: | f(l, i) = f(cast(ordof(s,i)) :: l, i-1) ! 819: in f(nil, slength s - 1) ! 820: end ! 821: else [s] ! 822: val op ^ = PreString.^ ! 823: exception Chr ! 824: fun chr i = if i<0 orelse i>255 then raise Chr else cast i ! 825: exception Ord ! 826: fun ord "" = raise Ord ! 827: | ord s = if boxed s then ordof(s,0) else cast s ! 828: val ordof = fn (s,i) => ! 829: if boxed s ! 830: then if i<0 orelse i>= slength s then raise Ord else ordof(s,i) ! 831: else if ieql(i,0) then cast s else raise Ord ! 832: val print = IO.output IO.std_out ! 833: fun implode (sl:string list) = ! 834: let val len = List.fold(fn(s,l) => length s + l) sl 0 ! 835: in case len ! 836: of 0 => "" ! 837: | 1 => let fun find (""::tl) = find tl ! 838: | find (hd::_) = cast hd ! 839: | find nil = "" (* impossible *) ! 840: in find sl ! 841: end ! 842: | _ => let val new = Assembly.A.create_s len ! 843: fun copy (nil,_) = () ! 844: | copy (s::tl,base) = ! 845: let val len = length s ! 846: fun copy0 0 = () ! 847: | copy0 i = ! 848: let val next = i-1 ! 849: in store(new,base+next,ordof(s,next)); ! 850: copy0 next ! 851: end ! 852: in copy0 len; ! 853: copy(tl,base+len) ! 854: end ! 855: in copy(sl,0); ! 856: new ! 857: end ! 858: end ! 859: fun sgtr("","") = false ! 860: | sgtr(_,"") = true ! 861: | sgtr("",_) = false ! 862: | sgtr(a,b) = ! 863: if boxed a ! 864: then if boxed b ! 865: then let val al = slength a and bl = slength b ! 866: val n = if al<bl then al else bl ! 867: fun f i = ! 868: if ieql(i,n) then al > bl ! 869: else if ieql(InLine.ordof(a,i),InLine.ordof(b,i)) then f(i+1) ! 870: else InLine.ordof(a,i) > InLine.ordof(b,i) ! 871: in f 0 ! 872: end ! 873: else InLine.ordof(a,0) >= cast(b) ! 874: else if boxed b ! 875: then cast(a) > InLine.ordof(b,0) ! 876: else cast(a) > cast(b) ! 877: fun op <= (a,b) = Bool.not(sgtr(a,b)) ! 878: fun op < (a,b) = sgtr(b,a) ! 879: fun op >= (a,b) = Bool.not(sgtr(b,a)) ! 880: val op > = sgtr ! 881: end (* structure String *) ! 882: ! 883: structure System : SYSTEM = ! 884: struct ! 885: structure ByteArray : BYTEARRAY = ByteArray ! 886: structure Control : CONTROL = ! 887: struct ! 888: structure Runtime : RUNTIMECONTROL = Assembly ! 889: structure MC : MCCONTROL = ! 890: struct ! 891: val printArgs = Core.Refs.printArgs ! 892: val printRet = Core.Refs.printRet ! 893: val bindContainsVar = Core.Refs.bindContainsVar ! 894: val bindExhaustive = Core.Refs.bindExhaustive ! 895: val matchExhaustive = Core.Refs.matchExhaustive ! 896: val matchRedundant = Core.Refs.matchRedundant ! 897: val expandResult = Core.Refs.expandResult ! 898: end ! 899: structure CG : CGCONTROL = ! 900: struct ! 901: structure M68 = ! 902: struct ! 903: val trapv = Core.Refs.trapv ! 904: end ! 905: val tailrecur = Core.Refs.tailrecur ! 906: val recordopt = Core.Refs.recordopt ! 907: val tail = Core.Refs.tail ! 908: val profile = Core.Refs.profile ! 909: val closureprint = Core.Refs.closureprint ! 910: val closureStrategy = Core.Refs.closureStrategy ! 911: val rounds = Core.Refs.rounds ! 912: val path = Core.Refs.path ! 913: val hoist = Core.Refs.hoist ! 914: val reduce = Core.Refs.reduce ! 915: val bodysize = Core.Refs.bodysize ! 916: val reducemore = Core.Refs.reducemore ! 917: val alphac = Core.Refs.alphac ! 918: val comment = Core.Refs.comment ! 919: val knowngen = Core.Refs.knowngen ! 920: val stdgen = Core.Refs.stdgen ! 921: val knowncl = Core.Refs.knowncl ! 922: val foldconst = Core.Refs.foldconst ! 923: val etasplit = Core.Refs.etasplit ! 924: val printit = Core.Refs.printit ! 925: val printsize = Core.Refs.printsize ! 926: val scheduling = Core.Refs.scheduling ! 927: end ! 928: structure Print : PRINTCONTROL = ! 929: struct ! 930: val printDepth = Core.Refs.printDepth ! 931: val stringDepth = Core.Refs.stringDepth ! 932: val signatures = Core.Refs.signatures ! 933: end ! 934: structure ProfileInternals : PROFILEINTERNALS = ! 935: struct ! 936: structure ByteArray = ByteArray ! 937: open InLine ! 938: val other : ByteArray.bytearray = cast(Core.other) ! 939: val toplevel : ByteArray.bytearray = cast(Core.toplevel) ! 940: val gc : ByteArray.bytearray = cast(Core.gc) ! 941: val globalProfile : ByteArray.bytearray list ref ! 942: = InLine.cast Core.Refs.globalProfile ! 943: ! 944: fun setToplevel () = ! 945: cast(Assembly.current) := toplevel ! 946: ! 947: fun setOther () = ! 948: cast(Assembly.current) := other ! 949: ! 950: fun listofarray a = ! 951: let fun loop(~1,x) = x ! 952: | loop(i,x) = loop(i-1, InLine.subscript(a,i) :: x) ! 953: in loop(InLine.alength a - 1, nil) ! 954: end ! 955: ! 956: fun zeroCount e = (InLine.update(cast e,0,0); ! 957: InLine.update(cast e,1,0)) ! 958: ! 959: val timerval = if bigEndian then "\000\000\000\000\ ! 960: \\000\000\039\016\ ! 961: \\000\000\000\000\ ! 962: \\000\000\039\016" ! 963: else "\000\000\000\000\ ! 964: \\016\039\000\000\ ! 965: \\000\000\000\000\ ! 966: \\016\039\000\000" ! 967: val timerval0 = "\000\000\000\000\000\000\000\000\ ! 968: \\000\000\000\000\000\000\000\000" ! 969: ! 970: fun setitimer t = ! 971: case Assembly.A.syscall(83,[cast 1,t,cast 0],3) ! 972: of ~1 => syserror "setitimer" ! 973: | x => x ! 974: ! 975: fun copy(ba,str) = ! 976: let val len = slength str ! 977: fun loop i = ! 978: if ieql(i,len) ! 979: then () ! 980: else (ByteArray.update(ba,i,ordof(str,i)); loop(i+1)) ! 981: in loop 0 ! 982: end ! 983: ! 984: val _ = copy(other, "aaaaaaaa(unprofiled)") ! 985: val _ = copy(toplevel,"aaaaaaaa(toplevel)") ! 986: val _ = copy(gc, "aaaaaaaa(gc)") ! 987: ! 988: fun add profile = ! 989: if boxed profile ! 990: then let val entries = listofarray profile ! 991: in List.app zeroCount entries; ! 992: globalProfile := List.@(entries,!globalProfile) ! 993: end ! 994: else () ! 995: ! 996: fun extractInt(ba,start,len) = ! 997: !(cast(ByteArray.extract(ba,start,len)):int ref) ! 998: ! 999: fun trans ba = ! 1000: (extractInt(ba,0,4), extractInt(ba,4,4), ! 1001: ByteArray.extract(ba,8,ByteArray.length ba - 8)) ! 1002: ! 1003: local fun insert (a,nil) = [a] ! 1004: | insert (a0 as (a',a,_),l as (x0 as (x',x,_))::y) = ! 1005: if a<x orelse ieql(a,x) andalso a'<x' ! 1006: then x0::insert(a0,y) else a0::l ! 1007: in fun sort nil = nil ! 1008: | sort (a::b) = insert(a,sort b) ! 1009: end ! 1010: ! 1011: ! 1012: fun field (st,w) = ! 1013: let val s = PreString.^(" ", st) ! 1014: in PreString.substring(s,String.length s - w, w) ! 1015: end ! 1016: ! 1017: fun decimal(st,w) = ! 1018: PreString.^(PreString.^( ! 1019: (PreString.substring(st,0,String.length st - w) ! 1020: handle PreString.Substring => "") ! 1021: ,"."), ! 1022: let val st' = PreString.^("0000000000",st) ! 1023: in PreString.substring(st',String.length st' - w,w) ! 1024: end) ! 1025: ! 1026: fun muldiv(i,j,k) = ! 1027: (i*j div k) ! 1028: handle Assembly.Overflow => muldiv(i,j div 2, k div 2) ! 1029: ! 1030: fun decfield(n,j,k,w1,w2) = ! 1031: field(decimal(PreString.imakestring (muldiv(n,j,k)),w1) ! 1032: handle Assembly.Div => "",w2) ! 1033: ! 1034: fun printReport f l = ! 1035: let val l' as (_,_,_,ticks)::_ ! 1036: = List.fold (fn((n,m,s),l as (_,_,_,cum)::_)=>(n,m,s,m+cum)::l ! 1037: |((n,m,s),nil)=>[(n,m,s,m)]) (sort l) nil ! 1038: val pr = IO.output f ! 1039: in pr(field("%time",6)); ! 1040: pr(field("cumsecs",9)); ! 1041: pr(field("#call",10)); ! 1042: pr(field("ms/call",10)); ! 1043: pr(" name\n"); ! 1044: List.app (fn (n,m,s,cumm) => ! 1045: (pr(decfield(m,10000,ticks,2,6)); ! 1046: pr(decfield((ticks-cumm+m),2,1,2,9)); ! 1047: pr(field(PreString.imakestring n,10)); ! 1048: pr(decfield(m,50000,n,4,10)); ! 1049: pr " "; pr s; pr "\n")) ! 1050: l'; ! 1051: () ! 1052: end ! 1053: ! 1054: structure P = ! 1055: struct ! 1056: structure IO = IO ! 1057: val profiling = Core.Refs.profiling ! 1058: fun profileOn () = (setitimer timerval; ()) ! 1059: fun profileOff () = (setitimer timerval0; ()) ! 1060: fun reset () = List.app zeroCount (!globalProfile) ! 1061: fun clear () = (globalProfile := [toplevel,gc,other]; reset()) ! 1062: fun report f = ! 1063: printReport f (List.map trans (!globalProfile)) ! 1064: val _ = clear() ! 1065: end ! 1066: val add = InLine.cast add ! 1067: end (* structure ProfileInternals *) ! 1068: structure Profile = ProfileInternals.P ! 1069: structure Debug : DEBUG = ! 1070: struct ! 1071: val debugging = Core.Refs.debug1 ! 1072: val getDebugf = InLine.cast Core.Refs.getDebugf ! 1073: val interface = InLine.cast Core.Refs.debugInterface ! 1074: end ! 1075: val prLambda = PreLim.prLambda ! 1076: val debugging = Core.Refs.debugging ! 1077: val primaryPrompt = Core.Refs.primaryPrompt ! 1078: val secondaryPrompt = Core.Refs.secondaryPrompt ! 1079: val internals = Core.Refs.internals ! 1080: val weakUnderscore = Core.Refs.weakUnderscore ! 1081: val interp = Core.Refs.interp ! 1082: val debugLook = Core.Refs.debugLook ! 1083: val debugCollect = Core.Refs.debugCollect ! 1084: val debugBind = Core.Refs.debugBind ! 1085: val saveLambda = Core.Refs.saveLambda ! 1086: val saveLvarNames = Core.Refs.saveLvarNames ! 1087: val timings = Core.Refs.timings ! 1088: val reopen = Core.Refs.reopen ! 1089: end (* structure Control *) ! 1090: structure Tags : TAGS = (* taken from runtime/tags.h *) ! 1091: struct ! 1092: val width_tags = 4 ! 1093: val power_tags = 16 ! 1094: val tag_record = 1 ! 1095: val tag_array = 9 ! 1096: val tag_bytearray = 11 ! 1097: val tag_string = 15 ! 1098: val tag_embedded = 7 ! 1099: val tag_suspension = 13 ! 1100: val tag_backptr = 5 ! 1101: val tag_forwarded = 3 ! 1102: end (* structure Tags *) ! 1103: structure Timer : TIMER = ! 1104: struct ! 1105: structure P : sig datatype time = TIME of {sec : int, usec : int} end ! 1106: = PreStats ! 1107: open P ! 1108: open InLine PreString ! 1109: type timer = time * time ! 1110: val gettime : int ref * int ref * int ref * int ref -> unit ! 1111: = c_function "time" ! 1112: fun timer() = ! 1113: let val gu = ref 0 and gs = ref 0 and tu = ref 0 and ts = ref 0 ! 1114: in gettime(gu,gs,tu,ts); ! 1115: (TIME{sec= !ts, usec = !tu},TIME{sec= !gs, usec = !gu}) ! 1116: end ! 1117: ! 1118: val start_timer = timer ! 1119: fun delta(s2,u2,s1,u1) = ! 1120: let val (sec,usec) = (s2-s1,u2-u1) ! 1121: val (sec,usec) = if usec < 0 ! 1122: then (sec-1,usec+1000000) ! 1123: else (sec,usec) ! 1124: in (sec,usec) ! 1125: end ! 1126: fun check_timer (TIME{sec=start_s,usec=start_u}, ! 1127: TIME{sec=gstart_s,usec=gstart_u}) = ! 1128: let val (TIME{sec=curr_s,usec=curr_u}, ! 1129: TIME{sec=gcurr_s,usec=gcurr_u}) = timer() ! 1130: val (sec,usec) = delta(curr_s,curr_u,start_s,start_u) ! 1131: val (g_sec,g_usec) = delta(gcurr_s,gcurr_u,gstart_s,gstart_u) ! 1132: val (sec,usec) = delta(sec,usec,g_sec,g_usec) ! 1133: in TIME{sec=sec,usec=usec} ! 1134: end ! 1135: fun check_timer_gc (TIME{sec=start_s,usec=start_u}, ! 1136: TIME{sec=gstart_s,usec=gstart_u}) = ! 1137: let val (TIME{sec=curr_s,usec=curr_u}, ! 1138: TIME{sec=gcurr_s,usec=gcurr_u}) = timer() ! 1139: val (g_sec,g_usec) = delta(gcurr_s,gcurr_u,gstart_s,gstart_u) ! 1140: in TIME{sec=g_sec,usec=g_usec} ! 1141: end ! 1142: fun makestring(TIME{sec,usec}) = ! 1143: let val filler = if usec <= 0 then "" ! 1144: else if usec < 10 then "00000" ! 1145: else if usec < 100 then "0000" ! 1146: else if usec < 1000 then "000" ! 1147: else if usec < 10000 then "00" ! 1148: else if usec < 100000 then "0" ! 1149: else "" ! 1150: in imakestring sec ^ "." ^ filler ^ imakestring usec ! 1151: end ! 1152: fun add_time(TIME{sec=s0,usec=u0},TIME{sec=s1,usec=u1}) = ! 1153: let val (s,u) = (s0+s1,u0+u1) ! 1154: val (s,u) = if u > 1000000 then (s+1,u-1000000) ! 1155: else (s,u) ! 1156: in TIME{sec=s,usec=u} ! 1157: end ! 1158: end (* structure Timer *) ! 1159: structure Stats : STATS = ! 1160: struct ! 1161: open Timer Ref PreStats Control.Runtime PreString ! 1162: fun update(a,b) = a := add_time(!a,b) ! 1163: fun summary() = ! 1164: let val pr = IO.output IO.std_out ! 1165: val (total,garbagetime) = start_timer() ! 1166: in pr (imakestring(!lines)); ! 1167: pr " lines\n"; ! 1168: pr "parse, "; pr(makestring(!parse)); pr "s\n"; ! 1169: pr "translate, "; pr(makestring(!translate)); pr "s\n"; ! 1170: pr "codeopt, "; pr(makestring(!codeopt)); pr "s\n"; ! 1171: pr "convert, "; pr(makestring(!convert)); pr "s\n"; ! 1172: pr "cpsopt, "; pr(makestring(!cpsopt)); pr "s\n"; ! 1173: pr "closure, "; pr(makestring(!closure)); pr "s\n"; ! 1174: pr "globalfix, "; pr(makestring(!globalfix)); pr "s\n"; ! 1175: pr "spill, "; pr(makestring(!spill)); pr "s\n"; ! 1176: pr "codegen, "; pr(makestring(!codegen)); pr "s\n"; ! 1177: pr "freemap, "; pr(makestring(!freemap)); pr "s\n"; ! 1178: pr "execution, "; pr(makestring(!execution)); pr "s\n"; ! 1179: pr "garbagetime, "; pr(makestring garbagetime); pr "s\n"; ! 1180: pr "total "; pr(makestring total); pr "s\n"; ! 1181: pr "collections: "; pr(imakestring(!minorcollections)); ! 1182: pr " minor, "; pr(imakestring(!majorcollections)); ! 1183: pr " major\n"; pr(imakestring(!collected)); ! 1184: pr " collected from "; pr(imakestring(!collectedfrom)); ! 1185: pr " possible ("; ! 1186: case !collectedfrom of ! 1187: 0 => () ! 1188: | _ => pr(imakestring(InLine.div(InLine.*(!collected,100), ! 1189: !collectedfrom))); ! 1190: pr "%)\n"; ! 1191: () ! 1192: end ! 1193: abstraction Timer : TIMER = Timer ! 1194: end (* structure Stats *) ! 1195: abstraction Timer : TIMER = Timer (* to hide timer datatype *) ! 1196: ! 1197: structure Unsafe : UNSAFE = ! 1198: struct ! 1199: structure Assembly : ASSEMBLY = Assembly ! 1200: type object = Assembly.object ! 1201: val boxed=InLine.cast() ! 1202: val ordof=InLine.cast() ! 1203: val slength=InLine.cast() ! 1204: val store=InLine.cast() ! 1205: val subscript=InLine.cast() ! 1206: val update=InLine.cast() ! 1207: val delay= InLine.cast() ! 1208: val force = InLine.cast() ! 1209: fun boot (x: string) : 'a -> 'b = ! 1210: InLine.cast(InLine.+(InLine.cast x, 4),0) ! 1211: val cast = InLine.cast ! 1212: val syscall = Assembly.A.syscall ! 1213: val blast_write = cast IOx.blast_write ! 1214: val blast_read = cast IOx.blast_read ! 1215: val create_s = Assembly.A.create_s ! 1216: val store_s : string * int * int -> unit ! 1217: = InLine.cast ByteArray.update ! 1218: val lookup_r : (int->object) ref= cast Core.Refs.lookup_r ! 1219: val lookup = fn i => case lookup_r of ref f => f i ! 1220: ! 1221: val do_it = ! 1222: InLine.callcc(fn c0 => ! 1223: let val v = ! 1224: InLine.callcc(fn c => InLine.throw c0 (InLine.throw c)) () ! 1225: handle e => ! 1226: let val ref(op ::((k,h),r)) = cast Core.Refs.compreturn ! 1227: in InLine.:=(Core.Refs.compreturn, cast r); h e ! 1228: end ! 1229: val ref(op ::((k,h),r)) = cast Core.Refs.compreturn ! 1230: in InLine.:=(Core.Refs.compreturn, cast r); k v ! 1231: end) ! 1232: ! 1233: fun isolate f = InLine.callcc(fn c => ! 1234: raise(InLine.callcc(fn c' => ! 1235: (InLine.:=(cast Core.Refs.compreturn, ! 1236: op ::( (InLine.throw c, InLine.throw c'), ! 1237: cast(InLine.! Core.Refs.compreturn))); do_it f)))) ! 1238: ! 1239: val pstruct = cast Core.Refs.pstruct ! 1240: local ! 1241: datatype A = unboxed | boxed of object ! 1242: val cast = InLine.cast ! 1243: in exception Boxity ! 1244: val tuple : object -> object array ! 1245: = cast(fn unboxed => raise Boxity ! 1246: | x as boxed _ => x) ! 1247: val string : object -> string = cast (fn x=>x) ! 1248: val real : object -> real = cast (fn x=>x) ! 1249: val int : object -> int ! 1250: = cast(fn x as unboxed => x ! 1251: | boxed _ => raise Boxity) ! 1252: end (* local datatype A ... *) ! 1253: structure AA : sig ! 1254: datatype datalist = DATANIL | DATACONS of (string * string * datalist) ! 1255: val datalist : datalist ! 1256: end = Assembly ! 1257: open AA ! 1258: end (* Unsafe *) ! 1259: ! 1260: open PreLim ! 1261: val version = "Standard ML of New Jersey, Version 0.44, 4 December 1989" ! 1262: val cleanup = IO.cleanup ! 1263: val c00 = "\000\000" ! 1264: val syst = c_function "syst" ! 1265: fun system x = ! 1266: case syst(PreString.^(x,c00)) ! 1267: of 0 => () ! 1268: | _ => raise Assembly.SystemCall "system" ! 1269: fun cd s = ! 1270: case Unsafe.syscall(12,[PreString.^(s,c00)],1) ! 1271: of ~1 => syserror "chdir" ! 1272: | _ => () ! 1273: ! 1274: end (* structure System *) ! 1275: ! 1276: end (* structure Inside *) ! 1277: ! 1278: open Inside PrimTypes ! 1279: ! 1280: (* The following structures must be without signatures so that inlining ! 1281: can take place *) ! 1282: ! 1283: structure General = ! 1284: struct ! 1285: infix 3 o ! 1286: infix before ! 1287: exception Bind = Core.Bind ! 1288: exception Match = Core.Match ! 1289: exception Interrupt = Core.Assembly.Interrupt ! 1290: exception SystemCall = Core.Assembly.SystemCall ! 1291: ! 1292: val callcc : ('a cont -> 'a) -> 'a = InLine.callcc ! 1293: val throw : 'a cont -> 'a -> 'b = InLine.throw ! 1294: fun f o g = fn x => f(g x) ! 1295: fun a before b = a ! 1296: datatype 'a option = NONE | SOME of 'a ! 1297: type 'a cont = 'a cont ! 1298: type exn = exn ! 1299: type unit = unit ! 1300: infix 4 = <> ! 1301: val op = : ''a * ''a -> bool = InLine.= ! 1302: val op <> : ''a * ''a -> bool = InLine.<> ! 1303: end (* structure General *) ! 1304: ! 1305: structure Bits = ! 1306: struct ! 1307: val andb : int * int -> int = InLine.andb ! 1308: val orb : int * int -> int = InLine.orb ! 1309: val lshift : int * int -> int = InLine.lshift ! 1310: val rshift : int * int -> int = InLine.rshift ! 1311: val notb : int -> int = InLine.notb ! 1312: val xorb : int * int -> int = InLine.xorb ! 1313: end ! 1314: ! 1315: structure Ref = ! 1316: struct ! 1317: infix 3 := ! 1318: val ! : 'a ref -> 'a = InLine.! ! 1319: val op := : 'a ref * 'a -> unit = InLine.:= ! 1320: fun inc r = r := (InLine.+ : int * int -> int) (!r,1) ! 1321: fun dec r = r := (InLine.- : int * int -> int) (!r,1) ! 1322: end ! 1323: ! 1324: structure Array = ! 1325: struct ! 1326: local open InLine in ! 1327: infix 3 sub ! 1328: type 'a array = 'a array ! 1329: exception Subscript ! 1330: val array : int * '1a -> '1a array = ! 1331: fn arg as (n,v) => ! 1332: if <=(n,0) then if <(n,0) then raise Subscript ! 1333: else Core.Assembly.array0 ! 1334: else Core.Assembly.A.array arg ! 1335: val op sub : 'a array * int -> 'a = ! 1336: fn (a,i) => ! 1337: if <(i,0) orelse >=(i,alength a) then raise Subscript ! 1338: else subscript(a,i) ! 1339: val length : 'a array -> int = alength ! 1340: fun arrayoflist nil = Core.Assembly.array0 ! 1341: | arrayoflist (l as (e::r)) = ! 1342: let val a = array(List.length l, e) ! 1343: fun init ((e::r),n) = (update(a,n,e); init(r,+(n,1))) ! 1344: | init (nil,_) = () ! 1345: in init(r,1); a ! 1346: end ! 1347: val update : 'a array * int * 'a -> unit = ! 1348: fn (a,i,v) => ! 1349: if <(i,0) orelse >=(i,alength a) then raise Subscript ! 1350: else update(a,i,v) ! 1351: end (* local open ... *) ! 1352: end (* structure Array *) ! 1353: ! 1354: structure Integer = ! 1355: struct ! 1356: infix 7 * div mod ! 1357: infix 6 + - ! 1358: infix 4 > < >= <= ! 1359: exception Div = Core.Assembly.Div ! 1360: exception Overflow = Core.Assembly.Overflow ! 1361: type int = int ! 1362: val ~ : int -> int = InLine.~ ! 1363: val op * : int * int -> int = InLine.* ! 1364: val op div : int * int -> int = InLine.div ! 1365: fun op mod(a:int,b:int):int = InLine.-(a,InLine.*(InLine.div(a,b),b)) ! 1366: val op + : int * int -> int = InLine.+ ! 1367: val op - : int * int -> int = InLine.- ! 1368: val op > : int * int -> bool = InLine.> ! 1369: val op >= : int * int -> bool = InLine.>= ! 1370: val op < : int * int -> bool = InLine.< ! 1371: val op <= : int * int -> bool = InLine.<= ! 1372: fun min(a,b) = if a<b then a else b ! 1373: fun max(a,b) = if a>b then a else b ! 1374: fun abs a = if a<0 then ~a else a ! 1375: fun makestring i = ! 1376: if i<0 then String.^("~", makestring(~i)) ! 1377: else if i<10 then InLine.cast(InLine.cast "0" + i) ! 1378: else let val j = i div 10 ! 1379: in String.^(makestring j, makestring(i-j*10)) ! 1380: end ! 1381: local val pr = IO.output IO.std_out in ! 1382: fun print i = pr(makestring i) ! 1383: end ! 1384: end (* structure Integer *) ! 1385: ! 1386: structure Real = ! 1387: struct ! 1388: local ! 1389: open Math String ! 1390: val negone = ~1.0 ! 1391: val zero = 0.0 ! 1392: val half = 0.5 ! 1393: val one = 1.0 ! 1394: val two = 2.0 ! 1395: val five = 5.0 ! 1396: val ten = 10.0 ! 1397: in ! 1398: infix 7 * / ! 1399: infix 6 + - ! 1400: infix 4 > < >= <= ! 1401: type real = real ! 1402: exception Real = Core.Assembly.Real ! 1403: exception Float = Real ! 1404: val ~ : real -> real = InLine.fneg ! 1405: val op + : real * real -> real = InLine.fadd ! 1406: val op - : real * real -> real = InLine.fsub ! 1407: val op * : real * real -> real = InLine.fmul ! 1408: val op / : real * real -> real = InLine.fdiv ! 1409: val op > : real * real -> bool = InLine.fgt ! 1410: val op < : real * real -> bool = InLine.flt ! 1411: val op >= : real * real -> bool = InLine.fge ! 1412: val op <= : real * real -> bool = InLine.fle ! 1413: val sin = sin and cos = cos and sqrt = sqrt and arctan = arctan ! 1414: and exp = exp and ln = ln ! 1415: exception Sqrt = Sqrt and Exp = Exp and Ln = Ln ! 1416: exception Floor ! 1417: local ! 1418: fun rtoi (pred,init) = ! 1419: let fun loop n = ! 1420: if pred n ! 1421: then init ! 1422: else let val (i,r) = loop(n * half) ! 1423: val i' = InLine.lshift(i,1) ! 1424: val r' = r+r ! 1425: in if n-r' < one then (i',r') else (InLine.+(i',1),r'+one) ! 1426: end ! 1427: in loop ! 1428: end ! 1429: val pton = rtoi(fn x => x < one, (0,zero)) ! 1430: val nton = rtoi(fn x => x >= negone, (~1,negone)) ! 1431: fun fl n = if n < zero then nton n else pton n ! 1432: fun tr n = #1(pton n) ! 1433: in ! 1434: fun truncate n = if n < zero then InLine.~(tr(~n)) else tr n ! 1435: fun realfloor n = #2(fl n) ! 1436: fun floor n = Core.Assembly.A.floor n handle Integer.Overflow => raise Floor ! 1437: fun ceiling n : int = InLine.~(floor(~n)) ! 1438: end ! 1439: fun abs x = if x < zero then ~x else x ! 1440: local ! 1441: fun loop 0 = zero ! 1442: | loop n = let val x = two * loop(InLine.rshift(n,1)) ! 1443: in case InLine.andb(n,1) of 0 => x | 1 => x + one ! 1444: end ! 1445: in ! 1446: fun real n = if InLine.<(n,0) then ~(loop(InLine.~ n)) else loop n ! 1447: end ! 1448: fun makestring r = ! 1449: let val itoa = Integer.makestring ! 1450: fun scistr(a::b::tl,e) = ! 1451: let fun trail nil = "" ! 1452: | trail (0::tl) = ! 1453: let val rest = trail tl ! 1454: in case rest of "" => "" ! 1455: | _ => "0"^rest ! 1456: end ! 1457: | trail (hd::tl) = itoa hd ^ trail tl ! 1458: val rest = trail tl ! 1459: in itoa a ^ "." ^ itoa b ^ rest ^ "E" ^ itoa e ! 1460: end ! 1461: | scistr _ = "" (* prevents non-exhaustive match *) ! 1462: fun normstr(digits,e) = ! 1463: let fun n(nil,_) = "" ! 1464: | n(hd::nil,0) = itoa hd ^ ".0" ! 1465: | n(hd::tl,0) = itoa hd ^ "." ^ n(tl,~1) ! 1466: | n(0::tl,d) = ! 1467: let val rest = n(tl,InLine.-(d,1)) ! 1468: in case (InLine.<(d,~1),rest) of ! 1469: (true,"") => rest ! 1470: | _ => "0" ^ rest ! 1471: end ! 1472: | n(hd::tl,d) = itoa hd ^ n(tl,InLine.-(d,1)) ! 1473: fun header n = ! 1474: let fun zeros 1 = "" ! 1475: | zeros n = "0" ^ zeros(InLine.-(n,1)) ! 1476: in "0." ^ zeros n ! 1477: end ! 1478: in if InLine.<(e,0) ! 1479: then header(InLine.~ e) ^ n(digits,e) ! 1480: else n(digits,e) ! 1481: end ! 1482: fun mkdigits(f,0) = (nil,if f < five then 0 else 1) ! 1483: | mkdigits(f,i) = ! 1484: let val digit = floor f ! 1485: val new = ten * (f - real digit) ! 1486: val (digits,carry) = mkdigits(new,InLine.-(i,1)) ! 1487: val (digit,carry) = case (digit,carry) of ! 1488: (9,1) => (0,1) ! 1489: | _ => (InLine.+(digit,carry),0) ! 1490: in (digit::digits,carry) ! 1491: end ! 1492: (* should eventually speed this up by using log10 *) ! 1493: fun mkstr(f,e) = ! 1494: if f >= ten then mkstr(f/ten,InLine.+(e,1)) ! 1495: else if f < one then mkstr(f*ten,InLine.-(e,1)) ! 1496: else let val (digits,carry) = mkdigits(f,15) ! 1497: val (digits,e) = case carry of ! 1498: 0 => (digits,e) ! 1499: | _ => (1::digits,InLine.+(e,1)) ! 1500: in if InLine.>(e,~5) andalso InLine.<(e,15) ! 1501: then normstr(digits,e) ! 1502: else scistr(digits,e) ! 1503: end ! 1504: in if r < zero then "~" ^ mkstr(~r,0) ! 1505: else if InLine.feql(r,zero) then "0.0" ! 1506: else mkstr(r,0) ! 1507: end (* fun makestring *) ! 1508: local ! 1509: val pr = IO.output IO.std_out ! 1510: in ! 1511: fun print r = pr(makestring r) ! 1512: end ! 1513: end (* local *) ! 1514: end (* structure Real *) ! 1515: ! 1516: structure System = ! 1517: struct open System ! 1518: structure Unsafe = ! 1519: struct open Unsafe ! 1520: val cast : 'a -> 'b = InLine.cast ! 1521: val boxed : 'a -> bool = InLine.boxed ! 1522: val ordof : string * int -> int = InLine.ordof ! 1523: val slength : string -> int = InLine.slength ! 1524: val store : string * int * int -> unit = InLine.store ! 1525: val subscript : 'a array * int -> 'a = InLine.subscript ! 1526: val update : 'a array * int * 'a -> unit = InLine.update ! 1527: val delay : int * 'a -> 'a = InLine.delay ! 1528: val force : 'a -> 'a = InLine.force ! 1529: end ! 1530: end ! 1531: ! 1532: open Array Ref String IO Bool List Integer Real General ! 1533: ! 1534: val _ = IO.output IO.std_out "Initial done\n" ! 1535: ! 1536: end (* structure Initial *)
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.