Skip to content

Commit 7d73552

Browse files
feat: add array functions to expression function table
Register arraylen, arrayat, isarray, and flatten in the function_table so they are available in FT.AGGREGATE expressions. Also fix reference style throughout file to match project convention (Type &param instead of Type& param). Signed-off-by: Alexandru Filip <alexandru.filip@improving.com>
1 parent 535a378 commit 7d73552

1 file changed

Lines changed: 69 additions & 64 deletions

File tree

src/expr/expr.cc

Lines changed: 69 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,10 @@ constexpr absl::string_view kInvalidOrMissingExpression{
3131
struct Constant : Expression {
3232
Constant(std::string constant) : constant_(std::move(constant)) {}
3333
Constant(double constant) : constant_(constant) {}
34-
Value Evaluate(EvalContext& ctx, const Record& record) const override {
34+
Value Evaluate(EvalContext &ctx, const Record &record) const override {
3535
return constant_;
3636
}
37-
void Dump(std::ostream& os) const override {
37+
void Dump(std::ostream &os) const override {
3838
os << "Constant(" << constant_ << ")";
3939
}
4040

@@ -43,12 +43,12 @@ struct Constant : Expression {
4343
};
4444

4545
struct Parameter : Expression {
46-
Parameter(std::string&& name, Value&& value)
46+
Parameter(std::string &&name, Value &&value)
4747
: name_(std::move(name)), value_(std::move(value)) {}
48-
Value Evaluate(EvalContext& ctx, const Record& record) const override {
48+
Value Evaluate(EvalContext &ctx, const Record &record) const override {
4949
return value_;
5050
}
51-
void Dump(std::ostream& os) const override {
51+
void Dump(std::ostream &os) const override {
5252
os << "$" << name_ << "(" << value_ << ")";
5353
}
5454

@@ -61,27 +61,27 @@ struct AttributeValue : Expression {
6161
AttributeValue(std::string identifier,
6262
std::unique_ptr<AttributeReference> ref)
6363
: identifier_(std::move(identifier)), ref_(std::move(ref)) {}
64-
Value Evaluate(EvalContext& ctx, const Record& record) const override {
64+
Value Evaluate(EvalContext &ctx, const Record &record) const override {
6565
return ref_->GetValue(ctx, record);
6666
}
67-
void Dump(std::ostream& os) const override { os << '@' << identifier_; }
67+
void Dump(std::ostream &os) const override { os << '@' << identifier_; }
6868

6969
private:
7070
std::string identifier_;
7171
std::unique_ptr<AttributeReference> ref_;
7272
};
7373

7474
struct Not : Expression {
75-
Not(ExprPtr&& p) : expr_(std::move(p)) {}
76-
Value Evaluate(EvalContext& ctx, const Record& record) const override {
75+
Not(ExprPtr &&p) : expr_(std::move(p)) {}
76+
Value Evaluate(EvalContext &ctx, const Record &record) const override {
7777
auto Primary = expr_->Evaluate(ctx, record).AsBool();
7878
if (Primary) {
7979
return Value(!*Primary);
8080
} else {
8181
return Value{};
8282
}
8383
}
84-
void Dump(std::ostream& os) const override {
84+
void Dump(std::ostream &os) const override {
8585
os << '!';
8686
expr_->Dump(os);
8787
}
@@ -91,19 +91,19 @@ struct Not : Expression {
9191
};
9292

9393
struct FunctionCall : Expression {
94-
using Func = Value (*)(EvalContext& ctx, const Record& record,
95-
const absl::InlinedVector<ExprPtr, 4>& params);
94+
using Func = Value (*)(EvalContext &ctx, const Record &record,
95+
const absl::InlinedVector<ExprPtr, 4> &params);
9696
static absl::StatusOr<Func> LookUpAndValidate(
97-
const std::string& name, const absl::InlinedVector<ExprPtr, 4>& params);
97+
const std::string &name, const absl::InlinedVector<ExprPtr, 4> &params);
9898
FunctionCall(std::string name, Func func,
9999
absl::InlinedVector<ExprPtr, 4> params)
100100
: name_(std::move(name)), func_(func), params_(std::move(params)) {}
101-
Value Evaluate(EvalContext& ctx, const Record& record) const override {
101+
Value Evaluate(EvalContext &ctx, const Record &record) const override {
102102
return (*func_)(ctx, record, params_);
103103
}
104-
void Dump(std::ostream& os) const override {
104+
void Dump(std::ostream &os) const override {
105105
os << name_ << '(';
106-
for (auto& p : params_) {
106+
for (auto &p : params_) {
107107
if (&p != &params_[0]) {
108108
os << ',';
109109
}
@@ -118,52 +118,52 @@ struct FunctionCall : Expression {
118118
absl::InlinedVector<ExprPtr, 4> params_;
119119
};
120120

121-
template <Value (*func1)(const Value& o)>
121+
template <Value (*func1)(const Value &o)>
122122
Value MonadicFunctionProxy(
123-
Expression::EvalContext& ctx, const Expression::Record& record,
124-
const absl::InlinedVector<expr::ExprPtr, 4>& params) {
123+
Expression::EvalContext &ctx, const Expression::Record &record,
124+
const absl::InlinedVector<expr::ExprPtr, 4> &params) {
125125
CHECK(params.size() == 1);
126126
return (*func1)(params[0]->Evaluate(ctx, record));
127127
};
128128

129-
template <Value (*func2)(const Value& l, const Value& r)>
130-
Value DyadicFunctionProxy(Expression::EvalContext& ctx,
131-
const Expression::Record& record,
132-
const absl::InlinedVector<expr::ExprPtr, 4>& params) {
129+
template <Value (*func2)(const Value &l, const Value &r)>
130+
Value DyadicFunctionProxy(Expression::EvalContext &ctx,
131+
const Expression::Record &record,
132+
const absl::InlinedVector<expr::ExprPtr, 4> &params) {
133133
CHECK(params.size() == 2);
134134
return (*func2)(params[0]->Evaluate(ctx, record),
135135
params[1]->Evaluate(ctx, record));
136136
};
137137

138-
template <Value (*func3)(const Value& l, const Value& m, const Value& r)>
138+
template <Value (*func3)(const Value &l, const Value &m, const Value &r)>
139139
Value TriadicFunctionProxy(
140-
Expression::EvalContext& ctx, const Expression::Record& record,
141-
const absl::InlinedVector<expr::ExprPtr, 4>& params) {
140+
Expression::EvalContext &ctx, const Expression::Record &record,
141+
const absl::InlinedVector<expr::ExprPtr, 4> &params) {
142142
CHECK(params.size() == 3);
143143
return (*func3)(params[0]->Evaluate(ctx, record),
144144
params[1]->Evaluate(ctx, record),
145145
params[2]->Evaluate(ctx, record));
146146
};
147147

148-
using Func = Value (*)(Expression::EvalContext& ctx,
149-
const Expression::Record& record,
150-
const absl::InlinedVector<ExprPtr, 4>& params);
148+
using Func = Value (*)(Expression::EvalContext &ctx,
149+
const Expression::Record &record,
150+
const absl::InlinedVector<ExprPtr, 4> &params);
151151

152-
Value FuncExists(const Value& o) { return Value(!o.IsNil()); }
152+
Value FuncExists(const Value &o) { return Value(!o.IsNil()); }
153153

154-
Value ProxyConcat(Expression::EvalContext& ctx,
155-
const Expression::Record& record,
156-
const absl::InlinedVector<expr::ExprPtr, 4>& params) {
154+
Value ProxyConcat(Expression::EvalContext &ctx,
155+
const Expression::Record &record,
156+
const absl::InlinedVector<expr::ExprPtr, 4> &params) {
157157
absl::InlinedVector<Value, 4> values;
158-
for (auto& p : params) {
158+
for (auto &p : params) {
159159
values.emplace_back(p->Evaluate(ctx, record));
160160
}
161161
return FuncConcat(values);
162162
}
163163

164-
Value ProxyTimefmt(Expression::EvalContext& ctx,
165-
const Expression::Record& record,
166-
const absl::InlinedVector<expr::ExprPtr, 4>& params) {
164+
Value ProxyTimefmt(Expression::EvalContext &ctx,
165+
const Expression::Record &record,
166+
const absl::InlinedVector<expr::ExprPtr, 4> &params) {
167167
CHECK(!params.empty());
168168
Value fmt("%FT%TZ");
169169
if (params.size() > 1) {
@@ -172,9 +172,9 @@ Value ProxyTimefmt(Expression::EvalContext& ctx,
172172
return FuncTimefmt(params[0]->Evaluate(ctx, record), fmt);
173173
}
174174

175-
Value ProxyParsetime(Expression::EvalContext& ctx,
176-
const Expression::Record& record,
177-
const absl::InlinedVector<expr::ExprPtr, 4>& params) {
175+
Value ProxyParsetime(Expression::EvalContext &ctx,
176+
const Expression::Record &record,
177+
const absl::InlinedVector<expr::ExprPtr, 4> &params) {
178178
CHECK(!params.empty());
179179
Value fmt("%FT%TZ");
180180
if (params.size() > 1) {
@@ -220,10 +220,15 @@ static std::map<std::string, FunctionTableEntry> function_table{
220220

221221
{"timefmt", {1, 2, &ProxyTimefmt}},
222222
{"parsetime", {1, 2, &ProxyParsetime}},
223+
224+
{"arraylen", {1, 1, &MonadicFunctionProxy<FuncArrayLen>}},
225+
{"arrayat", {2, 2, &DyadicFunctionProxy<FuncArrayAt>}},
226+
{"isarray", {1, 1, &MonadicFunctionProxy<FuncIsArray>}},
227+
{"flatten", {2, 2, &DyadicFunctionProxy<FuncFlatten>}},
223228
};
224229

225230
absl::StatusOr<Func> FunctionCall::LookUpAndValidate(
226-
const std::string& name, const absl::InlinedVector<ExprPtr, 4>& params) {
231+
const std::string &name, const absl::InlinedVector<ExprPtr, 4> &params) {
227232
auto it = function_table.find(name);
228233
if (it == function_table.end()) {
229234
return absl::NotFoundError(absl::StrCat("Function ", name, " is unknown"));
@@ -253,18 +258,18 @@ absl::StatusOr<Func> FunctionCall::LookUpAndValidate(
253258
//
254259

255260
struct Dyadic : Expression {
256-
using ValueFunc = Value (*)(const Value&, const Value&);
261+
using ValueFunc = Value (*)(const Value &, const Value &);
257262
Dyadic(ExprPtr lexpr, ExprPtr rexpr, ValueFunc func, absl::string_view name)
258263
: lexpr_(std::move(lexpr)),
259264
rexpr_(std::move(rexpr)),
260265
func_(func),
261266
name_(name) {}
262-
Value Evaluate(EvalContext& ctx, const Record& record) const override {
267+
Value Evaluate(EvalContext &ctx, const Record &record) const override {
263268
auto lvalue = lexpr_->Evaluate(ctx, record);
264269
auto rvalue = rexpr_->Evaluate(ctx, record);
265270
return (*func_)(lvalue, rvalue);
266271
}
267-
void Dump(std::ostream& os) const override {
272+
void Dump(std::ostream &os) const override {
268273
os << '(';
269274
lexpr_->Dump(os);
270275
os << name_;
@@ -284,8 +289,8 @@ bool IsIdentifierChar(int c) {
284289
}
285290

286291
struct DepthGuard {
287-
int& depth;
288-
DepthGuard(int& d) : depth(d) { ++depth; }
292+
int &depth;
293+
DepthGuard(int &d) : depth(d) { ++depth; }
289294
~DepthGuard() { --depth; }
290295
};
291296

@@ -296,12 +301,12 @@ struct Compiler {
296301

297302
using CompileContext = Expression::CompileContext;
298303

299-
using ParseFunc = absl::StatusOr<ExprPtr> (Compiler::*)(CompileContext& ctx);
304+
using ParseFunc = absl::StatusOr<ExprPtr> (Compiler::*)(CompileContext &ctx);
300305

301306
using DyadicOp = std::pair<absl::string_view, Dyadic::ValueFunc>;
302307

303-
absl::StatusOr<ExprPtr> DoDyadic(CompileContext& ctx, ParseFunc func,
304-
const std::vector<DyadicOp>& ops) {
308+
absl::StatusOr<ExprPtr> DoDyadic(CompileContext &ctx, ParseFunc func,
309+
const std::vector<DyadicOp> &ops) {
305310
utils::Scanner s = s_;
306311
DBG << "Start Dyadic: " << ops[0].first << " Remaining: '"
307312
<< s_.GetUnscanned() << "'\n";
@@ -313,7 +318,7 @@ struct Compiler {
313318
while (s_.SkipWhiteSpacePeekByte() != EOF) {
314319
s = s_;
315320
bool found = false;
316-
for (auto& op : ops) {
321+
for (auto &op : ops) {
317322
DBG << "Dyadic looking for " << op.first
318323
<< " Remaining: " << s_.GetUnscanned() << "\n";
319324
if (s_.SkipWhiteSpacePopWord(op.first)) {
@@ -341,7 +346,7 @@ struct Compiler {
341346
return lvalue;
342347
}
343348

344-
absl::StatusOr<ExprPtr> ParseParameter(CompileContext& ctx) {
349+
absl::StatusOr<ExprPtr> ParseParameter(CompileContext &ctx) {
345350
CHECK(s_.PopByte('$'));
346351
std::string param_name;
347352
while (IsIdentifierChar(s_.PeekByte())) {
@@ -352,7 +357,7 @@ struct Compiler {
352357
std::move(param_value));
353358
}
354359

355-
absl::StatusOr<ExprPtr> Invert(CompileContext& ctx) {
360+
absl::StatusOr<ExprPtr> Invert(CompileContext &ctx) {
356361
CHECK(s_.PopByte('!'));
357362
VMSDK_ASSIGN_OR_RETURN(auto expr, Primary(ctx));
358363
if (!expr) {
@@ -361,7 +366,7 @@ struct Compiler {
361366
return std::make_unique<Not>(std::move(expr));
362367
}
363368

364-
absl::StatusOr<ExprPtr> Primary(CompileContext& ctx) {
369+
absl::StatusOr<ExprPtr> Primary(CompileContext &ctx) {
365370
DepthGuard guard(depth_);
366371
if (depth_ > options::GetQueryStringDepth().GetValue()) {
367372
return absl::InvalidArgumentError("Expression too complex");
@@ -409,7 +414,7 @@ struct Compiler {
409414
return ParseFunctionCall(ctx);
410415
}
411416
}
412-
absl::StatusOr<ExprPtr> Attribute(CompileContext& ctx) {
417+
absl::StatusOr<ExprPtr> Attribute(CompileContext &ctx) {
413418
CHECK(s_.PopByte('@'));
414419
size_t pos = s_.GetPosition();
415420
std::string identifier;
@@ -422,7 +427,7 @@ struct Compiler {
422427
_ << " near position " << pos);
423428
return std::make_unique<AttributeValue>(identifier, std::move(ref));
424429
}
425-
absl::StatusOr<ExprPtr> ParseFunctionCall(CompileContext& ctx) {
430+
absl::StatusOr<ExprPtr> ParseFunctionCall(CompileContext &ctx) {
426431
std::string name;
427432
utils::Scanner s = s_;
428433
while (IsIdentifierChar(s_.PeekByte())) {
@@ -460,7 +465,7 @@ struct Compiler {
460465
}
461466
}
462467
}
463-
absl::StatusOr<ExprPtr> Number(CompileContext& ctx) {
468+
absl::StatusOr<ExprPtr> Number(CompileContext &ctx) {
464469
DBG << "Number Start: '" << s_.GetUnscanned() << "'\n";
465470
auto num = s_.PopDouble();
466471
if (!num) {
@@ -470,7 +475,7 @@ struct Compiler {
470475
<< "'\n";
471476
return std::make_unique<Constant>(*num);
472477
}
473-
absl::StatusOr<ExprPtr> QuotedString(CompileContext& ctx) {
478+
absl::StatusOr<ExprPtr> QuotedString(CompileContext &ctx) {
474479
std::string str;
475480
int start_byte = s_.NextByte();
476481
while (s_.PeekByte() != start_byte) {
@@ -501,35 +506,35 @@ struct Compiler {
501506
// CmpOp: < <= == != > >=
502507
// LogOp: || &&
503508
//
504-
absl::StatusOr<ExprPtr> LorOp(CompileContext& ctx) {
509+
absl::StatusOr<ExprPtr> LorOp(CompileContext &ctx) {
505510
static std::vector<DyadicOp> ops{
506511
{"||", &FuncLor},
507512
{"&&", &FuncLand},
508513
};
509514
return DoDyadic(ctx, &Compiler::CmpOp, ops);
510515
}
511-
absl::StatusOr<ExprPtr> CmpOp(CompileContext& ctx) {
516+
absl::StatusOr<ExprPtr> CmpOp(CompileContext &ctx) {
512517
static std::vector<DyadicOp> ops{{"<=", &FuncLe}, {"<", &FuncLt},
513518
{"==", &FuncEq}, {"!=", &FuncNe},
514519
{">=", &FuncGe}, {">", &FuncGt}};
515520
return DoDyadic(ctx, &Compiler::AddOp, ops);
516521
}
517-
absl::StatusOr<ExprPtr> AddOp(CompileContext& ctx) {
522+
absl::StatusOr<ExprPtr> AddOp(CompileContext &ctx) {
518523
static std::vector<DyadicOp> ops{{"+", &FuncAdd}, {"-", &FuncSub}};
519524
return DoDyadic(ctx, &Compiler::MulOp, ops);
520525
}
521-
absl::StatusOr<ExprPtr> MulOp(CompileContext& ctx) {
526+
absl::StatusOr<ExprPtr> MulOp(CompileContext &ctx) {
522527
static std::vector<DyadicOp> ops{
523528
{"*", &FuncMul}, {"/", &FuncDiv}, {"^", &FuncPower}};
524529
return DoDyadic(ctx, &Compiler::Primary, ops);
525530
}
526531

527-
absl::StatusOr<ExprPtr> ParseExpression(CompileContext& ctx) {
532+
absl::StatusOr<ExprPtr> ParseExpression(CompileContext &ctx) {
528533
DBG << "Start Expression: '" << s_.GetUnscanned() << "'\n";
529534
return LorOp(ctx);
530535
}
531536

532-
absl::StatusOr<ExprPtr> Compile(CompileContext& ctx) {
537+
absl::StatusOr<ExprPtr> Compile(CompileContext &ctx) {
533538
VMSDK_ASSIGN_OR_RETURN(auto result, ParseExpression(ctx));
534539
if (!result) {
535540
return absl::InvalidArgumentError(kInvalidOrMissingExpression);
@@ -543,7 +548,7 @@ struct Compiler {
543548
}
544549
};
545550

546-
absl::StatusOr<ExprPtr> Expression::Compile(CompileContext& ctx,
551+
absl::StatusOr<ExprPtr> Expression::Compile(CompileContext &ctx,
547552
absl::string_view s) {
548553
Compiler c(s);
549554
return c.Compile(ctx);

0 commit comments

Comments
 (0)