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

Remove restrictions on proc-component-ref #27

Open
cmacmackin opened this issue Oct 20, 2019 · 9 comments
Open

Remove restrictions on proc-component-ref #27

cmacmackin opened this issue Oct 20, 2019 · 9 comments
Labels
Clause 10 Standard Clause 10: Expressions and assignment Fortran 202y Proposals targeting the standard after F2023 unsubmitted Has not been submitted to the committee yet

Comments

@cmacmackin
Copy link

There may be a reason why the standards committee has chosen not to allow this, but I've found it very irritating that a proc-component-ref (R1039 in the draft 2018 standard) requires that the variable on the left-hand-side of the % character be a data-ref (according to C1027). This prevents type-bound function calls being performed on function results, as can be done in pretty much every other object-oriented language. Thus, the following code is illegal:

var = object%get_another_object()%get_yet_another()

Instead, something along the lines of

tmp = object%get_another_object()
var = tmp%get_yet_another()

is required. This is more verbose, especially as you try to chain more and more function calls together. Is there any reason for this restriction?

I would propose changing this. The definition of proc-component-ref could stay the same as before:

R1039  proc-component-ref        is  scalar-variable % procedure-component-name

but C1027 ("the scalar-variable shall be a data-ref that is not a coindexed object") would be amended to

the scalar-variable shall not be a coindexed object.

@FortranFan
Copy link
Member

FortranFan commented Oct 21, 2019

This appears similar to a proposal made last year for Fortran 202X.

Unfortunately that proposal was rejected, the minutes from the standard committee meeting indicate, "Discussion: This means having a part name in a designator being a function reference. Suggested that parsing would not be straightforward. Obvious workaround in the paper SV: 3 - 0 - 10"

@cmacmackin
Copy link
Author

Do you have a link to the paper they reference?

I'm not convinced about the parsing argument. Every other object oriented language manages to have a feature like this and I've written a grammar myself which is capable of that sort of parsing. This feels like (yet another) case of compiler vendors making programmers' lives more tedious and difficult in order to make their lives easier.

@FortranFan
Copy link
Member

Do you have a link to the paper they reference?
..

If I understood correctly, the paper they mention is the proposal itself which lists the use of a temporary which is just like what you mention in the original post here - that appears to be their suggested workaround ..

It's interesting to read of your experience with parsing such grammar: wonder if you can collaborate with @certik et al. at some point in the future, perhaps on LFortran, and prototype your great ideas in an implementation that other users can "play around" with!

@jacobwilliams
Copy link

jacobwilliams commented Oct 22, 2019

Yes, this would be an amazing! Image if we had a nice dynamic string class (see #24) and could do stuff like this:

  type(string) :: s
  type(string),dimension(:),allocatable :: s_array
  s = 'THIS, would, be, Amazing   '
  s_array = s%lower()%split(',')    ! would be: ['this', 'would', 'be', 'amazing']
  write(*,'(*(A,1X))') s_array  ! this would be amazing

I also think the excuses from the committee about why we can't have nice things are becoming very tiresome.

@certik
Copy link
Member

certik commented Oct 22, 2019

Another usecase that I often hit is if a function returns an array, to be able to do things like

f()(5)

Which might be related to this proposal. And unlike in #30 where I can see some downsides, here I don't see any downsides, it seems this proposal just naturally allows what's already in the language.
There are probably some reasons why this is not allowed, and so let's hear the reasons and discuss them.

@jacobwilliams I very well understand your frustration. That was one of the reason why I joined the committee (and I invite you to join as well if you can). What I found out is that the committee is composed of very nice and reasonable people that really care about Fortran, but sometimes the priorities are not well aligned with what should be done. That is one of the goals of this repository for us to brainstorm what we want to get done, and then pick the top 3 to 5 issues and prioritize them at the committee. For example this very issue, as well as #1 are issues that keep bothering me, but I kind of got used to them and so I am very happy that they got brought up, as I think those are some of the low hanging fruits to fix, which might not be that difficult to get agreement in the committee to fix.

@certik certik added Fortran 202y Proposals targeting the standard after F2023 unsubmitted Has not been submitted to the committee yet labels Oct 22, 2019
@cmacmackin
Copy link
Author

Yes, array access on a function result would also be useful, although I feel like that could potentially pose more issues with ambiguity in the language grammar, given that functions calls and array access both use parentheses (regrettably).

I don't buy the argument that chaining function calls together is difficult to parse. In fact, my experience was that it is easier to allow the parser to process that than to try writing a grammar that restricts it. While I see that the LFortran grammar would not accept chaining function results together like this, it also can not recognize all allowable calls to type-bound functions. The standard specifcies that something like

a = object%array_component(1)%function_call(1.5, 2.0)

is valid. It is far simpler to write a grammar which can recognize that and chaining together function results than one which can only recognize calling a type-bound function after array access.

I'm currently away from my laptop, where I've been experimenting with a grammar, but once I'm back home this evening I can post the relevant portion of it.

@certik
Copy link
Member

certik commented Oct 22, 2019

Another possibly related issue is #14. If results of a function can be used, then that could allow things like:

diag(A) = 1

Regarding the grammar, I agree, it's probably not difficult to parse. The latest LFortran grammar is in here: https://gitlab.com/lfortran/lfortran/blob/a2707be7386e57dc62ec9e1005a570cde2fc5b70/src/lfortran/parser/parser.yy if you want to play with it.

@FortranFan
Copy link
Member

FortranFan commented Oct 22, 2019

Another possibly related issue is #14. If results of a function can be used, then that could allow things like:

diag(A) = 1

..

@certik,

With respect to all the issues being reported here, you are an excellent moderator in bringing all the sides to the discussion like in your response to @jacobwilliams above. Hats off to you for that! I often allow my own frustration with Fortran to "boil over" and among my reasons for that include what I believe are the inconsistencies in both the semantics offered in the current version standard wrt the objections raised for new facilities as well as the disconnects in the work process to get new items added to the language like those in the list for Fortran 202X (more on this later elsewhere).

By the inconsistency in semantics, you will know the language already allows instructions such as

   diag(A) = 1

It's just that certain conditions need to be met which are essentially that A must either be a simply contiguous target or a contiguous pointer. Here's an example:

   integer, parameter :: N = 3
   integer, target :: A(N,N) !<-- mat is "simply contiguous"
   integer :: i, j

   A = reshape( [( (10*j + i, i=1,N ), j=1,N) ], [N, N])
   print *, "A before diagonal reset:"
   do i = 1, size(A,dim=1)
      print "(*(g0,1x))", A(:,i)
   end do

   diag(A) = 1

   print *, "A after the diagonal reset to unity:"
   do i = 1, size(A,dim=1)
      print "(*(g0,1x))", A(:,i)
   end do

contains

   function diag(Mat) result(r)

      ! Argument list
      integer, contiguous, target :: Mat(:,:)
      ! Function result
      integer, pointer :: r(:)

      ! Local variables
      integer, pointer :: FlattenedMat(:)

      ! Flatten the matix
      FlattenedMat(1:size(Mat,dim=1)*size(Mat,dim=2)) => Mat
      r => FlattenedMat(::size(A,dim=1)+1)

      return

   end function

end

Now gfortran does not support the above example, but I believe it is standard-conforming and it works with another compiler. Upon execution, the above example produces:

 A before diagonal reset:
11 12 13
21 22 23
31 32 33
 A after the diagonal reset to unity:
1 12 13
21 1 23
31 32 1

So my point is several of the concepts, semantics, and syntax e.g., auto-targeting, references (pointers) in any variable-definition context, etc. which can help what's being in the proposed in the original post here have already made it into the standard.

Thus in my mind the objections such as those that lead to rejections of the paper 18-134 are either half-baked or non-technical or both and it's only Fortran that suffers. It's a race out there and lots and lots of codebases are permanently being lost to Fortran.

Things are getting too far delayed needlessly and features delayed are features denied to persevering practitioners of Fortran.

Hence my constant refrain to accelerate certain aspects of the standard development and to establish better and more CONSISTENT and OBJECTIVE criteria to guide the development of the standard. Among these must be the idea to limit the objections by processor implementors on non-technical grounds (e.g., scope) until and unless they are firmly "holding their own feet to the fire" in terms of achieving standard-compliance per some reasonable schedule. Right now it's having both ways "have your cake and eat it too": implementations will not promise nor adhere to any schedule in terms of compliance (it can take decades to get a feature in) but yet get to override good proposals on the basis of scope. That does not seem fair in any way to all the Fortranners out there.

Anyways, yours and @zjibben's initiative with GitHub here is an excellent step in the right direction.

@cmacmackin
Copy link
Author

I've been experimenting with a Fortran grammar implemented using the Lark library (see here for a summary of the grammar syntax). While it is not complete yet, I've made some decent progress. The relevant bit to this discussion is

?primary_expr : primary_expr "(" [paren_contents] ")" -> parentheses_access
	      | primary_expr "%" NAME -> component_access
	      | primary_expr image_selector -> coarray_access
	      | _primary
_primary : literal_constant | NAME | array_constructor | "(" expr ")"

@certik certik added the Clause 10 Standard Clause 10: Expressions and assignment label Apr 23, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Clause 10 Standard Clause 10: Expressions and assignment Fortran 202y Proposals targeting the standard after F2023 unsubmitted Has not been submitted to the committee yet
Projects
None yet
Development

No branches or pull requests

4 participants