Treadnil

From Esolang
Jump to navigation Jump to search

Treadnil is an esolang by User:BoundedBeans based off the idea of time travel in a world with two dimensions of time.

Basic concepts

Coordinates are always 1-based unless specified otherwise.

A timeplane is a 32x32 matrix of cells called instants. Technically it can be any size, or have more than two dimensions, but since I already mostly wrote this spec, it will discuss a 32x32 matrix. For more dimensions add the additional coordinates in the same order, for stack operations and similar things. Each instant has a queue of instructions and a stack of more timeplanes. An instant with no instructions and an empty stack is considered empty, and is the default.

Every tick in metatime (time related to the actual execution of a Treadnil program in our world), an instruction in an instant is executed twice, one advancing on X and one advancing on Y. Each instruction is actually a pair of semantics, which has a different meaning depending on X vs. Y time flow. The instruction is removed from the queue. The new versions of the instant after the half instructions are copied to the cells directly after in their directions. Once this happens, the original instant is marked as having already happened, so it won't try again unless it is overwritten. The instant backwards in X and forwards in Y both by 1 cell is also marked as already happened to prevent conflict on the cell they both affect.

The timeplane does not wrap, instants that occur at the X+ edge do not continue on X, likewise for Y, and the instant on the corner does not ever continue.

The program cycles in a loop, doing the previous for all cells that haven't already happened, aren't empty, and aren't at the X+ Y+ corner, reading in X- to X+, Y- to Y+ order. The program terminates when no such cells exist.

This is more complicated since instants can time travel. Certain instructions cause the instant to not propagate on one axis and instead replace some other instant in the timeplane. Notably, the new replacement will no longer be marked as having already happened and will propagate through the further timeline.

Timeplanes as numbers

A 32x32 timeplane can be interpreted as a number from 0-1023 as the number of non-empty instants in it. Canonical numeric timeplanes as the result of instructions fill the various diagonals from the Y- to X- edge, starting with (1,1), then (2,1) and (1,2), then (3,1), (2,2), and (1,3), and so on, with instants with an empty stack and a single instruction with both halves set to Null. All math is done on 32x32 timeplanes, no other sizes are valid.

Half-Instructions

These half instructions ignore whitespace in the syntax, except in XML strings.

  • Null - Do nothing.
  • Nums[(i),(x1),(x2),(x3),etc] (where xn are a numbers and i is a half instruction) - push the numbers to the stack in order, then perform i
  • Timeplanes[(i),(t1),(t2),(t3),etc] (where tn are C-syntax strings representing timeplanes in XML format, and i is a half instruction) - push the timeplanes to the stack in order, then perform i
  • Instructions[(i1a),(i1b),(i2a),(i2b),(i3a),(i3b),etc] (where ina and inb are half-instructions) - Adds the instructions to the back of the queue in pairs
  • Add - Pop x, pop y, push y + x (all numbers)
  • Sub - Pop x, pop y, push y - x (all numbers)
  • Mul - Pop x, pop y, push y * x (all numbers)
  • DivMod - Pop x, pop y, push y modulo x, push y / x (all numbers)
  • Dup[(i)] (where i is a half instruction) - Pop x, push x twice, then perform i. Should make a separate copy, not a reference.
  • Swap[(i)] (where i is a half instruction) - Pop x, pop y, push x, push y, then perform i
  • Drop[(i)] (where i is a half instruction) - Pop and discard a timeplane, then perform i
  • Roll[(i)] (where i is a half instruction) - Pop x, roll the top timeplane x places down on the stack, then perform i
  • RRoll[(i)] (where i is a half instruction) - Pop x, roll the xth element to the top, then perform i
  • ExecTick - Execute the top timeplane for one tick, push the new timeplane back
  • ExecCycle - Execute the top timeplane for one cycle, push the new timeplane back
  • ExecFull - Execute the top timeplane until it halts
  • Repeat[(i)] (where i is a half instruction) - Pop n as a number. Do the non-timeflow/travel effects of i n times on the instant (as if it were a Church numeral). This still includes time manipulation and side effects, just not the time travel of THIS instant. This instant will still advance one unit though.
  • TimeTravel[(i)] (where i is a half instruction) - Pop y off the stack, pop x off the stack, then perform i, but instead of copying the result to the next instant, copy it to position (x,y) on the timeplane
  • Base [Get] instruction set
    • Get - Pop y as a number, pop x as a number, pop a timeplane t off the stack, replace this instant's entire state with that of the instant at position (x,y) in t. This does not count having already happened as part of the state.
  • [Get] GetInstructions - get the list instructions from the obtained instant and replace this instant's instructions with it
  • [Get] PrependInstructions - get the list instructions from the obtained instant and prepend this instant's instructions with it
  • [Get] AppendInstructions - get the list instructions from the obtained instant and append this instant's instructions with it
  • [Get] GetTimeplanes - get the timeplane stack from the obtained instant and replace the timeplane stack of this instant with it
  • [Get] PushTimeplanes - get the timeplane stack from the obtained instant and push all entries onto the timeplane stack of this instant as a block (not reversed)
  • [Get] PushTimeplanesR - get the timeplane stack from the obtained instant and push all entries onto the timeplane stack of this instant in a pop-push loop (reversed)
  • Any [Get]-class half instruction with "Here" prepended to the name - Like the original half instruction but gets it from this timeplane instead of the stack
  • Any [Get]-class half instruction with "Parent" prepended to the name - Like the original half instruction but gets it from the timeplane that contains this one in one of its stacks
  • CopyTimeplanesInto - Pop x as a number, pop y as a number, pop n as a number, pop n timeplanes, pop a timeplane t. Push the n timeplanes to the stack at position (x,y) in t, push the new version of t
  • CopyParentTimeplane[(i)] - Push a copy of the timeplane containing this timeplane in a stack, then run i
  • CopyThisTimeplane[(i)] - Push a copy of the timeplane containing this instant, then run i
  • IfTimeplaneEqual[(i),(j)] - Pop two timeplanes t and u, if t is the exact same as u in all contents, run i, otherwise j
  • IfInstantEqual[(i),(j)] - Pop x1, y1, x2, and y2 as numbers, pop a timeplane t. If t at (x1, y1) is exactly the same as t at (x2, y2) in all contents, run i, otherwise j
  • IfAlreadyHappened[(i),(j)] - Pop x and y as numbers, pop a timeplane t. If t at (x,y) already happened, run i, otherwise j.
  • IfLessThan[(i),(j)] - Pop x and y as numbers, if y < x, run i, otherwise j.
  • Switch[(n1),(i1),(n2),(i2),(n3),(i3)] - Pop x as a number. For each pair of n and i, if x == n, run i.
  • Force - Pop n, x, and y as numbers, pop a timeplane t. Force-run n instructions from the current instruction queue on t at (x,y), then remove them from the queue.
  • Out - Pop x as a number, output it as a byte modulo 256
  • In[(i)] - Take one byte of input and push it as a number, then run i. EOF pushes 256.
  • SaveStreams - Pop a number n, saves the In and Out streams to it as one of 1024 locations for later use. These streams won't be closed unless you use the CloseStreams command. Saving to a location that's already used will close the previous streams and replace them with the new ones.
  • LoadStreams - Pop a number n, loads the In and Out streams from it.
  • CloseStreams - Pop a number n, closes the streams stored at n and clears that location.
  • IO - Redirects the output stream to an internal string, pops a timeplane and ExecFulls it. The string is taken as:
    • A file path preceded with F. The In and Out streams are replaced with the file.
    • The string "S". The In and Out streams are replaced with stdin and stdout
    • The string "SE". The In and Out streams are replaced with stdin and stderr
    • A TCP address preceded with TC. The In and Out streams are replaced with that of the connection.
    • "TS(x)/(y)" uses the yth connection by server x.
  • TCPServerOpen - Pops x, ip1, ip2, ip3, ip4, port1, and port2 as numbers. Binds a server to ip1.ip2.ip3.ip4 on TCP port (port1 * 1024 + port2), assigns it an ID x to refer to later.
  • TCPServerAccept - Pops y as a number. Accepts y incoming connections
  • TCPServerClose - Pops x, closes TCP server x
  • Parallel[(i)] - Pops a timeplane t, ExecFulls t in a new thread. Runs i in the original thread and instant. You can communicate between threads with a TCP server. Each thread has its own timeplane and list of streams (the new thread's streams are all clear and the current streams are stdin and stdout).
  • IfSupportsEval[(i),(j)] - If this implementation supports eval, run i, otherwise j
  • Eval - Pops a timeplane t. Redirects the Out stream to an internal string. ExecFulls t, then interprets the resulting string in XML timeplane format and pushes the timeplane. Reverts the Out stream to what it was previously.
  • Die - Quits the timeplane early.
  • Extinction - Quits the entire program

Syntax

Programs are specified as the initial state of the top-level timeplane, in XML. The XML namespace URI is https://esolangs.org/wiki/Treadnil.

  • The XML element for a timeplane is <Timeplane dims="32,32"> (you can have numbers besides 32 and even 3 or more dimensions, but 1 or 0 dimensions are not allowed. It should contain 0 or more <Instant>s
  • <Instant coords="x,y" already="true/false"> elements. Each of these should contain an <Instructions> element and a <Stack> element.
  • <Instructions> should contain 0 or more <Instruction> elements.
  • <Instruction ins="Roll[Nop]/ExecCycle"> elements are empty
  • <Stack> should contain 0 or more <Timeplane> elements, from bottom to top on the stack

And since this is XML, it is of course extendable with more attributes and elements.

Examples

Hello, world

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<Timeplane dims="32,32" xmlns="https://esolangs.org/wiki/Treadnil">
  <Instant coords="1,1" already="false">
    <Instructions>
      <Instruction ins="
        Nums[Repeat[Out],33,100,108,114,111,119,
        32,111,108,108,101,72,12]/Null" />
      <Instruction ins="Extinction/Null" />
    </Instructions>
    <Stack />
  </Instant>
</Timeplane>

Truth-machine

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> 
<Timeplane dims="32,32" xmlns="https://esolangs.org/wiki/Treadnil">
  <Instant coords="1,1" already="false">
    <Instructions>
      <Instruction ins="
        Nums[In[IfTimeplaneEqual[Swap[Drop[ExecFull]],
        Drop[ExecFull]]],0]/Null" />
    </Instructions>
    <Stack>
      <Timeplane dims="2,2">
        <Instant coords="1,1" already="false">
          <Instructions>
            <Instructions ins="
              Nums[Out,49]/
              Nums[TimeTravel[GetInstructions],1,1,1,1]" />
          </Instructions>
          <Stack />
        </Instant>
      </Timeplane>
      <Timeplane dims="2,2">
        <Instant coords="1,1" already="false">
          <Instructions>
            <Instruction ins="Nums[Out,48]/Extinction" />
          </Instructions>
        </Instant>
        <Stack />
      </Timeplane>
    </Stack>
  </Instant>
</Timeplane>