Update homework 1 and 2

This commit is contained in:
Jeehoon Kang
2020-03-26 03:38:20 +09:00
parent 241a66fcc1
commit 8938a7ad8f
40 changed files with 5171 additions and 1504 deletions

543
src/c/ast_equiv.rs Normal file
View File

@@ -0,0 +1,543 @@
#![allow(unused_variables)]
use lang_c::ast::*;
use lang_c::span::Node;
use core::ops::Deref;
use itertools::izip;
trait IsEquiv {
fn is_equiv(&self, other: &Self) -> bool;
}
impl<T: IsEquiv> IsEquiv for Node<T> {
fn is_equiv(&self, other: &Self) -> bool {
self.node.is_equiv(&other.node)
}
}
impl<T: IsEquiv> IsEquiv for Box<T> {
fn is_equiv(&self, other: &Self) -> bool {
self.deref().is_equiv(other.deref())
}
}
impl<T: IsEquiv> IsEquiv for &T {
fn is_equiv(&self, other: &Self) -> bool {
(*self).is_equiv(*other)
}
}
impl<T: IsEquiv> IsEquiv for Option<T> {
fn is_equiv(&self, other: &Self) -> bool {
match (self, other) {
(Some(lhs), Some(rhs)) => lhs.is_equiv(rhs),
(None, None) => true,
_ => false,
}
}
}
impl<T: IsEquiv> IsEquiv for Vec<T> {
fn is_equiv(&self, other: &Self) -> bool {
self.len() == other.len() && izip!(self, other).all(|(lhs, rhs)| lhs.is_equiv(rhs))
}
}
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),
_ => false,
}
}
}
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::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::SizeOf(typename), Self::SizeOf(other_typename)) => {
typename.is_equiv(other_typename)
}
(Self::AlignOf(typename), Self::AlignOf(other_typename)) => {
typename.is_equiv(other_typename)
}
(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 {
match (self, other) {
(Self::Const, Self::Const) => true,
_ => false,
}
}
}
impl IsEquiv for CallExpression {
fn is_equiv(&self, other: &Self) -> bool {
self.callee.is_equiv(&other.callee) && self.arguments.is_equiv(&other.arguments)
}
}
pub fn assert_ast_equiv(lhs: &TranslationUnit, rhs: &TranslationUnit) {
if !lhs.is_equiv(rhs) {
panic!(
r#"assertion failed: `(left.is_equiv(right))`
left: `{:?}`,
right: `{:?}`"#,
lhs, rhs
)
}
}

6
src/c/mod.rs Normal file
View File

@@ -0,0 +1,6 @@
mod ast_equiv;
mod parse;
mod write_c;
pub use ast_equiv::assert_ast_equiv;
pub use parse::Parse;

559
src/c/parse.rs Normal file
View File

@@ -0,0 +1,559 @@
use core::ops::Deref;
use std::path::Path;
use lang_c::ast::*;
use lang_c::driver::{parse, Config, Error as ParseError};
use lang_c::span::Node;
use crate::Translate;
#[derive(Debug)]
pub enum Error {
ParseError(ParseError),
#[allow(dead_code)]
Unsupported,
}
#[derive(Default)]
pub struct Parse {}
impl<P: AsRef<Path>> Translate<P> for Parse {
type Target = TranslationUnit;
type Error = Error;
fn translate(&mut self, source: &P) -> Result<Self::Target, Self::Error> {
let config = Config::default();
let ast = parse(&config, source).map_err(Error::ParseError)?;
let unit = ast.unit;
unit.assert_supported();
Ok(unit)
}
}
trait AssertSupported {
fn assert_supported(&self);
}
impl<T: AssertSupported> AssertSupported for Node<T> {
fn assert_supported(&self) {
self.node.assert_supported();
}
}
impl<T: AssertSupported> AssertSupported for Option<T> {
fn assert_supported(&self) {
if let Some(this) = self {
this.assert_supported();
}
}
}
impl<T: AssertSupported> AssertSupported for Box<T> {
fn assert_supported(&self) {
self.deref().assert_supported();
}
}
impl<T: AssertSupported> AssertSupported for Vec<T> {
fn assert_supported(&self) {
self.iter().for_each(AssertSupported::assert_supported);
}
}
impl<T: AssertSupported> AssertSupported for [T] {
fn assert_supported(&self) {
self.iter().for_each(AssertSupported::assert_supported);
}
}
impl AssertSupported for TranslationUnit {
fn assert_supported(&self) {
self.0.assert_supported();
}
}
impl AssertSupported for ExternalDeclaration {
fn assert_supported(&self) {
match self {
Self::Declaration(decl) => decl.assert_supported(),
Self::StaticAssert(_) => panic!("ExternalDeclaration::StaticAssert"),
Self::FunctionDefinition(fdef) => fdef.assert_supported(),
}
}
}
impl AssertSupported for Declaration {
fn assert_supported(&self) {
self.specifiers.assert_supported();
self.declarators.assert_supported();
}
}
impl AssertSupported for FunctionDefinition {
fn assert_supported(&self) {
self.specifiers.assert_supported();
self.declarator.assert_supported();
assert!(self.declarations.is_empty());
self.statement.assert_supported();
}
}
impl AssertSupported for DeclarationSpecifier {
fn assert_supported(&self) {
match self {
Self::StorageClass(storage_class_specifier) => {
storage_class_specifier.assert_supported()
}
Self::TypeSpecifier(type_specifier) => type_specifier.assert_supported(),
Self::TypeQualifier(type_qualifier) => type_qualifier.assert_supported(),
Self::Function(_) => panic!("DeclarationSpecifier::Function"),
Self::Alignment(_) => panic!("DeclarationSpecifier::Alignment"),
Self::Extension(_) => panic!("DeclarationSpecifier::Extension"),
}
}
}
impl AssertSupported for StorageClassSpecifier {
fn assert_supported(&self) {
match self {
Self::Typedef => (),
_ => panic!("StorageClassifier other than Typedef"),
}
}
}
impl AssertSupported for TypeSpecifier {
fn assert_supported(&self) {
match self {
Self::Void => (),
Self::Char => (),
Self::Short => (),
Self::Int => (),
Self::Long => (),
Self::Float => (),
Self::Double => (),
Self::Signed => (),
Self::Unsigned => (),
Self::Bool => (),
Self::Complex => panic!("TypeSpecifier::Complex"),
Self::Atomic(_) => panic!("TypeSpecifier::Atomic"),
Self::Struct(struct_type) => struct_type.assert_supported(),
Self::Enum(_) => panic!("TypeSpecifier::Enum"),
Self::TypedefName(_) => (),
Self::TypeOf(_) => panic!("TypeSpecifier::TypeOf"),
Self::TS18661Float(_) => panic!("TypeSpecifier::TS18661Float"),
}
}
}
impl AssertSupported for StructType {
fn assert_supported(&self) {
self.kind.assert_supported();
self.declarations.assert_supported();
}
}
impl AssertSupported for StructDeclaration {
fn assert_supported(&self) {
match self {
Self::Field(field) => field.assert_supported(),
Self::StaticAssert(_) => panic!("StructDeclaration::StaticAssert"),
}
}
}
impl AssertSupported for StructField {
fn assert_supported(&self) {
self.specifiers.assert_supported();
self.declarators.assert_supported();
}
}
impl AssertSupported for StructDeclarator {
fn assert_supported(&self) {
self.declarator.assert_supported();
assert_eq!(true, self.bit_width.is_none());
}
}
impl AssertSupported for StructKind {
fn assert_supported(&self) {
match self {
Self::Struct => (),
Self::Union => panic!("StructKind::Union"),
}
}
}
impl AssertSupported for AlignmentSpecifier {
fn assert_supported(&self) {
match self {
Self::Type(typename) => typename.assert_supported(),
Self::Constant(_) => panic!(AlignmentSpecifier::Constant),
}
}
}
impl AssertSupported for InitDeclarator {
fn assert_supported(&self) {
self.declarator.assert_supported();
self.initializer.assert_supported();
}
}
impl AssertSupported for Initializer {
fn assert_supported(&self) {
match self {
Self::Expression(expr) => expr.assert_supported(),
Self::List(_) => panic!("Initializer::List"),
}
}
}
impl AssertSupported for Declarator {
fn assert_supported(&self) {
self.kind.assert_supported();
self.derived.assert_supported();
self.extensions.is_empty();
}
}
impl AssertSupported for DerivedDeclarator {
fn assert_supported(&self) {
match self {
Self::Pointer(pointer_qualifiers) => pointer_qualifiers.assert_supported(),
Self::Array(array_decl) => array_decl.assert_supported(),
Self::Function(func_decl) => func_decl.assert_supported(),
// Support when K&R function has no parameter
Self::KRFunction(kr_func_decl) => assert_eq!(true, kr_func_decl.is_empty()),
}
}
}
impl AssertSupported for PointerQualifier {
fn assert_supported(&self) {
match self {
Self::TypeQualifier(type_qualifier) => type_qualifier.assert_supported(),
Self::Extension(_) => panic!("PointerQualifier::Extension"),
}
}
}
impl AssertSupported for ArrayDeclarator {
fn assert_supported(&self) {
self.qualifiers.assert_supported();
self.size.assert_supported();
}
}
impl AssertSupported for TypeQualifier {
fn assert_supported(&self) {
match self {
Self::Const => (),
_ => panic!("TypeQualifier::_"),
}
}
}
impl AssertSupported for ArraySize {
fn assert_supported(&self) {
match self {
Self::VariableExpression(expr) => expr.assert_supported(),
_ => panic!("ArraySize::_"),
}
}
}
impl AssertSupported for FunctionDeclarator {
fn assert_supported(&self) {
self.parameters.assert_supported();
assert_eq!(self.ellipsis, Ellipsis::None);
}
}
impl AssertSupported for ParameterDeclaration {
fn assert_supported(&self) {
self.specifiers.assert_supported();
self.declarator.assert_supported();
self.extensions.is_empty();
}
}
impl AssertSupported for DeclaratorKind {
fn assert_supported(&self) {
match self {
Self::Abstract => (),
Self::Identifier(_) => (),
Self::Declarator(decl) => decl.assert_supported(),
}
}
}
impl AssertSupported for BlockItem {
fn assert_supported(&self) {
match self {
Self::Declaration(decl) => decl.assert_supported(),
Self::StaticAssert(_) => panic!("BlockItem::StaticAssert"),
Self::Statement(stmt) => stmt.assert_supported(),
}
}
}
impl AssertSupported for ForInitializer {
fn assert_supported(&self) {
match self {
Self::Empty => (),
Self::Expression(expr) => expr.assert_supported(),
Self::Declaration(decl) => decl.assert_supported(),
Self::StaticAssert(_) => panic!("ForInitializer::StaticAssert"),
}
}
}
impl AssertSupported for Statement {
fn assert_supported(&self) {
match self {
Self::Labeled(_) => panic!("Statement::Labeled"),
Self::Compound(items) => items.assert_supported(),
Self::Expression(expr) => expr.assert_supported(),
Self::If(stmt) => {
stmt.node.condition.assert_supported();
stmt.node.then_statement.assert_supported();
stmt.node.else_statement.assert_supported();
}
Self::Switch(stmt) => stmt.assert_supported(),
Self::While(stmt) => {
stmt.node.expression.assert_supported();
stmt.node.statement.assert_supported();
}
Self::DoWhile(stmt) => {
stmt.node.statement.assert_supported();
stmt.node.expression.assert_supported();
}
Self::For(stmt) => {
stmt.node.initializer.assert_supported();
stmt.node.condition.assert_supported();
stmt.node.step.assert_supported();
stmt.node.statement.assert_supported();
}
Self::Goto(_) => panic!("Statement::Goto"),
Self::Continue | Self::Break => (),
Self::Return(expr) => expr.assert_supported(),
Self::Asm(_) => panic!("Statement::Asm"),
}
}
}
impl AssertSupported for SwitchStatement {
fn assert_supported(&self) {
self.expression.assert_supported();
let items = if let Statement::Compound(items) = &self.statement.node {
items
} else {
panic!("`Statement` in the `switch` is unsupported except `Statement::Compound`")
};
for item in items {
let stmt = if let BlockItem::Statement(stmt) = &item.node {
&stmt.node
} else {
panic!(
"`BlockItem` in the `Statement::Compound` of the `switch` \
is unsupported except `BlockItem::Statement`"
)
};
let stmt_in_label = if let Statement::Labeled(label_stmt) = stmt {
label_stmt.node.label.assert_supported();
&label_stmt.node.statement.node
} else {
panic!(
"`BlockItem::Statement` in the `Statement::Compound` of the `switch` \
is unsupported except `Statement::Labeled`"
)
};
let items = if let Statement::Compound(items) = stmt_in_label {
items
} else {
panic!("`Statement` in the `label` is unsupported except `Statement::Compound`")
};
// Split last and all the rest of the elements of the `Compound` items
let (last, items) = items
.split_last()
.unwrap_or_else(|| panic!("`Statement::Compound` has no item"));
for item in items {
match &item.node {
BlockItem::Declaration(decl) => decl.assert_supported(),
BlockItem::StaticAssert(_) => panic!("BlockItem::StaticAssert"),
BlockItem::Statement(stmt) => {
assert_ne!(
&stmt.node,
&Statement::Break,
"`BlockItem::Statement` in the `Statement::Compound` of the \
`label` should not be `Statement::Break` except the last one"
);
stmt.assert_supported();
}
}
}
// The last element of the `items` must be `Statement::Break`
let stmt = if let BlockItem::Statement(stmt) = &last.node {
&stmt.node
} else {
panic!(
"`BlockItem` in the `Statement::Compound` of the `label` \
is unsupported except `BlockItem::Statement`"
)
};
assert_eq!(
stmt,
&Statement::Break,
"the last `BlockItem` in the `Statement::Compound` \
of the `label` must be `Statement::Break`"
);
}
}
}
impl AssertSupported for Expression {
fn assert_supported(&self) {
match self {
Self::Identifier(_) => (),
Self::Constant(constant) => constant.assert_supported(),
Self::StringLiteral(_) => panic!("Expression::StringLiteral"),
Self::GenericSelection(_) => panic!("Expression::GenericSelection"),
Self::Member(member) => member.assert_supported(),
Self::Call(call) => call.assert_supported(),
Self::CompoundLiteral(_) => panic!("Expression::CompoundLiteral"),
Self::SizeOf(typename) => typename.assert_supported(),
Self::AlignOf(typename) => typename.assert_supported(),
Self::UnaryOperator(unary) => unary.assert_supported(),
Self::Cast(cast) => cast.assert_supported(),
Self::BinaryOperator(binary) => binary.assert_supported(),
Self::Conditional(conditional) => conditional.assert_supported(),
Self::Comma(exprs) => exprs.assert_supported(),
Self::OffsetOf(_) => panic!("Expression::OffsetOf"),
Self::VaArg(_) => panic!("Expression::VaArg"),
Self::Statement(_) => panic!("Expression::Statement"),
}
}
}
impl AssertSupported for Label {
fn assert_supported(&self) {
match self {
Self::Identifier(_) => panic!("Label::Identifier"),
Self::Case(_) => (),
Self::Default => (),
}
}
}
impl AssertSupported for MemberExpression {
fn assert_supported(&self) {
self.expression.assert_supported();
}
}
impl AssertSupported for CallExpression {
fn assert_supported(&self) {
self.callee.assert_supported();
self.arguments.assert_supported();
}
}
impl AssertSupported for TypeName {
fn assert_supported(&self) {
self.specifiers.assert_supported();
self.declarator.assert_supported();
}
}
impl AssertSupported for SpecifierQualifier {
fn assert_supported(&self) {
match self {
Self::TypeSpecifier(type_specifier) => type_specifier.assert_supported(),
Self::TypeQualifier(type_qualifier) => type_qualifier.assert_supported(),
}
}
}
impl AssertSupported for UnaryOperatorExpression {
fn assert_supported(&self) {
self.operator.assert_supported();
self.operand.assert_supported();
}
}
impl AssertSupported for CastExpression {
fn assert_supported(&self) {
self.type_name.assert_supported();
self.expression.assert_supported();
}
}
impl AssertSupported for BinaryOperatorExpression {
fn assert_supported(&self) {
self.operator.assert_supported();
self.lhs.assert_supported();
self.rhs.assert_supported();
}
}
impl AssertSupported for Constant {
fn assert_supported(&self) {
match self {
Self::Integer(integer) => integer.assert_supported(),
Self::Float(float) => float.assert_supported(),
Self::Character(_) => (),
}
}
}
impl AssertSupported for Integer {
fn assert_supported(&self) {
assert_eq!(false, self.suffix.imaginary);
}
}
impl AssertSupported for Float {
fn assert_supported(&self) {
assert_eq!(self.base, FloatBase::Decimal);
self.suffix.format.assert_supported();
assert_eq!(false, self.suffix.imaginary);
}
}
impl AssertSupported for FloatFormat {
fn assert_supported(&self) {
match self {
Self::Float => (),
Self::Double => (),
Self::LongDouble => (),
Self::TS18661Format(_) => panic!("TS18861"),
}
}
}
impl AssertSupported for UnaryOperator {
fn assert_supported(&self) {}
}
impl AssertSupported for BinaryOperator {
fn assert_supported(&self) {}
}
impl AssertSupported for ConditionalExpression {
fn assert_supported(&self) {
self.condition.assert_supported();
self.then_expression.assert_supported();
self.else_expression.assert_supported();
}
}

47
src/c/write_c.rs Normal file
View File

@@ -0,0 +1,47 @@
use lang_c::ast::*;
use lang_c::span::Node;
use core::ops::Deref;
use std::io::{Result, Write};
use crate::write_base::*;
impl<T: WriteLine> WriteLine for Node<T> {
fn write_line(&self, indent: usize, write: &mut dyn Write) -> Result<()> {
self.node.write_line(indent, write)
}
}
impl<T: WriteString> WriteString for Node<T> {
fn write_string(&self) -> String {
self.node.write_string()
}
}
impl<T: WriteString> WriteString for Box<T> {
fn write_string(&self) -> String {
self.deref().write_string()
}
}
impl<T: WriteString> WriteString for &T {
fn write_string(&self) -> String {
(*self).write_string()
}
}
impl<T: WriteString> WriteString for Option<T> {
fn write_string(&self) -> String {
if let Some(this) = self {
this.write_string()
} else {
"".to_string()
}
}
}
impl WriteLine for TranslationUnit {
fn write_line(&self, _indent: usize, _write: &mut dyn Write) -> Result<()> {
todo!("homework 1")
}
}