1 Introduction
Some functions are naturally nonterminating, which makes them nontrivial to model in a logic of total functions. A prototypical example is a definitional interpreter [4], which defines the semantics of a programming language and diverges when the program being interpreted should diverge. A nice way to make a total model of such a function is to add a clock: an extra parameter whose ticks act as fuel for recursive calls. The clock makes the function terminating, since any application will eventually run out of fuel, without sacrificing reasoning about divergence, since divergence is equivalent to timing out for every initial clock. The clock idea is wellknown to users of ACL2 [1], and we have recently advocated for its use in higherorder logic (HOL) for definitions of programminglanguage semantics [3].
There is trade off to be made whenever a clocked function is defined: how intricate should the clock mechanism be? A more nuanced clock might lead to a better semantics but require a more subtle termination proof. There are two dimensions to consider:

On which recursive calls is the clock decremented?

Does the clock measure the depth or the length of execution? Equivalently: is the clock environmentlike (not returned) or statelike (threaded through)?
At the simple end of the first dimension is a clock that consumes fuel on every recursive call. While conceptually neat, and good for proving termination, this kind of clock mechanism can easily become a burden in later proofs. By contrast, if the clock is decremented only on problematic recursive calls, there is less clockrelated overhead in proofs.
Along the second dimension, an environmentlike clock supports a straightforward termination proof, whereas a statelike clock can make termination rather tricky. The difference is akin to reasoning about accumulatorpassing versus directly recursive functions. However, unlike accumulatorpassing style, measuring length versus depth of execution with the clock is a real semantic difference, and certain applications may call for one or the other.
In this paper, we illustrate the four options entailed by the two dimensions above and explain how clocked functions in each style can be defined. Our technical contribution is a simple technique by which the tricky termination proofs arising from a statelike clock are made simple.
One can read this paper as a tutorial on how to neatly define the clocked functions used in our previous paper on functional bigstep semantics [3]. The technique in Section 3.2 has been used to clean up the definitions of the semantics for the CakeML compiler’s 13 intermediate languages (https://cakeml.org).
Running example.
We will use Nipkow and Klein’s IMP language from Concrete Semantics [2] as a running example. The IMP language is a simple Whilelanguage with the following abstract syntax.
Arithmetic and Boolean expressions are given semantics (aval and bval respectively) as would be expected, as functions.
In what follows we define four clocked functional semantics for this language. Section 2 gives definitions with environmentlike clocks, and shows the pros and cons, within this style, of using the clock on every recursive call. Section 3 describes, and contrasts, statelike clocks, and illustrates the tricky termination problems they produce and how to solve them.
2 Environmentlike clocks
Our first evaluation function for commands has a simple clock mechanism: we decrement the clock on every recursive call, and do not return it. The clock, , is a natural number, and the result of evaluation is either None representing timeout or with the final state.
This definition may look neat at first, but observe that most clauses require a nonzero input clock (), which means that case analysis on the clock is required in all proofs. Nevertheless, the termination proof is trivial, since the clock itself is a wellfounded measure. (The termination proof is automatic in the HOL theorem prover.)
The function above can easily be modified to not check the clock for nonrecursive cases, e.g. Skip, but the result is just a less well presented function.
2.1 Problem with decrementeverywhere style
The problem with functions that decrement the clock on every recursive call is that nearly every proof needs to assume a lower limit on the clock or use induction. As a simple example, consider proving that is the same as . The proof of this simple property is made very cumbersome by the eager use of the clock in ev.
To prove a theorem relating the evaluation of the two commands, we require some very specific assumptions about the clock:
These assumptions are a nuisance to deal with in any proof where we want to use the theorem above.
2.2 Minimal use of the clock
It is preferable to decrement the clock only on problematic recursive calls, rather than on every call as above. In our example, the only problematic call is the recursion in the While case. In all other cases, the expression that is being evaluated shrinks. Therefore, we can define the clocked function as follows with a clockcheckanddecrement only in the While case.
With such a definition of the semantics, it is easy to prove that always evaluates the same as . The equality can be stated without assumptions and used directly as a rewrite rule.
Termination proof.
The equations defining evmin terminate because the lexicographic combination of measuring the clock and the size of the evaluated expression is wellfounded. For each recursive call, the clock either stays the same or shrinks; if it stays the same, then the size of the expression shrinks.
3 Statelike clocks
The previous section defined functions where the clock limits the depth of evaluation. In some circumstances, e.g. when defining interpreters, it makes sense to limit the length of evaluation instead. This length is related to the length of an equivalent trace in a smallstep semantics. The difference can be seen most clearly in constructs, like , where order might matter: we can either give clock ticks to each subexpression independently, or we can use the same ticks for both and, say, only evaluate after ’s ticks have been subtracted.
In the following definition, the clock is passed around as state, limiting length rather than depth. Each Someresult contains a storeandclock pair .
3.1 Challenging termination proof
Proving termination for functions that treat the clock as state is not as straightforward as previously. The reason for termination is the same as for evmin above, i.e. the clock decreases when the size of the expression does not. However, the termination proof is more difficult because the clock comes from recursive calls rather than from input arguments.
In the IMP language, this problem shows up in the termination goal for : here one needs to show that evaluation of in the state and clock produced by is smaller than the original input, i.e. and . This goal is problematic because we have yet to define cval. Though technically possible with modern definition packages, it is cumbersome to prove lemmas about cval before its termination proof is complete.
A common trick to avoid such difficult termination proofs is to define a function with redundant safety checks that make the termination proof simple. Once the function is defined, we can manually prove definitionlike equations without the added safety checks. The safety checks also need to be removed from the induction theorems produced for these definitions.
The obvious way to instrument a definition with checks that make the termination proof simple is to add a redundant safety check on the arguments to any problematic recursive call. For example, we could rephrase the problematic Seq case as follows with a redundant check of . We know that this check should always be false, but it is difficult to establish that property in the middle of the termination proof.
Once the function, in this case cval, is defined, one can manually prove the desired defining equation for the Seq case of cval:
Although, this technique of adding redundant safety checks to the incoming clock argument works, our experience with the CakeML compiler suggests that the removal of redundant safety checks on inputs tends to be ad hoc and tedious.
3.2 Simple definition technique: fixclock wrapper
In the course of defining many clocked functions for CakeML, we realised how the safety checks can be expressed in a way that makes them very easy to remove.
The trick is to perform the safety checks on the return from recursive calls (i.e. the production of potentially bad values) instead of at the sites of consumption of potentially bad values. For the running example, we define a new function, fixclock, and wrap it around the producer of potentially bad values. The fixclock wrapper adjusts the clock back to its original value if the clock somehow increased during the recursive call:
The formulation above makes the safety checks (fixclock) very easy to remove. Once the cval function is defined, we prove that the clock never increases
and use this property to prove the following rewrite rule, which we apply to both the defining theorem for cval and its associated induction theorem.
3.3 Decrement everywhere and statelike clock
The final combination of the two options from the introduction is to pick decrementeverywhere and statelike clock. We omit such a definition since it is an obvious rephrasing of the decrementeverywhere function ev from Section 2.
Is this combination useful? We envision that such formulations can be convenient stepping stones when proving equivalence between functional bigstep semantics and smallstep semantics, since a lengthlimiting clock decremented on each call can be made to match the length of the smallstep trace. However, we did not use this combination when proving such an equivalence [3].
4 Summary and related work
This short paper presents different styles of clocked definitions, and provides a simple definition technique for functions that treat the clock as a state component which gets threaded through evaluation.
Clocked functions are used in all major theorem provers, but are often seen as unwanted and the clocks are considered a burden. This paper’s purpose is to continue our recent work on programming language semantics [3] and to show that it is easy to define HOL functions with the clock as a state component.
ACL2 is a prover where clocked functions are encouraged and well supported. The ACL2 code base is full of examples of clocked functions, e.g. Centaur Inc’s industrial Verilog preprocessor^{1}^{1}1https://github.com/acl2/acl2/tree/master/books/centaur/vl/loader/preprocessor, retrieved 20160307. ACL2 even supports tricks that allow execution of clocked functions as if they didn’t have a clock^{2}^{2}2http://www.cs.utexas.edu/users/moore/acl2/vstte2012/acl2dkms/problem5/breadthfirst.lisp, retrieved 20160307.
Acknowledgements.
We thank Jared Davis for a long list of pointers on how clocked functions are used in ACL2. NICTA is funded by the Australian Government through the Department of Communications and the Australian Research Council through the ICT Centre of Excellence Program.
References
 [1] Kaufmann, M., Moore, J.S.: An ACL2 tutorial. In: Mohamed, O.A., Muñoz, C.A., Tahar, S. (eds.) Theorem Proving in Higher Order Logics (TPHOLs). LNCS, Springer (2008)
 [2] Nipkow, T., Klein, G.: Concrete Semantics  With Isabelle/HOL. Springer (2014)
 [3] Owens, S., Myreen, M.O., Kumar, R., Tan, Y.K.: Functional bigstep semantics. In: Thiemann, P. (ed.) European Symposium on Programming (ESOP). LNCS, Springer (2016)
 [4] Reynolds, J.C.: Definitional interpreters for higherorder programming languages. HigherOrder and Symbolic Computation 11(4), 363–397 (1998), http://dx.doi.org/10.1023/A:1010027404223