tx3_lang/
ir.rs

1//! The Tx3 language intermediate representation (IR).
2//!
3//! This module defines the intermediate representation (IR) for the Tx3
4//! language. It provides the structure for representing Tx3 programs in a more
5//! abstract form, suitable for further processing or execution.
6//!
7//! This module is not intended to be used directly by end-users. See
8//! [`lower`](crate::lower) for lowering an AST to the intermediate
9//! representation.
10
11use std::collections::{HashMap, HashSet};
12
13use serde::{Deserialize, Serialize};
14
15use crate::{Utxo, UtxoRef};
16
17#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
18pub struct StructExpr {
19    pub constructor: usize,
20    pub fields: Vec<Expression>,
21}
22
23impl StructExpr {
24    pub fn unit() -> Self {
25        Self {
26            constructor: 0,
27            fields: vec![],
28        }
29    }
30}
31
32#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
33pub enum BinaryOpKind {
34    Add,
35    Sub,
36}
37
38#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
39pub struct BinaryOp {
40    pub left: Expression,
41    pub right: Expression,
42    pub op: BinaryOpKind,
43}
44
45#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
46pub struct AssetExpr {
47    pub policy: Expression,
48    pub asset_name: Expression,
49    pub amount: Expression,
50}
51
52/// An ad-hoc compile directive.
53///
54/// It's a generic, pass-through structure that the final chain-specific
55/// compiler can use to compile custom structures. Tx3 won't attempt to process
56/// this IR structure for anything other than trying to apply / reduce its
57/// expressions.
58#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
59pub struct AdHocDirective {
60    pub name: String,
61    pub data: HashMap<String, Expression>,
62}
63
64#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
65pub enum ScriptSource {
66    Embedded(Expression),
67    UtxoRef {
68        r#ref: Expression,
69        source: Option<Expression>,
70    },
71}
72
73impl ScriptSource {
74    pub fn as_utxo_ref(&self) -> Option<Expression> {
75        match self {
76            Self::UtxoRef { r#ref, .. } => Some(r#ref.clone()),
77            Self::Embedded(Expression::UtxoRefs(x)) => Some(Expression::UtxoRefs(x.clone())),
78            _ => None,
79        }
80    }
81}
82
83#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
84pub struct PolicyExpr {
85    pub name: String,
86    pub hash: Expression,
87    pub script: Option<ScriptSource>,
88}
89
90#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
91pub enum Type {
92    Undefined,
93    Unit,
94    Int,
95    Bool,
96    Bytes,
97    Address,
98    UtxoRef,
99    AnyAsset,
100    Custom(String),
101}
102
103#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
104pub struct PropertyAccess {
105    pub object: Box<Expression>,
106    pub field: String,
107}
108
109#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
110pub enum Expression {
111    None,
112    Struct(StructExpr),
113    Bytes(Vec<u8>),
114    Number(i128),
115    Bool(bool),
116    String(String),
117    Address(Vec<u8>),
118    Hash(Vec<u8>),
119    UtxoRefs(Vec<UtxoRef>),
120    UtxoSet(HashSet<Utxo>),
121    Assets(Vec<AssetExpr>),
122
123    EvalParameter(String, Type),
124    EvalProperty(Box<PropertyAccess>),
125    EvalInputDatum(String),
126    EvalInputAssets(String),
127    EvalCustom(Box<BinaryOp>),
128
129    // queries
130    FeeQuery,
131
132    // pass-through
133    AdHocDirective(Box<AdHocDirective>),
134}
135
136impl Expression {
137    pub fn is_none(&self) -> bool {
138        matches!(self, Self::None)
139    }
140}
141
142#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Default)]
143pub struct InputQuery {
144    pub address: Option<Expression>,
145    pub min_amount: Option<Expression>,
146    pub r#ref: Option<Expression>,
147}
148
149#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
150pub struct Input {
151    pub name: String,
152    pub query: Option<InputQuery>,
153    pub refs: HashSet<UtxoRef>,
154    pub redeemer: Option<Expression>,
155    pub policy: Option<PolicyExpr>,
156}
157
158#[derive(Serialize, Deserialize, Debug, Clone)]
159pub struct Output {
160    pub address: Option<Expression>,
161    pub datum: Option<Expression>,
162    pub amount: Option<Expression>,
163}
164
165#[derive(Serialize, Deserialize, Debug, Clone)]
166pub struct Mint {
167    pub amount: Option<Expression>,
168    pub redeemer: Option<Expression>,
169}
170
171#[derive(Serialize, Deserialize, Debug, Clone)]
172pub struct Collateral {
173    pub query: InputQuery,
174}
175
176#[derive(Serialize, Deserialize, Debug, Clone)]
177pub struct Tx {
178    pub fees: Expression,
179    pub references: Vec<Expression>,
180    pub inputs: Vec<Input>,
181    pub outputs: Vec<Output>,
182    pub mint: Option<Mint>,
183    pub adhoc: Vec<AdHocDirective>,
184    pub collateral: Vec<Collateral>,
185}