Rocksolid Light

Welcome to novaBBS (click a section below)

mail  files  register  newsreader  groups  login

Message-ID:  

"And remember: Evil will always prevail, because Good is dumb." -- Spaceballs


devel / comp.lang.forth / Another mini-oop

SubjectAuthor
* Another mini-oopDoug Hoffman
+* Re: Another mini-oopNN
|+* Re: Another mini-oopDoug Hoffman
||`* Re: Another mini-oopRuvim
|| `* Re: Another mini-oopDoug Hoffman
||  `* Re: Another mini-oopRuvim
||   `- Re: Another mini-oopDoug Hoffman
|`* Re: Another mini-oopAnton Ertl
| `- Re: Another mini-oopNN
+- Re: Another mini-oopHugh Aguilar
+* Re: Another mini-oopnone
|`* Re: Another mini-oopDoug Hoffman
| `* Re: Another mini-oopdxforth
|  `- Re: Another mini-oopDoug Hoffman
+* Re: Another mini-oopRuvim
|`* Re: Another mini-oopDoug Hoffman
| +* Re: Another mini-oopRuvim
| |`* Re: Another mini-oopDoug Hoffman
| | `* Re: Another mini-oopRuvim
| |  `- Re: Another mini-oopDoug Hoffman
| +* Re: Another mini-oopRuvim
| |`* Re: Another mini-oopDoug Hoffman
| | `* Re: Another mini-oopRuvim
| |  `- Re: Another mini-oopDoug Hoffman
| `* Re: Another mini-oopRuvim
|  +* Re: Another mini-oopDoug Hoffman
|  |+- Re: Another mini-ooppahihu
|  |`- Re: Another mini-oopRuvim
|  `- Re: Another mini-oopDoug Hoffman
+* Re: Another mini-ooppahihu
|`- Re: Another mini-oopDoug Hoffman
`* Re: Another mini-oopluser droog
 +* Re: Another mini-oopluser droog
 |`- Re: Another mini-oopAnton Ertl
 `* Re: Another mini-oopDoug Hoffman
  `* Re: Another mini-oopluser droog
   `* Re: Another mini-oopDoug Hoffman
    +* Re: Another mini-oopluser droog
    |`- Re: Another mini-oopDoug Hoffman
    `- Re: Another mini-oopluser droog

Pages:12
Another mini-oop

<613dfe6e$0$700$14726298@news.sunsite.dk>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=14594&group=comp.lang.forth#14594

  copy link   Newsgroups: comp.lang.forth
Path: i2pn2.org!i2pn.org!usenet.goja.nl.eu.org!dotsrc.org!filter.dotsrc.org!news.dotsrc.org!not-for-mail
From: dhoffman...@gmail.com (Doug Hoffman)
Subject: Another mini-oop
Newsgroups: comp.lang.forth
X-Mozilla-News-Host: news://news.sunsite.dk
Date: Sun, 12 Sep 2021 09:19:42 -0400
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:78.0)
Gecko/20100101 Thunderbird/78.14.0
MIME-Version: 1.0
Content-Type: text/plain; charset=utf-8; format=flowed
Content-Language: en-US
Content-Transfer-Encoding: 7bit
Lines: 83
Message-ID: <613dfe6e$0$700$14726298@news.sunsite.dk>
Organization: SunSITE.dk - Supporting Open source
NNTP-Posting-Host: 2a8d374f.news.sunsite.dk
X-Trace: 1631452782 news.sunsite.dk 700 glidedog@gmail.com/68.55.82.126:49597
X-Complaints-To: staff@sunsite.dk
 by: Doug Hoffman - Sun, 12 Sep 2021 13:19 UTC

After paring away, the following code would be my idea of a mini-oop
extension for Forth. Not a 12 liner, but loc will be recovered quickly
as classes are written. Thanks to Bernd Paysan for a couple of ideas:

-Doug

\ *** begin code
0 value self
: dfa ( cls -- a) 8 cells + ;
: _mfa ( adr -- ofs) dup >r 2/ 2/ r@ xor 2/ 2/ r> xor 7 and cells ;
: mfa ( sel cls -- sel mfa) over _mfa + ;
: fm ( sel mfa -- xt) begin @ dup while 2dup cell+ @ =
if 2 cells + nip @ exit then repeat -1 abort" method?" ;
: class ( supClass 'name' -- cls) create here >r
9 cells dup allot r@ swap move r> ;
: makeSel ( 'name' -- sel ) create here dup _mfa c, 254 c,
does> over @ over c@ + fm self >r swap to self execute r> to self ;
: sel ( 'name' -- sel ) >in @ bl word find if >body dup 1+ c@ 254 =
if nip exit then then drop >in ! makeSel ;
: :m ( cls 'name' -- a xt) sel over mfa
here over @ , swap ! , here 0 , :noname ;
: ;m ( a xt -- ) postpone ; swap ! ; immediate
: :: ( cls 'name' -- ) ' >body swap mfa fm compile, ; immediate
: (ivar) ( offset 'name' -- ) create , does> ( -- addr ) @ self + ;
: var ( cls n 'name' -- ) over dfa dup @ (ivar) +! ;
create object 9 cells dup allot object swap erase cell object dfa !
object :m :init ;m drop
: new ( cls -- obj) dup dfa @ here swap allot tuck ! dup >r :init r> ;
: .. ( obj 'name' -- adr) ' >body @ + ;
\ *** end code

0 [if] \ usage example

object class button
cell var text
cell var len
cell var x
cell var y
:m :init ( addr u -- ) len ! text ! 0 x ! 0 y ! ;m
:m draw x @ y @ at-xy text @ len @ type ;m
drop

\ inheritance

: bold 27 emit ." [1m" ;
: normal 27 emit ." [0m" ;

button class bold-button
:m draw bold [ button :: draw ] normal ;m
drop

\ Create and draw the buttons:

s" normal button" button new constant foo
s" bold button" bold-button new constant bar
1 bar .. y !
page
foo draw
bar draw

[then]

0 [if] \ another example
\ note re-use of draw (and there is no inheritance relationship)
object class point
cell var x
cell var y
:m p! ( x y -- ) y ! x ! ;m
:m p@ ( -- x y ) x @ y @ ;m
:m draw x ? y ? ;m
:m :init ( x y -- ) self p! ;m \ late bind
\ :m :init ( x y -- ) [ point :: p! ] ;m \ alternatively early bind
drop

1 2 point new constant p1
p1 draw cr
foo draw \ draw still works on foo and bar
page bar draw
: test 3 4 p1 p! p1 draw p1 .. x @ p1 .. y @ + . ;
test
\ => 3 4 7

[then]

Re: Another mini-oop

<ad6f177f-ceb7-42b6-b698-ed5309fb68a3n@googlegroups.com>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=14607&group=comp.lang.forth#14607

  copy link   Newsgroups: comp.lang.forth
X-Received: by 2002:ad4:55eb:: with SMTP id bu11mr7855995qvb.57.1631484097615;
Sun, 12 Sep 2021 15:01:37 -0700 (PDT)
X-Received: by 2002:a05:622a:1911:: with SMTP id w17mr7281449qtc.228.1631484097381;
Sun, 12 Sep 2021 15:01:37 -0700 (PDT)
Path: i2pn2.org!i2pn.org!weretis.net!feeder8.news.weretis.net!proxad.net!feeder1-2.proxad.net!209.85.160.216.MISMATCH!news-out.google.com!nntp.google.com!postnews.google.com!google-groups.googlegroups.com!not-for-mail
Newsgroups: comp.lang.forth
Date: Sun, 12 Sep 2021 15:01:37 -0700 (PDT)
In-Reply-To: <613dfe6e$0$700$14726298@news.sunsite.dk>
Injection-Info: google-groups.googlegroups.com; posting-host=2a00:23c5:6f05:3a01:c010:9962:4db9:63e1;
posting-account=9A5f7goAAAD_QfJPZnlK3Xq_UhzYjdP-
NNTP-Posting-Host: 2a00:23c5:6f05:3a01:c010:9962:4db9:63e1
References: <613dfe6e$0$700$14726298@news.sunsite.dk>
User-Agent: G2/1.0
MIME-Version: 1.0
Message-ID: <ad6f177f-ceb7-42b6-b698-ed5309fb68a3n@googlegroups.com>
Subject: Re: Another mini-oop
From: november...@gmail.com (NN)
Injection-Date: Sun, 12 Sep 2021 22:01:37 +0000
Content-Type: text/plain; charset="UTF-8"
 by: NN - Sun, 12 Sep 2021 22:01 UTC

On Sunday, 12 September 2021 at 14:20:02 UTC+1, Doug Hoffman wrote:
> After paring away, the following code would be my idea of a mini-oop
> extension for Forth. Not a 12 liner, but loc will be recovered quickly
> as classes are written. Thanks to Bernd Paysan for a couple of ideas:
>
> -Doug
>
> \ *** begin code
> 0 value self
> : dfa ( cls -- a) 8 cells + ;
> : _mfa ( adr -- ofs) dup >r 2/ 2/ r@ xor 2/ 2/ r> xor 7 and cells ;
> : mfa ( sel cls -- sel mfa) over _mfa + ;
> : fm ( sel mfa -- xt) begin @ dup while 2dup cell+ @ =
> if 2 cells + nip @ exit then repeat -1 abort" method?" ;
> : class ( supClass 'name' -- cls) create here >r
> 9 cells dup allot r@ swap move r> ;
> : makeSel ( 'name' -- sel ) create here dup _mfa c, 254 c,
> does> over @ over c@ + fm self >r swap to self execute r> to self ;
> : sel ( 'name' -- sel ) >in @ bl word find if >body dup 1+ c@ 254 =
> if nip exit then then drop >in ! makeSel ;
> : :m ( cls 'name' -- a xt) sel over mfa
> here over @ , swap ! , here 0 , :noname ;
> : ;m ( a xt -- ) postpone ; swap ! ; immediate
> : :: ( cls 'name' -- ) ' >body swap mfa fm compile, ; immediate
> : (ivar) ( offset 'name' -- ) create , does> ( -- addr ) @ self + ;
> : var ( cls n 'name' -- ) over dfa dup @ (ivar) +! ;
> create object 9 cells dup allot object swap erase cell object dfa !
> object :m :init ;m drop
> : new ( cls -- obj) dup dfa @ here swap allot tuck ! dup >r :init r> ;
> : .. ( obj 'name' -- adr) ' >body @ + ;
> \ *** end code
>
> 0 [if] \ usage example
>
> object class button
> cell var text
> cell var len
> cell var x
> cell var y
> :m :init ( addr u -- ) len ! text ! 0 x ! 0 y ! ;m
> :m draw x @ y @ at-xy text @ len @ type ;m
> drop
>
> \ inheritance
>
> : bold 27 emit ." [1m" ;
> : normal 27 emit ." [0m" ;
>
> button class bold-button
> :m draw bold [ button :: draw ] normal ;m
> drop
>
> \ Create and draw the buttons:
>
> s" normal button" button new constant foo
> s" bold button" bold-button new constant bar
> 1 bar .. y !
> page
> foo draw
> bar draw
>
> [then]
>
> 0 [if] \ another example
> \ note re-use of draw (and there is no inheritance relationship)
> object class point
> cell var x
> cell var y
> :m p! ( x y -- ) y ! x ! ;m
> :m p@ ( -- x y ) x @ y @ ;m
> :m draw x ? y ? ;m
> :m :init ( x y -- ) self p! ;m \ late bind
> \ :m :init ( x y -- ) [ point :: p! ] ;m \ alternatively early bind
> drop
>
> 1 2 point new constant p1
> p1 draw cr
> foo draw \ draw still works on foo and bar
> page bar draw
> : test 3 4 p1 p! p1 draw p1 .. x @ p1 .. y @ + . ;
> test
> \ => 3 4 7
>
> [then]

Recently, I have been reading a little about the history of smalltalk. This lead me to Self.
They introduced me to the idea of class based oop vs prototype based oop.

I think most forth oop implementations I have seen appear to be class based.

Does anyone know why many if not all forths seem to favor the class based approach ?

Re: Another mini-oop

<613e8212$0$703$14726298@news.sunsite.dk>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=14608&group=comp.lang.forth#14608

  copy link   Newsgroups: comp.lang.forth
Path: i2pn2.org!i2pn.org!aioe.org!news.uzoreto.com!dotsrc.org!filter.dotsrc.org!news.dotsrc.org!not-for-mail
Subject: Re: Another mini-oop
Newsgroups: comp.lang.forth
References: <613dfe6e$0$700$14726298@news.sunsite.dk>
<ad6f177f-ceb7-42b6-b698-ed5309fb68a3n@googlegroups.com>
From: dhoffman...@gmail.com (Doug Hoffman)
Date: Sun, 12 Sep 2021 18:41:18 -0400
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:78.0)
Gecko/20100101 Thunderbird/78.14.0
MIME-Version: 1.0
In-Reply-To: <ad6f177f-ceb7-42b6-b698-ed5309fb68a3n@googlegroups.com>
Content-Type: text/plain; charset=utf-8; format=flowed
Content-Language: en-US
Content-Transfer-Encoding: 7bit
Lines: 21
Message-ID: <613e8212$0$703$14726298@news.sunsite.dk>
Organization: SunSITE.dk - Supporting Open source
NNTP-Posting-Host: 066dfd11.news.sunsite.dk
X-Trace: 1631486482 news.sunsite.dk 703 glidedog@gmail.com/68.55.82.126:54535
X-Complaints-To: staff@sunsite.dk
 by: Doug Hoffman - Sun, 12 Sep 2021 22:41 UTC

On 9/12/21 6:01 PM, NN wrote:

> Recently, I have been reading a little about the history of smalltalk. This lead me to Self.
> They introduced me to the idea of class based oop vs prototype based oop.
>
> I think most forth oop implementations I have seen appear to be class based.
>
> Does anyone know why many if not all forths seem to favor the class based approach ?

I have read some about the Meta Object Protocol. It made my head hurt.
If there is an advantage to the prototype based approach, and there may
be, I don't know it. Perhaps if someone provided working prototype based
code in Forth then maybe I could better compare and contrast the two
approaches.

Class based seems simplest to implement and understand, not entirely
sure. But we tend to favor simplicity in Forth as long as we don't give
up important functionality.

-Doug

Re: Another mini-oop

<2021Sep13.112412@mips.complang.tuwien.ac.at>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=14623&group=comp.lang.forth#14623

  copy link   Newsgroups: comp.lang.forth
Path: i2pn2.org!i2pn.org!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail
From: ant...@mips.complang.tuwien.ac.at (Anton Ertl)
Newsgroups: comp.lang.forth
Subject: Re: Another mini-oop
Date: Mon, 13 Sep 2021 09:24:12 GMT
Organization: Institut fuer Computersprachen, Technische Universitaet Wien
Lines: 47
Message-ID: <2021Sep13.112412@mips.complang.tuwien.ac.at>
References: <613dfe6e$0$700$14726298@news.sunsite.dk> <ad6f177f-ceb7-42b6-b698-ed5309fb68a3n@googlegroups.com>
Injection-Info: reader02.eternal-september.org; posting-host="adc1cc9999d4f6f902b7838f9a4a2636";
logging-data="4569"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX18naZZO9FU3CAkkHZcI+g+n"
Cancel-Lock: sha1:I42gngzLaFjeJl7vMmxdij8KgX0=
X-newsreader: xrn 10.00-beta-3
 by: Anton Ertl - Mon, 13 Sep 2021 09:24 UTC

NN <november.nihal@gmail.com> writes:
>Does anyone know why many if not all forths seem to favor the class based approach ?

A straightforward implementation of the prototype approach results on
one dispatch table per object, which costs quite a bit of memory.
Real-world prototype-based object-oriented languages optimize this by
deduplicating equal dispatch tables, which costs some complexity
(e.g., you need to reduplicate the table if the table is changed for
one of the objects). In the spirit of letting the programmer do the
work rather than the computer, class-based is preferable to
prototype-based.

But looking at the wider programming world, nearly all popular OO
languages are class-based, with JavaScript being the exception that
proves the rule. That is probably because classes are seen as
organizing principle, and even in a prototype-based language
programmers tend to think in terms of classes. So why not have them
as programming-language concept?

That being said, the new Gforth header is a prototype-based system
(but with a given, unextensible interface), rather than a class-based
system. That's because the interface to words works by creating a
word and then modifying it (with IMMEDIATE, SET-DOES>, SET-OPTIMIZE
etc.), so a class-based interface would not work. Consequently,
Gforth employs deduplication (there are only ~100 different tables for
4000 words, most of them due to SET-DOES>) and reduplication.

Given that deduplication is expensive (we use linear search),
eventually we have also introduced CREATE-FROM, which would just
create a word with the same table as another word, already
deduplicated. The way we use CREATE-FROM is, e.g.

['] >body create-from reveal

where >BODY is the prototype word. In the current sources, the
prototypes are all words that are otherwise useful, but from what I
read, a frequent pattern in prototype-based languages is to define a
prototype just to have a template for generating more objects of the
same type, which again indicates that classes are an organizing
principle wanted by programmers.

- anton
--
M. Anton Ertl http://www.complang.tuwien.ac.at/anton/home.html
comp.lang.forth FAQs: http://www.complang.tuwien.ac.at/forth/faq/toc.html
New standard: http://www.forth200x.org/forth200x.html
EuroForth 2021: https://euro.theforth.net/2021

Re: Another mini-oop

<7deec1bf-3063-4bd3-94d6-8579450d4c42n@googlegroups.com>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=14626&group=comp.lang.forth#14626

  copy link   Newsgroups: comp.lang.forth
X-Received: by 2002:a05:620a:15e8:: with SMTP id p8mr9627433qkm.27.1631534416051;
Mon, 13 Sep 2021 05:00:16 -0700 (PDT)
X-Received: by 2002:a05:622a:3d4:: with SMTP id k20mr8890129qtx.417.1631534415784;
Mon, 13 Sep 2021 05:00:15 -0700 (PDT)
Path: i2pn2.org!i2pn.org!weretis.net!feeder6.news.weretis.net!news.misty.com!border2.nntp.dca1.giganews.com!nntp.giganews.com!news-out.google.com!nntp.google.com!postnews.google.com!google-groups.googlegroups.com!not-for-mail
Newsgroups: comp.lang.forth
Date: Mon, 13 Sep 2021 05:00:15 -0700 (PDT)
In-Reply-To: <2021Sep13.112412@mips.complang.tuwien.ac.at>
Injection-Info: google-groups.googlegroups.com; posting-host=2a00:23c5:6f05:3a01:3921:279e:7340:f70b;
posting-account=9A5f7goAAAD_QfJPZnlK3Xq_UhzYjdP-
NNTP-Posting-Host: 2a00:23c5:6f05:3a01:3921:279e:7340:f70b
References: <613dfe6e$0$700$14726298@news.sunsite.dk> <ad6f177f-ceb7-42b6-b698-ed5309fb68a3n@googlegroups.com>
<2021Sep13.112412@mips.complang.tuwien.ac.at>
User-Agent: G2/1.0
MIME-Version: 1.0
Message-ID: <7deec1bf-3063-4bd3-94d6-8579450d4c42n@googlegroups.com>
Subject: Re: Another mini-oop
From: november...@gmail.com (NN)
Injection-Date: Mon, 13 Sep 2021 12:00:16 +0000
Content-Type: text/plain; charset="UTF-8"
Lines: 52
 by: NN - Mon, 13 Sep 2021 12:00 UTC

On Monday, 13 September 2021 at 10:51:20 UTC+1, Anton Ertl wrote:
> NN <novembe...@gmail.com> writes:
> >Does anyone know why many if not all forths seem to favor the class based approach ?
> A straightforward implementation of the prototype approach results on
> one dispatch table per object, which costs quite a bit of memory.
> Real-world prototype-based object-oriented languages optimize this by
> deduplicating equal dispatch tables, which costs some complexity
> (e.g., you need to reduplicate the table if the table is changed for
> one of the objects). In the spirit of letting the programmer do the
> work rather than the computer, class-based is preferable to
> prototype-based.
>
> But looking at the wider programming world, nearly all popular OO
> languages are class-based, with JavaScript being the exception that
> proves the rule. That is probably because classes are seen as
> organizing principle, and even in a prototype-based language
> programmers tend to think in terms of classes. So why not have them
> as programming-language concept?
>
> That being said, the new Gforth header is a prototype-based system
> (but with a given, unextensible interface), rather than a class-based
> system. That's because the interface to words works by creating a
> word and then modifying it (with IMMEDIATE, SET-DOES>, SET-OPTIMIZE
> etc.), so a class-based interface would not work. Consequently,
> Gforth employs deduplication (there are only ~100 different tables for
> 4000 words, most of them due to SET-DOES>) and reduplication.
>
> Given that deduplication is expensive (we use linear search),
> eventually we have also introduced CREATE-FROM, which would just
> create a word with the same table as another word, already
> deduplicated. The way we use CREATE-FROM is, e.g.
>
> ['] >body create-from reveal
>
> where >BODY is the prototype word. In the current sources, the
> prototypes are all words that are otherwise useful, but from what I
> read, a frequent pattern in prototype-based languages is to define a
> prototype just to have a template for generating more objects of the
> same type, which again indicates that classes are an organizing
> principle wanted by programmers.
>
> - anton
> --
> M. Anton Ertl http://www.complang.tuwien.ac.at/anton/home.html
> comp.lang.forth FAQs: http://www.complang.tuwien.ac.at/forth/faq/toc.html
> New standard: http://www.forth200x.org/forth200x.html
> EuroForth 2021: https://euro.theforth.net/2021

Doug and Anton,

Thanks for the explanations.

Re: Another mini-oop

<82ba93e7-59ae-43c8-972a-0d3bc3cf4039n@googlegroups.com>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=14644&group=comp.lang.forth#14644

  copy link   Newsgroups: comp.lang.forth
X-Received: by 2002:ac8:7ef6:: with SMTP id r22mr7233490qtc.158.1631662651745;
Tue, 14 Sep 2021 16:37:31 -0700 (PDT)
X-Received: by 2002:a05:622a:3d4:: with SMTP id k20mr7262657qtx.417.1631662651610;
Tue, 14 Sep 2021 16:37:31 -0700 (PDT)
Path: i2pn2.org!i2pn.org!weretis.net!feeder8.news.weretis.net!proxad.net!feeder1-2.proxad.net!209.85.160.216.MISMATCH!news-out.google.com!nntp.google.com!postnews.google.com!google-groups.googlegroups.com!not-for-mail
Newsgroups: comp.lang.forth
Date: Tue, 14 Sep 2021 16:37:31 -0700 (PDT)
In-Reply-To: <613dfe6e$0$700$14726298@news.sunsite.dk>
Injection-Info: google-groups.googlegroups.com; posting-host=198.241.2.100; posting-account=OxDKOgoAAADW0cxAqHqpN1zqeCoSsDap
NNTP-Posting-Host: 198.241.2.100
References: <613dfe6e$0$700$14726298@news.sunsite.dk>
User-Agent: G2/1.0
MIME-Version: 1.0
Message-ID: <82ba93e7-59ae-43c8-972a-0d3bc3cf4039n@googlegroups.com>
Subject: Re: Another mini-oop
From: hughagui...@gmail.com (Hugh Aguilar)
Injection-Date: Tue, 14 Sep 2021 23:37:31 +0000
Content-Type: text/plain; charset="UTF-8"
 by: Hugh Aguilar - Tue, 14 Sep 2021 23:37 UTC

On Sunday, September 12, 2021 at 6:20:02 AM UTC-7, Doug Hoffman wrote:
> After paring away, the following code would be my idea of a mini-oop
> extension for Forth. Not a 12 liner, but loc will be recovered quickly
> as classes are written. Thanks to Bernd Paysan for a couple of ideas:

I've seen Bernd Paysan's Mini-OOF and I was not impressed. It is inefficient.

I did find it amusing that Mini-OOF relies on a disambiguifier to work,
despite the fact that disambiguifiers are a taboo subject and Stephen Pelc
says that disambiguifiers don't work.

Here is my code:
---------------------------------------------------------------------------------------------------------------
\ ******
\ ****** This provides the IS-A function for classes.
\ ******

98769876 constant class-id \ used to make sure a class is actually a class; must be a distinctive value

0
w field .class-parent \ pointer to parent class \ must be first field
w field .class-size \ size of object
w field .class-id \ should always be CLASS-ID
constant class-struct

\ Every object has a W field in front which is a pointer to the class-struct for its class.

: check-class ( class -- )
.class-id @ class-id <> abort" *** tried to use a class that wasn't actually a class ***" ;

: create-nada ( -- ) \ create a class that has no parent
create
nil , \ .class-parent \ there is no parent
w , \ .class-size \ room for the object's pointer to its class-struct
class-id , \ .class-id \ this is for error-checking
does> ( -- )
true abort" *** it is illegal to make objects of class NADA ***" ;

create-nada nada \ NADA is the only class that has no parent

\ NADA is only available so it can be the parent of classes that have no parent.
\ It is not really a class that can be used as such.

' alloc constant heap-new \ give this to the class to get a new object in the heap
' concrete-alloc constant dict-new \ give this to the class to get a new object in the dictionary

: class-size ( class -- size )
.class-size @
dup 0< abort" *** CLASS-SIZE given a class that never had its .CLASS-SIZE field set by END-CLASS ***" ;

: size' ( -- size ) \ stream: class-name
' >body dup check-class
class-size ;

: object-size ( object -- size )
@ \ -- class
.class-size @ ; \ -- size

: class ( -- class offset ) \ stream: class-name parent-name
create here \ -- class
' >body \ -- class parent
dup check-class \ -- class parent \ make sure PARENT is a class
dup , \ -- class parent \ .class-parent
-1 , \ -- class parent \ .class-size \ this will get filled in by END-CLASS
class-id , \ -- class parent \ .class-id \ this is for error-checking
class-size \ -- class offset
does> ( 'alloc -- adr ) \ make a new object ( 'ALLOC is either HEAP-NEW or DICT-NEW)
>r \ 'alloc -- \ r: -- class
r@ class-size swap execute \ -- object
dup r@ class-size erase \ zero out the object
r> over ! ; \ first field of object is pointer to class

: end-class ( class offset -- )
over check-class \ make sure CLASS is a class
swap .class-size ! ;

char & comment \ this was an attempt at a METHOD similar to what is in Mini-OOF
\ This is commented out because it is too inefficient.
\ Just use the obvious technique as demonstrated in the example code later on (the TEXT.SHOW method).

67896789 constant method-id \ used to make sure a method is actually a method; must be a distinctive value

0
w field .method-offset
w field .method-id
constant method-struct

: method ( offset -- new-offset ) \ like FIELD except only for pointers to functions
create
dup , w + \ -- new-offset \ .method-offset
method-id , \ -- new-offset \ .method-id
does> ( object base-adr -- )
.method-offset @ \ -- object field-offset
over + perform ;

: <set-method> ( xt object 'method -- )
>body
dup .method-id @ method-id <> abort" *** <SET-METHOD> given a method that wasn't actually a method ***"
.method-offset @ + ! ;

: set-method ( xt object -- ) \ stream: method-name
' <set-method> ;

: [set-method] ( xt object -- ) \ stream: method-name
postpone ['] postpone <set-method> ;
immediate

\ METHOD is like FIELD in that it is used to define a field. It doesn't take a field-size but assumes one cell.
\ The method, when executed, will EXECUTE whatever is stored in that field (unlike a field that provides the address).
\ [SET-METHOD] is used in constructors to set the method to a particular xt (the user doesn't have direct access to the offset).

&

: <<is-a>> ( object target -- flag )
over check-class over check-class
= ;

: <is-a> ( object 'target -- flag )
swap @ swap >body <<is-a>> ;

: is-a ( object -- flag ) \ stream: target-class-name
' <is-a> ;

: [is-a] ( object -- flag ) \ stream: target-class-name
postpone ['] postpone <is-a> ;
immediate

: <<is-child-of>> ( ancestor class -- flag )
over check-class over check-class
begin
2dup = if 2drop true exit then
@ \ -- ancestor parent \ .class-parent is first field
dup 0= if 2drop false exit then
again ;

: <is-child-of> ( object 'ancestor )
>body swap @ <<is-child-of>> ;

: is-child-of ( object -- flag ) \ stream: ancestor-class-name
' <is-child-of> ;

: [is-child-of] ( object -- flag ) \ stream: ancestor-class-name
postpone ['] postpone <is-child-of> ;
immediate

\ IS-CHILD-OF tests if the object has ANCESTOR as an ancestor, meaning that it can use ANCESTOR's methods.

: <is-parent-of> ( object 'child )
>body swap @ swap <<is-child-of>> ;

: is-parent-of ( object -- flag ) \ stream: child-class-name
' <is-parent-of> ;

: [is-parent-of] ( object -- flag ) \ stream: child-class-name
postpone ['] postpone <is-parent-of> ;
immediate

\ IS-PARENT-OF tests if the object has CHILD as a child, meaning that it can be upgraded to be a CHILD.

: <become> ( object 'class -- new-object )
>body >r \ -- object \ r: -- class
r@ class-size realloc \ -- new-object
r> over ! ; \ -- new-object \ class is object's first field

\ <BECOME> converts an object into a new class.
\ The new class must either be an ancestor or a child of the object's class.
\ Use IS-CHILD-OF to find out if the object is a child of the new class (can be downgraded to the parent class).
\ Use IS-PARENT-OF to find out if the object is a parent of the new-class (can be upgraded to the child class).

: become ( object -- new-object ) \ stream: class-name
' <become> ;

: [become] ( object -- new-object ) \ stream: class-name
postpone ['] postpone <become> ;
immediate

char & comment \ this is a demonstration of a simple usage

class slnk nada
w field slnk.fore
end-class

: slnk.init ( node -- node )
nil over slnk.fore ! ;

: <slnk.kill> ( node -- )
drop ;

: slnk.each ( head rq -- ) \ rq: i*x node -- j*x
{ rq | next -- }
begin ?dup while \ -- node
dup slnk.fore @ to next
rq rex
next repeat ;

: slnk.tail ( head -- node )
nil swap begin dup while \ -- prev node
nip dup slnk.fore @ repeat drop ;

: slnk.link ( 1stHead 2ndHead -- NewHead ) \ makes one list
over 0= if nip exit then
dup 0= if drop exit then
over slnk.tail slnk.fore ! ;

class text slnk
w field text.adr
w field text.cnt
w field 'text.show
end-class

: text.show ( node -- )
dup 'text.show perform ;

: <text.show> ( node -- )
>r
cr r@ text.adr @ r@ text.cnt @ type
rdrop ;

: text.init ( adr cnt node -- node ) \ if adr:cnt came from $> then it is on the heap already
slnk.init >r
r@ text.cnt !
r@ text.adr !
['] <text.show> r@ 'text.show !
r> ;


Click here to read the complete article
Re: Another mini-oop

<nnd$4d1fb605$1da8ad9f@fab64ca368f8692c>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=14679&group=comp.lang.forth#14679

  copy link   Newsgroups: comp.lang.forth
Newsgroups: comp.lang.forth
Subject: Re: Another mini-oop
References: <613dfe6e$0$700$14726298@news.sunsite.dk>
X-Newsreader: trn 4.0-test77 (Sep 1, 2010)
From: alb...@cherry (none)
Originator: albert@cherry.(none) (albert)
Message-ID: <nnd$4d1fb605$1da8ad9f@fab64ca368f8692c>
Organization: KPN B.V.
Date: Thu, 16 Sep 2021 22:49:21 +0200
Path: i2pn2.org!i2pn.org!weretis.net!feeder6.news.weretis.net!4.us.feeder.erje.net!3.eu.feeder.erje.net!feeder.erje.net!news2.arglkargh.de!news.mixmin.net!feed.abavia.com!abe002.abavia.com!abp002.abavia.com!news.kpn.nl!not-for-mail
Lines: 106
Injection-Date: Thu, 16 Sep 2021 22:49:21 +0200
Injection-Info: news.kpn.nl; mail-complaints-to="abuse@kpn.com"
 by: none - Thu, 16 Sep 2021 20:49 UTC

In article <613dfe6e$0$700$14726298@news.sunsite.dk>,
Doug Hoffman <dhoffman888@gmail.com> wrote:
>After paring away, the following code would be my idea of a mini-oop
>extension for Forth. Not a 12 liner, but loc will be recovered quickly
>as classes are written. Thanks to Bernd Paysan for a couple of ideas:
>
>-Doug
>
>\ *** begin code
>0 value self
>: dfa ( cls -- a) 8 cells + ;
>: _mfa ( adr -- ofs) dup >r 2/ 2/ r@ xor 2/ 2/ r> xor 7 and cells ;
>: mfa ( sel cls -- sel mfa) over _mfa + ;
>: fm ( sel mfa -- xt) begin @ dup while 2dup cell+ @ =
> if 2 cells + nip @ exit then repeat -1 abort" method?" ;
>: class ( supClass 'name' -- cls) create here >r
> 9 cells dup allot r@ swap move r> ;
>: makeSel ( 'name' -- sel ) create here dup _mfa c, 254 c,
> does> over @ over c@ + fm self >r swap to self execute r> to self ;
>: sel ( 'name' -- sel ) >in @ bl word find if >body dup 1+ c@ 254 =
> if nip exit then then drop >in ! makeSel ;
>: :m ( cls 'name' -- a xt) sel over mfa
> here over @ , swap ! , here 0 , :noname ;
>: ;m ( a xt -- ) postpone ; swap ! ; immediate
>: :: ( cls 'name' -- ) ' >body swap mfa fm compile, ; immediate
>: (ivar) ( offset 'name' -- ) create , does> ( -- addr ) @ self + ;
>: var ( cls n 'name' -- ) over dfa dup @ (ivar) +! ;
>create object 9 cells dup allot object swap erase cell object dfa !
>object :m :init ;m drop
>: new ( cls -- obj) dup dfa @ here swap allot tuck ! dup >r :init r> ;
>: .. ( obj 'name' -- adr) ' >body @ + ;
>\ *** end code
>
>0 [if] \ usage example
>
>object class button
> cell var text
> cell var len
> cell var x
> cell var y
> :m :init ( addr u -- ) len ! text ! 0 x ! 0 y ! ;m
> :m draw x @ y @ at-xy text @ len @ type ;m
>drop
>
>\ inheritance
>
>: bold 27 emit ." [1m" ;
>: normal 27 emit ." [0m" ;
>
>button class bold-button
> :m draw bold [ button :: draw ] normal ;m
>drop
>
>\ Create and draw the buttons:
>
>s" normal button" button new constant foo
>s" bold button" bold-button new constant bar
>1 bar .. y !
>page
>foo draw
>bar draw
>
>[then]
>
>0 [if] \ another example
> \ note re-use of draw (and there is no inheritance relationship)
>object class point
> cell var x
> cell var y
> :m p! ( x y -- ) y ! x ! ;m
> :m p@ ( -- x y ) x @ y @ ;m
> :m draw x ? y ? ;m
> :m :init ( x y -- ) self p! ;m \ late bind
>\ :m :init ( x y -- ) [ point :: p! ] ;m \ alternatively early bind
>drop
>
>1 2 point new constant p1
>p1 draw cr
>foo draw \ draw still works on foo and bar
>page bar draw
>: test 3 4 p1 p! p1 draw p1 .. x @ p1 .. y @ + . ;
>test
>\ => 3 4 7
>
>[then]

I think it is unforthy to have both fields and methods.
I have only methods that work on offsets, like CREATE DOES>.
It is basically CREATE DOES> DOES> ... DOES>
Also if you have a one screen oop, other things than inheritance
have priority. (I have much experience with my one screen oop,
used the BUILD-aap that is automatically generated with class aap
a couple of times to generate arrays of aap. )

See also ciasdis on github. I am ready to be convinced of
inheritance if some one showed me how it improves ciasdis.
There are opcode parts that have common methods, so inheritance
could be in order.

Groetjes Albert
--
"in our communism country Viet Nam, people are forced to be
alive and in the western country like US, people are free to
die from Covid 19 lol" duc ha
albert@spe&ar&c.xs4all.nl &=n http://home.hccnet.nl/a.w.m.van.der.horst

Re: Another mini-oop

<6143b419$0$703$14726298@news.sunsite.dk>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=14681&group=comp.lang.forth#14681

  copy link   Newsgroups: comp.lang.forth
Path: i2pn2.org!i2pn.org!aioe.org!news.uzoreto.com!dotsrc.org!filter.dotsrc.org!news.dotsrc.org!not-for-mail
Subject: Re: Another mini-oop
Newsgroups: comp.lang.forth
References: <613dfe6e$0$700$14726298@news.sunsite.dk>
<nnd$4d1fb605$1da8ad9f@fab64ca368f8692c>
From: dhoffman...@gmail.com (Doug Hoffman)
Date: Thu, 16 Sep 2021 17:16:05 -0400
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:78.0)
Gecko/20100101 Thunderbird/78.14.0
MIME-Version: 1.0
In-Reply-To: <nnd$4d1fb605$1da8ad9f@fab64ca368f8692c>
Content-Type: text/plain; charset=utf-8; format=flowed
Content-Language: en-US
Content-Transfer-Encoding: 7bit
Lines: 35
Message-ID: <6143b419$0$703$14726298@news.sunsite.dk>
Organization: SunSITE.dk - Supporting Open source
NNTP-Posting-Host: f40704f4.news.sunsite.dk
X-Trace: 1631826970 news.sunsite.dk 703 glidedog@gmail.com/68.55.82.126:54372
X-Complaints-To: staff@sunsite.dk
 by: Doug Hoffman - Thu, 16 Sep 2021 21:16 UTC

On 9/16/21 4:49 PM, albert wrote:

> I think it is unforthy to have both fields and methods.

That's interesting.

> I have only methods that work on offsets, like CREATE DOES>.

What is at the offset if not a "field"?

> It is basically CREATE DOES> DOES> ... DOES>
> Also if you have a one screen oop, other things than inheritance
> have priority. (I have much experience with my one screen oop,
> used the BUILD-aap that is automatically generated with class aap
> a couple of times to generate arrays of aap. )
>
> See also ciasdis on github. I am ready to be convinced of
> inheritance if some one showed me how it improves ciasdis.
> There are opcode parts that have common methods, so inheritance
> could be in order.

I stopped debating "the right way" to do Forth objects years ago. I
think Bernd Paysan affected my thinking here. There are perhaps an
unlimited number of ways to do objects in Forth, none of them wrong as
long as the creator/user is satisfied. If you like what you have, and
apparently you do, then great.

-Doug

> Groetjes Albert
>

Re: Another mini-oop

<si0gpl$pfi$1@gioia.aioe.org>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=14682&group=comp.lang.forth#14682

  copy link   Newsgroups: comp.lang.forth
Path: i2pn2.org!i2pn.org!aioe.org!7AktqsUqy5CCvnKa3S0Dkw.user.46.165.242.75.POSTED!not-for-mail
From: dxfo...@gmail.com (dxforth)
Newsgroups: comp.lang.forth
Subject: Re: Another mini-oop
Date: Fri, 17 Sep 2021 08:34:29 +1000
Organization: Aioe.org NNTP Server
Message-ID: <si0gpl$pfi$1@gioia.aioe.org>
References: <613dfe6e$0$700$14726298@news.sunsite.dk>
<nnd$4d1fb605$1da8ad9f@fab64ca368f8692c>
<6143b419$0$703$14726298@news.sunsite.dk>
Mime-Version: 1.0
Content-Type: text/plain; charset=utf-8; format=flowed
Content-Transfer-Encoding: 7bit
Injection-Info: gioia.aioe.org; logging-data="26098"; posting-host="7AktqsUqy5CCvnKa3S0Dkw.user.gioia.aioe.org"; mail-complaints-to="abuse@aioe.org";
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:78.0) Gecko/20100101
Thunderbird/78.14.0
X-Notice: Filtered by postfilter v. 0.9.2
Content-Language: en-GB
 by: dxforth - Thu, 16 Sep 2021 22:34 UTC

On 17/09/2021 07:16, Doug Hoffman wrote:
>
> I stopped debating "the right way" to do Forth objects years ago. I
> think Bernd Paysan affected my thinking here. There are perhaps an
> unlimited number of ways to do objects in Forth, none of them wrong as
> long as the creator/user is satisfied. If you like what you have, and
> apparently you do, then great.

Is the creator satisfied when users aren't?

"Maybe it would be better if not so many people used Forth"
- attributed to Chuck Moore.

Re: Another mini-oop

<6145cdfd$0$692$14726298@news.sunsite.dk>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=14706&group=comp.lang.forth#14706

  copy link   Newsgroups: comp.lang.forth
Path: i2pn2.org!i2pn.org!usenet.goja.nl.eu.org!dotsrc.org!filter.dotsrc.org!news.dotsrc.org!not-for-mail
From: dhoffman...@gmail.com (Doug Hoffman)
Subject: Re: Another mini-oop
Newsgroups: comp.lang.forth
References: <613dfe6e$0$700$14726298@news.sunsite.dk>
<nnd$4d1fb605$1da8ad9f@fab64ca368f8692c>
<6143b419$0$703$14726298@news.sunsite.dk> <si0gpl$pfi$1@gioia.aioe.org>
X-Mozilla-News-Host: news://news.sunsite.dk
Date: Sat, 18 Sep 2021 07:31:06 -0400
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:78.0)
Gecko/20100101 Thunderbird/78.14.0
MIME-Version: 1.0
In-Reply-To: <si0gpl$pfi$1@gioia.aioe.org>
Content-Type: text/plain; charset=utf-8; format=flowed
Content-Language: en-US
Content-Transfer-Encoding: 7bit
Lines: 21
Message-ID: <6145cdfd$0$692$14726298@news.sunsite.dk>
Organization: SunSITE.dk - Supporting Open source
NNTP-Posting-Host: faad0f68.news.sunsite.dk
X-Trace: 1631964669 news.sunsite.dk 692 glidedog@gmail.com/68.55.82.126:49790
X-Complaints-To: staff@sunsite.dk
 by: Doug Hoffman - Sat, 18 Sep 2021 11:31 UTC

On 9/16/21 6:34 PM, dxforth wrote:

> Is the creator satisfied when users aren't?

First, quite a few programmers, perhaps especially Forthers, reject oop.

Second, Forth oop users often create their own extension.

Disregarding the above, the creator may or may not hear about
dissatisfaction. What little I've heard (about my extensions) has
included "the code is too large" and "the code is too complex".

I write for myself but am happy to listen to suggestions.

> "Maybe it would be better if not so many people used Forth"
> - attributed to Chuck Moore.

It appears this has/is happened/happening.

-Doug

Re: Another mini-oop

<sjmcuu$fk5$1@dont-email.me>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=14878&group=comp.lang.forth#14878

  copy link   Newsgroups: comp.lang.forth
Path: rocksolid2!news.neodome.net!news.mixmin.net!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail
From: ruvim.pi...@gmail.com (Ruvim)
Newsgroups: comp.lang.forth
Subject: Re: Another mini-oop
Date: Thu, 7 Oct 2021 12:00:13 +0300
Organization: A noiseless patient Spider
Lines: 117
Message-ID: <sjmcuu$fk5$1@dont-email.me>
References: <613dfe6e$0$700$14726298@news.sunsite.dk>
<ad6f177f-ceb7-42b6-b698-ed5309fb68a3n@googlegroups.com>
<613e8212$0$703$14726298@news.sunsite.dk>
Mime-Version: 1.0
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 8bit
Injection-Date: Thu, 7 Oct 2021 09:00:14 -0000 (UTC)
Injection-Info: reader02.eternal-september.org; posting-host="ca3293d87f28560a75becc0402fe280a";
logging-data="16005"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1+/5ZTKqLhkI/l6RrFKQJNY"
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:91.0) Gecko/20100101
Thunderbird/91.1.2
Cancel-Lock: sha1:VVMw3FkWLDD8S+QHdLBxYKjRBT4=
In-Reply-To: <613e8212$0$703$14726298@news.sunsite.dk>
Content-Language: en-US
 by: Ruvim - Thu, 7 Oct 2021 09:00 UTC

On 2021-09-13 01:41, Doug Hoffman wrote:
> On 9/12/21 6:01 PM, NN wrote:
>
>> Recently, I have been reading a little about the history of smalltalk.
>> This lead me to Self.
>>   They introduced me to the idea of class based oop vs prototype based
>> oop.
>>
>> I think most forth oop implementations I have seen appear to be class
>> based.
>>
>> Does anyone know why many if not all forths seem to favor the class
>> based approach ?
>
> I have read some about the Meta Object Protocol. It made my head hurt.
> If there is an advantage to the prototype based approach, and there may
> be, I don't know it. Perhaps if someone provided working prototype based
> code in Forth then maybe I could better compare and contrast the two
> approaches.
>
> Class based seems simplest to implement and understand, not entirely
> sure. But we tend to favor simplicity in Forth as long as we don't give
> up important functionality.

On some level, source code can be considered as a prototype.

Each object is defined in a file (in the form of source code, and it can
reference other files, of course). This file can be considered as a
prototype.

To instantiate an object, its source file is compiled.

Usually, the relations between objects are defined on the prototype-level.

To inherit an object B from an object A, the file of A is included into
the file of B:

# b.proto.fth

include a.proto.fth

\ override methods of A,
\ or define new methods here

To compose an object C from objects A and B (i.e., aggregation), their
files are included into dedicated word lists:

# c.proto.fth

include-object a1 a.proto.fth
include-object a2 a.proto.fth
include-object b b.proto.fth
\ NB: two A objects are used

\ Use A and B objects via the wordlists "a1", "a2",
\ and "b" correspondingly.

An object instance identified by its wid, and it contains all methods as
well as data (i.e. methods are not shared between instances as in the
class-based approach).

Obviously, this approach is easy applicable when objects are used
statically, since static binding (early binding) is used.

To implement dynamic binding, a method name can be resolved via the
object's wid at run time, as:

call-late ( i*x sd-name wid -- j*x )

With help of a recognizer, late call of method "foo" can look as

late:foo ( ... wid -- ... )

or, even without recognizers, as:

late{ foo bar buz }

A more advanced technique is to automatic rebind an object as:

include-abstract a1 a.proto.fth

\ use a1 methods as usual:
: foo ... a1::bar ... ;

\ a method to bind an actual object:
: use-a1 ( wid -- ) a1 bind-object ;
\ after performing this method,
\ the given instance of any A-compatible object is used
\ NB: only interface should be compatible.

: release-a1 ( -- ) a1 release-object ;
\ after performing this method,
\ a1::bar will raise an error (as well as before bind-a1)

This approach is applicable when the number of objects are not too big,
and objects itself are big, or when the size of data is far greater then
the size of code in objects.

I use this approach.

And it is why I discuss formalization of sections. A mechanism to
manage parts of dictionary allows to create and *destroy* such big objects.

--
Ruvim

Re: Another mini-oop

<61602d77$0$696$14726298@news.sunsite.dk>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=14897&group=comp.lang.forth#14897

  copy link   Newsgroups: comp.lang.forth
Path: rocksolid2!i2pn.org!aioe.org!news.uzoreto.com!dotsrc.org!filter.dotsrc.org!news.dotsrc.org!not-for-mail
Subject: Re: Another mini-oop
Newsgroups: comp.lang.forth
References: <613dfe6e$0$700$14726298@news.sunsite.dk>
<ad6f177f-ceb7-42b6-b698-ed5309fb68a3n@googlegroups.com>
<613e8212$0$703$14726298@news.sunsite.dk> <sjmcuu$fk5$1@dont-email.me>
From: dhoffman...@gmail.com (Doug Hoffman)
Date: Fri, 8 Oct 2021 07:37:22 -0400
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:78.0)
Gecko/20100101 Thunderbird/78.14.0
MIME-Version: 1.0
In-Reply-To: <sjmcuu$fk5$1@dont-email.me>
Content-Type: text/plain; charset=utf-8; format=flowed
Content-Language: en-US
Content-Transfer-Encoding: 8bit
Lines: 103
Message-ID: <61602d77$0$696$14726298@news.sunsite.dk>
Organization: SunSITE.dk - Supporting Open source
NNTP-Posting-Host: d5d91d08.news.sunsite.dk
X-Trace: 1633693047 news.sunsite.dk 696 glidedog@gmail.com/68.55.82.126:58935
X-Complaints-To: staff@sunsite.dk
 by: Doug Hoffman - Fri, 8 Oct 2021 11:37 UTC

On 10/7/21 5:00 AM, Ruvim wrote:

> On some level, source code can be considered as a prototype.
>
> Each object is defined in a file (in the form of source code, and it can
> reference other files, of course). This file can be considered as a
> prototype.
>
> To instantiate an object, its source file is compiled.
>
> Usually, the relations between objects are defined on the prototype-level.
>
> To inherit an object B from an object A, the file of A is included into
> the file of B:
>
>   # b.proto.fth
>
>     include a.proto.fth
>
>     \ override methods of A,
>     \ or define new methods here
>
>
> To compose an object C from objects A and B (i.e., aggregation), their
> files are included into dedicated word lists:
>
>   # c.proto.fth
>
>     include-object a1 a.proto.fth
>     include-object a2 a.proto.fth
>     include-object b b.proto.fth
>     \ NB: two A objects are used
>
>     \ Use A and B objects via the wordlists "a1", "a2",
>     \ and "b" correspondingly.
>
>
> An object instance identified by its wid, and it contains all methods as
> well as data (i.e. methods are not shared between instances as in the
> class-based approach).
>
> Obviously, this approach is easy applicable when objects are used
> statically, since static binding (early binding) is used.
>
>
> To implement dynamic binding, a method name can be resolved via the
> object's wid at run time, as:
>
>   call-late ( i*x  sd-name wid -- j*x )
>
> With help of a recognizer, late call of method "foo" can look as
>
>   late:foo ( ... wid -- ... )

If we have to supply a type identifier with a method call then that
isn't late binding. Or perhaps I mis-understand.

> or, even without recognizers, as:
>
>   late{ foo bar buz }
>
>
>
>
> A more advanced technique is to automatic rebind an object as:
>
>     include-abstract a1 a.proto.fth
>
>     \ use a1 methods as usual:
>     : foo ... a1::bar  ... ;
>
>     \ a method to bind an actual object:
>     : use-a1 ( wid -- )  a1 bind-object ;
>     \ after performing this method,
>     \ the given instance of any A-compatible object is used
>     \ NB: only interface should be compatible.
>
>     : release-a1 ( -- ) a1 release-object ;
>     \ after performing this method,
>     \ a1::bar will raise an error (as well as before bind-a1)
>
>
>
>
> This approach is applicable when the number of objects are not too big,
> and objects itself are big, or when the size of data is far greater then
> the size of code in objects.
>
> I use this approach.
>
> And it is why I discuss formalization of sections.  A mechanism to
> manage parts of dictionary allows to create and *destroy* such big objects.

Interesting. A complete working example would be very instructive. If I
understand correctly one needs a working sections for this.

-Doug

>
> --
> Ruvim

Re: Another mini-oop

<sjpo61$9vr$1@dont-email.me>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=14901&group=comp.lang.forth#14901

  copy link   Newsgroups: comp.lang.forth
Path: rocksolid2!news.neodome.net!weretis.net!feeder8.news.weretis.net!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail
From: ruvim.pi...@gmail.com (Ruvim)
Newsgroups: comp.lang.forth
Subject: Re: Another mini-oop
Date: Fri, 8 Oct 2021 18:30:06 +0300
Organization: A noiseless patient Spider
Lines: 184
Message-ID: <sjpo61$9vr$1@dont-email.me>
References: <613dfe6e$0$700$14726298@news.sunsite.dk>
<ad6f177f-ceb7-42b6-b698-ed5309fb68a3n@googlegroups.com>
<613e8212$0$703$14726298@news.sunsite.dk> <sjmcuu$fk5$1@dont-email.me>
<61602d77$0$696$14726298@news.sunsite.dk>
Mime-Version: 1.0
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 8bit
Injection-Date: Fri, 8 Oct 2021 15:30:09 -0000 (UTC)
Injection-Info: reader02.eternal-september.org; posting-host="7a03740e213dd5e890911cddedf5d6b4";
logging-data="10235"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX18FrV8qTBxteYpHuajfBVl1"
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:91.0) Gecko/20100101
Thunderbird/91.2.0
Cancel-Lock: sha1:1eUXagZ0ffwvvc7TwEId2HwAskw=
In-Reply-To: <61602d77$0$696$14726298@news.sunsite.dk>
Content-Language: en-US
 by: Ruvim - Fri, 8 Oct 2021 15:30 UTC

On 2021-10-08 14:37, Doug Hoffman wrote:
> On 10/7/21 5:00 AM, Ruvim wrote:
>
>> On some level, source code can be considered as a prototype.
>>
>> Each object is defined in a file (in the form of source code, and it
>> can reference other files, of course). This file can be considered as
>> a prototype.
>>
>> To instantiate an object, its source file is compiled.

Actually I don't sure: why does such a file (a set of files)
conceptually represent not a class, but a prototypical object?

Some reasoning is as follows.

A file contains a source code that describes and defines an object.
Hence, this file is a *form* of representation for the *object*.
Conceptually, it doesn't matter in what form an object is represented.
For example, a text-based serialization is also a form of representation
for an object.

But a class also describes and defines objects. Then, why this source
file cannot be considered as a class?

In a class-based OOP model every object always knows its class. If an
object doesn't know its class — it's not a class-based OOP.

While in a prototype-based OOP model it is possible that an object
doesn't know its prototype.

In the model described by me, an object doesn't know its source
(whatever it's called). Hence, this OOP model is rather prototype-based
than class-based, conceptually.

>>
>> Usually, the relations between objects are defined on the
>> prototype-level.
>>
>> To inherit an object B from an object A, the file of A is included
>> into the file of B:
>>
>>    # b.proto.fth
>>
>>      include a.proto.fth
>>
>>      \ override methods of A,
>>      \ or define new methods here
>>
>>
>> To compose an object C from objects A and B (i.e., aggregation), their
>> files are included into dedicated word lists:
>>
>>    # c.proto.fth
>>
>>      include-object a1 a.proto.fth
>>      include-object a2 a.proto.fth
>>      include-object b b.proto.fth
>>      \ NB: two A objects are used
>>
>>      \ Use A and B objects via the wordlists "a1", "a2",
>>      \ and "b" correspondingly.
>>
>>
>> An object instance identified by its wid, and it contains all methods
>> as well as data (i.e. methods are not shared between instances as in
>> the class-based approach).
>>
>> Obviously, this approach is easy applicable when objects are used
>> statically, since static binding (early binding) is used.
>>
>>
>> To implement dynamic binding, a method name can be resolved via the
>> object's wid at run time, as:
>>
>>    call-late ( i*x  sd-name wid -- j*x )
>>
>> With help of a recognizer, late call of method "foo" can look as
>>
>>    late:foo ( ... wid -- ... )
>
> If we have to supply a type identifier with a method call then that
> isn't late binding. Or perhaps I mis-understand.

This wid identifies not a type, not a class, but an object itself
(instance).

So the following phrases are equivalent:

a1::bar
a1 s" bar" call-late-
a1 late{ bar }
a1 late:bar

Where
a1 ( -- wid )
call-late- ( i*x wid sd-name -- j*x )

In the first case the early binding is used, if in compilation state,
since the name "bar" is resolved during compilation. In the next three
cases the name "bar" is resolved in run-time, immediately before call.
The word "a1" just places a wid on the stack, and this wid identifies an
*object*.

>
>> or, even without recognizers, as:
>>
>>    late{ foo bar buz }
>>
>>
>>
>>
>> A more advanced technique is to automatic rebind an object as:
>>
>>      include-abstract a1 a.proto.fth
>>
>>      \ use a1 methods as usual:
>>      : foo ... a1::bar  ... ;
>>
>>      \ a method to bind an actual object:
>>      : use-a1 ( wid -- )  a1 bind-object ;
>>      \ after performing this method,
>>      \ the given instance of any A-compatible object is used
>>      \ NB: only interface should be compatible.
>>
>>      : release-a1 ( -- ) a1 release-object ;
>>      \ after performing this method,
>>      \ a1::bar will raise an error (as well as before bind-a1)
>>
>>
>>
>>
>> This approach is applicable when the number of objects are not too
>> big, and objects itself are big, or when the size of data is far
>> greater then the size of code in objects.
>>
>> I use this approach.
>>
>> And it is why I discuss formalization of sections.  A mechanism to
>> manage parts of dictionary allows to create and *destroy* such big
>> objects.
>
> Interesting. A complete working example would be very instructive.

A one advantage of this approach is that almost every Forth source file
can be considered as a prototype. Nothing special is needed to define
properties and methods.

The only quite complex thing is an "include-abstract" method.

I don't have ready example in the classic Forth right now, since I use
this approach in ForthML language/extension (Something like XML syntax
for Forth).

For example, most files at https://git.io/JrVM7 are prototypes (I also
call them "models"). An implementation for a method like
"include-abstract" can be found at https://git.io/JrwQW

I will try to prepare an example in classic Forth too.

> If I understand correctly one needs a working sections for this.

It depends on your application. In some application you don't ever need
to free any object, you just create them, make your work, and terminates.

In some applications it's enough to free objects in LIFO order.

In some applications I use a pool of objects and reuse them in run-time.
A new object is created if the corresponding pool is empty only. A pool
is destroyed on optional hot reload only.

So, you need separate sections (storages) if you want to randomly free
such objects only.

--
Ruvim

Re: Another mini-oop

<6160a411$0$700$14726298@news.sunsite.dk>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=14902&group=comp.lang.forth#14902

  copy link   Newsgroups: comp.lang.forth
Path: rocksolid2!news.neodome.net!news.uzoreto.com!dotsrc.org!filter.dotsrc.org!news.dotsrc.org!not-for-mail
Subject: Re: Another mini-oop
Newsgroups: comp.lang.forth
References: <613dfe6e$0$700$14726298@news.sunsite.dk>
<ad6f177f-ceb7-42b6-b698-ed5309fb68a3n@googlegroups.com>
<613e8212$0$703$14726298@news.sunsite.dk> <sjmcuu$fk5$1@dont-email.me>
<61602d77$0$696$14726298@news.sunsite.dk> <sjpo61$9vr$1@dont-email.me>
From: dhoffman...@gmail.com (Doug Hoffman)
Date: Fri, 8 Oct 2021 16:03:23 -0400
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:78.0)
Gecko/20100101 Thunderbird/78.14.0
MIME-Version: 1.0
In-Reply-To: <sjpo61$9vr$1@dont-email.me>
Content-Type: text/plain; charset=utf-8; format=flowed
Content-Language: en-US
Content-Transfer-Encoding: 7bit
Lines: 10
Message-ID: <6160a411$0$700$14726298@news.sunsite.dk>
Organization: SunSITE.dk - Supporting Open source
NNTP-Posting-Host: cb34c651.news.sunsite.dk
X-Trace: 1633723409 news.sunsite.dk 700 glidedog@gmail.com/68.55.82.126:63253
X-Complaints-To: staff@sunsite.dk
 by: Doug Hoffman - Fri, 8 Oct 2021 20:03 UTC

On 10/8/21 11:30 AM, Ruvim wrote:

> This wid identifies not a type, not a class, but an object itself
> (instance).

Yes. I see you had that in your first post. Thanks for (re) explaining
it. You have an interesting approach. If it helps you, and apparently it
does, great!

-Doug

Re: Another mini-oop

<sjuf1e$bbi$1@dont-email.me>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=14912&group=comp.lang.forth#14912

  copy link   Newsgroups: comp.lang.forth
Path: rocksolid2!i2pn.org!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail
From: ruvim.pi...@gmail.com (Ruvim)
Newsgroups: comp.lang.forth
Subject: Re: Another mini-oop
Date: Sun, 10 Oct 2021 13:24:44 +0300
Organization: A noiseless patient Spider
Lines: 237
Message-ID: <sjuf1e$bbi$1@dont-email.me>
References: <613dfe6e$0$700$14726298@news.sunsite.dk>
Mime-Version: 1.0
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 8bit
Injection-Date: Sun, 10 Oct 2021 10:24:46 -0000 (UTC)
Injection-Info: reader02.eternal-september.org; posting-host="c28d4a31955b464aea547f7ec0ddf0c3";
logging-data="11634"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1/Ev/LSFpbtufMAe35rPXkw"
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:91.0) Gecko/20100101
Thunderbird/91.2.0
Cancel-Lock: sha1:6CEN0W2fcVtnyKx1Xa9tHCBN/Ek=
In-Reply-To: <613dfe6e$0$700$14726298@news.sunsite.dk>
Content-Language: en-US
 by: Ruvim - Sun, 10 Oct 2021 10:24 UTC

On 2021-09-12 16:19, Doug Hoffman wrote:
> After paring away, the following code would be my idea of a mini-oop
> extension for Forth. Not a 12 liner, but loc will be recovered quickly
> as classes are written. Thanks to Bernd Paysan for a couple of ideas:
>
> -Doug
>
> \ *** begin code
> 0 value self
> : dfa ( cls -- a) 8 cells + ;
> : _mfa ( adr -- ofs) dup >r 2/ 2/ r@ xor 2/ 2/ r> xor 7 and cells ;
> : mfa ( sel cls -- sel mfa) over _mfa + ;
> : fm ( sel mfa -- xt) begin @ dup while 2dup cell+ @ =
>   if 2 cells + nip @ exit then repeat -1 abort" method?" ;
> : class ( supClass 'name' -- cls) create here >r
>   9 cells dup allot r@ swap move r> ;
> : makeSel ( 'name' -- sel ) create here dup _mfa c, 254 c,
>   does> over @ over c@ + fm self >r swap to self execute r> to self ;
> : sel ( 'name' -- sel ) >in @ bl word find if >body dup 1+ c@ 254 =
>    if nip exit then then drop >in ! makeSel ;
> : :m ( cls 'name' -- a xt) sel over mfa
>    here over @ , swap !  , here 0 , :noname ;
> : ;m ( a xt -- ) postpone ; swap ! ; immediate
> : :: ( cls 'name' -- ) ' >body swap mfa fm compile, ; immediate
> : (ivar) ( offset 'name' -- ) create , does> ( -- addr ) @ self + ;
> : var ( cls n 'name' -- ) over dfa dup @ (ivar) +! ;
> create object 9 cells dup allot object swap erase  cell object dfa !
> object :m :init ;m drop
> : new ( cls -- obj) dup dfa @ here swap allot tuck ! dup >r :init r> ;
> : .. ( obj 'name' -- adr) ' >body @ + ;
> \ *** end code

I have taken a closer look at this example. Very concise code, but too
magical! I mean, plenty of magic numbers and abbreviated names, and lack
of comments in the same time.

Maybe somebody is interested what and how this code does in general.

The most important thing to say is that this code implements a
Smalltalk-like model of OOP. It means that late binding is always used
by default, and the class for a method call is unknown in compile time.

In this model, for each unique name of a method (regardless of classes)
a single selector is created. A selector is a definition that takes an
object from the stack, gets it's class, finds in the class a method
having the corresponding name, and performs this method for the object.

In this implementation, each unique name among names of all methods of
all classes is identified by the data field address of the corresponding
selector ("data field" in the standard notion, don't muddle it up with
the "dfa" word that probably means "data field area" of an object). So
when a selector is searching for a method, it compares not strings, but
these identifiers. This search is performed by iteration over a plain
single-linked list. For better performance, the methods of a class are
broken up into 8 lists according to a hash of their selector identifiers.

Since the set of selectors is single and global, I would place all the
selectors into one single wordlist.

At the moment, depending on the search order, a duplicate of selector
can be created, and then a defined method will be unfound in some cases.

Having a separate word list for selectors, a selector duplicate is
impossible, and the call of a method with help of a recognizer can look as:

msg::draw

I.e., it's qualified. Another variant is to just include the "msg"
wordlist into the search order, but this variant is more error-prone.

The word "var" unconditionally creates a new definition on every use.
So, it shadows the previous definition with the same name. (1)
Probably, such definitions should be local for their classes.

Concerning definition of methods. It's a very elegant solution: the name
(from the parsed argument) is used to get (or create) a selector, and
then an anonymous definition is used to define the method itself.

Although, the name "m:" is better than ":m" for a word that starts a
definition and has a parsed argument. (See also a small discussion on
this regard several months ago [1])
Also, the name ":m" matches the same pattern as the methods like
":init". It's better to avoid such clashes.

Some other comments see below.

[1] https://groups.google.com/g/comp.lang.forth/c/QY-XBI8e3AE/m/KsKsd2TCBAAJ

>
> 0 [if] \ usage example
>
> object class button
>   cell var text
>   cell var len
>   cell var x
>   cell var y
>  :m :init ( addr u -- ) len ! text ! 0 x ! 0 y ! ;m
>  :m draw  x @ y @ at-xy text @ len @ type ;m
> drop
>
> \ inheritance
>
> : bold   27 emit ." [1m" ;
> : normal 27 emit ." [0m" ;
>
> button class bold-button
>  :m draw bold [ button :: draw ] normal ;m
> drop
>
> \ Create and draw the buttons:
>
> s" normal button" button new constant foo
> s" bold button" bold-button new constant bar
> 1 bar .. y !
> page
> foo draw
> bar draw
>
> [then]
>
> 0 [if] \ another example
>  \ note re-use of draw (and there is no inheritance relationship)
> object class point
>   cell var x
>   cell var y
>  :m p! ( x y -- ) y ! x ! ;m
>  :m p@ ( -- x y ) x @ y @ ;m
>  :m draw x ? y ? ;m
>  :m :init ( x y -- ) self p! ;m  \ late bind
> \ :m :init ( x y -- ) [ point :: p! ] ;m \ alternatively early bind
> drop
>
> 1 2 point new constant p1
> p1 draw cr
> foo draw  \ draw still works on foo and bar
> page bar draw
> : test 3 4 p1 p! p1 draw  p1 .. x @ p1 .. y @ + . ;
(2)
> test
> \ => 3 4 7
>
> [then]

If these both examples are uncommented, and the file is loaded, the phrase:

bar .. y @ .

should print "1", but it actually prints "11" due to the problem (1).

Also, the line (2) doesn't work as expected since it implies special
compilation semantics for "..", that are not defined. To fix this
problem, ".." can be defined as follows:

: .. ( "name-field" -- | obj "name-field" -- addr-field )
' >body @ tt-lit ['] + tt-xt
; immediate

\ Where "tt-lit" and "tt-xt" are translators for x and xt data types
\ correspondingly, see "minimalistic core API for recognizers" [2].
\ They can be defined as follows:
: tt-lit ( x -- x | ) state @ if lit, exit then ;
: tt-xt ( i*x xt -- j*x ) state @ if compile, exit then execute ;

But it doesn't solve the problem (1).

If you places properties into the wordlist of the class, then you need
the class to access a property outside of its class definition. Also,
you need the class to make an early bound method call.

I would use recognizers for these case, that recognize some of the
following forms:

early:point/draw
prop:point/x

early:point#draw
prop:point#x

early:point.draw
prop:point.x

(choose what looks better)

Or use immediate words as:

early( point draw )
prop( point x )

early( point.draw )
prop( point.x )

early{ point/draw }
prop{ point/x }

(choose what looks better)

Rationale:
1. the parsed arguments (the arguments that are immediately taken
from the parse area) should be easy visible. It's a bad practice that
parsed arguments are not distinguishable in the source code.
2. It should work as expected in interpretation state too.

Just for illustration, the first variant for words "prop(" and "early("
can be defined as follows:

: prop( \ "name-class" "name-prop" ")"
' execute parse-name ')' parse 2drop ( cls sd-name-prop )
rot class>wordlist search-wordlist
if >body @ tt-lit ['] + tt-xt exit then
true abort" property is not found"
; immediate

: early( \ "name-class" "name-method" ")"
' execute parse-name ')' parse 2drop ( cls sd-name-method )
msg search-wordlist \ find the selector
if >body ( cls sel-id ) swap mfa fm tt-xt exit then
true abort" selector is not found"
; immediate

\ this code is not tested

[2] Proposal: minimalistic core API for recognizers
https://forth-standard.org/proposals/minimalistic-core-api-for-recognizers?hideDiff#reply-514

--
Ruvim

Re: Another mini-oop

<6162e4a6$0$700$14726298@news.sunsite.dk>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=14914&group=comp.lang.forth#14914

  copy link   Newsgroups: comp.lang.forth
Path: rocksolid2!news.neodome.net!news.uzoreto.com!dotsrc.org!filter.dotsrc.org!news.dotsrc.org!not-for-mail
Subject: Re: Another mini-oop
Newsgroups: comp.lang.forth
References: <613dfe6e$0$700$14726298@news.sunsite.dk>
<sjuf1e$bbi$1@dont-email.me>
From: dhoffman...@gmail.com (Doug Hoffman)
Date: Sun, 10 Oct 2021 09:03:29 -0400
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:78.0)
Gecko/20100101 Thunderbird/78.14.0
MIME-Version: 1.0
In-Reply-To: <sjuf1e$bbi$1@dont-email.me>
Content-Type: text/plain; charset=utf-8; format=flowed
Content-Language: en-US
Content-Transfer-Encoding: 8bit
Lines: 307
Message-ID: <6162e4a6$0$700$14726298@news.sunsite.dk>
Organization: SunSITE.dk - Supporting Open source
NNTP-Posting-Host: e93a45e3.news.sunsite.dk
X-Trace: 1633871014 news.sunsite.dk 700 glidedog@gmail.com/68.55.82.126:61895
X-Complaints-To: staff@sunsite.dk
 by: Doug Hoffman - Sun, 10 Oct 2021 13:03 UTC

On 10/10/21 6:24 AM, Ruvim wrote:
> On 2021-09-12 16:19, Doug Hoffman wrote:
>> After paring away, the following code would be my idea of a mini-oop
>> extension for Forth. Not a 12 liner, but loc will be recovered quickly
>> as classes are written. Thanks to Bernd Paysan for a couple of ideas:
>>
>> -Doug
>>
>> \ *** begin code
>> 0 value self
>> : dfa ( cls -- a) 8 cells + ;
>> : _mfa ( adr -- ofs) dup >r 2/ 2/ r@ xor 2/ 2/ r> xor 7 and cells ;
>> : mfa ( sel cls -- sel mfa) over _mfa + ;
>> : fm ( sel mfa -- xt) begin @ dup while 2dup cell+ @ =
>>    if 2 cells + nip @ exit then repeat -1 abort" method?" ;
>> : class ( supClass 'name' -- cls) create here >r
>>    9 cells dup allot r@ swap move r> ;
>> : makeSel ( 'name' -- sel ) create here dup _mfa c, 254 c,
>>    does> over @ over c@ + fm self >r swap to self execute r> to self ;
>> : sel ( 'name' -- sel ) >in @ bl word find if >body dup 1+ c@ 254 =
>>     if nip exit then then drop >in ! makeSel ;
>> : :m ( cls 'name' -- a xt) sel over mfa
>>     here over @ , swap !  , here 0 , :noname ;
>> : ;m ( a xt -- ) postpone ; swap ! ; immediate
>> : :: ( cls 'name' -- ) ' >body swap mfa fm compile, ; immediate
>> : (ivar) ( offset 'name' -- ) create , does> ( -- addr ) @ self + ;
>> : var ( cls n 'name' -- ) over dfa dup @ (ivar) +! ;
>> create object 9 cells dup allot object swap erase  cell object dfa !
>> object :m :init ;m drop
>> : new ( cls -- obj) dup dfa @ here swap allot tuck ! dup >r :init r> ;
>> : .. ( obj 'name' -- adr) ' >body @ + ;
>> \ *** end code
>
> I have taken a closer look at this example. Very concise code, but too
> magical! I mean, plenty of magic numbers and abbreviated names, and lack
> of comments in the same time.

Yes. It was written in the style of mini-OOF, which apparently people like

> Maybe somebody is interested what and how this code does in general.
>
> The most important thing to say is that this code implements a
> Smalltalk-like model of OOP. It means that late binding is always used
> by default, and the class for a method call is unknown in compile time.
>
>
> In this model, for each unique name of a method (regardless of classes)
> a single selector is created. A selector is a definition that takes an
> object from the stack, gets it's class, finds in the class a method
> having the corresponding name, and performs this method for the object.
>
> In this implementation, each unique name among names of all methods of
> all classes is identified by the data field address of the corresponding
> selector ("data field" in the standard notion, don't muddle it up with
> the "dfa" word that probably means "data field area" of an object). So
> when a selector is searching for a method, it compares not strings, but
> these identifiers. This search is performed by iteration over a plain
> single-linked list. For better performance, the methods of a class are
> broken up into 8 lists according to a hash of their selector identifiers.

Everything you say is exactly correct. Maybe the code is not too obtuse.

> Since the set of selectors is single and global, I would place all the
> selectors into one single wordlist.

I have tried that and was not satisfied with the extra code required.
Especially having to "reset" the search order in various places such as
when a method compilation fails. Besides, In the Smalltalk model all
message names are global.

> At the moment, depending on the search order, a duplicate of selector
> can be created, and then a defined method will be unfound in some cases.

In those cases we *want* it to be unfound.

> Having a separate word list for selectors, a selector duplicate is
> impossible, and the call of a method with help of a recognizer can look as:
>
>   msg::draw
>
> I.e., it's qualified. Another variant is to just include the "msg"
> wordlist into the search order, but this variant is more error-prone.

Yes. And more complex, which I strive to avoid.

> The word "var" unconditionally creates a new definition on every use.
> So, it shadows the previous definition with the same name. (1)
> Probably, such definitions should be local for their classes.

mini-OOF does it this way and many seem to like it. However, I have
written a, larger and more complex, version of what I show in the first
post of this thread that uses one wordlist for each class so instance
variable names are totally protected:

https://github.com/DouglasBHoffman/FMS2 (FMS2LL)

The code is more complex and uses about 4200 bytes instead of 1200
bytes (it has other oop features as well). But it is there for those
that want it.

> Concerning definition of methods. It's a very elegant solution: the name
> (from the parsed argument) is used to get (or create) a selector, and
> then an anonymous definition is used to define the method itself.
>
> Although, the name "m:" is better than ":m" for a word that starts a
> definition and has a parsed argument. (See also a small discussion on
> this regard several months ago [1])

:M has historical use dating back to 1984 (Neon) and is still used by
Win32Forth I believe.

> Also, the name ":m" matches the same pattern as the methods like
> ":init". It's better to avoid such clashes.

Simple to change if one wishes.

> Some other comments see below.
>
> [1]
> https://groups.google.com/g/comp.lang.forth/c/QY-XBI8e3AE/m/KsKsd2TCBAAJ
>
>>
>> 0 [if] \ usage example
>>
>> object class button
>>    cell var text
>>    cell var len
>>    cell var x
>>    cell var y
>>   :m :init ( addr u -- ) len ! text ! 0 x ! 0 y ! ;m
>>   :m draw  x @ y @ at-xy text @ len @ type ;m
>> drop
>>
>> \ inheritance
>>
>> : bold   27 emit ." [1m" ;
>> : normal 27 emit ." [0m" ;
>>
>> button class bold-button
>>   :m draw bold [ button :: draw ] normal ;m
>> drop
>>
>> \ Create and draw the buttons:
>>
>> s" normal button" button new constant foo
>> s" bold button" bold-button new constant bar
>> 1 bar .. y !
>> page
>> foo draw
>> bar draw
>>
>> [then]
>>
>> 0 [if] \ another example
>>   \ note re-use of draw (and there is no inheritance relationship)
>> object class point
>>    cell var x
>>    cell var y
>>   :m p! ( x y -- ) y ! x ! ;m
>>   :m p@ ( -- x y ) x @ y @ ;m
>>   :m draw x ? y ? ;m
>>   :m :init ( x y -- ) self p! ;m  \ late bind
>> \ :m :init ( x y -- ) [ point :: p! ] ;m \ alternatively early bind
>> drop
>>
>> 1 2 point new constant p1
>> p1 draw cr
>> foo draw  \ draw still works on foo and bar
>> page bar draw
>> : test 3 4 p1 p! p1 draw  p1 .. x @ p1 .. y @ + . ;
> (2)
>> test
>> \ => 3 4 7
>>
>> [then]
>
> If these both examples are uncommented, and the file is loaded, the phrase:
>
>   bar .. y @ .
>
> should print "1", but it actually prints "11" due to the problem (1).

Odd. It works fine on VFX, SwiftForth, and Gforth 0.7.3.

> Also, the line (2) doesn't work as expected since it implies special
> compilation semantics for "..", that are not defined.

Again, I don't see this problem on the 3 Forths mentioned.

> To fix this
> problem, ".." can be defined as follows:
>
>   : .. ( "name-field" -- | obj "name-field" -- addr-field )
>     ' >body @  tt-lit ['] + tt-xt
>   ; immediate
>
>
>   \ Where "tt-lit" and "tt-xt" are translators for x and xt data types
>   \ correspondingly, see "minimalistic core API for recognizers" [2].
>   \ They can be defined as follows:
>   : tt-lit ( x -- x | ) state @ if lit, exit then ;
>   : tt-xt ( i*x xt -- j*x ) state @ if compile, exit then execute

lit, is not standard and must be defined. Then what you show works, at
the cost of state-smartness and additional code. My preference is to not
use message-less instance variable access (like Smalltalk) and instead
define getter and setter methods if needed. But many apparently crave
message-less access so I provided it.

> But it doesn't solve the problem (1).


Click here to read the complete article
Re: Another mini-oop

<sjutiv$fpp$1@dont-email.me>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=14917&group=comp.lang.forth#14917

  copy link   Newsgroups: comp.lang.forth
Path: rocksolid2!i2pn.org!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail
From: ruvim.pi...@gmail.com (Ruvim)
Newsgroups: comp.lang.forth
Subject: Re: Another mini-oop
Date: Sun, 10 Oct 2021 17:33:01 +0300
Organization: A noiseless patient Spider
Lines: 132
Message-ID: <sjutiv$fpp$1@dont-email.me>
References: <613dfe6e$0$700$14726298@news.sunsite.dk>
<sjuf1e$bbi$1@dont-email.me> <6162e4a6$0$700$14726298@news.sunsite.dk>
Mime-Version: 1.0
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 8bit
Injection-Date: Sun, 10 Oct 2021 14:33:03 -0000 (UTC)
Injection-Info: reader02.eternal-september.org; posting-host="c28d4a31955b464aea547f7ec0ddf0c3";
logging-data="16185"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1/DFZNsLu3hIx6Doi8mJL9O"
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:91.0) Gecko/20100101
Thunderbird/91.2.0
Cancel-Lock: sha1:HV0Lh7JixVfQZiIVYXpVJuUqZvE=
In-Reply-To: <6162e4a6$0$700$14726298@news.sunsite.dk>
Content-Language: en-US
 by: Ruvim - Sun, 10 Oct 2021 14:33 UTC

On 2021-10-10 16:03, Doug Hoffman wrote:
> On 10/10/21 6:24 AM, Ruvim wrote:
>> On 2021-09-12 16:19, Doug Hoffman wrote:
>>> After paring away, the following code would be my idea of a mini-oop
>>> extension for Forth.
[...]
>>> \ *** end code
>>
>> I have taken a closer look at this example. Very concise code, but too
>> magical! I mean, plenty of magic numbers and abbreviated names, and
>> lack of comments in the same time.
>
> Yes. It was written in the style of mini-OOF, which apparently people like
>
[...]
>
> Everything you say is exactly correct. Maybe the code is not too obtuse.

I just suppose, having some comments or longer names at least, it could
take less time to me to understand these details :)

[...]
>> Although, the name "m:" is better than ":m" for a word that starts a
>> definition and has a parsed argument. (See also a small discussion on
>> this regard several months ago [1])
>
> :M has historical use dating back to 1984 (Neon) and is still used by
> Win32Forth I believe.

Probably we already discussed this, but I hadn't remembered that when
wrote it -)

[...]
>>> 1 bar .. y !
>>> page
>>> foo draw
>>> bar draw
>>>
>>> [then]
>>>
>>> 0 [if] \ another example
>>>   \ note re-use of draw (and there is no inheritance relationship)
>>> object class point
>>>    cell var x
>>>    cell var y
>>>   :m p! ( x y -- ) y ! x ! ;m
>>>   :m p@ ( -- x y ) x @ y @ ;m
>>>   :m draw x ? y ? ;m
>>>   :m :init ( x y -- ) self p! ;m  \ late bind
>>> \ :m :init ( x y -- ) [ point :: p! ] ;m \ alternatively early bind
>>> drop
>>>
>>> 1 2 point new constant p1
>>> p1 draw cr
>>> foo draw  \ draw still works on foo and bar
>>> page bar draw
>>> : test 3 4 p1 p! p1 draw  p1 .. x @ p1 .. y @ + . ;
>> (2)
>>> test
>>> \ => 3 4 7
>>>
>>> [then]
>>
>> If these both examples are uncommented, and the file is loaded, the
>> phrase:
>>
>>    bar .. y @ .
>>
>> should print "1", but it actually prints "11" due to the problem (1).
>
> Odd. It works fine on VFX, SwiftForth, and Gforth 0.7.3.

Maybe I do something wrong.
I uncomment the examples, add at the end:

bar .. y @ cr .( bar.y = ) . cr

and put the source into gist.

Now execution of the following shell command:

curl -L https://git.io/JoowS | gforth

prints at the end:

bar.y = 11

The same on Gforth 0.7.2 and Gforth 0.7.9_20210218

>> Also, the line (2) doesn't work as expected since it implies special
>> compilation semantics for "..", that are not defined.
>
> Again, I don't see this problem on the 3 Forths mentioned.

On execution the above shell command, on performing "test" after the
line (2), it shows the following error:

*the terminal*:82:5: error: Attempt to use zero-length string as a name

Probably we test different source codes.

>> To fix this problem, ".." can be defined as follows:
>>
>>    : .. ( "name-field" -- | obj "name-field" -- addr-field )
>>      ' >body @  tt-lit ['] + tt-xt
>>    ; immediate
>>
>>
>>    \ Where "tt-lit" and "tt-xt" are translators for x and xt data types
>>    \ correspondingly, see "minimalistic core API for recognizers" [2].
>>    \ They can be defined as follows:
>>    : tt-lit ( x -- x | ) state @ if lit, exit then ;
>>    : tt-xt ( i*x xt -- j*x ) state @ if compile, exit then execute
>
> lit, is not standard and must be defined.

Yes, I just suppose that most of us already know this word and so I
didn't provide its definition:

: lit, postpone literal ;

[...]

--
Ruvim

Re: Another mini-oop

<61634f52$0$701$14726298@news.sunsite.dk>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=14919&group=comp.lang.forth#14919

  copy link   Newsgroups: comp.lang.forth
Path: rocksolid2!i2pn.org!news.uzoreto.com!dotsrc.org!filter.dotsrc.org!news.dotsrc.org!not-for-mail
Subject: Re: Another mini-oop
Newsgroups: comp.lang.forth
References: <613dfe6e$0$700$14726298@news.sunsite.dk>
<sjuf1e$bbi$1@dont-email.me> <6162e4a6$0$700$14726298@news.sunsite.dk>
<sjutiv$fpp$1@dont-email.me>
From: dhoffman...@gmail.com (Doug Hoffman)
Date: Sun, 10 Oct 2021 16:38:39 -0400
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:78.0)
Gecko/20100101 Thunderbird/78.14.0
MIME-Version: 1.0
In-Reply-To: <sjutiv$fpp$1@dont-email.me>
Content-Type: text/plain; charset=utf-8; format=flowed
Content-Language: en-US
Content-Transfer-Encoding: 8bit
Lines: 21
Message-ID: <61634f52$0$701$14726298@news.sunsite.dk>
Organization: SunSITE.dk - Supporting Open source
NNTP-Posting-Host: 8aef4cf4.news.sunsite.dk
X-Trace: 1633898322 news.sunsite.dk 701 glidedog@gmail.com/68.55.82.126:63592
X-Complaints-To: staff@sunsite.dk
 by: Doug Hoffman - Sun, 10 Oct 2021 20:38 UTC

On 10/10/21 10:33 AM, Ruvim wrote:

>>>    bar .. y @ .
>>> should print "1", but it actually prints "11" due to the problem (1).

Eliminate the definition : .. ' >body @ + ;

Now do message-less instance variable access like this:
bar to self y @ . \ => "1"

>>> Also, the line (2) doesn't work as expected since it implies special
>>> compilation semantics for "..", that are not defined.
: test 3 4 p1 p! p1 draw p1 to self x @ y @ + . ;
test
\ => 3 4 7

If one uses self this way *inside* a class definition to access another
object's instance variables then the contents of self must be kept and
restored. This mini-oop just became smaller.

-Doug

Re: Another mini-oop

<sjvocg$anp$1@dont-email.me>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=14921&group=comp.lang.forth#14921

  copy link   Newsgroups: comp.lang.forth
Path: rocksolid2!i2pn.org!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail
From: ruvim.pi...@gmail.com (Ruvim)
Newsgroups: comp.lang.forth
Subject: Re: Another mini-oop
Date: Mon, 11 Oct 2021 01:10:24 +0300
Organization: A noiseless patient Spider
Lines: 150
Message-ID: <sjvocg$anp$1@dont-email.me>
References: <613dfe6e$0$700$14726298@news.sunsite.dk>
<sjuf1e$bbi$1@dont-email.me> <6162e4a6$0$700$14726298@news.sunsite.dk>
Mime-Version: 1.0
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 8bit
Injection-Date: Sun, 10 Oct 2021 22:10:25 -0000 (UTC)
Injection-Info: reader02.eternal-september.org; posting-host="995f90f1dcf3418c369fcae0d7717970";
logging-data="11001"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX18LHcxhcqlTBTmYd2gL2ehN"
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:91.0) Gecko/20100101
Thunderbird/91.2.0
Cancel-Lock: sha1:L8MNzrfWSvkH1Eoka9KY5vpvp30=
In-Reply-To: <6162e4a6$0$700$14726298@news.sunsite.dk>
Content-Language: en-US
 by: Ruvim - Sun, 10 Oct 2021 22:10 UTC

On 2021-10-10 16:03, Doug Hoffman wrote:
> On 10/10/21 6:24 AM, Ruvim wrote:
>> On 2021-09-12 16:19, Doug Hoffman wrote:
>>> After paring away, the following code would be my idea of a mini-oop
>>> extension for Forth.
[...]
>>> \ *** end code
>>
>> I have taken a closer look at this example. Very concise code, but too
>> magical! I mean, plenty of magic numbers and abbreviated names, and
>> lack of comments in the same time.
>
> Yes. It was written in the style of mini-OOF, which apparently people like
>
[...]
>> Since the set of selectors is single and global, I would place all the
>> selectors into one single wordlist.
>
> I have tried that and was not satisfied with the extra code required.
> Especially having to "reset" the search order in various places such as
> when a method compilation fails. Besides, In the Smalltalk model all
> message names are global.

A little disclaimer. I don't try to say what is better in your or
somebody's else particular case, but what could be better in my case or
in some abstract case that I imagine. Also I just share my thoughts or
reasonings. And sometimes I provide some additional information just to
be better understandable by other participants.

I find namespaces very useful and sometimes even crucial. Having
separate namespace for selectors an author can avoid some conflicts in
enough big programs.

As I can see, even Smalltalk now supports namespaces:
https://www.gnu.org/software/smalltalk/manual/html_node/Namespaces.html

Restoring of the search order is really a problem. A program can restore
it on the files boundaries, but not on lexical blocks level.

To do it on the lexical blocks level a program needs to nest the Forth
text interpreter. With FIND and Co. this problem can be solved only
partially. But it can be completely solved via recognizers, since the
top-level recognizer represents the step of the text interpreter loop.

>> At the moment, depending on the search order, a duplicate of selector
>> can be created, and then a defined method will be unfound in some cases.
>
> In those cases we *want* it to be unfound.

The problem is that you cannot guarantee that it will be unfound. Since
it depends on whether the selector for this method is available or not.

Also it makes selectors not global. And I don't yet see a use case when
it can be useful.

A small test case is following.

\ some helpers
: exch-current ( wid2 -- wid1 ) get-current swap set-current ;
: dev{ ( wid2 -- wid1 ) dup >order exch-current ;
: }dev ( wid1 -- ) previous exch-current drop ;
: export ( wid1 -- wid1 ) dup set-current ;

object class box1
:m open "(box1/open)" type ;m
drop

wordlist dup constant module2-private dev{
\ NB: selector for "open" is available,
\ but selector for "show" is not.
object class msgbox2
:m open "(msgbox2/open)" type ;m
:m show "(msgbox2/show)" type ;m
drop
export
synonym msgbox2 msgbox2
}dev

msgbox2 new constant mb2

mb2 open \ works
mb2 show \ doesn't work

msgbox2 class msgbox31
:m test self open self show "(msgbox31/test)" type ;m
\ "show" -- cannot be compiled
drop

box1 class box2
:m show "(box2/show)" type ;m
drop

msgbox2 class msgbox32
:m test self open self show "(msgbox32/test)" type ;m
drop

msgbox32 new constant mb32
mb32 test
\ now "show" is not found in run-time.

It's a case when "open" and "show" methods are defined in the same way
in the class "msgbox2", but accessibility of these methods is different.
It's error prone if the system allows such a situation.

>> Having a separate word list for selectors, a selector duplicate is
>> impossible, and the call of a method with help of a recognizer can
>> look as:
>>
>>    msg::draw
>>
>> I.e., it's qualified. Another variant is to just include the "msg"
>> wordlist into the search order, but this variant is more error-prone.
>
> Yes. And more complex, which I strive to avoid.
>
>> The word "var" unconditionally creates a new definition on every use.
>> So, it shadows the previous definition with the same name. (1)
>> Probably, such definitions should be local for their classes.
>
> mini-OOF does it this way and many seem to like it. However, I have
> written a, larger and more complex, version of what I show in the first
> post of this thread that uses one wordlist for each class so instance
> variable names are totally protected:
>
> https://github.com/DouglasBHoffman/FMS2  (FMS2LL)
>
> The code is more complex and uses about 4200 bytes instead of 1200
> bytes (it has other oop features as well). But it is there for those
> that want it.

Wow, far more comments! I didn't read them before )))
You had to place this link in the first post too.

[...]

--
Ruvim

Re: Another mini-oop

<sjvpnb$klu$1@dont-email.me>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=14922&group=comp.lang.forth#14922

  copy link   Newsgroups: comp.lang.forth
Path: rocksolid2!news.neodome.net!3.eu.feeder.erje.net!feeder.erje.net!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail
From: ruvim.pi...@gmail.com (Ruvim)
Newsgroups: comp.lang.forth
Subject: Re: Another mini-oop
Date: Mon, 11 Oct 2021 01:33:15 +0300
Organization: A noiseless patient Spider
Lines: 39
Message-ID: <sjvpnb$klu$1@dont-email.me>
References: <613dfe6e$0$700$14726298@news.sunsite.dk>
<sjuf1e$bbi$1@dont-email.me> <6162e4a6$0$700$14726298@news.sunsite.dk>
<sjutiv$fpp$1@dont-email.me> <61634f52$0$701$14726298@news.sunsite.dk>
Mime-Version: 1.0
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 8bit
Injection-Date: Sun, 10 Oct 2021 22:33:15 -0000 (UTC)
Injection-Info: reader02.eternal-september.org; posting-host="995f90f1dcf3418c369fcae0d7717970";
logging-data="21182"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1++jVldYDJ5JgrojP705ac2"
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:91.0) Gecko/20100101
Thunderbird/91.2.0
Cancel-Lock: sha1:EWyzFxZQlEd//lywlTWjfLd0wCQ=
In-Reply-To: <61634f52$0$701$14726298@news.sunsite.dk>
Content-Language: en-US
 by: Ruvim - Sun, 10 Oct 2021 22:33 UTC

On 2021-10-10 23:38, Doug Hoffman wrote:
> On 10/10/21 10:33 AM, Ruvim wrote:
>
>>>>    bar .. y @ .
>>>> should print "1", but it actually prints "11" due to the problem (1).
>
> Eliminate the definition : ..  ' >body @ +  ;
>
> Now do message-less instance variable access like this:
> bar to self y @ . \ => "1"

It prints "11" anyway. Since in this case the problem not in "..", but
in shadowing.

It applies to the object of the class "bold-button" the accessor "y"
from the class "point". Since "y" of the former is shadowed by "y" of
the latter.

Even very limited OOP should allow the same named properties in the
different classes, I think.

>>>> Also, the line (2) doesn't work as expected since it implies special
>>>> compilation semantics for "..", that are not defined.
> : test 3 4 p1 p! p1 draw  p1 to self x @  y @ + . ;
> test
> \ => 3 4 7
>
> If one uses self this way *inside* a class definition to access another
> object's instance variables then the contents of self must be kept and
> restored. This mini-oop just became smaller.

A possible solution is to just disallow access to not own instance
variables (properties).

--
Ruvim

Re: Another mini-oop

<61641de5$0$698$14726298@news.sunsite.dk>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=14928&group=comp.lang.forth#14928

  copy link   Newsgroups: comp.lang.forth
Path: rocksolid2!news.neodome.net!weretis.net!feeder8.news.weretis.net!usenet.goja.nl.eu.org!dotsrc.org!filter.dotsrc.org!news.dotsrc.org!not-for-mail
Subject: Re: Another mini-oop
Newsgroups: comp.lang.forth
References: <613dfe6e$0$700$14726298@news.sunsite.dk>
<sjuf1e$bbi$1@dont-email.me> <6162e4a6$0$700$14726298@news.sunsite.dk>
<sjutiv$fpp$1@dont-email.me> <61634f52$0$701$14726298@news.sunsite.dk>
<sjvpnb$klu$1@dont-email.me>
From: dhoffman...@gmail.com (Doug Hoffman)
Date: Mon, 11 Oct 2021 07:20:02 -0400
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:78.0)
Gecko/20100101 Thunderbird/78.14.0
MIME-Version: 1.0
In-Reply-To: <sjvpnb$klu$1@dont-email.me>
Content-Type: text/plain; charset=utf-8; format=flowed
Content-Language: en-US
Content-Transfer-Encoding: 7bit
Lines: 27
Message-ID: <61641de5$0$698$14726298@news.sunsite.dk>
Organization: SunSITE.dk - Supporting Open source
NNTP-Posting-Host: 64d7395c.news.sunsite.dk
X-Trace: 1633951205 news.sunsite.dk 698 glidedog@gmail.com/68.55.82.126:65163
X-Complaints-To: staff@sunsite.dk
 by: Doug Hoffman - Mon, 11 Oct 2021 11:20 UTC

On 10/10/21 6:33 PM, Ruvim wrote:

> It prints "11" anyway. Since in this case the problem not in "..", but
> in shadowing.

I should have warned that instance variable names can shadow and be
shadowed. But the example code will run correctly if executed in the
order as presented.

> Even very limited OOP should allow the same named properties in the
> different classes, I think.

It is allowed. But names can be shadowed. So one needs to either
not shadow or only use getter/setter methods for shadowed instance
variables.

Other minimalist Forth oop extensions have the same issue.

> A possible solution is to just disallow access to not own instance
> variables (properties).

Agreed. This is my personal preference and practice. But others
want message-less instance variable access. It was trivial to
provide it here so I did. My mistake was in not warning about the
shadowing issue.

-Doug

Re: Another mini-oop

<61642136$0$692$14726298@news.sunsite.dk>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=14929&group=comp.lang.forth#14929

  copy link   Newsgroups: comp.lang.forth
Path: rocksolid2!news.neodome.net!feeder1.feed.usenet.farm!feed.usenet.farm!news.uzoreto.com!dotsrc.org!filter.dotsrc.org!news.dotsrc.org!not-for-mail
Subject: Re: Another mini-oop
Newsgroups: comp.lang.forth
References: <613dfe6e$0$700$14726298@news.sunsite.dk>
<sjuf1e$bbi$1@dont-email.me> <6162e4a6$0$700$14726298@news.sunsite.dk>
<sjvocg$anp$1@dont-email.me>
From: dhoffman...@gmail.com (Doug Hoffman)
Date: Mon, 11 Oct 2021 07:34:11 -0400
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:78.0)
Gecko/20100101 Thunderbird/78.14.0
MIME-Version: 1.0
In-Reply-To: <sjvocg$anp$1@dont-email.me>
Content-Type: text/plain; charset=utf-8; format=flowed
Content-Language: en-US
Content-Transfer-Encoding: 7bit
Lines: 19
Message-ID: <61642136$0$692$14726298@news.sunsite.dk>
Organization: SunSITE.dk - Supporting Open source
NNTP-Posting-Host: 64d7395c.news.sunsite.dk
X-Trace: 1633952054 news.sunsite.dk 692 glidedog@gmail.com/68.55.82.126:65198
X-Complaints-To: staff@sunsite.dk
 by: Doug Hoffman - Mon, 11 Oct 2021 11:34 UTC

On 10/10/21 6:10 PM, Ruvim wrote:

> I find namespaces very useful and sometimes even crucial.

I provide them in FMS2 at https://github.com/DouglasBHoffman/FMS2

> Restoring of the search order is really a problem. A program can restore
> it on the files boundaries, but not on lexical blocks level.
>
> To do it on the lexical blocks level a program needs to nest the Forth
> text interpreter. With FIND and Co. this problem can be solved only
> partially. But it can be completely solved via recognizers, since the
> top-level recognizer represents the step of the text interpreter loop.

I have a word "restore" in FMS2 that does what I think is needed.
Recognizers may be a superior technique but I have not studied them yet.

-Doug

Re: Another mini-oop

<sk42j2$p7i$1@dont-email.me>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=14931&group=comp.lang.forth#14931

  copy link   Newsgroups: comp.lang.forth
Path: rocksolid2!news.neodome.net!3.eu.feeder.erje.net!feeder.erje.net!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail
From: ruvim.pi...@gmail.com (Ruvim)
Newsgroups: comp.lang.forth
Subject: Re: Another mini-oop
Date: Tue, 12 Oct 2021 16:29:05 +0300
Organization: A noiseless patient Spider
Lines: 95
Message-ID: <sk42j2$p7i$1@dont-email.me>
References: <613dfe6e$0$700$14726298@news.sunsite.dk>
<sjuf1e$bbi$1@dont-email.me> <6162e4a6$0$700$14726298@news.sunsite.dk>
<sjvocg$anp$1@dont-email.me> <61642136$0$692$14726298@news.sunsite.dk>
Mime-Version: 1.0
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 7bit
Injection-Date: Tue, 12 Oct 2021 13:29:07 -0000 (UTC)
Injection-Info: reader02.eternal-september.org; posting-host="84e70305e768665e4de7616833d27c2b";
logging-data="25842"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX19jUuDII1pvgDLBG5nCHlVE"
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:91.0) Gecko/20100101
Thunderbird/91.2.0
Cancel-Lock: sha1:dkQ9oWoMVfV2L6dZnjDiy5SjCGA=
In-Reply-To: <61642136$0$692$14726298@news.sunsite.dk>
Content-Language: en-US
 by: Ruvim - Tue, 12 Oct 2021 13:29 UTC

On 2021-10-11 14:34, Doug Hoffman wrote:
> On 10/10/21 6:10 PM, Ruvim wrote:
>
>> I find namespaces very useful and sometimes even crucial.

I mean namespaces as a conception. The standard word lists can play the
role of namespaces almost perfectly (when they are used). But the
standard provides only basic primitive tools for that.

I don't mean that an OOP module should use word lists or namespaces in
general. But no OOP module may violate a program in this regard.

>
> I provide them in FMS2 at https://github.com/DouglasBHoffman/FMS2

Probably you mean that namespaces (word lists) are *used* in FSM2.
Or do you provide some tools to manage namespaces? (please point to a
particular file then)

>> Restoring of the search order is really a problem. A program can
>> restore it on the files boundaries, but not on lexical blocks level.
>>
>> To do it on the lexical blocks level a program needs to nest the Forth
>> text interpreter. With FIND and Co. this problem can be solved only
>> partially. But it can be completely solved via recognizers, since the
>> top-level recognizer represents the step of the text interpreter loop.
>
> I have a word "restore" in FMS2 that does what I think is needed.

You wrote before about an error case ("compilation fails"):

| to "reset" the search order in various places
| such as when a method compilation fails.

If a method compilation fails, you cannot catch the corresponding
exception and perform "restore-order".

In FSM2LL.f, you as if define lexical blocks:

:class ... ;class

But you cannot process such a block as a single unit.
If an error occurs, you cannot catch this error and restore the search
order on the moment before ":class".

It's what I meant above.

> Recognizers may be a superior technique but I have not studied them yet.

In this case we don't need additional recognizers, we need to nest of
the Forth text interpreter. But when we nest it, we also need to unnest
it. So, we cannot just call "INTERPRET" (even if it's present). We need
to translate each word until ";class" is reached.

Conventional "interpret" can be defined as follows:

: interpret
begin parse-name dup while translate-lexeme ?nf ?stack repeat
2drop
;

Recognizer API just provides a way to define "translate-lexeme" or even
provides such a word itself.

And so it provides us with a way to nest the text interpreter, as follows.

: equals compare 0= ;

: interpret-till ( ... sd-name -- ... sd-name | ... 0 0 )
2>r begin parse-name dup while
2dup 2r@ equals if 2rdrop exit then
translate-lexeme ?nf ?stack
repeat 2rdrop
;

: :class
...
get-order n>r get-current >r
...
[: ";class" interpret-till nip 0= if -22 throw then ;] catch
r> set-current nr> set-order
throw ;class
;

So the word ":class" can restore the search order even if an error occurs.

--
Ruvim

Re: Another mini-oop

<61661c48$0$692$14726298@news.sunsite.dk>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=14934&group=comp.lang.forth#14934

  copy link   Newsgroups: comp.lang.forth
Path: rocksolid2!news.neodome.net!news.uzoreto.com!dotsrc.org!filter.dotsrc.org!news.dotsrc.org!not-for-mail
From: dhoffman...@gmail.com (Doug Hoffman)
Subject: Re: Another mini-oop
Newsgroups: comp.lang.forth
References: <613dfe6e$0$700$14726298@news.sunsite.dk>
<sjuf1e$bbi$1@dont-email.me> <6162e4a6$0$700$14726298@news.sunsite.dk>
<sjvocg$anp$1@dont-email.me> <61642136$0$692$14726298@news.sunsite.dk>
<sk42j2$p7i$1@dont-email.me>
X-Mozilla-News-Host: news://news.sunsite.dk
Date: Tue, 12 Oct 2021 19:37:43 -0400
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:78.0)
Gecko/20100101 Thunderbird/78.14.0
MIME-Version: 1.0
In-Reply-To: <sk42j2$p7i$1@dont-email.me>
Content-Type: text/plain; charset=utf-8; format=flowed
Content-Language: en-US
Content-Transfer-Encoding: 8bit
Lines: 114
Message-ID: <61661c48$0$692$14726298@news.sunsite.dk>
Organization: SunSITE.dk - Supporting Open source
NNTP-Posting-Host: ef04858a.news.sunsite.dk
X-Trace: 1634081865 news.sunsite.dk 692 glidedog@gmail.com/68.55.82.126:64817
X-Complaints-To: staff@sunsite.dk
 by: Doug Hoffman - Tue, 12 Oct 2021 23:37 UTC

On 10/12/21 9:29 AM, Ruvim wrote:
> On 2021-10-11 14:34, Doug Hoffman wrote:
>> On 10/10/21 6:10 PM, Ruvim wrote:
>>
>>> I find namespaces very useful and sometimes even crucial.
>
> I mean namespaces as a conception. The standard word lists can play the
> role of namespaces almost perfectly (when they are used). But the
> standard provides only basic primitive tools for that.
>
> I don't mean that an OOP module should use word lists or namespaces in
> general. But no OOP module may violate a program in this regard.
>
>
>>
>> I provide them in FMS2 at https://github.com/DouglasBHoffman/FMS2
>
> Probably you mean that namespaces (word lists) are *used* in FSM2.

Yes. This is what I meant.

> Or do you provide some tools to manage namespaces? (please point to a
> particular file then)

No. I provide no tools.

>>> Restoring of the search order is really a problem. A program can
>>> restore it on the files boundaries, but not on lexical blocks level.
>>>
>>> To do it on the lexical blocks level a program needs to nest the
>>> Forth text interpreter. With FIND and Co. this problem can be solved
>>> only partially. But it can be completely solved via recognizers,
>>> since the top-level recognizer represents the step of the text
>>> interpreter loop.
>>
>> I have a word "restore" in FMS2 that does what I think is needed.
>
> You wrote before about an error case ("compilation fails"):
>
> | to "reset" the search order in various places
> | such as when a method compilation fails.
>
> If a method compilation fails, you cannot catch the corresponding
> exception and perform "restore-order".

That is correct. What I do in FMS is simply capture the search order
"[0] when FMS is compiled". Upon a subsequent class compilation error
manually executing "restore-order" merely resets the search order to
[0]. This may not be the desired behavior. Though I do execute
restore-order using the deferred word restore. So it can be changed by
the user.

> In FSM2LL.f, you as if define lexical blocks:
>
>   :class ... ;class
>
> But you cannot process such a block as a single unit.
> If an error occurs, you cannot catch this error and restore the search
> order on the moment before ":class".
>
> It's what I meant above.

Got it.

>> Recognizers may be a superior technique but I have not studied them yet.
>
> In this case we don't need additional recognizers, we need to nest of
> the Forth text interpreter. But when we nest it, we also need to unnest
> it. So, we cannot just call "INTERPRET" (even if it's present). We need
> to translate each word until ";class" is reached.
>
> Conventional "interpret" can be defined as follows:
>
>   : interpret
>     begin parse-name dup while translate-lexeme ?nf ?stack repeat
>     2drop
>   ;
>
> Recognizer API just provides a way to define "translate-lexeme" or even
> provides such a word itself.
>
> And so it provides us with a way to nest the text interpreter, as follows.
>
>   : equals compare 0= ;
>
>   : interpret-till ( ... sd-name -- ... sd-name | ... 0 0 )
>     2>r begin parse-name dup while
>       2dup 2r@ equals if 2rdrop exit then
>       translate-lexeme ?nf ?stack
>     repeat 2rdrop
>   ;
>
>   : :class
>     ...
>     get-order n>r get-current >r
>     ...
>     [: ";class" interpret-till nip 0= if -22 throw then ;] catch
>     r> set-current nr> set-order
>     throw  ;class
>   ;
>
>
> So the word ":class" can restore the search order even if an error occurs.

Thanks for the explanation. I need to study the recognizer information.

-Doug

> --
> Ruvim

Re: Another mini-oop

<sk7l0u$3u0$1@dont-email.me>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=14937&group=comp.lang.forth#14937

  copy link   Newsgroups: comp.lang.forth
Path: rocksolid2!news.neodome.net!weretis.net!feeder8.news.weretis.net!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail
From: ruvim.pi...@gmail.com (Ruvim)
Newsgroups: comp.lang.forth
Subject: Re: Another mini-oop
Date: Thu, 14 Oct 2021 01:02:04 +0300
Organization: A noiseless patient Spider
Lines: 95
Message-ID: <sk7l0u$3u0$1@dont-email.me>
References: <613dfe6e$0$700$14726298@news.sunsite.dk>
<sjuf1e$bbi$1@dont-email.me> <6162e4a6$0$700$14726298@news.sunsite.dk>
Mime-Version: 1.0
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 8bit
Injection-Date: Wed, 13 Oct 2021 22:02:06 -0000 (UTC)
Injection-Info: reader02.eternal-september.org; posting-host="fd6a36f0527e0b7d6d8c69a8e1d91bf3";
logging-data="4032"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX191jaQsNTh83PUaQd8AGuMf"
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:91.0) Gecko/20100101
Thunderbird/91.2.0
Cancel-Lock: sha1:huEMOTY+qSC3FmJ7vXjpMpsz+6E=
In-Reply-To: <6162e4a6$0$700$14726298@news.sunsite.dk>
Content-Language: en-US
 by: Ruvim - Wed, 13 Oct 2021 22:02 UTC

On 2021-10-10 16:03, Doug Hoffman wrote:
> On 10/10/21 6:24 AM, Ruvim wrote:
>> On 2021-09-12 16:19, Doug Hoffman wrote:
>>> After paring away, the following code would be my idea of a mini-oop
>>> extension for Forth.
[...]
>> The word "var" unconditionally creates a new definition on every use.
>> So, it shadows the previous definition with the same name. (1)
>> Probably, such definitions should be local for their classes.
>
> mini-OOF does it this way and many seem to like it.

It seems, those many who like it need just a toy.

One of basic OOP features is encapsulation. So it's very unexpected to
an OOP model to not isolate instance variable accessors of different
classes from each other (and even from other code out of the classes).

As I can see, a sound OOP model cannot be implemented without utilizing
namespaces.

[...]

>> To fix this problem, ".." can be defined as follows:
>>
>>    : .. ( "name-field" -- | obj "name-field" -- addr-field )
>>      ' >body @  tt-lit ['] + tt-xt
>>    ; immediate
>>
>>
>>    \ Where "tt-lit" and "tt-xt" are translators for x and xt data types
>>    \ correspondingly, see "minimalistic core API for recognizers" [2].
>>    \ They can be defined as follows:
>>    : tt-lit ( x -- x | ) state @ if lit, exit then ;
>>    : tt-xt ( i*x xt -- j*x ) state @ if compile, exit then execute
>
> lit, is not standard and must be defined.
> Then what you show works,
> at the cost of state-smartness and additional code.

By the way, the magnitude of the "state-smartness" problem was
overestimated. The only problem in this regard is the problem of
incomplete "postpone", and this problem can be easy solved via a
standard polyfill.

[...]
>> Also, you need the class to make an early bound method call.

I mean unification: to do it by providing a class for both early binding
and accessing another's instance variables.

> Yes, the provided code in the original post of this thread shows how in
> the example use code. Is it a problem to provide the class when wanting
> early binding?  e.g., [ point :: draw ]
> Again, I always get complaints about "too much code" and "it is too
> complicated". [ point :: draw ] is dead simple to use with very little
> support code.

It doesn't look like a code that compiles anything.

A better variant:

[ point ]-> draw
or
[ point ]:: draw

Where

: ]:: ( cls "name" -- ) ] ' >body swap mfa fm compile, ; immediate

Also it's less likely to be misused.

But switching to interpretation state looks too forced and unnatural in
any case.

>
> Here  https://github.com/DouglasBHoffman/FMS2  I use:
>
> self  draw  \ late bind
> eself draw  \ early bind

I also saw "own draw" for early binding in some OOP implementations.

But my choice is to use early binding in a simple way (without any
special things), and use some special things/decorators for late binding
only. Rationale: late binding is required much less frequently than
early binding.

--
Ruvim

Pages:12
server_pubkey.txt

rocksolid light 0.9.8
clearnet tor