Unterschied zwischen AST und ASR

Nehmen wir einen einfachen Fortran-Code:

integer function f(a, b) result(r)
integer, intent(in) :: a, b
integer :: c, d
c = a + b - d
r = c * a
end function

und sehen uns an, wie der AST und die ASR aussehen.

AST

[1]:
%%showast
integer function f(a, b) result(r)
integer, intent(in) :: a, b
integer :: c, d
c = a + b - d
r = c * a
end function
(TranslationUnit [(Function f [(a) (b)] [(AttrType TypeInteger [] () None)] r () () [] [] [] [(Declaration (AttrType TypeInteger [] () None) [(AttrIntent In)] [(a [] [] () None ()) (b [] [] () None ())] ()) (Declaration (AttrType TypeInteger [] () None) [] [(c [] [] () None ()) (d [] [] () None ())] ())] [(= 0 c (- (+ a b) d) ()) (= 0 r (* c a) ())] [])])

Der AST enthält keine semantischen Informationen, hat aber Knoten zur Darstellung von Deklarationen wie integer, intent(in) :: a. Variablen wie a werden durch einen Name Knoten dargestellt und sind noch nicht mit ihren Deklarationen verbunden.

ASR

[2]:
%%showasr
integer function f(a, b) result(r)
integer, intent(in) :: a, b
integer :: c, d
c = a + b - d
r = c * a
end function
(TranslationUnit (SymbolTable 1 {f: (Function (SymbolTable 2 {a: (Variable 2 a [] In () () Default (Integer 4 []) Source Public Required .false.), b: (Variable 2 b [] In () () Default (Integer 4 []) Source Public Required .false.), c: (Variable 2 c [] Local () () Default (Integer 4 []) Source Public Required .false.), d: (Variable 2 d [] Local () () Default (Integer 4 []) Source Public Required .false.), r: (Variable 2 r [] ReturnVar () () Default (Integer 4 []) Source Public Required .false.)}) f [] [(Var 2 a) (Var 2 b)] [(= (Var 2 c) (IntegerBinOp (IntegerBinOp (Var 2 a) Add (Var 2 b) (Integer 4 []) ()) Sub (Var 2 d) (Integer 4 []) ()) ()) (= (Var 2 r) (IntegerBinOp (Var 2 c) Mul (Var 2 a) (Integer 4 []) ()) ())] (Var 2 r) Source Public Implementation () .false. .false. .false. .false. .false. [] [] .false.)}) [])

Die ASR enthält alle semantischen Informationen (Typen usw.), Knoten wie Function haben eine Symboltabelle und keine Deklarationsknoten. Variablen sind einfach Zeiger auf die Symboltabelle.

Diskussion

Das obige Beispiel war ein einfaches. Bei komplizierteren Beispielen, wie z. B. dem folgenden, werden die Dinge deutlicher:

integer function f2b(a) result(r)
use gfort_interop, only: c_desc1_int32
integer, intent(in) :: a(:)
interface
    integer function f2b_c_wrapper(a) bind(c, name="__mod1_MOD_f2b")
    use gfort_interop, only: c_desc1_t
    type(c_desc1_t), intent(in) :: a
    end function
end interface
r = f2b_c_wrapper(c_desc1_int32(a))
end function

AST muss alle use Anweisungen und den interface Block repräsentieren und die Dinge semantisch konsistent halten.

ASR hingegen verfolgt die c_desc1_int32, c_desc1_t und f2b_c_wrapper in der Symboltabelle und weiß, dass sie im Modul gfort_interop definiert sind, so dass ASR keinen dieser Deklarationsknoten hat.

Bei der Konvertierung von ASR nach AST erstellt LFortran alle entsprechenden AST-Deklarationsknoten automatisch und korrekt.