| Crates.io | amethyst_geode |
| lib.rs | amethyst_geode |
| version | 1.3.0 |
| created_at | 2025-05-17 15:36:50.802199+00 |
| updated_at | 2025-07-01 21:08:44.178674+00 |
| description | Turing Machine Programming Language Interpreter |
| homepage | https://github.com/VSebastian8/amethyst |
| repository | https://github.com/VSebastian8/amethyst |
| max_upload_size | |
| id | 1677958 |
| size | 544,882 |
Amethyst is a programming language where you write everything using Turing machines. Its goal is to help grow the understanding of this popular and powerful computational model.
If you have cargo, you can install the binary directly from crates.io
cargo install amethyst_geode
There are also precompiled binaries available for Windows, macOS, and Linux.
geode run code/add.myst -input 110+01 -o -limit 500 -tape
Or you can specify the compilation flags in a separate file:
geode r code/simple.myst -c config/example.txt -start verify
| Flag | Shorthand | Argument | Default |
|---|---|---|---|
| -input | -i | initial tape content | @ |
| -output | -o | false | |
| -tape | -t | false | |
| -bound | -b | max number of cells | none |
| -iterations / -limit | -iter / -l | max number of steps | 1200 |
| -debug | -d | false | |
| -config | -c | path/to/config.txt |
As a quality of life feature, amethyst supports the wildcard pattern _ in transitions. For a state, when a transition has a wildcard as the read symbol, all tape symbols that do not have an already matching transition will match the wildcard and the cell will be rewriten with the write symbol. When both the reading and writing symbols are wildcards, the cell will not be rewriten for all tape symbol that match. This functionality heavily helps with code readability and **avoiding repetition**.
Arrow states are states that do nothing but move to another state. The following notation: state1 -> state2; is syntactic sugar for state1 { _ / _, N -> state2}. This pattern appeared often when working with components, especially in the case of multiple macros where one final state simply lead into the next input state.
Components are a way to reuse code. Syntactically, they look like function arguments for the automata, but they are static copies of the specified turing machines.
E.g. Let's say we have written a turing machine that adds two numbers together and we would like to reuse this code. We can add this 'add' automaton as a component to the 'main' automaton like so automaton main(add a){...}. We can consider the 'a' component of a static turing machine with the blueprint of 'add'. We use 'a' as a black box, concerning ourselves only with its input a.initial_state and output a.accept_states & a.reject_states.
Each component's initial state is exposed to the parent turing machine. Final states (accepting and rejecting) of the component automata have to be rewriten in order to continue the execution of the parent machine.
Macros are a way to reduce boilerplate code, whether that be a very common and useful machine or a machine with many repetitive states.
E.g. To move exactly 8 cells to the right we would need 8 states with each state having the only job of making a right move and going to the next state.
These are not functions with variables, they are just syntactic sugar that gets expanded into a specific turing machine at compile time. Each macro-machine will have one initial state (input) and two final states (accept and reject). Some macros (such as move or shift) do not use the reject state since there's no way they can fail.
The following macros are present so far:
complement (automaton)
intersect (automaton, automaton)
reunion (automaton, automaton, automaton)
chain (automaton, automaton, automaton)
repeat (automaton, number)
move (moveSymbol, number)
override (moveSymbol, number, tapeSymbol)
place (string)
shift (moveSymbol, number)

geode run code/hello.myst -input WORLD -debug -output -tape
You can find more code examples here