Add Generator for visitor pattern (#89)

Signed-off-by: FluorineDog <guilin.gou@zilliz.com>
pull/4973/head^2
FluorineDog 2020-11-05 14:30:52 +08:00 committed by yefu.chen
parent 6828d19d37
commit e45df02874
33 changed files with 430 additions and 37 deletions

View File

@ -7,7 +7,7 @@ fi
CorePath=$1
formatThis() {
find "$1" | grep -E "(*\.cpp|*\.h|*\.cc)$" | grep -v "/thirdparty" | grep -v "\.pb\." | xargs clang-format-10 -i
find "$1" | grep -E "(*\.cpp|*\.h|*\.cc)$" | grep -v "gen_tools/templates" | grep -v "/thirdparty" | grep -v "\.pb\." | xargs clang-format-10 -i
}
formatThis "${CorePath}/src"

View File

@ -1,6 +1,8 @@
# TODO
set(MILVUS_QUERY_SRCS
BinaryQuery.cpp
deprecated/BinaryQuery.cpp
generated/PlanNode.cpp
generated/Expr.cpp
Parser.cpp
)
add_library(milvus_query ${MILVUS_QUERY_SRCS})

View File

@ -54,15 +54,6 @@ struct BoolBinaryExpr : BinaryExpr {
accept(ExprVisitor&) override;
};
// // TODO: not enabled in sprint 1
// struct ArthmeticBinaryOpExpr : BinaryExpr {
// enum class OpType { Add, Sub, Multiply, Divide };
// OpType op_type_;
// public:
// void
// accept(ExprVisitor&) override;
// };
using FieldId = int64_t;
struct TermExpr : Expr {

View File

@ -1,8 +1,8 @@
#pragma once
#include "pb/service_msg.pb.h"
#include "query/BooleanQuery.h"
#include "query/BinaryQuery.h"
#include "query/GeneralQuery.h"
#include "query/deprecated/BooleanQuery.h"
#include "query/deprecated/BinaryQuery.h"
#include "query/deprecated/GeneralQuery.h"
namespace milvus::wtf {

View File

@ -4,53 +4,53 @@
#include <any>
#include <string>
#include <optional>
#include "Predicate.h"
#include "Expr.h"
namespace milvus::query {
class QueryNodeVisitor;
class PlanNodeVisitor;
enum class QueryNodeType {
enum class PlanNodeType {
kInvalid = 0,
kScan,
kANNS,
};
// Base of all Nodes
struct QueryNode {
QueryNodeType node_type;
struct PlanNode {
PlanNodeType node_type;
public:
virtual ~QueryNode() = default;
virtual ~PlanNode() = default;
virtual void
accept(QueryNodeVisitor&) = 0;
accept(PlanNodeVisitor&) = 0;
};
using QueryNodePtr = std::unique_ptr<QueryNode>;
using PlanNodePtr = std::unique_ptr<PlanNode>;
struct VectorQueryNode : QueryNode {
std::optional<QueryNodePtr> child_;
struct VectorPlanNode : PlanNode {
std::optional<PlanNodePtr> child_;
int64_t num_queries_;
int64_t dim_;
FieldId field_id_;
public:
virtual void
accept(QueryNodeVisitor&) = 0;
accept(PlanNodeVisitor&) = 0;
};
struct FloatVectorANNS : VectorQueryNode {
struct FloatVectorANNS : VectorPlanNode {
std::shared_ptr<float> data;
std::string metric_type_; // TODO: use enum
public:
void
accept(QueryNodeVisitor&) override;
accept(PlanNodeVisitor&) override;
};
struct BinaryVectorANNS : VectorQueryNode {
struct BinaryVectorANNS : VectorPlanNode {
std::shared_ptr<uint8_t> data;
std::string metric_type_; // TODO: use enum
public:
void
accept(QueryNodeVisitor&) override;
accept(PlanNodeVisitor&) override;
};
} // namespace milvus::query

View File

@ -1 +0,0 @@
#pragma once

View File

@ -16,7 +16,7 @@
#include <utility>
#include <vector>
#include "query/BinaryQuery.h"
#include "BinaryQuery.h"
namespace milvus {
namespace query_old {

View File

@ -9,7 +9,7 @@
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
// or implied. See the License for the specific language governing permissions and limitations under the License.
#include "query/ValidationUtil.h"
#include "ValidationUtil.h"
#include "config/ServerConfig.h"
//#include "db/Constants.h"
//#include "db/Utils.h"

View File

@ -0,0 +1,28 @@
#pragma once
// Generated File
// DO NOT EDIT
#include "query/Expr.h"
#include "ExprVisitor.h"
namespace milvus::query {
void
BoolUnaryExpr::accept(ExprVisitor& visitor) {
visitor.visit(*this);
}
void
BoolBinaryExpr::accept(ExprVisitor& visitor) {
visitor.visit(*this);
}
void
TermExpr::accept(ExprVisitor& visitor) {
visitor.visit(*this);
}
void
RangeExpr::accept(ExprVisitor& visitor) {
visitor.visit(*this);
}
} // namespace milvus::query

View File

@ -0,0 +1,23 @@
#pragma once
// Generated File
// DO NOT EDIT
#include "query/Expr.h"
namespace milvus::query {
class ExprVisitor {
public:
virtual ~ExprVisitor() = 0;
public:
virtual void
visit(BoolUnaryExpr&) = 0;
virtual void
visit(BoolBinaryExpr&) = 0;
virtual void
visit(TermExpr&) = 0;
virtual void
visit(RangeExpr&) = 0;
};
} // namespace milvus::query

View File

@ -0,0 +1,18 @@
#pragma once
// Generated File
// DO NOT EDIT
#include "query/PlanNode.h"
#include "PlanNodeVisitor.h"
namespace milvus::query {
void
FloatVectorANNS::accept(PlanNodeVisitor& visitor) {
visitor.visit(*this);
}
void
BinaryVectorANNS::accept(PlanNodeVisitor& visitor) {
visitor.visit(*this);
}
} // namespace milvus::query

View File

@ -0,0 +1,17 @@
#pragma once
// Generated File
// DO NOT EDIT
#include "query/PlanNode.h"
namespace milvus::query {
class PlanNodeVisitor {
public:
virtual ~PlanNodeVisitor() = 0;
public:
virtual void
visit(FloatVectorANNS&) = 0;
virtual void
visit(BinaryVectorANNS&) = 0;
};
} // namespace milvus::query

View File

@ -0,0 +1,25 @@
#error TODO: copy this file out, and modify the content.
#include "query/generated/ShowExprVisitor.h"
namespace milvus::query {
void
ShowExprVisitor::visit(BoolUnaryExpr& expr) {
// TODO
}
void
ShowExprVisitor::visit(BoolBinaryExpr& expr) {
// TODO
}
void
ShowExprVisitor::visit(TermExpr& expr) {
// TODO
}
void
ShowExprVisitor::visit(RangeExpr& expr) {
// TODO
}
} // namespace milvus::query

View File

@ -0,0 +1,22 @@
#pragma once
// Generated File
// DO NOT EDIT
#include "ExprVisitor.h"
namespace milvus::query {
class ShowExprVisitor : ExprVisitor {
public:
virtual void
visit(BoolUnaryExpr& expr) override;
virtual void
visit(BoolBinaryExpr& expr) override;
virtual void
visit(TermExpr& expr) override;
virtual void
visit(RangeExpr& expr) override;
public:
};
} // namespace milvus::query

View File

@ -0,0 +1,15 @@
#error TODO: copy this file out, and modify the content.
#include "query/generated/ShowPlanNodeVisitor.h"
namespace milvus::query {
void
ShowPlanNodeVisitor::visit(FloatVectorANNS& node) {
// TODO
}
void
ShowPlanNodeVisitor::visit(BinaryVectorANNS& node) {
// TODO
}
} // namespace milvus::query

View File

@ -0,0 +1,16 @@
#pragma once
// Generated File
// DO NOT EDIT
#include "PlanNodeVisitor.h"
namespace milvus::query {
class ShowPlanNodeVisitor : PlanNodeVisitor {
public:
virtual void
visit(FloatVectorANNS& node) override;
virtual void
visit(BinaryVectorANNS& node) override;
public:
};
} // namespace milvus::query

View File

@ -6,7 +6,7 @@
#include "segcore/SegmentDefs.h"
// #include "knowhere/index/Index.h"
// #include "knowhere/index/IndexType.h"
#include "query/GeneralQuery.h"
#include "query/deprecated/GeneralQuery.h"
namespace milvus {
namespace segcore {

View File

@ -11,7 +11,7 @@
#include "ConcurrentVector.h"
#include "segcore/SegmentBase.h"
// #include "knowhere/index/structured_index/StructuredIndex.h"
#include "query/GeneralQuery.h"
#include "query/deprecated/GeneralQuery.h"
#include "utils/Status.h"
#include "segcore/DeletedRecord.h"
#include "EasyAssert.h"

View File

@ -11,7 +11,7 @@
#include "ConcurrentVector.h"
#include "segcore/SegmentBase.h"
// #include "knowhere/index/structured_index/StructuredIndex.h"
#include "query/GeneralQuery.h"
#include "query/deprecated/GeneralQuery.h"
#include "utils/Status.h"
#include "segcore/DeletedRecord.h"
#include "EasyAssert.h"

View File

@ -1,7 +1,9 @@
#include <gtest/gtest.h>
#include "query/Parser.h"
#include "query/Predicate.h"
#include "query/QueryNode.h"
#include "query/Expr.h"
#include "query/PlanNode.h"
#include "query/generated/ExprVisitor.h"
#include "query/generated/PlanNodeVisitor.h"
TEST(Query, Naive) {
SUCCEED();

View File

54
tools/core_gen/all_generate.py Executable file
View File

@ -0,0 +1,54 @@
#!python
# from gen_base_visitor import *
# from gen_node import *
from assemble import *
from meta_gen import *
def gen_file(rootfile, template, output, **kwargs):
namespace, root_base, struct_name = meta_gen(readfile(rootfile))
vc = assemble(readfile(template), namespace=namespace, root_base=root_base, struct_name=struct_name, **kwargs)
file = open(output, 'w')
file.write(vc)
if __name__ == "__main__":
query_path = "../../internal/core/src/query/"
output_path = query_path + "generated/"
node_names = ["Expr", "PlanNode"]
visitor_info = {
'Expr': [{
'visitor_name': "ShowExprVisitor",
"ctor_and_member": ' public:',
"parameter_name": 'expr',
}],
'PlanNode': [{
'visitor_name': "ShowPlanNodeVisitor",
"ctor_and_member": ' public:',
"parameter_name": 'node',
}]
}
for name in node_names:
rootfile = query_path + name + ".h"
template = 'templates/visitor_base.h'
output = output_path + name + 'Visitor.h'
gen_file(rootfile, template, output)
template = 'templates/node_def.cpp'
output = output_path + name + '.cpp'
gen_file(rootfile, template, output)
for info in visitor_info[name]:
vis_name = info['visitor_name']
template = 'templates/visitor_derived.h'
output = output_path + vis_name + '.h'
gen_file(rootfile, template, output, **info)
vis_name = info['visitor_name']
template = 'templates/visitor_derived.cpp'
output = output_path + vis_name + '.cpp'
gen_file(rootfile, template, output, **info)
print("Done")

39
tools/core_gen/assemble.py Executable file
View File

@ -0,0 +1,39 @@
#!python
from meta_gen import *
import copy
import sys
import re
def assemble(template, **kwargs):
pattern = re.compile("@@@@(.*?)\n((.|\n)*?)\n####", re.MULTILINE)
temp_info = pattern.findall(template)
# print(temp_info)
mapping = dict()
rep_map = dict()
# drop repetive field from mapping
for k, v in kwargs.items():
if isinstance(v, list):
rep_map[k] = v
else:
mapping[k] = v
for k, v, _ in temp_info:
info = k.split("@")
new_v = replace_all(v, **mapping)
assert(1 <= len(info) <= 2)
if len(info) == 2:
k = info[0]
rep = info[1]
new_v = "\n\n".join([new_v.replace("@@" + rep + "@@", rep_v) for rep_v in rep_map[rep]])
mapping[k] = new_v
return mapping["main"]
# if __name__ == "__main__":
# assert(len(sys.argv) == 2)
# root_file = sys.argv[1]
# namespace, root_base, struct_name = meta_gen(readfile(root_file))
# gen_all(readfile("templates/node_full.cpp"), namespace=namespace, root_base=root_base, struct_name=struct_name)

62
tools/core_gen/meta_gen.py Executable file
View File

@ -0,0 +1,62 @@
#!python
import re
import sys
def eprint(*args, **kwargs):
print(*args, file=sys.stderr, **kwargs)
def readfile(filename):
file = open(filename)
content = file.read()
return content
def replace_all(template, **kwargs):
for k, v in kwargs.items():
template = template.replace("@@" + k + "@@", v)
return template
def meta_gen(content):
namespace_pattern = re.compile(r"namespace(.*){")
results = namespace_pattern.findall(content)
assert(len(results) == 1)
namespace = results[0].strip()
struct_pattern = re.compile(r"struct (.*?){((.|\n)*?)^};", re.MULTILINE)
results = struct_pattern.findall(content)
body_pattern = re.compile(r"accept\((.*)Visitor ?& ?\) (.*?);")
# print(results)
# print(len(results[0]))
root_base = None
override_structs = []
for (title, body, _) in results:
pack = title.replace(' ', '').split(':')
if len(pack) == 1:
pack.append(None)
struct_name, base_name = pack
if not base_name:
root_base = struct_name
body_res = body_pattern.findall(body)
if len(body_res) != 1:
eprint(struct_name)
eprint(body_res)
eprint(body)
assert(false)
visitor_name, state = body_res[0]
assert(visitor_name == root_base)
if state.strip() == 'override':
override_structs.append(struct_name)
# print(body_res)
return namespace, root_base, override_structs
if __name__ == "__main__":
assert(len(sys.argv) == 2)
file = open(sys.argv[1])
content = file.read()
namespace, root_base, override_structs = meta_gen(content)
eprint(namespace)
eprint(root_base)
eprint(override_structs)

View File

View File

@ -0,0 +1,20 @@
@@@@body@struct_name
void
@@struct_name@@::accept(@@root_base@@Visitor& visitor) {
visitor.visit(*this);
}
####
@@@@main
#pragma once
// Generated File
// DO NOT EDIT
#include "query/@@root_base@@.h"
#include "@@root_base@@Visitor.h"
namespace @@namespace@@ {
@@body@@
} // namespace @@namespace@@
####

View File

@ -0,0 +1,20 @@
@@@@body@struct_name
virtual void
visit(@@struct_name@@&) = 0;
####
@@@@main
#pragma once
// Generated File
// DO NOT EDIT
#include "query/@@root_base@@.h"
namespace @@namespace@@ {
class @@root_base@@Visitor {
public:
virtual ~@@root_base@@Visitor() = 0;
public:
@@body@@
};
} // namespace @@namespace@@
####

View File

@ -0,0 +1,18 @@
@@@@func_list@struct_name
void
@@visitor_name@@::visit(@@struct_name@@& @@parameter_name@@) {
// TODO
}
####
@@@@main
#error TODO: copy this file out, and modify the content.
#include "query/generated/@@visitor_name@@.h"
namespace @@namespace@@ {
@@func_list@@
} // namespace @@namespace@@
####

View File

@ -0,0 +1,22 @@
@@@@base_visitor
@@root_base@@Visitor
####
@@@@body@struct_name
virtual void
visit(@@struct_name@@& @@parameter_name@@) override;
####
@@@@main
#pragma once
// Generated File
// DO NOT EDIT
#include "@@base_visitor@@.h"
namespace @@namespace@@ {
class @@visitor_name@@ : @@base_visitor@@ {
public:
@@body@@
@@ctor_and_member@@
};
} // namespace @@namespace@@
####