checking for self-assignment in fortran overloaded assignment - operator-overloading

I am trying to implement a polynomial class with fortran 2003, with overloaded arithmetic operations and assignments. The derived type maintains allocatable list of term definitions and coefficients, like this
type polynomial
private
type(monomial),dimension(:),allocatable :: term
double precision,dimension(:),allocatable :: coef
integer :: nterms=0
contains
...
end type polynomial
interface assignment(=)
module procedure :: polynomial_assignment
end interface
...
contains
elemental subroutine polyn_assignment(lhs,rhs)
implicit none
type(polynomial),intent(???) :: lhs
type(polynomial),intent(in) :: rhs
...
I had to make it elemental because this is intended to be used as matrices of polynomials. That does work, for the most cases at least. However, I somehow got myself into concerns about self-assignment here. One can simply check the pointers to see if things are the same in C++, but it doesn't seem to be an option in Fortran. However the compiler do detect the self-assignment and gave me a warning. (gfortran 4.9.0)
When I have intent(out) for lhs, the allocatable entries for both lhs and rhs appeared to be deallocated on entry to the subroutine, which made sense since they were both p, and an intent(out) argument would first be finalized.
Then I tried to avoid the deallocation with an intent(inout), and check self-assignment by modifying one field in the lhs output
elemental subroutine polyn_assignment(lhs,rhs)
implicit none
type(polynomial),intent(inout) :: lhs
type(polynomial),intent(in) :: rhs
lhs%nterms=rhs%nterms-5
if(lhs%nterms==rhs%nterms)then
lhs%nterms=rhs%nterms+5
return
end if
lhs%nterms=rhs%nterms
Well, now this is what surprised me. When i do
p=p
It didn't make the test and proceeded, giving me a polynomial with 0 terms but no memory violations. Confused, I printed lhs%nterms and rhs%nterms inside the assignment, only to find that they are different!
What is even more confusing is that when I did the same thing with
call polyn_assignment(p,p)
It works perfectly and detected that both arguments are the same. I am puzzled how an interface of a subroutine can run differently from the subroutine itself.
Is there something special about assignment in Fortran 2003 that I've missed?
(First time to ask a question here. Please correct me if i didn't do it right.)

If you have a statement a = b that invokes defined assignment via a subroutine sub, the assignment statement is equivalent to call sub(a, (b)). Note the parentheses - the right hand side argument is the result of evaluating a parenthesised expression and is therefore not conceptually the same object as b. See F2008 12.4.3.4.3 for details.
Consequently, a = a is equivalent to call sub(a, (a)). The two arguments are not aliased. It is different from call sub(a,a), the latter may (depending on the specifics of the internals of sub, including dummy argument attributes) break Fortran's argument aliasing rules (e.g. in your example, a statement such as call polyn_subroutine(a,a) is illegal).

Related

PureScript - Inferred Type Causes Compiler Warning

Consider the following simple snippet of PureScript code
a :: Int
a = 5
b :: Int
b = 7
c = a + b
main ∷ Effect Unit
main = do
logShow c
The program successfully infers the type of C to be Int, and outputs the expected result:
12
However, it also produces this warning:
No type declaration was provided for the top-level declaration of c.
It is good practice to provide type declarations as a form of documentation.
The inferred type of c was:
Int
in value declaration c
I find this confusing, since I would expect the Int type for C to be safely inferred. Like it often says in the docs, "why derive types when the compiler can do it for you?" This seems like a textbook example of the simplest and most basic type inference.
Is this warning expected? Is there a standard configuration that would suppress it?
Does this warning indicate that every variable should in fact be explicitly typed?
In most cases, and certainly in the simplest cases, the types can be inferred unambiguously, and indeed, in those cases type signatures are not necessary at all. This is why simpler languages, such as F#, Ocaml, or Elm, do not require type signatures.
But PureScript (and Haskell) has much more complicated cases too. Constrained types are one. Higher-rank types are another. It's a whole mess. Don't get me wrong, I love me some high-power type system, but the sad truth is, type inference works ambiguously with all of that stuff a lot of the time, and sometimes doesn't work at all.
In practice, even when type inference does work, it turns out that its results may be wildly different from what the developer intuitively expects, leading to very hard to debug issues. I mean, type errors in PureScript can be super vexing as it is, but imagine that happening across multiple top-level definitions, across multiple modules, even perhaps across multiple libraries. A nightmare!
So over the years a consensus has formed that overall it's better to have all the top-level definitions explicitly typed, even when it's super obvious. It makes the program much more understandable and puts constraints on the typechecker, providing it with "anchor points" of sorts, so it doesn't go wild.
But since it's not a hard requirement (most of the time), it's just a warning, not an error. You can ignore it if you wish, but do that at your own peril.
Now, another part of your question is whether every variable should be explicitly typed, - and the answer is "no".
As a rule, every top-level binding should be explicitly typed (and that's where you get a warning), but local bindings (i.e. let and where) don't have to, unless you need to clarify something that the compiler can't infer.
Moreover, in PureScript (and modern Haskell), local bindings are actually "monomorphised" - that's a fancy term basically meaning they can't be generic unless explicitly specified. This solves the problem of all the ambiguous type inference, while still working intuitively most of the time.
You can notice the difference with the following example:
f :: forall a b. Show a => Show b => a -> b -> String
f a b = s a <> s b
where
s x = show x
On the second line s a <> s b you get an error saying "Could not match type b with type a"
This happens because the where-bound function s has been monomorphised, - meaning it's not generic, - and its type has been inferred to be a -> String based on the s a usage. And this means that s b usage is ill-typed.
This can be fixed by giving s an explicit type signature:
f :: forall a b. Show a => Show b => a -> b -> String
f a b = s a <> s b
where
s :: forall x. Show x => x -> String
s x = show x
Now it's explicitly specified as generic, so it can be used with both a and b parameters.

Fortran Select Type with arrays [duplicate]

My question is, "Can a select type block be used to distinguish real :: realInput from real :: realArrayInput(:)?" It's clear how select type may be used to distinguish derived types, but becomes less clear to me how (or whether) it may be used on intrinsic types.
In Mad Libs form, can the blanks be filled in below to distinguish between the inputs above:
select type (input)
type is (real)
print *, "I caught the realInput"
type is (___________)
print *, "I caught the realArrayInput"
end select
I've found some related posts that did not quite contain the answer I was hoping for:
Select Type Issues
Determining Variable Type
No. input is either declared as an array or a scalar, even when it is polymorphic (and even when it is unlimited polymorphic).
The recent further interoperability with C TS (which may be part of F201X) introduced the concept of assumed rank and the RANK intrinsic, which may do what you want. But there are many limitations around what can be done with assumed rank objects. And regardless of that SELECT TYPE still only works on type. The syntax of the select type construct simply doesn't permit specification of rank in the type guard statements.
Obviously depending on what it is that you actually want to do (?) ... and beyond generic interfaces mentioned by others, a way to have objects that can be either array or scalar in current Fortran (there are other possibilities) is to use derived type wrappers that are an extension of a common parent type. You then use a polymorphic object declared as the parent type (or you can use an unlimited polymorphic object) to refer to an object of the relevant derived type.
TYPE :: parent
END TYPE parent
TYPE, EXTENDS(parent) :: scalar_wrapper
REAL :: scalar_component
END TYPE scalar_wrapper
TYPE, EXTENDS(parent) :: array_wrapper
REAL :: array_component(10)
END TYPE array_wrapper
...
SUBROUTINE what_am_i(object)
! Note that object is scalar, but that doesn't tell us
! the rank of the components of the dynamic type of object.
CLASS(parent), INTENT(IN) :: object
!****
SELECT TYPE (object)
TYPE IS (scalar_wrapper)
PRINT "('I am a scalar with value ',G0)", &
object%scalar_component
TYPE IS (array_wrapper)
PRINT "('I am an array with values ',*(G0,:,','))", &
object%array_component
CLASS DEFAULT
PRINT "('I am not sure what I am.')"
END SELECT
END SUBROUTINE what_am_i
Just to combine IanH's anwser and M.S.B's comment and explain more in detail: You can not use the select type construct to distinguish between real scalars and real arrays as they only differ in their dimension, but not in their type. When you declare your variable input, you already decide 'for ever', whether it has or it has not the dimension attribute:
class(*) :: input_scalar
class(*), dimension(10) :: input_array
Whichever value the variable takes later (or to whichever object it points to, if it is a pointer), it can not represent something with a dimensionality (rank) different from the one in its declaration.
On the other hand, you could for example use the interface construct (or generic in type bound procedures) to distinguish between objects of the same type but different ranks. The example below demonstrates that for scalar and rank one integer and real arrays.
module testmod
implicit none
interface typetest
module procedure typetest0, typetest1
end interface typetest
contains
subroutine typetest0(object)
class(*), intent(in) :: object
select type(object)
type is (real)
print *, "real scalar"
type is (integer)
print *, "integer scalar"
end select
end subroutine typetest0
subroutine typetest1(object)
class(*), dimension(:), intent(in) :: object
select type(object)
type is (real)
print *, "real array"
type is (integer)
print *, "integer array"
end select
end subroutine typetest1
end module testmod
program test
use testmod
implicit none
integer :: ii
integer, dimension(10) :: iarray
call typetest(ii) ! invokes typetest0
call typetest(iarray) ! invokes typetest1
end program test

Interfaces in Fortran

I stumbled over a particular problem with interfaces while debugging some code, where a called subroutine has a dummy argument of rank 2 but an actual argument of rank 1. The resulting difference in the arguments resulted in an invalid read.
To reproduce I created a small program (ignore the comments ! <> for now):
PROGRAM ptest
USE mtest ! <>
IMPLICIT NONE
REAL, ALLOCATABLE, DIMENSION(:) :: field
INTEGER :: n
REAL :: s
n = 10
ALLOCATE(field(n))
CALL RANDOM_NUMBER(field)
CALL stest(n, field, s)
WRITE(*,*) s
DEALLOCATE(field)
END PROGRAM
and a module
MODULE mtest ! <>
IMPLICIT NONE ! <>
CONTAINS ! <>
SUBROUTINE stest(n, field, erg)
INTEGER :: n
REAL, DIMENSION(n,n) :: field
REAL :: erg
erg = SUM(field)
END SUBROUTINE
END MODULE ! <>
As far as I understand, this subroutine gets an automatic (explicit?) interface from being placed in the module. The problem is, that the actual field has length 10, while the subroutine sums a field of length 10x10=100 which is clearly visible in valgrind as an invalid read.
Then I tested this same code without the module, i.e. all lines marked with ! <> got removed/commented. As a result, gfortran's -Wimplicit-interface threw a warning, but the code worked as before.
So my question is: What is the best way, to deal with such a situation? Should I always place a generic interface à la
INTERFACE stest
MODULE PROCEDURE stest
END INTERFACE
in the module? Or should I replace the definition of field with an deferred-shape array (i.e. REAL, ALLOCATABLE, DIMENSION(:,:) :: field)?
EDIT: To be more precise on my question, I don't want to solve this particular problem, but want to know, what to do, to get a better diagnostic output from the compiler.
E.g. the given code doesn't give an error message and does, in principle, produce a segmentation fault (though, the code doesn't notice it). Placing a generic interface produces at least an error, complaining, that no matching definition for stest is found, which is also not really helpful, especially in the case, where you don't have the source code. Only a deferred-shape array resulted in an understandable error message (rank mismatch).
And this is, were I'm wondering, why the automatic module interface doesn't give a similar warning/error message.
The compiler cannot warn you, because the code is legal! You just pass wrong n and a non-square number of points. For explicit shape arrays you are responsible for correct dimensions. Consider
ALLOCATE(field(1000))
CALL stest(10, field, s)
this code will work although the number of elements of the actual and dummy arguments is not the same. Maybe suggest to gfortran developers to check whether the dummy argument is not larger, but I am not sure how difficult that is.
The generic interface causes the compiler to check the TKR rules. No sequence association of arrays of different rank is allowed and the compilation will fail. Therefore it will disable all legal uses of passing arrays of different rank to explicit shape and assumed size dummy arguments and limit your possibilities.
What is the solution? Use explicit shape arrays for situations they are good for and use assumed shape arrays otherwise (possibly with the contiguous attribute). The generic interface might help too, but changes the semantics and limits the possible use.

Module calling an external procedure with implicit interface

The following code, combining module procedures and external procedures:
module module_dummy
implicit none
contains
subroutine foo(a)
real, intent(inout) :: a(:)
call bar(a)
end subroutine foo
end module module_dummy
program main
use module_dummy
implicit none
integer, parameter :: nelems = 100000000
real, allocatable :: a(:)
allocate( a(nelems) )
a = 0.0
call foo(a)
print *, a(1:10)
deallocate(a)
end program main
subroutine bar(a)
implicit none
real, intent(inout) :: a(:)
a = 1.0
end subroutine bar
seems to fail either:
with a segmentation fault
printing a block of 0.000 instead of a block of 1.000
on any platform I have tried so far. The problem is related to the implicit interface declaration of bar, and in fact the issue can be solved adding in any way an explicit interface, e.g. using:
module module_dummy
implicit none
contains
subroutine foo(a)
interface
subroutine bar(x)
real, intent(inout) :: x(:)
end subroutine bar
end interface
real, intent(inout) :: a(:)
call bar(a)
end subroutine foo
end module module_dummy
or declaring bar inside a module to be used by module_dummy.
Anyhow I really don't understand what is the error in the first place. What I have found on the Fortran 90 standard (sec. 12.3.2.4) says that:
The type, type parameters, and shape of dummy arguments of a procedure
referenced from a scoping unit where the interface of the procedure is
implicit must be such that the actual arguments are consistent with
the characteristics of the dummy arguments.
In this case the rule seems to be respected, as a is always declared as
real, intent(inout) :: a(:)
So, what am I missing in the interpretation of the standard that makes the previous code wrong?
Dummy arguments that are assumed shape must have an explicit interface at their point of reference. F90 12.3.1.1 item 2c.
Practically, assumed shape arrays are passed by passing a descriptor - a little structure that describes the bounds and the location of storage of the array. Ye-olde F77 explicit shape and assumed size arrays are passed simply by passing the address of the first element. Without the explicit interface the compiler doesn't know that it needs to build and pass the descriptor - hence chaos and confusion results.

How can I reuse definition (AST) subtrees in a macro?

I am working in a Scala embedded DSL and macros are becoming a main tool for achieving my purposes. I am getting an error while trying to reuse a subtree from the incoming macro expression into the resulting one. The situation is quite complex, but (I hope) I have simplified it for its understanding.
Suppose we have this code:
val y = transform {
val x = 3
x
}
println(y) // prints 3
where 'transform' is the involved macro. Although it could seem it does absolutely nothing, it is really transforming the shown block into this expression:
3 match { case x => x }
It is done with this macro implementation:
def transform(c: Context)(block: c.Expr[Int]): c.Expr[Int] = {
import c.universe._
import definitions._
block.tree match {
/* {
* val xNam = xVal
* xExp
* }
*/
case Block(List(ValDef(_, xNam, _, xVal)), xExp) =>
println("# " + showRaw(xExp)) // prints Ident(newTermName("x"))
c.Expr(
Match(
xVal,
List(CaseDef(
Bind(xNam, Ident(newTermName("_"))),
EmptyTree,
/* xExp */ Ident(newTermName("x")) ))))
case _ =>
c.error(c.enclosingPosition, "Can't transform block to function")
block // keep original expression
}
}
Notice that xNam corresponds with the variable name, xVal corresponds with its associated value and finally xExp corresponds with the expression containing the variable. Well, if I print the xExp raw tree I get Ident(newTermName("x")), and that is exactly what is set in the case RHS. Since the expression could be modified (for instance x+2 instead of x), this is not a valid solution for me. What I want to do is to reuse the xExp tree (see the xExp comment) while altering the 'x' meaning (it is a definition in the input expression but will be a case LHS variable in the output one), but it launches a long error summarized in:
symbol value x does not exist in org.habla.main.Main$delayedInit$body.apply); see the error output for details.
My current solution consists on the parsing of the xExp to sustitute all the Idents with new ones, but it is totally dependent on the compiler internals, and so, a temporal workaround. It is obvious that the xExp comes along with more information that the offered by showRaw. How can I clean that xExp for allowing 'x' to role the case variable? Can anyone explain the whole picture of this error?
PS: I have been trying unsuccessfully to use the substitute* method family from the TreeApi but I am missing the basics to understand its implications.
Disassembling input expressions and reassembling them in a different fashion is an important scenario in macrology (this is what we do internally in the reify macro). But unfortunately, it's not particularly easy at the moment.
The problem is that input arguments of the macro reach macro implementation being already typechecked. This is both a blessing and a curse.
Of particular interest for us is the fact that variable bindings in the trees corresponding to the arguments are already established. This means that all Ident and Select nodes have their sym fields filled in, pointing to the definitions these nodes refer to.
Here is an example of how symbols work. I'll copy/paste a printout from one of my talks (I don't give a link here, because most of the info in my talks is deprecated by now, but this particular printout has everlasting usefulness):
>cat Foo.scala
def foo[T: TypeTag](x: Any) = x.asInstanceOf[T]
foo[Long](42)
>scalac -Xprint:typer -uniqid Foo.scala
[[syntax trees at end of typer]]// Scala source: Foo.scala
def foo#8339
[T#8340 >: Nothing#4658 <: Any#4657]
(x#9529: Any#4657)
(implicit evidence$1#9530: TypeTag#7861[T#8341])
: T#8340 =
x#9529.asInstanceOf#6023[T#8341];
Test#14.this.foo#8339[Long#1641](42)(scala#29.reflect#2514.`package`#3414.mirror#3463.TypeTag#10351.Long#10361)
To recap, we write a small snippet and then compile it with scalac, asking the compiler to dump the trees after the typer phase, printing unique ids of the symbols assigned to trees (if any).
In the resulting printout we can see that identifiers have been linked to corresponding definitions. For example, on the one hand, the ValDef("x", ...), which represents the parameter of the method foo, defines a method symbol with id=9529. On the other hand, the Ident("x") in the body of the method got its sym field set to the same symbol, which establishes the binding.
Okay, we've seen how bindings work in scalac, and now is the perfect time to introduce a fundamental fact.
If a symbol has been assigned to an AST node,
then subsequent typechecks will never reassign it.
This is why reify is hygienic. You can take a result of reify and insert it into an arbitrary tree (that possibly defines variables with conflicting names) - the original bindings will remain intact. This works because reify preserves the original symbols, so subsequent typechecks won't rebind reified AST nodes.
Now we're all set to explain the error you're facing:
symbol value x does not exist in org.habla.main.Main$delayedInit$body.apply); see the error output for details.
The argument of the transform macro contains both a definition and a reference to a variable x. As we've just learned, this means that the corresponding ValDef and Ident will have their sym fields synchronized. So far, so good.
However unfortunately the macro corrupts the established binding. It recreates the ValDef, but doesn't clean up the sym field of the corresponding Ident. Subsequent typecheck assigns a fresh symbol to the newly created ValDef, but doesn't touch the original Ident that is copied to the result verbatim.
After the typecheck, the original Ident points to a symbol that no longer exists (this is exactly what the error message was saying :)), which leads to a crash during bytecode generation.
So how do we fix the error? Unfortunately there is no easy answer.
One option would be to utilize c.resetLocalAttrs, which recursively erases all symbols in a given AST node. Subsequent typecheck will then reestablish the bindings granted that the code you generated doesn't mess with them (if, for example, you wrap xExp in a block that itself defines a value named x, then you're in trouble).
Another option is to fiddle with symbols. For example, you could write your own resetLocalAttrs that only erases corrupted bindings and doesn't touch the valid ones. You could also try and assign symbols by yourself, but that's a short road to madness, though sometimes one is forced to walk it.
Not cool at all, I agree. We're aware of that and intend to try and fix this fundamental issue sometimes. However right now our hands are full with bugfixing before the final 2.10.0 release, so we won't be able to address the problem in the nearest future. upd. See https://groups.google.com/forum/#!topic/scala-internals/rIyJ4yHdPDU for some additional information.
Bottom line. Bad things happen, because bindings get messed up. Try resetLocalAttrs first, and if it doesn't work, prepare yourself for a chore.