<commit_before>-------------------------------
Gigatron Command Language (GCL)
-------------------------------
GCL is an interpreted low-level language for writing simple games for
the Gigatron TTL microcomputer, without bothering with the harsh timing
requirements of the hardware platform.

Technically, "GCL" is the source language or notation, while "vCPU" is the
virtual CPU, or interpreter, that is executing compiled GCL instructions.
The two are closely tied together.

---------------
Example program
---------------

{Draw the binary value of the largest 16-bit Fibonacci number on screen}

:$0300 {program load address}
[do                                     {Approximate BASIC equivalent}
  0 a=                                  {10 A=0}
  1 b=                                  {20 B=1}
  [do
    a b+ c=                             {30 C=A+B}
    b a= c b=                           {40 A=B: B=C}
    if>0 loop]                          {50 IF B>0 THEN 30}
  $4448 d=                              {60 D=$4448: REM MIDDLE OF SCREEN}
  [do
    c [if<0 15 d! else 5 d!]            {70 IF C<0 POKE D,15 ELSE POKE D,5}
    c c+ c=                             {80 C=C+C}
    1 d+ d=                             {90 D=1+D}
    -$4458 d+ if<0 loop]                {100 IF D<$4458 THEN 70}
  loop]                                 {110 GOTO 10}

-----------------
Programming model
-----------------
GCL draws most of its inspiration from SWEET16 (Apple II) and FALSE (Amiga).
The programming model is primarily "accumulator oriented".
To accommodate the lack of relative addressing and hardware stack on the host
CPU, expression and call stacks will be (mostly) static instead of dynamic.
vAC is the virtual accumulator
vPC is the virtual program counter. Programs run from RAM.
vAC and vPC are 16-bits and reside in the zero page.
vPC auto-increments just its low byte, but functions can cross page boundaries.
Program variables are 16-bit words and typically hold a number or a pointer.
Memory can be addressed as bytes or as unaligned little-endian words.
Most instructions use 2 bytes (opcode + operand), but some have 1 and others 3.
Opcodes are simply jump offsets into the interpeter ROM code page.
Named global variables reside in the zero page, locals in the code page itself.
XXX vSP: to be defined. Use [X] or [Y,D] addressing, or both (2 stack types)?
XXX Loading and starting of programs
XXX Simple GCL programs might be compiled by the host instead of offline?
XXX Threading and sleeping
XXX Dynamic memory allocation
XXX Memory-mapped I/O

-----------------
Notes on notation
-----------------
GCL programs are written as a long sequence of "words" without much structure
enforcement by the compiler. Most words map directly to a single virtual
instruction and therefore also encode an embedded operand (e.g. 1+).
Many words operate on both vAC and some variable or constant.
Sequences can be grouped with () {} or [], each of which has its own meaning.
Spaces and newlines just separate words. Use indentation for clarity.
There is no need for extra spaces around the grouping characters []{}().
'i' means an 8-bit integer constant.
'ii' means a 16-bit integer constant.
Constants are decimal, or hexadecimal when preceded with '$'.
Constants can be preceded by '-' or '+' (note: -$1000, not $-0000).
Global variable names are capitalized, while locals begin in lower case.
In "version 0" use just single letters a-z (locals) and A-Z (globals).
'x' means a named local variable and 'X' a named global variable.
'%i' means an unnamed local variable at location i in the code page, and
can be used in place of a local variable name.

----------------
Meaning of words
----------------
{...}                   Comments ignored by machine. Comments can be nested
ii                      Load integer constant into vAC, e.g. +1972, $be05
x= X=                   Store vAC into variable
x X                     Load vAC from variable
x+                      Add x to vAC
x-                      Subtract variable from vAC
i+                      Add small constant to vAC (XXX limit 0<=i<128?)
i-                      Subtract small constant from vAC (XXX limit 0<=i<128?)
[...]                   Code block, used with "if", "else", "do", "loop"
if>0                    Continue executing code if vAC > 0, otherwise jump to
                        end of the block (or past an optional matching "else")
                        Conditions are "=0" ">0" "<0" "<=0" ">=0" "<>0"
else                    When encountered, skip rest of code until end of block
do                      Mark start of loop
loop                    Jump back to matching "do"
i& i| i^                Logical AND, OR and XOR (note: just vAC's lower byte!)
x& v| v^                Logical AND, OR and XOR with variable x (16-bits)
~                       Invert all bits in vAC (XXX why no operand?)
:ii                     Set compile address, typically at start of program
x?                      Read byte from memory pointed by variable ("peek")
x!                      Write vAC as byte to memory pointed by variable ("poke")
i!                      Store vAC as byte into zero page address i
i?                      Read zero page as unsigned byte

---------------
Not decided yet
---------------<commit_msg>Minor formatting gcl.txt<commit_after>-------------------------------
Gigatron Command Language (GCL)
-------------------------------
GCL is an interpreted low-level language for writing simple games for
the Gigatron TTL microcomputer, without bothering with the harsh timing
requirements of the hardware platform.

Technically, "GCL" is the source language or notation, while "vCPU" is the
virtual CPU, or interpreter, that is executing compiled GCL instructions.
The two are closely tied together.

---------------
Example program
---------------

{Draw the binary value of the largest 16-bit Fibonacci number on screen}

:$0300 {program load address}
[do                                     {Approximate BASIC equivalent}
  0 a=                                  {10 A=0}
  1 b=                                  {20 B=1}
  [do
    a b+ c=                             {30 C=A+B}
    b a= c b=                           {40 A=B: B=C}
    if>0 loop]                          {50 IF B>0 THEN 30}
  $4448 d=                              {60 D=$4448: REM MIDDLE OF SCREEN}
  [do
    c [if<0 15 d! else 5 d!]            {70 IF C<0 POKE D,15 ELSE POKE D,5}
    c c+ c=                             {80 C=C+C}
    1 d+ d=                             {90 D=1+D}
    -$4458 d+ if<0 loop]                {100 IF D<$4458 THEN 70}
  loop]                                 {110 GOTO 10}

-----------------
Programming model
-----------------
GCL draws most of its inspiration from SWEET16 (Apple II) and FALSE (Amiga).
The programming model is primarily "accumulator oriented".
To accommodate the lack of relative addressing and hardware stack on the host
CPU, expression and call stacks will be (mostly) static instead of dynamic.
vAC is the virtual accumulator
vPC is the virtual program counter. Programs run from RAM.
vAC and vPC are 16-bits and reside in the zero page.
vPC auto-increments just its low byte, but function calls can go across pages.
Program variables are 16-bit words and typically hold a number or a pointer.
Memory can be addressed as bytes or as unaligned little-endian words.
Most instructions use 2 bytes (opcode + operand), but some have 1 and others 3.
Opcodes are simply jump offsets into the interpeter ROM code page.
Named global variables reside in the zero page, locals in the code page itself.
XXX vSP: to be defined. Use [X] or [Y,D] addressing, or both (2 stack types)?
XXX Loading and starting of programs
XXX Simple GCL programs might be compiled by the host instead of offline?
XXX Threading and sleeping
XXX Dynamic memory allocation
XXX Memory-mapped I/O

-----------------
Notes on notation
-----------------
GCL programs are written as a long sequence of "words" without much structure
enforcement by the compiler. Most words map directly to a single virtual
instruction and therefore also encode an embedded operand (e.g. 1+).
Many words operate on both vAC and some variable or constant.
Sequences can be grouped with () {} or [], each of which has its own meaning.
Spaces and newlines just separate words. Use indentation for clarity.
There is no need for extra spaces around the grouping characters []{}().
Constants are decimal, or hexadecimal when preceded with '$'.
Constants can be preceded by '-' or '+' (note: -$1000, not $-0000).
Global variable names are capitalized, while locals begin in lower case.
In "version 0" use just single letters a-z (locals) and A-Z (globals).
The overview below uses the following conventions:
'i' indicates an 8-bit integer constant.
'ii' indicates a 16-bit integer constant.
'x' indicates a named local variable and 'X' a named global variable.
Also, everywhere where 'x' is allowed, the '%i' notation can be used to denote
the unnamed local variable at location i in the current code page.

----------------
Meaning of words
----------------
{...}                   Comments ignored by machine. Comments can be nested
ii                      Load integer constant into vAC, e.g. +1972, $be05
x= X=                   Store vAC into variable
x X                     Load vAC from variable
x+                      Add x to vAC
x-                      Subtract variable from vAC
i+                      Add small constant to vAC (XXX limit 0<=i<128?)
i-                      Subtract small constant from vAC (XXX limit 0<=i<128?)
[...]                   Code block, used with "if", "else", "do", "loop"
if>0                    Continue executing code if vAC > 0, otherwise jump to
                        end of the block (or past an optional matching "else")
                        Conditions are "=0" ">0" "<0" "<=0" ">=0" "<>0"
else                    When encountered, skip rest of code until end of block
do                      Mark start of loop
loop                    Jump back to matching "do"
i& i| i^                Logical AND, OR and XOR (note: just vAC's lower byte!)
x& v| v^                Logical AND, OR and XOR with variable x (16-bits)
~                       Invert all bits in vAC (XXX why no operand?)
:ii                     Set compile address, typically at start of program
x?                      Read byte from memory pointed by variable ("peek")
x!                      Write vAC as byte to memory pointed by variable ("poke")
i!                      Store vAC as byte into zero page address i
i?                      Read zero page as unsigned byte

---------------
Not decided yet
---------------
{'fraction_non_alphanumeric': 0.10367392726932785, 'fraction_numerical': 0.021688323829110966, 'mean_word_length': 1.8650241028387788, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 28, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2284428', 'n_tokens_mistral': 2946, 'n_tokens_neox': 2660, 'n_words': 1456}