{"id":23418137,"url":"https://github.com/wa1tnr/c4a-dcs-a","last_synced_at":"2026-04-24T16:05:16.187Z","repository":{"id":269311778,"uuid":"906279271","full_name":"wa1tnr/c4a-dcs-a","owner":"wa1tnr","description":"c4a from Chris Curl - local effort to deconstruct or simplify - experimental.  New repository 20 Dec 2024","archived":false,"fork":false,"pushed_at":"2024-12-25T16:48:02.000Z","size":150,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-02-15T02:29:37.602Z","etag":null,"topics":["arduino-pico","ccurl-c4a","colorforth","cpp","earlephilhower","forth","littlefs","platformio","rp2350","rpi-rp2","rpipico2"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/wa1tnr.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-12-20T14:45:32.000Z","updated_at":"2024-12-20T15:19:43.000Z","dependencies_parsed_at":"2024-12-22T17:18:06.814Z","dependency_job_id":"ee0f271c-fd78-4448-99d7-fbedf175dd90","html_url":"https://github.com/wa1tnr/c4a-dcs-a","commit_stats":null,"previous_names":["wa1tnr/c4a-dcs-a"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wa1tnr%2Fc4a-dcs-a","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wa1tnr%2Fc4a-dcs-a/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wa1tnr%2Fc4a-dcs-a/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wa1tnr%2Fc4a-dcs-a/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/wa1tnr","download_url":"https://codeload.github.com/wa1tnr/c4a-dcs-a/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247999867,"owners_count":21031046,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["arduino-pico","ccurl-c4a","colorforth","cpp","earlephilhower","forth","littlefs","platformio","rp2350","rpi-rp2","rpipico2"],"created_at":"2024-12-23T00:15:24.938Z","updated_at":"2026-04-24T16:05:11.143Z","avatar_url":"https://github.com/wa1tnr.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# c4a: a 32-bit Forth system for PCs and Arduino, inspired by ColorForth and Tachyon\n\n## ColorForth's influence on c4a\n- c4a supports control characters in the whitespace that change the state.\u003cbr/\u003e\n- c4a has 4 states: INTERPRET, COMPILE, DEFINE, AND COMMENT,\u003cbr/\u003e\n- c4a also supports the standard state-change words.\u003cbr/\u003e\n\n| Ascii | Word  | State | Description|\n|:--    |:--    |:--    |:-- |\n|  $01  |  ]    |   1   | Compile |\n|  $02  |  :    |   2   | Define |\n|  $03  |  [    |   3   | Interpret/execute/immediate |\n|  $04  |       |   4   | Comment |\n|       |  (    |   4   | Comment, save current state |\n|       |  )    |       | End comment, restores saved state |\n\n**NOTE**: In the DEFINE state, c4a changes the state to COMPILE after adding the next word.\u003cbr/\u003e\n**NOTE**: Unlike ColorForth, ';' compiles EXIT and then changes the state to INTERPRET.\u003cbr/\u003e\n\n## Tachyon's influence on c4a\n- In c4a, a program is a sequence of WORD-CODEs. \u003cbr/\u003e\n- A WORD-CODE is a 32-bit unsigned number (i.e. - a DWORD). \u003cbr/\u003e\n- Primitives are assigned numbers sequentially from 0 to [BYE]. \u003cbr/\u003e\n- If a WORD-CODE is less than or equal to [BYE], it is a primitive. \u003cbr/\u003e\n- If the top 3 bits are set, it is a 29-bit unsigned literal, 0-$1FFFFFFF. \u003cbr/\u003e\n- If it is between [BYE], and $E0000000, it is the code address of a word to execute. \u003cbr/\u003e\n\n## CELLs in c4a\n- A **CELL** in c4a is 32-bits, the same size as a **WORD-CODE**.\n- Since development boards don't support 64-bits, neither does c4a.\n- For PCs, only 32-bit platforms are supported.\n- For 64-bit systems, see c4: https://github.com/CCurl/c4).\n\n## Building c4a\n \n### PCs - Windows and Linux, and probably others\n- Windows: there is a c4a.sln file for Visual Studio\n  - only the x86 target is supported\n- Linux: there is a makefile\n  - only the 32-bit configuration (-m32) is supported\n- Others:\n  - c4a is simple enough that it should be easy to migrate it to any platform\n\n### Development boards via the Arduino IDE:\n- I use the Arduino IDE v2.0\n- There is a c4a.ino file\n- File `c4a.h` controls parameters for the target board\n- Edit the section where isBOARD is defined to set the configuration for the board\n- Use `#define FILE_NONE` to disable support for blocks and LittleFS\n- For the RPI Pico:\n  - Use the arduino-pico from earlephilhower (https://github.com/earlephilhower/arduino-pico)\n  - The version must be 4.2.0 or later. Versions older than 4.0.0 do not support boards using\n    the RP2350 microcontroller.\n  - Use `#define FILE_PICO` to include support for LittleFS\n- For the Teensy-4.x:\n  - Use `#define FILE_TEENSY` to include support for LittleFS\n\n## c4a memory areas\nc4a provides a single memory area. See 'mem-sz' (MEM_SZ in c4a.h) for its size.\n- It is broken into 3 areas: CODE, VARS, and DICT.\n- The CODE area is an aray of WORD-CODEs starting at the beginning of the memory.\n  - `here` is an offset into the CODE area.\n  - The size of the CODE area is `code-sz`. See 'code-sz' (CODE_SZ in c4a.h).\n  - **NOTE**: Use `wc@` and `wc!` to get and set WORD-CODE values in the code area.\n  - **NOTE**: CODE slots 0-25 (`0 wc@ .. 25 wc@`) are reserved for c4a system values.\n  - **NOTE**: CODE slots 26-[BYE] (`26 wc@` .. `[BYE] wc@`) are unused by c4a.\n  - **NOTE**: So c4a provides space for about 75 'free' variables.\n  - **NOTE**: These are free for the user/application to use as desired.\n- The VARS area is defined to begin at address `code-sz wc-sz * memory +`.\n  - `vhere` is the absolute address of the first free byte the VARS area.\n- The DICT is at the end of the memory. 'last' grows toward the beginning of the memory.\n  - `last` is an offset into the memory area.\n- Use `-\u003ememory` to turn an offset into an address.\n\n| WORD    | STACK | DESCRIPTION |\n|:--      |:--    |:-- |\n| memory  | (--A) | A: starting address of the c4a memory |\n| mem-sz  | (--N) | N: size in BYTEs of the c4a memory |\n| code-sz | (--N) | N: number of in WORD-CODE slots in the code area |\n| dstk-sz | (--N) | N: size in CELLs of the DATA and RETURN stacks |\n| tstk-sz | (--N) | N: size in CELLs of the A and T stacks |\n| wc-sz   | (--N) | N: size in BYTEs of a WORD-CODE |\n| de-sz   | (--N) | N: size in BYTEs of a dictionary entry |\n| (dsp)   | (--N) | N: CODE slot for the data stack pointer |\n| (rsp)   | (--N) | N: CODE slot for the return stack pointer |\n| (lsp)   | (--N) | N: CODE slot for the loop stack pointer |\n| (tsp)   | (--N) | N: CODE slot for the T stack pointer |\n| (asp)   | (--N) | N: CODE slot for the A stack pointer |\n| (here)  | (--N) | N: CODE slot for the HERE variable |\n| (last)  | (--N) | N: CODE slot for the LAST variable |\n| base    | (--N) | N: CODE slot for the BASE variable |\n| state   | (--N) | N: CODE slot for the STATE variable |\n\n## c4a Strings\nStrings in c4a are NULL-terminated with no count byte.\u003cbr/\u003e\n\n## Format specifiers in `ftype` and `.\"`\nSimilar to the printf() function in C, c4a supports formatted output using '%'. \u003cbr/\u003e\nFor example `: ascii dup dup dup .\" char %c, decimal #%d, binary: %%%b, hex: $%x%n\" ;`.\n\n| Format | Stack | Description |\n|:--     |:--    |:-- |\n| %b     | (N--) | Print TOS in base 2. |\n| %c     | (N--) | EMIT TOS. |\n| %d     | (N--) | Print TOS in base 10. |\n| %e     | (--)  | EMIT `escape` (#27). |\n| %i     | (N--) | Print TOS in the current base. |\n| %n     | (--)  | Print CR/LF (13/10). |\n| %q     | (--)  | EMIT `\"` (#34). |\n| %s     | (A--) | Print TOS as a string (formatted). |\n| %S     | (A--) | Print TOS as a string (unformatted). |\n| %x     | (N--) | Print TOS in base 16. |\n| %[x]   | (--)  | EMIT [x]. |\n\n## The A stack\nc4a includes an A stack. \u003cbr/\u003e\nThis is somewhat similar to MachineForth's operations for 'a', but in c4a, it is a stack.\u003cbr/\u003e\nThe size of the A stack is configurable (see `tstk-sz`).\u003cbr/\u003e\n\n| WORD  | STACK | DESCRIPTION |\n|:--    |:--    |:-- |\n| `\u003ea`  | (N--) | Push N onto the A stack. |\n| `a!`  | (N--) | Set A-TOS to N. |\n| `a@`  | (--N) | N: copy of A-TOS. |\n| `a@+` | (--N) | N: copy of A-TOS, then increment A-TOS. |\n| `a@-` | (--N) | N: copy of A-TOS, then decrement A-TOS. |\n| `a\u003e`  | (--N) | Pop N from the A stack. |\n| adrop | (--)  | Drop A-TOS |\n\n## The T Stack\nc4a includes a T stack, with the same operations as the A stack. \u003cbr/\u003e\nNote that there are also additional words for the return stack. \u003cbr/\u003e\n\n| WORD  | STACK | DESCRIPTION |\n|:--    |:--    |:-- |\n| `\u003et`  | (N--) | Push N onto the T stack. |\n| `t!`  | (N--) | Set T-TOS to N. |\n| `t@`  | (--N) | N: copy of T-TOS. |\n| `t@+` | (--N) | N: copy of T-TOS, then increment T-TOS. |\n| `t@-` | (--N) | N: copy of T-TOS, then decrement T-TOS. |\n| `t\u003e`  | (--N) | Pop N from the T stack. |\n| tdrop | (--)  | Drop T-TOS |\n\n## c4a WORD-CODE primitives\nStack effect notation conventions:\n\n| TERM     | DESCRIPTION |\n|:--       |:-- |\n| SZ/NM/MD | String, uncounted, NULL terminated |\n| A        | Address |\n| C        | Number, 8-bits |\n| WC       | WORD-CODE, 32-bits |\n| N/X/Y    | Number, CELL sized |\n| F        | Flag: 0 mean0 false, \u003c\u003e0 means true |\n| R        | Register number |\n| FH       | File handle: 0 means no file |\n| I        | For loop index counter |\n\nThe primitives:\n\n| WORD        | STACK        | DESCRIPTION |\n|:--          |:--           |:-- |\n| (lit)       | (--WC)       | WC: WORD-CODE for LIT primitive |\n| (jmp)       | (--WC)       | WC: WORD-CODE for JMP primitive |\n| (jmpz)      | (--WC)       | WC: WORD-CODE for JMPZ primitive |\n| (jmpnz)     | (--WC)       | WC: WORD-CODE for JMPNZ primitive |\n| (njmpz)     | (--WC)       | WC: WORD-CODE for NJMPZ primitive |\n| (njmpnz)    | (--WC)       | WC: WORD-CODE for NJMPNZ primitive |\n| (exit)      | (--WC)       | WC: WORD-CODE for EXIT primitive |\n| exit        | (--)         | EXIT word |\n| dup         | (X--X X)     | Duplicate TOS (Top-Of-Stack) |\n| swap        | (X Y--Y X)   | Swap TOS and NOS (Next-On-Stack) |\n| drop        | (N--)        | Drop TOS |\n| over        | (N X--N X N) | Push NOS |\n| @           | (A--N)       | N: the CELL at absolute address A |\n| c@          | (A--C)       | C: the CHAR at absolute address A |\n| w@          | (A--W)       | W: the WORD at absolute address A |\n| wc@         | (N--WC)      | WC: the WORD-CODE in CODE slot N |\n| !           | (N A--)      | Store CELL N to absolute address A |\n| c!          | (C A--)      | Store CHAR C to absolute address A |\n| w!          | (W A--)      | Store WORD W to absolute address A |\n| wc!         | (WC N--)     | Store WORD-CODE WC to CODE slot N |\n| +           | (X Y--N)     | N: X + Y |\n| -           | (X Y--N)     | N: X - Y |\n| *           | (X Y--N)     | N: X * Y |\n| /           | (X Y--N)     | N: X / Y (integer division) |\n| /mod        | (X Y--M Q)   | M: X modulo Y, Q: quotient of X / Y |\n| 1+          | (X--Y)       | Increment TOS |\n| 1-          | (X--Y)       | Decrement TOS |\n| \u003c           | (X Y--F)     | F: 1 if (X \u003c Y), else 0 |\n| =           | (X Y--F)     | F: 1 if (X = Y), else 0 |\n| \u003e           | (X Y--F)     | F: 1 if (X \u003e Y), else 0 |\n| 0=          | (N--F)       | F: 1 if (N=0), else 0 |\n| and         | (X Y--N)     | N: X AND Y |\n| or          | (X Y--N)     | N: X OR  Y |\n| xor         | (X Y--N)     | N: X XOR Y |\n| com         | (X--Y)       | Y: X with all bits flipped (complement) |\n| for         | (N--)        | Begin FOR loop with bounds 0 and N-1. |\n| i           | (--I)        | N: Current FOR loop index. |\n| next        | (--)         | Increment I. If I \u003e= N, exit, else start loop again. |\n| unloop      | (--)         | Unwind the loop stack. **NOTE:** does NOT exit the loop. |\n| \u003er          | (N--)        | Push N onto the return stack |\n| r!          | (N--)        | Set R-TOS to N |\n| r@          | (--N)        | N: copy of R-TOS |\n| r@+         | (--N)        | N: copy of R-TOS, then increment it |\n| r@-         | (--N)        | N: copy of R-TOS, then decrement it |\n| r\u003e          | (--N)        | Pop N from the return stack |\n| rdrop       | (--)         | Drop R-TOS |\n| \u003et          | (N--)        | Push N onto the T stack |\n| t!          | (N--)        | Set T-TOS to N |\n| t@          | (--N)        | N: copy of T-TOS |\n| t@+         | (--N)        | N: copy of T-TOS, then increment T-TOS |\n| t@-         | (--N)        | N: copy of T-TOS, then decrement T-TOS |\n| t\u003e          | (--N)        | Pop N from the T stack |\n| tdrop       | (--)         | Drop T-TOS |\n| \u003ea          | (N--)        | Push N onto the A stack |\n| a!          | (N--)        | Set A-TOS to N |\n| a@          | (--N)        | N: copy of A-TOS |\n| a@+         | (--N)        | N: copy of A-TOS, then increment A-TOS |\n| a@-         | (--N)        | N: copy of A-TOS, then decrement A-TOS |\n| a\u003e          | (--N)        | Pop N from the A stack |\n| adrop       | (--)         | Drop A-TOS |\n| emit        | (C--)        | Output char C |\n| ;           | (--)         | Compile EXIT, set STATE=INTERPRET |\n| lit,        | (N--)        | Compile a push of number N |\n| next-wd     | (--L)        | L: length of the next word from the input stream |\n| immediate   | (--)         | Mark the last created word as IMMEDIATE |\n| inline      | (--)         | Mark the last created word as INLINE |\n| outer       | (S--)        | Send string S to the c4a outer interpreter |\n| addword     | (--)         | Add the next word to the dictionary |\n| timer       | (--N)        | N: Current time |\n| see X       | (--)         | Output the definition of word X |\n| ztype       | (S--)        | Print string at S (unformatted) |\n| ftype       | (S--)        | Print string at S (formatted) |\n| s-cpy       | (D S--D)     | Copy string S to D |\n| s-eq        | (D S--F)     | F: 1 if string S is equal to D (case sensitive) |\n| s-eqi       | (D S--F)     | F: 1 if string S is equal to D (NOT case sensitive) |\n| s-len       | (S--N)       | N: Length of string S |\n| z\"          | (--)         | -COMPILE: Create string S to next `\"` |\n|             | (--S)        | -RUN: push address S of string |\n| .\"          | (--)         | -COMPILE: execute `z\"`, compile `ftype` |\n|             | (--)         | -RUN: `ftype` on string |\n| find        | (--XT A)     | XT: Execution Token, A: Dict Entry address (0 0 if not found) |\n| loaded?     | (XT A--)     | Stops current load if A \u003c\u003e 0 (see `find`) |\n| fopen       | (NM MD--FH)  | NM: File Name, MD: Mode, FH: File Handle (0 if error/not found) |\n| fclose      | (FH--)       | FH: File Handle to close |\n| fdelete     | (NM--)       | NM: File Name to delete |\n| fread       | (A N FH--X)  | A: Buffer, N: Size, FH: File Handle, X: num chars read |\n| fwrite      | (A N FH--X)  | A: Buffer, N: Size, FH: File Handle, X: num chars written |\n| fseek       | (N FH--X)    | N: Size, FH: File Handle, X: return from func |\n| fsize       | (FH--N)      | FH: File Handle, N: file size |\n| fpos        | (FH--N)      | FH: File Handle, N: current file read/write position |\n| load        | (N--)        | N: Block number to load |\n| load-next   | (N--)        | Close the current block and load block N next |\n| blocks      | (--)         | Dump block cache |\n| block-addr  | (N--A)       | N: Block number, A: Address in cache |\n| flush       | (F--)        | F: True =\u003e clear cache |\n| flush-block | (N F--)      | N: Block number, F: True =\u003e clear cache entry |\n| edit        | (N--)        | N: Block number to edit |\n| system      | (S--)        | PC ONLY: S: String to send to `system()` |\n| bye         | (--)         | PC ONLY: Exit c4a |\n\n## c4a default words\nDefault words are defined in function `sys_load()` in file sys-load.cpp.\u003cbr/\u003e\nFor details, or to add or change the default words, modify that function.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwa1tnr%2Fc4a-dcs-a","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwa1tnr%2Fc4a-dcs-a","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwa1tnr%2Fc4a-dcs-a/lists"}