TI-BASIC interpreter for Fishstacks

Fishstacks is a deadfish derivative based on a stack the stack can only hold four elements when a fifth element is pushed the bottom element is kicked out and eventually printed out to the screen.

I've come up with an interpreter in TI-BASIC for my calculator. However, I fell slightly guilty about using all four variables ABCD. I wonder if there could be a better way? Maybe with lists (arrays). I've just started learning about them, so I don't feel confident switching over yet. Any guidance would be appreciated.

Also, in order not to push anything to the screen until something falls off the stack, I've had to initialize variables to -2. This is the main reason I have not converted to arrays yet; I don't see how they could address this issue. (maybe even throw a DOMAIN error).

:ClrHome
:Disp "FISHSTACKS IDSP","INTERPRETER"
:0->I
:-2->A
:A->B
:B->C
:C->D
:Input Str1
:While I<length(Str1)
:I+1->I
:sub(Str1,I,1)->Str2
:If Str2="I"
:A+1->A
:If Str2="D"
:A-1->A
:If Str2="S"
:A^2->A
:If Str2="P" and D>-1
:Then
:Disp D
:C->D
:B->C
:A->B
:0->A
:End
:If A=256 or A=-1
:0->A
:If A=-2
:Stop
:End


By convention, I've represented the STO→ character, → with ->

I was asked by @Timtech to join + post an improvement. Using arrays is a lot easier to understand, and there were so many optimizations that I decided to completely re-write the code. I'm sure it could be improved by other advanced programmers like me, as I'm using several long expressions here... note that L1 represents list #1 (2nd + 1 on the calculator) and ~ is the negative token.

:ClrHome
:Disp "FISHSTACKS IDSP","INTERPRETER
:DelVar IInput Str1
:DelVar L1~{2,2,2,2→L1
:While I<length(Str1
:I+1→I
:sub(Str1,I,1→Str2
:(Str2="I")-(Str2="D
:Ans+L1(4→L1(4
:If Str2="S
:L1(4)²→L1(4
:If Str2="P
:Then
:L1(1
:If 2+Ans
:Disp Ans
:ΔList(cumSum(L1->L1
:0->L1(4
:End
:L1(4
:If Ans=256 or Ans<0
:0->L1(4
:End


Improvements

1. Saved bytes by removing several unneeded ending parentheses and quotes
2. Used DelVar since it does not need a following colon
3. Used an array instead of four variables
4. Used a complex expression :(Str2="I")-(Str2="D saved to Ans to save space
5. Used ΔList(cumSum(L1->L1 to get L1 minus its first element
6. Several others I'm not listing due to their minisculity; mainly using Ans to save space and speed
• Wow great, I'm glad you could make it! Enjoy your stay. – Timtech Dec 16 '14 at 20:05
• Thanks @Timtech, I'll probably be answering your other questions in the near future, whenever I have the time. – FlyAwayBirdie Dec 16 '14 at 20:07
• Welcome to Code Review! – RubberDuck Dec 17 '14 at 2:09
• Haha, that good old TI-BASIC where not closing the parenthesis and the strings is the norm :D – Morwenn Dec 19 '14 at 0:26

Beyond the bad names that you are already aware of, I see a few things that could be improved.

str1 and str2 are bad variable names as well. They should be str and chr respectively. Those names would properly represent the data and make this code much more understandable. It would be instantly clear to anyone looking at the code that you're looping through each character of the string the user inputs.

This section of code makes no sense.

:If Str2="P" and D>-1
:Then
:Disp D
:C->D
:B->C
:A->C
:0->A
:End


Translated into a "normal" basic language, it looks like this.

    If char = "P" And d > -1 Then
Print d

d = c
c = b
c = a
a = 0
End If


And it is instantly obvious that you only need to make the assignment to c once.

:If Str2="P" and D>-1
:Then
:Disp D
:C->D
:A->C
:0->A
:End


The other improvement I can see here, is that I think it makes a lot of sense to use a For Loop instead of a While loop here. That way you wouldn't have to increment I manually on every iteration of the loop. It would make this little program a little cleaner.

• Unfortunately it seems like you are not familiar with the language; other than catching the typo, there's really no improvements. Strings cannot be renamed, For( loops take more space, etc. – Timtech Dec 16 '14 at 19:34
• tibasicdev.wikidot.com/for – Timtech Dec 16 '14 at 19:38
• I ope so too! And the bounty is open for another week, so maybe someone here will take notice. =) – RubberDuck Dec 16 '14 at 19:46
• Yep, one of my friends says he's writing up one now. – Timtech Dec 16 '14 at 19:48
• Well, the remark about string names is still pointless: you can't name variables in TI-BASIC. There are like a dozen of string variables named Str1, Str2, Str3... and you can't do anything about it. You have to use these cryptic names. – Morwenn Dec 19 '14 at 0:29
:ClrHome
:Disp "FISHSTACKS IDSP","INTERPRETER"
:-{2,2,2,0->L1
:Input Str1
:For(I,1,length(Str1
:sub(Str1,I,1
:If Ans≠"P"
:Then
:(Ans="I")-(Ans="D")+L1(4)^int(e^(Ans="S"->L1(4
:If Ans≥0 and Ans≠256
:Else
:L1(1
:If 2+Ans
:Disp Ans
:augment(ΔList(cumSum(L1)),{0->L1
:End
:End


I was able to shorten FlyAwayBirdie's answer even more by combining some expressions, moving the overflow checking earlier to take advantage of Ans, setting L1 in fewer bytes, using a For loop, and a couple of other things. Additionally, I initialized variables to -1 instead of -2, except for the initial accumulator which starts at 0 as per the spec.

You can remove the close quotes at the ends of the lines.

Edit: Saved a couple more bytes by not saving the substring to Str2.

Edit: Fixed overflow functionality; however, undefined commands will now be recognized as "P".

• Nice! Usually when he posts it's hard to improve upon it :P – Timtech May 25 '15 at 1:07