mirror of
https://github.com/kmc7468/cs420.git
synced 2025-12-14 22:38:46 +00:00
535 lines
18 KiB
Rust
535 lines
18 KiB
Rust
use lang_c::ast::*;
|
|
use lang_c::span::Node;
|
|
|
|
use crate::utils::IsEquiv;
|
|
|
|
impl<T: IsEquiv> IsEquiv for Node<T> {
|
|
fn is_equiv(&self, other: &Self) -> bool {
|
|
self.node.is_equiv(&other.node)
|
|
}
|
|
}
|
|
|
|
impl IsEquiv for TranslationUnit {
|
|
fn is_equiv(&self, other: &Self) -> bool {
|
|
self.0.is_equiv(&other.0)
|
|
}
|
|
}
|
|
|
|
impl IsEquiv for ExternalDeclaration {
|
|
fn is_equiv(&self, other: &Self) -> bool {
|
|
match (self, other) {
|
|
(Self::Declaration(decl), Self::Declaration(other_decl)) => decl.is_equiv(other_decl),
|
|
(Self::FunctionDefinition(fdef), Self::FunctionDefinition(other_fdef)) => {
|
|
fdef.is_equiv(other_fdef)
|
|
}
|
|
_ => false,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IsEquiv for Declaration {
|
|
fn is_equiv(&self, other: &Self) -> bool {
|
|
self.specifiers.is_equiv(&other.specifiers) && self.declarators.is_equiv(&other.declarators)
|
|
}
|
|
}
|
|
|
|
impl IsEquiv for FunctionDefinition {
|
|
fn is_equiv(&self, other: &Self) -> bool {
|
|
self.specifiers.is_equiv(&other.specifiers)
|
|
&& self.declarator.is_equiv(&other.declarator)
|
|
&& self.declarations.is_equiv(&other.declarations)
|
|
&& self.statement.is_equiv(&other.statement)
|
|
}
|
|
}
|
|
|
|
impl IsEquiv for InitDeclarator {
|
|
fn is_equiv(&self, other: &Self) -> bool {
|
|
self.declarator.is_equiv(&other.declarator) && self.initializer.is_equiv(&other.initializer)
|
|
}
|
|
}
|
|
|
|
impl IsEquiv for Initializer {
|
|
fn is_equiv(&self, other: &Self) -> bool {
|
|
match (self, other) {
|
|
(Self::Expression(expr), Self::Expression(other_expr)) => expr.is_equiv(other_expr),
|
|
(Self::List(items), Self::List(other_items)) => items.is_equiv(other_items),
|
|
_ => false,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IsEquiv for InitializerListItem {
|
|
fn is_equiv(&self, other: &Self) -> bool {
|
|
self.designation.is_empty()
|
|
&& other.designation.is_empty()
|
|
&& self.initializer.is_equiv(&other.initializer)
|
|
}
|
|
}
|
|
|
|
impl IsEquiv for Declarator {
|
|
fn is_equiv(&self, other: &Self) -> bool {
|
|
self.kind.is_equiv(&other.kind) && self.derived.is_equiv(&other.derived)
|
|
}
|
|
}
|
|
|
|
impl IsEquiv for DeclaratorKind {
|
|
fn is_equiv(&self, other: &Self) -> bool {
|
|
match (self, other) {
|
|
(Self::Abstract, Self::Abstract) => true,
|
|
(Self::Identifier(identifier), Self::Identifier(other_identifier)) => {
|
|
identifier.node.name == other_identifier.node.name
|
|
}
|
|
(Self::Declarator(decl), Self::Declarator(other_decl)) => decl.is_equiv(other_decl),
|
|
_ => false,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IsEquiv for DerivedDeclarator {
|
|
fn is_equiv(&self, other: &Self) -> bool {
|
|
match (self, other) {
|
|
(Self::Pointer(pointer_qualifiers), Self::Pointer(other_pointer_qualifiers)) => {
|
|
pointer_qualifiers.is_equiv(other_pointer_qualifiers)
|
|
}
|
|
(Self::Array(array_decl), Self::Array(other_array_decl)) => {
|
|
let array_decl = &array_decl.node;
|
|
let other_array_decl = &other_array_decl.node;
|
|
|
|
array_decl.qualifiers.is_equiv(&other_array_decl.qualifiers)
|
|
&& array_decl.size.is_equiv(&other_array_decl.size)
|
|
}
|
|
(Self::Function(func_decl), Self::Function(other_func_decl)) => {
|
|
let params = &func_decl.node.parameters;
|
|
let other_params = &other_func_decl.node.parameters;
|
|
params.is_equiv(other_params)
|
|
}
|
|
(Self::KRFunction(kr_func_decl), Self::KRFunction(other_kr_func_decl)) => {
|
|
kr_func_decl.is_equiv(other_kr_func_decl)
|
|
}
|
|
_ => false,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IsEquiv for PointerQualifier {
|
|
fn is_equiv(&self, other: &Self) -> bool {
|
|
match (self, other) {
|
|
(Self::TypeQualifier(type_qualifier), Self::TypeQualifier(other_type_qualifier)) => {
|
|
type_qualifier.is_equiv(other_type_qualifier)
|
|
}
|
|
_ => false,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IsEquiv for ArraySize {
|
|
fn is_equiv(&self, other: &Self) -> bool {
|
|
match (self, other) {
|
|
(Self::Unknown, Self::Unknown) => true,
|
|
(Self::VariableUnknown, Self::VariableUnknown) => true,
|
|
(Self::VariableExpression(expr), Self::VariableExpression(other_expr)) => {
|
|
expr.is_equiv(other_expr)
|
|
}
|
|
(Self::StaticExpression(expr), Self::StaticExpression(other_expr)) => {
|
|
expr.is_equiv(other_expr)
|
|
}
|
|
_ => false,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IsEquiv for ParameterDeclaration {
|
|
fn is_equiv(&self, other: &Self) -> bool {
|
|
self.specifiers.is_equiv(&other.specifiers)
|
|
&& self
|
|
.declarator
|
|
.as_ref()
|
|
.map(|d| &d.node)
|
|
.is_equiv(&other.declarator.as_ref().map(|d| &d.node))
|
|
}
|
|
}
|
|
|
|
impl IsEquiv for Statement {
|
|
fn is_equiv(&self, other: &Self) -> bool {
|
|
match (self, other) {
|
|
(Self::Labeled(stmt), Self::Labeled(other_stmt)) => {
|
|
stmt.node.label.is_equiv(&other_stmt.node.label)
|
|
&& stmt.node.statement.is_equiv(&other_stmt.node.statement)
|
|
}
|
|
(Self::Compound(items), Self::Compound(other_items)) => items.is_equiv(other_items),
|
|
(Self::Expression(expr), Self::Expression(other_expr)) => {
|
|
expr.as_ref().is_equiv(&other_expr.as_ref())
|
|
}
|
|
(Self::If(stmt), Self::If(other_stmt)) => {
|
|
let else_stmt = stmt.node.else_statement.as_ref();
|
|
let other_else_stmt = other_stmt.node.else_statement.as_ref();
|
|
stmt.node.condition.is_equiv(&other_stmt.node.condition)
|
|
&& stmt
|
|
.node
|
|
.then_statement
|
|
.is_equiv(&other_stmt.node.then_statement)
|
|
&& else_stmt.is_equiv(&other_else_stmt)
|
|
}
|
|
(Self::Switch(stmt), Self::Switch(other_stmt)) => {
|
|
stmt.node.expression.is_equiv(&other_stmt.node.expression)
|
|
&& stmt.node.statement.is_equiv(&other_stmt.node.statement)
|
|
}
|
|
(Self::While(stmt), Self::While(other_stmt)) => {
|
|
stmt.node.expression.is_equiv(&other_stmt.node.expression)
|
|
&& stmt.node.statement.is_equiv(&other_stmt.node.statement)
|
|
}
|
|
(Self::DoWhile(stmt), Self::DoWhile(other_stmt)) => {
|
|
stmt.node.statement.is_equiv(&other_stmt.node.statement)
|
|
&& stmt.node.expression.is_equiv(&other_stmt.node.expression)
|
|
}
|
|
(Self::For(stmt), Self::For(other_stmt)) => {
|
|
stmt.node.initializer.is_equiv(&other_stmt.node.initializer)
|
|
&& stmt
|
|
.node
|
|
.condition
|
|
.as_ref()
|
|
.is_equiv(&other_stmt.node.condition.as_ref())
|
|
&& stmt
|
|
.node
|
|
.step
|
|
.as_ref()
|
|
.is_equiv(&other_stmt.node.step.as_ref())
|
|
&& stmt.node.statement.is_equiv(&other_stmt.node.statement)
|
|
}
|
|
(Self::Goto(label), Self::Goto(other_label)) => label.is_equiv(other_label),
|
|
(Self::Continue, Self::Continue) => true,
|
|
(Self::Break, Self::Break) => true,
|
|
(Self::Return(expr), Self::Return(other_expr)) => expr.is_equiv(other_expr),
|
|
_ => false,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IsEquiv for Label {
|
|
fn is_equiv(&self, other: &Self) -> bool {
|
|
match (self, other) {
|
|
(Self::Identifier(ident), Self::Identifier(other_ident)) => ident.is_equiv(other_ident),
|
|
(Self::Case(expr), Self::Case(other_expr)) => expr.is_equiv(other_expr),
|
|
(Self::Default, Self::Default) => true,
|
|
_ => false,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IsEquiv for Identifier {
|
|
fn is_equiv(&self, other: &Self) -> bool {
|
|
self.name == other.name
|
|
}
|
|
}
|
|
|
|
impl IsEquiv for ForInitializer {
|
|
fn is_equiv(&self, other: &Self) -> bool {
|
|
match (self, other) {
|
|
(Self::Empty, Self::Empty) => true,
|
|
(Self::Expression(expr), Self::Expression(other_expr)) => expr.is_equiv(other_expr),
|
|
(Self::Declaration(decl), Self::Declaration(other_decl)) => decl.is_equiv(other_decl),
|
|
_ => false,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IsEquiv for Expression {
|
|
fn is_equiv(&self, other: &Self) -> bool {
|
|
match (self, other) {
|
|
(Self::Identifier(identifier), Self::Identifier(other_identifier)) => {
|
|
identifier.is_equiv(other_identifier)
|
|
}
|
|
(Self::Constant(constant), Self::Constant(other_constant)) => {
|
|
constant.is_equiv(other_constant)
|
|
}
|
|
(Self::StringLiteral(other_string_lit), Self::StringLiteral(string_lit)) => {
|
|
string_lit.is_equiv(other_string_lit)
|
|
}
|
|
(Self::Member(member), Self::Member(other_member)) => member.is_equiv(other_member),
|
|
(Self::Call(call), Self::Call(other_call)) => call.is_equiv(other_call),
|
|
(Self::SizeOfTy(size_of_ty), Self::SizeOfTy(other_size_of_ty)) => {
|
|
size_of_ty.is_equiv(other_size_of_ty)
|
|
}
|
|
(Self::SizeOfVal(size_of_val), Self::SizeOfVal(other_size_of_val)) => {
|
|
size_of_val.is_equiv(other_size_of_val)
|
|
}
|
|
(Self::AlignOf(align_of), Self::AlignOf(other_align_of)) => {
|
|
align_of.is_equiv(other_align_of)
|
|
}
|
|
(Self::UnaryOperator(unary), Self::UnaryOperator(other_unary)) => {
|
|
unary.node.operator.is_equiv(&other_unary.node.operator)
|
|
&& unary.node.operand.is_equiv(&other_unary.node.operand)
|
|
}
|
|
(Self::Cast(cast), Self::Cast(other_cast)) => {
|
|
cast.node.type_name.is_equiv(&other_cast.node.type_name)
|
|
&& cast.node.expression.is_equiv(&other_cast.node.expression)
|
|
}
|
|
(Self::BinaryOperator(binary), Self::BinaryOperator(other_binary)) => {
|
|
binary.node.lhs.is_equiv(&other_binary.node.lhs)
|
|
&& binary.node.operator.is_equiv(&other_binary.node.operator)
|
|
&& binary.node.rhs.is_equiv(&other_binary.node.rhs)
|
|
}
|
|
(Self::Conditional(conditional), Self::Conditional(other_conditional)) => {
|
|
conditional
|
|
.node
|
|
.condition
|
|
.is_equiv(&other_conditional.node.condition)
|
|
&& conditional
|
|
.node
|
|
.then_expression
|
|
.is_equiv(&other_conditional.node.then_expression)
|
|
&& conditional
|
|
.node
|
|
.else_expression
|
|
.is_equiv(&other_conditional.node.else_expression)
|
|
}
|
|
(Self::Comma(exprs), Self::Comma(other_exprs)) => {
|
|
exprs.as_ref().is_equiv(other_exprs.as_ref())
|
|
}
|
|
_ => false,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IsEquiv for TypeName {
|
|
fn is_equiv(&self, other: &Self) -> bool {
|
|
self.specifiers.is_equiv(&other.specifiers) && self.declarator.is_equiv(&other.declarator)
|
|
}
|
|
}
|
|
|
|
impl IsEquiv for SpecifierQualifier {
|
|
fn is_equiv(&self, other: &Self) -> bool {
|
|
match (self, other) {
|
|
(Self::TypeSpecifier(type_specifier), Self::TypeSpecifier(other_type_specifier)) => {
|
|
type_specifier.is_equiv(other_type_specifier)
|
|
}
|
|
|
|
(Self::TypeQualifier(type_qualifier), Self::TypeQualifier(other_type_qualifier)) => {
|
|
type_qualifier.is_equiv(other_type_qualifier)
|
|
}
|
|
_ => false,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IsEquiv for MemberExpression {
|
|
fn is_equiv(&self, other: &Self) -> bool {
|
|
self.expression.is_equiv(&other.expression)
|
|
&& self.operator.is_equiv(&other.operator)
|
|
&& self.identifier.is_equiv(&other.identifier)
|
|
}
|
|
}
|
|
|
|
impl IsEquiv for MemberOperator {
|
|
fn is_equiv(&self, other: &Self) -> bool {
|
|
self == other
|
|
}
|
|
}
|
|
|
|
impl IsEquiv for UnaryOperator {
|
|
fn is_equiv(&self, other: &Self) -> bool {
|
|
self == other
|
|
}
|
|
}
|
|
|
|
impl IsEquiv for BinaryOperator {
|
|
fn is_equiv(&self, other: &Self) -> bool {
|
|
self == other
|
|
}
|
|
}
|
|
|
|
impl IsEquiv for Constant {
|
|
fn is_equiv(&self, other: &Self) -> bool {
|
|
match (self, other) {
|
|
(Self::Integer(integer), Self::Integer(other_integer)) => {
|
|
integer.base.is_equiv(&other_integer.base)
|
|
&& integer.number == other_integer.number
|
|
&& integer.suffix.is_equiv(&other_integer.suffix)
|
|
}
|
|
(Self::Float(float), Self::Float(other_float)) => {
|
|
float.base == other_float.base
|
|
&& float.number == other_float.number
|
|
&& float.suffix.is_equiv(&other_float.suffix)
|
|
}
|
|
(Self::Character(literal), Self::Character(other_literal)) => literal == other_literal,
|
|
_ => false,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IsEquiv for IntegerBase {
|
|
fn is_equiv(&self, other: &Self) -> bool {
|
|
self == other
|
|
}
|
|
}
|
|
|
|
impl IsEquiv for IntegerSuffix {
|
|
fn is_equiv(&self, other: &Self) -> bool {
|
|
self.unsigned == other.unsigned && self.size == other.size
|
|
}
|
|
}
|
|
|
|
impl IsEquiv for FloatSuffix {
|
|
fn is_equiv(&self, other: &Self) -> bool {
|
|
self.imaginary == other.imaginary && self.format == other.format
|
|
}
|
|
}
|
|
|
|
impl IsEquiv for StringLiteral {
|
|
fn is_equiv(&self, other: &Self) -> bool {
|
|
self == other
|
|
}
|
|
}
|
|
|
|
impl IsEquiv for BlockItem {
|
|
fn is_equiv(&self, other: &Self) -> bool {
|
|
match (self, other) {
|
|
(Self::Declaration(decl), Self::Declaration(other_decl)) => decl.is_equiv(other_decl),
|
|
(Self::Statement(statement), Self::Statement(other_statement)) => {
|
|
statement.is_equiv(other_statement)
|
|
}
|
|
_ => false,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IsEquiv for DeclarationSpecifier {
|
|
fn is_equiv(&self, other: &Self) -> bool {
|
|
match (self, other) {
|
|
(
|
|
Self::StorageClass(storage_class_spec),
|
|
Self::StorageClass(other_storage_class_spec),
|
|
) => storage_class_spec.is_equiv(other_storage_class_spec),
|
|
(Self::TypeSpecifier(type_specifier), Self::TypeSpecifier(other_type_specifier)) => {
|
|
type_specifier.is_equiv(other_type_specifier)
|
|
}
|
|
(Self::TypeQualifier(type_qualifier), Self::TypeQualifier(other_type_qualifier)) => {
|
|
type_qualifier.is_equiv(other_type_qualifier)
|
|
}
|
|
_ => false,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IsEquiv for StorageClassSpecifier {
|
|
fn is_equiv(&self, other: &Self) -> bool {
|
|
self == other
|
|
}
|
|
}
|
|
|
|
impl IsEquiv for TypeSpecifier {
|
|
fn is_equiv(&self, other: &Self) -> bool {
|
|
match (self, other) {
|
|
(Self::Void, Self::Void) => true,
|
|
(Self::Char, Self::Char) => true,
|
|
(Self::Short, Self::Short) => true,
|
|
(Self::Int, Self::Int) => true,
|
|
(Self::Long, Self::Long) => true,
|
|
(Self::Float, Self::Float) => true,
|
|
(Self::Double, Self::Double) => true,
|
|
(Self::Signed, Self::Signed) => true,
|
|
(Self::Unsigned, Self::Unsigned) => true,
|
|
(Self::Bool, Self::Bool) => true,
|
|
(Self::Struct(struct_type), Self::Struct(other_struct_type)) => {
|
|
struct_type.is_equiv(other_struct_type)
|
|
}
|
|
(Self::Enum(enum_type), Self::Enum(other_enum_type)) => {
|
|
enum_type.is_equiv(other_enum_type)
|
|
}
|
|
(Self::TypedefName(identifier), Self::TypedefName(other_identifier)) => {
|
|
identifier.is_equiv(other_identifier)
|
|
}
|
|
_ => false,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IsEquiv for StructType {
|
|
fn is_equiv(&self, other: &Self) -> bool {
|
|
self.declarations.is_equiv(&other.declarations)
|
|
&& self.kind.is_equiv(&other.kind)
|
|
&& self.identifier.is_equiv(&other.identifier)
|
|
}
|
|
}
|
|
|
|
impl IsEquiv for StructKind {
|
|
fn is_equiv(&self, other: &Self) -> bool {
|
|
self == other
|
|
}
|
|
}
|
|
|
|
impl IsEquiv for StructDeclaration {
|
|
fn is_equiv(&self, other: &Self) -> bool {
|
|
match (self, other) {
|
|
(Self::Field(struct_field), Self::Field(other_struct_field)) => {
|
|
struct_field.is_equiv(other_struct_field)
|
|
}
|
|
_ => false,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IsEquiv for StructField {
|
|
fn is_equiv(&self, other: &Self) -> bool {
|
|
self.specifiers.is_equiv(&other.specifiers) && self.declarators.is_equiv(&other.declarators)
|
|
}
|
|
}
|
|
|
|
impl IsEquiv for StructDeclarator {
|
|
fn is_equiv(&self, other: &Self) -> bool {
|
|
self.declarator.is_equiv(&other.declarator) && self.bit_width.is_equiv(&other.bit_width)
|
|
}
|
|
}
|
|
|
|
impl IsEquiv for EnumType {
|
|
fn is_equiv(&self, other: &Self) -> bool {
|
|
self.identifier.is_equiv(&other.identifier) && self.enumerators.is_equiv(&other.enumerators)
|
|
}
|
|
}
|
|
|
|
impl IsEquiv for Enumerator {
|
|
fn is_equiv(&self, other: &Self) -> bool {
|
|
self.identifier.is_equiv(&other.identifier) && self.expression.is_equiv(&other.expression)
|
|
}
|
|
}
|
|
|
|
impl IsEquiv for TypeQualifier {
|
|
fn is_equiv(&self, other: &Self) -> bool {
|
|
matches!((self, other), (Self::Const, Self::Const))
|
|
}
|
|
}
|
|
|
|
impl IsEquiv for CallExpression {
|
|
fn is_equiv(&self, other: &Self) -> bool {
|
|
self.callee.is_equiv(&other.callee) && self.arguments.is_equiv(&other.arguments)
|
|
}
|
|
}
|
|
|
|
impl IsEquiv for SizeOfTy {
|
|
fn is_equiv(&self, other: &Self) -> bool {
|
|
self.0.is_equiv(&other.0)
|
|
}
|
|
}
|
|
|
|
impl IsEquiv for SizeOfVal {
|
|
fn is_equiv(&self, other: &Self) -> bool {
|
|
self.0.is_equiv(&other.0)
|
|
}
|
|
}
|
|
|
|
impl IsEquiv for AlignOf {
|
|
fn is_equiv(&self, other: &Self) -> bool {
|
|
self.0.is_equiv(&other.0)
|
|
}
|
|
}
|
|
|
|
pub(crate) fn assert_ast_equiv(lhs: &TranslationUnit, rhs: &TranslationUnit) {
|
|
if !lhs.is_equiv(rhs) {
|
|
panic!(
|
|
r#"assertion failed: `(left.is_equiv(right))`
|
|
left: `{lhs:?}`,
|
|
right: `{rhs:?}`"#
|
|
)
|
|
}
|
|
}
|