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
and look at what the AST and ASR look like.
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
())]
()
)]
[(Assignment
0
c
(- (+ a b) d)
()
)
(Assignment
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.
The AST can also be exported in JSON, including source file name, line and column information: lfortran example.f90 --show-ast --json
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.
.false.
),
b:
(Variable
2
b
[]
In
()
()
Default
(Integer 4)
()
Source
Public
Required
.false.
.false.
),
c:
(Variable
2
c
[]
Local
()
()
Default
(Integer 4)
()
Source
Public
Required
.false.
.false.
),
d:
(Variable
2
d
[]
Local
()
()
Default
(Integer 4)
()
Source
Public
Required
.false.
.false.
),
r:
(Variable
2
r
[]
ReturnVar
()
()
Default
(Integer 4)
()
Source
Public
Required
.false.
.false.
)
})
f
(FunctionType
[(Integer 4)
(Integer 4)]
(Integer 4)
Source
Implementation
()
.false.
.false.
.false.
.false.
.false.
[]
.false.
)
[]
[(Var 2 a)
(Var 2 b)]
[(Assignment
(Var 2 c)
(IntegerBinOp
(IntegerBinOp
(Var 2 a)
Add
(Var 2 b)
(Integer 4)
()
)
Sub
(Var 2 d)
(Integer 4)
()
)
()
)
(Assignment
(Var 2 r)
(IntegerBinOp
(Var 2 c)
Mul
(Var 2 a)
(Integer 4)
()
)
()
)]
(Var 2 r)
Public
.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.
The ASR can also be exported in JSON, including source file name, line and column information: lfortran example.f90 --show-asr --json
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.