feat: add map support and tuple deconstruction in let
This commit is contained in:
parent
26d2a95618
commit
80a9b7b36a
|
@ -219,6 +219,12 @@ pub enum Air {
|
||||||
scope: Vec<u64>,
|
scope: Vec<u64>,
|
||||||
value: Box<Self>,
|
value: Box<Self>,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
TupleAccessor {
|
||||||
|
scope: Vec<u64>,
|
||||||
|
names: Vec<String>,
|
||||||
|
tipo: Arc<Type>,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Air {
|
impl Air {
|
||||||
|
@ -255,7 +261,8 @@ impl Air {
|
||||||
| Air::Todo { scope, .. }
|
| Air::Todo { scope, .. }
|
||||||
| Air::Record { scope, .. }
|
| Air::Record { scope, .. }
|
||||||
| Air::RecordUpdate { scope, .. }
|
| Air::RecordUpdate { scope, .. }
|
||||||
| Air::Negate { scope, .. } => scope.to_vec(),
|
| Air::Negate { scope, .. }
|
||||||
|
| Air::TupleAccessor { scope, .. } => scope.to_vec(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -142,6 +142,8 @@ impl Type {
|
||||||
} if "List" == name && module.is_empty() => {
|
} if "List" == name && module.is_empty() => {
|
||||||
if let Type::Tuple { elems } = &*args[0] {
|
if let Type::Tuple { elems } = &*args[0] {
|
||||||
elems.len() == 2
|
elems.len() == 2
|
||||||
|
} else if let Type::Var { tipo } = &*args[0] {
|
||||||
|
matches!(tipo.borrow().get_uplc_type(), UplcType::Pair(_, _))
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
@ -385,6 +387,13 @@ impl TypeVar {
|
||||||
_ => vec![],
|
_ => vec![],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_uplc_type(&self) -> UplcType {
|
||||||
|
match self {
|
||||||
|
Self::Link { tipo } => tipo.get_uplc_type(),
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
|
|
@ -1112,7 +1112,9 @@ impl<'a> CodeGenerator<'a> {
|
||||||
Pattern::Constructor { .. } => {
|
Pattern::Constructor { .. } => {
|
||||||
self.pattern_ir(pattern, pattern_vec, value_vec, tipo, scope);
|
self.pattern_ir(pattern, pattern_vec, value_vec, tipo, scope);
|
||||||
}
|
}
|
||||||
Pattern::Tuple { .. } => todo!(),
|
Pattern::Tuple { .. } => {
|
||||||
|
self.pattern_ir(pattern, pattern_vec, value_vec, tipo, scope);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1368,7 +1370,55 @@ impl<'a> CodeGenerator<'a> {
|
||||||
pattern_vec.append(values);
|
pattern_vec.append(values);
|
||||||
pattern_vec.append(&mut nested_pattern);
|
pattern_vec.append(&mut nested_pattern);
|
||||||
}
|
}
|
||||||
Pattern::Tuple { .. } => todo!(),
|
Pattern::Tuple { elems, .. } => {
|
||||||
|
let mut elements_vec = vec![];
|
||||||
|
|
||||||
|
let mut names = vec![];
|
||||||
|
for element in elems {
|
||||||
|
match element {
|
||||||
|
Pattern::Var { name, .. } => {
|
||||||
|
names.push(name.clone());
|
||||||
|
}
|
||||||
|
a @ Pattern::List { .. } => {
|
||||||
|
let mut var_vec = vec![];
|
||||||
|
let item_name = format!("list_item_id_{}", self.id_gen.next());
|
||||||
|
names.push(item_name.clone());
|
||||||
|
var_vec.push(Air::Var {
|
||||||
|
constructor: ValueConstructor::public(
|
||||||
|
Type::App {
|
||||||
|
public: true,
|
||||||
|
module: String::new(),
|
||||||
|
name: String::new(),
|
||||||
|
args: vec![],
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
ValueConstructorVariant::LocalVariable {
|
||||||
|
location: Span::empty(),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
name: item_name,
|
||||||
|
scope: scope.clone(),
|
||||||
|
});
|
||||||
|
self.pattern_ir(
|
||||||
|
a,
|
||||||
|
&mut elements_vec,
|
||||||
|
&mut var_vec,
|
||||||
|
&tipo.get_inner_type()[0],
|
||||||
|
scope.clone(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
_ => todo!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pattern_vec.push(Air::TupleAccessor {
|
||||||
|
names,
|
||||||
|
scope,
|
||||||
|
tipo: tipo.clone().into(),
|
||||||
|
});
|
||||||
|
|
||||||
|
pattern_vec.append(values);
|
||||||
|
pattern_vec.append(&mut elements_vec);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1556,27 +1606,69 @@ impl<'a> CodeGenerator<'a> {
|
||||||
let list_type = tipo.get_inner_type()[0].clone();
|
let list_type = tipo.get_inner_type()[0].clone();
|
||||||
|
|
||||||
if constants.len() == args.len() && !tail {
|
if constants.len() == args.len() && !tail {
|
||||||
let list = Term::Constant(UplcConstant::ProtoList(
|
let list = if tipo.is_map() {
|
||||||
|
let mut convert_keys = vec![];
|
||||||
|
let mut convert_values = vec![];
|
||||||
|
for constant in constants {
|
||||||
|
match constant {
|
||||||
|
UplcConstant::ProtoPair(_, _, fst, snd) => {
|
||||||
|
convert_keys.push(*fst);
|
||||||
|
convert_values.push(*snd);
|
||||||
|
}
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
convert_keys = convert_constants_to_data(convert_keys);
|
||||||
|
convert_values = convert_constants_to_data(convert_values);
|
||||||
|
|
||||||
|
Term::Constant(UplcConstant::ProtoList(
|
||||||
|
UplcType::Pair(UplcType::Data.into(), UplcType::Data.into()),
|
||||||
|
convert_keys
|
||||||
|
.into_iter()
|
||||||
|
.zip(convert_values.into_iter())
|
||||||
|
.map(|(key, value)| {
|
||||||
|
UplcConstant::ProtoPair(
|
||||||
|
UplcType::Data,
|
||||||
|
UplcType::Data,
|
||||||
|
key.into(),
|
||||||
|
value.into(),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect_vec(),
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
Term::Constant(UplcConstant::ProtoList(
|
||||||
UplcType::Data,
|
UplcType::Data,
|
||||||
convert_constants_to_data(constants),
|
convert_constants_to_data(constants),
|
||||||
));
|
))
|
||||||
|
};
|
||||||
|
|
||||||
arg_stack.push(list);
|
arg_stack.push(list);
|
||||||
} else {
|
} else {
|
||||||
let mut term = if tail {
|
let mut term = if tail {
|
||||||
arg_stack.pop().unwrap()
|
arg_stack.pop().unwrap()
|
||||||
|
} else if tipo.is_map() {
|
||||||
|
Term::Constant(UplcConstant::ProtoList(
|
||||||
|
UplcType::Pair(UplcType::Data.into(), UplcType::Data.into()),
|
||||||
|
vec![],
|
||||||
|
))
|
||||||
} else {
|
} else {
|
||||||
Term::Constant(UplcConstant::ProtoList(UplcType::Data, vec![]))
|
Term::Constant(UplcConstant::ProtoList(UplcType::Data, vec![]))
|
||||||
};
|
};
|
||||||
|
|
||||||
for arg in args {
|
for arg in args {
|
||||||
|
let list_item = if tipo.is_map() {
|
||||||
|
arg
|
||||||
|
} else {
|
||||||
|
convert_type_to_data(arg, &list_type)
|
||||||
|
};
|
||||||
term = Term::Apply {
|
term = Term::Apply {
|
||||||
function: Term::Apply {
|
function: Term::Apply {
|
||||||
function: Term::Force(
|
function: Term::Force(
|
||||||
Term::Builtin(DefaultFunction::MkCons).force_wrap().into(),
|
Term::Builtin(DefaultFunction::MkCons).force_wrap().into(),
|
||||||
)
|
)
|
||||||
.into(),
|
.into(),
|
||||||
argument: convert_type_to_data(arg, &list_type).into(),
|
argument: list_item.into(),
|
||||||
}
|
}
|
||||||
.into(),
|
.into(),
|
||||||
argument: term.into(),
|
argument: term.into(),
|
||||||
|
@ -1600,7 +1692,40 @@ impl<'a> CodeGenerator<'a> {
|
||||||
let current_index = 0;
|
let current_index = 0;
|
||||||
let (first_name, names) = names.split_first().unwrap();
|
let (first_name, names) = names.split_first().unwrap();
|
||||||
|
|
||||||
|
let list_id = self.id_gen.next();
|
||||||
|
|
||||||
|
let head_list = if tipo.is_map() {
|
||||||
|
Term::Apply {
|
||||||
|
function: Term::Force(Term::Builtin(DefaultFunction::HeadList).into())
|
||||||
|
.into(),
|
||||||
|
argument: Term::Var(Name {
|
||||||
|
text: format!("__list_{}", list_id),
|
||||||
|
unique: 0.into(),
|
||||||
|
})
|
||||||
|
.into(),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
convert_data_to_type(
|
||||||
|
Term::Apply {
|
||||||
|
function: Term::Force(Term::Builtin(DefaultFunction::HeadList).into())
|
||||||
|
.into(),
|
||||||
|
argument: Term::Var(Name {
|
||||||
|
text: format!("__list_{}", list_id),
|
||||||
|
unique: 0.into(),
|
||||||
|
})
|
||||||
|
.into(),
|
||||||
|
},
|
||||||
|
&tipo.get_inner_type()[0],
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
term = Term::Apply {
|
term = Term::Apply {
|
||||||
|
function: Term::Lambda {
|
||||||
|
parameter_name: Name {
|
||||||
|
text: format!("__list_{}", list_id),
|
||||||
|
unique: 0.into(),
|
||||||
|
},
|
||||||
|
body: Term::Apply {
|
||||||
function: Term::Lambda {
|
function: Term::Lambda {
|
||||||
parameter_name: Name {
|
parameter_name: Name {
|
||||||
text: first_name.clone(),
|
text: first_name.clone(),
|
||||||
|
@ -1613,7 +1738,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
tail,
|
tail,
|
||||||
current_index,
|
current_index,
|
||||||
term,
|
term,
|
||||||
&tipo.get_inner_type()[0],
|
&tipo,
|
||||||
)
|
)
|
||||||
.into(),
|
.into(),
|
||||||
argument: Term::Apply {
|
argument: Term::Apply {
|
||||||
|
@ -1621,22 +1746,23 @@ impl<'a> CodeGenerator<'a> {
|
||||||
Term::Builtin(DefaultFunction::TailList).into(),
|
Term::Builtin(DefaultFunction::TailList).into(),
|
||||||
)
|
)
|
||||||
.into(),
|
.into(),
|
||||||
argument: value.clone().into(),
|
argument: Term::Var(Name {
|
||||||
|
text: format!("__list_{}", list_id),
|
||||||
|
unique: 0.into(),
|
||||||
|
})
|
||||||
|
.into(),
|
||||||
}
|
}
|
||||||
.into(),
|
.into(),
|
||||||
}
|
}
|
||||||
.into(),
|
.into(),
|
||||||
}
|
}
|
||||||
.into(),
|
.into(),
|
||||||
argument: convert_data_to_type(
|
argument: head_list.into(),
|
||||||
Term::Apply {
|
}
|
||||||
function: Term::Force(Term::Builtin(DefaultFunction::HeadList).into())
|
.into(),
|
||||||
|
}
|
||||||
.into(),
|
.into(),
|
||||||
argument: value.into(),
|
argument: value.into(),
|
||||||
},
|
|
||||||
&tipo.get_inner_type()[0],
|
|
||||||
)
|
|
||||||
.into(),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
arg_stack.push(term);
|
arg_stack.push(term);
|
||||||
|
@ -1649,8 +1775,6 @@ impl<'a> CodeGenerator<'a> {
|
||||||
} => {
|
} => {
|
||||||
let mut term = arg_stack.pop().unwrap();
|
let mut term = arg_stack.pop().unwrap();
|
||||||
|
|
||||||
let list_type = tipo.get_inner_type()[0].clone();
|
|
||||||
|
|
||||||
if let Some((tail_var, tail_name)) = tail {
|
if let Some((tail_var, tail_name)) = tail {
|
||||||
term = Term::Apply {
|
term = Term::Apply {
|
||||||
function: Term::Lambda {
|
function: Term::Lambda {
|
||||||
|
@ -1672,7 +1796,34 @@ impl<'a> CodeGenerator<'a> {
|
||||||
.into(),
|
.into(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
for (tail_var, head_name) in tail_head_names.into_iter().rev() {
|
for (tail_var, head_name) in tail_head_names.into_iter().rev() {
|
||||||
|
let head_list = if tipo.is_map() {
|
||||||
|
Term::Apply {
|
||||||
|
function: Term::Force(Term::Builtin(DefaultFunction::HeadList).into())
|
||||||
|
.into(),
|
||||||
|
argument: Term::Var(Name {
|
||||||
|
text: tail_var,
|
||||||
|
unique: 0.into(),
|
||||||
|
})
|
||||||
|
.into(),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
convert_data_to_type(
|
||||||
|
Term::Apply {
|
||||||
|
function: Term::Force(
|
||||||
|
Term::Builtin(DefaultFunction::HeadList).into(),
|
||||||
|
)
|
||||||
|
.into(),
|
||||||
|
argument: Term::Var(Name {
|
||||||
|
text: tail_var,
|
||||||
|
unique: 0.into(),
|
||||||
|
})
|
||||||
|
.into(),
|
||||||
|
},
|
||||||
|
&tipo.get_inner_type()[0],
|
||||||
|
)
|
||||||
|
};
|
||||||
term = Term::Apply {
|
term = Term::Apply {
|
||||||
function: Term::Lambda {
|
function: Term::Lambda {
|
||||||
parameter_name: Name {
|
parameter_name: Name {
|
||||||
|
@ -1682,20 +1833,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
body: term.into(),
|
body: term.into(),
|
||||||
}
|
}
|
||||||
.into(),
|
.into(),
|
||||||
argument: convert_data_to_type(
|
argument: head_list.into(),
|
||||||
Term::Apply {
|
|
||||||
function: Term::Builtin(DefaultFunction::HeadList)
|
|
||||||
.force_wrap()
|
|
||||||
.into(),
|
|
||||||
argument: Term::Var(Name {
|
|
||||||
text: tail_var,
|
|
||||||
unique: 0.into(),
|
|
||||||
})
|
|
||||||
.into(),
|
|
||||||
},
|
|
||||||
&list_type,
|
|
||||||
)
|
|
||||||
.into(),
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1729,19 +1867,14 @@ impl<'a> CodeGenerator<'a> {
|
||||||
let left = arg_stack.pop().unwrap();
|
let left = arg_stack.pop().unwrap();
|
||||||
let right = arg_stack.pop().unwrap();
|
let right = arg_stack.pop().unwrap();
|
||||||
|
|
||||||
let default_builtin = match tipo.deref() {
|
let default_builtin = if tipo.is_int() {
|
||||||
Type::App { name, .. } => {
|
DefaultFunction::EqualsInteger
|
||||||
if name == "Int" {
|
} else if tipo.is_string() {
|
||||||
Term::Builtin(DefaultFunction::EqualsInteger)
|
DefaultFunction::EqualsString
|
||||||
} else if name == "String" {
|
} else if tipo.is_bytearray() {
|
||||||
Term::Builtin(DefaultFunction::EqualsString)
|
DefaultFunction::EqualsByteString
|
||||||
} else if name == "ByteArray" {
|
|
||||||
Term::Builtin(DefaultFunction::EqualsByteString)
|
|
||||||
} else {
|
} else {
|
||||||
Term::Builtin(DefaultFunction::EqualsData)
|
DefaultFunction::EqualsData
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => unreachable!(),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let term = match name {
|
let term = match name {
|
||||||
|
@ -1778,16 +1911,13 @@ impl<'a> CodeGenerator<'a> {
|
||||||
}
|
}
|
||||||
.force_wrap(),
|
.force_wrap(),
|
||||||
BinOp::Eq => {
|
BinOp::Eq => {
|
||||||
match tipo.deref() {
|
if tipo.is_bool() {
|
||||||
Type::App { name, .. } => {
|
|
||||||
if name == "Bool" {
|
|
||||||
let term = Term::Force(
|
let term = Term::Force(
|
||||||
Term::Apply {
|
Term::Apply {
|
||||||
function: Term::Apply {
|
function: Term::Apply {
|
||||||
function: Term::Apply {
|
function: Term::Apply {
|
||||||
function: Term::Force(
|
function: Term::Force(
|
||||||
Term::Builtin(DefaultFunction::IfThenElse)
|
Term::Builtin(DefaultFunction::IfThenElse).into(),
|
||||||
.into(),
|
|
||||||
)
|
)
|
||||||
.into(),
|
.into(),
|
||||||
argument: left.into(),
|
argument: left.into(),
|
||||||
|
@ -1801,24 +1931,18 @@ impl<'a> CodeGenerator<'a> {
|
||||||
function: Term::Apply {
|
function: Term::Apply {
|
||||||
function: Term::Apply {
|
function: Term::Apply {
|
||||||
function: Term::Force(
|
function: Term::Force(
|
||||||
Term::Builtin(
|
Term::Builtin(DefaultFunction::IfThenElse)
|
||||||
DefaultFunction::IfThenElse,
|
|
||||||
)
|
|
||||||
.into(),
|
.into(),
|
||||||
)
|
)
|
||||||
.into(),
|
.into(),
|
||||||
argument: right.into(),
|
argument: right.into(),
|
||||||
}
|
}
|
||||||
.into(),
|
.into(),
|
||||||
argument: Term::Constant(
|
argument: Term::Constant(UplcConstant::Bool(false))
|
||||||
UplcConstant::Bool(false),
|
|
||||||
)
|
|
||||||
.into(),
|
.into(),
|
||||||
}
|
}
|
||||||
.into(),
|
.into(),
|
||||||
argument: Term::Constant(UplcConstant::Bool(
|
argument: Term::Constant(UplcConstant::Bool(true))
|
||||||
true,
|
|
||||||
))
|
|
||||||
.into(),
|
.into(),
|
||||||
}
|
}
|
||||||
.into(),
|
.into(),
|
||||||
|
@ -1830,10 +1954,106 @@ impl<'a> CodeGenerator<'a> {
|
||||||
|
|
||||||
arg_stack.push(term);
|
arg_stack.push(term);
|
||||||
return;
|
return;
|
||||||
|
} else if tipo.is_map() {
|
||||||
|
let term = Term::Apply {
|
||||||
|
function: Term::Apply {
|
||||||
|
function: default_builtin.into(),
|
||||||
|
argument: Term::Apply {
|
||||||
|
function: DefaultFunction::MapData.into(),
|
||||||
|
argument: left.into(),
|
||||||
}
|
}
|
||||||
|
.into(),
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
.into(),
|
||||||
|
argument: Term::Apply {
|
||||||
|
function: DefaultFunction::MapData.into(),
|
||||||
|
argument: right.into(),
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
};
|
};
|
||||||
|
arg_stack.push(term);
|
||||||
|
return;
|
||||||
|
} else if tipo.is_tuple()
|
||||||
|
&& matches!(tipo.get_uplc_type(), UplcType::Pair(_, _))
|
||||||
|
{
|
||||||
|
let term = Term::Apply {
|
||||||
|
function: Term::Apply {
|
||||||
|
function: default_builtin.into(),
|
||||||
|
argument: Term::Apply {
|
||||||
|
function: DefaultFunction::MapData.into(),
|
||||||
|
argument: Term::Apply {
|
||||||
|
function: Term::Apply {
|
||||||
|
function: Term::Builtin(DefaultFunction::MkCons)
|
||||||
|
.force_wrap()
|
||||||
|
.into(),
|
||||||
|
argument: left.into(),
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
argument: Term::Constant(UplcConstant::ProtoList(
|
||||||
|
UplcType::Pair(
|
||||||
|
UplcType::Data.into(),
|
||||||
|
UplcType::Data.into(),
|
||||||
|
),
|
||||||
|
vec![],
|
||||||
|
))
|
||||||
|
.into(),
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
argument: Term::Apply {
|
||||||
|
function: DefaultFunction::MapData.into(),
|
||||||
|
argument: Term::Apply {
|
||||||
|
function: Term::Apply {
|
||||||
|
function: Term::Builtin(DefaultFunction::MkCons)
|
||||||
|
.force_wrap()
|
||||||
|
.into(),
|
||||||
|
argument: right.into(),
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
argument: Term::Constant(UplcConstant::ProtoList(
|
||||||
|
UplcType::Pair(
|
||||||
|
UplcType::Data.into(),
|
||||||
|
UplcType::Data.into(),
|
||||||
|
),
|
||||||
|
vec![],
|
||||||
|
))
|
||||||
|
.into(),
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
};
|
||||||
|
arg_stack.push(term);
|
||||||
|
return;
|
||||||
|
} else if tipo.is_list()
|
||||||
|
|| matches!(tipo.get_uplc_type(), UplcType::List(_))
|
||||||
|
{
|
||||||
|
let term = Term::Apply {
|
||||||
|
function: Term::Apply {
|
||||||
|
function: default_builtin.into(),
|
||||||
|
argument: Term::Apply {
|
||||||
|
function: DefaultFunction::ListData.into(),
|
||||||
|
argument: left.into(),
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
argument: Term::Apply {
|
||||||
|
function: default_builtin.into(),
|
||||||
|
argument: Term::Apply {
|
||||||
|
function: DefaultFunction::ListData.into(),
|
||||||
|
argument: right.into(),
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
};
|
||||||
|
arg_stack.push(term);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Term::Apply {
|
Term::Apply {
|
||||||
function: Term::Apply {
|
function: Term::Apply {
|
||||||
|
@ -1845,16 +2065,13 @@ impl<'a> CodeGenerator<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
BinOp::NotEq => {
|
BinOp::NotEq => {
|
||||||
match tipo.deref() {
|
if tipo.is_bool() {
|
||||||
Type::App { name, .. } => {
|
|
||||||
if name == "Bool" {
|
|
||||||
let term = Term::Force(
|
let term = Term::Force(
|
||||||
Term::Apply {
|
Term::Apply {
|
||||||
function: Term::Apply {
|
function: Term::Apply {
|
||||||
function: Term::Apply {
|
function: Term::Apply {
|
||||||
function: Term::Force(
|
function: Term::Force(
|
||||||
Term::Builtin(DefaultFunction::IfThenElse)
|
Term::Builtin(DefaultFunction::IfThenElse).into(),
|
||||||
.into(),
|
|
||||||
)
|
)
|
||||||
.into(),
|
.into(),
|
||||||
argument: left.into(),
|
argument: left.into(),
|
||||||
|
@ -1874,15 +2091,13 @@ impl<'a> CodeGenerator<'a> {
|
||||||
argument: right.clone().into(),
|
argument: right.clone().into(),
|
||||||
}
|
}
|
||||||
.into(),
|
.into(),
|
||||||
argument: Term::Constant(
|
argument: Term::Constant(UplcConstant::Bool(
|
||||||
UplcConstant::Bool(false),
|
false,
|
||||||
)
|
))
|
||||||
.into(),
|
.into(),
|
||||||
}
|
}
|
||||||
.into(),
|
.into(),
|
||||||
argument: Term::Constant(
|
argument: Term::Constant(UplcConstant::Bool(true))
|
||||||
UplcConstant::Bool(true),
|
|
||||||
)
|
|
||||||
.into(),
|
.into(),
|
||||||
}
|
}
|
||||||
.into(),
|
.into(),
|
||||||
|
@ -1897,10 +2112,133 @@ impl<'a> CodeGenerator<'a> {
|
||||||
|
|
||||||
arg_stack.push(term);
|
arg_stack.push(term);
|
||||||
return;
|
return;
|
||||||
|
} else if tipo.is_map() {
|
||||||
|
let term = Term::Apply {
|
||||||
|
function: Term::Apply {
|
||||||
|
function: Term::Apply {
|
||||||
|
function: Term::Builtin(DefaultFunction::IfThenElse)
|
||||||
|
.force_wrap()
|
||||||
|
.into(),
|
||||||
|
argument: Term::Apply {
|
||||||
|
function: Term::Apply {
|
||||||
|
function: default_builtin.into(),
|
||||||
|
argument: Term::Apply {
|
||||||
|
function: DefaultFunction::MapData.into(),
|
||||||
|
argument: left.into(),
|
||||||
}
|
}
|
||||||
|
.into(),
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
.into(),
|
||||||
|
argument: Term::Apply {
|
||||||
|
function: DefaultFunction::MapData.into(),
|
||||||
|
argument: right.into(),
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
argument: Term::Constant(UplcConstant::Bool(false)).into(),
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
argument: Term::Constant(UplcConstant::Bool(true)).into(),
|
||||||
};
|
};
|
||||||
|
arg_stack.push(term);
|
||||||
|
return;
|
||||||
|
} else if tipo.is_tuple()
|
||||||
|
&& matches!(tipo.get_uplc_type(), UplcType::Pair(_, _))
|
||||||
|
{
|
||||||
|
// let term = Term::Apply {
|
||||||
|
// function: Term::Apply {
|
||||||
|
// function: default_builtin.into(),
|
||||||
|
// argument: Term::Apply {
|
||||||
|
// function: DefaultFunction::MapData.into(),
|
||||||
|
// argument: Term::Apply {
|
||||||
|
// function: Term::Apply {
|
||||||
|
// function: Term::Builtin(DefaultFunction::MkCons)
|
||||||
|
// .force_wrap()
|
||||||
|
// .into(),
|
||||||
|
// argument: left.into(),
|
||||||
|
// }
|
||||||
|
// .into(),
|
||||||
|
// argument: Term::Constant(UplcConstant::ProtoList(
|
||||||
|
// UplcType::Pair(
|
||||||
|
// UplcType::Data.into(),
|
||||||
|
// UplcType::Data.into(),
|
||||||
|
// ),
|
||||||
|
// vec![],
|
||||||
|
// ))
|
||||||
|
// .into(),
|
||||||
|
// }
|
||||||
|
// .into(),
|
||||||
|
// }
|
||||||
|
// .into(),
|
||||||
|
// }
|
||||||
|
// .into(),
|
||||||
|
// argument: Term::Apply {
|
||||||
|
// function: Term::Apply {
|
||||||
|
// function: Term::Builtin(DefaultFunction::MkCons)
|
||||||
|
// .force_wrap()
|
||||||
|
// .into(),
|
||||||
|
// argument: right.into(),
|
||||||
|
// }
|
||||||
|
// .into(),
|
||||||
|
// argument: Term::Constant(UplcConstant::ProtoList(
|
||||||
|
// UplcType::Pair(
|
||||||
|
// UplcType::Data.into(),
|
||||||
|
// UplcType::Data.into(),
|
||||||
|
// ),
|
||||||
|
// vec![],
|
||||||
|
// ))
|
||||||
|
// .into(),
|
||||||
|
// }
|
||||||
|
// .into(),
|
||||||
|
// };
|
||||||
|
// arg_stack.push(term);
|
||||||
|
// return;
|
||||||
|
todo!()
|
||||||
|
} else if tipo.is_list()
|
||||||
|
|| matches!(tipo.get_uplc_type(), UplcType::List(_))
|
||||||
|
{
|
||||||
|
let term = Term::Apply {
|
||||||
|
function: Term::Apply {
|
||||||
|
function: Term::Apply {
|
||||||
|
function: Term::Builtin(DefaultFunction::IfThenElse)
|
||||||
|
.force_wrap()
|
||||||
|
.into(),
|
||||||
|
argument: Term::Apply {
|
||||||
|
function: Term::Apply {
|
||||||
|
function: default_builtin.into(),
|
||||||
|
argument: Term::Apply {
|
||||||
|
function: DefaultFunction::ListData.into(),
|
||||||
|
argument: left.into(),
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
argument: Term::Apply {
|
||||||
|
function: default_builtin.into(),
|
||||||
|
argument: Term::Apply {
|
||||||
|
function: DefaultFunction::ListData.into(),
|
||||||
|
argument: right.into(),
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
argument: Term::Constant(UplcConstant::Bool(false)).into(),
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
argument: Term::Constant(UplcConstant::Bool(true)).into(),
|
||||||
|
};
|
||||||
|
|
||||||
|
arg_stack.push(term);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Term::Apply {
|
Term::Apply {
|
||||||
function: Term::Apply {
|
function: Term::Apply {
|
||||||
function: Term::Apply {
|
function: Term::Apply {
|
||||||
|
@ -2736,6 +3074,153 @@ impl<'a> CodeGenerator<'a> {
|
||||||
Air::Record { .. } => todo!(),
|
Air::Record { .. } => todo!(),
|
||||||
Air::RecordUpdate { .. } => todo!(),
|
Air::RecordUpdate { .. } => todo!(),
|
||||||
Air::Negate { .. } => todo!(),
|
Air::Negate { .. } => todo!(),
|
||||||
|
Air::TupleAccessor { tipo, names, .. } => {
|
||||||
|
let value = arg_stack.pop().unwrap();
|
||||||
|
let mut term = arg_stack.pop().unwrap();
|
||||||
|
let list_id = self.id_gen.next();
|
||||||
|
|
||||||
|
if names.len() == 2 {
|
||||||
|
term = Term::Apply {
|
||||||
|
function: Term::Lambda {
|
||||||
|
parameter_name: Name {
|
||||||
|
text: format!("__tuple_{}", list_id),
|
||||||
|
unique: 0.into(),
|
||||||
|
},
|
||||||
|
body: Term::Apply {
|
||||||
|
function: Term::Lambda {
|
||||||
|
parameter_name: Name {
|
||||||
|
text: names[0].clone(),
|
||||||
|
unique: 0.into(),
|
||||||
|
},
|
||||||
|
body: Term::Apply {
|
||||||
|
function: Term::Lambda {
|
||||||
|
parameter_name: Name {
|
||||||
|
text: names[1].clone(),
|
||||||
|
unique: 0.into(),
|
||||||
|
},
|
||||||
|
body: term.into(),
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
argument: Term::Apply {
|
||||||
|
function: Term::Builtin(DefaultFunction::SndPair)
|
||||||
|
.force_wrap()
|
||||||
|
.force_wrap()
|
||||||
|
.into(),
|
||||||
|
argument: Term::Var(Name {
|
||||||
|
text: format!("__tuple_{}", list_id),
|
||||||
|
unique: 0.into(),
|
||||||
|
})
|
||||||
|
.into(),
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
argument: Term::Apply {
|
||||||
|
function: Term::Builtin(DefaultFunction::FstPair)
|
||||||
|
.force_wrap()
|
||||||
|
.force_wrap()
|
||||||
|
.into(),
|
||||||
|
argument: Term::Var(Name {
|
||||||
|
text: format!("__tuple_{}", list_id),
|
||||||
|
unique: 0.into(),
|
||||||
|
})
|
||||||
|
.into(),
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
argument: value.into(),
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
let mut id_list = vec![];
|
||||||
|
|
||||||
|
for _ in 0..names.len() {
|
||||||
|
id_list.push(self.id_gen.next());
|
||||||
|
}
|
||||||
|
|
||||||
|
let current_index = 0;
|
||||||
|
let (first_name, names) = names.split_first().unwrap();
|
||||||
|
|
||||||
|
let head_list = if tipo.is_map() {
|
||||||
|
Term::Apply {
|
||||||
|
function: Term::Force(Term::Builtin(DefaultFunction::HeadList).into())
|
||||||
|
.into(),
|
||||||
|
argument: Term::Var(Name {
|
||||||
|
text: format!("__tuple_{}", list_id),
|
||||||
|
unique: 0.into(),
|
||||||
|
})
|
||||||
|
.into(),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
convert_data_to_type(
|
||||||
|
Term::Apply {
|
||||||
|
function: Term::Force(
|
||||||
|
Term::Builtin(DefaultFunction::HeadList).into(),
|
||||||
|
)
|
||||||
|
.into(),
|
||||||
|
argument: Term::Var(Name {
|
||||||
|
text: format!("__tuple_{}", list_id),
|
||||||
|
unique: 0.into(),
|
||||||
|
})
|
||||||
|
.into(),
|
||||||
|
},
|
||||||
|
&tipo.get_inner_type()[0],
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
term = Term::Apply {
|
||||||
|
function: Term::Lambda {
|
||||||
|
parameter_name: Name {
|
||||||
|
text: format!("__tuple_{}", list_id),
|
||||||
|
unique: 0.into(),
|
||||||
|
},
|
||||||
|
body: Term::Apply {
|
||||||
|
function: Term::Lambda {
|
||||||
|
parameter_name: Name {
|
||||||
|
text: first_name.clone(),
|
||||||
|
unique: 0.into(),
|
||||||
|
},
|
||||||
|
body: Term::Apply {
|
||||||
|
function: list_access_to_uplc(
|
||||||
|
names,
|
||||||
|
&id_list,
|
||||||
|
false,
|
||||||
|
current_index,
|
||||||
|
term,
|
||||||
|
&tipo,
|
||||||
|
)
|
||||||
|
.into(),
|
||||||
|
argument: Term::Apply {
|
||||||
|
function: Term::Force(
|
||||||
|
Term::Builtin(DefaultFunction::TailList).into(),
|
||||||
|
)
|
||||||
|
.into(),
|
||||||
|
argument: Term::Var(Name {
|
||||||
|
text: format!("__tuple_{}", list_id),
|
||||||
|
unique: 0.into(),
|
||||||
|
})
|
||||||
|
.into(),
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
argument: head_list.into(),
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
argument: value.into(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
arg_stack.push(term);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3066,7 +3551,7 @@ fn convert_constants_to_data(constants: Vec<UplcConstant>) -> Vec<UplcConstant>
|
||||||
})),
|
})),
|
||||||
UplcConstant::ProtoList(_, _) => todo!(),
|
UplcConstant::ProtoList(_, _) => todo!(),
|
||||||
UplcConstant::ProtoPair(_, _, _, _) => todo!(),
|
UplcConstant::ProtoPair(_, _, _, _) => todo!(),
|
||||||
UplcConstant::Data(_) => todo!(),
|
d @ UplcConstant::Data(_) => d,
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
new_constants.push(constant);
|
new_constants.push(constant);
|
||||||
|
@ -3172,6 +3657,29 @@ fn list_access_to_uplc(
|
||||||
) -> Term<Name> {
|
) -> Term<Name> {
|
||||||
let (first, names) = names.split_first().unwrap();
|
let (first, names) = names.split_first().unwrap();
|
||||||
|
|
||||||
|
let head_list = if tipo.is_map() {
|
||||||
|
Term::Apply {
|
||||||
|
function: Term::Force(Term::Builtin(DefaultFunction::HeadList).into()).into(),
|
||||||
|
argument: Term::Var(Name {
|
||||||
|
text: format!("tail_index_{}_{}", current_index, id_list[current_index]),
|
||||||
|
unique: 0.into(),
|
||||||
|
})
|
||||||
|
.into(),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
convert_data_to_type(
|
||||||
|
Term::Apply {
|
||||||
|
function: Term::Force(Term::Builtin(DefaultFunction::HeadList).into()).into(),
|
||||||
|
argument: Term::Var(Name {
|
||||||
|
text: format!("tail_index_{}_{}", current_index, id_list[current_index]),
|
||||||
|
unique: 0.into(),
|
||||||
|
})
|
||||||
|
.into(),
|
||||||
|
},
|
||||||
|
&tipo.clone().get_inner_type()[0],
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
if names.len() == 1 && tail {
|
if names.len() == 1 && tail {
|
||||||
Term::Lambda {
|
Term::Lambda {
|
||||||
parameter_name: Name {
|
parameter_name: Name {
|
||||||
|
@ -3210,22 +3718,7 @@ fn list_access_to_uplc(
|
||||||
.into(),
|
.into(),
|
||||||
}
|
}
|
||||||
.into(),
|
.into(),
|
||||||
argument: convert_data_to_type(
|
argument: head_list.into(),
|
||||||
Term::Apply {
|
|
||||||
function: Term::Force(Term::Builtin(DefaultFunction::HeadList).into())
|
|
||||||
.into(),
|
|
||||||
argument: Term::Var(Name {
|
|
||||||
text: format!(
|
|
||||||
"tail_index_{}_{}",
|
|
||||||
current_index, id_list[current_index]
|
|
||||||
),
|
|
||||||
unique: 0.into(),
|
|
||||||
})
|
|
||||||
.into(),
|
|
||||||
},
|
|
||||||
&Arc::new(tipo.clone()),
|
|
||||||
)
|
|
||||||
.into(),
|
|
||||||
}
|
}
|
||||||
.into(),
|
.into(),
|
||||||
}
|
}
|
||||||
|
@ -3295,15 +3788,7 @@ fn list_access_to_uplc(
|
||||||
.into(),
|
.into(),
|
||||||
}
|
}
|
||||||
.into(),
|
.into(),
|
||||||
argument: Term::Apply {
|
argument: head_list.into(),
|
||||||
function: Term::Force(Term::Builtin(DefaultFunction::HeadList).into()).into(),
|
|
||||||
argument: Term::Var(Name {
|
|
||||||
text: format!("tail_index_{}_{}", current_index, id_list[current_index]),
|
|
||||||
unique: 0.into(),
|
|
||||||
})
|
|
||||||
.into(),
|
|
||||||
}
|
|
||||||
.into(),
|
|
||||||
}
|
}
|
||||||
.into(),
|
.into(),
|
||||||
}
|
}
|
||||||
|
@ -3697,6 +4182,26 @@ fn convert_data_to_type(term: Term<Name>, field_type: &Arc<Type>) -> Term<Name>
|
||||||
},
|
},
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
|
} else if field_type.is_bool() {
|
||||||
|
Term::Apply {
|
||||||
|
function: Term::Apply {
|
||||||
|
function: Term::Builtin(DefaultFunction::EqualsInteger).into(),
|
||||||
|
argument: Term::Constant(UplcConstant::Integer(1)).into(),
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
argument: Term::Apply {
|
||||||
|
function: Term::Builtin(DefaultFunction::FstPair)
|
||||||
|
.force_wrap()
|
||||||
|
.force_wrap()
|
||||||
|
.into(),
|
||||||
|
argument: Term::Apply {
|
||||||
|
function: Term::Builtin(DefaultFunction::UnConstrData).into(),
|
||||||
|
argument: term.into(),
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
term
|
term
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,13 @@
|
||||||
use sample
|
use sample
|
||||||
|
|
||||||
pub fn spend(datum: sample.Datum, rdmr: sample.Redeemer, _ctx: Nil) -> Bool {
|
pub fn spend(datum: sample.Datum, rdmr: sample.Redeemer, _ctx: Nil) -> Bool {
|
||||||
let x = #(datum, rdmr, #[244])
|
let x = #(datum, #[244])
|
||||||
|
|
||||||
datum.random == rdmr.signer
|
let y = [#(#[222], #[222]), #(#[233], #[52])]
|
||||||
|
|
||||||
|
let [z, f, ..g] = y
|
||||||
|
|
||||||
|
let #(a, b) = x
|
||||||
|
|
||||||
|
z == #(#[222], #[222])
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue