Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

generation of null-safe expressions involving Java Optional #256

Open
abstratt opened this issue Mar 11, 2019 · 1 comment
Open

generation of null-safe expressions involving Java Optional #256

abstratt opened this issue Mar 11, 2019 · 1 comment

Comments

@abstratt
Copy link
Owner

abstratt commented Mar 11, 2019

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
Copy link
Owner Author

abstratt commented Mar 12, 2019

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant