1 #include <string>
2 #include <mbgl/style/expression/check_subtype.hpp>
3
4 namespace mbgl {
5 namespace style {
6 namespace expression {
7 namespace type {
8
errorMessage(const Type & expected,const Type & t)9 std::string errorMessage(const Type& expected, const Type& t) {
10 return {"Expected " + toString(expected) + " but found " + toString(t) + " instead."};
11 }
12
checkSubtype(const Type & expected,const Type & t)13 optional<std::string> checkSubtype(const Type& expected, const Type& t) {
14 if (t.is<ErrorType>()) return {};
15
16 optional<std::string> result = expected.match(
17 [&] (const Array& expectedArray) -> optional<std::string> {
18 if (!t.is<Array>()) { return {errorMessage(expected, t)}; }
19 const auto& actualArray = t.get<Array>();
20 const auto err = checkSubtype(expectedArray.itemType, actualArray.itemType);
21 if (err) return { errorMessage(expected, t) };
22 if (expectedArray.N && expectedArray.N != actualArray.N) return { errorMessage(expected, t) };
23 return {};
24 },
25 [&] (const ValueType&) -> optional<std::string> {
26 if (t.is<ValueType>()) return {};
27
28 const Type members[] = {
29 Null,
30 Boolean,
31 Number,
32 String,
33 Object,
34 Color,
35 Array(Value)
36 };
37
38 for (const auto& member : members) {
39 const auto err = checkSubtype(member, t);
40 if (!err) {
41 return {};
42 }
43 }
44 return { errorMessage(expected, t) };
45 },
46 [&] (const auto&) -> optional<std::string> {
47 if (expected != t) {
48 return { errorMessage(expected, t) };
49 }
50 return {};
51 }
52 );
53
54 return result;
55 }
56
57 } // namespace type
58 } // namespace expression
59 } // namespace style
60 } // namespace mbgl
61