Create an interpreter for "Counter"

7

1

"Counter" is a language I've created for the purpose of this question.

Rules

  • Commands are read from left to right from the first character.
  • Each command may be executed as it is read, or you may execute all commands together at the end.
  • In case of an error, all commands up till the error must be executed.
  • A program is written in exactly one line.
  • Data is stored in counters. At the start, there is exactly one counter. More can be created and deleted.
  • A counter holds an integer value between -100 and 100 (limits inclusive).
  • Exactly one counter is the selected counter at any point in time.
  • Counters are arranged in a 1d array, so one can move left (previous) or right (next) to change selected counter.

Commands

  • Any number between -100 and 100 - Set the currently selected counter to that value.
  • c - Create a counter immediately after the currently selected counter, make it the selected counter, and set it to 0.
  • d - Delete the currently selected counter, and make the previous one selected. If it is the first one, this is an error.
  • + - Make the next counter the selected one.
  • - - Make the previous counter the selected one. (Ensure that this command is not immediately followed by a number.)
  • o - Output the value in the selected counter, followed by a space.
  • ? - If the value in the selected counter is 0, apply the d command on it.
  • # - If the value in the selected counter is 0, ignore the next command.
  • (space) - No meaning, but is to be treated like a command, if preceded by a #. Used to demarcate numbers.

Errors

  • Going left of the leftmost counter, or right of the rightmost counter.
  • Deleting the first counter.
  • Encountering a # as the last command. (Of course, this means all commands will get executed anyways)
  • A command that does not exist.
  • A number that's too long.

Task

Create an interpreter in any language. Code will be in a file or given as input (your choice). Shortest code wins.

Lengthy example

Consider the code:

7cc--13 12do?+?#0#o3od-7o

Here is a breakdown of the program. [] indicates the selected counter.

Cmd   Memory    Output

7     [7]
c     7 [0]
c     7 0 [0]
-     7 [0] 0
-13   7 [-13] 0
      7 [-13] 0
12    7 [12] 0
d     [7] 0
o     [7] 0     7
?     [7] 0
+     7 [0]
?     [7]
#     [7]
0     [0]
#     [0]
o     [0]
3     [3]
o     [3]       3
d     This is an error. Program terminates here.

Total output 7 3

ghosts_in_the_code

Posted 2015-12-18T15:40:27.287

Reputation: 2 907

Oh, one thing you could still clarify is what exactly is allowed or required when an error is encountered. Clean termination of the program? Error message? Undefined behaviour as long as everything before the error works? – Martin Ender – 2015-12-19T10:18:44.813

1@Martin Any undefined behaviour as long as the previous commands have been executed and output is still visible. – ghosts_in_the_code – 2015-12-19T11:56:08.487

When you say "deleting the first counter" is an error do you mean "deleting the only existing counter" or do you mean "deleting the first counter even if other ones exist and could become the selected counter" For example: c-d – Jerry Jeremiah – 2016-01-13T04:04:49.510

@Jerry The second case – ghosts_in_the_code – 2016-01-13T07:18:00.157

Answers

1

Python3, 403 530 bytes

This is seriously golfable, but I can't think of how...

Thanks to @cat for 127 bytes!!! (I'm really bad at golfing in Python)

c=input()
a=[0]
s=0
i=0
def g(i,n):
 p=i
 if n:i+=1
 while c[i].isdigit():i+=1
 a[s]=int(c[p:i]);return i-1
def e():
 a.pop(s);s-=1
while i<len(c):
 d=c[i]
 if d.isdigit():i=g(i,0)
 elif d=='c':s+=1;a.insert(s,0)
 elif d=='d':e()
 elif d=='+':s+=1
 elif d=='-':
  if c[i+1].isdigit():i=g(i,1)
  else:s-=1
 elif d=='o':print(a[s],end=' ')
 elif d=='?':
  if a[s]==0:e()
 elif d=='#':
  if a[s]==0:i+=1
 i+=1

TheCoffeeCup

Posted 2015-12-18T15:40:27.287

Reputation: 626

here's 406 – cat – 2016-01-25T00:13:41.013

1

JavaScript (ES6) 228

s=>s.replace(/-?(\d+)|./g,(t,n)=>i?++i:C[k]&&(u='?-+# odc'.indexOf(t),n<101?C[k]=t:u>6?C[S='splice'](++k,0,'0'):u>5?C[S](k--,1):u>4?o+=C[k]+' ':u>2?+C[k]?0:i=-(u<4):u>1?k++:u>0?k--:~u?+C[k]||C[S](k--,1):i=1),i=o='',C=[k='0'])&&o

Less golfed

s=>(
  i=o='',
  C=[k='0'], // C: counters, k: current counter index
  s.replace(/-?(\d+)|./g,
    (t,n)=>( // tokenize, n is eventually the number, unsigned
      i?++i:C[k] && ( // i>0 or C[k] undefined -> error found
      u='?-+# odc'.indexOf(t),
      n<101?C[k]=t // n present and < 101 
      :u>6?C.splice(++k,0,'0') //c add counter
      :u>5?C.splice(k--,1) // d remove counter
      :u>4?o+=C[k]+' ' // o output
      :u>3?0 // space == NO OP
      :u>2?+C[k]?0:i=-1 // set i to -1 to skip the next command
      :u>1?k++
      :u>0?k--
      :~u?+C[k]||C.splice(k--,1) // ? conditional remove counter
      :i=1) // invalid command error
    )
  ),
  o // return output
)

edc65

Posted 2015-12-18T15:40:27.287

Reputation: 31 086

0

JavaScript ES6, 300 bytes

Hey look, a nice round number!

x=>x.match(/-\d*|\d+|./g).map(c=>e?0:q?q--:c-101?Math.abs(c)>100?e++:s[p]=+c:c=="c"?s.splice(++p,0,0):c=="d"?s.length>1?s.splice(p--,1):e++:c=="o"?o+=s[p]+" ":c=="-"?--p<0&&e++:c=="+"?++p>=s.length&&e++:c=="?"?s[p]||(s.length>1?s.splice(p--,1):e++):c=="#"?s[p]||q++:c==" "?0:e++,s=[],e=p=q=0,o="")&&o

It doesn't error on # at the end of a program because that wouldn't affect anything at all. Let me know if I need to anyway.

ETHproductions

Posted 2015-12-18T15:40:27.287

Reputation: 47 880