feat: start when expressions
This commit is contained in:
parent
8b24a66b7e
commit
86ea41adc3
|
@ -1,3 +1,4 @@
|
||||||
/target
|
/target
|
||||||
.idea
|
.idea
|
||||||
_site/
|
_site/
|
||||||
|
temp
|
|
@ -104,15 +104,18 @@ pub enum IR {
|
||||||
// },
|
// },
|
||||||
When {
|
When {
|
||||||
count: usize,
|
count: usize,
|
||||||
|
subject_name: String,
|
||||||
},
|
},
|
||||||
|
|
||||||
Clause {
|
Clause {
|
||||||
count: usize,
|
count: usize,
|
||||||
|
tipo: Arc<Type>,
|
||||||
|
subject_name: String,
|
||||||
},
|
},
|
||||||
|
|
||||||
Finally {
|
Discard,
|
||||||
count: usize,
|
|
||||||
},
|
Finally,
|
||||||
|
|
||||||
If {
|
If {
|
||||||
count: usize,
|
count: usize,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use std::{collections::HashMap, ops::Deref, sync::Arc};
|
use std::{collections::HashMap, fmt::format, ops::Deref, sync::Arc};
|
||||||
|
|
||||||
use uplc::{
|
use uplc::{
|
||||||
ast::{
|
ast::{
|
||||||
|
@ -193,23 +193,38 @@ impl<'a> CodeGenerator<'a> {
|
||||||
TypedExpr::When {
|
TypedExpr::When {
|
||||||
subjects, clauses, ..
|
subjects, clauses, ..
|
||||||
} => {
|
} => {
|
||||||
|
let subject_name = format!("__subject_name_{}", self.id_gen.next());
|
||||||
|
|
||||||
// assuming one subject at the moment
|
// assuming one subject at the moment
|
||||||
ir_stack.push(IR::When {
|
ir_stack.push(IR::When {
|
||||||
count: clauses.len() + 1,
|
count: clauses.len() + 1,
|
||||||
|
subject_name: subject_name.clone(),
|
||||||
});
|
});
|
||||||
|
|
||||||
let subject = subjects[0].clone();
|
let subject = subjects[0].clone();
|
||||||
|
|
||||||
self.build_ir(&subject, ir_stack);
|
self.build_ir(&subject, ir_stack);
|
||||||
|
|
||||||
if let Some((last_clause, clauses)) = clauses.split_last() {
|
if let Some((last_clause, clauses)) = clauses.split_last() {
|
||||||
let mut clauses_vec = vec![];
|
let mut clauses_vec = vec![];
|
||||||
|
let mut pattern_vec = vec![];
|
||||||
|
|
||||||
for clause in clauses {
|
for clause in clauses {
|
||||||
ir_stack.push(IR::Clause { count: 2 });
|
|
||||||
self.build_ir(&clause.then, &mut clauses_vec);
|
self.build_ir(&clause.then, &mut clauses_vec);
|
||||||
self.pattern_ir(&clause.pattern[0], ir_stack, &mut clauses_vec);
|
|
||||||
|
self.when_ir(
|
||||||
|
&clause.pattern[0],
|
||||||
|
&mut pattern_vec,
|
||||||
|
&mut clauses_vec,
|
||||||
|
&subject.tipo(),
|
||||||
|
subject_name.clone(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ir_stack.append(&mut pattern_vec);
|
||||||
|
|
||||||
let last_pattern = &last_clause.pattern[0];
|
let last_pattern = &last_clause.pattern[0];
|
||||||
ir_stack.push(IR::Finally { count: 2 });
|
ir_stack.push(IR::Finally);
|
||||||
|
|
||||||
self.build_ir(&last_clause.then, &mut clauses_vec);
|
self.build_ir(&last_clause.then, &mut clauses_vec);
|
||||||
self.pattern_ir(last_pattern, ir_stack, &mut clauses_vec);
|
self.pattern_ir(last_pattern, ir_stack, &mut clauses_vec);
|
||||||
|
@ -326,6 +341,38 @@ impl<'a> CodeGenerator<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn when_ir(
|
||||||
|
&self,
|
||||||
|
pattern: &Pattern<tipo::PatternConstructor, Arc<tipo::Type>>,
|
||||||
|
pattern_vec: &mut Vec<IR>,
|
||||||
|
values: &mut Vec<IR>,
|
||||||
|
tipo: &Type,
|
||||||
|
subject_name: String,
|
||||||
|
) {
|
||||||
|
match pattern {
|
||||||
|
Pattern::Int { value, .. } => {
|
||||||
|
pattern_vec.push(IR::Clause {
|
||||||
|
count: 2,
|
||||||
|
tipo: tipo.clone().into(),
|
||||||
|
subject_name,
|
||||||
|
});
|
||||||
|
|
||||||
|
pattern_vec.push(IR::Int {
|
||||||
|
value: value.clone(),
|
||||||
|
});
|
||||||
|
|
||||||
|
pattern_vec.append(values);
|
||||||
|
}
|
||||||
|
Pattern::String { .. } => todo!(),
|
||||||
|
Pattern::Var { .. } => todo!(),
|
||||||
|
Pattern::VarUsage { .. } => todo!(),
|
||||||
|
Pattern::Assign { .. } => todo!(),
|
||||||
|
Pattern::Discard { .. } => unreachable!(),
|
||||||
|
Pattern::List { .. } => todo!(),
|
||||||
|
Pattern::Constructor { .. } => todo!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn pattern_ir(
|
fn pattern_ir(
|
||||||
&self,
|
&self,
|
||||||
pattern: &Pattern<tipo::PatternConstructor, Arc<tipo::Type>>,
|
pattern: &Pattern<tipo::PatternConstructor, Arc<tipo::Type>>,
|
||||||
|
@ -338,7 +385,11 @@ impl<'a> CodeGenerator<'a> {
|
||||||
Pattern::Var { .. } => todo!(),
|
Pattern::Var { .. } => todo!(),
|
||||||
Pattern::VarUsage { .. } => todo!(),
|
Pattern::VarUsage { .. } => todo!(),
|
||||||
Pattern::Assign { .. } => todo!(),
|
Pattern::Assign { .. } => todo!(),
|
||||||
Pattern::Discard { .. } => todo!(),
|
Pattern::Discard { .. } => {
|
||||||
|
pattern_vec.push(IR::Discard);
|
||||||
|
|
||||||
|
pattern_vec.append(values);
|
||||||
|
}
|
||||||
Pattern::List { elements, tail, .. } => {
|
Pattern::List { elements, tail, .. } => {
|
||||||
let mut elements_vec = vec![];
|
let mut elements_vec = vec![];
|
||||||
|
|
||||||
|
@ -478,6 +529,9 @@ impl<'a> CodeGenerator<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
IR::Discard => {
|
||||||
|
arg_stack.push(Term::Constant(Constant::Unit));
|
||||||
|
}
|
||||||
IR::List { count, tipo, tail } => {
|
IR::List { count, tipo, tail } => {
|
||||||
let mut args = vec![];
|
let mut args = vec![];
|
||||||
|
|
||||||
|
@ -754,7 +808,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
arg_stack.push(term);
|
arg_stack.push(term);
|
||||||
}
|
}
|
||||||
IR::DefineFunc { func_name, .. } => {
|
IR::DefineFunc { func_name, .. } => {
|
||||||
let body = arg_stack.pop().unwrap();
|
let _body = arg_stack.pop().unwrap();
|
||||||
|
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
@ -762,8 +816,70 @@ impl<'a> CodeGenerator<'a> {
|
||||||
IR::DefineConstrFields { .. } => todo!(),
|
IR::DefineConstrFields { .. } => todo!(),
|
||||||
IR::DefineConstrFieldAccess { .. } => todo!(),
|
IR::DefineConstrFieldAccess { .. } => todo!(),
|
||||||
IR::When { .. } => todo!(),
|
IR::When { .. } => todo!(),
|
||||||
IR::Clause { .. } => todo!(),
|
IR::Clause {
|
||||||
IR::Finally { .. } => todo!(),
|
count,
|
||||||
|
tipo,
|
||||||
|
subject_name,
|
||||||
|
} => {
|
||||||
|
// clause to compare
|
||||||
|
let clause = arg_stack.pop().unwrap();
|
||||||
|
|
||||||
|
// the body to be run if the clause matches
|
||||||
|
let body = arg_stack.pop().unwrap();
|
||||||
|
|
||||||
|
// the final branch in the when expression
|
||||||
|
let mut term = arg_stack.pop().unwrap();
|
||||||
|
|
||||||
|
let checker = if tipo.is_int() {
|
||||||
|
DefaultFunction::EqualsInteger.into()
|
||||||
|
} else if tipo.is_bytearray() {
|
||||||
|
DefaultFunction::EqualsByteString.into()
|
||||||
|
} else if tipo.is_bool() {
|
||||||
|
todo!()
|
||||||
|
} else if tipo.is_string() {
|
||||||
|
DefaultFunction::EqualsString.into()
|
||||||
|
} else if tipo.is_list() {
|
||||||
|
todo!()
|
||||||
|
} else {
|
||||||
|
DefaultFunction::EqualsData.into()
|
||||||
|
};
|
||||||
|
|
||||||
|
term = Term::Apply {
|
||||||
|
function: Term::Apply {
|
||||||
|
function: Term::Apply {
|
||||||
|
function: Term::Force(DefaultFunction::IfThenElse.into()).into(),
|
||||||
|
argument: Term::Apply {
|
||||||
|
function: Term::Apply {
|
||||||
|
function: checker,
|
||||||
|
argument: Term::Var(Name {
|
||||||
|
text: subject_name,
|
||||||
|
unique: 0.into(),
|
||||||
|
})
|
||||||
|
.into(),
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
argument: clause.into(),
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
argument: body.into(),
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
argument: term.into(),
|
||||||
|
}
|
||||||
|
.force_wrap();
|
||||||
|
|
||||||
|
arg_stack.push(term);
|
||||||
|
}
|
||||||
|
IR::Finally => {
|
||||||
|
let clause = arg_stack.pop().unwrap();
|
||||||
|
|
||||||
|
if !clause.is_unit() {
|
||||||
|
let _body = arg_stack.pop().unwrap();
|
||||||
|
todo!();
|
||||||
|
}
|
||||||
|
}
|
||||||
IR::If { .. } => todo!(),
|
IR::If { .. } => todo!(),
|
||||||
IR::Constr { .. } => todo!(),
|
IR::Constr { .. } => todo!(),
|
||||||
IR::Fields { .. } => todo!(),
|
IR::Fields { .. } => todo!(),
|
||||||
|
|
|
@ -110,6 +110,16 @@ pub enum Term<T> {
|
||||||
Builtin(DefaultFunction),
|
Builtin(DefaultFunction),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T> Term<T> {
|
||||||
|
pub fn is_unit(&self) -> bool {
|
||||||
|
matches!(self, Term::Constant(Constant::Unit))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn force_wrap(self) -> Self {
|
||||||
|
Term::Force(self.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a, T> Display for Term<T>
|
impl<'a, T> Display for Term<T>
|
||||||
where
|
where
|
||||||
T: Binder<'a>,
|
T: Binder<'a>,
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
use std::{fmt::Display, str::FromStr};
|
use std::{fmt::Display, rc::Rc, str::FromStr};
|
||||||
|
|
||||||
use strum_macros::EnumIter;
|
use strum_macros::EnumIter;
|
||||||
|
|
||||||
use flat_rs::de;
|
use flat_rs::de;
|
||||||
|
|
||||||
|
use crate::ast::Term;
|
||||||
|
|
||||||
/// All the possible builtin functions in Untyped Plutus Core.
|
/// All the possible builtin functions in Untyped Plutus Core.
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
|
@ -389,3 +391,15 @@ impl DefaultFunction {
|
||||||
.to_string()
|
.to_string()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T> From<DefaultFunction> for Term<T> {
|
||||||
|
fn from(builtin: DefaultFunction) -> Self {
|
||||||
|
Term::Builtin(builtin)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> From<DefaultFunction> for Rc<Term<T>> {
|
||||||
|
fn from(builtin: DefaultFunction) -> Self {
|
||||||
|
Term::Builtin(builtin).into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue