progress

I'd rather be anything but ordinary

0%

GSoC Second Evaluations

This blog summarizes what I have done before GSoC’s second evaluation. I will talk about two things:

  • Refectoring LinearMachine
  • Writing a new LibTooling script to automatically refactor MulticlassMachine

Refectoring LinearMachine

Contiune to refactor Machines to make Machines stateless, the approach is similar to Non-parametric machines, Remove all constructor parameter that involving in labels/features, change all std::shared to const std::shared &, the only different thing is that we don’t want store label and feature in parametric machine, so we will add labels/features parameters in every method that need to access m_labels/m_features. LinearMachine is one of parametric machine.
The typical parametric machine refactor looks like this:

  1. Remove all constructor parameter that involving in labels/features.
    -NewtonSVM::NewtonSVM(float64_t c, std::shared_ptr<DotFeatures> traindat, std::shared_ptr<Labels> trainlab, int32_t itr)
    +NewtonSVM::NewtonSVM(float64_t c, int32_t itr)
  2. add labels/features parameters in every method that need to access m_labels/m_features
    -void NewtonSVM::init_model(std::shared_ptr<Features> data)
    +void NewtonSVM::init_model(const std::shared_ptr<DotFeatures>& features)
  3. change all std::shared_ptr parameter to const std::shared_ptr &
    -bool SGDQN::train(std::shared_ptr<Features> data)
    +bool SGDQN::train_machine(
    const std::shared_ptr<DotFeatures>& features, const std::shared_ptr<Labels>& labs)

Writing a new LibTooling script to automatically refactor MulticlassMachine

When you read the part of refactor LinearMachine, you may find that there are some repeted pattern exists, there are mainly 4 things in refactor, 1. remove label/features parameter in constructor, 2, add labels/features parameters in every method that need to access m_labels/m_features. 3, add argument for corresbonding call side. 4. change all std::shared_ptr to const std::shared_ptr &

From work of last month, we know LibTooling is a good tool to do those repeted things. So I choose to write a more powerfull tool which can automactically refactor MulticlassMachine, and it also can be use to refactor other Machines. The following parts is that how I implementate this LibTooling part.

  1. Find expressions access m_labels
    this part can be easily done by astmatcher.
    auto labels = memberExpr(member(hasName("m_labels")), hasAncestor(cxxMethodDecl(ofClass(isSameOrDerivedFrom("MulticlassMachine")))));
  2. Add the label parameter for the coressbonding method.
    we have got the memberExpr, then we can use another astmatcher to find the corressbonding method.
    auto methods = cxxMethodDecl(
    hasDescendant(labels), ofClass(isSameOrDerivedFrom("MulticlassMachine")),
    unless(hasAnyParameter(
    parmVarDecl(hasType(asString("std::shared_ptr<Labels>"))))));
    then we should add the labels argument for the method, first, find the position before right parentheses.
    auto loc = MatchedDecl->getTypeSourceInfo()->getTypeLoc().getAs<FunctionTypeLoc>();
    second, insert the const std::shared_ptr<Labels>& labs to the found position.
    FixItHint::CreateInsertion(loc.getLocalSourceRange().getEnd(), ", const std::shared_ptr<Labels>& labs");
  3. Fix the corresbonding call expression.
    we have changed the arguments of those methods, now we should fix the call side of those methods, again, use astmatcher find those CXXMemberCallExpr.
    auto call_methods = cxxMemberCallExpr(callee(methods));
    then get the right position, and insert labels argument.
    FixItHint::CreateInsertion(paramRange, inserted_context);
  4. Fix the arguments of constructor of classes have been changed.
    we have removed the label/feature argument of constructor, then we should also remove the corresbonding constructor initializer, we can use the following astmatcher find the cxxCtorInitializer.
    auto Initializer = cxxConstructorDecl(
    hasAnyConstructorInitializer(
    cxxCtorInitializer(isBaseInitializer()).bind("init")),
    ofClass(isDerivedFrom("MulticlassMachine")));
    use MatchedDecl->getInit() to get the CXXConstructExpr, then we can just remove the arguments that have type of std::shared_ptr<Labels>/std::shared_ptr<Features>.
    if (auto expr = dyn_cast<CXXConstructExpr>(child))
    {
    for (auto e : expr->arguments())
    {
    if (e->getType().getAsString() == "std::shared_ptr<Labels>")
    {
    auto loc = e->getSourceRange();
    FixItHint::CreateRemoval(loc);
    }
    }
    }