Facing problem towards understanding generics

I was looking at the wikipedia page for jagged arrays and thought to try it out using the new generics feature, as the below code is more like a copy paste job :sweat_smile:.

module A
  public :: jagged_type
  
  requirement r(T)
    type :: T; end type
  end requirement
   
  template type_t(T)
    requires r(T)
    
    type :: jagged_type
      type(T), allocatable :: row(:)
    end type jagged_type    
  end template  
end module A

program test
 use :: A
 instantiate type_t(integer)
 
 type(jagged_type) :: jagged(2)
 jagged(1)%row = [1, 2]
 jagged(2)%row = [(i, i = 1, 5)]
 
 print *, jagged(2)%row
end program test

Is the above code alright, as the lfortran compiler is issuing the following error

syntax error: Token 'end' is unexpected here
 --> input:7:3
  |
7 |   end requirement
  |   ^^^ 

If the above code is ok, do I use it for character type like this

instantiate type_t(character(len=:)), only: jagged_char => jagged_type
type(jagged_char) :: ragged
ragged%row = ['a', 'hoho']

Thank you for the help

I rearranged it to the following in hopes of avoiding the current compiler limitations:

module A
  private
  public :: example
  
  template type_t(T)
    type :: T; end type
    private
    public :: jagged_type
    
    type :: jagged_type
      type(T), allocatable :: row(:)
    end type jagged_type    
  end template
contains
  subroutine example
   instantiate type_t(integer), only: jagged_type
 
   type(jagged_type) :: jagged(2)
   jagged(1)%row = [1, 2]
   jagged(2)%row = [(i, i = 1, 5)]
 
   print *, jagged(2)%row
  end subroutine
end module A

program test
 use :: A, only: example
 call example
end program test

unfortunately it gives me the following error message, which I don’t fully understand why.

semantic error: Number of template arguments don't match
  --> input:15:4 - 16:2
   |
15 |       instantiate type_t(integer), only: jagged_type
   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^...
...
   |
16 |     
   | ...^^ 

However, to address you follow on question:

The answer is unfortunately no. Assumed or deferred kind or length type parameters are not allowed as type-spec actual template arguments. If you want support for arrays of varying length strings though, I’ve already got that implemented as iso_varying_string.

1 Like

Thank you for the solution. I also came across this problem to not being able to compile when I try to ran my program.

Can you please tell me in laymen terms why is this so?

Thank you.

If it’s correct code, please report bugs into our github issue tracker.

The template feature in LFortran is a prototype, so it’s very fragile.

If I understood the comment by @everythingfunctional above than I think so that first code is correct and second is a variation to by pass the limitation of lfortran but even it also not worked. If it can be confirmed I will report this issue and report back here, if that is alright.

@everythingfunctional can you please confirm @AniruddhaDas’s comment?

@AniruddhaDas, indeed, if Brad agrees, then if you could report it, that would be awesome. We’ll fix it.

1 Like

Yes, I believe the example I show should be valid.

1 Like

You end up right back in the middle of the problem you’re trying to solve.

I.e. this character(len=:) :: x is not allowed, so

template foo(T)
contains
  subroutine bar
    type(T) :: x
  end subroutine
end template

instantiate foo(character(len=:))

would instantiate invalid code. Basically, the only valid type-spec for all possible declarations (including non-allocatable, non-pointer scalar variables) is one with no deferred or assumed length or kind type parameters.

1 Like

Awesome, thanks @everythingfunctional. @AniruddhaDas please go ahead and report it. Copy the examples above and show the error messages. We’ll fix it.

1 Like

@certik I have open an issue with the number #1086. Please see if there is anything wrong or it need some improvement.

@everythingfunctional thank you so much for the explanation.

1 Like