cloudfier icon indicating copy to clipboard operation
cloudfier copied to clipboard

generation of null-safe expressions involving Java Optional

Open abstratt opened this issue 6 years ago • 1 comments

Should use Java Optional to implement null-safe object navigation.

Examples:

operation f1(a : Foo[0,1]) :Integer;
begin
    var x : String[0,1];
    x := self.attr1;
    return a?.m2(!!x, 3) ?: -1;
end;

Java code:

String x = this.getAttr1();
return Optional.ofNullable(a)
    .map(it -> 
        it.m2(Object.requireNotNull(x), 3)
    )
.orElseGet(
    () -> -1
);

Action breakdown:

/* AddVariableValue: x */ x :=
        /* ReadSelfAction */ self 
            /* ReadStructuralFeatureValue: attr1 */ .attr1
;

/* AddVariableValue: _result */ return
    /* ConditionalNode «DefaultValueExpression» -> Integer[1,1] */
        /* Clause 0 */
            /* Body */
                /* ReadVariable: a -> Foo[0,1] */ a
                    /* CallOperation: m1 -> Integer[0,1] */ ?.m2(
                        /* SAN «Cast Required» -> Integer[1,1] */
                            /* ReadVariable: x Integer[0,1] */,
                        /* LiteralValueSpecification: 3 -> Integer[1,1] */ 3
        /* Clause 1 */    
            /* Body */
                /* LiteralValueSpecification: -1 -> Integer[1,1] */ -1
        );

abstratt avatar Mar 11 '19 18:03 abstratt

Design notes

Cases where an optional should be used

elvis operator

expr1 ?: expr2

If exp2 is required:

Optional.of(expr1).orElseGet(() -> expr2)

If expr2 is optional:

Optional.of(expr1).or(() -> expr2)

Operation call or attribute access

foo := bar?.mtd1()?.attr2;

Turns into:

foo = Optional.ofNullable(bar).map(it -> it.mtd1()).map(it -> it.attr2).orElse(null);

Cases where an already-built optional should be assumed

Where the first input action requires an optional.

Cases where optionals should be resolved

elvis operator where fallback expression is required

var x : Integer, y : Integer[0,1];
x := y ?: 2;

Turns into:

Optional.ofNullable(y).orElseGet(() -> 2)

or

Optional.ofNullable(y).orElse(2)

Any case where an optional would be consumed by a non-optional bearing target

A chain of optionals starts when a sequence of features (method/attribute) accesses occurs in a chain (where the result of an optional expression is the target object of CallOperation or ReadStructuralFeature). So, if such chain is consumed by any other action, at this point, a resolution of the optional is required.

Solution

TBD

abstratt avatar Mar 12 '19 17:03 abstratt