Add COMMENT ExpressionType
The comment expression allows the user to insert single-line
comments into the generated code. These will not be moved or
optimized away.
Comment expressions should make it easier to understand the
generated autodiff code.
Change-Id: Ie87d0698aa6af2aac8a437a13b25e0fef33dbfdc
diff --git a/include/ceres/codegen/internal/expression.h b/include/ceres/codegen/internal/expression.h
index 7de7a77..5e1ff2c 100644
--- a/include/ceres/codegen/internal/expression.h
+++ b/include/ceres/codegen/internal/expression.h
@@ -229,6 +229,10 @@
ELSE,
ENDIF,
+ // A single comment line. Even though comments are 'unused' expression they
+ // will not be optimized away.
+ COMMENT,
+
// No Operation. A placeholder for an 'empty' expressions which will be
// optimized out during code generation.
NOP
@@ -301,6 +305,7 @@
static Expression CreateIf(ExpressionId condition);
static Expression CreateElse();
static Expression CreateEndIf();
+ static Expression CreateComment(const std::string& comment);
// Returns true if this is an arithmetic expression.
// Arithmetic expressions must have a valid left hand side.
diff --git a/include/ceres/codegen/macros.h b/include/ceres/codegen/macros.h
index fbb2951..ee5068a 100644
--- a/include/ceres/codegen/macros.h
+++ b/include/ceres/codegen/macros.h
@@ -104,6 +104,7 @@
#define CERES_IF(condition_) if (condition_)
#define CERES_ELSE else
#define CERES_ENDIF
+#define CERES_COMMENT(comment_)
#else
#define CERES_LOCAL_VARIABLE(_template_type, _local_variable) \
ceres::internal::InputAssignment<_template_type>::Get(_local_variable, \
@@ -114,6 +115,8 @@
AddExpressionToGraph(ceres::internal::Expression::CreateElse());
#define CERES_ENDIF \
AddExpressionToGraph(ceres::internal::Expression::CreateEndIf());
+#define CERES_COMMENT(comment_) \
+ AddExpressionToGraph(ceres::internal::Expression::CreateComment(comment_))
#endif
namespace ceres {
diff --git a/internal/ceres/code_generator.cc b/internal/ceres/code_generator.cc
index dd0ab82..76ab48f 100644
--- a/internal/ceres/code_generator.cc
+++ b/internal/ceres/code_generator.cc
@@ -221,6 +221,14 @@
result << indentation_ << "}";
break;
}
+ case ExpressionType::COMMENT: {
+ //
+ // Format: // <name>
+ // Example: // this is a comment
+ //
+ result << indentation_ << "// " + name;
+ break;
+ }
case ExpressionType::NOP: {
//
// Format: // <NOP>
diff --git a/internal/ceres/codegen/code_generator_test.cc b/internal/ceres/codegen/code_generator_test.cc
index a73ccac..17246a8 100644
--- a/internal/ceres/codegen/code_generator_test.cc
+++ b/internal/ceres/codegen/code_generator_test.cc
@@ -510,5 +510,13 @@
GenerateAndCheck(graph, expected_code);
}
+TEST(CodeGenerator, COMMENT) {
+ StartRecordingExpressions();
+ CERES_COMMENT("Hello");
+ auto graph = StopRecordingExpressions();
+ std::vector<std::string> expected_code = {"{", " // Hello", "}"};
+ GenerateAndCheck(graph, expected_code);
+}
+
} // namespace internal
} // namespace ceres
diff --git a/internal/ceres/codegen/expression_ref_test.cc b/internal/ceres/codegen/expression_ref_test.cc
index 88d0562..30672ad 100644
--- a/internal/ceres/codegen/expression_ref_test.cc
+++ b/internal/ceres/codegen/expression_ref_test.cc
@@ -401,5 +401,15 @@
EXPECT_EQ(reference, graph);
}
+TEST(ExpressionRef, COMMENT) {
+ StartRecordingExpressions();
+ CERES_COMMENT("This is a comment");
+ auto graph = StopRecordingExpressions();
+
+ ExpressionGraph reference;
+ reference.InsertBack(Expression::CreateComment("This is a comment"));
+ EXPECT_EQ(reference, graph);
+}
+
} // namespace internal
} // namespace ceres
diff --git a/internal/ceres/codegen/expression_test.cc b/internal/ceres/codegen/expression_test.cc
index ae96ea0..65daf69 100644
--- a/internal/ceres/codegen/expression_test.cc
+++ b/internal/ceres/codegen/expression_test.cc
@@ -169,6 +169,14 @@
{},
"",
0));
+
+ EXPECT_EQ(Expression::CreateComment("Test"),
+ Expression(ExpressionType::COMMENT,
+ ExpressionReturnType::VOID,
+ kInvalidExpressionId,
+ {},
+ "Test",
+ 0));
}
TEST(Expression, IsArithmeticExpression) {
@@ -194,6 +202,7 @@
Expression::CreateBinaryCompare("<", 3, 5).IsControlExpression());
ASSERT_TRUE(Expression::CreateIf(5).IsControlExpression());
ASSERT_TRUE(Expression::CreateEndIf().IsControlExpression());
+ ASSERT_TRUE(Expression::CreateComment("Test").IsControlExpression());
ASSERT_TRUE(Expression().IsControlExpression());
}
diff --git a/internal/ceres/expression.cc b/internal/ceres/expression.cc
index 0fec5a0..1a475b3 100644
--- a/internal/ceres/expression.cc
+++ b/internal/ceres/expression.cc
@@ -160,13 +160,22 @@
return Expression(ExpressionType::ENDIF);
}
+Expression Expression::CreateComment(const std::string& comment) {
+ return Expression(ExpressionType::COMMENT,
+ ExpressionReturnType::VOID,
+ kInvalidExpressionId,
+ {},
+ comment);
+}
+
bool Expression::IsArithmeticExpression() const {
return !IsControlExpression();
}
bool Expression::IsControlExpression() const {
return type_ == ExpressionType::IF || type_ == ExpressionType::ELSE ||
- type_ == ExpressionType::ENDIF || type_ == ExpressionType::NOP;
+ type_ == ExpressionType::ENDIF || type_ == ExpressionType::NOP ||
+ type_ == ExpressionType::COMMENT;
}
bool Expression::IsReplaceableBy(const Expression& other) const {