Long time no see!

20 views
Skip to first unread message

The Beez

unread,
May 2, 2021, 10:38:53 AM5/2/21
to 4tH-compiler
Hi 4tH-ers!

You haven't heard from me for along time, so let me explain what I've been doing alls this time.

You know I have been working for a LONG time on a humble Banana Pi M3. September last year I've gotten my brand new machine. In the old times I would have installed it up to the point where I essentially got most of my old machine back.

Unfortunately, that goes with a lot of stress, so I rarely expose myself to that. My work is stressing enough and I need my time to recuperate. I'll be 61 this year, in a few years 4tH will hit its 30th anniversary, so you can imagine I'm not the young god I used to be.

That means, most time I do during vacations, when I'm well rested and have few things that require my attention. I got my machine with Ubuntu 20.04 preinstalled, so my first attention was to restore the functionality of the Banana - since that is the setup I need for work. Which is particularly important in these times.

I wanted to restore my files from the 12 years old disks from my old machine. They're nicely located in a few USB enclosures, but 12 years - you never know what happens when you expose them to a long and intense workload. So I put that off.

The Xmas vacation I spend on restoring the monitoring capacity of my Raspi Pi B, which involved hooking it up to my old VGA monitor.

This vacation I've spend on restoring over a MILLION files of my old machine. I already got a few X-compilers working as well. My old development environment for packaging is restored as well. Yesterday I spend a whole day on configuring my old account. 

Since it is stored on a different, unpartitioned disk, I had some(!) trouble with getting SNAP packages to work. They don't work over a symbolic link, so I had to remount the disk under /home/users. Then I had to add the directory under /etc/apparmor.d/tunables/home.

Finally, finally it worked. Except for the keyboard in graphical apps. This was due to an ibus conflict, which had to be fixed by setting it to a different value in the MATE control center. I was exhausted after that, I must admit. In the end, it seems so simple and if I'd had that solution, it would have been fixed in 15 mins.

Next, I've tackled a thing in FOOS. The constructor was defined in a much different way from all other methods and that didn't do. So, I've defined a :NEW method. It is defined much like the :DELETE method, but uses a completely different technique. Note you can STILL use the "old" method as well.

The only restriction is that IF you use the new method, you MUST use curly braces. Other methods allow you to handle the object address yourself, but I must admit, I hardly ever do, so I can safely assume others won't as well. It takes away the abstraction and is a lot of hassle.

It requires some more testing, but I'm pretty confident it works just fine. Your class definitions get a lot less quirky look:

:class CarBuilder
   extends ICarBuilder
     field: _Car_
   end-extends {

     :new { new Car this -> _Car_ ! } ;method
     :virtual SetColor  { this -> _Car_ @ => Color!  } ;method
     :virtual SetWheels { this -> _Car_ @ => Wheels! } ;method
     :virtual Result@ { this -> _Car_ @ } ;method
     :delete { this -> _Car_ @ delete } ;method
   }

   private{ _Car_ }
;class

It works like replicating the address on the returnstack, so the braces can do their job. Of course, it requires an extra address on the stack, but if you're this much stack space, I guess you're in trouble already.

You may also note I've added a few odd routines. I did a 64 bit version of KISS, since otherwise you wouldn't have a high performance randomizer on you 64 bit machine.

Second, I've written a few routines I need to implement a lean version of ZIP. Without that one, formats like .XLSX are impossible, since these require ZIP. I can only tell you that the one posted on a Forth site won't do. These produce files which are so mangled that most ZIPers barf them out - so I gotta do this myself. I don't expect to include these in the current version, it's just a new project.

Having back my staging area means I can now start releasing stuff. Like I said before, it won't be all platforms at once. It'll be a few major ones and them some added bit by bit.

So, now you know where I'm at. Comments welcome.

Hans Bezemer

The Beez

unread,
May 3, 2021, 12:38:13 PM5/3/21
to 4tH-compiler
Hi 4tH-ers!

When looking at the code yesterday, I found out that curled braces are almost everywhere. So I thought, why not kill these pesky things. And that experiment worked out just fine. Even the :NEW problem of the previous FOOS version was solved this way. 

Drawback: don't exit methods prematurely using ?EXIT, EXIT or ;THEN. If you know what you're doing, you can get away with it using "}" (yes, it's still there), but you make your life a little more difficult that way. BTW, previous versions have had the same drawback, so not much is lost. The advantage is a MUCH cleaner and more Forth-like syntax:

\ Preprocessor FOOS command pattern demo - Copyright 2017, 2021 J.L. Bezemer
\ You can redistribute this file and/or modify it under
\ the terms of the GNU General Public License

include foos.4pp

\ The Command interface
:class Command
   extends Object
     virtual: MakeItSo
   end-extends
;class

\ The Invoker class
:class Switch                          ( cmd --)
   extends Object
     virtual: DoIt
   end-extends

   :virtual DoIt => MakeItSo ;method
;class

\ The Receiver class
:class Light
   extends Object
     virtual: turnOn
     virtual: turnOff
   end-extends

   :virtual turnOn  ." The light is on"  cr ;method
   :virtual turnOff ." The light is off" cr ;method
;class

\ The Command for turning on the light - ConcreteCommand #1
:class FlipUpCommand                   ( light --)
   extends Command
     field: theLight
   end-extends

   :new this -> theLight ! ;method
   :virtual MakeItSo this -> theLight @ => turnOn ;method

   private{ theLight }
;class

\ The Command for turning off the light - ConcreteCommand #2
:class FlipDownCommand                 ( light --)
   extends Command
     field: theLight
   end-extends

   :new this -> theLight ! ;method
   :virtual MakeItSo this -> theLight @ => turnOff ;method

   private{ theLight }
;class

static Light lamp
lamp static FlipUpCommand switchUp
lamp static FlipDownCommand switchDown
static Switch mySwitch

switchUp   mySwitch => DoIt
switchDown mySwitch => DoIt
switchUp   mySwitch => DoIt

I've converted all programs I converted yesterday and it's pretty painless. Lemme know what you think.

Hans Bezemer

The Beez

unread,
May 7, 2021, 4:19:37 AM5/7/21
to 4tH-compiler
Hi 4tH-ers!

It's done! The fifth incarnation of FOOS is a fact. And I'm quite proud of myself, because this was a significant cleanup of the syntax:
  1. It now has proper constructors and destructors without any significant technical drawbacks;
  2. All those pesky curly braces have been removed (they're still there for special occasions, though - like exiting early, switching objects within a method or changing methods of existing instances);
  3. A discrepancy in KINDOF has been fixed - it just returns a type;
  4. Lists and hashmaps were replicated several times. They're now a new kind of library - an class library;
  5. Use of the indispensible Dynamic String library - which makes the code much cleaner and easier to use;
  6. All but one of the examples now have proper destructors - and it works beautifully.
I wouldn't say conversion was a walk in the park. I could be including the wrong FOOS library, the Dynamic String library posed its own challenges - and of course I could always forget a curly brace here and there.
Often the lists and hashmaps would contain objects, so I created a subclass that assumed there were objects stored there, which allowed for a special destructor that would delete them silently when the list itself was deleted.

I think the current incarnation can be compare favorably with other OO Forth frameworks in ease of use and legibility. Lemme know what YOU think!

\ Preprocessor FOOS visitor pattern demo - Copyright 2017, 2021 J.L. Bezemer
\ You can redistribute this file and/or modify it under
\ the terms of the GNU General Public License


include lib/memcell.4th
include lib/dstringt.4th

include 4pp/lib/foos.4pp
include 4pp/foos/list.4pp

:class CarElement
   extends Object
     virtual: Accepts
   end-extends
;class

:class CarElementVisitor
   extends Object
     virtual: visit
   end-extends
;class

:class Wheel
   extends CarElement
     field:  name
     method: getName
   end-extends

   :new this -> name dup ds.init ds.place ;method
   :method getName this -> name ds.count  ;method
   :virtual Accepts this swap => visit    ;method
   :delete this -> name ds.free           ;method
;class

:class Body
   extends CarElement
   end-extends

   :virtual Accepts this swap => visit ;method
;class

:class Engine
   extends CarElement
   end-extends

   :virtual Accepts this swap => visit ;method
;class

:class Car
   extends CarElement
     field: elements
   end-extends

   :new
     new ObjectList this -> elements !

     s" front left"  new Wheel this -> elements @ -> lpush
     s" front right" new Wheel this -> elements @ -> lpush
     s" back left"   new Wheel this -> elements @ -> lpush
     s" back right"  new Wheel this -> elements @ -> lpush

     new Body   this -> elements @ -> lpush
     new Engine this -> elements @ -> lpush
   ;method

   :delete this -> elements @ delete ;method

   :virtual Accepts
      this -> elements @ -> lsize 1- \ example lists these in reverse
      begin                          ( vis i)
        dup 0<
      except
        over over this -> elements @ -> lget swap => visit 1-
      repeat drop this over => visit delete
   ;method
;class

:class CarElementDoVisitor
   extends CarElementVisitor
   end-extends

   :virtual visit
      dup type@ case
        typeof Body   of ." Moving my body" drop endof
        typeof Car    of ." Starting my car" drop endof
        typeof Wheel  of ." Kicking my " -> getName type ."  wheel" endof
        typeof Engine of ." Starting my engine" drop endof
      endcase cr
   ;method
;class

:class CarElementPrntVisitor
   extends CarElementVisitor
   end-extends

   :virtual visit
      dup type@ case
        typeof Body   of ." Visiting body" drop endof
        typeof Car    of ." Visiting car" drop endof
        typeof Wheel  of ." Visiting " -> getName type ."  wheel" endof
        typeof Engine of ." Visiting engine" drop endof
      endcase cr
   ;method
;class

instance Car myCar
new CarElementPrntVisitor myCar => Accepts cr
new CarElementDoVisitor myCar => Accepts

mycar delete

Hans Bezemer

The Beez

unread,
May 8, 2021, 10:28:28 AM5/8/21
to 4tH-compiler
Hi 4tH-ers!

So, all FOOS stuff has been uploaded. If you want a new manual which has been updated to accommodate these changes, you can get one here: https://thebeez.home.xs4all.nl/4tH/4tHmanual.pdf

Have phun!

Hans Bezemer

The Beez

unread,
May 9, 2021, 8:15:50 AM5/9/21
to 4tH-compiler
Hi 4tH-ers!

There have been some subtle, but important changes to FOOS. First of all, ALL examples now have proper constructors and destructors. 

The Singleton example has been almost completely rewritten. The reason for that is that it resembled somewhat a singleton, but as a matter of fact - it wasn't.

The point is - in the examples on the Internet, the new instance is created by calling a function getInstance() and disabling the constructor. Implementing a Multiton design pattern brought me a bit closer - but not completely.

The point is - how do you disable the constructor? In FOOS it is done by the :NEW keyword, which points to a completely hidden field in the object. I can't disable that. It would have no effect. The point is, FOOS *DOES* have a constructor, which is identical to the class name. By making that one private you can issue "new Singleton", "instance Singleton" or "static Singleton" anymore - your only access is through the "getInstance" method.

Now, the instance has to be locked. In other languages, this is achieved by making a static property inside the class - which FOOS doesn't have. So, it has to be allocated outside - which is perfectly feasible. We can even make it private, so outside manipulation doesn't work. By initializing it to (ERROR) we have a perfect way of probing it - through ERROR?

All of that HAS a consequence. Most singletons are created statically - which we made (almost) completely impossible. So - your best way is to make a dynamically created singleton - which is a minor price to pay. But now we're only allowed to call it by "lazy evaluation" (see: https://en.wikipedia.org/wiki/Lazy_initialization). Most languages use the "class name" for that - but we can't because it's also the name for the constructor (as we've seen before). For that, I created a dummy object (actually - just a constant) named "Nothing", which will allow you to do lazy initialization by serving as an object placeholder for calling static methods.

So, to make a long story short, combing all this allows you to create a singleton (or multiton) by using lazy initialization:

  Nothing -> getInstance to mySingleton

Subsequent calls to this method will give you the very same object over and over again, while other methods of creation are blocked. That's a Singleton pattern in my book. So, with all those tiny changes I think I achieved my goal. The FOOS keyword "single" is now superfluous and hence removed. If you ever used that one, take a look at the new implementation. It's in SVN.

Hans Bezemer

Reply all
Reply to author
Forward
0 new messages