= Nucleus: the game This is an intro to the Nucleus game and the kaon language. The goal is to write a program (quark) that will outlive every other program, in a shared memory core. == Installation instructions You can install lepton (the implimentation of nucleus) using flakes or cargo (TODO!). Using nix flakes: `+nix run git+https://time.ta.rdis.dev/el/lepton+` Using cargo: `+cargo install leptonvm(!)+` (TODO!) == Tutorial The "core" is a linear sequence of random-access memory, 4096 instructions wide. Access are 0-indexed and wrap around (Address 4096 is the same as address 0) Example core (4 instructions wide) |=== | Index | Instruction | 0 | JUMP | 1 | ADD | 2 | JUMP | 3 | DIE |=== Quarks are written in a language called kaon. Every quark must start with an author + title line. The format for a so-called "title line" is `+@ Author name : Program Name+`, such as `+@ John Doe : Brutus+`. Quarks are encouraged to have unique program names to reduce confusion about winners After the title line, one or more instructions follow. Each instruction takes the form of keyword, followed by one or more arguments. Arguments are comma-separated, with one or more spaces between the arguments and keyword. All arguments are also addresses. There are four kinds of addresses: literal, absolute, relative, and relative-offset. Literal addresses are a number, used as a value in a computation. They are stored in the core as a `+DIE+` instruction. Absolute addresses are prefixed with a `+#+`, such as `+#3+`. They reference addresses from the start of the core. A relative address is a number of instructions ahead or behind the current instruction, like `+.1+` (the next instruction). Each relative instruction is prefixed with a `+.+`. The last type of address, a relative-offset address takes the form of `+.x#y+`. This behaves like a relative address *except* that the value of address `+y+` is added to the computed relative address. This could be written as "The address x units from where I am plus the value of address y". .Jumps six instructions ahead ---- die 5 jump .1#-1 ---- If the instruction at `+y+` is not a `+DIE+`, the quark will stop execution. For example, `+.1#-1+` will move the value of `+.-1+` spaces past the next instruction (`+.1+`). Each quark has its own thread. Each cycle, the computer switches between threads. For two threads, A & B, this looks like: ABABABABABABAB; for three: ABCABCABCABCABC. When a program dies, it is no longer executed. If program C dies: ABC ABC AB AB AB. Dead quarks do *not* have their memory zeroed or otherwise removed. This means you could jump into a dead thread and revive it (though unlikely). A winner is declared when there is only one thread left. == Usage of lepton Lepton is the reference implementation of nucleus. It is available at https://time.ta.rdis.dev/el/lepton. Pass each program as an argument to the command line. Use `+RUST_LOG+` to enable logging. `+debug+` will list the loading and unloading of quarks. `+trace+` will print each instruction being executed. Passing `+-p+` / `+--playback+` will produce a dump of the core at each cycle for debugging / inspection. Each line contains the state from the current cycle (first line is before execution, second line is after cycle 1). To set the number of iterations, use `+-i+` / `+--iterations+` (The default is 4096*8) == Example quarks .A simple loop ---- @ Ellie : Loop jump .0 ---- Jumps to the current address .A quark that moves forward ---- @ Ellie : Jogger mov .0 .1 ---- Copy the current instruction to the next instruction (which is then executed) .A quark that bombs the core with DIE ---- @ Ellie : Bomber jump .2 die 0 mov .-1 .3#-1 add 1, .-2 jump .-2 ---- This uses relative-offset addresses to make the target of the bomb move forward (`+ADD+`). == Instruction reference |=== | Instruction syntax | Arguments | Results | Notes | `+move x, y+` | x: The source address; y: the destination address | Copies value x to y | y should not be constant. | `+cmp x, y+` | x: any value; y: any value | Compares x to y and sets the equality flag if they are | Only compares equality | `+ptlcmp x, y+` | x: any value; y: any value | Compares the instruction type of a to b. Sets the flag if they are | `+jump 0+` == `+jump 1+` | `+if a+` | a: any address | Jumps to a if the equality flag is set (i.e. the last `+cmp+` was true) | A constant is treated as an absolute address. | `+jump a+` | a: any address | Moves execution of the current thread to address a. | A constant is treated as an absolute address. | `+add a, b+` | a: any value; b: any address | Adds a to b and stores the result in b | b should not be constant. If b is constant, the program dies. | `+sub a, b+` | a: any value; b: any address | Subtracts a from b and stores the result in b | b should not be constant. If b is constant, the programs dies. | `+mul a, b+` | a: any value; b: any address | Multiplies a and b and stores the result in b | b should not be constant. If b is constant, the programs dies. | `+div a, b+` | a: any value; b: any address | divides a by b and stores the value in b | b should not be constant. The value of b should not b 0. If either of these is true, the program dies. | `+die x+` | x: any literal | If this instruction is executed, the program stops. However, it stores data for use by other instructions. | Magic death trap |===