Here is my 156 code

function a($s)
	dim $,$t,$y,$z
	while $s
		$ = left($s,1)
		$s = right($s,~)
		if $>#
			$a = (1+$y+$z)*(10*($=x)+$+($='/')*(10-$t)) + $a
			$z = ($t=x)*$y
			$y = ($=x | $='/')*($s<#)
			$t = $

And here is a brief explanation of it


Since we only care about the total score, we don't need to calculate each frame and then add those together. Instead we can keep a running total following the following idea:

Depending on the previous scores, we will add the current score
-once, if no spares or strikes carry over
-twice, if only one spare or strike carries over
-3 times, if a strike and either another strike or spare carries over

So we loop through each character in the string of scores passed in. If the character is not a space, i.e. $># then process...

First, we calculate the total for this score

$a = (1+$z+$y)*(10*($=x) + $ + ($='/')*(10-$t)) + $a

This is the multiplier. It will always be at least 1

If it's a strike, then the score is 10.

if $ is a number, then just add the number itself. If it's not a number, then it will evaluate to 0

If it's a spare, then the score is 10. BUT the spare means the current score PLUS the last one is 10, so we need to subtract
the previous score from 10

Now multiply the multiplier times the score, add to our current total and move on.

Next, we figure out the multiplier for the next round

$z= ($t=x)*$y
If the previous score was a strike and it we counted it this round, we'll count it next round

$y = ($=x | $='/')*($s<#)
if this score was a strike or a spare, and not in the 10th frame, then count it. If it is not in the 10th frame
then $x will begin with a space and therefore be less than #.

Store the current score in $y which will be needed if the next score is a spare, as well as for the next $z assignment.

Set $t to the current score which we may need in the next round