create struct Air Env

refactor out some to_strings
This commit is contained in:
Kasey White 2023-03-21 16:02:52 -04:00 committed by Lucas
parent 0060d29265
commit 32d34d5fd3
6 changed files with 118 additions and 139 deletions

View File

@ -1,13 +1,11 @@
use std::sync::Arc;
use indexmap::IndexSet;
use uplc::builtins::DefaultFunction;
use crate::{ use crate::{
ast::{BinOp, UnOp}, ast::{BinOp, UnOp},
tipo::{Type, ValueConstructor}, tipo::{Type, ValueConstructor},
IdGenerator,
}; };
use indexmap::IndexSet;
use std::sync::Arc;
use uplc::builtins::DefaultFunction;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum Air { pub enum Air {
// Primitives // Primitives
@ -15,53 +13,44 @@ pub enum Air {
scope: Vec<u64>, scope: Vec<u64>,
value: String, value: String,
}, },
String { String {
scope: Vec<u64>, scope: Vec<u64>,
value: String, value: String,
}, },
ByteArray { ByteArray {
scope: Vec<u64>, scope: Vec<u64>,
bytes: Vec<u8>, bytes: Vec<u8>,
}, },
Bool { Bool {
scope: Vec<u64>, scope: Vec<u64>,
value: bool, value: bool,
}, },
List { List {
scope: Vec<u64>, scope: Vec<u64>,
count: usize, count: usize,
tipo: Arc<Type>, tipo: Arc<Type>,
tail: bool, tail: bool,
}, },
Tuple { Tuple {
scope: Vec<u64>, scope: Vec<u64>,
tipo: Arc<Type>, tipo: Arc<Type>,
count: usize, count: usize,
}, },
Void { Void {
scope: Vec<u64>, scope: Vec<u64>,
}, },
Var { Var {
scope: Vec<u64>, scope: Vec<u64>,
constructor: ValueConstructor, constructor: ValueConstructor,
name: String, name: String,
variant_name: String, variant_name: String,
}, },
// Functions // Functions
Call { Call {
scope: Vec<u64>, scope: Vec<u64>,
count: usize, count: usize,
tipo: Arc<Type>, tipo: Arc<Type>,
}, },
DefineFunc { DefineFunc {
scope: Vec<u64>, scope: Vec<u64>,
func_name: String, func_name: String,
@ -70,19 +59,16 @@ pub enum Air {
recursive: bool, recursive: bool,
variant_name: String, variant_name: String,
}, },
Fn { Fn {
scope: Vec<u64>, scope: Vec<u64>,
params: Vec<String>, params: Vec<String>,
}, },
Builtin { Builtin {
scope: Vec<u64>, scope: Vec<u64>,
count: usize, count: usize,
func: DefaultFunction, func: DefaultFunction,
tipo: Arc<Type>, tipo: Arc<Type>,
}, },
// Operators // Operators
BinOp { BinOp {
scope: Vec<u64>, scope: Vec<u64>,
@ -90,52 +76,43 @@ pub enum Air {
count: usize, count: usize,
tipo: Arc<Type>, tipo: Arc<Type>,
}, },
UnOp { UnOp {
scope: Vec<u64>, scope: Vec<u64>,
op: UnOp, op: UnOp,
}, },
// Assignment // Assignment
Let { Let {
scope: Vec<u64>, scope: Vec<u64>,
name: String, name: String,
}, },
UnWrapData { UnWrapData {
scope: Vec<u64>, scope: Vec<u64>,
tipo: Arc<Type>, tipo: Arc<Type>,
}, },
WrapData { WrapData {
scope: Vec<u64>, scope: Vec<u64>,
tipo: Arc<Type>, tipo: Arc<Type>,
}, },
AssertConstr { AssertConstr {
scope: Vec<u64>, scope: Vec<u64>,
constr_index: usize, constr_index: usize,
}, },
AssertBool { AssertBool {
scope: Vec<u64>, scope: Vec<u64>,
is_true: bool, is_true: bool,
}, },
// When // When
When { When {
scope: Vec<u64>, scope: Vec<u64>,
tipo: Arc<Type>, tipo: Arc<Type>,
subject_name: String, subject_name: String,
}, },
Clause { Clause {
scope: Vec<u64>, scope: Vec<u64>,
tipo: Arc<Type>, tipo: Arc<Type>,
subject_name: String, subject_name: String,
complex_clause: bool, complex_clause: bool,
}, },
ListClause { ListClause {
scope: Vec<u64>, scope: Vec<u64>,
tipo: Arc<Type>, tipo: Arc<Type>,
@ -143,11 +120,9 @@ pub enum Air {
next_tail_name: Option<String>, next_tail_name: Option<String>,
complex_clause: bool, complex_clause: bool,
}, },
WrapClause { WrapClause {
scope: Vec<u64>, scope: Vec<u64>,
}, },
TupleClause { TupleClause {
scope: Vec<u64>, scope: Vec<u64>,
tipo: Arc<Type>, tipo: Arc<Type>,
@ -157,13 +132,11 @@ pub enum Air {
count: usize, count: usize,
complex_clause: bool, complex_clause: bool,
}, },
ClauseGuard { ClauseGuard {
scope: Vec<u64>, scope: Vec<u64>,
subject_name: String, subject_name: String,
tipo: Arc<Type>, tipo: Arc<Type>,
}, },
ListClauseGuard { ListClauseGuard {
scope: Vec<u64>, scope: Vec<u64>,
tipo: Arc<Type>, tipo: Arc<Type>,
@ -171,17 +144,14 @@ pub enum Air {
next_tail_name: Option<String>, next_tail_name: Option<String>,
inverse: bool, inverse: bool,
}, },
Finally { Finally {
scope: Vec<u64>, scope: Vec<u64>,
}, },
// If // If
If { If {
scope: Vec<u64>, scope: Vec<u64>,
tipo: Arc<Type>, tipo: Arc<Type>,
}, },
// Record Creation // Record Creation
Record { Record {
scope: Vec<u64>, scope: Vec<u64>,
@ -189,27 +159,23 @@ pub enum Air {
tipo: Arc<Type>, tipo: Arc<Type>,
count: usize, count: usize,
}, },
RecordUpdate { RecordUpdate {
scope: Vec<u64>, scope: Vec<u64>,
highest_index: usize, highest_index: usize,
indices: Vec<(usize, Arc<Type>)>, indices: Vec<(usize, Arc<Type>)>,
tipo: Arc<Type>, tipo: Arc<Type>,
}, },
// Field Access // Field Access
RecordAccess { RecordAccess {
scope: Vec<u64>, scope: Vec<u64>,
record_index: u64, record_index: u64,
tipo: Arc<Type>, tipo: Arc<Type>,
}, },
FieldsExpose { FieldsExpose {
scope: Vec<u64>, scope: Vec<u64>,
indices: Vec<(usize, String, Arc<Type>)>, indices: Vec<(usize, String, Arc<Type>)>,
check_last_item: bool, check_last_item: bool,
}, },
// ListAccess // ListAccess
ListAccessor { ListAccessor {
scope: Vec<u64>, scope: Vec<u64>,
@ -218,14 +184,12 @@ pub enum Air {
tail: bool, tail: bool,
check_last_item: bool, check_last_item: bool,
}, },
ListExpose { ListExpose {
scope: Vec<u64>, scope: Vec<u64>,
tipo: Arc<Type>, tipo: Arc<Type>,
tail_head_names: Vec<(String, String)>, tail_head_names: Vec<(String, String)>,
tail: Option<(String, String)>, tail: Option<(String, String)>,
}, },
// Tuple Access // Tuple Access
TupleAccessor { TupleAccessor {
scope: Vec<u64>, scope: Vec<u64>,
@ -233,19 +197,16 @@ pub enum Air {
tipo: Arc<Type>, tipo: Arc<Type>,
check_last_item: bool, check_last_item: bool,
}, },
TupleIndex { TupleIndex {
scope: Vec<u64>, scope: Vec<u64>,
tipo: Arc<Type>, tipo: Arc<Type>,
tuple_index: usize, tuple_index: usize,
}, },
// Misc. // Misc.
ErrorTerm { ErrorTerm {
scope: Vec<u64>, scope: Vec<u64>,
tipo: Arc<Type>, tipo: Arc<Type>,
}, },
Trace { Trace {
scope: Vec<u64>, scope: Vec<u64>,
tipo: Arc<Type>, tipo: Arc<Type>,
@ -295,7 +256,6 @@ impl Air {
| Air::Trace { scope, .. } => scope.clone(), | Air::Trace { scope, .. } => scope.clone(),
} }
} }
pub fn scope_mut(&mut self) -> &mut Vec<u64> { pub fn scope_mut(&mut self) -> &mut Vec<u64> {
match self { match self {
Air::Int { scope, .. } Air::Int { scope, .. }
@ -338,7 +298,6 @@ impl Air {
| Air::Trace { scope, .. } => scope, | Air::Trace { scope, .. } => scope,
} }
} }
pub fn tipo(&self) -> Option<Arc<Type>> { pub fn tipo(&self) -> Option<Arc<Type>> {
match self { match self {
Air::Int { .. } => Some( Air::Int { .. } => Some(
@ -418,7 +377,6 @@ impl Air {
| Air::TupleIndex { tipo, .. } | Air::TupleIndex { tipo, .. }
| Air::ErrorTerm { tipo, .. } | Air::ErrorTerm { tipo, .. }
| Air::Trace { tipo, .. } => Some(tipo.clone()), | Air::Trace { tipo, .. } => Some(tipo.clone()),
Air::DefineFunc { .. } Air::DefineFunc { .. }
| Air::Fn { .. } | Air::Fn { .. }
| Air::Let { .. } | Air::Let { .. }
@ -427,7 +385,6 @@ impl Air {
| Air::AssertBool { .. } | Air::AssertBool { .. }
| Air::Finally { .. } | Air::Finally { .. }
| Air::FieldsExpose { .. } => None, | Air::FieldsExpose { .. } => None,
Air::UnOp { op, .. } => match op { Air::UnOp { op, .. } => match op {
UnOp::Not => Some( UnOp::Not => Some(
Type::App { Type::App {
@ -451,3 +408,55 @@ impl Air {
} }
} }
} }
pub struct AirEnv<'a> {
pub id_gen: &'a mut IdGenerator,
pub scope: Vec<u64>,
pub air: Vec<Air>,
}
impl<'a> AirEnv<'a> {
pub fn new(id_gen: &'a mut IdGenerator) -> Self {
AirEnv {
id_gen,
scope: vec![0],
air: vec![],
}
}
pub fn new_with_scope(id_gen: &'a mut IdGenerator, scope: Vec<u64>) -> Self {
AirEnv {
id_gen,
scope,
air: vec![],
}
}
pub fn int(mut self, value: String) -> Self {
self.air.push(Air::Int {
scope: self.scope.clone(),
value,
});
self
}
pub fn string(mut self, value: String) -> Self {
self.air.push(Air::String {
scope: self.scope.clone(),
value,
});
self
}
pub fn byte_array(mut self, bytes: Vec<u8>) -> Self {
self.air.push(Air::ByteArray {
scope: self.scope.clone(),
bytes,
});
self
}
// pub fn sequence(mut self, expressions: AirEnv) -> Self{
// }
}

View File

@ -208,14 +208,14 @@ pub fn convert_type_to_data(term: Term<Name>, field_type: &Arc<Type>) -> Term<Na
Term::list_data() Term::list_data()
.apply( .apply(
Term::mk_cons() Term::mk_cons()
.apply(Term::fst_pair().apply(Term::var("__pair".to_string()))) .apply(Term::fst_pair().apply(Term::var("__pair")))
.apply( .apply(
Term::mk_cons() Term::mk_cons()
.apply(Term::snd_pair().apply(Term::var("__pair".to_string()))) .apply(Term::snd_pair().apply(Term::var("__pair")))
.apply(Term::empty_list()), .apply(Term::empty_list()),
), ),
) )
.lambda("__pair".to_string()) .lambda("__pair")
.apply(term) .apply(term)
} else if field_type.is_list() || field_type.is_tuple() { } else if field_type.is_list() || field_type.is_tuple() {
Term::list_data().apply(term) Term::list_data().apply(term)
@ -260,8 +260,8 @@ pub fn convert_data_to_type(term: Term<Name>, field_type: &Arc<Type>) -> Term<Na
} else if field_type.is_tuple() && matches!(field_type.get_uplc_type(), UplcType::Pair(_, _)) { } else if field_type.is_tuple() && matches!(field_type.get_uplc_type(), UplcType::Pair(_, _)) {
Term::mk_pair_data() Term::mk_pair_data()
.apply(Term::head_list().apply(Term::var("__list_data"))) .apply(Term::head_list().apply(Term::var("__list_data")))
.apply(Term::head_list().apply(Term::var("__tail".to_string()))) .apply(Term::head_list().apply(Term::var("__tail")))
.lambda("__tail".to_string()) .lambda("__tail")
.apply(Term::tail_list().apply(Term::var("__list_data"))) .apply(Term::tail_list().apply(Term::var("__list_data")))
.lambda("__list_data") .lambda("__list_data")
.apply(Term::unlist_data().apply(term)) .apply(Term::unlist_data().apply(term))
@ -470,7 +470,7 @@ pub fn list_access_to_uplc(
if names.len() == 1 && tail { if names.len() == 1 && tail {
if first == "_" && names[0] == "_" { if first == "_" && names[0] == "_" {
term.lambda("_".to_string()) term.lambda("_")
} else if first == "_" { } else if first == "_" {
term.lambda(names[0].clone()) term.lambda(names[0].clone())
.apply(Term::tail_list().apply(Term::var(format!( .apply(Term::tail_list().apply(Term::var(format!(
@ -580,7 +580,7 @@ pub fn list_access_to_uplc(
match &list_access_inner { match &list_access_inner {
Term::Lambda { .. } => list_access_inner, Term::Lambda { .. } => list_access_inner,
_ => list_access_inner.lambda("_".to_string()), _ => list_access_inner.lambda("_"),
} }
} else { } else {
let mut list_access_inner = list_access_to_uplc( let mut list_access_inner = list_access_to_uplc(
@ -978,14 +978,14 @@ pub fn wrap_validator_args(term: Term<Name>, arguments: &[TypedArg]) -> Term<Nam
for arg in arguments.iter().rev() { for arg in arguments.iter().rev() {
if !matches!(arg.tipo.get_uplc_type(), UplcType::Data) { if !matches!(arg.tipo.get_uplc_type(), UplcType::Data) {
term = term term = term
.lambda(arg.arg_name.get_variable_name().unwrap_or("_").to_string()) .lambda(arg.arg_name.get_variable_name().unwrap_or("_"))
.apply(convert_data_to_type( .apply(convert_data_to_type(
Term::var(arg.arg_name.get_variable_name().unwrap_or("_").to_string()), Term::var(arg.arg_name.get_variable_name().unwrap_or("_")),
&arg.tipo, &arg.tipo,
)); ));
} }
term = term.lambda(arg.arg_name.get_variable_name().unwrap_or("_").to_string()) term = term.lambda(arg.arg_name.get_variable_name().unwrap_or("_"))
} }
term term
} }

View File

@ -4615,7 +4615,7 @@ impl<'a> CodeGenerator<'a> {
term = Term::equals_integer() term = Term::equals_integer()
.apply(Term::integer(constr_index.into())) .apply(Term::integer(constr_index.into()))
.apply(Term::var(CONSTR_INDEX_EXPOSER.to_string()).apply(constr)) .apply(Term::var(CONSTR_INDEX_EXPOSER).apply(constr))
.delayed_if_else(term, error_term); .delayed_if_else(term, error_term);
arg_stack.push(term); arg_stack.push(term);
@ -4675,7 +4675,7 @@ impl<'a> CodeGenerator<'a> {
if tipo.is_bool() { if tipo.is_bool() {
let other_clauses = if complex_clause { let other_clauses = if complex_clause {
Term::var("__other_clauses_delayed".to_string()) Term::var("__other_clauses_delayed")
} else { } else {
term.clone() term.clone()
}; };
@ -4692,9 +4692,7 @@ impl<'a> CodeGenerator<'a> {
} }
if complex_clause { if complex_clause {
term = body term = body.lambda("__other_clauses_delayed").apply(term.delay());
.lambda("__other_clauses_delayed".to_string())
.apply(term.delay());
} }
} else { } else {
let condition = if tipo.is_int() { let condition = if tipo.is_int() {
@ -4719,12 +4717,9 @@ impl<'a> CodeGenerator<'a> {
if complex_clause { if complex_clause {
term = condition term = condition
.if_else( .if_else(body.delay(), Term::var("__other_clauses_delayed"))
body.delay(),
Term::var("__other_clauses_delayed".to_string()),
)
.force() .force()
.lambda("__other_clauses_delayed".to_string()) .lambda("__other_clauses_delayed")
.apply(term.delay()); .apply(term.delay());
} else { } else {
term = condition.delayed_if_else(body, term); term = condition.delayed_if_else(body, term);
@ -4754,12 +4749,9 @@ impl<'a> CodeGenerator<'a> {
if complex_clause { if complex_clause {
term = Term::var(tail_name) term = Term::var(tail_name)
.choose_list( .choose_list(body.delay(), Term::var("__other_clauses_delayed"))
body.delay(),
Term::var("__other_clauses_delayed".to_string()),
)
.force() .force()
.lambda("__other_clauses_delayed".to_string()) .lambda("__other_clauses_delayed")
.apply(arg.delay()); .apply(arg.delay());
} else { } else {
term = Term::var(tail_name).delayed_choose_list(body, arg); term = Term::var(tail_name).delayed_choose_list(body, arg);
@ -4773,9 +4765,7 @@ impl<'a> CodeGenerator<'a> {
let mut term = arg_stack.pop().unwrap(); let mut term = arg_stack.pop().unwrap();
let arg = arg_stack.pop().unwrap(); let arg = arg_stack.pop().unwrap();
term = term term = term.lambda("__other_clauses_delayed").apply(arg.delay());
.lambda("__other_clauses_delayed".to_string())
.apply(arg.delay());
arg_stack.push(term); arg_stack.push(term);
} }
@ -4787,7 +4777,7 @@ impl<'a> CodeGenerator<'a> {
let then = arg_stack.pop().unwrap(); let then = arg_stack.pop().unwrap();
if tipo.is_bool() { if tipo.is_bool() {
let mut term = Term::var("__other_clauses_delayed".to_string()); let mut term = Term::var("__other_clauses_delayed");
if matches!(checker, Term::Constant(boolean) if matches!(boolean.as_ref(), UplcConstant::Bool(true))) if matches!(checker, Term::Constant(boolean) if matches!(boolean.as_ref(), UplcConstant::Bool(true)))
{ {
term = Term::var(subject_name).if_else(then.delay(), term).force(); term = Term::var(subject_name).if_else(then.delay(), term).force();
@ -4817,10 +4807,7 @@ impl<'a> CodeGenerator<'a> {
}; };
let term = condition let term = condition
.if_else( .if_else(then.delay(), Term::var("__other_clauses_delayed"))
then.delay(),
Term::var("__other_clauses_delayed".to_string()),
)
.force(); .force();
arg_stack.push(term); arg_stack.push(term);
} }
@ -4847,17 +4834,11 @@ impl<'a> CodeGenerator<'a> {
if !inverse { if !inverse {
term = Term::var(tail_name) term = Term::var(tail_name)
.choose_list( .choose_list(term.delay(), Term::var("__other_clauses_delayed"))
term.delay(),
Term::var("__other_clauses_delayed".to_string()),
)
.force(); .force();
} else { } else {
term = Term::var(tail_name) term = Term::var(tail_name)
.choose_list( .choose_list(Term::var("__other_clauses_delayed"), term.delay())
Term::var("__other_clauses_delayed".to_string()),
term.delay(),
)
.force(); .force();
} }
@ -4925,8 +4906,8 @@ impl<'a> CodeGenerator<'a> {
self.needs_field_access = true; self.needs_field_access = true;
let constr = arg_stack.pop().unwrap(); let constr = arg_stack.pop().unwrap();
let mut term = Term::var(CONSTR_GET_FIELD.to_string()) let mut term = Term::var(CONSTR_GET_FIELD)
.apply(Term::var(CONSTR_FIELDS_EXPOSER.to_string()).apply(constr)) .apply(Term::var(CONSTR_FIELDS_EXPOSER).apply(constr))
.apply(Term::integer(record_index.into())); .apply(Term::integer(record_index.into()));
term = convert_data_to_type(term, &tipo); term = convert_data_to_type(term, &tipo);
@ -4970,7 +4951,7 @@ impl<'a> CodeGenerator<'a> {
term term
}; };
term = term.apply(Term::var(CONSTR_FIELDS_EXPOSER.to_string()).apply(value)); term = term.apply(Term::var(CONSTR_FIELDS_EXPOSER).apply(value));
arg_stack.push(term); arg_stack.push(term);
} }
@ -5032,7 +5013,7 @@ impl<'a> CodeGenerator<'a> {
.. ..
} => { } => {
self.needs_field_access = true; self.needs_field_access = true;
let tail_name_prefix = "__tail_index".to_string(); let tail_name_prefix = "__tail_index";
let record = arg_stack.pop().unwrap(); let record = arg_stack.pop().unwrap();
@ -5108,7 +5089,7 @@ impl<'a> CodeGenerator<'a> {
term = term term = term
.lambda(prev_tail_name) .lambda(prev_tail_name)
.apply(Term::var(CONSTR_FIELDS_EXPOSER.to_string()).apply(record)); .apply(Term::var(CONSTR_FIELDS_EXPOSER).apply(record));
arg_stack.push(term); arg_stack.push(term);
} }
@ -5144,7 +5125,7 @@ impl<'a> CodeGenerator<'a> {
} else { } else {
self.needs_field_access = true; self.needs_field_access = true;
term = convert_data_to_type( term = convert_data_to_type(
Term::var(CONSTR_GET_FIELD.to_string()) Term::var(CONSTR_GET_FIELD)
.apply(term) .apply(term)
.apply(Term::integer(tuple_index.into())), .apply(Term::integer(tuple_index.into())),
&tipo.get_inner_types()[tuple_index], &tipo.get_inner_types()[tuple_index],
@ -5226,7 +5207,7 @@ impl<'a> CodeGenerator<'a> {
let next_clause = arg_stack.pop().unwrap(); let next_clause = arg_stack.pop().unwrap();
term = term term = term
.lambda("__other_clauses_delayed".to_string()) .lambda("__other_clauses_delayed")
.apply(next_clause.delay()); .apply(next_clause.delay());
} }

View File

@ -45,3 +45,36 @@ test foo_4() {
False False
} }
} }
// type Seasons {
// Winter
// Spring
// Summer
// Fall
// }
// fn is_cold(season, hour) {
// when season is {
// Winter | Fall ->
// True
// _ if hour >= 18 ->
// True
// _ ->
// False
// }
// }
// test foo_5() {
// !is_cold(Spring, 15) && is_cold(Summer, 22)
// }
fn when_tuple(a: (Int, Int)) -> Int {
when a is {
(a, _b) ->
a
}
}
test spend() {
when_tuple((4, 1)) == 4
}

View File

@ -1,32 +0,0 @@
{
"preamble": {
"title": "aiken-lang/acceptance_test_048",
"version": "0.0.0",
"plutusVersion": "v2"
},
"validators": [
{
"title": "foo.spend",
"datum": {
"title": "a",
"schema": {
"$ref": "#/definitions/Data"
}
},
"redeemer": {
"title": "b",
"schema": {
"$ref": "#/definitions/Data"
}
},
"compiledCode": "586001000032323232323232323222253330063370e6464640046eb4c02c008dd69804800a5ef6c6010104000101010048020526163001001222533300800214984cc014c004c024008ccc00c00cc0280080055cd2b9b5573aaae7955cfaba157441",
"hash": "7ecbfc3ae91c4d5ba3799b4d283e385d457c860cd22034d825379ae2"
}
],
"definitions": {
"Data": {
"title": "Data",
"description": "Any Plutus data."
}
}
}

View File

@ -1,12 +0,0 @@
fn when_tuple(a: (Int, Int)) -> Int {
when a is {
(a, b) ->
a
}
}
validator {
fn spend(a: Data, b: Data, c) -> Bool {
when_tuple((4, 1)) == 4
}
}