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 refactorMulticlassMachine
Refectoring LinearMachine
Contiune to refactor Machine
s to make Machine
s 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:
- 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) - 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) - 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 Machine
s. The following parts is that how I implementate this LibTooling
part.
- 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")))));
- Add the label parameter for the coressbonding method.
we have got thememberExpr
, then we can use another astmatcher to find the corressbonding method.then we should add the labels argument for the method, first, find the position before right parentheses.auto methods = cxxMethodDecl(
hasDescendant(labels), ofClass(isSameOrDerivedFrom("MulticlassMachine")),
unless(hasAnyParameter(
parmVarDecl(hasType(asString("std::shared_ptr<Labels>"))))));second, insert theauto loc = MatchedDecl->getTypeSourceInfo()->getTypeLoc().getAs<FunctionTypeLoc>();
const std::shared_ptr<Labels>& labs
to the found position.FixItHint::CreateInsertion(loc.getLocalSourceRange().getEnd(), ", const std::shared_ptr<Labels>& labs");
- 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 thoseCXXMemberCallExpr
.then get the right position, and insert labels argument.auto call_methods = cxxMemberCallExpr(callee(methods));
FixItHint::CreateInsertion(paramRange, inserted_context);
- 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 thecxxCtorInitializer
.useauto Initializer = cxxConstructorDecl(
hasAnyConstructorInitializer(
cxxCtorInitializer(isBaseInitializer()).bind("init")),
ofClass(isDerivedFrom("MulticlassMachine")));MatchedDecl->getInit()
to get theCXXConstructExpr
, then we can just remove the arguments that have type ofstd::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);
}
}
}