Forth Synergy
   ๐Ÿง๐Ÿง๐Ÿง๐Ÿง
     ๐Ÿ™œ
July 24, 2021

FORTH ๐Ÿบ
the LONE WOLF

FORTH IS POWERFUL ๐Ÿ—ฒ
   ๐Ÿ™ค
โ€ข Compile Time Metaprogramming
โ€ข Domain Specific Languages

FORTH IS SUCCINCT ๐Ÿž
   ๐Ÿ™ค
: WASHER
   WASH SPIN RINSE SPIN ;

But FORTH can be CRYPTIC!  ๐Ÿ”ฎ
   ๐Ÿ™ค
: ch>stream ( ch st -- )
   dup wait-write
   >r r@ >write @ r@ >offset c!
   r@ >write @ 1+ r@ @ mod r> >write ! ;

How can we program
        ๐Ÿ‘ช
 Forth together?

Do we ๐Ÿ‘น
 want to?

More Hands aren't
   Always Good!
๐Ÿ–ฎ๐Ÿ’ ๐Ÿ–ฎ๐Ÿ’ ๐Ÿ–ฎ๐Ÿ’ ๐Ÿ–ฎ๐Ÿ’
๐Ÿ–ฎ๐Ÿ’ ๐Ÿ–ฎ๐Ÿ’ ๐Ÿ–ฎ๐Ÿ’ ๐Ÿ–ฎ๐Ÿ’
๐Ÿ–ฎ๐Ÿ’ ๐Ÿ–ฎ๐Ÿ’ ๐Ÿ–ฎ๐Ÿ’ ๐Ÿ–ฎ๐Ÿ’
๐Ÿ–ฎ๐Ÿ’ ๐Ÿ–ฎ๐Ÿ’ ๐Ÿ–ฎ๐Ÿ’ ๐Ÿ–ฎ๐Ÿ’

WHY THEN?      ๐Ÿ‘๐Ÿ‘๐Ÿ‘๐Ÿ‘
   ๐Ÿ™ค
โ€ข Sometimes you're programming
  with YOURSELF from years ago
โ€ข We use words because
  we hope to connect!
โ€ข Help Forth play in a complex world

FOCUS ON TWO GAPS
   ๐Ÿ™ค
โ€ข Modularity ๐Ÿ”Œ
โ€ข Data Abstraction

MODULARITY ๐Ÿ”Œ
    ๐Ÿ™ค
โ€ข Be explicit about interfaces
โ€ข Limit how much has to be
  understood at once
โ€ข Limit the effects of change

THINKING FORTH:                  ๐Ÿ“˜
      ๐Ÿ™ค
"But Forth extends the concepts of modularity
 and information-hiding further than any other
 contemporary language. Forth even hides
 the manner in which words are invoked and
 the way local arguments are passed."

How to make
     ๐Ÿ”Œ
 a Module?

FORML ๐Ÿ‘จโ€โš–๏ธ - Dewey Val Schorre
             ๐Ÿ™ค
: INTERNAL ( --> ADDR) CURRENT @ @ ;
: EXTERNAL ( --> ADDR) HERE ;
: MODULE( ADDRl ADDR2 --> )PFA LFA ! ;
โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”
https://www.complang.tuwien.ac.at
  /forth/forth-dimensions/FD-V2.pdf

INTERNAL                       ๐Ÿ‘จโ€โš–๏ธ
  100 constant stack-depth
  create elements stack-depth cells allot
  variable tos  elements tos !
EXTERNAL
  : >p ( n -- ) cell tos +! tos @ ! ;
  : p@ ( -- n ) tos @ @ ;
  : p> ( -- n ) p@ -1 cells tos +! ;
MODULE

GET-CURRENT VOCABULARY Stack ALSO Stack DEFINITIONS
  100 constant stack-depth
  create elements stack-depth cells allot
  variable tos  elements tos !
SET-CURRENT
  : >p ( n -- ) cell tos +! tos @ ! ;
  : p@ ( -- n ) tos @ @ ;
  : p> ( -- n ) p@ -1 cells tos +! ;
PREVIOUS                                          ๐Ÿ—ซ
โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”
https://www.complang.tuwien.ac.at/forth/gforth
  /Docs-html/Word-list-example.html#Word-list-example

PROBLEMS ๐Ÿ‘Ž ๐Ÿคข
   ๐Ÿ™ค
โ€ข Internals can't call externals
โ€ข Externals are shared with everyone

( What if this is INTERNAL? ๐Ÿคข )
: pover   p> p> dup >r >p >p r> ;
( But this is EXTERNAL ๐Ÿ˜ฒ)
: 2pdup   pover pover ;

GET-CURRENT VOCABULARY Stack ALSO Stack DEFINITIONS
  100 constant stack-depth
  create elements stack-depth cells allot
  variable tos  elements tos !
  : >p ( n -- ) cell tos +! tos @ ! ; ๐Ÿ˜•
  : pover   p> p> dup >r >p >p r> ; ๐Ÿ˜•
SET-CURRENT
  : 2pdup   pover pover ;  ๐Ÿ˜•
  : >p   >p ;  ๐Ÿ˜•
  : p@ ( -- n ) tos @ @ ;
  : p> ( -- n ) p@ -1 cells tos +! ;
PREVIOUS

+----------+
| stack.fs |<----+
+----------+     |
  ^              |
  |              |
+-+------+   +---+----+
| foo.fs |-->| bar.fs |
+--------+   +--------+
       ^      ^
       |      |
     +-+------++
     | main.fs |
     +---------+

N+1th MODULE SYSTEM โž•โž•
   ๐Ÿ™ค
โ€ข Python like import syntax
โ€ข Explicit out of order exports
โ€ข Two wordlists per module
โ€ข Share instances of an import

modules.fs  ๐Ÿ”Œ
โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”
wordlist constant modules
variable exporting
: >wordlist ( xt wid -- )
   get-current >r set-current execute r> set-current ;
: import-name ( a n -- )
   2dup included? 0= if
     2>r exporting @ wordlist exporting ! ( new exports )
     2r> 2dup 2>r nextname exporting @ ['] constant modules >wordlist
     get-current get-order ( save search order )
     only forth wordlist >order definitions ( new wordlist )
     2r> 2dup 2>r included
     set-order set-current ( restore search order )
     exporting ! ( restore exports ) 2r>
   then
   modules search-wordlist 0= throw execute >order ;
: import ( "module" ) bl parse import-name ;
: alias-last   latest name>string nextname lastxt alias ;
: export   ['] alias-last exporting @ >wordlist ;

collections/stack.fs  ๐Ÿ“š
โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”
100 constant stack-depth
create elements stack-depth cells allot
variable tos  elements tos !
: >p ( n -- ) cell tos +! tos @ ! ; EXPORT
: p@ ( -- n ) tos @ @ ; EXPORT
: p> ( -- n ) p@ -1 cells tos +! ; EXPORT

foo.fs  โœจ
โ€”โ€”โ€”โ€”โ€”โ€”
import collections/stack.fs
import bar.fs
: run   1 >p 2 >p 3 >p 3p. ; EXPORT

bar.fs  ๐Ÿ”ฅ
โ€”โ€”โ€”โ€”โ€”โ€”
import collections/stack.fs
: 3p.   p> p> p> . . . cr ; EXPORT

main.fs  ๐Ÿฆž
โ€”โ€”โ€”โ€”โ€”โ€”โ€”
needs modules.fs
import foo.fs
run bye

โš ๏ธ ~ WARNING ~ โš ๏ธ
Uncertain Findings

ELEMENTS OF PROGRAMMING ๐Ÿงช
   ๐Ÿ™ค
โ€ข Primitive Expressions
  - the simplest entities
    the language is concerned with
โ€ข Means of Combination
  - how compound elements are built
    from simpler ones
โ€ข Means of Abstraction
  - how compound elements can be
    named and manipulated as units
โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”
https://mitpress.mit.edu/sites/default
  /files/sicp/full-text/sicp/book/node5.html

MEANS OF DATA COMBINATION ๐Ÿงช
   ๐Ÿ™ค
โ€ข In conventions languages structures and arrays
  - Structures are feasible in Forth, but unidiomatic
  - Arrays in Forth are untyped
โ€ข This is a weak spot in Forth's typical usage
  - You can easily define strings,
    but not so easily fuse 2 of them into
    a First+Last name "thing".
  - You can make a stack and a string,
    but this doesn't naturally create a stack of strings.

MEANS OF DATA ABSTRACTION ๐Ÿงช
   ๐Ÿ™ค
โ€ข CREATE DOES> is the closest mechanism in Forth
  - But it dispatches only a single operation.

OBJECT ORIENTED LEXICONS ๐Ÿงฑ
   ๐Ÿ™ค
โ€ข SWOOP or other OO lexicons "solve" Forth's weak
  data combination and abstraction,
  but at the cost of a "C++/Java in Forth" style.
โ€ข OO puts data first, which usually requires naming
  that data. Forth wants data hidden/implicit:
  : WASHER
     WASH SPIN RINSE SPIN ;

CLASS POINT        โœด๏ธ
  VARIABLE X
  VARIABLE Y
  : SHOW ( -- )   X @ . Y @ . ;
  : DOT ( -- )   ." Point at " SHOW ;
END-CLASS
โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”
http://soton.mpeforth.com/flag/swoop/index.html

POINT BUILDS ORIGIN    โœด๏ธ
5 ORIGIN X !
8 ORIGIN Y !
ORIGIN DOT
โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”
http://soton.mpeforth.com/flag/swoop/index.html

0 VALUE FOO            \ Contains pointer to instance
POINT NEW TO FOO       \ Construct instance of class POINT
8 FOO USING POINT X !  \ Store data in X
99 FOO USING POINT Y ! \ Store data in Y
FOO USING POINT DOT    \ Display X and Y
FOO DESTROY  0 TO FOO  \ Release space     โœด๏ธ
โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”
http://soton.mpeforth.com/flag/swoop/index.html

DATA GENERALIZATION ๐ŸŽ–๏ธ
   ๐Ÿ™ค
โ€ข Naturalistic Forth relies on
  implict scope/context
โ€ข When data needs to generalize,
  this best happens by introducing
  abstraction of that context

APPROACHES TO GENERALIZATION ๐ŸŽ–๏ธ
   ๐Ÿ™ค
โ€ข Singleton - UPDATE, PAD
โ€ข Additional Stacks
  โ€ข Implicit Stack - String stack
  โ€ข Explicit Stack - Graphics Context
โ€ข Named - VOCABULARY, USE
โ€ข References - OPEN-FILE, ALLOCATE

IMPLICIT STACK ๐Ÿ“š
   ๐Ÿ™ค
$" foo" $" bar" $+ $.

EXPLICIT STACK ๐Ÿ“š

: box ( n -- ) ๐Ÿฅก
   4 0 do
     dup fd 90 rt
   loop drop ;

save-pen    ๐Ÿ–Š๏ธ
  100 100 moveto
  10 box
  200 200 moveto
  10 box
restore-pen

NAMED ๐Ÿ“›
  ๐Ÿ™ค
screen 10 box
printer 10 box

REFERENCES ๐Ÿ“™
  ๐Ÿ™ค
โ€ข Passed around on stack
โ€ข Remeber to release it!

EASY TRANSITIONS ๐Ÿ’บ
   ๐Ÿ™ค
Singleton โ†’ Stack
Singleton โ†’ Named

HARD TRANSITIONS ๐Ÿ˜ต
   ๐Ÿ™ค
Singleton โ†’ References
  โ€ข Update all callers
  โ€ข Manage lifetime

How to avoid
     ๐Ÿ“™
 References?

s" source.txt" R/O OPEN-FILE
READ-COMPLEX-DATA
CLOSE-FILE              ๐Ÿ—„๏ธ

s" source.txt" R/O OPEN-FILE infile
s" dest.txt" W/O OPEN-FILE outfile
infile READ-COMPLEX-DATA
outfile WRITE-COMPLEX-DATA
infile CLOSE-FILE
outfile CLOSE-FILE             ๐Ÿ“‚

s" source.txt" R/O OPEN-FILE
  s" dest.txt" W/O OPEN-FILE
    READ-COMPLEX-DATA FILE-SWAP
    WRITE-COMPLEX-DATA
  CLOSE-FILE
CLOSE-FILE                ๐Ÿ—ƒ๏ธ

What about
    ๐Ÿฆ
 Generics?

"PARTS"  โš™๏ธ
   ๐Ÿ™ค
โ€ข Create a scope/context
  bearing thing
โ€ข Use variables defined
  relative to a context
โ€ข Capture enough info to
  allocate multiple instances

variable @part  โš™๏ธ
: part ( "name" ) create here @part ! 0 , 0 , ;
: var ( sz "name" ) create @part @ , @part @ cell+ @ ,
                    @part @ cell+ +!  
                    does> dup @ @ swap cell+ @ + ;
: tuple ( n sz "name" ) swap 1- for dup var next drop ;
: part@ ( pt -- pt ) @ ;   : part! ( a pt -- ) ! ;
: part+! ( n a -- ) dup part@ rot + swap part! ;
: size ( a -- ) cell+ @ ;

: singleton ( pt -- )  ๐Ÿบ
   here over size allot swap part! ;

part point  โœด๏ธ
  3 cell tuple x y z
: p! ( x y z ) z ! y ! x ! ;
: p? x @ . y @ . z @ . ;
point singleton

: named ( pt "name" -- )  ๐Ÿ“›
   create dup , size allot
   does> dup cell+ swap @ part! ;

point named bob
point named joe
bob 1 2 3 p!
joe 2 3 4 p!
bob p? joe p?
  ๐Ÿ™ค
1 2 3
2 3 4      ๐Ÿ’ฏ

: stack ( n t "name" )  ๐Ÿ“š
   create 2dup , , 0 , here over part! size * allot ;
: pop ( st -- )
   dup @ size negate swap @ part+! ;
: push ( st -- )
   @ dup part@ over size dup >r over + r> cmove
   dup size swap part+! ;

30 point stack pstack   ๐Ÿ“š
: pdup   pstack push ;
: pdrop   pstack pop ;
: p.   p? pdrop ;
: p+   x @ y @ z @ pdrop
       z +! y +! x +! ;

1 2 3 p! pdup
2 3 4 p! pdup
5 6 7 p! p+
p. cr
p. cr
  ๐Ÿ™ค
 7 9 11
 1 2 3    ๐Ÿฅž

But I'm
    ๐Ÿ˜ž
 unsatified...

Make STACK ๐Ÿ“š
  a part?

part stack-part   ๐Ÿ“š
  cell var kind
  cell var start
  cell var items
: stack ( n t "name" )
   stack-part named lastxt execute
   kind ! items !  here start !
   kind @ size items @ * allot
   start @ kind @ part! ;
: stack+! ( n -- ) kind @ size * kind @ part+! ;
: stack-s ( -- a n ) kind @ part@ kind @ size ;
: pop ( st -- ) -1 stack+! ;
: push ( st -- ) stack-s 2dup + swap cmove
                 1 stack+! ;

But still I'm
     ๐Ÿ˜Ÿ
 unsatified...

DISCUSSION ๐Ÿบ
  & QUESTIONS?
      โš˜
  Thank you!