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 FunctionDef(Box<FnDef>),
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 as_fn_def(&self) -> Option<&FnDef> {
124 match self {
125 Symbol::FunctionDef(x) => Some(x.as_ref()),
126 _ => None,
127 }
128 }
129
130 pub fn target_type(&self) -> Option<Type> {
131 match self {
132 Symbol::ParamVar(_, ty) => Some(ty.as_ref().clone()),
133 Symbol::RecordField(x) => Some(x.r#type.clone()),
134 Symbol::Input(x) => x.datum_is().cloned(),
135 Symbol::Reference(x) => x.datum_is.clone(),
136 x => {
137 dbg!(x);
138 None
139 }
140 }
141 }
142}
143
144#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
145pub struct Identifier {
146 pub value: String,
147 pub span: Span,
148
149 #[serde(skip)]
151 pub(crate) symbol: Option<Symbol>,
152}
153
154impl Identifier {
155 pub fn new(value: impl Into<String>) -> Self {
156 Self {
157 value: value.into(),
158 symbol: None,
159 span: Span::DUMMY,
160 }
161 }
162
163 pub fn try_symbol(&self) -> Result<&Symbol, crate::lowering::Error> {
164 match &self.symbol {
165 Some(symbol) => Ok(symbol),
166 None => Err(crate::lowering::Error::MissingAnalyzePhase(
167 self.value.clone(),
168 )),
169 }
170 }
171
172 pub fn target_type(&self) -> Option<Type> {
173 self.symbol.as_ref().and_then(|x| x.target_type())
174 }
175}
176
177impl AsRef<str> for Identifier {
178 fn as_ref(&self) -> &str {
179 &self.value
180 }
181}
182
183#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default)]
184pub struct Program {
185 pub env: Option<EnvDef>,
186 pub txs: Vec<TxDef>,
187 pub types: Vec<TypeDef>,
188 pub aliases: Vec<AliasDef>,
189 pub assets: Vec<AssetDef>,
190 pub parties: Vec<PartyDef>,
191 pub policies: Vec<PolicyDef>,
192 #[serde(default)]
193 pub functions: Vec<FnDef>,
194 pub span: Span,
195
196 #[serde(skip)]
198 pub(crate) scope: Option<Rc<Scope>>,
199}
200
201#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
202pub struct EnvField {
203 pub name: String,
204 pub r#type: Type,
205 #[serde(default, skip_serializing_if = "Option::is_none")]
206 pub docstring: Option<String>,
207 pub span: Span,
208}
209
210#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
211pub struct EnvDef {
212 pub fields: Vec<EnvField>,
213 pub span: Span,
214}
215
216#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
217pub struct ParameterList {
218 pub parameters: Vec<ParamDef>,
219 pub span: Span,
220}
221
222#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
223pub struct TxDef {
224 pub name: Identifier,
225 #[serde(default, skip_serializing_if = "Option::is_none")]
226 pub docstring: Option<String>,
227 pub parameters: ParameterList,
228 pub locals: Option<LocalsBlock>,
229 pub references: Vec<ReferenceBlock>,
230 pub inputs: Vec<InputBlock>,
231 pub outputs: Vec<OutputBlock>,
232 pub validity: Option<ValidityBlock>,
233 pub mints: Vec<MintBlock>,
234 pub burns: Vec<MintBlock>,
235 pub signers: Option<SignersBlock>,
236 pub adhoc: Vec<ChainSpecificBlock>,
237 pub span: Span,
238 pub collateral: Vec<CollateralBlock>,
239 pub metadata: Option<MetadataBlock>,
240
241 #[serde(skip)]
243 pub(crate) scope: Option<Rc<Scope>>,
244}
245
246#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
247pub struct LocalsAssign {
248 pub name: Identifier,
249 pub value: DataExpr,
250 pub span: Span,
251}
252
253#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default)]
254pub struct LocalsBlock {
255 pub assigns: Vec<LocalsAssign>,
256 pub span: Span,
257}
258
259#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
260pub struct StringLiteral {
261 pub value: String,
262 pub span: Span,
263}
264
265impl StringLiteral {
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, Hash)]
275pub struct HexStringLiteral {
276 pub value: String,
277 pub span: Span,
278}
279
280impl HexStringLiteral {
281 pub fn new(value: impl Into<String>) -> Self {
282 Self {
283 value: value.into(),
284 span: Span::DUMMY,
285 }
286 }
287}
288
289#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
290pub enum CollateralBlockField {
291 From(DataExpr),
292 MinAmount(DataExpr),
293 Ref(DataExpr),
294}
295
296impl CollateralBlockField {
297 fn key(&self) -> &str {
298 match self {
299 CollateralBlockField::From(_) => "from",
300 CollateralBlockField::MinAmount(_) => "min_amount",
301 CollateralBlockField::Ref(_) => "ref",
302 }
303 }
304
305 pub fn as_data_expr(&self) -> Option<&DataExpr> {
306 match self {
307 CollateralBlockField::Ref(x) => Some(x),
308 _ => None,
309 }
310 }
311}
312
313#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
314pub struct CollateralBlock {
315 pub fields: Vec<CollateralBlockField>,
316 pub span: Span,
317}
318
319impl CollateralBlock {
320 pub(crate) fn find(&self, key: &str) -> Option<&CollateralBlockField> {
321 self.fields.iter().find(|x| x.key() == key)
322 }
323}
324
325#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
326pub enum InputBlockField {
327 From(DataExpr),
328 DatumIs(Type),
329 MinAmount(DataExpr),
330 Redeemer(DataExpr),
331 Ref(DataExpr),
332}
333
334impl InputBlockField {
335 fn key(&self) -> &str {
336 match self {
337 InputBlockField::From(_) => "from",
338 InputBlockField::DatumIs(_) => "datum_is",
339 InputBlockField::MinAmount(_) => "min_amount",
340 InputBlockField::Redeemer(_) => "redeemer",
341 InputBlockField::Ref(_) => "ref",
342 }
343 }
344
345 pub fn as_data_expr(&self) -> Option<&DataExpr> {
346 match self {
347 InputBlockField::Redeemer(x) => Some(x),
348 InputBlockField::Ref(x) => Some(x),
349 _ => None,
350 }
351 }
352
353 pub fn as_datum_type(&self) -> Option<&Type> {
354 match self {
355 InputBlockField::DatumIs(x) => Some(x),
356 _ => None,
357 }
358 }
359}
360
361#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
362pub struct ReferenceBlock {
363 pub name: String,
364 pub r#ref: DataExpr,
365 pub datum_is: Option<Type>,
366 pub span: Span,
367}
368
369#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
370pub struct MetadataBlockField {
371 pub key: DataExpr,
372 pub value: DataExpr,
373 pub span: Span,
374}
375
376#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
377pub struct MetadataBlock {
378 pub fields: Vec<MetadataBlockField>,
379 pub span: Span,
380}
381
382#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
383pub struct InputBlock {
384 pub name: String,
385 pub many: bool,
386 pub fields: Vec<InputBlockField>,
387 pub span: Span,
388}
389
390impl InputBlock {
391 pub(crate) fn find(&self, key: &str) -> Option<&InputBlockField> {
392 self.fields.iter().find(|x| x.key() == key)
393 }
394
395 pub(crate) fn datum_is(&self) -> Option<&Type> {
396 self.find("datum_is").and_then(|x| x.as_datum_type())
397 }
398}
399
400#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
401pub enum OutputBlockField {
402 To(Box<DataExpr>),
403 Amount(Box<DataExpr>),
404 Datum(Box<DataExpr>),
405}
406
407impl OutputBlockField {
408 fn key(&self) -> &str {
409 match self {
410 OutputBlockField::To(_) => "to",
411 OutputBlockField::Amount(_) => "amount",
412 OutputBlockField::Datum(_) => "datum",
413 }
414 }
415}
416
417#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
418pub struct OutputBlock {
419 pub name: Option<Identifier>,
420 pub optional: bool,
421 pub fields: Vec<OutputBlockField>,
422 pub span: Span,
423}
424
425impl OutputBlock {
426 pub(crate) fn find(&self, key: &str) -> Option<&OutputBlockField> {
427 self.fields.iter().find(|x| x.key() == key)
428 }
429}
430
431#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
432pub enum ValidityBlockField {
433 UntilSlot(Box<DataExpr>),
434 SinceSlot(Box<DataExpr>),
435}
436
437impl ValidityBlockField {
438 fn key(&self) -> &str {
439 match self {
440 ValidityBlockField::UntilSlot(_) => "until_slot",
441 ValidityBlockField::SinceSlot(_) => "since_slot",
442 }
443 }
444}
445
446#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
447pub struct ValidityBlock {
448 pub fields: Vec<ValidityBlockField>,
449 pub span: Span,
450}
451
452impl ValidityBlock {
453 pub(crate) fn find(&self, key: &str) -> Option<&ValidityBlockField> {
454 self.fields.iter().find(|x| x.key() == key)
455 }
456}
457
458#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
459pub enum MintBlockField {
460 Amount(Box<DataExpr>),
461 Redeemer(Box<DataExpr>),
462}
463
464impl MintBlockField {
465 fn key(&self) -> &str {
466 match self {
467 MintBlockField::Amount(_) => "amount",
468 MintBlockField::Redeemer(_) => "redeemer",
469 }
470 }
471}
472
473#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
474pub struct MintBlock {
475 pub fields: Vec<MintBlockField>,
476 pub span: Span,
477}
478
479#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
480pub struct SignersBlock {
481 pub signers: Vec<DataExpr>,
482 pub span: Span,
483}
484
485impl MintBlock {
486 pub(crate) fn find(&self, key: &str) -> Option<&MintBlockField> {
487 self.fields.iter().find(|x| x.key() == key)
488 }
489}
490
491#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
492pub struct RecordField {
493 pub name: Identifier,
494 pub r#type: Type,
495 pub span: Span,
496}
497
498impl RecordField {
499 pub fn new(name: &str, r#type: Type) -> Self {
500 Self {
501 name: Identifier::new(name),
502 r#type,
503 span: Span::DUMMY,
504 }
505 }
506}
507
508#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
509pub struct PartyDef {
510 pub name: Identifier,
511 #[serde(default, skip_serializing_if = "Option::is_none")]
512 pub docstring: Option<String>,
513 pub span: Span,
514}
515
516#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
517pub struct PartyField {
518 pub name: String,
519 pub party_type: String,
520}
521
522#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
523pub struct PolicyDef {
524 pub name: Identifier,
525 pub value: PolicyValue,
526 pub span: Span,
527}
528
529#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
530pub enum PolicyField {
531 Hash(DataExpr),
532 Script(DataExpr),
533 Ref(DataExpr),
534}
535
536#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
537pub struct PolicyConstructor {
538 pub fields: Vec<PolicyField>,
539 pub span: Span,
540}
541
542impl PolicyConstructor {
543 pub(crate) fn find_field(&self, field: &str) -> Option<&PolicyField> {
544 self.fields.iter().find(|x| match x {
545 PolicyField::Hash(_) => field == "hash",
546 PolicyField::Script(_) => field == "script",
547 PolicyField::Ref(_) => field == "ref",
548 })
549 }
550}
551
552#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
553pub enum PolicyValue {
554 Constructor(PolicyConstructor),
555 Assign(HexStringLiteral),
556}
557
558#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
559pub struct AnyAssetConstructor {
560 pub policy: Box<DataExpr>,
561 pub asset_name: Box<DataExpr>,
562 pub amount: Box<DataExpr>,
563 pub span: Span,
564}
565
566impl AnyAssetConstructor {
567 pub fn target_type(&self) -> Option<Type> {
568 Some(Type::AnyAsset)
569 }
570}
571
572#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
573pub struct RecordConstructorField {
574 pub name: Identifier,
575 pub value: Box<DataExpr>,
576 pub span: Span,
577}
578
579#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
580pub struct StructConstructor {
581 pub r#type: Identifier,
582 pub case: VariantCaseConstructor,
583 pub span: Span,
584
585 #[serde(skip)]
587 pub scope: Option<Rc<Scope>>,
588}
589
590impl StructConstructor {
591 pub fn target_type(&self) -> Option<Type> {
592 self.r#type.symbol.as_ref().and_then(|x| x.target_type())
593 }
594}
595
596#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
597pub struct VariantCaseConstructor {
598 pub name: Identifier,
599 pub fields: Vec<RecordConstructorField>,
600 pub spread: Option<Box<DataExpr>>,
601 pub span: Span,
602
603 #[serde(skip)]
605 pub scope: Option<Rc<Scope>>,
606}
607
608impl VariantCaseConstructor {
609 pub fn find_field_value(&self, field: &str) -> Option<&DataExpr> {
610 self.fields
611 .iter()
612 .find(|x| x.name.value == field)
613 .map(|x| x.value.as_ref())
614 }
615}
616
617#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
618pub struct ListConstructor {
619 pub elements: Vec<DataExpr>,
620 pub span: Span,
621}
622
623impl ListConstructor {
624 pub fn target_type(&self) -> Option<Type> {
625 self.elements.first().and_then(|x| x.target_type())
626 }
627}
628
629#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
630pub struct TupleConstructor {
631 pub elements: Vec<DataExpr>,
632 pub span: Span,
633}
634
635impl TupleConstructor {
636 pub fn target_type(&self) -> Option<Type> {
637 let elements = self
639 .elements
640 .iter()
641 .map(|x| x.target_type())
642 .collect::<Option<Vec<_>>>()?;
643
644 Some(Type::Tuple(elements))
645 }
646}
647
648#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
649pub struct MapField {
650 pub key: DataExpr,
651 pub value: DataExpr,
652 pub span: Span,
653}
654
655impl MapField {
656 pub fn target_type(&self) -> Option<Type> {
657 self.key.target_type()
658 }
659}
660
661#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
662pub struct MapConstructor {
663 pub fields: Vec<MapField>,
664 pub span: Span,
665}
666
667impl MapConstructor {
668 pub fn target_type(&self) -> Option<Type> {
669 if let Some(first_field) = self.fields.first() {
670 let key_type = first_field.key.target_type()?;
671 let value_type = first_field.value.target_type()?;
672 Some(Type::Map(Box::new(key_type), Box::new(value_type)))
673 } else {
674 None
675 }
676 }
677}
678
679#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
680pub struct UtxoRef {
681 pub txid: Vec<u8>,
682 pub index: u64,
683 pub span: Span,
684}
685
686#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
687pub struct NegateOp {
688 pub operand: Box<DataExpr>,
689 pub span: Span,
690}
691
692impl NegateOp {
693 pub fn target_type(&self) -> Option<Type> {
694 self.operand.target_type()
695 }
696}
697
698#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
699pub struct PropertyOp {
700 pub operand: Box<DataExpr>,
701 pub property: Box<DataExpr>,
702 pub span: Span,
703
704 #[serde(skip)]
706 pub(crate) scope: Option<Rc<Scope>>,
707}
708
709impl PropertyOp {
710 pub fn target_type(&self) -> Option<Type> {
711 if let (Some(Type::Tuple(elements)), DataExpr::Number(index)) =
714 (self.operand.target_type(), self.property.as_ref())
715 {
716 return elements.get(*index as usize).cloned();
717 }
718
719 self.property.target_type()
720 }
721}
722
723#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
724pub struct AddOp {
725 pub lhs: Box<DataExpr>,
726 pub rhs: Box<DataExpr>,
727 pub span: Span,
728}
729
730impl AddOp {
731 pub fn target_type(&self) -> Option<Type> {
732 self.lhs.target_type()
733 }
734}
735
736#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
737pub struct SubOp {
738 pub lhs: Box<DataExpr>,
739 pub rhs: Box<DataExpr>,
740 pub span: Span,
741}
742
743impl SubOp {
744 pub fn target_type(&self) -> Option<Type> {
745 self.lhs.target_type()
746 }
747}
748
749#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
750pub struct MulOp {
751 pub lhs: Box<DataExpr>,
752 pub rhs: Box<DataExpr>,
753 pub span: Span,
754}
755
756impl MulOp {
757 pub fn target_type(&self) -> Option<Type> {
758 self.lhs.target_type()
759 }
760}
761
762#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
763pub struct DivOp {
764 pub lhs: Box<DataExpr>,
765 pub rhs: Box<DataExpr>,
766 pub span: Span,
767}
768
769impl DivOp {
770 pub fn target_type(&self) -> Option<Type> {
771 self.lhs.target_type()
772 }
773}
774
775#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
776pub struct ConcatOp {
777 pub lhs: Box<DataExpr>,
778 pub rhs: Box<DataExpr>,
779 pub span: Span,
780}
781
782impl ConcatOp {
783 pub fn target_type(&self) -> Option<Type> {
784 self.lhs.target_type()
785 }
786}
787
788#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
789pub struct FnCall {
790 pub callee: Identifier,
791 pub args: Vec<DataExpr>,
792 pub span: Span,
793}
794
795impl FnCall {
796 pub fn target_type(&self) -> Option<Type> {
799 let fn_def = self.callee.symbol.as_ref()?.as_fn_def()?;
800 Some(fn_def.return_type.clone())
801 }
802}
803
804#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
805pub enum DataExpr {
806 None,
807 Unit,
808 Number(i64),
809 Bool(bool),
810 String(StringLiteral),
811 HexString(HexStringLiteral),
812 StructConstructor(StructConstructor),
813 ListConstructor(ListConstructor),
814 MapConstructor(MapConstructor),
815 TupleConstructor(TupleConstructor),
816 AnyAssetConstructor(AnyAssetConstructor),
817 Identifier(Identifier),
818 AddOp(AddOp),
819 SubOp(SubOp),
820 MulOp(MulOp),
821 DivOp(DivOp),
822 ConcatOp(ConcatOp),
823 NegateOp(NegateOp),
824 PropertyOp(PropertyOp),
825 UtxoRef(UtxoRef),
826 FnCall(FnCall),
827}
828
829impl DataExpr {
830 pub fn as_identifier(&self) -> Option<&Identifier> {
831 match self {
832 DataExpr::Identifier(x) => Some(x),
833 _ => None,
834 }
835 }
836
837 pub fn target_type(&self) -> Option<Type> {
838 match self {
839 DataExpr::Identifier(x) => x.target_type(),
840 DataExpr::None => Some(Type::Undefined),
841 DataExpr::Unit => Some(Type::Unit),
842 DataExpr::Number(_) => Some(Type::Int),
843 DataExpr::Bool(_) => Some(Type::Bool),
844 DataExpr::String(_) => Some(Type::Bytes),
845 DataExpr::HexString(_) => Some(Type::Bytes),
846 DataExpr::StructConstructor(x) => x.target_type(),
847 DataExpr::MapConstructor(x) => x.target_type(),
848 DataExpr::ListConstructor(x) => match x.target_type() {
849 Some(inner) => Some(Type::List(Box::new(inner))),
850 None => None,
851 },
852 DataExpr::TupleConstructor(x) => x.target_type(),
853 DataExpr::AddOp(x) => x.target_type(),
854 DataExpr::SubOp(x) => x.target_type(),
855 DataExpr::MulOp(x) => x.target_type(),
856 DataExpr::DivOp(x) => x.target_type(),
857 DataExpr::ConcatOp(x) => x.target_type(),
858 DataExpr::NegateOp(x) => x.target_type(),
859 DataExpr::PropertyOp(x) => x.target_type(),
860 DataExpr::AnyAssetConstructor(x) => x.target_type(),
861 DataExpr::UtxoRef(_) => Some(Type::UtxoRef),
862 DataExpr::FnCall(x) => x.target_type(),
863 }
864 }
865}
866
867#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
868pub enum AddressExpr {
869 String(StringLiteral),
870 HexString(HexStringLiteral),
871 Identifier(Identifier),
872}
873
874impl AddressExpr {
875 pub fn as_identifier(&self) -> Option<&Identifier> {
876 match self {
877 AddressExpr::Identifier(x) => Some(x),
878 _ => None,
879 }
880 }
881}
882
883#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
884pub enum Type {
885 Undefined,
886 Unit,
887 Int,
888 Bool,
889 Bytes,
890 Address,
891 Utxo,
892 UtxoRef,
893 AnyAsset,
894 List(Box<Type>),
895 Map(Box<Type>, Box<Type>),
896 Tuple(Vec<Type>),
897 Custom(Identifier),
898}
899
900impl std::fmt::Display for Type {
901 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
902 match self {
903 Type::Undefined => write!(f, "Undefined"),
904 Type::Unit => write!(f, "Unit"),
905 Type::Int => write!(f, "Int"),
906 Type::Bool => write!(f, "Bool"),
907 Type::Bytes => write!(f, "Bytes"),
908 Type::Address => write!(f, "Address"),
909 Type::UtxoRef => write!(f, "UtxoRef"),
910 Type::AnyAsset => write!(f, "AnyAsset"),
911 Type::Utxo => write!(f, "Utxo"),
912 Type::Map(key, value) => write!(f, "Map<{}, {}>", key, value),
913 Type::List(inner) => write!(f, "List<{inner}>"),
914 Type::Tuple(elements) => {
915 let inner = elements
916 .iter()
917 .map(|t| t.to_string())
918 .collect::<Vec<_>>()
919 .join(", ");
920 write!(f, "Tuple<{inner}>")
921 }
922 Type::Custom(id) => write!(f, "{}", id.value),
923 }
924 }
925}
926
927impl Type {
928 pub fn properties(&self) -> Vec<(String, Type)> {
929 match self {
930 Type::AnyAsset => {
931 vec![
932 ("amount".to_string(), Type::Int),
933 ("policy".to_string(), Type::Bytes),
934 ("asset_name".to_string(), Type::Bytes),
935 ]
936 }
937 Type::UtxoRef => {
938 vec![
939 ("tx_hash".to_string(), Type::Bytes),
940 ("output_index".to_string(), Type::Int),
941 ]
942 }
943 Type::Custom(identifier) => {
944 let def = identifier.symbol.as_ref().and_then(|s| s.as_type_def());
945
946 match def {
947 Some(ty) if ty.cases.len() == 1 => ty.cases[0]
948 .fields
949 .iter()
950 .map(|f| (f.name.value.clone(), f.r#type.clone()))
951 .collect(),
952 _ => vec![],
953 }
954 }
955 _ => vec![],
956 }
957 }
958
959 pub fn property_index(&self, property: DataExpr) -> Option<DataExpr> {
960 match self {
961 Type::AnyAsset | Type::UtxoRef | Type::Custom(_) => {
962 let identifier = property.as_identifier()?;
963 let properties = Self::properties(self);
964 properties
965 .iter()
966 .position(|(name, _)| name == &identifier.value)
967 .map(|index| DataExpr::Number(index as i64))
968 }
969 Type::List(_) => property
970 .target_type()
971 .filter(|ty| *ty == Type::Int)
972 .map(|_| property),
973 Type::Tuple(elements) => match property {
976 DataExpr::Number(index) if (0..elements.len() as i64).contains(&index) => {
977 Some(DataExpr::Number(index))
978 }
979 _ => None,
980 },
981 _ => None,
982 }
983 }
984}
985
986#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
987pub struct ParamDef {
988 pub name: Identifier,
989 pub r#type: Type,
990 #[serde(default, skip_serializing_if = "Option::is_none")]
991 pub docstring: Option<String>,
992}
993
994#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
995pub struct AliasDef {
996 pub name: Identifier,
997 pub alias_type: Type,
998 pub span: Span,
999}
1000
1001impl AliasDef {
1002 pub fn resolve_alias_chain(&self) -> Option<&TypeDef> {
1003 match &self.alias_type {
1004 Type::Custom(identifier) => match &identifier.symbol {
1005 Some(Symbol::TypeDef(type_def)) => Some(type_def),
1006 Some(Symbol::AliasDef(next_alias)) => next_alias.resolve_alias_chain(),
1007 _ => None,
1008 },
1009 _ => None,
1010 }
1011 }
1012
1013 pub fn is_alias_chain_resolved(&self) -> bool {
1014 self.resolve_alias_chain().is_some()
1015 }
1016}
1017
1018#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1019pub struct TypeDef {
1020 pub name: Identifier,
1021 pub cases: Vec<VariantCase>,
1022 pub span: Span,
1023}
1024
1025impl TypeDef {
1026 pub(crate) fn find_case_index(&self, case: &str) -> Option<usize> {
1027 self.cases.iter().position(|x| x.name.value == case)
1028 }
1029
1030 #[allow(dead_code)]
1031 pub(crate) fn find_case(&self, case: &str) -> Option<&VariantCase> {
1032 self.cases.iter().find(|x| x.name.value == case)
1033 }
1034}
1035
1036#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1037pub struct VariantCase {
1038 pub name: Identifier,
1039 pub fields: Vec<RecordField>,
1040 pub span: Span,
1041}
1042
1043impl VariantCase {
1044 #[allow(dead_code)]
1045 pub(crate) fn find_field_index(&self, field: &str) -> Option<usize> {
1046 self.fields.iter().position(|x| x.name.value == field)
1047 }
1048
1049 #[allow(dead_code)]
1050 pub(crate) fn find_field(&self, field: &str) -> Option<&RecordField> {
1051 self.fields.iter().find(|x| x.name.value == field)
1052 }
1053}
1054
1055#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1056pub struct AssetDef {
1057 pub name: Identifier,
1058 pub policy: DataExpr,
1059 pub asset_name: DataExpr,
1060 pub span: Span,
1061}
1062
1063#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1064pub struct LetBinding {
1065 pub name: Identifier,
1066 pub value: DataExpr,
1067 pub span: Span,
1068}
1069
1070#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1071pub struct FnBody {
1072 pub let_bindings: Vec<LetBinding>,
1073 pub result: Box<DataExpr>,
1074 pub span: Span,
1075}
1076
1077#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
1081pub enum BuiltinFn {
1082 MinUtxo,
1083 TipSlot,
1084 SlotToTime,
1085 TimeToSlot,
1086}
1087
1088impl BuiltinFn {
1089 pub const ALL: [BuiltinFn; 4] = [
1093 BuiltinFn::MinUtxo,
1094 BuiltinFn::TipSlot,
1095 BuiltinFn::SlotToTime,
1096 BuiltinFn::TimeToSlot,
1097 ];
1098}
1099
1100#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1101pub struct FnDef {
1102 pub name: Identifier,
1103 pub parameters: ParameterList,
1104 pub return_type: Type,
1105 pub body: Option<FnBody>,
1108 #[serde(default, skip_serializing_if = "Option::is_none")]
1111 pub builtin: Option<BuiltinFn>,
1112 pub span: Span,
1113
1114 #[serde(skip)]
1116 pub(crate) scope: Option<Rc<Scope>>,
1117}
1118
1119#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1120pub enum ChainSpecificBlock {
1121 Cardano(crate::cardano::CardanoBlock),
1122}