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

Configure Feed

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

Remove outdated fixers

+1 -911
+1 -7
compiler-core/src/fix.rs
··· 1 - mod bit_string_rename; 2 - mod import_type; 3 - #[cfg(test)] 4 - mod tests; 5 - 6 1 use crate::{ 7 2 format::{Formatter, Intermediate}, 8 3 Error, Result, ··· 21 16 let module = parsed.module; 22 17 23 18 // Fix 24 - let module = bit_string_rename::Fixer::fix(module); 25 - let module = import_type::Fixer::fix(module); 19 + // let module = some_fixer_module::Fixer::fix(module); 26 20 27 21 // Format 28 22 let mut buffer = String::new();
-116
compiler-core/src/fix/bit_string_rename.rs
··· 1 - use crate::{ 2 - ast::{ 3 - CallArg, Constant, CustomType, Definition, Import, SrcSpan, TypeAlias, TypeAst, 4 - TypeAstConstructor, UntypedConstant, UntypedDefinition, UntypedImport, UntypedModule, 5 - }, 6 - ast_folder::{ 7 - PatternFolder, TypeAstFolder, UntypedConstantFolder, UntypedExprFolder, UntypedModuleFolder, 8 - }, 9 - build::Target, 10 - }; 11 - use ecow::EcoString; 12 - 13 - #[derive(Debug, Default)] 14 - pub struct Fixer { 15 - prelude_module_import_alias: Option<EcoString>, 16 - bit_string_name: EcoString, 17 - bit_array_name: EcoString, 18 - } 19 - 20 - impl Fixer { 21 - pub fn fix(module: UntypedModule) -> UntypedModule { 22 - let mut fixer = Self { 23 - prelude_module_import_alias: None, 24 - bit_string_name: "BitString".into(), 25 - bit_array_name: "BitArray".into(), 26 - }; 27 - fixer.fix_module(module) 28 - } 29 - 30 - fn fix_module(&mut self, module: UntypedModule) -> UntypedModule { 31 - // Work out what BitString is called in this module 32 - for d in module.definitions.iter() { 33 - self.determine_names(&d.definition); 34 - } 35 - 36 - // Fix the module 37 - self.fold_module(module) 38 - } 39 - 40 - fn determine_names(&mut self, d: &UntypedDefinition) { 41 - match d { 42 - Definition::Function(_) | Definition::ModuleConstant(_) => (), 43 - 44 - Definition::CustomType(CustomType { name, .. }) 45 - | Definition::TypeAlias(TypeAlias { alias: name, .. }) => { 46 - if name == "BitString" && self.bit_string_name == "BitString" { 47 - self.bit_string_name = "".into(); 48 - } 49 - } 50 - 51 - Definition::Import(i) => { 52 - if i.module == "gleam" { 53 - self.prelude_module_import_alias = i.used_name(); 54 - } else { 55 - for i in i.unqualified_values.iter().chain(&i.unqualified_types) { 56 - if i.used_name() == "BitString" && self.bit_string_name == "BitString" { 57 - self.bit_string_name = "".into(); 58 - } 59 - } 60 - } 61 - } 62 - } 63 - } 64 - } 65 - 66 - impl UntypedModuleFolder for Fixer { 67 - fn fold_import(&mut self, mut i: UntypedImport, _target: Option<Target>) -> Import<()> { 68 - if i.module == "gleam" { 69 - i.unqualified_values 70 - .iter_mut() 71 - .chain(&mut i.unqualified_types) 72 - .filter(|i| i.name == "BitString") 73 - .for_each(|i| i.name = "BitArray".into()); 74 - } 75 - i 76 - } 77 - } 78 - 79 - impl UntypedConstantFolder for Fixer { 80 - fn fold_constant_record( 81 - &mut self, 82 - location: SrcSpan, 83 - module: Option<EcoString>, 84 - name: EcoString, 85 - args: Vec<CallArg<UntypedConstant>>, 86 - ) -> UntypedConstant { 87 - let name = if name == self.bit_string_name { 88 - self.bit_array_name.clone() 89 - } else { 90 - name 91 - }; 92 - Constant::Record { 93 - location, 94 - module, 95 - name, 96 - args, 97 - tag: (), 98 - typ: (), 99 - field_map: None, 100 - } 101 - } 102 - } 103 - 104 - impl UntypedExprFolder for Fixer {} 105 - 106 - impl TypeAstFolder for Fixer { 107 - fn fold_type_constructor(&mut self, mut constructor: TypeAstConstructor) -> TypeAst { 108 - if constructor.name == self.bit_string_name { 109 - constructor.name = self.bit_array_name.clone(); 110 - } 111 - 112 - TypeAst::Constructor(constructor) 113 - } 114 - } 115 - 116 - impl PatternFolder for Fixer {}
-219
compiler-core/src/fix/import_type.rs
··· 1 - use std::collections::HashMap; 2 - 3 - use crate::{ 4 - analyse::Inferred, 5 - ast::{ 6 - CallArg, Constant, Definition, Pattern, SrcSpan, TypeAst, TypeAstConstructor, 7 - UntypedConstant, UntypedDefinition, UntypedExpr, UntypedImport, UntypedModule, 8 - UntypedPattern, 9 - }, 10 - ast_folder::{ 11 - PatternFolder, TypeAstFolder, UntypedConstantFolder, UntypedExprFolder, UntypedModuleFolder, 12 - }, 13 - }; 14 - use ecow::EcoString; 15 - use im::HashSet; 16 - 17 - #[derive(Debug, Default)] 18 - pub struct Fixer { 19 - imports: HashMap<EcoString, Imported>, 20 - local_types: HashSet<EcoString>, 21 - local_values: HashSet<EcoString>, 22 - } 23 - 24 - impl Fixer { 25 - pub fn fix(module: UntypedModule) -> UntypedModule { 26 - Self::default().fix_module(module) 27 - } 28 - 29 - fn fix_module(&mut self, module: UntypedModule) -> UntypedModule { 30 - for d in module.definitions.iter() { 31 - self.register_items(&d.definition); 32 - } 33 - 34 - // Determine which imported constructors are used as types and which are 35 - // used as values. 36 - let mut module = self.fold_module(module); 37 - 38 - for d in module.definitions.iter_mut() { 39 - if let Definition::Import(ref mut i) = d.definition { 40 - self.fix_import(i); 41 - } 42 - } 43 - 44 - module 45 - } 46 - 47 - fn register_unqualified_imported_constructors(&mut self, i: &UntypedImport) { 48 - for unqualified in &i.unqualified_values { 49 - let first_char = unqualified.name.chars().next().unwrap_or('a'); 50 - if first_char.is_uppercase() { 51 - let data = Imported { 52 - module: i.module.clone(), 53 - used_as_type: false, 54 - used_as_value: false, 55 - }; 56 - let _ = self.imports.insert(unqualified.used_name().clone(), data); 57 - } 58 - } 59 - } 60 - 61 - fn fix_import(&mut self, import: &mut UntypedImport) { 62 - let existing_types: HashSet<EcoString> = import 63 - .unqualified_types 64 - .iter() 65 - .map(|t| t.used_name().clone()) 66 - .collect(); 67 - let mut types = vec![]; 68 - let mut values = vec![]; 69 - 70 - for unqualified in import.unqualified_values.drain(..) { 71 - match self.imports.get_mut(unqualified.used_name()) { 72 - Some(i) if i.module == import.module => { 73 - if i.used_as_type && !existing_types.contains(unqualified.used_name()) { 74 - types.push(unqualified.clone()); 75 - } 76 - if i.used_as_value { 77 - values.push(unqualified.clone()); 78 - } 79 - } 80 - _ => values.push(unqualified), 81 - } 82 - } 83 - 84 - import.unqualified_values = values; 85 - for t in types { 86 - import.unqualified_types.push(t); 87 - } 88 - } 89 - 90 - fn register_items(&mut self, definition: &UntypedDefinition) { 91 - match definition { 92 - Definition::Function(_) | Definition::ModuleConstant(_) => (), 93 - 94 - Definition::TypeAlias(a) => { 95 - let _ = self.local_types.insert(a.alias.clone()); 96 - } 97 - 98 - Definition::CustomType(c) => { 99 - let _ = self.local_types.insert(c.name.clone()); 100 - for c in &c.constructors { 101 - let _ = self.local_values.insert(c.name.clone()); 102 - } 103 - } 104 - 105 - Definition::Import(i) => self.register_unqualified_imported_constructors(i), 106 - } 107 - } 108 - } 109 - 110 - impl UntypedModuleFolder for Fixer {} 111 - 112 - impl UntypedConstantFolder for Fixer { 113 - fn fold_constant_record( 114 - &mut self, 115 - location: SrcSpan, 116 - module: Option<EcoString>, 117 - name: EcoString, 118 - args: Vec<CallArg<UntypedConstant>>, 119 - ) -> UntypedConstant { 120 - if module.is_none() 121 - && !(name == "Ok" || name == "Error") 122 - && !self.local_values.contains(&name) 123 - { 124 - if let Some(import) = self.imports.get_mut(&name) { 125 - import.used_as_value = true; 126 - } 127 - } 128 - Constant::Record { 129 - location, 130 - module, 131 - name, 132 - args, 133 - tag: (), 134 - typ: (), 135 - field_map: None, 136 - } 137 - } 138 - 139 - fn fold_constant_var( 140 - &mut self, 141 - location: SrcSpan, 142 - module: Option<EcoString>, 143 - name: EcoString, 144 - ) -> UntypedConstant { 145 - if module.is_none() && !self.local_values.contains(&name) { 146 - if let Some(import) = self.imports.get_mut(&name) { 147 - import.used_as_value = true; 148 - } 149 - } 150 - Constant::Var { 151 - location, 152 - module, 153 - name, 154 - constructor: None, 155 - typ: (), 156 - } 157 - } 158 - } 159 - 160 - impl UntypedExprFolder for Fixer { 161 - fn fold_var(&mut self, location: SrcSpan, name: EcoString) -> UntypedExpr { 162 - if !(self.local_values.contains(&name) || name == "Ok" || name == "Error") { 163 - if let Some(import) = self.imports.get_mut(&name) { 164 - import.used_as_value = true; 165 - } 166 - } 167 - UntypedExpr::Var { location, name } 168 - } 169 - } 170 - 171 - impl TypeAstFolder for Fixer { 172 - fn fold_type_constructor(&mut self, constructor: TypeAstConstructor) -> TypeAst { 173 - let name = &constructor.name; 174 - if constructor.module.is_none() 175 - && !(name == "Result" || name == "List") 176 - && !self.local_types.contains(name) 177 - { 178 - if let Some(import) = self.imports.get_mut(&constructor.name) { 179 - import.used_as_type = true; 180 - } 181 - } 182 - 183 - TypeAst::Constructor(constructor) 184 - } 185 - } 186 - 187 - impl PatternFolder for Fixer { 188 - fn fold_pattern_constructor( 189 - &mut self, 190 - location: SrcSpan, 191 - name: EcoString, 192 - arguments: Vec<CallArg<UntypedPattern>>, 193 - module: Option<EcoString>, 194 - with_spread: bool, 195 - ) -> UntypedPattern { 196 - if module.is_none() && !self.local_types.contains(&name) { 197 - if let Some(import) = self.imports.get_mut(&name) { 198 - import.used_as_value = true; 199 - } 200 - } 201 - 202 - Pattern::Constructor { 203 - location, 204 - name, 205 - arguments, 206 - module, 207 - with_spread, 208 - constructor: Inferred::Unknown, 209 - type_: (), 210 - } 211 - } 212 - } 213 - 214 - #[derive(Debug, Default)] 215 - struct Imported { 216 - module: EcoString, 217 - used_as_type: bool, 218 - used_as_value: bool, 219 - }
-569
compiler-core/src/fix/tests.rs
··· 1 - use super::*; 2 - 3 - use camino::Utf8Path; 4 - 5 - fn fix(src: &str) -> String { 6 - parse_fix_and_format(&src.into(), Utf8Path::new("test")).unwrap() 7 - } 8 - 9 - #[test] 10 - fn empty() { 11 - assert_eq!(fix(""), "\n") 12 - } 13 - 14 - #[test] 15 - fn import() { 16 - assert_eq!( 17 - fix("import gleam.{BitString} 18 - 19 - type X = 20 - BitString"), 21 - "import gleam.{type BitArray} 22 - 23 - type X = 24 - BitArray 25 - " 26 - ); 27 - } 28 - 29 - #[test] 30 - fn import_new_syntax() { 31 - assert_eq!( 32 - fix("import gleam.{type BitString} 33 - 34 - type X = 35 - BitString"), 36 - "import gleam.{type BitArray} 37 - 38 - type X = 39 - BitArray 40 - " 41 - ); 42 - } 43 - 44 - #[test] 45 - fn import_aliased() { 46 - assert_eq!( 47 - fix("import gleam.{type BitString as B}"), 48 - "import gleam.{type BitArray as B}\n" 49 - ); 50 - } 51 - 52 - #[test] 53 - fn alias() { 54 - assert_eq!( 55 - fix("pub type X = 56 - BitString 57 - "), 58 - "pub type X = 59 - BitArray 60 - " 61 - ); 62 - } 63 - 64 - #[test] 65 - fn alias_qualified() { 66 - assert_eq!( 67 - fix("import gleam 68 - 69 - pub type X = 70 - gleam.BitString 71 - "), 72 - "import gleam 73 - 74 - pub type X = 75 - gleam.BitArray 76 - " 77 - ); 78 - } 79 - 80 - #[test] 81 - fn alias_qualified_aliased() { 82 - assert_eq!( 83 - fix("import gleam as g 84 - 85 - pub type X = 86 - g.BitString 87 - "), 88 - "import gleam as g 89 - 90 - pub type X = 91 - g.BitArray 92 - " 93 - ); 94 - } 95 - 96 - #[test] 97 - fn custom_type() { 98 - assert_eq!( 99 - fix("pub type X { 100 - X(BitString) 101 - } 102 - "), 103 - "pub type X { 104 - X(BitArray) 105 - } 106 - " 107 - ); 108 - } 109 - 110 - #[test] 111 - fn custom_type_qualified() { 112 - assert_eq!( 113 - fix("import gleam 114 - 115 - pub type X { 116 - X(gleam.BitString) 117 - } 118 - "), 119 - "import gleam 120 - 121 - pub type X { 122 - X(gleam.BitArray) 123 - } 124 - " 125 - ); 126 - } 127 - 128 - #[test] 129 - fn custom_type_qualified_aliased() { 130 - assert_eq!( 131 - fix("import gleam as g 132 - 133 - pub type X { 134 - X(g.BitString) 135 - } 136 - "), 137 - "import gleam as g 138 - 139 - pub type X { 140 - X(g.BitArray) 141 - } 142 - " 143 - ); 144 - } 145 - 146 - #[test] 147 - fn shadowed_by_alias() { 148 - assert_eq!( 149 - fix("pub type X = 150 - BitString 151 - 152 - pub type BitString = 153 - Int 154 - "), 155 - "pub type X = 156 - BitString 157 - 158 - pub type BitString = 159 - Int 160 - " 161 - ); 162 - } 163 - 164 - #[test] 165 - fn shadowed_by_custom_type() { 166 - assert_eq!( 167 - fix("pub type X = 168 - BitString 169 - 170 - pub type BitString { 171 - B 172 - } 173 - "), 174 - "pub type X = 175 - BitString 176 - 177 - pub type BitString { 178 - B 179 - } 180 - " 181 - ); 182 - } 183 - 184 - #[test] 185 - fn shadowed_by_import() { 186 - assert_eq!( 187 - fix("import x.{BitString} 188 - 189 - pub type X = 190 - BitString 191 - "), 192 - "import x.{type BitString} 193 - 194 - pub type X = 195 - BitString 196 - " 197 - ); 198 - } 199 - 200 - #[test] 201 - fn return_type() { 202 - assert_eq!( 203 - fix("pub fn main() -> BitString { 204 - todo 205 - } 206 - "), 207 - "pub fn main() -> BitArray { 208 - todo 209 - } 210 - " 211 - ); 212 - } 213 - 214 - #[test] 215 - fn arguments() { 216 - assert_eq!( 217 - fix("pub fn main( 218 - a: BitString, 219 - b b: List(BitString), 220 - z, 221 - _: BitString, 222 - _: BitString, 223 - ) -> Nil { 224 - todo 225 - } 226 - "), 227 - "pub fn main( 228 - a: BitArray, 229 - b b: List(BitArray), 230 - z, 231 - _: BitArray, 232 - _: BitArray, 233 - ) -> Nil { 234 - todo 235 - } 236 - " 237 - ); 238 - } 239 - 240 - #[test] 241 - fn let_annotation() { 242 - assert_eq!( 243 - fix("pub fn main() { 244 - let x: List(BitString) = todo 245 - } 246 - "), 247 - "pub fn main() { 248 - let x: List(BitArray) = todo 249 - } 250 - " 251 - ); 252 - } 253 - 254 - #[test] 255 - fn use_annotation() { 256 - assert_eq!( 257 - fix("pub fn main() { 258 - use x: List(BitString), y: BitString <- todo 259 - } 260 - "), 261 - "pub fn main() { 262 - use x: List(BitArray), y: BitArray <- todo 263 - } 264 - " 265 - ); 266 - } 267 - 268 - #[test] 269 - fn constant() { 270 - assert_eq!( 271 - fix("pub const x: BitString = <<>>"), 272 - "pub const x: BitArray = <<>>\n" 273 - ); 274 - } 275 - 276 - #[test] 277 - fn imported_used_in_const() { 278 - assert_eq!( 279 - fix("import x.{X} 280 - 281 - const x = X 282 - "), 283 - "import x.{X} 284 - 285 - const x = X 286 - " 287 - ); 288 - } 289 - 290 - #[test] 291 - fn imported_type_only() { 292 - assert_eq!( 293 - fix("import x.{X} 294 - 295 - const x = X 296 - 297 - type Y { 298 - X(X) 299 - } 300 - "), 301 - "import x.{type X} 302 - 303 - const x = X 304 - 305 - type Y { 306 - X(X) 307 - } 308 - " 309 - ); 310 - } 311 - 312 - #[test] 313 - fn imported_value_and_type() { 314 - assert_eq!( 315 - fix("import x.{X} 316 - 317 - const x = X 318 - 319 - type Y { 320 - Y(X) 321 - } 322 - "), 323 - "import x.{type X, X} 324 - 325 - const x = X 326 - 327 - type Y { 328 - Y(X) 329 - } 330 - " 331 - ); 332 - } 333 - 334 - #[test] 335 - fn imported_value_only() { 336 - assert_eq!( 337 - fix("import x.{X} 338 - 339 - const x = X 340 - 341 - type X { 342 - Z(X) 343 - } 344 - "), 345 - "import x.{X} 346 - 347 - const x = X 348 - 349 - type X { 350 - Z(X) 351 - } 352 - " 353 - ); 354 - } 355 - 356 - #[test] 357 - fn pattern() { 358 - assert_eq!( 359 - fix("import x.{X} 360 - 361 - pub fn main(x) { 362 - case x { 363 - X -> 1 364 - _ -> 0 365 - } 366 - } 367 - "), 368 - "import x.{X} 369 - 370 - pub fn main(x) { 371 - case x { 372 - X -> 1 373 - _ -> 0 374 - } 375 - } 376 - " 377 - ); 378 - } 379 - 380 - #[test] 381 - fn aliased_type_import() { 382 - assert_eq!( 383 - fix("import x.{X as Y} 384 - 385 - pub type Z = 386 - Y 387 - "), 388 - "import x.{type X as Y} 389 - 390 - pub type Z = 391 - Y 392 - " 393 - ); 394 - } 395 - 396 - #[test] 397 - fn already_fixed() { 398 - assert_eq!( 399 - fix("import x.{type X, X} 400 - 401 - pub const x = X 402 - 403 - pub type Z = 404 - X 405 - "), 406 - "import x.{type X, X} 407 - 408 - pub const x = X 409 - 410 - pub type Z = 411 - X 412 - ", 413 - ); 414 - } 415 - 416 - #[test] 417 - fn error_type() { 418 - assert_eq!( 419 - fix("import thing.{Error} 420 - 421 - pub fn main() -> Result(Nil, Error) { 422 - Error(thing.make_error()) 423 - } 424 - "), 425 - "import thing.{type Error} 426 - 427 - pub fn main() -> Result(Nil, Error) { 428 - Error(thing.make_error()) 429 - } 430 - " 431 - ); 432 - } 433 - 434 - #[test] 435 - fn ok_type() { 436 - assert_eq!( 437 - fix("import thing.{Ok} 438 - 439 - pub fn main() -> Result(Ok, Nil) { 440 - Ok(thing.make_ok()) 441 - } 442 - "), 443 - "import thing.{type Ok} 444 - 445 - pub fn main() -> Result(Ok, Nil) { 446 - Ok(thing.make_ok()) 447 - } 448 - " 449 - ); 450 - } 451 - 452 - #[test] 453 - fn list_value() { 454 - assert_eq!( 455 - fix("import thing.{List} 456 - 457 - pub fn main() -> List(Int) { 458 - List 459 - [] 460 - } 461 - "), 462 - "import thing.{List} 463 - 464 - pub fn main() -> List(Int) { 465 - List 466 - [] 467 - } 468 - " 469 - ); 470 - } 471 - #[test] 472 - fn result_value() { 473 - assert_eq!( 474 - fix("import thing.{Result} 475 - 476 - pub fn main() -> Result(Int, Nil) { 477 - Result 478 - Ok(1) 479 - } 480 - "), 481 - "import thing.{Result} 482 - 483 - pub fn main() -> Result(Int, Nil) { 484 - Result 485 - Ok(1) 486 - } 487 - " 488 - ); 489 - } 490 - 491 - #[test] 492 - fn const_error_type() { 493 - assert_eq!( 494 - fix("import thing.{Error} 495 - 496 - pub const x = Error 497 - 498 - pub type Y = 499 - Error 500 - "), 501 - "import thing.{type Error} 502 - 503 - pub const x = Error 504 - 505 - pub type Y = 506 - Error 507 - " 508 - ); 509 - } 510 - 511 - #[test] 512 - fn const_ok_type() { 513 - assert_eq!( 514 - fix("import thing.{Ok} 515 - 516 - pub const x = Ok 517 - 518 - pub type Y = 519 - Ok 520 - "), 521 - "import thing.{type Ok} 522 - 523 - pub const x = Ok 524 - 525 - pub type Y = 526 - Ok 527 - " 528 - ); 529 - } 530 - 531 - #[test] 532 - fn const_list_value() { 533 - assert_eq!( 534 - fix("import thing.{List} 535 - 536 - pub const x = List 537 - 538 - pub type Y = 539 - List(Int) 540 - "), 541 - "import thing.{List} 542 - 543 - pub const x = List 544 - 545 - pub type Y = 546 - List(Int) 547 - " 548 - ); 549 - } 550 - 551 - #[test] 552 - fn const_result_value() { 553 - assert_eq!( 554 - fix("import thing.{Result} 555 - 556 - pub const x = Result 557 - 558 - pub type Y = 559 - Result(Int, Nil) 560 - "), 561 - "import thing.{Result} 562 - 563 - pub const x = Result 564 - 565 - pub type Y = 566 - Result(Int, Nil) 567 - " 568 - ); 569 - }