[comp.object] Type Systems and Dynamic Binding

dmg@ssc-vax.uucp (David M Geary) (04/03/91)

In article <7689:Mar2623:28:5091@kramden.acf.nyu.edu>> (Dan Bernstein) writes:
>>In article <48805@nigel.ee.udel.edu> new@ee.udel.edu (Darren New) writes:

>> Hmm... How about a window with a hetrogeneous collection of buttons, sliders,
>> text displays, etc, all of which respond to "redraw" and "is the mouse
>> over you"?

>struct {any object; void (*redraw)(); int (*ismouseover)();} *whatsinwindow();

>Here ``any'' is a polymorphic type (e.g., void * in C), and *redraw
>takes an ``any'' argument. Naturally, languages like C++ encapsulate the
>above struct into a single ``class,'' but that's merely syntactic sugar.

A void* is not a "polymorphic type", and C++ provides much more than
"merely syntactic sugar".

In article <25655:Mar2803:50:2491@kramden.acf.nyu.edu> (Dan Bernstein) writes:
>In article <49087@nigel.ee.udel.edu> new@ee.udel.edu (Darren New) writes:
>> Am I crazy, or isn't (void *) impossible to indirect?  Don't you have
>> to type-cast it first?  Isn't this dynamic typing implemented on top of
                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>> C?
  ^^^

>YES. People are tossing around the term ``dynamic typing'' as if it were
>some truly important feature. ``Yeah, Bob, not only does the language
>have *loops*, but it has *dynamic typing*!'' ``Wow! *Dynamic typing*?
>Really?''

 NO.  This is *not* an example of dynamic typing implemented on top of C.

> On the occasions when I want dynamically typed variables, I
>can use them without trouble in C.

  No you cannot;  C has no support whatsover for "dynamically typed variables."

>Sure, this requires a void pointer type. SO WHAT? As I pointed out when
>I entered this discussion, the language does need *some* type that can
>represent *all* values if it's going to support dynamic typing. C has
>such a type, and adequate macros, and that's enough for me to get work
>done.

  C has absolutely nothing akin to dynamic typing.  One cannot "implement
dynamic typing on top of C", without writing some kind of preprocessor, such
has been done with Objective-C.  I think that there is some confusion over
terminology here:  

1)  Dynamic binding:

  Dynamic binding is a feature whereby the compiler chooses the correct
function to apply to some object, depending upon the *type* of the object.
If I have dynamic binding, I can have code like the following (in C++):

int  list::insert(linkable& lnk, int pos)
{
 ....

 lnk.setNextNode(NULL);   // Compiler chooses appropriate function to call
		          // for the given object.
 ...
}

  The C compiler will allow *any type* to be passed to list::insert(),
as long as the type is a linkable (or is a descendent of class linkable).
Therefore, the programmer may send different types to the function
list::insert(), and the compiler determines the appropriate function
to call, depending upon the type of lnk for lnk.setNextNode().  However, since
C++ is statically typed, the first argument to list::insert() *must* be
either a linkable, or a descendent of linkable.  If not, the COMPILER
WILL GENERATE A COMPILE-TIME ERROR.

  Bertrand Meyer, of Eiffel fame, has already posted an example of this
kind in Eiffel, (which, like C++ has multiple inheritance and dynamic
binding).


2)  Dynamic typing:

  With "dynamic typing", one may write (in Objective-C):

id  collection = [Container new];

[collection add:[Dog new]];
[collection add:[Cat new]];
[collection add:[bottleOWine new]];

  Here, one is adding arbitrary elements to a collection.  There is 
*no restriction whatsoever* as to the type of things that can be
added to the collection.  Note that this differs from the C++ example,
where all elements added to the list *must* be linkables (or
descendents of class linkable).  

The "pitfall" of dynamic typing, of course, is that it is possible to
try to apply a method to an object, which the object is not prepared
to deal with, and the error MAY NOT BE CAUGHT UNTIL RUNTIME.  In a statically
typed language, such as Eiffel and C++ the compiler will simply not allow
that to happen.

  Lastly, note that neither of the two examples given above may be
implemented in C, without the programmer *at one time or another*
explicitly identifying the types of all objects being operated upon.
(In other words, in Dan's example above, it is the programmer's,
not the compiler's, responsiblity to ensure that the correct functions
are called for the appropriate types).


Here, BTW, are some good references.  I would suggest that Dan read
some of these before providing any more erroneous information in the
tradition of his previous postings:

Object Oriented Software Construction,   Bertrand Meyer. (excellent, BTW)
Object Oriented Programming,             Brad Cox.
An introduction To OOP and C++,          Wiener & Pinson  

brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (04/04/91)

In article <3776@ssc-bee.ssc-vax.UUCP> dmg@ssc-vax.uucp (David M Geary) writes:
>In article <7689:Mar2623:28:5091@kramden.acf.nyu.edu>> (Dan Bernstein) writes:
>>>In article <48805@nigel.ee.udel.edu> new@ee.udel.edu (Darren New) writes:
>>>Hmm... How about a window with a hetrogeneous collection of buttons, sliders,
>>>text displays, etc, all of which respond to "redraw" and "is the mouse
>>>over you"?
>>struct {any object; void (*redraw)(); int (*ismouseover)();} *whatsinwindow();
 [ ... ]
>NO.  This is *not* an example of dynamic typing implemented on top of C.

What a load of... uh, what I mean is that this is a perfect example of
the fact that dynamic typing is just a programming technique. (``A state
of mind'' is perhaps too fluffy for such a serious discussion as this.)

With appropriate macros, I can use the above structure in the same way
as someone using a dynamically typed language. In fact, with a
reasonable preprocessor like AT&T's C++, I can declare the structure in
the same way. I can get all the same type-checking (at run-time, too!).

You can shout all you want about it not *really* being dynamic typing.
But it obviously is. Why does it so offend you that dynamic typing can
be implemented so effectively outside the compiler?

> A void* is not a "polymorphic type", and C++ provides much more than
> "merely syntactic sugar".

Uh-huh, whatever you say, boss.

> > On the occasions when I want dynamically typed variables, I
> >can use them without trouble in C.
> No you cannot;  C has no support whatsover for "dynamically typed variables."

It has a macro facility that is adequate to let me use a variable, x,
that can take on any value I can express in the language, and that
forces me to use x as the type it is currently holding. What else do you
want out of types, other than the syntax and the checking?

> One cannot "implement
> dynamic typing on top of C", without writing some kind of preprocessor,

In case you haven't noticed, C has a preprocessor. It's not great, but
it works. But even if it didn't, I would happily use m4. As I've said
before, you cannot change the fundamental characteristics of a language
by adding a library---or a preprocessor.

>   Here, one is adding arbitrary elements to a collection.  There is 
> *no restriction whatsoever* as to the type of things that can be
> added to the collection.  Note that this differs from the C++ example,
> where all elements added to the list *must* be linkables (or
> descendents of class linkable).  

Nobody has come up with any examples of why anyone would want to use
such a list---i.e., a list which does not have a definite type, and to
which you cannot meaningfully apply any particular operations. Do you
have a brilliant example that everyone else has missed?

>   Lastly, note that neither of the two examples given above may be
> implemented in C, without the programmer *at one time or another*
> explicitly identifying the types of all objects being operated upon.

C++ is a counterexample.

> Here, BTW, are some good references.  I would suggest that Dan read
> some of these before providing any more erroneous information in the
> tradition of his previous postings:

Why, thank you, ma'am.

Here, BTW, is an excellent reference. I strongly suggest that you read
it---and work at least 10% of the exercises---before you post anything,
again, anywhere, ever.

Art of Computer Programming, Donald E. Knuth. 3 volumes.

---Dan

gudeman@cs.arizona.edu (David Gudeman) (04/08/91)

In article  <11479:Apr319:53:2191@kramden.acf.nyu.edu> Dan Bernstein writes:
]With appropriate macros, I can use the above structure in the same way
]as someone using a dynamically typed language. In fact, with a
]reasonable preprocessor like AT&T's C++, I can declare the structure in
]the same way. I can get all the same type-checking (at run-time, too!).

Well I can't.  I've tried pretty hard to find a way to get extensible
dynamic typing in C++, and I don't believe it can be done.  I'm
talking about (1) a single package that I write including a header and
linked module, (2) minimal overhead for new dynamic types, (3) using
dynamically typed values just like statically typed values.  If you
can do this I'd like to see it.
--
					David Gudeman
gudeman@cs.arizona.edu
noao!arizona!gudeman

dmg@ssc-vax (David M Geary) (04/09/91)

  Dan Bernstein claims to be able to implement dynamic typing on top of C:

]   Dan Bernstein
]]  David Geary
]]] David Gudeman

]struct {any object; void (*redraw)(); int (*ismouseover)();} *whatsinwindow();

]] NO.  This is *not* an example of dynamic typing implemented on top of C.

]With appropriate macros, I can use the above structure in the same way
]as someone using a dynamically typed language. In fact, with a
]reasonable preprocessor like AT&T's C++, I can declare the structure in
]the same way. I can get all the same type-checking (at run-time, too!).

]]] Well I can't.  I've tried pretty hard to find a way to get extensible
]]] dynamic typing in C++, and I don't believe it can be done ...  
]]] If you can do this I'd like to see it.

  I'd like to see it also.  Either Dan does not understand dynamic typing, or
he has found something which the rest of the world needs to know.  Let's take 
the window example since that was the original context of this discussion:

Developer A implements buttons, menus, and icons which are displayable in a
window.  Developer A provides developer B with:

  1)  Header files defining structures for buttons, menus and icons.
      
      (menu.h, button.h and icon.h).

  2)  Object modules which implement functionality for each.
      
      (menu.o, button.o and icon.o).

 Menus, buttons, and icons all have a pointer to a redraw function in their
 structure definition; however, structures for buttons, menus and icons are
 all different, ie:

 struct button                        struct menu
 {                                    { 
   int   x,y,w,h;                       int    x,y,w,h;
   char* text;                          int    numItems;
                                        char** itemText; 
   void  (*redraw)();                    
 };                                     void   (*redraw)();                   
                                      };
 struct icon
 {
   int      x,y,w,h;
   bitmap*  picture;

   void     (*redraw)();
 };

 Developer A provides a function that returns a list of things in a window
(things being buttons, menus, and icons).  Let's call the function
getListOfThingsInWindow().

 Now, developer B, given the header files and object modules defined above,
processes the list, and displays all items on the list in a fashion similar
to:

   drawWindowThings(window)
     window_t* window;
   {
     list_t*  wlist = getListOfThingsInWindow(window);

     for(each object in wlist)
       redraw the object
   }

  Admittedly, the same effect can be had (in C++) if developer A ensures that
buttons, menus, and icons all have a superclass in common, such as
windowThing which has a redraw method.  However, that is *not* dynamic typing,
that is inheritance - two very different things.
  
  Dan, since you can implement dynamic typing in C, would you please post
the *appropriate macros* so that developer B can get his job done, without
*in any way* having to modify (recompile) the object modules that are supplied
from developer A.

brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (04/12/91)

In article <3810@ssc-bee.ssc-vax.UUCP> dmg@ssc-vax.UUCP (David M Geary) writes:
>   Dan Bernstein claims to be able to implement dynamic typing on top of C:

Although I can implement and have implemented dynamic typing with a
suitable preprocessor over C, I did not make that claim in the quoted
material. Please read a quote before you paraphrase it.

> ]   Dan Bernstein
> ]]  David Geary
> ]]] David Gudeman
> ]struct {any object; void (*redraw)(); int (*ismouseover)();} *whatsinwindow();
> ]] NO.  This is *not* an example of dynamic typing implemented on top of C.

The original example in question was *presented* as an example of what
people do with heterogeneous (dynamically typed) lists. I responded with
the above structure to show how you implement the same thing in C, and
here Geary claims that the example was no longer an example of dynamic
typing. Sheesh. My response:

> ]With appropriate macros, I can use the above structure in the same way
> ]as someone using a dynamically typed language. In fact, with a
> ]reasonable preprocessor like AT&T's C++, I can declare the structure in
> ]the same way. I can get all the same type-checking (at run-time, too!).

What can one mean by typing, if not storage format plus type-checking
plus syntax? What I said here was that C++ has sufficient typing for
this example. Where do you see this claim of dynamic typing in C?

I'll answer your (trivial) question anyway, even though it has been
adequately answered by Chip and others in comp.lang.misc.

  [ sample problem ]

If you had been keeping up with the discussion in comp.lang.misc, you
would understand that giving the same name to variables in different
structures does NOT imply any magical connection between those
variables. In order to solve your problem as stated, you must make the
connection explicit, like so (as per my structure as above):

  struct redrawable { void *object; void (*redraw)(); } ;
  ...
  struct redrawable menu2redraw(struct menu *m)
  { struct redrawable r; r.object = m; r.redraw = m->redraw; }

(OO fans will note that I have just, in effect, defined a subtype.)
That makes the connection between menus and the redrawing you want to
deal with. Similarly for button and icon.

>  Developer A provides a function that returns a list of things in a window
> (things being buttons, menus, and icons).  Let's call the function
> getListOfThingsInWindow().

Wrong, wrong, wrong. There is no such thing in C as a list of buttons,
menus, and icons. My point in the heterogenous-list discussion was that
people only use heterogeneous lists as (a) union types; (b) objects, to
which a FIXED set of operations will be applied. What you mean is that A
defines a function to return a list of redrawables.

>  Now, developer B, given the header files and object modules defined above,
> processes the list, and displays all items on the list in a fashion similar
> to:
>    drawWindowThings(window)
>      window_t* window;
>    {
>      list_t*  wlist = getListOfThingsInWindow(window);
>      for(each object in wlist)
>        redraw the object
>    }

foo->redraw(foo->object); Done.

>   Admittedly, the same effect can be had (in C++) if developer A ensures that
> buttons, menus, and icons all have a superclass in common, such as
> windowThing which has a redraw method.

As almost everyone in the comp.lang.misc discussion realized, you can
also define a SUBclass as I just did. As Chip pointed out explicitly,
you can avoid tricky inheritance issues by having the subclasses *point*
to their parents, but I've written the above solution in C anyway.

---Dan

dmg@ssc-vax.uucp (David M Geary) (04/16/91)

]    Dan Bernstein
]]   David Geary

]]   Dan Bernstein claims to be able to implement dynamic typing on top of C:
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

] Although I can implement and have implemented dynamic typing with a
] suitable preprocessor over C, I did not make that claim in the quoted
                                ^^^^^^^^^^^^^^^^^^^^^^^^^^
] material. Please read a quote before you paraphrase it.

]The original example in question was *presented* as an example of what
]people do with heterogeneous (dynamically typed) lists. I responded with
                                                         ^^^^^^^^^^^^^^^^
]the above structure to show how you implement the same thing in C, and
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
]here Geary claims that the example was no longer an example of dynamic
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
]typing. Sheesh. My response:
 ^^^^^^

  Sheesh yourself.  Either it *was* an example of dynamic typing or it
was *not*.  You cannot have it both ways, Dan.  I did not claim
that your example was *no longer* an example of dynamic typing.  I said
that your example was *never* an example of dynamic typing.
  Here, BTW, since you do not want me to paraphrase, is the original
article written by Bernstein:

------------------------------------------------------------------------------

%  = Darren New
%% = Dan Bernstein

In article <25655:Mar2803:50:2491@kramden.acf.nyu.edu> (Dan Bernstein) writes:
%In article <49087@nigel.ee.udel.edu> new@ee.udel.edu (Darren New) writes:
%% Am I crazy, or isn't (void *) impossible to indirect?  Don't you have
%% to type-cast it first?  Isn't this dynamic typing implemented on top of
                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
%% C?
  ^^^

%YES. People are tossing around the term ``dynamic typing'' as if it were
%some truly important feature. ``Yeah, Bob, not only does the language
%have *loops*, but it has *dynamic typing*!'' ``Wow! *Dynamic typing*?
%Really?''

-----------------------------------------------------------------------------

  YES is pretty clear to me.  Did you really mean NO?  If so, then I 
misunderstood.


]If you had been keeping up with the discussion in comp.lang.misc, you
]would understand that giving the same name to variables in different
]structures does NOT imply any magical connection between those
]variables. In order to solve your problem as stated, you must make the
]connection explicit, like so (as per my structure as above):

  Exactly what I was trying to say.  Dan Bernstein is *not* implementing
dynamic typing on top of C.

  Since it appeared to me that Bernstein was claiming to be implementing
dynamic typing on top of C, I posted the following challenge for Dan:

]]Developer A implements buttons, menus, and icons which are displayable in a
]]window.  Developer A provides developer B with:

]]  1)  Header files defining structures for buttons, menus and icons.
]]      (menu.h, button.h and icon.h).

]]  2)  Object modules which implement functionality for each.
]]      (menu.o, button.o and icon.o).

]] Menus, buttons, and icons all have a pointer to a redraw function in their
]] structure definition; however, structures for buttons, menus and icons are
]] all different, ie:

]] struct button                        struct menu
]] {                                    { 
]]   int   x,y,w,h;                       int    x,y,w,h;
]]   char* text;                          int    numItems;
                                        char** itemText; 
]]   void  (*redraw)();                    
]] };                                     void   (*redraw)();                   
                                      };
]] struct icon
]] {
]]   int      x,y,w,h;
]]   bitmap*  picture;

]]   void     (*redraw)();
]] };

]] Developer A provides a function that returns a list of things in a window
]](things being buttons, menus, and icons).  Let's call the function
]]getListOfThingsInWindow().

]] Now, developer B, given the header files and object modules defined above,
]]processes the list, and displays all items on the list in a fashion similar
]]to:

]]   drawWindowThings(window)
]]     window_t* window;
]]   {
]]     list_t*  wlist = getListOfThingsInWindow(window);

]]     for(each object in wlist)
]]       redraw the object
]]   }

]]  Dan, since you can implement dynamic typing in C, would you please post
]]the *appropriate macros* so that developer B can get his job done, without
]]*in any way* having to modify (recompile) the object modules that are supplied
]]from developer A.

Dan replies with:

foo->redraw(foo->object); Done.

  No.  Wrong.  Not done.  Dan is using his own structure instead of those
I provided in the example.  In the example above, each object in wlist
must be a void*.  You cannot defererence a void pointer.  You cannot implement
dynamic typing in C without writing an external preprocessor.  Period.

  BTW, this whole series of postings occurred because I thought that Bernstein
claimed to have implemented dynamic typing in C without writing any
*external* preprocessor.  (As did others in this newsgroup).  Since this is 
impossible to do, I posted the above challenge.  Now, Dan seems to be claiming 
that he never stated he could implement dynamic typing on top of C without 
writing any *external* preprocessor.

  If Bernstein's claim today is that he *cannot* implement dynamic typing
on top of C withoug writing an external preprocessor, then we are in 
agreement.

brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (04/17/91)

In article <3843@ssc-bee.ssc-vax.UUCP> dmg@ssc-vax.uucp (David M Geary) writes:
> ]]   Dan Bernstein claims to be able to implement dynamic typing on top of C:
>                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

David, there is a big difference between claiming that a *particular*
example of dynamic typing can be implemented (directly) in C, and
claiming that *all* examples of dynamic typing can be implemented
(directly) in C. As you will realize if you reread your article, I have
claimed the former, for several particular examples. I have not claimed
the latter, though of course a more powerful preprocessor obviates this
argument. In other words, please stop misquoting me; it's getting rather
tiresome.

> ]If you had been keeping up with the discussion in comp.lang.misc, you
> ]would understand that giving the same name to variables in different
> ]structures does NOT imply any magical connection between those
> ]variables. In order to solve your problem as stated, you must make the
> ]connection explicit, like so (as per my structure as above):
>   Exactly what I was trying to say.  Dan Bernstein is *not* implementing
> dynamic typing on top of C.

Making an explicit connection between button->redraw and mouse->redraw
has absolutely nothing to do with dynamic typing. There are statically
typed languages where the connection IS explicit: "redraw" is (in
effect) a string which is sent as a message to the object, and by
declaring two different objects that support "redraw" you automatically
make them usable in the same context.

>   Since it appeared to me that Bernstein was claiming to be implementing
> dynamic typing on top of C,

For each EXAMPLE of dynamic typing that people put up, I showed how it
would typically be implemented (directly) in C. I hope you can see the
difference between this and what you're talking about.

>   No.  Wrong.  Not done.  Dan is using his own structure instead of those
> I provided in the example.  In the example above, each object in wlist
> must be a void*.

Ah. So you're saying ``Developer A provides an almost entirely useless
function. It lets you count the number of objects in a window, or test
whether another object you have happens to be in the window. Gee, Dan,
you can't use this function to redraw everything in the window!''

What a shock.

Are you trying to solve real programming problems, or whimper about how
you can't solve them? I've shown you how they would be solved in C.
You're saying ``no, no, you're not allowed to solve them, because your
solution uses your structure rather than my structure.'' Who tf cares?
It's a solution. You can write a trivial interface to convert between
the structures. It works. End of discussion.

> You cannot implement
> dynamic typing in C without writing an external preprocessor.

You can implement all real-world EXAMPLES---or, at least, every example
that's come up in this group---of dynamic typing directly in C. That's
exactly what I've been doing. People say ``hey, here's a use of dynamic
typing,'' and I show them how a C programmer would accomplish the same
result.

---Dan

dan@ece.arizona.edu (Dan Filiberti) (04/17/91)

In article <27313@kramden.acf.nyu.edu> brnstnd@kramden.acf.nyu writes:
>You can implement all real-world EXAMPLES---or, at least, every example
>that's come up in this group---of dynamic typing directly in C. That's
>exactly what I've been doing. People say ``hey, here's a use of dynamic
>typing,'' and I show them how a C programmer would accomplish the same
>result.


So what?  I don't see your point.  Sure, you could probably accomplish
the same result, but at an unreasonable production cost.  And, no matter
how much you insist, C DOES NOT SUPPORT DYNAMIC TYPING.  Period.  The
whole point of having dynamic typing is reusability of code.  And, if
I wanted to reuse the modules you have written, I'd have to use your
interface...what makes you think that I would want to do that!  Sorry,
but your point is dumb.  If you're argueing against using C++, I can 
give you at least two great reasons to use it:

1.  Dynamic Typing is easily and readily available, done the same way
	every time.

2.  If you don't want to use dynamic typing, then DON'T.  C++ doesn't
	force you to do anything, just write C if you want.


So please, tell me your point, and end this useless thread....



		Daniel Filiberti
		dan@helios.ece.arizona.edu [:)}

amanda@visix.com (Amanda Walker) (04/18/91)

In article <1991Apr16.183750@ece.arizona.edu> dan@ece.arizona.edu (Dan
Filiberti) writes:

   And, no matter how much you insist, C DOES NOT SUPPORT DYNAMIC
   TYPING.  Period.

Lisp supports dynamic typing.  Lisp can be interpreted by, or
translated into, C.  Therefore, C supports dynamic typing.  QED.

Now, you can argue that the C language does not *include* dynamic
typing.  I don't think anyone here would disagree with you there.
However, you can certainly *implement* dynamic typing in C, with as
low an overhead as you can get in any other language.

   The whole point of having dynamic typing is reusability of code.  And, if
   I wanted to reuse the modules you have written,

That's portability, not reusability.  Dynamic typing can be just as useful
when I want to reuse my own code as when you want to reuse it.  And if
you want to reuse my code, you have to use whatever framework I wrote it
in anyway.

   I'd have to use your
   interface...what makes you think that I would want to do that!

That's a red herring.  The interface is always fixed, whether its
explicit or implicit in the language used.  I will agree that implicit
support helps portability.

   1.  Dynamic Typing is easily and readily available, done the same way
	   every time.

OK so far...

   2.  If you don't want to use dynamic typing, then DON'T.  C++ doesn't
	   force you to do anything, just write C if you want.

So why bother with C++, then?  I don't follow you...  Either you're going
to use C++ features, in which case using C++ is a good idea, or you're not,
in which case it's silly.  You can't have it both ways...

--
Amanda Walker						      amanda@visix.com
Visix Software Inc.					...!uunet!visix!amanda
-- 
"How can I worry about your miserable violin when I am speaking to my God?"
		--Beethoven

dmg@ssc-vax.uucp (David M Geary) (04/18/91)

]   Dan Bernstein
]]  David Geary
]]] Darren New

]] Dan Bernstein claims to be able to implement dynamic typing on top of C:
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

] David, there is a big difference between claiming that a *particular*
] example of dynamic typing can be implemented (directly) in C, and
] claiming that *all* examples of dynamic typing can be implemented
] (directly) in C. As you will realize if you reread your article, I have
] claimed the former, for several particular examples. I have not claimed
] the latter ...

] For each EXAMPLE of dynamic typing that people put up, I showed how it
] would typically be implemented (directly) in C. I hope you can see the
] difference between this and what you're talking about.

  If C had dynamic typing, we would be able to do this:

  void  doFooToThingsInList(list)
    list_t*  list;
  {
    void*  nextThingInList;

    while(nextThingInList = list->getNextThing())
      nextThingInList->foo(&nextThingInList);
  }

  However, this is not possible, due to the fact that a void* in C must
have a cast applied to it before it can be dereferenced.  Therefore, we 
must do something like the following:

((someType*)nextThingInList)->foo(&nextThingInList);

In other words, the *programmer* is responsible for ensuring that the statement
((someType*)nextThingInList)->foo() is valid for the type someType.

  With dynamic typing, however, this requirement (that the programmer ensures
that all statements are type-safe) is no longer a requirement at all.  The
responsiblity for type-safety is no longer left to the programmer, as there
is no requirement that all statements be type-safe.


]]] Am I crazy, or isn't (void *) impossible to indirect?  Don't you have
]]] to type-cast it first?  Isn't this dynamic typing implemented on top of
                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
]]] C?
   ^^^

]YES. People are tossing around the term ``dynamic typing'' as if it were
 ^^^
]some truly important feature. ``Yeah, Bob, not only does the language
]have *loops*, but it has *dynamic typing*!'' ``Wow! *Dynamic typing*?
]Really?''

  NO.  It was *not* dynamic typing implemented on top of C.  It was 
an example of what a programmer in a statically typed language has to do
in order to accomplish what is (more simply) done with a dynamically typed
language.  

  Dynamic typing *is* a truly important feature.  It allows a greater
degree of code reuse.  Dan, if you would take the time to understand the
scenario I proposed where one developer provides another developer with
classes of objects in a window, the benefits of dynamic typing would be
apparent.

]You can implement all real-world EXAMPLES---or, at least, every example
]that's come up in this group---of dynamic typing directly in C. That's

  You cannot implement the real-world example that I posted earlier
directly in C.  If you wish, I will post a different real-world example
of dynamic typing that cannot be implemented directly in C.

olson@juliet.ll.mit.edu ( Steve Olson) (04/18/91)

In article <1991Apr17.173651.23103@visix.com> amanda@visix.com (Amanda Walker) writes:
   Now, you can argue that the C language does not *include* dynamic
   typing.  I don't think anyone here would disagree with you there.
   However, you can certainly *implement* dynamic typing in C, with as
   low an overhead as you can get in any other language.

No question that you can implement user-defined dynamic typing (or 
object-oriented programming - I see this thread is cross-posted) on
top of a language such a C.  But what do you mean by "overhead"?  Often
there will low machine overhead - but programmer overhead might be a
different story.  Which one is more important will vary drastically
between different applications.

   --
   Amanda Walker						      amanda@visix.com

- Steve Olson
  MIT Lincoln Laboratory
  olson@juliet.ll.mit.edu

cs450a03@uc780.umd.edu (04/18/91)

Dan Bernstein writes:

>For each EXAMPLE of dynamic typing that people put up, I showed how
>it would typically be implemented (directly) in C. I hope you can see
>the difference between this and what you're talking about.

heh heh heh... Excellent :-) 

 f(x, y)
LIMIT ERROR

------------------------

Let's say I was trying to implement a dynamically typed language in C.
(Of course, I wouldn't _really_ be that crazy  :-)  Let's say I wanted
to detect when, for instance, the addition of 2 integers produces an
invalid result.  Let's say that I can not accept a severe performance
hit for this checking (most of the time, it's not going to happen.
When it does happen, I'm going to switch to float -- performance must
be better than floating point).

Now, I know that this sort of information is available if I was
working in assembly (I'm not working on a pathologically silly
machine).  But how would I do it in C?  As near as I can tell, C just
throws the information away.

This is a _very_ simple sort of test.  I'd want to detect erroneous
results for every primitive expression I built into the language.
These tests would be less significant (in terms of time and space)
than simple housekeeping (loads and stores, loop management, etc.) if
I were working in assembly.

How do I do it?

Raul Rockwell

diamond@jit345.swstokyo.dec.com (Norman Diamond) (04/18/91)

In article <1991Apr17.173651.23103@visix.com> amanda@visix.com (Amanda Walker) writes:
>In article <1991Apr16.183750@ece.arizona.edu> dan@ece.arizona.edu (Dan
>Filiberti) writes:
>   And, no matter how much you insist, C DOES NOT SUPPORT DYNAMIC
>   TYPING.  Period.
>Lisp supports dynamic typing.  Lisp can be interpreted by, or
>translated into, C.  Therefore, C supports dynamic typing.  QED.
>Now, you can argue that the C language does not *include* dynamic
>typing.  I don't think anyone here would disagree with you there.
>However, you can certainly *implement* dynamic typing in C, with as
>low an overhead as you can get in any other language.

I hope we're not going to repeat the metalinguistic argument over
the meaning of the word "support."  An electric power cable can be
used as a tool by a programmer to write code to support dynamic typing.
(I'm using several such cables to write a Usenet article too.)
But the programmer is writing the code to do the support.  The
cable itself does not do the support.  A pencil does not support
software design the way some CAD products do.
--
Norman Diamond       diamond@tkov50.enet.dec.com
If this were the company's opinion, I wouldn't be allowed to post it.

amanda@visix.com (Amanda Walker) (04/19/91)

diamond@jit345.swstokyo.dec.com (Norman Diamond) writes:

   A pencil does not support
   software design the way some CAD products do.

And it's a good thing, too :).

A pencil is so far the most effective software design tool I have found...
--
Amanda Walker						      amanda@visix.com
Visix Software Inc.					...!uunet!visix!amanda
-- 
"A keyboard... how quaint!"	--Star Trek IV: The Voyage Home

cs450a03@uc780.umd.edu (04/19/91)

Joseph Allen    >
Me              >>
>>Let's say I was trying to implement a dynamically typed language in C.
>>(Of course, I wouldn't _really_ be that crazy  :-)  Let's say I wanted
>>to detect when, for instance, the addition of 2 integers produces an
>>invalid result.

>#define add(a,b) (a<0 && b<0 && a+b>=0 || a>=0 && b>=0 && a+b<0 ? error():a+b)

Ok, that should work, fairly generically I'd hope.

Now how do I generalize that to multiplication?

>I believe C is not really the problem.  What you want is for the
>processor to give an integer overflow signal so that the calculation
>can be repeated in floating point.  Unfortunately most (all?) don't.
> 
>Even in an interpretive language you'd have to:
> 
>	add
>	bov error
>	sub
>	bov error
>	mul
>	bov error

Interpretive??  That looks like _assembly_

Also note the existence of the new HP machines which have add and
branch semantics (and presumably multiply and branch).

I would hope that that's branch on overflow (though I haven't actually
asked -- if not you'd still have to execute two machine instructions
per HLL op).

Finally, note that a lot of time in assembly is spent in "routine
housekeeping" -- things like fetching and storing variable values, as
opposed to actually computing the results specified by the HLL.

Raul Rockwell

jallen@eeserv1.ic.sunysb.edu (Joseph Allen) (04/19/91)

In article <17APR91.21054415@uc780.umd.edu> cs450a03@uc780.umd.edu writes:
>Let's say I was trying to implement a dynamically typed language in C.
>(Of course, I wouldn't _really_ be that crazy  :-)  Let's say I wanted
>to detect when, for instance, the addition of 2 integers produces an
>invalid result.  Let's say that I can not accept a severe performance
>hit for this checking (most of the time, it's not going to happen.
>When it does happen, I'm going to switch to float -- performance must
>be better than floating point).

>How do I do it?

#define add(a,b) (a<0 && b<0 && a+b>=0 || a>=0 && b>=0 && a+b<0 ? error():a+b)

:-)

I believe C is not really the problem.  What you want is for the processor
to give an integer overflow signal so that the calculation can be repeated
in floating point.  Unfortunately most (all?) don't.

Even in an interpretive language you'd have to:

	add
	bov error
	sub
	bov error
	mul
	bov error

which is quite gross.
--
#define h 23 /* Height */         /* jallen@ic.sunysb.edu (129.49.12.74) */
#define w 79 /* Width */                       /* Amazing */
int i,r,b[]={-w,w,1,-1},d,a[w*h];m(p){a[p]=2;while(d=(p>2*w?!a[p-w-w]?1:0:0)|(
p<w*(h-2)?!a[p+w+w]?2:0:0)|(p%w!=w-2?!a[p+2]?4:0:0)|(p%w!=1?!a[p-2]?8:0:0)){do
i=3&(r=(r*57+1))/d;while(!(d&(1<<i)));a[p+b[i]]=2;m(p+2*b[i]);}}main(){r=time(
0L);m(w+1);for(i=0;i%w?0:printf("\n"),i!=w*h;i++)printf("#\0 "+a[i]);}

brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (04/19/91)

In article <17APR91.21054415@uc780.umd.edu> cs450a03@uc780.umd.edu writes:
> Let's say I was trying to implement a dynamically typed language in C.
> (Of course, I wouldn't _really_ be that crazy  :-)  Let's say I wanted
> to detect when, for instance, the addition of 2 integers produces an
> invalid result.

Okay, I know what you're about to say, and I agree with you completely.
One of the problems with C is that it supports so few arithmetic
operations: my favorite example is getting the high word of a multiply,
Herman Rubin's favorite example is dividing two floats and getting an
integer quotient and float remainder, and your example here is adding
two integers and getting an exception of some sort upon overflow. (Note
that any good language or library would provide both the unrestricted
operation of add-with-undefined-effects-upon-overflow and the restricted
operation here.)

Now what does this have to do with dynamic typing? Exception handling is
not dynamic typing.

---Dan

quale@saavik.cs.wisc.edu (Douglas E. Quale) (04/19/91)

In article <1991Apr17.173651.23103@visix.com> amanda@visix.com (Amanda Walker) writes:
>
>However, you can certainly *implement* dynamic typing in C, with as
>low an overhead as you can get in any other language.
>

This is not true.  A C implementation of dynamic typing will be slower.
A compiler for a dynamic language can take advantage of its knowledge of
datatype representations to generate faster code.

Two simple examples:

  1) tag operations for type discrimination

     A compiler for a dynamically typed language can dedicate a register to
     hold a bitmask that will speed type tag operations.  A C program would
     either use an immediate value or a global variable, either of which is
     slower and bulkier on many architectures.

  2) generic arithmetic

     Suppose the dynamic language includes generic arithmetic on integers of
     arbitrary size.  In lisp this would give two types of integer, fixnum
     and bignum.  A lisp compiler can add two fixnums inline and branch on
     the overflow flag to a bignum routine if the sum of the fixnums is too
     large.  C blithely ignores integer overflow.  In addition, some CPU
     architectures have special instructions to speed tagged arithmetic
     (notably the Sparc).  I would be surprised if C compilers were able to
     use that instruction for generic arithmetic.

... and there are numerous other type representation hacks that an
implementation of a dynamically-typed language system can exploit.

-- Doug Quale
saavik.cs.wisc.edu

eliot@cs.qmw.ac.uk (Eliot Miranda) (04/29/91)

In article <1991Apr19.132239.9252@daffy.cs.wisc.edu> quale@saavik.cs.wisc.edu (Douglas E. Quale) writes:
>In article <1991Apr17.173651.23103@visix.com> amanda@visix.com (Amanda Walker) writes:
>>
>>However, you can certainly *implement* dynamic typing in C, with as
>>low an overhead as you can get in any other language.
>>
>
>This is not true.  A C implementation of dynamic typing will be slower.
>A compiler for a dynamic language can take advantage of its knowledge of
>datatype representations to generate faster code.
>
>Two simple examples:
>
>  1) tag operations for type discrimination
>
>     A compiler for a dynamically typed language can dedicate a register to
>     hold a bitmask that will speed type tag operations.  A C program would
>     either use an immediate value or a global variable, either of which is
>     slower and bulkier on many architectures.
I have tried this in my Smalltalk VM. On both 68020 & SPARC there is no
significant difference in performance attributable to dedicating a register
to tag detection. Add a register here loose it there.
>
>  2) generic arithmetic
>
>     Suppose the dynamic language includes generic arithmetic on integers of
>     arbitrary size.  In lisp this would give two types of integer, fixnum
>     and bignum.  A lisp compiler can add two fixnums inline and branch on
>     the overflow flag to a bignum routine if the sum of the fixnums is too
>     large.  C blithely ignores integer overflow.  In addition, some CPU
>     architectures have special instructions to speed tagged arithmetic
>     (notably the Sparc).  I would be surprised if C compilers were able to
>     use that instruction for generic arithmetic.
>
>... and there are numerous other type representation hacks that an
>implementation of a dynamically-typed language system can exploit.

If you use gcc which has a) global register variables & b) a powerful
trap-door to assembler you can certainly produce as efficient a dynamic binder
in C as you could in any system.  I've written a quick threaded-code
Smalltalk VM in C with minimal assembler (the direct threaded code jump).
It would be easy to define Smalltalk objects at the C level.

I accept that using (or at least specifying a language in terms of) an abstract
machine leads to a concise design at one level.  This does not imply that
such a solution will be implementable more efficiently.

With persistence (& perversity) one can get C to compile to very efficient
machine code. With good compiler support (gcc) less persistence is required :-).
Using C as an assembler is becomming more & more popular because it works not
just because its relatively easy to do.
-- 
Eliot Miranda			email:	eliot@dcs.qmw.ac.uk
Dept of Computer Science	ARPA:	eliot%dcs.qmw.ac.uk@nsf.ac.uk
Queen Mary Westfield College	UUCP:	eliot@qmw-dcs.uucp
Mile End Road			Fax:	081 980 6533 (+44 81 980 6533)
LONDON E1 4NS			Tel:	071 975 5229 (+44 71 975 5229)

mathew@mantis.co.uk (mathew) (04/30/91)

eliot@cs.qmw.ac.uk (Eliot Miranda) writes:
> In article <1991Apr19.132239.9252@daffy.cs.wisc.edu> quale@saavik.cs.wisc.edu
> >     A compiler for a dynamically typed language can dedicate a register to
> >     hold a bitmask that will speed type tag operations.  A C program would
> >     either use an immediate value or a global variable, either of which is
> >     slower and bulkier on many architectures.
>
> I have tried this in my Smalltalk VM. On both 68020 & SPARC there is no
> significant difference in performance attributable to dedicating a register
> to tag detection. Add a register here loose it there.

You're saying that you've tried keeping the tags in memory vs. keeping them
in a register on a 68020, and you've not noticed any difference?  I find this
a little hard to believe.

Exactly what changes did you make to the code in order to use register-based
tags rather than memory-based tags, and what sort of program did you run in
order to test the result?


mathew

-- 
mathew - mathew@mantis.co.uk or mcsun!ukc!ibmpcug!mantis!mathew

quale@saavik.cs.wisc.edu (Douglas E. Quale) (05/01/91)

eliot@cs.qmw.ac.uk (Eliot Miranda) writes:
> In article <1991Apr19.132239.9252@daffy.cs.wisc.edu> quale@saavik.cs.wisc.edu
> >     A compiler for a dynamically typed language can dedicate a register to
> >     hold a bitmask that will speed type tag operations.  A C program would
> >     either use an immediate value or a global variable, either of which is
> >     slower and bulkier on many architectures.
>
> I have tried this in my Smalltalk VM. On both 68020 & SPARC there is no
> significant difference in performance attributable to dedicating a register
> to tag detection. Add a register here loose it there.
>

Experience in lisp implementation shows that it is often a good tradeoff to
dedicate one or two registers to tag masks.  Another trick is to have a
register pointing to a vector in memory that holds commonly used constants
and subroutines so that they can be accessed by a short immediate offset
register indirect mode.

The best papers in tagging issues for lisp are a couple by Hennessy.
One of the most interesting results is that even for lisp, the percentage of
execution time spent by ALL tag operations -- tag checking, extraction and
addition -- is much smaller than I would have thought.  I think it is a common
perception that static typing is always an order of magnitude faster than
dynamic binding, but this is not the case.

Analysis of Smalltalk implementation issues might give different results, of
course, and I am not familiar with the Smalltalk literature.

-- Doug Quale
quale@saavik.cs.wisc.edu

eliot@cs.qmw.ac.uk (Eliot Miranda) (05/01/91)

In article <7w4813w164w@mantis.co.uk> mathew@mantis.co.uk (mathew) writes:
>eliot@cs.qmw.ac.uk (Eliot Miranda) writes:
>> In article <1991Apr19.132239.9252@daffy.cs.wisc.edu> quale@saavik.cs.wisc.edu
>> >     A compiler for a dynamically typed language can dedicate a register to
>> >     hold a bitmask that will speed type tag operations.  A C program would
>> >     either use an immediate value or a global variable, either of which is
>> >     slower and bulkier on many architectures.
>>
>> I have tried this in my Smalltalk VM. On both 68020 & SPARC there is no
>> significant difference in performance attributable to dedicating a register
>> to tag detection. Add a register here loose it there.
>
>You're saying that you've tried keeping the tags in memory vs. keeping them
>in a register on a 68020, and you've not noticed any difference?  I find this
>a little hard to believe.
>
>Exactly what changes did you make to the code in order to use register-based
>tags rather than memory-based tags, and what sort of program did you run in
>order to test the result?
>
The program is a "dynamic translation to direct threaded code" Smalltalk-80
virtual machine written in C, compiled with GCC & edited into threaded code by
sed-scripts run on the compiler generated assembler.  The system is about
20,000 lines of C.  The system is tested by running the standard Smalltalk-80
macro benchmark suite, which produces a performance figure in percents of a
Dorado, Xerox's fastest D machine.

The format of tagged data is tags in the bottom 2 bits
	01 -> 30 bit signed integer
	10 -> 16 bit unsigned character
	11 -> 30 bit fixed point (16 bit fraction)
	00 -> Ordinary Object Pointer

Using GCC one can declare global register variables, e.g.
register void (**tcip)() asm("a5");
declares the threaded code instruction pointer to be in a5 on 68020s.

To test tags using immediate masks I use:

#define TagMask 3
#define isTagged(o) ((unsigned long)(o)&TagMask)

To test tags using a tag register I use:

#define TagMask 3
register unsigned long tagReg asm("d3");
#define isTagged ((unsigned long)(o)&tagReg)

	...

	tagReg = TagMask

	...

The code generated by the two sequences is either
	movel a3@,d6
	moveq #3,d2
	andl d6,d2
	jeq LABEL
or
	movel a3@,d6
	andl d3,d6
	jeq LABEL

When I compared the two variants they ran the benchmarks to within 0.5% of
each other.  This difference is below the noise and hence not significant.
I suspect that this is because
	a) moveq is very quick
	b) reserving a register for the tag mask slows down other parts of
	   the system, cancelling out.

Baically optimizations are tradeoffs between representations, and each
implementation of a given piece of functionality will have its performance and
its cost.
-- 
Eliot Miranda			email:	eliot@dcs.qmw.ac.uk
Dept of Computer Science	ARPA:	eliot%dcs.qmw.ac.uk@nsf.ac.uk
Queen Mary Westfield College	UUCP:	eliot@qmw-dcs.uucp
Mile End Road			Fax:	081 980 6533 (+44 81 980 6533)
LONDON E1 4NS			Tel:	071 975 5229 (+44 71 975 5229)