# Tock

Tock is an esolang/model of computation created by User:Silver. The name is because it puts a lot of focus on working in discrete steps, and Tick was taken.

## Overview

There is a collection of functions taking an integer `t` to a real. These functions can depend on the values that the other functions take for `t-1`, but not for any other input, so `f(t)` can be defined in terms of `g(t-1)` but not `g(t)`, `g(t-2)`, `g(t+1)` or `g(3)`. Two functions, called `halt` and `out`, are special: the output of the program is the value of `out(t)` for the smallest `t` such that `halt(t)` is zero.

## Language

A program is a collection of functions, which must include functions called `halt` and `out`. Each function is defined as follows:

```[function name] [initial value] {
[expression]
}
```

or:

```[function name] [initial value] {
[condition] : [expression];
[condition] : [expression];
otherwise : [expression]
}
```

A function name can consist of alphabetical characters and underscores only. The initial value is a number.

A condition consists of two expressions related by one of `=`, `!=`, `>`, `<`, `>=` or `<=`. Clauses of a piecewise definition are checked sequentially, the otherwise clause is optional (but the program will throw an error if no clause matches).

An expression is an arithmetical expression using `+`, `-`, `*`, `/`, `^`, `%` and `()`. It can contain both numbers and the names of other functions. Those names are interpreted as the values of those functions at `t-1`.

Line comments are permitted using double slashes.

## Examples

The following is a simple program that outputs 10:

```halt 10 {
halt - 1
}

out 0 {
out + 1
}
```

While the following outputs 20:

```halt 1 {
counter = 10: 0;
otherwise: 1
}

out 0 {
counter * 2
}

counter 0 {
counter + 1
}
```

See fractran.tock in the implementation repository linked below for a more involved example.

## Computational Class

Tock is Turing Complete, as shown by the existence of the following translation of Fractran:

```halt 1 {
pointer > [number of fractions]: 0;
otherwise: 1;
}

out 0 { n }

mode 0 {
(mode + 1) % 4;
// modes are:
// 0 - load pointed at fraction
// 1 - compare fraction to current n
// 2 - update n and pointer accordingly
// 3 - check if finished
}

pointer 0 {
mode + (10 * current_match) = 12: 0; // return to start
mode + (10 * current_match) = 2: pointer + 1; // next fraction
otherwise: pointer;
}

current_fract_numerator 1 {
pointer + ([number larger than number of fractions] * mode) = 0: [numerator of first fraction];
pointer + ([number larger than number of fractions] * mode) = 1: [numerator of second fraction];
...
otherwise: current_fract_numerator;
}

current_fract_denominator 1 {
pointer + ([number larger than number of fractions] * mode) = 0: [denominator of first fraction];
pointer + ([number larger than number of fractions] * mode) = 1: [denominator of second fraction];
...
otherwise: current_fract_denominator;
}

current_match 0 {
(n * current_fract_numerator) % current_fract_denominator = 0: 1;
otherwise: 0;
}

n [input to the fractran program] {
current_match + ([number larger than the number of fractions] * mode) = ([same large number] * 2) + 1: n * (current_fract_numerator / current_fract_denominator);
otherwise: n;
}
```

See fractran.tock in the implementation repository linked below for an example of using this to translate a fractran program.

## Implementation

An implementation exists at [1]