Using the Turing Machine

The basics of the Turing Machine

By writing "Hello world!", you just used the output functionality of TML. Of course, there are many other (far more interesting) things you can do with this language, so let's hop into it!

Defining the Machine

To start, let's take a look at the following .tml code:

/*
    An example program creating the starting values in the Turing machine.
*/
print("Starting turing machine...");
setValues(# 2 0);

// Set the starting position of the machine
setPosition(0);

You can print out the values in the machine by running with the following shortcut:

print(); (or, for in the future with a command, ?print()) This will just print out what's currently in the machine.

This code first prints the starting message, and initializes the machine with data in the following array: [2, 0]. TML is zero-indexed, so setting the position of the machine at zero means that if the machine reads there, it will return a 0.

These blockers also don't count as an index, so moving across them functions as if there was nothing there.

Initializing the Machine

Unlike previous versions, newer versions don't require the use of a generate(); function call. If you don't know this existed, don't worry about it. Simply set the values in the tape and starting position, and you're good to go!

Setting your Commands

At long last, you can get into setting pages and awareness! You can create your first command with the following:

setCommand(
    // Setting first commands
    AWARENESS=2, PAGE=0,
        ?setTape(3)
        ?move(1)
        ?setTape(-1)
        ?print()
        ?stop()
);

The starting page is zero, but the starting awareness is always what the carriage is currently reading.

Here's the break-down of what this setCommand does:

  1. AWARENESS and PAGE set the awareness and page number for this command

  2. The ? prefix is the "future symbol". This function will then execute whenever this page/awareness combination is reached, and not instantly like the other commands. All of these commands can be run normally as well.

  3. So, this then, when the code is run, sets the tape to 3 (so the tape is now 3 0), moves right one (3 0), sets the tape to -1 (3 -1), prints the result (# 3 -1) and stops the machine.

The idea of a "future" function is critical to understanding how the machine works. These future functions are what will happen if the machine reaches that page/awareness combo, not immediately when it's read like the other functions.

Bitwise And Program

Here's a way to perform the bitwise-and operation:

/*
    Should apply and operation in a bitwise manner, leaving result in second "byte" while first is unchanged

    Expected output:
    Final result:
    # 1 0 1 0 1 1 0 2 # 0 0 1 0 1 1 1 2
*/
print("Starting turing machine...");

setValues(# 1 0 1 0 1 1 1 2 # 0 1 1 0 1 1 1 2);
setPosition(0);

const forward = 8;
const back = -7;


print();
setCommand(
    AWARENESS=0, PAGE=0,
        ?move(forward)
        ?goToPage(1)
        ?print(?readTape())
);

setCommand(
    AWARENESS=1, PAGE=0,
        ?move(forward)
        ?goToPage(2)
        ?print(?readTape())
);

setCommand(
    AWARENESS=2, PAGE=0,
        ?stop()
);

setCommand(
    AWARENESS=0, PAGE=1,
        ?setTape(0)
        ?move(back)
        ?goToPage(0)
);
setCommand(
    AWARENESS=1, PAGE=1,
        ?setTape(0)
        ?move(back)
        ?goToPage(0)
);
setCommand(
    AWARENESS=0, PAGE=2,
        ?setTape(0)
        ?move(back)
        ?goToPage(0)
);
setCommand(
    AWARENESS=1, PAGE=2,
        ?setTape(1)
        ?move(back)
        ?goToPage(0)
);

run();
print("Final result:");
print();

The most important new feature added here is the idea of constants. You can declare a constant like this:

const myValue = 3;

These constants are global, and are read first, so you can use a constant at the beginning of the program, even if you declare it at the very end! To use them, simply type the variable name wherever you want to use it, and there you go! Please not that they only work for integers.

The readTape()function can be used to print out Current value: 0 for example, if the carriage was currently reading a zero at its position. In this case, it's being used in the future, so it will execute with the command.

Try thinking through this logic exercise before you read the rest of this section - it'll get you accustomed to thinking the right way.

Bitwise And Think-through

OK - hopefully you've thought this through. First, the tape is created with the starting bits, and 2's that are used to terminate the process. Each time a part of the program runs, the carriage moves forward 8, and back 7, so that it walks forward until the 2's are reached.

First, the start command is loaded when the page is zero with the awareness at the starting position, in this case with the value of 1. It moves the carriage forward, and then shifts to page 2, and as it currently is reading a zero, it sets the value to zero, and then moves back 7 to continue the process.

In fact, the commands on pages 1 and 2 form a table:

Page/Aware
Page 1
Page 2

Awareness 0

0

0

Awareness 1

0

1

This actually should make a lot of sense - Page 1 corresponds to reading a 0 in the first binary number, and Page 2, to reading a 1, and the next read awareness is used to compute the bitwise-and operation. After this, the program goes back to page 0 to shift the carraige forward again, print the tape, and go to the proper page. This process continues again awareness 2 is reached on this page, at which point the ?stop() command stops the machine, and the process exits.

Hopefully, this example provided some useful information and examples for you!

Last updated