1pub(crate) use crate::{
2 ast::{
3 self, Annotation, ArgBy, ArgName, AssignmentKind, AssignmentPattern, BinOp, Bls12_381Point,
4 ByteArrayFormatPreference, CallArg, Curve, DataType, DataTypeKey, DefinitionLocation,
5 Located, LogicalOpChainKind, ParsedCallArg, RecordConstructorArg, RecordUpdateSpread, Span,
6 TraceKind, TypedArg, TypedAssignmentKind, TypedClause, TypedDataType, TypedIfBranch,
7 TypedPattern, TypedRecordUpdateArg, UnOp, UntypedArg, UntypedAssignmentKind, UntypedClause,
8 UntypedIfBranch, UntypedRecordUpdateArg,
9 },
10 parser::token::Base,
11 tipo::{
12 ModuleValueConstructor, Type, TypeVar, ValueConstructor, ValueConstructorVariant,
13 check_replaceable_opaque_type, convert_opaque_type, lookup_data_type_by_tipo,
14 },
15};
16use indexmap::IndexMap;
17use pallas_primitives::alonzo::{Constr, PlutusData};
18use std::{fmt::Debug, ops::Deref, rc::Rc};
19use uplc::{
20 KeyValuePairs,
21 ast::Data,
22 machine::{runtime::convert_tag_to_constr, value::from_pallas_bigint},
23};
24use vec1::Vec1;
25
26#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
27pub enum TypedExpr {
28 UInt {
29 location: Span,
30 tipo: Rc<Type>,
31 value: String,
32 base: Base,
33 },
34
35 String {
36 location: Span,
37 tipo: Rc<Type>,
38 value: String,
39 },
40
41 ByteArray {
42 location: Span,
43 tipo: Rc<Type>,
44 bytes: Vec<u8>,
45 preferred_format: ByteArrayFormatPreference,
46 },
47
48 CurvePoint {
49 location: Span,
50 tipo: Rc<Type>,
51 point: Box<Curve>,
52 preferred_format: ByteArrayFormatPreference,
53 },
54
55 Sequence {
56 location: Span,
57 expressions: Vec<Self>,
58 },
59
60 Pipeline {
66 location: Span,
67 expressions: Vec<Self>,
68 },
69
70 Var {
71 location: Span,
72 constructor: ValueConstructor,
73 name: String,
74 },
75
76 Fn {
77 location: Span,
78 tipo: Rc<Type>,
79 is_capture: bool,
80 args: Vec<TypedArg>,
81 body: Box<Self>,
82 return_annotation: Option<Annotation>,
83 },
84
85 List {
86 location: Span,
87 tipo: Rc<Type>,
88 elements: Vec<Self>,
89 tail: Option<Box<Self>>,
90 },
91
92 Call {
93 location: Span,
94 tipo: Rc<Type>,
95 fun: Box<Self>,
96 args: Vec<CallArg<Self>>,
97 },
98
99 BinOp {
100 location: Span,
101 tipo: Rc<Type>,
102 name: BinOp,
103 left: Box<Self>,
104 right: Box<Self>,
105 },
106
107 Assignment {
108 location: Span,
109 tipo: Rc<Type>,
110 value: Box<Self>,
111 pattern: TypedPattern,
112 kind: TypedAssignmentKind,
113 comment: Option<String>,
114 },
115
116 Trace {
117 location: Span,
118 tipo: Rc<Type>,
119 then: Box<Self>,
120 text: Box<Self>,
121 },
122
123 When {
124 location: Span,
125 tipo: Rc<Type>,
126 subject: Box<Self>,
127 clauses: Vec<TypedClause>,
128 },
129
130 If {
131 location: Span,
132 #[serde(with = "Vec1Ref")]
133 branches: Vec1<TypedIfBranch>,
134 final_else: Box<Self>,
135 tipo: Rc<Type>,
136 },
137
138 RecordAccess {
139 location: Span,
140 tipo: Rc<Type>,
141 label: String,
142 index: u64,
143 record: Box<Self>,
144 },
145
146 ModuleSelect {
147 location: Span,
148 tipo: Rc<Type>,
149 label: String,
150 module_name: String,
151 module_alias: String,
152 constructor: ModuleValueConstructor,
153 },
154
155 Tuple {
156 location: Span,
157 tipo: Rc<Type>,
158 elems: Vec<Self>,
159 },
160
161 Pair {
162 location: Span,
163 tipo: Rc<Type>,
164 fst: Box<Self>,
165 snd: Box<Self>,
166 },
167
168 TupleIndex {
169 location: Span,
170 tipo: Rc<Type>,
171 index: usize,
172 tuple: Box<Self>,
173 },
174
175 ErrorTerm {
176 location: Span,
177 tipo: Rc<Type>,
178 },
179
180 RecordUpdate {
181 location: Span,
182 tipo: Rc<Type>,
183 spread: Box<Self>,
184 args: Vec<TypedRecordUpdateArg>,
185 },
186
187 UnOp {
188 location: Span,
189 value: Box<Self>,
190 tipo: Rc<Type>,
191 op: UnOp,
192 },
193}
194
195#[derive(serde::Serialize, serde::Deserialize)]
196#[serde(remote = "Vec1")]
197struct Vec1Ref<T>(#[serde(getter = "Vec1::as_vec")] Vec<T>);
198
199impl<T> From<Vec1Ref<T>> for Vec1<T> {
200 fn from(v: Vec1Ref<T>) -> Self {
201 Vec1::try_from_vec(v.0).unwrap()
202 }
203}
204
205impl TypedExpr {
206 pub fn is_simple_expr_to_format(&self) -> bool {
207 match self {
208 Self::String { .. } | Self::UInt { .. } | Self::ByteArray { .. } | Self::Var { .. } => {
209 true
210 }
211 Self::Pair { fst, snd, .. } => {
212 fst.is_simple_expr_to_format() && snd.is_simple_expr_to_format()
213 }
214 Self::Tuple { elems, .. } => elems.iter().all(|e| e.is_simple_expr_to_format()),
215 Self::List { elements, .. } if elements.len() <= 3 => {
216 elements.iter().all(|e| e.is_simple_expr_to_format())
217 }
218 Self::UnOp { value, .. } => value.is_simple_expr_to_format(),
219 _ => false,
220 }
221 }
222
223 pub fn and_then(self, next: Self) -> Self {
224 if let TypedExpr::Trace {
225 tipo,
226 location,
227 then,
228 text,
229 } = self
230 {
231 return TypedExpr::Trace {
232 tipo,
233 location,
234 then: Box::new(then.and_then(next)),
235 text,
236 };
237 }
238
239 TypedExpr::Sequence {
240 location: self.location(),
241 expressions: vec![self, next],
242 }
243 }
244
245 pub fn sequence(exprs: &[TypedExpr]) -> Self {
246 TypedExpr::Sequence {
247 location: Span::empty(),
248 expressions: exprs.to_vec(),
249 }
250 }
251
252 pub fn let_(value: Self, pattern: TypedPattern, tipo: Rc<Type>, location: Span) -> Self {
253 TypedExpr::Assignment {
254 tipo: tipo.clone(),
255 value: value.into(),
256 pattern,
257 kind: AssignmentKind::let_(),
258 comment: None,
259 location,
260 }
261 }
262
263 pub fn flexible_expect(
265 value: Self,
266 pattern: TypedPattern,
267 tipo: Rc<Type>,
268 location: Span,
269 ) -> Self {
270 TypedExpr::Assignment {
271 tipo: tipo.clone(),
272 value: value.into(),
273 pattern,
274 kind: if tipo.is_data() {
275 AssignmentKind::let_()
276 } else {
277 AssignmentKind::expect()
278 },
279 comment: None,
280 location,
281 }
282 }
283
284 pub fn local_var(name: &str, tipo: Rc<Type>, location: Span) -> Self {
285 TypedExpr::Var {
286 constructor: ValueConstructor {
287 public: true,
288 variant: ValueConstructorVariant::LocalVariable {
289 location: Span::empty(),
290 },
291 tipo: tipo.clone(),
292 },
293 name: name.to_string(),
294 location,
295 }
296 }
297
298 pub fn tipo(&self) -> Rc<Type> {
299 match self {
300 Self::Var { constructor, .. } => constructor.tipo.clone(),
301 Self::Trace { then, .. } => then.tipo(),
302 Self::Fn { tipo, .. }
303 | Self::UInt { tipo, .. }
304 | Self::ErrorTerm { tipo, .. }
305 | Self::When { tipo, .. }
306 | Self::List { tipo, .. }
307 | Self::Call { tipo, .. }
308 | Self::If { tipo, .. }
309 | Self::UnOp { tipo, .. }
310 | Self::BinOp { tipo, .. }
311 | Self::Tuple { tipo, .. }
312 | Self::Pair { tipo, .. }
313 | Self::String { tipo, .. }
314 | Self::ByteArray { tipo, .. }
315 | Self::TupleIndex { tipo, .. }
316 | Self::Assignment { tipo, .. }
317 | Self::ModuleSelect { tipo, .. }
318 | Self::RecordAccess { tipo, .. }
319 | Self::RecordUpdate { tipo, .. }
320 | Self::CurvePoint { tipo, .. } => tipo.clone(),
321 Self::Pipeline { expressions, .. } | Self::Sequence { expressions, .. } => expressions
322 .last()
323 .map(TypedExpr::tipo)
324 .unwrap_or_else(Type::void),
325 }
326 }
327
328 pub fn replace_type(&mut self, new_type: Rc<Type>) {
329 match self {
330 Self::Var { constructor, .. } => {
331 constructor.tipo = new_type;
332 }
333 Self::Trace { then, .. } => then.replace_type(new_type),
334 Self::Fn { tipo, .. }
335 | Self::UInt { tipo, .. }
336 | Self::ErrorTerm { tipo, .. }
337 | Self::When { tipo, .. }
338 | Self::List { tipo, .. }
339 | Self::Call { tipo, .. }
340 | Self::If { tipo, .. }
341 | Self::UnOp { tipo, .. }
342 | Self::BinOp { tipo, .. }
343 | Self::Tuple { tipo, .. }
344 | Self::Pair { tipo, .. }
345 | Self::String { tipo, .. }
346 | Self::ByteArray { tipo, .. }
347 | Self::TupleIndex { tipo, .. }
348 | Self::Assignment { tipo, .. }
349 | Self::ModuleSelect { tipo, .. }
350 | Self::RecordAccess { tipo, .. }
351 | Self::RecordUpdate { tipo, .. }
352 | Self::CurvePoint { tipo, .. } => *tipo = new_type,
353 Self::Pipeline { expressions, .. } | Self::Sequence { expressions, .. } => {
354 expressions
355 .last_mut()
356 .expect("trying to replace type of an empty sequence or pipeline")
357 .replace_type(new_type);
358 }
359 }
360 }
361
362 pub fn is_literal(&self) -> bool {
363 matches!(
364 self,
365 Self::UInt { .. }
366 | Self::List { .. }
367 | Self::Tuple { .. }
368 | Self::String { .. }
369 | Self::ByteArray { .. }
370 )
371 }
372
373 pub fn is_error_term(&self) -> bool {
374 matches!(self, Self::ErrorTerm { .. })
375 }
376
377 pub fn is_assignment(&self) -> bool {
379 matches!(self, Self::Assignment { .. })
380 }
381
382 pub fn definition_location(&self) -> Option<DefinitionLocation<'_>> {
383 match self {
384 TypedExpr::Fn { .. }
385 | TypedExpr::UInt { .. }
386 | TypedExpr::Trace { .. }
387 | TypedExpr::List { .. }
388 | TypedExpr::Call { .. }
389 | TypedExpr::When { .. }
390 | TypedExpr::ErrorTerm { .. }
391 | TypedExpr::BinOp { .. }
392 | TypedExpr::Tuple { .. }
393 | TypedExpr::Pair { .. }
394 | TypedExpr::UnOp { .. }
395 | TypedExpr::String { .. }
396 | TypedExpr::Sequence { .. }
397 | TypedExpr::Pipeline { .. }
398 | TypedExpr::ByteArray { .. }
399 | TypedExpr::Assignment { .. }
400 | TypedExpr::TupleIndex { .. }
401 | TypedExpr::RecordAccess { .. }
402 | TypedExpr::CurvePoint { .. } => None,
403 TypedExpr::If { .. } => None,
404
405 TypedExpr::RecordUpdate { .. } => None,
408
409 TypedExpr::ModuleSelect {
411 module_name,
412 constructor,
413 ..
414 } => Some(DefinitionLocation {
415 module: Some(module_name.as_str()),
416 span: constructor.location(),
417 }),
418
419 TypedExpr::Var { constructor, .. } => Some(constructor.definition_location()),
421 }
422 }
423
424 pub fn type_defining_location(&self) -> Span {
425 match self {
426 Self::Fn { location, .. }
427 | Self::UInt { location, .. }
428 | Self::Var { location, .. }
429 | Self::Trace { location, .. }
430 | Self::ErrorTerm { location, .. }
431 | Self::When { location, .. }
432 | Self::Call { location, .. }
433 | Self::List { location, .. }
434 | Self::BinOp { location, .. }
435 | Self::Tuple { location, .. }
436 | Self::Pair { location, .. }
437 | Self::String { location, .. }
438 | Self::UnOp { location, .. }
439 | Self::Pipeline { location, .. }
440 | Self::ByteArray { location, .. }
441 | Self::Assignment { location, .. }
442 | Self::TupleIndex { location, .. }
443 | Self::ModuleSelect { location, .. }
444 | Self::RecordAccess { location, .. }
445 | Self::RecordUpdate { location, .. }
446 | Self::CurvePoint { location, .. } => *location,
447
448 Self::If { branches, .. } => branches.first().body.type_defining_location(),
449
450 Self::Sequence {
451 expressions,
452 location,
453 ..
454 } => expressions
455 .last()
456 .map(TypedExpr::location)
457 .unwrap_or(*location),
458 }
459 }
460
461 pub fn location(&self) -> Span {
462 match self {
463 Self::Fn { location, .. }
464 | Self::UInt { location, .. }
465 | Self::Trace { location, .. }
466 | Self::Var { location, .. }
467 | Self::ErrorTerm { location, .. }
468 | Self::When { location, .. }
469 | Self::Call { location, .. }
470 | Self::If { location, .. }
471 | Self::List { location, .. }
472 | Self::BinOp { location, .. }
473 | Self::Tuple { location, .. }
474 | Self::Pair { location, .. }
475 | Self::String { location, .. }
476 | Self::UnOp { location, .. }
477 | Self::Sequence { location, .. }
478 | Self::Pipeline { location, .. }
479 | Self::ByteArray { location, .. }
480 | Self::Assignment { location, .. }
481 | Self::TupleIndex { location, .. }
482 | Self::ModuleSelect { location, .. }
483 | Self::RecordAccess { location, .. }
484 | Self::RecordUpdate { location, .. }
485 | Self::CurvePoint { location, .. } => *location,
486 }
487 }
488
489 pub fn find_node(&self, byte_index: usize) -> Option<Located<'_>> {
492 if !self.location().contains(byte_index) {
493 return None;
494 }
495
496 match self {
497 TypedExpr::ErrorTerm { .. }
498 | TypedExpr::Var { .. }
499 | TypedExpr::UInt { .. }
500 | TypedExpr::String { .. }
501 | TypedExpr::ByteArray { .. }
502 | TypedExpr::ModuleSelect { .. }
503 | TypedExpr::CurvePoint { .. } => Some(Located::Expression(self)),
504
505 TypedExpr::Trace { text, then, .. } => text
506 .find_node(byte_index)
507 .or_else(|| then.find_node(byte_index))
508 .or(Some(Located::Expression(self))),
509
510 TypedExpr::Pipeline { expressions, .. } | TypedExpr::Sequence { expressions, .. } => {
511 expressions.iter().find_map(|e| e.find_node(byte_index))
512 }
513
514 TypedExpr::Fn {
515 body,
516 args,
517 return_annotation,
518 ..
519 } => args
520 .iter()
521 .find_map(|arg| arg.find_node(byte_index))
522 .or_else(|| body.find_node(byte_index))
523 .or_else(|| {
524 return_annotation
525 .as_ref()
526 .and_then(|a| a.find_node(byte_index))
527 })
528 .or(Some(Located::Expression(self))),
529
530 TypedExpr::Tuple {
531 elems: elements, ..
532 } => elements
533 .iter()
534 .find_map(|e| e.find_node(byte_index))
535 .or(Some(Located::Expression(self))),
536
537 TypedExpr::Pair { fst, snd, .. } => [fst, snd]
538 .iter()
539 .find_map(|e| e.find_node(byte_index))
540 .or(Some(Located::Expression(self))),
541
542 TypedExpr::List { elements, tail, .. } => elements
543 .iter()
544 .find_map(|e| e.find_node(byte_index))
545 .or_else(|| tail.as_ref().and_then(|t| t.find_node(byte_index)))
546 .or(Some(Located::Expression(self))),
547
548 TypedExpr::Call { fun, args, .. } => args
549 .iter()
550 .find_map(|arg| arg.find_node(byte_index))
551 .or_else(|| fun.find_node(byte_index))
552 .or(Some(Located::Expression(self))),
553
554 TypedExpr::BinOp { left, right, .. } => left
555 .find_node(byte_index)
556 .or_else(|| right.find_node(byte_index))
557 .or(Some(Located::Expression(self))),
558
559 TypedExpr::Assignment { value, pattern, .. } => pattern
560 .find_node(byte_index, &value.tipo())
561 .or_else(|| value.find_node(byte_index)),
562
563 TypedExpr::When {
564 subject, clauses, ..
565 } => subject
566 .find_node(byte_index)
567 .or_else(|| {
568 clauses
569 .iter()
570 .find_map(|clause| clause.find_node(byte_index, &subject.tipo()))
571 })
572 .or(Some(Located::Expression(self))),
573
574 TypedExpr::RecordAccess {
575 record: expression, ..
576 }
577 | TypedExpr::TupleIndex {
578 tuple: expression, ..
579 } => expression
580 .find_node(byte_index)
581 .or(Some(Located::Expression(self))),
582
583 TypedExpr::RecordUpdate { spread, args, .. } => args
584 .iter()
585 .find_map(|arg| arg.find_node(byte_index))
586 .or_else(|| spread.find_node(byte_index))
587 .or(Some(Located::Expression(self))),
588
589 TypedExpr::If {
590 branches,
591 final_else,
592 ..
593 } => branches
594 .iter()
595 .find_map(|branch| {
596 branch
597 .condition
598 .find_node(byte_index)
599 .or_else(|| branch.body.find_node(byte_index))
600 })
601 .or_else(|| final_else.find_node(byte_index))
602 .or(Some(Located::Expression(self))),
603
604 TypedExpr::UnOp { value, .. } => value
605 .find_node(byte_index)
606 .or(Some(Located::Expression(self))),
607 }
608 }
609
610 pub fn void(location: Span) -> Self {
611 TypedExpr::Var {
612 name: "Void".to_string(),
613 constructor: ValueConstructor {
614 public: true,
615 variant: ValueConstructorVariant::Record {
616 name: "Void".to_string(),
617 arity: 0,
618 field_map: None,
619 location: Span::empty(),
620 module: String::new(),
621 constructors_count: 1,
622 },
623 tipo: Type::void(),
624 },
625 location,
626 }
627 }
628}
629
630#[derive(Debug, Clone, PartialEq, Copy)]
632pub enum FnStyle {
633 Plain,
634 Capture,
635 BinOp(BinOp),
636}
637
638#[derive(Debug, Clone, PartialEq)]
639pub enum UntypedExpr {
640 UInt {
641 location: Span,
642 value: String,
643 base: Base,
644 },
645
646 String {
647 location: Span,
648 value: String,
649 },
650
651 Sequence {
652 location: Span,
653 expressions: Vec<Self>,
654 },
655
656 Var {
657 location: Span,
658 name: String,
659 },
660
661 Fn {
662 location: Span,
663 fn_style: FnStyle,
664 arguments: Vec<UntypedArg>,
665 body: Box<Self>,
666 return_annotation: Option<Annotation>,
667 },
668
669 List {
670 location: Span,
671 elements: Vec<Self>,
672 tail: Option<Box<Self>>,
673 },
674
675 Call {
676 arguments: Vec<CallArg<Self>>,
677 fun: Box<Self>,
678 location: Span,
679 },
680
681 BinOp {
682 location: Span,
683 name: BinOp,
684 left: Box<Self>,
685 right: Box<Self>,
686 },
687
688 ByteArray {
689 location: Span,
690 bytes: Vec<(u8, Span)>,
691 preferred_format: ByteArrayFormatPreference,
692 },
693
694 CurvePoint {
695 location: Span,
696 point: Box<Curve>,
697 preferred_format: ByteArrayFormatPreference,
698 },
699
700 PipeLine {
701 expressions: Vec1<Self>,
702 one_liner: bool,
703 },
704
705 Assignment {
706 location: Span,
707 value: Box<Self>,
708 patterns: Vec1<AssignmentPattern>,
709 kind: UntypedAssignmentKind,
710 comment: Option<String>,
711 },
712
713 Trace {
714 kind: TraceKind,
715 location: Span,
716 then: Box<Self>,
717 label: Box<Self>,
718 arguments: Vec<Self>,
719 },
720
721 TraceIfFalse {
722 location: Span,
723 value: Box<Self>,
724 },
725
726 When {
727 location: Span,
728 subject: Box<Self>,
729 clauses: Vec<UntypedClause>,
730 },
731
732 If {
733 location: Span,
734 branches: Vec1<UntypedIfBranch>,
735 final_else: Box<Self>,
736 },
737
738 FieldAccess {
739 location: Span,
740 label: String,
741 container: Box<Self>,
742 },
743
744 Tuple {
745 location: Span,
746 elems: Vec<Self>,
747 },
748
749 Pair {
750 location: Span,
751 fst: Box<Self>,
752 snd: Box<Self>,
753 },
754
755 TupleIndex {
756 location: Span,
757 index: usize,
758 tuple: Box<Self>,
759 },
760
761 ErrorTerm {
762 location: Span,
763 },
764
765 RecordUpdate {
766 location: Span,
767 constructor: Box<Self>,
768 spread: RecordUpdateSpread,
769 arguments: Vec<UntypedRecordUpdateArg>,
770 },
771
772 UnOp {
773 op: UnOp,
774 location: Span,
775 value: Box<Self>,
776 },
777
778 LogicalOpChain {
779 kind: LogicalOpChainKind,
780 expressions: Vec<Self>,
781 location: Span,
782 },
783}
784
785pub const DEFAULT_TODO_STR: &str = "aiken::todo";
786
787pub const DEFAULT_ERROR_STR: &str = "aiken::error";
788
789impl UntypedExpr {
790 pub fn reify_constant(
797 data_types: &IndexMap<&DataTypeKey, &TypedDataType>,
798 cst: uplc::ast::Constant,
799 tipo: Rc<Type>,
800 ) -> Result<Self, String> {
801 UntypedExpr::do_reify_constant(data_types, cst, tipo)
802 }
803
804 pub fn is_discard(&self) -> bool {
805 matches!(self, UntypedExpr::Var { name, ..} if name.starts_with("_"))
806 }
807
808 pub fn reify_data(
815 data_types: &IndexMap<&DataTypeKey, &TypedDataType>,
816 data: PlutusData,
817 tipo: Rc<Type>,
818 ) -> Result<Self, String> {
819 UntypedExpr::do_reify_data(data_types, data, tipo)
820 }
821
822 fn reify_with<T, F>(
823 data_types: &IndexMap<&DataTypeKey, &TypedDataType>,
824 t: T,
825 tipo: Rc<Type>,
826 with: F,
827 ) -> Result<Self, String>
828 where
829 T: Debug,
830 F: Fn(&IndexMap<&DataTypeKey, &TypedDataType>, T, Rc<Type>) -> Result<Self, String>,
831 {
832 if let Type::Var { tipo: var_tipo, .. } = tipo.deref() {
833 match &*var_tipo.borrow() {
834 TypeVar::Link { tipo } => {
835 return Self::reify_with(data_types, t, tipo.clone(), with);
836 }
837 _ => unreachable!("unbound type during reification {tipo:?} -> {t:?}"),
838 }
839 }
840
841 if check_replaceable_opaque_type(&tipo, data_types) {
850 let DataType { name, .. } = lookup_data_type_by_tipo(data_types, &tipo)
851 .expect("Type just disappeared from known types? {tipo:?}");
852
853 let inner_type = convert_opaque_type(&tipo, data_types, false);
854
855 let value = Self::reify_with(data_types, t, inner_type, with)?;
856
857 return Ok(UntypedExpr::Call {
858 location: Span::empty(),
859 arguments: vec![CallArg {
860 label: None,
861 location: Span::empty(),
862 value,
863 }],
864 fun: Box::new(UntypedExpr::Var {
865 name,
866 location: Span::empty(),
867 }),
868 });
869 }
870
871 with(data_types, t, tipo)
872 }
873
874 fn do_reify_constant(
875 data_types: &IndexMap<&DataTypeKey, &TypedDataType>,
876 cst: uplc::ast::Constant,
877 tipo: Rc<Type>,
878 ) -> Result<Self, String> {
879 Self::reify_with(data_types, cst, tipo, |data_types, cst, tipo| match cst {
880 uplc::ast::Constant::Data(data) => UntypedExpr::do_reify_data(data_types, data, tipo),
881
882 uplc::ast::Constant::Integer(i) => {
883 UntypedExpr::do_reify_data(data_types, Data::integer(i), tipo)
884 }
885
886 uplc::ast::Constant::ByteString(bytes) => {
887 UntypedExpr::do_reify_data(data_types, Data::bytestring(bytes), tipo)
888 }
889
890 uplc::ast::Constant::ProtoList(_, args) => match tipo.deref() {
891 Type::App {
892 module,
893 name,
894 args: type_args,
895 ..
896 } if module.is_empty() && name.as_str() == "List" => {
897 if let [inner] = &type_args[..] {
898 Ok(UntypedExpr::List {
899 location: Span::empty(),
900 elements: args
901 .into_iter()
902 .map(|arg| {
903 UntypedExpr::do_reify_constant(data_types, arg, inner.clone())
904 })
905 .collect::<Result<Vec<_>, _>>()?,
906 tail: None,
907 })
908 } else {
909 Err(
910 "invalid List type annotation: the list has multiple type-parameters."
911 .to_string(),
912 )
913 }
914 }
915 Type::Tuple { elems, .. } => Ok(UntypedExpr::Tuple {
916 location: Span::empty(),
917 elems: args
918 .into_iter()
919 .zip(elems)
920 .map(|(arg, arg_type)| {
921 UntypedExpr::do_reify_constant(data_types, arg, arg_type.clone())
922 })
923 .collect::<Result<Vec<_>, _>>()?,
924 }),
925 _ => Err(format!(
926 "invalid type annotation. expected List but got: {tipo:?}"
927 )),
928 },
929
930 uplc::ast::Constant::ProtoPair(_, _, left, right) => match tipo.deref() {
931 Type::Pair { fst, snd, .. } => {
932 let elems = [left.as_ref(), right.as_ref()]
933 .into_iter()
934 .zip([fst, snd])
935 .map(|(arg, arg_type)| {
936 UntypedExpr::do_reify_constant(
937 data_types,
938 arg.to_owned(),
939 arg_type.clone(),
940 )
941 })
942 .collect::<Result<Vec<_>, _>>()?;
943
944 Ok(UntypedExpr::Pair {
945 location: Span::empty(),
946 fst: elems.first().unwrap().to_owned().into(),
947 snd: elems.last().unwrap().to_owned().into(),
948 })
949 }
950 _ => Err(format!(
951 "invalid type annotation. expected Pair but got: {tipo:?}"
952 )),
953 },
954
955 uplc::ast::Constant::Unit => Ok(UntypedExpr::Var {
956 location: Span::empty(),
957 name: "Void".to_string(),
958 }),
959
960 uplc::ast::Constant::Bool(is_true) => Ok(UntypedExpr::Var {
961 location: Span::empty(),
962 name: if is_true { "True" } else { "False" }.to_string(),
963 }),
964
965 uplc::ast::Constant::String(value) => Ok(UntypedExpr::String {
966 location: Span::empty(),
967 value,
968 }),
969
970 uplc::ast::Constant::Bls12_381G1Element(pt) => Ok(UntypedExpr::CurvePoint {
971 location: Span::empty(),
972 point: Curve::Bls12_381(Bls12_381Point::G1(*pt)).into(),
973 preferred_format: ByteArrayFormatPreference::HexadecimalString,
974 }),
975
976 uplc::ast::Constant::Bls12_381G2Element(pt) => Ok(UntypedExpr::CurvePoint {
977 location: Span::empty(),
978 point: Curve::Bls12_381(Bls12_381Point::G2(*pt)).into(),
979 preferred_format: ByteArrayFormatPreference::HexadecimalString,
980 }),
981
982 uplc::ast::Constant::Bls12_381MlResult(ml) => {
983 let mut bytes = Vec::new();
984
985 bytes.extend((*ml).to_bendian());
986
987 Ok(UntypedExpr::Call {
991 location: Span::empty(),
992 arguments: vec![CallArg {
993 label: None,
994 location: Span::empty(),
995 value: UntypedExpr::ByteArray {
996 location: Span::empty(),
997 bytes: bytes.into_iter().map(|b| (b, Span::empty())).collect(),
998 preferred_format: ByteArrayFormatPreference::HexadecimalString,
999 },
1000 }],
1001 fun: Box::new(UntypedExpr::Var {
1002 name: "MillerLoopResult".to_string(),
1003 location: Span::empty(),
1004 }),
1005 })
1006 }
1007 })
1008 }
1009
1010 fn reify_blind(data: PlutusData) -> Self {
1011 match data {
1012 PlutusData::BigInt(ref i) => UntypedExpr::UInt {
1013 location: Span::empty(),
1014 base: Base::Decimal {
1015 numeric_underscore: false,
1016 },
1017 value: from_pallas_bigint(i).to_string(),
1018 },
1019
1020 PlutusData::BoundedBytes(bytes) => {
1021 let bytes: Vec<u8> = bytes.into();
1022
1023 UntypedExpr::ByteArray {
1024 location: Span::empty(),
1025 bytes: bytes.into_iter().map(|b| (b, Span::empty())).collect(),
1026 preferred_format: ByteArrayFormatPreference::HexadecimalString,
1027 }
1028 }
1029
1030 PlutusData::Array(elems) => UntypedExpr::List {
1031 location: Span::empty(),
1032 elements: elems
1033 .to_vec()
1034 .into_iter()
1035 .map(UntypedExpr::reify_blind)
1036 .collect::<Vec<_>>(),
1037 tail: None,
1038 },
1039
1040 PlutusData::Map(indef_or_def) => {
1041 let kvs = match indef_or_def {
1042 KeyValuePairs::Def(kvs) => kvs,
1043 KeyValuePairs::Indef(kvs) => kvs,
1044 };
1045
1046 UntypedExpr::List {
1047 location: Span::empty(),
1048 elements: kvs
1049 .into_iter()
1050 .map(|(k, v)| UntypedExpr::Pair {
1051 location: Span::empty(),
1052 fst: UntypedExpr::reify_blind(k).into(),
1053 snd: UntypedExpr::reify_blind(v).into(),
1054 })
1055 .collect::<Vec<_>>(),
1056 tail: None,
1057 }
1058 }
1059
1060 PlutusData::Constr(Constr {
1061 tag,
1062 any_constructor,
1063 fields,
1064 }) => {
1065 let ix = convert_tag_to_constr(tag).or(any_constructor).unwrap() as usize;
1066
1067 let fields = fields
1068 .to_vec()
1069 .into_iter()
1070 .map(|field| CallArg {
1071 location: Span::empty(),
1072 label: None,
1073 value: UntypedExpr::reify_blind(field),
1074 })
1075 .collect::<Vec<_>>();
1076
1077 let mut arguments = vec![CallArg {
1078 location: Span::empty(),
1079 label: None,
1080 value: UntypedExpr::UInt {
1081 location: Span::empty(),
1082 value: ix.to_string(),
1083 base: Base::Decimal {
1084 numeric_underscore: false,
1085 },
1086 },
1087 }];
1088 arguments.extend(fields);
1089
1090 UntypedExpr::Call {
1091 location: Span::empty(),
1092 arguments,
1093 fun: UntypedExpr::Var {
1094 name: "Constr".to_string(),
1095 location: Span::empty(),
1096 }
1097 .into(),
1098 }
1099 }
1100 }
1101 }
1102
1103 fn do_reify_data(
1104 data_types: &IndexMap<&DataTypeKey, &TypedDataType>,
1105 data: PlutusData,
1106 tipo: Rc<Type>,
1107 ) -> Result<Self, String> {
1108 let tipo = Type::collapse_links(tipo);
1109
1110 if let Type::App { name, module, .. } = tipo.deref()
1111 && module.is_empty()
1112 && name == "Data"
1113 {
1114 return Ok(Self::reify_blind(data));
1115 }
1116
1117 Self::reify_with(
1118 data_types,
1119 data,
1120 tipo,
1121 |data_types, data, tipo| match data {
1122 PlutusData::BigInt(ref i) => Ok(UntypedExpr::UInt {
1123 location: Span::empty(),
1124 base: Base::Decimal {
1125 numeric_underscore: false,
1126 },
1127 value: from_pallas_bigint(i).to_string(),
1128 }),
1129
1130 PlutusData::BoundedBytes(bytes) => {
1131 if tipo.is_string() {
1132 Ok(UntypedExpr::String {
1133 location: Span::empty(),
1134 value: String::from_utf8(bytes.to_vec()).expect("invalid UTF-8 string"),
1135 })
1136 } else {
1137 let bytes: Vec<u8> = bytes.into();
1138 Ok(UntypedExpr::ByteArray {
1139 location: Span::empty(),
1140 bytes: bytes.into_iter().map(|b| (b, Span::empty())).collect(),
1141 preferred_format: ByteArrayFormatPreference::HexadecimalString,
1142 })
1143 }
1144 }
1145
1146 PlutusData::Array(args) => match tipo.deref() {
1147 Type::App {
1148 module,
1149 name,
1150 args: type_args,
1151 ..
1152 } if module.is_empty() && name.as_str() == "List" => {
1153 if let [inner] = &type_args[..] {
1154 Ok(UntypedExpr::List {
1155 location: Span::empty(),
1156 elements: args
1157 .to_vec()
1158 .into_iter()
1159 .map(|arg| {
1160 UntypedExpr::do_reify_data(data_types, arg, inner.clone())
1161 })
1162 .collect::<Result<Vec<_>, _>>()?,
1163 tail: None,
1164 })
1165 } else {
1166 Err(
1167 "invalid List type annotation: the list has multiple type-parameters."
1168 .to_string(),
1169 )
1170 }
1171 }
1172 Type::Tuple { elems, .. } => Ok(UntypedExpr::Tuple {
1173 location: Span::empty(),
1174 elems: args
1175 .to_vec()
1176 .into_iter()
1177 .zip(elems)
1178 .map(|(arg, arg_type)| {
1179 UntypedExpr::do_reify_data(data_types, arg, arg_type.clone())
1180 })
1181 .collect::<Result<Vec<_>, _>>()?,
1182 }),
1183 Type::Pair { fst, snd, .. } => {
1184 let mut elems = args
1185 .to_vec()
1186 .into_iter()
1187 .zip([fst, snd])
1188 .map(|(arg, arg_type)| {
1189 UntypedExpr::do_reify_data(data_types, arg, arg_type.clone())
1190 })
1191 .collect::<Result<Vec<_>, _>>()?;
1192
1193 Ok(UntypedExpr::Pair {
1194 location: Span::empty(),
1195 fst: elems.remove(0).into(),
1196 snd: elems.remove(0).into(),
1197 })
1198 }
1199 _ => Err(format!(
1200 "invalid type annotation. expected List but got: {tipo:?}"
1201 )),
1202 },
1203
1204 PlutusData::Constr(Constr {
1205 tag,
1206 any_constructor,
1207 fields,
1208 }) => {
1209 let ix = convert_tag_to_constr(tag).or(any_constructor).unwrap() as usize;
1210
1211 if let Type::App { args, .. } = tipo.deref()
1212 && let Some(DataType {
1213 constructors,
1214 typed_parameters,
1215 ..
1216 }) = lookup_data_type_by_tipo(data_types, &tipo)
1217 {
1218 if constructors.is_empty() {
1219 return Ok(UntypedExpr::Var {
1220 location: Span::empty(),
1221 name: "Data".to_string(),
1222 });
1223 }
1224
1225 let constructor = &constructors[ix];
1226
1227 let generics = typed_parameters.iter().zip(args).fold(
1228 IndexMap::new(),
1229 |mut generics, (generic, arg)| {
1230 if let Some(ix) = generic.get_generic_id() {
1231 generics.insert(ix, arg.clone());
1232 }
1233
1234 generics
1235 },
1236 );
1237
1238 return if fields.is_empty() {
1239 Ok(UntypedExpr::Var {
1240 location: Span::empty(),
1241 name: constructor.name.to_string(),
1242 })
1243 } else {
1244 let arguments = fields
1245 .to_vec()
1246 .into_iter()
1247 .zip(constructor.arguments.iter())
1248 .map(|(field, RecordConstructorArg { label, tipo, .. })| {
1249 let mut tipo = tipo;
1250
1251 if let Type::Var { tipo: var, .. } =
1254 Type::collapse_links(tipo.clone()).as_ref()
1255 && let TypeVar::Generic { id } = &*var.borrow()
1256 {
1257 tipo = generics.get(id).expect("unknown generic?");
1258 }
1259
1260 UntypedExpr::do_reify_data(data_types, field, tipo.clone()).map(
1261 |value| CallArg {
1262 label: label.clone(),
1263 location: Span::empty(),
1264 value,
1265 },
1266 )
1267 })
1268 .collect::<Result<Vec<_>, _>>()?;
1269
1270 Ok(UntypedExpr::Call {
1271 location: Span::empty(),
1272 arguments,
1273 fun: Box::new(UntypedExpr::Var {
1274 name: constructor.name.to_string(),
1275 location: Span::empty(),
1276 }),
1277 })
1278 };
1279 }
1280
1281 Err(format!(
1282 "invalid type annotation {tipo:?} for {}{} constructor with fields: {fields:?}",
1283 ix + 1,
1284 ordinal::Ordinal::<usize>(ix + 1).suffix(),
1285 ))
1286 }
1287
1288 PlutusData::Map(indef_or_def) => {
1289 let kvs = match indef_or_def {
1290 KeyValuePairs::Def(kvs) => kvs,
1291 KeyValuePairs::Indef(kvs) => kvs,
1292 };
1293
1294 UntypedExpr::do_reify_data(
1295 data_types,
1296 Data::list(
1297 kvs.into_iter()
1298 .map(|(k, v)| Data::list(vec![k, v]))
1299 .collect(),
1300 ),
1301 tipo,
1302 )
1303 }
1304 },
1305 )
1306 }
1307
1308 pub fn todo(reason: Option<Self>, location: Span) -> Self {
1309 UntypedExpr::Trace {
1310 location,
1311 kind: TraceKind::Todo,
1312 then: Box::new(UntypedExpr::ErrorTerm { location }),
1313 label: Box::new(reason.unwrap_or_else(|| UntypedExpr::String {
1314 location,
1315 value: DEFAULT_TODO_STR.to_string(),
1316 })),
1317 arguments: Vec::new(),
1318 }
1319 }
1320
1321 pub fn fail(reason: Option<Self>, location: Span) -> Self {
1322 if let Some(reason) = reason {
1323 UntypedExpr::Trace {
1324 location,
1325 kind: TraceKind::Error,
1326 then: Box::new(UntypedExpr::ErrorTerm { location }),
1327 label: Box::new(reason),
1328 arguments: Vec::new(),
1329 }
1330 } else {
1331 UntypedExpr::ErrorTerm { location }
1332 }
1333 }
1334
1335 pub fn tuple_index(self, index: usize, location: Span) -> Self {
1336 UntypedExpr::TupleIndex {
1337 location: self.location().union(location),
1338 index,
1339 tuple: Box::new(self),
1340 }
1341 }
1342
1343 pub fn field_access(self, label: String, location: Span) -> Self {
1344 UntypedExpr::FieldAccess {
1345 location: self.location().union(location),
1346 label,
1347 container: Box::new(self),
1348 }
1349 }
1350
1351 pub fn call(self, args: Vec<ParsedCallArg>, location: Span) -> Self {
1352 let mut holes = Vec::new();
1353
1354 let args = args
1355 .into_iter()
1356 .enumerate()
1357 .map(|(index, a)| match a {
1358 CallArg {
1359 value: Some(value),
1360 label,
1361 location,
1362 } if !value.is_discard() => CallArg {
1363 value,
1364 label,
1365 location,
1366 },
1367 CallArg {
1368 value,
1369 label,
1370 location,
1371 } => {
1372 let name = format!(
1373 "{}__{index}_{}",
1374 ast::CAPTURE_VARIABLE,
1375 match value {
1376 Some(UntypedExpr::Var { ref name, .. }) => name,
1377 _ => "_",
1378 }
1379 );
1380
1381 holes.push(ast::UntypedArg {
1382 location: Span::empty(),
1383 annotation: None,
1384 doc: None,
1385 by: ArgBy::ByName(ast::ArgName::Named {
1386 label: name.clone(),
1387 name: name.clone(),
1388 location: Span::empty(),
1389 }),
1390 is_validator_param: false,
1391 });
1392
1393 ast::CallArg {
1394 label,
1395 location,
1396 value: UntypedExpr::Var { location, name },
1397 }
1398 }
1399 })
1400 .collect();
1401
1402 let call = UntypedExpr::Call {
1403 location: self.location().union(location),
1404 fun: Box::new(self),
1405 arguments: args,
1406 };
1407
1408 if holes.is_empty() {
1409 call
1410 } else {
1411 UntypedExpr::Fn {
1412 location: call.location(),
1413 fn_style: FnStyle::Capture,
1414 arguments: holes,
1415 body: Box::new(call),
1416 return_annotation: None,
1417 }
1418 }
1419 }
1420
1421 pub fn append_in_sequence(self, next: Self) -> Self {
1422 let location = Span {
1423 start: self.location().start,
1424 end: next.location().end,
1425 };
1426
1427 match (self.clone(), next.clone()) {
1428 (left @ Self::Sequence { .. }, right @ Self::Sequence { .. }) => Self::Sequence {
1429 location,
1430 expressions: vec![left, right],
1431 },
1432 (
1433 _,
1434 Self::Sequence {
1435 expressions: mut next_expressions,
1436 ..
1437 },
1438 ) => {
1439 let mut current_expressions = vec![self];
1440
1441 current_expressions.append(&mut next_expressions);
1442
1443 Self::Sequence {
1444 location,
1445 expressions: current_expressions,
1446 }
1447 }
1448
1449 (_, _) => Self::Sequence {
1450 location,
1451 expressions: vec![self, next],
1452 },
1453 }
1454 }
1455
1456 pub fn location(&self) -> Span {
1457 match self {
1458 Self::PipeLine { expressions, .. } => expressions.last().location(),
1459 Self::Trace { then, .. } => then.location(),
1460 Self::TraceIfFalse { location, .. }
1461 | Self::Fn { location, .. }
1462 | Self::Var { location, .. }
1463 | Self::UInt { location, .. }
1464 | Self::ErrorTerm { location, .. }
1465 | Self::When { location, .. }
1466 | Self::Call { location, .. }
1467 | Self::List { location, .. }
1468 | Self::ByteArray { location, .. }
1469 | Self::BinOp { location, .. }
1470 | Self::Tuple { location, .. }
1471 | Self::Pair { location, .. }
1472 | Self::String { location, .. }
1473 | Self::Assignment { location, .. }
1474 | Self::TupleIndex { location, .. }
1475 | Self::FieldAccess { location, .. }
1476 | Self::RecordUpdate { location, .. }
1477 | Self::UnOp { location, .. }
1478 | Self::LogicalOpChain { location, .. }
1479 | Self::If { location, .. }
1480 | Self::CurvePoint { location, .. } => *location,
1481 Self::Sequence {
1482 location,
1483 expressions,
1484 ..
1485 } => expressions.last().map(Self::location).unwrap_or(*location),
1486 }
1487 }
1488
1489 pub fn start_byte_index(&self) -> usize {
1490 match self {
1491 Self::Sequence {
1492 expressions,
1493 location,
1494 ..
1495 } => expressions
1496 .first()
1497 .map(|e| e.start_byte_index())
1498 .unwrap_or(location.start),
1499 Self::PipeLine { expressions, .. } => expressions.first().start_byte_index(),
1500 Self::Trace { location, .. } | Self::Assignment { location, .. } => location.start,
1501 _ => self.location().start,
1502 }
1503 }
1504
1505 pub fn binop_precedence(&self) -> u8 {
1506 match self {
1507 Self::BinOp { name, .. } => name.precedence(),
1508 Self::PipeLine { .. } => 0,
1509 _ => u8::MAX,
1510 }
1511 }
1512
1513 pub fn is_simple_expr_to_format(&self) -> bool {
1517 match self {
1518 Self::String { .. } | Self::UInt { .. } | Self::ByteArray { .. } | Self::Var { .. } => {
1519 true
1520 }
1521 Self::Pair { fst, snd, .. } => {
1522 fst.is_simple_expr_to_format() && snd.is_simple_expr_to_format()
1523 }
1524 Self::Tuple { elems, .. } => elems.iter().all(|e| e.is_simple_expr_to_format()),
1525 Self::List { elements, .. } if elements.len() <= 3 => {
1526 elements.iter().all(|e| e.is_simple_expr_to_format())
1527 }
1528 _ => false,
1529 }
1530 }
1531
1532 pub fn lambda(
1533 names: Vec<(ArgName, Span, Option<Annotation>)>,
1534 expressions: Vec<UntypedExpr>,
1535 location: Span,
1536 ) -> Self {
1537 Self::Fn {
1538 location,
1539 fn_style: FnStyle::Plain,
1540 arguments: names
1541 .into_iter()
1542 .map(|(arg_name, location, annotation)| UntypedArg {
1543 location,
1544 doc: None,
1545 annotation,
1546 is_validator_param: false,
1547 by: ArgBy::ByName(arg_name),
1548 })
1549 .collect(),
1550 body: Self::Sequence {
1551 location,
1552 expressions,
1553 }
1554 .into(),
1555 return_annotation: None,
1556 }
1557 }
1558}