Date: Mon, 1 Apr 91 17:24:53 PST From: Subject: Bad code for address arithmetic (1.6) This program exhibits a bug in the code generated for address arithmetic. UNSAFE MODULE Bug2 EXPORTS Main; IMPORT Word, Wr, Stdio, Fmt; TYPE Entry = RECORD r: Word.T; val: REFANY := NIL; END; VAR e: Entry; eP1, eP2: UNTRACED REF Entry; eA1, eA2: ADDRESS; BEGIN eP1 := ADR(e); eP2 := eP1; eA1 := ADR(e); eA2 := eA1; Wr.PutText(Stdio.stdout, Fmt.F("ADRSIZE=%s\n", Fmt.Int(ADRSIZE(Entry)))); INC(eP2, ADRSIZE(Entry)); INC(eA2, ADRSIZE(Entry)); Wr.PutText(Stdio.stdout, Fmt.F("eP1=%s, eP2 = %s\n", Fmt.Addr(eP1), Fmt.Addr(eP2))); Wr.PutText(Stdio.stdout, Fmt.F("eA1=%s, eA2 = %s\n", Fmt.Addr(eA1), Fmt.Addr(eA2))); END Bug2. The output from this (on my DECstation 5000) was: ADRSIZE=8 eP1=1000f068, eP2=1000f0a8 <---- incorrect increase of 64 bytes eA1=1000f068, eP2=1000f070 <---- correct increase of 8 bytes The generated code is similar for the "UNTRACED REF Entry" and ADDRESS case (eP2 += 8, eA2 += 8), but those of you who know C will realise that the C compiler has chosen to scale the addition based on its knowledge of the type, which is not what the Modula-3 compiler expected. Mick Jordan ------------------------------------------------------------------------------ Date: Mon, 1 Apr 91 17:33:20 PST From: muller@src.dec.com (Eric Muller) Subject: Re: Bad code for address arithmetic (1.6) In article <9104020125.AA12615@jumbo.pa.dec.com>, mjordan (Mick Jordan) writes: > > This program exhibits a bug in the code generated for address arithmetic. Sorry about that. It will be fixed for the next release. -- Eric. ------------------------------------------------------------------------------ Date: Mon, 1 Apr 91 17:40:25 PST From: muller@src.dec.com (Eric Muller) Subject: Re: Bad code for address arithmetic (1.6) In article <9104020125.AA12615@jumbo.pa.dec.com>, mjordan (Mick Jordan) writes: > > This program exhibits a bug in the code generated for address arithmetic. > ... > INC(eP2, ADRSIZE(Entry)); > INC(eA2, ADRSIZE(Entry)); While waiting for the next release, you can use: eP2 := eP2 + ADRSIZE (Entry); eA2 := eA2 + ADRSIZE (Entry); -- Eric. ------------------------------------------------------------------------------ Date: Mon, 1 Apr 91 17:53:13 PST From: muller@src.dec.com (Eric Muller) Subject: SRC-M3 1.6: bug in ParseParams.GetParameter Norman Ramsey reported that ParseParams.GetParameter does not behave as decribed in the interface: Returns NIL if num >= NumParameters. Actually, a random action is taken in that case, which may even core dump the program. Fixed for the next release. Thanks to Norman for reporting the bug. -- Eric. ------------------------------------------------------------------------------ Date: Mon, 1 Apr 91 18:00:12 PST From: muller@src.dec.com (Eric Muller) Subject: SRC-M3 1.6: bug in STextTable. Norman Ramsey and David Golberg reported that STextTable sometime fails with a runtime error in Text.Compare. The Text module now implements its interface properly, i.e. it complains when a NIL Text.T is passed to one of the Text routines. Unfortunately I failed to modify all the clients of Text so that they do not call Text.xxx with a NIL Text.T. Here is a version of STextTable.Compare that will do the right thing: PROCEDURE Compare (arg: REFANY; key1, key2: STable.Key): INTEGER = BEGIN IF key1 = NIL THEN key1 := ""; END; IF key2 = NIL THEN key2 := ""; END; RETURN Text.Compare (key1, key2) END Compare; Thanks to Norman and David for reporting this bug. -- Eric. ------------------------------------------------------------------------------ Date: 2 Apr 91 16:57:38 GMT From: nr@atomic.Princeton.EDU (Norman Ramsey) Subject: Proposal for change in the RTMisc interface The current RTMisc interface handles ``cleanup on exit'' as follows: TYPE Exitor <: REFANY; PROCEDURE RegisterExitor (p: PROCEDURE (n: INTEGER)): Exitor; (* Registers the procedure p to be executed when Exit is called; it is passed the argument of Exit. The registered procedures are executed in the reverse order. *) PROCEDURE UnregisterExitor (e: Exitor); (* removes e's procedure from the registered set. *) PROCEDURE Exit (n: INTEGER); (* call the registered exitors and terminate the program with status 'n' *) I propose the following change, to make it possible for exitors to have more state: TYPE Exitor <: REFANY; TYPE ExitorClosure = OBJECT METHODS apply(n:INTEGER); END; PROCEDURE RegisterExitor (p: ExitorClosure): Exitor; (* Registers the procedure p to be executed when Exit is called; it is passed the argument of Exit. The registered procedures are executed in the reverse order. *) PROCEDURE UnregisterExitor (e: Exitor); (* removes e's procedure from the registered set. *) PROCEDURE Exit (n: INTEGER); (* call the registered exitors and terminate the program with status 'n' *) Comments? -- Norman Ramsey nr@princeton.edu ------------------------------------------------------------------------------ Date: Tue, 2 Apr 1991 15:08:39 -0600 (CST) From: Dick Orgass Subject: SRC Modula-3 V 1.6 for IBM RISC 6000 Many thanks to Eric Muller for a good new compiler and for all his help with ports to IBM platforms. There are three minor details to fix in the 1.6 distribution for RISC 6000: (1) system/runtime/M3Machine.h.IBMR2 The definitions of PRIVATE, IMPORT and EXPORT that begin on line 18 should have the word volatile deleted so that they read as follows: #define PRIVATE static #define IMPORT extern #define EXPORT because the system C compiler does not accept declarations of functions whose return value is modified by volatile. This change does not preserve the intent of these declarations, variables that are private, imported or exported should be declared volatile but the return value of functions should not be volatile. However, preserving the original intent requires a modification of the compiler itself. (2) system/runtime/M3Runtime.h Comment out the extern declarations for TC_* that begins on line 22 of the file so that these identifiers are not multiply defined. The compiler emits a second declaration (with the volatile modifier) when these identifiers are used. The system C compiler rejects the redeclaration. (3) build util/mkexport before building the library The program mkexport is used to generate the export list for the shared libraries that come with SRC Modula-3 including the core library. It is not built from the top level make file. Before starting the system build, compile mkexport as follows: cd util bsdcc -o mkexport mkexport.c Instructions for adding bsdcc to your system are at the top of file util/config.dist-IBMR2. Known RISC 6000 bugs With the above corrections, the distributed system passes all test cases and runs all programs except the following: (1) tests/ptests/p083 There is an undefined symbol when the test program is linked; Eric reports that the link succeeds on DEC platforms. (2) demos/pickles/Graph4Test This pickle test program terminates with an unhandled exception Pkl.Error instead of terminating correctly. (3) tools/pp/m3pp The pretty printer is not working correctly. When tools/pp/Main.m3 is formatted, there is an assert failure at line 588 of Formatter.m3; when tools/pp/Parse.i3 is formatted, there is an assert failure at line 913 of Formatter.m3. Similar problems come up when formatting other Modula-3 source files. Dick ------------------------------------------------------------------------------ Date: Wed, 3 Apr 91 14:24:03 +0200 From: lawrence@chorus.fr (Lawrence Albinson) I just spent the Easter weekend porting the SRC Modula-3 (v1.6) system to the Acorn R140 workstation. I started from the R260 release, and from a v1.5 system that I had been playing with, on and off, for some time. The R140 has just 4Mb of memory and when running RISC iX 1.21 this leaves just 3Mb for userland. I found a number of ways to reduce the code size of the compiler and to improve its throughput. I would appreciate comments on the wisdom, or stupidity, of the various measures I took. They were: 1 Turned off ASSERT checking. I imagine this is a bad idea, but I have the release version of the compiler to hand should I suspect this to be a problem. 2 Simplified NILCHECK macros to just evaluate their arguments. Again, I imagine this is a bad idea in principle. Ditto my comment in 1 above. 3 Turned off versions stamp generation. 4 Added an option to control the generation of the CHECKSTACKOVERFLOW macro. I assume this is safe in a single threaded program. Besides, the ARM procedure call standard has support for multi-threaded stacks, and the C compiler knows about it. I might get round to using this feature at some time. 5 Added an option to control the generation of the PrintProc's. 6 Added code to more aggressively eliminate generation of unused MapProc's. 7 Simplified the ZERO1 macro to take just a variable name, and modified the compiler to leave out the &. This is because the ARM C compiler spots define before define chains in the case of: _z = 0; _z = exp; but not in the case of: *(int *)&_z = 0; _z = exp; Also collapsed all the bigger ZERO macros into bzero calls. The net result of the above changes was to reduce the compiler from a static size of 1.8Mb to 1.3Mb. This made the difference between heavy paging and barely paging at all for most compilations. The command 'time m3 -D../Interfaces -C SetExpr.m3' gave 34.4u 4.7s 1:12 54% for the release version and 19.9u 2.1s 0:30 72% for the modified version. I have no feel for the actual level of interest in the ARM version of SRC Modula-3. If there is interest, I will be more than happy to make my changes available. Finally, thanks to all of you at SRC and in the user community for doing such a good job. The system is a real treat to use. Keep up the good work. Lawrence Albinson ------------------------------------------------------------------------------ Date: 3 Apr 91 20:00:18 GMT From: mccalpin@perelandra.cms.udel.edu (John D. McCalpin) Subject: Re: SRC Modula-3 V 1.6 for IBM RISC 6000 >>>>> On 2 Apr 91 21:08:39 GMT, orgass+@rchland.ibm.com (Dick Orgass) said: Dick> Many thanks to Eric Muller for a good new compiler and for all Dick> his help with ports to IBM platforms. Dick> There are three minor details to fix in the 1.6 distribution for Dick> RISC 6000: [ details deleted ] I am confused about the 'cpp' in the config.dist-IBMR2 file. It defines cpp as /usr/local/lib/cpp, which is not the one that IBM supplies! When util/imake runs /lib/cpp on the file util/generic, the /lib/cpp program barfs at the line: /**/#------------------What to do claiming that it is an invalid # command (which is certainly is). Is the intent of the /**/ in that line to prevent cpp from attempting to process the line as a cpp directive? Anyway, I also tried using the public domain cpp from volume 1 of comp.sources.unix and got similar complaints. Is there another cpp that I should be using? -- John D. McCalpin mccalpin@perelandra.cms.udel.edu Assistant Professor mccalpin@brahms.udel.edu College of Marine Studies, U. Del. J.MCCALPIN/OMNET ------------------------------------------------------------------------------ Date: 3 Apr 91 19:09:29 GMT From: timb@ecst.csuchico.edu (Timothy Berger) Subject: Porting M3 to hp850 : Where to start ? I would like to port modula-3 to our HP 850. I have two questions: 1) Has this been done before? 2) Which currently available port would make this port the least painful? Thanks!, Tim B. ------------------------------------------------------------------------------ Date: 4 Apr 91 01:56:10 GMT From: nr@Princeton.EDU (Norman Ramsey) Subject: help wanted with Thread.Alert I don't understand why my thread isn't raising Thread.Alerted in the following program: MODULE Alert EXPORTS Main; IMPORT Rd, Wr, Thread, Fmt; FROM Stdio IMPORT stdin, stdout; PROCEDURE Copy(cl:Thread.Closure):REFANY RAISES {} = VAR result := NEW(REF INTEGER); BEGIN result^ := 0; TRY LOOP WITH line = Rd.GetLine(stdin) DO INC(result^); Wr.PutText(stdout,Fmt.F("line is `%s\'\n",line)); END; END; EXCEPT Thread.Alerted => Wr.PutText(stdout,"Alert!\n"); | Rd.EndOfFile => Wr.PutText(stdout,"EOT\n"); END; RETURN result; END Copy; VAR t := Thread.Fork(NEW(Thread.Closure, apply := Copy)); BEGIN Thread.Alert(t); Wr.PutText(stdout,"Thread has been alerted.\n"); Wr.PutText(stdout,Fmt.F("Read %s lines\n", Fmt.Int(NARROW(Thread.Join(t),REF INTEGER)^))); END Alert. Here's some output: nr@hart (44) % a.out Thread has been alerted. one line is `one' two line is `two' three line is `three' EOT Read 3 lines Can anybody help me understand this behavior? I have a much larger, more complicated program that's getting hung on exit because there's a thread lingering around trying to read stdin and I can't successfully alert the thread. -- Norman Ramsey nr@princeton.edu ------------------------------------------------------------------------------ Date: 5 Apr 91 03:10:00 GMT From: thomas@qut.edu.au Subject: Request for Modula-3 and Oberon code for complex numbers I am looking for some simple code to implement complex numbers and arithmetic in Modula-3 and Oberon. If anyone has such code in either or both languages and would be willing to give it to me I would be most appreciative. Please email your responses to me. Thanks! Au revoir, @~~Richard Thomas aka. The AppleByter -- The Misplaced Canadian~~~~@ { AARNet: richard@water.fit.qut.edu.au InterNet: R.Thomas@qut.edu.au } { PSI: PSI%505272223015::R.Thomas } @~~School of Computing Science - Queensland University of Technology~~@ ------------------------------------------------------------------------------ Date: Thu, 4 Apr 91 17:02:23 MET DST From: Thomas Roemke Subject: Re: help wanted with Thread.Alert nr@@Princeton.EDU (Norman Ramsey) writes: >I don't understand why my thread isn't raising Thread.Alerted in the >following program: >[..] see below. Thread.Alert(t) marks t as alerted, nothing else. No exception is raised, neither in the calling nor in the marked thread. If you want to have that behaviour, you've to raise an exception explicitly, e.g. MODULE Alert EXPORTS Main; IMPORT Rd, Wr, Thread, Fmt; FROM Stdio IMPORT stdin, stdout; PROCEDURE Copy(cl:Thread.Closure):REFANY RAISES {} = VAR result := NEW(REF INTEGER); BEGIN result^ := 0; TRY LOOP IF Thread.TestAlert() THEN EXIT; (* or RAISE Thread.Alerted *) END; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ WITH line = Rd.GetLine(stdin) DO INC(result^); Wr.PutText(stdout,Fmt.F("line is `%s\'\n",line)); END; END; EXCEPT Thread.Alerted => Wr.PutText(stdout,"Alert!\n"); | Rd.EndOfFile => Wr.PutText(stdout,"EOT\n"); END; RETURN result; END Copy; VAR t := Thread.Fork(NEW(Thread.Closure, apply := Copy)); BEGIN Thread.Alert(t); Wr.PutText(stdout,"Thread has been alerted.\n"); Wr.PutText(stdout,Fmt.F("Read %s lines\n", Fmt.Int(NARROW(Thread.Join(t),REF INTEGER)^))); END Alert. However, there's possibly a true bug left (SRC 1.6 SPARC). Using Thread.AlertJoin(t) instead of of Thread.Join(t) has to raise Thread.Alerted, since t is an alerted thread, but nothing happens..... Thomas -- (* Thomas Roemke, University of Paderborn, Germany modula-3@uni-paderborn.de ..!uunet!mcsun!unido!pbinfo!modula-3 *) ------------------------------------------------------------------------------ Date: Thu, 04 Apr 91 07:08:39 PST From: harbison@bert.pinecreek.com Subject: Modula-3 library listings and Newsletter The request from thomas@qut.edu.au re: "Request for Modula-3 and Oberon code for complex numbers" reminded me to post this: Pine Creek Software is building a list of 3rd-party library software for Modula-3. We will eventually create a repository for publically- available code and a complete listing that includes public and commercially-available code. If you have anything you'd like to offer to other programmers, or anything you plan to sell, please drop me a note. (DON'T send the code, yet.) A preliminary list will be published in the first Modula-3 newsletter coming out in May, and will be posted here. "Modula-3 Newsletter? How can I get it?" (I hear you ask.) If you've posted messages to comp.lang.modula3 with your mailing address included, you'll get it. If you've sent a Modula-3 Interest Form to us--or had any other communication with Pine Creek Software on Modula-3--you'll get it. If you haven't done any of these things, it would be a Good Idea to drop me a note with your mailing address. Sam Harbison Pine Creek Software; 305 S. Craig St., Suite 300; Pittsburgh, PA 15213 +1 412 681 9811; harbison@bert.pinecreek.com ------------------------------------------------------------------------------ Date: 4 Apr 91 16:50:38 GMT From: nr@hart.Princeton.EDU (Norman Ramsey) Subject: Re: help wanted with Thread.Alert In article <9104041502.AA04492@thor.uni-paderborn.de> modula-3@uni-paderborn.de (Thomas Roemke) writes: > Thread.Alert(t) marks t as alerted, nothing else. No > exception is raised, neither in the calling nor in the > marked thread. Well, no, that's not the way it's supposed to work. From the Rd interface: (* Many operations on a reader can wait indefinitely. For example, GetChar can wait if the user is not typing. In general these waits are alertable, so each procedure that might wait includes Thread.Alerted in its RAISES clause. *) PROCEDURE GetLine(rd: T): TEXT RAISES {EndOfFile, Failure, Alerted, Error}; ^^^^^^^ -- Norman Ramsey nr@princeton.edu ------------------------------------------------------------------------------ Date: 5 Apr 91 02:01:00 GMT From: lance@motcsd.csd.mot.com (lance.norskog) Subject: Status of M-3 Hello- I just heard about this language last night, and am studying the M3 Language Report. This is much better than C++. What's the current status of DEC's Modula-3 system? Does it have a port for the 386? 8086? Does it have a generic GNU-CC port? Is it robust and in use for large projects today, or is it still gurus-only? Are there large projects written in Modula-3 available for anonymous FTP? Large object libraries, a' la the copyleft C++ class libraries? Some of us learn best by reading existing work. Are there X-Window bindings? On the subject, is it easy to build C interfaces? Is there a method for cross-compiling raw Mach 3.0 systems? Do Modula-3 threads become Mach threads, get assigned to separate processors automatically, etc.? Thanks, Lance Norskog ------------------------------------------------------------------------------ Date: Thu, 4 Apr 91 20:01:17 PST From: Subject: Re: Status of M-3 [Lance Norskog:] What's the current status of DEC's Modula-3 system? Does it have a port for the 386? 8086? Does it have a generic GNU-CC port? Are there X-Window bindings? Is it easy to build C interfaces? All these questions are answered in the documentation that comes with the release, available via FTP from gatekeeper.dec.com. See Eric Muller's message of Mar/28 to this newsgroup. Is it robust and in use for large projects today, or is it still gurus-only? I am working on a Modula-3 graphics application with >150 modules, >25,000 lines of code. SRC Modula-3 is definitely OK for that size scale. Are there large projects written in Modula-3 available for anonymous FTP? There is the compiler itself, of course. Large object libraries, a' la the copyleft C++ class libraries? Not that I know of. The SRC Modula-3 package includes some basic libraries (strings, streams, tables, X bindings, etc.) but they aren't well planned or polished, and few of them are actually object-oriented. There is a somewhat larger set of libraries that were written at the (now closed) Olivetti Research Center, and may still be available; check with Mick Jordan. Better libraries are sorely needed. Jorge Stolfi DEC systems Research Center (Don't blame me, I'm only a user) ------------------------------------------------------------------------------ Date: 5 Apr 91 07:33:44 GMT From: modula-3@uni-paderborn.de (Thomas Roemke) Subject: Re: help wanted with Thread.Alert nr@hart.Princeton.EDU (Norman Ramsey) writes: >Well, no, that's not the way it's supposed to work. From the Rd >interface: >(* >Many operations on a reader can wait indefinitely. For example, >GetChar can wait if the user is not typing. In general these waits are >alertable, so each procedure that might wait includes Thread.Alerted >in its RAISES clause. *) >PROCEDURE GetLine(rd: T): TEXT RAISES {EndOfFile, Failure, Alerted, Error}; > ^^^^^^^ Oops. Sorry Norman. My answer was a result of misunderstanding your question. I answered to 'Why isn't t (automatically) raising Thread.Alerted ?' and your question actually was 'Why isn't Rd.GetLine raising it ?'. Thomas (* Thomas Roemke, University of Paderborn, Germany modula-3@uni-paderborn.de ..!uunet!mcsun!unido!pbinfo!modula-3 *) ------------------------------------------------------------------------------ Date: Fri, 05 Apr 91 06:43:57 PST From: harbison@bert.pinecreek.com Subject: M3 Newsletter mailing list If you sent me your mailing address for the Modula-3 newsletter before Friday 10am EST, please resend it. I had a system glitch and lost the messages. Sorry for the inconvenience. Sam Harbison Pine Creek Software; 305 S. Craig St., Suite 300; Pittsburgh, PA 15213 +1 412 681 9811; harbison@bert.pinecreek.com ------------------------------------------------------------------------------ Date: Fri, 5 Apr 1991 13:23:32 -0600 (CST) From: Dick Orgass Subject: Re: SRC Modula-3 V 1.6 for IBM RISC 6000 John, The version of cpp shipped with AIX 3.1 for RISC 6000 is a strict ANSI cpp and doesn't get along with imake at all. At least we haven't been able to figure out how to do it. The X11 product does have another version of cpp that is supposed to get along with imake (/usr/lpp/X11/Xamples/util/cpp). I started Modula-3 ports before the system was released and so I used (and still use) the 4.3 BSD cpp which is /usr/local/lib/cpp on our systems. I'd offer to send this cpp to you but there are license issues that will take far longer than either of us want to wait. Please let me know what happens either by mail or to this bboard. Dick ------------------------------------------------------------------------------ Date: Fri, 5 Apr 91 12:14:04 PST From: Subject: 1.6 bugs The following bugs have been reported in version 1.6: 1. FileStream.OpenRead(x) aborts with an assertion failure when x names a directory. It should return a reader on the underlying file. Fix: in system/corelib/filerw/UFileRdWr.m3, in CreateFileWriter line 356, change <*ASSERT FALSE*> to RAISE Failure (openFailure); in CreateFileReader line 386, change CoreOS.SIFREG => to CoreOS.SIFREG, CoreOS.SIFDIR => in CreateFileReader line 389, change <*ASSERT FALSE*> to RAISE Failure (openFailure); 2. Multi-threaded programs may deadlock while terminating when there's a thread blocked in a select on stdin. The problem is that RTMisc.Exit calls its registered cleanup routines. Stdio registers a cleanup routine that calls Rd.Close. It tries to lock the mutex in Stdio.stdin, but the reading thread already has the lock. The runtime doesn't recognize this as a deadlock since the select could return at any time. This problem is especially obnoxious when the program is trying to abort. 3. Formatter.Align was changed to take an object instead of a (procedure, REFANY) pair. Formatter.m3 was incompletely updated. This bug will cause assertion failures in programs that use Formatter (e.g. m3pp). Fix: in libs/misc/formatter/Formatter.m3, in the main body, line 1069, change DefineOp (PrintAlign, 5, 11) to DefineOp (PrintAlign, 4, 11) 4. In spite of their signatures, some routines in Rd don't raise Thread.Alerte d. Fix: in system/corelib/filerw/UFileRdWr.m3, in TerminalReaderSeek link 262, change RTScheduler.IOSelect to RTScheduler.IOAlertSelect Thanks to Norman Ramsey and David Nichols for reporting these bugs. - Bill Kalsow ------------------------------------------------------------------------------ Date: Fri, 5 Apr 1991 14:36:30 -0600 (CST) From: Dick Orgass Subject: Re: Status of M-3 Excerpts from netnews.comp.lang.modula3: 5-Apr-91 Status of M-3 lance.norskog@motcsd.csd (790) > What's the current status of DEC's Modula-3 system? Does it have > a port for the 386? 8086? Does it have a generic GNU-CC port? There is a port for AIX PS/2 in the SRC distribution; in runs on 386 and 486 systems. Though there are some small problems, it works quite well with both the product C compiler and with MetaWare's High C. Last summer, I tried to compile version 1.5 with gcc 1.37.0 but could not get the system to work; after replacing somewhere around a dozen gcc compiled binaries with High C compiled binaries, I gave up. Things might well be a good bit better wtih gcc 1.39.x. I probably won't try this because I don't want to take the time to build gcc. Later this afternoon, I'll post comments about the problems with the PS/2 version. Dick ------------------------------------------------------------------------------ Date: Fri, 5 Apr 1991 15:11:35 -0600 (CST) From: Dick Orgass Subject: SRC Modula-3 V 1.6 for AIX PS/2, V 1.2 There's a nit mistake of mine in the source file .ROOT/libs/aix-ps2-1-2/os/Udir.m3. Because of this nit, it is the case that libm3aix-ps2-1-2.a is a client of libm3data.a. Since the former library is linked with all user programs by default, this would also force linking with libm3data.a; not a very good idea considering the simple use of Char.NUL. Modify line 6 of Udir.m3 to be IMPORT Text; Modify line 23 of Udir.m3 to be: IF name[i] = '\000' THEN EXIT ELSE INC(nameLength) END The distributed configuration file, util/config.dist-AIX386, uses /usr/local/lib/cpp as the C preprocessor for imake because the product (ANSI) cpp and imake don't get along. This is a port of the 4.3 BSD cpp. The MIT version distributed with X11 might also work. The same three problems that I previously reported for the RISC 6000 port also appear with AIX PS/2 and there a few additional bugs depending on which C compiler is used. I suspect that something strange is happening in the compilation of the intermediate C file for Thread.m3 but haven't been able to find the problem. The three problems shared with the RISC 6000 port are: (1) tests/ptests/p083 There is an undefined symbol when the test program is linked; Eric reports that the link succeeds on DEC platforms. (2) demos/pickles/Graph4Test This pickle test program terminates with an unhandled exception Graph4Test.Bug which is raised at line 120 of Graph4Test.m3; the 6000 version is at line 115. (3) tools/pp/m3pp The pretty printer is not working correctly. When tools/pp/Main.m3 is formatted, there is an assert failure at line 588 of Formatter.m3; when tools/pp/Parse.i3 is formatted, there is an assert failure at line 913 of Formatter.m3. Similar problems come up when formatting other Modula-3 source files. The following problem occurs independent of the C compiler that is used to translate the intermediate C files: (4) Test case p032 fails in the following strange ways. If the input is from /dev/null (as in the imake file), there is an unhandled exception, Rd.Failure, followed by a error message concerning deadlock followed by a fairly large number of messages about a run time error dereferencing NIL; evenually the whole thing stops. If the input is from a real terminal, the everyting is ok unless the first input character is end-of-file (^D); in this case the program goes into a loop without producing any output. If the entire system is compiled using MetaWare's High C with or without optimization and with or without -g, the following problems come up: (5a) Test case p007 terminates with a Modula-3 runtime error concerning dereferencing NIL after the characters "16: " starting at the beginning of a line are emitted. (6a) Test case p008 terminates with a Bus Error and no Modula-3 error message immediately after the first line of output is produce. If the product C compiler, without optimization and without symbol tables is used the following problems come up: (5b) Test case p005 fails with a Modula-3 runtime error concerning an attempt to dereference NIL. (6b) All of the pickle test programs in demos/pickles fail with either a bus error or a Modula-3 runtime error concerning an attempt to dereference NIL. The solution that I adopted was to use the optimized High C version except for Thread.mo. For this module, I use /bin/cc to create a .s file. I edited the .s file to correct one incompatibility between the two compilers. For High C, a public char is one byte while for cc a public char is four bytes. This occurs exactly and only in identifiers that begin M3_EXPORTS_ and M3_IMPORTS_. This provided me with the best solution: Only p005 breaks and pickles are very close to working. Thanks to Eric Muller for doing a fine job on version 1.6 and for all his help while I was working on this port. Dick ------------------------------------------------------------------------------ Date: Fri, 5 Apr 91 17:56:43 PST From: amdcad!sun0!mri!woolsey (Jeff Woolsey) Subject: 1.6 experiences so far Fri Apr 5 14:31:41 PST 1991 Differences noted between m3-1.5 and m3-1.6 . First of all, the distribution is still inconvenient for Sys V.3 machines -- it's full of symbolic links and long filenames. This is where I ultimately want to run it. (Let's not construe this as doubting my sanity; this is driven by economic needs. :-) ) For now, I use a SPARCstation. I include here my experiences recompiling with 1.6 what previously compiled and ran with 1.5 . m3-1.6 enforces a slightly different language than 1.5 did. 1.5 accepts the following CASE statement while 1.6 complains: CASE something OF 1 => dothis() | 2 => dothat() | ELSE donothing() END; m3-1.6 is much more strict than 1.5 about importing an unsafe interface in a safe module (e.g. M3toC). Fortunately (or not) I was able to construct another safe interface that imported these things. At the moment I'm stuck at the following: m3 -c -g -k toa9.m3 M3 runtime error: Segmentation violation - possible attempt to dereference NIL Program /usr3/users/woolsey/sun4/lib/m3/m3compiler got fatal signal 3. *** Error code 1 make: Fatal error: Command failed for target `toa9.mo' I haven't yet had the time to isolate this case. Installation of this release on a SPARCstation, once I found enough disk space, was very clean. I'll also have to look into porting my change which provided file and line number information for some of the runtime faults (unless it has been incorporated into this release). (Namely these guys: _M3Runtime__AssertFault (); _M3Runtime__ReturnFault (); _M3Runtime__CaseFault (); _M3Runtime__TypecaseFault (); _M3Runtime__RangeFault (); _M3Runtime__NarrowFault (); ) -- Jeff Woolsey Microtec Research, Inc. 800 950 5554 amdcad!sun0!woolsey@amd.COM +1 408 980 1300 90% of my mail more than 3 hops away vanishes. Tell me why. ------------------------------------------------------------------------------ Date: Sat, 06 Apr 91 10:28:27 -0500 From: abbas@osf.org Subject: Re: M3 Newsletter mailing list Abbas Birjandi 7 Longfellow Rd. Wellesley, MA 02181 e-mail:birjandi@osf.osf.org ------------------------------------------------------------------------------ Date: 7 Apr 91 15:52:35 GMT From: mccalpin@perelandra.cms.udel.edu (John D. McCalpin) Subject: install trouble: 1.6 on IBMR2 I am running into an error that I cannot understand in the early stages of installation of 1.6 on an IBM RS/6000. After much fiddling (including telling imake to not delete its temporary makefiles), I isolated the problem to line 105 of util/m3fromC.tmpl. I don't understand the whole 'imake' process well enough to hazard a guess as to what is going on. Anybody have any ideas? The offending lines are: ======================================================================= #include "generic" /* When we compile Modula-3 files, we compile first the interfaces, then the implemenations */ interfaces:: implementations:: <-------- This is line 105 #include INCLUDE_IMAKEFILE ======================================================================= The log of the session is: ======================================================================= $ cd /usr/src/Lang/Modula3/dist-1.6 $ make system cd system; \ .ROOT/util/m3fromC; \ (cd corelib; .ROOT/util/m3all allObjs.o); \ (cd compiler; .ROOT/util/m3all link-compiler); cpp -I. -I.ROOT/util -I. make -f /tmp/Imf.NLgAB6 MAKE=.ROOT/util/imake MAKEFILE=Imakefile Make: 1254-040 Line number 105 of the description file must include a separator character. Quitting. .ROOT/util/imake: Exit code 1. Stop. 1254-004 The error code from the last failed command is 1. Make Quitting. ======================================================================= -- John D. McCalpin mccalpin@perelandra.cms.udel.edu Assistant Professor mccalpin@brahms.udel.edu College of Marine Studies, U. Del. J.MCCALPIN/OMNET ------------------------------------------------------------------------------ Date: Mon, 8 Apr 1991 12:50:15 +0100 From: Peter.Robinson@computer-lab.cambridge.ac.uk Subject: Re: 1.6 bugs | 4. In spite of their signatures, some routines in Rd don't raise | Thread.Alerted. | | Fix: in system/corelib/filerw/UFileRdWr.m3, | in TerminalReaderSeek link 262, | change RTScheduler.IOSelect | to RTScheduler.IOAlertSelect | | Thanks to Norman Ramsey and David Nichols for reporting these bugs. This fixes Norman Ramsey's problem, but a similar program that I have been struggling with still doesn't seem to work. The idea is to read a line of input from stdin with a 10 second timeout if nothing is read: MODULE Alerts EXPORTS Main; IMPORT Rd, Stdio, Thread, Time, Wr; TYPE Getter = Thread.Closure OBJECT text: TEXT; status := "latent"; METHODS apply := DoGet; END; Timer = Thread.Closure OBJECT interval: CARDINAL; victim: Thread.T; METHODS apply := DoTime; END; PROCEDURE DoGet (self: Getter): REFANY RAISES {} = BEGIN TRY self.status := "reading"; self.text := Rd.GetLine (Stdio.stdin); self.status := "finished"; EXCEPT Thread.Alerted => self.text := ""; self.status := "interrupted"; END; RETURN self; END DoGet; PROCEDURE DoTime (self: Timer): REFANY RAISES {} = BEGIN Time.LongPause (self.interval); Thread.Alert (self.victim); RETURN self; END DoTime; VAR getter := NEW (Getter); thread := Thread.Fork (getter); BEGIN EVAL Thread.Fork (NEW (Timer, interval := 10, victim := thread)); TRY EVAL Thread.AlertJoin (thread); Wr.PutText (Stdio.stdout, "normal join\n"); EXCEPT Thread.Alerted => Wr.PutText (Stdio.stdout, "alerted join\n"); END; Wr.PutText (Stdio.stdout, getter.status & "\n"); Wr.Close (Stdio.stdout); END Alerts. If I have understood it correctly, there should be three possible outcomes: 1. You type quickly and get a normal join with a status of finished. 2. You press return momentarily before the timer goes off and get an alerted join with a status of either reading or finished. 3. You type too slowly and get a normal join with a status of interrupted. The first works just fine. The second occurs with probability approximately zero and has not been tested experimentally. The third is giving problems. Until the latest release, it simply did not work; Rd.GetLine never raised Alerted. With the fix to UFileRdWr.m3, the thread executing getter still seems to be waiting on a select for terminal, even after being marked as alerted. The transcript goes as follows: $ Alerts test normal join interrupted $ test: Command not found. $ The line "test" is typed taking more than 10 seconds, but the alert is only raised when the line is completed. However, the input is then ignored and so is picked up by the shell as the next command. My guess is that the scheduler is proceeding as follows: 1. getter is forked and the thread descheduled pending a select for the read. 2. timer is forked and the thread descheduled pending a select for the timeout. 3. The scheduler blocks on a select for the read or the timeout. 4. The timeout occurs and its thread is rescheduled; it marks getter as alerted and exits. 5. The scheduler ignores the fact that getter is marked as alerted and blocks on another select for the read. 6. When the line of typing is completed, the select returns, the scheduler notices the alert and duly raises Alerted, without the line being read. Of course, I may have got hold of the wrong end of the stick. Advice welcomed. - Peter Robinson. ------------------------------------------------------------------------------ Date: 8 Apr 91 15:08:29 GMT From: nr@atomic.Princeton.EDU (Norman Ramsey) Subject: Re: 1.6 bugs In article Peter.Robinson@computer-lab.cambridge.ac.uk writes: > This fixes Norman Ramsey's problem, but a similar program that I have been > struggling with still doesn't seem to work. You're not alone, Peter---the toy I posted now works, but my ``real'' program doesn't work yet---I have to hit a carriage return to terminate a ``select'' call before my thread is alerted and my program will terminate. This problem isn't serious enough for me to take the time to produce a toy that demonstrates the problem. Norman -- Norman Ramsey nr@princeton.edu ------------------------------------------------------------------------------ Date: Mon, 8 Apr 91 10:43:47 PDT From: Subject: Re: 1.6 bugs Sure enough, the scheduler's polling loop wasn't checking for alerts in the threads that were blocked in I/O or timers. Fix: system/corelib/thread/Thread.m3, in Thread.Yield, lines 332 - 387 change: CASE t.state OF | State.pausing => <<< case body 1 >>> | State.blocking => <<< case body 2 >>> ELSE (* do nothing, these are not interesting *) END; to: CASE t.state OF | State.pausing => IF (t.alertable) AND (t.alertPending) THEN CanRun (t); ELSE <<< case body 1 >>> END; | State.blocking => IF (t.alertable) AND (t.alertPending) THEN CanRun (t); ELSE <<< case body 2 >>> END; ELSE (* do nothing, these are not interesting *) END; - Bill Kalsow ------------------------------------------------------------------------------ Date: 9 Apr 91 14:40:58 GMT From: orgass+@rchland.ibm.com (Dick Orgass) Subject: Re: install trouble: 1.6 on IBMR2 In the referenced message, John McCalpin describes a problem with make/imake on RISC 6000 systems (called IBMR2 in the Modula-3 distribution). John's problem is related to the interaction between cpp and imake. The following is an explanation and a solution to the problem that John appears to be describing. The design and implementation of imake assumes a BSD style C preprocessor and the distributed source (.ROOT/util/imake.c) has code for getting along with System V style C preprocessors. The difference between the two styles that is of interest here is the treatment of tabs. BSD style preprocessors leave tabs in place while System V style preprocessors compress them to spaces. The C preprocessor, /lib/cpp, provided with the AIX 3.1 C compiler is a strict ANSI C preprocessor which cannot be used with imake because of output format incompatibilities. The MIT X distribution includes a version of cpp that is System V like and which can be used with imake. For AIX 3.1, this is in directory /usr/lpp/X11/Xamples/util/cpp. This version of cpp can be used with imake (both the MIT version and the source distributed with SRC Modula-3 -- .ROOT/util/imake.c) provided that one change is made to the source file .ROOT/util/imake.c: Modify line 129 so that it reads as follows: #if defined(sun) || defined(SYSV) || defined(hpux) || (defined(_IBMR2) && defined(_AIX)) [The above is a single line but it may be wrapped in transit through various mailers.] If imake is built from the resulting source file and if the version of cpp from the MIT X distribution is used, imake will work correctly for IBMR2. Dick ------------------------------------------------------------------------------ Date: 9 Apr 91 18:34:33 GMT From: nr@.Princeton.EDU (Norman Ramsey) Subject: Vague design question I wish to create an object that represents a target program suitable for debugging. For simplicity's sake, let me say that the target may be in one of three states: Disconnected: I have symbol table information but no process is executing the target program. Stopped: I am connected to a process that is executing the target program but is currently awaiting instructions from the debugger. Running: I am connected to a process that is executing the target program and is not listening to the debugger. Now, given methods may or may not apply depending on the state. For example, a ``connect'' method applies only to a target in a disconnected state; only a stopped target can be continued, &c. One possible strategy is to use subtyping to distinguish various states, but since targets can change states, many methods would have to return new targets (and somehow invalidate the old ones). Here's an example of that style: TYPE T <: ROOT; Disconnected = T OBJECT METHODS connect(pid:Pid.T):Stopped; END; Stopped = T OBJECT METHODS continue():Running; END; Running = T OBJECT METHODS interrupt():Stopped; END; Worries about this technique: -- clients of the interface must track which subtype they have -- all state-changing methods must invalidate the old object, and all methods must ensure their arguments are valid objects -- what if I can't shoehorn my methods into a single inheritance hierarchy? An alternate technique would be to have a single target type that includes a state: TYPE State = {Disconnected, Stopped, Running}; T <: OBJECT state: State; METHODS connect(pid:Pid.T); (* Disconnected --> Stopped *) continue(); (* Stopped --> Running *) interrupt(); (* Running --> Stopped *) END; Advantages: -- clients need not track which state the target is in, provided they handle exceptions when operations are applied to the wrong state. Troubles: -- all methods must ensure their arguments are in valid states -- specification of what methods do to the states might get complicated I'm leaning toward the second solution, probably just because it's more like non-object-oriented programming, and problems I encounter are likely to be familiar ones. I would appreciate hearing people's comments about this problem, or about experience they've had with similar problems. -- Norman Ramsey nr@princeton.edu ------------------------------------------------------------------------------ Date: Tue, 9 Apr 91 19:50:17 GMT From: craig@leland.Stanford.EDU (Craig Chambers) Subject: Re: Vague design question Dynamic inheritance ala Self would be a convenient mechanism to provide the cha nging behavior modes of the single debuggee object. The interface to clients would b e something much along the lines of your second proposal, but the internal implementation w ould be more well organized and factored. Since M3 doesn't support dynamic inheritance , you could simulate it with a wrapper object whose single instance variable was chan ged from one internal state to another; the wrapper object forwards messages to the cont ained instance variable. -- Craig Chambers ------------------------------------------------------------------------------ Date: Wed, 10 Apr 91 18:03:33 MET DST From: Thomas Roemke Subject: Local procedure assignment (Bug in M3 1.6 SPARC)? Assigning a local procedure is illegal. In the case of procedure variables the compiler has to generate code for verifying this at runtime. The pro- gram below has to raise an exception (or just terminate execution??), since the second assignment to x is illegal (i.e. a local procedure). Am I right ? MODULE LProcAssign EXPORTS Main; VAR x: PROCEDURE (); PROCEDURE q(p: PROCEDURE (); b: BOOLEAN := TRUE) = PROCEDURE z() = BEGIN END z; BEGIN x := p; (* runtime check (b = FALSE => runtime error) * ) IF b THEN q(z,FALSE); (* correct, local z *) END END q; PROCEDURE z() = BEGIN END z; BEGIN q(z); (* correct, global z *) END LProcAssign. Thomas -- (* Thomas Roemke, University of Paderborn, Germany modula-3@uni-paderborn.de ..!uunet!mcsun!unido!pbinfo!modula-3 *) ------------------------------------------------------------------------------ Date: 10 Apr 91 15:23:10 GMT From: buschman@tubsibr.uucp (Andreas Buschmann) Subject: DISPOSE statement and other pointer related question Hallo, In the Modula3 report Page 49: A DISPOSE Statement has the form: DISPOSE (v) where v is a writable designator with a fixed or object reference type. If v is untraced, the statement frees the storage for v's referent and sets v to NIL. Freeing storage to which active references remain is an unchecked runtime error. (a) If v is traced, the statement is equivalent to v := NIL. If v is NIL, the statement is a no-op. (b) Two questions rise here: a) is this an unchecked runtime error if and only if v is untraced, or is it one if v is traced, too? b) is this if and only if v is tracedm or if it is untraced, too? As I'm writing an interpreter for a subset of Modula3, the answer is at least interesting for the memory management. Ah, some additional questions: - is (a) the reason for DISPOSE beeing an unsafe operation? - is there a version of the repost in ascii, or dvi format to filter through dvi2tty, to get a report I can grep in? - I have't found a save way (without using unsafe features) getting a checked reference onto a variable, or on a part of a structure or array. I wan't the same effect as in ALGOL68 writing: INT ii := 20; REF INT iii := ii; write (iii) which doesn't make much at the first glance, but is necessary for some iterative rewritings of recursive algorithms for linked list inserting. For my interpreter I created a procedureal operator LOCATION: LOCATION (VAR x: Any) : REF Any How is this supposed to go in the new standard? I am not so happy with th long name LOCATION, but dont want to use the abbeviation LOC because of its different meaning in Algol68 as a local storage allocator in contrast to HEAP, which is semantically equivalent to NEW in m3. Tschuess Andreas ------------------------------------------------------------------------------ Date: 10 Apr 91 19:00:23 GMT From: yost@calvin.Berkeley.EDU (Dave Yost) Subject: Zortech Modula-3? I just called Zortech at 800-848-8408 and spoke with Adrian Reynolds, Director of Marketing. (I was prompted by the mailer I just got announcing the release of their C++ compiler for the Mac. That's what made me think to call them. He hadn't heard of Modula-3. I directed him to Sam Harbison's Nov 90 Byte article. He seemed interested in the prospect of catching the wave early. Everyone else interested in Modula-3 (except perhaps other vendors who want to sell compilers :-) might think about calling him too. You know how something starts to sound like a trend when you hear it from different sources. The non-800 number is 617-937-0696. --dave yost ------------------------------------------------------------------------------ Date: 10 Apr 91 21:33:12 GMT From: al158305@mtecv2.mty.itesm.mx (Gustavo Cordova Avila) Subject: Porting to Amiga Hi! This is the first time I post to this group, although I've been reading it for some time now. Has anybody ported the DEC implementation to the Amiga OS? Or, if nobody has, I'd like to undertake the project, but the question is: How big are the sources and in what languaje are they? I know it must be a dumb question, but somebody's gotta ask it :) Gustavo -- | From Mexico! Majoring in Electronics Systems Engineering, | | ITESM presents to you: Gustavo Cordova Avila!!! | | And then I woke up :) +------------------------------------+ +-----------------------+ ------------------------------------------------------------------------------ Date: 11 Apr 91 16:07:56 GMT From: nr@cs.Princeton.EDU (Norman Ramsey) Subject: Question about Thread.AlertJoin I note: PROCEDURE AlertJoin (t: T): REFANY RAISES {Alerted}; (* Like Join, but if the thread is marked alerted at the time of call or sometime during the wait, raise Alerted. Implementations may raise additional exceptions. *) I assume ``the thread'' referred to is the thread executing AlertJoin, not the thread t which is the argument to AlertJoin? -- Norman Ramsey nr@princeton.edu ------------------------------------------------------------------------------ Date: Thu, 11 Apr 91 13:13:48 PDT From: Subject: Re: Question about Thread.AlertJoin > PROCEDURE AlertJoin (t: T): REFANY RAISES {Alerted}; > (* Like Join, but if the thread is marked alerted at the time of call or > sometime during the wait, raise Alerted. Implementations may raise > additional exceptions. *) > I assume ``the thread'' referred to is the thread executing AlertJoin, > not the thread t which is the argument to AlertJoin? Yes. - Bill Kalsow ------------------------------------------------------------------------------ Date: Thu, 11 Apr 91 13:18:04 PDT From: Subject: Re: Local procedure assignment (Bug in M3 1.6 SPARC)? > Assigning a local procedure is illegal. In the case of procedure variables > the compiler has to generate code for verifying this at runtime. The pro- > gram below has to raise an exception (or just terminate execution??), since > the second assignment to x is illegal (i.e. a local procedure). Am I right ? Yes, the second assignment 'x := p' where p = q.z is a checked runtime error. The Modula-3 Report does not specify the behavior of a checked runtime error. SRC Modula-3 terminates with a core dump (or at least it should) on all checked runtime errors. - Bill Kalsow ------------------------------------------------------------------------------ Date: Thu, 11 Apr 91 13:23:12 PDT From: Subject: Re: Question about Thread.AlertJoin Norman Ramsey asks: PROCEDURE AlertJoin (t: T): REFANY RAISES {Alerted}; (* Like Join, but if the thread is marked alerted at the time of call or sometime during the wait, raise Alerted. Implementations may raise additional exceptions. *) I assume ``the thread'' referred to is the thread executing AlertJoin, not the thread t which is the argument to AlertJoin? Correct. More evidence of the need for Larch Modula-3. ------------------------------------------------------------------------------ Date: Thu, 11 Apr 91 13:36:37 PDT From: Subject: Re: DISPOSE statement and other pointer related question > A DISPOSE Statement has the form: > > DISPOSE (v) > > where v is a writable designator with a fixed or object reference > type. > If v is untraced, the statement frees the storage for v's referent > and sets v to NIL. > Freeing storage to which active references remain is an unchecked > runtime error. (a) > If v is traced, the statement is equivalent to v := NIL. > If v is NIL, the statement is a no-op. (b) > > Two questions rise here: > a) is this an unchecked runtime error if and only if v is untraced, > or is it one if v is traced, too? The statement labeled (a) above is true, it doesn't depend on v. The statement doesn't have much to do with DISPOSE, except that DISPOSE is the only language defined way to free storage. The following statement says that if v is traced, "DISPOSE (v)" is equivalent to "v := NIL". Since that assignment doesn't free storage, it cannot cause an unchecked runtime error. > b) is this if and only if v is traced or if it is untraced, too? The statement (b) is true for both traced and untraced v's. > - is (a) the reason for DISPOSE beeing an unsafe operation? Yes, anything that can cause unchecked runtime errors is unsafe. > - is there a version of the repost in ascii, or dvi format to > filter through dvi2tty, to get a report I can grep in? No. > - I have't found a save way (without using unsafe features) getting > a checked reference onto a variable, or on a part of a structure > or array. I wan't the same effect as in ALGOL68 writing: > > INT ii := 20; > REF INT iii := ii; > write (iii) > > which doesn't make much at the first glance, but is necessary for > some iterative rewritings of recursive algorithms for linked list > inserting. Right, Algol68 REFs are not the same as Modula-3 REFs. > For my interpreter I created a procedureal operator LOCATION: > > LOCATION (VAR x: Any) : REF Any > > How is this supposed to go in the new standard? I don't understand. Are you proposing that LOCATION be added to the language? If so, you should post a full explanation of the proposal and its impact. For instance, it appears to me that LOCATION would place great constraints on the possible allocator/collector implementations. Since I can use LOCATION to create a REF to an arbirary field in an arbitrary record, the collector cannot assume that type tags are near by? - Bill Kalsow ------------------------------------------------------------------------------ Date: Thu, 11 Apr 91 13:50:06 PDT From: Subject: Re: Porting to Amiga > Has anybody ported the DEC implementation to the Amiga OS? I don't know of any such ports. > How big are the sources and in what languaje are they? SRC Modula-3 isn't the smallest possible Modula-3 system. The current distribution is just under 5MB compressed. It's around 15MB uncompressed. That includes the Modula-3 sources for the compiler and libraries and enough C "object code" to bootstrap the system. The compiler proper is about 33K lines of Modula-3 or 1.2 MB. - Bill Kalsow ------------------------------------------------------------------------------ Date: 12 Apr 91 10:43:04 GMT From: sakkinen@jyu.fi (Markku Sakkinen) Subject: Two Oberon questions (I suppose these are currently the two most appropriate groups for discussions about Oberon.) First question: How is the type equivalence of two objects really defined in Oberon? Modula-2 has "name equivalence", but Modula-3 has gone over to structural equivalence (in my opinion: unfortunately). Wirth's original language definition in Software - Practice and Experience (July 1988) sidesteps this question rather completely. However, it is not even allowed to use the name of a previously defined procedure type to declare the type of a procedure being defined. This is a kind of structural equivalence. On the other hand, type equivalence is not mentioned among the differences in the companion paper (same issue of S-P&E) "From Modula to Oberon". Second question: Can function procedures in Oberon return structured values? In Modula-2 they cannot, but in Modula-3 this defect has been corrected. Again, the language definition carefully avoids saying anything (which would imply "yes"), but neither is this mentioned as a difference from Modula-2 (which would imply "no"). Common addition to both questions: Has the principle perhaps even been changed over the years? Do different implementations of Oberon differ? Markku Sakkinen Department of Computer Science and Information Systems University of Jyvaskyla (a's with umlauts) PL 35 SF-40351 Jyvaskyla (umlauts again) Finland SAKKINEN@FINJYU.bitnet (alternative network address) ------------------------------------------------------------------------------ Date: 13 Apr 91 01:42:29 GMT From: preston@ariel.rice.edu (Preston Briggs) Subject: Re: Two Oberon questions sakkinen@jytko.jyu.fi (Markku Sakkinen) writes: >First question: >How is the type equivalence of two objects really defined in Oberon? >Modula-2 has "name equivalence", but Modula-3 has gone over to >structural equivalence (in my opinion: unfortunately). >Wirth's original language definition in Software - Practice and Experience >(July 1988) sidesteps this question rather completely. In a later paper, perhaps about the Oberon system, Wirth let slip that Oberon (the language) uses name equivalence. Of course, you have to make these exceptions for procedure passed as parameters, and pretty soon you end up wishing he had just said structural equivalence and let it go at that. >Can function procedures in Oberon return structured values? Nope. This one is in the report, somewhere. Of course, I may be out of date. Preston Briggs ------------------------------------------------------------------------------ Date: 15 Apr 91 04:33:11 GMT From: eepjm@cc.newcastle.edu.au Subject: Re: Two Oberon questionsREAD/NEW/FOLLOWUP In article <1991Apr12.104304.4194@jyu.fi>, sakkinen@jyu.fi (Markku Sakkinen) writes: > ... > Second question: > Can function procedures in Oberon return structured values? > In Modula-2 they cannot, but in Modula-3 this defect has been corrected. > Again, the language definition carefully avoids saying anything > (which would imply "yes"), but neither is this mentioned as a difference > from Modula-2 (which would imply "no"). For some time now I have been telling my students that Modula-2 removed the rather pointless Pascal restriction on the type of a function result. I based this claim on two observations: (a) the M-2 compiler which I use does allow structured values to be returned; (b) Wirth's books on the subject avoid saying anything about it (which, as above, implies "yes"). Am I wrong? If so, to whom do I complain? Surely we don't have to go back to forcing M-2 programmers to memorise the totally artifical distinction between "structured" and "unstructured". Peter Moylan eepjm@cc.newcastle.edu.au P.S. (Totally different topic, but while I think of it .... Does the emerging Modula-2 standard say how to declare a structured constant? This is something which definitely needs standardising : most compiler writers recognise that there must be a facility to declare, for example, an array of constants, but so far this feature has not been portable.) ------------------------------------------------------------------------------ Date: Mon, 15 Apr 91 11:51:17 +0200 From: buschman@tubsibr.uucp (Andreas Buschmann) Subject: DISPOSE statement and other pointer related question Hi! I tried to place this in comp.lang.modula3, but it bounced, so I retry it via the mailing list. Tschuess Andreas /|) Andreas Buschmann /-|) TU Braunschweig, Germany (West) ^^^^ was bitnet: buschman%tubsibr@dbsinf6.bitnet uucp: buschman@tubsibr.uucp p.s. it bounced at compuserve.com, but I don't know what I have done wrong. so here it is again: Hallo, In the Modula3 report Page 49: A DISPOSE Statement has the form: DISPOSE (v) where v is a writable designator with a fixed or object reference type. If v is untraced, the statement frees the storage for v's referent and sets v to NIL. Freeing storage to which active references remain is an unchecked runtime error. (a) If v is traced, the statement is equivalent to v := NIL. If v is NIL, the statement is a no-op. (b) Two questions rise here: a) is this an unchecked runtime error if and only if v is untraced, or is it one if v is traced, too? b) is this if and only if v is tracedm or if it is untraced, too? As I'm writing an interpreter for a subset of Modula3, the answer is at least interesting for the memory management. Ah, some additional questions: - is (a) the reason for DISPOSE beeing an unsafe operation? - is there a version of the repost in ascii, or dvi format to filter through dvi2tty, to get a report I can grep in? - I have't found a save way (without using unsafe features) getting a checked reference onto a variable, or on a part of a structure or array. I wan't the same effect as in ALGOL68 writing: INT ii := 20; REF INT iii := ii; write (iii) which doesn't make much at the first glance, but is necessary for some iterative rewritings of recursive algorithms for linked list inserting. For my interpreter I created a procedureal operator LOCATION: LOCATION (VAR x: Any) : REF Any How is this supposed to go in the new standard? I am not so happy with th long name LOCATION, but dont want to use the abbeviation LOC because of its different meaning in Algol68 as a local storage allocator in contrast to HEAP, which is semantically equivalent to NEW in m3. Tschuess Andreas ------------------------------------------------------------------------------ Date: Mon, 15 Apr 91 15:54:25 +0200 From: buschman@tubsibr.uucp (Andreas Buschmann) Subject: LOCATION Hi! > > For my interpreter I created a procedureal operator LOCATION: > > > > LOCATION (VAR x: Any) : REF Any > > > > How is this supposed to go in the new standard? > > I don't understand. Are you proposing that LOCATION be added to the > language? If so, you should post a full explanation of the proposal > and its impact. For instance, it appears to me that LOCATION would > place great constraints on the possible allocator/collector implementations. > Since I can use LOCATION to create a REF to an arbirary field in an > arbitrary record, the collector cannot assume that type tags are near by? > > - Bill Kalsow no, I am not sure about proposing this to be added to the language. At this moment it is a local hack of mine, which doesn't interfere with my heap storage implementation (I am using bitmaps to keep track of which storage is still in use). What I want to know is: how do I get the same effect, with legal actions defined in Modula3. Tschuess Andreas A C example of what I want to do: typedef struct node { struct node *next; int info; } NODE; #define NO_NODE ((NODE*) 0) insert (NODE **list; NODE *new_node) { NODE **ptr; for (ptr = list; *ptr != NO_NODE && (*ptr) -> info < new_node -> info; ptr = &((*ptr) -> next)); new_node -> next = *ptr; *ptr = new_node; } in Algol68 this would be: MODE NODE = STRUCT ( REF NODE next; INT info ); REF NODE no node = NIL; PROC insert (REF REF NODE list; REF NODE new node) = BEGIN REF REF NODE ptr; ptr := list; WHILE (ptr <> no node | info OF ptr < info OF new node | false) DO ptr := next OF ptr OD; next OF new node := ptr; REF NODE ptr := new node END ------------------------------------------------------------------------------ Date: Mon, 15 Apr 91 09:26:22 PDT From: Subject: Re: LOCATION I don't think it's possible to simulate LOCATION in Modula-3. It's possible to LOOPHOLE ADDRESSs to REFANYs in the unsafe part of the langugage. There's no guarantee that the result is usable. - Bill Kalsow ------------------------------------------------------------------------------ Date: Mon, 15 Apr 91 10:37:38 PDT From: Subject: Re: Local procedure assignment (Bug in M3 1.6 SPARC)? I tried Thomas Roemke's program here. The compiler doesn't generate the correct code when it calls "q(z,FALSE)". Since the local procedure q.z doesn't depend on any values in its parent's frame, the compiler decides that it can be passed like a top-level procedure. This is a bug. Adding "VAR zb := b;" as a local declaration in q.z causes the compiler to emit the correct code. Thanks for the bug report. - Bill Kalsow. ------------------------------------------------------------------------------ Date: Tue, 16 Apr 91 10:46:56 -0400 From: hudson@yough.cs.umass.edu (Rick Hudson) Subject: LOCATION buschman@tubsibr writes: > Hi! > > > For my interpreter I created a procedural operator LOCATION: > > > > > > LOCATION (VAR x: Any) : REF Any > > > > > > How is this supposed to go in the new standard? > > > > I don't understand. Are you proposing that LOCATION be added to the > > language? If so, you should post a full explanation of the proposal > > and its impact. For instance, it appears to me that LOCATION would > > place great constraints on the possible allocator/collector implementations . > > Since I can use LOCATION to create a REF to an arbitrary field in an > > arbitrary record, the collector cannot assume that type tags are near by? > > > > - Bill Kalsow > > no, I am not sure about proposing this to be added to the language. At > this moment it is a local hack of mine, which doesn't interfere with > my heap storage implementation (I am using bitmaps to keep track of > which storage is still in use). What I want to know is: how do I get > the same effect, with legal actions defined in Modula3. Module-3 the language has outlawed such actions. Bill Kalsow has indicated a one of the reasons. When I implement list manipulating routines I tend to do it recursively. If I am concerned about efficiency, I restrict my recursion to be tail recursion. Any reasonable compiler will optimize away the tail recursion leaving me with readable and efficient code :-). - Rick ------------------------------------------------------------------------------ Date: 17 Apr 91 12:53:54 GMT From: sakkinen@jyu.fi (Markku Sakkinen) Subject: Re: Two Oberon questions In article <1991Apr12.104304.4194@jyu.fi> I asked: >First question: >How is the type equivalence of two objects really defined in Oberon? > ... >Wirth's original language definition in Software - Practice and Experience >(July 1988) sidesteps this question rather completely. > ... It seems that this crucial issue really remains undefined! I could not find any mention of it even in the newest revision (Oct. 1990) of the language report, as available by anonymous FTP from ETH Zurich. >Second question: >Can function procedures in Oberon return structured values? > ... Oh dear, already the original language report clearly said 'no' in subsection 10.1; how could I have failed to note it? Therefore, no improvement over Pascal and Modula-2, unfortunately. However, since SET is one basic type in Oberon (instead of constructed set types as in Pascal and Modula-2), it is allowed as a return type. >Common addition to both questions: >Has the principle perhaps even been changed over the years? >Do different implementations of Oberon differ? According to the answers I received, implementations apply "name equivalence" to types. Thanks once again to everybody who sent answers or comments! Markku Sakkinen Department of Computer Science and Information Systems University of Jyvaskyla (a's with umlauts) PL 35 SF-40351 Jyvaskyla (umlauts again) Finland SAKKINEN@FINJYU.bitnet (alternative network address) ------------------------------------------------------------------------------ Date: Wed, 17 Apr 1991 17:47:24 -0500 (CDT) From: Dick Orgass Subject: Nit on Wr.i3 In one sense, this question is a real nit but there is a longer term performance question behind the nit. The procedures Wr.PutString and UnsafeWr.FastPutString are both declared so that the second parameter, the ARRAY OF CHAR to be written is a value parameter. This forces the compiler to write code to copy the array just to again copy it into the writer's buffer; the intermediate copy is then destroyed. By examining the code of the implementations of these procedures (in WrMove.m3), it's easy to see that the actual parameters are not modified. I propose that the declaration of these procedures be changed as follows: In Wr: PROCEDURE PutString(wr: T; READONLY a: ARRAY OF CHAR) RAISES {Failure, Alerted, Error}; In UnsafeWr: PROCEDURE FastPutString(wr: Wr.T; READONLY a: ARRAY OF CHAR) RAISES {Failure, Alerted, Error}; Dick ------------------------------------------------------------------------------ Date: 17 Apr 91 07:23:14 GMT From: brandis@inf.ethz.ch (Marc Brandis) Subject: Re: Two Oberon questions In article <1991Apr12.104304.4194@jyu.fi> sakkinen@jytko.jyu.fi (Markku Sakkine n) writes: >How is the type equivalence of two objects really defined in Oberon? >Modula-2 has "name equivalence", but Modula-3 has gone over to >structural equivalence (in my opinion: unfortunately). Oberon uses name equivalence as does Modula-2. There are two special cases in which structural equivalence is used: Open arrays and procedure variables. >Can function procedures in Oberon return structured values? No. There are good reasons not to allow this. It is rather complicated to implement and it is hard to find good examples where you need it. If you want to return a structured value, you would have to first assemble it into a local variable, which would then be copied to the final destination. In an efficient implementation, this would be an implicit VAR parameter. The common idea in Wirth's languages is not to hide what is going on, so in this respect it is better to declare the VAR parameter explicitly and to assemble the result directly into it. Note that you cannot use the result of such a function in an expression. All what you could do with it would be to assign it to another variable or to pass it to a procedure as a parameter. If you look at the intended programming style in Oberon, you will see that structure assignments and passing of structures as value-parameters occurs rarely. >Do different implementations of Oberon differ? The implementations of Oberon implemented at ETH do not. I cannot comment on other implementations, but I guess that the answer is also no. Marc-Michael Brandis Computer Systems Laboratory, ETH-Zentrum (Swiss Federal Institute of Technology ) CH-8092 Zurich, Switzerland email: brandis@inf.ethz.ch ------------------------------------------------------------------------------ Date: Thu, 18 Apr 1991 19:31:34 GMT From: vsanchez@casbah.acns.nwu.edu (Victor Sanchez) Subject: Re: Two Oberon questions >In article <1991Apr12.104304.4194@jyu.fi> sakkinen@jytko.jyu.fi (Markku Sakkin en) writes: > >>Can function procedures in Oberon return structured values? > No. But it is not needed (I think). Please somebody correct me if I am wrong, but if you have automatic garbage collection you can use the pointers to structures in a more flexible way. e.g. suppose we are writing a set of function that perform operations on matrices. We define a structure called Matrix. We would like the functions to return a matrix structure so we can chain the operations: a = MultMat(a,AddMat(b,c)); instead of AddMat(b,c,temp1); MultMat(a,temp1,a); This cannot be done if the functions deal with pointers to Matrices, because, for example the routine MultMat cannot DISPOSE(a) and then assign it the new pointer to the structure. If garbage collection exists then we can happily change the place in memory pointer "a" is pointing to, the garbage collector will realize that the old memory pointed by "a" is not used anymore and make it available. So you can now use pointers to structures complety to replace return structures, perhaps one pays a price for that, but returning structures is not very efficient anyways. Is this correct? Or am I missunderstanding the way garbage collection works? Victor Sanchez ------------------------------------------------------------------------------ Date: Fri, 19 Apr 91 06:13:18 GMT From: treese@crl.dec.com (Win Treese) Subject: SRC compiler run-time error Not that it's a major problem, but the following interface: INTERFACE Foo; <*EXTERNAL> PROCEDURE bar(i: INTEGER) RAISES {}; END Foo. which is missing an asterisk in the EXTERNAL pragma, has the following problem when compiled: 38 caddo> m3 -c foo.m3 M3 runtime error: Text.Cat: NIL argument Win Treese Cambridge Research Lab treese@crl.dec.com Digital Equipment Corp. ------------------------------------------------------------------------------ Date: Fri, 19 Apr 91 00:52:38 PDT From: Subject: Re: Two Oberon questions [sakkinen] Can function procedures in Oberon return structured values? [brandis] No. There are good reasons not to allow this. It is rather complicated to implement and it is hard to find good examples where you need it. I suppose this is true, provided one looks for such examples only in programs written in C, Pascal, Modula-2, or Oberon... Seriously, there are many applications that *scream* for structured return parameters: complex numbers, intervals, rectangles, points and lines, tagged pointers, array descriptors, etc, etc. Here at SRC we program in an extension of Modula-2 that supports structured results; they are used extensively in our system software, and I at least find them indispensable. [brandis] If you want to return a structured value, you would have to first assemble it into a local variable, which would then be copied to the final destination. In an efficient implementation, this would be an implicit VAR parameter. The common idea in Wirth's languages is not to hide what is going on, so in this respect it is better to declare the VAR parameter explicitly and to assemble the result directly into it. Using explicit VAR parameters to return results makes programs much more prolix and unreadable than necessary. The programmer not only has to declare (and invent names for) the temporary variables, but is also forced to use an assembly-like, bottom-up coding style. Compare VAR t1, t2, t3: Complex.T; Add(a, b, t1); Sub(c, d, t2) Mul(t1, t2, t3); Sub(t3, u, x) with x := Sub(Mul(Add(a, b), Add(c, d)), u) As for "not to hide what is going on,", please note that high-level languages were invented specifically to hide the boring details of programs that are best handled by the computer. Considering the relative costs of computer cycles vs. programming manpower, one could almost say that any coding technique that can be automated *should* be automated. In particular, the implicit VAR parameter method labeled by the poster as "complicated to implement" seems actually quite trivial to me, and certainly worth the benefit. Am I missing something? --jorge ------------------------------------------------------------------------------ Date: Fri, 19 Apr 91 00:53:10 PDT From: Subject: Re: Two Oberon questions [sakkinen] Can function procedures in Oberon return structured values? [vsanchez] ... if you have automatic garbage collection you can use the pointers to structures ... perhaps one pays a price for that, but returning structures is not very efficient anyway. Garbage collection and pointers can replace structured return values in some uses, but not all. It should cost only two or three instructions to return a two-word record as a procedure result. If you account for the cost of running the garbage collector, allocating that same record from the heap may well cost thousands of instructions---two or three orders of magnitude more. So, the pointer/heap solution is acceptable only in some cases: for low-intensity uses, for large structures, for values that will get copied many times, etc.. For many other uses (complex numbers, points, dates, etc.) structured return values will be a lot cheaper. Moreover, in languages like Modula-2 and Pascal, the use of heap records requires extra code: NEW calls, "^" operators, temporary variables. Structured return values are more natural and easier to use. Finally, allowing structured return values does not mean making the language more complex; on the contrary, it means removing a rather arbitrary rule... Jorge Stolfi DEC Systems Research Center, Palo Alto stolfi@src.dec.com ---------------------------------------------------------------------- DISCLAIMER: Don't blame me, I'm only a user. ------------------------------------------------------------------------------ Date: Fri, 19 Apr 91 08:51:12 GMT From: Marc Wachowitz Subject: Structure return (was Re: Two Oberon questions) Recently there were comments saying returning structures were difficult to implement or inefficient. I don't think this is the case. Just have the caller suplly the address where the result is expected. If it's a variable (i.e. the call was of the form variable := Func() ), the final code is the same as with VAR parameters, so it's obviously not particularly difficult or inefficient. If the call is part of an expression (which implies it's the argument of another procedure call), the caller just allocates the space for the argument on the call stack and passes its address to the structure-returning procedure. There is no temporary local variable in the callee, access goes through this address. So it's again the same as a VAR parameter. The only difference is that you don't need to supply variables explicitly, but they are implicitly allocated by the compiler on the call stack, which is probably not very expensive. Example, which also shows the usefulnes of structure returns, assuming there's a notation for structure values (meaning should be obvious): TYPE Complex = RECORD re, im: REAL END; PROCEDURE Sum(a, b: Complex): Complex; BEGIN RETURN Complex(a.re + b.re, a.im + b.im) END Sum; Similar definition for PROCEDURE Prod(a, b: Complex): Complex; Now you can write expressions like a := Sum(x, Prod(y, z)) similar to normal formulae (a := x + y * z). With VAR parameters only you had to write: PROCEDURE Add(VAR a: Complex; b: Complex); BEGIN a.re := a.re + b.re; a.im := a.im + b.im; END Sum; Similar for PROCEDURE Mul(VAR a: Complex; b: Complex); VAR temp: Complex; ... a := y; Mul(a, z); Add(a, x); Now imagine the expression were much more complex. You would end up playing the role for a FORmular TRANslator, instead of the compiler doing such simple things for you. Using pointers instead does provide for the same notation as the value passing method, but the performance penalty may be high if you must (read: cannot) cooperate with a traditional environment of library functions etc. This would only change if all variables were pointers (as in LISP systems), which would allow the application of generational incremental garbage collection. As far as I know, there's yet no implementation of this for "uncooperative" environments. ------------------------------------------------------------------------------ Date: Fri, 19 Apr 91 14:57:30 MET DST From: Thomas Roemke Subject: ASSERT vs. error message The program below contains an illegal default method value for p. I expected to get an error message like ''default is incompatible with method t ype'', but instead I got: M3 runtime error, "Type.m3":473: ASSERT failed Program /homes/thor/modula-3/m3_1.6/lib/m3/m3compiler got fatal signal 3. Why are you using an ASSERT ? Is the computation of ''is AB a supertype of A'' more complex than calculating A <: AB ? MODULE bugtest EXPORTS Main; TYPE A = OBJECT a: INTEGER METHODS p() := Pab END; AB = A OBJECT b: INTEGER END; PROCEDURE Pab(self: AB) = BEGIN END Pab; BEGIN END bugtest. Thomas -- (* Thomas Roemke, University of Paderborn, Germany modula-3@uni-paderborn.de ..!uunet!mcsun!unido!pbinfo!modula-3 *) ------------------------------------------------------------------------------ Date: Fri, 19 Apr 91 09:50:08 -0400 From: hudson@yough.cs.umass.edu (Rick Hudson) Subject: Re: Two Oberon questions stolfi@src.dec.COM writes: > > It should cost only two or three instructions to return a two-word > record as a procedure result. If you account for the cost of running > the garbage collector, allocating that same record from the heap may > well cost thousands of instructions---two or three orders of magnitude > more. > Around here we sit around and count the number of instructions/record it takes to do allocation and garbage collection on our fingers. This myth that GC takes thousands of instruction for each allocation just isn't true. I agree that structured returns are certainly useful, but the readability and expressability arguments are the important ones. - Rick ------------------------------------------------------------------------------ Date: Fri, 19 Apr 91 08:01:16 -0700 From: challal@kazan.dec.com (EIS PARIS Diderot) Subject: Problem making demos I have installed m3 vers 1.6 on our Decstation 5400 with ULTRIX version 4.1 and have successfully executed: make system, make install-system, make tools, make test. However when I try make demos I get the following errors. Have you any idea what is causing this and how to correct it? (By the way I broke the compile command into 4 lines in this message for readability) Thanks in advance Freddy +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --- X11R4 starting on Fri Apr 19 16:00:03 GMT 1991 ------ games starting on Fri Apr 19 16:00:04 GMT 1991 --------- hw starting on Fri Apr 19 16:00:05 GMT 1991 /usr/local/bin/m3 -O -o hw hw.mo -lm3misc -lm3Xaw -lm3Xt -lm3X11 /usr/local/lib/libXaw.a /usr/local/lib/libXmu.a /usr/local/lib/libXext.a /usr/local/lib/libXt.a /usr/local/lib/libX11.a ld: Can't locate file for: -lXaw ld: Usage: ld [options] file [...] linking *** Error code 1 Stop. .ROOT/util/imake: Exit code 1. Stop. *** Error code 1 Stop. .ROOT/util/imake: Exit code 1. Stop. *** Error code 1 Stop. .ROOT/util/imake: Exit code 1. Stop. *** Error code 1 Stop. .ROOT/util/imake: Exit code 1. Stop. *** Error code 1 Stop. ------------------------------------------------------------------------------ Date: Fri, 19 Apr 91 10:25:29 PDT From: Subject: Re: Nit on Wr.i3 Thanks for pointing out the omission. The next release will change Wr.{Fast}PutString to take a READONLY ARRAY OF CHAR. - Bill Kalsow ------------------------------------------------------------------------------ Date: Fri, 19 Apr 91 11:08:19 PDT From: Subject: Re: SRC compiler run-time error Thanks for the bug report. An internal table in the compiler wasn't initialized properly. The compiler crashed trying to give the error message: missing '*>' It's fixed for the next release. - Bill Kalsow ------------------------------------------------------------------------------ Date: Fri, 19 Apr 91 11:14:34 PDT From: Subject: Re: ASSERT vs. error message Thanks for the bug report. The compiler crashed while type checking the default method. An internal invariant was not maintained, hence the ASSERT. If there was no internal problem, you would have gotten an error message. - Bill Kalsow ------------------------------------------------------------------------------ Date: Fri, 19 Apr 91 11:18:53 PDT From: Subject: Re: Problem making demos It looks like your driver /usr/local/bin/m3 isn't configured correctly. Run '/usr/local/bin/m3 "-?"' to verify the configuration of your driver. Then, add "-v" and "-d" to your link command. The resulting output should tell you what's happening. - Bill Kalsow ------------------------------------------------------------------------------ Date: Mon, 22 Apr 1991 09:30:12 +0100 From: Peter.Robinson@computer-lab.cambridge.ac.uk Subject: Re: SRC compiler run-time error Win Treese mentioned a faulty interface giving rise to the compiler failing with the message: > M3 runtime error: Text.Cat: NIL argument (and Bill Kalsow replied saying that it would be fixed in the next release). Might this be an opportunity to mention a misleading comment in the Text interface: | (* Contrary to what the "Modula-3 report (revised)" says, Text accepts and | returns NIL for the empty string *) when, of course, it doesn't. - Peter Robinson. ------------------------------------------------------------------------------ Date: 20 Apr 91 19:16:44 GMT From: buschman@tubsibr.uucp (Andreas Buschmann) Subject: names of methods and instance variables of OBJECTs Hello, If I declare a type A beeing an OBJECT with a field named x and a method named y, am I allowed to declare B beeing A OBJECT with a field named y and a method named x, or only one of them? In the report I find: The names introduced in FieldList and MethodList must be (1) distinct. ... A field or method in a subtype masks any field or method with (2) the same name in the supertype. To access such a masked field, use NARROW to view the subtype variable as a member of the supertype. The following example compiles ok, but terminates while running with: fatal error: can't open display '' MODULE Main; TYPE O1 = OBJECT i : INTEGER; METHODS m () := p; END; TYPE O2 = O1 OBJECT m : INTEGER; END; TYPE O3 = O1 OBJECT METHODS i (); END; PROCEDURE p (self : O1) = BEGIN END p; BEGIN EVAL NEW (O2, m := 2); EVAL NEW (O3, i := p); END Main. this is SRC Modula-3 v1.5 running on a SUN3 on a SUN4 running v1.6 ther is no error message, it just runs. so does (1) include the names used in the super classes or not? And why? Tschuess Andreas /|) Andreas Buschmann /-|) TU Braunschweig, Germany (West) ^^^^ was bitnet: buschman%tubsibr@dbsinf6.bitnet uucp: buschman@tubsibr.uucp ------------------------------------------------------------------------------ Date: Mon, 22 Apr 91 08:39:59 PDT From: Subject: Re: SRC compiler run-time error > Might this be an opportunity to mention a misleading comment in the Text > interface: > > | (* Contrary to what the "Modula-3 report (revised)" says, Text accepts and > | returns NIL for the empty string *) > > when, of course, it doesn't. Oops. Thanks. We got too much grief for supporting the NIL extension to the Text interface, so we removed it. The comment will be corrected in the next release. - Bill Kalsow ------------------------------------------------------------------------------ Date: Mon, 22 Apr 91 08:50:52 PDT From: Subject: Re: names of methods and instance variables of OBJECTs > If I declare a type A beeing an OBJECT with a field named x and a > method named y, am I allowed to declare B beeing A OBJECT with a field > named y and a method named x, or only one of them? Yes, the following is legal: TYPE A = OBJECT x: INTEGER METHODS y () END; TYPE B = A OBJECT y: INTEGER METHODS x () END; > In the report I find: > > The names introduced in FieldList and MethodList must be (1) > distinct. > > ... > > A field or method in a subtype masks any field or method with (2) > the same name in the supertype. To access such a masked field, > use NARROW to view the subtype variable as a member of the > supertype. > so does (1) include the names used in the super classes or not? And > why? No, "FieldList" and "MethodList" are names for syntactic pieces of an object declaration. They are not the set of all field or method names in the object. > The following example compiles ok, but terminates while running with: > fatal error: can't open display '' Usually, "can't open display" indicates that your program cannot contact an X server. I doubt it's a Modula-3 problem. - Bill Kalsow ------------------------------------------------------------------------------ Date: Mon, 22 Apr 91 16:53:30 -0400 From: hudson@yough.cs.umass.edu (Rick Hudson) Subject: GC references (was RE: Two Oberon questions) stolfi@src.dec.COM writes: > > > Around here we sit around and count the number of > instructions/record it takes to do allocation and garbage collection > on our fingers. This myth that GC takes thousands of instruction > for each allocation just isn't true. > > Congratulations, you must be a very happy man... Actually, I just broke my finger playing basketball, thus ending my digital computing for a while :-) > I presume you have a good incremental garbage collector in a favorable > architecture, and you measured its performance on typical real-world > programs (whatever that means). Moon, David ("Garbage Collection in a Large Lisp System" Conference Record of the 1984 ACM Symposium on Lisp and Functional Programming) and Ungar, David and Jackson, Frank, ("Tenuring Policies for Generation-Based Storage Reclamation", OOPSLA 1988 Conference Proceedings) describe techniques aimed at improving garbage collection in "real" world situations. > Forgive me if I sound a bit skeptical, but often the cost of garbage > collection does not scale linearly with working set size. Do you still > get tens of instruction/record when you have, say, 5MB worth of active > nodes? The above references discuss your concerns. > For example, the SRC Modula-3 compiler currently uses a copying > garbage collector, whose cost per allocation grows rather quickly as > the size of accessible structures approaches the total available memory > size. Does the SRC Modula-3 use Bartlett's, Joel F. (Mostly Copying Garbage Collection Picks Up Generations and C+, DEC-WRL Tech note TN12) enhancements that incorporate generations. I would have guessed that this work would have lessened such problems. > > Note also that, depending on the implementation, the mere existence > of GC may slow down all pointer assignments quite a bit, even when > the program is not doing any allocations. Bartlett (above) reports a 4% to 12% slowdown due to remembered set maintenance in Scheme->C using some of the Gabriel benches. > For instance, our Modula-2+ > GC is partly based on reference counts, and the code for an assignment > of the form ref1^.field := ref2 must update the reference count of > ref2^. Since Modula-2+ programs are usually multi-threaded and run > on multi-processor workstations, that code must be careful to do the > right thing even when two threads are trying to update the same count > at the same time. On a vanilla VAX architecture, this apparently takes > at least a dozen VAX instructions. Reference count GCs also deal poorly with reference count overflow as well as circular list structures. Mark-and-Sweep collection do not seem practical either, but Zorn, Benjamin ("Comparing Mark-and-Sweep and Stop-and-Copy Garbage Collection" 1990 ACM Conference on Lisp and Functional Programming) has added generations and indicated why we should reconsider Mark-and-Sweep algorithms. Apple, Andrew W. and Li, Kai ("Virtual Memory Primitives for User Programs" Architectural Support for Programming Languages and Operating Systems, 1991) discusses what support would be needed from the OS to implement faster incremental, generational GCs, some of their suggestions deal directly with how to handle pointer updates and other remembered set problems. Hope this helps. - Rick ------------------------------------------------------------------------------ Date: Mon, 22 Apr 91 18:55:53 -0400 From: Roger Hoover Subject: What's wrong with this: When I compile the following interface with 1.6: INTERFACE CoverTree; TYPE obj = OBJECT link: ARRAY [0..164] OF obj; END; END CoverTree. I get: % m3 -c CT.i3 CT.i3:5: redefinition of `struct struct_1' CT.i3:5: redefinition of `t1' CT.i3:5: here is the previous declaration of `t1' What is wrong? ------------------------------------------------------------------------------ Date: 22 Apr 91 14:21:14 GMT From: sfk@otter.hpl.hp.com (Steve Knight) Subject: Replies to FAQ - What's modula-3? Some while ago I posted the FAQ "Err ... what's modula-3". As promised, here is a only slightly edited summary of the replies I received. Thanks to everyone who took the time to help me out! Also, I was successful in recovering the postscript report from gatekeeper.dec.com, although I had to use the split version for stupid printers. Steve Knight, HP Labs, Bristol, UK replies follow: ----------------------------------------------------------------------------- From: MADMATS@ELCGL.EPFL.CH (Mats Weber) I think a previous article in this newsgroup gives bibliographic references on Modula-3. If you can't find them, you can get the modula-3 lang. report through anonymous ftp on gatekeeper.dec.com (it is named Report.ps and resides in /pub/DEC/Modula-3/). An article describing Modula-3 appeared in Byte a few months ago, too. I think Modula-3 is very interesting. Basically, it's Modula-2 + objects with inheritance and dynamic binding + exceptions + better interface/module structure + Threads + garbage collection. Mats Weber ----------------------------------------------------------------------------- From: harbison@bert.pinecreek.com See my article in the November '90 BYTE for an overview of the Modula-3 language. There's also a second article in the upcoming (March) issue of Computer Language. The reference manual (60 pp.) is available as a tech report (#52) from Digital Systems Research Center, 130 Lytton Ave, Palo Alto CA 94301. There have been no direct comparisons with Modula-2, but Modula-3 is both more and less--it adds exceptions, threads, objects, garbage collection, and (more recently) generics. It takes away nested modules and simplifies the type system. It has a particlarly good system for defining opaque object types and hiding representations. It breaks virtually no new ground, but includes features of proven utility in various languages. In spite of all this, it still feels like a small language. M3 is not an extension of M2: M3 compilers won't compile M2 programs or vice versa, although a myopic M2 programmer might mistake an M3 program for M2. Other miscellania: M3 has initializations on variable declarations and default initialization of record and object types. The WITH statement is more like Lisp's LET than Pascal/Modula-2's WITH. The FOR statement automatically declares its control variable, like Ada. M3 is "safe" from undefined runtime behavior unless the programmer labels some interfaces or modules as UNSAFE, in which case he/she gets access to a few dangerous but occasionally useful functions such as DISPOSE, address arithmetic, etc. Summary: Modula-3 is a safe and robust programming language with the set of features needed by modern system programmers. Nevertheless, it still has the feel of a "small" language, in the spirit of Modula-2 and contrary to languages like Ada and C++. Sam Harbison Pine Creek Software, Pittsburgh, PA. +1 412 681 9811 ----------------------------------------------------------------------------- From: buschman@tubsibr.UUCP (Andreas Buschmann) Hi! I have a list of differences between modula-2 and modula-3, but it has some shortcommings: a. it isn't complete. i have done it last summer, and since then discovered some more things which i didn't add to the list. b. its my personal point of view. c. its in german. if you still want it, drop me a note, and, if you have, give me the id of your bitnet account. (its about 23kbyte of text) Tschuess Andreas /|) Andreas Buschmann /-|) TU Braunschweig, Germany (West) ^^^^ was ----------------------------------------------------------------------------- From: larry@titan.tsd.arlut.utexas.edu (Larry Maturo) You can ftp to gatekeeper.dec.com using anonymous ftp and then cd to pub/DEC/Modula-3 and download the Modula-3 source code and all it's associated documentation. Basically, Modula-3 is Modula-2 with objects. The objects are based on records, like C++, Turbo Pascal, and Quick Pascal. It also uses structural compatibility so that you can assign one array slice to another if the elements are of the same type, even though the arrays themselves are of different types. It does allow branding of types so that a variable of a branded type is only compatible with other variables of that branded type. It also has the concept of traced and untraced storage. Traced storage uses garbage collection and untraced storage dosen't. It also allows mixing and matching of interface modules and implementation modules instead of requiring that each implementation module have only one definition module. Hopes this helps. Larry Maturo | Opinions expressed herein must be Applied Research Laboratories | yours, neither I nor my employer have University of Texas at Austin | any. P.O. Box 8029 | Austin, Texas 78713-8029 | | When you're as great as I am it's hard larry @titan.tsd.arlut.utexas.edu | to be modest, but I succeed where | others fail. ----------------------------------------------------------------------------- From: Robert Stroud Modula-3 = Modula-2+ + objects (single inheritance only) Modula-2+ = Modula-2 + exception handling + threads + "safe programming" For a good description of the rationale for Modula-2+, see the paper by Paul Rovner "Extending Modula-2 to build large Integrated Systems" IEEE Software November 1986. I am not aware of a comparable rationale for Modula-3. Whereas Modula-2+ is upwards compatible with Modula-2, Modula-3 is not - there are some minor syntactic changes and some fairly fundamental changes in the area of pointers to support "safe programming". Modula-3 objects are a bit like Oberon's Record Extensions (Oberon was Wirth's successor to Modula-2) except that Modula-3 records distinguish data fields from method fields. Unusually, in an object oriented language, the objects are not opaque within the scope of an object type declaration, but it is possible to export a partial type definition from a module and achieve encapsulation that way. (In C++ terms, all fields are public and all functions are virtual). Another unusual feature is that the method fields of an object can be specified as each instance of the object is created but defaults are allowed. This overview is perhaps a bit too brief for you but I hope it is helpful - mail me if you don't get something better. Cheers. Robert Stroud, Computing Laboratory, University of Newcastle upon Tyne. EMAIL R.J.Stroud@newcastle.ac.uk ----------------------------------------------------------------------------- From: woolsey%mri%sun0@ames.arc.nasa.gov (Jeff Woolsey) Well, here are the syntactic differences I found. One of my gripes was addressed in the 12 Changes. The major difference between the languages, though is that Modula-3 has OBJECTs. Other significant differences appear in the way that strings are handled. Wed Aug 1 12:03:54 PDT 1990 Notes on converting Modula-2 programs to Modula-3. value Modula-2 form Modula-3 form Syntactic differences ========= =========== + 100B 8_100 = 34C '\034' = 'STRING' permitted "STRING" - '''' '\'' - '"' '\"' - """" "\"" - "'" "\'" = <> # - ;; missing = ODD(x) (1 = x MOD 2) = INCL(set, elt); set := set + S{elt}; = EXCL(set, elt); set := set - S{elt}; = TYPE COLOR=(RED, BLUE, GREEN) TYPE COLOR={RED, BLUE, GREEN} + WITH record DO x(field) END WITH y=record.field DO x(y) END = CASE x OF 4: END CASE x OF 4 => END + PROCEDURE X(A: CHAR); PROCEDURE X(A: CHAR)= = PROCEDURE X; PROCEDURE X()= = X; X(); = POINTER TO REF = CHR(x) VAL(x, CHAR) = IMPLEMENTATION MODULE x; MODULE x; = DEFINITION MODULE x; INTERFACE x; = HALT missing, exception? = PROCEDURE X() END X; PROCEDURE X()= BEGIN END X; = MODULE X; MODULE X EXPORTS Main; Semantic differences ======== =========== - "LITERAL" = ARRAY OF CHAR "LITERAL" = TEXT = CARDINAL=[0..2*LAST(INTEGER)+1] CARDINAL=[0..LAST(INTEGER)] = RECORD CASE BOOLEAN OF END END missing ? IMPORT COLOR; RED IMPORT COLOR; COLOR.RED Apparent bugs in SRC Modula-3 1.4 ======== ==== == === ======== === LAST(INTEGER)+LAST(INTEGER)+1 does not generate a checked runtime error. This is listed in the release notes. Null statements ;; driver the parser batty. The compiler fails with an assertion botch that has something to do with passing TEXT to PROCEDUREs that want ARRAY OF CHAR. Fixed in 1.6. Opinions ======== TEXT appears to be a botch. String literals, "hi there", are of type TEXT, and this is what a lot of procedures want as parameters, but I cannot index a TEXT variable (being opaque I can't dereference and index it either, even if I know what it is). I usually end up mirroring such a variable with a TEXT version and an ARRAY OF CHAR version. There HAS to be a better way. IMPORT TextF addresses a lot of this, but is not complete. Still no module-termination code. May be able to finagle it with exceptions. Jeff Woolsey Microtec Research, Inc. ..!amdcad!sun0!woolsey +1 408 980 1300 x585 ----------------------------------------------------------------------------- ------------------------------------------------------------------------------ Date: Tue, 23 Apr 1991 11:35:51 PDT From: Hans_Boehm.PARC@xerox.com Subject: Re: GC references (was RE: Two Oberon questions) Rick Hudson writes: "Reference count GCs also deal poorly with reference count overflow as well as circular list structures. Mark-and-Sweep collection do not seem practical either, but Zorn, Benjamin ("Comparing Mark-and-Sweep and Stop-and-Copy Garbage Collection" 1990 ACM Conference on Lisp and Functional Programming) has added generations and indicated why we should reconsider Mark-and-Sweep algorithms." I would like to amend the last sentence with a further plea for caution. The tradeoffs between various techniques are much more subtle than some of the recent literature indicates. Reference counting may well win if your heap is nearly full most of the time. It may win in other cases, too. See DeTreville, "Experience with Concurrent Garbage Collectors for Modula-2", SRC report 64. Similarly Mark-and-Sweep seems to win in a number of cases, even in a much purer form than that used by Ben Zorn. It can handle large numbers of ambiguous references. It requires significantly less compiler support. It almost always touches significantly less memory during full collections. It allows hashing on addresses. I would argue that there are better (stock hardware) parallel collection algorithms available than for copying collection. (See our upcoming SIGPLAN paper.) Of course, copying collection has its advantages, too. But there seems to be no shortage of papers advertising those. Hans ------------------------------------------------------------------------------ Date: Tue, 23 Apr 91 20:15:14 PDT From: harbison@bert.pinecreek.com Subject: The missing Comp. Lang. article A previous message alluded to a Modula-3 article in the March issue of Computer Language. Well, it's not there. Since the editor accepted the article, and I corrected the page proofs they sent, and they said it would be in the March issue, I just ASSUMED... ...but it got bumped. I'm going to try to place it in JOOP or JPAM. It's on Objects and Modules in Modula-3. However, if you're dying to read more on Modula-3, Prentice Hall expects Greg Nelson's collection Systems Programming in Modula-3 to be in-stock by mid-May. Look for it at a bookstore near you. If you can't find it, you can order it from Pine Creek. Sam Harbison Pine Creek Software; 305 S. Craig St., Suite 300; Pittsburgh, PA 15213 +1 412 681 9811; harbison@bert.pinecreek.com ------------------------------------------------------------------------------ Date: 24 Apr 91 19:20:15 GMT From: buschman@tubsibr.uucp (Andreas Buschmann) Subject: OBJECTs and their default methods Hello, here is another question about OBJECTs. suppose we have the following declarations: TYPE O1 = OBJECT METHODS m () : INTEGER := zehn END; TYPE O2 = O1 OBJECT m : INTEGER := 2 END; PROCEDURE zehn (self : O1): INTEGER = BEGIN RETURN 10; END zehn; what is the meaning of O2.m in the following block? a) O1's default method m (zehn) b) O2's default value for m (2) c) this is illegal d) something else in the report on page 39 there is the sentence r.f, o.f, I.x, T.m, E.id ... If T is an object type and m is the name of one of T's methods, then T.m denotes T's default m method. the SRC compiler v1.6 says types not assignable if i try to assign the value of this to an integer or a procedure variable. Tschuess Andreas ------------------------------------------------------------------------------ Date: 25 Apr 91 13:06:34 GMT From: sakkinen@jyu.fi (Markku Sakkinen) Subject: Re: GC references (was RE: Two Oberon questions) In article <91Apr23.113622pdt.16245@alpha.xerox.com> Hans_Boehm.PARC@xerox.com writes: > ... >Of course, copying collection has its advantages, too. But there seems to be >no shortage of papers advertising those. One very important disadvantage of copying collection is that it restricts the possible semantics of objects: no finalisation (destructors, as in C++) is possible. This has been explicitly admitted at least in Edelson's report. One could very well paraphrase the above restriction: "Old objects never die, they just fade quietly away." Markku Sakkinen Department of Computer Science and Information Systems University of Jyvaskyla (a's with umlauts) PL 35 SF-40351 Jyvaskyla (umlauts again) Finland SAKKINEN@FINJYU.bitnet (alternative network address) ------------------------------------------------------------------------------ Date: 26 Apr 91 00:01:26 GMT From: chased@rbbb.Eng.Sun.COM (David Chase) Subject: Re: GC references (was RE: Two Oberon questions) sakkinen@jytko.jyu.fi (Markku Sakkinen) writes: >One very important disadvantage of copying collection is that it >restricts the possible semantics of objects: no finalisation >(destructors, as in C++) is possible. Finalisation is possible with copying collection, though it is not pretty. The game played is somewhat like the game played to implement "weak pointers". Registering a pointer for finalisation is implemented by hiding it on a list (hidden by its encoding, or hidden by design). At a collection, assume that all the live pointers have been forwarded. At this point, traverse the list of finalizable objects. Each pointer stored there is either forwarded, or about to die. All the sickly pointers are placed on another list, and the objects that they reference are copied into new space. Of course, these objects may reference other objects, etc. At this point, you've got a couple of choices based on how you feel about cyclic and shared finalisable garbage. The easy answer is to declare that it is all going to die, and to finalise everything on the "sickly list". The hard answer is to assume that finalisation might alter the accessibility of memory (e.g., "global_variable := my_component"), and proceed accordingly. Except for cycles, even this can be dealt with, though it is painful (find the roots of the finalisable garbage graph, finalise them, put everything else back on the finalisable list, wait till next collection). One hopes that better algorithms to do this exist, but it is possible. David ------------------------------------------------------------------------------ Date: Fri, 26 Apr 91 10:17:32 PDT From: Subject: Udir.i3 If you look at this interface, you will note that it has a comment about a difference for SunOS (4.0 and upwards actually), but no field inserted. This makes code which scans directories fail. TYPE gen_dir = RECORD (* describes directory entry *) (* SunOS has another field here. *) gd_ino: Ctypes.unsigned_long; (* inode number of entry *) gd_reclen: Ctypes.unsigned_short; (* record length in bytes *) gd_namelen: Ctypes.unsigned_short; (* name length in bytes *) gd_name: Ctypes.char; (* C array *) (* name *) END; The declaration should read: TYPE gen_dir = RECORD (* describes directory entry *) gd_off: Ctypes.long; (* offset of next disk directory entry * ) gd_ino: Ctypes.unsigned_long; (* inode number of entry *) gd_reclen: Ctypes.unsigned_short; (* record length in bytes *) gd_namelen: Ctypes.unsigned_short; (* name length in bytes *) gd_name: Ctypes.char; (* C array *) (* name *) END; Sadly this means that simply using the "ultrix-3-1" library for SunOS is no longer viable. Anyway, I am sure there are other differences. Mick Jordan ------------------------------------------------------------------------------ Date: Fri, 26 Apr 1991 15:29:03 -0500 (CDT) From: Dick Orgass Subject: Re: Udir.i3 The intent of the target specific libraries is that they are to accurately reflect the details of the target on which clients are running. In a lot of ways Udir.i3 is the most difficult of the target specific interfaces. All three of the IBM platforms are different from each other and quite different from Ultrix. These differences show up in two ways: the details of the record declarations and the names of the record fields. The first is of very little consequence if the people doing the ports do their job correctly (unlike this author) but the second is more difficult. Whe I did Udir.i3 for our platforms, I followed sys/dir.h for type names, field size and field names. This means I get a record type DIR with fields of the form dd_* as well as record type struct_dirent with fields whose names are of the form d_*. It appears that for Ultrix and, possibly, SunOS, one gets a record type gen_dir with field names gd_*. It is this latter kind of difference that makes clients of Udir.i3 non-portable. Perhaps we should agree to use exactly the type names and field names in the POSIX or X/Open spec with possible additions or omissions to match our targets. Dick ------------------------------------------------------------------------------ Date: Fri, 26 Apr 1991 16:20:15 -0500 (CDT) From: Dick Orgass Subject: Bug fixes for IBM RISC/6000 Shared Libraries There is a small annoying problem caused by an incorrect detail in the creation of the .ma files for shared libraries and AIX 3.1. The rule for creating .ma at line 63 of util/m3all.tmpl and at line 58 of util/m3fromC.tmpl should be as follows: libm3$(LIB).ma: libm3$(LIB).a $(OBJS) @@\ ar ru libm3tmp.a $(OBJS) @@\ $(M3AR) libm3tmp.a @@\ mv libm3tmp.ma libm3$(LIB).ma @@\ rm libm3tmp.a @@\ -rm .ROOT/libs/libm3$(LIB).ma @@\ ln -s `pwd`/libm3$(LIB).ma .ROOT/libs In the distributed version of this rule, the .ma file is created directly from the .a file. However, the result is incorrect because the .ma file indicates that all of the initilization procedures for a library are in a single module. As a result, when an initialization program is written all of these initilization procs are called even if there is no client of the module in the application! The above rule avoids this problem. I think there is a more efficient solution but this will solve immediate problems. Udir.i3 There are a few small errors in libs/aix-3-1/os/Udir.i3 which can be corrected as follows. Modify line 7 so that is reads: IMPORT Utypes; Replace lines 21-22 with the following three lines: MAXNAMLEN = 255; (* Maximum length of component of file path name. *) MAXNAMELEN = MAXNAMLEN; MAXPATHLEN = 1023; (* Maximum length of file path name. *) Modify line 39 so that it reads: d_ino: Utypes.ino_t; Dick ------------------------------------------------------------------------------ Date: 27 Apr 91 20:50:06 GMT From: nr@cs.Princeton.EDU (Norman Ramsey) Subject: NARROW I recently noticed that no explicit NARROW is required in assignments and in passing value parameters. Are there any other places where NARROW is not required? -- Norman Ramsey nr@princeton.edu ------------------------------------------------------------------------------