mist@wmt.UUCP (Michiel Steltman) (02/15/90)
Again, after the posting on CO2 two weeks ago, I post this (long) reply on request of a friend who has no access to usenet facilities. So, please, respond to him directly: pkr@media01.uucp , uunet!hp4nl!media01!pkr ############################################################### Dear readers The posting about CO2 of 2 weeks ago raised some questions that I would like to answer with this posting. >That looks pretty hot, but is it "CO2" or "Co2"? >James "Greenhouse" Salsman The name is derived from C Object Oriented, and is thus CO2. If you could see my original Macintosh derived file, you could also see the subscript. Unfortunately subscripts are a luxury in most computer systems. About the greenhouse effect, I can assure you that it is very hot, but of the kind which does not harm the environment. >Organization: Gore Enterprises >CO2 looks interesting, but I don't see any major differences between it and >Objective C. For example: > >> Objective C solves some of the problems but has the drawback >> that it is not available on all computers and needs special >> pre-processing. > >I suppose "special pre-processing" means compiling those parts of a >program that are in the Objective C language but not in the C language into >C code. For instance, converting > [rectangle moveBy:1.0 :2.0] >into something like > _msg(rectangle, "moveBy::", 1.0, 2.0) >and so on. > >If that's what was meant, that's certainly true---Objective C is a >different language than C, you can't just run an Objective C program >through a C compiler. But: > >> How is this CO2 used? It is very easy to use Co2, it is just >> like normal C and it consists of standard libraries with >> methods and a program called SYNTOR. > >Doesn't Syntor also perform "special pre-processing" on a CO2 program? >So, what exactly are the fundamental differences between CO2 and Objective C? > >Jacob Gore As I told in my message about CO2, there are not many differences between CO2 & Objective-C. But there is one very important difference, which is that the sources are NOT preprocessed. You can use any C-source and compile and link it in any CO2 application, I will try to explain how we did it by showing the activities to create a method in a class. The main difference with Obj. C is that all the definitions are maintained in a separate file (a <app>.s file). This file is run through Syntor which generates a <app>.c file that can be processed by any C compiler. The sources of the Syntor program are standard C again. If I want to create the message foo(a,b,c) in class Bar, the I enter the following definition in the .s file: >Object::Bar { data{int xyz;} message foo; }; Object::Puppet { data{int abc;}; message foo; }; This is translated by Syntor to the following: (functionally anyway) foo(self) { tableType t={ Puppet, om_Puppet_foo, Bar, om_Bar_foo }; dispatch(self, t); } This means that methods from the same message are grouped together. In objective C the methods of a class are grouped together, which explains the need of message routine. It is true that you need syntor to preprocess the .s file into a .c file. But when you are writing the application code this is rarely needed. It is only done when messages are added or instance variables are changed. So the big advantage over Obj. C is that turbo-c, quick-c and those other easy to use development environments with built-in editors can still be used. application definition file code +----+ syntor +-+--+ | +----+ +----+ | | | | | | | | .c | | |.s | -> | .c| | +-+ | | | | +----+ +----+ +----+ | / compiler +-----------------------+ | +----+ +-+--+ | | | | | .o | | | +-+ +----+ I hope that this explains your questions. If it is still not clear, or if you disagree with my arguments, please let me know. >From: kumamoto@sj.ate.slb.com (Danny Kumamoto) >I'm interested in your CO2. I don't care for C++ either. > >I'm using sort of an oo technique with plain C, but I don't >like the idea of writing everything from scratch, what is normally >available in Smalltalk (the latter really spoiled me in what I >now expect from a programming language). Sigh. >Thanks for any info. >Danny As I explained in the original story, CO2 is not a product. We have used it to develop a page-make up terminal for the newspaper market. Unfortunately we are not in the business of selling this kind of software. We have a debugger, windows system, collections and much more. But only a part of it is documented good enough to sell. We have therefore taken a part, the basic object system with: Bags, Sets, Ordered collections, Sorted collections, Array, Bytecollections, Strings, Dictionary and some other minor classes, and made a dos-diskette of it. If this generates enough interest, or if some componay would like to make it into a product then we are willing to supply the remainder of the code. >Peter- > >Your scheme for doing object-oriented programming in C is very >intriguing. I started to consider how I would implement this and >reached an impasse. Can you possibly send me the output from SYNTOR >on the ACCOUNT.S file you included in your example? > > Thanks, > Ralph (attunix.att.com!grk) The scheme we have been using is intriguing. It uses a mental switch because the way we have done it is 90 degrees from the smalltalk, C++ and objective C approach. Smalltalk started by grouping the messsages into a class Class Foo (Anybody knows where Foo comes from?) abc def Class Bar abc To find the correct method for a message Smalltalk looks into the dictionary of the class of the receiver: receiver -> class -> method dictionary | message -> + | method In CO2 which grouped the methods with the same name and indexed them on class. abc Foo om_Foo_abc Bar om_Bar_abc def Foo om_Foo_def The grouping is done by using the C linker. A message is a procedure. This procedure looks like: abc(self) { tableType t={ Foo om_Foo_abc, Bar,om_Bar_abc }; dispatch(self, t); } The dispatch routine looks in the table, locates the class of self in that table and finds the correct procedure (method). In real life it is a little bit more complex because the dispatching is done using a packed trie that is optimized with some tricks. This means that the lookup is done with 2 indexes. This lookup also handles the super send, does not understand and the full inheritance. The advantage this way are plenty. First a normal C compiler can be used because a message has become a normal procedure call. Second there are much less methods per message (CO2) than methods per class. (Smalltalk). I have included the sources of Syntor at the end. These are not the sources of account.s but of a comparable program. It put them at the end because it is pretty much and quite unreadable. I also included the file syntor.h so that you can translate the macro's. Goodluck. >Could Your Please Send me information ,price and availability >of CO2 environment > > 1) UNIX (?) > 2) DOS (?) >Thanks................ >Rodrigo Laurens (Secretary) CO2 is not a standard product, shrinked wrapped and the like. I have prepared a DOS floppy for the turbo C compiler that contains the sources of a basic system. Received: From the interest that this generates depend our action to make it a full blown product. (I would love to see it in a shrink wrapped version!). About Unix and other environments I can tell you that we have it running under RMX (one of the best O.S. in the world), Sun road runner, Macintosh, DOS (turbo-C) and the Watcom C compiler for the phar lap tools. Portability is very good because we use a subset of ANSI that is almost completely compatible with Kernighan & Ritchie. We use full prototypes but they can be removed by defining some macro's. >In a recent article in comp.lang.c++ I read about >CO2. The article mentioned source code availability >for $50. >Is this the complete package, or a crippled version >that demonstrates the system, but is no good for >real work? > >I am very interested in CO2 and would like to try >porting it to my Amiga. > >Please let me know what is included in the distribution. >Also, please indicate what form of payment is acceptable >to you. > It is not a crippled version. It demonstrates CO2 and you can use it to build life systems, as I have done many times. It is no complete product and has no manuals. So you can get it at your own risk. But the first version is only available for dos. To obtain the product you can send a Fax to Mediasystemen 31-23-315210 (holland) Please put the following words in the Fax We hereby ask you to send us a demo version of CO2 for dos. We will not use anything from this product for resale to any other party. Please specify mastercard number and expiration date for the $50. >Is it available for ftp somewhere? Could it become so? >How large is it (that is, could it be shar'd and mailed to comp.sources)? > > kipp hickman Unfortunately we do not have such facilities. But please refer to the previous question to see how you can obtain the demo diskette. I sure hope that I have answered the questions in a way that is understandable. Please realize that part of this work is hobby for me. As told before Mediasystemen is in the business of selling editorial systems and not software. but we think that this product is so nice that it should be shared by others. If there are more areas where I have not been clear, pleas send a mail to me and I will answer it as soon as possible. Peter Kriens pkr@media01.uucp Mediasystemen Holland Postbox 4932 2003 EX Haarlem 31-23-319075 Fax 31-23-315210 For the interested parties here is an output of syntor and the include file /* CO2 | SYNTOR MEDIASYSTEMEN (c) 1989 DATE : Sun Feb 4 07:58:39 1990 */ #include "syntor.h" /* TYPEDEFS FOR CLASSES */ typedef struct{ unsigned n ; unsigned capacity ; unsigned endPos ; unsigned startPos ; function sortBlock ; } typeSorted; #define szSorted sizeof(typeSorted) typedef struct{ unsigned n ; unsigned capacity ; } typeObjCol; #define szObjCol sizeof(typeObjCol) #define szObject 0 #define szCollect 0 #define szClass 0 #define szFactory 0 typedef struct{ unsigned n ; unsigned capacity ; unsigned endPos ; unsigned startPos ; } typeOrdered; #define szOrdered sizeof(typeOrdered) /**/ /* PUBLIC TABLE */ /* ------------------------------- */ /* F 3: Sorted */ PUBLIC(Sorted,3) /* F 5: ObjCol */ PUBLIC(ObjCol,5) /* F 7: Object */ PUBLIC(Object,7) /* F 9: Collect */ PUBLIC(Collect,9) /* F 11: Class */ PUBLIC(Class,11) /* F 13: Factory */ PUBLIC(Factory,13) /* F 15: Ordered */ PUBLIC(Ordered,15) /* F 1: Integer (dereferenced) */ PUBLIC(Integer,7) /* C : Integer class */ PUBLIC(IntegerClass,6) /* ------------------------------- */ /**/ /* OBJECT-TABLE */ /* ------------------------------- */ otBEGIN( 16) /* 0: ILLEGAL OBJECT */ otOBJCT(0,0,0) /* 1: INTEGER DEREFERENCE */ , otOBJCT(0,0,0) /*C 2: Sorted */ , otOBJCT( 10, szSorted, 3 ) /*F 3: Sorted */ , otOBJCT( 3, szSorted , 2 ) /*C 4: ObjCol */ , otOBJCT( 10, szObjCol, 5 ) /*F 5: ObjCol */ , otOBJCT( 5, szObjCol , 4 ) /*C 6: Object */ , otOBJCT( 10, szObject, 7 ) /*F 7: Object */ , otOBJCT( 7, szObject , 6 ) /*C 8: Collect */ , otOBJCT( 10, szCollect, 9 ) /*F 9: Collect */ , otOBJCT( 9, szCollect , 8 ) /*C 10: Class */ , otOBJCT( 10, szClass, 11 ) /*F 11: Class */ , otOBJCT( 11, szClass , 10 ) /*C 12: Factory */ , otOBJCT( 10, szFactory, 13 ) /*F 13: Factory */ , otOBJCT( 13, szFactory , 12 ) /*C 14: Ordered */ , otOBJCT( 10, szOrdered, 15 ) /*F 15: Ordered */ , otOBJCT( 15, szOrdered , 14 ) /* ------------------------------- */ otEND(16) /**/ /* SUPER-TABLE */ /* ------------------------------- */ stBEGIN(16) /* 0: ILLEGAL OBJECT */ stSUPER(0) /* 1: INTEGER DEREFERENCE */ , stSUPER(0) /* C 2: Ordered :: Sorted */ , stSUPER(14) /* F 3: Ordered :: Sorted */ , stSUPER(15) /* C 4: Collect :: ObjCol */ , stSUPER(8) /* F 5: Collect :: ObjCol */ , stSUPER(9) /* C 6: :: Object */ , stSUPER(0) /* F 7: :: Object */ , stSUPER(12) /* C 8: Object :: Collect */ , stSUPER(6) /* F 9: Object :: Collect */ , stSUPER(7) /* C 10: Object :: Class */ , stSUPER(6) /* F 11: Object :: Class */ , stSUPER(7) /* C 12: Class :: Factory */ , stSUPER(10) /* F 13: Class :: Factory */ , stSUPER(11) /* C 14: ObjCol :: Ordered */ , stSUPER(4) /* F 15: ObjCol :: Ordered */ , stSUPER(5) /* ------------------------------- */ stEND(16) /**/ /* MESSAGE TABLE */ /* - */ msEXTRN(om_Ordered_indexOf) /* 0: indexOf */ msBEGIN(indexOf) /* */ msNOIMPLM() /* - */ , msMETHD(14, om_Ordered_indexOf) /* 0: - */ msEND(2,0,0) /* - */ msEXTRN(om_Ordered_insertAt) /* 1: insertAt */ msBEGIN(insertAt) /* */ msNOIMPLM() /* - */ , msMETHD(14, om_Ordered_insertAt) /* 1: - */ msEND(2,1,1) /* - */ msEXTRN(om_Object_initialize) /* - */ msEXTRN(om_Sorted_initialize) /* - */ msEXTRN(om_ObjCol_initialize) /* - */ msEXTRN(om_Ordered_initialize) /* 2: initialize */ msBEGIN(initialize) /* - */ msSTUB(6, om_Object_initialize) /* - */ , msMETHD(2, om_Sorted_initialize) /* - */ , msMETHD(4, om_ObjCol_initialize) /* - */ , msMETHD(14, om_Ordered_initialize) /* 2: - */ msEND(4,2,2) /* - */ msEXTRN(om_Factory_newSize) /* 3: newSize */ msBEGIN(newSize) /* - */ msMETHD(12, om_Factory_newSize) /* 3: - */ msEND(1,3,3) /* - */ msEXTRN(om_Object_swap) /* 4: swap */ msBEGIN(swap) /* - */ msMETHD(6, om_Object_swap) /* 4: - */ msEND(1,4,4) /* - */ msEXTRN(om_Class_factoryOf) /* 5: factoryOf */ msBEGIN(factoryOf) /* */ msNOIMPLM() /* - */ , msMETHD(10, om_Class_factoryOf) /* 5: - */ msEND(2,5,14) /* - */ msEXTRN(om_Factory_new) /* 6: new */ msBEGIN(new) /* - */ msMETHD(12, om_Factory_new) /* 6: - */ msEND(1,6,5) /* - */ msEXTRN(om_Ordered_addLast) /* 7: addLast */ msBEGIN(addLast) /* */ msNOIMPLM() /* - */ , msMETHD(14, om_Ordered_addLast) /* 7: - */ msEND(2,7,6) /* - */ msEXTRN(om_Ordered_addFirst) /* 8: addFirst */ msBEGIN(addFirst) /* */ msNOIMPLM() /* - */ , msMETHD(14, om_Ordered_addFirst) /* 8: - */ msEND(2,8,8) /* - */ msEXTRN(om_Factory_classOf) /* 9: classOf */ msBEGIN(classOf) /* - */ msMETHD(12, om_Factory_classOf) /* 9: - */ msEND(1,9,7) /* - */ msEXTRN(om_ObjCol_size) /* 10: size */ msBEGIN(size) /* */ msNOIMPLM() /* - */ , msMETHD(4, om_ObjCol_size) /* 10: - */ msEND(2,10,26) /* - */ msEXTRN(om_Object_eq) /* 11: eq */ msBEGIN(eq) /* - */ msMETHD(6, om_Object_eq) /* 11: - */ msEND(1,11,9) /* - */ msEXTRN(om_Object_next) /* - */ msEXTRN(om_ObjCol_next) /* - */ msEXTRN(om_Ordered_next) /* 12: next */ msBEGIN(next) /* - */ msMETHD(6, om_Object_next) /* - */ , msMETHD(4, om_ObjCol_next) /* - */ , msMETHD(14, om_Ordered_next) /* 12: - */ msEND(3,12,29) /* - */ msEXTRN(om_Sorted_sortFromTo) /* 13: sortFromTo */ msBEGIN(sortFromTo) /* */ msNOIMPLM() /* - */ , msMETHD(2, om_Sorted_sortFromTo) /* 13: - */ msEND(2,13,10) /* - */ msEXTRN(om_Object_reset) /* 14: reset */ msBEGIN(reset) /* - */ msSTUB(6, om_Object_reset) /* 14: - */ msEND(1,14,11) /* - */ msEXTRN(om_Collect_doIt) /* 15: doIt */ msBEGIN(doIt) /* */ msNOIMPLM() /* - */ , msMETHD(8, om_Collect_doIt) /* 15: - */ msEND(2,15,30) /* - */ msEXTRN(om_Object_doesNotUnderstand) /* 16: doesNotUnderstand */ msBEGIN(doesNotUnderstand) /* - */ msMETHD(6, om_Object_doesNotUnderstand) /* 16: - */ msEND(1,16,12) /* - */ msEXTRN(om_Factory_elementSize) /* - */ msEXTRN(of_ObjCol_elementSize) /* 17: elementSize */ msBEGIN(elementSize) /* - */ msSTUB(12, om_Factory_elementSize) /* - */ , msMETHD(5, of_ObjCol_elementSize) /* 17: - */ msEND(2,17,32) /* - */ msEXTRN(om_Object_release) /* 18: release */ msBEGIN(release) /* - */ msSTUB(6, om_Object_release) /* 18: - */ msEND(1,18,13) /* - */ msEXTRN(om_Object_dispose) /* - */ msEXTRN(om_Collect_dispose) /* 19: dispose */ msBEGIN(dispose) /* - */ msMETHD(6, om_Object_dispose) /* - */ , msMETHD(8, om_Collect_dispose) /* 19: - */ msEND(2,19,37) /* - */ msEXTRN(om_Object_hash) /* 20: hash */ msBEGIN(hash) /* - */ msMETHD(6, om_Object_hash) /* 20: - */ msEND(1,20,15) /* - */ msEXTRN(om_Object_error) /* 21: error */ msBEGIN(error) /* - */ msMETHD(6, om_Object_error) /* 21: - */ msEND(1,21,16) /* - */ msEXTRN(om_Collect_grow) /* 22: grow */ msBEGIN(grow) /* */ msNOIMPLM() /* - */ , msMETHD(8, om_Collect_grow) /* 22: - */ msEND(2,22,44) /* - */ msEXTRN(om_Sorted_add) /* - */ msEXTRN(om_Ordered_add) /* 23: add */ msBEGIN(add) /* */ msNOIMPLM() /* - */ , msMETHD(2, om_Sorted_add) /* - */ , msMETHD(14, om_Ordered_add) /* 23: - */ msEND(3,23,40) /* - */ msEXTRN(om_Object_species) /* 24: species */ msBEGIN(species) /* - */ msMETHD(6, om_Object_species) /* 24: - */ msEND(1,24,17) /* - */ msEXTRN(om_Ordered_addBefore) /* 25: addBefore */ msBEGIN(addBefore) /* */ msNOIMPLM() /* - */ , msMETHD(14, om_Ordered_addBefore) /* 25: - */ msEND(2,25,47) /**/ /* --------------------------------- */ /* Use 8 bit table */ tr8() /* --------------------------------- */ /* */ trSTART(62) /* _ 0 */ trEMPTY(0,0) /* _ 1 */ , trEMPTY(0,0) /* om Ordered indexOf 2 */ , trMETHOD(2,1) /* om Ordered insertAt 3 */ , trMETHOD(2,1) /* om Sorted initialize 4 */ , trMETHOD(2,1) /* _ 5 */ , trEMPTY(0,0) /* om ObjCol initialize 6 */ , trMETHOD(4,2) /* _ 7 */ , trEMPTY(0,0) /* om Ordered addLast 8 */ , trMETHOD(2,1) /* _ 9 */ , trEMPTY(0,0) /* om Ordered addFirst 10 */ , trMETHOD(2,1) /* _ 11 */ , trEMPTY(0,0) /* om Sorted sortFromTo 12 */ , trMETHOD(2,1) /* _ 13 */ , trEMPTY(0,0) /* om Ordered indexOf 14 */ , trMETHOD(14,1) /* om Ordered insertAt 15 */ , trMETHOD(14,1) /* om Ordered initialize 16 */ , trMETHOD(14,3) /* om Class factoryOf 17 */ , trMETHOD(3,1) /* _ 18 */ , trEMPTY(0,0) /* om Class factoryOf 19 */ , trMETHOD(5,1) /* om Ordered addLast 20 */ , trMETHOD(14,1) /* om Class factoryOf 21 */ , trMETHOD(7,1) /* om Ordered addFirst 22 */ , trMETHOD(14,1) /* om Class factoryOf 23 */ , trMETHOD(9,1) /* om Class factoryOf 24 */ , trMETHOD(10,1) /* om Class factoryOf 25 */ , trMETHOD(11,1) /* om Class factoryOf 26 */ , trMETHOD(12,1) /* om Class factoryOf 27 */ , trMETHOD(13,1) /* om ObjCol size 28 */ , trMETHOD(2,1) /* om Class factoryOf 29 */ , trMETHOD(15,1) /* om ObjCol size 30 */ , trMETHOD(4,1) /* om Ordered next 31 */ , trMETHOD(2,2) /* om Collect doIt 32 */ , trMETHOD(2,1) /* om ObjCol next 33 */ , trMETHOD(4,1) /* om Collect doIt 34 */ , trMETHOD(4,1) /* of ObjCol elementSize 35 */ , trMETHOD(3,1) /* _ 36 */ , trEMPTY(0,0) /* of ObjCol elementSize 37 */ , trMETHOD(5,1) /* om Collect doIt 38 */ , trMETHOD(8,1) /* om Collect dispose 39 */ , trMETHOD(2,1) /* om ObjCol size 40 */ , trMETHOD(14,1) /* om Collect dispose 41 */ , trMETHOD(4,1) /* om Sorted add 42 */ , trMETHOD(2,1) /* om Ordered next 43 */ , trMETHOD(14,2) /* om Collect doIt 44 */ , trMETHOD(14,1) /* om Collect dispose 45 */ , trMETHOD(8,1) /* om Collect grow 46 */ , trMETHOD(2,1) /* of ObjCol elementSize 47 */ , trMETHOD(15,1) /* om Collect grow 48 */ , trMETHOD(4,1) /* om Ordered addBefore 49 */ , trMETHOD(2,1) /* _ 50 */ , trEMPTY(0,0) /* om Collect dispose 51 */ , trMETHOD(14,1) /* om Collect grow 52 */ , trMETHOD(8,1) /* _ 53 */ , trEMPTY(0,0) /* om Ordered add 54 */ , trMETHOD(14,2) /* _ 55 */ , trEMPTY(0,0) /* _ 56 */ , trEMPTY(0,0) /* _ 57 */ , trEMPTY(0,0) /* om Collect grow 58 */ , trMETHOD(14,1) /* _ 59 */ , trEMPTY(0,0) /* _ 60 */ , trEMPTY(0,0) /* om Ordered addBefore 61 */ , trMETHOD(14,1) /* - */ trEND() /**/ /* INITIAL PROCS */ /* ------------------------------- */ /* ------------------------------- */ inBEGIN() /* ------------------------------- */ inEND() /**/ /* SETTINGS */ /* ------------------------------- */ /* objtable grow increment */ INCREMENT(250) /* Exception handler */ EXCEPTION(doNothing) #include "syntor.h" The file syntor.h: /* V1.4 */ #ifdef SYNTORFIRST oj_tableType * oj_table = oj_startTable; unsigned oj_count; unsigned oj_free; #else #include "co2.h" #include "point.h" extern void doNothing(); extern void noMethod(); void (*oj_jump)(); typedef struct { char * method; } tT; typedef struct { unsigned class:11; unsigned index:5; } trieRecord; #define otBEGIN(l) oj_tableType oj_startTable[ l ] = { #define otOBJCT(cl,sz,p) sz, cl, (char *) p #define otEND(l) }; unsigned oj_length = l; #define stBEGIN(l) object oj_super[ l + 1 ] = { #define stSUPER(nr) nr #define stEND(l) }; #define msEXTRN(name) extern void name(); #define msBEGIN(name) void name(self){static tT t[]={ #define msMETHD(id,name) (char *)name #define msSTUB(id,name) (char *)doNothing #define msEND(nr,seq,stat) }; (*oj_jump)(self,t,stat ); } #define msNOIMPLM() (char *) noMethod #define tr8() #define tr16() #define trSTART(s) trieRecord Trie[s] = { #define trEMPTY(n,a) 0,0 #define trMETHOD(n,a) n,a #define trSTUB(n,a) n,a #define trEND() }; #define inEXTRN(name) extern void name(); #define inBEGIN() void oj_initial() { #define inPROCE(name) name(); #define inEND() } #define PUBLIC(name,val) object name = val; #define INCREMENT(v) unsigned oj_incr = v; #define EXCEPTION(v) extern void v(); char *exceptionHandler=(char *) v; #define SYNTORFIRST 1 #endif ======= -- Michiel Steltman hp4nl!wmt!mist +-----------------------------+ Westmount Technology B.V. | Phone: +31 15 610815 | Poortweg 8, 2612 PA Delft | Fax: +31 15 565701 | The Netherlands +-----------------------------+