1use core::str::FromStr;
4
5use alloc::{
6 borrow::Cow,
7 collections::{BTreeMap, BTreeSet},
8 format,
9 string::{String, ToString},
10 vec::Vec,
11};
12
13use crate::{
14 lex::Span,
15 parser::{ParserError, ParserErrorKind},
16 strings::{StringPartsIter, unescape},
17 wasm::{DisplayType, WasmType, WasmTypeKind, WasmValue, WasmValueError},
18 writer::merge_map_entries,
19};
20
21#[derive(Clone, Debug)]
23pub struct Node {
24 ty: NodeType,
25 span: Span,
26 children: Vec<Node>,
27}
28
29impl Node {
30 pub(crate) fn new(
31 ty: NodeType,
32 span: impl Into<Span>,
33 children: impl IntoIterator<Item = Node>,
34 ) -> Self {
35 Self {
36 ty,
37 span: span.into(),
38 children: Vec::from_iter(children),
39 }
40 }
41
42 pub fn ty(&self) -> NodeType {
44 self.ty
45 }
46
47 pub fn span(&self) -> Span {
49 self.span.clone()
50 }
51
52 pub fn as_bool(&self) -> Result<bool, ParserError> {
54 match self.ty {
55 NodeType::BoolTrue => Ok(true),
56 NodeType::BoolFalse => Ok(false),
57 _ => Err(self.error(ParserErrorKind::InvalidType)),
58 }
59 }
60
61 pub fn as_number<T: FromStr>(&self, src: &str) -> Result<T, ParserError> {
64 self.ensure_type(NodeType::Number)?;
65 self.slice(src)
66 .parse()
67 .map_err(|_| self.error(ParserErrorKind::InvalidValue))
68 }
69
70 pub fn as_char(&self, src: &str) -> Result<char, ParserError> {
72 self.ensure_type(NodeType::Char)?;
73 let inner = &src[self.span.start + 1..self.span.end - 1];
74 let (ch, len) = if inner.starts_with('\\') {
75 unescape(inner).ok_or_else(|| self.error(ParserErrorKind::InvalidEscape))?
76 } else {
77 let ch = inner.chars().next().unwrap();
78 (ch, ch.len_utf8())
79 };
80 if len != inner.len() {
82 return Err(self.error(ParserErrorKind::MultipleChars));
83 }
84 Ok(ch)
85 }
86
87 pub fn as_str<'src>(&self, src: &'src str) -> Result<Cow<'src, str>, ParserError> {
89 let mut parts = self.iter_str(src)?;
90 let Some(first) = parts.next().transpose()? else {
91 return Ok("".into());
92 };
93 match parts.next().transpose()? {
94 None => Ok(first),
96 Some(second) => {
98 let s: String = [Ok(first), Ok(second)]
99 .into_iter()
100 .chain(parts)
101 .collect::<Result<_, _>>()?;
102 Ok(s.into())
103 }
104 }
105 }
106
107 pub fn iter_str<'src>(
110 &self,
111 src: &'src str,
112 ) -> Result<impl Iterator<Item = Result<Cow<'src, str>, ParserError>>, ParserError> {
113 match self.ty {
114 NodeType::String => {
115 let span = self.span.start + 1..self.span.end - 1;
116 Ok(StringPartsIter::new(&src[span.clone()], span.start))
117 }
118 NodeType::MultilineString => {
119 let span = self.span.start + 3..self.span.end - 3;
120 Ok(StringPartsIter::new_multiline(
121 &src[span.clone()],
122 span.start,
123 )?)
124 }
125 _ => Err(self.error(ParserErrorKind::InvalidType)),
126 }
127 }
128
129 pub fn as_tuple(&self) -> Result<impl ExactSizeIterator<Item = &Node>, ParserError> {
131 self.ensure_type(NodeType::Tuple)?;
132 Ok(self.children.iter())
133 }
134
135 pub fn as_list(&self) -> Result<impl ExactSizeIterator<Item = &Node>, ParserError> {
137 self.ensure_type(NodeType::List)?;
138 Ok(self.children.iter())
139 }
140
141 pub fn as_map(&self) -> Result<impl ExactSizeIterator<Item = (&Node, &Node)>, ParserError> {
147 match self.ty {
148 NodeType::TupleSet | NodeType::EmptySet => (),
149 _ => return Err(self.error(ParserErrorKind::InvalidType)),
150 }
151 Ok(self.children.chunks(2).map(|chunk| (&chunk[0], &chunk[1])))
152 }
153
154 pub fn as_record<'this, 'src>(
160 &'this self,
161 src: &'src str,
162 ) -> Result<impl ExactSizeIterator<Item = (&'src str, &'this Node)>, ParserError> {
163 self.ensure_type(NodeType::TupleSet)?;
164 let mut seen = BTreeSet::new();
165 for key in self.children.iter().step_by(2) {
166 let field = key.as_label(src).map_err(|_| {
167 ParserError::with_detail(
168 ParserErrorKind::InvalidType,
169 key.span(),
170 "expected a record field label",
171 )
172 })?;
173 if !seen.insert(field) {
174 return Err(ParserError::with_detail(
175 ParserErrorKind::DuplicateField,
176 key.span(),
177 format!("{field:?}"),
178 ));
179 }
180 }
181 Ok(self
182 .children
183 .chunks(2)
184 .map(|chunk| (chunk[0].as_label(src).unwrap(), &chunk[1])))
185 }
186
187 pub fn as_variant<'this, 'src>(
190 &'this self,
191 src: &'src str,
192 ) -> Result<(&'src str, Option<&'this Node>), ParserError> {
193 match self.ty {
194 NodeType::Label => Ok((self.as_label(src)?, None)),
195 NodeType::VariantWithPayload => {
196 let label = self.children[0].as_label(src)?;
197 let value = &self.children[1];
198 Ok((label, Some(value)))
199 }
200 _ => Err(self.error(ParserErrorKind::InvalidType)),
201 }
202 }
203
204 pub fn as_enum<'src>(&self, src: &'src str) -> Result<&'src str, ParserError> {
206 self.as_label(src)
207 }
208
209 pub fn as_option(&self) -> Result<Option<&Node>, ParserError> {
211 match self.ty {
212 NodeType::OptionSome => Ok(Some(&self.children[0])),
213 NodeType::OptionNone => Ok(None),
214 _ => Err(self.error(ParserErrorKind::InvalidType)),
215 }
216 }
217
218 pub fn as_result(&self) -> Result<Result<Option<&Node>, Option<&Node>>, ParserError> {
221 let payload = self.children.first();
222 match self.ty {
223 NodeType::ResultOk => Ok(Ok(payload)),
224 NodeType::ResultErr => Ok(Err(payload)),
225 _ => Err(self.error(ParserErrorKind::InvalidType)),
226 }
227 }
228
229 pub fn as_flags<'this, 'src: 'this>(
231 &'this self,
232 src: &'src str,
233 ) -> Result<impl Iterator<Item = &'src str> + 'this, ParserError> {
234 match self.ty {
235 NodeType::Flags | NodeType::EmptySet => (),
236 _ => return Err(self.error(ParserErrorKind::InvalidType)),
237 }
238 Ok(self.children.iter().map(|node| node.as_label(src).unwrap()))
239 }
240
241 fn as_label<'src>(&self, src: &'src str) -> Result<&'src str, ParserError> {
242 self.ensure_type(NodeType::Label)?;
243 let label = self.slice(src);
244 let label = label.strip_prefix('%').unwrap_or(label);
245 Ok(label)
246 }
247
248 pub fn to_wasm_value<V: WasmValue>(&self, ty: &V::Type, src: &str) -> Result<V, ParserError> {
250 Ok(match ty.kind() {
251 WasmTypeKind::Bool => V::make_bool(self.as_bool()?),
252 WasmTypeKind::S8 => V::make_s8(self.as_number(src)?),
253 WasmTypeKind::S16 => V::make_s16(self.as_number(src)?),
254 WasmTypeKind::S32 => V::make_s32(self.as_number(src)?),
255 WasmTypeKind::S64 => V::make_s64(self.as_number(src)?),
256 WasmTypeKind::U8 => V::make_u8(self.as_number(src)?),
257 WasmTypeKind::U16 => V::make_u16(self.as_number(src)?),
258 WasmTypeKind::U32 => V::make_u32(self.as_number(src)?),
259 WasmTypeKind::U64 => V::make_u64(self.as_number(src)?),
260 WasmTypeKind::F32 => V::make_f32(self.as_number(src)?),
261 WasmTypeKind::F64 => V::make_f64(self.as_number(src)?),
262 WasmTypeKind::Char => V::make_char(self.as_char(src)?),
263 WasmTypeKind::String => V::make_string(self.as_str(src)?),
264 WasmTypeKind::List => self.to_wasm_list(ty, src)?,
265 WasmTypeKind::Record => self.to_wasm_record(ty, src)?,
266 WasmTypeKind::Tuple => self.to_wasm_tuple(ty, src)?,
267 WasmTypeKind::Variant => self.to_wasm_variant(ty, src)?,
268 WasmTypeKind::Enum => self.to_wasm_enum(ty, src)?,
269 WasmTypeKind::Option => self.to_wasm_option(ty, src)?,
270 WasmTypeKind::Result => self.to_wasm_result(ty, src)?,
271 WasmTypeKind::Flags => self.to_wasm_flags(ty, src)?,
272 WasmTypeKind::Map => self.to_wasm_map(ty, src)?,
273 other => {
274 return Err(
275 self.wasm_value_error(WasmValueError::UnsupportedType(other.to_string()))
276 );
277 }
278 })
279 }
280
281 pub fn to_wasm_params<'types, V: WasmValue + 'static>(
284 &self,
285 types: impl IntoIterator<Item = &'types V::Type>,
286 src: &str,
287 ) -> Result<Vec<V>, ParserError> {
288 let mut types = types.into_iter();
289 let mut values = self
290 .as_tuple()?
291 .map(|node| {
292 let ty = types.next().ok_or_else(|| {
293 ParserError::with_detail(
294 ParserErrorKind::InvalidParams,
295 node.span().clone(),
296 "more param(s) than expected",
297 )
298 })?;
299 node.to_wasm_value::<V>(ty, src)
300 })
301 .collect::<Result<Vec<_>, _>>()?;
302 for ty in types {
304 if ty.kind() == WasmTypeKind::Option {
305 values.push(V::make_option(ty, None).map_err(|err| self.wasm_value_error(err))?);
306 } else {
307 return Err(ParserError::with_detail(
308 ParserErrorKind::InvalidParams,
309 self.span.end - 1..self.span.end,
310 "missing required param(s)",
311 ));
312 }
313 }
314 Ok(values)
315 }
316
317 fn to_wasm_list<V: WasmValue>(&self, ty: &V::Type, src: &str) -> Result<V, ParserError> {
318 let element_type = ty.list_element_type().unwrap();
319 let elements = self
320 .as_list()?
321 .map(|node| node.to_wasm_value(&element_type, src))
322 .collect::<Result<Vec<_>, _>>()?;
323 V::make_list(ty, elements).map_err(|err| self.wasm_value_error(err))
324 }
325
326 fn to_wasm_record<V: WasmValue>(&self, ty: &V::Type, src: &str) -> Result<V, ParserError> {
327 let mut values = self.as_record(src)?.collect::<BTreeMap<_, _>>();
328 let record_fields = ty.record_fields().collect::<Vec<_>>();
329 let fields = record_fields
330 .iter()
331 .map(|(name, field_type)| {
332 let value = match (values.remove(name.as_ref()), field_type.kind()) {
333 (Some(node), _) => node.to_wasm_value(field_type, src)?,
334 (None, WasmTypeKind::Option) => V::make_option(field_type, None)
335 .map_err(|err| self.wasm_value_error(err))?,
336 _ => {
337 return Err(
338 self.wasm_value_error(WasmValueError::MissingField(name.to_string()))
339 );
340 }
341 };
342 Ok((name.as_ref(), value))
343 })
344 .collect::<Result<Vec<_>, _>>()?;
345 if !values.is_empty() {
346 return Err(self.error(ParserErrorKind::InvalidValue));
348 }
349 V::make_record(ty, fields).map_err(|err| self.wasm_value_error(err))
350 }
351
352 fn to_wasm_tuple<V: WasmValue>(&self, ty: &V::Type, src: &str) -> Result<V, ParserError> {
353 let types = ty.tuple_element_types().collect::<Vec<_>>();
354 let values = self.as_tuple()?;
355 if types.len() != values.len() {
356 return Err(
357 self.wasm_value_error(WasmValueError::WrongNumberOfTupleValues {
358 want: types.len(),
359 got: values.len(),
360 }),
361 );
362 }
363 let values = ty
364 .tuple_element_types()
365 .zip(self.as_tuple()?)
366 .map(|(ty, node)| node.to_wasm_value(&ty, src))
367 .collect::<Result<Vec<_>, _>>()?;
368 V::make_tuple(ty, values).map_err(|err| self.wasm_value_error(err))
369 }
370
371 fn to_wasm_variant<V: WasmValue>(&self, ty: &V::Type, src: &str) -> Result<V, ParserError> {
372 let (label, payload) = self.as_variant(src)?;
373 let payload_type = ty
374 .variant_cases()
375 .find_map(|(case, payload)| (case == label).then_some(payload))
376 .ok_or_else(|| self.wasm_value_error(WasmValueError::UnknownCase(label.into())))?;
377 let payload_value = self.to_wasm_maybe_payload(label, &payload_type, payload, src)?;
378 V::make_variant(ty, label, payload_value).map_err(|err| self.wasm_value_error(err))
379 }
380
381 fn to_wasm_enum<V: WasmValue>(&self, ty: &V::Type, src: &str) -> Result<V, ParserError> {
382 V::make_enum(ty, self.as_enum(src)?).map_err(|err| self.wasm_value_error(err))
383 }
384
385 fn to_wasm_option<V: WasmValue>(&self, ty: &V::Type, src: &str) -> Result<V, ParserError> {
386 let payload_type = ty.option_some_type().unwrap();
387 let value = match self.ty {
388 NodeType::OptionSome => {
389 self.to_wasm_maybe_payload("some", &Some(payload_type), self.as_option()?, src)?
390 }
391 NodeType::OptionNone => {
392 self.to_wasm_maybe_payload("none", &None, self.as_option()?, src)?
393 }
394 _ if flattenable(payload_type.kind()) => Some(self.to_wasm_value(&payload_type, src)?),
395 _ => {
396 return Err(self.error(ParserErrorKind::InvalidType));
397 }
398 };
399 V::make_option(ty, value).map_err(|err| self.wasm_value_error(err))
400 }
401
402 fn to_wasm_result<V: WasmValue>(&self, ty: &V::Type, src: &str) -> Result<V, ParserError> {
403 let (ok_type, err_type) = ty.result_types().unwrap();
404 let value = match self.ty {
405 NodeType::ResultOk => {
406 Ok(self.to_wasm_maybe_payload("ok", &ok_type, self.as_result()?.unwrap(), src)?)
407 }
408 NodeType::ResultErr => Err(self.to_wasm_maybe_payload(
409 "err",
410 &err_type,
411 self.as_result()?.unwrap_err(),
412 src,
413 )?),
414 _ => match ok_type {
415 Some(ty) if flattenable(ty.kind()) => Ok(Some(self.to_wasm_value(&ty, src)?)),
416 _ => return Err(self.error(ParserErrorKind::InvalidType)),
417 },
418 };
419 V::make_result(ty, value).map_err(|err| self.wasm_value_error(err))
420 }
421
422 fn to_wasm_flags<V: WasmValue>(&self, ty: &V::Type, src: &str) -> Result<V, ParserError> {
423 let names = ty.flags_names().collect::<Vec<_>>();
425 let mut flags = self.as_flags(src)?.collect::<Vec<_>>();
426 flags.sort_by_cached_key(|flag| names.iter().position(|name| name == flag));
427 V::make_flags(ty, flags).map_err(|err| self.wasm_value_error(err))
428 }
429
430 fn to_wasm_map<V: WasmValue>(&self, ty: &V::Type, src: &str) -> Result<V, ParserError> {
431 let (key_type, value_type) = ty.map_key_value_types().unwrap();
432 let entries = self
433 .as_map()?
434 .map(|(key, value)| {
435 let key_value = key.to_wasm_map_key(&key_type, src)?;
436 let encoded_key = crate::to_string(&key_value).map_err(|err| {
437 ParserError::with_source(ParserErrorKind::WasmValueError, key.span(), err)
438 })?;
439 Ok((
440 encoded_key,
441 key_value,
442 value.to_wasm_value(&value_type, src)?,
443 ))
444 })
445 .collect::<Result<Vec<_>, ParserError>>()?;
446 V::make_map(ty, merge_map_entries(entries)).map_err(|err| self.wasm_value_error(err))
447 }
448
449 fn to_wasm_map_key<V: WasmValue>(&self, ty: &V::Type, src: &str) -> Result<V, ParserError> {
450 if self.ty != NodeType::Label {
451 return self.to_wasm_value(ty, src);
452 }
453 match (ty.kind(), self.slice(src)) {
455 (WasmTypeKind::Bool, "true") => Ok(V::make_bool(true)),
456 (WasmTypeKind::Bool, "false") => Ok(V::make_bool(false)),
457 _ => Err(ParserError::with_detail(
458 ParserErrorKind::InvalidType,
459 self.span(),
460 format!("expected a {} key, found a label", DisplayType(ty)),
461 )),
462 }
463 }
464
465 fn to_wasm_maybe_payload<V: WasmValue>(
466 &self,
467 case: &str,
468 payload_type: &Option<V::Type>,
469 payload: Option<&Node>,
470 src: &str,
471 ) -> Result<Option<V>, ParserError> {
472 match (payload_type.as_ref(), payload) {
473 (Some(ty), Some(node)) => Ok(Some(node.to_wasm_value(ty, src)?)),
474 (None, None) => Ok(None),
475 (Some(_), None) => {
476 Err(self.wasm_value_error(WasmValueError::MissingPayload(case.into())))
477 }
478 (None, Some(_)) => {
479 Err(self.wasm_value_error(WasmValueError::UnexpectedPayload(case.into())))
480 }
481 }
482 }
483
484 fn wasm_value_error(&self, err: WasmValueError) -> ParserError {
485 ParserError::with_source(ParserErrorKind::WasmValueError, self.span(), err)
486 }
487
488 pub(crate) fn slice<'src>(&self, src: &'src str) -> &'src str {
489 &src[self.span()]
490 }
491
492 fn ensure_type(&self, ty: NodeType) -> Result<(), ParserError> {
493 if self.ty == ty {
494 Ok(())
495 } else {
496 Err(self.error(ParserErrorKind::InvalidType))
497 }
498 }
499
500 fn error(&self, kind: ParserErrorKind) -> ParserError {
501 ParserError::new(kind, self.span())
502 }
503}
504
505fn flattenable(kind: WasmTypeKind) -> bool {
506 !matches!(kind, WasmTypeKind::Option | WasmTypeKind::Result)
508}
509
510#[derive(Clone, Copy, Debug, PartialEq)]
512pub enum NodeType {
513 BoolTrue,
515 BoolFalse,
517 Number,
520 Char,
523 String,
526 MultilineString,
529 Tuple,
532 List,
535 TupleSet,
544 EmptySet,
547 Label,
550 VariantWithPayload,
553 OptionSome,
556 OptionNone,
558 ResultOk,
561 ResultErr,
564 Flags,
568}