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

Configure Feed

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

Represent tuples as their own type, not structs

author
Danielle Maywood
committer
nandi
date (Jul 26, 2026, 12:11 PM -0700) commit c3c41d93 parent a20054a3 change-id lnolnmyt
+198 -18
+70 -6
compiler-core/src/cranelift.rs
··· 75 75 76 76 let returns = mangle_type_name(returns); 77 77 78 - eco_format!("F{}{}R{}", arguments.len(), arguments, returns) 78 + eco_format!("F{}f{}R{}", arguments.len(), arguments, returns) 79 + } 80 + ast::CompleteType::Tuple { elements } => { 81 + let elements = elements 82 + .iter() 83 + .map(mangle_type_name) 84 + .map(|s| eco_format!("{}{}", s.len(), s)) 85 + .join(""); 86 + 87 + eco_format!("T{}t{}", elements.len(), elements) 79 88 } 80 89 ast::CompleteType::Struct { elements } => { 81 90 let elements = elements ··· 84 93 .map(|s| eco_format!("{}{}", s.len(), s)) 85 94 .join(""); 86 95 87 - eco_format!("C{}{}", elements.len(), elements) 96 + eco_format!("C{}c{}", elements.len(), elements) 88 97 } 89 98 ast::CompleteType::List(element_type) => { 90 99 let element = mangle_type_name(element_type); ··· 100 109 arguments: &[ast::CompleteType], 101 110 returns: &ast::CompleteType, 102 111 ) -> EcoString { 103 - let arguments = arguments.iter().map(mangle_type_name).join(","); 112 + let arguments = arguments 113 + .iter() 114 + .map(mangle_type_name) 115 + .map(|s| eco_format!("{}{}", s.len(), s)) 116 + .join(""); 104 117 let returns = mangle_type_name(returns); 105 118 106 119 eco_format!( 107 - "M{}{}_{}{}_A{}{}_R{}", 120 + "M{}{}_{}{}_A{}a{}_R{}", 108 121 module.len(), 109 122 module.replace("/", "_"), 110 123 name.len(), ··· 204 217 arguments: _, 205 218 returns: _, 206 219 } => types::I64, 220 + ast::CompleteType::Tuple { elements: _ } => types::I64, 207 221 ast::CompleteType::Struct { elements: _ } => types::I64, 208 222 ast::CompleteType::List(_complete_type) => types::I64, 209 223 } ··· 300 314 arguments: _, 301 315 returns: _, 302 316 } => todo!(), 317 + ast::CompleteType::Tuple { elements: _ } => todo!(), 303 318 ast::CompleteType::Struct { elements: _ } => todo!(), 304 319 ast::CompleteType::List(_complete_type) => todo!(), 305 320 }, ··· 418 433 tail: _, 419 434 type_: _, 420 435 } => todo!(), 436 + ast::Expression::Tuple { items, type_: _ } => { 437 + let mut sig = self.module.make_signature(); 438 + sig.params.push(AbiParam::new(types::I64)); 439 + sig.returns.push(AbiParam::new(types::I64)); 440 + 441 + let id = self 442 + .module 443 + .declare_function("malloc", Linkage::Import, &sig) 444 + .expect("failed to declare malloc"); 445 + 446 + let malloc = self.module.declare_func_in_func(id, &mut self.builder.func); 447 + 448 + let size_arg = self 449 + .builder 450 + .ins() 451 + .iconst(types::I64, (items.len() as i64) * 8); 452 + 453 + let call = self.builder.ins().call(malloc, &[size_arg]); 454 + let ptr = self.builder.inst_results(call)[0]; 455 + 456 + for (index, item) in items.into_iter().enumerate() { 457 + let index = index as i32; 458 + 459 + let value = self.translate(item); 460 + 461 + _ = self.builder.ins().store( 462 + MemFlags::new(), 463 + value, 464 + ptr, 465 + Offset32::new(index * 8), 466 + ); 467 + } 468 + 469 + ptr 470 + } 471 + ast::Expression::TupleAccess { 472 + value, 473 + index, 474 + type_, 475 + } => { 476 + let ptr = self.translate(*value); 477 + 478 + self.builder.ins().load( 479 + translate_type(&type_), 480 + MemFlags::new(), 481 + ptr, 482 + Offset32::new(index as i32 * 8), 483 + ) 484 + } 421 485 ast::Expression::Struct { 422 486 tag, 423 487 items, ··· 442 506 let call = self.builder.ins().call(malloc, &[size_arg]); 443 507 let ptr = self.builder.inst_results(call)[0]; 444 508 445 - let tag = i64::from(tag.unwrap_or_default()); 446 - let tag = self.builder.ins().iconst(types::I64, tag); 509 + let tag = self.builder.ins().iconst(types::I64, i64::from(tag)); 447 510 _ = self 448 511 .builder 449 512 .ins() ··· 558 621 } 559 622 ast::Expression::Panic { type_, .. } => match type_ { 560 623 ast::CompleteType::Func { .. } 624 + | ast::CompleteType::Tuple { .. } 561 625 | ast::CompleteType::Struct { .. } 562 626 | ast::CompleteType::List(_) 563 627 | ast::CompleteType::String
+4 -6
compiler-core/src/cranelift/mir.rs
··· 173 173 return_type: IncompleteType::Struct { elements: vec![] }, 174 174 parameters, 175 175 body: Expression::Block(vec![Expression::<IncompleteType>::Struct { 176 - tag: Some(index as u32), 176 + tag: index as u32, 177 177 items: constructor 178 178 .arguments 179 179 .iter() ··· 620 620 location: _, 621 621 type_, 622 622 elements, 623 - } => Expression::Struct { 624 - tag: None, 623 + } => Expression::Tuple { 625 624 items: elements 626 625 .iter() 627 626 .map(|element| self.translate_expression(element)) ··· 633 632 type_, 634 633 index, 635 634 tuple, 636 - } => Expression::StructAccess { 635 + } => Expression::TupleAccess { 637 636 value: Box::new(self.translate_expression(tuple)), 638 637 index: *index, 639 638 type_: Translator::translate_type(type_), ··· 1140 1139 crate::ast::Constant::Tuple { 1141 1140 location: _, 1142 1141 elements, 1143 - } => Expression::Struct { 1144 - tag: None, 1142 + } => Expression::Tuple { 1145 1143 items: elements 1146 1144 .iter() 1147 1145 .map(|element| self.translate_constant(element))
+22 -1
compiler-core/src/cranelift/mir/ast.rs
··· 11 11 arguments: Vec<IncompleteType>, 12 12 returns: Box<IncompleteType>, 13 13 }, 14 + Tuple { 15 + elements: Vec<IncompleteType>, 16 + }, 14 17 Struct { 15 18 elements: Vec<IncompleteType>, 16 19 }, ··· 29 32 Func { 30 33 arguments: Vec<CompleteType>, 31 34 returns: Box<CompleteType>, 35 + }, 36 + Tuple { 37 + elements: Vec<CompleteType>, 32 38 }, 33 39 Struct { 34 40 elements: Vec<CompleteType>, ··· 197 203 type_: T, 198 204 }, 199 205 206 + Tuple { 207 + items: Vec<Expression<T>>, 208 + type_: T, 209 + }, 210 + 211 + TupleAccess { 212 + value: Box<Expression<T>>, 213 + index: u64, 214 + type_: T, 215 + }, 216 + 200 217 Struct { 201 - tag: Option<u32>, 218 + tag: u32, 202 219 items: Vec<Expression<T>>, 203 220 type_: T, 204 221 }, ··· 269 286 Expression::FloatDiv { .. } => IncompleteType::Bool, 270 287 Expression::StringConcat { .. } => IncompleteType::Bool, 271 288 Expression::List { type_, .. } => type_.clone(), 289 + Expression::Tuple { type_, .. } => type_.clone(), 290 + Expression::TupleAccess { type_, .. } => type_.clone(), 272 291 Expression::Struct { type_, .. } => type_.clone(), 273 292 Expression::StructTag { .. } => IncompleteType::Int, 274 293 Expression::StructAccess { type_, .. } => type_.clone(), ··· 314 333 Expression::FloatDiv { .. } => CompleteType::Bool, 315 334 Expression::StringConcat { .. } => CompleteType::Bool, 316 335 Expression::List { type_, .. } => type_.clone(), 336 + Expression::Tuple { type_, .. } => type_.clone(), 337 + Expression::TupleAccess { type_, .. } => type_.clone(), 317 338 Expression::Struct { type_, .. } => type_.clone(), 318 339 Expression::StructTag { .. } => CompleteType::Int, 319 340 Expression::StructAccess { type_, .. } => type_.clone(),
+53
compiler-core/src/cranelift/mir/lower.rs
··· 113 113 114 114 self.collect_type_ids(returns, complete_returns); 115 115 } 116 + IncompleteType::Tuple { elements } => { 117 + let CompleteType::Tuple { elements: complete } = complete else { 118 + unreachable!("types should not be diverged") 119 + }; 120 + 121 + for (element, complete) in elements.iter().zip(complete.iter()) { 122 + self.collect_type_ids(element, complete); 123 + } 124 + } 116 125 IncompleteType::Struct { elements } => { 117 126 let CompleteType::Struct { elements: complete } = complete else { 118 127 unreachable!("types should not be diverged") ··· 286 295 tail: tail.map(|t| Box::new(self.translate_expression(*t))), 287 296 type_: self.translate_type(type_), 288 297 }, 298 + Expression::Tuple { items, type_ } => Expression::Tuple { 299 + items: items 300 + .into_iter() 301 + .map(|item| self.translate_expression(item)) 302 + .collect(), 303 + type_: self.translate_type(type_), 304 + }, 305 + Expression::TupleAccess { 306 + value, 307 + index, 308 + type_, 309 + } => Expression::TupleAccess { 310 + value: Box::new(self.translate_expression(*value)), 311 + index, 312 + type_: self.translate_type(type_), 313 + }, 289 314 Expression::Struct { tag, items, type_ } => Expression::Struct { 290 315 tag, 291 316 items: items ··· 349 374 .collect(), 350 375 returns: Box::new(self.translate_type(*returns)), 351 376 }, 377 + IncompleteType::Tuple { elements } => CompleteType::Tuple { 378 + elements: elements 379 + .into_iter() 380 + .map(|element| self.translate_type(element)) 381 + .collect(), 382 + }, 352 383 IncompleteType::Struct { elements } => CompleteType::Struct { 353 384 elements: elements 354 385 .into_iter() ··· 562 593 .transpose()?, 563 594 type_: type_.try_into()?, 564 595 }), 596 + Expression::Tuple { items, type_ } => Ok(Expression::Tuple { 597 + items: items 598 + .into_iter() 599 + .map(Expression::try_from) 600 + .collect::<Result<Vec<_>, _>>()?, 601 + type_: type_.try_into()?, 602 + }), 603 + Expression::TupleAccess { 604 + value, 605 + index, 606 + type_, 607 + } => Ok(Expression::TupleAccess { 608 + value: Box::new(Expression::try_from(*value)?), 609 + index, 610 + type_: type_.try_into()?, 611 + }), 565 612 Expression::Struct { tag, items, type_ } => Ok(Expression::Struct { 566 613 tag, 567 614 items: items ··· 628 675 .map(Self::try_from) 629 676 .collect::<Result<Vec<_>, _>>()?, 630 677 returns: Box::new(Self::try_from(*returns)?), 678 + }), 679 + IncompleteType::Tuple { elements } => Ok(Self::Tuple { 680 + elements: elements 681 + .into_iter() 682 + .map(Self::try_from) 683 + .collect::<Result<Vec<_>, _>>()?, 631 684 }), 632 685 IncompleteType::Struct { elements } => Ok(Self::Struct { 633 686 elements: elements
+44 -2
compiler-core/src/cranelift/mir/visit.rs
··· 219 219 visit_expression_list(self, items, tail, type_); 220 220 } 221 221 222 + fn visit_expression_tuple(&mut self, items: &'mir mut Vec<Expression<T>>, type_: &'mir mut T) { 223 + visit_expression_tuple(self, items, type_); 224 + } 225 + 226 + fn visit_expression_tuple_access( 227 + &mut self, 228 + value: &'mir mut Expression<T>, 229 + index: &'mir mut u64, 230 + type_: &'mir mut T, 231 + ) { 232 + visit_expression_tuple_access(self, value, index, type_); 233 + } 234 + 222 235 fn visit_expression_struct( 223 236 &mut self, 224 - tag: &'mir mut Option<u32>, 237 + tag: &'mir mut u32, 225 238 items: &'mir mut Vec<Expression<T>>, 226 239 type_: &'mir mut T, 227 240 ) { ··· 322 335 Expression::FloatDiv { lhs, rhs } => v.visit_expression_float_div(lhs, rhs), 323 336 Expression::StringConcat { lhs, rhs } => v.visit_expression_string_concat(lhs, rhs), 324 337 Expression::List { items, tail, type_ } => v.visit_expression_list(items, tail, type_), 338 + Expression::Tuple { items, type_ } => v.visit_expression_tuple(items, type_), 339 + Expression::TupleAccess { 340 + value, 341 + index, 342 + type_, 343 + } => v.visit_expression_tuple_access(value, index, type_), 325 344 Expression::Struct { tag, items, type_ } => v.visit_expression_struct(tag, items, type_), 326 345 Expression::StructTag { value } => v.visit_expression_struct_tag(value), 327 346 Expression::StructAccess { ··· 626 645 } 627 646 } 628 647 648 + pub fn visit_expression_tuple<'mir, T, V>( 649 + v: &mut V, 650 + items: &'mir mut Vec<Expression<T>>, 651 + _type: &'mir mut T, 652 + ) where 653 + V: Visit<'mir, T> + ?Sized, 654 + { 655 + for item in items { 656 + v.visit_expression(item); 657 + } 658 + } 659 + 660 + pub fn visit_expression_tuple_access<'mir, T, V>( 661 + v: &mut V, 662 + value: &'mir mut Expression<T>, 663 + _index: &'mir mut u64, 664 + _type: &'mir mut T, 665 + ) where 666 + V: Visit<'mir, T> + ?Sized, 667 + { 668 + v.visit_expression(value); 669 + } 670 + 629 671 pub fn visit_expression_struct<'mir, T, V>( 630 672 v: &mut V, 631 - _tag: &'mir mut Option<u32>, 673 + _tag: &'mir mut u32, 632 674 items: &'mir mut Vec<Expression<T>>, 633 675 _type: &'mir mut T, 634 676 ) where
test/project_cranelift/a.out

This is a binary file and will not be displayed.

+2 -2
test/project_cranelift/main.c
··· 1 1 #include <stdio.h> 2 2 3 - unsigned long long M17project_cranelift_4main_A0_RI(); 3 + unsigned long long M17project_cranelift_4main_A0a_RI(); 4 4 5 5 int main() { 6 - unsigned long long outcome = M17project_cranelift_4main_A0_RI(); 6 + unsigned long long outcome = M17project_cranelift_4main_A0a_RI(); 7 7 printf("%lld\n", outcome); 8 8 }
+3 -1
test/project_cranelift/src/project_cranelift.gleam
··· 13 13 pub fn main() { 14 14 let wibble = Wibble(x: 30, y: 35) 15 15 let wobble = Wobble(x: 40) 16 + let sample = #(1, 2, 3) 17 + let sample = sample.0 + sample.1 + sample.2 16 18 17 - sum(wibble) + sum(wobble) 19 + sum(wibble) + sum(wobble) + sample 18 20 }