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