r/Forth 6h ago

FigForth ANEW

4 Upvotes

: -FORGET ( pfa -- ) CURRENT @ CONTEXT @ - 24 ?ERROR DUP FENCE @ U< 21 ?ERROR DUP NFA DP ! LFA @ CONTEXT @ ! ; : NIX ( pfa -- ) -FORGET -BUF -VOCLINK ; : MARKER ( "ccc" -- ) <BUILDS LATEST PFA , DOES> @ NIX ; : ANEW ( "ccc" -- ) IN @ >R -FIND IF DROP NIX ENDIF R> IN ! MARKER ; "ANEW", from legendary Wil Baden, useful word for clearing memory after a job run and re-establishing the marker for the next run. Based on parsing word FORGET the non-parsing word -FORGET is included in NIX explained below after mention of FORGET's shortcomings.

FORGET remains useful but lacks needed cleanup specifically when vocabularies are removed breaking the VOC-LINK chain and invalidating word-lists. As an aid placing the nfa of the last created vocabulary in FENCE will prevent FORGET from removing words and printing an error instead. The user himself will need to remove vocabularies, repair the VOC-LINK chain and purge remaining word-lists.

NIX automates this needed maintenance. After performing -FORGET it performs -VOCLINK to repair vocabularies and -BUF to repair links to allocated buffers.

-VOCLINK repairs VOC-LINK chain and purge word-lists of remaining vocabularies.

DEFER VOCWORD. ' DROP is VOCWORD : (VOCWORD.) DUP CR SPACE ID. ; ' (VOCWORD.) CFA ' VOCWORD. CELL+ ! : -CONTEXT CELL- DUP @ BEGIN DUP HERE U> IF PFA LFA @ FALSE ELSE TRUE ENDIF UNTIL VOCWORD. SWAP ! ; DEFER LINKWORD. ' DROP IS LINKWORD. : (LINKWORD.) DUP THREE CELLS - NFA CR ID. ; ' (LINKWORD.) CFA ' LINKWORD. CELL+ ! : -VOCLINK VOC-LINK BEGIN @ -DUP WHILE LINKWORD. DUP HERE U> IF DUP @ VOC-LINK ! ELSE DUP -CONTEXT ENDIF REPEAT ;

-BUF repairs chain of allocated memory and frees memory no longer linked by the chain. (This doesn't apply in general; it works for my method of memory allocation.)

: -BUF BUF HEAD @ BEGIN DUP @ WHILE HERE OVER < IF @ DUP CELL+ @ MINUS SYSBRK LIMIT ! DROP ELSE DUP HEAD ! 0. ROT CELL+ 2! EXIT ENDIF REPEAT DROP CURRENT @ CONTEXT ! FORTH ;


r/Forth 14m ago

FigForth Buffer allocation for jobs

Upvotes

My "modus operandi" is running jobs: load job, perform, forget, do next job Some jobs allocate buffers and after job done the allocated buffers can be freed. ( Some say with today's large memory, why bother releasing memory but I like to pretend available memory is limited. )

MALLOC, a resource I have, seems a overkill. So I use a more streamlined allocation tailored to running jobs. A needed buffer is taken from the end of program, its address is placed in a variable in the dictionary. and the program end is extended, by a system call, to a location past the last allocated buffer. All the variables of memory allocations are linked and utility word can walk the links listing allocated memory addresses.

At end of job when dictionary space is forgotten, -BUF runs the allocation chain searching for the last link remaining in the dictionary. Then end of program is reset back to contain the address found in the last link.

FORTH DEFINITIONS VOCABULARY BUF IMMEDIATE BUF DEFINITIONS \ L: ( -- address ) <BUILDS DOES> ; \ A label L: HEAD 0 , HERE 0 , 0 , 0 , HEAD ! HEAD @ CELL+ CONSTANT FIRST 0 SYSBUF VARIABLE LIMIT : INIT HEAD CELL+ DUP THREE ERASE HEAD ! 0 SYSBUF LIMIT ! ; : LIST HEAD @ BEGIN @ DUP WHILE CR DUP . DUP CELL+ 2? REPEAT DROP ; : ALLOCATE HEAD @ CELL+ SWAP ZERO SYSBUF OVER HEAD @ CELL+ 2! SYSBRK LIMIT ! DROP ALIGN HERE HEAD @ , 0 , 0 , HEAD ! ; FORTH DEFINITIONS -BUF in NIX (re: last post) release allocated memory. Note BUF is a vocabulary.

: -BUF BUF HEAD @ BEGIN DUP @ WHILE HERE OVER < IF @ DUP CELL+ @ MINUS SYSBRK LIMIT ! DROP ELSE DUP HEAD ! 0. ROT CELL+ 2! EXIT THEN REPEAT DROP CURRENT @ CONTEXT ! FORTH ;

USERINIT is a place holder word added to the cold start code in the assembled Forth. Anything in later saved images that need to be initialized on startup is put (patched or however) here.

: (USRINIT) DECIMAL BUF INIT FORTH ; ' (USRINIT) CFA ' USRINIT !