fortran66のブログ

fortran について書きます。

【メモ帳】あらゆる構造から exit !

Fortran 2008 で exit の拡張

Fortran 2008 では exit の適用範囲が広がって、ほぼすべての構造(construct)から exit できるようになりました。脱構築ポストモダンFortran

私は、少し誤解していて exit のあとのラベルは省略できるものと思っていましたが construct 終端のラベルとともに、必須でした。

Modern Fortran Explained §20.1.7 によると、 従来の do 構造のほかに、associate、block、if、select case、select type の各構造から exit できるそうです。

なお並列動作の観点から、do concurrent、critical の構造からは exit できません。そもそも順序がないので、これは当然でしょう。

また書いてありませんが forall や where は代入文なので、これらからも exit できません。というか、出ようもない。
[追記] forall や where construct もラベルがつけられるのですが、何の用途があるのかよく分かりません。よくよく考えると forall の方は、単一の forall 文の集合体と見なせるので、途中での脱出もありかもしれないと思ったりもしました。

Modern Fortran Explained (Numerical Mathematics and Scientific Computation)

Modern Fortran Explained (Numerical Mathematics and Scientific Computation)

Introduction to Programming with Fortran: With Coverage of Fortran 90, 95, 2003, 2008 and 77

Introduction to Programming with Fortran: With Coverage of Fortran 90, 95, 2003, 2008 and 77

Modern Fortran in Practice

Modern Fortran in Practice

Modern Fortran: Style and Usage

Modern Fortran: Style and Usage

ソースプログラム

intel fortran v.17 は対応していません。v.18 は if 構造に else 文が出てくると、コンパイラの内部エラーが出てしまいます。コンパイラのバグだと思われます。なお gfortran v.7 では else があっても大丈夫です。

    program test
      implicit none
      integer, target :: i = 0, m = 0
      class(*), pointer :: c => null()
      
  aa: associate (k => i)
        if (k == 1) exit aa
        print *, 'associate'
      end associate aa   
      
  bb: block
        use, intrinsic :: iso_fortran_env
        print *, compiler_version()
        print *, compiler_options()
        print *, 'block1'
        exit bb
        print *, 'block2'
      end block bb

  dd: do m = 1, 10
        if (m == 5) exit dd
        print *, 'm=', m
      end do dd
          
  ff: if (i == 0) then
        i = i + 1
        exit ff
        i = i + 999
     ! else !
        i = i + 10
      end if ff
      
  sc: select case (i)
        case (0)
          print *, 'case 0'
          exit sc
          print *, 'case 0'
        case (1)
          print *, 'case 1'
          exit sc
          print *, 'case 1'
        case default  
          print *, 'case default'
        end select sc    
        
        c => i
   st: select type (c)
       type is (integer)
         print *, 'int'
         exit st
         print *, 'int'
       type is (real)
         print *, 'real'
       class default
         print *, 'class default'      
       end select st 
        
      print *, 'end: i=', i
    end program test

実行結果

intel v.18
 associate
 インテル(R) 64 対応インテル(R) Visual Fortran コンパイラー (IA-32 対応アプリケ・
 [ション用) バージョン 18.0.1.156 ビルド 20171018

 /nologo /debug:full /Od /standard-semantics /warn:interfaces /module:Debug\ /ob
 ject:Debug\ /FdDebug\vc150.pdb /traceback /check:bounds /check:stack /libs:dll
 /threads /dbglibs /c /Qlocation,link,C:\Program Files (x86)\Microsoft Visual St
 udio\2017\Community\Common7\IDE\VC\\bin /Qm32
 block1
 m= 1
 m= 2
 m= 3
 m= 4
 case 1
 int
 end: i= 1
続行するには何かキーを押してください . . .
gfortran v.7
$gfortran -std=f2008 *.f95 -o main
$main
 associate
 GCC version 7.1.1 20170622 (Red Hat 7.1.1-3)
 -mtune=generic -march=x86-64 -std=f2008
 block1
 m=           1
 m=           2
 m=           3
 m=           4
 case 1
 int
 end: i=           1