[nnc] Add more tests for acl dom to text operations (#2719)
authorEfimov Alexander/AI Tools Lab/./Samsung Electronics <a.efimov@samsung.com>
Wed, 26 Dec 2018 20:30:54 +0000 (23:30 +0300)
committerGitHub Enterprise <noreply-CODE@samsung.com>
Wed, 26 Dec 2018 20:30:54 +0000 (23:30 +0300)
Tested entities:
- ArtifactIndex
- ArtifactRet
- ArtifactBreak
- ArtifactCont
- ArtifactVariable
- ArtifactBlock
- ArtifactForLoop
- ArtifactIf
- ArtifactFunction
- ArtifactClassVariable
- ArtifactClassFunction
- ArtifactClass
- ArtifactModule

Signed-off-by: Efimov Alexander <a.efimov@samsung.com>
contrib/nnc/passes/acl_soft_backend/ArtifactGeneratorCppCode.cpp
contrib/nnc/passes/acl_soft_backend/ArtifactGeneratorCppDecl.cpp
contrib/nnc/unittests/acl_backend/CMakeLists.txt
contrib/nnc/unittests/acl_backend/DOMToText.cpp

index 44fb100..d81fdf9 100644 (file)
@@ -184,6 +184,7 @@ void ArtifactGeneratorCppCode::visit(const ArtifactIf* node) {
 }
 
 void ArtifactGeneratorCppCode::visit(const ArtifactFunction* node) {
+  // TODO implement this function
 }
 
 void ArtifactGeneratorCppCode::visit(const ArtifactClass* node) {
@@ -203,6 +204,8 @@ void ArtifactGeneratorCppCode::visit(const ArtifactClass* node) {
     }
   }
 
+  //TODO add constructors of public variables
+
   node->getConstrBlock()->accept(this);
   _out << endl;
 
index a65d0b4..d415f48 100644 (file)
@@ -119,6 +119,8 @@ void ArtifactGeneratorCppDecl::visit(const ArtifactClass* node) {
   if (!node->privateFunctions().empty())
     _out << endl;
 
+  // TODO add public variables
+
   for (auto e : node->privateVariables()) {
     _out << _ind;
     e->accept(this);
index afc430b..012ae37 100644 (file)
@@ -1,8 +1,11 @@
 set(ACL_CPP_BACKEND_UTEST_SOURCES DOMToText.cpp MIRToDOM.cpp)
 
-add_nnc_unit_test(nnc_acl_cpp_backend_test ${ACL_CPP_BACKEND_UTEST_SOURCES} ${OPTIONS_SRC})
+file(GLOB_RECURSE ACL_IN_SOURCES "${NNC_ACL_BACKEND_DIR}/*.in")
+make_generated_sources("${ACL_IN_SOURCES}" ${CMAKE_CURRENT_BINARY_DIR} ACL_GENERATED_SOURCES)
+
+add_nnc_unit_test(nnc_acl_cpp_backend_test ${ACL_CPP_BACKEND_UTEST_SOURCES} ${OPTIONS_SRC} ${ACL_GENERATED_SOURCES})
 
 if (TARGET nnc_acl_cpp_backend_test)
     nncc_target_link_libraries(nnc_acl_cpp_backend_test nnc_core nnc_support acl_soft_backend_cpp)
-    target_include_directories(nnc_acl_cpp_backend_test PRIVATE ${NNC_ACL_BACKEND_DIR})
+    target_include_directories(nnc_acl_cpp_backend_test PRIVATE ${NNC_ACL_BACKEND_DIR} ${CMAKE_CURRENT_BINARY_DIR})
 endif()
index ee52b3a..d071a01 100644 (file)
@@ -27,6 +27,8 @@
 #include "ArtifactGeneratorCppCode.h"
 #include "ArtifactGeneratorCppDecl.h"
 
+#include "AclArtifactUtilities.generated.h"
+
 #include "gtest/gtest.h"
 
 using namespace std;
@@ -203,54 +205,281 @@ TEST(acl_backend_dom_to_text, ArtifactBinaryExpr) {
   }
 }
 
-TEST(acl_backend_dom_to_text, DISABLED_ArtifactIndex) {
-  //TODO
+TEST(acl_backend_dom_to_text, ArtifactIndex) {
+  stringstream code_out;
+  ArtifactGeneratorCppCode code_gen(code_out);
+  const char* arr_name = "a";
+  const char* idx_name = "b";
+  shared_ptr<ArtifactId> arr = AF::id(arr_name);
+  shared_ptr<ArtifactId> idx = AF::id(idx_name);
+  shared_ptr<ArtifactIndex> indexing = AF::ind(arr, idx);
+  indexing->accept(&code_gen);
+  ASSERT_EQ(code_out.str(), "a[b]");
 }
 
-TEST(acl_backend_dom_to_text, DISABLED_ArtifactRet) {
-  //TODO
+TEST(acl_backend_dom_to_text, ArtifactRet) {
+  stringstream code_out;
+  ArtifactGeneratorCppCode code_gen(code_out);
+  const char* result_name = "a";
+  shared_ptr<ArtifactId> result = AF::id(result_name);
+  ArtifactRet ret(result);
+  ret.accept(&code_gen);
+  ASSERT_EQ(code_out.str(), "return a");
 }
 
-TEST(acl_backend_dom_to_text, DISABLED_ArtifactBreak) {
-  //TODO
+TEST(acl_backend_dom_to_text, ArtifactBreak) {
+  stringstream code_out;
+  ArtifactGeneratorCppCode code_gen(code_out);
+  ArtifactBreak brk;
+  brk.accept(&code_gen);
+  ASSERT_EQ(code_out.str(), "break");
 }
 
-TEST(acl_backend_dom_to_text, DISABLED_ArtifactCont) {
-  //TODO
+TEST(acl_backend_dom_to_text, ArtifactCont) {
+  stringstream code_out;
+  ArtifactGeneratorCppCode code_gen(code_out);
+  ArtifactCont cont;
+  cont.accept(&code_gen);
+  ASSERT_EQ(code_out.str(), "continue");
 }
 
-TEST(acl_backend_dom_to_text, DISABLED_ArtifactVariable) {
-  //TODO
+TEST(acl_backend_dom_to_text, ArtifactVariable) {
+  stringstream code_out;
+  ArtifactGeneratorCppCode code_gen(code_out);
+  const char* var_type = "int";
+  const char* var_name = "data";
+  shared_ptr<ArtifactLiteral> dim1 = AF::lit("2");
+  shared_ptr<ArtifactLiteral> dim2 = AF::lit("3");
+  list<shared_ptr<ArtifactExpr>> dims{dim1, dim2};
+  list<shared_ptr<ArtifactExpr>> initializers{AF::lit("123")};
+  shared_ptr<ArtifactVariable> var_decl = AF::var(var_type, var_name, dims, initializers);
+  var_decl->accept(&code_gen);
+  // TODO generate initializers in braces
+  ASSERT_EQ(code_out.str(), "int data[2][3](123)");
 }
 
-TEST(acl_backend_dom_to_text, DISABLED_ArtifactBlock) {
-  //TODO
+TEST(acl_backend_dom_to_text, ArtifactBlock) {
+  stringstream code_out;
+  ArtifactGeneratorCppCode code_gen(code_out);
+  const char* var_name = "var";
+  const char* lit_val = "123";
+
+  shared_ptr<ArtifactExpr> id = AF::id(var_name);
+  shared_ptr<ArtifactExpr> lit = AF::lit(lit_val);
+  const list<shared_ptr<ArtifactExpr>> args{id, lit};
+
+  shared_ptr<ArtifactFunctionCall> call = AF::call("foo", args);
+
+  ArtifactBlock block;
+
+  block.addStatement(call);
+
+  block.accept(&code_gen);
+  ASSERT_EQ(code_out.str(), " {\n  foo(var, 123);\n}\n");
 }
 
-TEST(acl_backend_dom_to_text, DISABLED_ArtifactForLoop) {
-  //TODO
+TEST(acl_backend_dom_to_text, ArtifactForLoop) {
+  stringstream code_out;
+  ArtifactGeneratorCppCode code_gen(code_out);
+  const char* var_name = "i";
+  const char* var_type = "int";
+
+  shared_ptr<ArtifactVariable> iter = AF::var(var_type, var_name, {}, {AF::lit("0")});
+  shared_ptr<ArtifactExpr> step = AF::bin(ArtifactBinOp::plusAssign, AF::id(var_name), AF::lit("1"));
+  shared_ptr<ArtifactExpr> cond = AF::bin(ArtifactBinOp::lessOrEq, AF::id(var_name), AF::lit("123"));
+
+  shared_ptr<ArtifactBinaryExpr> expr = AF::bin(ArtifactBinOp::plusAssign, AF::id("hello"), AF::id("world"));
+
+  ArtifactForLoop loop(iter, cond, step);
+
+  loop.getBlock()->addStatement(expr);
+
+  loop.accept(&code_gen);
+  ASSERT_EQ(code_out.str(), "for(int i(0); i <= 123; i += 1) {\n  hello += world;\n}\n");
+}
+
+TEST(acl_backend_dom_to_text, ArtifactIf) {
+  stringstream code_out;
+  ArtifactGeneratorCppCode code_gen(code_out);
+  const char* var_name = "i";
+
+  shared_ptr<ArtifactExpr> cond = AF::bin(ArtifactBinOp::lessOrEq, AF::id(var_name), AF::lit("123"));
+
+  shared_ptr<ArtifactBinaryExpr> expr = AF::bin(ArtifactBinOp::plusAssign, AF::id("hello"), AF::id("world"));
+
+  ArtifactIf if_stmt(cond);
+
+  if_stmt.getBlock()->addStatement(expr);
+
+  if_stmt.accept(&code_gen);
+  ASSERT_EQ(code_out.str(), "if(i <= 123) {\n  hello += world;\n}\n");
+}
+
+TEST(acl_backend_dom_to_text, ArtifactFunction) {
+  stringstream code_out;
+  stringstream decl_out;
+  ArtifactGeneratorCppCode code_gen(code_out);
+  ArtifactGeneratorCppDecl decl_gen(decl_out);
+  const char* ret_type = "int";
+  const char* func_name = "foo";
+  shared_ptr<ArtifactVariable> arg1 = AF::var("int", "a");
+  shared_ptr<ArtifactVariable> arg2 = AF::var("bool", "b");
+  list<shared_ptr<ArtifactVariable>> args{arg1, arg2};
+
+  // test public class variable
+  ArtifactFunction func_decl(ret_type, func_name, args);
+
+  func_decl.accept(&code_gen);
+  ASSERT_EQ(code_out.str(), "");
+  func_decl.accept(&decl_gen);
+
+  ASSERT_EQ(decl_out.str(), "int foo(int a, bool b);");
 }
 
-TEST(acl_backend_dom_to_text, DISABLED_ArtifactIf) {
-  //TODO
+TEST(acl_backend_dom_to_text, ArtifactClassVariable) {
+  stringstream code_out;
+  stringstream decl_out;
+  ArtifactGeneratorCppCode code_gen(code_out);
+  ArtifactGeneratorCppDecl decl_gen(decl_out);
+
+  const char* var_type = "int";
+  const char* var_name = "data";
+
+  ArtifactClass cls("Class");
+
+  shared_ptr<ArtifactLiteral> dim1 = AF::lit("2");
+  shared_ptr<ArtifactLiteral> dim2 = AF::lit("3");
+  list<shared_ptr<ArtifactExpr>> dims{dim1, dim2};
+  list<shared_ptr<ArtifactExpr>> list_of_initializer{AF::lit("123")};
+  ArtifactClassVariable var_decl(&cls, var_type, var_name, dims, list_of_initializer);
+
+  var_decl.accept(&code_gen);
+  ASSERT_EQ(code_out.str(), "data(123)");
+  var_decl.accept(&decl_gen);
+  // fixme dimensions are not taken into account, remove ';'
+  ASSERT_EQ(decl_out.str(), "int data;\n");
 }
 
-TEST(acl_backend_dom_to_text, DISABLED_ArtifactFunction) {
-  //TODO
+TEST(acl_backend_dom_to_text, ArtifactClassFunction) {
+  stringstream code_out;
+  stringstream decl_out;
+  ArtifactGeneratorCppCode code_gen(code_out);
+  ArtifactGeneratorCppDecl decl_gen(decl_out);
+  const char* ret_type = "int";
+  const char* func_name = "foo";
+  shared_ptr<ArtifactVariable> arg1 = AF::var("int", "a");
+  shared_ptr<ArtifactVariable> arg2 = AF::var("bool", "b");
+  list<shared_ptr<ArtifactVariable>> args{arg1, arg2};
+
+  ArtifactClass cls("Class");
+
+  // test public class variable
+  shared_ptr<ArtifactClassFunction> cls_func_decl = cls.func(true, ret_type, func_name, args);
+
+  cls_func_decl->accept(&code_gen);
+  // FIXME do not print new line in this visitor
+  ASSERT_EQ(code_out.str(), "int Class::foo(int a, bool b) {\n}\n\n");
+  cls_func_decl->accept(&decl_gen);
+
+  ASSERT_EQ(decl_out.str(), "int foo(int a, bool b);\n");
+
+  decl_out.str("");
+  code_out.str("");
+
+  // test private class variable
+  cls_func_decl = cls.func(false, ret_type, func_name, args);
+
+  cls_func_decl->accept(&code_gen);
+  // FIXME do not print new line in this visitor
+  ASSERT_EQ(code_out.str(), "int Class::foo(int a, bool b) {\n}\n\n");
+  cls_func_decl->accept(&decl_gen);
+
+  ASSERT_EQ(decl_out.str(), "int foo(int a, bool b);\n");
 }
 
-TEST(acl_backend_dom_to_text, DISABLED_ArtifactClassVariable) {
-  //TODO
+static shared_ptr<ArtifactClassVariable> createClsVariable(ArtifactClass& cls,
+                                                      const char* var_name,
+                                                      bool is_public) {
+  const char* var_type = "int";
+  shared_ptr<ArtifactLiteral> dim1 = AF::lit("2");
+  shared_ptr<ArtifactLiteral> dim2 = AF::lit("3");
+  list<shared_ptr<ArtifactExpr>> dims{dim1, dim2};
+  list<shared_ptr<ArtifactExpr>> initializers{AF::lit("123")};
+  shared_ptr<ArtifactClassVariable> var_decl =
+      cls.var(is_public, var_type, var_name, dims, initializers);
+  return var_decl;
 }
 
-TEST(acl_backend_dom_to_text, DISABLED_ArtifactClassFunction) {
-  //TODO
+static shared_ptr<ArtifactClassFunction> createClsFunction(ArtifactClass& cls,
+                                                      const char* func_name,
+                                                      bool is_public) {
+  const char* var_type = "int";
+  const char* func_type = "void";
+  shared_ptr<ArtifactVariable> var1 = AF::var(var_type, "a");
+  shared_ptr<ArtifactVariable> var2 = AF::var(var_type, "b");
+  list<shared_ptr<ArtifactVariable>> args{var1, var2};
+  shared_ptr<ArtifactClassFunction> func_decl = cls.func(is_public, func_type, func_name, args);
+  return func_decl;
 }
 
-TEST(acl_backend_dom_to_text, DISABLED_ArtifactClass) {
-  //TODO
+TEST(acl_backend_dom_to_text, ArtifactClass) {
+  stringstream code_out;
+  stringstream decl_out;
+  ArtifactGeneratorCppCode code_gen(code_out);
+  ArtifactGeneratorCppDecl decl_gen(decl_out);
+
+  ArtifactClass cls("Class");
+
+  createClsFunction(cls, "public_foo", true);
+  createClsFunction(cls, "private_bar", false);
+
+  createClsVariable(cls, "visible", true);
+  createClsVariable(cls, "invisible", false);
+
+  // Test cpp file generation
+  cls.accept(&code_gen);
+  ASSERT_EQ(code_out.str(), "Class::Class() : invisible(123) {\n}\n\n"
+                            "void Class::public_foo(int a, int b) {\n}\n\n"
+                            "void Class::private_bar(int a, int b) {\n}\n\n");
+
+  // Test header file generation
+  cls.accept(&decl_gen);
+
+  ASSERT_EQ(decl_out.str(), "class Class {\npublic:\n  Class();\n"
+                            "  void public_foo(int a, int b);"
+                            "\n\nprivate:\n  void private_bar(int a, int b);\n\n"
+                            "  int invisible;\n};\n");
 }
 
-TEST(acl_backend_dom_to_text, DISABLED_ArtifactModule) {
-  //TODO
+TEST(acl_backend_dom_to_text, ArtifactModule) {
+  stringstream code_out;
+  stringstream decl_out;
+  ArtifactGeneratorCppCode code_gen(code_out);
+  ArtifactGeneratorCppDecl decl_gen(decl_out);
+
+  ArtifactModule m("module");
+
+  m.addHeaderInclude("foo.h");
+  m.addHeaderSysInclude("vector");
+  m.addSourceInclude("bar.h");
+  m.addSourceSysInclude("list");
+
+  shared_ptr<ArtifactClass> cls = m.createClass("Class");
+
+  // test cpp file generation
+  // We use snippet code to encode some common functions
+  // This snippet is wrapped in prefix and postfix code
+  const char* code_prefix = "#include \"module.h\"\n\n#include <list>\n\n#include \"bar.h\"\n\n";
+  const char* code_suffix = "\nClass::Class() {\n}\n\n";
+
+  string ref_data = string(code_prefix) +
+      string(AclArtifactUtilities, sizeof(AclArtifactUtilities)) + code_suffix;
+  m.accept(&code_gen);
+  ASSERT_EQ(code_out.str(), ref_data);
+
+  // test header code generation
+  const char* ref_decl_data = "#include \"foo.h\"\n#include \"vector\"\n\nclass Class {\npublic:\n  Class();\n\nprivate:\n};\n";
+  m.accept(&decl_gen);
+
+  ASSERT_EQ(decl_out.str(), ref_decl_data);
 }