mod.rs
1 // Copyright (C) 2019-2025 ADnet Contributors 2 // This file is part of the ADL library. 3 4 // The ADL library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 9 // The ADL library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 14 // You should have received a copy of the GNU General Public License 15 // along with the ADL library. If not, see <https://www.gnu.org/licenses/>. 16 17 mod annotation; 18 pub use annotation::*; 19 20 mod intrinsic; 21 pub use intrinsic::*; 22 23 mod variant; 24 pub use variant::*; 25 26 mod input; 27 pub use input::*; 28 29 mod output; 30 pub use output::*; 31 32 mod mode; 33 pub use mode::*; 34 35 use crate::{Block, ConstParameter, FunctionStub, Identifier, Indent, Node, NodeID, TupleType, Type}; 36 use adl_span::{Span, Symbol}; 37 38 use itertools::Itertools as _; 39 use serde::{Deserialize, Serialize}; 40 use std::fmt; 41 42 /// A function definition. 43 #[derive(Clone, Default, Serialize, Deserialize)] 44 pub struct Function { 45 /// Annotations on the function. 46 pub annotations: Vec<Annotation>, 47 /// Is this function a transition, inlined, or a regular function?. 48 pub variant: Variant, 49 /// The function identifier, e.g., `foo` in `function foo(...) { ... }`. 50 pub identifier: Identifier, 51 /// The function's const parameters. 52 pub const_parameters: Vec<ConstParameter>, 53 /// The function's input parameters. 54 pub input: Vec<Input>, 55 /// The function's output declarations. 56 pub output: Vec<Output>, 57 /// The function's output type. 58 pub output_type: Type, 59 /// The body of the function. 60 pub block: Block, 61 /// The entire span of the function definition. 62 pub span: Span, 63 /// The ID of the node. 64 pub id: NodeID, 65 } 66 67 impl PartialEq for Function { 68 fn eq(&self, other: &Self) -> bool { 69 self.identifier == other.identifier 70 } 71 } 72 73 impl Eq for Function {} 74 75 impl Function { 76 /// Initialize a new function. 77 #[allow(clippy::too_many_arguments)] 78 pub fn new( 79 annotations: Vec<Annotation>, 80 variant: Variant, 81 identifier: Identifier, 82 const_parameters: Vec<ConstParameter>, 83 input: Vec<Input>, 84 output: Vec<Output>, 85 block: Block, 86 span: Span, 87 id: NodeID, 88 ) -> Self { 89 let output_type = match output.len() { 90 0 => Type::Unit, 91 1 => output[0].type_.clone(), 92 _ => Type::Tuple(TupleType::new(output.iter().map(|o| o.type_.clone()).collect())), 93 }; 94 95 Function { annotations, variant, identifier, const_parameters, input, output, output_type, block, span, id } 96 } 97 98 /// Returns function name. 99 pub fn name(&self) -> Symbol { 100 self.identifier.name 101 } 102 } 103 104 impl From<FunctionStub> for Function { 105 fn from(function: FunctionStub) -> Self { 106 Self { 107 annotations: function.annotations, 108 variant: function.variant, 109 identifier: function.identifier, 110 const_parameters: vec![], 111 input: function.input, 112 output: function.output, 113 output_type: function.output_type, 114 block: Block::default(), 115 span: function.span, 116 id: function.id, 117 } 118 } 119 } 120 121 impl fmt::Debug for Function { 122 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 123 write!(f, "{self}") 124 } 125 } 126 127 impl fmt::Display for Function { 128 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 129 for annotation in &self.annotations { 130 writeln!(f, "{annotation}")?; 131 } 132 133 match self.variant { 134 Variant::Inline => write!(f, "inline ")?, 135 Variant::Function => write!(f, "function ")?, 136 Variant::AsyncFunction => write!(f, "async function ")?, 137 Variant::Transition => write!(f, "transition ")?, 138 Variant::AsyncTransition => write!(f, "async transition ")?, 139 Variant::Script => write!(f, "script ")?, 140 } 141 142 write!(f, "{}", self.identifier)?; 143 if !self.const_parameters.is_empty() { 144 write!(f, "::[{}]", self.const_parameters.iter().format(", "))?; 145 } 146 write!(f, "({})", self.input.iter().format(", "))?; 147 148 match self.output.len() { 149 0 => {} 150 1 => { 151 if !matches!(self.output[0].type_, Type::Unit) { 152 write!(f, " -> {}", self.output[0])?; 153 } 154 } 155 _ => { 156 write!(f, " -> ({})", self.output.iter().format(", "))?; 157 } 158 } 159 160 writeln!(f, " {{")?; 161 for stmt in self.block.statements.iter() { 162 writeln!(f, "{}{}", Indent(stmt), stmt.semicolon())?; 163 } 164 write!(f, "}}") 165 } 166 } 167 168 crate::simple_node_impl!(Function);