Throwback Friday: Renumber my ZX spectrum BASIC listing The first programming language I was exposed to was Sinclair BASIC.  Like many BASIC dialects, it requires all source code lines to be numbered.

As a result, use of the GO TO command was idiomatic and jumps execution to the given line number (no labels).

Also there is a related GO SUB command which can be used as a rudimentary function call.  Again, execution jumps to the given line number, but when a RETURN command is reached, execution jumps back to the next instruction after the GO SUB.

Similarly the RUN command will restart program execution at the given line.

Anyone who has spent any time in a line-numbered BASIC interpreter will have learned to use a numbering scheme with gaps in it.  This is so that it is easier to insert new lines of code.  However even then, you may still find yourself needing to insert new lines in between consecutively numbered lines.



Given a line-numbered BASIC listing as input, output the same program but renumbered such that the line numbers start at 10 and increment by steps of 10.  The input listing may have GO TO or GO SUB commands, so the numbers associated with these must also be adjusted.


GO TO and GO SUB commands are either on their own lines or at the end of IF THEN lines.  Its safe to say ^(\d+) .*GO (TO|SUB) (\d+)$ is sufficient to match such lines.  These commands in quotes should be ignored.
RUN commands will always be on their own lines.  In this case a line number is optional.  If it is missing, then the interpreter simply starts at the top of the program.
If a GO TO, GO SUB or RUN command references a non-existent line, then it will instead jump to the next defined line.  Your entry needs to deal with this and ensure any such line references are fixed so they point to the correct line.  Behaviour may be undefined if a line number after the end of the program is given in one of these commands.
Line numbers will always be positive integers 1 to 9999 (as per the manual).  This means that input programs will never have more than 999 lines.
Input lines will always be numbered in numerically ascending order.
For the purposes of this challenge, input listings will only contain printable ASCII.  You don't need to worry about the ZX character set.  Having said that, if your entry is actually written in ZX BASIC or appropriate z80 assembly/machine code (and there are emulators out there), then you may choose for your input to be encoded in the ZX character set instead.
You may not use any renumber libraries or utilities that are specifically tailored for this purpose.


Example Input:

1 REM "A rearranged guessing game"
2 INPUT A: CLS
3 INPUT "Guess the number ", B
10 IF A=B THEN PRINT "Correct": STOP
100 IF A&lt;B THEN GO SUB 125
120 IF A&gt;B THEN GO SUB 122
121 GO TO 3
125 PRINT "Try again"
126 RETURN
127 REM "An example of GO TO 7 and GO SUB 13 in quotes"


Example Output:

10 REM "A rearranged guessing game"
20 INPUT A: CLS
30 INPUT "Guess the number ", B
40 IF A=B THEN PRINT "Correct": STOP
50 IF A&lt;B THEN GO SUB 80
60 IF A&gt;B THEN GO SUB 80
70 GO TO 30
80 PRINT "Try again"
90 RETURN
100 REM "An example of GO TO 7 and GO SUB 13 in quotes"




I wanted to link to a ZX BASIC manual.  The best I could find seems to be http://www.worldofspectrum.org/ZXBasicManual/index.html but this seems to be a dead link.  The wayback machine has a copy though.
JavaScript (ES6) 177

Edit Added the (costly) scan for the next valid line number

l=&gt;l.split`
`.map((x,i)=&gt;([,n,t]=x.match(/(\d+)(.*)/),l[n]=10*-~i,t),l=[]).map((x,i)=&gt;10*-~i+x.replace(/(UN |GO TO |UB )(\d+)$/,(a,b,c)=&gt;(l.some((v,i)=&gt;i&lt;c?0:a=b+v),a))).join`
`


TEST



f=l=&gt;
  l.split`\n`
  .map((x,i)=&gt;([,n,t]=x.match(/(\d+)(.*)/),l[n]=10*-~i,t),l=[])
  .map((x,i)=&gt;10*-~i+x.replace(/(UN |GO TO |UB )(\d+)$/,(a,b,c)=&gt;(l.some((v,i)=&gt;i&lt;c?0:a=b+v),a)))
  .join`\n`
        
//TEST
console.log=x=&gt;O.textContent+=x+'\n'
  
test=`1 REM "A rearranged guessing game"
2 INPUT A: CLS
3 INPUT "Guess the number ", B
10 IF A=B THEN PRINT "Correct": STOP
100 IF A&lt;B THEN GO SUB 125
120 IF A&gt;B THEN GO SUB 122
121 GO TO 3
125 PRINT "Try again"
126 RETURN`
console.log(test+'\n\n'+f(test))
&lt;pre id=O&gt;&lt;/pre&gt;