create ir and start to replace plutus code gen with ir

This commit is contained in:
Kasey White 2022-11-26 02:50:49 -05:00 committed by Lucas
parent 6870a5cab7
commit 2a00b896fc
4 changed files with 581 additions and 10 deletions

203
crates/lang/src/ir.rs Normal file
View File

@ -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)] ]

View File

@ -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 {

365
crates/lang/src/uplc_two.rs Normal file
View File

@ -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!()
}
}

View File

@ -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
}
}