251 lines
7.1 KiB
Rust
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)
|
|
}
|
|
}
|