Fork of daniellemaywood.uk/gleam — Wasm codegen work
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}