Skip to content
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 24 additions & 10 deletions crates/tx3-cardano/src/compile/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -288,24 +288,38 @@ fn compile_outputs(
tx: &tir::Tx,
network: Network,
) -> Result<Vec<primitives::TransactionOutput<'static>>, Error> {
let mut resolved: Vec<_> = tx
.outputs
.iter()
.map(|out| (out.optional, compile_output_block(out, network)))
.filter(|(optional, output)| !optional || output_has_assets(output))
.map(|(_, output)| output)
.collect::<Result<Vec<_>, _>>()?;
let outputs = tx.outputs.iter().filter_map(|out| {
let compiled = compile_output_block(out, network);

if out.optional && !output_has_assets(&compiled) {
return None;
}

let idx = out.declared_index.as_number().map(|n| n as usize);
Some(compiled.map(|o| (idx, o)))
});

let cardano_outputs = tx
.adhoc
.iter()
.filter(|x| x.name.as_str() == "cardano_publish")
.map(|adhoc| compile_cardano_publish_directive(adhoc, network))
.map(|adhoc| {
let idx = adhoc
.data
.get("declared_index")
.and_then(|expr| expr.as_number())
.map(|n| n as usize);

compile_cardano_publish_directive(adhoc, network).map(|o| (idx, o))
});

let mut all_outputs: Vec<_> = outputs
.chain(cardano_outputs)
.collect::<Result<Vec<_>, _>>()?;

resolved.extend(cardano_outputs);
all_outputs.sort_by_key(|(idx, _)| idx.unwrap_or(usize::MAX));

Ok(resolved)
Ok(all_outputs.into_iter().map(|(_, out)| out).collect())
}

pub fn compile_cardano_publish_directive(
Expand Down
1 change: 1 addition & 0 deletions crates/tx3-lang/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,7 @@ pub struct OutputBlock {
pub optional: bool,
pub fields: Vec<OutputBlockField>,
pub span: Span,
pub declared_index: Option<usize>,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why declared_index instead of index?
is there a conflicting index which is not declared?

if not, rename it to just index

}

impl OutputBlock {
Expand Down
21 changes: 19 additions & 2 deletions crates/tx3-lang/src/cardano.rs
Original file line number Diff line number Diff line change
Expand Up @@ -586,6 +586,7 @@ pub struct CardanoPublishBlock {
pub name: Option<Identifier>,
pub fields: Vec<CardanoPublishBlockField>,
pub span: Span,
pub declared_index: Option<usize>,
}

impl CardanoPublishBlock {
Expand Down Expand Up @@ -663,7 +664,12 @@ impl AstNode for CardanoPublishBlock {
.map(|x| CardanoPublishBlockField::parse(x))
.collect::<Result<Vec<_>, _>>()?;

Ok(CardanoPublishBlock { name, fields, span })
Ok(CardanoPublishBlock {
name,
fields,
span,
declared_index: None,
})
}

fn span(&self) -> &Span {
Expand Down Expand Up @@ -727,12 +733,21 @@ impl IntoLower for CardanoPublishBlock {
&self,
ctx: &crate::lowering::Context,
) -> Result<Self::Output, crate::lowering::Error> {
let data = self
let mut data: HashMap<String, ir::Expression> = self
.fields
.iter()
.map(|x| x.into_lower(ctx))
.collect::<Result<_, _>>()?;

data.insert(
"declared_index".to_string(),
ir::Expression::Number(
self.declared_index
.map(|x| x as i128)
.expect("Publish block must have a declaration index"),
),
);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The lowering phase should not be used for enforcing invariants.

If the user should be aware of the rule, then the analyze phase should check the rule.

The assertion of the rule should be applied when needed. In this case, the compiler should be then one erroring when the value is missing.

Ok(ir::AdHocDirective {
name: "cardano_publish".to_string(),
data,
Expand Down Expand Up @@ -938,6 +953,7 @@ mod tests {
))),
],
span: Span::DUMMY,
declared_index: None,
}
);

Expand Down Expand Up @@ -967,6 +983,7 @@ mod tests {
))),
],
span: Span::DUMMY,
declared_index: None,
}
);

Expand Down
2 changes: 2 additions & 0 deletions crates/tx3-lang/src/lowering.rs
Original file line number Diff line number Diff line change
Expand Up @@ -697,12 +697,14 @@ impl IntoLower for ast::OutputBlock {
let address = self.find("to").into_lower(ctx)?.unwrap_or_default();
let datum = self.find("datum").into_lower(ctx)?.unwrap_or_default();
let amount = self.find("amount").into_lower(ctx)?.unwrap_or_default();
let declared_ix = self.declared_index.unwrap();

Ok(ir::Output {
address,
datum,
amount,
optional: self.optional,
declared_index: ir::Expression::Number(declared_ix as i128),
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we use an explicit expression type?
Why can't we rely on the into_lower method as we do with the rest of the fields?

})
}
}
Expand Down
22 changes: 20 additions & 2 deletions crates/tx3-lang/src/parsing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -208,16 +208,32 @@ impl AstNode for TxDef {
let mut signers = None;
let mut metadata = None;

let mut declared_index: usize = 0;

for item in inner {
match item.as_rule() {
Rule::locals_block => locals = Some(LocalsBlock::parse(item)?),
Rule::reference_block => references.push(ReferenceBlock::parse(item)?),
Rule::input_block => inputs.push(InputBlock::parse(item)?),
Rule::output_block => outputs.push(OutputBlock::parse(item)?),
Rule::output_block => {
let mut ob = OutputBlock::parse(item)?;
ob.declared_index = Some(declared_index);
declared_index += 1;
outputs.push(ob);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this shouldn't be here. We're coupling the rules of a specifc type of AST in the parsing logic of a totally unrelated block.

On top of that, the AST is not in charge of defining the indexes of the outputs. The AST describes the intent of the user that typed the code. The index expression should remain as an optional expression all the way down until the compiler is forced to add a value.

}
Rule::validity_block => validity = Some(ValidityBlock::parse(item)?),
Rule::mint_block => mints.push(MintBlock::parse(item)?),
Rule::burn_block => burns.push(MintBlock::parse(item)?),
Rule::chain_specific_block => adhoc.push(ChainSpecificBlock::parse(item)?),
Rule::chain_specific_block => {
let mut csb = ChainSpecificBlock::parse(item)?;
let ChainSpecificBlock::Cardano(cardano_block) = &mut csb;
if let crate::cardano::CardanoBlock::Publish(pb) = cardano_block {
pb.declared_index = Some(declared_index);
declared_index += 1;
}

adhoc.push(csb);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as previous comment.

}
Rule::collateral_block => collateral.push(CollateralBlock::parse(item)?),
Rule::signers_block => signers = Some(SignersBlock::parse(item)?),
Rule::metadata_block => metadata = Some(MetadataBlock::parse(item)?),
Expand Down Expand Up @@ -617,6 +633,7 @@ impl AstNode for OutputBlock {
optional,
fields,
span,
declared_index: None,
})
}

Expand Down Expand Up @@ -2464,6 +2481,7 @@ mod tests {
}))),
],
span: Span::DUMMY,
declared_index: None,
}
);

Expand Down
3 changes: 3 additions & 0 deletions crates/tx3-tir/src/model/v1beta0.rs
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,8 @@ pub struct Output {
pub datum: Expression,
pub amount: Expression,
pub optional: bool,
#[serde(default)]
pub declared_index: Expression,
}

#[derive(Serialize, Deserialize, Debug, Clone)]
Expand Down Expand Up @@ -522,6 +524,7 @@ impl Node for Output {
datum: self.datum.apply(visitor)?,
amount: self.amount.apply(visitor)?,
optional: self.optional,
declared_index: self.declared_index,
};

Ok(visited)
Expand Down
1 change: 1 addition & 0 deletions crates/tx3-tir/src/reduce/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1159,6 +1159,7 @@ impl Composite for Output {
datum: f(self.datum)?,
amount: f(self.amount)?,
optional: self.optional,
declared_index: self.declared_index,
})
}
}
Expand Down
6 changes: 4 additions & 2 deletions examples/asteria.ast
Original file line number Diff line number Diff line change
Expand Up @@ -597,7 +597,8 @@
"dummy": false,
"start": 1158,
"end": 1379
}
},
"declared_index": 0
},
{
"name": null,
Expand Down Expand Up @@ -651,7 +652,8 @@
"dummy": false,
"start": 1385,
"end": 1449
}
},
"declared_index": 1
}
],
"validity": null,
Expand Down
10 changes: 8 additions & 2 deletions examples/asteria.move_ship.tir
Original file line number Diff line number Diff line change
Expand Up @@ -1168,7 +1168,10 @@
]
}
},
"optional": false
"optional": false,
"declared_index": {
"Number": 0
}
},
{
"address": {
Expand Down Expand Up @@ -1262,7 +1265,10 @@
]
}
},
"optional": false
"optional": false,
"declared_index": {
"Number": 1
}
}
],
"validity": null,
Expand Down
9 changes: 6 additions & 3 deletions examples/buidler_fest_2026.ast
Original file line number Diff line number Diff line change
Expand Up @@ -537,7 +537,8 @@
"dummy": false,
"start": 958,
"end": 1063
}
},
"declared_index": 0
},
{
"name": {
Expand Down Expand Up @@ -672,7 +673,8 @@
"dummy": false,
"start": 1069,
"end": 1246
}
},
"declared_index": 1
},
{
"name": {
Expand Down Expand Up @@ -733,7 +735,8 @@
"dummy": false,
"start": 1252,
"end": 1331
}
},
"declared_index": 2
}
],
"validity": {
Expand Down
15 changes: 12 additions & 3 deletions examples/buidler_fest_2026.buy_ticket.tir
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,10 @@
]
}
},
"optional": false
"optional": false,
"declared_index": {
"Number": 0
}
},
{
"address": {
Expand Down Expand Up @@ -458,7 +461,10 @@
}
}
},
"optional": false
"optional": false,
"declared_index": {
"Number": 1
}
},
{
"address": {
Expand Down Expand Up @@ -486,7 +492,10 @@
}
]
},
"optional": false
"optional": false,
"declared_index": {
"Number": 2
}
}
],
"validity": {
Expand Down
3 changes: 2 additions & 1 deletion examples/burn.ast
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,8 @@
"dummy": false,
"start": 337,
"end": 412
}
},
"declared_index": 0
}
],
"validity": null,
Expand Down
5 changes: 4 additions & 1 deletion examples/burn.burn_stuff.tir
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,10 @@
]
}
},
"optional": false
"optional": false,
"declared_index": {
"Number": 0
}
}
],
"validity": null,
Expand Down
6 changes: 4 additions & 2 deletions examples/cardano_witness.ast
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,8 @@
"dummy": false,
"start": 404,
"end": 481
}
},
"declared_index": 0
}
],
"validity": null,
Expand Down Expand Up @@ -525,7 +526,8 @@
"dummy": false,
"start": 972,
"end": 1049
}
},
"declared_index": 0
}
],
"validity": null,
Expand Down
5 changes: 4 additions & 1 deletion examples/cardano_witness.mint_from_native_script.tir
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,10 @@
]
}
},
"optional": false
"optional": false,
"declared_index": {
"Number": 0
}
}
],
"validity": null,
Expand Down
5 changes: 4 additions & 1 deletion examples/cardano_witness.mint_from_plutus.tir
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,10 @@
]
}
},
"optional": false
"optional": false,
"declared_index": {
"Number": 0
}
}
],
"validity": null,
Expand Down
Loading