Would be more comfortable, but probably less logical: One does not want to apply any implicit
settings to the names which are imported from modules via use
, as they should use the implicit
settings of their defining module. Therefore, it makes sense to me to declare implicit whatever
only after the module imports, and then it will be consistently applied to all variables declared further down.
Hello, after my test, this does not seem to be a bug. Because j
in the parent variable domain is not assigned an initial value, and it happens that the memory state of the program causes j = 2
in the parent variable domain, you can assign j
in the block
to other values, such as 4
, you can prove this !
@kargl Here comes my demos:
program main_2
integer :: i = 21, j
print *, j
block
integer :: j
j = 4
end block
print *, j
end program main_2
Itās just that j
in the parent variable domain has not been assigned an initial value, and its value happens to be 2. It is not the value of j
in the block
that affects it.
Links
I ran your code in the gcc bugzilla, but I still canāt understand that it is a bug..
It normally obeys the variable implicit declaration
@kargl From the different results of ifort and gfortran, I seem to understand what you mean, which is surprising!
It seems that ifort and gfortran have an ambiguity about implicit declarations containing
block
.ā¦ ā¦ Picture display is also a way of presentation
Online Compiler: Compiler Explorer (godbolt.org)
program foo
call block1
print *
call block2
print *, "Normal exit."
end program foo
!
! For an implicitly declared variable (e.g., i and j here), the
! scope of the variable is from the inclusive scoping unit. That
! is, 'j = 1' in block1 is implicitly declared to be in the
! namespace of block1. In addition, the implicitly declared 'i'
! in block bah is also in the namespace of block1.
!
subroutine block1
j = 1
bah: block
i = 42
j = 42
end block bah
if (i /= 42) print *, 1, i ! i should be 42
if (j /= 42) print *, 2, j
end subroutine block1
!
! In the following 'i' has an implicit declaration in the scope
! of block2. The explicit declaration of 'i' in block bah means
! that this 'i' has the scope of bah.
!
subroutine block2
i = 1
j = 1
bah: block
integer i
i = 42
j = 42
if (i /= 42) print *, 3, i
if (j /= 42) print *, 4, j
end block bah
if (i /= 1) print *, 5, i
if (j /= 42) print *, 6, j
end subroutine block2
I have not yet seen a Fortran compiler that can compile source code displayed in a picture .
There is another way of saying that we should always write implicit none
. When we do not write, the specific problems that arise may be determined by the compiler. (I donāt know. If anyone are interested, you can check the Fortran standard)
If there is a description in the standard that can prove that this is a bug, I think it is the best.
When the standard lacks instructions and different implementations of the compiler, it may not be a bug.
I just want to show that the results are different, nothing more. And forgot to post the source code.
@zoziha ,
So, to add to your understanding, the bug in gfortran can be illustrated by the following 5-liner:
block
j = 42
end block
print *, "j = ", j, "; expected is 42"
end
C:\temp>gfortran p.f90 -o p.exe
C:\temp>p.exe
j = 1 ; expected is 42
Two other compilers work as expected:
- Intel Fortran
C:\temp>ifort /standard-semantics /check:uninit p.f90
Intel(R) Fortran Intel(R) 64 Compiler Classic for applications running on Intel(R) 64, Version 2021.4.0 Build 20210910_000000
Copyright (C) 1985-2021 Intel Corporation. All rights reserved.Microsoft (R) Incremental Linker Version 14.29.30040.0
Copyright (C) Microsoft Corporation. All rights reserved.-out:p.exe
-subsystem:console
p.objC:\temp>p.exe
j = 42 ; expected is 42
- NAG Fortran
C:\temp>type p.f90
block
j = 42
end block
print *, "j = ", j, ā; expected is 42ā
endC:\temp>nagfor p.f90 -o p.exe
NAG Fortran Compiler Release 7.0(Yurakucho) Build 7048
[NAG Fortran Compiler normal termination]C:\temp>p.exe
j = 42 ; expected is 42C:\temp>
Although the results are inconsistent, I am not sure that this is a bug. Whoever is interested can consult the Fortran standard. After all, there are some attributes that can be determined by the compiler, such as:
- format ā(g0)ā
Add format_string routine to format other types to strings by St-Maxwell Ā· Pull Request #444 Ā· fortran-lang/stdlib Ā· GitHub - allocatable array in heap
[stdlib_linalg] Add zeros, ones function. by zoziha Ā· Pull Request #478 Ā· fortran-lang/stdlib Ā· GitHub
To avoid this problem, we need now try to implicit none
.
program main
implicit none
call block1
call block2
write(*,*)"exit"
end program main
subroutine block1
implicit none
integer::i,j
j=1
bah:block
i=42
j=42
end block bah
if(i/=42)write(*,*) '1',i
if(j/=42)write(*,*) '2',j
end subroutine block1
subroutine block2
implicit none
integer::i,j
i=1
j=1
bah:block
integer::i
i=42
j=42
if(i/=42)write(*,*) '3',i
if(j/=42)write(*,*) '4',j
end block bah
if(i/=1)write(*,*) '5',i
if(j/=42)write(*,*) '6',j
end subroutine block2
Itās a pity that almost 4 years and 3 major versions later it is still there, not fixed. Unless it is fixed in gcc 12 which I have no access to.
You donāt expect an ordinary Fortran (!) user to contribute to a compiler of ~1 million LOC written in C and (now mostly, as I read) C++, do you?
I agree with @kargl on that. I am a physicist too and never had a compiler course either.
As a community we really have to start contributing to our open source compilers. There is no other way. Many people here already do.
All the open source Fortran compilers are written in C or C++. They differ in details how they are constructed.
However, if you want to contribute to a runtime library, the LFortranās runtime library is written in Fortran. We are looking for contributors.
Things have to arrive soon at a stage where the Fortran compilers are bootstrapped in Fortran itself. This will lead to two immediate benefits:
- The number of contributors will increase considerably I predict, possibly even by orders of magnitude.
- There will be better appreciation for the needless, near asinine limitations in the language standard with various aspects (e.g., no built-in intrinsic string type) and there will be stronger support and direction to enhance the language.
Yeah, it would indeed help. But as I said, itās hard enough to deliver a compiler in any language, so I chose the easiest path forward, which is C++ for me. If I did it in Fortran, I would fail.
Which books on compilers do the compiler writers recommend? The book by Aho et al. is famous but also 1000 pages long.
Yes, Flang and LFortran are written in a similar way, front end, middle end, backend.
For LFortran, the middle end representation is called ASR (Abstract Semantic Representation), and it has several backends, such as lowering to LLVM.
The frontend has a parser (currently using Bison) that creates an AST (or reports a syntax error), and then there is a layer that transforms AST to ASR, which collects all the errors and warnings.
The part that can possibly be in Fortran is the AST to ASR translation. The AST and ASR nodes are generated, so we could generate a Fortran representation. But it would still be only a small part of the compiler.
One could possibly write Fortran API for LLVM, and then also the ASR->LLVM could be in Fortran.
We could write a Fortran backend to Bison (lot of work) or create a new parser in pure Fortran (also a lot of work).
We could write a Fortran backend to re2c (lot of work), or write a tokenizer in Fortran.
But at some point, given that all the tools for compiler writing are in C or C++, itās just better to stick to those languages and at least the whole compiler is written in one language, which has many engineering advantages. If itās going to be a mix of C or C++ and Fortran, it only adds to the engineering complexity.
If we give up LLVM, LFortran also has a direct x86 (and weāll add arm) backend. That one could be written in Fortran in principle. But it doesnāt do any optimizations, so itās going to be slow to execute (but fast to compile).
And finally, there is performance of compilation. I have spent a lot of time ensuring the C++ implementation is very fast. We use a custom allocator, and allocate C style structs ourselves. I donāt know how to do that in Fortran. And so it is going to be slow. The rest of C++ language features that we use can probably be emulated with C macros (ugly, but it would do the job).
We could have an LFortran language extension that would allow to effectively deal with derived types using a linear allocator and also extend the language to do whatever else we need. We could even do it in some way so that the Fortran parts of the compiler still compiles with other compilers, but when recompiled with LFortran we would get the speed.
But this is no easy task, an order of magnitude larger than just using C++. My goal is to deliver a compiler, actually deliver. I have to focus on that.
If however there is anybody (such as you @FortranFan) that would like to work on it in Fortran, I am happy to generate the Fortran AST and ASR nodes in Fortran. I can figure out how to link with the C++ compiler, and maybe you can write an ASR->ASR optimization pass, in Fortran. I think that is doable (although as I said, it adds complexity to the compiler, but if there is community interest and weāll get contributors, it might be worth it). Just let me know.
We have serialization and deserialization (automatically generated) for the ASR. So we could save it to a file, then we load it (in Fortran), do some optimization, and save it back to a file. That way it is independent of LFortran, and we can add hooks to execute some passes that way. Slower, but it would not be complicated (as long as it is optional, invoked with some command line option). If there is anybody interested, let me know.
I also own a copy of āCompiler Design in Cā by Allan Holub, but I cannot recommend
this book as I stopped reading after 50-ish pages due to the high rate of typos and
errors. Other than that, I donāt own any compiler design books.
Thanks ā Holub has made his book and code available. It has 3.5 stars on Amazon.
The compiler design book with the best Amazon rating is Cooper and Torczon, āEngineering a Compiler, 2nd Editionā. Its slightly shorter than Aho et alās Dragon Book, and reputedly better organized.
The errata for āEngineering a Compilerā is small but exists.
https://www.cs.rice.edu/~keith/Errata.html