[comp.lang.objective-c] Implementation of Objective C

esink@turia.dit.upm.es (Eric W. Sink) (05/27/91)

Greetings all !  I recently posted a request for an Objective C
grammar to c.l.objective-c.  Well, I should have phrased my
question better, and I've come up with a few more.  I'm toying around
with the idea of implementing an ObjC compiler, but I currently know
little about the language.  I haven't had a chance to buy Cox's book
yet.  I do have ``Intro to Objective C on the NeXT Machine'', by
Gerrit Huizenga.  The information I'm looking for needs to be a bit
more precise.   Anyone willing to give answers to the following : ?

1.  What new keywords (in the ANSI C sense of a keyword) are added to
ANSI C ?  Which of the following are keywords, and which are not :
@interface, @implementation, @end, @selector, self, super, id, SEL,
nil, Object, new, free

2.  Is Object (the class) declared somewhere, or does the compiler
simply recognize it as already existent ?  If it is declared and
implemented somewhere using Objective C, why can't other root classes
exist ?  What does its declaration look like (I want to know how to
parse a class declaration which has no super class)

3.  I assume that a 'message send' is a primary expression, as it
appears in the ANSI C grammar.  In other words, the following
expressions are all possible :

   [ obj msg][12] = 33; /* assume the method returns (int *) */
   [ obj msg]();        /* assume the method returns a func ptr */
   x = a + *([obj msg]); /* again, method returns (int *) */

I also assume that the id and SEL elements of a message send are
postfix expressions, so the following is legal :

   id foo();
   SEL bar();
   [foo() bar()];

4.  Is a class (factory) object represented differently than an
instance ?  Are messages to a class object dispatched differently ?
How is new implemented ?  What other factory methods are implemented
by Object ?  isa (what does isa return, a factory object ? )?

5.  My biggest question :  How exactly does dispatching work ?  I
assume that every instance is a dynamically allocated region of memory
which contains all the instance variables PLUS a pointer to some data
structure.  I assume for now that this data structure is in fact the
factory object for the class of the instance, and that factory objects
contain the 1. dispatch table as well as a pointer to the 2. super class,
but it doesn't matter, as long as those two items are available
to each instance.  The dispatch table associates message selectors
with methods for the given class, so we take the message being sent,
convert it to a SEL, use the SEL as the index into the table and get
the address of the method.  Arguments have to get pushed onto the
stack (right to left ?), and the receiving object gets pushed (first
or last ?), and we call the method.  My questions :  how do we convert
the method name to a SEL ?  The manner in which this conversion occurs
is very important, because every source file which uses this class
must arrive at the same SEL for the same method name, and most
importantly, that SEL must be the same as the one calculated during
the actual genertion of the dispatch table, which I assume is
generated while compiling the @implementation of the class. (sentence
way to long, sorry)  What happens if the source file we are compiling,
uses many classes, and a given method foo: appears in more than one
place in the class hierarchy (assume that the various uses of foo: are
not inherited versions of the same method, but are quite distinct
methods along totally different lines of inheritance, but simply
happen to have the same name).  Now, how do we know which foo: to use
?  How do we map to a SEL ?  How to we type check arguments ?  How do
we know the type of the resulting message send ?  Is SEL of type
int (a table index requiring scaling) or of type char *, (a table
offset requiring no scaling).
  Consider the following example :  Is this code legal Objective C ?
  Since I see so many problems with it, I'm beginning to speculate
  that ObjC simply prohibits behavior like this...

@interface classone : Object
{
  int x,y;
}
- (long *) foo:(int) v1 :(short) v2;  /* This is foo:: */
@end

@interface classtwo : Object
{
   long a,b,c,d,e,f,g;
}
- bar;
- qwerty:vary;
- (short) foo:(int) a1 :(short) a2;  /* This is a distinct foo:: */
@end

@interface classthree : classone
- (short) foo:(short) v1 : (long) v2; /* Can I override a method with
a new method of different type ? */
@end

int main()
{
  id objekt;
  int k;

  k = [objekt foo:11:22];
  
  /* What is the type of the rhs of this
  assignment ? What is the SEL ? To what do we convert the arguments
  for pushing onto the stack ? */
}

I plead for patience with respect to my terribly trivial questions.
BTW, the few ObjC features exemplified in Huizenga's notes appear to
be enough for a usable language.  I speculate that ObjC doesn't
contain that much more (or else it would be the melting pot that C++
is).  Am I right ?

I really like the looks of Objective C.  I have some experience
implementing oo languages, but not compiled ones.  Separate
compilation does seem to offer some problems.  I was considering
implementing a subset of C++, but I'm leaning towards Objective C
instead.

Thanks in advance for any replies !

Eric


Eric W. Sink                     | "If no one is criticizing |Opinions
Departamento de Telematica       | your work, it is possible |mine -
Universidad Politecnica de Madrid| that you are not doing    |all of
esink@turia.dit.upm.es           | anything." -George Verwer |them.

lerman@stpstn.UUCP (Ken Lerman) (05/28/91)

In article <1991May27.073640.13936@dit.upm.es> esink@turia.dit.upm.es (Eric W. Sink) writes:
->
->Greetings all !  I recently posted a request for an Objective C
->grammar to c.l.objective-c.  Well, I should have phrased my
->question better, and I've come up with a few more.  I'm toying around
->with the idea of implementing an ObjC compiler, but I currently know
->little about the language.  I haven't had a chance to buy Cox's book
->yet.  I do have ``Intro to Objective C on the NeXT Machine'', by
->Gerrit Huizenga.  The information I'm looking for needs to be a bit
->more precise.   Anyone willing to give answers to the following : ?

->1.  What new keywords (in the ANSI C sense of a keyword) are added to
->ANSI C ?  Which of the following are keywords, and which are not :
->@interface, @implementation, @end, @selector, self, super, id, SEL,
->nil, Object, new, free

If it begins with @, it is a keyword.  Otherwise, it is NOT.  That is
from a language standpoint.  From a practical standpoint, it would be
bad form to (anbd might generate errors) to redefine id in some weird way.


->2.  Is Object (the class) declared somewhere, or does the compiler
->simply recognize it as already existent ?  If it is declared and
->implemented somewhere using Objective C, why can't other root classes
->exist ?  What does its declaration look like (I want to know how to
->parse a class declaration which has no super class)

@interface Object
{
@public
	struct _SHARED *isa;
	unsigned short	attr;
	unsigned short	objID;
}

Note that the Objective-C language and runtime permit you to have more
than one root class.  It is a quirk (feature ?) of Stepstone's
Objective-C 4.0 (and subsequent) implementation that it tests that there is an instance variable named "isa".

->
->3.  I assume that a 'message send' is a primary expression, as it
->appears in the ANSI C grammar.  In other words, the following
->expressions are all possible :
->
->   [ obj msg][12] = 33; /* assume the method returns (int *) */
->   [ obj msg]();        /* assume the method returns a func ptr */
->   x = a + *([obj msg]); /* again, method returns (int *) */

Yes, that is correct.

->I also assume that the id and SEL elements of a message send are
->postfix expressions, so the following is legal :

->   id foo();
->   SEL bar();
->   [foo() bar()];

Yes for the receiver, NO for the selector.  The selector is "looked
up" at compile time.  If you want to do [foo() bar()] you must do a
little more work and use [foo() perform:bar()].


->4.  Is a class (factory) object represented differently than an
->instance ?

NO.

->  Are messages to a class object dispatched differently ?

NO.

->How is new implemented ?
+ new
{ 
    id newObject = (*_alloc)((SHR)self, 0); 
    return newObject;
}

_alloc is a vector to alloc which uses malloc.

->  What other factory methods are implemented

+  initialize;
+  poseAs: aFactoryId;
+ (unsigned ) ndxVarSize;
+  new;
+  new: (unsigned) arg;
+  free;
+  readFrom:(STR )aFileName;
+ (SHR ) class;
+ (SHR ) self;
+ (SHR ) superClass;
+ (BOOL) isSubclassOf: aClass;
+ (BOOL ) instancesRespondTo:(STR )aSelector;
+ (IMP ) instanceMethodFor:(SEL )aSelector;

>by Object ?  isa (what does isa return, a factory object ? )?

isa is an instance variable of Object.  (See above)




->5.  My biggest question :  How exactly does dispatching work ?  I
->assume that every instance is a dynamically allocated region of memory
->which contains all the instance variables PLUS a pointer to some data
->structure.  I assume for now that this data structure is in fact the
->factory object for the class of the instance, and that factory objects
->contain the 1. dispatch table as well as a pointer to the 2. super class,
->but it doesn't matter, as long as those two items are available
->to each instance.  The dispatch table associates message selectors
->with methods for the given class, so we take the message being sent,
->convert it to a SEL, use the SEL as the index into the table and get
->the address of the method.  Arguments have to get pushed onto the
->stack (right to left ?), and the receiving object gets pushed (first
->or last ?), and we call the method.  My questions :  how do we convert
->the method name to a SEL ?  The manner in which this conversion occurs
->is very important, because every source file which uses this class
->must arrive at the same SEL for the same method name, and most
->importantly, that SEL must be the same as the one calculated during
->the actual genertion of the dispatch table, which I assume is
->generated while compiling the @implementation of the class. (sentence
->way to long, sorry)  What happens if the source file we are compiling,
->uses many classes, and a given method foo: appears in more than one
->place in the class hierarchy (assume that the various uses of foo: are
->not inherited versions of the same method, but are quite distinct
->methods along totally different lines of inheritance, but simply
->happen to have the same name).  Now, how do we know which foo: to use

The question of which foo: to use is a problem.  If they are declared
the same, it is easy.  If they are different, the current
implementation gives a warning and then uses one or the other.  If you
want to use the one associated with Apple, declare the receiver to be
an Apple * instead of an id, and you will get it (and no warning).

->?  How do we map to a SEL ?  How to we type check arguments ?  How do
->we know the type of the resulting message send ?  Is SEL of type
->int (a table index requiring scaling) or of type char *, (a table
->offset requiring no scaling).

Unfortunately, this subject is a little too complex to describe here.
Why not get a University license which will include the source to the
runtime and read the code.  Or buy a PC copy for a few hundred dollars
(I'm not in sales, so I can't give you a price).  The source of the runtime should be all you need to figure this stuff out.

->  Consider the following example :  Is this code legal Objective C ?
->  Since I see so many problems with it, I'm beginning to speculate
->  that ObjC simply prohibits behavior like this...
->
->@interface classone : Object
->{
->  int x,y;
->}
->- (long *) foo:(int) v1 :(short) v2;  /* This is foo:: */
->@end
->
->@interface classtwo : Object
->{
->   long a,b,c,d,e,f,g;
->}
->- bar;
->- qwerty:vary;
->- (short) foo:(int) a1 :(short) a2;  /* This is a distinct foo:: */
->@end
->
->@interface classthree : classone
->- (short) foo:(short) v1 : (long) v2; /* Can I override a method with
->a new method of different type ? */
->@end
->
->int main()
->{
->  id objekt;
->  int k;
->
->  k = [objekt foo:11:22];
->  
->  /* What is the type of the rhs of this
->  assignment ? What is the SEL ? To what do we convert the arguments
->  for pushing onto the stack ? */
->}

As stated above, you will get a warning concerning the ambiguous
selector.  I'm not sure whether you will get errors or warnings caused
by the types of the arguments not matching the selector type or not.
If you do not, and you are on a platform using ANSI C, you might get
automatic type conversion caused by message prototyping.  On a
non-ANSI platform, chars and shorts are automatically promoted to
ints.  floats are promoted to doubles.

->
->I plead for patience with respect to my terribly trivial questions.
->BTW, the few ObjC features exemplified in Huizenga's notes appear to
->be enough for a usable language.  I speculate that ObjC doesn't
->contain that much more (or else it would be the melting pot that C++
->is).  Am I right ?

I am not familiar with Huizenga's notes.  From a language standpoint,
Objective-C doesn't contain much more than you've discussed.  But the
runtime libraries can take a while to master.

->
->I really like the looks of Objective C.  I have some experience
->implementing oo languages, but not compiled ones.  Separate
->compilation does seem to offer some problems.  I was considering
->implementing a subset of C++, but I'm leaning towards Objective C
->instead.
->
->Thanks in advance for any replies !
->
->Eric
->
->
->Eric W. Sink                     | "If no one is criticizing |Opinions
->Departamento de Telematica       | your work, it is possible |mine -
->Universidad Politecnica de Madrid| that you are not doing    |all of
->esink@turia.dit.upm.es           | anything." -George Verwer |them.

Ken

shirley@gothamcity.jsc.nasa.gov (Bill Shirley) (05/30/91)

Mr Sink answered most of the questions with more knowledge than I,
but what I am wondering is this...

Doesn't Objective-C have some kind of runtime environment (like
LISP and smalltalk) ?  Doesn't this involve a little more than
just "writing a compiler" like you would for C (or FORTRAN,
Pascal, ...)?

That's how I understood it to be, am I wrong?

     ____     ____       ____			Bill Shirley
    / ___|   / ___|     / ___|			bill@gothamcity.jsc.nasa.gov
   |_|      |_|ciences |_|			_______________________________
    _omputer     _      _			Opinions expressed are obtained|
   | |___    ___| |    | |___orporation		by a room full of immortal apes|
    \____|  |____/      \____|			with unbreakable typewriters.  |
  						~~~~~~~~~~~DISCLAIMER~~~~~~~~~~~

esink@turia.dit.upm.es (Eric Wayne Sink) (05/31/91)

In article <1991May30.142255.27573@aio.jsc.nasa.gov> shirley@gothamcity.jsc.nasa.gov (Bill Shirley) writes:
>Mr Sink answered most of the questions with more knowledge than I,
>but what I am wondering is this...


Mr. Sink answered no questions at all.  Ken, from StepStone answered them.
Eric (that's me) asked them.

>
>Doesn't Objective-C have some kind of runtime environment (like
>LISP and smalltalk) ?  Doesn't this involve a little more than
>just "writing a compiler" like you would for C (or FORTRAN,
>Pascal, ...)?
>
>That's how I understood it to be, am I wrong?

I have learned that you are indeed right.  Writing the actual compiler
for Objective C is not all that hard.  The runtime system is far
hairier than I was expecting.

>     ____     ____       ____			Bill Shirley
>    / ___|   / ___|     / ___|			bill@gothamcity.jsc.nasa.gov

Eric



Eric W. Sink                     | "If no one is criticizing |Opinions
Departamento de Telematica       | your work, it is possible |mine -
Universidad Politecnica de Madrid| that you are not doing    |all of
esink@turia.dit.upm.es           | anything." -George Verwer |them.

lerman@stpstn.UUCP (Ken Lerman) (05/31/91)

In article <1991May30.142255.27573@aio.jsc.nasa.gov> shirley@gothamcity.jsc.nasa.gov (Bill Shirley) writes:
...
|>Doesn't Objective-C have some kind of runtime environment (like
|>LISP and smalltalk) ?  Doesn't this involve a little more than
|>just "writing a compiler" like you would for C (or FORTRAN,
|>Pascal, ...)?
...

Yes, Objective-C has a runtime environment.  (But C and Fortran do,
too.)  The Objective-C runtime includes the messager, object creation
and freeing code, and lots of other "twisty little passages, all different."

Ken