Amo/src/parser/infix.rs

251 lines
7.1 KiB
Rust

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<TightExpr>, Vec< TightExpr>);
pub trait GenIR {
fn gen_ir(
self,
bindings: &BindingScope,
parent: &Identifier,
index: u32,
type_context: bool,
) -> ir::Result<LinkedList<ir::expr::Expr>>;
}
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<NextRank: GenIR, NextRank2: GenIR, Op: InfixOp> GenIR for (NextRank, Vec<(Op, NextRank2)>) {
fn gen_ir(
self,
bindings: &BindingScope,
parent: &Identifier,
index: u32,
type_context: bool,
) -> ir::Result<LinkedList<ir::expr::Expr>> {
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<NextRank: GenIR, Op: InfixOp> GenIR for (LinkedList<Expr>, Vec<(Op, NextRank)>) {
fn gen_ir(
self,
bindings: &BindingScope,
parent: &Identifier,
index: u32,
type_context: bool,
) -> ir::Result<LinkedList<ir::expr::Expr>> {
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<dyn FnOnce(LinkedList<ir::expr::Expr>) -> ir::Result<LinkedList<ir::expr::Expr>>>) =
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<Rank5Exp>);
impl GenIR for Rank7Exp {
fn gen_ir(
self,
bindings: &BindingScope,
parent: &Identifier,
index: u32,
type_context: bool,
) -> ir::Result<LinkedList<ir::expr::Expr>> {
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<LinkedList<ir::expr::Expr>> {
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<G: GenIR> GenIR for Box<G> {
fn gen_ir(
self,
bindings: &BindingScope,
parent: &Identifier,
index: u32,
type_context: bool,
) -> ir::Result<LinkedList<ir::expr::Expr>> {
(*self).gen_ir(bindings, parent, index, type_context)
}
}