Reversible programming language

A reversible programming language is designed to bridge the gap between the theoretical models of reversible computing and practical software development. They provide constructs that allow programmers to write code that is guaranteed, by the language's syntax and semantics, to be executable both forwards and backwards deterministically.

Core concepts and design principles

The fundamental goal of a reversible programming language is to support computation that is deterministic in both the forward and backward directions.This is typically achieved by ensuring that every primitive operation and composite statement within the language is locally invertible. Local invertibility means that each basic computational step has a well-defined inverse, and the inverse of a sequence of steps is the sequence of inverse steps performed in reverse order.

Key in the design of many reversible languages is cleanliness or garbage-free computation. This means avoiding the accumulation of auxiliary information (like computation histories or ancilla bits) that is generated solely for the purpose of enabling reversibility but is not part of the desired output. Clean reversible languages aim to perform computations and their reversals using only the specified input and output variables.

To achieve local invertibility and cleanliness, reversible languages typically incorporate several features:

Janus Language

Janus is widely recognized as the first structured, imperative programming language designed explicitly for reversible computation. Originally conceived by Christopher Lutz and Howard Derby at Caltech in the 1980s, it was later rediscovered, formalized, and extended, notably by Tetsuo Yokoyama and Robert Glück.

Design philosophy

Janus embodies the principle of local invertibility. It operates on a global store of variables (no heap allocation or local procedure scope in early versions) and ensures that every statement has a unique inverse.

Syntax and semantics

Implementations and code examples

Several online interpreters for Janus exist. Janus has been used to implement various algorithms reversibly, including computing Fibonacci pairs and simulating RTMs, Fast Fourier Transform (FFT) and graph algorithms, and simulating the Schrödinger wave equation.

The following fibpair procedure in Janus calculates a pair of consecutive Fibonacci numbers. Given an input n, it sets x1 to F(n) and x2 to F(n+1), assuming x1 and x2 are initially 0:

int n x1 x2 // variable declarations

procedure fibpair
    if n=0 then
        x1 += 1
        x2 += 1
    else
        n -= 1
        call fibpair
        x1 += x2
        x1 <=> x2
    fi x1=x2

For calling and uncalling the Fibonacci-pair procedure we use

procedure main_fwd 
    n += 4
    call fibpair

prodecure main_bwd
    x1 += 5
    x2 += 8 
    uncall fibpair 

R Language (MIT)

The R language (distinct from the statistical language R) was developed by Michael P. Frank at MIT in the late 1990s as part of the Reversible Computing project. It is an imperative, compiled language featuring an S-expression (Lisp-like) syntax. A key aspect of R's design was its close integration with hardware development; it was designed to target the Pendulum reversible instruction set architecture (PISA), developed concurrently at MIT for an adiabatic CMOS processor.

Syntax and semantics

Pendulum/PISA target architecture

The R language was designed with a specific hardware target: the Pendulum processor.

Code examples

The following PISA assembly code simulates a free-falling object. It includes a main section to call and "uncall" (reverse) a subroutine named Fall, which contains the core simulation logic.

Call Fall:
10: ADDI h 1000
11: ADDI tend 5
12: BRA 16       ; call

Uncall Fall:
18: ADDI v 40
19: ADDI t 4
20: ADDI tend 4
21: RBRA 7       ; uncall

Subroutine Fall:
27: BRA 9
28: SWAPBR rtn   ; br <=> rtn
29: NEG rtn      ; rtn=-rtn
30: BGTZ t 5     ; t > 0?
31: ADDI v 10    ; v += 10
32: ADDI h 5     ; h += 5
33: SUB h v      ; h -= v
34: ADDI t 1     ; t += 1
35: BNE t tend -5 ; t != tend?
36: BRA -9

The R program defines global variables for height (h), end time (tend), velocity (v), and current time (t). The core logic is encapsulated in the Fall subroutine, which simulates the object's motion. The main routine initializes parameters, calls Fall to simulate forward motion, then modifies parameters and calls Fall in reverse (rcall Fall), mirroring the structure of the PISA example's "Call Fall" and "Uncall Fall" sections.

A key feature of R's if statement is that the conditional expression must evaluate to the same truth value before and after the execution of its then block. The Fall subroutine in PISA (lines 30-36) effectively has a loop that runs as long as t is not equal to tend, but this loop is only entered if an initial condition (implied by BGTZ t 5 meaning skip if t > 0, so run if t <= 0) is met. To translate this faithfully and handle R's if semantics, the R code for Fall uses a let binding to capture the state of the initial condition (t <= 0) before the loop. The if then operates on this captured, unchanging boolean value. The loop itself is represented by R's for construct, iterating tend times, which corresponds to the PISA loop structure (BNE t tend -5).

;; Global variable declarations
(defword h)
(defword tend)
(defword v)
(defword t)

;; Subroutine to simulate falling
;; Corresponds to PISA "Subroutine Fall" (lines 27-36)
(defsub Fall ()
  ;; The PISA code at line 30 (BGTZ t 5) skips the main simulation
  ;; if t > 0. This means the simulation loop runs if t <= 0.
  ;; We use 'let' to capture this condition, and 'if' operates on the captured value.
  (let ((do_run <- (<= t 0))) ;; Capture condition: t must be <= 0 to run.
                             ;; 'do_run' is a local temporary.
    (if do_run ;; If the condition was true (t was <= 0 initially)
        then
          (progn ;; Execute the simulation loop
            ;; The PISA loop (lines 31-35) effectively iterates 'tend' times,
            ;; incrementing 't' each time, starting from its initial value (which is 0
            ;; when 'do_run' is true). The BNE t tend -5 continues as long as t != tend.
            ;; R's 'for' loop is a suitable high-level representation.
            ;; We assume 'tend' represents the number of iterations *from t=0*.
            (for i = 1 to tend ;; Loop 'tend' times
              (progn
                (+= v 10)      ;; PISA: ADDI v 10
                (+= h 5)       ;; PISA: ADDI h 5
                (-= h v)       ;; PISA: SUB h v
                (++ t)         ;; PISA: ADDI t 1
              )
            )
          )
        ;; else (if 'do_run' is false, meaning t was > 0 initially), do nothing,
        ;; mimicking the PISA BGTZ t 5 branch.
    )
    ;; Upon exiting 'let', 'do_run' is restored/cleared, satisfying R's rules
    ;; for 'let' and ensuring the 'if do_run' invariant holds for 'do_run'.
  )
)

;; Main program routine
(defmain ()
  ;; Initialize global variables to 0.
  ;; While PISA doesn't show explicit zeroing, R programs often start clean.
  ;; These are reversible assignments.
  (-= h h)         ;; h = 0
  (-= tend tend)   ;; tend = 0
  (-= v v)         ;; v = 0
  (-= t t)         ;; t = 0

  ;; --- "Call Fall" section from PISA ---
  ;; Set initial parameters for forward simulation
  (+= h 1000)     ; PISA: ADDI h 1000
  (+= tend 5)     ; PISA: ADDI tend 5
                  ; t and v are 0 from initialization.

  ;; Call the Fall subroutine to simulate forward motion
  ;; PISA: BRA 16 (relative branch to call setup, actual call is implicit)
  (call Fall)

  ;; State after (call Fall) with h_initial=1000, tend_initial=5, t_initial=0, v_initial=0:
  ;; Inside Fall: do_run = (<= 0 0) = true. Loop runs 5 times.
  ;; t becomes 0 + 5 = 5.
  ;; v becomes 0 + 5*10 = 50.
  ;; h becomes 1000 + 5*5 - (10+20+30+40+50) = 1000 + 25 - 150 = 875.
  ;; tend remains 5 (Fall does not modify the 'tend' global it uses for loop count).

  ;; (printword h) (printword v) (printword t) (printword tend) (println)
  ;; Expected: h=875, v=50, t=5, tend=5

  ;; --- "Uncall Fall" section from PISA ---
  ;; The PISA code modifies v, t, and tend before the reverse call.
  ;; Current state from R perspective: h=875, v=50, t=5, tend=5.
  (+= v 40)    ; PISA: ADDI v 40. v = 50 + 40 = 90
  (+= t 4)     ; PISA: ADDI t 4.  t = 5 + 4 = 9
  (+= tend 4)  ; PISA: ADDI tend 4. global 'tend' becomes 5 + 4 = 9
  ;; h remains 875.

  ;; Perform the reverse call to Fall
  ;; PISA: RBRA 7 (relative branch to uncall setup)
  (rcall Fall)

  ;; Behavior of (rcall Fall):
  ;; 'rcall Fall' executes the inverse of 'Fall'.
  ;; Inside 'Fall' (conceptually, during rcall):
  ;;   The (let ((do_run <- (<= t 0))) ...) block is reversed.
  ;;   The (<= t 0) condition is evaluated with current t=9. (<= 9 0) is false.
  ;;   So, 'do_run' (if we consider its "uncomputed" state) would correspond to 'false'.
  ;;   The 'if do_run' block's 'then' part (the loop) was not executed in the forward
  ;;   direction corresponding to this 'false' condition. Thus, its reverse also does nothing.
  ;; The net effect, matching PISA's BGTZ t 5, is that if t > 0, the main body of Fall
  ;; (and its reverse) is skipped.
  ;; Final state after (rcall Fall): h=875, v=90, t=9, tend=9.
  ;; This is because 'Fall' was effectively a no-op due to t=9 > 0.
  ;; The 'rcall' correctly reverses this no-op.

  ;; (printword h) (printword v) (printword t) (printword tend) (println)
  ;; Expected: h=875, v=90, t=9, tend=9
)

Overview of other reversible languages

Research has continued beyond Janus and R, exploring different paradigms and features:

Comparison of reversible programming languages

The following table summarizes key characteristics of some prominent reversible programming languages discussed above:

Comparison of Reversible Programming Languages
LanguageJanusR (MIT)EelROOPL
Paradigm Imperative, Procedural Imperative, Compiled Imperative, Partially Reversible Imperative, Object-Oriented
Reversibility Model Full (Locally Invertible) Full (Locally Invertible) Partial (Allows Irreversible Ops) Full (Locally Invertible)
Key Control Flow if..fi (test+assert),
from..until (assert+test)
(if..) (invariant),
(for..) (invariant)
Protected/General if/loop,
Log/Unroll blocks
Reversible if, loop (similar to Janus),
Method Calls
Data Types Integers, Arrays, Stacks Integers, Arrays Integers, Arrays, Log Stack Integers, Arrays, User-defined Classes (Objects), Inheritance
Inversion Mechanism uncall statement,
Local Inversion
rcall statement,
Local Inversion
Unroll statement
(uses Log Stack)
uncall (for methods),
Local Inversion
Target/Compiler Interpreters,
Partial Evaluator,
Self-Interpreter
PISA (Pendulum ISA) Compiler Compiler & Interpreter (Java-based),
Energy Simulation
PISA Compiler
(Garbage-free)

This comparison highlights the different design choices made. Janus and R enforce full reversibility through language constructs, differing primarily in syntax (C-like vs S-expression) and target (interpretation vs PISA compilation). Eel introduces partial reversibility, allowing irreversible operations at the cost of using a log stack for reversal information and incurring a conceptual energy cost, aiming for greater flexibility. ROOPL extends the fully reversible imperative model with object-oriented features, demonstrating the applicability of higher-level abstractions.

References

  1. 1 2 Glück, Robert; Yokoyama, Tetsuo (2023). "Reversible computing from a programming language perspective". Theoretical Computer Science. 953 113429. doi:10.1016/j.tcs.2022.06.010.
  2. 1 2 Thomsen, Michael Kirkedal (2023). "Design of Reversible Computing Systems; Large Logic, Languages, and Circuits". arXiv:2309.11832 [cs.PL].
  3. ↑ Thomsen, Michael Kirkedal; Axelsen, Holger Bock; Glück, Robert (2011). "A Reversible Processor Architecture and Its Reversible Logic Design". In De Vos, Alexis; Wille, Robert (eds.). Reversible Computation - Third International Workshop, RC 2011, Gent, Belgium, July 4–5, 2011. Revised Papers. Lecture Notes in Computer Science. Vol. 7165. Springer. pp. 30–42. doi:10.1007/978-3-642-29517-1_3. Reversible programming language at DBLP Bibliography Server.
  4. 1 2 3 4 5 6 7 8 9 10 11 Yokoyama, Tetsuo (2010). "Reversible Computation and Reversible Programming Languages". In Ulidowski, Irek (ed.). Proceedings of the Workshop on Reversible Computation, RC@ETAPS 2009, York, UK, March 22, 2009. Electronic Notes in Theoretical Computer Science. Vol. 253. Elsevier. pp. 71–81. doi:10.1016/J.ENTCS.2010.02.007. Reversible programming language at DBLP Bibliography Server.
  5. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 Choudhury, Vikraman (April 2018). "Reversible Programming Languages" (PDF).
  6. 1 2 3 4 Palazzo, Matteo; Roversi, Luca (2025). "Reversible Computation with Stacks and "Reversible Management of Failures"". arXiv:2501.05259 [cs.PL].
  7. 1 2 Haulund, Tue; Mogensen, Torben Ægidius; Glück, Robert (2017). "Implementing Reversible Object-Oriented Language Features on Reversible Machines". In Phillips, Iain; Rahaman, Hafizur (eds.). Reversible Computation - 9th International Conference, RC 2017, Kolkata, India, July 6–7, 2017, Proceedings. Lecture Notes in Computer Science. Vol. 10301. Springer. pp. 66–73. doi:10.1007/978-3-319-59936-6_5. Reversible programming language at DBLP Bibliography Server.
  8. ↑ "Janus: a reversible imperative programming language". University of Copenhagen (DIKU). Retrieved April 9, 2025.
  9. ↑ "Reversible Algorithms" (PDF). Computing Research Association. Retrieved April 9, 2025.
  10. ↑ Yokoyama, Tetsuo; Glück, Robert (2007). "A reversible programming language and its invertible self-interpreter". In Ramalingam, G.; Visser, Eelco (eds.). Proceedings of the 2007 ACM SIGPLAN Workshop on Partial Evaluation and Semantics-based Program Manipulation, 2007, Nice, France, January 15–16, 2007. ACM. pp. 144–153. doi:10.1145/1244381.1244404. Reversible programming language at DBLP Bibliography Server.
  11. ↑ Frank, Michael P. (1999). Reversibility for efficient computing (PhD thesis). Cambridge, MA, USA: Massachusetts Institute of Technology. hdl:1721.1/9464. Reversible programming language at DBLP Bibliography Server.
  12. 1 2 Vieri, Carlin (1999). Reversible computer engineering and architecture (PhD thesis). Cambridge, MA, USA: Massachusetts Institute of Technology. hdl:1721.1/80144. Reversible programming language at DBLP Bibliography Server.
  13. ↑ Axelsen, Holger Bock; Glück, Robert; Yokoyama, Tetsuo (2007). "Reversible Machine Code and Its Abstract Processor Architecture". In Diekert, Volker; Volkov, Mikhail V.; Voronkov, Andrei (eds.). Computer Science - Theory and Applications, Second International Symposium on Computer Science in Russia, CSR 2007, Ekaterinburg, Russia, September 3–7, 2007, Proceedings. Lecture Notes in Computer Science. Vol. 4649. Springer. pp. 56–69. doi:10.1007/978-3-540-74510-5_9. Reversible programming language at DBLP Bibliography Server.
  14. ↑ Tyagi, Nirvan; Lynch, Jayson; Demaine, Erik D. (2016). "Toward an Energy Efficient Language and Compiler for (Partially) Reversible Algorithms". arXiv:1605.08475 [cs.PL].
  15. ↑ "Reversible Computation" (PDF). Classroom Presentation at Appalachian State University. Retrieved April 9, 2025.
  16. ↑ Kaarsgaard, Robin; Rennela, Mathys (2021). "Join inverse rig categories for reversible functional programming, and beyond". In Sokolova, Ana (ed.). Proceedings 37th Conference on Mathematical Foundations of Programming Semantics, MFPS 2021, Hybrid: Salzburg, Austria and Online, 30th August - 2nd September, 2021. EPTCS. Vol. 351. pp. 152–167. arXiv:2105.09929. doi:10.4204/EPTCS.351.10. Reversible programming language at DBLP Bibliography Server.
  17. 1 2 Haulund, Tue (2017). "Design and Implementation of a Reversible Object-Oriented Programming Language". arXiv:1707.07845 [cs.PL].
  18. ↑ Glück, Robert; Kaarsgaard, Robin (2018). "A Categorical Foundation for Structured Reversible Flowchart Languages". In Staton, Sam (ed.). Proceedings of the Thirty-Fourth Conference on the Mathematical Foundations of Programming Semantics, MFPS 2018, Dalhousie University, Halifax, Canada, June 6–9, 2018. Electronic Notes in Theoretical Computer Science. Vol. 341. Elsevier. pp. 155–171. doi:10.1016/J.ENTCS.2018.03.021. Reversible programming language at DBLP Bibliography Server.
  19. 1 2 3 Matsuda, Kazutaka; Wang, Meng (2024). "Sparcl: A language for partially invertible computation". Journal of Functional Programming. 34 e2. doi:10.1017/S0956796823000126. Reversible programming language at DBLP Bibliography Server.
  20. ↑ Grandi, Claudio; Moshiri, Dariush; Roversi, Luca (2019). "Introducing Yet Another Reversible Language". arXiv:1902.05369 [cs.PL].
  21. ↑ "Hermes: A Language for Lightweight Encryption" (PDF). Reversible Computation (RC) Lecture. Retrieved April 9, 2025.
  22. ↑ Amy, Matthew; Roetteler, Martin; Svore, Krysta M. (2016). "Verified Compilation of Space-Efficient Reversible Circuits". Computer Aided Verification. Lecture Notes in Computer Science. Vol. 10427. pp. 3–21. arXiv:1603.01635. doi:10.1007/978-3-319-63390-9_1. ISBN 978-3-319-63389-3.
  23. ↑ Lanese, Ivan; Schultz, Ulrik Pagh; Ulidowski, Irek (2022). "Reversible Computing in Debugging of Erlang Programs". IT Professional. 24 (1): 74–80. Bibcode:2022ITPro..24a..74L. doi:10.1109/MITP.2021.3117920. hdl:11585/884503. Reversible programming language at DBLP Bibliography Server.