Path: csiph.com!v102.xanadu-bbs.net!xanadu-bbs.net!news.mixmin.net!aioe.org!.POSTED!not-for-mail From: "Rod Pemberton" Newsgroups: comp.lang.forth Subject: Re: ColorForth - another dead end? Date: Sat, 30 May 2015 15:34:52 -0400 Organization: Aioe.org NNTP Server Lines: 198 Message-ID: References: <78d1736a-9742-4e70-9539-bd41a3c7d44f@googlegroups.com> <34540e95-71cd-4f60-8c9f-f24bb438116e@googlegroups.com> <5ecf958e-bd96-4a9d-a32a-61f5d8a7b6ba@googlegroups.com> <9bc6ede1-d4bd-43f1-a684-6de2163fa7ab@googlegroups.com> <924c582d-d98f-4afb-876d-8a991a6a4727@googlegroups.com> NNTP-Posting-Host: n4wpt9zq8xR26Ttf9mo2BA.user.speranza.aioe.org Mime-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1; format=flowed; delsp=yes Content-Transfer-Encoding: 7bit X-Complaints-To: abuse@aioe.org User-Agent: Opera Mail/12.16 (Linux) X-Notice: Filtered by postfilter v. 0.8.2 Xref: csiph.com comp.lang.forth:39469 On Sat, 30 May 2015 01:22:27 -0400, Raimond Dragomir wrote: >> > C structs are powerful, the fields are associated with the object. >> >> You must specify the struct name and field in C to access the field. >> That's true with both of the component selection operators in C: >> '.' and '->' >> >> So, what do you mean by "the fields are associated with the object?" > > No you don't specify the struct name, you specify the object name which > happens to have the type of that struct. > I understand what you're saying. FYI, I refer to mystruct1, mystruct2 as the type of the struct, whereas obj1, obj2 are the names of the structs. > struct mystruct1 { int x; int y; } > struct mystruct2 { int y; int x; } > struct mystruct1 obj1; > struct mystruct2 obj2; > obj1.x > obj2.x > > Tell me how can you do that in Forth. You're familiar with the offsetof() macro for C, yes? I.e., every C compiler must have one or it's equivalent. It's usually coded similarly to this: #define offsetof(s,e) ((int)((char *)&((s *)0)->e-(char *)0)) That casts NULL, represented syntactically as '0' here, to a pointer to the start of 's' which is used to index 'e'. The address of s->e is taken which is relative to NULL and subtracts NULL the start of the struct to provide the offset of 'e' relative to the start of the struct. AIUI, Forth usually creates a bunch of custom words for each array for each offset. Those are like offsetof() which have hardcoded offset value for 'e'. In C, all objects are mapped onto an array of bytes. So, we can use arrays for structs in Forth, like C, and build up C like functionality from there. E.g., these take an address for the start of the struct: : OBJ1 ( a -- a+n ) 0 CELLS + ; : OBJ2 ( a -- a+n ) 1 CELLS + ; CREATE MYSTRUCT1 2 CELLS ALLOT CREATE MYSTRUCT2 2 CELLS ALLOT MYSTRUCT1 OBJ1 @ MYSTRUCT1 OBJ2 @ MYSTRUCT2 OBJ1 @ MYSTRUCT2 OBJ2 @ Of course, you could put the @ in offset definitions: : OBJ1 ( a -- i ) 0 CELLS + @ ; : OBJ2 ( a -- i ) 1 CELLS + @ ; CREATE MYSTRUCT1 2 CELLS ALLOT CREATE MYSTRUCT2 2 CELLS ALLOT MYSTRUCT1 OBJ1 MYSTRUCT1 OBJ2 MYSTRUCT2 OBJ1 MYSTRUCT2 OBJ2 Of course, you can define those to be their own words: : MYSTRUCTS1.OBJ1 MYSTRUCTS1 OBJ1 ; : MYSTRUCTS1.OBJ2 MYSTRUCTS1 OBJ2 ; : MYSTRUCTS2.OBJ1 MYSTRUCTS2 OBJ1 ; : MYSTRUCTS2.OBJ2 MYSTRUCTS2 OBJ2 ; MYSTRUCTS1.OBJ1 MYSTRUCTS1.OBJ2 MYSTRUCTS2.OBJ1 MYSTRUCTS2.OBJ2 Creating a more generic version in Forth might go something like: : OBJ1 0 ; : OBJ2 1 ; : OFFSETOF ( a n -- i ) CELLS + @ ; MYSTRUCTS1 OBJ1 OFFSETOF MYSTRUCTS1 OBJ2 OFFSETOF MYSTRUCTS2 OBJ1 OFFSETOF MYSTRUCTS2 OBJ2 OFFSETOF Or, if we rename OFFSETOF to '->' to be more C like: : -> ( a n -- i ) CELLS + @ ; MYSTRUCTS1 OBJ1 -> MYSTRUCTS1 OBJ2 -> MYSTRUCTS2 OBJ1 -> MYSTRUCTS2 OBJ2 -> Of course, those only work for CELL sized objects. You'd need to simulate C's sizeof() functionality in Forth to fix that. Forth doesn't have a typesystem, so that information must be hardcoded by you ... E.g., : OBJ1 0 1 ; \ cell size offset 0 : OBJ2 1 1 ; \ cell size offset 1 \ let's do some CHAR's too ... : OBJC1 1 0 ; \ char size offset of 1 : OBJC2 3 0 ; \ char size offset of 3 The second value is a flag to indicate CELL sized object. : -> ( a n x -- i ) IF CELLS THEN + @ ; Of course, that doesn't know if the size of the object to be fetched is a CELL or a CHAR, and so fetches a CELL which we probably don't want for a byte sized object, assuming it's a CHAR. Technically, Forth doesn't have type information, but it has two data types: CELL and CHAR. CELL serves as a large integer and as address pointers. Strings are passed as addresses. So, we can assume if not CELL then CHAR. : -> ( a n x -- i ) IF CELLS + @ ELSE + C@ THEN ; In full, : -> ( a n x -- i ) IF CELLS + @ ELSE + C@ THEN ; CREATE MYSTRUCT1 2 CELLS ALLOT CREATE MYSTRUCT2 2 CELLS ALLOT : OBJ1 0 1 ; \ cell size offset 0 : OBJ2 1 1 ; \ cell size offset 1 : OBJC1 1 0 ; \ byte size offset of 1 : OBJC3 3 0 ; \ byte size offset of 3 : MYSTRUCTS1.OBJ1 MYSTRUCTS1 OBJ1 -> ; : MYSTRUCTS1.OBJ2 MYSTRUCTS1 OBJ2 -> ; : MYSTRUCTS2.OBJ1 MYSTRUCTS2 OBJ1 -> ; : MYSTRUCTS2.OBJ2 MYSTRUCTS2 OBJ2 -> ; : MYSTRUCTS1.OBJC1 MYSTRUCTS1 OBJC1 -> ; \ char : MYSTRUCTS1.OBJC3 MYSTRUCTS1 OBJC3 -> ; \ char : MYSTRUCTS2.OBJC1 MYSTRUCTS2 OBJC1 -> ; \ char : MYSTRUCTS2.OBJC3 MYSTRUCTS2 OBJC3 -> ; \ char MYSTRUCTS1.OBJ1 MYSTRUCTS1.OBJ2 MYSTRUCTS2.OBJ1 MYSTRUCTS2.OBJ2 MYSTRUCTS1.OBJC1 MYSTRUCTS1.OBJC3 MYSTRUCTS2.OBJC1 MYSTRUCTS2.OBJC3 If you throw CREATE .. DOES> into the mix, you might be able to automate the process of creating all or many of those pre-liminary definitions. Hopefully, that's easy to do for someone here who is skilled in Forth. I.e., you could implement structs in Forth much like rudimentary arrays with only two possible types for each item, either CELL or CHAR . This is what they are in C but with some sizeof() and offsetof() information used by the compiler and additional types thrown in to the mix. http://www.forth.org/svfig/Len/arrays.htm http://www.forth.com/starting-forth/sf8/sf8.html > This is a price that Forth has to pay for it's simplicity. Agreed. As to whatever was going on in the rest of the thread with Hugh, I haven't really read that. Rod Pemberton -- If fewer guns reduced murders, how does one explain Moscow, Chicago, New York, and South Africa?