105 lines
7.1 KiB
Markdown
105 lines
7.1 KiB
Markdown
# T3X
|
|
|
|
{ Just discovered this thanks to a friend, WORK IN PROGRESS, MAY HAVE ERRORS etc. ~drummyfish }
|
|
|
|
T3X is a family of relatively obscure [minimalist](minimalism.md) [programming languages](programming_language.md) similar to [Pascal](pascal.md), made by Nils M Holm. There are different versions of the language (dating back to the [90s](90s.md)), distinct mainly by "feature richness" and small polishing over the years, but being very similar in general; most notable is probably **T3X/0** (made in 2022), described as a "sweet spot" between minimalism and "practical usability". The code is released under permissive [free software](free_software.md) [licenses](license.md), some even under [CC0](cc0.md), but sadly some of the formal specifications are proprietary and accessible only after payment. The languages are very well implemented, the body of work is a joy to behold and explore -- even though very strictly speaking these languages aren't the absolute peak of minimalism (some even sport some kind of "simplified [OOP](oop.md)") but rather seem like an attempt at remaking an oldschool language in nicest way possible while keeping to some pragmatic and practical choices, still compared to anything [modern](modern.md) they are super minimal; [C](c.md) definitely looks like a pile of [bloat](bloat.md) compared to T3X languages. For more details see the author's website at https://t3x.org/t3x/index.html.
|
|
|
|
The languages are very cool but their implementation is probably what's even more notable here: T3X/0 is [self hosted](self_hosting.md) in about 4 thousand lines { Doing `wc -l *.t library/*.t`. ~drummyfish }, [bootstrappable](bootstrap.md) and extremely [portable](portability.md) (so far lists e.g. generic [Unix](unix.md), [freeBSD](freebsd.md), [mac](mac.md), [DOS](dos.md), CP/M, 386, [x86](x86.md), [ARM](arm.md)), allowing cross compilation basically on every supported platform to any other etc. This is an example of how software should be written.
|
|
|
|
The languages evolved from early (1995) experimental languages named `T_1` and `T_2` into a big tree of languages and compilers. The most notable ones are currently probably these:
|
|
|
|
- **T3X** (1997): Some kind of stable language emerged from the initial languages.
|
|
- **T3X9** (2017): T3X subset, smallest (around 1600 [LOC](loc.md) of self hosted code) but (looks like) not extremely portable because directly targets 386 architecture.
|
|
- **T3X/Z** (2019): Port of T3X9 to Z80 architecture.
|
|
- **T3X/86** (2021): Port of T3X9 to x86 [DOS](dos.md).
|
|
- **T3Xr7** (2003): A little more bloated.
|
|
- **T3X/0** (2022): Probably the most notable one, something between T3X9 and T3Xr7. Highly portable.
|
|
|
|
Worthy of mention is also so called **Tcode**, a [bytecode](bytecode.md) and [virtual machine](vm.md) (called *TCVM*) that the languages use. They also compile to native binary programs, but the bytecode also allows for interpreting the programs, decouples the compiler frontend and backends etc.
|
|
|
|
The author, Nils M Holm, is a [Buddhist](buddhism.md) (according to his website a "pragmatic" one) minimalist programmer living in Germany, probably of older age (considering he keeps talking about programming in the 80s and was making own languages in the 90s), who has published an impressive number of books (sadly [proprietary](proprietary.md)) on the topic of minimalist programming, compilers, [Lisp](lisp.md) etc., sharing some views with [LRS](lrs.md) (expressing sadness about what computer science has evolved into since the 80s, that "[hackers](hacking.md) turned into entrepreneurs" and so on).
|
|
|
|
LRS is always very happy to see people strive for simplicity and we applaud the author's passion and incredible effort over several decades whose fruit is now very helpful to the entire world. A few words of criticism could be stated of course, like always, for example that the language seems to go for unnecessary features such as modules or even objects -- there is no need to implement modules that enforce encapsulation and allow dot syntax like for example `t3x.write` if we can achieve the same thing by simply writing a library with prefixed functions, e.g. `t3x_write` (while keeping private members further prefixed with `_`, like `_t3x_internalvariable`). Some syntax elements, like `do ... end` instead of plain curly brackets (which are objectively better) seem to be perhaps a little driven by nostalgia. From ultraminimalist point of view the language is actually quite feature rich, which is fine, but then suddenly some really useful features that would be expected at this level, such as a number printing function, seem to be missing. Some functions and constructs are a little tricky and not self-documenting, for example the for loop just takes 2 arguments and it's not clear what they mean, the upper bound behaves like traditional C for loop, i.e. iterating as long as the variable is BELOW (and NOT equal) to the bound, but whereas in C this is clear by the presence of the `<` operator, here we are left guessing, and one would probably expect `<=` is actually implied { Before looking it up I actually even considered that it may say the NUMBER of iterations. ~drummyfish }. Also the built-in printing function is a bit awkward, first taking file descriptor, then the string, and then the length of the string (which itself is zero terminated). In any case the author will probably keep improving the language as he has been for a long time, so we may very likely expect his work to get more and more polished.
|
|
|
|
## T3X/0: The Language
|
|
|
|
Here is a summary of T3X/0, the language we find most [interesting](interesting.md).
|
|
|
|
It is vaguely similar to [Pascal](pascal.md), imperative, procedural, case insensitive, may be both compiled and interpreted (includes [bytecode](bytecode.md)). Features include procedures, vectors, [recursion](recursion.md), [modules](module.md) etc. There are a few simple [data types](data_type.md) such as integers, vectors, byte vectors and strings (which are actually just vectors of integers).
|
|
|
|
As a code example here is our standardized **divisor tree [algorithm](algorithm.md)** implemented in T3X/0:
|
|
|
|
```
|
|
use t3x: t; ! include the core module
|
|
|
|
printChar(c) do
|
|
t.write(1,@c,1);
|
|
end
|
|
|
|
printNum(x) do
|
|
if (x > 99)
|
|
printChar('0' + x / 100);
|
|
|
|
if (x > 9)
|
|
printChar('0' + (x / 10) mod 10);
|
|
|
|
printChar('0' + x mod 10);
|
|
end
|
|
|
|
! recursive function, prints divisor tree of x
|
|
printDivisorTree(x) do
|
|
var a, b, i;
|
|
a := -1;
|
|
b := -1;
|
|
|
|
for (i = 2,x / 2 + 1) ! find two closest divisors
|
|
if (x mod i = 0) do
|
|
a := i;
|
|
b := x / i;
|
|
|
|
if (b <= a)
|
|
leave;
|
|
end
|
|
|
|
printChar('(');
|
|
|
|
ie (a > 1) do
|
|
printDivisorTree(a);
|
|
printChar(' ');
|
|
printNum(x);
|
|
printChar(' ');
|
|
printDivisorTree(b);
|
|
end else
|
|
printNum(x);
|
|
|
|
printChar(')');
|
|
end
|
|
|
|
do var str::4, n, i, c; ! main program
|
|
while (%1) do ! main loop, read numbers from the user
|
|
t.write(1,"enter a number: ",16);
|
|
t.read(0,str,3);
|
|
n := 0;
|
|
i := 0;
|
|
|
|
while (str::i \= 0 /\ str::i \= '\n') do ! convert str to num
|
|
c := str::i - '0';
|
|
|
|
if (c < 0 \/ c > 9)
|
|
halt 0;
|
|
|
|
n := n * 10 + c;
|
|
i := i + 1;
|
|
end
|
|
|
|
printDivisorTree(n);
|
|
printChar('\n');
|
|
end
|
|
end
|
|
```
|
|
|
|
## See Also
|
|
|
|
- [LIL](lil.md)
|
|
- [uxn](uxn.md)
|
|
- [comun](comun.md) |