Hi Tobias,

On Mon, Sep 8, 2025 at 10:54 PM Tobias Burnus <[email protected]> wrote:
> * * *
>
> >>> +  if (true_expr->rank != false_expr->rank)
> >>> +    {
> >>> +      gfc_error ("true_expr at %L and false_expr at %L in conditional "
> >>> +                "expression must have the same rank",
> >>> +                &true_expr->where, &false_expr->where);
> >>> +      return false;
> >>> +    }
> >> I wonder whether 'true_expr' / 'false_expr' are the best wording; Fortran
> >> itself just has:
> >>
> >> "R1002 conditional-expr is ( scalar-logical-expr ? expr
> >>                               [ : scalar-logical-expr ? expr ]... : expr )
> >> "C1004 Each expr of a conditional-expr shall have the same declared type, 
> >> kind
> >>          type parameters, and rank."
> >>
> >> and
> >>
> >> "Evaluation of a conditional-expr evaluates each scalar-logical-expr in
> >>    order, until the value of a scalar-logical-expr is true, or there are
> >>    no more scalar-logical-exprs. If the value of a scalar-logical-expr is
> >>    true, its subsequent expr is chosen; otherwise, the last expr of the
> >>    conditional-expr is chosen. The chosen expr is evaluated, and its
> >>    value is the value of the conditional expression."
> >>
> >> I wonder whether we shouldn't just use 'expr' without true_/false_
> >> prefix; I am especially stumbling over the underscore but also
> >> "true/false expr" sounds a bit odd.
> > I'm open to different naming. In the GCC C frontend, the
> > build_conditional_expr function uses op1 and op2, while the Clang AST
> > uses an expression array with COND, LHS, and RHS
>
> Note: I am not talking about the internal name - I am totally fine with
> true_expr and false_expr.
>
> I am talking about the wording presented to the Fortran user, who
> will see the compiler error message.
>
> Thus, "+  if (true_expr->rank != false_expr->rank)" is perfectly fine
> with me.
>
> But instead of:
>
> Error: true_expr at (1) and false_expr at (2) in conditional expression must 
> have the same rank
>
> I wonder whether it would be more Fortran like (without loosing
> information) to say:
>
> Error: expr at (1) and expr at (2) in conditional expression must have the 
> same rank
>
>
> which avoids the underscore and true/false prefix.
>

Yeah, that makes sense. Fixed.

> * * *
>
> BTW, just thinking about it: When simplifying, I wonder
> whether we want to have a special case for
>    cond ? expr1 : expr1
>
> Namely, condition is only known at runtime but both expressions are
> identically? I think gfc_dep_compare_expr (...) == 0 does this.
> (If you add it, please re-check that my claim is correct.)
>

It seems like a good optimization to me. However, our current
implementation already seems to have this capability. When I attempt
to use `i > 0 ? j : j` and view the output using dump-tree-original, I
only see `i = j`. My initial assumption is that COND_EXPR will perform
this transformation for simple scalar types that we currently support.
I believe we will need this optimization for future complex types, so
perhaps we should hold this until we actually need this part.

For gfc_dep_compare_expr, yes returning 0 indicates that the two
expressions are identical.

> * * *
>
> > I'm not sure if I'm understanding you correctly here. Are you
> > suggesting we treat the conditional expression as a special case for
> > EXPR_OP (the ternary operator)?
> > My initial thought, which isn't fully developed, is to store a nullptr
> > for the nil in the AST. However, this would require a null check every
> > time we use the true/false expr...
>
> Not as ternery operator, only for .NIL.:
>
> I was wondering about .NIL. as an operator that takes 0 expressions
> with it - contrary to .NOT. that takes one (unary) and .AND. that takes
> two (binary). - I got the idea because of the '.<something>.' it looks
> very much like an operator and fits into the parser for operators.
>
> But I have not thought whether that has additional implications or
> how many code changes it requires.
>
> Your idea of using nullptr is also interesting - and at a first glance,
> should work. On the second thought, wouldn't this have issues (a) for
> the diagnostic if gfc_expr == nullptr as there is also no expr->where
> in that case. Additionally, (b) condition is known at compile time,
> the might simplify to nullptr - which has issues. Having a special
> case for EXPR_CONDITIONAL is fine - as it is localized, but adding
> it elsewhere is a problem, especially as we already have several
> null values in Fortran:
>
> At least null(), c_null_ptr, and c_null_funptr come into my mind.
> And  '(cond ? c_null_ptr : .nil.)' looks like a valid expression,
> depending on the associated dummy argument.
>
> If you can get it working, having a nullptr for .NIL. works for me,
> but I fear it won't work out and (too) many hacks are required.
>
>
> But I am not sure whether there is a better third solution or whether
> we can get one of the two ideas (.NIL. as EXPR_OP or as nullptr working).
>

Yeah, you convinced me. Just using a nullptr doesn't seem to work.
I came up with another idea: using a gfc_expr with type
EXPR_CONDITIONAL and a condition of nullptr (actually cond/true/false
could all be nullptr).
For any valid cond-expr, the condition must be a valid
scalar-logical-expr. So using a nullptr cond to indicate a .NIL. seems
safe. It is also localized, no need to touch the EXPR_OP part. Not
sure if this will have any bad case, though.

* * *

BTW, the newly attached patch has a properly wrapped commit message : )

Thanks,
Yuao

Attachment: 0001-fortran-implement-conditional-expression-for-fortran.patch
Description: Binary data

Reply via email to