Number: 1401 Title: Posix.Process.waitpid_nh is buggy. Keywords: waitpid_nj Submitter: Stephen Weeks Date: 6/18/98 Version: 110.0.3 System: x86-linux Severity: medium Problem: The program below (Code: section) causes the error: uncaught exception SysErr: unknown child status I believe the program should terminate. The call to waitpid_nh is raising the exception, but it should return NONE. Code: open Posix.Process val _ = case fork() of NONE => (sleep(Time.fromSeconds 5); exit 0w0) | SOME pid => (waitpid_nh(W_CHILD pid, []); ()) Transcript: Comments: Fix: The problem is in runtime/c-libs/posix-process/waitpid.c. The status buffer should not be checked if WNOHANG was used and the result pid was 0. Test: bug1401.1.sml Owner: jhr Status: open ---------------------------------------------------------------------- Number: 1402 Title: Word.fmt incorrectly uses lowercase letters for hex digits. Keywords: Word.fmt Submitter: Stephen Weeks Date: 6/18/98 Version: 110.0.3 System: x86-linux Severity: Problem: The code: Word.fmt StringCvt.HEX 0wxABCDEF returns: "abcdef" According to the basis library specification http://cm.bell-labs.com/cm/cs/what/smlnj/doc/basis/pages/word.html#SIG:WORD.fmt:VAL, the hexadecimal digits 10-15 are represented as [A-F]. Hence, the correct result is "ABCDEF". Comments: Fix: Test: bug1402.1.sml Owner: jhr Status: open ---------------------------------------------------------------------- Number: 1403 Title: Possible bug is Posix.FileSys.pathconf Keywords: pathconf Submitter: Stephen Weeks Date: 6/21/98 Version: 110.0.3 System: x86-linux Severity: Problem: I am confused by the fact that pathconf returns SOME 0w0 instead of NONE when a property is false. This does not appear to agree with the basis library specification: http://cm.bell-labs.com/cm/cs/what/smlnj/doc/basis/pages/posix-file-sys.html#SIG:POSIX_FILE_SYS.pathconf:VAL For example, on my machine, the following code: Posix.FileSys.pathconf("/bin/ls", "VDISABLE"); returns the following: val it = SOME 0wx0 : Word32.word option I believe that it should return NONE. Comments: Fix: The C code for mkValue in src/runtime/c-libs/posix-filesys/pathconf.c has the following test: if (val >= 0) { Perhaps this should be: if (val > 0) { Test: tests.posix/bug1403.1.sml Owner: jhr Status: open ---------------------------------------------------------------------- Number: 1404 Title: Parser combinator implements bind incorrectly Keywords: SML/NJ library, parser combinators Submitter: Andrew Kennedy Andrew.Kennedy@persimmon.co.uk Date: 06/23/98 Version: 110 System: Any/All Any Unix Subsystem: SML/NJ Library Severity: minor Problem: ParserComb.bind has wrong implementation -- it doesn't eat its input if the parse succeeds. Comments: Obviously the parser combinators haven't been used. Please test them! Fix: Replace p2' t1 getc strm by p2' t1 getc strm1 Test: ? Owner: jhr, erg Status: fixed in 110.8 [jhr, 8/5/98] ---------------------------------------------------------------------- Number: 1405 Title: Posix.TTY discrepancy with Basis Library spec Keywords: Submitter: Stephen Weeks Date: 6/24/98 Version: 110.0.3 System: x86-linux Severity: Problem: According to the Basis Library spec http://cm.bell-labs.com/cm/cs/what/smlnj/doc/basis/pages/posix-tty.html, the following functions should be defined in Posix.TTY.TC getattr setattr sendbreak drain flush flow However, in SML/NJ, they are defined in Posix.TTY Comments: Fix: Test: ? Owner: jhr Status: open ---------------------------------------------------------------------- Number: 1406 Title: STRING does not agree with Basis Library spec Keywords: STRING Submitter: Stephen Weeks Date: 6/25/98 Version: 110.0.3 System: x86-linux Severity: Problem: The Basis Library spec says that the STRING signature should contain a structure specification: structure Char : CHAR The SML/NJ implementation omits this. Comments: [jhr, 6/25/97] This is still an open issue in the design of the basis (including type defs vs substructures). Until this is resolved, we are holding off changes to the SML/NJ signatures. Fix: Test: ? Owner: jhr Status: open ---------------------------------------------------------------------- Number: 1407 Title: ARRAY does not agree with Basis Library spec Keywords: ARRAY Submitter: Stephen Weeks Date: 6/25/98 Version: 110.0.3 System: x86-linux Severity: major Problem: As part of the ARRAY signature, SML/NJ has the value specification: val array0 : 'a array The Basis Library spec does not include this. Comments: Fix: Test: bug1407.1.sml Owner: jhr Status: fixed in 110.0.6 ---------------------------------------------------------------------- Number: 1408 Title: OrdSet.app order doesn't agree with comment Keywords: Submitter: George Russell george@persimmon.com Date: 07/07/98 Version: 110.6 System: Alpha Digital Unix 4.0B Subsystem: Other Severity: cosmetic Problem: IntBinarySet.app appears to apply the function to the elements of the set in INCREASING order. This is what I want, but the relevant bit of ord-set-sig.sml says > val app : (item -> unit) -> set -> unit > (* Apply a function to the entries of the set > * in decreasing order *) Code: IntBinarySet.app (print o Int.toString) (IntBinarySet.addList(IntBinarySet.empty,[1,2,3,4])); Transcript: Standard ML of New Jersey v110.6 [FLINT v1.41], May 21, 1998 [CM; autoload enabled] - IntBinarySet.app(print o Int.toString)(IntBinarySet.addList(IntBinarySet.empty,[1,2,3,4])); [Autoloading...] [recovering /rnd/tools/sml110.6/src/smlnj-lib/Util/CM/alpha32-unix/lib-base-sig.sml.bin... done] [recovering /rnd/tools/sml110.6/src/smlnj-lib/Util/CM/alpha32-unix/lib-base.sml.bin... done] [recovering /rnd/tools/sml110.6/src/smlnj-lib/Util/CM/alpha32-unix/ord-key-sig.sml.bin... done] [recovering /rnd/tools/sml110.6/src/smlnj-lib/Util/CM/alpha32-unix/ord-set-sig.sml.bin... done] [recovering /rnd/tools/sml110.6/src/smlnj-lib/Util/CM/alpha32-unix/int-binary-set.sml.bin...GC #0.0.0.0.1.3: (8 ms) done] [Autoloading done.] 1234val it = () : unit Comments: Fix: Test: bug1408.1.sml Owner: jhr, erg Status: open ---------------------------------------------------------------------- Number: 1409 Title: Swaps reals in a structure or tuple Keywords: reals modules tuples Submitter: Elsa L. Gunter elsa@research.bell-labs.com Date: 07/13/98 Version: 110.7 System: x86 Linux 2.0 and after Subsystem: SML compiler Severity: critical Problem: If you create a functor that creates at least 7 real values, and you apply the functor to get a structure, and you rebind those values, two of the values will get swapped (see code). Additional information: You seem to need at leat 7 real values for this problem to occur. It is also important that they first be generated inside a functor. It is seems necesary that the rebinding is taking place in a function that has at least two cases to it, and that the argument to the function is itself generated by a function application. In the code, the tuple at the end paira calculated values with what they should be. Code: functor T () = struct val g = 1.0 val f = 2.0 val m = 3.0 val p = 4.0 val q = 5.0 val u = 6.0 val h = 7.0 end; structure E = struct datatype t = A | B fun b _ = B val s = b() structure C = T () val {g,f,m,h,p,q,u} = case s of A => {g = C.g, f = C.f, m = C.m, h = C.h, p = C.p, q = C.q, u = C.u} | _ => {g = C.g, f = C.f, m = C.m, h = C.h, p = C.p, q = C.q, u = C.u} end; val test = ((E.g , 1.0),(E.f , 2.0),(E.m , 3.0),(E.p ,4.0),(E.q , 5.0),(E.u , 6.0), (E.h , 7.0 )) Transcript: tiree% /home/sml/Versions/110.7/bin/sml Standard ML of New Jersey v110.7 [FLINT v1.41], June 2, 1998 val use = fn : string -> unit - use "pay.sml"; [opening pay.sml] functor T : structure E : sig structure C : datatype t = A | B val b : 'a -> t val f : real val g : real val h : real val m : real val p : real val q : real val s : t val u : real end val test = ((1.0,1.0),(2.0,2.0),(3.0,3.0),(4.0,4.0),(6.0,5.0),(5.0,6.0),(7.0,7.0)) : (real * real) * (real * real) * (real * real) * (real * real) * (real * real) * (real * real) * (real * real) val it = () : unit Comments: Fix: [Zhong, 7/13/98] It is caused by the usual misuse of "foldr" (instead of "foldl") in one of my argument spilling algorithms. The fix of Elsa's bug involves changes to the file named "FLINT/cps/cpstrans.sml" (attached) in 110.7. Test: bug1409.1.sml Owner: Zhong Status: fixed in 110.7.2 [Zhong, 7/13/98] ---------------------------------------------------------------------- Number: 1410 Title: no comments in %header Keywords: %header comments Submitter: Elsa L. Gunter elsa@research.bell-labs.com Date: 07/13/98 Version: 110.0.3 System: Any/All Any Unix Subsystem: ML-Yacc Severity: minor Problem: Comments in the argument to %header in the input .grm file to ml-yacc are not correctly parsed. In fact, they cause a false error to be generated. Code: %% %term ident of string | EOF %nonterm START of lambda_term %eop EOF %pos int %header (functor L()(* test *)) %% START : ident (ident) Transcript: tiree% ml-yacc lam.grm lam.grm, line 6: Error: syntax error: deleting PERCENT_HEADER BOGUS_VALUE UNKNOWN ? ml-yacc: uncaught exception Semantic Comments: I originally encountered this bug because it occurs in the file yacc.grm in the code for ml-yacc. I will probably fix it myself eventually if nobody else gets there first. Fix: Test: Owner: Andrew Status: open ---------------------------------------------------------------------- Number: 1411 Title: bad type checking of lazy fun declaration Keywords: lazy, type checking Submitter: Philip Wadler Date: 7/8/98 Version: 110.7.1 System: - Severity: major Problem: An incorrect type is inferred for a lazy fun declaration Code: Compiler.Control.lazysml := true; datatype lazy 'a stream = Nil | Cons of 'a * 'a stream; fun lazy map f Nil = Nil | map f (Cons(x,xs)) = Cons(f x, map f xs); Transcript: datatype 'a stream = Cons of 'a * 'a stream ?.susp | Nil type 'a stream = 'a ?.stream ?.susp stdIn:10.3-11.47 Warning: match nonexhaustive stdIn:10.3-11.47 Warning: match nonexhaustive (f,$ Nil) => ... val map = fn : 'a -> 'b ?.stream ?.susp -> 'c ?.stream ?.susp Comments: Fix: In elaborate/elabcore.sml, only the first clause of the map_ function was being processed, because a recursive function wasn't recursing on the rest of the clauses. Test: tests.lazy/bug1411.1.sml Owner: dbm Status: fixed in 110.7.2 ---------------------------------------------------------------------- Number: 1412 Title: lazy datatype spec expands to duplicate type specs Keywords: lazy, datatype specs, signatures Submitter: Philip Wadler Date: 7/9/98 Version: 110.7.1 System: - Severity: major Problem: Because the strict and lazy type names generated by a lazy datatype specifications are the same, signature elaboration complains about duplicate specifications. Code: signature STREAM = sig datatype lazy stream = Nil | Cons of string * stream end; structure Stream : STREAM = struct datatype lazy stream = Nil | Cons of string * stream end; Transcript: - use "bug1412.1.sml"; [opening bug1412.1.sml] GC #0.0.0.0.1.6: (3 ms) bug1412.1.sml:5.3-7.31 Error: duplicate specifications for type constructor stream in signature Comments: (Andrew being too clever!) Fix: make the internal (strict) datatype name distinct from the external suspended version (e.g. stream! and stream, respectively), as in Wadler's original expansion. This affects compiler/Semant/elaborate/elabtype.sml in the function elabDATATYPEdec. Test: tests.lazy/bug1412.1.sml Owner: dbm Status: fixed in 110.7.2 [dbm, 7/22/98] ---------------------------------------------------------------------- Number: 1413 Title: can't read from instream from process created by Unix.execute Keywords: Unix.exectute, TextIO, IO, processes Submitter: Elsa Gunter Date: 7/20/97 Version: 110.0.3, 110.7 System: mipseb-irix6.2, sparc-solaris2.5, x86-linux Severity: major Problem: A process is created using Unix.execute, and output is sent to that process, flushed, and the output stream is closed. When input from the process is read it contains (part of) a "Bad file number" error message. Code: val execute = Unix.streamsOf o Unix.execute; val (instrm,outstrm) = execute("cat",[]); TextIO.output(outstrm,"abcd"); TextIO.flushOut outstrm; TextIO.closeOut outstrm; val s = TextIO.inputAll instrm; Transcript: - val execute = Unix.streamsOf o Unix.execute; val execute = fn : string * string list -> TextIO.instream * TextIO.outstream - val (instrm,outstrm) = execute("cat",[]); val instrm = - : TextIO.instream val outstrm = - : TextIO.outstream - TextIO.output(outstrm,"abcd"); val it = () : unit - TextIO.flushOut outstrm; val it = () : unit - TextIO.closeOut outstrm; val it = () : unit - val s = TextIO.inputAll instrm; val s = "\nuncaught exception SysErr: Bad file number [badf]\n raised at: Date: 7/21/98 Version: 110.7 (not 110.0.3?) System: - Severity: major Problem: Instantiating a signature containing a sharing constraint causes "Compiler bug: Instantiate: unexpected DATATYPE 354" Code: signature SIG1 = sig type t type u datatype c = C of u and d = D of t * c (* needed! *) end; signature SIG2 = sig type s = int (* <------ that is the culprit I think *) end; signature SIG3 = sig structure A : SIG1 structure B : SIG2 sharing type B.s = A.c (* not valid *) end; Transcript: Standard ML of New Jersey v110.8 [FLINT v1.41], August 5, 1998 - use "test/bugs/bug1414.1.sml"; [opening test/bugs/bug1414.1.sml] signature SIG1 = sig type t type u datatype c = C of u datatype d = D of t * c end signature SIG2 = sig type s = int end Error: Compiler bug: Instantiate: unexpected DATATYPE 354 Comments: [dbm] The sharing should be rejected, because int can't share with a datatype, but a sensible error message should be generated instead of a compiler bug. It may be that 110.0.3 accepts this code without an error because instantiation is not turned on for signature declarations. [Michael Siff, 7/21/98] But actually, my original code (not as simple) was like: signature SIG2 sig structure A : ORD_KEY type s = A.ord_key end and this too resulted in bug 1414. I have since corrected it to be: signature SIG2 sig structure A : ORD_KEY type s sharing type s = A.ord_key end Fix: Test: bug1414.1.sml, bug1414.2.sml Owner: dbm, Zhong Status: fixed in 110.9 (dbm) ---------------------------------------------------------------------- Number: 1415 Title: Date.fmt raises Date on large strings Keywords: Date.fmt Submitter: Stephen Weeks Date: 8/6/98 Version: 110.7 System: x86-linux Severity: Problem: Date.fmt raises Date when you pass it a format string of length 512 or greater, as demonstrated by the following program. Code: Date.fmt (implode(List.tabulate(512, fn _ => #" "))) (Date.fromTimeLocal(Time.now())); Transcript: uncaught exception Date raised at: boot/date.sml:60.41-60.45 Comments: Fix: runtime/c-libs/smlnj-date/strftime.c should allocate a larger buffer when the call to strftime returns 0. [jhr] Upon further examination, I think that this should be fixed in SML. We can break the format string apart and feed it to strftime a piece at a time. Once we have all of the results, then we can concatenate the final result. This avoids the potential problem of stressing the C memory allocator in pathalogical cases. [Weeks, 8/6/98] I agree that this works, but you'll have to be pretty conservative on the chunk size, or make a pass over the format string to get an upper bound on the size of the result string. [jhr, 8/6/98] We need to make a pass over the format string anyway to check for illegal format options (we cannot rely on strftime to do this). This is something that our implementation does not do yet, but it should. Test: bug1415.1.sml Owner: jhr Status: open ---------------------------------------------------------------------- Number: 1416 Title: Date.fmt produces incorrect results on %j, %U, %W, and % Keywords: Date.fmt Submitter: Stephen Weeks Date: 8/6/98 Version: 110.7 System: x86-linux Severity: Problem: Date.fmt produces incorrect results for format directives that depend on tm_yday, i.e. %j, %U, and %W. It also does not follow the spec for format directives that are undefined, e.g. %z. Code: Date.fmt("%j %U %W %z") (Date.fromTimeLocal(Time.now())) Transcript: val it = "001 00 00 " : string Comments: Fix: In PervEnv/Basis/date.sml toTM should return the appropriate value for tm_yday, not 0. Test: bug1416.1.sml Owner: jhr Status: open ---------------------------------------------------------------------- Number: 1417 Title: problems with datatype replication in functors Keywords: modules, datatype replication Submitter: Chris Paris Date: 8/14/98 Version: 110 System: sparc-solaris2.5 (untested on others) Severity: life threatening! Problem: Datatype replication involving mutually recursive datatypes sometimes fails. Code: (* bug1417.1.sml *) signature DB = sig type foo = int datatype partition_classes = STATIC_CLASSES of foo and alloc_class = ALLOC_CLASS of unit end; functor Evolve(Db : DB) = struct datatype partition_classes = datatype Db.partition_classes end; (* bug1417.2.sml *) signature DB = sig datatype transaction = TRANSACTION of lockinfo and lockinfo = READLOCK of unit end functor Evolve(Db : DB) : DB = struct datatype lockinfo = datatype Db.lockinfo datatype transaction = datatype Db.transaction end; Another example from Leif Kornstaedt (7/5/99): (* bug1417.3.sml *) signature S = sig type t datatype u = C1 and v = C2 of t end functor F(type t) :> S where type t = t = struct type t = t datatype u = C1 and v = C2 of t end structure M1 = F(type t = int) structure M2 = struct datatype v = datatype M1.v end Transcript: Standard ML of New Jersey, Version 110, December 9, 1997 [CM; autoload enabled] - use "bug1417.1.sml"; [opening bug1417.1.sml] Error: Compiler bug: TypesUtil: expandTyc:PATHtyc - use "bug1417.2.sml"; [opening bug1417.2.sml] bug1417.2.sml:7.13-11.8 Error: value type in structure doesn't match signature spec name: TRANSACTION spec: Db.lockinfo -> Db.transaction actual: ?.lockinfo -> Db.transaction Comments: Works in 110.7 and 110.8. However, it is not practical for me to port from 110 to the current bleeding edge. Fix: Test: bug1417.1.sml, bug1417.2.sml Owner: dbm, Zhong Status: fixed in 110.8, open in 110.0.4 ---------------------------------------------------------------------- Number: 1418 Title: CM.set_path is a constant function Keywords: CM, CMPATH, CM.set_path Submitter: Elsa Gunter Date: 8/13/98 Version: 110.0.8 (110.0.3?) System: - Severity: major Problem: CM.set_path always returns nil, even after a path has been set. Transcript: - CM.set_path NONE; val it = [] : string list - CM.set_path (SOME ["/home/sml/Versions/110.8/lib"]); val it = [] : string list - CM.set_path NONE; val it = [] : string list Comments: Fix: (Matthias verify?) In cm/cm.sml change the definition of set_path to: fun set_path arg = (if isSome arg then EntityDesc.clear () else (); map AbsPath.elab (CmConfig.path (Option.map (List.map AbsPath.rigidcur) arg))) Test: tests.cm/bug1418.1.sml Owner: Blume Status: fixed in 110.9 (Blume) ---------------------------------------------------------------------- Number: 1419 Title: incorrect printing of signature containing "where type" Keywords: signatures, where type, printing Submitter: Dave MacQueen Date: 8/17/98 Version: 110.0.3, 110.8 System: - Severity: minor Problem: When a signature including a where type specification is printed it can appear as though free variable capture has occurred, even though it hasn't. Code: signature S = sig type s type t end; signature S1 = sig type s structure A : S where type t = s end; Transcript: - signature S = sig type s type t end; signature S = sig type s type t end - signature S1 = = sig = type s = structure A : S where type t = s = end; signature S1 = sig type s structure A : sig type s type t = s (* this refers to the outer s! *) end end Comments: This is a result of the way where types are elaborated. The type definition is moved inward to the site of the type specification that it applies to, but after the rhs has been elaborated, so there is no danger of free variable capture. But when printed, the transformed signature looks like free variable capture has happened. Fix: Test: bug1419.1.sml Owner: dbm Status: open ---------------------------------------------------------------------- Number: 1420 Title: improper printing of "multiple defs at tycon spec" warning message Keywords: error messages, printing Submitter: Dave MacQueen Date: 8/17/98 Version: 110.8 System: - Severity: medium Problem: An "" is printed for the path of a tycon spec in the "multiple defs at tycon spec" warning message. Code: Transcript: - use "test/bugs/bug1386.1.sml"; [opening test/bugs/bug1386.1.sml] signature CAT = sig eqtype cat val c : cat end signature L_F = sig eqtype t structure Cat : sig type cat = t val c : cat end val r : t end test/bugs/bug1386.1.sml:17.9-22.4 Warning: multiple defs at tycon spec: (secondary definitions ignored) test/bugs/bug1386.1.sml:21.13-21.27 Error: operator and operand don't agree [tycon mismatch] operator domain: ?.cat * ?.cat operand: ?.cat * ?.t in expression: Cat.c = LF.r Comments: Fix: Test: bug1420.1.sml (derived from bug1386.1.sml) Owner: dbm Status: open ---------------------------------------------------------------------- Number: 1421 Title: incorrect type comparison for val spec in signature match Keywords: signature matching Submitter: Norman Ramsey Date: 8/18/98 Version: 110.0.3, 110.8 System: - Severity: major Problem: The following declarations are rejected, but should not be. Code: signature E = sig type 'a err val OK : 'a -> 'a err val map : ('a -> 'b) -> 'a err -> 'b err end; structure E1 : E = struct type 'a err = 'a fun OK x = x fun map1 f = f val map = map1 (* causes an error ... *) end; Transcript: Standard ML of New Jersey, Version 110.0.3, January 30, 1998 - use "test/bugs/bug1421.1.sml"; [opening test/bugs/bug1421.1.sml] signature E = sig type 'a err val OK : 'a -> 'a err val map : ('a -> 'b) -> 'a err -> 'b err end test/bugs/bug1421.1.sml:9.1-14.4 Error: value type in structure doesn't match signature spec name: map spec: ('a -> 'b) -> 'a ?.E1.err -> 'b ?.E1.err actual: 'a -> 'a Comments: Fix: In typesutil.sml, function equalType, add "IBOUND _" in addition to "VARty _" patterns for fourth and fifth clauses of function eq. Test: bug1421.1.sml Owner: Zhong Status: fixed in 110.9, 110.0.4 [Zhong, 8/18/98] ---------------------------------------------------------------------- Number: 1422 Title: Core dump on Sparc when using lazy features Keywords: lazy, sparc Submitter: Matthias Blume blume@kurims.kyoto-u.ac.jp Date: 08/18/98 Version: 110.8 System: Sparc Solaris SunOS helium 5.6 Generic_105181-04 sun4u sparc SUNW,Ultra-1 Subsystem: SML compiler Severity: critical Problem: The following code crashes version 110.8 with a core dump on the Sparc (Solaris on Ultra-1). The same code does NOT crash on x86 (Linux). Could this be related to bug 1389? If so, this would mean that the problem is probably NOT in the code generator since we are using a brand-new one... A problem in the runtime system/GC perhaps? Code: Compiler.Control.lazysml := true; datatype lazy l = Nil | Cons of int * l; fun fst _ Nil = [] | fst 0 _ = [] | fst n (Cons (x, l)) = x :: fst (n - 1) l; val rec lazy ones = Cons (1, ones); fst 10 ones; Transcript: Standard ML of New Jersey v110.8 [FLINT v1.41], August 5, 1998 - Compiler.Control.lazysml := true; val it = () : unit - datatype lazy l = Nil | Cons of int * l; datatype l! = Cons of int * l! ?.susp | Nil type l = l! ?.susp - fun fst _ Nil = [] = | fst 0 _ = [] = | fst n (Cons (x, l)) = x :: fst (n - 1) l; val fst = fn : int -> l -> int list - val rec lazy ones = Cons (1, ones); GC #0.0.0.0.1.7: (10 ms) val ones = $$ : l! ?.susp - fst 10 ones; Bus error Comments: The same code runs fine on the X86 (Pentium notebook running Linux): [blume@hana blume]$ ML/8/bin/sml Standard ML of New Jersey v110.8 [FLINT v1.41], August 5, 1998 val use = fn : string -> unit - Compiler.Control.lazysml := true; val it = () : unit - datatype lazy l = Nil | Cons of int * l; datatype l! = Cons of int * l! ?.susp | Nil type l = l! ?.susp - fun fst _ Nil = [] = | fst 0 _ = [] = | fst n (Cons (x, l)) = x :: fst (n - 1) l; val fst = fn : int -> l -> int list - val rec lazy ones = Cons (1, ones); GC #0.0.0.0.1.19: (10 ms) val ones = $$ : l! ?.susp - fst 10 ones; val it = [1,1,1,1,1,1,1,1,1,1] : int list [Matthias, 8/28/98] > [Lal] I have not been able to find the bug exhibited by the lazy evaluation > program you sent. It is clear that it is not specific to the sparc but > generic to MLRISC. > > I therefore suspected the implementation of mkspecial, getspecial, and > setspecial -- but they all seem to be correct. Well, maybe they aren't correct after all. I now recall an incident that occured a while ago: CM crashed on me (with a bus error), and I was able to resolve that problem (although it was never explained) by eliminating the use of the built-in "suspension" facility (delay/force). The problem occured on the Alpha, which at that time was one of the few MLRISC-based implementations. Since I assume that the implementation technology for delay/force back then and laziness now is the same, I would really suggest we should look into this again. (Back when the problem occured first, someone more or less dismissed it as unimportant and surely not to be blamed on get/set/mkspecial. I didn't pursue the issue any further because it didn't seem mission-critical at the time.) Fix: [Lal] I have committed a change to CodeGen/main/mlriscGen.sml that fixes bug1422. Test: bug1422.1.sml Owner: Leung, Lal? Status: fixed in 110.8.1 [Lal] ---------------------------------------------------------------------- Number: 1423 Title: 2.0 + 2.0 = nan Keywords: reals Submitter: George Russell george@persimmon.com Date: 08/10/98 Version: 110.8 System: Sparc Solaris uname -a returns SunOS rosalind 5.5.1 Generic_103640-18 sun4m sparc SUNW,... Subsystem: SML compiler Severity: critical Problem: Floating point doesn't work! Code: 2.0 + 2.0; Transcript: Standard ML of New Jersey v110.8 [FLINT v1.41], August 5, 1998 val use = fn : string -> unit - 2.0 + 2.0; val it = nan : real Comments: [Alan] Unfortunately, we are unable to reproduce on this end. [George] That's odd. Are you sure you've tried it on Sparc/Solaris? I was wondering whether this new ML-RISC was to blame. [Alan] Yes, it's odd. I've tried to repro it on various sparc/solaris/sun-os combinations with no luck: SunOS valis 5.6 Generic_105181-06 sun4m sparc SUNW,SPARCstation-5 SunOS optlab2 5.5.1 Generic_103640-08 sun4u sparc SUNW,Ultra-1 SunOS merv 4.1.4 2 sun4m SunOS vex 5.5.1 Generic_103640-18 sun4u sparc SUNW,Ultra-2 The new MLRISC is likely to be the culprit. [Alan] Could you also check to see if Real.==(2.0+2.0, 4.0) returns true? [George] It returns false [Alan] That's very strange. Could you send me the dumps for the following? val a = 2.0 val b = 2.0 + 2.0 val c = Real.toManExp a val d = Real.toManExp b val e = Real.toManExp Real.posInf val f = Real.==(1.0/0.0,Real.posInf) val g = Real.==(2.0+2.0,Real.posInf) and Compiler.Control.CG.printFlowgraph := Compiler.Control.CG.AFTER_RA; 2.0 + 2.0; [Lal] Only occurs on older sparcs. Fix: Test: bug1423.1.sml Owner: Alan Leung Status: fixed in 110.8.1 [Leung, Lal] ---------------------------------------------------------------------- Number: 1424 Title: inadaquate signature matching error message Keywords: Submitter: Date: Version: System: Severity: Problem: Bad signature matching error message. Does not specify which type names did not match. Transcript: ../MLRISC/X86/X86RegAlloc.sml:1.9-80.4 Error: type name does not match definitional specification ../MLRISC/X86/X86RegAlloc.sml:1.9-80.4 Error: type name does not match definitional specification Comments: Fix: Test: ? Owner: dbm Status: open ---------------------------------------------------------------------- Number: 1425 Title: Compiler bug: Literals: unexpected CPS header in litsplit Keywords: code generation, floating point Submitter: John Reppy Date: 5/21/98 Version: 110.5.1 System: ? Severity: major Problem: real division causes compiler bug Code: Transcript: - 1.1-1.0; val it = 0.1 : real - it/2.0; Error: Compiler bug: Literals: unexpected CPS header in litsplit Comments: Fix: Test: bug1425.1.sml Owner: Zhong Status: fixed in 110.6 ---------------------------------------------------------------------- Number: 1426 Title: smlnj-c interface function, second call core dumps Keywords: smlnj-c, foreign function call Submitter: "Karsten Lueth" Date: 7/28/98 Version: 110.0.3 System: sparc/solaris Severity: major Problem: I have some problems with C interface of SML.110. When I try to call a ML function from C, it will only work at the first call. When call the same function for a second time, it will crash with a segmentaton fault. Code: The C function: void x(int (*f)()) { int i; i = f(); i = f(); } The ML registration: val x = registerCFn("x", [CfunctionT([],CintT)], CvoidT); Transcript: Comments: Fix: Riccardo fixed the bug which had to do with gc. Test: - Owner: Riccardo, jhr Status: fixed in 110.8.1 [Riccardo] ---------------------------------------------------------------------- Number: 1427 Title: End-of-file marks in Stream IO Keywords: IO Submitter: Andrew Appel Date: 08/17/98 Version: 110.8 System: Any/All Any Unix Subsystem: SML basis library Severity: minor Problem: When buffered input is done from a stream device (pipe, tty, socket), there can be multiple end-of-file marks (i.e., zero-length inputs). This is only partially reflected in functional stream input. The program below demonstrates, when the following sequence is typed into the interactive standard input: "abcdef\n^D^Dabcde\n" The sequence of inputs should be, "abcdef\n", "", "", "abcde\n", and indeed the first time through this is the case. But the second time the same functional input stream is read, the sequence is "abcdef\n", "abcde\n"; the empty strings are lost. This violates the rule that for any TextIO.StreamIO.instream f, input(f) = input(f) Code: structure TS = TextIO.StreamIO fun test f = let val f0 = TextIO.getInstream f fun g(i,0) = () | g(i,k) = let val (s,i') = TS.input i in print (Int.toString (size s) ^ "\n"); g(i',k-1) end in g(f0,4); print "***\n"; g(f0,4) end Transcript: 7 0 0 6 *** 7 6 Comments: Fix this in bin-io-fn.sml and text-io-fn.sml by having an explicit end-of-file mark in the sequence of buffers. Fix: Test: Owner: jhr? Status: fixed in 110.9.1 ---------------------------------------------------------------------- Number: 1428 Title: CM docs out of date Keywords: Tools.stdShellProcessor Submitter: Norman Ramsey Date: 08/18/98 Version: 110.8 System: Any/All Any Unix Subsystem: Compilation manager (CM) Severity: minor Problem: Tools.stdShellProcessor appears to have a new type which is not reflected in the example on page 23 of the manual: lex+source.nw:9.2-10.69 Error: operator and operand don't agree [tycon mismatch] operator domain: {mkCommand:unit -> string, tool:string} operand: {command:string, tool:string} in expression: Tools.stdShellProcessor {command=command,tool="ML-Lex+"} Code: functor LexSourceFun (structure Tools: CMTOOLS val command: string) = struct local val runlex = Tools.stdShellProcessor { command = command, tool = "ML-Lex+" } fun rule source = let val smlfile = source ^ ".sml" in [(smlfile, SOME "sml")] end val validator = Tools.stdTStampValidator val processor = runlex (* install MlLex class *) open Tools val class = "mllex+" fun sfx s = addClassifier (stdSfxClassifier { sfx = s, class = class }) in val _ = addToolClass { class = class, rule = dontcare rule, validator = validator, processor = processor } val _ = sfx "lex+" val _ = sfx "l+" end end Transcript: [opening lex+source.sml] lex+source.nw:9.2-10.69 Error: operator and operand don't agree [tycon mismatch] operator domain: {mkCommand:unit -> string, tool:string} operand: {command:string, tool:string} in expression: Tools.stdShellProcessor {command=command,tool="ML-Lex+"} Comments: Fix: update the documentation Test: Owner: Blume Status: fixed in 110.8.2 (Blume) ---------------------------------------------------------------------- Number: 1429 Title: two problems with StreamIO.setPosOut Keywords: I/O, StreamIO, setPosOut Submitter: Andrew Appel Date: 8/19/98 Version: 110.8 System: - Severity: medium Problem: In reading text-io-fn.sml (StreamIO.setPosOut) I noticed two minor bugs: 1. setPosOut should flush the buffer before changing position 2. setPosOut raises an exception whose string refers to "getPosOut" Comments: Fix: Test: Owner: jhr Status: open ---------------------------------------------------------------------- Number: 1430 Title: heap2exec broken Keywords: heap2exec, executables Submitter: Carlos Puchol Date: 8/20/98 Version: System: Severity: Problem: it seems like heap2exec is not bundling things right. Transcript: $ /usr/local/sml/110/bin/sml +@SMLload=tl2strl.heap.sparc-solaris Usage: tl2strl [-v] [-cr] [-ch] [-h] $ /usr/local/sml/110/bin/heap2exec +/usr/local/sml/110/runtime-standalone/run.sparc-solaris +tl2strl.heap.sparc-solaris tl2strl bundling /usr/local/sml/110/runtime-standalone/run.sparc-solaris bundling tl2strl.heap.sparc-solaris setting heap offset to 167556. done. $ ./tl2strl ./tl2strl: Fatal error -- unable to open heap image "sml-image" Comments: Fix: Test: Owner: Lorenz Status: open ---------------------------------------------------------------------- Number: 1431 Title: yypos in ml-lex is off by one (or two) Keywords: ml-lex Submitter: John Reppy Submitter: George Russell Date: 08/22/98, 9/8/98 Version: 110.0.3 System: Any/All Any Unix Subsystem: ML-Lex Severity: major Problem: The first character in the input stream is being assigned position 2. It probably should get the value 0, since this would correspond with standard indexing conventions for ML, but a value of 1 would also be okay --- 2 seems like a bug. Code: (ML-Lex file test.lex follows) type lexresult=int val error=TextIO.print fun eof _ = ~1 %% %% . => (print("yypos="^Int.toString yypos);Char.ord(String.sub(yytext,0))); Transcript: Standard ML of New Jersey v110.8 [FLINT v1.41], August 5, 1998 val use = fn : string -> unit - use "test.lex.sml"; [opening test.lex.sml] GC #0.0.0.0.1.7: (14 ms) GC #0.0.0.0.2.27: (21 ms) GC #0.0.0.1.3.46: (34 ms) structure Mlex : sig structure Internal : structure UserDeclarations : exception LexError val makeLexer : (int -> string) -> unit -> Internal.result end val it = () : unit - Mlex.makeLexer(fn i=>TextIO.inputN(TextIO.stdIn,i))(); a yypos=2val it = 97 : Mlex.Internal.result Comments: [jhr] This is an annoying bug (I spent half a day discovering it just a couple of weeks ago). Andrew Appel claims that it has been known for some time, but there was a concern that if it was fixed, then the fix might break people's code that depended on the incorrect behavior. Personally, I'd like to see it fixed, but at least we should document it. Fix: Test: - Owner: Andrew? Status: open ---------------------------------------------------------------------- Number: 1432 Title: signature match fails for datatype specs if "where type" is used Keywords: signatures, datatypes, "where" clause Submitter: Matthias Blume Date: 08/31/98 Version: 110.8.1 System: Any/All Any Unix Subsystem: SML compiler Severity: major Problem: Information about a type being a datatype is lost when the type spec was augmented using a "where type" clause. This is true even if left and right side of the equation in the "where" clause are already known to be datatypes. This problem is new in 110.8.1. It did not occur in 110.8. (The problem occurs within the CML sources.) Code: signature S1 = sig datatype dt = DT end; signature S2 = sig structure nestedS1 : S1 end; structure globalS1 = struct datatype dt = DT end; functor F2 ( structure argS : S2 where type nestedS1.dt = globalS1.dt ) = struct structure myS1 : S1 = argS.nestedS1 end; Transcript: - use "t.sml"; [opening t.sml] t.sml:18.5-18.40 Error: type dt must be a datatype Comments: In the source code given above, if you delete the "where type" clause on line 15, then everything elaborates fine. [Matthias (original message)] I tried to locally fix the CML sources to be able to compile them under 110.8.1. But I run into a strange problem. When compiling src/cml/src/IO/text-io-fn.sml I see the following errors: ... [compiling IO/text-io-fn.sml -> IO/CM/sparc-unix/text-io-fn.sml.bin] IO/text-io-fn.sml:880.24-883.31 Error: type reader must be a datatype IO/text-io-fn.sml:880.24-883.31 Error: type writer must be a datatype This message refers to the instantiation of the ChanIO functor. Apparently, somehow the compiler seems to think that the reader/writer types in PIO aren't datatypes. Why is that? If they really aren't, then I can't seem to understand the structure of the sources. But if they are, then why does the compiler think they aren't? Is this somehow related to Dave's fix of bug 1364? Does the fix need another fix? Fix: Added "repl:bool" field to TYCspec argument to indicate when a spec is a datatype replication spec (either directly or indirectly via a "where type" definition that applies to the spec). The repl field is definied in ElabSig (Semant/elaborate/elabsig.sml). The information is used in Instantiate, where the type instances associated with a repl spec are unwrapped (in function fixUpTycEnt). This will make checkTycBinding in SigMatch work properly when matching a datatype spec against a type created by signature instantiation (as in the example above). Test: bug1432.1.sml, ..., bug1432.8.sml Owner: dbm Status: fixed in 110.9 (110.8.2) and 110.0.4 [dbm, 9/14/98] ---------------------------------------------------------------------- Number: 1433 Title: eqtype u=t doesn't force eqtype. Keywords: modules Submitter: George Russell george@persimmon.co.uk Date: 08/28/98 Version: 110.8 System: Alpha Digital Unix 4.0B Subsystem: SML compiler Severity: minor Problem: eqtype t=u seems to be an SML/NJ extension so it is not defined how it should work, but in my opinion this code should typecheck. Code: structure A :> sig type t eqtype u=t val v: u end= struct type t=int type u=int val v=1 end; (A.v=A.v); Transcript: Standard ML of New Jersey v110.8 [FLINT v1.41], August 5, 1998 val use = fn : string -> unit - structure A:>sig type t eqtype u=t val v:u end = = struct type t=int type u=int val v=1 end; structure A : sig type t type u = t val v : u end - (A.v=A.v); stdIn:8.1-8.10 Error: operator and operand don't agree [equality type required] operator domain: ''Z * ''Z operand: A.u * A.u in expression: A.v = A.v Comments: See bug 1152 (which appears to be related but which was fixed). [dbm, 9/10/98] Thanks for the bug report, which is now bug 1433. There is certainly something bogus here, since A.t is abstract (and therefore not an equality type), while A.u is specified to be an equality type and is equal to A.t. Probably there should be an error when the signature constraint is matched in the declaration of A. You are right that the "eqtype u = t" is not supported in the SML '97 Definition, but I believe that one can construct an equivalent situation with "where type": signature S = sig type t structure X : sig eqtype u end where type u = t val v : X.u end; This signature should not elaborate successfully according to rule (64), but it currently does elaborate in SML/NJ 110.0.3 through 110.8. Fix: Partial fix, for direct eqtype definitional specs: Added an error check to elabTYPEspec in elabsig.sml to generate an error message when an eqtype spec includes a definition. This still leaves open the problem of what to do when a definition is applied to an eqtype spec through a where type defn. It is rather difficult to fix the "where type" version. The problem is that when the rhs of the where type def (here "t") is elaborated by elabType within ElabSig, the type constructed contains the relatized (PATHtyc) version of T, and it is not possible to determine the equality property of PATHtycs. Perhaps this could be dealt with by adding an equality property field to PATHtycs. Test: bug1433.1.sml, bug1433.2.sml Owner: dbm Status: open (partially fixed in 110.9) ---------------------------------------------------------------------- Number: 1434 Title: bogus "Error: non-constructor applied to argument in pattern: ::" Keywords: types patterns list infix Submitter: Elsa L. Gunter elsa@research.bell-labs.com Date: 09/01/98 Version: 110.8 System: x86 Linux 2.0.0 Subsystem: SML compiler Severity: minor Problem: When a non-existant structure is opened within another structure, subsequent occurrences of :: in patterns fail to be treated as constructors and raise a bogus "Error: non-constructor applied to argument in pattern: ::" message. Code: structure A = struct open B val (x::y) = [1,2] end; Transcript: coll% sml Standard ML of New Jersey v110.8 [FLINT v1.41], August 5, 1998 val use = fn : string -> unit - use "test.sml"; [opening test.sml] test.sml:3.1-3.7 Error: unbound structure: B test.sml:4.5-4.29 Error: non-constructor applied to argument in pattern: :: - structure A = struct open B val (x::y) = [1,2] end; = = = = stdIn:8.1-8.7 Error: unbound structure: B stdIn:9.5-9.19 Error: non-constructor applied to argument in pattern: :: Comments: Fix: Test: bug1434.1.sml Owner: dbm Status: open ---------------------------------------------------------------------- Number: 1435 Title: ML-Yacc documentation needs to be updated Keywords: ml-yacc, documentation Submitter: John Reppy Date: 8/19/08 Version: 110.0.3 - 110.8 System: - Severity: major Problem: The ML-Yacc documentation ought to be updated to reflect the use of CM (e.g., section 5 currently talks about loading "base.sml"). Comments: Fix: Test: - Owner: Andrew? Status: open ---------------------------------------------------------------------- Number: 1436 Title: representation exception raised by C function Keywords: pretty printing, Representation exception, C interface Submitter: ammons@cs.wisc.edu Date: 9/4/1998 Version: 110.0.3 System: sparc-solaris2.6, x86-linux2.0.30 Severity: major Problem: The pretty printer throws an exception while pretty printing some values massaged from values returned by interfaced C code. Code: C side. Add this line to cfun-list.h: C_CALLS_CFUNC("test", test, void *, (void)) and define test as void* test(void) { return (void*) test; } Create a new runtime. ML side. Register the test function. Unwrap the returned caddr and wrap it back up with a new datatype, as in the following transcript: Transcript: whitelight:objs$ sml @SMLrun=./run.x86-linux Standard ML of New Jersey, Version 110.0.3, January 30, 1998 [CM; autoload enabled] - CM.make'("/usr/local/smlnj-110/install/smlnj-c/sources.cm"); [starting dependency analysis] [scanning /usr/local/smlnj-110/install/smlnj-c/sources.cm] [checking /usr/local/smlnj-110/install/smlnj-c/CM/x86-unix/sources.cm.stable ... not usable] GC #0.0.0.0.1.4: (20 ms) [dependency analysis completed] [recovering /usr/local/smlnj-110/install/smlnj-c/CM/x86-unix/c-calls.sig.sml.bin... done] [recovering /usr/local/smlnj-110/install/smlnj-c/CM/x86-unix/cutil.sig.sml.bin... done] [recovering /usr/local/smlnj-110/install/smlnj-c/CM/x86-unix/cutil.sml.bin... done] [recovering /usr/local/smlnj-110/install/smlnj-c/CM/x86-unix/cc-info.sig.sml.bin... done] [recovering /usr/local/smlnj-110/install/smlnj-c/CM/x86-unix/cc-info.defaults.sml.bin... done] [recovering /usr/local/smlnj-110/install/smlnj-c/CM/x86-unix/cc-info.gcc-x86-linux.sml.bin... done] [recovering /usr/local/smlnj-110/install/smlnj-c/CM/x86-unix/cc-info.gcc-sparc-sunos.sml.bin... done] [recovering /usr/local/smlnj-110/install/smlnj-c/CM/x86-unix/cc-info.cc-mipseb-irix5.sml.bin... done] [recovering /usr/local/smlnj-110/install/smlnj-c/CM/x86-unix/c-calls.sml.bin... done] [introducing new bindings into toplevel environment...] val it = () : unit - structure C = CCalls(structure CCInfo = GCCInfoX86Linux); structure C : C_CALLS - datatype mud = Mud of C.caddr; datatype mud = Mud of ?.C.CAddress.caddr - fun make_mud(C.Caddr a) = Mud a; stdIn:20.1-20.32 Warning: match nonexhaustive Caddr a => ... val make_mud = fn : C.cdata -> mud - val f_test = C.registerAutoFreeCFn("test", [], C.CaddrT); val f_test = fn : C.cdata list -> C.cdata - f_test []; val it = Caddr - : C.cdata - make_mud(f_test []); uncaught exception Representation raised at: boot/Unsafe/object.sml:65.19-65.33 print/ppobj.sml:354.20 print/ppobj.sml:354.20 util/pp.sml:554.6 - Comments: Fix: Test: - Owner: Lorenz?, Zhong? Status: open ---------------------------------------------------------------------- Number: 1437 Title: Unix.signal missing Keywords: Unix, signals Submitter: Stephen Weeks Date: 9/8/98 Version: 110.7 System: x86-linux Severity: Problem: The type signal is missing from the Unix structure. Comments: Fix: Test: - Owner: jhr Status: open ---------------------------------------------------------------------- Number: 1438 Title: Wrong types for TextIO.StreamIO.inputAll and TextIO.StreamIO.mkInstream Keywords: types, IO, TextIO, StreamIO Submitter: Elsa L. Gunter Date: 09/14/98 Version: 110.8 System: Any/All Any Unix Subsystem: SML basis library Severity: minor Problem: The types for inputAll and mkInstream in TextIO.StreamIO are wrong under Unix (but right under Win32). They are TextIO.StreamIO.inputAll : ?.TextIO.instream -> TextIO.StreamIO.vector * ?.TextIO.instream TextIO.StreamIO.mkInstream : TextIO.StreamIO.reader * TextIO.StreamIO.vector option -> ?.TextIO.instream but the Standard Basis says they should be TextIO.StreamIO.inputAll : TextIO.StreamIO.instream -> TextIO.StreamIO.vector TextIO.StreamIO.mkInstream : TextIO.StreamIO.reader * TextIO.StreamIO.vector -> TextIO.Stream.instream That is, inputAll is returning an extra instream, and mkInstream is taking a vector option instead of a vector. Also note that the type ?.TextIO.insteam is being printed in place of TextIO.StreamIO.instream. This is rather confusing at best. Code: val x = (TextIO.StreamIO.inputAll,TextIO.StreamIO.mkInstream); Transcript: Standard ML of New Jersey v110.8 [FLINT v1.41], August 5, 1998 val use = fn : string -> unit - val x = (TextIO.StreamIO.inputAll,TextIO.StreamIO.mkInstream); val x = (fn,fn) : (?.TextIO.instream -> TextIO.StreamIO.vector * ?.TextIO.instream) * (TextIO.StreamIO.reader * TextIO.StreamIO.vector option -> ?.TextIO.instream) Comments: The types seem to be right under Win32, although I think it prints ?.TextIO.instream in place of TextIO.StreamIO.instream there as well. Fix: Test: Owner: jhr, Appel Status: fixed in 110.8.1 [Andrew] ---------------------------------------------------------------------- Number: 1439 Title: OS.FileSys.access raises inappropriate SysErr exception Keywords: exception, file-system Submitter: Elsa L. Gunter elsa@research.bell-labs.com Date: 09/14/98 Version: 110.8 System: Any/All Windows NT 4.0 Subsystem: SML compiler Severity: minor Problem: OS.FileSys.access raises "uncaught exception SysErr: access: cannot get file attributes" when a file doesn't exist under Windows NT, but it returns false under linux. The Standard Basis says: "The function will only raise OS.SysErr for errors unrelated to resolving the the pathname and related permissions, such as being interupted by a signal during the system call." Code: (* Let "toto" be a file that doesn't exist *) val x = OS.FileSys.access ("toto",[]); Transcript: I don't have easy access to WIndows NT at the moment, but the line in quotes in the Description of Problem was cut from a real session. Comments: Fix: Test: Owner: jhr, Appel Status: open ---------------------------------------------------------------------- Number: 1440 Title: CM.set_path has no effect in Win 32 or Irix 6.4 Keywords: CM search path Submitter: Elsa L. Gunter elsa@research.bell-labs.com Date: 09/14/98 Version: 110.8 System: x86 Windows NT 4.0 Subsystem: Compilation manager (CM) Severity: critical Problem: CM.set_path always returns the same list in Win 32 and Irix 6.4. This appears to reflect an unchanging search path for CM under these operating systems. Code: val x = (CM.set_path (SOME ["/usr/local/hol"]); CM.set_path NONE); Transcript: Standard ML of New Jersey v110.8 [FLINT v1.41], August 5, 1998 val use = fn : string -> unit - val x = (CM.set_path (SOME ["/usr/local/hol"]); CM.set_path NONE); val x = [".","/home/sml/Versions/110.8/lib"] : string list Comments: This works in the linux version and the solaris version. [Matthias, 10/9/98] I have no access to a Win32 version, but (as expected) this bug does not seem to exist on the Irix 6.4 version. I suspect that it was a transient problem related to some out-of-date sources. (There is no reason whatsoever why CM.set_path should behave differently on different systems.) See also bug 1418. Fix: Test: tests.cm/bug1418.sml Owner: Blume Status: fixed in 110.8.1 (IRIX, Solaris, Windows?) ---------------------------------------------------------------------- Number: 1441 Title: reading input from stdIn in emacs under Windows Keywords: input, Windows Submitter: Robert Harper Date: 9/14/98 Version: 110.8 System: x86/Windows Severity: minor Problem: If I invoke a function, say, read(), that reads from stdIn, the trailing newline from the invocation "read();" gets read as input. Code: Transcript: Standard ML of New Jersey v110.8 [FLINT v1.41], August 5, 1998 - fun read () = TextIO.input TextIO.stdIn; val read = fn : unit -> TextIO.vector - read (); val it = "\n" : TextIO.vector - (* To get this final prompt I have to hit return *) Comments: This is running under emacs (emacs 20.3.1 on a PC running NT4.0SP3). It appears to work properly from the cmd prompt. Perhaps it's an emacs bug after all. [Lorenz, 9/15/98] The emacs shell mode under NT/W95 (gnu emacs) is known to be buggy in this respect. I reported a number of bugs, similar to those below, to Voelker over a year ago and they apparently still remain open. If the problems appear at the DOS prompt as well, please let me know. Fix: - Test: - Owner: Riccardo, Lorenz Status: not a bug ---------------------------------------------------------------------- Number: 1442 Title: EOF to terminate read terminates top level in emacs under Windows Keywords: input, I/O, Windows Submitter: Robert Harper Date: 9/14/98 Version: 110.8 System: x86/Windows Severity: minor Problem: I invoke a function, say, read(), that reads from stdIn. Then if I send eof to terminate the read, it returns and then also closes the top level for me, exiting sml. Transcript: - fun read () = TextIO.input TextIO.stdIn; val read = fn : unit -> TextIO.vector - read(); abcdval it = "abcd" : TextIO.vector Comments: This is running under emacs (emacs 20.3.1 on a PC running NT4.0SP3). It appears to work properly from the cmd prompt. Perhaps it's an emacs bug after all. [Lorenz, 9/15/98] The emacs shell mode under NT/W95 (gnu emacs) is known to be buggy in this respect. I reported a number of bugs, similar to those below, to Voelker over a year ago and they apparently still remain open. If the problems appear at the DOS prompt as well, please let me know. Fix: - Test: - Owner: Riccardo, Lorenz Status: not a bug ---------------------------------------------------------------------- Number: 1443 Title: Real.toManExp broken -- wrong exponent returned. Keywords: Real64.toManExp (file: real64.sml) Submitter: dew@pgroup.com (David Wohlford) Date: 9/16/1998 Version: 110.0.3 System: any arch/any OS Severity: minor/major Problem: Real.toManExp returns incorrect values for the exponent of floating point numbers. For example, Real.toManExp 7.0 => {exp=3, man=0.875}. The exponent should be 2. Also, Real.toManExp 0.0 returns {exp=~1022, man=0.0}. I believe 1.0 * (2^(e_min-1)) is the standard for representing 0.0. The problem seems to be that there is a spurious addition of 1 to the exponent to work around a previous bug in logb. This doesn't seem to be necessary anymore, and other code in the module with similar exponent-extracting needs doesn't do this anymore (I think -- should check to be sure). [dbm] May be related to bug 1362. Code: Real.toManExp 7.0; Real.toManExp 0.0; Transcript: - Compiler.version; val it = {date="January 30, 1998",system="Standard ML of New Jersey", version_id=[110,0,3]} : {date:string, system:string, version_id:int list} - Real.toManExp 7.0; val it = {exp=3,man=0.875} : {exp:int, man:real} - Real.toManExp 0.0; val it = {exp=~1022,man=0.0} : {exp:int, man:real} - Real.toManExp 1.0; val it = {exp=1,man=0.5} : {exp:int, man:real} Comments: It looks like the mantissa is only correct given this incorrect exponent. With this function as it is, it is hard to write a function that will take a real number and return/write a bit-representation of the number (e.g. for outputting constant initializations to a .s file). [Aleksandar Nanevski [mailto:aleks+@cs.cmu.edu], 7/19/00] Real.toManExp doesn't return the correct values for numbers close to maxFinite: - Real.toManExp Real.maxFinite; val it = {exp=0,man=1.79769313486e308} : {exp:int, man:real} when the exp should be actually 1023, and the man something else. Here's the code that implements this function in the Basis: (* AARGH! Our version of logb gives a value that's one less than the rest of the world's logb functions. We should fix this systematically some time. *) fun toManExp x = case I.+(Assembly.A.logb x, 1) of ~1023 => if x==0.0 then {man=x,exp=0} else let val {man=m,exp=e} = toManExp(x*1048576.0) in {man=m,exp=I.-(e,20)} end | 1024 => {man=x,exp=0} | i => {man=Assembly.A.scalb(x,I.~ i),exp=i} Now, to implement a new version of toManExp, I will not be able to access these Assembly.A functions. So the code will necessarily be tricky and slow. This bug has been pointed out a long time ago actually. I found it in the openbug list for SML-NJ under the numbers 1319, 1362 and 1443. There is also one other thing that worries me -- it involves the fp arithmetic on Pentium. The Pentium has 80 bit long internal registers for floating point operations. This means that after a chain of operations has been performed using values from the registers, the final result will be rounded to 64 bits and stored in memory. However, while this improves the stability of numerical computations, it is not quite by the IEEE standard (or rather, the standard is a bit vague on that issue). What happens is that if your computation has been performed solely in the registers you'll get a different result then if some of the intermediate results has been pushed to memory and then retrieved back into a register. So, logically equivalent expressions, whose equality can be proved in the IEEE standard may give different results, depending on how the register allocation has been performed. Aside, it breaks the extended floats on Pentium, unless special care is taken to do these rounding after every operation (which is slow), or set specific FP unit flags which prevent the additional bits from being used -- which will probably have to be done by installing a C function into the runtime system. I haven't noticed any bad instances of this problem so far, but that's mainly because I didn't run too extensive tests. Anyway, I wanted to make you aware of this problem, since it looks to me that the consequences are beyond just extended floats, and rather influence the correctness of the whole compiler -- it doesn't look very pretty to me to have provably equivalent programs (provable under the `axioms' of the IEEE standard) produce different values on the same machine, let alone on different machines. Again, I'm not sure that SML-NJ actually does this badly; I wouldn't know until I test everything. But, I have a nagging feeling, which grew after I saw SML-NJ basis implementation of the Real.minPos: local (* The x86 uses extended precision (80 bits) internally, therefore * it is necessary to write out the result of r * 0.5 to get * 64 bit precision. *) val mem = InlineT.PolyArray.array(1, minNormalPos) val update = InlineT.PolyArray.update val subscript = InlineT.PolyArray.chkSub fun f () = let val r = subscript(mem, 0) val y = r * 0.5 in update(mem, 0, y); if subscript(mem, 0) == 0.0 then r else f () end in val minPos = f() end Do you perhaps happen to know any details on this already? If yes, it can save me some time in hacking and debugging. [Aleksandar Nanevski [mailto:aleks+@cs.cmu.edu], 7/20/00] As you asked, the file with fixes for the bugs I've noticed in the Real structure is attached. Even though it still uses some of the old functions in the cases when they do behave correctly, it should be easy for the SML-NJ people to plug in the assembly primitives and fix the bugs in the standard basis. (********************************************** ** Real.sml ** sml ** ** Aleksandar Nanevski ** ** Fixes the bug in Real.toManExp. It didn't ** work for numbers with exponents around ** Real.maxFinite. ** ** Implementation of fromManExp and split which ** do not depend on the rounding mode. Important ** since these functions are used in InfInt and ** Rational to approximate numbers to their ** nearest float. Besides, as they were originally, ** they violated the specification given in the ** Standard Basis. ** ** ** TODO: ** - fromManExp should set the overflow and ** underflow flags when appropriate. **********************************************) structure Real : REAL = struct structure I = Int open Real infix == val p512 = Real.fromManExp{man=1.0, exp=512} val q512 = Real.fromManExp{man=1.0, exp=Int.~ 512} fun toManExp x = if x >= 1.0 then (* the exponent is positive, so we can divide by 2^512 with no overflow or underflow *) let val {man=m, exp=k} = Real.toManExp (q512 * x) in {man=m, exp=Int.+(k, 512)} end else if x == 0.0 then {man=0.0, exp=0} else (* the exponent is negative, so we can multiply by 2^512 with no overflow or underflow *) let val {man=m, exp=k} = Real.toManExp (p512 * x) in {man=m, exp=Int.-(k, 512)} end (* original fromManExp depends on the rounding mode when *) (* overflowing or underflowing; this is not specified by *) (* the standard basis, and is not good for some functions *) (* on infinite integers and rationals *) val maxFinHalfPos = 0.5 * maxFinite val maxFinHalfNeg = ~maxFinHalfPos val minPosDouble = 2.0 * minPos val minNegDouble = ~minPosDouble fun fromManExp {man=m, exp=e} = if (m >= 0.5 andalso m <= 1.0 orelse m <= ~0.5 andalso m >= ~1.0) then if I.>(e, 1020) then if m > 0.0 then if I.>(e, 1050) then posInf else let fun f(i, x) = if i=0 then x else if (x > maxFinHalfPos) then posInf else f(I.-(i, 1), x+x) in f(I.-(e, 1020), Real.fromManExp{man=m, exp=1020}) end else if I.>(e, 1050) then negInf else let fun f(i, x) = if i=0 then x else if (x < maxFinHalfNeg) then negInf else f(I.-(i, 1), x+x) in f(I.-(e, 1020), Real.fromManExp{man=m, exp=1020}) end else if I.<(e, I.~ 1020) then if I.<(e, I.~ 1200) then 0.0 else if m > 0.0 then let fun f(i, x) = if i = 0 then x else if (x < minPosDouble) then 0.0 (* with setting the underflow flag *) else f(I.-(i, 1), x*0.5) in f(I.-(1020, e), Real.fromManExp{man=m, exp=I.~ 1020}) end else let fun f(i, x) = if i=0 then x else if (x > minNegDouble) then 0.0 (* with setting the underflow flag *) else f(I.-(i, 1), x*0.5) in f(I.-(1020, e), Real.fromManExp{man=m, exp=I.~ 1020}) end else Real.fromManExp{man=m, exp=e} (* This is the common case! *) else let val {man=m', exp=e'} = toManExp m in fromManExp{man=m', exp=I.+(e', e)} end (* SML-NJ calls this maxInt; I changed it's name into *) (* maxPosInt. It is the smallest float with the property *) (* *) (* Forall x:float. (x >= maxPosInt) => (x:int) *) (* *) (* It is equal to 2^52. *) val maxPosInt = 4503599627370496.0 val maxNegInt = ~ maxPosInt (* split and realMod should be independent of the rounding mode *) fun split x = if x > 0.0 then if x > maxPosInt then {whole=x, frac=0.0} (* how to make a signed zero? *) else (* SML-NJ says this rounds according to the rounding mode. *) (* It seems though it doesn't do the job for exponents *) (* above 53 under other roundings; hence the check above *) (* Besides, a check as above is needed anyway if we want *) (* to return correctly as specified by the Basis, on *) (* inputs x=posInf and x=negInf. SML-NJ had an error *) (* there too, even under the default rounding *) let val w = (x + maxPosInt) - maxPosInt val f = x - w (* this is computed exactly *) in (* check the signs *) if f < 0.0 then {whole=w-1.0, frac=1.0+f} else {whole=w, frac=f} end else if x < maxNegInt then {whole=x, frac=0.0} (* how to make a signed zero? *) else let val w = (x - maxPosInt) + maxPosInt val f = x - w in if f > 0.0 then {whole=w+1.0, frac=f-1.0} else {whole=w, frac=f} end val realMod = #frac o split end Fix: Test: bug1443.1.sml Owner: jhr, Andrew Status: open ---------------------------------------------------------------------- Number: 1444 Title: First Century Blues Keywords: Dates Submitter: George Russell george@persimmon.co.uk Date: 09/17/98 Version: 110.8 System: Alpha Digital Unix 4.0B Subsystem: SML basis library Severity: minor Problem: Date.toString does not conform with the standard. It prints Year 1 as " 0 1" and (perhaps this is more likely to be noticed) the first day of the month as " 1" (not "01" as seems implied by the basis document). Code: Date.date{year=1,month=Date.Jan,day=1,hour=0,minute=0,second=0,offset=NONE}; Date.toString it; Transcript: Date.date{year=1,month=Date.Jan,day=1,hour=0,minute=0,second=0,offset=NONE}; val it = DATE {day=1,hour=0,isDst=NONE,minute=0,month=Jan,offset=NONE,second=0,wday=Mon, yday=0,year=1} : Date.date - Date.toString it; val it = "Mon Jan 1 00:00:00 0 1" : string Comments: Fix: Test: bug1444.1.sml Owner: jhr? Status: open ---------------------------------------------------------------------- Number: 1445 Title: uncaught Unbound in FLINT/trans/transtypes.sml Keywords: FLINT, transtypes, types Submitter: Dave MacQueen Date: 9/21/98 Version: 110.0.3 - 110.8.1 System: - Severity: major Problem: Elaborating a functor decl causes an uncaught exception Unbound (probably EntityEnv.Unbound?). Code: signature S1 = sig type t val x : t (* needed *) end; signature S2 = sig structure T : S1 end; signature S3 = sig type s datatype t = Kt of s (* s needed *) end; (* ok *) functor F1 (structure C : S2 structure D : S2 structure E : S3 sharing D.T = C.T sharing type E.t = C.T.t) = struct end; (* ok *) functor F2 (structure C : S2 structure D : S2 where T = C.T structure E : S3 where type t = C.T.t) = struct end; (* uncaught exception Unbound at FLINT/trans/transtypes.sml:277.33-277.43 *) functor F (structure C : S2 structure D : S2 where T = C.T (* needed *) structure E : S3 sharing type E.t = C.T.t) = (* needed *) struct end; Transcript: Standard ML of New Jersey v110.8 [FLINT v1.41], August 5, 1998 - use "x1.sml"; [opening x1.sml] signature S1 = sig type t val x : t end GC #0.0.0.0.1.2: (10 ms) signature S2 = sig structure T : sig type t val x : t end end signature S3 = sig type s datatype t = Kt of s end functor F1 : functor F2 : uncaught exception Unbound raised at: FLINT/trans/transtypes.sml:277.33-277.43 FLINT/trans/translate.sml:150.39 Comments: In 110.0.3 error message is: uncaught exception Unbound raised at: translate/transmodules.sml:80.33-80.43 translate/translate.sml:129.39 If the parameter signature for F is declared separately, as in signature S4 = sig structure C : S2 structure D : S2 where T = C.T (* needed *) structure E : S3 sharing type E.t = C.T.t end; functor F(X:S4) = struct end; then the elaboration of the S4 declaration succeeds, but the functor declaration fails as before. Fix: In Instantiate/buildStrClass/finalize, eliminate the conditional on eqSig(sign,sign') in the SOME(VARstrDef...) case for defining finalEnt, always returning (GENERATE_ENT false). The bug code illustrates that even when signatures agree, a VARstrDef can introduce external free entVars (in this case for type s in S3), requiring some context entityEnv (see also mkEntEnv later in instantiate.sml). Test: bug1445.1.sml, bug1445.2.sml Owner: Zhong, dbm Status: fixed in 110.9 [dbm, Zhong] ---------------------------------------------------------------------- Number: 1446 Title: "Translate: unexpected tyvar INSTANTIATED in mkPE" in lazy code Keywords: lazy, translate Submitter: Phil Wadler Date: 9/22/98 Version: 110.8.1 System: - Severity: major Problem: Certain lazy declarations cause: Compiler bug: Translate: unexpected tyvar INSTANTIATED in mkPE Code: (* bug1446.1.sml *) infixr 5 >>; datatype lazy series = >> of int * series; fun lazy recip () = (* ok if "lazy" removed on this line *) let val rec lazy rs = 1 >> rs in rs end; ============ (* bug1446.2.sml *) datatype lazy series = >> of int * series; fun lazy tail (x>>xs) = xs; fun lazy plus (f>>fs,g>>gs) = f+g >> plus(fs,gs); let val rec lazy rs = let val lazy rs1 = tail rs in 0 >> 1 >> plus(rs1,rs) end in rs end; Transcript: Standard ML of New Jersey v110.8 [FLINT v1.41], August 5, 1998 - Compiler.Control.lazysml := true; val it = () : unit - use "test/src/lazy/ps2.sml"; [opening test/src/lazy/ps2.sml] infixr 5 >> datatype series! = >> of int * series! ?.susp type series = series! ?.susp Error: Compiler bug: Translate: unexpected tyvar INSTANTIATED in mkPE Comments: Fix: [Zhong] The bug was caused by the fact that we were not generating new copies of the "forceExp" function in the elabDec function in Semantics/elaborate/elabcore.sml. Test: bug1446.1.sml, bug1446.2.sml Owner: dbm, Zhong Status: fixed in 110.9.1 [Zhong, 9/24/98] ---------------------------------------------------------------------- Number: 1447 Title: Real.fmt fails on large real number Keywords: Real, format, conversion, StringCvt Submitter: Dave MacQueen Date: 10/6/98 Version: 110.8.2+ System: sparc/solaris 2.5.1 Severity: medium Problem: Real.fmt adds a spurious .1 when converting round real numbers above 91827364509181.0 to a string. Code: (* bug1447.1.sml *) Real.fmt (StringCvt.FIX(SOME 0)) 91827364509181.0; Real.fmt (StringCvt.FIX(SOME 1)) 91827364509181.0; Real.fmt (StringCvt.FIX(SOME 2)) 91827364509181.0; Real.fmt (StringCvt.FIX(SOME 0)) 91827364509182.0; Real.fmt (StringCvt.FIX(SOME 1)) 91827364509182.0; Real.fmt (StringCvt.FIX(SOME 2)) 91827364509182.0; Real.fmt (StringCvt.FIX(SOME 0)) 91827364509183.0; Real.fmt (StringCvt.FIX(SOME 1)) 91827364509183.0; Real.fmt (StringCvt.FIX(SOME 2)) 91827364509183.0; Transcript: - use "/home/sml/Dev/bugs/tests/bug1447.1.sml"; [opening /home/sml/Dev/bugs/tests/bug1447.1.sml] val it = "91827364509181" : string val it = "91827364509181.0" : string val it = "91827364509181.00" : string val it = "91827364509182" : string val it = "91827364509182.1" : string val it = "91827364509182.10" : string val it = "91827364509183" : string val it = "91827364509183.1" : string val it = "91827364509183.10" : string val it = () : unit Comments: This comes from the basis/real.sml regression test. It causes test 11c to fail. Fix: Test: bug1447.1.sml Owner: jhr? Status: open ---------------------------------------------------------------------- Number: 1448 Title: Real.round does not round to nearest even for ties Keywords: Real, round Submitter: Dave MacQueen Date: 10/6/98 Version: 110.8.2+ System: sparc/solaris 2.5.1 Severity: major Problem: Real.round rounds upward, rather than to the nearest even, in the case of a tie. Code: Real.round 0.5; Real.round 1.5; Real.round 2.5; Real.round (~0.5); Real.round (~1.5); Transcript: - Real.round 0.5; val it = 1 : int - Real.round 1.5; val it = 2 : int - Real.round 2.5; val it = 3 : int - Real.round(~0.5); val it = 0 : int - Real.round(~1.5); val it = ~1 : int Comments: This comes from test 7a in the basis/real.sml regression tests. Fix: Test: bug1448.1.sml Owner: dbm Status: fixed in 110.0.6 [dbm] ---------------------------------------------------------------------- Number: 1449 Title: FFT benchmark gives wrong answers. Keywords: reals Submitter: Andrew Kennedy andrew@persimmon.co.uk Date: 10/07/98 Version: 110.8 System: Any/All Other (describe below) Subsystem: SML compiler Severity: major Problem: The FFT benchmark gives the wrong answers on all architectures that we have tested. Code: structure Main = struct local open Array Math val printr = print o Real.toString val printi = print o Int.toString in val PI = 3.14159265358979323846 val tpi = 2.0 * PI fun fft px py np = let fun find_num_points i m = if i < np then find_num_points (i+i) (m+1) else (i,m) val (n,m) = find_num_points 2 1 in if n <> np then let fun loop i = if i > n then () else ( update(px, i, 0.0); update(py, i, 0.0); loop (i+1)) in loop (np+1); print "Use "; printi n; print " point fft\n" end else (); let fun loop_k k n2 = if k >= m then () else let val n4 = n2 div 4 val e = tpi / (real n2) fun loop_j j a = if j > n4 then () else let val a3 = 3.0 * a val cc1 = cos(a) val ss1 = sin(a) val cc3 = cos(a3) val ss3 = sin(a3) fun loop_is is id = if is >= n then () else let fun loop_i0 i0 = if i0 >= n then () else let val i1 = i0 + n4 val i2 = i1 + n4 val i3 = i2 + n4 val r1 = sub(px, i0) - sub(px, i2) val _ = update(px, i0, sub(px, i0) + sub(px, i2)) val r2 = sub(px, i1) - sub(px, i3) val _ = update(px, i1, sub(px, i1) + sub(px, i3)) val s1 = sub(py, i0) - sub(py, i2) val _ = update(py, i0, sub(py, i0) + sub(py, i2)) val s2 = sub(py, i1) - sub(py, i3) val _ = update(py, i1, sub(py, i1) + sub(py, i3)) val s3 = r1 - s2 val r1 = r1 + s2 val s2 = r2 - s1 val r2 = r2 + s1 val _ = update(px, i2, r1*cc1 - s2*ss1) val _ = update(py, i2, ~s2*cc1 - r1*ss1) val _ = update(px, i3, s3*cc3 + r2*ss3) val _ = update(py, i3, r2*cc3 - s3*ss3) in loop_i0 (i0 + id) end in loop_i0 is; loop_is (2 * id - n2 + j) (4 * id) end in loop_is j (2 * n2); loop_j (j+1) (e * real j) end in loop_j 1 0.0; loop_k (k+1) (n2 div 2) end in loop_k 1 n end; (************************************) (* Last stage, length=2 butterfly *) (************************************) let fun loop_is is id = if is >= n then () else let fun loop_i0 i0 = if i0 > n then () else let val i1 = i0 + 1 val r1 = sub(px, i0) val _ = update(px, i0, r1 + sub(px, i1)) val _ = update(px, i1, r1 - sub(px, i1)) val r1 = sub(py, i0) val _ = update(py, i0, r1 + sub(py, i1)) val _ = update(py, i1, r1 - sub(py, i1)) in loop_i0 (i0 + id) end in loop_i0 is; loop_is (2*id - 1) (4 * id) end in loop_is 1 4 end; (*************************) (* Bit reverse counter *) (*************************) let fun loop_i i j = if i >= n then () else (if i < j then (let val xt = sub(px, j) in update(px, j, sub(px, i)); update(px, i, xt) end; let val xt = sub(py, j) in update(py, j, sub(py, i)); update(py, i, xt) end) else (); let fun loop_k k j = if k < j then loop_k (k div 2) (j-k) else j+k val j' = loop_k (n div 2) j in loop_i (i+1) j' end) in loop_i 1 1 end; n end fun abs x = if x >= 0.0 then x else ~x fun test np = let val _ = (printi np; print "... ") val enp = real np val npm = (np div 2) - 1 val pxr = array (np+2, 0.0) val pxi = array (np+2, 0.0) val t = PI / enp val _ = update(pxr, 1, (enp - 1.0) * 0.5) val _ = update(pxi, 1, 0.0) val n2 = np div 2 val _ = update(pxr, n2+1, ~0.5) val _ = update(pxi, n2+1, 0.0) fun loop_i i = if i > npm then () else let val j = np - i val _ = update(pxr, i+1, ~0.5) val _ = update(pxr, j+1, ~0.5) val z = t * real i val y = ~0.5*(cos(z)/sin(z)) val _ = update(pxi, i+1, y) val _ = update(pxi, j+1, ~y) in loop_i (i+1) end val _ = loop_i 1 (*** val _ = print "\n" fun loop_i i = if i > 15 then () else (print i; print "\t"; print (sub(pxr, i+1)); print "\t"; print (sub(pxi, i+1)); print "\n"; loop_i (i+1)) val _ = loop_i 0 ***) val _ = fft pxr pxi np (*** fun loop_i i = if i > 15 then () else (print i; print "\t"; print (sub(pxr, i+1)); print "\t"; print (sub(pxi, i+1)); print "\n"; loop_i (i+1)) val _ = loop_i 0 ***) fun loop_i i zr zi kr ki = if i >= np then (zr,zi) else let val a = abs(sub(pxr, i+1) - real i) val (zr, kr) = if zr < a then (a, i) else (zr, kr) val a = abs(sub(pxi, i+1)) val (zi, ki) = if zi < a then (a, i) else (zi, ki) in loop_i (i+1) zr zi kr ki end val (zr, zi) = loop_i 0 0.0 0.0 0 0 val zm = if abs zr < abs zi then zi else zr in printr zm; print "\n" end fun loop_np i np = if i > 13 then () else (test np; loop_np (i+1) (np*2)) fun main () = loop_np 1 16 end end Transcript: SML/NJ: 16... 8.881784197e~16 32... 3.5527136788e~15 64... 1.06581410364e~14 128... 2.84217094304e~14 256... 5.68434188608e~14 512... 1.16795462191e~13 1024... 3.41060513165e~13 2048... 7.95807864051e~13 4096... 1.40154554629e~12 8192... 3.63797880709e~12 16384... 7.27595761418e~12 32768... 1.45519152284e~11 65536... 2.91038304567e~11 MLJ (and Moscow ML): 16... 8.88178419700E~16 32... 2.66453525910E~15 64... 1.42108547152E~14 128... 2.93098878501E~14 256... 5.86197757002E~14 512... 1.70530256582E~13 1024... 3.41060513165E~13 2048... 9.09494701773E~13 4096... 1.81898940355E~12 8192... 5.45696821064E~12 16384... 1.09139364213E~11 32768... 2.18278728426E~11 65536... 5.82076609135E~11 Comments: Fix: Test: bug1449.1.sml Owner: Lal? Status: open ---------------------------------------------------------------------- Number: 1450 Title: bugs in Array2.fromList and Array2.row Keywords: Array2 fromList row Submitter: Huh Choong Gil earny@mathx.kaist.ac.kr Date: 10/10/98 Version: 110.0.3 System: Any/All Any Unix Subsystem: SML basis library Severity: major Problem: wrong behavior of Array2.fromList and Array2.row Code: from src/sml-nj/boot/array2.sml fun fromList [] = {data = Assembly.array0, nrows = 0, ncols = 0} ... List.revAppend (revCol, l)) ... end fun row ({data, nrows, ncols}, i) = let ... else mkVec (stop+nrows-1, []) end Transcript: * bug of Array2.fromList - val a = Array2.fromList [[1,2],[3,4],[5,6]]; val a = - : int Array2.array - Array2.app Array2.RowMajor (fn x => print (Int.toString x)) a; 125634val it = () : unit * bug of Array2.row - val b = Array2.tabulate Array2.RowMajor (2,1,fn _ => 1); val b = - : int Array2.array - Array2.nRows b; val it = 2 : int - Array2.row (b,1); uncaught exception subscript out of bounds raised at: boot/array2.sml:114.21-114.26 Comments: Fix: * bug of Array2.fromList The problem is the line List.revAppend (revCol, l)) in fun Array2.fromList of array2.sml which i think should be List.@(l, List.rev revCol)) * bug of Array2.row the problem is the line else mkVec (stop+nrows-1, []) in fun Array2.row of array2.sml which i think should be else mkVec (stop+ncols-1, []) Test: Owner: jhr Status: fixed in 110.9.1 and in 110.0.4 [jhr, 10/19/98] ---------------------------------------------------------------------- Number: 1451 Title: Math.sin(large number) is wrong Keywords: maths Submitter: George Russell george@persimmon.com Date: 10/13/98 Version: 110.8 System: Alpha Digital Unix 4.0B Subsystem: SML basis library Severity: minor Problem: sin(large number) returns ~1.0, 1.0 or 0.0 Code: Math.sin(1e16); Math.sin(1.1e16); Math.sin(1.2e16); Math.sin(1.3e16); Transcript: Standard ML of New Jersey v110.8 [FLINT v1.41], August 5, 1998 val use = fn : string -> unit - Math.sin(1e16); val it = 0.0 : real - Math.sin(1.1e16); val it = ~1.0 : real - Math.sin(1.2e16); val it = 1.0 : real - Math.sin(1.3e16); val it = 0.0 : real Comments: This values are inconsistent - if sin(x)=0, sin(x+y)= -1, then x= 0 mod 2pi, y= 3pi/2 mod 2pi; therefore sin(x+2y)=0 and sin(x+3y)=1. Fix: Do what fdlibm does and use multiprecision arithmetic to compute x mod 2pi exactly. This is the ideal solution, since it ensures consistency, even though the results aren't very meaningful. Otherwise, return an answer which is obviously wrong (EG NaN or x), since the program surely must be. Test: Owner: jhr, Andrew Status: open ---------------------------------------------------------------------- Number: 1452 Title: Math.sinh(small number)=0.0 Keywords: reals Submitter: George Russell george@persimmon.com Date: 10/13/98 Version: 110.8 System: Alpha Digital Unix 4.0B Subsystem: SML basis library Severity: minor Problem: For small x, sinh(x) is approximately x. However New Jersey thinks it is 0. Code: Math.sinh(1e~20); Transcript: Standard ML of New Jersey v110.8 [FLINT v1.41], August 5, 1998 val use = fn : string -> unit - Math.sinh(1e~20); val it = 0.0 : real Comments: Similar considerations apply to Math.tanh. Fix: I suspect that SML/NJ is using a formula which is something like sinh(x)=(e^x - e^{-x})/2. For small x, e^x=1, so SML/NJ falls into the ancient trap of subtracting two nearly equal quantities. One way of circumventing this is to use the expm1 function (available on Digital Unix, Sparc-Solaris and Linux at least) which is equal to e^x -1. Then we have sinh(x)=0.5*expm1(x)*(1+ 1/(expm1(x)+1)). (See fdlibm for more details). Test: bug1452.1.sml Owner: jhr, Andrew Status: open ---------------------------------------------------------------------- Number: 1453 Title: Compiler bug: LtyExtern: incorrect lambda types in lt_select Keywords: lazy compiler Submitter: Kevin Watkins kw+@cs.cmu.edu Date: 10/22/98 Version: 110.8, 110.9.1 System: x86 Linux 2.0.32 (Redhat 4.2) Subsystem: SML compiler Severity: major Problem: Compiler internal error was reported while processing source code using `lazy' and a polymorphic datatype. Note: the following val _ = Compiler.Control.lazysml := true; datatype lazy stream = Nil | Cons of unit * stream; val rec lazy x = Cons(raise Subscript, x); is accepted. Code: val _ = Compiler.Control.lazysml := true; datatype lazy 'a stream = Nil | Cons of 'a * 'a stream; val rec lazy x = Cons(raise Subscript, x); Transcript: gs73$ sml Standard ML of New Jersey v110.8 [FLINT v1.41], August 5, 1998 [CM; autoload enabled] - val _ = Compiler.Control.lazysml := true; - datatype lazy 'a stream = Nil | Cons of 'a * 'a stream; datatype 'a stream! = Cons of 'a * 'a stream! ?.susp | Nil type 'a stream = 'a stream! ?.susp - val rec lazy x = Cons(raise Subscript, x); Error: Compiler bug: LtyExtern: incorrect lambda types in lt_select Comments: Fix: Test: tests.lazy/bug1453.1.sml Owner: dbm, Zhong Status: open ---------------------------------------------------------------------- Number: 1454 Title: Unexpected force of lazy suspension in pattern match Keywords: lazy pattern-match Submitter: Kevin Watkins kw+@cs.cmu.edu Date: 10/22/98 Version: 110.8 System: x86 Linux 2.0.32 (Redhat 4.2) Subsystem: SML compiler Severity: major Problem: The implementation of `lazy' in 110.8 does not seem to respect the semantics described in Wadler et al (How to add laziness to a strict language without even being odd). I have provided source code for a simple example which demonstrates the problem in the place provided on this bug report form. It raises an exception rather than returning [] as one would expect. Code: val _ = Compiler.Control.lazysml := true; datatype lazy stream = Nil | Cons of int * stream; fun take (s, 0) = [] | take (Nil, _) = raise Subscript | take (Cons(x, s), n) = x::take(s, n-1); val rec lazy don't_force_me = Cons(raise Fail "Was forced", don't_force_me); (* should return [] but raises Fail instead *) take(don't_force_me, 0); Transcript: gs73$ sml Standard ML of New Jersey v110.8 [FLINT v1.41], August 5, 1998 [CM; autoload enabled] - val _ = Compiler.Control.lazysml := true; - datatype lazy stream = Nil | Cons of int * stream; datatype stream! = Cons of int * stream! ?.susp | Nil type stream = stream! ?.susp - fun take (s, 0) = [] = | take (Nil, _) = raise Subscript = | take (Cons(x, s), n) = x::take(s, n-1); val take = fn : stream! ?.susp * int -> int list - val rec lazy don't_force_me = Cons(raise Fail "Was forced", = don't_force_me); GC #0.0.0.0.1.16: (0 ms) val don't_force_me = $$ : stream! ?.susp - (* should return [] but raises Fail instead *) - take(don't_force_me, 0); uncaught exception Fail: Was forced raised at: stdIn:15.42-15.59 Comments: One might argue that the semantics of pattern matching should allow the behavior I'm claiming is incorrect. However, the very example with which the Wadler et al paper motivates the "even" versus "odd" definition of lazy data structures fails. Here is the code from Figure 3 of the paper: datatype lazy 'a stream = Nil | Cons of 'a * 'a stream; fun lazy map f Nil = Nil | map f (Cons(x,xs)) = Cons(f x, map f xs); fun lazy countdown n = Cons (n, countdown (n-1)); fun cutoff 0 xs = [] | cutoff n Nil = [] | cutoff n (Cons(x,xs)) = x :: cutoff (n-1) xs; The motivating example is in section 2.1 of the paper. Since `sqrt' no longer raises an exception in this version of SML, I will use `div' instead. We would expect cutoff 4 (map (fn x => 100 div x) (countdown 4)); to return [25, 33, 50, 100] but instead it raises Div. [Related report from Bob Harper, 10/1/98] Compiler.Control.lazysml := true; datatype lazy 'a stream = && of 'a * 'a stream; infixr &&; fun shd (h && _) = h; fun stl (_ && t) = t; (* eager *) fun lazy ltl (_ && t) = t; (* lazy *) fun lazy smap f (h && t) = (f h) && (smap f t) fun lazy szip (h && t, h' && t') = (h, h') && (szip (t, t')); val rec lazy s = 1 && 1 && smap (op +) (szip (s, stl s)) My expectation is that I should be able to take shd s and shd(stl s) without problem, but that taking shd (stl (stl s)) should loop. However, it loops the first time I take shd s. I don't get it. Apparently the second argument to the first "&&" is not suspended properly, or something like that. Could you please explain? Also, compare the following: val rec lazy s1 = 1 && s2 and lazy s2 = 1 && s3 and lazy s3 = smap (op +) (szip (s1, s2)) which works fine, as does the version in which s2 is replaced by stl s1. What gives? I would've thought these would be equivalent. Fix: Test: tests.lazy/bug1454.1.sml, bug1454.2.sml Owner: dbm, Wadler Status: open ---------------------------------------------------------------------- Number: 1455 Title: IntInf not properly supported Keywords: IntInf Submitter: Henry Cejtin Date: 10/30/98 Version: 110.8 System: Any/All Any Unix Subsystem: SML compiler Severity: minor Problem: According to the basis documentation (integer.html), if an implementation provides the IntInf structure, then LargeInt.int is supposed to be the same as IntInf.int. Similarly, literals should be accepted for IntInf.int constants. I.e., val x: IntInf.int = 9 should be accepted. Finally, the standard infix arithmetic operations, (+, -, ...) should be overloaded for IntInf.int. Comments: [dbm, 2/11/99] Support for IntInf is optional, but we should add it. The signature of IntInf is currently incomplete (lacks bitwise operations), and a higher performance implementation using primop support would be desirable. Fix: Test: Owner: jhr, Lal Status: not a bug ---------------------------------------------------------------------- Number: 1456 Title: Int.sameSign Keywords: Int.sameSign Submitter: Henry Cejtin henry@research.nj.nec.com Date: 10/30/98 Version: 110.8 System: Any/All Any Unix Subsystem: SML basis library Severity: minor Problem: The basis documentation says that Int.sameSign (x, y) should be equivalent to Int.sign x = Int.sign y Int.sign 0 --> 0 Int.sign 1 --> 1 and yet Int.sameSign (0, 1) -> true From experiments, it seems that sameSign (x, y) is simply testing if the sign bit of x and y is the same. Actually, I find this to be more useful, but either the documentation or the behavior should be changed. Note, the same behavior is exhibited by Int32.sameSign. Code: Int.sameSign (0, 1); Int32.sameSign (0, 1); Transcript: - Int.sameSign (0, 1); val it = true : bool - Int32.sameSign (0, 1); val it = true : bool Comments: Fix: Test: bug1456.1.sml Owner: jhr, Lal Status: open ---------------------------------------------------------------------- Number: 1457 Title: Posix.FileSys.readdir Keywords: Posix.Filesys.readdir Submitter: Henry Cejtin henry@research.nj.nec.com Date: 10/30/98 Version: 110.8 System: Any/All Any Unix Subsystem: SML basis library Severity: major Problem: In Posix.FileSys, what is the argument for readdir having the signature dirstream -> string instead of dirstream -> string option and having it return the empty string if there are no more directories? This seems completely insane to me. Note, that the C readdir() returns NULL when there are no more directories, so even it is closer to a string option. Comments: [jhr, 2/8/99] This is a basis spec issue; we implement the spec. Fix: Change Posix.FileSys.readdir so that it returns a string option, with NONE indicating the end of the directory has been reached. Test: Owner: jhr Status: not a bug ---------------------------------------------------------------------- Number: 1458 Title: Uninformative IO exception message / crash Keywords: IO Submitter: Allyn Dimock Date: 11/04/98 Version: 110.0.3 full-cm System: SGI Severity: minor Problem: Transcript below typed at command loop causes crash. The crash is probably a "feature" rather than a bug -- I should restore the old value of out before closing the temporary stream. But: it would be nice to have the error handled and something more informative than "" printed out. Code: Transcript: - val oldout = !Control.Print.out; val oldout = {flush=fn,say=fn} : {flush:unit -> unit, say:string -> unit} - val out = TextIO.openOut("xxx.xxx"); val out = - : TextIO.outstream - val sayout = {say = fn(s) => TextIO.output (out,s), flush = fn() => TextIO.flushOut(out)}; val sayout = {flush=fn,say=fn} : {flush:unit -> unit, say:TextIO.vector -> unit} - Control.Print.out := sayout; SmlnjFrontEnd.smlnjFrontEnd("test1a.sml"); GC #1.9.15.56.197.4729: (9 ms) ================== SMLNJ Lambda Term: ================== Untyped Cil Term: let.14 i: = .3{0=1.1:,1=2.2:} in i.7: GC #1.9.15.57.198.4747: (15 ms) GC #1.9.15.58.199.4753: (26 ms) %time cumsec #call name 33.33 .01 0 Major GC ...... GC #1.9.16.61.202.4768: (0 ms) TextIO.closeOut(out); /usr/local/sml/bin/sml-full-cm: Fatal error -- Uncaught exception Io with raised at boot/IO/text-io-fn.sml:444.14-444.56 Process sml-full-cm exited abnormally with code 1 by the way, the contents of xxx.xxx is: arctic 37% more xxx.xxx val it = () : unit - [opening test1a.sml] FN(v3 : S{}, i2 = RECORD(1,2) SRECORD(i2)) val it = () : unit - arctic 38% Comments: (Attempt to use mcprint to a file) [jhr, 11/4/98] This is a "feature" of having an interactive top-level loop that shares its streams with executing programs. Fix: Test: Owner: jhr Status: not a bug ---------------------------------------------------------------------- Number: 1459 Title: segmentation fault after an interrupt Keywords: core dump, interrupt Submitter: Elsa Gunter Date: 11/13/98 Version: 110.9.1 System: x86/Linux Severity: major Problem: Yesterday, just before I went home, I encountered the following bad bahavior form sml version 110.9.1 running under Linux: Transcript: ... GC #4.38.85.145.802.29587: (40 ms) GC #4.38.85.145.803.29589: (40 ms) GC #4.38.85.145.804.29590: (10 ms) GC #4.38.85.145.805.29622: (20 ms) GC #4.39.86.146.806.29700: (120 ms) Interrupt - use "cm-make.sml"; GC #4.39.86.146.807.29706: (30 ms) /usr/local/bin/sml: Fatal error -- unexpected fault, signal = 11, code = 0x804c34d 481.0u 4.6s 11:47.57 68.6% 0+0k 0+0io 941pf+0w cambridge% Comments: The compiler was busy compiling something big, and I didn't need it to finish and I didn't want to wait for it, so I interupted it. Then I tried to use another file and it immediately died on me. I can't reproduce the problem, but I thought I shiuld pass it along especially since there was some information generated when it died. Fix: Test: Owner: ? Status: not reproducible ---------------------------------------------------------------------- Number: 1460 Title: CM.stabilize(') fails when calling BinIO under Win32 Keywords: CM, IO Submitter: Elsa L. Gunter, elsa@research.bell-labs.com Date: 11/13/98 Version: 110.9.1 System: x86-win32 ie. windows nt, windows 95 (I haven't checked 98 yet) Severity: major Problem: When CM.stabilize' is called it fails with an IO exception generated by BinIO.inputAll claiming an subscript is out of bounds Code: File [test.sml] structure A = struct end File [test.cm] Group is test.sml val _ = CM.stabilize'{group="test.cm", recursively=false}; Transcript: Standard ML of New Jersey v110.9.1 [FLINT v1.41], October 19, 1998 - val _ = CM.stabilize'{group="test.cm", recursively=false}; [starting dependency analysis] [scanning test.cm] [checking CM\x86-win32\test.cm.stable... not usable] [parsing test.sml] [Creating directory CM\DEPEND ...] [dependency analysis completed] [compiling test.sml -> CM\x86-win32\test.sml.bin] [Creating directory CM\x86-win32 ...] [wrote CM\x86-win32\test.sml.bin] [starting dependency analysis] [dependency analysis completed] writing CM\x86-win32\test.cm.stable failed] uncaught exception Io: inputAll failed on "CM\x86-win32\test.sml.bin" with exception subscript out of bounds raised at: PervEnv/IO/bin-io-fn.sml:107.14-107.56 ../cm/decl/decl.sml:260.41 ../cm/util/interrupt.sml:35.58-35.61 ../cm/decl/decl.sml:376.45-376.48 ../cm/decl/decl.sml:384.8-384.11 - - Comments: It doesn't matter whether a CM.make' has been done on the group test.cm, or not. [Blume] It appears that inputAll on Win32 is the culprit. Fix: Test: - Owner: Lorenz, Riccardo Status: open ---------------------------------------------------------------------- Number: 1461 Title: Changing directories confuses CM sharing Keywords: CM, share Submitter: Elsa L. Gunter, elsa@research.bell-labs.com Date: 12/10/98 Version: 110.9.1 System: x86-linux Severity: major Problem: When the directory is changed on CM, by exporting a heap and restarting it in a different place, or by using OS.FileSys.chDir, CM seems to loose track of modules that it has already loaded and executed. Code: (* Code and Instructions *) Make the following directories: bug bug/bug1 bug/bug2 Create the following files: (* bug/bug1/first.sml *) structure First = struct val x = ref 0 end (*------------------------------------*) (* bug/bug1/first.cm *) Library structure First is first.sml : shared (*------------------------------------*) (* bug/bug2/second.sml *) structure Second = struct val y = !First.x end (*------------------------------------*) (* bug/bug2/second.cm *) Library structure Second is ../bug1/first.cm second.sml : shared (*------------------------------------*) (* bug/load1.sml *) val _ = CM.make' {group = "/bug/bug1/first.cm", force_relink = false}; val _ = First.x := 3; fun finish () = CM.make' {group = "/bug/bug2/second.cm", force_relink = false}; val _ = SMLofNJ.exportML "bug"; (*------------------------------------*) Now while in the directory bug, start sml and execute use "load1.sml"; finish(); Stop sml, then start <> and execute finish(); Second.y; Stop sml, cd .., then start <> and execute finish(); Second.y; The fisrt value of Second.y is 3, while the second is 0. I claim the second is wrong. To see an alternate way of generating the same problem, add the following files: (*------------------------------------*) (* bug/bug2/third.sml *) structure Third = struct val y = !First.x end (*------------------------------------*) (* bug/bug2/third.cm *) Library structure Third is ../bug1/first.cm third.sml : shared (*------------------------------------*) (* bug/load2.sml *) val _ = CM.make' {group = "/bug/bug1/first.cm", force_relink = false}; val _ = First.x := 3; val _ = CM.make' {group = "/bug/bug2/second.cm", force_relink = false}; Second.y; val _ = OS.FileSys.chDir ".." (* any place different, really *) val _ = CM.make' {group = "/bug/bug2/third.cm", force_relink = false}; Third.y; val result = (Second.y = Third.y); (*------------------------------------*) Now, while in the bug directory, start sml and execute use "load2.sml" I claim the value of result should be true, but is false. I append a tar-gzip-uuencoded copy of the bug directory at the end of this report. Transcript: norfolk% ls -R bug1/ bug2/ load1.sml load2.sml bug1: first.cm first.sml bug2: second.cm second.sml third.cm third.sml norfolk% sml Standard ML of New Jersey v110.9.1 [FLINT v1.41], October 19, 1998 val use = fn : string -> unit - use "load1.sml"; [opening load1.sml] [starting dependency analysis] [scanning /home/elsa/bug/bug1/first.cm] [checking /home/elsa/bug/bug1/CM/x86-unix/first.cm.stable... not usable] [parsing /home/elsa/bug/bug1/first.sml] [Creating directory /home/elsa/bug/bug1/CM/DEPEND ...] [dependency analysis completed] [compiling /home/elsa/bug/bug1/first.sml -> /home/elsa/bug/bug1/CM/x86-unix/first.sml.bin] [Creating directory /home/elsa/bug/bug1/CM/x86-unix ...] [wrote /home/elsa/bug/bug1/CM/x86-unix/first.sml.bin] [introducing new bindings into toplevel environment...] val finish = fn : unit -> bool GC #1.1.1.1.1.14: (120 ms) write 1,0: 27020 bytes [0x40c00000..0x40c0698c) @ 0x2000 write 1,1: 7800 bytes [0x40c60008..0x40c61e80) @ 0x9000 write 1,2: 11692 bytes [0x40cb0000..0x40cb2dac) @ 0xb000 write 1,3: 2656 bytes [0x40d20000..0x40d20a60) @ 0xe000 write 2,0: 70136 bytes [0x40d80000..0x40d911f8) @ 0xf000 write 2,1: 73480 bytes [0x40e30008..0x40e41f10) @ 0x21000 write 2,2: 16948 bytes [0x40ef0000..0x40ef4234) @ 0x33000 write 2,3: 2304 bytes [0x40f20000..0x40f20900) @ 0x38000 write 2,0: 5 big objects (5 pages) @ 0x39000 write 3,0: 27584 bytes [0x40f40000..0x40f46bc0) @ 0x3a450 write 3,1: 59736 bytes [0x40f70008..0x40f7e960) @ 0x41450 write 3,2: 18660 bytes [0x40fc0000..0x40fc48e4) @ 0x50450 write 3,3: 1288 bytes [0x40fe0000..0x40fe0508) @ 0x55450 write 4,0: 228 bytes [0x41000000..0x410000e4) @ 0x56450 write 4,1: 264 bytes [0x41010008..0x41010110) @ 0x57450 write 4,2: 124 bytes [0x41020000..0x4102007c) @ 0x58450 write 4,3: 24 bytes [0x41030000..0x41030018) @ 0x59450 write 5,0: 371204 bytes [0x41050000..0x410aaa04) @ 0x5a450 write 5,1: 575864 bytes [0x41220008..0x412ac980) @ 0xb5450 write 5,2: 147236 bytes [0x414e0000..0x41503f24) @ 0x142450 write 5,3: 52220 bytes [0x415a0000..0x415acbfc) @ 0x166450 write 5,0: 323 big objects (6625 pages) @ 0x173450 val it = () : unit - finish(); [starting dependency analysis] [scanning /home/elsa/bug/bug2/second.cm] [checking /home/elsa/bug/bug2/CM/x86-unix/second.cm.stable... not usable] [parsing /home/elsa/bug/bug2/second.sml] [Creating directory /home/elsa/bug/bug2/CM/DEPEND ...] [dependency analysis completed] [compiling /home/elsa/bug/bug2/second.sml -> /home/elsa/bug/bug2/CM/x86-unix/second.sml.bin] [Creating directory /home/elsa/bug/bug2/CM/x86-unix ...] [wrote /home/elsa/bug/bug2/CM/x86-unix/second.sml.bin] [introducing new bindings into toplevel environment...] val it = true : bool - norfolk% sml @SMLload=bug; uncaught exception Io: input failed on "load1.sml", Bad file number raised at: PervEnv/IO/text-io-fn.sml:113.14-113.56 Parse/main/frontend.sml:92.32 Parse/main/frontend.sml:92.32 - finish(); [starting dependency analysis] [scanning /home/elsa/bug/bug2/second.cm] [checking /home/elsa/bug/bug2/CM/x86-unix/second.cm.stable... not usable] [dependency analysis completed] [recovering /home/elsa/bug/bug2/CM/x86-unix/second.sml.bin... done] [introducing new bindings into toplevel environment...] val it = true : bool - Second.y; val it = 3 : int - GC #0.0.0.0.1.5: (20 ms) norfolk% cd .. norfolk% sml @SMLload=bug/bug uncaught exception Io: input failed on "load1.sml", Bad file number raised at: PervEnv/IO/text-io-fn.sml:113.14-113.56 Parse/main/frontend.sml:92.32 Parse/main/frontend.sml:92.32 - finish(); [starting dependency analysis] [scanning /home/elsa/bug/bug2/second.cm] [checking /home/elsa/bug/bug2/CM/x86-unix/second.cm.stable... not usable] [scanning /home/elsa/bug/bug1/first.cm] [checking /home/elsa/bug/bug1/CM/x86-unix/first.cm.stable... not usable] GC #0.0.0.0.1.3: (10 ms) [dependency analysis completed] [recovering /home/elsa/bug/bug1/CM/x86-unix/first.sml.bin... done] [recovering /home/elsa/bug/bug2/CM/x86-unix/second.sml.bin... done] [introducing new bindings into toplevel environment...] val it = true : bool - Second.y; val it = 0 : int - norfolk% cd bug norfolk% sml Standard ML of New Jersey v110.9.1 [FLINT v1.41], October 19, 1998 val use = fn : string -> unit - use "load2.sml"; [opening load2.sml] [starting dependency analysis] [scanning /home/elsa/bug/bug1/first.cm] [checking /home/elsa/bug/bug1/CM/x86-unix/first.cm.stable... not usable] [dependency analysis completed] [recovering /home/elsa/bug/bug1/CM/x86-unix/first.sml.bin... done] [introducing new bindings into toplevel environment...] [starting dependency analysis] [scanning /home/elsa/bug/bug2/second.cm] [checking /home/elsa/bug/bug2/CM/x86-unix/second.cm.stable... not usable] GC #0.0.0.0.1.10: (10 ms) [dependency analysis completed] [recovering /home/elsa/bug/bug2/CM/x86-unix/second.sml.bin... done] [introducing new bindings into toplevel environment...] val it = 3 : int [starting dependency analysis] [scanning /home/elsa/bug/bug2/third.cm] [checking /home/elsa/bug/bug2/CM/x86-unix/third.cm.stable... not usable] [scanning /home/elsa/bug/bug1/first.cm] [checking /home/elsa/bug/bug1/CM/x86-unix/first.cm.stable... not usable] [parsing /home/elsa/bug/bug2/third.sml] [dependency analysis completed] [recovering /home/elsa/bug/bug1/CM/x86-unix/first.sml.bin... done] [compiling /home/elsa/bug/bug2/third.sml -> /home/elsa/bug/bug2/CM/x86-unix/third.sml.bin] [wrote /home/elsa/bug/bug2/CM/x86-unix/third.sml.bin] [introducing new bindings into toplevel environment...] val it = 0 : int val result = false : bool val it = () : unit - norfolk% Comments: Here is a uuencoded, gzipped, tar file with the test files and directories. Unpacked version can be found in bugs/tests.cm/bug1461. ========= begin 644 bug.tgz M'XL(`"XF<#8``^U946^B0!#VM?R*.5Y.FP9W%W9)VOATESY<[/7!>V\0ETJ* M8!:X2"[WWV]!04M[M4UD-7:_Q*BX,A-FOIEO9Z?YX[#7,5W%[ND![1KQTKD:>8)@!Z/4D^%O1/#5,9?OG"72?"1^+O8 M!L`($:SCKP)-_(-0I)GE+SJP(-^#-QE__4KOE/*"KK/W8QU?Q7@1;M8;0I!,9O+X(5C$#P`)#!8\W\L\2&_^3D M])_6_TK0Q#_E?A+/.A&`^^H_1G2K_^1"6?\98[K^J\`K^F]29<):`%K6\]V! M7+?.$ZT)SP-M_G!5_K_KS(3_M?^UVFBN_^Y MH,7_(\U_Z);_Y2RXG/\XFO\JT**];O^?#"7_H\2;D6ZH7V$?_QFAS?S'9N7Y M#W+U_E\-2IH_2)I_N[,6WA/_"G\>19(OY15S.$\6?%@^E^&+4T+SRKBX``@2 MX?,'P:,P?I)_";PHY7]O#*.^ZZ9VP/4([)W+[S*V,Y*JK+UA;KUUL8H=$_<3 MZS:,^*1(+7_^/11@6I8)_4OPX@*6D>=SF(5!P`6/LRL0W(NB`BX''_:QELW[ M7*RJ:^.AX&D>9?+W?NVZ_+Q9,KA1J:AJ_N,C\M_>[O\I8ZSBOZO/?Y5`*?^# M/(8@C,-T#OU!!W6@-CNY&R?!SQ\67RT3D=V-P93W,>6"8S]M#8W3PC_5`W1N $`"@````` ` end ========= Fix: Test: tests.cm/bug1461 Owner: Matthias Status: fixed in 110.20 [Matthias] ---------------------------------------------------------------------- Number: 1462 Title: Error in "g" format handling Keywords: Format (SMLofNJ-LIB) Submitter: David McClain dmcclain@azstarnet.com Date: 12/12/98 Version: 110.0.3 System: x86 Windows NT 4.0 sr 3 (build 1381) Subsystem: SML/NJ Library Severity: minor Problem: Machine and OS Independent: The handling of the "%g" format code for reals incorrectly omits the decimal point, so that, e.g., Format.format "%g" [Format.REAL 1.2E8] ---> 12e08. It's relatively simple to fix the omission in the "format" function, in module Format.sml. Code: See above... Transcript: see above... Comments: None. But, NICE WORK! Please keep it up!! Fix: fun format s = let val fmts = compileFormat s fun doField (flags, wid, ty, arg) = let fun padFn s = (case (#ljust flags, wid) of (_, NoPad) => s | (false, Wid i) => padLeft(s, i) | (true, Wid i) => padRight(s, i) (* end case *)) fun zeroPadFn (sign, s) = (case wid of NoPad => raise BadFormat | (Wid i) => zeroLPad(s, i - (String.size sign)) (* end case *)) fun negate i = ((PosInt(~i)) handle _ => MaxInt) fun doSign i = (case (i < 0, #sign flags, #neg_char flags) of (false, AlwaysSign, _) => ("+", PosInt i) | (false, BlankSign, _) => (" ", PosInt i) | (false, _, _) => ("", PosInt i) | (true, _, TildeSign) => ("~", negate i) | (true, _, _) => ("-", negate i) (* end case *)) fun doRealSign sign = (case (sign, #sign flags, #neg_char flags) of (false, AlwaysSign, _) => "+" | (false, BlankSign, _) => " " | (false, _, _) => "" | (true, _, TildeSign) => "~" | (true, _, _) => "-" (* end case *)) fun doExpSign (exp, isCap) = let val e = if isCap then "E" else "e" fun mkExp e = zeroLPad(Int.toString e, 2) in case (exp < 0, #neg_char flags) of (false, _) => [e, mkExp exp] | (true, TildeSign) => [e, "~", mkExp(~exp)] | (true, _) => [e, "-", mkExp(~exp)] (* end case *) end fun octal i = let val (sign, i) = doSign i val sign = if (#base flags) then sign^"0" else sign val s = intToOctal i in if (#zero_pad flags) then sign ^ zeroPadFn(sign, s) else padFn (sign ^ s) end fun decimal i = let val (sign, i) = doSign i val s = intToStr i in if (#zero_pad flags) then sign ^ zeroPadFn(sign, s) else padFn (sign ^ s) end fun hexidecimal i = let val (sign, i) = doSign i val sign = if (#base flags) then sign^"0x" else sign val s = intToHex i in if (#zero_pad flags) then sign ^ zeroPadFn(sign, s) else padFn (sign ^ s) end fun capHexidecimal i = let val (sign, i) = doSign i val sign = if (#base flags) then sign^"0X" else sign val s = intToHeX i in if (#zero_pad flags) then sign ^ zeroPadFn(sign, s) else padFn (sign ^ s) end in case (ty, arg) of (OctalField, LINT i) => octal i | (OctalField, INT i) => octal(Int.toLarge i) | (IntField, LINT i) => decimal i | (IntField, INT i) => decimal(Int.toLarge i) | (HexField, LINT i) => hexidecimal i | (HexField, INT i) => hexidecimal(Int.toLarge i) | (CapHexField, LINT i) => capHexidecimal i | (CapHexField, INT i) => capHexidecimal(Int.toLarge i) | (CharField, CHR c) => padFn(String.str c) | (BoolField, BOOL false) => padFn "false" | (BoolField, BOOL true) => padFn "true" | (StrField, ATOM s) => padFn(Atom.toString s) | (StrField, STR s) => padFn s | (RealField{prec, format=F_Format}, REAL r) => let val {sign, mantissa} = RealFormat.realFFormat(r, prec) val sign = doRealSign sign in if ((prec = 0) andalso (#base flags)) then padFn(concat[sign, mantissa, "."]) else padFn(sign ^ mantissa) end | (RealField{prec, format=E_Format isCap}, REAL r) => let val {sign, mantissa, exp} = RealFormat.realEFormat(r, prec) val sign = doRealSign sign val expStr = doExpSign(exp, isCap) in if ((prec = 0) andalso (#base flags)) then padFn(concat(sign :: mantissa :: "." :: expStr)) else padFn(concat(sign :: mantissa :: expStr)) end | (RealField{prec, format=G_Format isCap}, REAL r) => let val prec = if (prec = 0) then 1 else prec val {sign, whole, frac, exp} = RealFormat.realGFormat(r, prec) val sign = doRealSign sign val expStr = (case exp of SOME e => doExpSign(e, isCap) | NONE => []) val num = if (#base flags) then let val diff = prec - ((size whole) + (size frac)) in if (diff > 0) then zeroRPad(frac, (size frac)+diff) else frac end else if (frac = "") then "" else ("." ^ frac) in (* Here is a cheap fix, but it will conflict with the line above... *) padFn(concat(sign::whole::"."::frac::expStr)) end | (_, LEFT(w, arg)) => let val flags = { sign = (#sign flags), neg_char = (#neg_char flags), zero_pad = (#zero_pad flags), base = (#base flags), ljust = true, large = false } in doField (flags, Wid w, ty, arg) end | (_, RIGHT(w, arg)) => doField (flags, Wid w, ty, arg) | _ => raise BadFmtList (* end case *) end fun doArgs ([], [], l) = SS.concat(rev l) | doArgs ((Raw s)::rf, args, l) = doArgs(rf, args, s::l) | doArgs (Field(flags, wid, ty)::rf, arg::ra, l) = doArgs (rf, ra, SS.all (doField (flags, wid, ty, arg)) :: l) | doArgs _ = raise BadFmtList in fn args => doArgs (fmts, args, []) end (* format *) Test: Owner: jhr Status: open ---------------------------------------------------------------------- Number: 1463 Title: Broken ARRAY2 Code Keywords: indexing/projection Submitter: David McClain dmcclain@azstarnet.com Date: 12/13/98 Version: 110.0.3 System: x86 Windows NT 4.0 r 3 (build 1381) Subsystem: SML basis library Severity: major Problem: Indexing for projection of rows works incorrectly. Code: structure A2 = Array2; val x = A2.tabulate A2.RowMajor (2,3,fn (r,c) => 10 * r + c); A2.row(x,0); --> val it = #[0,1] : int vector (* Nope! *) A2.row(x,1); --> val it = #[10,11] : int vector (* ditto *) A2.column(x,0); --> val it = #[0,10] : int vector (* these are okay *) A2.column(x,1); --> val it = #[1,11] : int vector A2.column(x,2); --> val it = #[2,12] : int vector Transcript: see above Comments: Looks like I need to implement my own... Fix: This one is a bit beyond me at this early time... Test: bug1463.1.sml Owner: jhr, Emden Status: fixed in 110.9.1 and in 110.0.4 [jhr] ---------------------------------------------------------------------- Number: 1464 Title: unnecessary instantiation of local nongeneralized types Keywords: type checking, generalization Submitter: Matthias Blume Date: 12/16/98 Version: 110.x System: - Severity: minor Problem: It think it is unnecessary to instantiate any non-generalized type vars that belong to definitions between "local" and "in". Those definitions never escape to the top level (which is the only place where they would hurt). Code: Transcript: Comments: [dbm] Declarations in local part of a local dec should be treated the same as the declarations in let expressions. Fix: Test: Owner: dbm Status: open ---------------------------------------------------------------------- Number: 1465 Title: Type variables not as general as Definition. Keywords: type variable Submitter: Stephen Weeks Date: 12/17/98 Version: Standard ML of New Jersey v110.9.1 [FLINT v1.41], October 19, 1998 System: x86-linux Severity: Problem: The class of type variables allowed is not as general as allowed in the Definition. For example, I believe the following four declarations are valid. Code: type '' t = int type '_ t = int type ''' t = int type ''1 t = int Transcript: Comments: Fix: In ml.lex, the case for type variables should be changed from: "'"("'"?)("_"|{num})?{id} to the following: "'"{idchars}* Test: bug1465.1.sml Owner: dbm Status: open ---------------------------------------------------------------------- Number: 1466 Title: GC signal never sent Keywords: runtime, GC Submitter: Roland McGrath Date: 12/16/1998 Version: 110.8 System: x86-linux Severity: minor Problem: The Signals.sigGC signal is never in fact raised. Furthermore, in fixing this I discovered the additional bug that any ML signal causes an extra unwarranted minor GC. In the case of the GC signal, this iterates infinitely, running the sigGC handler function repeatedly and nothing else. Code: (* set the GC handler to print so we can tell *) open Signals; setHandler (sigGC, HANDLER (fn (_,_,k) => (print "foobar\n"; k))); (* force a collection *) SMLofNJ.Internals.GC.doGC 99; (* it should have printed "foobar\n", but it didn't *) Transcript: Standard ML of New Jersey v110.8 [FLINT v1.41], August 5, 1998 [full] val use = fn : string -> unit - open Signals; opening Signals eqtype signal datatype sig_action = DEFAULT | HANDLER of signal * int * unit ?.cont -> unit ?.cont | IGNORE val listSignals : unit -> signal list val toString : signal -> string val fromString : string -> signal option val setHandler : signal * sig_action -> sig_action val overrideHandler : signal * sig_action -> sig_action val inqHandler : signal -> sig_action datatype sigmask = MASK of signal list | MASKALL val maskSignals : sigmask -> unit val unmaskSignals : sigmask -> unit val masked : unit -> sigmask val pause : unit -> unit val sigINT : signal val sigALRM : signal val sigTERM : signal val sigGC : signal - setHandler (sigGC, HANDLER (fn (_,_,k) => (print "foobar\n"; k))); val it = IGNORE : sig_action - SMLofNJ.Internals.GC.doGC 99; GC #1.1.1.1.1.11: (62 ms) val it = () : unit Comments: For some reason I have not ascertained, there are always at least two collections at once (the sigGC handler is always called at least twice). I don't think this is right, but two is closer to one than zero is by my reckoning. [jhr, 12/16/98] The GC signal got disabled a while back when I was fixing some problems with the signal handlers. It will be fixed in the new run-time system that we are working on (should be out in Feb 1999). GC signals should not be generated for minor collections, so the infinite loop that you encountered can be avoided. [Roland McGrath] > Firstly, do you agree with my analysis that handling an ML signal induces a > spurious minor collection and my fix to avoid that by restoring the real > limit pointer? In my view it is that bug, not signalling on minor > collections, that is responsible for the infinite loop. (And, harmless > though it may be, I would like to avoid the extra unwarranted > collection--when we have clock ticks arriving as ML signals, the cost of > the extra collection might become a practical concern.) [jhr] In the earlier implementation, where GC signals were actually generated, I chose to only generate them for "major" collections. Minor collections happen at a very high rate, and it seems excessive to generate a signal for each one. As far as the extra collection goes, avoiding it in your situation is probably worth while, but I don't think that it is worth fixing for the current run-time. I'll try to avoid it in the new run-time. [Roland McGrath] > Secondly, I think I really would like to have my signal handler run for > minor collections. I am interested in your opinion on this. My use of the > GC signal is, along with weak pointers, to implement finalizers for a > special kind of object (i.e. an ML record held weakly is logically keeping > alive a foreign object that must be explicitly deallocated). These objects > have extent appropriate for minor collections (they are a kind of call > frame). As they may be created and become garbage very quickly, I am > concerned about delaying their collection until a major collection. (I can > work around the problem by catching an actual resource shortage, forcing a > major collection (with SMLofNJ.Internals.GC.doGC), and retrying the > allocation, before diagnosing it as an out-of-resource exception.) [jhr] In the new collector, we directly support finalized objects (using Dybvig's guardian scheme), but we do not finalize objects on minor collections. In a copy collected system, finalization should never be relied on to free objects in a timely fashion. You will need some backup to force finalization (by doing GC), when a scare resource is exhausted. Handling weak pointers and finalized objects requires extra overhead, which I'd like to avoid in minor collections. Fix: The following patch to the runtime does three things: 1 (gc/call-gc.c). Call GCSignal at the end of InvokeGC. I don't know if this is the right place to call it, but it's the obvious one. It delivers the signal to whichever vproc invoked the GC, which seems correct. 2 (kernel/run-ml). When handling an ML signal, reset the limit pointer to the real heap limit if we do not perform a GC. This should probably go in a subroutine in gc/*.c, and I don't think it dtrt for MP. 3 (mach-dep/signal-util.c). I don't think this was actually necessary to fix anything, since numPendingSigs and numPendingSysSigs are added together and the sum tested. But it just looked wrong to me. Index: smlnj/runtime/gc/call-gc.c diff -c smlnj/runtime/gc/call-gc.c:1.1.1.1 smlnj/runtime/gc/call-gc.c:1.2 *** smlnj/runtime/gc/call-gc.c:1.1.1.1 Tue Oct 6 18:05:08 1998 --- smlnj/runtime/gc/call-gc.c Wed Dec 16 16:50:48 1998 *************** *** 230,235 **** --- 230,237 ---- ASSIGN(ProfCurrent, PROF_RUNTIME); + GCSignal (msp->ml_vproc); + } /* end of InvokeGC */ Index: smlnj/runtime/kernel/run-ml.c diff -c smlnj/runtime/kernel/run-ml.c:1.1.1.2 smlnj/runtime/kernel/run-ml.c:1.2 *** smlnj/runtime/kernel/run-ml.c:1.1.1.2 Tue Oct 6 18:10:03 1998 --- smlnj/runtime/kernel/run-ml.c Wed Dec 16 16:50:48 1998 *************** *** 17,22 **** --- 17,23 ---- #include "c-library.h" #include "profile.h" #include "gc.h" + #include "../gc/heap.h" /* XXX for HEAP_LIMIT */ /* local functions */ PVT void UncaughtExn (ml_val_t e); *************** *** 90,95 **** --- 91,103 ---- /* check for GC */ if (NeedGC (msp, 4*ONE_K)) InvokeGC (msp, 0); + else + /* Reset the limit pointer since no actual GC happened. + Otherwise, we would do a spurious GC before handling + the signal (which is especially problematical for + the GC signal!). */ + msp->ml_limitPtr = HEAP_LIMIT(msp->ml_heap); + /* invoke the ML signal handler */ ChooseSignal (vsp); msp->ml_arg = MakeHandlerArg (msp, sigh_resume); Index: smlnj/runtime/mach-dep/signal-util.c diff -c smlnj/runtime/mach-dep/signal-util.c:1.1.1.1 smlnj/runtime/mach-dep/signal-util.c:1.2 *** smlnj/runtime/mach-dep/signal-util.c:1.1.1.1 Tue Oct 6 18:05:10 1998 --- smlnj/runtime/mach-dep/signal-util.c Wed Dec 16 16:50:48 1998 *************** *** 31,39 **** vsp->vp_sigCode = vsp->vp_pendingSigQ[vsp->vp_nextPendingSig].sigNum; vsp->vp_sigCount = vsp->vp_pendingSigQ[vsp->vp_nextPendingSig].count; if (IS_SYSTEM_SIG(vsp->vp_sigCode)) ! vsp->vp_numPendingSigs -= vsp->vp_sigCount; else ! vsp->vp_numPendingSysSigs -= vsp->vp_sigCount; /* advance the pending queue */ if ((--vsp->vp_numInQ == 0) || (++vsp->vp_nextPendingSig == NUM_SIGS)) --- 31,39 ---- vsp->vp_sigCode = vsp->vp_pendingSigQ[vsp->vp_nextPendingSig].sigNum; vsp->vp_sigCount = vsp->vp_pendingSigQ[vsp->vp_nextPendingSig].count; if (IS_SYSTEM_SIG(vsp->vp_sigCode)) ! vsp->vp_numPendingSysSigs -= vsp->vp_sigCount; else ! vsp->vp_numPendingSigs -= vsp->vp_sigCount; /* advance the pending queue */ if ((--vsp->vp_numInQ == 0) || (++vsp->vp_nextPendingSig == NUM_SIGS)) Test: - Owner: jhr Status: open ---------------------------------------------------------------------- Number: 1467 Title: Looping functions fail in FLINT Keywords: FLINT Submitter: Allen Leung leunga@cs.nyu.edu Date: 12/30/98 Version: 110.11 System: Any/All Any Unix Subsystem: SML compiler Severity: minor Problem: FLINT fails on functions such as fun loop() = loop() or fun loop i = loop i Note: The previous bug reported by me is actually caused by this simple problem. Please discard previous report. Code: Transcript: - fun loop() = loop(); looking up unbound v27{3,3} while in fcontract phase uncaught exception IntmapF raised at: ../comp-lib/intmapf.sml:199.25-199.32 FLINT/opt/fcontract.sml:327.13 FLINT/main/flintcomp.sml:146.13 - fun loop i = loop i; while in reify phase uncaught exception RecoverLty raised at: ../comp-lib/intmap.sml:28.41-28.44 FLINT/main/flintcomp.sml:146.13 Comments: [jhr, 12/30/98] It appears that this bug was introduced in 110.10. Fix: Test: Owner: Zhong Status: open ---------------------------------------------------------------------- Number: 1468 Title: ccalls crashes on Cfunction(fn _ => Cvoid) Keywords: runtime, ccalls Submitter: Roland McGrath Date: 12/30/1998 Version: 110.8 System: x86-linux Severity: minor Problem: An ML function called from C that returns Cvoid crashes the runtime. Code: Transcript: Comments: I did not provide source or transcript because it requires a runtime with ccalls compiled in and hacked with some C function available via CCalls that makes a callback to ML. Passing such a function `Cfunction(fn _ => Cvoid)' will crash the runtime when that ML function attempts to return to C. Fix: Patch to runtime/c-libs/smlnj-ccalls/c-calls-fns.c follows. Index: c-calls-fns.c =================================================================== RCS file: /projects/express/cvsroot/smlnj/runtime/c-libs/smlnj-ccalls/c-calls-fns.c,v retrieving revision 1.2 retrieving revision 1.3 diff -u -b -p -r1.2 -r1.3 --- c-calls-fns.c 1998/12/16 20:00:01 1.2 +++ c-calls-fns.c 1998/12/30 19:43:18 1.3 @@ -178,6 +178,12 @@ PVT Word_t convert_result(ml_state_t *ms char *t = chp->rettype; int err; + if (*t == 'V') + /* The return type is void, meaning val must be Cvoid + * and our return value will be ignored by the C caller. + */ + return 0; + /* front-end of interface guarantees that ret is a valid * return value for a C function: Word_t or some pointer */ Test: * Owner: Lorenz, Riccardo Status: open ---------------------------------------------------------------------- Number: 1469 Title: Integer assignment should be unboxed assign Keywords: FLINT convert Submitter: Allen Leung leunga@cs.nyu.edu Date: 12/30/98 Version: 110.11 System: Any/All Any Unix Subsystem: SML compiler Severity: major Problem: Integer assignment should use unboxedassign. In 110.11 storelist maintainence instructions are generated for assignments such as x := y where x : int ref Note: mandelbrot runs about twice as slow on the HP and 1/3 slower on the sparc when compared to 110.9.1 Code: Compiler.Control.CG.printit := true; val x = ref 0; fun f y = x := y; Transcript: ************************************************* v481(v497[PV],v496[PV],v495[C],v494[PV],v493[PV],v492[PV],v491[I]) = v496.1 -> v498[PV] assign(v498,v491) v495(v495,v494,v493,v492,(I)0) ************************************************* Comments: [jhr, 12/30/98] This one is probably my fault. When I put in the new array representation support, I had to make := and Array.update be different (the Array.update has an extra level of indirection). I guess that I must have broken the type-based specialization. [jhr, 12/30/98] I just took a look at the code (from the 110.11 sources), and I'm not sure why the optimization isn't being done. Here is the code from FLINT/cpsopt/contract.sml: fun setter (P.update, [_, _, INT _]) = P.unboxedupdate | setter (P.update, [_, _, REAL _]) = P.boxedupdate | setter (P.update, [_, _, STRING _]) = P.boxedupdate | setter (P.update, [_, _, VAR v]) = (case #info(get v) of (FNinfo _) => P.boxedupdate | (RECinfo _) => P.boxedupdate | (OFFinfo _) => P.boxedupdate | _ => P.update (* end case *)) | setter (P.assign, [_, INT _]) = P.unboxedassign | setter (i, _) = i It looks like assignment of int refs should be translated to an unboxedassign. [Zhong, 12/30/98] This is not the right place. To fix it, you need to add a new "UNBOXEDASSIGN" primop into the FLINT/kernel/primop.{sig,sml}. Then add the following case to the "classPrim" function in FLINT/reps/wrapping.sml: | (PO.ASSIGN, [tc]) => (* special *) let val np = if LT.tc_upd_prim tc = PO.UNBOXEUPDATE then PO.UNBOXEDASSIGN else p in ((d, np, lt, ts), false, false) end Fix: [jhr, 12/30/98] I've put in a fix (supplied by Zhong) for this bug and it seems to work (at least the cps says "unboxedassign"). I'll commit these changes for 110.12; note that the pickler has changed to handle the new UNBOXEDASSIGN primop. Test: bug1469.1.sml Owner: jhr Status: fixed in 110.12 ---------------------------------------------------------------------- Number: 1470 Title: compilation blowup (in FLINT?) Keywords: compiler performance Submitter: Daniel Wang Date: 9/10/98 Version: 110.0.3 System: - Severity: major Problem: Should I expect this to elaborate in a resonable amount of time for 110.0.3. The signature elaborates in almost no time, but when elaborating the structure things get bogged down. The FLINT types should be able to represent this type efficiently right? So is this a performance bug in the elaborator? When sml gets bogged down elaborating the structure it's space usage seems t