======================================================================= 1 === Date: 1 Feb 93 18:06:15 GMT From: moss@cs.cmu.edu (Eliot Moss) Subject: status of GNU Modula-3 Well, we said we'd try to have an alpha release of GNU Modula-3 (gm3) by the end January, and since it's now February I thought I should post and let you know that we didn't make it. Here are the features we know we have yet to handle for the alpha release: - SUBARRAY: almost done, but initial attempt had inappropriate data structures in the compiler for nested open arrays, so it had to be redone - REVEAL: this requires some external support for enforcing the langauge rules across compilations; all designed and into implementation - FLOAT(): trivial, just not done yet - nested procedures: requires only front-end work since static nesting is supported in gcc 2.0 and higher, just not done yet Our strategy has been to attempt compiling the various files in libm3 and fix whatever is missing/broken until those files all compile. We will then move on to other SRC libraries using the same approach. Naturally there may be features other than the four listed above that need some work, but these four must be taken care of before other significant ones are uncovered. I note that exception handling and gc are working fine. Features that the alpha release will definitely lack are: complete support for threads (no forking, but mutexes, conditions, and LOCK will be partially implemented so that you can use thread-safe code), complete gdb support (in particular, we're not emitting the symbol table info needed to access variables at run time, but breakpoints and stepping by source line number will work), full support for the float libraries, and extended floats (not yet supported by gcc). The alpha release will be for the VAX only, but there are some folks who will get the code so they can start looking at it and perhaps start porting efforts to other architectures. Why is this all taking so long? We are working with minimal staff -- a half time professional programmer and a half time graduate student. Also, the programmer's other responsibilities recently and unexpectedly demanded about a month of full-time work (which we owe them). So, with regrets, we now predict alpha release in mid-March. We also don't want to release something that will waste too much testers' time, so we don't want to push it out the door too early. However, our testing, beyond whether something compiles without errors, is likely to be pretty cursory -- we'll be relying on the alpha testers to find the more subtle bugs in generated code. Alpha testers can help us some, though. It would be helpful to have priorities from you of which packages or language features you really MUST have, which are very desirable but not absolute requirements, and which you don't care about right away. We thank you all for your interest, patience, and support (especially SRC for financial and other assistance!) -- Eliot Moss -- J. Eliot B. Moss, Associate Professor Visiting Associate Professor Department of Computer Science School of Computer Science Lederle Graduate Research Center Carnegie Mellon University University of Massachusetts 5000 Forbes Avenue Amherst, MA 01003 Pittsburgh, PA 15213-3891 (413) 545-4206, 545-1249 (fax) (412) 268-6767, 681-5739 (fax) Moss@cs.umass.edu Moss@cs.cmu.edu ======================================================================= 2 === Date: 1 Feb 93 17:56:19 GMT From: mlo@dcs.qmw.ac.uk (Mike Osborne) Subject: Network Interface Example I recently downloaded the Network interface, but there were no example programs So I've written one.... These programs use the Network interface posted recently by Norman. I wanted to test the interface, so I wrote a small client and server, which together provide an addition service. They are not very well written (I haven't attempted to handle many exceptions, and the port/hostname are hardcoded) But they may give some idea of how the network interface can be used. If you have any more examples using this library, post them! Norman, if you are reading this, is this the right way to use the interface? Do you have any example programs? Mike Delete everything above including this line #!/bin/sh # This is a shell archive. # Run the file through sh to extract its contents. # shar: Shell Archiver # Run the following text with /bin/sh to create: # ArithClient.m3 # ArithServer.m3 # This archive created: Mon Feb 1 17:50:03 1993 cat << \SHAR_EOF > ArithClient.m3 MODULE Main; IMPORT Network,Fmt,Scan,Rd,Wr,Stdio; VAR netreader: Network.T; VAR first,second,response: INTEGER; BEGIN (* connect to the server *) Wr.PutText(Stdio.stdout,"Attempting to connect to the Arithmetic Server\n"); netreader := Network.Connect("hostname",5041); (* some arbitary port *) Wr.PutText(Stdio.stdout,"Got connection\n\n\n"); LOOP (* Get some numbers to send to the server *) Wr.PutText(Stdio.stdout,"Enter the first number :\n"); Wr.Flush(Stdio.stdout); first := Scan.Int(Rd.GetLine(Stdio.stdin)); Wr.PutText(Stdio.stdout,"Enter the second number :\n"); Wr.Flush(Stdio.stdout); second := Scan.Int(Rd.GetLine(Stdio.stdin)); (* Send the numbers to the server *) Wr.PutText(netreader.wr,Fmt.Int(first)); Wr.PutText(netreader.wr,"\n"); Wr.Flush(netreader.wr); Wr.PutText(netreader.wr,Fmt.Int(second)); Wr.PutText(netreader.wr,"\n"); Wr.Flush(netreader.wr); response := Scan.Int(Rd.GetLine(netreader.rd)); (* Read back the response * ) (* Display the result *) Wr.PutText(Stdio.stdout,"The result of addition is: "); Wr.PutText(Stdio.stdout,Fmt.Int(response)); (* and display it *) Wr.PutText(Stdio.stdout,"\n\n"); END END Main. SHAR_EOF cat << \SHAR_EOF > ArithServer.m3 (* Example arithmetic server using the networking interface *) (* Mike Osborne (mlo@dcs.qmw.ac.uk) *) MODULE Main; IMPORT Network,Thread,Fmt,Scan,Rd,Wr,Stdio; TYPE AddClosure = Thread.Closure OBJECT connection : Network.T OVERRIDES apply := Add END; TYPE ServerLoopClosure = Thread.Closure OBJECT serviceport : Network.Server OVERRIDES apply := ServerLoop END; VAR server: Network.Server; PROCEDURE Add(self: AddClosure):REFANY RAISES {} = VAR first,second,result: INTEGER; BEGIN LOOP TRY first := Scan.Int(Rd.GetLine(self.connection.rd)); second := Scan.Int(Rd.GetLine(self.connection.rd)); (* This is where the server does its "work" *) result := first + second; (* Send the result to the client *) Wr.PutText(self.connection.wr,Fmt.Int(result)); Wr.PutText(self.connection.wr,"\n"); Wr.Flush(self.connection.wr); EXCEPT | Rd.EndOfFile => EXIT; END; END; RETURN (NIL); END Add; (* This procedure loops calling Network.Accept repeatedly. *) (* Each time Network.Accept returns, a new thread is forked to service the *) (* connection. It is intended to be run as a thread which will allow the *) (* server process to continue *) PROCEDURE ServerLoop(self : ServerLoopClosure):REFANY RAISES {} = VAR connection: Network.T; BEGIN WHILE (TRUE) DO connection := Network.Accept(self.serviceport); EVAL Thread.Fork(NEW(AddClosure,connection := connection)); END; END ServerLoop; BEGIN (* create a server on port 5041 *) server := Network.Serve(5041); (* create a thread to handle incoming connections *) EVAL Thread.Fork(NEW(ServerLoopClosure,serviceport := server)); (* This can be an empty statement, if the server is not intended to do *) (* anything other than provide the arithmetic service. Otherwise, we could *) (* add internal server monitoring/administration facilities here *) REPEAT UNTIL Rd.GetChar(Stdio.stdin) = 'q'; END Main. SHAR_EOF # End of shell archive exit 0 -- Michael Osborne Internet: mlo@dcs.qmw.ac.uk Computer Science Department JANET: mlo@uk.ac.qmw.dcs Queen Mary & Westfield College Mile End Road Telephone: +44 71-975 5244/5/9 LONDON, E1 4NS, UK Fax: +44 81-980 6533 ======================================================================= 3 === Date: Mon, 1 Feb 1993 19:24:28 GMT From: schaeppe@nessie.cs.id.ethz.ch (Christian Schaepper) Subject: RFD: comp.lang.oberon R E Q U E S T F O R D I S C U S S I O N ------------------------------------------- This is a Request For Discussion (RFD) for the creation of a newsgroup for the discussion of issues regarding the Oberon language and system. GROUP NAME comp.lang.oberon STATUS unmoderated CHARTER comp.lang.oberon (unmoderated) will be a newsgroup for discussion of all types of issues regarding the Oberon language and system. RATIONALE Due to historical reasons, topics related to Oberon are currently being discussed in comp.lang.modula2. Not everyone may be aware of this fact and thus miss the discussion related to Oberon. Further, readers of comp.lang.modula2 might not like the "abuse" of their newsgroup. The creation of comp.lang.oberon solves both problems. BACKGROUND Oberon is really three things: - the name of a project started by Proff. N. Wirth and J. Gutknecht (both at ETH Zurich) with the goal of developing a modern and portable operating system for personal workstations - a general-purpose programming language (the successor of Modula-2) with type extension as its principal new feature (The programming language Oberon-2, designed to make object oriented programming easier, is a true extension of Oberon) - an extensible operating system, complete with a novel user interface and associated software tools The Oberon system (including the Oberon compiler) is available as freeware via anonymous ftp from neptune.inf.ethz.ch (129.132.101.33) (directory 'Oberon') for the following machines: IBM PC (386 or better), Macintosh II (Apple), SPARC (Sun), DECstation/3100 and 3500, RS/6000 (IBM) (You'll also find some docu (including language reports) there) SCHEDULE This RFD was issued on February 1 and will last for 30 days. If this RFD is approved, a CFV will be issued on March 4, and the voting period will end at 11:59 (MET), March 25. -- +-----------------------------------------------------------------------------+ | Christian Schaepper, Zurich, Switzerland schaeppe@nessie.cs.id.ethz.ch | | DECnet (HEPNET/SPAN): EZINFO::SCHAEPPER (57413::SCHAEPPER) | +-----------------------------------------------------------------------------+ ======================================================================= 4 === Date: Mon, 1 Feb 93 21:12:23 GMT From: norman@flash.bellcore.com (Norman Ramsey) Subject: example of Network interface I didn't post an example program that uses the Network interface because the only real example I have is ugly, and I didn't want to spend the time making it clean. Here's a bowdlerized version, with lots of the complexity and ugliness removed. It should all be obvious, except perhaps what to do with UnixError.E. I show only the server; the client side is uninteresting. So uninteresting, in fact, that for a while I used `telnet' as the client. Norman MODULE Serve EXPORTS Main; IMPORT ... VAR server : Network.Server; PROCEDURE Usage() = BEGIN ... END Usage; (* print msg and exit *) PROCEDURE Args() RAISES {UnixError.E} = VAR i := 1; BEGIN <> CASE Params.Count - i OF | 0 => server := Network.Serve(); (* any port in a storm *) | 1 => TRY server := Network.Serve(CScan.Int(Params.Get(i))); (* port named on command line * ) EXCEPT Scan.BadFormat => Usage(); END; ELSE Usage(); END; END Args; PROCEDURE Go() RAISES {UnixError.E} = BEGIN Args(); Log.Shout("Serving host %s port %s...", Network.Host(server), Fmt.Int(Network.Port(server))); LOOP Thread.Fork(NEW(Conn, net := Network.Accept(server), name := "Anonymous")); END; END Go; TYPE Conn = Thread.Closure OBJECT name : TEXT; net : Network.T; OVERRIDES apply := Listen; END; PROCEDURE Listen(conn:Conn):REFANY = BEGIN TRY LOOP Command.Invoke(conn, Rd.GetLine(conn.net.rd), Cmds, Unknown); END; EXCEPT | Rd.Failure => Log.Shout("lost connection to " & conn.name); | Rd.EndOfFile => Log.Shout(conn.name & " closed connection"); | Thread.Alerted => Log.Shout(conn.name & " thread alerted"); END; Rd.Close(conn.net.rd); Wr.Close(conn.net.wr); RETURN NIL; END Listen; BEGIN TRY Go() EXCEPT UnixError.E(rec) => Log.Shout("serve: %s (%s)", rec.msg, Fmt.Int(rec.errno)); END; END Serve. ======================================================================= 5 === Date: Tue, 2 Feb 93 02:26:41 GMT From: jdd@src.dec.com (John DeTreville) Subject: Porting the new garbage collector As you may know, the garbage collector in the new Modula-3 system is incremental and generational, depending internally on VM protection to read-protect or write-protect the heap. The details of using VM protection differ greatly between versions of Unix. In the initial release, I implemented the necessary internal support only for DECstations running Ultrix, since that's what I use. On other architectures, the collector defaults to ordinary old non-generational stop-&-copy behavior, just like the previous one. Thanks to David Goldberg of PARC, there will soon be a complete collector port to the SPARC under SunOS. You'll get smaller interruptions of service and less time spent in the collector, as in the Ultrix version. If you're brave, you might want to port the low-level VM support to your own favorite machine; ask me for information. It should be possible to port the collector to most modern architectures and Unixes. You'll have to know Section 2 of your Unix manual quite thoroughly; see runtime/src/DS3100/RTHeapDepC.c for why. Cheers, John ======================================================================= 6 === Date: 31 Jan 93 03:58:03 GMT From: awenn@matilda.vut.edu.au (Andrew Wenn) Subject: Modula3 and Acorn RISCiX Is anyone else in this group using Modula3 on an Acorn RISCix machine? If so I would like to hear from you. Andrew. --------------------------------------------------------------------------- Andrew Wenn Victoria University of Technology Footscray Campus. awenn@matilda.vut.edu.au phone 03 688 4342 fax 03 688 4804 --------------------------------------------------------------------------- ======================================================================= 7 === Date: Tue, 02 Feb 93 17:45:27 -0800 From: heydon@src.dec.com Subject: Re: Inheritance and opaque types. mjordan@src.dec.com (Mick Jordan) wrote: > There is no language-level support for allowing a subtype > accces to hidden fields, but denying other clients access. > The convention is to place the half-hidden fields in a separate > interface, and publicise that this is intended for subtype > clients only. You can use partial revelations to arrange this. He then gave the following canonical example (which I have corrected slightly): INTERFACE Foo; TYPE T <: Public; Public = OBJECT (* public fields *) METHODS (* public methods *) END; END Foo. INTERFACE FooRep; IMPORT Foo; TYPE T = Foo.Public OBJECT (* semi-private fields *) END; REVEAL Foo.T <: T; END FooRep. MODULE Foo; IMPORT FooRep; REVEAL T = FooRep.T OBJECT (* private fields *) OVERRIDES (* method implementations *) END; BEGIN END Foo. In this scheme, we have "Foo.T <: FooRep.T <: Foo.Public". A client that imports only "Foo" sees only the public fields, but a client that imports both "Foo" and "FooRep" sees both the public and semi-private fields. Of course, inside the "Foo" module, the private fields are visible as well. With this scheme, the order of the fields within a "Foo.T" is: public, semi-private, and then private; so the public fields are a prefix of the object. We can arrange for the semi-private fields to be a prefix instead: INTERFACE Foo; TYPE Private <: ROOT; Public = Private OBJECT (* public fields *) METHODS (* public methods *) END; T <: Public; END Foo. INTERFACE FooRep; IMPORT Foo; REVEAL Foo.Private = OBJECT (* semi-private fields *) END; END FooRep. MODULE Foo; IMPORT Foo, FooRep; REVEAL T = Public OBJECT (* private fields *) OVERRIDES (* method implementations *) END; BEGIN END Foo. With this scheme, we have "Foo.T <: Foo.Public <: Foo.Private". The reason we might want the private fields in the prefix is to be able to reveal in the "FooRep" interface that a "Foo.Private" is a subtype of some other object type that we might want importers of "FooRep" to see. For example, we could have instead written: INTERFACE FooRep; IMPORT Foo; REVEAL Foo.Private = MUTEX OBJECT (* semi-private fields *) END; END FooRep. This declares that "Foo.Private <: MUTEX", so clients that import both "Foo" and "FooRep" not only have access to both the public and semi-private fields of a "Foo.T", but they can also LOCK a "Foo.T" object as well. In fact, the structure of the "Wr", "WrClass", "UnsafeWr" interfaces -- and their implementation in the "WrRep" module -- is somewhat similar to this scheme. See Chapter 6 of SPwM3. In particular, see the third and second paragraphs from the bottom of pg 143 of SPwM3 for a description of how to leave room for extra fields in the prefix and/or suffix of an object. - Allan Allan Heydon heydon@src.dec.com DEC Systems Research Center (415) 853-2142 130 Lytton Ave. (415) 853-2104 (FAX) Palo Alto, CA 94301 ======================================================================= 8 === Date: Wed, 03 Feb 1993 20:47:47 GMT From: bieman@CS.ColoState.EDU (james bieman) Subject: Modula-3 compiler for PC's I am looking for a Modula-3 compiler for PC's running MS Windows or DOS. We are currently using Modula-3 in an undergraduate software engineering course and we have off-campus students (some in other states) without access to the internet (for remote logins) who need to use their PC's for assignments. In this course, we do not use any UNSAFE features. I (and my students) will appreciate any helpful information. Jim Bieman ------------------------------------------------------------- James Bieman Email: bieman@cs.colostate.edu Computer Science Department Phone: (303)491-7096 Colorado State University Fax: (303) 491-6639 Fort Collins, CO 80523 -- James Bieman Email: bieman@cs.colostate.edu Computer Science Department Phone: (303)491-7096 Colorado State University Fax: (303) 491-2293 Fort Collins, CO 80523 ======================================================================= 9 === Date: Wed, 03 Feb 1993 03:11:46 +1000 From: Arthur@cswamp.apana.org.au (Arthur Marsh) Subject: ARM 610 and garbage collection [was Help installing m3 on ARM] On Tue 26 Jan at 23:39 Andrew Wenn wrote: AW> From: awenn@matilda.vut.edu.au (Andrew Wenn) AW> I am installing m3 on an ACORN machine using the ARM AW> architecture and RISCiX. Although of no help with your immediate problem, I noticed in the November 1992 issue of Byte on page 297: "The ARM610 MMU lets you implement an efficient *concurrent* garbage collector as a permanent background task". Would this be of interest to somone implementing M3 on an ARM based architecture? * Origin: Camelot Swamp MJCNA, Hawthorndene, Sth Australia (8:7000/8) ======================================================================= 10 === Date: Fri, 5 Feb 93 00:34:00 GMT From: Eric Muller Subject: Modula-3 Frequently Asked Questions (FAQ) Archive-name: Modula-3-faq Last-modified: Feb 04 1993 Modula-3 Frequently Asked Questions =================================== What is Modula-3 ? The goal of Modula-3 is to be as simple and safe as it can be while meeting the needs of modern systems programmers. Instead of exploring new features, we studied the features of the Modula family of languages that have proven themselves in practice and tried to simplify them into a harmonious language. We found that most of the successful features were aimed at one of two main goals: greater robustness, and a simpler, more systematic type system. Modula-3 descends from Mesa, Modula-2, Cedar, and Modula-2+. It also resembles its cousins Object Pascal, Oberon, and Euclid. Modula-3 retains one of Modula-2's most successful features, the provision for explicit interfaces between modules. It adds objects and classes, exception handling, garbage collection, lightweight processes (or threads), and the isolation of unsafe features. Is Modula-3 a superset of Modula-2 ? No; valid Modula-2 programs are not valid Modula-3 programs. However, there is a tool to help convert Modula-2 programs to Modula-3. Where can I get a description of Modula-3 ? The definition of Modula-3 is contained in: System Programming with Modula-3 Edited by Greg Nelson Prentice Hall Series in Innovative Technology ISBN 0-13-590464-1 L.C. QA76.66.S87 1991 also known as SPwM3. Here is the table of contents: 1. Introduction 2. Language Definition 3. Standard Interfaces 4. An Introduction to Programming with Threads 5. Thread Synchronization: A Formal Specification 6. I/O Streams: Abstract Types, Real Programs 7. Trestle Window System Tutorial 8. How the Language Got its Spots Chapters 2 and 3 have been reprinted in Sigplan Notices, Volume 27, Number 8, August 1992, pp 15-42. Sam Harbison has written a more tutorial book about Modula3: Modula-3 Samuel P. Harbison Prentice Hall, 1992 ISBN 0-13-596396-6 Where can I get other information on Modula-3 ? There is a Usenet newsgroup, comp.lang.modula3. The archives of that group are available via anonymous ftp from gatekeeper.dec.com in pub/DEC/Modula-3/comp.lang.modula3. If you do not have access to Usenet, there is a relay mailing list; send a message to m3-request@src.dec.com to be added to it. There are a couple high-level overview articles available: "Modula-3", Sam Harbison, Byte, Vol. 15, No. 12, October 1990, pp 385+. "Safe Programming with Modula-3", Sam Harbison, Dr. Dobb's Journal, Vol. 17, No. 10, October 1992, pp 88+. A description of the Modula-3 type system is in "The Modula-3 Type System", Luca Cardelli, Jim Donahue, Mick Jordan, Bill Kalsow, Greg Nelson, Conference Record of the Sixteenth Annual ACM Symposium on Principles of Programming Languages (POPL), Austin Texas, January 11-13 1989, pp 202-212. The Trestle window system toolkit and higher-level FormsVBT toolkit, available with Modula-3, are documented in the following reports: "Trestle Reference Manual", Mark S. Manasse and Greg Nelson, SRC Research Report 68, December 1991. "Trestle Tutorial", Mark S. Manasse and Greg Nelson, SRC Research Report 69, May 1, 1992. "The FormsVBT Reference Manual", Marc H. Brown and James R. Meehan, (soon to be SRC Research Report ??). These reports can be ordered by e-mail; send your request to src-reports@src.dec.com. Where can I get an implementation ? There is only one implementation available today. It has been built by SRC and is available via anonymous ftp from gatekeeper.dec.com in pub/DEC/Modula-3/release. Contributed software can be found in pub/DEC/Modula-3/contrib. The current version, 2.11, implements the language defined in SPwM3. There are versions for the following machines: AIX386 IBM PC running AIX/PS2, AP3000 Apollo DN4500 running Domain/OS ARM Acorn R260 running RISC iX 1.21 DS3100 DECstation 3100 and 5000 running Ultrix 4.0 and 4.2 HP300 HP 9000/300 running HP-UX 8.0 HPPA HP 700/800 running HP-UX 8.0 IBMR2 IBM R6000 running AIX 3.1, IBMRT IBM RT running IBM/4.3, NEXT NeXT running ? OKI Okidata 7300 (i860) running AT&T SVR4.0 SPARC SPARCstation running SunOS 4.1.x SUN3 SUN3 running SunOS SUN386 Sun 386i running SunOS 4.0.1 UMAX Encore Multimax running UMAX 4.3 (R4.1.1) VAX VAX running Ultrix 3.1 SRC Modula-3 includes a user manual, compiler, runtime library, some libraries and a few other goodies (see below). The compiler generates C as an intermediate language and should be fairly easy to port. Except for the very lowest levels of the thread implementation, the entire system is written in Modula-3. What if I don't have ftp access ? Unfortunately, we cannot deliver Modula-3 other than by anonymous ftp. Fortunately, Prime Time Freeware (PTF) includes Modula-3. PTF is a set of two ISO-9660 CDroms filled with 3GB of freeware, issued semi-annually. The latest issue, Volume 1, Number 2, July 1992, contains SRC Modula-3 2.07. PTF is distributed via bookstores and mail. You can reach PTF using: Email: ptf@cfcl.com Fax: [1] (408) 738 2050 Voice: [1] (408) 738 4832 Mail: Prime Time Freeware 415-112 N. Mary Ave., Suite 50 Sunnyvale, CA 94086 USA Can I contribute Modula-3 software ? Certainly. Send us what you are willing to share, be it programs, libraries or other things. We'll put them in the distribution. Right now, the pub/DEC/Modula-3/contrib directory contains: m3rpc an rpc system from Xerox Parc M2toM3 a translator from Modula-2 to Modula-3 m3pc an implementation of Modula-3 for PCs. -- Eric. ======================================================================= 11 === Date: 5 Feb 93 04:05:31 GMT From: aobrodsk@undergrad.math.waterloo.edu (Alex Brodsky) Subject: question reg m3pc In the latest faq release, there was mention of m3 for pc, in the file m3pc, to be made available at gatekeeper, as of Thursday February 4, 1993, I could not find it in the specified directory, could someone please clarify the situation. Thanks very much. ttyl Alex ======================================================================= 12 === Date: 5 Feb 93 12:17:32 GMT From: marc@ecrc.de (Marc Bourgois) Subject: network objects I've come across this concept a few times in relation to m3, but I haven't got a clear idea what they are (will be). Since distribution is a key issue for us, I'm interested in all descriptions/ideas m3 designers/implementers have about it. So, could you please post something about network objects? --- Marc Bourgois European Computer-Industry Research Centre Tel. + (49) 89-92699-179 Arabellastr 17, 8000 Muenchen 81. Germany. Internet: marc@ecrc.de UUCP: ..unido!ecrc!marc ======================================================================= 13 === Date: 6 Feb 1993 17:14:31 GMT From: jgshir@athena.mit.edu (John G Shirlaw) Subject: Modula-3 on the NeXT Hi, Has anyone out there got 2.11 running on the NeXT yet? Thanks john. ======================================================================= 14 === Date: 4 Feb 93 14:13:06 GMT From: dagenais@vlsi (Michel Dagenais) Subject: Forking a Modula 3 program A student here recently had problems with Fork. The M3 program would create 2 pipes, fork, and the child would exec a C program. It worked fine until a number of interfaces were added to the import list. Then, the child and parent would die somewhat randomly. It turns out that when threads are started by imported interfaces, the run time starts using virtual timers. The timers are inherited by the child and eventually the C program (through fork and exec). The C program is not prepared to handle a virtual timer signal and dies, breaking the pipe to the parent. Resetting the timer easily solves the problem, once it is identified. Thus, if you need forking, check the virtual timer. A suitable comment in the Unix.m3 and Uexec.m3 interfaces, close to the fork and exec procedures, could be a good idea. -- --------------------------------------------------------------------- Prof. Michel Dagenais dagenais@vlsi.polymtl.ca Dept of Electrical and Computer Eng. Ecole Polytechnique de Montreal tel: (514) 340-4029 --------------------------------------------------------------------- ======================================================================= 15 === Date: 8 Feb 93 11:23:30 GMT From: serls@dashs.denver.co.us (Dave Serls) Subject: Re: Modula-3 for OS/2? Well, that's it. Is it possible to port the SRC to OS/2 version 2.x? Its 32-bitness should help. -- ============================================================================ Dave Serls 303-973-6120 serls@dashs.denver.co.us Sorry Software ============================================================================ ======================================================================= 16 === Date: Tue, 9 Feb 93 00:29:41 GMT From: Eric Muller Subject: Re: question reg m3pc m3pc is now available from gatekeeper. The FAQ was just a little bit in advance of the rest of the world. Enjoy, Eric. ======================================================================= 17 === Date: Mon, 8 Feb 93 19:30:36 GMT From: Eric Muller Subject: Re: Modula-3 for OS/2? In article <729170610snx@dashs.denver.co.us>, serls@dashs.denver.co.us (Dave Se rls) writes: |> Well, that's it. Is it possible to port the SRC to |> OS/2 version 2.x? Its 32-bitness should help. I think that on our side, we know too little about OS/2 to really answer that question. You may be interested to know that the Interface Police is working on a set of OS-independent interfaces that should make it much easier to run Modula-3 on OSes that don't look like Unix; and that these interfaces will be implemented for Unix machines as well as Windows NT machines. -- Eric. ======================================================================= 18 === Date: Mon, 8 Feb 93 19:28:01 GMT From: Eric Muller Subject: Re: Forking a Modula 3 program In article , dagenais@vlsi (Michel Dagenais) writes: |> A student here recently had problems with Fork. [...] |> It turns out that when threads are started by imported interfaces, the run |> time starts using virtual timers. More precisely, the first time Thread.Fork is invoked, it starts the virtual timer. This leaves unthreaded programs simpler. There is no direct interaction with the import/export relations. However, a change in the imports/exports may change the order of initialization of modules, and change the order in which Thread.Fork and Unix.fork are called in your program. |> The timers are inherited by the child and |> eventually the C program (through fork and exec). The UProcess interface takes care of this detail (among others) for you. When the work of interface police will be available, the use of the U* interfaces will be discouraged, in favor of the OS-independant interfaces that will take care of these things. -- Eric. ======================================================================= 19 === Date: Mon, 8 Feb 93 20:46:59 GMT From: norman@flash.bellcore.com (Norman Ramsey) Subject: Re: Forking a Modula 3 program In article <1993Feb8.192801.12589@src.dec.com> Eric Muller writes: >The UProcess interface takes care of this detail (among others) for you. UProcess wasn't distributed with 2.11. When will it be available on gatekeeper? Norman ======================================================================= 20 === Date: Mon, 8 Feb 93 21:08:12 GMT From: Eric Muller Subject: Re: Forking a Modula 3 program In article <1993Feb8.192801.12589@src.dec.com>, I wrote: |> The UProcess interface takes care of this detail (among others) for you. But I forgot that UProcess is not exported. It is below. It will make its way into the next release of libm3. #!/bin/sh # This is a shell archive (shar 3.32) # made 02/08/1993 21:06 UTC by muller@procope.pa.dec.com # Source directory /tmp_mnt/hoax/r/dlusers2/muller/tmp/uprocess # # existing files will NOT be overwritten # # This shar contains: # length mode name # ------ ---------- ------------------------------------------ # 5099 -rw-r--r-- UProcess.i3 # 10101 -rw-r--r-- UProcess.m3 # 41 -rw-r--r-- m3makefile # if touch 2>&1 | fgrep 'amc' > /dev/null then TOUCH=touch else TOUCH=true fi # ============= UProcess.i3 ============== if test X"$1" != X"-c" -a -f 'UProcess.i3'; then echo "File already exists: skipping 'UProcess.i3'" else echo "x - extracting UProcess.i3 (Text)" sed 's/^X//' << 'SHAR_EOF' > UProcess.i3 && X(* Copyright ) 1991, 1992 Digital Equipment Corporation. *) X(* Distributed only by permission. *) X(* Created on Tue Nov 26 18:30:56 PST 1991 by meehan *) X(* Last modified on Mon Feb 8 13:08:08 PST 1993 by muller *) X(* modified on Tue Mar 3 11:20:22 PST 1992 by meehan *) X XINTERFACE UProcess; X X(* An interface for creating Unix processes and communicating with them via X Unix pipes. *) X XIMPORT Rd, Thread, Usignal, Wr; X XTYPE X Handle = MUTEX OBJECT X pid : CARDINAL; (* the process ID (pid) *) X stdin : Wr.T; X stdout, stderr: Rd.T; X stdin_t, stdout_t, stderr_t: Thread.T; X condition: Thread.Condition; (* Broadcast when child dies. *) X childDied: BOOLEAN; (* Guarded by the mutex *) X status: WaitStatus; (* Valid only when childDied = TRUE *) X END; X WaitStatus = RECORD X exitCode : [0 .. 255]; X terminationSignal: [0 .. 127]; X dumpedCore : BOOLEAN X END; X XEXCEPTION Error(TEXT); (* Unix errors are reported this way. *) X XPROCEDURE Fork ( program : TEXT; X READONLY args : ARRAY OF TEXT; X mergeOutput := FALSE; X ignoreOutput := FALSE): Handle X RAISES {Error, Rd.Failure, Wr.Failure}; X(* This forks a Unix subprocess and opens up to 3 streams to communicate X with it. X X "program" should be a pathname, e.g., "/usr/local/bin/foo". Fork uses X execvp(2), which "duplicates the shell's actions in searching for an X executable file in a list of directories. The directory list is obtained X from the environment." X X "args" should be the complete list of arguments, including argument 0, X the name of the program, e.g., "foo". X X Upon return, the 'stdin' field of the Handle is a *writer* to the caller X of Fork. The characters sent to write appear on Stdio.stdin of the X forked process. X X Likewise, 'stdout' and 'stderr' are *readers* to the caller of Fork, and X they get their characters from Stdio.stdout and Stdio.stderr of the X forked process. X X If "mergeOutput" is true, then the 'stderr' field of the the result X is NIL and characters written to Stdio.stderr by the forked process X appear on the 'stdout' field of the result handler. X X If "ignoreOutput" is true, then output from the child's stdout and stderr X will be read and discarded. The 'stderr' and 'stdout' fields of X the result handler are NIL. X X Fork first disables the virtual interval timer; see setitimer(2); This X prevents other threads from running while we're cloning the image. X X Fork then calls vfork(2). The child process closes the "writing" X side of its stdin pipe, and the "reading" side of its stdout and X stderr pipes. It calls dup2(2) to reset its stdin, stdout, and X stderr. Finally, it calls execvp(2) to run the program. X X The parent process then re-enables the virtual timer, even if an X exception was raised. X X All errors in the child process, up to and including the "execvp", X produce error messages on Stdio.stderr, and the child process calls X _exit(2), not exit(2). X X The returned value, "handle", is a subtype of MUTEX. The mutex X guards the "childDied" field, which is FALSE when the fork is X created. When the child-process terminates, a background thread X will set "handle.childDied" to true and will call Thread.Broadcast X on "handle.condition". After that point, the value of the "status" X field is valid. X X *) X XPROCEDURE Wait (h: Handle); X(* This is a simple mechanism for blocking the current thread (not the X entire process) until the child process ("h.pid") X and the threads forked by AttachStreams have terminated. X After this procedure returns, the value of "h.status" is defined. X *) X XPROCEDURE Signal (h: Handle; signal := Usignal.SIGTERM) RAISES {Error}; X(* This signals the subprocess. It takes no action with respect to the X I/O streams. *) X XPROCEDURE AttachStreams (h : Handle; X stdinReader : Rd.T := NIL; X stdoutWriter, stderrWriter: Wr.T := NIL ); X(* This will fork a separate thread to read characters from X "stdinReader" and write them to "h.stdin", unless "stdinReader" X h.stdin is NIL. X Likewise, it will fork a thread to reader characters from X "h.stdout" and write them to the stdoutWriter, unless stdoutWriter X or h.stdout is NIL. Likewise for the stderr pipe and stderrWriter. X These threads terminate on Rd.EndOfFile, Rd.Failure, Wr.Failure, or X Thread.Alerted. The effect of attaching more than one stream to X the same pipe is undefined. When a newline is read from any reader X ("stdinReader", "h.stdout", or "h.stderr"), it will be sent to the X corresponding writer, and then Wr.Flush will be called on that X writer. X Threads that are created are remembered in the handle, and Wait will X join those threads. *) X XEND UProcess. X X SHAR_EOF $TOUCH -am 0208130693 UProcess.i3 && chmod 0644 UProcess.i3 || echo "restore of UProcess.i3 failed" set `wc -c UProcess.i3`;Wc_c=$1 if test "$Wc_c" != "5099"; then echo original size 5099, current size $Wc_c fi fi # ============= UProcess.m3 ============== if test X"$1" != X"-c" -a -f 'UProcess.m3'; then echo "File already exists: skipping 'UProcess.m3'" else echo "x - extracting UProcess.m3 (Text)" sed 's/^X//' << 'SHAR_EOF' > UProcess.m3 && X(* Copyright (C) 1992, Digital Equipment Corporation * ) X(* All rights reserved. * ) X(* See the file COPYRIGHT for a full description. * ) X(* * ) X(* modified on Mon Aug 17 21:27:16 PDT 1992 by meehan * ) X XUNSAFE MODULE UProcess; X XIMPORT Ctypes, Fmt, IntRefTbl, M3toC, Rd, Stdio, Thread, Time, Unix, Uexec; XIMPORT UFileRdWr, Utime, Wr, RTMisc, Uerror, SmallIO, Usignal; X XFROM Uerror IMPORT errno; X X<* PRAGMA LL *> X XVAR PidTable := IntRefTbl.New (); X XTYPE X Arec = RECORD X name: Ctypes.CharStar; X argv: REF ARRAY OF Ctypes.CharStar X END; X APipe = ARRAY [0 .. 1] OF Ctypes.int; X VPipe = Thread.Closure OBJECT X rd : Rd.T; X wr : Wr.T; X name: TEXT X OVERRIDES X apply := RW X END; X XPROCEDURE Close (pid, n: INTEGER) RAISES {Error} = X BEGIN X IF Unix.close (n) = -1 THEN X Gripe (pid, "close " & Fmt.Int (n)); X END; X END Close; X XPROCEDURE Pipe (VAR p: APipe) RAISES {Error} = X BEGIN X IF Unix.pipe (p) = -1 THEN X Gripe (-1, "pipe"); X END; X END Pipe; X XPROCEDURE Dup2 (pid, a, b: INTEGER) RAISES {Error} = X BEGIN X IF Unix.dup2 (a, b) = -1 THEN X Gripe (pid, "dup2 " & Fmt.Int (a) & ", " & Fmt.Int (b)); X END; X END Dup2; X XPROCEDURE Fork ( program : TEXT; X READONLY args : ARRAY OF TEXT; X mergeOutput := FALSE; X ignoreOutput := FALSE ): Handle X RAISES {Error, Rd.Failure, Wr.Failure} = X VAR X stdin, stdout, stderr: APipe; X h : Handle; X pid : INTEGER; X arec := ConvertArgs (program, args); X oit : Utime.struct_itimerval; X BEGIN X Pipe (stdin); X IF NOT ignoreOutput THEN X Pipe (stdout); X IF NOT mergeOutput THEN X Pipe (stderr); X END; X END; X X (* Disable the timer BEFORE forking. *) X VAR nit := Utime.struct_itimerval { X it_interval := Utime.struct_timeval {0, 0}, X it_value := Utime.struct_timeval {0, 0}}; X BEGIN X IF Utime.setitimer (Utime.ITIMER_VIRTUAL, nit, oit) = -1 THEN X Gripe (-1, "Couldn't disable virtual timer."); X END; X END; X X TRY (* FINALLY re-enable timer *) X pid := Unix.vfork (); X X IF pid < 0 THEN X Gripe (pid, "Couldn't fork."); X X ELSIF pid = 0 THEN (* child *) X (* connect stdin to end of pipe *) X Close (pid, stdin [Unix.writeEnd]); X Dup2 (pid, stdin [Unix.readEnd], SmallIO.stdin); X Close (pid, stdin [Unix.readEnd]); X X IF ignoreOutput THEN X (* connect stdout and stderr to /dev/null *) X VAR devnull := Unix.open (M3toC.TtoS ("/dev/null"), X Unix.O_WRONLY, Unix.Mrwrwrw); X BEGIN X IF devnull = -1 THEN X Gripe (pid, "Couldn't open /dev/null in child"); X END; X Dup2 (pid, devnull, SmallIO.stdout); X Dup2 (pid, devnull, SmallIO.stderr); X Close (pid, devnull); X END; X ELSE X (* connect stdout to write end of pipe *) X Close (pid, stdout [Unix.readEnd]); X Dup2 (pid, stdout [Unix.writeEnd], SmallIO.stdout); X Close (pid, stdout [Unix.writeEnd]); X X IF mergeOutput THEN X (* connect stderr to stdout *) X Dup2 (pid, SmallIO.stdout, SmallIO.stderr); X ELSE X Close (pid, stderr [Unix.readEnd]); X Dup2 (pid, stderr [Unix.writeEnd], SmallIO.stderr); X Close (pid, stderr [Unix.writeEnd]); X END; X END; X X WITH v = Uexec.execvp (arec.name, ADR (arec.argv [0])) DO X Gripe (pid, Fmt.F ("execvp returned %s!", Fmt.Int (v))); END; X X X ELSE (* parent *) X h := NEW (Handle, pid := pid, X condition := NEW (Thread.Condition), childDied := FALSE, X stdin_t := NIL, stdout_t := NIL, stderr_t := NIL); X X Close (pid, stdin [Unix.readEnd]); X h.stdin := UFileRdWr.CreateFileWriter (stdin [Unix.writeEnd], TRUE); X IF ignoreOutput THEN X h.stdout := NIL; X h.stderr := NIL; X ELSE X Close (pid, stdout [Unix.writeEnd]); X h.stdout := UFileRdWr.CreateFileReader (stdout [Unix.readEnd]); X IF mergeOutput THEN X h.stderr := NIL; X ELSE X Close (pid, stderr [Unix.writeEnd]); X h.stderr := UFileRdWr.CreateFileReader (stderr [Unix.readEnd]); X END; X END; X X FreeArgs (arec); X EVAL PidTable.put (pid, h); X RETURN h X END X X FINALLY (* Restore previous virtual timer. *) X VAR nit: Utime.struct_itimerval; BEGIN X IF Utime.setitimer (Utime.ITIMER_VIRTUAL, oit, nit) # 0 THEN X Gripe (-1, "Couldn't re-enable virtual timer."); END; END; X END X END Fork; X XPROCEDURE Gripe (pid: INTEGER; msg: TEXT) RAISES {Error} = X VAR e := errno; X BEGIN X msg := Fmt.F ("pid %s, %s Errno = %s: %s", Fmt.Int (pid), msg, Fmt.Int (e) , X M3toC.StoT (Uerror.GetFrom_sys_errlist (e))); X IF pid = 0 THEN (* child *) X TRY X Wr.PutText (Stdio.stderr, msg); X Wr.Flush (Stdio.stderr) X EXCEPT X ELSE (* ignore failures at this point *) X END; X RTMisc.Exit (99) X ELSE X RAISE Error (msg) X END X END Gripe; X X XPROCEDURE ConvertArgs (program: TEXT; READONLY args: ARRAY OF TEXT): Arec X RAISES {Error} = X VAR X result: Arec; X j := 0; X BEGIN X result.argv := NEW (REF ARRAY OF Ctypes.CharStar, 1 + NUMBER (args)); X result.name := M3toC.TtoS (program); X FOR i := FIRST (args) TO LAST (args) DO X result.argv [j] := M3toC.TtoS (args [i]); X INC (j) X END; X result.argv [NUMBER (args)] := NIL; X RETURN result X END ConvertArgs; X XPROCEDURE FreeArgs (VAR arec: Arec) = X BEGIN X M3toC.FreeS (arec.name); X FOR j := FIRST (arec.argv^) TO LAST (arec.argv^) DO X IF arec.argv [j] = NIL THEN X EXIT X ELSE X M3toC.FreeS (arec.argv [j]); X arec.argv [j] := NIL X END X END X END FreeArgs; X XPROCEDURE AttachStreams (h : Handle; X stdinReader : Rd.T := NIL; X stdoutWriter, stderrWriter: Wr.T := NIL ) = X BEGIN X IF stdinReader # NIL AND h.stdin # NIL THEN X h.stdin_t := Thread.Fork (NEW (VPipe, rd := stdinReader, wr := h.stdin, X name := "stdin")) X END; X IF stdoutWriter # NIL AND h.stdout # NIL THEN X h.stdout_t := Thread.Fork (NEW (VPipe, X rd := h.stdout, wr := stdoutWriter, X name := "stdout")) X END; X IF stderrWriter # NIL AND h.stderr # NIL THEN X h.stderr_t := Thread.Fork (NEW (VPipe, X rd := h.stderr, wr := stderrWriter, X name := "stderr")) X END X END AttachStreams; X XPROCEDURE RW (vp: VPipe): REFANY = X BEGIN X TRY X LOOP X WITH c = Rd.GetChar (vp.rd) DO X Wr.PutChar (vp.wr, c); X IF c = '\n' THEN Wr.Flush (vp.wr) END X END X END X EXCEPT X | Rd.EndOfFile, Rd.Failure, Wr.Failure, Thread.Alerted => X END; X RETURN NIL X END RW; X XVAR X mu := NEW (MUTEX); X c := NEW (Thread.Condition); <* LL = mu *> X waiters: CARDINAL := 0; <* LL = mu *> X XPROCEDURE Wait3Forever (<* UNUSED *> cl: Thread.Closure): REFANY = X VAR X status: Uexec.w_T; X h : Handle; X ref : REFANY; X BEGIN X LOOP (* outer *) X LOCK mu DO WHILE waiters = 0 DO Thread.Wait (mu, c) END END; X LOOP (* inner *) X WITH x = Uexec.wait3 ( X ADR (LOOPHOLE (status, Uexec.w_A)), Uexec.WNOHANG, NIL) DO X IF x > 0 THEN X TRY X IF PidTable.delete (x, ref) THEN X h := ref; X LOCK h DO X h.status.exitCode := status.w_Retcode; X h.status.terminationSignal := status.w_Termsig; X h.status.dumpedCore := status.w_Coredump # 0; X h.childDied := TRUE; X Thread.Broadcast (h.condition) X END X END X EXCEPT X IntRefTbl.NotFound => X END X ELSE X (* x might be -1 and errno = ECHILD (no children). OK *) X LOCK mu DO X IF waiters = 0 THEN EXIT END (* resume outer loop *) X END; X Time.Pause (100000) (* and resume inner loop *) X END (* IF x > 0 *) X END (* WITH *) X END (* inner LOOP *) X END (* outer LOOP *) X END Wait3Forever; X XPROCEDURE Wait (h: Handle) = X BEGIN X LOCK mu DO INC (waiters); Thread.Signal (c) END; X LOCK h DO X WHILE NOT h.childDied DO Thread.Wait (h, h.condition) END X END; X IF h.stdin_t # NIL THEN X EVAL Thread.Join (h.stdin_t); X h.stdin_t := NIL; X END; X IF h.stdout_t # NIL THEN X EVAL Thread.Join (h.stdout_t); X h.stdout_t := NIL; X END; X IF h.stderr_t # NIL THEN X EVAL Thread.Join (h.stderr_t); X h.stderr_t := NIL; X END; X LOCK mu DO DEC (waiters) END X END Wait; X XPROCEDURE Signal (h: Handle; signal := Usignal.SIGTERM) RAISES {Error} = X BEGIN X IF Usignal.kill (h.pid, signal) # 0 THEN X Gripe (h.pid, "Couldn't signal child process.") X END X END Signal; X XBEGIN X EVAL Thread.Fork (NEW (Thread.Closure, apply := Wait3Forever)) XEND UProcess. X SHAR_EOF $TOUCH -am 0208130693 UProcess.m3 && chmod 0644 UProcess.m3 || echo "restore of UProcess.m3 failed" set `wc -c UProcess.m3`;Wc_c=$1 if test "$Wc_c" != "10101"; then echo original size 10101, current size $Wc_c fi fi # ============= m3makefile ============== if test X"$1" != X"-c" -a -f 'm3makefile'; then echo "File already exists: skipping 'm3makefile'" else echo "x - extracting m3makefile (Text)" sed 's/^X//' << 'SHAR_EOF' > m3makefile && XModule (UProcess) X XLibrary (m3uprocess) X SHAR_EOF $TOUCH -am 0208130693 m3makefile && chmod 0644 m3makefile || echo "restore of m3makefile failed" set `wc -c m3makefile`;Wc_c=$1 if test "$Wc_c" != "41"; then echo original size 41, current size $Wc_c fi fi exit 0 -- Eric. ======================================================================= 21 === Date: 8 Feb 93 20:45:28 GMT From: nettles+@cs.cmu.edu (Scott Nettles) Subject: Details on the new incremental GC? Being the garbage collection weeny that I am, I'd like to hear more details about the new incremental collector. I'd also like to know more about how finalization works. Could someone in the know either post or point me at some documentation? Thanks! Scott nettles@cs.cmu.edu ======================================================================= 22 === Date: Thu, 11 Feb 93 20:38:02 GMT From: jdd@src.dec.com (John DeTreville) Subject: Re: Details on the new incremental GC? The new collector is really pretty vanilla, although a little complex in its implementation. As you recall, the old collector was a stop-and-copy collector. The new one is based on the old one, but uses VM synchronization to achieve incremental collection (a la Appel/Ellis/Li). With an incremental collector, the program can run during a collection. The collector is implemented as a monitor; program actions like allocations drive it forward but each collection is broken into a large number of small pieces. We maintain the invariant that locals and globals hold only objects in the new space. Therefore, the only way the program could access references to the old space is by deferencing "gray" heap objects, those in the new space whose references into the old space have not yet been updated. To keep this from happening, we read-protect all pages containing gray objects. As the collector cleans gray pages, it unprotects them. If the program tries to read a gray page, it gets a fault, the collector cleans the page and unprotects it, and restarts the program. The program can therefore never get a reference into the old space. Write-protection of heap pages is also used to implement generational collection, maintaining the "remembered set." Pages in the older generation are write-protected; a write fault simply clears the protection but remembers that the page might now contain a reference into the newer generation. Not all architectures can support VM protection. Moreover, some of the code is OS-dependent, and it's currently implemented only for DECstations running Ultrix and SPARCs running SunOS. When the code is not implemented, the collector becomes an ordinary stop-and-copy collector, much like the previous one. Incremental collection gives almost unnoticable interruptions of service due to collections. Generational collection spends less total time in the collector. That's fairly nontechnical; let me know if you have more detailed questions. Cheers, John ======================================================================= 23 === Date: Fri, 12 Feb 93 18:49:56 GMT From: jdd@src.dec.com (John DeTreville) Subject: Re: Details on the new incremental GC? [Scott asked me some more questions via mail, and asked me to post the answers.] Do you have any special tricks to avoid a flurry of faults when you've just flipped or has that not been a problem? All I can do right now is to try to encourage locality. The previous collector treated the gray pages as a queue; I treat them as a stack, which is better. Whenever the collector gets to choose what page to clean, it cleans the current copy page, which increases the number of intra-page references. And I separate REF-containing objects from non-REF-containing when I copy them, so that I never need to protect objects with no REFs. In general is the overhead of fault handling a big deal? Yes and no. It's higher than I'd like, but the collector runs faster than the old one, so things could be worse. BTW, I think the most interesting work is in the generational side; I'll be writing it up soon. How does finalization work and what's the interface to it? I've appended the interface; it's messy to implement but has good semantics, and I believe it's portable to other collector strategies. I've recently polished the words; let me know if it's confusing. To support weak refs in the collector, we first do an ordinary copy without treating weak refs as roots. If there are no weakly-referenced nodes, we're done. Otherwise, we then need a mark phase on weakly referenced nodes remaining in the old space, that moves them to the new space if they're reachable from another weakly-referenced node; then we copy everything reachable from them. Finally, we treat weakly referenced nodes as roots and copy everything from them to the new space. Whew. There's a little bit of optimization in distinguishing weakly-referenced objects with and without cleanup procedures. Cheers, John ---------- (* Copyright 1992 by Digital Equipment Corp. *) (* Most Modula-3 programs simply let the garbage collector deallocate storage automatically, but some programs need more control. For example, if a variable allocated in the traced heap contains a handle on a resource in the operating system or in some other address space, then when the variable is garbage-collected it may be important to deallocate the resource. The "WeakRef" interface provides this additional control. A {\it node} is a datum allocated on the traced heap. Thus a node is either the referent of a variable of a fixed reference type or the data record of a traced object. A "WeakRef.T" is a data structure that refers to a node without protecting the node from the garbage collector. If "w" is a weak reference, we write "nd(w)" to denote the node to which "w" refers. We say that a weak reference "w" {\it dies} at the moment that the garbage collector detects that "nd(w)" is unreachable. A precise definition of unreachable is given below. Once a weak reference has died, it remains dead forever, even if the node to which it refers becomes reachable again. Associated with each weak reference "w" is a {\it cleanup procedure} "cp(w)". If the cleanup procedure is not "NIL", the garbage collector will schedule a call to it when the weak reference dies. *) INTERFACE WeakRef; TYPE T = ARRAY [0..7] OF BITS 8 FOR [0..255]; (* Please treat this as though it were an opaque type: the only operations allowed are assignment, equality tests, and the procedures in this interface. *) PROCEDURE FromRef(r: REFANY; p: CleanUpProc := NIL): T; (* Return a weak reference "w" such that "nd(w) = r" and "cp(w) = p". It is a checked runtime error if "r" is "NIL". It is illegal to create more than one weak reference with a non-nil cleanup to the same node; violations of this rule may lead to a checked runtime error, or may cause one of the cleanup actions to be omitted. "FromRef" is not necessarily functional: it is possible that "nd(w1) = nd(w2)" but "w1 # w2". *) PROCEDURE ToRef(w: T): REFANY; (* Return a reference to "nd(w)", unless "w" is dead, in which case return "NIL". *) TYPE CleanUpProc = PROCEDURE(READONLY w: T; r: REFANY); (* If "cp(w)" is not "NIL", then when "w" dies, the garbage collector will schedule the call "cp(w)(w, )". *) END WeakRef. (* The cleanup procedure will be executed at some point after the weak reference dies. A cleanup procedure is called with no locks held; it must return promptly to allow other objects to be cleaned up. The computation "cp(w)(w, ref)" is allowed to store "ref" in a non-local variable, thus making "nd(w)" reachable again; the heap storage will not have been freed. This does not change the fact that "w" is dead. The cleanup procedure can re-enable cleanup, if desired, by creating a new weak reference to "nd(w)". The storage for a node is reclaimed when it is unreachable and all weak references to it are dead and all cleanup calls scheduled for it have been completed. Finally we come to the precise definition of ``reachable'': A node is {\it reachable} if it can be reached by a path of traced references starting from a current procedure activation record, a global variable, or a weakly referenced node with a non-nil cleanup {\it other than itself}. Thus a weak reference to a node "nd" does not make "nd" reachable, but if it has a non-nil cleanup, it makes other nodes referenced from "nd" reachable. For example, if "A" and "B" are two nodes that are weakly referenced by weak references with non-nil cleanup procedures, then if "B" is reachable from "A", then "B" is reachable. But if "A" is not reachable, then the garbage collector will eventually detect this and schedule the cleanup of "A". If the cleanup call returns without resurrecting "A", then "A"'s storage will be reclaimed, at which point "B" will be unreachable, which will lead to its cleanup. If "A" and "B" are weakly referenced nodes with non-nil cleanups that are connected by a cycle of traced references, then both of them are reachable. As long as the cycle persists, neither will be cleaned up. This situation represents a storage leak and should be avoided. \subsection*{Examples} {\bf 1}.\ \ Suppose you want writers of the class "WrX.T" to be automatically flushed and closed if they become unreachable. Then you could write code like the following in the "WrX" module: | MODULE WrX; IMPORT WeakRef, Wr, ...; | | PROCEDURE New(...): T = | VAR res := NEW(T); BEGIN | (* ... initialize res as a WrX.T ... *) | EVAL WeakRef.FromRef(res, Cleanup); | RETURN res | END New; | | PROCEDURE Cleanup(self: WeakRef.T; ref: REFANY) = | VAR wr: T := ref; BEGIN | IF NOT Wr.Closed(wr) THEN | Wr.Flush(wr); | Wr.Close(wr) | END | END Cleanup; | There is no danger that another thread could close the writer after the test "NOT Wr.Closed(wr)" and before the call "Wr.Flush(wr)", since when "Cleanup" is called, the writer is unreachable. Therefore the cleanup method has exclusive access to the writer. {\bf 2.}\ \ The network object runtime must map wire representations for network objects into surrogate objects. To hand out the same surrogate for the same wire representation, it keeps a table mapping wire representations to surrogates. This table contains weak references, so the table entry itself does not prevent the surrogate from being collected. When the surrogate is collected, it is removed from the table and the server containing that object is notified that the client no longer has a surrogate for it. When a weak reference in the table becomes dead, the network object represented by the dead surrogate might be unmarshaled by the address space before the surrogate is cleaned up. In this case the unmarshaling code resurrects the unreachable surrogate by creating a new weak reference and inserting it in the table in place of the dead weak reference. The cleanup code can tell whether to report in clean by checking whether there is a new weak reference in the table or not. Here is a sketch of the code: | TYPE Surrogate = OBJECT wr: WireRep; ... END; | VAR | mu := NEW(MUTEX); | <* LL >= {mu} *> | tbl := NEW(WireRepToWeakRefTbl.T); The mutex "mu" must be held to read or write "tbl" (that is what the "LL" pragma means). The table "tbl" maps "WireRep"s to "WeakRef"s that reference surrogates. The following invariants hold whenever "mu" is not held: If "tbl(wrep)" is not dead, then "nd(tbl(wrep))" is the surrogate for the network object whose wire representation is "wrep". If "tbl(wrep)" is dead, then the surrogate for "wrep" is unreachable. If "tbl" has no entry for "wrep", then the address space contains no surrogate for "wrep". | PROCEDURE Cleanup(wref: WeakRef.T; ref: REFANY) = | <* LL = {} *> | VAR | srg := NARROW(ref, Surrogate); | tblVal: WeakRef.T; | BEGIN | LOCK mu DO | IF tbl.get(srg.wr, tblVal) AND wref = tblVal | THEN | EVAL tbl.delete(srg.wr); | ... Report that srg is deleted ... | END | END | END Cleanup; | | PROCEDURE WireRepToSrg(wrep: WireRep): Surrogate = | VAR wref: WeakRef.T; res: Surrogate; BEGIN | LOCK mu DO | IF tbl.get(wrep, wref) THEN | res := WeakRef.ToRef(wref); | IF res # NIL THEN RETURN res END | END; | res := NewSurrogate(wrep); | EVAL tbl.put(wrep, WeakRef.FromRef(res, Cleanup)); | RETURN res | END | END WireRepToSrg; In the above we assume that "NewSurrogate" creates a new surrogate from a wire representation. *) ======================================================================= 24 === Date: Fri, 12 Feb 1993 15:26:51 GMT From: os102@cl.cam.ac.uk (Oliver Stephens) Subject: Oddity with TextPorts I wonder if anyone else has come across this one: If I have a Trestle program running iconised for a length of time (like overnight, say) then when I de-iconise it, about 1 out of 5 times, TextPorts won't accept any keyboard or mouse input, no matter how hard and long I try and make them. Buttons still work OK, so do home-grown VBTs and things like ListVBTs and ScrollBars; it seems to be unique to TextPorts. (I am running m3 2.11 on SPARC under mwm with X11R4) ------------------------------------------------------------------------- Olly Stephens oliver.stephens@cl.cam.ac.uk Computer Laboratory University of Cambridge Loved you there and then, and now like a sheep United Kingdom - Van Morrison ======================================================================= 25 === Date: Sat, 13 Feb 93 01:01:02 -0800 From: msm@src.dec.com Subject: Re: Object type questions In response to your questions, 1) It is a bit verbose, but that's the idiom that we've grown accustomed to for making partial revelations. If you were willing to repeat all of the declarations for the type in its revelation, you could dispense with giving the intermediate type a name, but that's much more error-prone. One might think about some syntactic sugar for "the minimal type matching what's statically known about T", which you could use in the revelation, but instead the Public convention has grown up. 2) Even if you reveal the method values in the declaration of a type, method invocation is still going to have to examine the method suite of the object, because any call to the method might be a call on an object which is (synamically) a subtype of the static type, and which might therefore override the method. This is related to your confusion with point 3. To achieve an effect like C++ non-virtual member functions, you should either define procedures in the interface, or, instead of calling object.method, you should call ObjectType.method. 3) Narrowing an object to a supertype doesn't change any properties of the object; it merely changes your view of the mapping of names within the object to offsets in the object (either by extending the map, or contracting it). You can think of the methods of an object simply as extra procedure-valued fields of the object (although the implementation is more space-efficient than that). Another way of thinking about it is that METHODS in M3 are like virtual member functions in C++. Suppose we have A = OBJECT a: INTEGER END; B = A OBJECT b: INTEGER END; If I take an object of type B, and I narrow it to an A, and pass it to a procedure expecting an A, the b field is still there; that procedure just can't name it. Similarly, if we have A = OBJECT METHODS a() := AProc END; B = A OBJECT OVERRIDES a := BProc END; If b is a B, B.a() invokes BProc, as does NARROW(b, A).a(), since no value has changed. (If B was defined to be A OBJECT METHODS a := BProc END; that would introduce a new "field" named a which would obscure the old field of that name. When I narrow it to an A, the name a refers to the offset for the old field, and thus to AProc). I can always invoke AProc by calling A.a(b), if I want; that may be useful in the implementation of BProc, for instance. Without this, method overriding wouldn't accomplish much of anything. The reason that you create a subtype of some type is so that you can pass it to all the same old procedures that statically expect the supertype. The reason that you override a method is to define a new behavior for that operation; if that's not what you want, you should add a new method instead. Mark ======================================================================= 26 === Date: 12 Feb 93 03:58:50 GMT From: robh@eclipse.cs.colorado.edu (Robert G Henderson) Subject: Object type questions I have a few questions related to object types. I welcome any information you can provide. Feel free to point me to the applicable documentation when appropriate (in other words, RTFM responses will be gracious accepted as long as you tell me which M :-). 1. I find the use of object types in conjunction with information hiding to be a bit cumbersome. I am defining a public type in the interface to expose those features of the class I want public. I then make the actual class a subtype of this public type in order to hide the features of the class I want private. Is this the "accepted" way of achieving information hiding with classes? It just seems a little strange to have to declare two actual object types for each conceptual class just to achieve information hiding. 2. I am declaring METHODS in the public object type (in the interface) and not initializing them. I then OVERRIDE them (in the module) and provide a procedure that implements the method. For example: In the interface: TYPE T <: Public_T; Public_T = OBJECT METHODS Foo(); Bar(); END; and in the module: REVEAL T = Public_T BRANDED OBJECT SomethingPrivate: INTEGER; OVERRIDES Foo := FooProc; Bar := BarProc; END; The problem I am having with this is related to run-time performance. I am finding that the the calls to Foo and Bar are incurring overhead related to dynamic dispatch so a call to object.Foo() is somewhat more expensive than to ModuleName.FooProc(object). I would expect to pay the overhead of dynamic dispatch if I declared an object type that was a subtype of this type and overrode Foo and Bar. However, I don't really need the overhead of dispatch. But, by using the technique shown above to achieve information hiding with object types, it seems that I am paying the cost. Is there a way to achieve this level of information hiding with object types and not pay the dispatch overhead and without having to make normal procedure calls like ModuleName.FooProc(object)? 3. I am a little puzzled by the interaction between OVERRIDEs and NARROW. If an object that overrides a method defined in the superclass is NARROWed to the supertype, the overridden method is still not visible. What was the motivation behind these semantics? Why would you not want the NARROW to reveal the method in the supertype, as is the case if the subtype declares a new METHOD rather than overriding? I greatly appreciate any and all responses to these (hopefully not *too* naive) questions. I'm relatively new to Modula-3 and am trying to gain a better understanding of the language. Feel free to respond either via a followup post or email, whichever you feel appropriate. Thanks. --Rob ------------- Rob Henderson Department of Computer Science CSops Staff/Graduate Student Campus Box 430, ECEE00-69 robh@cs.colorado.edu University of Colorado (303) 492-5720 Boulder, CO 80309-0430 ======================================================================= 27 === Date: 13 Feb 93 01:02:52 GMT From: dmiller@beta.tricity.wsu.edu (David L. Miller) Subject: Re: Help with building mentor In article , bmiller@atto.cs.umn.edu (Bradley N. Miller ) writes: |> |> one executable is large than the whole package! |> If anyone could give me any pointers as to where I might have gone |> astray I would really appreciate it. (my sysadmin too) |> Those numbers sound about like what I encountered when building m3... I ended up with most executables in the 5MB to 6MB range with a peak of about 18MB :( |> Brad |> |> bmiller@cs.umn.edu |> -- |> ---------------------------------------------------------------------------- --- |> Brad Miller | e-mail: bmiller@cs.umn.edu | |> University of Minnesota | | |> | this space for rent | -- ***************************************************************************** David L. Miller Internet: dmiller@beta.tricity.wsu.edu Systems Programmer/Network Analyst BITNET: MILLERD@WSUVM1 Washington State University Tri-Cities UUCP: ...!yoda!dmiller 100 Sprout Road Richland, WA 99352 Phone: (509)375-9245 ***************************************************************************** ======================================================================= 28 === Date: Sat, 13 Feb 93 17:40:09 -0800 From: msm@src.dec.com Subject: Re: Help with building mentor No error; M3 executables (especially with symbols) are very large. If you're running on a SPARC, you might try using shared libraries to reduce the disk requirements for executables. You should also be able to strip the executables and gain a significant savings in size; using your C optimizer may also help, if it doesn't produce code that doesn't work. Mark ======================================================================= 29 === Date: Sun, 14 Feb 93 07:06:43 GMT From: Eric Muller Subject: Re: Help with building mentor You can reduce the size of executable by not compiling with debug (the default). In mentor/src/m3makefile, add the line: M3OPT = at the top. -- Eric. ======================================================================= 30 === Date: 12 Feb 93 21:25:02 GMT From: bmiller@atto.cs.umn.edu (Bradley N. Miller) Subject: Help with building mentor Well, After reading the 'Color and Sound in Algorithm Animation' article in the December issue of Computer, I was motivated to build the modula3 system so I could run some of the animations myself. So here is where I'm at: I think that I have everything built correctly up to the point of building mentor. I do a m3make build_install.mentor, and off we go compiling for a VERY long time. finally I see a message that we are linking, and shortly after that we are out of disk space. So I try again, same result. Now, as an experiment I decided to build just one part of mentor. so I cd to euclid/src and do a make. This actually works however this is what the euclid executable looks like: -rwx------ 1 bmiller 12419072 Feb 12 15:20 /home/grad08/bmiller/m3/mentor.ex/ euclid/src/euclid No wonder I run out of disk space when I try to build everything! Now the thing that puzzles me is that according to the README these are the characteristics of the mentor package File Build Inst. Src. Desc name size disk cpu mentor 328 9762 42 4 1017 algorithm animation demos one executable is large than the whole package! If anyone could give me any pointers as to where I might have gone astray I would really appreciate it. (my sysadmin too) Brad bmiller@cs.umn.edu -- ------------------------------------------------------------------------------- Brad Miller | e-mail: bmiller@cs.umn.edu | University of Minnesota | | | this space for rent | ======================================================================= 31 === Date: 13 Feb 1993 02:24:51 GMT From: patl@bodacia.Eng.Sun.COM (Pat Lashley) Subject: Cstdio/SmallIO porting question I'm starting a Modula-3 port to a non-unix system. The easiest method is probably to use some unix emulation capabilities that were developed (by someone else) for the gcc port. It looks pretty smooth so far, except for the I/O buffer definition in Cstdio.i3. The stdio.h file on the target system claims to be based on the BSD Tahoe release. The definition of the I/O buffer is significantly different from that on SunOS4.x, Solaris-2, or any other system I'm familiar with. (Among other things, it has separate read and write counters, a pointer for a separate ungetc buffer for long ungetc's, etc.) The standard SmallIO package is expecting an iobuf that consists of little more than a couple of pointers, a size, and a count. I'm not familiar enough with the SRC m3 system to know whether I should simply stick with the simple iobuf definition in Cstdio; or should I re-write SmallIO to use the longer definition. I'm hoping that someone out there can clear up my ignorance... Thanks, -Pat --- PMLashley plashley@Sun.COM SunSoft:NeWS/TNT "Those who do not understand NeWS are doomed to recreate it - badly" ======================================================================= 32 === Date: 16 Feb 93 00:49:02 GMT From: patl@bodacia.Eng.Sun.COM (Pat Lashley) Subject: :? SunOS/OW patch required for M3 X11 apps Some of the X11 demo apps (e.g. solitaire) are crashing OpenWindows. I seem to recall seeing a message a while back that contained the number of a SunOS or OpenWindows patch that fixes this. I thought I'd saved it, but I can't find it in my archives, nor in a quick search of the archives on gatekeeper. Could one of you kind souls please mail me the info? Thanks, -Pat --- PMLashley plashley@Sun.COM SunSoft:NeWS/TNT "Those who do not know NeWS are doomed to recreate it - badly." ======================================================================= 33 === Date: Mon, 15 Feb 1993 16:23:25 GMT From: bmiller@myria.cs.umn.edu (Bradley N. Miller) Subject: Re: Help with building mentor Thanks very much to all who responded to my plea. Stripping the executable reduced the size of the file by a whopping 10 Meg! I am also going to try a build with the debug option turned off and see what that gets me. Thanks again, Brad bmiller@cs.umn.edu ======================================================================= 34 === Date: 16 Feb 93 23:38:49 GMT From: dsims@don.ece.uc.edu (David Sims) Subject: yacc grammar available for Modula-3? Does anyone have a yacc grammar for Modula-3? -- David Sims Dept. of Electrical and Computer Engineering david.sims@uc.edu University of Cincinnati (513) 556-2499 Cincinnati OH 45221-0030 RIPEM mail accepted. USA ======================================================================= 35 === Date: Wed, 17 Feb 93 23:02:00 -0800 From: meehan@src.dec.com Subject: Re: yacc grammar available for Modula-3? Does anyone have a yacc grammar for Modula-3? There's one in the pretty-printer sources (Parse.yacc) that come with the distribution. Opening comment from that file: A yacc source file for the Modula-3 pretty-printer. This grammar was constructed from the grammar given in the Modula-3 report; the main problem was to get it right for yacc (an expression can start by a type). Expect 2 shift/reduce conflicts. ======================================================================= 36 === Date: 16 Feb 93 22:48:55 GMT From: werts@aardvark.cecs.csulb.edu (Michael Werts) Subject: Difficulty using Trestle I having problems again. This time I'm trying to compile and run the sample programs in the Trestle distribution. I attempted the following from sun4-m3/trestle/Apps. -------------------------------------------------------- lynx.cecs.csulb.edu# ../../bin/m3make m3makefile all `m3makefile' is up to date. /u1/sun4-m3/bin/m3 -w1 -make -why -g -D../src/xvbt:../src/vbt:../src/split:../src/trestle -commands -o TypeInTest TypeInTest.m3 ../SPARC/libm3ui.a -lm3X11R4 -lX11 inhale ../SPARC/libm3ui.a inhale /u1/sun4-m3/lib/m3/libm3X11R4.a inhale /usr/lib/libX11.a inhale /u1/sun4-m3/lib/m3/libm3.a inhale /usr/lib/libm.a new objects -> linking TypeInTest missing compiled interface "TrestleComm.io" imported by: TypeInTest.m3 missing compiled interface "TypeInVBT.io" imported by: TypeInTest.m3 missing compiled interface "HVSplit.io" imported by: TypeInTest.m3 missing compiled interface "Trestle.io" imported by: TypeInTest.m3 rm .m3imports rm TypeInTest_m.o Fatal Error: incomplete program *** Error code 255 make: Fatal error: Command failed for target `TypeInTest' ------------------------------------------------------------ What is going on here? I think I ran "m3make clean.all" after installing everything. Did I trash some files that I needed? libm3 is still usable. Why would "clean.all" delete files needed to compile Trestle programs, but not delete files needed for programs using libm3? Also, can Trestle programs be invoked from OpenWindows? -- MICHAEL WERTS -- werts@csulb.edu Computer Engineering Computer Science California State University Long Beach ======================================================================= 37 === Date: 13 Feb 93 22:21:59 PST From: offline!marc (Marc Duponcheel) Subject: M3 reference book I am a C++ programmer and I would like to know more about M3. So, is there a de-facto book (maybe from Wirth) ? And are some C++ features present in M3 such as multiple inheritance virtual inheritance virtual methods operator and function overloading templates exceptions Thanks for any reply ... It might be my trigger for M3 -- preferred e-mail address marc@offline.UUCP happy Amiga 4000 user (UUCP node & FIDO point) at HOME happy Sun Sparc user (mdup@cimad) at WORK ========== // =================================================== Thanks to \X/ Amiga for being the best computer ever ... ==================================================================== ======================================================================= 38 === Date: Thu, 18 Feb 93 09:34:30 -0800 From: msm@src.dec.com Subject: Re: M3 reference book The standard reference is Greg Nelson. System Programming in Modula-3. Prentice Hall, May 1991 The language has virtual inheritance and methods (all methods and instance variables are virtual; if you want non-virtuals, you make them module variables or procedures), templates (generics), and exceptions. It does not have multiple inheritance, although you can get that effect by using run-time type fiddling. It doesn't have operator or function overloading; a lot of the demand for function loading goes away because M3 does have default values for parameters, and keyword parameter passing (which can be used in the same call as positional parameters); it also has modules, so that the same procedure name can be used to mean different things when qualified by different module names. There is no support for operator overloading. Bottom line: The advantages for M3 are a cleaner type system, thread support, automatic garbage collection, no need for an ARM to let you know what the designer thought the language was supposed to mean, a rich and standard set of interfaces to build on top of. The disadvantages are no multiple inheritance (which only helps you for classes which noone has further subclassed anyway), no method syntax for non-virtual functions and variables, no operator overloading. Mark ======================================================================= 39 === Date: 17 Feb 93 15:41:15 GMT From: buschman@slsvaat.sel.de (Andreas Buschmann US/ESI R.127 Tel.3841) Subject: Re: yacc grammar available for Modula-3? dsims@don.ece.uc.edu (David Sims) writes: : Does anyone have a yacc grammar for Modula-3? Yup, I have one. but - it is clobbered with calls to actions (I tried to implement an Interpreter for m3) - it is the language as described in Luca Cardelli, James Donahue, Lucille Glassman, Mick Jordan, Bill Kaslow, Greg Nelson. Modula-3 Report (revised). October 1989. it does not include the changes from Greg Nelson. System Programming in Modula-3. Prentice Hall, May 1991 - the grammar works ok with bison, yacc, byacc. It relies on a flex scanner which does more than one symbol lookahead when the keyword PROCEDURE is found, to decide between declarations and expressions. (An other idea would have been to hand information about the current state of the parser back to the scaner.) If you are interested I'll dig it up from its floppy disk. Tschuess Andreas -- #include /|) Andreas Buschmann /-|) SEL Stuttgart US/ESI buschman@us-es.sel.de ======================================================================= 40 === Date: Wed, 17 Feb 1993 21:13:51 GMT From: werts@piggy.cecs.csulb.edu (Michael Werts) Subject: Trestle trouble I just looked in /lib in our Modula-3 directory. There does not appear to be any library for Trestle, i.e. something of the form libm3Trestle.{a|ax}. Could this cause the problem I mentioned in my previous posting ("Difficulty using Trestle")? -- MICHAEL WERTS -- werts@csulb.edu Computer Engineering Computer Science California State University Long Beach ======================================================================= 41 === Date: 17 Feb 93 13:13:46 +1000 From: shtodd@vaxsar.vassar.edu Subject: looking for xview or OLIT libs for m3 Hello, I am tring to locate interface files for the xview and/or OLIT libraries. I am using m3 on a sun running SunOS 4.1.1 and OpenWindows 3. If you can help me, please write to shtodd@vassar.edu. Thank you for your time, Shad Todd ======================================================================= 42 === Date: Fri, 19 Feb 1993 08:20:00 +0000 From: Simon.Johnston@purplet.demon.co.uk (Simon Johnston) Subject: Modula-2 standards document To: klaeren@informatik.uni-tuebingen.de I've just read a posting from you in the comp.lang.modula2 news group saying that the postscript version of the Modula-2 standards doc is 7Mb, is this compressed? If not is it possible to send a compressed version? If not is there an ftp site where I can get it from? Thanks very much. ---------------------------------------------------------------------------- Simon Johnston - ICL Retail Systems - +44 (0)344 476320 3&4 Willoughby Road, Bracknell, Berks, RG12 4TJ, United Kingdom S.K.Johnston.bra0801@oasis.icl.co.uk -or- Simon.Johnston@purplet.demon.co.uk ======================================================================= 43 === Date: 21 Feb 93 20:51:50 GMT From: moss@cs.cmu.edu (Eliot Moss) Subject: Re: What does `TYPE var: (CARDINAL);' mean? If I recall correctly, there are a few (unusual) situations where parentheses are necessary to disambiguate types. Consider the type of a procedure that returns a procedure and might signal an exception. (I don't have my M3 book here, but this should give you the idea): TYPE PPP = PROCEDURE (): PROCEDURE (): INTEGER RAISES {FOO}; This is ambiguous in terms of which procedure gets the RAISES clause. Parentheses can disambiguate as follows: TYPE PP1 = PROCEDURE (): (PROCEDURE (): INTEGER RAISES {FOO}); TYPE PP2 = PROCEDURE (): (PROCEDURE (): INTEGER) RAISES {FOO}; There may be other cases but this is the one that comes to mind. Just as with expressions, parentheses do not change the meaning (of parsed types), but aid the parsing. Hence, they would not appear in abstract syntax. Hence, VAR var: (CARDINAL); means exactly the same thing as VAR var: CARDINAL; Hope this clarifies ..... EM -- J. Eliot B. Moss, Associate Professor Visiting Associate Professor Department of Computer Science School of Computer Science Lederle Graduate Research Center Carnegie Mellon University University of Massachusetts 5000 Forbes Avenue Amherst, MA 01003 Pittsburgh, PA 15213-3891 (413) 545-4206, 545-1249 (fax) (412) 268-6767, 681-5739 (fax) Moss@cs.umass.edu Moss@cs.cmu.edu ======================================================================= 44 === Date: 25 Mar 93 17:53:12 GMT From: moss@cs.cmu.edu (Eliot Moss) Subject: GNU Modula-3 alpha release status We said we'd try to get the initial (alpha) release of GNU Modula-3 out some time this month (March), and we're in the process of figuring out what to release and how to package it up. We expect to have something in roughly two weeks (watch this space for a notice). What would this be? First, it is a compiler for the VAX (only) under Ultrix (only), definitely without threads, and probably still failing a small number of the tests in the SRC test suite (which implies that not all of libm3 is likely to work either). The actual release information will detail more about what's working and what's not at that time. We DO currently pass all the compiler tests that the SRC compiler did when it was first released (i.e., the ones we fail are more obscure things that users uncovered over time). Second, the release itself will be a compressed tar file including sources and executables. The executables will probably work only if you put libraries, etc., in the expected places (otherwise, you'll need to rebuild from sources). The compiler is written in C and should be compiled with a recent version of gcc (so you'll need gcc installed). The system also uses gld (the GNU linker). This release should be most useful to people undertaking ports to other machines and operating systems, since it will give them a head start on understanding the compiler and getting the full system ready. It may be of some use for ordinary programming, but it really depends on whether you tend to use features that tickle the remaining bugs. We are indeed interested in alpha test reports, but only if they tell us something new (i.e., we'll provide a list of known deficiencies). When the release is made, we'll also start email discussions with the various parties who have indicated they might undertake ports, to help sort out who will do what. Regards, and thanks for your continued interest and encouragement -- EM -- J. Eliot B. Moss, Associate Professor Visiting Associate Professor Department of Computer Science School of Computer Science Lederle Graduate Research Center Carnegie Mellon University University of Massachusetts 5000 Forbes Avenue Amherst, MA 01003 Pittsburgh, PA 15213-3891 (413) 545-4206, 545-1249 (fax) (412) 268-6767, 681-5739 (fax) Moss@cs.umass.edu Moss@cs.cmu.edu ======================================================================= 45 === Date: Sun, 21 Feb 1993 19:13:40 GMT From: dmb@srl03.cacs.usl.edu (David M. Brumley) Subject: Re: What does `TYPE var: (CARDINAL);' mean? Argh, argh, argh. I meant, "What does `VAR var: (CARDINAL);' mean?". ======================================================================= 46 === Date: 21 Feb 93 18:14:05 GMT From: dmb@srl03.cacs.usl.edu (David M. Brumley) Subject: What does `TYPE var: (CARDINAL);' mean? Would someone explain the semantics of the type production `Type = "(" Type ")".'? I can't seem to find an example in _SPwM3_ and the compiler source implies that the parens are meaningless. ======================================================================= 47 === Date: Sun, 21 Feb 93 13:28:52 -0800 From: meehan@src.dec.com Subject: Re: What does `TYPE var: (CARDINAL);' mean? Would someone explain the semantics of the type production `Type = "(" Type ")".'? I can't seem to find an example in _SPwM3_ and the compiler source implies that the parens are meaningless. The parentheses are needed to resolve [rare] cases of potential ambiguity. There is an example on the very last line of section 2.2.8, page 20: In a procedure type, RAISES binds to the closest preceding PROCEDURE, That is, the parentheses are required in: TYPE T = PROCEDURE (): (PROCEDURE ()) RAISES {}; Not a stellar example, since "RAISES {}" is redundant. Consider TYPE T = PROCEDURE (): (PROCEDURE ()) RAISES {E}; VAR p: T; "p" is a procedure that can raise exception E. It returns a procedure that raises no exceptions. The only other place I've seen parentheses used for type-declarations is in revelations: INTERFACE Z; TYPE T <: OBJECT slot: INTEGER METHODS p() END; (* ... *) END Z. MODULE Z; REVEAL T = (OBJECT slot: INTEGER METHODS p() END) BRANDED OBJECT OVERRIDES p := P END; (* ... *) BEGIN END Z. The more idiomatic way to do this is to write: TYPE Public = OBJECT slot: INTEGER METHODS p () END; REVEAL T = Public BRANDED OBJECT OVERRIDES p := P END; The "Public" declaration often goes in the interface. ======================================================================= 48 === Date: 22 Feb 93 03:49:51 GMT From: ednstras@kraken.itc.gu.edu.au (Michael Strasser) Subject: Modula-3 for OS/2 It is my understanding that no-one yet has ported the SRC M3 compiler to OS/2. I am an OS/2 user and believe that M3 will suit it admirably, using OS/2's built-in threads. I would like to hear from anyone who is contemplating the port or who may have taken tentative steps towards it (as I have done). I am willing to help but don't have the time to do it all myself. Please E-mail me if you are interested. I have a quite good general knowledge of OS/2 architecture and will happily learn more about it and Modula-3. -- Mike Strasser Internet: M.Strasser@edn.gu.edu.au. Faculty of Education Griffith University Brisbane, Australia ======================================================================= 49 === Date: Mon, 22 Feb 1993 13:46:28 GMT From: gloeckler@fh-ulm.de (Thomas Gloeckler) Subject: Re: Modula-2 standards document In article <115.2B85599D@purplet.demon.co.uk> Simon.Johnston@purplet.demon.co.u k (Simon Johnston) writes: >I've just read a posting from you in the comp.lang.modula2 news group saying >that the postscript version of the Modula-2 standards doc is 7Mb, is this >compressed? If not is it possible to send a compressed version? If not is >there an ftp site where I can get it from? I found it on ftp.mathematik.uni-ulm.de : /pub/soft/modula/standard User anonymous wfr Thomas Gloeckler ======================================================================= 50 === Date: Wed, 24 Feb 1993 17:50:37 GMT From: barton@chopin.eche.ualberta.ca (Bob Barton System Administrator (403)4 92 5160) Subject: RS6000 build problem I have obtained the release 2.11 from gatekeeper.dec.com and started the build. Everything was going fine until I started to do the m3make build_install.all (the libm3 part worked OK) when I got the following message in the tools section. Wed Feb 24 10:29:48 MST 1993 ****************************************** tools zcat tools-2.11.tar.Z | /bin/tar xf - /usr/local/bin/m3make -f m3makefile.tools all install mkdir tools/pp/IBMR2 mkdir tools/coverage/IBMR2 mkdir tools/gnuemacs/IBMR2 mkdir tools/m3bundle/IBMR2 -------------------------------------- tools/pp/IBMR2 /usr/local/bin/m3 -w1 -make -why -g -X1_-I../src_ -o m3pp -F.PGM_SOU RCES -ll new source -> compiling ../src/y.tab.c new source -> compiling ../src/ExceptionArg.i3 new source -> compiling ../src/FBE.i3 new source -> compiling ../src/FBEPostScript.i3 new source -> compiling ../src/FBEWr.i3 new source -> compiling ../src/Parse.i3 new source -> compiling ../src/NewFormatter.i3 new source -> compiling ../src/Main.m3 new source -> compiling ../src/FBEPostScript.m3 "../src/FBEPostScript.m3", line 432: warning: potentially unhandled exception ( ) "../src/FBEPostScript.m3", line 486: warning: potentially unhandled exception ( ) 2 warnings encountered new source -> compiling ../src/FBEWr.m3 new source -> compiling ../src/Parse.m3 new source -> compiling ../src/NewFormatter.m3 new objects -> linking m3pp 0706-317 ERROR: Unresolved or undefined symbols detected: Symbols in error (followed by references) are dumped to the load map. The -bloadmap: option will create a load map. alloca Fatal Error: program "/bin/bsdcc" failed (exit status 16) make: 1254-004 The error code from the last command is -1. Make Quitting. make: 1254-004 The error code from the last command is 2. Make Quitting. make: 1254-004 The error code from the last command is 2. Make Quitting. Any suggestions? Thank you. --,,,, | D | R.L. Barton Department of Chemical Engineering | A | Tel (403) 492-5160 University of Alberta | C | Fax (403) 492-2881 Edmonton, Alberta, Canada T6G 2G6 | S | Internet barton@chopin.eche.ualberta.ca --'''' ======================================================================= 51 === Date: 23 Feb 93 04:50:13 GMT From: friedl@mtndew.Tustin.CA.US (Stephen Friedl) Subject: anybody got Modula-3 for SCO UNIX? Hi folks, A customer of mine is researching languages to use for a *serious* development environment for multiple embedded hardware platforms, and Modula-3 has caught his eye. We thought about using something like C or C++, but these are either just too tough for the person off the street who is likely to be our target developer. After looking at it for a while, I have become quite enamored with this language and am looking forward to working with it. I got the source form the Prime Time Freeware CD and am trying to build a version for SCO UNIX starting from the AIX386 definition, and I am so far having no joy. The SCO C compiler has more bugs than Rush Limbaugh has opinions, and the debugger itself dumps core with regularity. I don't have a working GNU C compiler for this platform (having troubles with the header files), so at this point I am really stuck. I am confident that with time I could figure it out, but I am reluctant to rack up lots of hours on my customer's nickel. I would love to hear from those hardy souls who have gone down this road, and am also interested in finding wizards-for-hire that know the internals well (particularly the code generator). Thanks much, Stephen P.S. - I have just requested this group from uunet's postmaster, but it might take a day or so for this to take effect: email replies preferred. -- Stephen J Friedl | Software Consultant | Tustin, CA | +1 714 544-6561 3b2-kind-of-guy | I speak for me ONLY | KA8CMY | uunet!mtndew!friedl Attorneys are paranoid because they assume everybody else is dishonest too ======================================================================= 52 === Date: 25 Feb 93 04:41:16 GMT From: moss@cs.cmu.edu (Eliot Moss) Subject: Re: Recursive data structures using generics? This seems to me like a pretty screwy way to do things: INTERFACE Node; IMPORT NodeStack; TYPE T = OBJECT id: TEXT; stack: NodeStack.T; END; You did not say, but I gather Stack(Foo).T is defined as some kind OBJECT type with a T in it, so I suppose you get (if you macro expand by hand) a well defined recursive Modula-3 type. I think the reason I feel this is screwy is because it is defining a very simple kind of recursive type across multiple modules. I would expect the recursive aspect to be defined more locally, especially with stacks, since the physical linking of the sturctures is inherent to the ADT Stack and should not be exposed. (I know, you'll pull a StackRep interface out of the hat next!) One reason to disallow circular interface dependencies is that in their presence there is no well-defined order for compiling the interfaces, and interfaces and modules are designed to be separately compiled. When things are that intertwined, they should be in a single interface, so the compiler has allt he necessary knowledge in one place. So, in a nutshell, the answer to your question "why?" is "because of separate compilation". Hope this helps. What would have made more sense to me would be a generic interface along these lines (pardon syntax goofs, please): INTERFACE Stack(Element); TYPE T = OBJECT item: Element.T; next: T; END; END. Regards -- Eliot -- J. Eliot B. Moss, Associate Professor Visiting Associate Professor Department of Computer Science School of Computer Science Lederle Graduate Research Center Carnegie Mellon University University of Massachusetts 5000 Forbes Avenue Amherst, MA 01003 Pittsburgh, PA 15213-3891 (413) 545-4206, 545-1249 (fax) (412) 268-6767, 681-5739 (fax) Moss@cs.umass.edu Moss@cs.cmu.edu ======================================================================= 53 === Date: 24 Feb 93 20:02:44 GMT From: rhoover@watson.ibm.com (Roger Hoover) Subject: Re: RS6000 build problem In article <1993Feb24.175037.15399@kakwa.ucs.ualberta.ca>, barton@chopin.eche.u alberta.ca (Bob Barton System Administrator (403)492 5160) writes: |> I have obtained the release 2.11 from gatekeeper.dec.com and started the bui ld. |> Everything was going fine until I started to do the m3make build_install.all |> (the libm3 part worked OK) when I got the following message in the tools |> section. ..... |> new source -> compiling ../src/NewFormatter.m3 |> new objects -> linking m3pp |> 0706-317 ERROR: Unresolved or undefined symbols detected: |> Symbols in error (followed by references) are |> dumped to the load map. |> The -bloadmap: option will create a load map. |> alloca |> .... |> Any suggestions? Thank you. Unfortunately the tools m3makefile is a mess. It looks like an attempt was made to encorporate calls to lex and yacc in the makefile, but it was abandoned. As a result, the makefile tries to make the y.tab.c and lex.yy.c files in tools/pp/src, but these were generated for the wrong system. I posted the following last fall (along with similar fixes for the gnuemacs tool), but they never made it into the release: ---------------------------------------------------------------------- Return-Path: root Received: from localhost by trek.watson.ibm.com (AIX 3.2/UCB 5.64/920123) id AA26748; Fri, 13 Nov 1992 08:44:50 -0500 Message-Id: <9211131344.AA26748@trek.watson.ibm.com> To: m3@src.dec.com, muller@src.dec.com Cc: rhoover X-External-Networks: yes Subject: gnuemacs fixes for IBMR2 Date: Fri, 13 Nov 92 08:44:49 EST From: Roger Hoover To compile gnuemacs (from the tools package), you must change hash.h as follows and re lex and yacc parse.lex and parse.yacc respectively. diff -c 2.08/gnuemacs/src/hash.h gnuemacs/src/hash.h *** 2.08/gnuemacs/src/hash.h Tue Mar 24 16:06:27 1992 --- gnuemacs/src/hash.h Fri Nov 13 08:34:10 1992 *************** *** 175,180 **** --- 175,183 ---- return(NULL); } + #ifdef _IBMR2 + extern void exit(); + #endif void install(where) PTRKEYWORDENTRY where; ======================================================================= 54 === Date: Wed, 24 Feb 1993 23:48:31 GMT From: rhoover@watson.ibm.com (Roger Hoover) Subject: Recursive data structures using generics? I'd like to use generics in a recursive data structure. For example, consider an object type that uses the Stack generic in SPwM3: :::::::::::::: Node.i3 :::::::::::::: INTERFACE Node; IMPORT NodeStack; TYPE T = OBJECT id: TEXT; stack: NodeStack.T; END; Now, NodeStack is a stack of Node.T. Thus, we have: :::::::::::::: NodeStack.i3 :::::::::::::: INTERFACE NodeStack = Stack(Node) END NodeStack. Unfortunately this gives: "./Node.i3", line 3: circular imports (NodeStack -> Node -> NodeStack) Questions: 1) Is there a way to write this data structure using the stack generic? 2) Why are circular interface imports not allowed? roger rhoover@watson.ibm.com ======================================================================= 55 === Date: 26 Feb 93 23:25:20 GMT From: najork@cs.uiuc.edu (Marc Najork) Subject: Re: Recursive data structures using generics? Well, here is one way to handle the problem Roger described. It's not pretty, but it works ... And I agree, it would be nice to allow for cyclic imports in interfaces, and then just compile all the interfaces in a strongly connected component at once. Certainly feasible, but would probably require quite some reworking of the compiler. And of course we would have to change the language definition ... (see SPwM3 p. 43) -- Marc Najork :::::::::::::: NodeStack.i3 :::::::::::::: INTERFACE NodeStack = Stack(Node) END NodeStack. :::::::::::::: Node.i3 :::::::::::::: INTERFACE Node; TYPE T <: ROOT; :::::::::::::: PrivateNode.i3 :::::::::::::: INTERFACE PrivateNode; IMPORT NodeStack; FROM Node IMPORT T; REVEAL T <: Private; TYPE Private = OBJECT id: TEXT; stack: NodeStack.T; END; :::::::::::::: Node.m3: :::::::::::::: MODULE Node EXPORTS Node, PrivateNode; REVEAL T = Private BRANDED OBJECT END; .... ======================================================================= 56 === Date: 26 Feb 93 13:52:15 GMT From: moss@cs.cmu.edu (Eliot Moss) Subject: Re: Recursive data structures using generics? Ok, now I understand the programming problem that gave rise to the situation that the compiler complained about (which induced you to complain about the compiler :-). To recap, you wanted to implement a graph with a representation of each Node consisting of some other data plus a Stack of the edges, i.e., a Stack of references to Nodes. One could readily define such a recursive type in a single interface or module. However, in this case, Stack was already available as a separate generic interface. You tried to instantiate it, producing Stack(Node) (being free with notation), but this failed because the instantiated Stack interface depends on the Node interface and vice versa, giving rise to a cycle of interface dependencies, which is illegal. Thus, reuse is compromised. There may be some tricky way out of this, but I can't think of it in 30 seconds :-). It does sound like a kind of language bug/deficiency, and upon reflection I agree that cyclic interface dependencies don't impress me as being a fundamental problem. As you pointed out, the compiler can read in all the interfaces and resolve the definitions in any compilation involved, and there must already be logic to prevent reading interfaces in more than once during a compilation. Perhaps the SRC folks could comment further on this one? If it is crucial you get your program up and running, you could instantiate Stack on REFANY or OBJECT and use NARROW to extract the Node objects -- not great, but perhaps workable. -- J. Eliot B. Moss, Associate Professor Visiting Associate Professor Department of Computer Science School of Computer Science Lederle Graduate Research Center Carnegie Mellon University University of Massachusetts 5000 Forbes Avenue Amherst, MA 01003 Pittsburgh, PA 15213-3891 (413) 545-4206, 545-1249 (fax) (412) 268-6767, 681-5739 (fax) Moss@cs.umass.edu Moss@cs.cmu.edu ======================================================================= 57 === Date: Thu, 25 Feb 1993 15:43:32 GMT From: rhoover@watson.ibm.com (Roger Hoover) Subject: Re: Recursive data structures using generics? In article , moss@cs.cmu.edu (Eliot Moss) writes: |> This seems to me like a pretty screwy way to do things: |> |> INTERFACE Node; |> IMPORT NodeStack; |> TYPE |> T = OBJECT |> id: TEXT; |> stack: NodeStack.T; |> END; |> |> You did not say, but I gather Stack(Foo).T is defined as some kind OBJECT ty pe |> with a T in it, so I suppose you get (if you macro expand by hand) a well |> defined recursive Modula-3 type. |> |> I think the reason I feel this is screwy is because it is defining a very |> simple kind of recursive type across multiple modules. I would expect the |> recursive aspect to be defined more locally, especially with stacks, since t he |> physical linking of the sturctures is inherent to the ADT Stack and should n ot |> be exposed. (I know, you'll pull a StackRep interface out of the hat next!) |> As I said in the original post, the stack is that in SPwM3 (Page 46). I do not think that I'm doing something screwy---I just want to build a graph whose edgelists are kept in a stack. Why should I have to write my own stack implementation when I have Greg Nelson's? All implementation details of the stack are hidden. I know it must be a valid recursive type, because Node.T is an object type. The 'screwy' part of this is that generics must be in seperate modules. Thus, to use one in a recursive type, I am forced to define the type across multiple modules. |> One reason to disallow circular interface dependencies is that in their |> presence there is no well-defined order for compiling the interfaces, and |> interfaces and modules are designed to be separately compiled. When things a re |> that intertwined, they should be in a single interface, so the compiler has |> allt he necessary knowledge in one place. So, in a nutshell, the answer to |> your question "why?" is "because of separate compilation". I don't buy this. The SRC compiler reads all of the imported interfaces when I compile an interface (otherwise, it couldn't give me the circularity error). I see no reason why it can't read all imported interfaces and resolve the type declarations. |> Hope this helps. What would have made more sense to me would be a generic |> interface along these lines (pardon syntax goofs, please): |> |> INTERFACE Stack(Element); |> TYPE T = OBJECT |> item: Element.T; |> next: T; |> END; |> END. I don't understand. How does this give me a graph of nodes with a stack of edges? roger rhoover@watson.ibm.com