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