this happens a lot, I want to find out how something works but I don’t know the said programming language and so I can’t read the source code, I’ve tried looking up stuff in cheatsheets but they don’t really help that much and Search Engines are obviously useless for this since they can’t search symbols, so how do you read the source code without spending time learning the language ?

  • @ttmrichter
    link
    41 year ago

    OK, let’s take that weird one apart so I can show you the strategy for reasoning about it: Index'Pos(Index'Succ(Index'First));

    First, Index'Pos is clearly separating two lexical items: Index and Pos. Where have we seen either of those before? Pos is only ever used on the right hand side of ', so that’s a clue that this is some kind of component of Index. Index is defined, however. Let’s take a look at that specification again.

    generic
       type Element_Type is private;
       type Index is (<>);
       type Collection is array(Index) of Element_Type;
       with function "<=" (Left, Right : Element_Type) return Boolean is <>;
    procedure Gnome_Sort(Item : in out Collection);
    

    Index is a type. What type? (<>). That’s just gibberish if you only know Python and C, but we can still tease out some information.

    First, Index has a name that means something. It’s, well, an index. And if we look at Collection right underneath it, it’s an index into an array. So Index is likely an integer.

    So 'Pos is some kind of operation or member or something on the type of an integer. And it suggests that it means some kind of position. What could “position” mean to an integer?

    The clue lies in how the function there gets used. I didn’t put it there (because I was already being long-winded) but here’s the example of using that:

    with Gnome_Sort;
    with Ada.Text_Io; use Ada.Text_Io;
    
    procedure Gnome_Sort_Test is
       type Index is range 0..9;
       type Buf is array(Index) of Integer;
       procedure Sort is new Gnome_Sort(Integer, Index, Buf);
       A : Buf := (900, 700, 800, 600, 400, 500, 200, 100, 300, 0);
    begin
       for I in A'range loop
          Put(Integer'Image(A(I)));
       end loop;
       New_Line;
       Sort(A);
       for I in A'range loop
          Put(Integer'Image(A(I)));
       end loop;
       New_Line;
    end Gnome_Sort_Test;
    

    And here the penny drops. The Gnome_Sort routine is generic (clue: generic in the specification). The index has to be defined for it. We do that with the three lines immediately after the procedure line in the use case. Index is an integer in the range of 0…9.

    Because the Gnome_Sort procedure is generic, we make no assumptions about what the array ranges are: here it’s 0…9, but it could just as easily have been -1277516794231…125164987325159876. So these 'Pos, 'First, and 'Last and 'Val and such things are used to step through loops in a type-safe way that’s guaranteed to never step out of the array boundaries.

    But it’s largely unimportant. These are Ada-isms focused on Ada’s obsession: correctness. That’s just line noise, really, for purposes of understanding the code. We can kind of intuit that I is starting from the successor ('Succ) of the first ('First) (a.k.a the second) element of the array and going through it until it reaches the end of it (<= Index'Last). This guess is further bolstered by the comparison of things indexed via I - 1 against I.

    Decoding this is a dollop of familiarity with paradigms and coding approaches and decent contextual guessing. Is it better to just know the language? Yep. But even not knowing it you can tease out everything you need to work out how a gnome sort works. Part of the skill set in reading alien code is to learn how to relax and gloss over the bits that you don’t understand until you see the shape of the whole thing, after which, if you’re familiar with the paradigm, you can start making very good guesses as to what the unfamiliar bits actually mean. (Again, if you’re unfamiliar with the paradigm you’re … going to need to learn.)