diff --git a/crates/lang/src/ir.rs b/crates/lang/src/ir.rs new file mode 100644 index 00000000..58c043fd --- /dev/null +++ b/crates/lang/src/ir.rs @@ -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, + }, + + Var { + constructor: ValueConstructor, + name: String, + }, + + // Fn { + // tipo: Arc, + // is_capture: bool, + // args: Vec>>, + // body: Box, + // return_annotation: Option, + // }, + 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, + // value: Box, + // then: Box, + // pattern: Pattern>, + // }, + 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, + // label: String, + // module_name: String, + // module_alias: String, + // constructor: ModuleValueConstructor, + // }, + + // Tuple { + // + // tipo: Arc, + // elems: Vec, + // }, + + // TupleIndex { + // + // tipo: Arc, + // index: u64, + // tuple: Box, + // }, + Todo { + label: Option, + tipo: Arc, + }, + + RecordUpdate { + tipo: Arc, + spread: Box, + args: Vec, + }, + + Negate { + value: Box, + }, +} + +// 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)] ] diff --git a/crates/lang/src/lib.rs b/crates/lang/src/lib.rs index ff60f69e..a3bd8253 100644 --- a/crates/lang/src/lib.rs +++ b/crates/lang/src/lib.rs @@ -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 { diff --git a/crates/lang/src/uplc_two.rs b/crates/lang/src/uplc_two.rs new file mode 100644 index 00000000..b0630dd9 --- /dev/null +++ b/crates/lang/src/uplc_two.rs @@ -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)>, + // uplc_function_holder_lookup: IndexMap, + // uplc_data_holder_lookup: IndexMap, + // uplc_data_constr_lookup: IndexMap, + // uplc_data_usage_holder_lookup: IndexMap, + function_recurse_lookup: IndexMap, + functions: &'a HashMap, TypedExpr>>, + // type_aliases: &'a HashMap<(String, String), &'a TypeAlias>>, + data_types: &'a HashMap>>, + // imports: &'a HashMap<(String, String), &'a Use>, + // constants: &'a HashMap<(String, String), &'a ModuleConstant, String>>, +} + +impl<'a> CodeGenerator<'a> { + pub fn new( + functions: &'a HashMap, TypedExpr>>, + // type_aliases: &'a HashMap<(String, String), &'a TypeAlias>>, + data_types: &'a HashMap>>, + // imports: &'a HashMap<(String, String), &'a Use>, + // constants: &'a HashMap<(String, String), &'a ModuleConstant, 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) -> Program { + 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) { + 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 = vec![]; + let mut value_vec: Vec = vec![]; + let mut pattern_vec: Vec = 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, define_vec: &mut Vec) { + todo!() + } + + fn pattern_ir( + &self, + pattern: &crate::ast::Pattern>, + pattern_vec: &mut Vec, + ) { + todo!() + } +} diff --git a/examples/sample/validators/swap.ak b/examples/sample/validators/swap.ak index b18bf996..457aee44 100644 --- a/examples/sample/validators/swap.ak +++ b/examples/sample/validators/swap.ak @@ -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 } }