use std::mem::swap;
use super::{defs::{GetType, IsPrimary, IsUnsafe}, rustdecl::{RInit, RType}, rustexpr::*, rustprimitives::{RLit, TypedIdent}};
impl IsPrimary for RPrimaryExpr {
fn is_primary(&self) -> bool {
match self {
Self::RInit(rinit) => {
match rinit.as_ref() {
RInit::Expr(rexpr) => rexpr.is_primary(),
_ => false
}
},
Self::Expr(rexpr) => rexpr.is_primary(),
_ => true
}
}
fn into_primary(self) -> RPrimaryExpr {
match self {
Self::RInit(rinit) => {
match *rinit {
RInit::Expr(rexpr) => rexpr.into_primary(),
_ => Self::RInit(rinit)
}
},
Self::Expr(rexpr) => rexpr.into_primary(),
_ => self
}
}
}
impl IsPrimary for RFieldExpr {
fn is_primary(&self) -> bool {
self.1.is_empty()
}
fn into_primary(self) -> RPrimaryExpr {
self.0.into_primary()
}
}
macro_rules! impl_isprimary {
($for:ty : $field:ident) => {
impl IsPrimary for $for {
fn is_primary(&self) -> bool {
match self {
Self::$field(expr) => expr.is_primary(),
_ => false
}
}
fn into_primary(self) -> RPrimaryExpr {
match self {
Self::$field(expr) => expr.into_primary(),
_ => RExpr::from(self).into()
}
}
}
};
}
impl_isprimary!(RPostfixExpr : Field);
impl_isprimary!(RUnaryExpr : Postfix);
impl_isprimary!(RCastExpr : Unary);
impl_isprimary!(RMulExpr : Cast);
impl_isprimary!(RAddExpr : Mul);
impl_isprimary!(RShiftExpr : Add);
impl_isprimary!(RAndExpr : Shift);
impl_isprimary!(RXorExpr : And);
impl_isprimary!(ROrExpr : Xor);
impl_isprimary!(RCompExpr : Or);
impl_isprimary!(RLogAndExpr : Comp);
impl_isprimary!(RLogOrExpr : And);
impl_isprimary!(RTernary : Or);
impl_isprimary!(RAssignExpr : Ternary);
impl_isprimary!(RExpr : Expr);
impl From<RExpr> for RPrimaryExpr {
fn from(value: RExpr) -> Self {
if value.is_primary() { value.into_primary() }
else { Self::Expr(Box::new(value)) }
}
}
impl From<RExpr> for RFieldExpr {
fn from(value: RExpr) -> Self {
let ty=value.get_type().get_type_alias();
Self(value.into(), vec![], ty)
}
}
macro_rules! impl_from {
($for:ty : $field:ident) => {
impl From<RExpr> for $for {
fn from(value: RExpr) -> Self {
Self::$field(value.into())
}
}
};
($for:ty : $field:ident;) => {
impl From<RExpr> for $for {
fn from(value: RExpr) -> Self {
Self::$field(Box::new(value.into()))
}
}
};
}
impl_from!(RPostfixExpr : Field;);
impl_from!(RUnaryExpr : Postfix;);
impl_from!(RCastExpr : Unary);
impl_from!(RMulExpr : Cast);
impl_from!(RAddExpr : Mul);
impl_from!(RShiftExpr : Add);
impl_from!(RAndExpr : Shift);
impl_from!(RXorExpr : And);
impl_from!(ROrExpr : Xor);
impl_from!(RCompExpr : Or);
impl_from!(RLogAndExpr : Comp);
impl_from!(RLogOrExpr : And);
impl_from!(RTernary : Or;);
impl_from!(RAssignExpr : Ternary);
macro_rules! impl_into {
($from:ty : $ty:ty => $field:ident) => {
impl From<$from> for RExpr {
fn from(value: $from) -> Self {
<$ty>::$field(value).into()
}
}
};
($from:ty : $ty:ty => $field:ident;) => {
impl From<$from> for RExpr {
fn from(value: $from) -> Self {
<$ty>::$field(Box::new(value)).into()
}
}
};
}
impl From<usize> for RExpr {
fn from(value: usize) -> Self {
RLit::Int(value.to_string(), RType::Usize).into()
}
}
impl_into!(RLit : RPrimaryExpr => Lit);
impl From<RPrimaryExpr> for RExpr {
fn from(value: RPrimaryExpr) -> Self {
let ty=value.get_type().get_type_alias();
RFieldExpr(value, vec![],ty).into()
}
}
impl_into!(RFieldExpr : RPostfixExpr => Field;);
impl_into!(RPostfixExpr : RUnaryExpr => Postfix;);
impl_into!(RUnaryExpr : RCastExpr => Unary);
impl_into!(RCastExpr : RMulExpr => Cast);
impl_into!(RMulExpr : RAddExpr => Mul);
impl_into!(RAddExpr : RShiftExpr => Add);
impl_into!(RShiftExpr : RAndExpr => Shift);
impl_into!(RAndExpr : RXorExpr => And);
impl_into!(RXorExpr : ROrExpr => Xor);
impl_into!(ROrExpr : RCompExpr => Or);
impl_into!(RCompExpr : RLogAndExpr => Comp);
impl_into!(RLogAndExpr : RLogOrExpr => And);
impl_into!(RLogOrExpr : RTernary => Or;);
impl From<RTernary> for RExpr {
fn from(value: RTernary) -> Self {
RAssignExpr::Ternary(value).into()
}
}
impl_into!(RAssignExpr : Self => Expr;);
impl Default for RLit {
fn default() -> Self {
Self::Int(String::default(), RType::default())
}
}
impl Default for RPrimaryExpr {
fn default() -> Self {
Self::Lit(RLit::default())
}
}
impl Default for RPostfixExpr {
fn default() -> Self {
Self::Field(Box::default())
}
}
impl Default for RUnaryExpr {
fn default() -> Self {
Self::Postfix(Box::default())
}
}
impl Default for RCastExpr {
fn default() -> Self {
Self::Unary(RUnaryExpr::default())
}
}
impl Default for RMulExpr {
fn default() -> Self {
Self::Cast(RCastExpr::default())
}
}
impl Default for RAddExpr {
fn default() -> Self {
Self::Mul(RMulExpr::default())
}
}
impl From<(RExpr,RField,RType)> for RFieldExpr {
fn from(value: (RExpr,RField,RType)) -> Self {
Self(RPrimaryExpr::Expr(Box::new(value.0)),vec![value.1],value.2)
}
}
impl From<(RExpr,RField,RType)> for RPostfixExpr {
fn from(value: (RExpr,RField,RType)) -> Self {
Self::Field(Box::new(value.into()))
}
}
impl RPostfixExpr {
pub(super) fn insert_field(&mut self, field: RField, ty: RType) {
if let Self::Field(rfield_expr) = self {
rfield_expr.1.push(field);
rfield_expr.2=ty;
}
else {
let mut tmp=Self::default();
swap(&mut tmp, self);
*self=Self::from((tmp.into(),field,ty));
}
}
}
impl From<(RExpr,RField,RType)> for RUnaryExpr {
fn from(value: (RExpr,RField,RType)) -> Self {
Self::Postfix(Box::new(value.into()))
}
}
impl RUnaryExpr {
pub(super) fn insert_field(&mut self, field: RField, ty: RType) {
if let Self::Postfix(rpostfix_expr) = self {
rpostfix_expr.insert_field(field,ty);
}
else {
let mut tmp=Self::default();
swap(&mut tmp, self);
*self=Self::from((tmp.into(),field,ty));
}
}
}
impl From<(RExpr,RField,RType)> for RCastExpr {
fn from(value: (RExpr,RField,RType)) -> Self {
Self::Unary(value.into())
}
}
impl RCastExpr {
pub(super) fn insert_field(&mut self, field: RField, ty: RType) {
if let Self::Unary(runary_expr) = self {
runary_expr.insert_field(field, ty);
}
else {
let mut tmp=Self::default();
swap(&mut tmp, self);
*self=Self::from((tmp.into(),field,ty));
}
}
pub(super) fn unwrap_unary(self) -> RUnaryExpr {
match self {
Self::Unary(runary_expr) => runary_expr,
Self::Cast(..) => RExpr::from(self).into(),
}
}
}
impl From<(RExpr,RField,RType)> for RMulExpr {
fn from(value: (RExpr,RField,RType)) -> Self {
Self::Cast(value.into())
}
}
impl RMulExpr {
pub(super) fn insert_field(&mut self, field: RField, ty: RType) {
if let Self::Cast(cast_expr) = self {
cast_expr.insert_field(field, ty);
}
else {
let mut tmp=Self::default();
swap(&mut tmp, self);
*self=Self::from((tmp.into(),field,ty));
}
}
}
impl From<(RExpr,RField,RType)> for RAddExpr {
fn from(value: (RExpr,RField,RType)) -> Self {
Self::Mul(value.into())
}
}
impl RAddExpr {
pub(super) fn insert_field(&mut self, field: RField, ty: RType) {
if let Self::Mul(mul_expr) = self {
mul_expr.insert_field(field, ty);
}
else {
let mut tmp=Self::default();
swap(&mut tmp, self);
*self=Self::from((tmp.into(),field,ty));
}
}
}
macro_rules! tricky_syntax {
($type_name:expr,$cast_expr:tt,$context:expr) => {
macro_rules! impl_add_expr {
($rident:expr,$cast:expr,$id:ident) => {
{
let lhs_ty=$context.get_variable_ty(&$rident.0).ok_or_else(|| c2rust_err!("Could not find type of variable '{}' in context!",$rident.0))?.clone();
let lhs_global=$context.is_variable_mutable_global(&$rident.0);
let lhs=RAddExpr::Mul(RMulExpr::Cast(Self::Unary(RUnaryExpr::from(RPrimaryExpr::Ident(TypedIdent($rident, Box::new(lhs_ty), lhs_global))))));
return Ok(RExpr::from(RAddExpr::$id(Box::new(lhs), RMulExpr::Cast(Self::rfrom(*$cast, $context)?))).into())
}
};
}
fn unwrap_unary(postfix: PostfixExpr) -> Result<UnaryExpr> {
if let PostfixExpr::Primary(primary, _)=postfix {
if let PrimaryExpr::Expr(mut expr)=*primary {
if !expr.0.is_empty() {
if let AssignmentExpr::Cond(CondExpr(_,mut log_or))=expr.0.remove(0) {
if !log_or.0.is_empty() {
let mut log_and=log_or.0.remove(0);
if !log_and.0.is_empty() {
let mut or=log_and.0.remove(0);
if !or.0.is_empty() {
let mut xor=or.0.remove(0);
if !xor.0.is_empty() {
let mut and=xor.0.remove(0);
if !and.0.is_empty() {
if let CastExpr::Unary(unary)=*and.0.remove(0).0.0.0.0.0 {
return Ok(unary);
}
}
}
}
}
}
}
}
}
}
Err(c2rust_err!("Could not convert Postfix Expression into Unary Expression!"))
}
if $type_name.0.0.len()==1 && matches!(*$cast_expr,CastExpr::Unary(_)) {
let fst=safe_remove(&mut $type_name.0.0,0,c2rust_err!("Specifier-Qualifier List must not be empty inside Typedef!"))?;
if let SpecifierQualifier::Typedef(name)=fst {
let rident=RIdent::from(name.0.clone());
if $context.get_typedef_alias(&rident.0).is_none() {
if let CastExpr::Unary(mut unary)=*$cast_expr {
loop {
match unary {
UnaryExpr::Postfix(postfix_expr) => unary=unwrap_unary(*postfix_expr)?,
UnaryExpr::Ref(cast_expr) => {
let lhs_ty=$context.get_variable_ty(&rident.0).ok_or_else(|| c2rust_err!("Could not find type of variable '{}' in context!",rident.0))?.clone();
let lhs_global=$context.is_variable_mutable_global(&rident.0);
let lhs=RAndExpr::Shift(RShiftExpr::Add(RAddExpr::Mul(RMulExpr::Cast(Self::Unary(RUnaryExpr::from(RPrimaryExpr::Ident(TypedIdent(rident, Box::new(lhs_ty), lhs_global))))))));
return Ok(RExpr::from(RAndExpr::And(Box::new(lhs), RShiftExpr::Add(RAddExpr::Mul(RMulExpr::Cast(Self::rfrom(*cast_expr, $context)?))))).into())
},
UnaryExpr::Deref(cast_expr) => {
let lhs_ty=$context.get_variable_ty(&rident.0).ok_or_else(|| c2rust_err!("Could not find type of variable '{}' in context!",rident.0))?.clone();
let lhs_global=$context.is_variable_mutable_global(&rident.0);
let lhs=RMulExpr::Cast(Self::Unary(RUnaryExpr::from(RPrimaryExpr::Ident(TypedIdent(rident, Box::new(lhs_ty), lhs_global)))));
return Ok(RExpr::from(RMulExpr::Mul(Box::new(lhs), Self::rfrom(*cast_expr, $context)?)).into())
},
UnaryExpr::Plus(cast_expr) => impl_add_expr!(rident,cast_expr,Add),
UnaryExpr::Minus(cast_expr) => impl_add_expr!(rident,cast_expr,Sub),
_ => return Err(c2rust_err!("Invalid symbol found in Typedef Cast expression '({name:?}) {unary:?}'!"))
}
}
}
return Err(c2rust_err!("Could not convert Cast Expression into Unary Expression!"))
}
$type_name.0.0.insert(0, SpecifierQualifier::Typedef(name));
}
else { $type_name.0.0.insert(0, fst); }
}
};
}
pub(crate) use tricky_syntax;
impl From<RInit> for RFieldExpr {
fn from(value: RInit) -> Self {
RPrimaryExpr::RInit(Box::new(value)).into()
}
}
impl From<RPrimaryExpr> for RFieldExpr {
fn from(value: RPrimaryExpr) -> Self {
let ty=value.get_type().get_type_alias();
Self(value, vec![], ty)
}
}
impl From<RPrimaryExpr> for RUnaryExpr {
fn from(value: RPrimaryExpr) -> Self {
Self::Postfix(Box::new(RPostfixExpr::Field(Box::new(value.into()))))
}
}
impl From<RUnaryExpr> for RAssignExpr {
fn from(value: RUnaryExpr) -> Self {
let val=RExpr::from(value);
if let RExpr::Expr(expr)=val { *expr }
else { val.into() }
}
}
impl IsUnsafe for TypedIdent {
fn is_unsafe(&self) -> bool {
self.2
}
}
impl IsUnsafe for RPrimaryExpr {
fn is_unsafe(&self) -> bool {
match self {
Self::Ident(ident)=> ident.is_unsafe(),
Self::RInit(init) => init.is_unsafe(),
Self::Expr(expr) => expr.is_unsafe(),
Self::Lit(_) => false
}
}
}
impl IsUnsafe for RFieldExpr {
fn is_unsafe(&self) -> bool {
self.0.is_unsafe()
}
}
impl IsUnsafe for RPostfixExpr {
fn is_unsafe(&self) -> bool {
match self {
Self::Field(rfield_expr) => rfield_expr.is_unsafe(),
Self::Func(rpostfix_expr, rassign_exprs, _) => rpostfix_expr.is_unsafe()||rassign_exprs.iter().any(IsUnsafe::is_unsafe),
Self::Array(rpostfix_expr, rexpr) => rpostfix_expr.is_unsafe()||rexpr.is_unsafe(),
Self::Sizeof(runary_expr) => runary_expr.is_unsafe(),
Self::SizeofType(_) => false,
}
}
}
impl IsUnsafe for RUnaryExpr {
fn is_unsafe(&self) -> bool {
match self {
Self::Postfix(this) => this.is_unsafe(),
Self::Minus(that)|Self::Deref(that)|Self::Not(that)|Self::Ref(that)|Self::RefMut(that) => that.is_unsafe()
}
}
}
impl IsUnsafe for RCastExpr {
fn is_unsafe(&self) -> bool {
match self {
Self::Unary(this) => this.is_unsafe(),
Self::Cast(that, _) => that.is_unsafe()
}
}
}
macro_rules! impl_is_unsafe {
($for:ty, $id:ident, $id2:ident $(,$ids:ident)*) => {
impl IsUnsafe for $for {
fn is_unsafe(&self) -> bool {
match self {
Self::$id(this) => this.is_unsafe(),
Self::$id2(lhs, rhs)$(|Self::$ids(lhs, rhs))* => lhs.is_unsafe()||rhs.is_unsafe(),
}
}
}
};
}
impl_is_unsafe!(RMulExpr, Cast, Mul, Div, Mod);
impl_is_unsafe!(RAddExpr, Mul, Add, Sub);
impl_is_unsafe!(RShiftExpr, Add, LShift, RShift);
impl_is_unsafe!(RAndExpr, Shift, And);
impl_is_unsafe!(RXorExpr, And, Xor);
impl_is_unsafe!(ROrExpr, Xor, Or);
impl_is_unsafe!(RCompExpr, Or, Eq, Neq, Gt, Gte, Lt, Lte);
impl_is_unsafe!(RLogAndExpr, Comp, And);
impl_is_unsafe!(RLogOrExpr, And, Or);
impl IsUnsafe for RTernary {
fn is_unsafe(&self) -> bool {
match self {
Self::Or(rlog_or_expr) => rlog_or_expr.is_unsafe(),
Self::Ternary(rlog_or_expr, rexpr, rternary) => rlog_or_expr.is_unsafe()||rexpr.is_unsafe()||rternary.is_unsafe(),
}
}
}
impl IsUnsafe for RAssignExpr {
fn is_unsafe(&self) -> bool {
match self {
Self::Ternary(rternary) => rternary.is_unsafe(),
Self::Assign(runary_expr, rassign_expr)|
Self::AddAssign(runary_expr, rassign_expr)|
Self::SubAssign(runary_expr, rassign_expr)|
Self::MulAssign(runary_expr, rassign_expr)|
Self::DivAssign(runary_expr, rassign_expr)|
Self::ModAssign(runary_expr, rassign_expr)|
Self::LShiftAssign(runary_expr, rassign_expr)|
Self::RShiftAssign(runary_expr, rassign_expr)|
Self::AndAssign(runary_expr, rassign_expr)|
Self::OrAssign(runary_expr, rassign_expr)|
Self::XorAssign(runary_expr, rassign_expr) => runary_expr.is_unsafe()||rassign_expr.is_unsafe(),
}
}
}
impl IsUnsafe for RExpr {
fn is_unsafe(&self) -> bool {
match self {
Self::Expr(rassign_expr) => rassign_expr.is_unsafe(),
Self::Block(rassign_exprs) => rassign_exprs.iter().any(IsUnsafe::is_unsafe),
}
}
}
impl IsUnsafe for RInit {
fn is_unsafe(&self) -> bool {
match self {
Self::Expr(rexpr) => rexpr.is_unsafe(),
Self::Array(rinits, _) => rinits.iter().any(IsUnsafe::is_unsafe),
Self::Struct(_, items) => items.iter().map(|x| &x.1).any(IsUnsafe::is_unsafe),
Self::Union(_, item) => item.1.is_unsafe(),
Self::Default(_) => false,
}
}
}