Search code examples
rascal

How to initialize a tuple containing an list of expressions in Rascal


I'm trying to create a method that recursively looks for a For-loop. I need to initialize the return value first (a tuple) but how do I do this exactly? I've tried: tuple[list[Expression],Statement] = [];

Also, if I would bind a complete statement, like;

case s:\for(_,_,_,_): 

would this be the correct type: tuple[list[Expression],Statement]?

public tuple[list[Expression],Statement] showForLoops(loc project) {
 set[loc] files = javaFiles(project);
 set[Declaration] decls = createAstsFromFiles(files, false);
 tuple[list[Expression],Statement] result = [];
visit (decls) {
 case \for(initializers,_,_,body): result += < initializers, body>;
}
return(result);
}


Solution

  • The plain answer is that you have to choose a Statement type like this:

    result = <[], empty()>; // using the empty statement as a default
    

    Note how I did not use a type (it can be inferred)

    You could also write it with a type:

    tuple[list[Expression],Statement] result = <[], empty()>;
    

    There are other ways though to write this code, which you might find interesting.

    The \for constructor itself, can replace the concept of the tuple you required. You can later project out its fields using myForLoop.initializers (for example):

    Statement findFirstForStatement(loc project) {
        decls = createAstsFromFiles(files, false);
        visit(decls) {
           case f:\for(_,_,_,_): return f;
        }
        return empty();
    }
    
    rascal>ff = findFirstForStatement(pr);
    Statement: for(....)
    rascal>ff.initializers
    list[Expression]: [...]
    

    Or you can use a Maybe:

    import util::Maybe;
    
    Maybe[tuple[list[Expression], Statement]] findFirstForLoop(loc project) {
       decls = createAstsFromFiles(files, false);
       visit(decls) {
           case f:\for(_,_,_,_) : return just(f);
       }
       return nothing();
    }
    

    Or, finally, you might throw an exception if you can't find anything:

    Statement findFirstForLoop(loc project) {
       decls = createAstsFromFiles(files, false);
       visit(decls) {
           case f:\for(_,_,_,_) : return f;
       }
    
       throw "couldn't find a for loop";
    }
    

    And a Bonus example collects all the for loops instead of finding the first:

    list[Statement] getAllForLoops(loc project) {
       decls = createAstsFromFiles(files, false);
       result = [];
    
       visit(decls) {
           case f:\for(_,_,_,_) : result += [f];
       }
       return result;
    }
    

    Could also be written as a comprehension:

    list[Statement] getAllForLoops(loc project) {
       decls = createAstsFromFiles(files, false);
       return [ f | /f:\for(_,_,_,_) := decls];
    }