Skip to content
Open
Show file tree
Hide file tree
Changes from 10 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
1 change: 1 addition & 0 deletions crates/tx3-cardano/src/compile/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ fn compile_data_expr(ir: &ir::Expression) -> Result<primitives::PlutusData, Erro
ir::Expression::String(x) => Ok(x.as_str().as_data()),
ir::Expression::Struct(x) => compile_struct(x),
ir::Expression::Address(x) => Ok(x.as_data()),
ir::Expression::Tuple(x) => Ok(x.try_as_data()?),
_ => Err(Error::CoerceError(
format!("{:?}", ir),
"DataExpr".to_string(),
Expand Down
11 changes: 11 additions & 0 deletions crates/tx3-cardano/src/compile/plutus_data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,16 @@ impl TryIntoData for Vec<ir::Expression> {
}
}

impl TryIntoData for (ir::Expression, ir::Expression) {
fn try_as_data(&self) -> Result<PlutusData, super::Error> {
let (fst, snd) = self;
Ok(PlutusData::Array(MaybeIndefArray::Def(vec![
fst.try_as_data()?,
snd.try_as_data()?,
])))
}
}

impl TryIntoData for ir::StructExpr {
fn try_as_data(&self) -> Result<PlutusData, super::Error> {
let fields = self
Expand Down Expand Up @@ -135,6 +145,7 @@ impl TryIntoData for ir::Expression {
ir::Expression::Address(x) => Ok(x.as_data()),
ir::Expression::Hash(x) => Ok(x.as_data()),
ir::Expression::List(x) => x.try_as_data(),
ir::Expression::Tuple(x) => x.try_as_data(),
x => Err(super::Error::CoerceError(
format!("{:?}", x),
"PlutusData".to_string(),
Expand Down
13 changes: 13 additions & 0 deletions crates/tx3-lang/src/analyzing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -534,11 +534,22 @@ impl Analyzable for ListConstructor {
}
}

impl Analyzable for TupleConstructor {
fn analyze(&mut self, parent: Option<Rc<Scope>>) -> AnalyzeReport {
self.fst.analyze(parent.clone()) + self.snd.analyze(parent.clone())
}

fn is_resolved(&self) -> bool {
self.fst.is_resolved() && self.snd.is_resolved()
}
}

impl Analyzable for DataExpr {
fn analyze(&mut self, parent: Option<Rc<Scope>>) -> AnalyzeReport {
match self {
DataExpr::StructConstructor(x) => x.analyze(parent),
DataExpr::ListConstructor(x) => x.analyze(parent),
DataExpr::TupleConstructor(x) => x.analyze(parent),
DataExpr::Identifier(x) => x.analyze(parent),
DataExpr::AddOp(x) => x.analyze(parent),
DataExpr::SubOp(x) => x.analyze(parent),
Expand Down Expand Up @@ -670,6 +681,7 @@ impl Analyzable for Type {
match self {
Type::Custom(x) => x.analyze(parent),
Type::List(x) => x.analyze(parent),
Type::Tuple(fst, snd) => fst.analyze(parent.clone()) + snd.analyze(parent),
_ => AnalyzeReport::default(),
}
}
Expand All @@ -678,6 +690,7 @@ impl Analyzable for Type {
match self {
Type::Custom(x) => x.is_resolved(),
Type::List(x) => x.is_resolved(),
Type::Tuple(fst, snd) => fst.is_resolved() && snd.is_resolved(),
_ => true,
}
}
Expand Down
2 changes: 1 addition & 1 deletion crates/tx3-lang/src/applying.rs
Original file line number Diff line number Diff line change
Expand Up @@ -521,7 +521,7 @@ impl Composite for ir::Coerce {
Self::NoOp(x) => Ok(Self::NoOp(x)),
Self::IntoAssets(x) => Ok(Self::NoOp(x.into_assets()?)),
Self::IntoDatum(x) => Ok(Self::NoOp(x.into_datum()?)),
Self::IntoScript(x) => todo!(),
Self::IntoScript(_x) => todo!(),
}
}
}
Expand Down
24 changes: 24 additions & 0 deletions crates/tx3-lang/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -558,6 +558,26 @@ impl AnyAssetConstructor {
}
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct TupleConstructor {
pub fst: Box<DataExpr>,
pub snd: Box<DataExpr>,
pub span: Span,
}

impl TupleConstructor {
pub fn target_type(&self) -> Option<Type> {
Some(Type::Tuple(
Box::new(self.fst.target_type()?),
Box::new(self.snd.target_type()?),
))
}

pub fn is_resolved(&self) -> bool {
self.fst.target_type().is_some() && self.snd.target_type().is_some()
}
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct RecordConstructorField {
pub name: Identifier,
Expand Down Expand Up @@ -687,6 +707,7 @@ pub enum DataExpr {
HexString(HexStringLiteral),
StructConstructor(StructConstructor),
ListConstructor(ListConstructor),
TupleConstructor(TupleConstructor),
StaticAssetConstructor(StaticAssetConstructor),
AnyAssetConstructor(AnyAssetConstructor),
Identifier(Identifier),
Expand Down Expand Up @@ -716,6 +737,7 @@ impl DataExpr {
DataExpr::HexString(_) => Some(Type::Bytes),
DataExpr::StructConstructor(x) => x.target_type(),
DataExpr::ListConstructor(x) => x.target_type(),
DataExpr::TupleConstructor(x) => x.target_type(),
DataExpr::AddOp(x) => x.target_type(),
DataExpr::SubOp(x) => x.target_type(),
DataExpr::NegateOp(x) => x.target_type(),
Expand Down Expand Up @@ -756,6 +778,7 @@ pub enum Type {
AnyAsset,
List(Box<Type>),
Custom(Identifier),
Tuple(Box<Type>, Box<Type>),
}

impl std::fmt::Display for Type {
Expand All @@ -772,6 +795,7 @@ impl std::fmt::Display for Type {
Type::Utxo => write!(f, "Utxo"),
Type::List(inner) => write!(f, "List<{}>", inner),
Type::Custom(id) => write!(f, "{}", id.value),
Type::Tuple(fst, snd) => write!(f, "({} {})", fst, snd),
}
}
}
Expand Down
1 change: 1 addition & 0 deletions crates/tx3-lang/src/ir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ pub enum Type {
AnyAsset,
List,
Custom(String),
Tuple,
Comment thread
Benja272 marked this conversation as resolved.
}

#[derive(Encode, Decode, Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
Expand Down
14 changes: 14 additions & 0 deletions crates/tx3-lang/src/lowering.rs
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,7 @@ impl IntoLower for ast::Type {
ast::Type::AnyAsset => Ok(ir::Type::AnyAsset),
ast::Type::List(_) => Ok(ir::Type::List),
ast::Type::Custom(x) => Ok(ir::Type::Custom(x.value.clone())),
ast::Type::Tuple(_, _) => Ok(ir::Type::Tuple),
}
}
}
Expand Down Expand Up @@ -410,6 +411,17 @@ impl IntoLower for ast::ListConstructor {
}
}

impl IntoLower for ast::TupleConstructor {
type Output = ir::Expression;

fn into_lower(&self, ctx: &Context) -> Result<Self::Output, Error> {
let fst = self.fst.into_lower(ctx)?;
let snd = self.snd.into_lower(ctx)?;

Ok(ir::Expression::Tuple(Box::new((fst, snd))))
Comment thread
Benja272 marked this conversation as resolved.
Outdated
}
}

impl IntoLower for ast::DataExpr {
type Output = ir::Expression;

Expand All @@ -422,6 +434,7 @@ impl IntoLower for ast::DataExpr {
ast::DataExpr::HexString(x) => ir::Expression::Bytes(hex_decode(&x.value)?),
ast::DataExpr::StructConstructor(x) => ir::Expression::Struct(x.into_lower(ctx)?),
ast::DataExpr::ListConstructor(x) => ir::Expression::List(x.into_lower(ctx)?),
ast::DataExpr::TupleConstructor(x) => x.into_lower(ctx)?,
ast::DataExpr::StaticAssetConstructor(x) => x.into_lower(ctx)?,
ast::DataExpr::AnyAssetConstructor(x) => x.into_lower(ctx)?,
ast::DataExpr::Unit => ir::Expression::Struct(ir::StructExpr::unit()),
Expand Down Expand Up @@ -872,4 +885,5 @@ mod tests {
test_lowering!(local_vars);

test_lowering!(cardano_witness);
test_lowering!(tuple);
}
41 changes: 41 additions & 0 deletions crates/tx3-lang/src/parsing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1039,6 +1039,28 @@ impl AstNode for ListConstructor {
}
}

impl AstNode for TupleConstructor {
const RULE: Rule = Rule::tuple_constructor;

fn parse(pair: Pair<Rule>) -> Result<Self, Error> {
let span = pair.as_span().into();
let mut inner = pair.into_inner();

let fst = DataExpr::parse(inner.next().unwrap())?;
let snd = DataExpr::parse(inner.next().unwrap())?;

Ok(TupleConstructor {
fst: Box::new(fst),
snd: Box::new(snd),
span,
})
}

fn span(&self) -> &Span {
&self.span
}
}

impl DataExpr {
fn number_parse(pair: Pair<Rule>) -> Result<Self, Error> {
Ok(DataExpr::Number(pair.as_str().parse().unwrap()))
Expand Down Expand Up @@ -1137,6 +1159,9 @@ impl AstNode for DataExpr {
Rule::hex_string => Ok(DataExpr::HexString(HexStringLiteral::parse(x)?)),
Rule::struct_constructor => DataExpr::struct_constructor_parse(x),
Rule::list_constructor => DataExpr::list_constructor_parse(x),
Rule::tuple_constructor => {
Ok(DataExpr::TupleConstructor(TupleConstructor::parse(x)?))
}
Rule::unit => Ok(DataExpr::Unit),
Rule::identifier => DataExpr::identifier_parse(x),
Rule::utxo_ref => DataExpr::utxo_ref_parse(x),
Expand Down Expand Up @@ -1171,6 +1196,7 @@ impl AstNode for DataExpr {
DataExpr::HexString(x) => x.span(),
DataExpr::StructConstructor(x) => x.span(),
DataExpr::ListConstructor(x) => x.span(),
DataExpr::TupleConstructor(x) => x.span(),
DataExpr::StaticAssetConstructor(x) => x.span(),
DataExpr::AnyAssetConstructor(x) => x.span(),
DataExpr::Identifier(x) => x.span(),
Expand Down Expand Up @@ -1203,6 +1229,12 @@ impl AstNode for Type {
let inner = inner.into_inner().next().unwrap();
Ok(Type::List(Box::new(Type::parse(inner)?)))
}
Rule::tuple_type => {
let mut inner = inner.into_inner();
let fst = Type::parse(inner.next().unwrap())?;
let snd = Type::parse(inner.next().unwrap())?;
Ok(Type::Tuple(Box::new(fst), Box::new(snd)))
}
Rule::custom_type => Ok(Type::Custom(Identifier::new(inner.as_str().to_owned()))),
x => unreachable!("Unexpected rule in type: {:?}", x),
}
Expand Down Expand Up @@ -1444,6 +1476,13 @@ mod tests {

input_to_ast_check!(Type, "list", "List<Int>", Type::List(Box::new(Type::Int)));

input_to_ast_check!(
Type,
"tuple",
"Tuple<Int, Bytes>",
Type::Tuple(Box::new(Type::Int), Box::new(Type::Bytes))
);

input_to_ast_check!(
Type,
"identifier",
Expand Down Expand Up @@ -2327,4 +2366,6 @@ mod tests {
test_parsing!(local_vars);

test_parsing!(cardano_witness);

test_parsing!(tuple);
}
7 changes: 7 additions & 0 deletions crates/tx3-lang/src/tx3.pest
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,12 @@ primitive_type = {

custom_type = { identifier }
list_type = { "List<" ~ type ~ ">" }
tuple_type = { "Tuple<" ~ type ~ "," ~ type ~ ">"}

type = {
primitive_type |
list_type |
tuple_type |
custom_type
}

Expand Down Expand Up @@ -141,6 +143,7 @@ data_expr = { data_prefix* ~ data_primary ~ data_postfix* ~ (data_infix ~ data_p
string |
struct_constructor |
list_constructor |
tuple_constructor |
any_asset_constructor |
static_asset_constructor |
identifier |
Expand Down Expand Up @@ -180,6 +183,10 @@ list_constructor = {
"[" ~ (data_expr ~ ",")* ~ data_expr? ~ "]"
}

tuple_constructor = {
"(" ~ data_expr ~ "," ~ data_expr ~ ")"
}

// input block

input_block_from = { "from" ~ ":" ~ data_expr }
Expand Down
Loading