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