/*
 * Copyright 2011, The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "slang_rs_ast_replace.h"

#include "slang_assert.h"

#include "llvm/Support/Casting.h"

namespace slang {

void RSASTReplace::ReplaceStmt(
    clang::Stmt *OuterStmt,
    clang::Stmt *OldStmt,
    clang::Stmt *NewStmt) {
  mOldStmt = OldStmt;
  mNewStmt = NewStmt;
  mOuterStmt = OuterStmt;

  // This simplifies use in various Stmt visitor passes where the only
  // valid type is an Expr.
  mOldExpr = llvm::dyn_cast<clang::Expr>(OldStmt);
  if (mOldExpr) {
    mNewExpr = llvm::dyn_cast<clang::Expr>(NewStmt);
  }
  Visit(mOuterStmt);
}

void RSASTReplace::ReplaceInCompoundStmt(clang::CompoundStmt *CS) {
  clang::Stmt **UpdatedStmtList = new clang::Stmt*[CS->size()];

  unsigned UpdatedStmtCount = 0;
  clang::CompoundStmt::body_iterator bI = CS->body_begin();
  clang::CompoundStmt::body_iterator bE = CS->body_end();

  for ( ; bI != bE; bI++) {
    if (matchesStmt(*bI)) {
      UpdatedStmtList[UpdatedStmtCount++] = mNewStmt;
    } else {
      UpdatedStmtList[UpdatedStmtCount++] = *bI;
    }
  }

  CS->setStmts(C, UpdatedStmtList, UpdatedStmtCount);

  delete [] UpdatedStmtList;

  return;
}

void RSASTReplace::VisitStmt(clang::Stmt *S) {
  // This function does the actual iteration through all sub-Stmt's within
  // a given Stmt. Note that this function is skipped by all of the other
  // Visit* functions if we have already found a higher-level match.
  for (clang::Stmt::child_iterator I = S->child_begin(), E = S->child_end();
       I != E;
       I++) {
    if (clang::Stmt *Child = *I) {
      if (!matchesStmt(Child)) {
        Visit(Child);
      }
    }
  }
  return;
}

void RSASTReplace::VisitCompoundStmt(clang::CompoundStmt *CS) {
  VisitStmt(CS);
  ReplaceInCompoundStmt(CS);
  return;
}

void RSASTReplace::VisitCaseStmt(clang::CaseStmt *CS) {
  if (matchesStmt(CS->getSubStmt())) {
    CS->setSubStmt(mNewStmt);
  } else {
    VisitStmt(CS);
  }
  return;
}

void RSASTReplace::VisitDefaultStmt(clang::DefaultStmt *DS) {
  if (matchesStmt(DS->getSubStmt())) {
    DS->setSubStmt(mNewStmt);
  } else {
    VisitStmt(DS);
  }
  return;
}

void RSASTReplace::VisitDoStmt(clang::DoStmt *DS) {
  if (matchesExpr(DS->getCond())) {
    DS->setCond(mNewExpr);
  } else if (matchesStmt(DS->getBody())) {
    DS->setBody(mNewStmt);
  } else {
    VisitStmt(DS);
  }
  return;
}

void RSASTReplace::VisitForStmt(clang::ForStmt *FS) {
  if (matchesStmt(FS->getInit())) {
    FS->setInit(mNewStmt);
  } else if (matchesExpr(FS->getCond())) {
    FS->setCond(mNewExpr);
  } else if (matchesExpr(FS->getInc())) {
    FS->setInc(mNewExpr);
  } else if (matchesStmt(FS->getBody())) {
    FS->setBody(mNewStmt);
  } else {
    VisitStmt(FS);
  }
  return;
}

void RSASTReplace::VisitIfStmt(clang::IfStmt *IS) {
  if (matchesExpr(IS->getCond())) {
    IS->setCond(mNewExpr);
  } else if (matchesStmt(IS->getThen())) {
    IS->setThen(mNewStmt);
  } else if (matchesStmt(IS->getElse())) {
    IS->setElse(mNewStmt);
  } else {
    VisitStmt(IS);
  }
  return;
}

void RSASTReplace::VisitSwitchCase(clang::SwitchCase *SC) {
  slangAssert(false && "Both case and default have specialized handlers");
  VisitStmt(SC);
  return;
}

void RSASTReplace::VisitSwitchStmt(clang::SwitchStmt *SS) {
  if (matchesExpr(SS->getCond())) {
    SS->setCond(mNewExpr);
  } else {
    VisitStmt(SS);
  }
  return;
}

void RSASTReplace::VisitWhileStmt(clang::WhileStmt *WS) {
  if (matchesExpr(WS->getCond())) {
    WS->setCond(mNewExpr);
  } else if (matchesStmt(WS->getBody())) {
    WS->setBody(mNewStmt);
  } else {
    VisitStmt(WS);
  }
  return;
}

}  // namespace slang
