use std::fmt::Display;
use crate::{ccarp::error::{c2rust_err, safe_unwrap, safe_remove, CCErr, Result}, ccarp_c::{decl::{InitialiserList, SpecifierQualifier}, expr::*}};
use super::{defs::{print_vec, CastInto, Context, Eval, GetType, RFrom, RInto}, rustdecl::{RInit, RType}, rustexpr_helper::tricky_syntax, rustprimitives::{RIdent, RLit, TypedIdent}};
macro_rules! bin_rfrom {
($from:ty,$for:ty,$rhs:ty,$def:ident,$($op:pat => $id:ident),+) => {
impl RFrom<$from> for $for {
fn rfrom(value: $from, context: &mut Context) -> Result<Self> {
let mut val=value;
let last=val.1.pop();
match last {
Some((op,current)) => {
let mut lhs: $for=val.rinto(context)?;
let mut rhs: $rhs=current.rinto(context)?;
let ty=RType::stronger(lhs.get_type().get_type_alias(), rhs.get_type().get_type_alias());
if let Some(ty)=ty {
lhs=lhs.cast(&ty);
rhs=rhs.cast(&ty);
}
match op {
$(
$op => Ok(Self::$id(Box::new(lhs), rhs)),
)+
}
},
None => Ok(Self::$def((*val.0).rinto(context)?)),
}
}
}
};
($from:ty,$for:ty,$rhs:ty,$def:ident,$other:ident;) => {
impl RFrom<$from> for $for {
fn rfrom(value: $from, context: &mut Context) -> Result<Self> {
let mut val=value;
let last=safe_unwrap!(val.0.pop();"Expression","Expression");
if val.0.is_empty() { Ok(Self::$def(last.rinto(context)?)) }
else {
let mut lhs: $for=val.rinto(context)?;
let mut rhs: $rhs=last.rinto(context)?;
let ty=RType::stronger(lhs.get_type().get_type_alias(), rhs.get_type().get_type_alias());
if let Some(ty)=ty {
lhs=lhs.cast(&ty);
rhs=rhs.cast(&ty);
}
Ok(Self::$other(Box::new(lhs), rhs))
}
}
}
};
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum RPrimaryExpr {
Lit(RLit),
Ident(TypedIdent),
RInit(Box<RInit>), Expr(Box<RExpr>) }
impl RFrom<PrimaryExpr> for RPrimaryExpr {
fn rfrom(value: PrimaryExpr, context: &mut Context) -> Result<Self> {
match value {
PrimaryExpr::Literal(literal) => Ok(Self::Lit(literal.into())),
PrimaryExpr::Ident(identifier) => Ok(Self::Ident(RIdent::from(identifier).rinto(context)?)),
PrimaryExpr::Expr(expression) => Ok(Self::Expr(Box::new(RExpr::rfrom(*expression,context)?))),
}
}
}
impl Display for RPrimaryExpr {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Lit(literal) => write!(f,"{literal}"),
Self::Ident(identifier) => write!(f,"{identifier}"),
Self::Expr(expression) => write!(f,"({expression})"),
Self::RInit(rinit) => write!(f,"{rinit}"),
}
}
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum RField {
Field(RIdent), UnsafeField(RIdent), Method(RIdent, Vec<RExpr>), UnsafeMethod(RIdent, Vec<RExpr>) }
impl Display for RField {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Field(rident)|Self::UnsafeField(rident) => write!(f,"{rident}"),
Self::Method(rident,args)|Self::UnsafeMethod(rident, args) => write!(f,"{rident}({})",print_vec(args, ",")),
}
}
}
#[derive(Debug, PartialEq, Eq, Clone, Default)]
pub struct RFieldExpr(pub RPrimaryExpr,pub Vec<RField>, pub RType);
impl Display for RFieldExpr {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if self.1.is_empty() { write!(f,"{}",self.0) }
else if self.1.iter().any(|x| matches!(x,RField::UnsafeField(_)|RField::UnsafeMethod(..))) {
write!(f,"unsafe {{{}.{}}}",self.0,print_vec(&self.1, "."))
}
else { write!(f,"{}.{}",self.0,print_vec(&self.1, ".")) }
}
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum RPostfixExpr {
Field(Box<RFieldExpr>),
Func(Box<RPostfixExpr>,Vec<RAssignExpr>,RType), Array(Box<RPostfixExpr>,Box<RExpr>), Sizeof(Box<RUnaryExpr>), SizeofType(RType) }
impl RFrom<PostfixExpr> for RPostfixExpr {
fn rfrom(value: PostfixExpr, context: &mut Context) -> Result<Self> {
match value {
PostfixExpr::Primary(primary_expr, postfixes) => Self::primary(*primary_expr, postfixes, context),
PostfixExpr::List(ty, init) => {
let mut inits=vec![];
for mut i in init { inits.append(&mut i.0); }
let rinit=RInit::rfrom((InitialiserList(inits),<(RType,_)>::rfrom(*ty,context)?.0),context)?;
Ok(Self::Field(Box::new(rinit.into())))
},
}
}
}
impl Display for RPostfixExpr {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Field(rfield_expr) => write!(f,"{rfield_expr}"),
Self::Func(rpostfix_expr, rassign_expr,_) => write!(f,"{rpostfix_expr}({})",print_vec(rassign_expr, ", ")),
Self::Array(rpostfix_expr, rexpr) => write!(f,"{rpostfix_expr}[{rexpr}]"),
Self::Sizeof(runary_expr) => write!(f,"size_of_val(&{runary_expr})"),
Self::SizeofType(rtype) => write!(f,"size_of::<{rtype}>()"),
}
}
}
impl RPostfixExpr {
fn primary(primary_expr: PrimaryExpr, postfixes: Vec<Postfix>, context: &mut Context) -> Result<Self> {
let mut post=Self::Field(Box::new(RPrimaryExpr::rfrom(primary_expr,context)?.into()));
for postfix in postfixes {
match postfix {
Postfix::Brackets(expression) => {
let index=RExpr::rfrom(*expression,context)?;
let ty=post.get_type().get_type_alias();
post=
match ty {
RType::ThinPoint(rtype)|RType::ThinPointMut(rtype) => {
post.insert_field(RField::UnsafeMethod(RIdent("index".to_string()), vec![index.cast(&RType::Usize)]), *rtype); post
},
RType::Point(rtype)|RType::PointMut(rtype) => {
post.insert_field(RField::UnsafeMethod(RIdent("as_ref().unwrap".to_string()), vec![]), RType::Ref(vec![], rtype)); Self::Array(Box::new(post), Box::new(index.cast(&RType::Usize)))
},
_ => Self::Array(Box::new(post), Box::new(index.cast(&RType::Usize))),
};
},
Postfix::Function(argument_expr_list) => {
let fn_ty=post.get_type().get_type_alias();
let mut arg_list=vec![];
let (args,ty)=
if let RType::Function(args, ret)=fn_ty {
for (arg,ty) in argument_expr_list.0.into_iter().zip(args) {
arg_list.push(RAssignExpr::rfrom(arg,context)?.cast(&ty));
}
(arg_list,*ret)
}
else {
for x in argument_expr_list.0 { arg_list.push(x.rinto(context)?); }
(arg_list,context.get_fn_return_value(&post).ok_or_else(|| c2rust_err!("Could not find return value of function '{post}' in context!"))?)
};
post=Self::Func(Box::new(post), args, ty);
},
Postfix::Dot(identifier)|Postfix::Arrow(identifier) => {
let ty=post.get_type().get_type_alias();
let field=
if matches!(ty,RType::Union(_)|RType::UnionDecl(..)) { RField::UnsafeField(identifier.into()) } else { RField::Field(identifier.into()) };
let ty=context.get_field_ty(ty.clone(),&field).ok_or_else(|| c2rust_err!("Could not find field ('{field}') type of struct/union '{ty}' in context!"))?;
post.insert_field(field,ty);
},
Postfix::Inc => {
let ty=post.get_type().get_type_alias();
let field=
if matches!(ty,RType::Point(_)|RType::PointMut(_)|RType::ThinPoint(_)|RType::ThinPointMut(_)) {
RField::UnsafeMethod(RIdent("inc_post".to_string()),vec![])
} else { RField::Method(RIdent("inc_post".to_string()),vec![]) };
post.insert_field(field,ty);
},
Postfix::Dec => {
let ty=post.get_type().get_type_alias();
let field=
if matches!(ty,RType::Point(_)|RType::PointMut(_)|RType::ThinPoint(_)|RType::ThinPointMut(_)) {
RField::UnsafeMethod(RIdent("dec_post".to_string()),vec![])
} else { RField::Method(RIdent("dec_post".to_string()),vec![]) };
post.insert_field(field,ty);
},
}
}
Ok(post)
}
}
macro_rules! unary {
($id:ident, $cast:expr, $context:expr) => {
{
let rcast=RCastExpr::rfrom(*$cast, $context)?;
match rcast {
RCastExpr::Unary(unary) => Ok(Self::Unary(RUnaryExpr::$id(Box::new(unary)))),
RCastExpr::Cast(..) => Ok(Self::Unary(RUnaryExpr::$id(Box::new(RExpr::from(rcast).into())))),
}
}
};
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum RUnaryExpr {
Postfix(Box<RPostfixExpr>),
Minus(Box<RUnaryExpr>), Deref(Box<RUnaryExpr>), Not(Box<RUnaryExpr>), Ref(Box<RUnaryExpr>), RefMut(Box<RUnaryExpr>) }
impl RFrom<UnaryExpr> for RCastExpr {
fn rfrom(value: UnaryExpr, context: &mut Context) -> Result<Self> {
match value {
UnaryExpr::Postfix(postfix_expr) => Ok(Self::Unary(RUnaryExpr::Postfix(Box::new((*postfix_expr).rinto(context)?)))),
UnaryExpr::Inc(unary_expr) => {
let mut c=Self::rfrom(*unary_expr, context)?;
let ty=c.get_type().get_type_alias();
if matches!(ty,RType::Point(_)|RType::PointMut(_)|RType::ThinPoint(_)|RType::ThinPointMut(_)) {
c.insert_field(RField::UnsafeMethod(RIdent("pre_inc".to_string()),vec![]),ty);
}
else { c.insert_field(RField::Method(RIdent("pre_inc".to_string()),vec![]),ty); }
Ok(c)
},
UnaryExpr::Dec(unary_expr) => {
let mut c=Self::rfrom(*unary_expr, context)?;
let ty=c.get_type().get_type_alias();
if matches!(ty,RType::Point(_)|RType::PointMut(_)|RType::ThinPoint(_)|RType::ThinPointMut(_)) {
c.insert_field(RField::UnsafeMethod(RIdent("pre_dec".to_string()),vec![]),ty);
}
else { c.insert_field(RField::Method(RIdent("pre_dec".to_string()),vec![]),ty); }
Ok(c)
},
UnaryExpr::Ref(cast_expr) => unary!(Ref,cast_expr,context),
UnaryExpr::Deref(cast_expr) => {
let rcast=Self::rfrom(*cast_expr, context)?;
match rcast {
Self::Unary(unary) => Ok(Self::Unary(unary.deref())),
Self::Cast(..) => Ok(Self::Unary(RUnaryExpr::from(RExpr::from(rcast)).deref())),
}
},
UnaryExpr::Plus(cast_expr) => (*cast_expr).rinto(context),
UnaryExpr::Minus(cast_expr) => {
let mut rcast=Self::rfrom(*cast_expr, context)?;
let ty=rcast.get_type().get_type_alias();
if ty.is_unsigned() { rcast=rcast.cast(&ty.get_signed_variant()); }
match rcast {
Self::Unary(unary) => Ok(Self::Unary(RUnaryExpr::Minus(Box::new(unary)))),
Self::Cast(..) => Ok(Self::Unary(RUnaryExpr::Minus(Box::new(RExpr::from(rcast).into())))),
}
},
UnaryExpr::Bnot(cast_expr)|UnaryExpr::Not(cast_expr) => unary!(Not, cast_expr,context),
UnaryExpr::Sizeof(unary_expr) => {
let cast= Self::rfrom(*unary_expr, context)?;
if let Self::Unary(unary) = cast {
Ok(Self::Unary(RUnaryExpr::Postfix(Box::new(RPostfixExpr::Sizeof(Box::new(unary))))))
}
else { Ok(Self::Unary(RExpr::from(cast).into())) }
},
UnaryExpr::SizeofType(type_name) => {
Ok(Self::Unary(RUnaryExpr::Postfix(Box::new(RPostfixExpr::SizeofType(<(RType,_)>::rfrom(*type_name, context)?.0)))))
},
}
}
}
impl Display for RUnaryExpr {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Postfix(rpostfix_expr) => write!(f,"{rpostfix_expr}"),
Self::Minus(runary_expr) => write!(f,"-{runary_expr}"),
Self::Deref(runary_expr) => write!(f,"*{runary_expr}"),
Self::Not(runary_expr) => {
if matches!(runary_expr.get_type().get_type_alias(),RType::BoolI8) { write!(f,"(!({runary_expr}!=0) as i8)") }
else { write!(f,"!{runary_expr}") }
},
Self::Ref(runary_expr) => write!(f,"&{runary_expr}"),
Self::RefMut(runary_expr) => write!(f,"&mut {runary_expr}"),
}
}
}
impl RUnaryExpr {
#[must_use]
pub fn deref(mut self) -> Self {
match self.get_type().get_type_alias() {
RType::Ref(..)|RType::RefMut(..) => {
let postfix=
match self {
Self::Postfix(rpostfix_expr) => *rpostfix_expr,
_ => RPostfixExpr::from(RExpr::from(self))
};
Self::Postfix(Box::new(RPostfixExpr::Array(Box::new(postfix), Box::new(RExpr::from(0)))))
},
RType::Point(rtype)|RType::PointMut(rtype) => {
self.insert_field(RField::UnsafeMethod(RIdent("as_ref().unwrap".to_string()), vec![]), RType::Ref(vec![], rtype));
let postfix=
if let Self::Postfix(post)=self { *post }
else { RPostfixExpr::from(RExpr::from(self)) };
Self::Postfix(Box::new(RPostfixExpr::Array(Box::new(postfix),Box::new(RExpr::from(0)))))
},
RType::ThinRef(..)|RType::ThinRefMut(..) => Self::Deref(Box::new(self)),
RType::ThinPoint(rtype)|RType::ThinPointMut(rtype) => {
self.insert_field(RField::UnsafeMethod(RIdent("as_ref().unwrap".to_string()), vec![]), RType::Ref(vec![], rtype));
Self::Deref(Box::new(self))
},
_ => self }
}
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum RCastExpr {
Unary(RUnaryExpr),
Cast(Box<RCastExpr>,RType) }
impl RFrom<CastExpr> for RCastExpr {
fn rfrom(value: CastExpr, context: &mut Context) -> Result<Self> {
match value {
CastExpr::Unary(unary_expr) => unary_expr.rinto(context),
CastExpr::Cast(mut type_name, cast_expr) => {
tricky_syntax!(type_name,cast_expr,context);
Ok(Self::rfrom(*cast_expr, context)?.cast(&<(RType,_)>::rfrom(*type_name,context)?.0))
},
}
}
}
impl Display for RCastExpr {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Unary(runary_expr) => write!(f,"{runary_expr}"),
Self::Cast(rcast_expr, rtype) => {
match rtype {
RType::Bool => write!(f,"({rcast_expr}!=0)"),
RType::BoolI8 => {
if matches!(rcast_expr.get_type().get_type_alias(),RType::Bool) { write!(f,"{rcast_expr} as {rtype}") }
else if let Ok(val)=rcast_expr.eval(&Context::default()) {
if val==0 || val==1 { write!(f,"{rcast_expr} as {rtype}") }
else { write!(f,"({rcast_expr}!=0) as {rtype}") }
}
else { write!(f,"({rcast_expr}!=0) as {rtype}") }
},
_ => write!(f,"{rcast_expr} as {rtype}")
}
},
}
}
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum RMulExpr {
Cast(RCastExpr),
Mul(Box<RMulExpr>,RCastExpr), Div(Box<RMulExpr>,RCastExpr), Mod(Box<RMulExpr>,RCastExpr), }
bin_rfrom!(MulExpr,RMulExpr,RCastExpr,Cast,MulOp::Mul => Mul,MulOp::Div => Div,MulOp::Mod => Mod);
impl Display for RMulExpr {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Cast(rcast_expr) => write!(f,"{rcast_expr}"),
Self::Mul(rmul_expr, rcast_expr) => write!(f,"{rmul_expr} * {rcast_expr}"),
Self::Div(rmul_expr, rcast_expr) => write!(f,"{rmul_expr} / {rcast_expr}"),
Self::Mod(rmul_expr, rcast_expr) => write!(f,"{rmul_expr} % {rcast_expr}"),
}
}
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum RAddExpr {
Mul(RMulExpr),
Add(Box<RAddExpr>,RMulExpr), Sub(Box<RAddExpr>,RMulExpr) }
impl RFrom<AddExpr> for RAddExpr {
fn rfrom(value: AddExpr, context: &mut Context) -> Result<Self> {
let mut val=value;
let last=val.1.pop();
match last {
Some((op,current)) => {
let mut lhs: Self=val.rinto(context)?;
let mut rhs: RMulExpr=current.rinto(context)?;
let ty=RType::stronger(lhs.get_type().get_type_alias(), rhs.get_type().get_type_alias());
if let Some(ty)=ty {
lhs=lhs.cast(&ty);
rhs=rhs.cast(&ty);
}
match op {
AddOp::Add => {
let ty=lhs.get_type().get_type_alias();
if matches!(ty,RType::Point(_)|RType::PointMut(_)|RType::ThinPoint(_)|RType::ThinPointMut(_)) {
lhs.insert_field(RField::UnsafeMethod(RIdent("c_add".to_string()), vec![rhs.into()]), ty);
Ok(lhs)
}
else { Ok(Self::Add(Box::new(lhs), rhs)) }
},
AddOp::Sub => {
let ty=lhs.get_type().get_type_alias();
if matches!(ty,RType::Point(_)|RType::PointMut(_)|RType::ThinPoint(_)|RType::ThinPointMut(_)) {
lhs.insert_field(RField::UnsafeMethod(RIdent("c_sub".to_string()), vec![rhs.into()]), ty);
Ok(lhs)
}
else { Ok(Self::Sub(Box::new(lhs), rhs)) }
}
}
},
None => Ok(Self::Mul((*val.0).rinto(context)?)),
}
}
}
impl Display for RAddExpr {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Mul(rmul_expr) => write!(f,"{rmul_expr}"),
Self::Add(radd_expr, rmul_expr) => write!(f,"{radd_expr} + {rmul_expr}"),
Self::Sub(radd_expr, rmul_expr) => write!(f,"{radd_expr} - {rmul_expr}"),
}
}
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum RShiftExpr {
Add(RAddExpr),
LShift(Box<RShiftExpr>,RAddExpr), RShift(Box<RShiftExpr>,RAddExpr) }
bin_rfrom!(ShiftExpr,RShiftExpr,RAddExpr,Add,ShiftOp::LShift => LShift,ShiftOp::RShift => RShift);
impl Display for RShiftExpr {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Add(radd_expr) => write!(f,"{radd_expr}"),
Self::LShift(rshift_expr, radd_expr) => write!(f,"{rshift_expr} << {radd_expr}"),
Self::RShift(rshift_expr, radd_expr) => write!(f,"{rshift_expr} >> {radd_expr}"),
}
}
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum RAndExpr {
Shift(RShiftExpr),
And(Box<RAndExpr>,RShiftExpr) }
impl RFrom<AndExpr> for RAndExpr {
fn rfrom(value: AndExpr, context: &mut Context) -> Result<Self> {
let mut val=value;
let last=RCompExpr::rfrom(safe_unwrap!(val.0.pop();"Eq Expression Chain","Binary And Expression"),context)?;
if val.0.is_empty() {
if let RCompExpr::Or(ROrExpr::Xor(RXorExpr::And(and)))=last { Ok(and) }
else { Ok(Self::Shift(RExpr::from(last).into())) }
}
else {
let sh=
if let RCompExpr::Or(ROrExpr::Xor(RXorExpr::And(Self::Shift(sh)))) = last { sh }
else { RExpr::from(last).into() };
let mut lhs: Self=val.rinto(context)?;
let mut rhs=sh;
let ty=RType::stronger(lhs.get_type().get_type_alias(), rhs.get_type().get_type_alias());
if let Some(ty)=ty {
lhs=lhs.cast(&ty);
rhs=rhs.cast(&ty);
}
Ok(Self::And(Box::new(lhs), rhs))
}
}
}
impl Display for RAndExpr {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Shift(rshift_expr) => write!(f,"{rshift_expr}"),
Self::And(rand_expr, rshift_expr) => write!(f,"{rand_expr} & {rshift_expr}"),
}
}
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum RXorExpr {
And(RAndExpr),
Xor(Box<RXorExpr>,RAndExpr) }
bin_rfrom!(XorExpr,RXorExpr,RAndExpr,And,Xor;);
impl Display for RXorExpr {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::And(rand_expr) => write!(f,"{rand_expr}"),
Self::Xor(rxor_expr, rand_expr) => write!(f,"{rxor_expr} ^ {rand_expr}"),
}
}
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum ROrExpr {
Xor(RXorExpr),
Or(Box<ROrExpr>,RXorExpr) }
bin_rfrom!(OrExpr,ROrExpr,RXorExpr,Xor,Or;);
impl Display for ROrExpr {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Xor(rxor_expr) => write!(f,"{rxor_expr}"),
Self::Or(ror_expr, xor_expr) => write!(f,"{ror_expr} | {xor_expr}"),
}
}
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum RCompExpr {
Or(ROrExpr),
Eq(Box<RCompExpr>,ROrExpr), Neq(Box<RCompExpr>,ROrExpr), Gt(Box<RCompExpr>,ROrExpr), Lt(Box<RCompExpr>,ROrExpr), Gte(Box<RCompExpr>,ROrExpr), Lte(Box<RCompExpr>,ROrExpr), }
impl RFrom<EqExpr> for RCompExpr {
fn rfrom(value: EqExpr, context: &mut Context) -> Result<Self> {
let mut val=value;
let last=val.1.pop();
match last {
Some((op,current)) => {
let comp=Self::rfrom(current,context)?;
let or=
if let Self::Or(ror_expr)=comp { ror_expr }
else { RExpr::from(comp).into() };
let mut lhs: Self=val.rinto(context)?;
let mut rhs=or;
let ty=RType::stronger(lhs.get_type().get_type_alias(), rhs.get_type().get_type_alias());
if let Some(ty)=ty {
lhs=lhs.cast(&ty);
rhs=rhs.cast(&ty);
}
match op {
EqOp::Eq => Ok(Self::Eq(Box::new(lhs), rhs)),
EqOp::Neq => Ok(Self::Neq(Box::new(lhs), rhs)),
}
},
None => (*val.0).rinto(context),
}
}
}
impl RFrom<RelExpr> for RCompExpr {
fn rfrom(value: RelExpr, context: &mut Context) -> Result<Self> {
let mut val=value;
let last=val.1.pop();
match last {
Some((op,current)) => {
let or=ROrExpr::Xor(RXorExpr::And(RAndExpr::Shift(current.rinto(context)?)));
let mut lhs: Self=val.rinto(context)?;
let mut rhs=or;
let ty=RType::stronger(lhs.get_type().get_type_alias(), rhs.get_type().get_type_alias());
if let Some(ty)=ty {
lhs=lhs.cast(&ty);
rhs=rhs.cast(&ty);
}
match op {
RelOp::Gt => Ok(Self::Gt(Box::new(lhs), rhs)),
RelOp::Lt => Ok(Self::Lt(Box::new(lhs), rhs)),
RelOp::Gte => Ok(Self::Gte(Box::new(lhs), rhs)),
RelOp::Lte => Ok(Self::Lte(Box::new(lhs), rhs)),
}
},
None => Ok(Self::Or(ROrExpr::Xor(RXorExpr::And(RAndExpr::Shift((*val.0).rinto(context)?))))),
}
}
}
impl Display for RCompExpr {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Or(ror_expr) => write!(f,"{ror_expr}"),
Self::Eq(rcomp_expr, ror_expr) => write!(f,"{rcomp_expr} == {ror_expr}"),
Self::Neq(rcomp_expr, ror_expr) => write!(f,"{rcomp_expr} != {ror_expr}"),
Self::Gt(rcomp_expr, ror_expr) => write!(f,"{rcomp_expr} < {ror_expr}"),
Self::Lt(rcomp_expr, ror_expr) => write!(f,"{rcomp_expr} > {ror_expr}"),
Self::Gte(rcomp_expr, ror_expr) => write!(f,"{rcomp_expr} <= {ror_expr}"),
Self::Lte(rcomp_expr, ror_expr) => write!(f,"{rcomp_expr} >= {ror_expr}"),
}
}
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum RLogAndExpr {
Comp(RCompExpr),
And(Box<RLogAndExpr>,RCompExpr) }
impl RFrom<LogAndExpr> for RLogAndExpr {
fn rfrom(value: LogAndExpr, context: &mut Context) -> Result<Self> {
let mut val=value;
let last=safe_unwrap!(val.0.pop();"Or Expression Chain","Logical And Expression");
if val.0.is_empty() { Ok(Self::Comp(RCompExpr::Or(last.rinto(context)?))) }
else {
let mut lhs: Self=val.rinto(context)?;
let mut rhs=RCompExpr::Or(last.rinto(context)?);
lhs=lhs.cast(&RType::Bool);
rhs=rhs.cast(&RType::Bool);
Ok(Self::And(Box::new(lhs), rhs))
}
}
}
impl Display for RLogAndExpr {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Comp(rcomp_expr) => write!(f,"{rcomp_expr}"),
Self::And(rlog_and_expr, rcomp_expr) => write!(f,"{rlog_and_expr} && {rcomp_expr}"),
}
}
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum RLogOrExpr {
And(RLogAndExpr),
Or(Box<RLogOrExpr>,RLogAndExpr) }
impl RFrom<LogOrExpr> for RLogOrExpr {
fn rfrom(value: LogOrExpr, context: &mut Context) -> Result<Self> {
let mut val=value;
let last=safe_unwrap!(val.0.pop();"Logical And Expression Chain","Logical Or Expression");
if val.0.is_empty() { Ok(Self::And(last.rinto(context)?)) }
else {
let mut lhs: Self=val.rinto(context)?;
let mut rhs: RLogAndExpr=last.rinto(context)?;
lhs=lhs.cast(&RType::Bool);
rhs=rhs.cast(&RType::Bool);
Ok(Self::Or(Box::new(lhs), rhs))
}
}
}
impl Display for RLogOrExpr {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::And(rlog_and_expr) => write!(f,"{rlog_and_expr}"),
Self::Or(rlog_or_expr, rlog_and_expr) => write!(f,"{rlog_or_expr} || {rlog_and_expr}"),
}
}
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum RTernary {
Or(Box<RLogOrExpr>),
Ternary(Box<RLogOrExpr>,Box<RExpr>,Box<RTernary>) }
impl RFrom<CondExpr> for RTernary {
fn rfrom(value: CondExpr, context: &mut Context) -> Result<Self> {
let mut val=value;
if val.0.is_empty() { Ok(Self::Or(Box::new((*val.1).rinto(context)?))) }
else {
let (or,expr)=safe_remove(&mut val.0,0,c2rust_err!("Coditional Expression cannot be empty inside Ternary Expression!"))?;
let mut or: RLogOrExpr=or.rinto(context)?;
or=or.cast(&RType::Bool);
let mut lhs: RExpr=(*expr).rinto(context)?;
let mut rhs: Self=val.rinto(context)?;
let ty=RType::stronger(lhs.get_type().get_type_alias(), rhs.get_type().get_type_alias());
if let Some(ty)=ty {
lhs=lhs.cast(&ty);
rhs=rhs.cast(&ty);
}
Ok(Self::Ternary(Box::new(or), Box::new(lhs), Box::new(rhs)))
}
}
}
impl Display for RTernary {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Or(rlog_or_expr) => write!(f,"{rlog_or_expr}"),
Self::Ternary(rlog_or_expr, rexpr, rternary) => write!(f,"if {rlog_or_expr} {{ {rexpr} }} else {{ {rternary} }}"),
}
}
}
pub type RConstExpr=RTernary;
impl RFrom<ConstExpr> for RConstExpr {
fn rfrom(value: ConstExpr, context: &mut Context) -> Result<Self> {
value.0.rinto(context)
}
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum RAssignExpr {
Ternary(RTernary),
Assign(RUnaryExpr,Box<RAssignExpr>),
AddAssign(RUnaryExpr,Box<RAssignExpr>),
SubAssign(RUnaryExpr,Box<RAssignExpr>),
MulAssign(RUnaryExpr,Box<RAssignExpr>),
DivAssign(RUnaryExpr,Box<RAssignExpr>),
ModAssign(RUnaryExpr,Box<RAssignExpr>),
LShiftAssign(RUnaryExpr,Box<RAssignExpr>),
RShiftAssign(RUnaryExpr,Box<RAssignExpr>),
AndAssign(RUnaryExpr,Box<RAssignExpr>),
OrAssign(RUnaryExpr,Box<RAssignExpr>),
XorAssign(RUnaryExpr,Box<RAssignExpr>),
}
impl RFrom<AssignmentExpr> for RAssignExpr {
fn rfrom(value: AssignmentExpr, context: &mut Context) -> Result<Self> {
fn assign(unary: UnaryExpr, assignment_expr: AssignmentExpr, context: &mut Context, s: &str) -> Result<RAssignExpr> {
let mut unary=RCastExpr::rfrom(unary, context)?.unwrap_unary();
let expr=RExpr::Expr(Box::new(assignment_expr.rinto(context)?)); let ty=unary.get_type().get_type_alias();
let field=if matches!(ty,RType::Point(_)|RType::PointMut(_)|RType::ThinPoint(_)|RType::ThinPointMut(_)) {
RField::UnsafeMethod(RIdent(s.to_string()), vec![expr.cast(&RType::Isize)])
}
else { RField::Method(RIdent(s.to_string()), vec![expr.cast(&ty)]) };
unary.insert_field(field, ty);
Ok(RAssignExpr::from(unary))
}
type A=AssignmentExpr;
match value {
A::Cond(cond_expr) => Ok(Self::Ternary(cond_expr.rinto(context)?)),
A::Assign(unary_expr, assignment_expr) => assign(unary_expr, *assignment_expr,context,"c_assign"),
A::MulAssign(unary_expr, assignment_expr) => assign(unary_expr, *assignment_expr, context, "c_mul_assign"),
A::DivAssign(unary_expr, assignment_expr) => assign(unary_expr, *assignment_expr, context, "c_div_assign"),
A::ModAssign(unary_expr, assignment_expr) => assign(unary_expr, *assignment_expr, context, "c_mod_assign"),
A::AddAssign(unary_expr, assignment_expr) => assign(unary_expr, *assignment_expr, context, "c_add_assign"),
A::SubAssign(unary_expr, assignment_expr) => assign(unary_expr, *assignment_expr, context, "c_sub_assign"),
A::LShiftAssign(unary_expr, assignment_expr) => assign(unary_expr, *assignment_expr, context, "c_lshift_assign"),
A::RShiftAssign(unary_expr, assignment_expr) => assign(unary_expr, *assignment_expr, context, "c_rshift_assign"),
A::AndAssign(unary_expr, assignment_expr) => assign(unary_expr, *assignment_expr, context, "c_and_assign"),
A::XorAssign(unary_expr, assignment_expr) => assign(unary_expr, *assignment_expr, context, "c_xor_assign"),
A::OrAssign(unary_expr, assignment_expr) => assign(unary_expr, *assignment_expr, context, "c_or_assign"),
}
}
}
impl Display for RAssignExpr {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Ternary(rternary) => write!(f,"{rternary}"),
Self::Assign(runary_expr, rassign_expr) => write!(f,"{runary_expr} = {rassign_expr}"),
Self::AddAssign(runary_expr, rassign_expr) => write!(f,"{runary_expr} += {rassign_expr}"),
Self::SubAssign(runary_expr, rassign_expr) => write!(f,"{runary_expr} -= {rassign_expr}"),
Self::MulAssign(runary_expr, rassign_expr) => write!(f,"{runary_expr} *= {rassign_expr}"),
Self::DivAssign(runary_expr, rassign_expr) => write!(f,"{runary_expr} /= {rassign_expr}"),
Self::ModAssign(runary_expr, rassign_expr) => write!(f,"{runary_expr} %= {rassign_expr}"),
Self::LShiftAssign(runary_expr, rassign_expr) => write!(f,"{runary_expr} <<= {rassign_expr}"),
Self::RShiftAssign(runary_expr, rassign_expr) => write!(f,"{runary_expr} >>= {rassign_expr}"),
Self::AndAssign(runary_expr, rassign_expr) => write!(f,"{runary_expr} &= {rassign_expr}"),
Self::OrAssign(runary_expr, rassign_expr) => write!(f,"{runary_expr} |= {rassign_expr}"),
Self::XorAssign(runary_expr, rassign_expr) => write!(f,"{runary_expr} ^= {rassign_expr}")
}
}
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum RExpr {
Expr(Box<RAssignExpr>), Block(Vec<RAssignExpr>) }
impl RFrom<Expression> for RExpr {
fn rfrom(value: Expression, context: &mut Context) -> Result<Self> {
let mut val=value;
if val.0.len()==1 {
Ok(Self::Expr(Box::new(safe_remove(&mut val.0, 0, c2rust_err!("Assignment Expression Chain cannot be empty inside Expression!"))?.rinto(context)?)))
}
else {
let mut blocks=vec![];
for x in val.0 {
blocks.push(x.rinto(context)?);
}
Ok(Self::Block(blocks))
}
}
}
impl Display for RExpr {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Expr(rassign_expr) => {
write!(f,"{rassign_expr}")
},
Self::Block(assignment_exprs) => {
write!(f,"{{ {} }}", print_vec(assignment_exprs, "; "))
},
}
}
}