[Question]
  [
## Background
[**Conway chained arrow notation**](https://en.wikipedia.org/wiki/Conway_chained_arrow_notation) is a notation to express very large numbers. It consists of zero or more positive integers separated by right arrows, e.g. \$2 \to 3 \to 4 \to 5 \to 6 \$.
Assuming \$p, q, a\_1, \dots, a\_n\$ are positive integers and \$X\$ is an abbreviation for a nonempty chain \$a\_1 \to a\_2 \to \dots \to a\_n\$, the rules for evaluating such a notation are as follows:
$$
\begin{align}
(\text{empty chain}) &= 1 \\
(p) &= p \\
p \to q &= p^q \\
X \to 1 &= X \\
X \to 1 \to p &= X \\
X \to (p+1)\to (q+1) &= X \to (X \to p\to (q+1))\to q
\end{align}
$$
A length-3 chain has an equivalent up-arrow notation: \$ p \to q \to r = p \uparrow^r q\$.
Note that the arrow notation cannot be treated as some kind of binary operator:
$$
\begin{align}
2 \to 3 \to 2 &= 16 \\
2 \to (3 \to 2) &= 512 \\
(2 \to 3) \to 2 &= 64
\end{align}
$$
More examples can be found on the Wikipedia page linked above.
## Task
Given a (possibly empty) list of positive integers, interpret it as Conway chained arrow notation and evaluate it into a single number.
It is OK if your program gives wrong answers for large values due to the limits (bounds and/or precision) of your language's number type, as long as the underlying algorithm is correct.
Standard [code-golf](/questions/tagged/code-golf "show questions tagged 'code-golf'") rules apply. The shortest code in bytes wins.
## Test cases
```
Input => Output
[] => 1
[1] => 1
[99999999] => 99999999
[5, 5] => 3125
[4, 8] => 65536
[1, 2, 4] => 1
[2, 2, 4] => 4
[2, 3, 2] => 16
[2, 4, 2] => 65536
[4, 3, 2] => 4^256 = 1.34e154
[2, 2, 3, 2] => 4
```
  
[Answer]
# [Haskell](https://www.haskell.org/), ~~75~~ ~~68~~ 63 bytes
```
f(q:p:x)|p^q>p,x>[]=f$q-1:f(q:p-1:x):x|1<2=f$p^q:x
f[x]=x
f _=1
```
[Try it online!](https://tio.run/##PYpNCsMgEEb3OUUWWUSwgtZAKzUXEVukVRJqrPkpdZG72yGkHZjvzbyZzsxP630eTB9kHxY7mftSvYPvg53JYGJZz93rQxyZrHkgsvns6lFEkdAar2MbcWqVlq4aD1RsF2BCIq30wkDDj0iFU0lLQHmTNGelC0Whz3vB2OAG8oQ5JMcM050MyPBxJ//v/OfBfAE "Haskell – Try It Online")
Takes input as a list in reversed order, since in Haskell it's easier to deal with the beginning of a list than with the end of it.
Now shorter and uglier!
Rules 3,4,5,6 are combined in the first line. The most important trick is realizing that `p^q==p` *iff* `p==1||q==1` (where `^` is exponentiation and we're dealing with strictly positive numbers). We check the conditions to apply rule 6 (p and q greater than 1, at least three elements in the input) and if they are valid we do so recursively. If these conditions fail we know that either there is a 1 in the first two elements or there are just two elements in total: for both of this cases `f(p^q:x)` can solve the task.
The last two lines deal with inputs with less than two elements. They could be rewritten as a single line `f x=last$1:x` but the score would not change.
---
Below the original solution, no golfing tricks, just beautiful Haskell code:
```
f[]=1
f[p]=p
f[q,p]=p^q
f(1:x)=f x
f(_:1:x)=f x
f(q:p:x)=f$q-1:f(q:p-1:x):x
```
[Try it online!](https://tio.run/##TYnRCoMgFIbvfYouuigwwWawCT6JuCGbkqxMs7He3p2ijR045/u///Q6Pc0w5FE7L5xfzKzvS/nyg/MmkVGHokr99CaWzEY/arL32UolKLIyKBEAEW/hGpGtKF9rYYsV4o3/SeRhlzI2lO/abF@@5iwVkhT2cgzEDndwz5jBZbjF9GALbPHpIPs5@/bQfAA "Haskell – Try It Online")
[Answer]
# [dc](https://www.gnu.org/software/bc/manual/dc-1.05/html_mono/dc.html), ~~112~~ 107 bytes
```
?[dz0r^+q]sZ[rd3Rd_3R^q]sE[ilfx1rq]sA[iSplfx1rLprq]sB[z2>Zz2=Ed1=Ard1=B1-rlfx3RSpr1-lfx_3Rri1+Lp1+r3R]dsfxp
```
[Try it online!](https://tio.run/##HYyxCoAwDAV/xb0IpnVVUXBzqptBHQxCwSHGpfTna3R53MHx6Mi5Q0qVbOZenwWFnKfd@U1txHCdEUSxxzDzLxN/PmCy7ZJsMxI0vegMUIoGzs8sUCrpiQQwE4MR51d6zsg526Iu7As "dc – Try It Online")
[Or verify all the test cases.](https://tio.run/##RY9Pa4NAEMXv@yke0puYdl0DLURLAvYUKJhbliRYd60LVrdjoUH63e0kETKHH@89hvnzUQ7NVJU/yOCp/6Tya2EqrFZB/v4WTK/ajE90DL8Pw16TUYU5qeLILteurc@SWK612/mr2fqL3@gxzvZjnOZGpmtibGRE3KCKnScZseIh5GS49TIkVRzMUJ/9xAuF@G1ca0G2NGhdZwVgegZgq6ZH1CF4uORIMwT3/BYG@APfHtVYPN5/uY7o7CSkeJlLLLEUCZ6FRIxExDMVYmbCTGZ9y/4B)
The input is on stdin (a line with space-separated numbers), and the output is on stdout.
---
**How it works:**
dc is a stack-based language. The recursive macro `f` does the Conway chained-arrow calculation, but the stack is treated differently from what you usually see:
1. The input to `f` is the **entire stack** when the call is made. (So `f` essentially takes a variable number of arguments.)
2. If the stack at the time of call is
$$a\_1 \; a\_2 \; \dots \; a\_n$$
(with the top of the stack on the right), `f` will compute the value of
$$a\_1 \to a\_2 \to \dots \to a\_n$$
and push it on top of the stack, **but it leaves the arguments on the stack also.**
So `f` turns the stack
$$a\_1 \; a\_2 \; \dots \; a\_n$$
into
$$a\_1 \; a\_2 \; \dots \; a\_n \; [\text{ArrowValue}(a\_1 \; a\_2 \; \dots \; a\_n)]$$
where I've written \$\;[\text{ArrowValue}(a\_1 \; a\_2 \; \dots \; a\_n)]\;\$ for the value of \$\;a\_1 \to a\_2 \to \dots \to a\_n.\$
There are several auxiliary macros as well. All the usual complex control structures other languages have (loops, conditionals, functions) are implemented in dc using macros.
---
Note that dc produces a few error messages or warnings due to the golfing tricks used, but they don't interrupt program execution, and the messages are just written to stderr. Examples of these: duplicating when there's nothing on the stack, adding when there's only one item on the stack, or setting the input base to an illegal value.
The code also makes use of the fact that we can distinguish positive numbers from \$0\$ by whether the power \$0^x\$ is \$0\$ or \$1.\$
---
Here's a detailed summary of the program's operation, updated for the revised, shorter answer.
```
?  Read a line of space-separated numbers, written in the usual
   Conway chained-arrow order, pushing them onto the stack in turn.
   (The chained arrow sequence will start at the bottom of the stack,
   since that's pushed first, and will end at the top of the stack, since
   that's pushed last.)
        MACRO Z
Macro Z will only be called when the stack either is empty or
has just one item p on it.  We'll analyze both possibilities.
[   Start macro.
         Stack: Empty   or   p
 d    Duplicate.
         Stack: Empty   or   p p
 z    Push the size of the stack.
         Stack: 0       or   p p 2
 0    Push 0.
         Stack: 0 0     or   p p 2 0
 r
      Swap.
         Stack: 0 0     or   p p 0 2
 ^    Exponentiate.
         Stack: 1       or   p p 0
 +    Add top 2 items if they exist.
         Stack: 1       or   p p
 q    Exit this macro and the macro which called it.
]sZ End macro and name it Z.
Summary of Z:
      Turn: Empty stack
      Into: 1
and
      Turn: p
      into: p p
        MACRO E
[       Start a macro.  Assume the stack is: ... p q (top on right).
 r        Swap.                         Stack: ... q p
 d        Duplicate.                    Stack: ... q p p
 3R       Rotate left the top 3 items.  Stack: ... p p q
 d        Duplicate.                    Stack: ... p p q q
 _3R      Rotate right the top 3 items. Stack: ... p q p q
 ^        Exponentiate.                 Stack: ... p  q p**q
 q        Exit this macro and the macro which called it.
]sE     End the macro and name it E.
Summary of E:
  Turn: ... p q
  into: ... p q p**q
        MACRO A
[       Start a macro.  Assume the stack is:   ... p (top on right).
 i        Discard the top of stack.  (Actually make it the new input radix just because dc wants a place to put it.)
                                        Stack: ...
 lfx      Call f recursively.           Stack: ... ArrowValue(...)
 1        Push 1.                       Stack: ... ArrowValue(...) 1
 r        Swap.                         Stack: ... 1 ArrowValue(...)
 q        Exit this macro and the macro which called it.
]sA     End the macro and name it A.
Summary of A:
  Turn: ... p
  into: ... 1 ArrowValue(...)
        MACRO B
[       Start a macro.  Assume the stack is:    ... p q (top on right).
 i        Discard top of stack (by storing it as the input radix).
                                         Stack: ... p 
 Sp       Pop p off the stack and
          push it onto stack p.          Stack: ...
 lfx      Call f recursively.            Stack: ... ArrowValue(...)
 1        Push 1.                        Stack: ... ArrowValue(...) 1
 r        Swap.                         Stack: ... 1 ArrowValue(...)
 Lp       Pop the old value of p from stack p.
                                        Stack: ... 1 ArrowValue(...) p
 r        Swap                          Stack: ... 1 p ArrowValue(...)
 q        Exit this macro and the macro which called it.
]sB     End the macro and name it B.
Summary of B:
  Turn: ... p q
  into: ... 1 p ArrowValue(...)
        MACRO f
[       Start a macro.
 z      Push the stack size.
 2>     If the stack size was 0 or 1,
 O        then call macro Z and return from f.
          In this case, we've turned ...
                                into ... 1
                     or we've turned ... p 
                                into ... p p
 z2=E   If the stack size was 2,
          then call macro E and return from f.
          In this case, we've turned ... p q
                                into ... p q p**q
        If we get here, the stack size is at least 3.
 d1=A   If the item at the top of the stack == 1,
          then call macro A and return from f.
          In this case, we've turned ... 1
                                into ... 1 ArrowValue(...)
        If we get here, the stack size is at least 3 and the item at the top of the stack isn't 1.
                              Stack: ... p q r
          where r != 1.
 r      Swap.                 Stack: ... p r q      
 d1=B   If the item at the top of the stack == 1,
          then call macro B and return from f.
        In this case, we've turned   ... p 1 r
                              into   ... p 1 r ArrowValue(... p)
        If we get here, the stack size is at least 3, neither of the items at the top of the stack is 1,
        and we've already gone from
                              Stack: ... p q r
                           to Stack: ... p r q               
 1-     Subtract 1.           Stack: ... p r q-1
 r      Swap.                 Stack: ... p q-1 r
 lfx    Call f recursively.   Stack: ... p q-1 r [ArrowValue(... p q-1 r)]
 3R     Rotate left the top 3 items on the stack.
                              Stack: ... p r [ArrowValue(... p q-1 r)] q-1
 Sp     Pop q-1 off the stack and push it onto stack p.
                              Stack: ... p r [ArrowValue(... p q-1 r)] 
 r      Swap.                 Stack: ... p [ArrowValue(... p q-1 r)] r
 1-     Subtract 1.           Stack: ... p [ArrowValue(... p q-1 r)] r-1
 lfx    Call f recursively.   Stack: ... p  [ArrowValue(... p q-1 r)]  r-1  [ArrowValue(... p ArrowValue(... p q-1 r) r-1)]
 _3R    Rotate right the top 3 items on the stack.
                              Stack: ... p  [ArrowValue(... p ArrowValue(... p q-1 r) r-1)]  [ArrowValue(... p q-1 r)]  r-1
 r      Swap:                 Stack: ... p  [ArrowValue(... p ArrowValue(... p q-1 r) r-1)]  r-1  [ArrowValue(... p q-1 r)]
 i      Discard the top item. Stack: ... p  [ArrowValue(... p ArrowValue(... p q-1 r) r-1)]  r-1
 1+     Add 1                 Stack: ... p  [ArrowValue(... p ArrowValue(... p q-1 r) r-1)]  r
 Lp     Load the old value of q-1 from stack p.
                              Stack: ... p  [ArrowValue(... p ArrowValue(... p q-1 r) r-1)]  r  q-1
 1+     Add 1.                Stack: ... p  [ArrowValue(... p ArrowValue(... p q-1 r) r-1)]  r  q
 r      Swap.                 Stack: ... p  [ArrowValue(... p ArrowValue(... p q-1 r) r-1)]  q  r
 3R     Rotate left the top 3 items on the stack.
                              Stack: ... p  q  r  [ArrowValue(... p ArrowValue(... p q-1 r) r-1)]
]       End the macro,
dsf       save it on the stack, and name it f.
Summary of f:
  Turn: ...
  into: ... ArrowValue(...)
x       Execute f.
p       Print the desired value, which is now at the top of the stack.
```
[Answer]
# [C (gcc)](https://gcc.gnu.org/) -m32 -lm, ~~159~~ ~~150~~ ~~137~~ 136 bytes
```
f(a,b,u,t)int*a,*b;{t=a-b?b-a-1?*a-1?b-a-2?a[1]-1?t=a[1]--,a[1]=f(a,b),--*a,u=f(a,b),++*a,a[1]=t,u:f(a+2,b):pow(a[1],*a):f(a+1,b):*a:1;}
```
[Try the test cases online!](https://tio.run/##dc/daoMwGAbg817FR2Gg5stB1MKmSGnr/y10PYgWi9A/Nt0OSm99WaJrMbAIMXnf5CGkpoe6FqKxOFbYY2e3587h6FThrYs4rZYV5ZQtHfVTS3fJt2wng9xVC4pqigZvI6XS9o9EiEzDdod9IEviyjq4Xr4t1aLD7aFlqnV4wMK7kNfDibdn6@vS7u0ZwE0OUG0pSajC9UPGxpq/7N/Pc4TGKhFK2w5nj5Or7Q4iuLH7/8dXCCvCpmA9gre/z@DWCGvdbUa3QFgYzAZhQ9ypiUfziuAbTIwQ6yYZjY/gIpielSAkxJuydMpcA0sRUp1lI5PGM7MMIdNZ/mS@meUIuc4K7TazLBAK4isJcBc/dXPkh09BT54r6PH0Cw "C (gcc) – Try It Online") (except for `[4, 3, 2]`, which overflows).
*9 bytes off thanks to ceilingcat!*
*And saved 1 more byte thanks to ceilingcat too.*
---
Input is taken as an array of ints in reverse order, and is passed as a [pointer to the beginning and a pointer to (the location immediately after) the end](https://codegolf.meta.stackexchange.com/a/14972/59825).
---
**The following applies to the previous version of the program. The current version uses exponentiation from the C math library. The compilation flag `-m32` is now used so that the usual `#include <math.h>` line can be omitted.**
C doesn't have exponentiation built in, so the previous version handled that by changing the 3rd and 4th rules of the recursive definition from
$$
\begin{align}
p \to q &= p^q \\
X \to 1 &= X \\
\end{align}
$$
to
$$
\begin{align}
\quad\quad\quad\quad\quad X \to 1 &= X \\
 p \to q &= (p \to q-1)\*p \\
\end{align}
$$
[Answer]
# [APL (Dyalog Unicode)](https://www.dyalog.com/), ~~57~~ ~~49~~ ~~48~~ 46 [bytes](https://github.com/abrudz/SBCS)
*Saved 8 bytes thanks to @[Bubbler](https://codegolf.stackexchange.com/users/78410/bubbler)!*
```
{3>≢w←⍵↓⍨⊃⍸1≠⍵:*/⌽w⋄(∇(⊃w-1),,∘(2↓w))⍣(1⊃w)⊢1}
```
[Try it online!](https://tio.run/##SyzI0U2pTMzJT///qG@qp/@jtgkG/9OAZLWx3aPOReVA1qPerY/aJj/qXfGoq/lR7w7DR50LgEJWWvqPevaWP@pu0XjU0a4BlCvXNdTU0XnUMUPDCKi@XFPzUe9iDUOQhOajrkWGtSALgMalKTzqXcMFYxvDWaYKpnC2kYKxghEKz4TrUe9cBZiICVDM6D8A "APL (Dyalog Unicode) – Try It Online")
A monadic function that must be given the input in reverse. Now also requires zero-indexing. This is slightly different from Conway's definition, but I *think* it's equivalent. If anyone can find a more math-y proof, that'd be great.
This is how Conway described his chained arrow notation:
> 
> Our own "chained arrow" notation names some even larger numbers. In this, a^^...^^b (with c arrows) is called a->b->c.
> 
> 
> a->b-> ... ->x->y-> 1 is another name for a->b-> ... ->x->y
> 
> 
> and a ... x->y->(z+1) is defined to be
> 
> 
> a ... x if y = 1,
> 
> 
> a ... x->(a...x)->z if y = 2,
> 
> 
> a ... x->(a...x->(a...x)->z)->z if y = 3
> 
> 
> and so on.
> 
> 
> 
No one likes ones (and \$X\to 1\$ evaluates to \$X\$), so we first remove leading ones using `⍵↓⍨⊃⍸1≠⍵`. `⊃⍸1≠⍵` is the first (`⊃`) index where (`⍸`) there isn't a 1 (`1≠⍵`), and we drop (`↓`) until that index. The result of that is assigned to `w` to reuse.
We can replace the first rule from here with the first three rules from the question. So if `w` has 0, 1, or 2 elements (`3>≢w`), we can fold over it with exponentiation (`*/⌽w`), because according to APL's rules, `*/x` is `x` and `*/⍬` (`⍬` is an empty set) is 1. We do have to reverse (`⌽`) `w` again, though, because it was reversed in the first place.
The second part of the function takes care of cases when `w` is in the form \$X \to y \to (z+1)\$. It's essentially \$y\$ applications of the function \$\lambda a. X \to a \to z\$, starting, with 1.
If \$y\$ and \$z\$ are both 1, then this becomes \$X \to 1 \to 1\$. Next iteration, `w` will be just \$X\$. If only \$y\$ is 1, then it becomes \$X \to 1 \to z\$. After that, it becomes \$X \to 1 \to (z-1)\$, then \$X \to 1 \to (z-2)\$, and so on until it reaches \$X \to 1 \to 1\$, which gives us \$X\$. So this satisfies the fifth rule in the question (\$X \to 1 \to p = X\$).
If \$y\$ is greater than 1, this becomes
$$
X \to (X \to (... (X \to (X \to (1) \to z) \to z) ...) \to z) \to z\\
= X \to (X \to (... (X \to (X) \to z) ...) \to z) \text{ (by question's 5th rule)}
$$
The second is Conway's definition (there are \$y\$ copies of \$X\$ and \$y-1\$ copies of \$z\$). In the first, there are \$y\$ copies of both \$X\$ and \$z\$.
[Answer]
# [J](http://jsoftware.com/), 90 79 75 bytes
```
(1:`]`(^~/)`(2&}.$:@,~<:@{.,[:$:]-2=#\)@.(3<.#))`($:@}.~1+i.&1)@.(1 e.2&{.)
```
[Try it online!](https://tio.run/##ZZDLSsRAEEX3/RWFGZJuzJRWP4IW0xAUXIkLt5oxIJlRN35AnPx67MfEZ0Mt7qnLKei3@QSrPXiGCmo4Bw6zRri@v72ZJXHf9XI7nale6vKAK27racPtiPUDr7hba188qhal2WChQikUDjjR6SuWFDnBgLocUc1K3F0h6CyMPimfFmU0cj1lZQhFtPZhn3RdEvnQHpcTnNHI6uu4EDuPsG8/UIjh@eUdCDzsoKp@Jsrh8vgSW0JeGdIuYQcuk8Y50yRk4eKXDDTYDGwC@htQcyQG9F9NKIXJNEpDBeLf2K12sUFo7EDunzqq5k8 "J – Try It Online")
Takes input in reverse order.
I suspect there's room for more golfing yet. I may return to it tomorrow.
[Answer]
# Rust, 161 bytes
```
fn f(s:&[u32])->u32{match
s{[]=>1,[x]=>*x,[p,q]=>p.pow(*q),[x@..,1]=>f(x),[x@..,1,_]=>f(x),[x@..,p,q]=>f(&[x,&[f(&[x,&[p-1],&[*q]].concat())],&[q-1]].concat())}}
```
Uses Rusts pattern matching. The last case is a little verbose, because there's no spread operator.
[Try it](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&code=fn%20f(s%3A%20%26%5Bu32%5D)%20-%3E%20u32%20%7B%0A%20%20%20%20match%20s%20%7B%0A%20%20%20%20%20%20%20%20%5B%5D%3D%3E1%2C%0A%20%20%20%20%20%20%20%20%5Bx%5D%3D%3E*x%2C%0A%20%20%20%20%20%20%20%20%5Bp%2Cq%5D%3D%3Ep.pow(*q)%2C%0A%20%20%20%20%20%20%20%20%5Bx%40..%2C1%5D%3D%3Ef(x)%2C%0A%20%20%20%20%20%20%20%20%5Bx%40..%2C1%2C_%5D%3D%3Ef(x)%2C%0A%20%20%20%20%20%20%20%20%5Bx%40..%2Cp%2Cq%5D%3D%3Ef(%26%5Bx%2C%20%26%5Bf(%26%5Bx%2C%26%5Bp-1%2C*q%5D%5D.concat())%5D%2C%20%26%5Bq-1%5D%5D.concat())%0A%20%20%20%20%7D%0A%7D%0Afn%20main()%20%7B%0A%20%20%20%20assert_eq!(1%2C%20f(%26%5B%5D))%3B%0A%20%20%20%20assert_eq!(1%2C%20f(%26%5B1%5D))%3B%0A%20%20%20%20assert_eq!(99999999%2C%20f(%26%5B99999999%5D))%3B%0A%20%20%20%20assert_eq!(3125%2C%20f(%26%5B5%2C%205%5D))%3B%0A%20%20%20%20assert_eq!(65536%2C%20f(%26%5B4%2C%208%5D))%3B%0A%20%20%20%20assert_eq!(1%2C%20f(%26%5B1%2C%202%2C%204%5D))%3B%0A%20%20%20%20assert_eq!(4%2C%20f(%26%5B2%2C%202%2C%204%5D))%3B%0A%20%20%20%20assert_eq!(16%2C%20f(%26%5B2%2C%203%2C%202%5D))%3B%0A%20%20%20%20assert_eq!(65536%2C%20f(%26%5B2%2C%204%2C%202%5D))%3B%0A%20%20%20%20%2F%2F%20assert_eq!(1%2C%20f(%26%5B4%2C%203%2C%202%5D))%3B%20%2F%2F%20panics%20because%20of%20overflow%0A%20%20%20%20assert_eq!(4%2C%20f(%26%5B2%2C%202%2C%203%2C%202%5D))%3B%0A%7D) on the rust playground.
## Readable version
```
fn f(s: &[u32]) -> u32 {
    match s {
        []=>1,
        [x]=>*x,
        [p,q]=>p.pow(*q),
        [x@..,1]=>f(x),
        [x@..,1,_]=>f(x),
        [x@..,p,q]=>f(&[x, &[f(&[x,&[p-1,*q]].concat())], &[q-1]].concat())
    }
}
```
[Answer]
# JavaScript (ES7), ~~78~~ 77 bytes
Takes the list in reverse order.
```
f=([q,p,...a])=>a+a?f(--q?--p?[q,f([++q,p,...a]),...a]:a:[p,...a]):p**q||q||1
```
[Try it online!](https://tio.run/##Xc3dioMwEAXg@z7F3BlrTIkm0nWxXvUpgguDJt2WYvxZetV3d6PVKh0Cwe@cODd8YF921@YvrG2lh8FkRLW0oYwxLPzshAHmhoRhm4dhk7vIEBUEa@N1pZiqRdJmv2@fT3f48K12AKqgsM7hAHxEvtUFv@aZMofL95hJCvL9xmUxj@TogsJx64mUcTJtoBBREK9s2RB9oJgxdr42k1nFVt8/Fh918RPJBDLgLBaaS7HumWrznmLHjO3OWP4ShOwEpa17e9fsbi/EUx4EgOxmrzXxqOezBqtzXZGj79wrIIWxYAiyTj9012viuxn@AQ "JavaScript (Node.js) – Try It Online")
### With BigInt support (78 bytes)
This version accepts either a list of *Numbers* or a list of *BigInts* and returns a value of the same type.
```
f=([q,p,...a])=>a+a?f(--q?--p?[q,f([++q,p,...a]),...a]:a:[p,...a]):p?p**q:q||1
```
[Try it online!](https://tio.run/##Xc3BjoIwEAbgu08xN4qUmkJLXDZIsomHfYaGTSZQXIwLBYwn350tCGKcS9Pv/9s54w37vKvM1a@bQg9DmRDVUkMZY5i5yQE9TEvi@23q@ya1UUmU562NxxFjrBaJTWq22zZu73c@fKoNgMoorLPbAR@Rv@qCH/NMmcXlPmaSgny@sVnIAzm6oLB/9UjKMJo2UAgoiEe2bAjeUMwYWl@b0aziVZ8fi7e6@AlkBAlwFgrNpVj3TLV5T7ZhZdMdMf8lCMkB8qbum4tml@ZEHOWAB8jOTVUThzouM1gc64LsXetOBjGMhZIg@0NDvqrTd311Wadvuus1ce0M/w "JavaScript (Node.js) – Try It Online")
[Answer]
# [Python 2](https://docs.python.org/2/), ~~117~~ ~~112~~ 111 bytes
```
f=lambda x:(len(x)<3)*reduce(lambda a,b:b**a,x,1)or f((1in x[:2])*x[1:]or[x[0]-1,f([x[0],x[1]-1]+x[2:])]+x[2:])
```
[Try it online!](https://tio.run/##fY5RC4MgFIXf9yt8VHcHqRkk65eID7UVG2wV0cD9@nYNt1qDgaDnu@eeY/8cL10rp6kpbuW9OpfEG3qrW@rZUTE@1OfHqaZxVEJlKs5L8CBYN5CGUnFtibdGOsa9FcZ1g/U2cQcBDZ1fgBil23srjWPve/KFVaDdrh@u7UioDQ5m0cg5xcCwgYxhQrT8@Up0YKNjRSEWKTZaBi1XOk9mkicL0zC71MomQIIKMF@YQraNT4FIPIGmqxIgKlKRfeE04kxrlW0X0jmGc6l/Rp@S6QU "Python 2 – Try It Online")
Takes input in reverse order.
A recursive function that takes in a list of positive integers and returns a single number.
In order to save bytes, we combine the 3 base cases into one expression:
```
(len(x)<3)*reduce(lambda a,b:b**a,x,1)
```
which returns either \$1\$, \$p\$, or \$p^q\$.
---
The recursive cases are also mashed together via:
```
f((1in x[:2])*x[1:]or[x[0]-1,f([x[0],x[1]-1]+x[2:])]+x[2:])
```
which becomes `f(x[1:])` when `x[0]` is \$1\$ or `x[1]` is \$1\$, and becomes `f([x[0]-1,f([x[0],x[1]-1]+x[2:])]+x[2:])` otherwise.
[Answer]
# [Erlang (escript)](http://erlang.org/doc/man/escript.html), 111 bytes
Port of the Haskell answer. The last case seems to time out.
```
f([])->1;f([P])->P;f([1|X])->f(X);f([Q,P])->math:pow(P,Q);f([_,1|X])->f(X);f([Q,P|X])->f([Q-1,f([Q,P-1|X])|X]).
```
[Try it online!](https://tio.run/##ZY7NCoMwDIDvfQrxVCEd1FXYuuEz6E3oypChW4d/aMGL7@6abm6HBdp8/ZI2rcam7O6smm6jGexK1poqHbGUnxxkSBkSXwrkmhYRHnPwpba0Dzn0M80g9/4K/42bUDnj8FbMd@HarW1pOhwZsJQELhoz2Uk@e2fDSxeClxjK9HIeja2owtfd/aU4M0WUBqI4bsdPICeQYDqAwCQgBr5BjBDDfgPxM@Jbco5o7Ye7T74A "Erlang (escript) – Try It Online")
[Answer]
# [Factor](https://factorcode.org/), 144 bytes
```
:: g ( x -- y )
x llength 3 < [ x 1 [ swap ^ ] foldl ]
[ x car 1 = [ x cdr g ]
[ 1 x cadr [ x cdr cdr cons x car 1 - swons g ] times ] if
] if ;
```
[Try it online!](https://tio.run/##VVDBTsMwDL3nK94RDp3UrkjQAddpl10QJ1SkKEu3iCwtSSY2TXx7eSkZaLHy8uznWLY7qWLvx9eX1XrZ4EN7py2sCTHA9kragL2Muwlm3cGpaHoXMHgd42nwxkUR9OdBO6UDFmK1bhCUl1HtxqbBFjc4oihwwq04wlrttiw2xyPeKJTE8CUHvKNF19uNRSuSoKSn@DQlqY1nnRQvJ4XuJTzd1M7lR8FyyWc@otmzpRamEwmwGM8441uAWOb3IZ/s3tF@2T3qzGpUf@mJV5lXnOKf11fx@iqHCo2T5j09p@2yxRmb05KL@gE "Factor – Try It Online")
Takes a linked list in reverse order. Uses the algorithm described in [user's APL answer](https://codegolf.stackexchange.com/a/215515/78410).
Using linked lists is shorter than using arrays when the code involves a lot of dissection at the start (and you don't need sophisticated sequence operations):
```
first (5)              > car (3)
rest (4)               > cdr (3)
second (6) > 1 nth (5) > cadr (4)
prefix (6)             > cons (4)
swap prefix (11)       > swons (5)
unclip (6)             = uncons (6)
unclip swap (11)       > unswons (7)
```
### How it works
```
:: g ( x -- y )         ! Takes a list `x` and returns a number
  x llength 3 < [         ! If x has 2 or fewer numbers...
    x 1 [ swap ^ ] foldl    ! Reduce by ^ on reversed arguments
  ] [                     ! Otherwise `x` is in the form of `X->y->z`
    x car 1 = [           ! If z is 1...
      x cdr g               ! Remove z(=1) and recurse
    ] [                   ! Otherwise...
      1                     ! Setup the initial value of 1
      x cadr                ! Setup the loop count of y
      [ x cdr cdr cons      ! Build y':X
        x car 1 - swons g ] ! Build z-1:y':X
      times                 ! Iterate the above function y times to 1
    ] if
  ] if
```
[Answer]
# [05AB1E](https://github.com/Adriandmen/05AB1E/wiki/Commands), ~~68~~ 66 [bytes](https://github.com/Adriandmen/05AB1E/wiki/Codepage)
```
"D©g2‹iPë`i)Y.Vëi)Y.Vë)\®`®g<imëX®šUs<s)Y.VXćsUDgÍsŠǝRć<šRY.V"DV.V
```
This was pretty hard in a stack-based language..
[Try it online](https://tio.run/##yy9OTMpM/f9fyeXQynSjRw07MwMOr07I1IzUCzu8Gkppxhxal3BoXbpNZu7h1RGH1h1dGFpsUwySizjSXhzqkn64t/joguNzg4602xxdGAQUV3IJ0wv7/z/aSMdIx1jHKBYA) or [verify all test cases](https://tio.run/##yy9OTMpM/V9Waa@k8KhtkoKSfeV/JZdDK9ONHjXszAw4vDohUzNSL@zwaiilGXNoXcKhdek2mbmHV0ccWnd0YWixTTFILuJIe3GoS/rh3uKjC47PDTrSbnN0YRBQXMklTC/sv45mzP/o6FidaEMgtoQCINNUxxRImuhYgKR0jHRMgLQRnDbWMQLTJmDaBM6HyMQCAA).
**Explanation:**
```
"                          "# Start a string we can execute as 05AB1E code
                            # to mimic recursive calls:
 D                          # Duplicate the list at the top of the stack
                            # (which will be the (implicit) input at the start)
  ©                         # Store it in variable `®` (without popping)
   g2‹i                     # Pop one, and if its length is smaller than 2:
       P                    #  Take the product
                            #  ([] → 1; [p] → p)
   ë                        # Else (the length is >= 2):
    `                       #  Dump the contents of the list onto the stack
     i                      #  Pop the top value, and if it's a 1:
      )                     #   Wrap the remaining values into a list
       Y.V                  #   And do a recursive call
                            #   (p=1 for [...,q,p] → recursive call to [...,q])
     ë                      #  Else:
      i                     #   Pop the second top value, and if it's a 1:
       )                    #    Wrap the remaining values into a list
        Y.V                 #    And do a recursive call
                            #    (q=1 for [...,q,p] → recursive call to [...])
      ë                     #   Else:
       )\                   #    Discard everything on the stack
         ®`                 #    Dump the contents of `®` onto the stack again
           ®g<i             #    If the length of `®` is 2:
               m            #     Take the power of the two values
                            #     ([p,q] → p^q)
              ë             #    Else (the length is >= 3):
               X®šU         #     Prepend `®` to list `X`
                            #     (`X` is 1 by default, but that doesn't matter;
                            #      it'll become [[...,p,q],1] and the 1 is ignored)
               s<s)         #     Decrease the second value from the top by 1
                   Y.V      #     And do a recursive call
                            #     ([...,p,q] → recursive call to [...,p-1,q],
                            #      let's call its result `R` for the moment)
               Xć           #     Extract the first list from variable `X` again,
                 sU         #     and pop and store the remaining values as new `X`
                 DgÍ        #     Take its length - 2 (without popping by duplicating first)
                            #     (let's call this length-2 `I` for the moment)
                    sŠ      #     Swap & triple-swap ([...,R,[...,p,q],I] → [...,[...,p,q],R,I])
                      ǝ     #     Insert value `R` into the list at (0-based) index `I`
                            #     ([...,[...,p,q]] → [...,[...,R,q]])
                 Rć<šR      #     And decrease the last value in the top list by 1
                            #     ([...,[...,R,q]] → [...,[...,R,q-1]])
                       Y.V  #     And do a recursive call again
"                          "# End the string of 05AB1E code
 DV                         # Store a copy of this string in variable `Y`
   .V                       # Execute it as 05AB1E code (`Y.V` is how we can do recursive calls)
                            # (after which the result is output implicitly)
```
[Answer]
# [Pyth](https://github.com/isaacg1/pyth), ~~40~~ 38 bytes
```
L?tJtby?}1<b2J+,thby+,hbthJtJttb|^F_b1
```
[Try it online!](https://tio.run/##RYwxCsMwDEX3nkKrSYbYsgyGQrYMpjcopKDJYwtaDO3ZXTl200n//cfXs0iu9bZKEi7rx17ZpWmWzGWaM0tOKoTf@/ZgW19Q7gbspV37C86A6yEuGuNyAIH2OASQCuozcIAG4gGocP7xCrrxY4INbBjkGwUiDKf2Bnat6d/0ff0C "Pyth – Try It Online")
Takes input in reverse order.
`L` defines a recursive function named `y` that takes in a list `b` of positive integers and returns a single number.
Similarly to my Python answer, the base cases are combined into one expression:
```
|^F_b1
```
in which `^F_b` folds the exponentiation function `^` over `b` in reverse. If `b` has 2 elements \$(q,p)\$ this will return \$p^q\$, if `b` has 1 element \$(p)\$ it will return \$p\$, and if `b` is empty it will return 0 (`| .. 1` turns the 0 into 1, as needed)
---
The recursive cases are handled by:
```
y?}1<b2J+,thby+,hbthJtJttb
```
This part is a pretty straightforward translation of the recursive rules. If either of the first two elements of `b` are 1 it calls `y` on `tb` (equivalent to `b[1:]` in Python)\*. Otherwise, the formula \$X \to (X \to p\to (q+1))\to q\$ is passed recusively to `y`.
\*The rule \$X \to 1 \to p = X\$ thus takes two steps instead of one, but doing it this way saves a few bytes.
[Answer]
# Java, 282 chars
```
interface c{int n[]=new int[99];static void main(String[]a){int i=0,j=a.length;for(;i<j;)n[i]=new Integer(a[i++]);System.out.print(j<1?1:j<2?n[0]:c(j));}static int c(int j){j-=n[j-2]<2?2:n[j-1]<2?1:0;if(j<3)return(int)Math.pow(n[0],n[1]);n[j-2]--;n[j-2]=c(j);n[j-1]--;return c(j);}}
```
Readable version:
```
interface c{
    int n[]=new int[99];
    static void main(String[]a){
        int i=0,j=a.length;for(;i<j;)n[i]=new Integer(a[i++]);
        System.out.print(j<1?1:j<2?n[0]:c(j));
    }
    static int c(int j){
        j-=n[j-2]<2?2:n[j-1]<2?1:0;
        if(j<3)return(int)Math.pow(n[0],n[1]);
        n[j-2]--;
        n[j-2]=c(j);
        n[j-1]--;
        return c(j);
    }
}
```
[Answer]
# [Clojure](https://clojure.org/), 117 bytes
```
(defn f([]1)([q]q)([q p](Math/pow p q))([q p & x](if(== p(f q p))(apply f p x)(apply f(dec q)(apply f q(dec p)x)x))))
```
[Try it online!](https://tio.run/##TZDhCsIgFIX/7ynOr3AwCjcdRdgb9ARiEGtSMTZdRevp6zY32RXE853rkWvVdPdXX3@/7FLbFpZpw1OmvfH/Hc6w4/l53bjuDQefBogVBsNulikFxywIkXN2rvnAkj1EQakVXYueH4FLB1pU9Gr3qD30AJ1og706gCeax9NuqgBmlWiZQQZW8FwmWmTYBl1KWZQUkSHPIGJQvtRi1AWhyS9HICKYQsSySZxyWUKBrwtRcynmzLFjzjXM9bf22bSIP9D/BwzT/gA "Clojure – Try It Online")
Handles all test cases, takes input arguments in reverse order.
[Answer]
# [Wolfram Language (Mathematica)](https://www.wolfram.com/wolframscript/), ~~67~~ 66 bytes
```
f[x__,1,_:0]=f@x
f[x___,p_:1,q_:1]=If[x<1,p^q,f[x,f[x,p-1,q],q-1]]
```
[Try it online!](https://tio.run/##RYnBCoMwEETv@Q2hpxEaG6GVWnLtrdCjbEOQSj0oSfEgBP31NIkFF3bmMW/Q0@c96KlvtfddMysFDlUdqe7kzNKgYFTFYUNQfQ/TlcO8LAKlN3mQBJtzIv/49uPUZPmtkzKjw/ps9bg65hYwx2Nc/he5RBlL4Jw0CogIxQ4nFBuIDcS@bJIt/gc "Wolfram Language (Mathematica) – Try It Online")
[Answer]
# [Scala](https://www.scala-lang.org/), ~~156~~ 141 bytes
```
val f:Seq[Int]=>Int={case x if x.size<3=>(x:\1.0)(math.pow(_,_))toInt
case 1::x=>f(x)case p::1::x=>f(x)case q::p::x=>f(q-1::f(q::p-1::x)::x)}
```
[Try it in Scastie](https://scastie.scala-lang.org/8Zz4FyQzS120VPE5CEkpYg)
Note: Input must be a reversed `List`. If it's not reversed, the algorithm won't work correctly, and if it's not a `List`, there'll be a MatchError.
I hate that `math.pow(_,_)` works but just `math.pow` would need the first argument to be a `Double`.
]