| 1 | //! Declaration AST nodes. |
| 2 | //! |
| 3 | //! Types, attributes, entity declarations, USE statements, IMPLICIT, |
| 4 | //! derived type definitions, and legacy declaration forms. |
| 5 | |
| 6 | use super::expr::SpannedExpr; |
| 7 | use super::Spanned; |
| 8 | |
| 9 | /// A spanned declaration. |
| 10 | pub type SpannedDecl = Spanned<Decl>; |
| 11 | |
| 12 | /// A Fortran declaration. |
| 13 | #[derive(Debug, Clone, PartialEq)] |
| 14 | #[allow(clippy::enum_variant_names)] |
| 15 | pub enum Decl { |
| 16 | /// Type declaration: `integer, allocatable :: x(:), y` |
| 17 | TypeDecl { |
| 18 | type_spec: TypeSpec, |
| 19 | attrs: Vec<Attribute>, |
| 20 | entities: Vec<EntityDecl>, |
| 21 | }, |
| 22 | |
| 23 | /// Standalone `PRIVATE` or `PUBLIC` statement that sets the module's |
| 24 | /// default access for all subsequent declarations. |
| 25 | AccessDefault { access: Attribute }, |
| 26 | |
| 27 | /// `PUBLIC :: name1, name2` or `PRIVATE :: assignment(=)` — sets |
| 28 | /// access on specific names or generic specs. |
| 29 | AccessList { |
| 30 | access: Attribute, |
| 31 | names: Vec<String>, |
| 32 | }, |
| 33 | |
| 34 | /// `implicit none` or `implicit none(type, external)` |
| 35 | ImplicitNone { external: bool, type_: bool }, |
| 36 | |
| 37 | /// `implicit double precision (a-h, o-z)` |
| 38 | ImplicitStmt { specs: Vec<ImplicitSpec> }, |
| 39 | |
| 40 | /// Derived type definition |
| 41 | DerivedTypeDef { |
| 42 | name: String, |
| 43 | extends: Option<String>, |
| 44 | attrs: Vec<TypeAttr>, |
| 45 | components: Vec<SpannedDecl>, |
| 46 | type_bound_procs: Vec<TypeBoundProc>, |
| 47 | final_procs: Vec<String>, |
| 48 | }, |
| 49 | |
| 50 | /// `use module_name [, only: ...]` |
| 51 | UseStmt { |
| 52 | module: String, |
| 53 | nature: UseNature, |
| 54 | renames: Vec<Rename>, |
| 55 | only: Option<Vec<OnlyItem>>, |
| 56 | }, |
| 57 | |
| 58 | /// `parameter (pi = 3.14159, e = 2.71828)` |
| 59 | ParameterStmt { pairs: Vec<(String, SpannedExpr)> }, |
| 60 | |
| 61 | /// `common /block_name/ x, y, z` |
| 62 | CommonBlock { |
| 63 | name: Option<String>, |
| 64 | vars: Vec<String>, |
| 65 | }, |
| 66 | |
| 67 | /// `equivalence (a, b), (c, d)` |
| 68 | EquivalenceStmt { groups: Vec<Vec<SpannedExpr>> }, |
| 69 | |
| 70 | /// `data x /1.0/, y /2.0/` |
| 71 | DataStmt { sets: Vec<DataSet> }, |
| 72 | |
| 73 | /// `enum, bind(c)` |
| 74 | EnumDef { |
| 75 | enumerators: Vec<(String, Option<SpannedExpr>)>, |
| 76 | }, |
| 77 | |
| 78 | /// Standalone attribute statement: `allocatable :: x`, `dimension(10) :: a` |
| 79 | AttributeStmt { |
| 80 | attr: Attribute, |
| 81 | entities: Vec<String>, |
| 82 | }, |
| 83 | } |
| 84 | |
| 85 | // ---- Type specifiers ---- |
| 86 | |
| 87 | /// Fortran type specifier. |
| 88 | #[derive(Debug, Clone, PartialEq)] |
| 89 | pub enum TypeSpec { |
| 90 | Integer(Option<KindSelector>), |
| 91 | Real(Option<KindSelector>), |
| 92 | DoublePrecision, |
| 93 | Complex(Option<KindSelector>), |
| 94 | DoubleComplex, |
| 95 | Logical(Option<KindSelector>), |
| 96 | Character(Option<CharSelector>), |
| 97 | /// `type(my_type)` — derived type reference |
| 98 | Type(String), |
| 99 | /// `class(my_type)` — polymorphic |
| 100 | Class(String), |
| 101 | /// `class(*)` — unlimited polymorphic |
| 102 | ClassStar, |
| 103 | /// `type(*)` — assumed type |
| 104 | TypeStar, |
| 105 | } |
| 106 | |
| 107 | /// Kind selector: `(4)`, `(kind=4)`, `*4` |
| 108 | #[derive(Debug, Clone, PartialEq)] |
| 109 | pub enum KindSelector { |
| 110 | Expr(SpannedExpr), |
| 111 | Star(SpannedExpr), // *4 (old-style) |
| 112 | } |
| 113 | |
| 114 | /// Character selector: `(10)`, `(len=10, kind=1)`, `*10` |
| 115 | #[derive(Debug, Clone, PartialEq)] |
| 116 | pub struct CharSelector { |
| 117 | pub len: Option<LenSpec>, |
| 118 | pub kind: Option<SpannedExpr>, |
| 119 | } |
| 120 | |
| 121 | /// Character length specification. |
| 122 | #[derive(Debug, Clone, PartialEq)] |
| 123 | pub enum LenSpec { |
| 124 | Expr(SpannedExpr), |
| 125 | Star, // len=* (assumed length) |
| 126 | Colon, // len=: (deferred length) |
| 127 | } |
| 128 | |
| 129 | // ---- Attributes ---- |
| 130 | |
| 131 | /// Declaration attribute. |
| 132 | #[derive(Debug, Clone, PartialEq)] |
| 133 | pub enum Attribute { |
| 134 | Dimension(Vec<ArraySpec>), |
| 135 | Allocatable, |
| 136 | Pointer, |
| 137 | Target, |
| 138 | Intent(Intent), |
| 139 | Optional, |
| 140 | Save, |
| 141 | Parameter, |
| 142 | Value, |
| 143 | Volatile, |
| 144 | Asynchronous, |
| 145 | Protected, |
| 146 | Contiguous, |
| 147 | External, |
| 148 | Intrinsic, |
| 149 | Bind(Option<String>), // bind(c, name="cfunc") |
| 150 | Public, |
| 151 | Private, |
| 152 | } |
| 153 | |
| 154 | /// Intent specification. |
| 155 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] |
| 156 | pub enum Intent { |
| 157 | In, |
| 158 | Out, |
| 159 | InOut, |
| 160 | } |
| 161 | |
| 162 | /// Array specification for dimension attribute. |
| 163 | #[derive(Debug, Clone, PartialEq)] |
| 164 | pub enum ArraySpec { |
| 165 | /// `(10)` or `(1:10)` — explicit bounds |
| 166 | Explicit { |
| 167 | lower: Option<SpannedExpr>, |
| 168 | upper: SpannedExpr, |
| 169 | }, |
| 170 | /// `(:)` — assumed shape (for dummy arguments) |
| 171 | AssumedShape { lower: Option<SpannedExpr> }, |
| 172 | /// `(*)` — assumed size (last dimension only) |
| 173 | AssumedSize { lower: Option<SpannedExpr> }, |
| 174 | /// `(:)` with allocatable/pointer — deferred shape |
| 175 | Deferred, |
| 176 | /// `(..)` — assumed rank (F2018) |
| 177 | AssumedRank, |
| 178 | } |
| 179 | |
| 180 | // ---- Entity declarations ---- |
| 181 | |
| 182 | /// An entity in a type declaration: `x`, `x = 0`, `x(:,:)`, `ptr => null()` |
| 183 | #[derive(Debug, Clone, PartialEq)] |
| 184 | pub struct EntityDecl { |
| 185 | pub name: String, |
| 186 | pub array_spec: Option<Vec<ArraySpec>>, |
| 187 | pub char_len: Option<LenSpec>, // character entity-specific length |
| 188 | pub init: Option<SpannedExpr>, // = expr |
| 189 | pub ptr_init: Option<SpannedExpr>, // => expr |
| 190 | } |
| 191 | |
| 192 | // ---- Derived type parts ---- |
| 193 | |
| 194 | /// Derived type attribute. |
| 195 | #[derive(Debug, Clone, PartialEq)] |
| 196 | pub enum TypeAttr { |
| 197 | Public, |
| 198 | Private, |
| 199 | Abstract, |
| 200 | Bind(Option<String>), |
| 201 | Extends(String), |
| 202 | } |
| 203 | |
| 204 | /// Type-bound procedure. |
| 205 | #[derive(Debug, Clone, PartialEq)] |
| 206 | pub struct TypeBoundProc { |
| 207 | pub name: String, |
| 208 | pub interface: Option<String>, // procedure(iface) :: name |
| 209 | pub binding: Option<String>, // procedure :: name => binding |
| 210 | pub bindings: Vec<String>, // generic :: name => specific_a, specific_b |
| 211 | pub attrs: Vec<String>, // pass, nopass, deferred, etc. |
| 212 | pub is_generic: bool, |
| 213 | } |
| 214 | |
| 215 | // ---- USE statement parts ---- |
| 216 | |
| 217 | /// USE module nature. |
| 218 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] |
| 219 | pub enum UseNature { |
| 220 | Normal, |
| 221 | Intrinsic, |
| 222 | NonIntrinsic, |
| 223 | } |
| 224 | |
| 225 | /// USE rename: `local => remote` |
| 226 | #[derive(Debug, Clone, PartialEq)] |
| 227 | pub struct Rename { |
| 228 | pub local: String, |
| 229 | pub remote: String, |
| 230 | } |
| 231 | |
| 232 | /// USE ONLY item. |
| 233 | #[derive(Debug, Clone, PartialEq)] |
| 234 | pub enum OnlyItem { |
| 235 | Name(String), |
| 236 | Rename(Rename), |
| 237 | Generic(String), |
| 238 | } |
| 239 | |
| 240 | // ---- IMPLICIT parts ---- |
| 241 | |
| 242 | /// Implicit type specification: `double precision (a-h, o-z)` |
| 243 | #[derive(Debug, Clone, PartialEq)] |
| 244 | pub struct ImplicitSpec { |
| 245 | pub type_spec: TypeSpec, |
| 246 | pub ranges: Vec<(char, char)>, |
| 247 | } |
| 248 | |
| 249 | // ---- DATA statement parts ---- |
| 250 | |
| 251 | /// A data set: `x /1.0/` or `(a(i), i=1,10) /10*0.0/` |
| 252 | #[derive(Debug, Clone, PartialEq)] |
| 253 | pub struct DataSet { |
| 254 | pub objects: Vec<SpannedExpr>, |
| 255 | pub values: Vec<SpannedExpr>, |
| 256 | } |
| 257 |