Files
clyx/README.md
T

204 lines
11 KiB
Markdown
Raw Normal View History

2026-07-02 23:26:38 +03:00
# Clyx programming language
## About
2026-07-03 12:56:00 +03:00
Clyx (pronounced like _clicks_) is a concatenative, stack-oriented, interpreted programming language designed for simplicity, minimalism, and metaprogramming capabilities.
2026-07-02 23:26:38 +03:00
2026-07-04 17:10:08 +03:00
Clyx aims for maximum portability and can be implemented in any modern runtime environment that supports data structures defined in JSON (numbers, strings, arrays and key-value dictionaries). Extra features varying in portability include filesystem support and TCP socket I/O.
2026-07-02 23:26:38 +03:00
2026-07-03 10:38:04 +03:00
The core spec of Clyx is mostly stable but the standard library is still a work-in-progress.
2026-07-02 23:26:38 +03:00
## Language features
2026-07-04 16:56:08 +03:00
- Single, unbounded data stack that can hold numbers, strings and lists (here called Q-forms)
2026-07-02 23:26:38 +03:00
- Forth-like parsing, RPN (postfix notation) and word definition mechanics
2026-07-04 16:56:08 +03:00
- Tcl-like bracket syntax and Janet-like list operations on Q-forms
- Homoiconicity: Q-forms and strings can be manipulated as data and executed dynamically
2026-07-02 23:26:38 +03:00
- Character I/O (implementation-dependent)
- File I/O (may not support all features on some targets)
- TCP socket I/O (may not be supported on some targets)
2026-07-03 12:47:21 +03:00
- Host language interop (may not be supported on some targets, only to be used when nothing else helps)
2026-07-02 23:26:38 +03:00
- Platform-agnostic [standard library](lib.clx)
- Ability to include custom modules into the current runtime context (depends on file I/O capabilities)
2026-07-03 16:13:44 +03:00
## Implementations
2026-07-03 16:15:02 +03:00
- [Reference implementation in Python](clyx-python/clyx/clyx.py) (compatible with MicroPython and [T-DeckARD](https://codeberg.org/luxferre/t-deckard) on CircuitPython)
2026-07-03 16:13:44 +03:00
- [Reference implementation in Go](clyx-go/clyx.go)
2026-07-03 10:11:18 +03:00
## Installation
Depending on the implementation, there are several installation ways.
2026-07-03 10:26:57 +03:00
### Reference Python (CPython) implementation installation
2026-07-03 10:38:04 +03:00
For the easiest way to install the reference Python-based Clyx implementation, [pipx](https://pipx.pypa.io/stable/) is recommended:
2026-07-03 10:11:18 +03:00
```sh
2026-07-03 10:38:04 +03:00
pipx install "git+https://codeberg.org/luxferre/clyx.git#subdirectory=clyx-python"
2026-07-03 10:11:18 +03:00
```
This will install the REPL as `clyx` into your current environment.
2026-07-03 12:23:09 +03:00
Then, you can just run `pipx upgrade clyx` to upgrade to the new release versions whenever they come out.
2026-07-03 10:26:57 +03:00
### Reference implementation for MicroPython
Clone this repo, then run `sh dist-python.sh`. A `dist/clyx_py/clyx` directory will appear, which will contain all the files necessary to run `micropython clyx.py [prog.clx]` on the desktop or copy them to the target device.
2026-07-03 16:15:02 +03:00
### Reference implementation for CircuitPython + T-DeckARD runtime
2026-07-03 10:11:18 +03:00
Clone this repo, then mount your T-Deck's CircuitPython volume, and then run:
```sh
sh dist-python.sh /path/to/mounted/volume/app/clyx
```
This will install Clyx as a T-DeckARD applet.
2026-07-03 16:12:25 +03:00
### Reference Go implementation installation
2026-07-04 10:16:52 +03:00
To install the Go-based Clyx implementation and its tools (including `clyxc`) directly from Git, run:
2026-07-03 16:12:25 +03:00
```sh
2026-07-04 10:16:52 +03:00
go install codeberg.org/luxferre/clyx/...@latest
2026-07-03 16:12:25 +03:00
```
2026-07-04 10:22:14 +03:00
*(Note: If you are installing immediately after a new commit or release has been pushed, Go's default module proxy might serve a cached version. You can bypass this cache by running `GOPROXY=direct go install codeberg.org/luxferre/clyx/...@latest` instead).*
2026-07-04 10:16:52 +03:00
For maximum performance, you can pass optimization flags to build stripped binaries without debug symbols, bounds checks, or inlining:
2026-07-03 16:12:25 +03:00
```sh
2026-07-04 10:16:52 +03:00
go install -a -trimpath -gcflags=all="-l -B -e" -ldflags "-s -w" codeberg.org/luxferre/clyx/...@latest
2026-07-03 16:12:25 +03:00
```
2026-07-04 10:16:52 +03:00
This will install the executables as `clyx` and `clyxc` into your `$GOPATH/bin` directory. To upgrade to the latest versions at any time, simply run the same command again.
2026-07-03 16:12:25 +03:00
Alternatively, to compile and build it locally, navigate to the `clyx-go` directory and run:
```sh
cd clyx-go
make
```
This will build the `clyx` executable.
2026-07-02 23:26:38 +03:00
## Usage
Note: this section describes how to run the interpreter itself. For the language manual, refer to [Clyx Reference Manual](clyx_manual.md).
2026-07-04 09:23:54 +03:00
All core implementations must accept one or more `.clx` files to run (either via command line or via library call parameter). If multiple files are passed, they are executed in sequence. If a `_main` word is defined in the workspace after running all source files, it is automatically executed as the entry point. The REPL is implemented in Clyx itself and resides in the [clyx_repl.clx](clyx_repl.clx) file.
2026-07-02 23:26:38 +03:00
2026-07-03 10:26:57 +03:00
### Running the reference Python implementation
2026-07-04 09:23:54 +03:00
If Clyx is installed as a PyPi package, use `clyx [prog1.clx prog2.clx ...]` to run the REPL or one or more programs.
2026-07-03 10:26:57 +03:00
2026-07-04 09:23:54 +03:00
Otherwise, to run the REPL, run `[micro]python clyx.py` command from the directory created by `./dist-python.sh`. Pass one or more `.clx` files additionally to run them directly.
2026-07-03 10:26:57 +03:00
### Running as a T-DeckARD applet
2026-07-02 23:26:38 +03:00
2026-07-03 10:11:18 +03:00
To run the REPL inside T-DeckARD:
```
from app.clyx import clyx
clyx.repl()
```
2026-07-03 10:26:57 +03:00
To run a Clyx source file directly, issue `clyx.clyx('path/to/file.clx')` instead.
2026-07-03 16:30:57 +03:00
Caveats:
1. The entire operation is rather slow (which is expected for an interpreted runtime on top of CircuitPython on this class of machines) and may sometimes overflow the allocated (native) Python stack. As such, it's not recommended to `src` files from the REPL if you can run them directly instead.
2. Don't forget to mount an SD card or run `unlock_rootfs()` if you want to use file writing capabilities inside T-DeckARD environment.
2026-07-03 16:12:25 +03:00
### Running the Go implementation
To run the REPL, execute the compiled `clyx` binary without arguments:
```sh
./clyx
```
2026-07-04 09:23:54 +03:00
To run programs directly, pass the path to the `.clx` files as arguments:
2026-07-03 16:12:25 +03:00
```sh
2026-07-04 09:23:54 +03:00
./clyx path/to/program1.clx path/to/program2.clx
2026-07-03 16:12:25 +03:00
```
2026-07-04 08:52:56 +03:00
### Self-contained Packaging (Compilation)
The Go implementation supports reading an optional ZIP archive appended directly to the end of the `clyx` binary. This allows you to package your Clyx source code into a single executable file.
2026-07-04 10:13:40 +03:00
To package your program, you can use the `clyxc` utility.
2026-07-04 10:10:38 +03:00
2026-07-04 10:13:40 +03:00
#### Installing `clyxc`
2026-07-04 10:16:52 +03:00
Install the utility directly from Git (this also installs the main `clyx` binary):
```sh
go install codeberg.org/luxferre/clyx/...@latest
```
Or to install only the compiler utility:
2026-07-04 10:13:40 +03:00
```sh
go install codeberg.org/luxferre/clyx/clyxc@latest
```
Alternatively, if compiling locally from the repository root:
```sh
go install ./clyxc
```
#### Using `clyxc`
Run the compiler by passing the output binary path followed by the list of source files or directories:
```sh
clyxc out-bin-path src1 src2...
```
*(Note: `clyxc` requires the main `clyx` interpreter binary to be installed in your `$GOPATH/bin` directory).*
#### Manual Packaging Alternative
If you prefer not to use `clyxc`, you can package the application manually:
2026-07-04 08:52:56 +03:00
1. Create a ZIP archive containing all your `.clx` source files.
2. Append the ZIP archive to the compiled `clyx` binary:
```sh
cat clyx my_app.zip > my_app_executable
chmod +x my_app_executable
```
When the packed executable runs:
- The interpreter automatically detects the appended ZIP archive.
- It iterates through all `.clx` files in the archive and evaluates (`src`) them.
- If a `_main` word is defined in the environment, it is executed automatically.
- If `_main` is not present, the interpreter falls back to running the standard REPL.
2026-07-02 23:26:38 +03:00
## FAQ
### Where does the name Clyx originate from?
Similarly to [LVTL](https://codeberg.org/luxferre/lvtl-x) and [LTTB](https://codeberg.org/luxferre/lttb), the prototype of Clyx had been called LPLF (Luxferre's Pointer-Less Forth). However, as the finalized language began to differ from the Forth standard in too many ways, a decision was made to focus on the concatenative nature itself. Thus, the word ConCat had been chosen, which was quickly modded into ConLynx and then naturally shortened to Clyx.
Additionally, this name can be viewed as an acronym hinting at the order some binary operations pop their operands from the stack: "Compute by Loading Y, then X".
2026-07-03 12:36:14 +03:00
### Is this language high-level or low-level?
More of a high-level one (because you don't have any memory control), but in fact it can be both.
2026-07-04 16:56:08 +03:00
Clyx combines the conceptual simplicity of Forth (and concatenative/RPN programming in general) with list definition syntax, manipulation and metaprogramming capabilities of Janet and Tcl, making it much more practical for everyday tasks. At the same time, you can build abstraction levels as high as you need to, making it a nice choice for creating custom DSLs (domain-specific languages), especially with the `next` word that pushes the next logical token onto the stack, allowing to change token processing order.
2026-07-03 12:36:14 +03:00
2026-07-02 23:26:38 +03:00
### Why not just pick up a Forth instead?
Forth is good if you are fine with only being able to push integers onto the stack and building all your abstractions using direct memory access. Clyx, on the other hand, does not have direct memory access because it was designed for the systems that might not even give you one, but you can do so much more with the data types that it allows you to push onto the stack without involving any trickery.
While diverging from some "purity" aspects, Clyx is a decent choice for newcomers that want to try out a totally new programming paradigm without investing too much time into fighting the language's quirks.
2026-07-04 17:10:08 +03:00
### Why are lists called Q-forms in Clyx?
Idiomatically, lists (as a data structure, as in Python lists or JSON arrays) can only hold data. Q-form is short for "quotation form", which just means that it is a quoted (block-like) sequence that can be treated both as data and as code. Physically, Q-forms are implemented as random-access lists or arrays in 100% cases, but logically, it's important to maintain this distinction that Q-forms can hold program code and lists in general do not. Besides, the term "list" is confusing in general because, apart from the random access lists used to implement Q-forms, it can also refer to linked lists or double-linked lists, which have totally different sets of features and constraints.
2026-07-03 12:36:14 +03:00
### What do I need to do to create my own Clyx implementation?
2026-07-04 16:09:50 +03:00
Just port the core interpreter along with the 50 primitive words, stubbing out the words that cannot be supported by the target platform if there are any, so that if a program that e.g. uses `nopen` runs on a non-networked host environment, then the user would get a clear message that an unsupported core primitive word has been encountered and the program has been terminated because of that.
2026-07-03 12:36:14 +03:00
Apart from that, your implementation needs to be able to load `lib.clx` (standard library source) upon initialization, and `clyx_repl.clx` upon passing no parameters (if it is CLI-based).
2026-07-03 12:21:19 +03:00
### Doesn't `hseval` primitive make Clyx programs non-portable across different implementations?
2026-07-04 16:09:50 +03:00
Yes, it does, because it works differently across different host environments and languages (e.g. Python expression evaluation vs. Go system shell command execution), so it must only be used as a last resort when any other attempts to interact with the outside world are unsuccessful. Additionally, using `hseval` introduces extra security risks. Nevertheless, this primitive had been added in order to enable some host-specific interoperability that would otherwise be impossible or very cumbersome to implement, such as browser-based deployments.
2026-07-03 12:21:19 +03:00
In other words, `hseval` is sometimes very useful in very specific cases, but please avoid using it unless you have a really good reason to use it.
2026-07-02 23:26:38 +03:00
## Credits
Created by Luxferre in 2026, released into the public domain with no warranties.