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 {