Fork of daniellemaywood.uk/gleam — Wasm codegen work
2

Configure Feed

Select the types of activity you want to include in your feed.

gleam / compiler-core / src / ast / constant.rs
7.4 kB 236 lines
1use super::*; 2use crate::type_::{FieldMap, HasType}; 3 4pub type TypedConstant = Constant<Arc<Type>, EcoString>; 5pub type UntypedConstant = Constant<(), ()>; 6 7// TODO: remove RecordTag paramter 8#[derive(Debug, Clone, PartialEq, Eq)] 9pub enum Constant<T, RecordTag> { 10 Int { 11 location: SrcSpan, 12 value: EcoString, 13 int_value: BigInt, 14 }, 15 16 Float { 17 location: SrcSpan, 18 value: EcoString, 19 float_value: LiteralFloatValue, 20 }, 21 22 String { 23 location: SrcSpan, 24 value: EcoString, 25 }, 26 27 Tuple { 28 location: SrcSpan, 29 elements: Vec<Self>, 30 }, 31 32 List { 33 location: SrcSpan, 34 elements: Vec<Self>, 35 type_: T, 36 }, 37 38 Record { 39 location: SrcSpan, 40 module: Option<(EcoString, SrcSpan)>, 41 name: EcoString, 42 arguments: Vec<CallArg<Self>>, 43 tag: RecordTag, 44 type_: T, 45 field_map: Option<FieldMap>, 46 record_constructor: Option<Box<ValueConstructor>>, 47 }, 48 49 BitArray { 50 location: SrcSpan, 51 segments: Vec<BitArraySegment<Self, T>>, 52 }, 53 54 Var { 55 location: SrcSpan, 56 module: Option<(EcoString, SrcSpan)>, 57 name: EcoString, 58 constructor: Option<Box<ValueConstructor>>, 59 type_: T, 60 }, 61 62 StringConcatenation { 63 location: SrcSpan, 64 left: Box<Self>, 65 right: Box<Self>, 66 }, 67 68 /// A placeholder constant used to allow module analysis to continue 69 /// even when there are type errors. Should never end up in generated code. 70 Invalid { 71 location: SrcSpan, 72 type_: T, 73 }, 74} 75 76impl TypedConstant { 77 pub fn type_(&self) -> Arc<Type> { 78 match self { 79 Constant::Int { .. } => type_::int(), 80 Constant::Float { .. } => type_::float(), 81 Constant::String { .. } | Constant::StringConcatenation { .. } => type_::string(), 82 Constant::BitArray { .. } => type_::bit_array(), 83 Constant::Tuple { elements, .. } => { 84 type_::tuple(elements.iter().map(|element| element.type_()).collect()) 85 } 86 Constant::List { type_, .. } 87 | Constant::Record { type_, .. } 88 | Constant::Var { type_, .. } 89 | Constant::Invalid { type_, .. } => type_.clone(), 90 } 91 } 92 93 pub fn find_node(&self, byte_index: u32) -> Option<Located<'_>> { 94 if !self.location().contains(byte_index) { 95 return None; 96 } 97 Some(match self { 98 Constant::Int { .. } 99 | Constant::Float { .. } 100 | Constant::String { .. } 101 | Constant::Var { .. } 102 | Constant::Invalid { .. } => Located::Constant(self), 103 Constant::Tuple { elements, .. } | Constant::List { elements, .. } => elements 104 .iter() 105 .find_map(|element| element.find_node(byte_index)) 106 .unwrap_or(Located::Constant(self)), 107 Constant::Record { arguments, .. } => arguments 108 .iter() 109 .find_map(|argument| argument.find_node(byte_index)) 110 .unwrap_or(Located::Constant(self)), 111 Constant::BitArray { segments, .. } => segments 112 .iter() 113 .find_map(|segment| segment.find_node(byte_index)) 114 .unwrap_or(Located::Constant(self)), 115 Constant::StringConcatenation { left, right, .. } => left 116 .find_node(byte_index) 117 .or_else(|| right.find_node(byte_index)) 118 .unwrap_or(Located::Constant(self)), 119 }) 120 } 121 122 pub fn definition_location(&self) -> Option<DefinitionLocation> { 123 match self { 124 Constant::Int { .. } 125 | Constant::Float { .. } 126 | Constant::String { .. } 127 | Constant::Tuple { .. } 128 | Constant::List { .. } 129 | Constant::BitArray { .. } 130 | Constant::StringConcatenation { .. } 131 | Constant::Invalid { .. } => None, 132 Constant::Record { 133 record_constructor: value_constructor, 134 .. 135 } 136 | Constant::Var { 137 constructor: value_constructor, 138 .. 139 } => value_constructor 140 .as_ref() 141 .map(|constructor| constructor.definition_location()), 142 } 143 } 144 145 pub(crate) fn referenced_variables(&self) -> im::HashSet<&EcoString> { 146 match self { 147 Constant::Var { name, .. } => im::hashset![name], 148 149 Constant::Invalid { .. } 150 | Constant::Int { .. } 151 | Constant::Float { .. } 152 | Constant::String { .. } => im::hashset![], 153 154 Constant::List { elements, .. } | Constant::Tuple { elements, .. } => elements 155 .iter() 156 .map(|element| element.referenced_variables()) 157 .fold(im::hashset![], im::HashSet::union), 158 159 Constant::Record { arguments, .. } => arguments 160 .iter() 161 .map(|argument| argument.value.referenced_variables()) 162 .fold(im::hashset![], im::HashSet::union), 163 164 Constant::BitArray { segments, .. } => segments 165 .iter() 166 .map(|segment| { 167 segment 168 .options 169 .iter() 170 .map(|option| option.referenced_variables()) 171 .fold(segment.value.referenced_variables(), im::HashSet::union) 172 }) 173 .fold(im::hashset![], im::HashSet::union), 174 175 Constant::StringConcatenation { left, right, .. } => left 176 .referenced_variables() 177 .union(right.referenced_variables()), 178 } 179 } 180} 181 182impl HasType for TypedConstant { 183 fn type_(&self) -> Arc<Type> { 184 self.type_() 185 } 186} 187 188impl<A, B> Constant<A, B> { 189 pub fn location(&self) -> SrcSpan { 190 match self { 191 Constant::Int { location, .. } 192 | Constant::List { location, .. } 193 | Constant::Float { location, .. } 194 | Constant::Tuple { location, .. } 195 | Constant::String { location, .. } 196 | Constant::Record { location, .. } 197 | Constant::BitArray { location, .. } 198 | Constant::Var { location, .. } 199 | Constant::Invalid { location, .. } 200 | Constant::StringConcatenation { location, .. } => *location, 201 } 202 } 203 204 #[must_use] 205 pub fn can_have_multiple_per_line(&self) -> bool { 206 match self { 207 Constant::Int { .. } 208 | Constant::Float { .. } 209 | Constant::String { .. } 210 | Constant::Var { .. } => true, 211 212 Constant::Tuple { .. } 213 | Constant::List { .. } 214 | Constant::Record { .. } 215 | Constant::BitArray { .. } 216 | Constant::StringConcatenation { .. } 217 | Constant::Invalid { .. } => false, 218 } 219 } 220} 221 222impl<A, B> HasLocation for Constant<A, B> { 223 fn location(&self) -> SrcSpan { 224 self.location() 225 } 226} 227 228impl<A, B> bit_array::GetLiteralValue for Constant<A, B> { 229 fn as_int_literal(&self) -> Option<BigInt> { 230 if let Constant::Int { int_value, .. } = self { 231 Some(int_value.clone()) 232 } else { 233 None 234 } 235 } 236}