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 / metadata / module_decoder.rs
23 kB 626 lines
1#![allow(clippy::unnecessary_wraps)] // Needed for macro 2 3use capnp::text; 4use ecow::EcoString; 5use itertools::Itertools; 6 7use crate::{ 8 Result, 9 ast::{ 10 BitArrayOption, BitArraySegment, CallArg, Constant, Publicity, SrcSpan, TypedConstant, 11 TypedConstantBitArraySegment, TypedConstantBitArraySegmentOption, 12 }, 13 build::Origin, 14 line_numbers::LineNumbers, 15 schema_capnp::{self as schema, *}, 16 type_::{ 17 self, AccessorsMap, Deprecation, FieldMap, ModuleInterface, RecordAccessor, Type, 18 TypeConstructor, TypeValueConstructor, TypeValueConstructorField, TypeVariantConstructors, 19 ValueConstructor, ValueConstructorVariant, expression::Implementations, 20 }, 21 uid::UniqueIdGenerator, 22}; 23use std::{collections::HashMap, io::BufRead, sync::Arc}; 24 25macro_rules! read_vec { 26 ($reader:expr_2021, $self:expr_2021, $method:ident) => {{ 27 let reader = $reader; 28 let mut vec = Vec::with_capacity(reader.len() as usize); 29 for reader in reader.into_iter() { 30 let value = $self.$method(&reader)?; 31 vec.push(value); 32 } 33 vec 34 }}; 35} 36 37macro_rules! read_hashmap { 38 ($reader:expr_2021, $self:expr_2021, $method:ident) => {{ 39 let reader = $reader; 40 let mut map = HashMap::with_capacity(reader.len() as usize); 41 for prop in reader.into_iter() { 42 let name = $self.string(prop.get_key()?)?; 43 let values = $self.$method(&prop.get_value()?.into())?; 44 let _ = map.insert(name, values); 45 } 46 map 47 }}; 48} 49 50#[derive(Debug)] 51pub struct ModuleDecoder { 52 ids: UniqueIdGenerator, 53 type_var_id_map: HashMap<u64, u64>, 54} 55 56impl ModuleDecoder { 57 pub fn new(ids: UniqueIdGenerator) -> Self { 58 Self { 59 ids, 60 type_var_id_map: Default::default(), 61 } 62 } 63 64 pub fn read(&mut self, reader: impl BufRead) -> Result<ModuleInterface> { 65 let message_reader = 66 capnp::serialize_packed::read_message(reader, capnp::message::ReaderOptions::new())?; 67 let reader = message_reader.get_root::<module::Reader<'_>>()?; 68 69 Ok(ModuleInterface { 70 name: self.string(reader.get_name()?)?, 71 package: self.string(reader.get_package()?)?, 72 is_internal: reader.get_is_internal(), 73 origin: Origin::Src, 74 values: read_hashmap!(reader.get_values()?, self, value_constructor), 75 types: read_hashmap!(reader.get_types()?, self, type_constructor), 76 types_value_constructors: read_hashmap!( 77 reader.get_types_constructors()?, 78 self, 79 type_variants_constructors 80 ), 81 accessors: read_hashmap!(reader.get_accessors()?, self, accessors_map), 82 line_numbers: self.line_numbers(&reader.get_line_numbers()?)?, 83 src_path: self.str(reader.get_src_path()?)?.into(), 84 warnings: vec![], 85 minimum_required_version: self.version(&reader.get_required_version()?), 86 }) 87 } 88 89 fn string(&self, reader: text::Reader<'_>) -> Result<EcoString> { 90 self.str(reader).map(|str| str.into()) 91 } 92 93 fn str<'a>(&self, reader: text::Reader<'a>) -> Result<&'a str> { 94 reader 95 .to_str() 96 .map_err(|_| capnp::Error::failed("String contains non-utf8 charaters".into()).into()) 97 } 98 99 fn type_constructor( 100 &mut self, 101 reader: &type_constructor::Reader<'_>, 102 ) -> Result<TypeConstructor> { 103 let type_ = self.type_(&reader.get_type()?)?; 104 let deprecation = reader.get_deprecated()?; 105 let deprecation = if deprecation.is_empty() { 106 Deprecation::NotDeprecated 107 } else { 108 Deprecation::Deprecated { 109 message: self.string(deprecation)?, 110 } 111 }; 112 Ok(TypeConstructor { 113 publicity: self.publicity(reader.get_publicity()?)?, 114 origin: self.src_span(&reader.get_origin()?)?, 115 module: self.string(reader.get_module()?)?, 116 parameters: read_vec!(reader.get_parameters()?, self, type_), 117 type_, 118 deprecation, 119 documentation: self.optional_string(self.str(reader.get_documentation()?)?), 120 }) 121 } 122 123 fn type_(&mut self, reader: &schema::type_::Reader<'_>) -> Result<Arc<Type>> { 124 use schema::type_::Which; 125 match reader.which()? { 126 Which::App(reader) => self.type_app(&reader), 127 Which::Fn(reader) => self.type_fn(&reader), 128 Which::Tuple(reader) => self.type_tuple(&reader), 129 Which::Var(reader) => self.type_var(&reader), 130 } 131 } 132 133 fn type_app(&mut self, reader: &schema::type_::app::Reader<'_>) -> Result<Arc<Type>> { 134 let package = self.string(reader.get_package()?)?; 135 let module = self.string(reader.get_module()?)?; 136 let name = self.string(reader.get_name()?)?; 137 let args = read_vec!(&reader.get_parameters()?, self, type_); 138 let inferred_variant = self.inferred_variant(&reader.get_inferred_variant()?)?; 139 140 Ok(Arc::new(Type::Named { 141 publicity: Publicity::Public, 142 package, 143 module, 144 name, 145 args, 146 inferred_variant, 147 })) 148 } 149 150 fn type_fn(&mut self, reader: &schema::type_::fn_::Reader<'_>) -> Result<Arc<Type>> { 151 let retrn = self.type_(&reader.get_return()?)?; 152 let args = read_vec!(&reader.get_arguments()?, self, type_); 153 Ok(Arc::new(Type::Fn { args, retrn })) 154 } 155 156 fn type_tuple(&mut self, reader: &schema::type_::tuple::Reader<'_>) -> Result<Arc<Type>> { 157 let elems = read_vec!(&reader.get_elements()?, self, type_); 158 Ok(Arc::new(Type::Tuple { elems })) 159 } 160 161 fn type_var(&mut self, reader: &schema::type_::var::Reader<'_>) -> Result<Arc<Type>> { 162 let serialized_id = reader.get_id(); 163 let id = self.get_or_insert_type_var_id(serialized_id); 164 Ok(type_::generic_var(id)) 165 } 166 167 fn get_or_insert_type_var_id(&mut self, id: u64) -> u64 { 168 match self.type_var_id_map.get(&id) { 169 Some(&id) => id, 170 None => { 171 let new_id = self.ids.next(); 172 let _ = self.type_var_id_map.insert(id, new_id); 173 new_id 174 } 175 } 176 } 177 178 fn type_variants_constructors( 179 &mut self, 180 reader: &types_variant_constructors::Reader<'_>, 181 ) -> Result<TypeVariantConstructors> { 182 let variants = reader 183 .get_variants()? 184 .iter() 185 .map(|r| self.type_value_constructor(&r)) 186 .try_collect()?; 187 let type_parameters_ids = read_vec!( 188 reader.get_type_parameters_ids()?, 189 self, 190 type_variant_constructor_type_parameter_id 191 ); 192 Ok(TypeVariantConstructors { 193 variants, 194 type_parameters_ids, 195 }) 196 } 197 198 fn type_variant_constructor_type_parameter_id(&mut self, i: &u16) -> Result<u64> { 199 Ok(self.get_or_insert_type_var_id(*i as u64)) 200 } 201 202 fn type_value_constructor( 203 &mut self, 204 reader: &type_value_constructor::Reader<'_>, 205 ) -> Result<TypeValueConstructor> { 206 Ok(TypeValueConstructor { 207 name: self.string(reader.get_name()?)?, 208 parameters: read_vec!( 209 reader.get_parameters()?, 210 self, 211 type_value_constructor_parameter 212 ), 213 }) 214 } 215 216 fn type_value_constructor_parameter( 217 &mut self, 218 reader: &type_value_constructor_parameter::Reader<'_>, 219 ) -> Result<TypeValueConstructorField> { 220 Ok(TypeValueConstructorField { 221 type_: self.type_(&reader.get_type()?)?, 222 }) 223 } 224 225 fn inferred_variant(&mut self, reader: &inferred_variant::Reader<'_>) -> Result<Option<u16>> { 226 use schema::inferred_variant::Which; 227 match reader.which()? { 228 Which::Unknown(_) => Ok(None), 229 Which::Inferred(variant) => Ok(Some(variant)), 230 } 231 } 232 233 fn value_constructor( 234 &mut self, 235 reader: &value_constructor::Reader<'_>, 236 ) -> Result<ValueConstructor> { 237 let type_ = self.type_(&reader.get_type()?)?; 238 let variant = self.value_constructor_variant(&reader.get_variant()?)?; 239 let publicity = self.publicity(reader.get_publicity()?)?; 240 let deprecation = reader.get_deprecated()?; 241 let deprecation = if deprecation.is_empty() { 242 Deprecation::NotDeprecated 243 } else { 244 Deprecation::Deprecated { 245 message: self.string(deprecation)?, 246 } 247 }; 248 Ok(ValueConstructor { 249 deprecation, 250 publicity, 251 type_, 252 variant, 253 }) 254 } 255 256 fn publicity(&self, reader: publicity::Reader<'_>) -> Result<Publicity> { 257 match reader.which()? { 258 publicity::Which::Public(()) => Ok(Publicity::Public), 259 publicity::Which::Private(()) => Ok(Publicity::Private), 260 publicity::Which::Internal(reader) => match reader?.which()? { 261 option::Which::None(()) => Ok(Publicity::Internal { 262 attribute_location: None, 263 }), 264 option::Which::Some(reader) => Ok(Publicity::Internal { 265 attribute_location: Some(self.src_span(&reader?)?), 266 }), 267 }, 268 } 269 } 270 271 fn constant(&mut self, reader: &constant::Reader<'_>) -> Result<TypedConstant> { 272 use constant::Which; 273 match reader.which()? { 274 Which::Int(reader) => Ok(self.constant_int(self.str(reader?)?)), 275 Which::Float(reader) => Ok(self.constant_float(self.str(reader?)?)), 276 Which::String(reader) => Ok(self.constant_string(self.str(reader?)?)), 277 Which::Tuple(reader) => self.constant_tuple(&reader?), 278 Which::List(reader) => self.constant_list(&reader), 279 Which::Record(reader) => self.constant_record(&reader), 280 Which::BitArray(reader) => self.constant_bit_array(&reader?), 281 Which::Var(reader) => self.constant_var(&reader), 282 Which::StringConcatenation(reader) => self.constant_string_concatenation(&reader), 283 } 284 } 285 286 fn constant_int(&self, value: &str) -> TypedConstant { 287 Constant::Int { 288 location: Default::default(), 289 value: value.into(), 290 int_value: crate::parse::parse_int_value(value).expect("int value to parse as bigint"), 291 } 292 } 293 294 fn constant_float(&self, value: &str) -> TypedConstant { 295 Constant::Float { 296 location: Default::default(), 297 value: value.into(), 298 } 299 } 300 301 fn constant_string(&self, value: &str) -> TypedConstant { 302 Constant::String { 303 location: Default::default(), 304 value: value.into(), 305 } 306 } 307 308 fn constant_tuple( 309 &mut self, 310 reader: &capnp::struct_list::Reader<'_, constant::Owned>, 311 ) -> Result<TypedConstant> { 312 Ok(Constant::Tuple { 313 location: Default::default(), 314 elements: read_vec!(reader, self, constant), 315 }) 316 } 317 318 fn constant_list(&mut self, reader: &constant::list::Reader<'_>) -> Result<TypedConstant> { 319 let type_ = self.type_(&reader.get_type()?)?; 320 Ok(Constant::List { 321 location: Default::default(), 322 elements: read_vec!(reader.get_elements()?, self, constant), 323 type_, 324 }) 325 } 326 327 fn constant_record(&mut self, reader: &constant::record::Reader<'_>) -> Result<TypedConstant> { 328 let type_ = self.type_(&reader.get_type()?)?; 329 let tag = self.string(reader.get_tag()?)?; 330 let args = read_vec!(reader.get_args()?, self, constant_call_arg); 331 Ok(Constant::Record { 332 location: Default::default(), 333 module: Default::default(), 334 name: Default::default(), 335 args, 336 tag, 337 type_, 338 field_map: None, 339 }) 340 } 341 342 fn constant_call_arg( 343 &mut self, 344 reader: &constant::Reader<'_>, 345 ) -> Result<CallArg<TypedConstant>> { 346 Ok(CallArg { 347 implicit: None, 348 label: Default::default(), 349 location: Default::default(), 350 value: self.constant(reader)?, 351 }) 352 } 353 354 fn constant_bit_array( 355 &mut self, 356 reader: &capnp::struct_list::Reader<'_, bit_array_segment::Owned>, 357 ) -> Result<TypedConstant> { 358 Ok(Constant::BitArray { 359 location: Default::default(), 360 segments: read_vec!(reader, self, bit_array_segment), 361 }) 362 } 363 364 fn constant_var(&mut self, reader: &constant::var::Reader<'_>) -> Result<TypedConstant> { 365 let type_ = self.type_(&reader.get_type()?)?; 366 let module = self.optional_string(self.str(reader.get_module()?)?); 367 let name = reader.get_name()?; 368 let constructor = self.value_constructor(&reader.get_constructor()?)?; 369 Ok(Constant::Var { 370 location: Default::default(), 371 module: module.map(|module| (module, Default::default())), 372 name: self.string(name)?, 373 constructor: Some(Box::from(constructor)), 374 type_, 375 }) 376 } 377 378 fn constant_string_concatenation( 379 &mut self, 380 reader: &constant::string_concatenation::Reader<'_>, 381 ) -> Result<TypedConstant> { 382 Ok(Constant::StringConcatenation { 383 location: Default::default(), 384 left: Box::new(self.constant(&reader.get_left()?)?), 385 right: Box::new(self.constant(&reader.get_right()?)?), 386 }) 387 } 388 389 fn bit_array_segment( 390 &mut self, 391 reader: &bit_array_segment::Reader<'_>, 392 ) -> Result<TypedConstantBitArraySegment> { 393 Ok(BitArraySegment { 394 location: Default::default(), 395 type_: self.type_(&reader.get_type()?)?, 396 value: Box::new(self.constant(&reader.get_value()?)?), 397 options: read_vec!(reader.get_options()?, self, bit_array_segment_option), 398 }) 399 } 400 401 fn bit_array_segment_option( 402 &mut self, 403 reader: &bit_array_segment_option::Reader<'_>, 404 ) -> Result<TypedConstantBitArraySegmentOption> { 405 use bit_array_segment_option::Which; 406 Ok(match reader.which()? { 407 Which::Bytes(_) => BitArrayOption::Bytes { 408 location: Default::default(), 409 }, 410 Which::Integer(_) => BitArrayOption::Int { 411 location: Default::default(), 412 }, 413 Which::Float(_) => BitArrayOption::Float { 414 location: Default::default(), 415 }, 416 Which::Bits(_) => BitArrayOption::Bits { 417 location: Default::default(), 418 }, 419 Which::Utf8(_) => BitArrayOption::Utf8 { 420 location: Default::default(), 421 }, 422 Which::Utf16(_) => BitArrayOption::Utf16 { 423 location: Default::default(), 424 }, 425 Which::Utf32(_) => BitArrayOption::Utf32 { 426 location: Default::default(), 427 }, 428 Which::Utf8Codepoint(_) => BitArrayOption::Utf8Codepoint { 429 location: Default::default(), 430 }, 431 Which::Utf16Codepoint(_) => BitArrayOption::Utf16Codepoint { 432 location: Default::default(), 433 }, 434 Which::Utf32Codepoint(_) => BitArrayOption::Utf32Codepoint { 435 location: Default::default(), 436 }, 437 Which::Signed(_) => BitArrayOption::Signed { 438 location: Default::default(), 439 }, 440 Which::Unsigned(_) => BitArrayOption::Unsigned { 441 location: Default::default(), 442 }, 443 Which::Big(_) => BitArrayOption::Big { 444 location: Default::default(), 445 }, 446 Which::Little(_) => BitArrayOption::Little { 447 location: Default::default(), 448 }, 449 Which::Native(_) => BitArrayOption::Native { 450 location: Default::default(), 451 }, 452 Which::Size(reader) => BitArrayOption::Size { 453 location: Default::default(), 454 short_form: reader.get_short_form(), 455 value: Box::new(self.constant(&reader.get_value()?)?), 456 }, 457 Which::Unit(reader) => BitArrayOption::Unit { 458 location: Default::default(), 459 value: reader.get_value(), 460 }, 461 }) 462 } 463 464 fn value_constructor_variant( 465 &mut self, 466 reader: &value_constructor_variant::Reader<'_>, 467 ) -> Result<ValueConstructorVariant> { 468 use value_constructor_variant::Which; 469 match reader.which()? { 470 Which::ModuleConstant(reader) => self.module_constant_variant(&reader), 471 Which::ModuleFn(reader) => self.module_fn_variant(&reader), 472 Which::Record(reader) => self.record(&reader), 473 } 474 } 475 476 fn module_constant_variant( 477 &mut self, 478 reader: &value_constructor_variant::module_constant::Reader<'_>, 479 ) -> Result<ValueConstructorVariant> { 480 Ok(ValueConstructorVariant::ModuleConstant { 481 documentation: self.optional_string(self.str(reader.get_documentation()?)?), 482 location: self.src_span(&reader.get_location()?)?, 483 literal: self.constant(&reader.get_literal()?)?, 484 module: self.string(reader.get_module()?)?, 485 implementations: self.implementations(reader.get_implementations()?), 486 }) 487 } 488 489 fn optional_string(&self, str: &str) -> Option<EcoString> { 490 if str.is_empty() { 491 None 492 } else { 493 Some(str.into()) 494 } 495 } 496 497 fn src_span(&self, reader: &src_span::Reader<'_>) -> Result<SrcSpan> { 498 Ok(SrcSpan { 499 start: reader.get_start(), 500 end: reader.get_end(), 501 }) 502 } 503 504 fn module_fn_variant( 505 &self, 506 reader: &value_constructor_variant::module_fn::Reader<'_>, 507 ) -> Result<ValueConstructorVariant> { 508 Ok(ValueConstructorVariant::ModuleFn { 509 name: self.string(reader.get_name()?)?, 510 module: self.string(reader.get_module()?)?, 511 arity: reader.get_arity() as usize, 512 field_map: self.field_map(&reader.get_field_map()?)?, 513 location: self.src_span(&reader.get_location()?)?, 514 documentation: self.optional_string(self.str(reader.get_documentation()?)?), 515 implementations: self.implementations(reader.get_implementations()?), 516 external_erlang: self.optional_external(reader.get_external_erlang()?)?, 517 external_javascript: self.optional_external(reader.get_external_javascript()?)?, 518 }) 519 } 520 521 fn implementations(&self, reader: implementations::Reader<'_>) -> Implementations { 522 Implementations { 523 gleam: reader.get_gleam(), 524 uses_erlang_externals: reader.get_uses_erlang_externals(), 525 uses_javascript_externals: reader.get_uses_javascript_externals(), 526 can_run_on_erlang: reader.get_can_run_on_erlang(), 527 can_run_on_javascript: reader.get_can_run_on_javascript(), 528 } 529 } 530 531 fn record( 532 &self, 533 reader: &value_constructor_variant::record::Reader<'_>, 534 ) -> Result<ValueConstructorVariant> { 535 Ok(ValueConstructorVariant::Record { 536 name: self.string(reader.get_name()?)?, 537 module: self.string(reader.get_module()?)?, 538 arity: reader.get_arity(), 539 variants_count: reader.get_constructors_count(), 540 field_map: self.field_map(&reader.get_field_map()?)?, 541 location: self.src_span(&reader.get_location()?)?, 542 documentation: self.optional_string(self.str(reader.get_documentation()?)?), 543 variant_index: reader.get_constructor_index(), 544 }) 545 } 546 547 fn field_map(&self, reader: &option::Reader<'_, field_map::Owned>) -> Result<Option<FieldMap>> { 548 use option::Which; 549 Ok(match reader.which()? { 550 Which::None(_) => None, 551 Which::Some(reader) => Some({ 552 let reader = reader?; 553 FieldMap { 554 arity: reader.get_arity(), 555 fields: read_hashmap!(&reader.get_fields()?, self, u32), 556 } 557 }), 558 }) 559 } 560 561 fn u32(&self, i: &boxed_u_int32::Reader<'_>) -> Result<u32> { 562 Ok(i.get_value()) 563 } 564 565 fn accessors_map(&mut self, reader: &accessors_map::Reader<'_>) -> Result<AccessorsMap> { 566 Ok(AccessorsMap { 567 publicity: self.publicity(reader.get_publicity()?)?, 568 type_: self.type_(&reader.get_type()?)?, 569 shared_accessors: read_hashmap!(&reader.get_shared_accessors()?, self, record_accessor), 570 variant_specific_accessors: read_vec!( 571 &reader.get_variant_specific_accessors()?, 572 self, 573 variant_specific_accessors 574 ), 575 }) 576 } 577 578 fn variant_specific_accessors( 579 &mut self, 580 reader: &variant_specific_accessors::Reader<'_>, 581 ) -> Result<HashMap<EcoString, RecordAccessor>> { 582 Ok(read_hashmap!( 583 &reader.get_accessors()?, 584 self, 585 record_accessor 586 )) 587 } 588 589 fn record_accessor(&mut self, reader: &record_accessor::Reader<'_>) -> Result<RecordAccessor> { 590 Ok(RecordAccessor { 591 index: reader.get_index() as u64, 592 label: self.string(reader.get_label()?)?, 593 type_: self.type_(&reader.get_type()?)?, 594 }) 595 } 596 597 fn line_starts(&mut self, i: &u32) -> Result<u32> { 598 Ok(*i) 599 } 600 601 fn line_numbers(&mut self, reader: &line_numbers::Reader<'_>) -> Result<LineNumbers> { 602 Ok(LineNumbers { 603 length: reader.get_length(), 604 line_starts: read_vec!(reader.get_line_starts()?, self, line_starts), 605 }) 606 } 607 608 fn version(&self, reader: &version::Reader<'_>) -> hexpm::version::Version { 609 hexpm::version::Version::new(reader.get_major(), reader.get_minor(), reader.get_patch()) 610 } 611 612 fn optional_external( 613 &self, 614 reader: option::Reader<'_, external::Owned>, 615 ) -> Result<Option<(EcoString, EcoString)>> { 616 match reader.which()? { 617 option::Which::None(()) => Ok(None), 618 option::Which::Some(reader) => { 619 let reader = reader?; 620 let module = self.string(reader.get_module()?)?; 621 let function = self.string(reader.get_function()?)?; 622 Ok(Some((module, function))) 623 } 624 } 625 } 626}