======================================================================= 1 === Date: Fri, 1 May 1992 12:44:07 GMT From: laverman@cs.rug.nl (Bert Laverman) Subject: Re: A proposal for a new construction It is interesting to see that different projects to enhance/change Pascal and Modula go in the same direction. The orthogonalization of the type system, especially in connection with function result values seems a generally accepted `way to go', though WIrth himself still refuses structured values as function result. (ref Oberon) The strings also keep popping up. C seems the only language that managed to get a generally `accepted' method of handling them without introducing a new type, thanks to it's way of dealing with pointers and arrays. Variant records however have disappeared both in Oberon and Modula-3, since they have been replaced by Objects. The Modula-2000 UNION seems to do away with the major drawback of variant records (that you can assign to a field of one variant, and next treat the same record as if it were another variant altogether) The example seems to indicate that UNIONs are like pointers-to- records, just as M3 Objects. If we next see the different members of the union as different children of the same base Object type, then the VARIANT statement looks remarkably like TYPECASE in M3. Concluding, I think that all options offered by UNIONs are already available in Modula-3... Greetings, Bert -- #include Bert Laverman, Dept. of Computing Science, Groningen University Friendly mail to: laverman@cs.rug.nl The rest to: /dev/null ======================================================================= 2 === Date: Fri, 1 May 92 13:56:59 PDT From: muller@src.dec.com (Eric Muller) Subject: archive of comp.lang.modula3 for April 92 available on gatekeeper The articles posted to comp.lang.modula3 in April 92 are available on gatekeeper.dec.com, in pub/DEC/Modula-3/comp.lang.modula3/92-04.Z. Articles posted the previous months are available in similarly named files in the same directory. -- Eric. ======================================================================= 3 === Date: 1 May 92 21:28:26 GMT From: n8243274@henson.cc.wwu.edu (steven l. odegard) Subject: How to contain extensions to the language, with examples I suppose it is human nature to want to do a small "improvement" when laboring to consider a given design. I propose the following means for permitting the implementation of such "improvements" without sacrificing portability, and illustrate such with a minor "improvement" of my own. To use any "improvement" the designer of the implementation may want to provide, include them within an _extension_ bracket. An _extension_ syntactically functions like a pragma, and is contained within the brackets [* and *]. Unlike a pragma, however, the implementation is not permitted to ignore an extension. They are intended to mark the use of extended features the designer of the implementation may desire to provide. The implementation will also be required to implement the means for converting a program text with its implemented extensions into a functionally equivalent program text without those extensions. To illustrate this, I frequently find the need to declare a REF variable and also initialize its referent. It would be convenient for me to do this while initializing the REF variable. The proposal is as follows: Immediately following an assignment statement or initializer for a variable in a declaration, any number of extensions with the keyword .- REFERENT -. may be appended, of the form: [* REFERENT : type := expression *] it declares the referent of the variable being initialized or of the designator of the assignemt statement, exactly as for a variable initialization. For example, consider: VAR r : REFANY := NEW( REF INTEGER ) [* REFERENT : INTEGER := 123 *] ; declares and initializes r to be a REF INTEGER. Moreover, r^ is initialized as an integer so that .- r^ = 123 -.. This is equivalent to the following: VAR r : REFANY := NEW( REF INTEGER ) ; ... BEGIN NARROW( r, REF INTEGER )^ := 123 ; Another example follows: VAR k := NEW( REF REF INTEGER ) [* REFERENT := NEW( REF INTEGER ) *] [* REFERENT := 123 *] ; This is equivalent to: VAR k := NEW( REF REF INTEGER ) ; ... BEGIN k^ := NEW( REF INTEGER ) ; k^^ := 123 ; Consider: BEGIN r := NEW( REF INTEGER ) [* REFERENT : INTEGER := r^ *] ; This employies a different referent to contain the same value. It is equivalent to: BEGIN VAR r_temp : INTEGER := NARROW( r, REF INTEGER )^ ; BEGIN r := NEW( REF INTEGER ) ; NARROW( r, REF INTEGER )^ := r_temp END ; The effect is that any change in r^ now cannot possibly effect the change of any other value. Finally, a new reference value is declared to point to itself: VAR circular : REFANY := NEW( REF REFANY ) [* REFERENT : REFANY := circular *] ; This is functionally equivalent to VAR circular : REFANY := NEW( REF REFANY ) ; ... BEGIN NARROW( circular, REF REFANY )^ := circular ; ----- Throughout the months, there has been discussion on permitting the expression operators to function also for complex-valued expressions, matrix-valued expressions, and so on. One possibility is to design a system for declaring procedures functioning to define the operators for a group, lattice or boolean algebra. A keyword in an extension bracket, say: [* OVERLOAD INFIX Matrix + * *] A1 + A2 * A3 will indicate that the expression above is really a call of function-procedures defined within the module Matrix. The module in which this expression appears may indicate the employment of this extension within itself in this manner: IMPORT [* OVERLOAD INFIX + * / *] Matrix ; This states that Matrix will be used overloaded into infix operators of marked expressions in this module. The Matrix interface itself may appear: [* LOADOVER INFIX + * / *] INTERFACE Matrix ; ... [* LOADOVER INFIX * *] PROCEDURE Mul( A, B : Matrix ) : Matrix RAISES { Undefined } ; Declaring that this procedure is available to be overloaded into "*" as in the original expression above. The implementation must provide for a provision to replace all such expressions with their expanded forms, for portability. The output of such a required conversion of the expression above could appear: (* OVERLOAD INFIX Matrix + * *) Matrix.Add( A1, Matrix.Mul( A2, A3 )) ; which is generated so that all of the rules for expression precidence are satisfied. (I definitely prefer this to the lexical nightmare in Ada.) ----- I now challenge anyone who wants a pet extension to the language to implement the conversion from the extended language into the unextended language. For operator overloading, this will require an extensive peering into the languages type sytem; for the referent declaration, less peering will be required. I further contend that features of the language that prove to be unusable be moved into extension brackets as a precursor to their elimination. I propose that IMPORT Stdio ; FROM Stdio IMPORT stdin, stdout ; be changed to IMPORT Stdio [* UNQUALIFYING stdin, stdout *] ; --S. Lee ODEGARD 13722 Aurora Ave N Seattle, WA 98133-6913 USA -- --S. Lee ODEGARD 13722 Aurora Ave N Seattle, WA 98133-6913 USA ======================================================================= 4 === Date: Fri, 1 May 92 18:29:48 -0400 From: Norman Ramsey Subject: initialization order bugs The new compiler initializes modules in a different order than the old, and I have a bug in my program that results in modules not always being initialized in the right order. Does anyone have experience in tracking these down, or advice about how to fix them? Any ideas about how to write a tool that computes the ``depends on'' relation described in the language reference manual? Norman Ramsey ======================================================================= 5 === Date: Fri, 01 May 92 15:40:29 -0700 From: Subject: Re: initialization order bugs The only trick I use is to add the "-keep" flag when I link. Near the end of the resulting _m3main.c file, the modules and interfaces are listed in the order that they will be called. - Bill ======================================================================= 6 === Date: Fri, 1 May 92 16:06:14 PDT From: mjordan@src.dec.com (Mick Jordan) Subject: Re: initialization order bugs In article <9205012229.AA09053@cs.Princeton.EDU>, Norman Ramsey writes: > The new compiler initializes modules in a different order than the old, > and I have a bug in my program that results in modules not always being > initialized in the right order. Does anyone have experience in tracking > these down, or advice about how to fix them? Any ideas about how to > write a tool that computes the ``depends on'' relation described in the > language reference manual? > You can use the "m3check" tool in the AST toolkit to show the "depends-on_relat ion, provided that you compile all your implementation modules. Generally you can av oid compiling the implementations of the runtime, since it is highly unlikely that they participate in a cycle. If your source is not all in the current directory then you need to provide m3check with a search path containing your library directories. Then do: % m3check -cid -D dir1 dir2 ... m3check> Scan m3check> PreLink m3check> ShowDependsOn module This will list the "depends-on" relation for "module". The "-cid" option instru cts m3check to compile all the sources in all the directories "dir1 dir2 ...", rath er than just the current directory. Note that, unless you include the runtime sou rces you will get lots of messages about unimplemented procedures and unrevealed opaque types. There is another option to the pre-linker (which must be set on the m3check command line, "-md"), that will warn you of mutual depedendencies between modules. Unfortunately, you will find that almost all modules are mutually dependent, because of cross-imported types. What you really need to know is what modules actually "call" other modules in their initialisation code. If the linker knows the (transitively closed) set of called modules, then it can either work out a safe order to call the init bodies in, or report an error. So to fix things, look for modules with calls in the init code, then replace some of these with explicit initialisation procedures to break the cycles. Mick Jordan ======================================================================= 7 === Date: 3 May 92 14:55:19 GMT From: sakkinen@jyu.fi (Markku Sakkinen) Subject: Re: A proposal for a new construction In article <1992May1.124407.11596@cs.rug.nl> laverman@cs.rug.nl (Bert Laverman) writes: > ... > The strings also keep popping up. C seems the only language that >managed to get a generally `accepted' method of handling them without >introducing a new type, thanks to it's way of dealing with pointers >and arrays. > ... Old Fortrans (before Fortran 77, that is) also handled strings without having a specific type for them, and in a way which was even a bit worse that C's. All current programming languages that come to my mind handle strings in a more orderly fashion than C -- well, standard Pascal is too constrained to be convenient. ---------------------------------------------------------------------- Fight against terrorism: destroy the army HQ in Belgrade! Markku Sakkinen (sakkinen@jytko.jyu.fi) SAKKINEN@FINJYU.bitnet (alternative network address) Department of Computer Science and Information Systems University of Jyvaskyla (a's with umlauts) PL 35 SF-40351 Jyvaskyla (umlauts again) Finland ---------------------------------------------------------------------- ======================================================================= 8 === Date: Mon, 4 May 1992 12:41:04 GMT From: wyant@centerline.com (Geoff Wyant) Subject: Re: How to contain extensions to the language I suggest that anyone wanting to add a new feature be required to name an existing one that should be removed ;-). I'm only half facetious here. The biggest problem in language design is knowing when to stop. If something can be expressed in terms of existing language features and doesn't add substantial expressive power, then it probably shouldn't even be suggested. just my $.02 worth. --- Geoff Wyant wyant@centerline.com Centerline Software, Inc. (Formerly Saber Software, Inc) 10 Fawcett Street Cambridge, Ma. 01238 ======================================================================= 9 === Date: 4 May 92 15:23:54 GMT From: nr@hart (Norman Ramsey) Subject: Re: initialization order bugs I have written a small Icon program that reads the SRC compilers .ix and .mx files in order to compute the dependence graph of a Modula-3 program (as described by the ``depends on'' and ``uses'' relations in the language definition, p47 of Greg's book). To help swat initialization bugs, the program then computes the strongly connected components of the graph. There is an option to print out the components as a graph, suitably for drawing with the dag tool from Bell Labs. There is also an option to print the names of the modules in each component; these are precisely the sets of ``mutually dependent modules'' that Mick Jordan refers to in his message. With this information, there are two ways of trying to fix initialization bugs. One can restructure the program, trying to break cycles in the graph, or one can prowl the source code of the modules, trying to find where explicit initialization should be inserted. Icon is available from the University of Arizona; I don't know the details. Norman Ramsey # To unbundle, "sed '1,/^# To unbundle/d' < thisfile | sh" # To unbundle, make sure both lines appear in the file # Mon May 4 11:13:51 EDT 1992 echo m3depend.icn 1>&2 sed 's/^-//' >'m3depend.icn' <<'End of m3depend.icn' -# -# m3depend -- operations on Modula-3 dependence graph -# -# -# -# m3depend reads Modula-3 dependence information from .ix and .mx files. -# It will then print out a version of the graph usable by dag(1), for -# visualization, or it can print out strongly connected components, for -# killing initiailization bugs -# -# usage: m3depend [options] [*.ix] [*.mx] -# -# options: -# -graph produce dag(1) description of dependence graph -# -scc dag(1) description of strongly connnected components -# -above n print only strongly connected components with -# more than n nodes (default 1) -# -modules print modules in strongly connected components -# -ledger tell dag(1) to use 11x17 paper -# -# default is -graph - -record edge(head, tail, items) # an edge in the graph - -global nodes, edges # set of nodes, edges -global succ, pred # table of successors and predecessors - -global gstart # starts a dag graph (determines paper size) -global minsccsize # print strongly connected components above thi s size - -global showscc # procedure used to show a strongly connected c omponent - -procedure main(args) - succ := table(set()) - pred := table(set()) - nodes := set() - edges := set() - showscc := sccdag - graph := &null - scc := &null - gstart := ".GS 8.5 11" - minsccsize := 1 - while args[1][1:2] == "-" do - case a := pop(args) of { - "-scc" : scc := 1 - "-graph" : graph := 1 - "-ledger" : { gstart := ".GS 16 10" - write("%! PostScript") - write("/setpapertraybyname {") - write(" { /trayname exch def statusdict trayname known {") - write(" statusdict trayname get exec } if} stopped") - write(" { handleerror } if}bind def") - write("/ledgertray setpapertraybyname") - } - "-above" : { minsccsize := 1 <= integer(pop(args)) ; scc := 1 } - "-modules" : { showscc := sccmodules ; scc := 1 } - default : write(&errout, "Unrecognized argument: ", a) - } - if /graph & /scc then graph := 1 - if *args ~= 0 then every parse(open(!args)) else parse(&input) - if \graph then { - write(gstart) - every edge := !edges do - write(edge[1], " ", edge[2], " " || \edge[3] | "", ";") - write(".GE") - } - if \scc then - every dfsnodes(nodes, succ, sccvisit) -end - - -# addedge - add to adjacency set table, creating new set if none present - -procedure addedge(table, e1, e2) # ensures defaults work right - if not member(table, e1) then table[e1] := set() - return insert(table[e1], e2) -end - - -# dfsnodes - generate results of visit in dfs order - -procedure dfsnodes(nodes, succ, visit) - /visit := dfsvisit - marked := table() - numbers := create seq() - every node := !nodes do - if not member(marked, node) then - suspend visit(node, succ, marked, numbers) -end - - -# dfsvisit - perform depth-first numbering of nodes - -procedure dfsvisit(node, succ, marked, numbers) # node not in marked - /numbers := create seq() - marked[node] := @numbers - suspend(node) -end - - -# ismodule - produce node name iff module name - -procedure ismodule(node) - if node[-3:0] == ".m3" then return node else fail -end - - -# parse - read edges from file and put in globals - -procedure parse(input) # read edges and stuff in globals - every e := readedge(input) do { - insert(edges, e) - insert(nodes, e[1]) - insert(nodes, e[2]) - addedge(succ,e[1],e[2]) - addedge(pred,e[2],e[1]) - } -end - - -# readedge - generate all edges from a SRC M3 *.?x file - -procedure readedge(input) # generate all edges from a modula-3 *.?x file - printing := &null - while line := read(input) do line ? - if ="M3 v2.1" then printing := 1 - else if ="/*" then printing := &null - else if \printing then { - tag := tab(any('IM')) & thisfile := tab(0) || "." || map(tag) || "3" - if ="A" & tag == "M" then - suspend edge(tab(0) || ".i3", thisfile, "dashed") - else if ="B" then suspend edge(thisfile, tab(0) || ".i3") - } - close(input) -end - - -# sccdag - show a strongly-connected component in dag(1) format - -procedure sccdag(nodes) - if *nodes > minsccsize then { - write(gstart) - every write("draw ", ismodule(!nodes), " as Box;") - every head := !nodes do - every tail := !succ[head] & member(nodes, tail) do - write(head, " ", tail, if ismodule(tail) then " dashed;" else ";") - write(".GE") - } -end - - -# sccmodules - print modules of scc - -procedure sccmodules(nodes) - if *nodes > minsccsize then { - write("% Strongly connected:") - every write("% ", ismodule(!nodes)) - write() - } -end - - -# sccvisit - visit procedure to compute strongly connected components - -procedure sccvisit(node, succ, marked, numbers, stack) # node not in marked - /stack := [] - min := marked[node] := @numbers - push(stack, node) - every n := !succ[node] do - min >:= (\marked[n] | sccvisit(n, succ, marked, numbers, stack)) \ 1 - if min = marked[node] then { - result := set() - while (n := pop(stack)) ~== node do { - insert(result, n) ; marked[n] := *nodes + 1 - } - insert(result, n) ; marked[n] := *nodes + 1 - showscc(result) - } - return min -end End of m3depend.icn ======================================================================= 10 === Date: Mon, 4 May 1992 15:37:15 GMT From: mday@jukebox.lcs.mit.edu (Mark Day) Subject: Re: >>A proposal for a new construction > ljp@sm.luth.se (Johan Persson) writes: As a lot of you has pointed out, one can make a similiar construct as the one I suggested with OBJECT's and TYPECASE. But I think one has missed my point then. What I tried to say was that I don't think it's particular naturally the way you do it in M3 today. As Eliot Moss has pointed out, CLU is a language that already has the features you propose, in the form of oneofs, variants, and the tagcase statement. It's very hard to express M3-like inheritance in CLU, whereas it's merely "unnatural" to express variant objects in M3. The designers of M3 were constrained by their "complexity budget." If they had to choose between object inheritance and variants, I think they made the right decision by going with inheritance. --Mark Day mday@lcs.mit.edu ======================================================================= 11 === Date: 4 May 92 16:12:06 GMT From: lins@Apple.COM (Chuck Lins ) Subject: Why no structured function results in Oberon [Was: Proposal for a new construction] In article <1992May1.124407.11596@cs.rug.nl> laverman@cs.rug.nl (Bert Laverman) writes: > >It is interesting to see that different projects to enhance/change >Pascal and Modula go in the same direction. The orthogonalization >of the type system, especially in connection with function result >values seems a generally accepted `way to go', though WIrth himself >still refuses structured values as function result. (ref Oberon) The reason Wirth did not include them in Oberon is that a special construct is not necessary. The programmer merely declares an additional type, that is a pointer to the structured type. Then you return a variable of the pointer type. It is trivial for the programmer to do this, and thus comes at essentially zero cost (on both the programmer's and compiler-writer's part). Wirth's belief is that if you complain about efficiency of allocating a structure on the heap, your allocator is broken. -- Chuck Lins, Apple Computer, Inc. Oberon-2 Paladin lins@apple.com Searching... Searching... Searching for Solevig Dommartin ======================================================================= 12 === Date: 4 May 92 16:14:53 GMT From: lins@Apple.COM (Chuck Lins ) Subject: Re: How to contain extensions to the language In article <1992May4.124104.20875@centerline.com> wyant@riposte.com writes: >I suggest that anyone wanting to add a new feature be required >to name an existing one that should be removed ;-). I'm only >half facetious here. The biggest problem in language design is >knowing when to stop. If something can be expressed in terms of >existing language features and doesn't add substantial expressive >power, then it probably shouldn't even be suggested. Gee, sounds like Geoff would like Oberon :-) Look at what C++ has turned into just because the language designer did not how to say no. -- Chuck Lins, Apple Computer, Inc. Oberon-2 Paladin lins@apple.com Searching... Searching... Searching for Solevig Dommartin ======================================================================= 13 === Date: 5 May 92 06:24:43 GMT From: eckam@cs.utexas.edu (Daniel James Eckam) Subject: objects Yes, it is I again, STUDENT PROGRAMMER, with another question that will most likely be obvious to the expert readership at large. But I noticed that my last article (on stdout) prompted a fair bit of debate, so perhaps students like me have a valuable role in pointing out confusing aspects of the language. For instance, it's very confusing to me that this program produces a "Segmentation violation - possible attempt to dereference NIL". Could someone help clarify what's going on? [This is on a Sun4 with M3 version 2.04.] Dan Eckam ------------------------------------------------------------------- MODULE Test EXPORTS Main; TYPE FW_Monitor = OBJECT value: INTEGER:= 0; METHODS update(toAdd: INTEGER):= Update; END; VAR M: FW_Monitor; PROCEDURE Update(self: FW_Monitor; toAdd: INTEGER) = BEGIN INC(self.value, toAdd); END Update; BEGIN M.update(0); END Test. ======================================================================= 14 === Date: Tue, 05 May 92 00:52:44 -0700 From: Subject: Re: objects .. this program produces a "Segmentation violation - possible attempt to dereference NIL". Could someone help clarify what's going on? TYPE FW_Monitor = OBJECT ... VAR M: FW_Monitor; ... BEGIN M.update(0); END Test. You have declared that M is a variable of type FW_Monitor, but you haven't assigned it a value, so M is an arbitrary value of type FW_Monitor. (See SPwM3, section 2.4.3). In practice, the usual "arbitrary value" for REFs is NIL, so you got the segmentation violation when you tried to access the "update" method of NIL. The fix is simple: VAR M := NEW (FW_Monitor); ======================================================================= 15 === Date: 5 May 92 10:24:15 GMT From: laverman@cs.rug.nl (Bert Laverman) Subject: Re: >>A proposal for a new construction > I belive the code would be simplified if one were allowed to write > TYPECASE e OF > Const(c) : ... > | Var(v) : ... > | Opexp(op,l,r) : ... > END Apart from the last one, something like this _IS_ allowed. You can give an identifier just like you do here with 'Const(c)', and then c will be bound to NARROW(e, Const) in the statements of that case. > But what is more seriously is that you will not get a static error > (or atleast a warning) if you forget to handle one typecase. This kind > of warning could be extremly usefull in my opinion. In Modula-3 this is a checked runtime error, not a compile-time error, since you simply can't know beforehand what extensions of your basic type have been made. Greetings, Bert -- #include Bert Laverman, Dept. of Computing Science, Groningen University Friendly mail to: laverman@cs.rug.nl The rest to: /dev/null ======================================================================= 16 === Date: 5 May 92 14:49:29 GMT From: moss@cs.umass.edu (Eliot Moss) Subject: Re: Why no structured function results in Oberon [Was: Proposal for a new construction] People aren't usualy so concerned with the cost of allocating the structure on the heap as with the cost of getting the storage back ... :-) Seriously, I am minded mostly to agree, but I also don't see why a language should force a load on the storage subsystem unnecessarily, and it is simple enough for the caller to allocate space for a return value, etc. Wirth seems to have this point of view that every argument and result should be sized to fit in a register, and I just don't understand this view .... -- J. Eliot B. Moss, Assistant Professor Department of Computer Science Lederle Graduate Research Center University of Massachusetts Amherst, MA 01003 (413) 545-4206, 545-1249 (fax); Moss@cs.umass.edu ======================================================================= 17 === Date: 5 May 1992 12:50:48 -0500 From: eckam@cs.utexas.edu (Daniel James Eckam) Subject: Thread.Wait thanks to all who sent email about my objects problem. Boy, that one was a stupid question. OK, now I'm wondering about a threads problem. I've got a program in which I need to repeatedly operate on several partitions of an array in parallel, and I want to synchronize it so that each thread completes a cycle of operations before going on to the next cycle. So in the apply procedure of the thread, it seems the logical thing to do is to wait on a condition variable from the thread manager, then signal another condition variable at the end of the cycle. The thread manager broadcasts to the first condition variable at the beginning of each cycle, and waits once for each thread on the second condition variable at the end of each cycle. 1) does Thread.Signal unblock threads which have not yet blocked? That is, if a signal occurs before a wait, will the wait cause a block? And when does Thread.Signal unblock more than one thread? The documentation I've read is not very clear about this. 2) Why does Thread.Wait require a MUTEX as an argument? This seems rather burdensome for my application, since the threads don't lock their partitions. (I suppose I could have the object procedure wait for the condition, since the object procedures lock the object, but that seems too asymmetric.) Is there a better solution than using condition variables for this? Perhaps a MUTEX counter for the end-of-cycle condition variable would be better? Dan Eckam ======================================================================= 18 === Date: Wed, 6 May 1992 12:27:29 GMT From: piet@cs.ruu.nl (Piet van Oostrum) Subject: Re: Why no structured function results in Oberon [Was: Proposal for a new construction] >>>>> lins@Apple.COM (Chuck Lins ) (CL) writes: CL> The reason Wirth did not include them in Oberon is that a special construct CL> is not necessary. The programmer merely declares an additional type, that i s CL> a pointer to the structured type. Then you return a variable of the pointer CL> type. It is trivial for the programmer to do this, and thus comes at CL> essentially zero cost (on both the programmer's and compiler-writer's part) . It may be relatively [my insertion] trivial, but I think it is still unnatural. It clutters the program with NEWs, extra assignment statements and dereferences. Besides that there is no reason to for this restriction. And it is yet another exception to be remembered. It also means that you cannot write generic functions that work both for simple types and structured types (e.g. a sorting routine). I think I find this the most compelling reason to despise this kind of rule. CL> Wirth's belief is that if you complain about efficiency of allocating a CL> structure on the heap, your allocator is broken. My belief is that if Wirth complains about the difficulty of compiling functions with structure results, his compiler implementation is broken. -- Piet* van Oostrum, Dept of Computer Science, Utrecht University, Padualaan 14, P.O. Box 80.089, 3508 TB Utrecht, The Netherlands. Telephone: +31 30 531806 Uucp: uunet!mcsun!ruuinf!piet Telefax: +31 30 513791 Internet: piet@cs.ruu.nl (*`Pete') ======================================================================= 19 === Date: Wed, 6 May 1992 09:16:30 PDT From: Pavel Curtis Subject: Re: Thread.Wait I would solve your thread synchronization problem by maintaining a MUTEX-protected counter which is initialized to zero. Each of the worker threads begins each cycle by locking the MUTEX, bumping the counter, and testing whether or not the new counter value is equal to the number of workers (apparently a constant in your implementation). If the counter is not yet up to the number of workers (i.e., not every thread has `checked in' yet), then the thread waits on a condition variable (call it `cycleStarted'). If the counter *is* up to the number of workers, then Broadcast cycleStarted to wake everyone up and leave the monitor. Now all of the threads are running in this cycle. When each thread finishes their piece of the work, they again grab the MUTEX and now decrement the counter. If it's not yet zero, then they wait on another condition variable, say `cycleEnded'. If it *is* zero, then all of the threads have finished and the final one again Broadcasts to a condition variable, this time cycleEnded. Note that the counter is already zero, ready for the next cycle to begin. It may well be that you can do without the synchronization at the beginning of each cycle. In that case, the counter should be initialized to the number of worker threads and reset to that number by the thread that decrements it to zero, just before broadcasting to cycleEnded. This solution seems pretty simple to me, which may mean that it has performance problems; maybe someone else can improve on that aspect of it. Pavel ======================================================================= 20 === Date: 6 May 92 19:45:36 GMT From: thor@asgard.mty.itesm.mx (Antonio Quesada-Duarte) Subject: Benchmarks, comparative info, etc. Hi There! Here at ITESM at Monterrey (MEXICO) we are interested in start using Modula-3, but we would like to have a basis to take make or not the change. Doed anybody in netland know where I can find some sort of benchmarks or comparative info. I do not mean benchmark programs, but results from benchmarks alredy performed. Something that appeared in a magazine or a thing like that. Any help will be gratly appreciated. Please respond to thor@asgard.mty.itesm.mx Thanks a lot! >From Monterrey, MEXICO Antonio Quesada-Duarte ======================================================================= 21 === Date: Wed, 6 May 92 13:04:01 PDT From: jdd@src.dec.com (John DeTreville) Subject: Re: Modula-3 Users Group Meeting... This is an update on the state of planning for the Modula-3 Users' Group (MUG) meeting, to be held at DEC SRC in Palo Alto on June 16. The MUG meeting is now jointly sponsored by Digital Equipment Corporation's Systems Research Center and by the Xerox PARC Computer Science Laboratory. Many thanks to our two sponsors. Here is a tentative agenda. 9:00 AM - 1:00 PM Talks. 1:00 PM - 2:00 PM Lunch. 2:00 PM - 3:00 PM Short talks. 3:00 PM - 4:45 PM Breakout sessions. 4:45 PM - 5:30 PM Reports from breakout sessions. 5:30 PM - 6:00 PM Wrapup. The morning talks will be 10-20 minutes, and we have a lot. Even so, there's still a little room if you aren't yet on the list. The current list includes: Bill Kalsow, DEC SRC. "SRC's plans for Modula-3 this year". Eliot Moss, University of Massachusetts at Amherst. "GNU Modula-3". Jim Meehan, DEC SRC. "FormsVBT". Loretta Guarino, DEC SRC. Hector demo. Eric Muller, DEC SRC. showheap/showthreads demo. Dave Nichols, Xerox PARC CSL. "Sun RPC". David Evers, Cambridge University. "Network objects at Cambridge". Greg Nelson, DEC SRC. "Network objects at SRC". Mick Jordan, DEC SRC. "The M3AST toolkit". Jorge Stolfi, DEC SRC. "Using generics". Hans Boehm, Xerox PARC CSL. "Replacing the Modula-3 runtime with PCR" Frode Odegard, Odegard Labs. "Commercializing Modula-3". John DeTreville, DEC SRC. "Taking over the world with Modula-3". Marc H. Brown, DEC SRC. "The Mentor project for algorithm animation". Greg Nelson, DEC SRC. "The Sparta project for static program analysis tools". David Goldberg, Xerox PARC CSL. "Why does Modula-3 have all those required Float interfaces?". (I've made up titles in a few cases, and one or two entire talks. All this is subject to change. We'll post a revised agenda before the actual meeting.) MUG will provide lunch. We'll have a few conference rooms set aside for technical discussions over lunch, plus a couple of larger areas if you'd rather just eat and socialize. The short talks are expected to last 5 minutes, and attendees are urged to consider giving a short talk. The short talks currently scheduled include those by: David Evers, Cambridge University. Sam Harbison, Pine Creek Software. Bert Laverman, University of Gronigen. Norman Ramsey, Princeton University. Win Treese, DEC Cambridge Research Laboratory Remember that we would also welcome demos, if arrangements are made far enough in advance. Breakout sessions allow parallel technical discussions of topics of interest. At MUG, we'll ask for volunteers to run breakout sessions, and a show of hands of those who'd want to take part. Our own list of possible breakout sessions include: Numerical analysis. Modula-3 in education. Extensions to Trestle. RPC. Modula-3 on PCs. Compiler back-ends. Extension languages. Critique of Modula-3 libraries. Lexer/parser generators for Modula-3. Language changes in Modula-4. Afterwards, each breakout session will present a short report on the discussions back to the entire group, and there'll be a short wrapup. Although MUG is over at 6:00 (whew!), Palo Alto contains a number of restaurants where participants can continue their conversations until all hours. As the time for MUG draws closer, we will post travel directions, street maps, and so on. If you have any questions, comments, etc., please send them to mug-meeting@src.dec.com, which should finally work. Cheers, John ======================================================================= 22 === Date: Thu, 07 May 1992 14:20:01 GMT From: holiday@bnr.ca Subject: Re: Why no structured function results in Oberon [Was: Proposal for a new construction] I have to agree with Piet, both about the desirability of returning structures by value, and that any good compiler should be able to do that without sweating. The desirability of something like Oberon as a teaching tool, for example, goes up in proportion to the language's orthogonality, particularly with respect to the type system. --------------------------------------------------------------------------- Matt Holiday #include holiday@bnr.ca BNR Richardson ======================================================================= 23 === Date: 8 May 92 09:52:04 GMT From: laverman@cs.rug.nl (Bert Laverman) Subject: Re: Why no structured function results in Oberon In article <1992May07.142001.19508@bnr.ca>, holiday@bnr.ca writes: > The desirability of something like Oberon as a teaching tool, for example, go es > up in proportion to the language's orthogonality, particularly with respect t o > the type system. I don't quite know wether this evaluates to supporting or denying Oberons usefu lness, but let me give an example of where (I think) Oberon fails: >From the Oberon syntax: ... Factor = Designator ["(" [ExprList] ")"] | number | character | .... ... Designator = Qualident {"." ident | "[" ExprList "]" | "^" | "(" QualIdent ")"}. ... So: field selection, indexing, dereferencing, and typeguarding can be repeate d as often as wanted. However, as soon as the result is a function pointer, and it is applied, it is not allowed to continue. A solution would be to use parentheses, but they are not allowed for forming a designator. So the function result must be assigned, and then used... I definately like the Modula-3 approach much better. Greetings, Bert -- #include Bert Laverman, Dept. of Computing Science, Groningen University Friendly mail to: laverman@cs.rug.nl The rest to: /dev/null ======================================================================= 24 === Date: Fri, 8 May 1992 11:26:10 GMT From: laverman@cs.rug.nl (Bert Laverman) Subject: SRC-m3 for the HP9000/700 There was a post some time ago about somebody who announced that he would start the port of SRC-m3 to the HP 9000/700. SInce then, silence. I would like this port very much, but would like the benefit of other people's experience on this... My own first attempt came to a grinding halt in Wildjmp.i3, I simply don't understand what I have to do with that one. The docs only explain globally why it is there, not what the arrays do, or what the escapist solution might be. DO I have to call HP to ask what their implementation of setjmp() is? Then what? Maybe the writer/originator of this interface can explain. Greetings, Bert -- #include Bert Laverman, Dept. of Computing Science, Groningen University Friendly mail to: laverman@cs.rug.nl The rest to: /dev/null ======================================================================= 25 === Date: Fri, 8 May 92 13:58:55 EDT From: wyant@centerline.com Subject: premature (but useful) concern on GNU M3 Will GNU M3 be interoperable with DEC SRC M3 ? By that I mean link time and runtime compatibilty: naming encodings are identical, object layouts are the same, exception handling, etc. In the C++ world, there are a number of incompatible C++ compilers and runtimes. I'd rather not see that repeated with M3. Maybe this is a fool's quest though. cheers, --geoff ======================================================================= 26 === Date: 8 May 92 18:20:24 GMT From: lins@Apple.COM (Chuck Lins ) Subject: Re: Why no structured function results in Oberon In article <1992May8.095204.10719@cs.rug.nl> laverman@cs.rug.nl (Bert Laverman) writes: > >From the Oberon syntax: > ... > Factor = Designator ["(" [ExprList] ")"] | number | character | .... > ... > Designator = Qualident {"." ident | "[" ExprList "]" | "^" | "(" QualIdent ")"}. > ... > So: field selection, indexing, dereferencing, and typeguarding can be repeat ed > as often as wanted. However, as soon as the result is a function pointer , > and it is applied, it is not allowed to continue. A solution would > be to use parentheses, but they are not allowed for forming a designator . > So the function result must be assigned, and then used... So? Why is this a problem? I suspect because you perceive some kind of benefit. The value can be passed as a parameter (this is a form of assignment). If the value is an object, it is true that you must assign the object to an actual variable before calling a method or accessing a field of that object. I suspect that there would be zero benefit. Adding features to *any* software because the programmer likes them, is not a reason for doing so. There must be an actual measurable benefit. Reducing the number of keystrokes by 1% will not impact the development schedule or developmental costs of the software. Just curious, but do you have empirical evidence supporting such a change? Why does software (or language) development remind me so much of baroque architecture? Chuck Lins, Oberon-2 Paladin, lins@apple.com -- Chuck Lins, Apple Computer, Inc. Oberon-2 Paladin lins@apple.com Searching... Searching... Searching for Solevig Dommartin ======================================================================= 27 === Date: 8 May 92 23:15:11 GMT From: diwan@cs.umass.edu (Amer Diwan) Subject: Re: premature (but useful) concern on GNU M3 >>>>> On 8 May 92 17:58:55 GMT, wyant@centerline.com said: wyant> Will GNU M3 be interoperable with DEC SRC M3 ? By wyant> that I mean link time and runtime compatibilty: wyant> naming encodings are identical, object layouts wyant> are the same, exception handling, etc. Unfortunately not. Our (GNU M3 group) implementation of many features is very different from those used in SRC M3. For instance, SRC M3 uses setjmps etc. to implement exceptions but we use compiler generated tables (along with some run-time support) to do the same. Also, our garbage collection scheme expects significant support from the compiler in the form of tables (see our SIGPLAN 92 paper) which is different from how SRC M3 does it. SO, it is unlikely that modules generated by the two compilers will be link compatible. Amer -- ------------------------------------------------------------------------------ Amer Diwan Department of Computer Science University of Massachusetts Amherst, MA 01003 (413) 545-0256 diwan@cs.umass.edu ------------------------------------------------------------------------------ ======================================================================= 28 === Date: 9 May 92 13:07:58 GMT From: gip7@sci.kun.nl (GIP groep 7 - Shing Paul Rob Edwin Jack Rene) Subject: Modula-3 & real-time;questions. Modula-3 is new for me. I'm not able to lay my hands on a programmers manual so I hope that one of you is willing and able to answer a few questions about Modula 3. I'm doing a little research on object oriented or object based languages which have a potential to be used for realtime programming. Questions: 1. Can modula-3 be used as a realtime programming language? 2. Is modula-3 := modula-2 + object-oriented data structures, or are some modula-2 features not present in modula-3? Thanking you in advance: Paul Janssen e-mail:gip7@sci.kun.nl ======================================================================= 29 === Date: 9 May 92 17:30:43 GMT From: moss@cs.umass.edu (Eliot Moss) Subject: Re: premature (but useful) concern on GNU M3 The points that Amer made are true, but I'm not sure they're the most relevant ones. For example, I did make a commitment that people can turn off our gc stuff and use other approaches if they want to. However, you would certainly have difficulty mixing SRC modules with ours in the sense that our run time relies on the presence of compiler generated tables that the SRC compiler does not, and (because of its strategy of using a C compiler) *cannot*, generate. In particular, GM3 does exceptions "the right way" -- no normal case overhead, using tables to locate handlers at run time. The M3 spec implies that this is to be preferred over normal-case-overhead approaches. If you want everything done the same way as SRC M3, then why bother with a native code compiler? There are other things that may be different as well, though I cannot say for sure, and they include details of calling sequences, choice of names emitted to the linker, linkage strategy, detailed layout of OBJECT types and method suites (we will be providing gc support routines customized to each type, stored in the method suite), TYPECODE and TYPECASE algorithm, etc. On the other hand, we *do* expect one to be able to compile SRC library sources and use them with our system just fine. It's not clear to me what strong benefits would accrue from mixing modules produced by different compilers, and it is clear that you would be eliminating a number of the potential gains of functionality and performance we hope to offer. -- J. Eliot B. Moss, Assistant Professor Department of Computer Science Lederle Graduate Research Center University of Massachusetts Amherst, MA 01003 (413) 545-4206, 545-1249 (fax); Moss@cs.umass.edu ======================================================================= 30 === Date: 9 May 92 17:36:30 GMT From: moss@cs.umass.edu (Eliot Moss) Subject: Re: Why no structured function results in Oberon Chuck Lins seemed to be claiming that having to assign a function result to a variable and then dereferencing the variable, etc., was not a big deal because it adds only a few keystrokes to the program, etc. I agree with the viewpoint that terseness of expression is a poor metric for judging language features. What disturbs me about this case is rather different: we have a special case that the programmer has to remember, and there is no really good reason to have the special case. It sounds as if a minor problem is syntax design, or a (to me, unjustified) obscure position w.r.t. function results, is being tossed into the programmer's lap. But I may have misinterpreted Chuck's message, for I was having trouble, at this point in the thread, determining the side of the issue on which he stands. -- J. Eliot B. Moss, Assistant Professor Department of Computer Science Lederle Graduate Research Center University of Massachusetts Amherst, MA 01003 (413) 545-4206, 545-1249 (fax); Moss@cs.umass.edu ======================================================================= 31 === Date: Sun, 10 May 92 16:21:38 GMT From: ggf@saifr00.cfsat.honeywell.com (Gary Frederick) Subject: M3 2.06 and the NeXT I got 2.06 to see if it would build any easier on the NeXT and ran into a problem or two right out of the box. It uses a command 'dirname' that the NeXT does not have. How do I get around that. Also, where is the file m3makefile.boot? I can not find it. Gary ======================================================================= 32 === Date: 10 May 92 23:04:30 GMT From: gip7@sci.kun.nl (GIP groep 7 - Shing Paul Rob Edwin Jack Rene) Subject: Modula-3 & real-time;questions. Sorry for bothering you all. I found all the answers in the FAQ . ------------------------------------------------------- Paul Janssen,student at Nijmegen University, the Netherlands. Still got a lot to learn :). ======================================================================= 33 === Date: Mon, 11 May 1992 07:48:24 GMT From: laverman@cs.rug.nl (Bert Laverman) Subject: Re: Why no structured function results in Oberon Chuck write: > So? Why is this a problem? I suspect because you perceive some kind of > benefit. The value can be passed as a parameter (this is a form of assignment ). > If the value is an object, it is true that you must assign the object to an > actual variable before calling a method or accessing a field of that object. It presents the programmer with Yet Another Exception to how he/she can use his/her types... 'h'mmm this function returns a record.. oh no, that has to be a pointer-to-a-record, and then the record is passed as a parameter... oh no I have to assign it first'. I sincerely believe that orthogonality in the type system of a language can only improve it. Modula-3's way of viewing dereferencing/field selection/ indexing/application as an operation, to be used in an expression as all other operations, makes it tremendously cleaner. Greetings, Bert -- #include Bert Laverman, Dept. of Computing Science, Groningen University Friendly mail to: laverman@cs.rug.nl The rest to: /dev/null ======================================================================= 34 === Date: Mon, 11 May 92 14:58:30 PDT From: Subject: Re: Why no structured function results in Oberon > [Chuck Lins:] [A compound return value] can be passed as a parameter > (this is a form of assignment). Well, which of these would you rather write: === (1) ================================ FROM Complex IMPORT Make, Add, Mul, Div; VAR x, y, z, t1, t2, t3: Complex.T; BEGIN Make(2.0, 1.0, t1); Mul(x, t1, t2); Make(2.0, -1.0, t1); Mul(y, t1, t3); Add(t2, t3, t1); Add(x, y, t2); Div(t1, t2, z) END ========================================= === (2) ================================ FROM Complex IMPORT Make, Add, Mul, Div; VAR x, y, z: Complex.T; BEGIN z := Div( Add(Mul(Make(2.0, 1.0), x), Mul(Make(2.0, -1.0), y)), Add(x, y) ) END ========================================= === (3) ================================ VAR x, y, z: COMPLEX; BEGIN z := ((2 + IMG) * x + (2 - IMG) * y) / (x + y) END ========================================= You say Wirth says we all should learn to love (1). Modula-3 at least lets you write (2). (Incidentally, FORTRAN lets you write something close to (3); which is one of several good reasons why numerical people haven't yet switched to "better" languages like Pascal and Modula.) > There must be an actual measurable benefit. Reducing the number > of keystrokes by 1% will not impact the development schedule or > developmental costs of the software. Perhaps not, but 99 such improvements could cut the costs by 99%... (Of course, cost savings are not necessarily additive, so the total value of may be less than 99%. But it may also be *greater*...) Jorge Stolfi DEC Systems Research Center stolfi@src.dec.com ------------------------------------------------------------------------- DISCLAIMER: I am only an often grumpy but basically happy Modula-3 user. Needless to say, my personal opinions do not always agree with those of the Modula-3 designers, and do not reflect DEC's official position on these matters (if there is any). ======================================================================= 35 === Date: Tue, 12 May 1992 01:52:59 GMT From: vsanchez@casbah.acns.nwu.edu (Victor Sanchez) Subject: Re: Why no structured function results in Oberon In article <9205112158.AA10880@jumbo.pa.dec.com> stolfi (Jorge Stolfi) writes: > > > [Chuck Lins:] [A compound return value] can be passed as a parameter > > (this is a form of assignment). > >Well, which of these would you rather write: > > Stuff deleted. > === (2) ================================ > FROM Complex IMPORT Make, Add, Mul, Div; > VAR x, y, z: Complex.T; > BEGIN > z := Div( > Add(Mul(Make(2.0, 1.0), x), > Mul(Make(2.0, -1.0), y)), > Add(x, y) > ) > END > ========================================= > > >Modula-3 at least lets you write (2). > > > Jorge Stolfi > DEC Systems Research Center > stolfi@src.dec.com > I tend to agree with Jorge about the lack of structured type returns. I prefer to have then. However, I think Oberon allows you to create something like example 2. Because of the inclusion of the garbage collector, Complex.T can be a pointer to a structure, then the function: a:= make(1.0,2.1); would return a pointer to the structure. The old value of "a" is lost and (if I understand correctly) the collector would free the memory that "a" used to point to. The only diference here from structured returns is that the programer of the package has to explicity allocate the memory for the return structure. Now, I do not know much about compiler implementation and would like to know if one technique is more efficient than the other. My own experiences with garbage collection in old Lisp interpreters is not very good, but I have heard that the algorithms have gotten much better. Could anyone care to comment? The point could be moot because some Oberon compilers for microcomputers do not include the garbage collector (e.g. Amiga Oberon and the MSDOS version). Victor Sanchez Now, I will like to here a ======================================================================= 36 === Date: Wed, 13 May 1992 07:46:28 GMT From: laverman@cs.rug.nl (Bert Laverman) Subject: Re: Why no structured function results in Oberon Victor Sanchez writes: > Jorge Stolfi wrote: > > === (2) ================================ > > FROM Complex IMPORT Make, Add, Mul, Div; > > VAR x, y, z: Complex.T; > > BEGIN > > z := Div( > > Add(Mul(Make(2.0, 1.0), x), > > Mul(Make(2.0, -1.0), y)), > > Add(x, y) > > ) > > END > > ========================================= > I tend to agree with Jorge about the lack of structured type returns. I prefe r > to have then. However, I think Oberon allows you to create something like > example 2. Because of the inclusion of the garbage collector, Complex.T can > be a pointer to a structure, then the function: > > a:= make(1.0,2.1); > > would return a pointer to the structure. The old value of "a" is lost and > (if I understand correctly) the collector would free the memory that "a" > used to point to. The only diference here from structured returns is that > the programer of the package has to explicity allocate the memory for > the return structure. Of course, this is what GC is all about, and both Oberon and Modula-3 do it, _but_ If you look at the Oberon report, you'll see that you simply _CAN'T_ reproduce (2), because _THE_SYNTAX_DOESN'T_ALLOW_IT_. Sure, you can return a pointer in stead of the record itself, but this pointer result _must_be_assigne d_, and cannot be immediately dereferenced. The net effect isn't much better than (1) from the original posting, with as only difference that results are now passed as function-results, in stead of through VAR parameters. VAR parameters are in that case more efficient (usually). > Now, I do not know much about compiler implementation and would like to know > if one technique is more efficient than the other. My own experiences with > garbage collection in old Lisp interpreters is not very good, but I have > heard that the algorithms have gotten much better. Could anyone care to > comment? A few doors down the hall work is being done on `the Groningen Oberon Compile r', which is essentially Oberon-2, plus exceptions. (;-)) When pressed on the quest ion of structured function results, the reply was that the idea was nice in princip le, but it prompts extra copy actions. The usual approach is to allocate space for the result, and then call the function. If the result must be assigned, a copy of the entire record is needed, which would not have been necessary with a VAR par ameter. Passing the address of a piece of memory instead doesn't solve this, as the onl y way to avoid the copy is by passing the address of the variable-to-be-assigned- to, and this can create chaos if the function references the same variable as a glo bal. > The point could be moot because some Oberon compilers for microcomputers do > not include the garbage collector (e.g. Amiga Oberon and the MSDOS version). Worse, they won't allow anything like (2) at all... Greetings, Bert -- #include Bert Laverman, Dept. of Computing Science, Groningen University Friendly mail to: laverman@cs.rug.nl The rest to: /dev/null ======================================================================= 37 === Date: Fri, 15 May 1992 01:11:07 GMT From: johnr@ee.uts.edu.au (John Reekie) Subject: Modula3 vs Oberon?? Forgive me if ther is a FAQ answering these questions -- I can't find it. Would someone be willing to enlighten me on: i) How is Modula3 different to Oberon? ii) What are the standard references ot Modula3 and Oberon? iii) Are either of these languages suitable for teaching, and are their any good textbooks available for this purpose? Please reply by email unless you think it is of interest to the rest of this group Thank you very nuch John Reekie johnr@ee.uts.edu.au ======================================================================= 38 === Date: Mon, 18 May 92 11:58 GMT From: David Bruce <"ISIS::dib%hermes.mod.uk"@relay.MOD.UK> Subject: Modula-3 for the NeXT? Can anyone out there tell me if a Modula-3 system (from SRC, GNU or any other) for the NeXT? If so, what versions of the O/S, M3 etc. are needed? Many thanks, David Bruce ---- post: DRA Malvern, St Andrews Road, Malvern, Worcestershire WR14 3PS, ENGLAND email: dib%hermes.mod.uk@relay.mod.uk (internet) phone: +44 684 895112 fax: +44 684 894303 ======================================================================= 39 === Date: Mon, 18 May 92 08:03:51 EDT From: wyant@centerline.com Subject: Trestle extensions ? Has anyone extended Trestle to have additional useful splits 'n leaves, such as scrollbars, editable text, and listboxes ? thanks ! --geoff Geoff Wyant wyant@centerline.com Centerline Software, Inc. (Formerly Saber Software, Inc) 10 Fawcett Street Cambridge, Ma. 01238 ======================================================================= 40 === Date: 18 May 92 18:29:32 GMT From: lins@Apple.COM (Chuck Lins ) Subject: Re: Why no structured function results in Oberon [I was away at Apple's WWDC all week adn unable to respond sooner] In article moss@cs.umass.edu writes: >Chuck Lins seemed to be claiming that having to assign a function result to a >variable and then dereferencing the variable, etc., was not a big deal because >it adds only a few keystrokes to the program, etc. > >I agree with the viewpoint that terseness of expression is a poor metric for >judging language features. What disturbs me about this case is rather >different: we have a special case that the programmer has to remember, and >there is no really good reason to have the special case. It sounds as if a >minor problem is syntax design, or a (to me, unjustified) obscure position >w.r.t. function results, is being tossed into the programmer's lap. > >But I may have misinterpreted Chuck's message, for I was having trouble, at >this point in the thread, determining the side of the issue on which he >stands. My position is that structured function results are unnecessary since there is an already existing notation within the language for accomplishing the same goal. Further, this alternative notation is not a burden on the programmer. In most cases, it will not be a burden on the efficiency of the resulting program either. In some cases, it will be more efficient (eg when passing structured results back up the call chain). You must remember the overriding design principle of Oberon: "As simple as possible, but no simpler" All languages (computer or human) will have special rules somewhere (well maybe except for Scheme :-). I think the proper way to judge the rules are on such criteria as: o how many special rules exist in the language? o how often must the programmer invoke the special rule(s)? o what is the burden placed on the programmer? and probably others that i'm forgetting at the moment. Actually, now that i think about it, every language is nothing more than a set of special rules, ie, it's syntax. Considering that humans are very capable of handling very complex special language rules in every day communication with natural language, i doubt that any programmer will have any problem with the one very simple rule. >>>>> Devil's Advocate Hat on Now <<<<< Since one can pass multiple arguments to a routine, why can't you return multiple function results? This seems like it could be useful. For example, in the case of returning a COMPLEX number, I could return two values, the real and imaginary parts. (Yes I'm well aware that Lisp does support this notion) <<<<< Oberon Hat Back On >>>>> wrt the special case of COMPLEX data type, I believe that for the numeric applications where it tends to appear, it should be a basic type. In fact, in Seneca (an Oberon derivative for numeric processing designed by Robert Griesemer at ETH) COMPLEX is a basic type. And yes Burt, you can write Piet's #2 in Oberon. My goal here is not to try and convert Modula-3ans to Oberon. Hopefully the minimalism of Oberon will encourage the designers not to create a monstrosity like C++ when they consider extending Modula-3. Even Oberon will be extended over time. But this will occur only after carefull consideration of the benefits derived from the feature. Also, perhaps the language is not the best place for a capability. Maybe it should be in the development environment (which i consider to be something other than emacs, a compiler, and a linker). -- Chuck Lins, Apple Computer, Inc. Oberon-2 Paladin lins@apple.com ======================================================================= 41 === Date: Mon, 18 May 92 14:12:34 PDT From: muller@src.dec.com (Eric Muller) Subject: cost of map procs I have made some experiments to access the performance of the mechanism used to find traced references in referents. This is the mechanism used by the garbage collector to construct the set of accessible referents. The same mechanism is used for find untraced references and procedures in referents, to support pickles. This is also the mechanism which will be used for network objects (where more types will have to be handled). In the mechanism currently used by SRC Modula-3 (2.06), the compiler generates one procedure for each type, called the map procedure for that type. This map procedure takes as arguments a referent and a procedure to apply to each of the components of interest in the referent. A bit mask (on the fixed enumeration TRACED, UNTRACED, PROC) selects the components of interest. An alternative uses an encoding the map not as a procedure but as a sequence of virtual instructions to be interpreted (this is what the Olivetti implementation did). In this experiment, a virtual instruction is 1, 2 or 3 16-bit words long. The first word indicates the kind of component present (TRACED, UNTRACED, PROC, ARRAY OF TRACED, ARRAY OF UNTRACED, ARRAY OF PROC). In the case of arrays, this is followed by a length. Finally, there is the offset of the component in the referent. This method can be optimized: most of the places that call the map procedure know the procedure to apply to the components. By inlining the interpreter and the procedure to apply, the system can go faster. One could also implement "code modification" by deriving special purpose maps from the general one built by the compiler. For example, the garbage collector is interested only in TRACED and ARRAY OF TRACED; the first time a type is processed, a map containing only the relevant instructions could be built. Another optimization is to concatenate the maps of the supertypes with the map of a type. In the current system, each direct type/subtype relation costs a procedure call (inlining the parent procedure is not always possible a compile time). Code modification is not part of this experiment, but concatenation is (implicitly). The test program (see below) similates a heap of 100,000 referents, each being of the type T: TYPE T = OBJECT a: REF INTEGER; b: UNTRACED REF INTEGER; END OBJECT c: REF INTEGER; d: ARRAY [1..10] OF REF INTEGER; e: PROCEDURE (); END; Four compilation configurations have been used: cc -g, cc -O2, gcc -g and gcc -O2 (cc 1.31, gcc 2.1), all on a DECstation 5000/200 running Ultrix 4.2a. This is the number of cycles executed per referent where the apply procedure is a non-taken test (if (v) {...} where v = 0), as reported by pixie: current new new, inline cc -g 432 547 316 cc -O2 255 291 154 gcc -g 500 665 410 gcc -O2 240 308 183 The code size for the map procedures (in bytes), obtained by "wc -l" on the disassembled code: current cc -g 408 cc -O2 312 gcc -g 472 gcc -O2 264 This does not include the symbol table entries; there are no globals variables. The encoded map occupies 22 bytes and no symbol table entries. The code size for the map procedures in solitaire (compiled with cc -g) is 47,244 bytes. The full program code size is 1,511,424 bytes It seems that we are roughly at an equililibrium point right now. To get a significant advantage from the virtual code approach, one needs to inline the interpreter. Furthermore, the interpreter scheme requires that the compiler be in synch with the runtime, more than today (the interpreter is really in the compiler right now; the compiler/runtime dependency is just the signature of the map proc). The absolute size of the map procs is not a problem. I would say that speed advantage barely compensate for the added complexity of the system. On the other hand, network objects will require more types to be handled. For example, integers and floating-points will have to be handled. The amount of code in the map not executed while used by the garbage collector will become significant; this tends to show that the "modifying code" approach may be interesting. Also, the absolute size of the map proc may become prohibitive and the saving of the "virtual code" approach are very important. Eric. Here is all the code I used, in case you want to try some variations. #!/bin/sh # This is a shell archive (shar 3.32) # made 05/18/1992 21:09 UTC by muller@procope.pa.dec.com # Source directory /tmp_mnt/flimflam/r/dlusers5/muller/work/mapspeed # # existing files WILL be overwritten # # This shar contains: # length mode name # ------ ---------- ------------------------------------------ # 2305 -rw-r--r-- proc.c # 130 -rw-r--r-- header.h # 234 -rw-r--r-- user.c # 419 -rw-r--r-- user2.c # 779 -rw-r--r-- makefile # if touch 2>&1 | fgrep 'amc' > /dev/null then TOUCH=touch else TOUCH=true fi # ============= proc.c ============== echo "x - extracting proc.c (Text)" sed 's/^X//' << 'SHAR_EOF' > proc.c && X#include X#include "header.h" X Xextern void map (); Xextern void map2 (); X Xstruct { X void (*proc) (); X short map [20]; X int dummy; X int val[10]; } r [HEAP_SIZE]; X Xint ops; X Xvoid move (ref) X int *ref; X{ X if (ops & 1) { X printf ("%d ", *ref); } X} X Xvoid interpret_map (func, map, ref, mask) X void (*func)(); X short *map; X char *ref; X int mask; X{ X while (*map != 0) { X if (*map & mask) { X if (*map++ & ARRAY) { X int n = *map++; X int *pp = (int*)(ref + *map); X while (n-- != 0) { X func (pp++); }} X else { X func (ref + *map); }} X map++; } X} X Xvoid collect () X{ X int i; X for (i = 0; i < HEAP_SIZE; i++) { X void (*proc) () = r[i].proc; X if (proc != 0) { X proc (move, & (r[i].dummy), TRACED); }} X} X Xvoid newcollect () X{ X int i; X for (i = 0; i < HEAP_SIZE; i++) { X if (r[i].map [0] != 0) { X interpret_map (move, r[i].map, & (r[i].dummy), TRACED); }} X} X Xvoid newcollectinline () X{ X int i; X for (i = 0; i < HEAP_SIZE; i++) { X short *map = r[i].map; X char *p = (char*) &(r[i].dummy); X while (*map != 0) { X if (*map & TRACED) { X if (*map++ & ARRAY) { X int n = *map++; X int *pp = (int*) (p + *map); X while (n-- != 0) { X if (ops & 1) { X printf ("%d ", *pp); }}} X else { X move (p + *map); }} X map++; }} X} X Xvoid setup () X{ X int i, j; X for (i = 0; i < HEAP_SIZE; i++) { X r[i].proc = map; X for (j = 0; j < 10; j++) { X r[i].val[j] = 10 *j + i; } X r[i].map [0] = TRACED; X r[i].map [1] = OFFSET; X r[i].map [2] = UNTRACED; X r[i].map [3] = OFFSET; X r[i].map [4] = TRACED; X r[i].map [5] = OFFSET; X r[i].map [6] = (ARRAY | TRACED); X r[i].map [7] = 10; X r[i].map [8] = OFFSET; X r[i].map [9] = PROC; X r[i].map[10] = OFFSET; X r[i].map[11] = 0; } X} X Xmain (argc, argv) X int argc; X char ** argv; X{ X if (argc != 2) { X fprintf (stderr, "usage: %s n\n", argv[0]); X exit (1); } X X ops = atoi (argv[1]); X X setup (); X X if (ops & 2) { X if (ops & 1) { X printf ("collect: "); } X collect (); } X X if (ops & 4) { X if (ops & 1) { X printf ("\nnewcollect: "); } X newcollect (); } X X if (ops & 8) { X if (ops & 1) { X printf ("\nnewcollectinline: "); } X newcollectinline (); } X X if (ops & 1) { X printf ("\n"); } X} X SHAR_EOF $TOUCH -am 0515180492 proc.c && chmod 0644 proc.c || echo "restore of proc.c failed" set `wc -c proc.c`;Wc_c=$1 if test "$Wc_c" != "2305"; then echo original size 2305, current size $Wc_c fi # ============= header.h ============== echo "x - extracting header.h (Text)" sed 's/^X//' << 'SHAR_EOF' > header.h && X#define HEAP_SIZE 100000 X#define TRACED 1 X#define UNTRACED 2 X#define PROC 4 X#define ARRAY 8 X X#define OFFSET sizeof (int) SHAR_EOF $TOUCH -am 0515175192 header.h && chmod 0644 header.h || echo "restore of header.h failed" set `wc -c header.h`;Wc_c=$1 if test "$Wc_c" != "130"; then echo original size 130, current size $Wc_c fi # ============= user.c ============== echo "x - extracting user.c (Text)" sed 's/^X//' << 'SHAR_EOF' > user.c && X#include "header.h" X Xvoid map2 (func, ref, mask) X void (*func) (); X char* ref; X int mask; X{ X if (mask & TRACED) { /* REF */ X func (ref+OFFSET); } X if (mask & UNTRACED) { /* UNTRACED REF */ X func (ref+OFFSET); } X} SHAR_EOF $TOUCH -am 0515180492 user.c && chmod 0644 user.c || echo "restore of user.c failed" set `wc -c user.c`;Wc_c=$1 if test "$Wc_c" != "234"; then echo original size 234, current size $Wc_c fi # ============= user2.c ============== echo "x - extracting user2.c (Text)" sed 's/^X//' << 'SHAR_EOF' > user2.c && X#include "header.h" X Xvoid map (func, ref, mask) X void (*func) (); X char* ref; X int mask; X{ X map2 (func, ref, mask); /* supertype */ X if (mask & TRACED) { /* REF */ X func (ref+OFFSET); } X if (mask & TRACED) { /* ARRAY [1..10] OF REF */ X int i = 10; X int *pp = (int*) (ref + OFFSET); X while (i-- > 0) { X func (pp++); }} X if (mask & PROC) { /* PROCEDURE */ X func (ref+OFFSET); } X} X SHAR_EOF $TOUCH -am 0515180492 user2.c && chmod 0644 user2.c || echo "restore of user2.c failed" set `wc -c user2.c`;Wc_c=$1 if test "$Wc_c" != "419"; then echo original size 419, current size $Wc_c fi # ============= makefile ============== echo "x - extracting makefile (Text)" sed 's/^X//' << 'SHAR_EOF' > makefile && Xall:: X cc -O2 -o proc.ccO proc.c user.c user2.c X pixie proc.ccO X proc.ccO.pixie 14 X prof -pixie proc.ccO > proc.ccO.res X time proc.ccO 2 X time proc.ccO 2 X time proc.ccO 4 X time proc.ccO 8 X Xall:: X cc -g -o proc.ccg proc.c user.c user2.c X pixie proc.ccg X proc.ccg.pixie 14 X prof -pixie proc.ccg > proc.ccg.res X time proc.ccg 2 X time proc.ccg 2 X time proc.ccg 4 X time proc.ccg 8 X Xall:: X gcc -O2 -o proc.gccO proc.c user.c user2.c X pixie proc.gccO X proc.gccO.pixie 14 X prof -pixie proc.gccO > proc.gccO.res X time proc.gccO 2 X time proc.gccO 2 X time proc.gccO 4 X time proc.gccO 8 X Xall:: X gcc -g -o proc.gccg proc.c user.c user2.c X pixie proc.gccg X proc.gccg.pixie 14 X prof -pixie proc.gccg > proc.gccg.res X time proc.gccg 2 X time proc.gccg 2 X time proc.gccg 4 X time proc.gccg 8 X XFRC: SHAR_EOF $TOUCH -am 0515184392 makefile && chmod 0644 makefile || echo "restore of makefile failed" set `wc -c makefile`;Wc_c=$1 if test "$Wc_c" != "779"; then echo original size 779, current size $Wc_c fi exit 0 ======================================================================= 42 === Date: Mon, 18 May 92 23:39:04 PDT From: surak!frode (Frode Odegard) Subject: network objects (Was: Re: cost of map procs) Eric Muller writes: > I have made some experiments to access the performance of the > mechanism used to find traced references in referents. This is the > mechanism used by the garbage collector to construct the set of > accessible referents. The same mechanism is used for find untraced > references and procedures in referents, to support pickles. This is > also the mechanism which will be used for network objects (where more > types will have to be handled). Can you tell us more about the network objects ? - Frode (frode@odegard.com, in spite of headers) ======================================================================= 43 === Date: 19 May 92 14:04:26 GMT From: dagenais@vlsi.polymtl.ca (Michel Dagenais) Subject: Re: Trestle extensions ? > Has anyone extended Trestle to have additional useful > splits 'n leaves, such as scrollbars, editable text, > and listboxes ? I have two students working on editable text, paragraphs, graphics and equations. Now that the courses are finished they should be able to concentrate on that. Of course whenever something useful comes out it will be announced and made available for FTP. I believe the DEC SRC release should soon include FORMS VBT which may include some useful higher level Trestle splits and leaves. -- --------------------------------------------------------------------- Prof. Michel Dagenais dagenais@vlsi.polymtl.ca Dept of Electrical and Computer Eng. Ecole Polytechnique de Montreal tel: (514) 340-4029 --------------------------------------------------------------------- ======================================================================= 44 === Date: 19 May 92 14:17:21 GMT From: dagenais@vlsi.polymtl.ca (Michel Dagenais) Subject: Modula 3 BOF at SIGPLAN 1992 PLDI In addition to the full day Modula 3 "workshop" (on Tuesday June 16th at DEC SRC in Palo Alto), there will be a Modula 3 BOF at SIGPLAN 1992 PLDI in San Francisco. Tentative plans are for Thursday June 18th at 19h30. For those who cannot make it for the full day meeting or dont want to spend a full day on Modula 3, this should be an excellent opportunity to get better acquainted with the language and other current or prospective Modula 3 users. More details on the exact time and location will follow shortly in this newsgroup. There are some problems getting a room, maybe we should consider going outside... somewhere like the Ghirardelli chocolate factory perhaps. :-)') -- --------------------------------------------------------------------- Prof. Michel Dagenais dagenais@vlsi.polymtl.ca Dept of Electrical and Computer Eng. Ecole Polytechnique de Montreal tel: (514) 340-4029 --------------------------------------------------------------------- ======================================================================= 45 === Date: Tue, 19 May 92 12:33:42 -0700 From: Subject: Re: Trestle extensions ? At the risk of sounding like I'm self-promoting "vaporware", there is indeed quite a bit of extensions to Trestle that we have done here. There is a toolkit with the additional useful splits 'n leaves, such as scrollbars, editable text, and listboxes. There's also a "mini" version of the FormsVBT UIMS layered atop that. Jim Meehan and I are working deligently on preparing the initial alpha release for gatekeeper. Our current goal is before the end of the month. ======================================================================= 46 === Date: Wed, 20 May 1992 13:21:49 GMT From: larry@tsd.arlut.utexas.edu (Larry Maturo) Subject: Re: Why no structured function results in Oberon In article <67270@apple.Apple.COM> lins@Apple.COM (Chuck Lins ) writes: > >You must remember the overriding design principle of Oberon: > >"As simple as possible, but no simpler" > I must say I agree with this whole heartedly but have one caveat to it. Writin g complex code is easy. The problem is that maintaining complex code is very hard. The language should support, as directly as possible, what the programme r is trying to accomplish so that reading the code makes his intention clear. This makes the langauge more complex but makes programs written in it less complex and easier to maintain. I don't know that this has any bearing on aggregate function return values in the general case, however, I would say it has a lot to do with not being able to declare aggregate constants (such as conversion tables) and with not being able to directly return them when needed. Constant tables are very expressive of the programmers intent and should be supported in a language with whatever scaffolding is required. I would be happy to limit the aggregate support to constants however, if this simplifies anything. +-----------------------------------+----------------------------------------+ | | | | Larry Maturo | Opinions expressed herein must be | | Tactical Simulation Division | yours, neither I nor my employer have | | Applied Research Laboratories | any. | | University of Texas at Austin | | | P.O. Box 8029 +----------------------------------------+ | Austin, Texas 78713-8029 | | | | When you're as great as I am it's hard | | larry@titan.tsd.arlut.utexas.edu | to be modest, but I succeed where | | | others fail. | +-----------------------------------+----------------------------------------+ ======================================================================= 47 === Date: Wed, 20 May 92 15:15:34 GMT From: pattis@cs.washington.edu (Richard Pattis) Subject: Re: Why no structured function results in Oberon >In article <67270@apple.Apple.COM> lins@Apple.COM (Chuck Lins ) writes: > >You must remember the overriding design principle of Oberon: > >"As simple as possible, but no simpler" > As a gross overgeneralization, I'd characterize Wirth languages as easy to write compilers for, but hard to program in. Question: is this because Wirth spends more time writing compilers than applications? Exactly who draws the line between these simplicities? There is no need for six relational operators: just < along with AND works just fine. Why wasn't this simplification made? For that matter the logical operators are unnecessary because they can be simulated with nested ifs. Ditto. -- ------------------------------------------------------------------------------ Richard E. Pattis "Programming languages are like Department of Computer Science pizzas - they come in only "too" and Engineering sizes: too big and too small." ======================================================================= 48 === Date: Wed, 20 May 92 18:07:08 PDT From: Subject: Re: Why no structured function results in Oberon The issue of "big" procedure return values (records and arrays): can be split into two separate question: (1) Is it better to keep big return values on the stack, or should they be allocated on the heap and passed around as pointers? (2) should the compiler handle structured return values automatically, or should the programmer be forced to use explicit mechanisms (VAR parameters, NEW, etc)? I think the answer to (1) is obvious once one looks the costs involved. First, consider stack allocation. Given a reasonably decent machine and compiler, the cost of copying a structured return value to the caller's stack frame should be no more than 2--3 machine cycles per word (for a suitable definition of "machine cycle" and "word"). This cost is substantial but not excessive; after all, the "intrinsic" cost of computing the result will hardly be less than one cycle per word. For example, if the intrinsic cost of Complex.Multiply is 3 cycles per word, copying the result adds at most 50% overhead. Besides, in most cases the return value doesn't even have to be copied at all. If its size is known in advance, the caller can reserve space for it beforehand, and the callee can store the data directly into that space. (Incidentally, with this trick one can also avoid copying the same result multiple times when returning from several procedures in a row.) Now, consider the cost of returning a big value as a heap record. Let's be generous and assume that the heap allocation procedure gets expanded inline, and takes only a couple of cycles on the average. However, to this direct "allocation cost" we must add the indirect "heap pollution costs". During the node's lifetime, each run of the garbage collector will spend several extra cycles handling it: either returning the node to the storage pool, or marking it reachable, copying it, and relocating its references. These costs are hard to estimate, but I would be surprised if one could reduce them to less than 10 cycles per node-word, at each GC run. Note also that the mere presence of that node will cause the garbage collector to run slightly more often than usual (assuming the maximum heap size is fixed). Although the increase in GC frequency is small, the cost of a GC run is large; and according to my algebra this extra term has about the same magnitude as the other costs above. Moreover, note that these estimates are only for the incremental cost of adding *one* node to the heap, all else being equal. However, if the maximum heap size is fixed, the garbage collection costs grow more than linearly as the number of reachable node increases; so, if *all* large return values were to be allocated on the heap, the extra cost per word would be much higher than the above estimates. The bottom line is that allocating return values on the heap is at least one order of magnitude more expensive than copying them onto the stack. Therefore, the heap approach just can't be used for low-level routines like Complex.Multiply and Point.Add, for which copying is already a major overhead. Another way to look at this question is to view the stack as a mere optimization trick for speeding up the garbage collection of values and variables whose lifetimes can be predicted statically. Thus, when one says that all big return values should be allocated on the heap, one is implicitly saying that this optimization is not worth the trouble for multi-word values. I believe that the numbers say otherwise. --xOx-- As for question (2), I think the answer is obvious: the compiler should handle large results automatically, because that is what compilers are for. Given that the heap technique is too expensive for many common applications, a compiler that does not handle big return values will force the programmer to use VAR parameters instead. As I said before, this solution results in unreadable assembly-like code: Make(2.0, 1.0, t1); Mul(x, t1, t2); Make(2.0, -1.0, t1); Mul(y, t1, t3); Add(t2, t3, t1); Add(x, y, t2); Div(t1, t2, z) ... Another reason for allowing big return values is to make the language more orthogonal, which is an important requisite for generic modules, source-level optimizers, and other program manipulation tools. \begin{soapbox} Let's not forget that high-level languages were invented to make programming easier; and this is still their *only* purpose. Let's keep in mind also that programmer time is much more valuable than computer time; and that a new language is not worth designing unless it is meant to be used by tens of thousands of programmers. Therfore, the primary goal of every language designer should not be to keep the language simple and the compiler small, but rather to automate every aspect of the programmer's work that can be usefully automated. Incidentally, I wonder whether the famous Einstein phrase --- "Make it as simple as possible, but not simpler" --- which the disciples of the Minimalist School of Language Design are so fond of quoting, actually means what they think it means. I couldn't find the context of that quote, but considering that it came from the man who replaced Newton's physics by Minkowskian four-tensors and curved spacetime, I read it as a defense of *complexity*: "while simplicity is important, often the only way to make progress is to make things more complicated." So, I implore you, dear language designers, please heed Eistein's advice: make your languages as simple as possible, BUT NOT SIMPLER. \end{soapbox} Jorge Stolfi Department of Cybheretics DEC Systems Research Center .. Un vieux peripateticien dit tout haut avec confiance : << L'ame est une entelechie, et une raison par qui elle a la puissance d'etre ce qu'elle est. C'est ce que declare Aristote, page 633 de l'edition du Louvre. >> Il cita le passage. << Je n'entends pas trop bien le grec, dit le geant. -- Ni moi non plus, dit la mite philosophique. -- Porquoi donc, repit le Sirien, citez-vous un certain Aristote en grec? -- C'est, repliqua le savant, qu'il faut bien citer ce qu'on ne comprend point du tout dans la langue qu'on entend le moins. >> -- Voltaire, /Micromegas/ ======================================================================= 49 === Date: Thu, 21 May 1992 10:10:35 PDT From: boehm.PARC@xerox.com Subject: Re: Why no structured function results in Oberon At the risk of repetition: 1. I also don't understand why disallowing structured return values simplifies the language. It introduces a distinction between simple types and structured types. The programmer has to keep them straight. There may be other reasons for introducing this distinction (e.g. real polymorphic functions are a lot cheaper to implement when restricted to one word objects), but I would never argue that this distinction is a good thing. (The right definition of "structured type" isn't always obvious, either. A good compiler should be able to represent something that amounts to a disjoint union of pointers and small integers in a single word. Treating such a type as structured is then completely pointless.) 2. I agree with Jorge's conclusions about the cost of allocation, but I think there is another important point. A stack allocated record will almost certainly reside in an already cached location that is likely to be reused once the record is no longer needed. A heap allocated structure will almost certainly result in a cache miss, and the resulting cache line is unlikely to get reused immediately. Thus, with less than a 1 MB or so cache (and assuming something other than reference counting as the primary GC mechanism), it seems likely that you will lose up to one order of magnitude in performance simply as a result of cache misses, even with a hypothetical perfect garbage collector. (Reference counting has diffferent, but comparable problems). Hans ======================================================================= 50 === Date: 21 May 92 19:01:18 GMT From: n8243274@henson.cc.wwu.edu (S. Lee ODEGARD) Subject: proposal to map runtime errors into exceptions explicitely Explicit Exception Mapping There has been some argument of whether exceeding range bounds, a NARROW failure, deferenciation of NIL, or other runtime error should be explicitely mapped into exceptions or left to just cause an orderly halt of the computation. Where these are mapped into trappable exceptions, then the exception must be implicitely included in the raises list of all procedures in the language. I have a different proposal that permits the same functionality and is slightly more expressive without the implicit raises and the thorny question of whether these implicit exceptions should be caught by TRY EXCEPT ELSE. The _Extension_ ( see article same author ) [* FAIL exception *] may precede any expression. It is to signal that any of the mentioned runtime difficulties that may be encountered when evaluating that expression are, instead of halting the computation, to raise the exception /exception/. As with any portable extension, this is implemented in the unextended language via a translation schema. Here is an example from my own work: PROCEDURE Iproc ( P : Param ; <* UNUSED *> VAR S : Stack ) RAISES { Incomp } (* COVERS Interp *) = BEGIN ( [* FAIL Incomp( Tib{ Es.Param, Et.Match } ) *] NARROW( P, REF Tproc ) )^() END Iproc ; The extension [* FAIL *] precedes the NARROW expression and signals that the failure of NARROW raises the exception /Incomp/. The parenthesis indicate that I do not wish to handle the possible deferentiation of NIL in that manner. The translation into the functionally equivalent unextended language reads: PROCEDURE Iproc ( P : Param ; <* UNUSED *> VAR S : Stack ) RAISES { Incomp } (* COVERS Interp *) = (* interpreter for parameterless procedures *) BEGIN (* [] FAIL *) IF NOT ISTYPE( P, REF Tproc ) THEN RAISE Incomp( Tib{ Es.Param, Et.Match } ) END ; ( (* [*] FAIL Incomp( Tib{ Es.Param, Et.Match } *) NARROW( P, REF Tproc ) )^() END Iproc ; --S. Lee ODEGARD 13722 Aurora Ave N Seattle, WA 98133-6913 USA ======================================================================= 51 === Date: 21 May 1992 19:06:43 GMT From: jfarrell@jf.Eng.Sun.COM (Jerry Farrell) Subject: Safety of threads I've looked at the discussions of the various thread facilities in Ch. 2 - 5 of SPwM3, and can't find explicit statements that certain errors are checked. For instance, on p.70, Join's error is called out explicitly as checked, but Release's is not. In fact, the note on the REQUIRES clause on p. 123 can be read to mean that the error *need not* be checked: [After the specification of Release, which contains REQUIRES holder[m] = CURRENT] A REQUIRES clause states a precondition the implementation may rely on; the caller must ensure that the condition holds.... The specification does not constrain the implementation to any particular behavior if the precondition is not satisfied. I don't really believe the conclusion this leads toward -- I don't think Releasing a mutex makes a module unsafe. Maybe the manual needs to be tightened up? Or am I missing something staring me in the face? ======================================================================= 52 === Date: Thu, 21 May 92 19:16:31 PDT From: muller@src.dec.com (Eric Muller) Subject: help with RECORD layout The algorithm currently used in the SRC Modula-3 compiler to determine the layout of RECORD seems to be broken. This is no big surprise, as the problem is difficult. We would like to fix that, but we need to find the right algorithm to use. Below is a program that reports the size of various structures. This will certainly not capture all the details we will eventually need, but looking at the numbers it produces, we should have a better idea of what to do next. I would be grateful if you could run this program on as many machines, using as many different C compilers as you can find. It does not matter if SRC Modula-3 does not run on those machines or with those compilers. When you send me the result, please be as specific as you can about the machine, operating system and compiler origin and version. Thanks for your help, Eric (muller@src.dec.com) /* struct: Find about structure layout in C */ /* version 1 */ /* Last modified on Thu May 21 19:16:21 PDT 1992 by muller */ /*---------------------------------------------------------- size of char ---*/ void bits_per_byte () { char c; int b; c = 1; b = 0; do { c = c << 1; b++; } while (c != 0); printf ("\nBITS PER BYTE = %d\n", b); } /*------------------------------------------------------------ alignments ---*/ typedef int function (); #define alignment(TYPE) \ ((long)((char *)&((struct{char c; TYPE d;}*)0)->d - (char *)0)) void alignments () { printf ("\nALIGNMENTS\n"); printf ("char=%ld short=%ld int=%ld long=%ld\n", alignment(char), alignment(short), alignment(int), alignment(long)); printf ("float=%ld double=%ld\n", alignment(float), alignment(double)); printf ("char*=%ld int*=%ld func*=%ld\n", alignment(char *), alignment(int *), alignment(function *)); } /*----------------------------------------------------------- bit fields ---*/ #define SZ(x) sizeof(x) #ifdef ZERO_SIZE_OK typedef struct {int x: 0x00;} S0x00; #endif typedef struct {int x: 0x01;} S0x01; typedef struct {int x: 0x02;} S0x02; typedef struct {int x: 0x03;} S0x03; typedef struct {int x: 0x04;} S0x04; typedef struct {int x: 0x05;} S0x05; typedef struct {int x: 0x06;} S0x06; typedef struct {int x: 0x07;} S0x07; typedef struct {int x: 0x08;} S0x08; typedef struct {int x: 0x09;} S0x09; typedef struct {int x: 0x0a;} S0x0a; typedef struct {int x: 0x0b;} S0x0b; typedef struct {int x: 0x0c;} S0x0c; typedef struct {int x: 0x0d;} S0x0d; typedef struct {int x: 0x0e;} S0x0e; typedef struct {int x: 0x0f;} S0x0f; typedef struct {int x: 0x10;} S0x10; typedef struct {int x: 0x11;} S0x11; typedef struct {int x: 0x12;} S0x12; typedef struct {int x: 0x13;} S0x13; typedef struct {int x: 0x14;} S0x14; typedef struct {int x: 0x15;} S0x15; typedef struct {int x: 0x16;} S0x16; typedef struct {int x: 0x17;} S0x17; typedef struct {int x: 0x18;} S0x18; typedef struct {int x: 0x19;} S0x19; typedef struct {int x: 0x1a;} S0x1a; typedef struct {int x: 0x1b;} S0x1b; typedef struct {int x: 0x1c;} S0x1c; typedef struct {int x: 0x1d;} S0x1d; typedef struct {int x: 0x1e;} S0x1e; typedef struct {int x: 0x1f;} S0x1f; typedef struct {int x: 0x20;} S0x20; #ifdef ZERO_SIZE_OK typedef struct {char a; int x: 0x00;} Sc0x00; #endif typedef struct {char a; int x: 0x01;} Sc0x01; typedef struct {char a; int x: 0x02;} Sc0x02; typedef struct {char a; int x: 0x03;} Sc0x03; typedef struct {char a; int x: 0x04;} Sc0x04; typedef struct {char a; int x: 0x05;} Sc0x05; typedef struct {char a; int x: 0x06;} Sc0x06; typedef struct {char a; int x: 0x07;} Sc0x07; typedef struct {char a; int x: 0x08;} Sc0x08; typedef struct {char a; int x: 0x09;} Sc0x09; typedef struct {char a; int x: 0x0a;} Sc0x0a; typedef struct {char a; int x: 0x0b;} Sc0x0b; typedef struct {char a; int x: 0x0c;} Sc0x0c; typedef struct {char a; int x: 0x0d;} Sc0x0d; typedef struct {char a; int x: 0x0e;} Sc0x0e; typedef struct {char a; int x: 0x0f;} Sc0x0f; typedef struct {char a; int x: 0x10;} Sc0x10; typedef struct {char a; int x: 0x11;} Sc0x11; typedef struct {char a; int x: 0x12;} Sc0x12; typedef struct {char a; int x: 0x13;} Sc0x13; typedef struct {char a; int x: 0x14;} Sc0x14; typedef struct {char a; int x: 0x15;} Sc0x15; typedef struct {char a; int x: 0x16;} Sc0x16; typedef struct {char a; int x: 0x17;} Sc0x17; typedef struct {char a; int x: 0x18;} Sc0x18; typedef struct {char a; int x: 0x19;} Sc0x19; typedef struct {char a; int x: 0x1a;} Sc0x1a; typedef struct {char a; int x: 0x1b;} Sc0x1b; typedef struct {char a; int x: 0x1c;} Sc0x1c; typedef struct {char a; int x: 0x1d;} Sc0x1d; typedef struct {char a; int x: 0x1e;} Sc0x1e; typedef struct {char a; int x: 0x1f;} Sc0x1f; typedef struct {char a; int x: 0x20;} Sc0x20; #ifdef ZERO_SIZE_OK typedef struct {short a; int x: 0x00;} Ss0x00; #endif typedef struct {short a; int x: 0x01;} Ss0x01; typedef struct {short a; int x: 0x02;} Ss0x02; typedef struct {short a; int x: 0x03;} Ss0x03; typedef struct {short a; int x: 0x04;} Ss0x04; typedef struct {short a; int x: 0x05;} Ss0x05; typedef struct {short a; int x: 0x06;} Ss0x06; typedef struct {short a; int x: 0x07;} Ss0x07; typedef struct {short a; int x: 0x08;} Ss0x08; typedef struct {short a; int x: 0x09;} Ss0x09; typedef struct {short a; int x: 0x0a;} Ss0x0a; typedef struct {short a; int x: 0x0b;} Ss0x0b; typedef struct {short a; int x: 0x0c;} Ss0x0c; typedef struct {short a; int x: 0x0d;} Ss0x0d; typedef struct {short a; int x: 0x0e;} Ss0x0e; typedef struct {short a; int x: 0x0f;} Ss0x0f; typedef struct {short a; int x: 0x10;} Ss0x10; typedef struct {short a; int x: 0x11;} Ss0x11; typedef struct {short a; int x: 0x12;} Ss0x12; typedef struct {short a; int x: 0x13;} Ss0x13; typedef struct {short a; int x: 0x14;} Ss0x14; typedef struct {short a; int x: 0x15;} Ss0x15; typedef struct {short a; int x: 0x16;} Ss0x16; typedef struct {short a; int x: 0x17;} Ss0x17; typedef struct {short a; int x: 0x18;} Ss0x18; typedef struct {short a; int x: 0x19;} Ss0x19; typedef struct {short a; int x: 0x1a;} Ss0x1a; typedef struct {short a; int x: 0x1b;} Ss0x1b; typedef struct {short a; int x: 0x1c;} Ss0x1c; typedef struct {short a; int x: 0x1d;} Ss0x1d; typedef struct {short a; int x: 0x1e;} Ss0x1e; typedef struct {short a; int x: 0x1f;} Ss0x1f; typedef struct {short a; int x: 0x20;} Ss0x20; #ifdef ZERO_SIZE_OK typedef struct {int a; int x: 0x00;} Si0x00; #endif typedef struct {int a; int x: 0x01;} Si0x01; typedef struct {int a; int x: 0x02;} Si0x02; typedef struct {int a; int x: 0x03;} Si0x03; typedef struct {int a; int x: 0x04;} Si0x04; typedef struct {int a; int x: 0x05;} Si0x05; typedef struct {int a; int x: 0x06;} Si0x06; typedef struct {int a; int x: 0x07;} Si0x07; typedef struct {int a; int x: 0x08;} Si0x08; typedef struct {int a; int x: 0x09;} Si0x09; typedef struct {int a; int x: 0x0a;} Si0x0a; typedef struct {int a; int x: 0x0b;} Si0x0b; typedef struct {int a; int x: 0x0c;} Si0x0c; typedef struct {int a; int x: 0x0d;} Si0x0d; typedef struct {int a; int x: 0x0e;} Si0x0e; typedef struct {int a; int x: 0x0f;} Si0x0f; typedef struct {int a; int x: 0x10;} Si0x10; typedef struct {int a; int x: 0x11;} Si0x11; typedef struct {int a; int x: 0x12;} Si0x12; typedef struct {int a; int x: 0x13;} Si0x13; typedef struct {int a; int x: 0x14;} Si0x14; typedef struct {int a; int x: 0x15;} Si0x15; typedef struct {int a; int x: 0x16;} Si0x16; typedef struct {int a; int x: 0x17;} Si0x17; typedef struct {int a; int x: 0x18;} Si0x18; typedef struct {int a; int x: 0x19;} Si0x19; typedef struct {int a; int x: 0x1a;} Si0x1a; typedef struct {int a; int x: 0x1b;} Si0x1b; typedef struct {int a; int x: 0x1c;} Si0x1c; typedef struct {int a; int x: 0x1d;} Si0x1d; typedef struct {int a; int x: 0x1e;} Si0x1e; typedef struct {int a; int x: 0x1f;} Si0x1f; typedef struct {int a; int x: 0x20;} Si0x20; #ifdef ZERO_SIZE_OK typedef struct {long a; int x: 0x00;} Sl0x00; #endif typedef struct {long a; int x: 0x01;} Sl0x01; typedef struct {long a; int x: 0x02;} Sl0x02; typedef struct {long a; int x: 0x03;} Sl0x03; typedef struct {long a; int x: 0x04;} Sl0x04; typedef struct {long a; int x: 0x05;} Sl0x05; typedef struct {long a; int x: 0x06;} Sl0x06; typedef struct {long a; int x: 0x07;} Sl0x07; typedef struct {long a; int x: 0x08;} Sl0x08; typedef struct {long a; int x: 0x09;} Sl0x09; typedef struct {long a; int x: 0x0a;} Sl0x0a; typedef struct {long a; int x: 0x0b;} Sl0x0b; typedef struct {long a; int x: 0x0c;} Sl0x0c; typedef struct {long a; int x: 0x0d;} Sl0x0d; typedef struct {long a; int x: 0x0e;} Sl0x0e; typedef struct {long a; int x: 0x0f;} Sl0x0f; typedef struct {long a; int x: 0x10;} Sl0x10; typedef struct {long a; int x: 0x11;} Sl0x11; typedef struct {long a; int x: 0x12;} Sl0x12; typedef struct {long a; int x: 0x13;} Sl0x13; typedef struct {long a; int x: 0x14;} Sl0x14; typedef struct {long a; int x: 0x15;} Sl0x15; typedef struct {long a; int x: 0x16;} Sl0x16; typedef struct {long a; int x: 0x17;} Sl0x17; typedef struct {long a; int x: 0x18;} Sl0x18; typedef struct {long a; int x: 0x19;} Sl0x19; typedef struct {long a; int x: 0x1a;} Sl0x1a; typedef struct {long a; int x: 0x1b;} Sl0x1b; typedef struct {long a; int x: 0x1c;} Sl0x1c; typedef struct {long a; int x: 0x1d;} Sl0x1d; typedef struct {long a; int x: 0x1e;} Sl0x1e; typedef struct {long a; int x: 0x1f;} Sl0x1f; typedef struct {long a; int x: 0x20;} Sl0x20; #ifdef ZERO_SIZE_OK typedef struct {char a; int x: 0x00; char c;} Sc0x00c; #endif typedef struct {char a; int x: 0x01; char c;} Sc0x01c; typedef struct {char a; int x: 0x02; char c;} Sc0x02c; typedef struct {char a; int x: 0x03; char c;} Sc0x03c; typedef struct {char a; int x: 0x04; char c;} Sc0x04c; typedef struct {char a; int x: 0x05; char c;} Sc0x05c; typedef struct {char a; int x: 0x06; char c;} Sc0x06c; typedef struct {char a; int x: 0x07; char c;} Sc0x07c; typedef struct {char a; int x: 0x08; char c;} Sc0x08c; typedef struct {char a; int x: 0x09; char c;} Sc0x09c; typedef struct {char a; int x: 0x0a; char c;} Sc0x0ac; typedef struct {char a; int x: 0x0b; char c;} Sc0x0bc; typedef struct {char a; int x: 0x0c; char c;} Sc0x0cc; typedef struct {char a; int x: 0x0d; char c;} Sc0x0dc; typedef struct {char a; int x: 0x0e; char c;} Sc0x0ec; typedef struct {char a; int x: 0x0f; char c;} Sc0x0fc; typedef struct {char a; int x: 0x10; char c;} Sc0x10c; typedef struct {char a; int x: 0x11; char c;} Sc0x11c; typedef struct {char a; int x: 0x12; char c;} Sc0x12c; typedef struct {char a; int x: 0x13; char c;} Sc0x13c; typedef struct {char a; int x: 0x14; char c;} Sc0x14c; typedef struct {char a; int x: 0x15; char c;} Sc0x15c; typedef struct {char a; int x: 0x16; char c;} Sc0x16c; typedef struct {char a; int x: 0x17; char c;} Sc0x17c; typedef struct {char a; int x: 0x18; char c;} Sc0x18c; typedef struct {char a; int x: 0x19; char c;} Sc0x19c; typedef struct {char a; int x: 0x1a; char c;} Sc0x1ac; typedef struct {char a; int x: 0x1b; char c;} Sc0x1bc; typedef struct {char a; int x: 0x1c; char c;} Sc0x1cc; typedef struct {char a; int x: 0x1d; char c;} Sc0x1dc; typedef struct {char a; int x: 0x1e; char c;} Sc0x1ec; typedef struct {char a; int x: 0x1f; char c;} Sc0x1fc; typedef struct {char a; int x: 0x20; char c;} Sc0x20c; #ifdef ZERO_SIZE_OK typedef struct {char a; int x: 0x00; short c;} Sc0x00s; #endif typedef struct {char a; int x: 0x01; short c;} Sc0x01s; typedef struct {char a; int x: 0x02; short c;} Sc0x02s; typedef struct {char a; int x: 0x03; short c;} Sc0x03s; typedef struct {char a; int x: 0x04; short c;} Sc0x04s; typedef struct {char a; int x: 0x05; short c;} Sc0x05s; typedef struct {char a; int x: 0x06; short c;} Sc0x06s; typedef struct {char a; int x: 0x07; short c;} Sc0x07s; typedef struct {char a; int x: 0x08; short c;} Sc0x08s; typedef struct {char a; int x: 0x09; short c;} Sc0x09s; typedef struct {char a; int x: 0x0a; short c;} Sc0x0as; typedef struct {char a; int x: 0x0b; short c;} Sc0x0bs; typedef struct {char a; int x: 0x0c; short c;} Sc0x0cs; typedef struct {char a; int x: 0x0d; short c;} Sc0x0ds; typedef struct {char a; int x: 0x0e; short c;} Sc0x0es; typedef struct {char a; int x: 0x0f; short c;} Sc0x0fs; typedef struct {char a; int x: 0x10; short c;} Sc0x10s; typedef struct {char a; int x: 0x11; short c;} Sc0x11s; typedef struct {char a; int x: 0x12; short c;} Sc0x12s; typedef struct {char a; int x: 0x13; short c;} Sc0x13s; typedef struct {char a; int x: 0x14; short c;} Sc0x14s; typedef struct {char a; int x: 0x15; short c;} Sc0x15s; typedef struct {char a; int x: 0x16; short c;} Sc0x16s; typedef struct {char a; int x: 0x17; short c;} Sc0x17s; typedef struct {char a; int x: 0x18; short c;} Sc0x18s; typedef struct {char a; int x: 0x19; short c;} Sc0x19s; typedef struct {char a; int x: 0x1a; short c;} Sc0x1as; typedef struct {char a; int x: 0x1b; short c;} Sc0x1bs; typedef struct {char a; int x: 0x1c; short c;} Sc0x1cs; typedef struct {char a; int x: 0x1d; short c;} Sc0x1ds; typedef struct {char a; int x: 0x1e; short c;} Sc0x1es; typedef struct {char a; int x: 0x1f; short c;} Sc0x1fs; typedef struct {char a; int x: 0x20; short c;} Sc0x20s; #ifdef ZERO_SIZE_OK typedef struct {char a; int x: 0x00; int c: 0x00;} Sc0x000x00; #endif typedef struct {char a; int x: 0x01; int c: 0x01;} Sc0x010x01; typedef struct {char a; int x: 0x02; int c: 0x02;} Sc0x020x02; typedef struct {char a; int x: 0x03; int c: 0x03;} Sc0x030x03; typedef struct {char a; int x: 0x04; int c: 0x04;} Sc0x040x04; typedef struct {char a; int x: 0x05; int c: 0x05;} Sc0x050x05; typedef struct {char a; int x: 0x06; int c: 0x06;} Sc0x060x06; typedef struct {char a; int x: 0x07; int c: 0x07;} Sc0x070x07; typedef struct {char a; int x: 0x08; int c: 0x08;} Sc0x080x08; typedef struct {char a; int x: 0x09; int c: 0x09;} Sc0x090x09; typedef struct {char a; int x: 0x0a; int c: 0x0a;} Sc0x0a0x0a; typedef struct {char a; int x: 0x0b; int c: 0x0b;} Sc0x0b0x0b; typedef struct {char a; int x: 0x0c; int c: 0x0c;} Sc0x0c0x0c; typedef struct {char a; int x: 0x0d; int c: 0x0d;} Sc0x0d0x0d; typedef struct {char a; int x: 0x0e; int c: 0x0e;} Sc0x0e0x0e; typedef struct {char a; int x: 0x0f; int c: 0x0f;} Sc0x0f0x0f; typedef struct {char a; int x: 0x10; int c: 0x10;} Sc0x100x10; typedef struct {char a; int x: 0x11; int c: 0x11;} Sc0x110x11; typedef struct {char a; int x: 0x12; int c: 0x12;} Sc0x120x12; typedef struct {char a; int x: 0x13; int c: 0x13;} Sc0x130x13; typedef struct {char a; int x: 0x14; int c: 0x14;} Sc0x140x14; typedef struct {char a; int x: 0x15; int c: 0x15;} Sc0x150x15; typedef struct {char a; int x: 0x16; int c: 0x16;} Sc0x160x16; typedef struct {char a; int x: 0x17; int c: 0x17;} Sc0x170x17; typedef struct {char a; int x: 0x18; int c: 0x18;} Sc0x180x18; typedef struct {char a; int x: 0x19; int c: 0x19;} Sc0x190x19; typedef struct {char a; int x: 0x1a; int c: 0x1a;} Sc0x1a0x1a; typedef struct {char a; int x: 0x1b; int c: 0x1b;} Sc0x1b0x1b; typedef struct {char a; int x: 0x1c; int c: 0x1c;} Sc0x1c0x1c; typedef struct {char a; int x: 0x1d; int c: 0x1d;} Sc0x1d0x1d; typedef struct {char a; int x: 0x1e; int c: 0x1e;} Sc0x1e0x1e; typedef struct {char a; int x: 0x1f; int c: 0x1f;} Sc0x1f0x1f; typedef struct {char a; int x: 0x20; int c: 0x20;} Sc0x200x20; #ifdef ZERO_SIZE_OK typedef struct {char a; int x: 0x00; int c: 0x00; char z;} Sc0x000x00c; #endif typedef struct {char a; int x: 0x01; int c: 0x01; char z;} Sc0x010x01c; typedef struct {char a; int x: 0x02; int c: 0x02; char z;} Sc0x020x02c; typedef struct {char a; int x: 0x03; int c: 0x03; char z;} Sc0x030x03c; typedef struct {char a; int x: 0x04; int c: 0x04; char z;} Sc0x040x04c; typedef struct {char a; int x: 0x05; int c: 0x05; char z;} Sc0x050x05c; typedef struct {char a; int x: 0x06; int c: 0x06; char z;} Sc0x060x06c; typedef struct {char a; int x: 0x07; int c: 0x07; char z;} Sc0x070x07c; typedef struct {char a; int x: 0x08; int c: 0x08; char z;} Sc0x080x08c; typedef struct {char a; int x: 0x09; int c: 0x09; char z;} Sc0x090x09c; typedef struct {char a; int x: 0x0a; int c: 0x0a; char z;} Sc0x0a0x0ac; typedef struct {char a; int x: 0x0b; int c: 0x0b; char z;} Sc0x0b0x0bc; typedef struct {char a; int x: 0x0c; int c: 0x0c; char z;} Sc0x0c0x0cc; typedef struct {char a; int x: 0x0d; int c: 0x0d; char z;} Sc0x0d0x0dc; typedef struct {char a; int x: 0x0e; int c: 0x0e; char z;} Sc0x0e0x0ec; typedef struct {char a; int x: 0x0f; int c: 0x0f; char z;} Sc0x0f0x0fc; typedef struct {char a; int x: 0x10; int c: 0x10; char z;} Sc0x100x10c; typedef struct {char a; int x: 0x11; int c: 0x11; char z;} Sc0x110x11c; typedef struct {char a; int x: 0x12; int c: 0x12; char z;} Sc0x120x12c; typedef struct {char a; int x: 0x13; int c: 0x13; char z;} Sc0x130x13c; typedef struct {char a; int x: 0x14; int c: 0x14; char z;} Sc0x140x14c; typedef struct {char a; int x: 0x15; int c: 0x15; char z;} Sc0x150x15c; typedef struct {char a; int x: 0x16; int c: 0x16; char z;} Sc0x160x16c; typedef struct {char a; int x: 0x17; int c: 0x17; char z;} Sc0x170x17c; typedef struct {char a; int x: 0x18; int c: 0x18; char z;} Sc0x180x18c; typedef struct {char a; int x: 0x19; int c: 0x19; char z;} Sc0x190x19c; typedef struct {char a; int x: 0x1a; int c: 0x1a; char z;} Sc0x1a0x1ac; typedef struct {char a; int x: 0x1b; int c: 0x1b; char z;} Sc0x1b0x1bc; typedef struct {char a; int x: 0x1c; int c: 0x1c; char z;} Sc0x1c0x1cc; typedef struct {char a; int x: 0x1d; int c: 0x1d; char z;} Sc0x1d0x1dc; typedef struct {char a; int x: 0x1e; int c: 0x1e; char z;} Sc0x1e0x1ec; typedef struct {char a; int x: 0x1f; int c: 0x1f; char z;} Sc0x1f0x1fc; typedef struct {char a; int x: 0x20; int c: 0x20; char z;} Sc0x200x20c; #ifdef ZERO_SIZE_OK typedef struct {char a; int x: 0x00; int c: 0x01; short z;} Sc0x000x00s; #endif typedef struct {char a; int x: 0x01; int c: 0x01; short z;} Sc0x010x01s; typedef struct {char a; int x: 0x02; int c: 0x02; short z;} Sc0x020x02s; typedef struct {char a; int x: 0x03; int c: 0x03; short z;} Sc0x030x03s; typedef struct {char a; int x: 0x04; int c: 0x04; short z;} Sc0x040x04s; typedef struct {char a; int x: 0x05; int c: 0x05; short z;} Sc0x050x05s; typedef struct {char a; int x: 0x06; int c: 0x06; short z;} Sc0x060x06s; typedef struct {char a; int x: 0x07; int c: 0x07; short z;} Sc0x070x07s; typedef struct {char a; int x: 0x08; int c: 0x08; short z;} Sc0x080x08s; typedef struct {char a; int x: 0x09; int c: 0x09; short z;} Sc0x090x09s; typedef struct {char a; int x: 0x0a; int c: 0x0a; short z;} Sc0x0a0x0as; typedef struct {char a; int x: 0x0b; int c: 0x0b; short z;} Sc0x0b0x0bs; typedef struct {char a; int x: 0x0c; int c: 0x0c; short z;} Sc0x0c0x0cs; typedef struct {char a; int x: 0x0d; int c: 0x0d; short z;} Sc0x0d0x0ds; typedef struct {char a; int x: 0x0e; int c: 0x0e; short z;} Sc0x0e0x0es; typedef struct {char a; int x: 0x0f; int c: 0x0f; short z;} Sc0x0f0x0fs; typedef struct {char a; int x: 0x10; int c: 0x10; short z;} Sc0x100x10s; typedef struct {char a; int x: 0x11; int c: 0x11; short z;} Sc0x110x11s; typedef struct {char a; int x: 0x12; int c: 0x12; short z;} Sc0x120x12s; typedef struct {char a; int x: 0x13; int c: 0x13; short z;} Sc0x130x13s; typedef struct {char a; int x: 0x14; int c: 0x14; short z;} Sc0x140x14s; typedef struct {char a; int x: 0x15; int c: 0x15; short z;} Sc0x150x15s; typedef struct {char a; int x: 0x16; int c: 0x16; short z;} Sc0x160x16s; typedef struct {char a; int x: 0x17; int c: 0x17; short z;} Sc0x170x17s; typedef struct {char a; int x: 0x18; int c: 0x18; short z;} Sc0x180x18s; typedef struct {char a; int x: 0x19; int c: 0x19; short z;} Sc0x190x19s; typedef struct {char a; int x: 0x1a; int c: 0x1a; short z;} Sc0x1a0x1as; typedef struct {char a; int x: 0x1b; int c: 0x1b; short z;} Sc0x1b0x1bs; typedef struct {char a; int x: 0x1c; int c: 0x1c; short z;} Sc0x1c0x1cs; typedef struct {char a; int x: 0x1d; int c: 0x1d; short z;} Sc0x1d0x1ds; typedef struct {char a; int x: 0x1e; int c: 0x1e; short z;} Sc0x1e0x1es; typedef struct {char a; int x: 0x1f; int c: 0x1f; short z;} Sc0x1f0x1fs; typedef struct {char a; int x: 0x20; int c: 0x20; short z;} Sc0x200x20s; void bitfields () { printf ("\nSIZES OF STRUCT; _ is a bitfield\n"); printf (" _ c_ s_ i_ l_\n"); #ifdef ZERO_SIZE_OK printf ("0x00 %5d %5d %5d %5d %5d\n", SZ (S0x00), SZ (Sc0x00), SZ (Ss0x00), S Z (Si0x00), SZ (Sl0x00)); #endif printf ("0x01 %5d %5d %5d %5d %5d\n", SZ (S0x01), SZ (Sc0x01), SZ (Ss0x01), S Z (Si0x01), SZ (Sl0x01)); printf ("0x02 %5d %5d %5d %5d %5d\n", SZ (S0x02), SZ (Sc0x02), SZ (Ss0x02), S Z (Si0x02), SZ (Sl0x02)); printf ("0x03 %5d %5d %5d %5d %5d\n", SZ (S0x03), SZ (Sc0x03), SZ (Ss0x03), S Z (Si0x03), SZ (Sl0x03)); printf ("0x04 %5d %5d %5d %5d %5d\n", SZ (S0x04), SZ (Sc0x04), SZ (Ss0x04), S Z (Si0x04), SZ (Sl0x04)); printf ("0x05 %5d %5d %5d %5d %5d\n", SZ (S0x05), SZ (Sc0x05), SZ (Ss0x05), S Z (Si0x05), SZ (Sl0x05)); printf ("0x06 %5d %5d %5d %5d %5d\n", SZ (S0x06), SZ (Sc0x06), SZ (Ss0x06), S Z (Si0x06), SZ (Sl0x06)); printf ("0x07 %5d %5d %5d %5d %5d\n", SZ (S0x07), SZ (Sc0x07), SZ (Ss0x07), S Z (Si0x07), SZ (Sl0x07)); printf ("0x08 %5d %5d %5d %5d %5d\n", SZ (S0x08), SZ (Sc0x08), SZ (Ss0x08), S Z (Si0x08), SZ (Sl0x08)); printf ("0x09 %5d %5d %5d %5d %5d\n", SZ (S0x09), SZ (Sc0x09), SZ (Ss0x09), S Z (Si0x09), SZ (Sl0x09)); printf ("0x0a %5d %5d %5d %5d %5d\n", SZ (S0x0a), SZ (Sc0x0a), SZ (Ss0x0a), S Z (Si0x0a), SZ (Sl0x0a)); printf ("0x0b %5d %5d %5d %5d %5d\n", SZ (S0x0b), SZ (Sc0x0b), SZ (Ss0x0b), S Z (Si0x0b), SZ (Sl0x0b)); printf ("0x0c %5d %5d %5d %5d %5d\n", SZ (S0x0c), SZ (Sc0x0c), SZ (Ss0x0c), S Z (Si0x0c), SZ (Sl0x0c)); printf ("0x0d %5d %5d %5d %5d %5d\n", SZ (S0x0d), SZ (Sc0x0d), SZ (Ss0x0d), S Z (Si0x0d), SZ (Sl0x0d)); printf ("0x0e %5d %5d %5d %5d %5d\n", SZ (S0x0e), SZ (Sc0x0e), SZ (Ss0x0e), S Z (Si0x0e), SZ (Sl0x0e)); printf ("0x0f %5d %5d %5d %5d %5d\n", SZ (S0x0f), SZ (Sc0x0f), SZ (Ss0x0f), S Z (Si0x0f), SZ (Sl0x0f)); printf ("0x10 %5d %5d %5d %5d %5d\n", SZ (S0x10), SZ (Sc0x10), SZ (Ss0x10), S Z (Si0x10), SZ (Sl0x10)); printf ("0x11 %5d %5d %5d %5d %5d\n", SZ (S0x11), SZ (Sc0x11), SZ (Ss0x11), S Z (Si0x11), SZ (Sl0x11)); printf ("0x12 %5d %5d %5d %5d %5d\n", SZ (S0x12), SZ (Sc0x12), SZ (Ss0x12), S Z (Si0x12), SZ (Sl0x12)); printf ("0x13 %5d %5d %5d %5d %5d\n", SZ (S0x13), SZ (Sc0x13), SZ (Ss0x13), S Z (Si0x13), SZ (Sl0x13)); printf ("0x14 %5d %5d %5d %5d %5d\n", SZ (S0x14), SZ (Sc0x14), SZ (Ss0x14), S Z (Si0x14), SZ (Sl0x14)); printf ("0x15 %5d %5d %5d %5d %5d\n", SZ (S0x15), SZ (Sc0x15), SZ (Ss0x15), S Z (Si0x15), SZ (Sl0x15)); printf ("0x16 %5d %5d %5d %5d %5d\n", SZ (S0x16), SZ (Sc0x16), SZ (Ss0x16), S Z (Si0x16), SZ (Sl0x16)); printf ("0x17 %5d %5d %5d %5d %5d\n", SZ (S0x17), SZ (Sc0x17), SZ (Ss0x17), S Z (Si0x17), SZ (Sl0x17)); printf ("0x18 %5d %5d %5d %5d %5d\n", SZ (S0x18), SZ (Sc0x18), SZ (Ss0x18), S Z (Si0x18), SZ (Sl0x18)); printf ("0x19 %5d %5d %5d %5d %5d\n", SZ (S0x19), SZ (Sc0x19), SZ (Ss0x19), S Z (Si0x19), SZ (Sl0x19)); printf ("0x1a %5d %5d %5d %5d %5d\n", SZ (S0x1a), SZ (Sc0x1a), SZ (Ss0x1a), S Z (Si0x1a), SZ (Sl0x1a)); printf ("0x1b %5d %5d %5d %5d %5d\n", SZ (S0x1b), SZ (Sc0x1b), SZ (Ss0x1b), S Z (Si0x1b), SZ (Sl0x1b)); printf ("0x1c %5d %5d %5d %5d %5d\n", SZ (S0x1c), SZ (Sc0x1c), SZ (Ss0x1c), S Z (Si0x1c), SZ (Sl0x1c)); printf ("0x1d %5d %5d %5d %5d %5d\n", SZ (S0x1d), SZ (Sc0x1d), SZ (Ss0x1d), S Z (Si0x1d), SZ (Sl0x1d)); printf ("0x1e %5d %5d %5d %5d %5d\n", SZ (S0x1e), SZ (Sc0x1e), SZ (Ss0x1e), S Z (Si0x1e), SZ (Sl0x1e)); printf ("0x1f %5d %5d %5d %5d %5d\n", SZ (S0x1f), SZ (Sc0x1f), SZ (Ss0x1f), S Z (Si0x1f), SZ (Sl0x1f)); printf ("0x20 %5d %5d %5d %5d %5d\n", SZ (S0x20), SZ (Sc0x20), SZ (Ss0x20), S Z (Si0x20), SZ (Sl0x20)); printf ("\n c_c c__ c__c c_s c__s\n"); #ifdef ZERO_SIZE_OK printf ("0x00 %5d %5d %5d %5d %5d\n", SZ (Sc0x00c), SZ (Sc0x000x00), SZ (Sc0x 000x00c), SZ (Sc0x00s), SZ (Sc0x000x00s)); #endif printf ("0x01 %5d %5d %5d %5d %5d\n", SZ (Sc0x01c), SZ (Sc0x010x01), SZ (Sc0x 010x01c), SZ (Sc0x01s), SZ (Sc0x010x01s)); printf ("0x02 %5d %5d %5d %5d %5d\n", SZ (Sc0x02c), SZ (Sc0x020x02), SZ (Sc0x 020x02c), SZ (Sc0x02s), SZ (Sc0x020x02s)); printf ("0x03 %5d %5d %5d %5d %5d\n", SZ (Sc0x03c), SZ (Sc0x030x03), SZ (Sc0x 030x03c), SZ (Sc0x03s), SZ (Sc0x030x03s)); printf ("0x04 %5d %5d %5d %5d %5d\n", SZ (Sc0x04c), SZ (Sc0x040x04), SZ (Sc0x 040x04c), SZ (Sc0x04s), SZ (Sc0x040x04s)); printf ("0x05 %5d %5d %5d %5d %5d\n", SZ (Sc0x05c), SZ (Sc0x050x05), SZ (Sc0x 050x05c), SZ (Sc0x05s), SZ (Sc0x050x05s)); printf ("0x06 %5d %5d %5d %5d %5d\n", SZ (Sc0x06c), SZ (Sc0x060x06), SZ (Sc0x 060x06c), SZ (Sc0x06s), SZ (Sc0x060x06s)); printf ("0x07 %5d %5d %5d %5d %5d\n", SZ (Sc0x07c), SZ (Sc0x070x07), SZ (Sc0x 070x07c), SZ (Sc0x07s), SZ (Sc0x070x07s)); printf ("0x08 %5d %5d %5d %5d %5d\n", SZ (Sc0x08c), SZ (Sc0x080x08), SZ (Sc0x 080x08c), SZ (Sc0x08s), SZ (Sc0x080x08s)); printf ("0x09 %5d %5d %5d %5d %5d\n", SZ (Sc0x09c), SZ (Sc0x090x09), SZ (Sc0x 090x09c), SZ (Sc0x09s), SZ (Sc0x090x09s)); printf ("0x0a %5d %5d %5d %5d %5d\n", SZ (Sc0x0ac), SZ (Sc0x0a0x0a), SZ (Sc0x 0a0x0ac), SZ (Sc0x0as), SZ (Sc0x0a0x0as)); printf ("0x0b %5d %5d %5d %5d %5d\n", SZ (Sc0x0bc), SZ (Sc0x0b0x0b), SZ (Sc0x 0b0x0bc), SZ (Sc0x0bs), SZ (Sc0x0b0x0bs)); printf ("0x0c %5d %5d %5d %5d %5d\n", SZ (Sc0x0cc), SZ (Sc0x0c0x0c), SZ (Sc0x 0c0x0cc), SZ (Sc0x0cs), SZ (Sc0x0c0x0cs)); printf ("0x0d %5d %5d %5d %5d %5d\n", SZ (Sc0x0dc), SZ (Sc0x0d0x0d), SZ (Sc0x 0d0x0dc), SZ (Sc0x0ds), SZ (Sc0x0d0x0ds)); printf ("0x0e %5d %5d %5d %5d %5d\n", SZ (Sc0x0ec), SZ (Sc0x0e0x0e), SZ (Sc0x 0e0x0ec), SZ (Sc0x0es), SZ (Sc0x0e0x0es)); printf ("0x0f %5d %5d %5d %5d %5d\n", SZ (Sc0x0fc), SZ (Sc0x0f0x0f), SZ (Sc0x 0f0x0fc), SZ (Sc0x0fs), SZ (Sc0x0f0x0fs)); printf ("0x10 %5d %5d %5d %5d %5d\n", SZ (Sc0x10c), SZ (Sc0x100x10), SZ (Sc0x 100x10c), SZ (Sc0x10s), SZ (Sc0x100x10s)); printf ("0x11 %5d %5d %5d %5d %5d\n", SZ (Sc0x11c), SZ (Sc0x110x11), SZ (Sc0x 110x11c), SZ (Sc0x11s), SZ (Sc0x110x11s)); printf ("0x12 %5d %5d %5d %5d %5d\n", SZ (Sc0x12c), SZ (Sc0x120x12), SZ (Sc0x 120x12c), SZ (Sc0x12s), SZ (Sc0x120x12s)); printf ("0x13 %5d %5d %5d %5d %5d\n", SZ (Sc0x13c), SZ (Sc0x130x13), SZ (Sc0x 130x13c), SZ (Sc0x13s), SZ (Sc0x130x13s)); printf ("0x14 %5d %5d %5d %5d %5d\n", SZ (Sc0x14c), SZ (Sc0x140x14), SZ (Sc0x 140x14c), SZ (Sc0x14s), SZ (Sc0x140x14s)); printf ("0x15 %5d %5d %5d %5d %5d\n", SZ (Sc0x15c), SZ (Sc0x150x15), SZ (Sc0x 150x15c), SZ (Sc0x15s), SZ (Sc0x150x15s)); printf ("0x16 %5d %5d %5d %5d %5d\n", SZ (Sc0x16c), SZ (Sc0x160x16), SZ (Sc0x 160x16c), SZ (Sc0x16s), SZ (Sc0x160x16s)); printf ("0x17 %5d %5d %5d %5d %5d\n", SZ (Sc0x17c), SZ (Sc0x170x17), SZ (Sc0x 170x17c), SZ (Sc0x17s), SZ (Sc0x170x17s)); printf ("0x18 %5d %5d %5d %5d %5d\n", SZ (Sc0x18c), SZ (Sc0x180x18), SZ (Sc0x 180x18c), SZ (Sc0x18s), SZ (Sc0x180x18s)); printf ("0x19 %5d %5d %5d %5d %5d\n", SZ (Sc0x19c), SZ (Sc0x190x19), SZ (Sc0x 190x19c), SZ (Sc0x19s), SZ (Sc0x190x19s)); printf ("0x1a %5d %5d %5d %5d %5d\n", SZ (Sc0x1ac), SZ (Sc0x1a0x1a), SZ (Sc0x 1a0x1ac), SZ (Sc0x1as), SZ (Sc0x1a0x1as)); printf ("0x1b %5d %5d %5d %5d %5d\n", SZ (Sc0x1bc), SZ (Sc0x1b0x1b), SZ (Sc0x 1b0x1bc), SZ (Sc0x1bs), SZ (Sc0x1b0x1bs)); printf ("0x1c %5d %5d %5d %5d %5d\n", SZ (Sc0x1cc), SZ (Sc0x1c0x1c), SZ (Sc0x 1c0x1cc), SZ (Sc0x1cs), SZ (Sc0x1c0x1cs)); printf ("0x1d %5d %5d %5d %5d %5d\n", SZ (Sc0x1dc), SZ (Sc0x1d0x1d), SZ (Sc0x 1d0x1dc), SZ (Sc0x1ds), SZ (Sc0x1d0x1ds)); printf ("0x1e %5d %5d %5d %5d %5d\n", SZ (Sc0x1ec), SZ (Sc0x1e0x1e), SZ (Sc0x 1e0x1ec), SZ (Sc0x1es), SZ (Sc0x1e0x1es)); printf ("0x1f %5d %5d %5d %5d %5d\n", SZ (Sc0x1fc), SZ (Sc0x1f0x1f), SZ (Sc0x 1f0x1fc), SZ (Sc0x1fs), SZ (Sc0x1f0x1fs)); printf ("0x20 %5d %5d %5d %5d %5d\n", SZ (Sc0x20c), SZ (Sc0x200x20), SZ (Sc0x 200x20c), SZ (Sc0x20s), SZ (Sc0x200x20s)); } /*------------------------------------------------------------ structures ---*/ #define offset(TYPE,FIELD) \ ((long)((char *)&((TYPE*)0)->FIELD - (char *)0)) typedef struct {char a;} Schar; typedef struct {char a; char b;} Schar_char; typedef struct {char a; short b;} Schar_short; typedef struct {char a; int b;} Schar_int; typedef struct {char a; long b;} Schar_long; void structures () { printf ("\nSTRUCTURES\n"); printf ("Schar: size = %d, offset(a) = %d\n", sizeof (Schar), offset (Schar,a)); printf ("Schar_char: size = %d, offset(a) = %d, offset (b) = %d\n", sizeof (Schar_char), offset (Schar_char,a), offset (Schar_char,b)); printf ("Schar_short: size = %d, offset(a) = %d, offset (b) = %d\n", sizeof (Schar_short), offset (Schar_short,a), offset (Schar_short,b)) ; printf ("Schar_int: size = %d, offset(a) = %d, offset (b) = %d\n", sizeof (Schar_int), offset (Schar_int,a), offset (Schar_int,b)); printf ("Schar_long: size = %d, offset(a) = %d, offset (b) = %d\n", sizeof (Schar_long), offset (Schar_long,a), offset (Schar_long,b)); } main () { bits_per_byte (); alignments (); structures (); bitfields (); printf ("\nDONE.\n"); printf ("Please mail the result to muller@src.dec.com with a precise descript ion\n"); printf ("of the machine, operating system, and C compiler you used.\n"); printf ("Thanks a lot !\n"); } ======================================================================= 53 === Date: 22 May 92 18:27:51 GMT From: n8243274@gonzo.cc.wwu.edu (S. Lee ODEGARD) Subject: needed: required interface for mapping runtime errors to exceptions If the implementer chooses to map runtime errors to exceptions, then she would be required to include a standard interface, say Err, so that including Err.E in the raises clause of a procedure will handle runtime error exceptions in a way consistent across all implementations. The interface would specify the parameter that Err.E contains. Also, may I suggest that the implicit exception not be mapped to Err.E, but to an unnameable exception that can be trapped in the following manner: TRY ... code including procedure call that raises an exception ... that is not in its raises list -- the implicit exception EXCEPT NIL => Wr.PutText( Stdio.stdout, "Unhandled exception error encountered." & " Please report to author.\n" ) ; | Err.E( K ) => Err.Document( Stdio.stdout, K ) ; END ; Using NIL in this way does represent an extension to the language definition, but I feel it is an intuitive one. It is the exception that could be raised by a procedure with raises clause RAISES {} Further, the proposal is upwardly compatible with the language definition, and does not impact the language standard in any other way. Its implementation only would require the modification of the TRY-EXCEPT statement protocol. --S. Lee ODEGARD 13722 Aurora Ave N Seattle, WA 98133-6913 USA ======================================================================= 54 === Date: 23 May 92 09:38:37 GMT From: n8243274@henson.cc.wwu.edu (S. Lee ODEGARD) Subject: Q. Can I trap a terminal-entered interrupt as an exception? We have M3 on a DECstation running Ultrix 4.3. If I enter "^C" to the terminal during a process of long duration, the entire program halts. Can I trap ^C or some other interrupt as a Thread.Alerted or some other exception? ======================================================================= 55 === Date: 25 May 92 13:09:30 GMT From: deryck@dcs.glasgow.ac.uk (Deryck F Brown) Subject: Integer literals bug in SRC-2.06? The following program compiles without error (and prints the number 100!): MODULE Bug EXPORTS Main; IMPORT Wr, Stdio, Fmt; BEGIN Wr.PutText (Stdio.stdout, Fmt.Int (10_A0) & "\n") END Bug. According to Nelson, page 51: "Each digit must be less than base." Is this a deliberate departure from the definition or just an oversight? While I'm here (so to speak) has anyone tried to construct SunOS shared libraries for SRC-2.06? Having 300k "hello world" programs makes it hard to convince people that M3 is any good. Thanks Deryck -- Deryck F. Brown |JANET: deryck@uk.ac.glasgow.dcs Comp. Sci. Dept, The University |INTERNET: deryck@dcs.glasgow.ac.uk Glasgow, G12 8QQ, UK |USENET: ...!uunet!ukc!glasgow!deryck =============================================================================== = ======================================================================= 56 === Date: 25 May 92 13:22:04 GMT From: deryck@dcs.glasgow.ac.uk (Deryck F Brown) Subject: Formal specification of Modula-3 Is there anybody working on a formal specification of the semantics of Modula-3? I have recently started a project to write an action semantics[1] of Modula-3 based on one for Pascal[2]. Is there a better place for discussing the finer points of the language's semantics? Many thanks Deryck [1] P. D. Mosses. Action Semantics. Cambridge Univerisity Press, Cambridge, England, 1992. [2] P. D. Mosses and D. A. Watt. Pascal Action Semantics. Computer Science Department, Aarhus University, Denmark. In preparation. -- Deryck F. Brown |JANET: deryck@uk.ac.glasgow.dcs Comp. Sci. Dept, The University |INTERNET: deryck@dcs.glasgow.ac.uk Glasgow, G12 8QQ, UK |USENET: ...!uunet!ukc!glasgow!deryck =============================================================================== = ======================================================================= 57 === Date: 25 May 92 20:09:47 GMT From: clayton@cc.gatech.edu (R. Clayton) Subject: Quest on a sparc. I'm trying to get Quest running on a sun 4 (SunOS 4.1.1g) and I've run into a couple of problems: I had to massage the QM source (e.g., deleted collection_allowed and renamed the module exporting argc and argv) before I could get it to compile. I started with the DECStation source. Did anybody else have these problems or did I screw up the modula-3 2.05 installation? I have a copy of what I imagine to be the portable version of the byte code (Quest.qm.p from gatekeeper.dec.com) but PortableToNative dies with an assertion violation in Format when I try to convert it to sparc format. Any clues? ======================================================================= 58 === Date: Mon, 25 May 92 19:51:54 PDT From: schedler@src.dec.com (Richard Schedler) Subject: Re: Formal specification of Modula-3 Deryck F. Brown writes: > Is there anybody working on a formal specification of the semantics of > Modula-3? > > I have recently started a project to write an action semantics[1] of Modula-3 > based on one for Pascal[2]. > > Is there a better place for discussing the finer points of the language's > semantics? I'm afraid the only method I have had some exposure to is VDM. Derek Andrews of the University of Leicester would be the man to talk to about the efforts of the ISO working group for Modula-2 standardization. Over a (relatively long) period of time, the complete syntax and semantics of Modula-2 (as it "evolved") was described in VDM. Can't find to find an email address for Dr. Andrews - sorry. The best I can do is a snailmail address: Derek Andrews, Dept. Head. Computing Studies Dept. University of Leicester University Road Leicester, EI 7RH United Kingdom I suppose that, given your location, you could just telephone him :-) For the current version of the Modula-2 draft standard, call Real Time Associates (+44-81-656-7333). In the book "VDM '87; VDM -- A formal method at work" there is a very illustrative paper describing efforts at Denmark's DDC (Dansk Datamatik Center) to formally specify Ada's semantics using VDM. The title of the paper is "VDM in Three Generations of Ada Formal Descriptions". The name of the author is Jan Storbank Pedersen and the address of DDC is listed as: Lundtoftebej 1C DK-2800 Lyngby Denmark I'm sure ddc's domain is something like ddc.dk :-) The VDM '87 proceedings were published by Springer-Verlag (ISBN 0-387-17654-3). In my humble opinon, Modula-3 badly needs a formal description. I suspect however, that such an effort may be underway at SRC. - Frode -------------------------------------------------------------------- Frode Odegard, Odegard Labs, 100 Bush Street, Suite 625, San Francisco, CA 94104, USA, +1-415-434-4242, +1-415-982-3167 (fax), +1-415-905-6201 (voice mail), frode@odegard.com (internet) ======================================================================= 59 === Date: 26 May 92 16:57:52 GMT From: lins@Apple.COM (Chuck Lins ) Subject: Re: Why no structured function results in Oberon In article <1992May20.151534.20341@beaver.cs.washington.edu> pattis@cs.washingt on.edu (Richard Pattis) writes: >>In article <67270@apple.Apple.COM> lins@Apple.COM (Chuck Lins ) writes: >> >>You must remember the overriding design principle of Oberon: >> >>"As simple as possible, but no simpler" >> > >As a gross overgeneralization, I'd characterize Wirth languages as easy to >write compilers for, but hard to program in. Question: is this because Wirth >spends more time writing compilers than applications? No, he spends more time designing hardware. The only reason Oberon was designed was because he couldn't do things he wanted in Modula-2. And because he was more interested in designing the Ceres hardware and the Oberon operating system, the language was kept as small as possible so he didn't have to spend extra time writing compilers. It's mostly the students at ETH who have to 'suffer' from Wirth's languages :-) Considering that they've written page layout systems (ala PageMaker), VLSI circuit layout systems, geometric modeling packages, and many other programs and systems all with this minimal language, I'd say they've done quite well. > >Exactly who draws the line between these simplicities? There is no need for >six relational operators: just < along with AND works just fine. Why wasn't >this simplification made? For that matter the logical operators are unnecessar y >because they can be simulated with nested ifs. Ditto. The designer. And so if you really think the above it true, we know that all programs can be represented with sequences and branches, so let's get rid of all those extaneous looping constructs like WHILE, REPEAT, LOOP, and FOR! Bring back the GOTO!! It's all you'll ever need :-) -- Chuck Lins, Apple Computer, Inc. Oberon-2 Paladin lins@apple.com "Oppression breeds violence" - Front Line Assembly ======================================================================= 60 === Date: Thu, 28 May 1992 00:09:29 GMT From: ron@donatello.ee.adfa.oz.au (Ron Brandis) Subject: Help on ARRAYS Can more than 1D arrays be initialised ? To initialise a 1D array: VAR column := ARRAY [1..5] OF INTEGER {1,2,3,4,5}; So how do I initialise VAR matrix := ARRAY [1..5],[1..5] OF INTEGER {???????????????}; Thanks =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= Ronald Brandis, __ /\ University College UNSW, Electrical Eng. Dept. / \/ \ Australian Defence Force Academy, / \ Canberra ACT 2600. ++61 6 2688191 (w) / / AUSTRALIA ++61 6 2516741 (h) \. __ */ ++61 6 2688443 (fax) `-' \_/ , Email on Internet/AARnet: r-brandis@adfa.oz.au =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= ======================================================================= 61 === Date: Thu, 28 May 92 09:21:52 PDT From: surak!frode (Frode Odegard) Subject: Re: Help on ARRAYS Ron Brandis (ron@donatello.ee.adfa.oz.au) writes: > So how do I initialise > > VAR > matrix := ARRAY [1..5],[1..5] OF INTEGER {???????????????}; > TYPE A5 = ARRAY [1..5] OF INTEGER; TYPE AA5 = ARRAY [1..5] OF A5; VAR matrix := AA5 {A5 {1, 2, 3, 4, 5}, A5 {1, 2, 3, 4, 5}, A5 {1, 2, 3, 4, 5}, A5 {1, 2, 3, 4, 5}, A5 {1, 2, 3, 4, 5} }; This expands to: VAR matrix := ARRAY [1..5], [1..5] OF INTEGER { ARRAY [1..5] OF INTEGER {1, 2, 3, 4, 5}, ARRAY [1..5] OF INTEGER {1, 2, 3, 4, 5}, ARRAY [1..5] OF INTEGER {1, 2, 3, 4, 5}. ARRAY [1..5] OF INTEGER {1, 2, 3, 4, 5} ARRAY [1..5] OF INTEGER {1, 2, 3, 4, 5} }; I prefer the short form :-) - Frode -------------------------------------------------------------------- Frode Odegard, Odegard Labs, 100 Bush Street, Suite 625, San Francisco, CA 94104, USA, +1-415-434-4242, +1-415-982-3167 (fax), +1-415-905-6201 (voice mail), frode@odegard.com (internet) ======================================================================= 62 === Date: 28 May 92 23:28:17 GMT From: mdixon@parc.xerox.com (Mike Dixon) Subject: Side Effects & Language Design (A Poll) The designers of Euclid and Turing incorporated an interesting feature: functions and procedures are prohibited from causing side effects. More precisely, each subprogram must explicitly declare (through an "import" declaration) which variables from its enclosing scope it will access, and how it will access them (read or read/write). It is a compile-time error to attempt to modify a variable which is not passed or imported as a var parameter. (You can think of this as formalizing and then checking a kind of information that usually is left to the documentation.) Furthermore, functions may not have var imports or parameters; together, these constraints ensure that functions cannot cause any caller-visible state changes. (Actually getting this to work depends on some other language features, such as prohibiting aliasing and introducing explicit zones for dynamic allocation.) Prohibiting side effects has some obvious advantages: it makes it easier to understand and reason about programs (since all the dataflow is explicit), it can make compiler optimization easier (for the same reason), and it can prevent an important class of bugs (where unanticipated side effects change a program's behavior). On the other hand, there are also disadvantages. One of the most important is that it may force "implementation details" into a subprogram's interface declaration. As a trivial example, a factorial function that wishes to cache its result in a table must now explicitly import that table as part of its interface (which in turn will force us to rewrite it as a procedure rather than a function). So here's the question: how significant do you consider the benefits of prohibiting side effects? If your favorite programming language could guarantee that all the visible effects of a subprogram had been explicitly declared, would that make it easier to understand programs? Have you run into bugs caused by unanticipated side effects? If this could be done without mixing implementation details into the interfaces, would you be interested in having such a feature? (This is not a hypothetical question; we have an approach that we believe solves that problem.) -- .mike. ======================================================================= 63 === Date: 29 May 92 14:32:30 GMT From: templ@inf.ethz.ch (Josef Templ) Subject: _NILCHECKB(e) On a Sparc, m3 generates code for NIL check as defined in include/M3Maschine.h #define _NILCHECKB(e) _M3__nil_check_char = ((char*)(e))[-1]; Is it ok to change this macro to #define _NILCHECKB(e) e; in order to avoid explicit NIL tests? On a Sparc, NIL access is caught anyway on an attempt to read or write low memory pages. - Josef ======================================================================= 64 === Date: Fri, 29 May 1992 17:35:29 GMT From: wittbj@cube05.csus.edu (brian witt) Subject: Re: Side Effects & Language Design (A Poll) In article mdixon@parc.xerox.com (Mike Dixon) writ es: >The designers of Euclid and Turing incorporated an interesting >feature: functions and procedures are prohibited from causing side >effects. More precisely, each subprogram must explicitly declare >(through an "import" declaration) which variables from its enclosing >scope it will access, and how it will access them (read or >read/write). >[...] > As a trivial example, a factorial >function that wishes to cache its result in a table must now >explicitly import that table as part of its interface (which in turn >will force us to rewrite it as a procedure rather than a function). > >So here's the question: how significant do you consider the benefits >of prohibiting side effects? I would hastily suggest that "reference" categories are solvable problems that today's higher performance compilers do handle. Both GNU GCC and Watcom C compilers support global optimization where small, seperate functions may be placed "inline" of where they are called (other compilers do this also). And those with register coloring really ignore the C storage hint "register" cuz the compiler can enregister it whenver/where ever it would be beneficial. If you removed a listing of external referencing, then a "smart tool" would have to analyze the code; whereas in Turing, say, a Perl script, could determine if any illegal references were to occur. Of course pointer aliasing can blow this all to Dan Qualye's bathroom! :-) :-) (When Turing was annouced, it looked *really* good. Alas, I program C for money and fame, ie SimCity for the Amiga.) Perhaps pre-conditions, post conditions, and class/function invariants would yield more "high level" assurance of proper functioning (ala Eiffel). This are details that a software tool would have difficulty in trying to deduce about some code; details the programmer really ought to know, IMHO. And then better training for programmers and these features would actually be used! :-) :-) :-) > .mike. -- ======================================================================== ! Brian Witt [Sac State Comp Science] "Waldo, the pariot, is dead" Internet: wittbj@cube01.ccs.csus.edu -- Agent Cooper #define POSIX_ME_HARDER 1 <-- GNU ======================================================================= 65 === Date: Fri, 29 May 92 18:52:45 GMT From: muller@src.dec.com (Eric Muller) Subject: Re: _NILCHECKB(e) In article <1992May29.143230.22523@neptune.inf.ethz.ch>, templ@inf.ethz.ch (Jos ef Templ) writes: > On a Sparc, m3 generates code for NIL check as > defined in include/M3Maschine.h > #define _NILCHECKB(e) _M3__nil_check_char = ((char*)(e))[-1]; > > Is it ok to change this macro to > #define _NILCHECKB(e) e; > in order to avoid explicit NIL tests? > On a Sparc, NIL access is caught anyway on an > attempt to read or write low memory pages. Not all possible NIL accesses will be caught by the memory system. Let A be any (byte) address that is mapped, and define VAR x: REF ARRAY [1..A] OF CHAR; then x^[A] does not produce a fault if x is NIL. Sometime, the compiler does know that the offset is too large to be safe. Sometime, it does not know the offset at all (consider accessing a field in an object with an opaque supertype; the supertype could have a field which is a very large array). In those cases, the compiler has to generate an explicit check. On the other hand, compiler/src//Target.i3 contains the definition: (* NIL checking *) FIRSTREADABLEADDR = 16_400000; (* Read or write references to addresses in the range [0..FIRSTREADABLE-1] will cause an address faults. Hence, no explicit NIL checks are needed for dereferencing with offsets in this range. *) If the compiler knows that the offset is smaller than FIRSTREADABLEADDR, then no check is generated. The value of FIRSTREADABLEADDR in the SPARC version is currently 0. I suspect that we can have a better value; can anyone tell us what it is ? -- Eric. ======================================================================= 66 === Date: Sun, 31 May 1992 12:16:26 GMT From: templ@inf.ethz.ch (Josef Templ) Subject: Re: _NILCHECKB(e) In article <1992May29.185245.7492@src.dec.com> muller@src.dec.com (Eric Muller) writes: >The value of FIRSTREADABLEADDR in the SPARC version is currently 0. I >suspect that we can have a better value; can anyone tell us what it is ? On a Sparcstation 1 running SunOS 4.1.1 FIRSTREADABLEADDR = 8192 but FIRSTWRITABLEADDR = 90112 IMHO, the latter renders explicit NIL checks almost superflous even if the compiler does not know the offsets at compile time (which seems to be the regular case in OO programs). However, I agree that you have to do explicit checks if you want to be 100% safe. - Josef ======================================================================= 67 === Date: 31 May 92 22:26:02 GMT From: guerrieri@wecrow.enet.dec.com Subject: CFP - 2nd Int. Workshop on Software Reusability Call for Papers Second International Workshop on Software Reusability Lucca, Italy March 24-26, 1993 SPONSORED BY THE IEEE COMPUTER SOCIETY IN COLLABORATION WITH ACM SIGSOFT CORPORATE SUPPORT BY: AT&T Bell Northern Research, Ltd. Bull S.A Commission of European Communities (on behalf of the REBOOT Project) Digital Equipment Corporation Hewlett-Packard IBM NEC Scientific Applications International Corp. Verbund Software Technik Nordrhein-Westfalen CHAIRS US : Ruben Prieto Diaz Europe : Pat Hall Japan : Masao Matsumoto Local : John Favaro Programme: Bill Frakes Finance : Mitch Lubars PROGRAMME COMMITTEE G. Arango (US) J. Bacquet (Neth) D. Batory (US) [demo session coordinator] I. Baxter (US) [co-sponsors coordinator] J. Bo"rstler (Germany) P. Devanbu (US) E. Doberkat (Germany) L. Dusink (Neth) M. Griss (US) E. Guerrieri (US) [publicity coordinator] K. Harada (Japan) S. Isoda (Japan) A. Martelli (Italy) K. Matsumura (Japan) J. Morel (France) J. Poulin (US) W. Scha"fer (Germany) J. Solderitsch (US) H. van Vliet (Neth) M. Wirsing (Germany) The Second International Workshop on Software Reusability, following the guidelines of the first workshop of 1991 in Dortmund, Germany, is organized to bring together known researchers in Software Reusability from the international community. Several anecdotal successes in software reuse have been reported and presented as encouraging examples. There is a need for solutions that can be applied across domain and organization boundaries. The central objective of the workshop is to explore reuse solutions that include methods and tools, either proposed, prototyped, or applied in practice. Assessment of such methods and tools is critical, as are innovative factors affecting reuse and key reuse inhibitors. One expected outcome is an assessment on the state of the art as seen by the participants, and another is to propose a research agenda for software reusability. Workshop proceedings will be published. The workshop will consist of selected technical presentations, parallel working groups, and plenary sessions. Attendance is limited and is by invitation on the basis of a submitted paper. THEMES The workshop will address the following principal themes: o Methods, Tools, and Environments: Methods and tools that support reuse; integrated reuse environments; methods and tools for requirements, design, and code. o Reuse Library Methods: Classification and cataloging; component matching, library operation, and performance; library usage. o Generative Approaches to Reuse: Executable specifications; code generation; transformational approaches. o Constructive Approaches to Reuse: Integration of reusable components; version control; methods and techniques to modify, verify, test, and adapt reusable components. o Theoretical Aspects of Reuse: Formal approaches to the reuse process; formal models of components; verification and validation of components and their composition. o Organizational and Management Techniques for Implementing Reuse: Incentives; economic and financial techniques; asset acquisition; measurement and experimentation; reliability models; human factors. o Domain Analysis Methods and Techniques: Domain modeling; conceptual modeling; knowledge acquisition; object-oriented techniques; re-engineering and reverse engineering. Working groups will be formed based on these themes. INSTRUCTIONS TO AUTHORS To ensure a coherent and productive workshop, attendance is limited to 100. Authors should take care to explain the relevance of their work to the workshop themes and its theoretical and practical value. Submissions may be either a full paper (max. 5000 words) discussing novel approaches or detailed experience, a position paper (max. 2000 words) discussing research in progress, research perspectives, or practical experience, or a video tape of an ongoing project (max. 25 minutes). Only full papers will be published in the proceedings and considered for presentation at the workshop. Position papers will be distributed to participants, and video tapes will be shown during the workshop (in lieu of live prototype demonstrations). Full paper and position paper submissions (5 copies) should be sent to Bill Frakes by September 15, 1992. Video tape submissions should be sent to either Don Batory or John Favaro by September 15, 1992. Full Papers and Position Papers: Bill Frakes Software Engineering Guild 400 Drew Ct. Sterling, VA 22170 tel: 1-703-450-5954 email: 70761.1176@CompuServe.com NTSC-format video submissions: Don Batory Department of Computer Sciences 2.124 Taylor Hall University of Texas Austin, Texas 78712 email: dsb@cs.utexas.edu PAL-format video submissions: John Favaro INTECS Sistemi S.p.A. Via Fratti, 14 56125 Pisa, Italy email: favaro@pisa.intecs.it IMPORTANT DATES September 15, 1992 ----> Submission deadline October 30, 1992 ----> Notification of acceptance December 15, 1992 ----> Camera-ready copy due