Where did you COME FROM?

9

1

INTERCAL is a wonderful language, but it is not always easy to understand other people's code. This is particularly the case if they use the COME FROM statement.

INTERCAL IS MADNESS

Challenge definition

  1. Write a program or function which take the source code of an INTERCAL program as a text/data stream. If you write a function it is recommended that you also provide a program to call the function, but it will not count towards your score.
  2. The function output will be a text/data stream of the jumps that program makes, according to the following instructions. The output does not need to be printed, but it does need to be a single text, not an array of strings (for example).
  3. Each line of output will consist of the statement which will be COME FROM and the line number of its COME FROM statement, separated by a ->. An example:

    (310)   DO .4 <- .3 -> 55
    
  4. You can trim these lines of source code, but it is not necessary to.

  5. The test cases will only consist of noncomputed labels (i.e., integer labels).
  6. The output must be sorted by the source code order of the statements which will be COME FROM, not their label, nor the order of the COME FROM statements or their labels.
  7. It is possible for multiple statements to COME FROM the same label. In such cases the COME FROM line numbers must be sorted, and separated by commas.
  8. It is possible for a statement to COME FROM itself.
  9. A COME FROM statement may be prefixed with a NOT statement. In such cases the line number must be wrapped in square brackets.
  10. The words COME FROM can appear in a comment and must be ignored. You do not need to fully parse the file: if they are followed by a label (a number in parentheses) then you can assume it is a real statement.

Scoring

Entrants will be scored by the character length of their program or function.

Test cases

These test cases all come from the calvinmetcalf/intercal Github repo. Although any useful application will safely accept any input, for the purposes of this challenge you need only account for these five test cases.

rot13.i

(10) PLEASE DON'T GIVE UP -> 87
(33) DON'T GIVE UP -> 92

primes.i

(15)    DO (13) NEXT -> 26
(16)    DO .12 <- .1 -> 6
(23)    DO (21) NEXT -> 3

unlambda.i

(7202)  DO RETRIEVE .203+,202 -> 75
(4202)  DO ,202SUB.201.202#7 <- ,201SUB.201.202#7 -> 108
(6202)  DO ,201SUB.201.202#7 <- ,202SUB.201.202#7 -> 117
(4203)  DO READ OUT ,201SUB.201.202#7 -> 133
(4302)  DO .302 <- .2 -> 181
(5410)  DO ,400SUB#124 <- #4 $ #17 -> 293
(3410)  PLEASE (4410) NEXT -> 288
(5402)  DO (412) NEXT -> 328
(4412)  PLEASE (3412) NEXT -> 334
(3423)  DO FORGET #2 -> 375
(4404)  DO RETRIEVE .311+.312 -> 411
(5404)  PLEASE DO (414) NEXT -> 430
(4434)  DO FORGET #1 -> 441
(3454)  DO (103) NEXT -> 451
(5502)  DO .512 <- .312 -> 520
(8503)  PLEASE RETRIEVE .311+.312 -> 621
(7503)  DO (302) NEXT -> 515
(3622)  DO (302) NEXT -> 514
(603)   PLEASE FORGET #2 -> 622

pass.i

(10)    DO  NOTHING -> 5, 11
(20)    PLEASE  (100) NEXT -> 6
(30)    PLEASE  (200) NEXT -> 12
(103)   DO  (104) NEXT -> 27
(104)   DO  (105) NEXT -> 19
(1) DO  (2) NEXT -> 36
(2) DO  (105) NEXT -> 194
(202)   DO NOT  .2 <- #2 AGAIN -> [196]
(203)   DO  (204) NEXT -> 167
(204)   DO  (205) NEXT -> 159

continuation.i

(8201)  DO NOTHING -> 165, 271
(8202)  PLEASE NOTE Fork threads, one dormant, one alive -> 53, 58
(8211)  DO COME FROM (8211) -> 60
(8216)  DO NOTHING -> 71
(8215)  DO NOTHING -> 68
(8217)  DO COME FROM (8217) AGAIN -> 118
(8299)  DO COME FROM (8299) AGAIN -> 141
(8274)  DO (8273) NEXT ONCE -> 158
(8259)  PLEASE DO NOTHING -> 166
(8276)  DO COME FROM (8276) AGAIN -> 199
(8278)  PLEASE DO COME FROM (8278) AGAIN -> 237

curiousdannii

Posted 2015-09-14T04:49:48.280

Reputation: 657

2It baffles me that no one made a Cotton Eyed Joe reference yet :-). – mınxomaτ – 2015-09-14T06:20:42.537

22INTERCAL is a wonderful language downvoted for offensive language. – Fatalize – 2015-09-14T07:37:52.063

Are you sure yout want to score by characters length? Challenges are usually scored by bytes length here. – Fatalize – 2015-09-14T08:50:43.860

@Fatalize I thought about it both ways. The common advantages of character scoring like encoding large numbers as unicode characters probably won't be useful, but I thought that if someone can take advantage of the scoring I'd be interested to see what they can do. – curiousdannii – 2015-09-14T08:54:21.373

Can we assume that the label is at the start of a line? Such that ^(\d+) grabs the label? – orlp – 2015-09-14T10:56:33.990

@orlp Make sure you can pass all the test cases, but kudos if you can make it safer in general. – curiousdannii – 2015-09-14T11:04:59.573

@curiousdannii Also, do we have to protect against a comment that says COME FROM (NaN) or COME FROM (HELLOWORLD) or COME FROM (10 LETS NOT MATCH BRACKETS? – orlp – 2015-09-14T11:12:13.900

@orlp No the test cases are all safe. I'll edit it to clarify that for the purposes of this challenge, passing these five test cases is sufficient. – curiousdannii – 2015-09-14T11:13:47.890

Answers

2

JavaScript, 232 bytes

function c(d){for(var l,o,f,c,p=/^.(\d+).+?$/gm,a=/(T\s+)?C.{7}M .(\d+)/g,r='';l=p.exec(d);)for(f=0;o=a.exec(d);)o[2]==l[1]&&(c=d.slice(0,o.index).split('\n').length,r+=f++?', ':'\n'+l[0]+' -> ',r+=o[1]?'['+c+']':c);return r.trim()}

To be called with

var data = require( 'fs' ).readFileSync( process.argv[2] ).toString();
console.log( c( data ) );

Explanation

function c(d){
    for(
        // Initialise variables
        var l,o,f,c,p=/^.(\d+).+?$/gm,a=/(T\s+)?C.{7}M .(\d+)/g,r='';
        // Find lines beginning with a label
        l=p.exec(d);)
            for(
                // Reset a have-we-output-this-line flag
                f=0;
                // Find CALL FROM statements
                o=a.exec(d);)
                    // Filter to CALL FROM statements which have the current line
                    o[2]==l[1]&&(
                        // Calculate the line number of this CALL FROM statement
                        c=d.slice(0,o.index).split('\n').length,
                        // Concat the output for this line
                        r+=f++?', ':'\n'+l[0]+' -> ',r+=o[1]?'['+c+']':c);
    // Trim an initial new line
    return r.trim()}

curiousdannii

Posted 2015-09-14T04:49:48.280

Reputation: 657

1The biggest bloat here is calculating the line number, but as the challenge author I thought I'd leave it in as an easy attempt to try to beat. – curiousdannii – 2015-09-16T04:43:10.277