A small language deserves a small interpreter Here is a very simple language definition:

A Variable is any string that does not contain ^, &lt;, &gt;, !, or ?
The empty string is a valid variable identifier
The value of every variable starts at 0.
A Statement is one of (var is a Variable, P is a Program):
    var^   -&gt; changes var to be equal to 1 more than itself
    var&lt;P&gt; -&gt; while var &gt; 0, changes var to be equal to 1 less than itself, then runs P
    var! -&gt; output value of var
    var? -&gt; ask for non-negative integer as input, increase var by that value
A Program is a concatenation of Statements, running a Program means running each Statement in order


Example programs (note that the empty string is a variable, but I will use it sparingly for the sake of clarity, and some variables are zeroed out in the program when they are usually 0 by default):

&lt;&gt;: sets the value of the empty string variable to 0
b&lt;&gt;b?b&lt;a^&gt;: asks for b, then adds the value stored in b to a, zeroing b in the process
b&lt;&gt;b?a&lt;&gt;b&lt;a^&gt;: asks for b, then sets a to the value of b, zeroing b in the process
a&lt;&gt;c&lt;&gt;b&lt;a^c^&gt;c&lt;b^&gt; : copies the value in b into a without zeroing it
b&lt;&gt;c&lt;&gt;a&lt;c^c^c&lt;b^&gt;&gt;b! : outputs a multiplied by 2
b^b&lt;a&lt;&gt;a?a!b^&gt; : outputs what you input, forever


Your goal is to write the smallest interpreter for this language.


The value of a variable can be arbitrarily large and should only be limited by the total memory your language has access to, in theory, but you are only required to handle values up to 2^256.
Your program should be able to handle arbitrarily long programs, in theory, but you will only be required to work on programs under 2^32 characters long. You are required to handle nested loops of depth up to 2^32 as well.
You can assume that the program is a valid program, and that you will only ever get non-negative integers when you ask for input. You can also assume that only ASCII printable characters are included in the input string. 
The speed of the program you interpret doesn't matter, it will already be painfully slow for things as simple as 5-digit multiplication, without optimization.
If you want to use a language which cannot reasonably accept input or produce output in the way described by the language, use any interpretation you want to make it possible. This applies to any reason your language can't implement some required behavior. I want all languages to be able to compete.
Shortest program wins. Standard loopholes apply.
Ruby, 182 bytes

$h=Hash.new 0
def r(c)c.scan(/(([^!?^&lt;&gt;]*)(&lt;(\g&lt;1&gt;*)&gt;|[!?^]))/){$4?($1=~/(.*?)&lt;(.*)&gt;/
($h[$1]-=1;r$2)while$h[$1]&gt;0):$3&lt;?"?p($h[$2]):$h[$2]+=$3&lt;?@?STDIN.gets.to_i:
1}end
r IO.read *$*


Try it like this:

$ cat code
a?b&lt;&gt;c&lt;&gt;a&lt;c^c^c&lt;b^&gt;&gt;b!

$ ruby lynn.rb code
3                           &lt;-- input
6                           &lt;-- output


How it works

The r function tokenizes an input string and executes each token:

def r(c)
    c.scan(/(([^!?^&lt;&gt;]*)(&lt;(\g&lt;1&gt;*)&gt;|[!?^]))/){
        ...
    }
end


We look for some variable name $2 matching [^!?^&lt;&gt;]*, followed by either


&lt;...&gt; where ... matches zero or more programs (\g is recursion), in which case $4 isn't nil
A !, ?, or ^ character, captured by $3, in which case $4 is nil.


Then the logic for executing a token is quite simple when indenting it a bit:

$4 ? (                                    # If it's a loop:
    $1 =~ /(.*?)&lt;(.*)&gt;/                   #   Re-match token*
    ($h[$1]-=1; r $2) while $h[$1] &gt; 0    #   Recurse to run loop
) :                                       # Else:
    $3 &lt; ?"                               #   If it's an !:
      ? p($h[$2])                         #     Print the var
      : $h[$2] +=                         #   Else, increment it by:
          $3 &lt; ?@                         #     If it's a ?:
              ? STDIN.gets.to_i           #       User input
              : 1                         #     Else: 1

* There's an oniguruma bug, I think, that keeps me from simply using $3 here.