Search code examples
transformationrascal

How do I select an the first element in a list of an optional sort while transforming using the ADT?


Is there a way to select the head of a list of an optional term while transforming such that if it exists you get the element else you get an empty string or the result of calling the function doesn't return anything? For example, if you had the ADT:

data TakeAction = set(list[OptVal] opt, str expandedId, NumVal numVal)

which corresponded with the syntax:

syntax TakeAction = set: SET OptVal? EXPANDEDID NumVal

and you try to write a function like so:

public str prettyTakeAction(TakeAction::set(list[OptVal] opt, str expandedId, NumVal numVal)) = "SET <prettyOptVal(opt)><expandedId> = <prettyNumVal(numVal)>";

where

public str prettyOptVal(OptVal::optVal()) = "OPTIONAL"

When I try this out, If I omit the OPTIONAL, I get an error, for example

SET a = 8 will throw an error, while SET OPTIONAL a = 3 will work


Solution

  • At the moment we do not have a very clean solution for this but the following hack is being used.

    The idea is to (mis?)use the enumeration operator (<-) that will succeed when the option is present and it will fail otherwise. The following tests illustrate this:

    syntax OptTestGrammar = A? a B b;
    
    syntax A = "a";
    syntax B = "b";
    
    layout L = " "*;
    
    test bool optionalNotPresentIsFalse() = !((A)`a` <- ([OptTestGrammar] "b").a);
    test bool optionalPresentIsTrue() = (A)`a` <- ([OptTestGrammar] "ab").a;
    

    This can easily be applied to your example. Hope this solves your problem.