create ir and start to replace plutus code gen with ir
This commit is contained in:
parent
6870a5cab7
commit
2a00b896fc
|
@ -0,0 +1,203 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use vec1::Vec1;
|
||||
|
||||
use crate::{
|
||||
ast::{
|
||||
Annotation, Arg, AssignmentKind, BinOp, CallArg, Clause, IfBranch, Pattern, Span,
|
||||
TypedRecordUpdateArg,
|
||||
},
|
||||
tipo::{ModuleValueConstructor, PatternConstructor, Type, ValueConstructor},
|
||||
};
|
||||
|
||||
// []
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum IR {
|
||||
Int {
|
||||
value: String,
|
||||
},
|
||||
|
||||
String {
|
||||
value: String,
|
||||
},
|
||||
|
||||
ByteArray {
|
||||
bytes: Vec<u8>,
|
||||
},
|
||||
|
||||
Var {
|
||||
constructor: ValueConstructor,
|
||||
name: String,
|
||||
},
|
||||
|
||||
// Fn {
|
||||
// tipo: Arc<Type>,
|
||||
// is_capture: bool,
|
||||
// args: Vec<Arg<Arc<Type>>>,
|
||||
// body: Box<Self>,
|
||||
// return_annotation: Option<Annotation>,
|
||||
// },
|
||||
List {
|
||||
count: usize,
|
||||
},
|
||||
|
||||
Tail {
|
||||
count: usize,
|
||||
},
|
||||
|
||||
// func(x, other(y))
|
||||
//[ Define(3) x definition *lam_body* -> [ (x [ (func [ func x [ (y [ other y ]) *definition* ] ]) *definition* ]) *definition* ], Define func -> [ (func [ func x [ (y [ other y ]) *definition* ] ]) *definition* ] , Call func -> [ func x [ (y [ other y ]) *definition* ] ], Var x -> x, Define y -> [ (y [ other y ]) *definition* ], Call other -> [ other y ], Var y -> y]
|
||||
|
||||
// [y_varCall other_var Call Call x_defCall func_var ]
|
||||
Call {
|
||||
count: usize,
|
||||
},
|
||||
|
||||
BinOp {
|
||||
name: BinOp,
|
||||
count: usize,
|
||||
},
|
||||
|
||||
Assignment {
|
||||
count: usize,
|
||||
kind: AssignmentKind,
|
||||
},
|
||||
|
||||
DefineFunc {
|
||||
func_name: String,
|
||||
module_name: String,
|
||||
count: usize,
|
||||
},
|
||||
|
||||
DefineConst {
|
||||
func_name: String,
|
||||
module_name: String,
|
||||
count: usize,
|
||||
},
|
||||
|
||||
DefineConstrFields {
|
||||
func_name: String,
|
||||
module_name: String,
|
||||
count: usize,
|
||||
},
|
||||
|
||||
DefineConstrFieldAccess {
|
||||
func_name: String,
|
||||
module_name: String,
|
||||
count: usize,
|
||||
},
|
||||
|
||||
// Try {
|
||||
// tipo: Arc<Type>,
|
||||
// value: Box<Self>,
|
||||
// then: Box<Self>,
|
||||
// pattern: Pattern<PatternConstructor, Arc<Type>>,
|
||||
// },
|
||||
When {
|
||||
count: usize,
|
||||
},
|
||||
|
||||
Clause {
|
||||
count: usize,
|
||||
},
|
||||
|
||||
Finally {
|
||||
count: usize,
|
||||
},
|
||||
|
||||
If {
|
||||
count: usize,
|
||||
},
|
||||
|
||||
Constr {
|
||||
count: usize,
|
||||
},
|
||||
|
||||
Fields {
|
||||
count: usize,
|
||||
},
|
||||
|
||||
RecordAccess {
|
||||
label: String,
|
||||
index: u64,
|
||||
count: usize,
|
||||
},
|
||||
|
||||
FieldsExpose {
|
||||
count: usize,
|
||||
},
|
||||
|
||||
// ModuleSelect {
|
||||
// tipo: Arc<Type>,
|
||||
// label: String,
|
||||
// module_name: String,
|
||||
// module_alias: String,
|
||||
// constructor: ModuleValueConstructor,
|
||||
// },
|
||||
|
||||
// Tuple {
|
||||
//
|
||||
// tipo: Arc<Type>,
|
||||
// elems: Vec<Self>,
|
||||
// },
|
||||
|
||||
// TupleIndex {
|
||||
//
|
||||
// tipo: Arc<Type>,
|
||||
// index: u64,
|
||||
// tuple: Box<Self>,
|
||||
// },
|
||||
Todo {
|
||||
label: Option<String>,
|
||||
tipo: Arc<Type>,
|
||||
},
|
||||
|
||||
RecordUpdate {
|
||||
tipo: Arc<Type>,
|
||||
spread: Box<Self>,
|
||||
args: Vec<TypedRecordUpdateArg>,
|
||||
},
|
||||
|
||||
Negate {
|
||||
value: Box<Self>,
|
||||
},
|
||||
}
|
||||
|
||||
// pub fn get(r: Int) -> This{g: Int}{
|
||||
// This{ g: r }
|
||||
// }
|
||||
//let x = get(rdmr) when datum is { Hold(h, thing: f) -> h > x.g, Sell{price} -> x.g == price }
|
||||
|
||||
// [ When(3) datum_var Clause(2) FieldsExpose(3) datum_var h_field_var f_field_var Binop(Greater, 2) h_var FieldAccess(2) x_var g_field Finally(2) Binop(2, EqualsInteger) FieldAccess x_var g_field_var ]
|
||||
|
||||
// [ Assignment(2) ]
|
||||
|
||||
// [ Assignment(2) x_var ]
|
||||
|
||||
// [ Assignment(2) x_var Call(2) ]
|
||||
|
||||
// [ Assignment(2) x_var Call(2) func_get_var ]
|
||||
// ^Mark this index function insertion
|
||||
|
||||
// [ Assignment(2) x_var Call(2) func_get_var rdmr_var When(4)]
|
||||
|
||||
// [ Assignment(2) x_var Call(2) func_get_var ]
|
||||
|
||||
// (var rdmr)
|
||||
|
||||
// [ Assignment(2) x_var Call(2) ]
|
||||
|
||||
// (var func_get)
|
||||
|
||||
// arg stack [ (var rdmr)]
|
||||
|
||||
// [ Assignment(2) x_var ]
|
||||
|
||||
// [(var func_get) (var rdmr)]
|
||||
|
||||
// [ Assignment(2)]
|
||||
|
||||
// (var x)
|
||||
|
||||
// arg stack [ [(var func_get) (var rdmr)] ]
|
|
@ -7,10 +7,12 @@ pub mod ast;
|
|||
pub mod builtins;
|
||||
pub mod expr;
|
||||
pub mod format;
|
||||
pub mod ir;
|
||||
pub mod parser;
|
||||
pub mod pretty;
|
||||
pub mod tipo;
|
||||
pub mod uplc;
|
||||
pub mod uplc_two;
|
||||
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub struct IdGenerator {
|
||||
|
|
|
@ -0,0 +1,365 @@
|
|||
use std::{collections::HashMap, sync::Arc};
|
||||
|
||||
use indexmap::IndexMap;
|
||||
use uplc::{
|
||||
ast::{Name, Program, Term},
|
||||
parser::interner::Interner,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
ast::{DataType, Function, TypedArg},
|
||||
expr::TypedExpr,
|
||||
ir::IR,
|
||||
tipo,
|
||||
uplc::{
|
||||
ConstrFieldKey, ConstrUsageKey, DataTypeKey, FunctionAccessKey, ScopeLevels, ScopedExpr,
|
||||
},
|
||||
};
|
||||
|
||||
pub struct CodeGenerator<'a> {
|
||||
// uplc_function_holder: Vec<(String, Term<Name>)>,
|
||||
// uplc_function_holder_lookup: IndexMap<FunctionAccessKey, ScopeLevels>,
|
||||
// uplc_data_holder_lookup: IndexMap<ConstrFieldKey, ScopedExpr>,
|
||||
// uplc_data_constr_lookup: IndexMap<DataTypeKey, ScopeLevels>,
|
||||
// uplc_data_usage_holder_lookup: IndexMap<ConstrUsageKey, ScopeLevels>,
|
||||
function_recurse_lookup: IndexMap<FunctionAccessKey, usize>,
|
||||
functions: &'a HashMap<FunctionAccessKey, &'a Function<Arc<tipo::Type>, TypedExpr>>,
|
||||
// type_aliases: &'a HashMap<(String, String), &'a TypeAlias<Arc<tipo::Type>>>,
|
||||
data_types: &'a HashMap<DataTypeKey, &'a DataType<Arc<tipo::Type>>>,
|
||||
// imports: &'a HashMap<(String, String), &'a Use<String>>,
|
||||
// constants: &'a HashMap<(String, String), &'a ModuleConstant<Arc<tipo::Type>, String>>,
|
||||
}
|
||||
|
||||
impl<'a> CodeGenerator<'a> {
|
||||
pub fn new(
|
||||
functions: &'a HashMap<FunctionAccessKey, &'a Function<Arc<tipo::Type>, TypedExpr>>,
|
||||
// type_aliases: &'a HashMap<(String, String), &'a TypeAlias<Arc<tipo::Type>>>,
|
||||
data_types: &'a HashMap<DataTypeKey, &'a DataType<Arc<tipo::Type>>>,
|
||||
// imports: &'a HashMap<(String, String), &'a Use<String>>,
|
||||
// constants: &'a HashMap<(String, String), &'a ModuleConstant<Arc<tipo::Type>, String>>,
|
||||
) -> Self {
|
||||
CodeGenerator {
|
||||
// uplc_function_holder: Vec::new(),
|
||||
// uplc_function_holder_lookup: IndexMap::new(),
|
||||
// uplc_data_holder_lookup: IndexMap::new(),
|
||||
// uplc_data_constr_lookup: IndexMap::new(),
|
||||
// uplc_data_usage_holder_lookup: IndexMap::new(),
|
||||
function_recurse_lookup: IndexMap::new(),
|
||||
functions,
|
||||
// type_aliases,
|
||||
data_types,
|
||||
// imports,
|
||||
// constants,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn generate(&mut self, body: TypedExpr, arguments: Vec<TypedArg>) -> Program<Name> {
|
||||
let mut ir_stack = vec![];
|
||||
|
||||
self.build_ir(&body, &mut ir_stack);
|
||||
|
||||
todo!();
|
||||
|
||||
// self.uplc_function_holder_lookup
|
||||
// .sort_by(|_key1, value1, _key2, value2| {
|
||||
// if value1.is_less_than(value2, true) {
|
||||
// Ordering::Less
|
||||
// } else if value2.is_less_than(value1, true) {
|
||||
// Ordering::Greater
|
||||
// } else {
|
||||
// Ordering::Equal
|
||||
// }
|
||||
// });
|
||||
|
||||
// println!("DATA HOLDER LOOKUP{:#?}", self.uplc_data_holder_lookup);
|
||||
|
||||
// println!(
|
||||
// "DATA USAGE HOLDER {:#?}",
|
||||
// self.uplc_data_usage_holder_lookup
|
||||
// );
|
||||
|
||||
// let mut term = self.recurse_code_gen(&body, ScopeLevels::new());
|
||||
|
||||
// // Apply constr exposer to top level.
|
||||
// term = Term::Apply {
|
||||
// function: Term::Lambda {
|
||||
// parameter_name: Name {
|
||||
// text: "constr_fields_exposer".to_string(),
|
||||
// unique: 0.into(),
|
||||
// },
|
||||
// body: term.into(),
|
||||
// }
|
||||
// .into(),
|
||||
// argument: Term::Lambda {
|
||||
// parameter_name: Name {
|
||||
// text: "constr_var".to_string(),
|
||||
// unique: 0.into(),
|
||||
// },
|
||||
// body: Term::Apply {
|
||||
// function: Term::Force(
|
||||
// Term::Force(Term::Builtin(DefaultFunction::SndPair).into()).into(),
|
||||
// )
|
||||
// .into(),
|
||||
// argument: Term::Apply {
|
||||
// function: Term::Builtin(DefaultFunction::UnConstrData).into(),
|
||||
// argument: Term::Var(Name {
|
||||
// text: "constr_var".to_string(),
|
||||
// unique: 0.into(),
|
||||
// })
|
||||
// .into(),
|
||||
// }
|
||||
// .into(),
|
||||
// }
|
||||
// .into(),
|
||||
// }
|
||||
// .into(),
|
||||
// };
|
||||
|
||||
// term = self.add_arg_getter(term);
|
||||
|
||||
// term = Term::Force(
|
||||
// Term::Apply {
|
||||
// function: Term::Apply {
|
||||
// function: Term::Apply {
|
||||
// function: Term::Force(Term::Builtin(DefaultFunction::IfThenElse).into())
|
||||
// .into(),
|
||||
// argument: term.into(),
|
||||
// }
|
||||
// .into(),
|
||||
// argument: Term::Delay(Term::Constant(Constant::Unit).into()).into(),
|
||||
// }
|
||||
// .into(),
|
||||
// argument: Term::Delay(Term::Error.into()).into(),
|
||||
// }
|
||||
// .into(),
|
||||
// );
|
||||
|
||||
// for arg in arguments.iter().rev() {
|
||||
// term = Term::Lambda {
|
||||
// parameter_name: uplc::ast::Name {
|
||||
// text: arg.arg_name.get_variable_name().unwrap_or("_").to_string(),
|
||||
// unique: Unique::new(0),
|
||||
// },
|
||||
// body: Rc::new(term),
|
||||
// }
|
||||
// }
|
||||
|
||||
// let mut program = Program {
|
||||
// version: (1, 0, 0),
|
||||
// term,
|
||||
// };
|
||||
|
||||
// let mut interner = Interner::new();
|
||||
|
||||
// println!("{}", program.to_pretty());
|
||||
|
||||
// interner.program(&mut program);
|
||||
|
||||
// program
|
||||
}
|
||||
|
||||
pub(crate) fn build_ir(&mut self, body: &TypedExpr, ir_stack: &mut Vec<IR>) {
|
||||
match body {
|
||||
TypedExpr::Int { value, .. } => ir_stack.push(IR::Int {
|
||||
value: value.to_string(),
|
||||
}),
|
||||
TypedExpr::String { value, .. } => ir_stack.push(IR::String {
|
||||
value: value.to_string(),
|
||||
}),
|
||||
TypedExpr::ByteArray { bytes, .. } => ir_stack.push(IR::ByteArray {
|
||||
bytes: bytes.to_vec(),
|
||||
}),
|
||||
TypedExpr::Sequence { expressions, .. } => {
|
||||
for expr in expressions {
|
||||
self.build_ir(expr, ir_stack);
|
||||
}
|
||||
}
|
||||
TypedExpr::Pipeline { expressions, .. } => {
|
||||
for expr in expressions {
|
||||
self.build_ir(expr, ir_stack);
|
||||
}
|
||||
}
|
||||
TypedExpr::Var {
|
||||
constructor, name, ..
|
||||
} => {
|
||||
ir_stack.push(IR::Var {
|
||||
constructor: constructor.clone(),
|
||||
name: name.clone(),
|
||||
});
|
||||
|
||||
// Add constructor information here?
|
||||
}
|
||||
TypedExpr::Fn { .. } => todo!(),
|
||||
TypedExpr::List { elements, tail, .. } => {
|
||||
ir_stack.push(IR::List {
|
||||
count: if tail.is_some() {
|
||||
elements.len() + 1
|
||||
} else {
|
||||
elements.len()
|
||||
},
|
||||
});
|
||||
for element in elements {
|
||||
self.build_ir(element, ir_stack)
|
||||
}
|
||||
if let Some(tail) = tail {
|
||||
ir_stack.push(IR::Tail { count: 1 });
|
||||
self.build_ir(tail, ir_stack);
|
||||
}
|
||||
}
|
||||
TypedExpr::Call { fun, args, .. } => {
|
||||
ir_stack.push(IR::Call {
|
||||
count: args.len() + 1,
|
||||
});
|
||||
self.build_ir(fun, ir_stack);
|
||||
|
||||
for arg in args {
|
||||
self.build_ir(&arg.value, ir_stack);
|
||||
}
|
||||
}
|
||||
TypedExpr::BinOp {
|
||||
name, left, right, ..
|
||||
} => {
|
||||
ir_stack.push(IR::BinOp {
|
||||
name: *name,
|
||||
count: 2,
|
||||
});
|
||||
self.build_ir(left, ir_stack);
|
||||
self.build_ir(right, ir_stack);
|
||||
}
|
||||
TypedExpr::Assignment {
|
||||
value,
|
||||
pattern,
|
||||
kind,
|
||||
..
|
||||
} => {
|
||||
let mut define_vec: Vec<IR> = vec![];
|
||||
let mut value_vec: Vec<IR> = vec![];
|
||||
let mut pattern_vec: Vec<IR> = vec![];
|
||||
pattern_vec.push(IR::Assignment {
|
||||
count: 3,
|
||||
kind: *kind,
|
||||
});
|
||||
|
||||
self.build_ir(value, &mut value_vec);
|
||||
self.define_ir(&value_vec, &mut define_vec);
|
||||
|
||||
self.pattern_ir(pattern, &mut pattern_vec);
|
||||
|
||||
for define in define_vec {
|
||||
ir_stack.push(define);
|
||||
}
|
||||
for pattern in pattern_vec {
|
||||
ir_stack.push(pattern);
|
||||
}
|
||||
for value in value_vec {
|
||||
ir_stack.push(value);
|
||||
}
|
||||
}
|
||||
TypedExpr::Try { .. } => todo!(),
|
||||
TypedExpr::When {
|
||||
subjects, clauses, ..
|
||||
} => {
|
||||
// assuming one subject at the moment
|
||||
ir_stack.push(IR::When {
|
||||
count: clauses.len() + 1,
|
||||
});
|
||||
let subject = subjects[0].clone();
|
||||
|
||||
self.build_ir(&subject, ir_stack);
|
||||
|
||||
if let Some((last_clause, clauses)) = clauses.split_last() {
|
||||
for clause in clauses {
|
||||
ir_stack.push(IR::Clause { count: 2 });
|
||||
self.pattern_ir(&clause.pattern[0], ir_stack);
|
||||
self.build_ir(&clause.then, ir_stack);
|
||||
}
|
||||
let last_pattern = &last_clause.pattern[0];
|
||||
|
||||
let mut pattern_vec = vec![];
|
||||
let mut value_vec = vec![];
|
||||
|
||||
self.pattern_ir(last_pattern, &mut pattern_vec);
|
||||
self.build_ir(&last_clause.then, &mut value_vec);
|
||||
|
||||
let mut final_vec = vec![];
|
||||
|
||||
final_vec.push(IR::Finally { count: 1 });
|
||||
|
||||
let pattern_field_map = match last_pattern {
|
||||
crate::ast::Pattern::Int { .. } => todo!(),
|
||||
crate::ast::Pattern::String { .. } => todo!(),
|
||||
crate::ast::Pattern::Var { .. } => todo!(),
|
||||
crate::ast::Pattern::VarUsage { .. } => todo!(),
|
||||
crate::ast::Pattern::Assign { .. } => todo!(),
|
||||
crate::ast::Pattern::Discard { name, location } => todo!(),
|
||||
crate::ast::Pattern::List { .. } => todo!(),
|
||||
crate::ast::Pattern::Constructor {
|
||||
is_record,
|
||||
location,
|
||||
name,
|
||||
arguments,
|
||||
module,
|
||||
constructor,
|
||||
with_spread,
|
||||
tipo,
|
||||
} => {
|
||||
let data_type_key = DataTypeKey {
|
||||
module_name: module.clone().unwrap_or_default(),
|
||||
defined_type: name.to_string(),
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
// ir_stack.push(IR::Finally {
|
||||
// count: ,
|
||||
// });
|
||||
};
|
||||
}
|
||||
TypedExpr::If {
|
||||
location,
|
||||
branches,
|
||||
final_else,
|
||||
tipo,
|
||||
} => todo!(),
|
||||
TypedExpr::RecordAccess {
|
||||
location,
|
||||
tipo,
|
||||
label,
|
||||
index,
|
||||
record,
|
||||
} => todo!(),
|
||||
TypedExpr::ModuleSelect {
|
||||
location,
|
||||
tipo,
|
||||
label,
|
||||
module_name,
|
||||
module_alias,
|
||||
constructor,
|
||||
} => todo!(),
|
||||
TypedExpr::Todo {
|
||||
location,
|
||||
label,
|
||||
tipo,
|
||||
} => todo!(),
|
||||
TypedExpr::RecordUpdate {
|
||||
location,
|
||||
tipo,
|
||||
spread,
|
||||
args,
|
||||
} => todo!(),
|
||||
TypedExpr::Negate { location, value } => todo!(),
|
||||
}
|
||||
}
|
||||
|
||||
fn define_ir(&self, value_vec: &Vec<IR>, define_vec: &mut Vec<IR>) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn pattern_ir(
|
||||
&self,
|
||||
pattern: &crate::ast::Pattern<tipo::PatternConstructor, Arc<tipo::Type>>,
|
||||
pattern_vec: &mut Vec<IR>,
|
||||
) {
|
||||
todo!()
|
||||
}
|
||||
}
|
|
@ -11,8 +11,8 @@ pub type Redeemer {
|
|||
}
|
||||
|
||||
pub type Reen {
|
||||
Buy { signer: ByteArray, amount: Int }
|
||||
Sell
|
||||
Buy1 { signer: ByteArray, amount: Int }
|
||||
Sell1
|
||||
}
|
||||
|
||||
pub fn twice(f: fn(Int) -> Int, initial: Int) -> Int {
|
||||
|
@ -43,13 +43,14 @@ pub fn who(a: ByteArray) -> ByteArray {
|
|||
builtin.append_bytearray(a, #[12, 255])
|
||||
}
|
||||
|
||||
pub fn spend(
|
||||
datum: sample.Datum,
|
||||
rdmr: Redeemer,
|
||||
ctx: spend.ScriptContext,
|
||||
) -> Bool {
|
||||
when [1, 2, 3] is {
|
||||
[a, b, ..] -> True
|
||||
[] -> False
|
||||
pub type Datum {
|
||||
Buy
|
||||
Sell
|
||||
}
|
||||
|
||||
pub fn spend(datum: Datum, _rdmr: Nil, _ctx: Nil) -> Bool {
|
||||
when datum is {
|
||||
Sell -> True
|
||||
Buy -> False
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue