Make a ;#*:) interpreter A few month back, I made a language called ;# (Semicolon Hash) and it started a little bit of a craze (it even got its own tag, as you can see). But, as with everything, the craze died down, and questions related to it stopped being posted.

However, a few people were annoyed at the lack of capability of ;# and this lead to someone creating a Turing complete version. Eventually, I decided to create ;# 2.0 with an extended set of commands:

; - Increment the accumulator
# - Modulo the accumulator by 127, output as ASCII character and reset the accumulator to 0
: - Open a while loop
) - Close a while loop. You can assume that all loops will be closed.
* - Take a byte of input, and add it to the accumulator. Input is recycled, so if the end of the input is reached, it wraps around to the start.


FYI: ;#*:) still isn't Turing complete

For example, a cat program would be

*:#*)

*     - Take a byte of input
 :  ) - While the input character is not a null byte...
  #   -   Print as character
   *  -   Take a byte of input


For this, the input must be terminated with a null byte, otherwise the program will repeat the input until the heat death of the universe.

and to add two numbers (input and output as char codes):

**#

*   - Take input (e.g. \x02); A=2
 *  - Take input (e.g. \x03); A=5
  # - Output A as character (\x05)


Your task is to interpret ;#*:). Your program/function will be given 2 inputs, the program and the program's input, and you have to interpret the given program.

A few rules:

1) Your program may not halt termination due to an error unless 2) happens. Output to STDERR is allowed, just so long as it doesn't affect the program's execution.

2) If the second input is empty (a ;#*:) program with no input) and * occurs in the code, you don't have to handle the error and can cause any kind of behaviour you want; summon Cthulhu, make Dennis lose his rep, anything you want.

3) All characters that aren't ;#*:) are ignored and have no effect on anything.

Nested loops can happen, and all loops will be closed, so ;:*:#*);) is valid code

This is a code golf, so shortest code wins.

Some tests to check your program against:

program, input (as ASCII characters; \xxx is a byte literal) =&gt; output

*#*:#*), "1" =&gt; 11111111...
**#, "12" =&gt; c
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;#;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;#;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;#;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;#;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;#;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;#;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;#;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;#;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;#;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;#;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;#;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;#;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;#, "abc" =&gt; Hello, World!
*#, "" =&gt; undefined
Hello, World!, "" =&gt; (nothing)
*:#*):;#*)*#, "Hello,\x00World!" =&gt; Hello,W
*:#*), "Testing\x00" =&gt; Testing
*:#*), "Testing" =&gt; TestingTestingTestingTesting...
;:*:#*);*), "123\x00" =&gt; 223d3d3d...


And, to help you even more, this is an ungolfed reference implementation in Python. In this version, I have decided to make the * on empty input be ignored.

Good luck!
Ruby, 147 144 bytes

Saved 3 bytes thanks to m-chrzan!



z=STDIN.read
eval ARGV[i=a=0].gsub(/./){|e|"#{{?;=&gt;"a+=1",?#=&gt;"putc(a%127);a=0",?:=&gt;"while a&gt;0",?)=&gt;"end",?*=&gt;"a+=z[i%=z.size].ord;i+=1"}[e]};"}


Try it online!

Program is taken from first command line argument.