Skip to content

c4a from Chris Curl - with platformio RP2350 support. make clean ; make ; make uploadfs ; make upload - new repo 18 Dec 2024

License

Notifications You must be signed in to change notification settings

wa1tnr/c4a-lcl-bpio

Folders and files

NameName
Last commit message
Last commit date

Latest commit

5b365b7 · Dec 17, 2024

History

45 Commits
Dec 2, 2024
Dec 17, 2024
Nov 11, 2024
Dec 13, 2024
Dec 2, 2024
Dec 13, 2024
Dec 5, 2024
Dec 4, 2024
Dec 13, 2024
Dec 13, 2024
Dec 13, 2024
Dec 13, 2024
Dec 13, 2024
Dec 11, 2024
Dec 13, 2024
Dec 17, 2024
Dec 17, 2024
Dec 9, 2024
Dec 2, 2024
Dec 9, 2024
Dec 2, 2024
Dec 17, 2024
Dec 11, 2024
Dec 11, 2024
Dec 8, 2024
Dec 9, 2024
Dec 12, 2024
Dec 8, 2024

Repository files navigation

c4a: a 32-bit Forth system for PCs and Arduino, inspired by ColorForth and Tachyon

ColorForth's influence on c4a

  • c4a supports control characters in the whitespace that change the state.
  • c4a has 4 states: INTERPRET, COMPILE, DEFINE, AND COMMENT,
  • c4a also supports the standard state-change words.
Ascii Word State Description
$01 ] 1 Compile
$02 : 2 Define
$03 [ 3 Interpret/execute/immediate
$04 4 Comment
( 4 Comment, save current state
) End comment, restores saved state

NOTE: In the DEFINE state, c4a changes the state to COMPILE after adding the next word.
NOTE: Unlike ColorForth, ';' compiles EXIT and then changes the state to INTERPRET.

Tachyon's influence on c4a

  • In c4a, a program is a sequence of WORD-CODEs.
  • A WORD-CODE is a 32-bit unsigned number (i.e. - a DWORD).
  • Primitives are assigned numbers sequentially from 0 to [BYE].
  • If a WORD-CODE is less than or equal to [BYE], it is a primitive.
  • If the top 3 bits are set, it is a 29-bit unsigned literal, 0-$1FFFFFFF.
  • If it is between [BYE], and $E0000000, it is the code address of a word to execute.

CELLs in c4a

  • A CELL in c4a is 32-bits, the same size as a WORD-CODE.
  • Since development boards don't support 64-bits, neither does c4a.
  • For PCs, only 32-bit platforms are supported.
  • For 64-bit systems, see c4: https://github.com/CCurl/c4).

Building c4a

PCs - Windows and Linux, and probably others

  • Windows: there is a c4a.sln file for Visual Studio
    • only the x86 target is supported
  • Linux: there is a makefile
    • only the 32-bit configuration (-m32) is supported
  • Others:
    • c4a is simple enough that it should be easy to migrate it to any platform

Development boards via the Arduino IDE:

  • I use the Arduino IDE v2.0
  • There is a c4a.ino file
  • File c4a.h controls parameters for the target board
  • Edit the section where isBOARD is defined to set the configuration for the board
  • Use #define FILE_NONE to disable support for blocks and LittleFS
  • For the RPI Pico:
    • Use the arduino-pico from earlephilhower (https://github.com/earlephilhower/arduino-pico)
    • The version must be 4.2.0 or later. Versions older than 4.0.0 do not support boards using the RP2350 microcontroller.
    • Use #define FILE_PICO to include support for LittleFS
  • For the Teensy-4.x:
    • Use #define FILE_TEENSY to include support for LittleFS

c4a memory areas

c4a provides a single memory area. See 'mem-sz' (MEM_SZ in c4a.h) for its size.

  • It is broken into 3 areas: CODE, VARS, and DICT.
  • The CODE area is an aray of WORD-CODEs starting at the beginning of the memory.
    • here is an offset into the CODE area.
    • The size of the CODE area is code-sz. See 'code-sz' (CODE_SZ in c4a.h).
    • NOTE: Use wc@ and wc! to get and set WORD-CODE values in the code area.
    • NOTE: CODE slots 0-25 (0 wc@ .. 25 wc@) are reserved for c4a system values.
    • NOTE: CODE slots 26-[BYE] (26 wc@ .. [BYE] wc@) are unused by c4a.
    • NOTE: So c4a provides space for about 75 'free' variables.
    • NOTE: These are free for the user/application to use as desired.
  • The VARS area is defined to begin at address code-sz wc-sz * memory +.
    • vhere is the absolute address of the first free byte the VARS area.
  • The DICT is at the end of the memory. 'last' grows toward the beginning of the memory.
    • last is an offset into the memory area.
  • Use ->memory to turn an offset into an address.
WORD STACK DESCRIPTION
memory (--A) A: starting address of the c4a memory
mem-sz (--N) N: size in BYTEs of the c4a memory
code-sz (--N) N: number of in WORD-CODE slots in the code area
dstk-sz (--N) N: size in CELLs of the DATA and RETURN stacks
tstk-sz (--N) N: size in CELLs of the A and T stacks
wc-sz (--N) N: size in BYTEs of a WORD-CODE
de-sz (--N) N: size in BYTEs of a dictionary entry
(dsp) (--N) N: CODE slot for the data stack pointer
(rsp) (--N) N: CODE slot for the return stack pointer
(lsp) (--N) N: CODE slot for the loop stack pointer
(tsp) (--N) N: CODE slot for the T stack pointer
(asp) (--N) N: CODE slot for the A stack pointer
(here) (--N) N: CODE slot for the HERE variable
(last) (--N) N: CODE slot for the LAST variable
base (--N) N: CODE slot for the BASE variable
state (--N) N: CODE slot for the STATE variable

c4a Strings

Strings in c4a are NULL-terminated with no count byte.

Format specifiers in ftype and ."

Similar to the printf() function in C, c4a supports formatted output using '%'.
For example : ascii dup dup dup ." char %c, decimal #%d, binary: %%%b, hex: $%x%n" ;.

Format Stack Description
%b (N--) Print TOS in base 2.
%c (N--) EMIT TOS.
%d (N--) Print TOS in base 10.
%e (--) EMIT escape (#27).
%i (N--) Print TOS in the current base.
%n (--) Print CR/LF (13/10).
%q (--) EMIT " (#34).
%s (A--) Print TOS as a string (formatted).
%S (A--) Print TOS as a string (unformatted).
%x (N--) Print TOS in base 16.
%[x] (--) EMIT [x].

The A stack

c4a includes an A stack.
This is somewhat similar to MachineForth's operations for 'a', but in c4a, it is a stack.
The size of the A stack is configurable (see tstk-sz).

WORD STACK DESCRIPTION
>a (N--) Push N onto the A stack.
a! (N--) Set A-TOS to N.
a@ (--N) N: copy of A-TOS.
a@+ (--N) N: copy of A-TOS, then increment A-TOS.
a@- (--N) N: copy of A-TOS, then decrement A-TOS.
a> (--N) Pop N from the A stack.
adrop (--) Drop A-TOS

The T Stack

c4a includes a T stack, with the same operations as the A stack.
Note that there are also additional words for the return stack.

WORD STACK DESCRIPTION
>t (N--) Push N onto the T stack.
t! (N--) Set T-TOS to N.
t@ (--N) N: copy of T-TOS.
t@+ (--N) N: copy of T-TOS, then increment T-TOS.
t@- (--N) N: copy of T-TOS, then decrement T-TOS.
t> (--N) Pop N from the T stack.
tdrop (--) Drop T-TOS

c4a WORD-CODE primitives

Stack effect notation conventions:

TERM DESCRIPTION
SZ/NM/MD String, uncounted, NULL terminated
A Address
C Number, 8-bits
WC WORD-CODE, 32-bits
N/X/Y Number, CELL sized
F Flag: 0 mean0 false, <>0 means true
R Register number
FH File handle: 0 means no file
I For loop index counter

The primitives:

WORD STACK DESCRIPTION
(lit) (--WC) WC: WORD-CODE for LIT primitive
(jmp) (--WC) WC: WORD-CODE for JMP primitive
(jmpz) (--WC) WC: WORD-CODE for JMPZ primitive
(jmpnz) (--WC) WC: WORD-CODE for JMPNZ primitive
(njmpz) (--WC) WC: WORD-CODE for NJMPZ primitive
(njmpnz) (--WC) WC: WORD-CODE for NJMPNZ primitive
(exit) (--WC) WC: WORD-CODE for EXIT primitive
exit (--) EXIT word
dup (X--X X) Duplicate TOS (Top-Of-Stack)
swap (X Y--Y X) Swap TOS and NOS (Next-On-Stack)
drop (N--) Drop TOS
over (N X--N X N) Push NOS
@ (A--N) N: the CELL at absolute address A
c@ (A--C) C: the CHAR at absolute address A
w@ (A--W) W: the WORD at absolute address A
wc@ (N--WC) WC: the WORD-CODE in CODE slot N
! (N A--) Store CELL N to absolute address A
c! (C A--) Store CHAR C to absolute address A
w! (W A--) Store WORD W to absolute address A
wc! (WC N--) Store WORD-CODE WC to CODE slot N
+ (X Y--N) N: X + Y
- (X Y--N) N: X - Y
* (X Y--N) N: X * Y
/ (X Y--N) N: X / Y (integer division)
/mod (X Y--M Q) M: X modulo Y, Q: quotient of X / Y
1+ (X--Y) Increment TOS
1- (X--Y) Decrement TOS
< (X Y--F) F: 1 if (X < Y), else 0
= (X Y--F) F: 1 if (X = Y), else 0
> (X Y--F) F: 1 if (X > Y), else 0
0= (N--F) F: 1 if (N=0), else 0
and (X Y--N) N: X AND Y
or (X Y--N) N: X OR Y
xor (X Y--N) N: X XOR Y
com (X--Y) Y: X with all bits flipped (complement)
for (N--) Begin FOR loop with bounds 0 and N-1.
i (--I) N: Current FOR loop index.
next (--) Increment I. If I >= N, exit, else start loop again.
unloop (--) Unwind the loop stack. NOTE: does NOT exit the loop.
>r (N--) Push N onto the return stack
r! (N--) Set R-TOS to N
r@ (--N) N: copy of R-TOS
r@+ (--N) N: copy of R-TOS, then increment it
r@- (--N) N: copy of R-TOS, then decrement it
r> (--N) Pop N from the return stack
rdrop (--) Drop R-TOS
>t (N--) Push N onto the T stack
t! (N--) Set T-TOS to N
t@ (--N) N: copy of T-TOS
t@+ (--N) N: copy of T-TOS, then increment T-TOS
t@- (--N) N: copy of T-TOS, then decrement T-TOS
t> (--N) Pop N from the T stack
tdrop (--) Drop T-TOS
>a (N--) Push N onto the A stack
a! (N--) Set A-TOS to N
a@ (--N) N: copy of A-TOS
a@+ (--N) N: copy of A-TOS, then increment A-TOS
a@- (--N) N: copy of A-TOS, then decrement A-TOS
a> (--N) Pop N from the A stack
adrop (--) Drop A-TOS
emit (C--) Output char C
; (--) Compile EXIT, set STATE=INTERPRET
lit, (N--) Compile a push of number N
next-wd (--L) L: length of the next word from the input stream
immediate (--) Mark the last created word as IMMEDIATE
inline (--) Mark the last created word as INLINE
outer (S--) Send string S to the c4a outer interpreter
addword (--) Add the next word to the dictionary
timer (--N) N: Current time
see X (--) Output the definition of word X
ztype (S--) Print string at S (unformatted)
ftype (S--) Print string at S (formatted)
s-cpy (D S--D) Copy string S to D
s-eq (D S--F) F: 1 if string S is equal to D (case sensitive)
s-eqi (D S--F) F: 1 if string S is equal to D (NOT case sensitive)
s-len (S--N) N: Length of string S
z" (--) -COMPILE: Create string S to next "
(--S) -RUN: push address S of string
." (--) -COMPILE: execute z", compile ftype
(--) -RUN: ftype on string
find (--XT A) XT: Execution Token, A: Dict Entry address (0 0 if not found)
loaded? (XT A--) Stops current load if A <> 0 (see find)
fopen (NM MD--FH) NM: File Name, MD: Mode, FH: File Handle (0 if error/not found)
fclose (FH--) FH: File Handle to close
fdelete (NM--) NM: File Name to delete
fread (A N FH--X) A: Buffer, N: Size, FH: File Handle, X: num chars read
fwrite (A N FH--X) A: Buffer, N: Size, FH: File Handle, X: num chars written
fseek (N FH--X) N: Size, FH: File Handle, X: return from func
fsize (FH--N) FH: File Handle, N: file size
fpos (FH--N) FH: File Handle, N: current file read/write position
load (N--) N: Block number to load
load-next (N--) Close the current block and load block N next
blocks (--) Dump block cache
block-addr (N--A) N: Block number, A: Address in cache
flush (F--) F: True => clear cache
flush-block (N F--) N: Block number, F: True => clear cache entry
edit (N--) N: Block number to edit
system (S--) PC ONLY: S: String to send to system()
bye (--) PC ONLY: Exit c4a

c4a default words

Default words are defined in function sys_load() in file sys-load.cpp.
For details, or to add or change the default words, modify that function.

About

c4a from Chris Curl - with platformio RP2350 support. make clean ; make ; make uploadfs ; make upload - new repo 18 Dec 2024

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published