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