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

LET statement concept #279

Open
klausler opened this issue Jul 19, 2022 · 4 comments
Open

LET statement concept #279

klausler opened this issue Jul 19, 2022 · 4 comments

Comments

@klausler
Copy link

klausler commented Jul 19, 2022

The LET statement is proposed as a single solution for several needs identified in other issues: fixing implicit SAVE on initialized variables, adding immutable objects, "auto" type and shape inference, and fixing the scope and semantics of ASSOCIATE. LET statements could replace many local variable and pointer declarations, and all instances of ASSOCIATE. It might have particularly useful applications in interactive environments.

let-stmt ::= LET [, let-attr-list] :: let-decl-list
let-attr ::= declaration-type-spec | MUTABLE | PROCEDURE ( [ proc-interface ] ) | POINTER
let-decl ::= name = expr | name => data-target | name => proc-target

The doubled colons are not optional.

The LET statement would be an executable statement (namely a new "action-stmt"), not a specification statement. It introduces one or more new names into the enclosing block or execution-part. The scope of each name extends to the end of the enclosing block or execution-part, but does not include any inner subprograms -- i.e., LET names cannot be host-associated into subprograms. By "block" here, I do indeed mean the term as it is defined by the standard, and intentionally imply that LET names, unlike anything else in Fortran, are scoped by IF and DO and other constructs, not just BLOCK constructs. An initialization expression may contain a reference to a previous LET name from earlier in the same LET statement.

The names declared in a LET statement may not already be in use in the enclosing block or executable-part. The names may not appear in DATA or NAMELIST or EQUIVALENCE. The names do not have the SAVE or TARGET attributes, and cannot be coarrays. When LET names are referenced in DO CONCURRENT, they implicitly have LOCAL_INIT locality.

Each name in a LET statement declares and initializes a variable or pointer. The type can be explicit (LET,INTEGER::N=666), in which case conversions apply, or is inferred from the dynamic type of the initializer (LET::A=FOO()). The shape is inferred from the initialization; no explicit or assumed or deferred bounds may appear. The interface of a procedure pointer can be explicit, or it can be inferred when the proc-target has an explicit interface.

The attribute MUTABLE allows the names to appear in a variable definition context, which would otherwise be prohibited.

There will be constraints and/or requirements on control flow in the containing scope; it is not conforming to jump "over" a LET statement and then reference one of its names later if it remains uninitialized.

(Obvious constraints on incompatible attributes and the semantics of finalization are left as exercises.)

(EDITS: removed PARAMETER attribute and null-init initialization -- they are not essential to the idea.)

@rouson
Copy link

rouson commented Jul 19, 2022

I'm adding a comment to link this to #221. @klausler @everythingfunctional feel free to remove this comment if the two are unrelated.

@ashe2
Copy link

ashe2 commented Jul 19, 2022

This is a very nice solution to the concerns mentioned above. It also allows for variables to be declared where they are used, which is a style many people prefer.

Some syntax alternatives:

  • Use VARIABLE rather than MUTABLE -- the term "variable" appears many times in the standard and "mutable" (and "immutable") aren't used at all.
  • Or follow the example of Scala and Kotlin and replace LET with VAL for the immutable case and VAR for the mutable case.

@certik
Copy link
Member

certik commented Jul 19, 2022

I think this is a good idea overall.

I've been going back and forth on this, because I actually do not like the "auto" feature in C++. However, for interactive usage (say in LFortran) having "let" actually would be very handy. What I had in mind was to introduce an --infer command line option that would allow you to do x = 5 and it would be equivalent to let x = 5. One would optionally use --infer in interactive mode, but not in production non-interactive mode. But having let in the language is better than the --infer option because:

  • You can copy and paste the code from an interactive session into production code without modifications (for --infer I was planning to have LFortran rewrite your code to insert declarations as needed, but that's less ideal); You can still automatically rewrite the code if you want to, but you don't need to
  • It would work with any Fortran compiler, it would be standard Fortran
  • No special command line option needed (that is always preferable)
  • let is backwards compatible

Regarding my own objections to let in Fortran and auto in C++: it would be more for interactive use, and it does not have to be encouraged for production code if you do not like it. For a production code base, one could use compiler options to disable certain features that the given code base does not like (one can run this at continuous integration, so that pull requests from 3rd party contributors would fail if they use let, and so one does not need to lose any time arguing over it).

Conclusion: I think this proposal might work.

@ashe2
Copy link

ashe2 commented Jul 20, 2022

I've been going back and forth on this, because I actually do not like the "auto" feature in C++.

A nice feature of this proposal is that you can provide an explicit type if you want to. You still get all of the benefits apart from type inference: initialized variables without SAVE, immutable objects that don't have to be initialized with compile-time constants, declarations close to use.

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

4 participants