1use serde::{Deserialize, Serialize};
12use std::{collections::HashMap, rc::Rc};
13
14#[derive(Debug, PartialEq, Eq)]
15pub struct Scope {
16 pub(crate) symbols: HashMap<String, Symbol>,
17 pub(crate) parent: Option<Rc<Scope>>,
18}
19
20#[derive(Debug, Clone, PartialEq, Eq)]
21pub enum Symbol {
22 EnvVar(String, Box<Type>),
23 ParamVar(String, Box<Type>),
24 LocalExpr(Box<DataExpr>),
25 Output(usize),
26 Input(Box<InputBlock>),
27 Reference(Box<ReferenceBlock>),
28 PartyDef(Box<PartyDef>),
29 PolicyDef(Box<PolicyDef>),
30 AssetDef(Box<AssetDef>),
31 TypeDef(Box<TypeDef>),
32 AliasDef(Box<AliasDef>),
33 RecordField(Box<RecordField>),
34 VariantCase(Box<VariantCase>),
35 Function(String),
36 Fees,
37}
38
39#[derive(Debug, Clone, Serialize, Deserialize)]
40pub struct Span {
41 dummy: bool,
42 pub start: usize,
43 pub end: usize,
44}
45
46impl Default for Span {
47 fn default() -> Self {
48 Self::DUMMY
49 }
50}
51
52impl Eq for Span {}
53
54impl PartialEq for Span {
55 fn eq(&self, other: &Self) -> bool {
56 if self.dummy || other.dummy {
57 return true;
58 }
59
60 self.start == other.start && self.end == other.end
61 }
62}
63
64impl std::hash::Hash for Span {
65 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
66 self.start.hash(state);
67 self.end.hash(state);
68 }
69}
70
71impl Span {
72 pub const DUMMY: Self = Self {
73 dummy: true,
74 start: 0,
75 end: 0,
76 };
77
78 pub fn new(start: usize, end: usize) -> Self {
79 Self {
80 dummy: false,
81 start,
82 end,
83 }
84 }
85}
86
87impl Symbol {
88 pub fn as_type_def(&self) -> Option<&TypeDef> {
89 match self {
90 Symbol::TypeDef(x) => Some(x.as_ref()),
91 _ => None,
92 }
93 }
94
95 pub fn as_alias_def(&self) -> Option<&AliasDef> {
96 match self {
97 Symbol::AliasDef(x) => Some(x.as_ref()),
98 _ => None,
99 }
100 }
101
102 pub fn as_variant_case(&self) -> Option<&VariantCase> {
103 match self {
104 Symbol::VariantCase(x) => Some(x.as_ref()),
105 _ => None,
106 }
107 }
108
109 pub fn as_field_def(&self) -> Option<&RecordField> {
110 match self {
111 Symbol::RecordField(x) => Some(x.as_ref()),
112 _ => None,
113 }
114 }
115
116 pub fn as_policy_def(&self) -> Option<&PolicyDef> {
117 match self {
118 Symbol::PolicyDef(x) => Some(x.as_ref()),
119 _ => None,
120 }
121 }
122
123 pub fn target_type(&self) -> Option<Type> {
124 match self {
125 Symbol::ParamVar(_, ty) => Some(ty.as_ref().clone()),
126 Symbol::RecordField(x) => Some(x.r#type.clone()),
127 Symbol::Input(x) => x.datum_is().cloned(),
128 Symbol::Reference(x) => x.datum_is.clone(),
129 x => {
130 dbg!(x);
131 None
132 }
133 }
134 }
135}
136
137#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
138pub struct Identifier {
139 pub value: String,
140 pub span: Span,
141
142 #[serde(skip)]
144 pub(crate) symbol: Option<Symbol>,
145}
146
147impl Identifier {
148 pub fn new(value: impl Into<String>) -> Self {
149 Self {
150 value: value.into(),
151 symbol: None,
152 span: Span::DUMMY,
153 }
154 }
155
156 pub fn try_symbol(&self) -> Result<&Symbol, crate::lowering::Error> {
157 match &self.symbol {
158 Some(symbol) => Ok(symbol),
159 None => Err(crate::lowering::Error::MissingAnalyzePhase(
160 self.value.clone(),
161 )),
162 }
163 }
164
165 pub fn target_type(&self) -> Option<Type> {
166 self.symbol.as_ref().and_then(|x| x.target_type())
167 }
168}
169
170impl AsRef<str> for Identifier {
171 fn as_ref(&self) -> &str {
172 &self.value
173 }
174}
175
176#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default)]
177pub struct Program {
178 pub env: Option<EnvDef>,
179 pub txs: Vec<TxDef>,
180 pub types: Vec<TypeDef>,
181 pub aliases: Vec<AliasDef>,
182 pub assets: Vec<AssetDef>,
183 pub parties: Vec<PartyDef>,
184 pub policies: Vec<PolicyDef>,
185 pub span: Span,
186
187 #[serde(skip)]
189 pub(crate) scope: Option<Rc<Scope>>,
190}
191
192#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
193pub struct EnvField {
194 pub name: String,
195 pub r#type: Type,
196 pub span: Span,
197}
198
199#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
200pub struct EnvDef {
201 pub fields: Vec<EnvField>,
202 pub span: Span,
203}
204
205#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
206pub struct ParameterList {
207 pub parameters: Vec<ParamDef>,
208 pub span: Span,
209}
210
211#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
212pub struct TxDef {
213 pub name: Identifier,
214 pub parameters: ParameterList,
215 pub locals: Option<LocalsBlock>,
216 pub references: Vec<ReferenceBlock>,
217 pub inputs: Vec<InputBlock>,
218 pub outputs: Vec<OutputBlock>,
219 pub validity: Option<ValidityBlock>,
220 pub mints: Vec<MintBlock>,
221 pub burns: Vec<MintBlock>,
222 pub signers: Option<SignersBlock>,
223 pub adhoc: Vec<ChainSpecificBlock>,
224 pub span: Span,
225 pub collateral: Vec<CollateralBlock>,
226 pub metadata: Option<MetadataBlock>,
227
228 #[serde(skip)]
230 pub(crate) scope: Option<Rc<Scope>>,
231}
232
233#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
234pub struct LocalsAssign {
235 pub name: Identifier,
236 pub value: DataExpr,
237 pub span: Span,
238}
239
240#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default)]
241pub struct LocalsBlock {
242 pub assigns: Vec<LocalsAssign>,
243 pub span: Span,
244}
245
246#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
247pub struct StringLiteral {
248 pub value: String,
249 pub span: Span,
250}
251
252impl StringLiteral {
253 pub fn new(value: impl Into<String>) -> Self {
254 Self {
255 value: value.into(),
256 span: Span::DUMMY,
257 }
258 }
259}
260
261#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
262pub struct HexStringLiteral {
263 pub value: String,
264 pub span: Span,
265}
266
267impl HexStringLiteral {
268 pub fn new(value: impl Into<String>) -> Self {
269 Self {
270 value: value.into(),
271 span: Span::DUMMY,
272 }
273 }
274}
275
276#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
277pub enum CollateralBlockField {
278 From(DataExpr),
279 MinAmount(DataExpr),
280 Ref(DataExpr),
281}
282
283impl CollateralBlockField {
284 fn key(&self) -> &str {
285 match self {
286 CollateralBlockField::From(_) => "from",
287 CollateralBlockField::MinAmount(_) => "min_amount",
288 CollateralBlockField::Ref(_) => "ref",
289 }
290 }
291
292 pub fn as_data_expr(&self) -> Option<&DataExpr> {
293 match self {
294 CollateralBlockField::Ref(x) => Some(x),
295 _ => None,
296 }
297 }
298}
299
300#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
301pub struct CollateralBlock {
302 pub fields: Vec<CollateralBlockField>,
303 pub span: Span,
304}
305
306impl CollateralBlock {
307 pub(crate) fn find(&self, key: &str) -> Option<&CollateralBlockField> {
308 self.fields.iter().find(|x| x.key() == key)
309 }
310}
311
312#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
313pub enum InputBlockField {
314 From(DataExpr),
315 DatumIs(Type),
316 MinAmount(DataExpr),
317 Redeemer(DataExpr),
318 Ref(DataExpr),
319}
320
321impl InputBlockField {
322 fn key(&self) -> &str {
323 match self {
324 InputBlockField::From(_) => "from",
325 InputBlockField::DatumIs(_) => "datum_is",
326 InputBlockField::MinAmount(_) => "min_amount",
327 InputBlockField::Redeemer(_) => "redeemer",
328 InputBlockField::Ref(_) => "ref",
329 }
330 }
331
332 pub fn as_data_expr(&self) -> Option<&DataExpr> {
333 match self {
334 InputBlockField::Redeemer(x) => Some(x),
335 InputBlockField::Ref(x) => Some(x),
336 _ => None,
337 }
338 }
339
340 pub fn as_datum_type(&self) -> Option<&Type> {
341 match self {
342 InputBlockField::DatumIs(x) => Some(x),
343 _ => None,
344 }
345 }
346}
347
348#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
349pub struct ReferenceBlock {
350 pub name: String,
351 pub r#ref: DataExpr,
352 pub datum_is: Option<Type>,
353 pub span: Span,
354}
355
356#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
357pub struct MetadataBlockField {
358 pub key: DataExpr,
359 pub value: DataExpr,
360 pub span: Span,
361}
362
363#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
364pub struct MetadataBlock {
365 pub fields: Vec<MetadataBlockField>,
366 pub span: Span,
367}
368
369#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
370pub struct InputBlock {
371 pub name: String,
372 pub many: bool,
373 pub fields: Vec<InputBlockField>,
374 pub span: Span,
375}
376
377impl InputBlock {
378 pub(crate) fn find(&self, key: &str) -> Option<&InputBlockField> {
379 self.fields.iter().find(|x| x.key() == key)
380 }
381
382 pub(crate) fn datum_is(&self) -> Option<&Type> {
383 self.find("datum_is").and_then(|x| x.as_datum_type())
384 }
385}
386
387#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
388pub enum OutputBlockField {
389 To(Box<DataExpr>),
390 Amount(Box<DataExpr>),
391 Datum(Box<DataExpr>),
392}
393
394impl OutputBlockField {
395 fn key(&self) -> &str {
396 match self {
397 OutputBlockField::To(_) => "to",
398 OutputBlockField::Amount(_) => "amount",
399 OutputBlockField::Datum(_) => "datum",
400 }
401 }
402}
403
404#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
405pub struct OutputBlock {
406 pub name: Option<Identifier>,
407 pub optional: bool,
408 pub fields: Vec<OutputBlockField>,
409 pub span: Span,
410}
411
412impl OutputBlock {
413 pub(crate) fn find(&self, key: &str) -> Option<&OutputBlockField> {
414 self.fields.iter().find(|x| x.key() == key)
415 }
416}
417
418#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
419pub enum ValidityBlockField {
420 UntilSlot(Box<DataExpr>),
421 SinceSlot(Box<DataExpr>),
422}
423
424impl ValidityBlockField {
425 fn key(&self) -> &str {
426 match self {
427 ValidityBlockField::UntilSlot(_) => "until_slot",
428 ValidityBlockField::SinceSlot(_) => "since_slot",
429 }
430 }
431}
432
433#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
434pub struct ValidityBlock {
435 pub fields: Vec<ValidityBlockField>,
436 pub span: Span,
437}
438
439impl ValidityBlock {
440 pub(crate) fn find(&self, key: &str) -> Option<&ValidityBlockField> {
441 self.fields.iter().find(|x| x.key() == key)
442 }
443}
444
445#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
446pub enum MintBlockField {
447 Amount(Box<DataExpr>),
448 Redeemer(Box<DataExpr>),
449}
450
451impl MintBlockField {
452 fn key(&self) -> &str {
453 match self {
454 MintBlockField::Amount(_) => "amount",
455 MintBlockField::Redeemer(_) => "redeemer",
456 }
457 }
458}
459
460#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
461pub struct MintBlock {
462 pub fields: Vec<MintBlockField>,
463 pub span: Span,
464}
465
466#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
467pub struct SignersBlock {
468 pub signers: Vec<DataExpr>,
469 pub span: Span,
470}
471
472impl MintBlock {
473 pub(crate) fn find(&self, key: &str) -> Option<&MintBlockField> {
474 self.fields.iter().find(|x| x.key() == key)
475 }
476}
477
478#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
479pub struct RecordField {
480 pub name: Identifier,
481 pub r#type: Type,
482 pub span: Span,
483}
484
485impl RecordField {
486 pub fn new(name: &str, r#type: Type) -> Self {
487 Self {
488 name: Identifier::new(name),
489 r#type,
490 span: Span::DUMMY,
491 }
492 }
493}
494
495#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
496pub struct PartyDef {
497 pub name: Identifier,
498 pub span: Span,
499}
500
501#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
502pub struct PartyField {
503 pub name: String,
504 pub party_type: String,
505}
506
507#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
508pub struct PolicyDef {
509 pub name: Identifier,
510 pub value: PolicyValue,
511 pub span: Span,
512}
513
514#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
515pub enum PolicyField {
516 Hash(DataExpr),
517 Script(DataExpr),
518 Ref(DataExpr),
519}
520
521#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
522pub struct PolicyConstructor {
523 pub fields: Vec<PolicyField>,
524 pub span: Span,
525}
526
527impl PolicyConstructor {
528 pub(crate) fn find_field(&self, field: &str) -> Option<&PolicyField> {
529 self.fields.iter().find(|x| match x {
530 PolicyField::Hash(_) => field == "hash",
531 PolicyField::Script(_) => field == "script",
532 PolicyField::Ref(_) => field == "ref",
533 })
534 }
535}
536
537#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
538pub enum PolicyValue {
539 Constructor(PolicyConstructor),
540 Assign(HexStringLiteral),
541}
542
543#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
544pub struct AnyAssetConstructor {
545 pub policy: Box<DataExpr>,
546 pub asset_name: Box<DataExpr>,
547 pub amount: Box<DataExpr>,
548 pub span: Span,
549}
550
551impl AnyAssetConstructor {
552 pub fn target_type(&self) -> Option<Type> {
553 Some(Type::AnyAsset)
554 }
555}
556
557#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
558pub struct RecordConstructorField {
559 pub name: Identifier,
560 pub value: Box<DataExpr>,
561 pub span: Span,
562}
563
564#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
565pub struct StructConstructor {
566 pub r#type: Identifier,
567 pub case: VariantCaseConstructor,
568 pub span: Span,
569
570 #[serde(skip)]
572 pub scope: Option<Rc<Scope>>,
573}
574
575impl StructConstructor {
576 pub fn target_type(&self) -> Option<Type> {
577 self.r#type.symbol.as_ref().and_then(|x| x.target_type())
578 }
579}
580
581#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
582pub struct VariantCaseConstructor {
583 pub name: Identifier,
584 pub fields: Vec<RecordConstructorField>,
585 pub spread: Option<Box<DataExpr>>,
586 pub span: Span,
587
588 #[serde(skip)]
590 pub scope: Option<Rc<Scope>>,
591}
592
593impl VariantCaseConstructor {
594 pub fn find_field_value(&self, field: &str) -> Option<&DataExpr> {
595 self.fields
596 .iter()
597 .find(|x| x.name.value == field)
598 .map(|x| x.value.as_ref())
599 }
600}
601
602#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
603pub struct ListConstructor {
604 pub elements: Vec<DataExpr>,
605 pub span: Span,
606}
607
608impl ListConstructor {
609 pub fn target_type(&self) -> Option<Type> {
610 self.elements.first().and_then(|x| x.target_type())
611 }
612}
613
614#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
615pub struct MapField {
616 pub key: DataExpr,
617 pub value: DataExpr,
618 pub span: Span,
619}
620
621impl MapField {
622 pub fn target_type(&self) -> Option<Type> {
623 self.key.target_type()
624 }
625}
626
627#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
628pub struct MapConstructor {
629 pub fields: Vec<MapField>,
630 pub span: Span,
631}
632
633impl MapConstructor {
634 pub fn target_type(&self) -> Option<Type> {
635 if let Some(first_field) = self.fields.first() {
636 let key_type = first_field.key.target_type()?;
637 let value_type = first_field.value.target_type()?;
638 Some(Type::Map(Box::new(key_type), Box::new(value_type)))
639 } else {
640 None
641 }
642 }
643}
644
645#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
646pub struct UtxoRef {
647 pub txid: Vec<u8>,
648 pub index: u64,
649 pub span: Span,
650}
651
652#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
653pub struct NegateOp {
654 pub operand: Box<DataExpr>,
655 pub span: Span,
656}
657
658impl NegateOp {
659 pub fn target_type(&self) -> Option<Type> {
660 self.operand.target_type()
661 }
662}
663
664#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
665pub struct PropertyOp {
666 pub operand: Box<DataExpr>,
667 pub property: Box<DataExpr>,
668 pub span: Span,
669
670 #[serde(skip)]
672 pub(crate) scope: Option<Rc<Scope>>,
673}
674
675impl PropertyOp {
676 pub fn target_type(&self) -> Option<Type> {
677 self.property.target_type()
678 }
679}
680
681#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
682pub struct AddOp {
683 pub lhs: Box<DataExpr>,
684 pub rhs: Box<DataExpr>,
685 pub span: Span,
686}
687
688impl AddOp {
689 pub fn target_type(&self) -> Option<Type> {
690 self.lhs.target_type()
691 }
692}
693
694#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
695pub struct SubOp {
696 pub lhs: Box<DataExpr>,
697 pub rhs: Box<DataExpr>,
698 pub span: Span,
699}
700
701impl SubOp {
702 pub fn target_type(&self) -> Option<Type> {
703 self.lhs.target_type()
704 }
705}
706
707#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
708pub struct ConcatOp {
709 pub lhs: Box<DataExpr>,
710 pub rhs: Box<DataExpr>,
711 pub span: Span,
712}
713
714impl ConcatOp {
715 pub fn target_type(&self) -> Option<Type> {
716 self.lhs.target_type()
717 }
718}
719
720#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
721pub struct FnCall {
722 pub callee: Identifier,
723 pub args: Vec<DataExpr>,
724 pub span: Span,
725}
726
727#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
728pub enum DataExpr {
729 None,
730 Unit,
731 Number(i64),
732 Bool(bool),
733 String(StringLiteral),
734 HexString(HexStringLiteral),
735 StructConstructor(StructConstructor),
736 ListConstructor(ListConstructor),
737 MapConstructor(MapConstructor),
738 AnyAssetConstructor(AnyAssetConstructor),
739 Identifier(Identifier),
740 MinUtxo(Identifier),
741 ComputeTipSlot,
742 SlotToTime(Box<DataExpr>),
743 TimeToSlot(Box<DataExpr>),
744 AddOp(AddOp),
745 SubOp(SubOp),
746 ConcatOp(ConcatOp),
747 NegateOp(NegateOp),
748 PropertyOp(PropertyOp),
749 UtxoRef(UtxoRef),
750 FnCall(FnCall),
751}
752
753impl DataExpr {
754 pub fn as_identifier(&self) -> Option<&Identifier> {
755 match self {
756 DataExpr::Identifier(x) => Some(x),
757 _ => None,
758 }
759 }
760
761 pub fn target_type(&self) -> Option<Type> {
762 match self {
763 DataExpr::Identifier(x) => x.target_type(),
764 DataExpr::None => Some(Type::Undefined),
765 DataExpr::Unit => Some(Type::Unit),
766 DataExpr::Number(_) => Some(Type::Int),
767 DataExpr::Bool(_) => Some(Type::Bool),
768 DataExpr::String(_) => Some(Type::Bytes),
769 DataExpr::HexString(_) => Some(Type::Bytes),
770 DataExpr::StructConstructor(x) => x.target_type(),
771 DataExpr::MapConstructor(x) => x.target_type(),
772 DataExpr::ListConstructor(x) => match x.target_type() {
773 Some(inner) => Some(Type::List(Box::new(inner))),
774 None => None,
775 },
776 DataExpr::AddOp(x) => x.target_type(),
777 DataExpr::SubOp(x) => x.target_type(),
778 DataExpr::ConcatOp(x) => x.target_type(),
779 DataExpr::NegateOp(x) => x.target_type(),
780 DataExpr::PropertyOp(x) => x.target_type(),
781 DataExpr::AnyAssetConstructor(x) => x.target_type(),
782 DataExpr::UtxoRef(_) => Some(Type::UtxoRef),
783 DataExpr::MinUtxo(_) => Some(Type::AnyAsset),
784 DataExpr::ComputeTipSlot => Some(Type::Int),
785 DataExpr::SlotToTime(_) => Some(Type::Int),
786 DataExpr::TimeToSlot(_) => Some(Type::Int),
787 DataExpr::FnCall(_) => None, }
789 }
790}
791
792#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
793pub enum AddressExpr {
794 String(StringLiteral),
795 HexString(HexStringLiteral),
796 Identifier(Identifier),
797}
798
799impl AddressExpr {
800 pub fn as_identifier(&self) -> Option<&Identifier> {
801 match self {
802 AddressExpr::Identifier(x) => Some(x),
803 _ => None,
804 }
805 }
806}
807
808#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
809pub enum Type {
810 Undefined,
811 Unit,
812 Int,
813 Bool,
814 Bytes,
815 Address,
816 Utxo,
817 UtxoRef,
818 AnyAsset,
819 List(Box<Type>),
820 Map(Box<Type>, Box<Type>),
821 Custom(Identifier),
822}
823
824impl std::fmt::Display for Type {
825 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
826 match self {
827 Type::Undefined => write!(f, "Undefined"),
828 Type::Unit => write!(f, "Unit"),
829 Type::Int => write!(f, "Int"),
830 Type::Bool => write!(f, "Bool"),
831 Type::Bytes => write!(f, "Bytes"),
832 Type::Address => write!(f, "Address"),
833 Type::UtxoRef => write!(f, "UtxoRef"),
834 Type::AnyAsset => write!(f, "AnyAsset"),
835 Type::Utxo => write!(f, "Utxo"),
836 Type::Map(key, value) => write!(f, "Map<{}, {}>", key, value),
837 Type::List(inner) => write!(f, "List<{inner}>"),
838 Type::Custom(id) => write!(f, "{}", id.value),
839 }
840 }
841}
842
843impl Type {
844 pub fn properties(&self) -> Vec<(String, Type)> {
845 match self {
846 Type::AnyAsset => {
847 vec![
848 ("amount".to_string(), Type::Int),
849 ("policy".to_string(), Type::Bytes),
850 ("asset_name".to_string(), Type::Bytes),
851 ]
852 }
853 Type::UtxoRef => {
854 vec![
855 ("tx_hash".to_string(), Type::Bytes),
856 ("output_index".to_string(), Type::Int),
857 ]
858 }
859 Type::Custom(identifier) => {
860 let def = identifier.symbol.as_ref().and_then(|s| s.as_type_def());
861
862 match def {
863 Some(ty) if ty.cases.len() == 1 => ty.cases[0]
864 .fields
865 .iter()
866 .map(|f| (f.name.value.clone(), f.r#type.clone()))
867 .collect(),
868 _ => vec![],
869 }
870 }
871 _ => vec![],
872 }
873 }
874
875 pub fn property_index(&self, property: DataExpr) -> Option<DataExpr> {
876 match self {
877 Type::AnyAsset | Type::UtxoRef | Type::Custom(_) => {
878 let identifier = property.as_identifier()?;
879 let properties = Self::properties(self);
880 properties
881 .iter()
882 .position(|(name, _)| name == &identifier.value)
883 .map(|index| DataExpr::Number(index as i64))
884 }
885 Type::List(_) => property
886 .target_type()
887 .filter(|ty| *ty == Type::Int)
888 .map(|_| property),
889 _ => None,
890 }
891 }
892}
893
894#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
895pub struct ParamDef {
896 pub name: Identifier,
897 pub r#type: Type,
898}
899
900#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
901pub struct AliasDef {
902 pub name: Identifier,
903 pub alias_type: Type,
904 pub span: Span,
905}
906
907impl AliasDef {
908 pub fn resolve_alias_chain(&self) -> Option<&TypeDef> {
909 match &self.alias_type {
910 Type::Custom(identifier) => match &identifier.symbol {
911 Some(Symbol::TypeDef(type_def)) => Some(type_def),
912 Some(Symbol::AliasDef(next_alias)) => next_alias.resolve_alias_chain(),
913 _ => None,
914 },
915 _ => None,
916 }
917 }
918
919 pub fn is_alias_chain_resolved(&self) -> bool {
920 self.resolve_alias_chain().is_some()
921 }
922}
923
924#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
925pub struct TypeDef {
926 pub name: Identifier,
927 pub cases: Vec<VariantCase>,
928 pub span: Span,
929}
930
931impl TypeDef {
932 pub(crate) fn find_case_index(&self, case: &str) -> Option<usize> {
933 self.cases.iter().position(|x| x.name.value == case)
934 }
935
936 #[allow(dead_code)]
937 pub(crate) fn find_case(&self, case: &str) -> Option<&VariantCase> {
938 self.cases.iter().find(|x| x.name.value == case)
939 }
940}
941
942#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
943pub struct VariantCase {
944 pub name: Identifier,
945 pub fields: Vec<RecordField>,
946 pub span: Span,
947}
948
949impl VariantCase {
950 #[allow(dead_code)]
951 pub(crate) fn find_field_index(&self, field: &str) -> Option<usize> {
952 self.fields.iter().position(|x| x.name.value == field)
953 }
954
955 #[allow(dead_code)]
956 pub(crate) fn find_field(&self, field: &str) -> Option<&RecordField> {
957 self.fields.iter().find(|x| x.name.value == field)
958 }
959}
960
961#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
962pub struct AssetDef {
963 pub name: Identifier,
964 pub policy: DataExpr,
965 pub asset_name: DataExpr,
966 pub span: Span,
967}
968
969#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
970pub enum ChainSpecificBlock {
971 Cardano(crate::cardano::CardanoBlock),
972}