use std::collections::LinkedList; use crate::{token::{InfixRank1, InfixRank2, InfixRank3, InfixRank5, InfixRank6, Literal, InfixRank4}, ir::{BindingScope, Identifier, self, expr::{get_last_ident, Operation, Expr}, IrError, value::Value}, join, cons_ll, cons}; use super::expr::TightExpr; pub type Rank1Exp = (Rank2Exp, Vec<(InfixRank1, Rank2Exp)>); pub type Rank2Exp = (Rank3Exp, Vec<(InfixRank2, Rank3Exp)>); pub type Rank3Exp = (Rank4Exp, Vec<(InfixRank3, Rank4Exp)>); pub type Rank4Exp = (Rank5Exp, Vec<(InfixRank4, Rank5Exp)>); pub type Rank5Exp = (Rank6Exp, Vec<(InfixRank5, Rank6Exp)>); pub type Rank6Exp = (Rank7Exp, Vec<(InfixRank6, Rank7Exp)>); pub type Rank7Exp = (Box, Vec< TightExpr>); pub trait GenIR { fn gen_ir( self, bindings: &BindingScope, parent: &Identifier, index: u32, type_context: bool, ) -> ir::Result>; } pub enum Direction { LeftToRight, RightToLeft } pub trait InfixOp { fn gen_ir(&self) -> Operation; fn direction(&self) -> Direction { Direction::LeftToRight } } impl InfixOp for InfixRank1 { fn gen_ir(&self) -> Operation { match self { Self::LOr => Operation::LOr, Self::VBar => Operation::VariantUnion, } } } impl InfixOp for InfixRank2 { fn gen_ir(&self) -> Operation { match self { Self::LAnd => Operation::LAnd, Self::Aro => Operation::FunctionType, } } fn direction(&self) -> Direction { match self { Self::LAnd => Direction::LeftToRight, Self::Aro => Direction::RightToLeft, } } } impl InfixOp for InfixRank3 { fn gen_ir(&self) -> Operation { match self { Self::Eq => Operation::Eq, Self::NEq => Operation::NEq, Self::LessThan => Operation::LessThan, Self::GreaterThan => Operation::GreaterThan, } } } impl InfixOp for InfixRank4 { fn gen_ir(&self) -> Operation { Operation::Range } } impl InfixOp for InfixRank5 { fn gen_ir(&self) -> Operation { match self { Self::Add => Operation::Add, Self::Sub => Operation::Sub, } } } impl InfixOp for InfixRank6 { fn gen_ir(&self) -> Operation { match self { Self::Mul => Operation::Mul, Self::Mod => Operation::Mod, Self::Div => Operation::Div, } } } impl GenIR for (NextRank, Vec<(Op, NextRank2)>) { fn gen_ir( self, bindings: &BindingScope, parent: &Identifier, index: u32, type_context: bool, ) -> ir::Result> { let (first_arg, ops) = self; if !ops.is_empty() { let ident = parent.subid_with_name(String::new(), index); let prior_expressions = first_arg.gen_ir(bindings, &ident, 0, type_context)?; (prior_expressions, ops).gen_ir(bindings, &ident, 1, type_context) } else { first_arg.gen_ir(bindings, parent, index, type_context) } } } impl GenIR for (LinkedList, Vec<(Op, NextRank)>) { fn gen_ir( self, bindings: &BindingScope, parent: &Identifier, index: u32, type_context: bool, ) -> ir::Result> { let (first_arg_exprs, mut ops) = self; if let Some((this_op, second_arg)) = ops.pop() { let this_ident = parent.subid_with_name(String::new(), index); let direction = this_op.direction(); let (second_arg_exprs, finish_result): (_, Box) -> ir::Result>>) = match direction { Direction::LeftToRight => ( second_arg.gen_ir(bindings, parent, index + 1, type_context)?, Box::new(|all_exprs| (all_exprs, ops).gen_ir(bindings, parent, index + 2, type_context)), ), Direction::RightToLeft => ( (second_arg, ops).gen_ir(bindings, parent, index + 1, type_context)?, Box::new(|all_exprs| ir::Result::Ok(all_exprs)) ), }; let op = this_op.gen_ir(); let first_arg_ident = get_last_ident(&first_arg_exprs).ok_or(IrError::MissingExpression)?; let second_arg_ident = get_last_ident(&second_arg_exprs).ok_or(IrError::MissingExpression)?; let first_arg_name = &first_arg_ident.0; let second_arg_name = &second_arg_ident.0; let final_name = format!("{first_arg_name}-{op:?}-{second_arg_name}"); let this_ident = this_ident.set_name(final_name); let new_expr = ir::expr::Expr { identifier: this_ident, operation: op, formals: vec![first_arg_ident, second_arg_ident], }; let all_prior_exprs = join(first_arg_exprs, second_arg_exprs); let all_exprs = cons_ll(all_prior_exprs, new_expr); finish_result(all_exprs) } else { Ok(first_arg_exprs) } } } //pub tsecond_arg.gen_ir(bindings, parent, index + 1, type_context)ype Rank4Exp = (TightExpr, Vec); impl GenIR for Rank7Exp { fn gen_ir( self, bindings: &BindingScope, parent: &Identifier, index: u32, type_context: bool, ) -> ir::Result> { let (thing_to_be_called, arguments) = self; if arguments.is_empty() { thing_to_be_called.gen_ir(bindings, parent, index, type_context) } else { let this_ident = parent.subid_with_name(String::new() /*will replace*/, index); let n_args = arguments.len() + 1; let (arg_idents, prior_exprs) = Some(*thing_to_be_called) .into_iter() .chain(arguments) .enumerate() .map(|(i, arg)| arg.gen_ir(bindings, &this_ident, i as u32, type_context)) .try_fold( (Vec::with_capacity(n_args), LinkedList::new()), |(idents, exprs), new_exprs| new_exprs.and_then(|new_exprs2| Ok(( cons( idents, get_last_ident(&new_exprs2).ok_or(IrError::MissingExpression)? ), join(exprs, new_exprs2) )) ) )?; let call_ident_name = &arg_idents.get(0).ok_or(IrError::MissingExpression)?.0; let new_ident_name = format!("{call_ident_name}_result"); let new_expr = ir::expr::Expr { identifier: this_ident.set_name(new_ident_name), operation: Operation::Call, formals: arg_idents, }; Ok(cons_ll(prior_exprs, new_expr)) } } } impl GenIR for TightExpr { fn gen_ir( self, bindings: &BindingScope, parent: &Identifier, index: u32, type_context: bool, ) -> ir::Result> { match self { TightExpr::Literal(l) => { let value = match l { Literal::String(s) => Value::String(s), Literal::Int(i) => Value::Int(i as usize), }; let expr = ir::expr::Expr { identifier: parent.subid_with_name(format!("literal"), index), operation: Operation::Const(value), formals: Vec::new(), }; Ok(LinkedList::from([expr])) }, TightExpr::Grouped(e) => e.gen_ir(bindings, parent, index, type_context), TightExpr::Symbol(s) => if let Some(ident) = bindings.lookup(&s) { Ok(LinkedList::from([Expr { identifier: ident.clone(), operation: Operation::NoOp, formals: Vec::new(), }])) } else if type_context { todo!("Custom types aren't implemented yet") } else { Err(IrError::Undefined(s)) }, } } } impl GenIR for Box { fn gen_ir( self, bindings: &BindingScope, parent: &Identifier, index: u32, type_context: bool, ) -> ir::Result> { (*self).gen_ir(bindings, parent, index, type_context) } }