Skip to content
This repository has been archived by the owner on Aug 8, 2023. It is now read-only.

Commit

Permalink
[core] Implement Expression::serialize()
Browse files Browse the repository at this point in the history
Issue #10714
- Each expression stores its operator as a string, and default serialization is [operator, serialize(child1), ...]
- Custom implementations of `serialize` for Expression types that don't follow the pattern
- expression::Value -> mbgl::Value converter
- node_expression bindings to expose `serialize`
  • Loading branch information
ChrisLoer authored and jfirebaugh committed Feb 28, 2018
1 parent f4833a2 commit e276afa
Show file tree
Hide file tree
Showing 30 changed files with 262 additions and 40 deletions.
3 changes: 3 additions & 0 deletions include/mbgl/style/expression/array_assertion.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ class ArrayAssertion : public Expression {
std::vector<optional<Value>> possibleOutputs() const override {
return input->possibleOutputs();
}

mbgl::Value serialize() const override;
std::string getOperator() const override { return "array"; }

private:
std::unique_ptr<Expression> input;
Expand Down
2 changes: 2 additions & 0 deletions include/mbgl/style/expression/assertion.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ class Assertion : public Expression {
bool operator==(const Expression& e) const override;

std::vector<optional<Value>> possibleOutputs() const override;

std::string getOperator() const override;

private:
std::vector<std::unique_ptr<Expression>> inputs;
Expand Down
2 changes: 2 additions & 0 deletions include/mbgl/style/expression/at.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ class At : public Expression {
std::vector<optional<Value>> possibleOutputs() const override {
return { nullopt };
}

std::string getOperator() const override { return "at"; }

private:
std::unique_ptr<Expression> index;
Expand Down
2 changes: 2 additions & 0 deletions include/mbgl/style/expression/boolean_operator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ class Any : public Expression {
bool operator==(const Expression& e) const override;
std::vector<optional<Value>> possibleOutputs() const override;

std::string getOperator() const override { return "any"; }
private:
std::vector<std::unique_ptr<Expression>> inputs;
};
Expand All @@ -41,6 +42,7 @@ class All : public Expression {
bool operator==(const Expression& e) const override;
std::vector<optional<Value>> possibleOutputs() const override;

std::string getOperator() const override { return "all"; }
private:
std::vector<std::unique_ptr<Expression>> inputs;
};
Expand Down
1 change: 1 addition & 0 deletions include/mbgl/style/expression/case.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ class Case : public Expression {

std::vector<optional<Value>> possibleOutputs() const override;

std::string getOperator() const override { return "case"; }
private:
std::vector<Branch> branches;
std::unique_ptr<Expression> otherwise;
Expand Down
1 change: 1 addition & 0 deletions include/mbgl/style/expression/coalesce.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ class Coalesce : public Expression {
return args.at(i).get();
}

std::string getOperator() const override { return "coalesce"; }
private:
Args args;
};
Expand Down
1 change: 1 addition & 0 deletions include/mbgl/style/expression/coercion.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ class Coercion : public Expression {

std::vector<optional<Value>> possibleOutputs() const override;

std::string getOperator() const override;
private:
EvaluationResult (*coerceSingleValue) (const Value& v);
std::vector<std::unique_ptr<Expression>> inputs;
Expand Down
15 changes: 10 additions & 5 deletions include/mbgl/style/expression/compound_expression.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,16 @@ namespace detail {
// each CompoundExpression definition's type::Type data from the type of its
// "evaluate" function.
struct SignatureBase {
SignatureBase(type::Type result_, variant<std::vector<type::Type>, VarargsType> params_) :
SignatureBase(type::Type result_, variant<std::vector<type::Type>, VarargsType> params_, std::string name_) :
result(std::move(result_)),
params(std::move(params_))
params(std::move(params_)),
name(std::move(name_))
{}
virtual ~SignatureBase() = default;
virtual std::unique_ptr<Expression> makeExpression(const std::string& name, std::vector<std::unique_ptr<Expression>>) const = 0;
virtual std::unique_ptr<Expression> makeExpression(std::vector<std::unique_ptr<Expression>>) const = 0;
type::Type result;
variant<std::vector<type::Type>, VarargsType> params;
std::string name;
};
} // namespace detail

Expand Down Expand Up @@ -111,6 +113,10 @@ class CompoundExpression : public CompoundExpressionBase {
}
return false;
}

std::string getOperator() const override {
return signature.name;
}

private:
Signature signature;
Expand All @@ -128,8 +134,7 @@ struct CompoundExpressionRegistry {

ParseResult parseCompoundExpression(const std::string name, const mbgl::style::conversion::Convertible& value, ParsingContext& ctx);

ParseResult createCompoundExpression(const std::string& name,
const CompoundExpressionRegistry::Definition& definition,
ParseResult createCompoundExpression(const CompoundExpressionRegistry::Definition& definition,
std::vector<std::unique_ptr<Expression>> args,
ParsingContext& ctx);

Expand Down
1 change: 1 addition & 0 deletions include/mbgl/style/expression/equals.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ class Equals : public Expression {
EvaluationResult evaluate(const EvaluationContext&) const override;
std::vector<optional<Value>> possibleOutputs() const override;

std::string getOperator() const override { return negate ? "!=" : "=="; }
private:
std::unique_ptr<Expression> lhs;
std::unique_ptr<Expression> rhs;
Expand Down
11 changes: 11 additions & 0 deletions include/mbgl/style/expression/expression.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,17 @@ class Expression {
* complete set of outputs is statically undecidable.
*/
virtual std::vector<optional<Value>> possibleOutputs() const = 0;

virtual mbgl::Value serialize() const {
std::vector<mbgl::Value> serialized;
serialized.emplace_back(getOperator());
eachChild([&](const Expression &child) {
serialized.emplace_back(child.serialize());
});
return serialized;
};

virtual std::string getOperator() const = 0;

protected:
template <typename T>
Expand Down
3 changes: 3 additions & 0 deletions include/mbgl/style/expression/interpolate.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,9 @@ class Interpolate : public InterpolateBase {
}
return false;
}

mbgl::Value serialize() const override;
std::string getOperator() const override { return "interpolate"; }
};

} // namespace expression
Expand Down
4 changes: 4 additions & 0 deletions include/mbgl/style/expression/let.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ class Let : public Expression {
return result.get();
}

mbgl::Value serialize() const override;
std::string getOperator() const override { return "let"; }
private:
Bindings bindings;
std::unique_ptr<Expression> result;
Expand Down Expand Up @@ -66,6 +68,8 @@ class Var : public Expression {

std::vector<optional<Value>> possibleOutputs() const override;

mbgl::Value serialize() const override;
std::string getOperator() const override { return "var"; }
private:
std::string name;
std::shared_ptr<Expression> value;
Expand Down
14 changes: 12 additions & 2 deletions include/mbgl/style/expression/literal.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,16 @@ namespace expression {

class Literal : public Expression {
public:
Literal(Value value_) : Expression(typeOf(value_)), value(value_) {}
Literal(type::Array type_, std::vector<Value> value_) : Expression(type_), value(value_) {}
Literal(Value value_)
: Expression(typeOf(value_))
, value(value_)
{}

Literal(type::Array type_, std::vector<Value> value_)
: Expression(type_)
, value(value_)
{}

EvaluationResult evaluate(const EvaluationContext&) const override {
return value;
}
Expand All @@ -37,6 +45,8 @@ class Literal : public Expression {
return value;
}

mbgl::Value serialize() const override;
std::string getOperator() const override { return "literal"; }
private:
Value value;
};
Expand Down
4 changes: 3 additions & 1 deletion include/mbgl/style/expression/match.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@ class Match : public Expression {
bool operator==(const Expression& e) const override;

std::vector<optional<Value>> possibleOutputs() const override;


mbgl::Value serialize() const override;
std::string getOperator() const override { return "match"; }
private:
std::unique_ptr<Expression> input;
Branches branches;
Expand Down
2 changes: 2 additions & 0 deletions include/mbgl/style/expression/step.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ class Step : public Expression {

static ParseResult parse(const mbgl::style::conversion::Convertible& value, ParsingContext& ctx);

mbgl::Value serialize() const override;
std::string getOperator() const override { return "step"; }
private:
const std::unique_ptr<Expression> input;
const std::map<double, std::unique_ptr<Expression>> stops;
Expand Down
1 change: 1 addition & 0 deletions include/mbgl/style/expression/value.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ struct ValueConverter<float> {
template<>
struct ValueConverter<mbgl::Value> {
static Value toExpressionValue(const mbgl::Value& value);
static mbgl::Value fromExpressionValue(const Value& value);
};

template <typename T, std::size_t N>
Expand Down
1 change: 1 addition & 0 deletions include/mbgl/style/function/convert.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ class ErrorExpression : public Expression {
return {};
}

std::string getOperator() const override { return "error"; }
private:
std::string message;
};
Expand Down
27 changes: 19 additions & 8 deletions platform/node/src/node_expression.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "node_conversion.hpp"
#include "node_expression.hpp"
#include "node_feature.hpp"

#include <mbgl/style/expression/parsing_context.hpp>
#include <mbgl/style/expression/is_constant.hpp>
Expand All @@ -24,6 +25,8 @@ void NodeExpression::Init(v8::Local<v8::Object> target) {
Nan::SetPrototypeMethod(tpl, "isFeatureConstant", IsFeatureConstant);
Nan::SetPrototypeMethod(tpl, "isZoomConstant", IsZoomConstant);

Nan::SetPrototypeMethod(tpl, "serialize", Serialize);

Nan::SetMethod(tpl, "parse", Parse);

constructor.Reset(tpl->GetFunction()); // what is this doing?
Expand All @@ -39,31 +42,31 @@ type::Type parseType(v8::Local<v8::Object> type) {
{"color", type::Color},
{"value", type::Value}
};

v8::Local<v8::Value> v8kind = Nan::Get(type, Nan::New("kind").ToLocalChecked()).ToLocalChecked();
std::string kind(*v8::String::Utf8Value(v8kind));

if (kind == "array") {
type::Type itemType = parseType(Nan::Get(type, Nan::New("itemType").ToLocalChecked()).ToLocalChecked()->ToObject());
mbgl::optional<std::size_t> N;

v8::Local<v8::String> Nkey = Nan::New("N").ToLocalChecked();
if (Nan::Has(type, Nkey).FromMaybe(false)) {
N = Nan::Get(type, Nkey).ToLocalChecked()->ToInt32()->Value();
}
return type::Array(itemType, N);
}

return types[kind];
}

void NodeExpression::Parse(const Nan::FunctionCallbackInfo<v8::Value>& info) {
v8::Local<v8::Function> cons = Nan::New(constructor);

if (info.Length() < 1 || info[0]->IsUndefined()) {
return Nan::ThrowTypeError("Requires a JSON style expression argument.");
}

mbgl::optional<type::Type> expected;
if (info.Length() > 1 && info[1]->IsObject()) {
expected = parseType(info[1]->ToObject());
Expand All @@ -84,7 +87,7 @@ void NodeExpression::Parse(const Nan::FunctionCallbackInfo<v8::Value>& info) {
info.GetReturnValue().Set(wrapped);
return;
}

v8::Local<v8::Array> result = Nan::New<v8::Array>();
for (std::size_t i = 0; i < ctx.getErrors().size(); i++) {
const auto& error = ctx.getErrors()[i];
Expand Down Expand Up @@ -140,7 +143,7 @@ struct ToValue {
}
return scope.Escape(result);
}

v8::Local<v8::Value> operator()(const mbgl::Color& color) {
return operator()(std::vector<Value> {
static_cast<double>(color.r),
Expand Down Expand Up @@ -227,4 +230,12 @@ void NodeExpression::IsZoomConstant(const Nan::FunctionCallbackInfo<v8::Value>&
info.GetReturnValue().Set(Nan::New(isZoomConstant(*expression)));
}

void NodeExpression::Serialize(const Nan::FunctionCallbackInfo<v8::Value>& info) {
NodeExpression* nodeExpr = ObjectWrap::Unwrap<NodeExpression>(info.Holder());
const std::unique_ptr<Expression>& expression = nodeExpr->expression;

const mbgl::Value serialized = expression->serialize();
info.GetReturnValue().Set(toJS(serialized));
}

} // namespace node_mbgl
3 changes: 3 additions & 0 deletions platform/node/src/node_expression.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ class NodeExpression : public Nan::ObjectWrap {
static void GetType(const Nan::FunctionCallbackInfo<v8::Value>&);
static void IsFeatureConstant(const Nan::FunctionCallbackInfo<v8::Value>&);
static void IsZoomConstant(const Nan::FunctionCallbackInfo<v8::Value>&);

static void Serialize(const Nan::FunctionCallbackInfo<v8::Value>&);

static Nan::Persistent<v8::Function> constructor;

std::unique_ptr<Expression> expression;
Expand Down
4 changes: 3 additions & 1 deletion platform/node/test/expression.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ suite.run('native', {ignores: ignores, tests: tests}, (fixture) => {
compiled.isZoomConstant = expression.isZoomConstant();
compiled.type = expression.getType();

console.log("input: " + JSON.stringify(fixture.expression));
console.log("output: " + JSON.stringify(expression.serialize()));

const evaluate = fixture.inputs || [];
const evaluateResults = [];
for (const input of evaluate) {
Expand All @@ -68,4 +71,3 @@ suite.run('native', {ignores: ignores, tests: tests}, (fixture) => {

return result;
});

19 changes: 19 additions & 0 deletions src/mbgl/style/expression/array_assertion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,25 @@ ParseResult ArrayAssertion::parse(const Convertible& value, ParsingContext& ctx)
));
}

mbgl::Value ArrayAssertion::serialize() const {
std::vector<mbgl::Value> serialized;
serialized.emplace_back(getOperator());


const auto array = getType().get<type::Array>();
if (array.itemType.is<type::StringType>()
|| array.itemType.is<type::NumberType>()
|| array.itemType.is<type::BooleanType>()) {
serialized.emplace_back(type::toString(array.itemType));
if (array.N) {
serialized.emplace_back(uint64_t(*array.N));
}
}

serialized.emplace_back(input->serialize());
return serialized;
}

} // namespace expression
} // namespace style
} // namespace mbgl
4 changes: 4 additions & 0 deletions src/mbgl/style/expression/assertion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ ParseResult Assertion::parse(const Convertible& value, ParsingContext& ctx) {
return ParseResult(std::make_unique<Assertion>(it->second, std::move(parsed)));
}

std::string Assertion::getOperator() const {
return type::toString(getType());
}

EvaluationResult Assertion::evaluate(const EvaluationContext& params) const {
for (std::size_t i = 0; i < inputs.size(); i++) {
EvaluationResult value = inputs[i]->evaluate(params);
Expand Down
7 changes: 7 additions & 0 deletions src/mbgl/style/expression/coercion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,13 @@ Coercion::Coercion(type::Type type_, std::vector<std::unique_ptr<Expression>> in
}
}

std::string Coercion::getOperator() const {
return getType().match(
[](const type::NumberType&) { return "to-number"; },
[](const type::ColorType&) { return "to-color"; },
[](const auto&) { assert(false); return ""; });
}

using namespace mbgl::style::conversion;
ParseResult Coercion::parse(const Convertible& value, ParsingContext& ctx) {
static std::unordered_map<std::string, type::Type> types {
Expand Down
Loading

0 comments on commit e276afa

Please sign in to comment.