======================================================================= 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 <std/disclaimer>

  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 <nr@Princeton.EDU>
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:    <kalsow@src.dec.com>
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 <nr@Princeton.E
DU> 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:    <meehan@src.dec.com>
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 <std/disclaimer>

  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 <Pavel@parc.xerox.com>
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

<std.disclaimer>


======================================================================= 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 <std/disclaimer>
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 <std/disclaimer>

  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 <std/disclaimer>

  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 <std/disclaimer>

  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:    <stolfi@src.dec.com>
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 <std/disclaimer>

  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.92May9133630@ibis.cs.umass.edu> 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 <stdio.h>
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 <muller@src.dec.com> 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:    <mhb@src.dec.com>
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:    <stolfi@src.dec.com>
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 <deryck@dcs.glasgow.uk> 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.707095697@thelonius> 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/<architecture>/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



