Skip to content

Commit 4c35e2f

Browse files
aw-query: Add preprocessing and refcounting
1 parent 2fc85f3 commit 4c35e2f

File tree

6 files changed

+235
-47
lines changed

6 files changed

+235
-47
lines changed

aw-query/src/functions.rs

+20-20
Original file line numberDiff line numberDiff line change
@@ -7,97 +7,97 @@ pub type QueryFn =
77
fn(args: Vec<DataType>, env: &VarEnv, ds: &Datastore) -> Result<DataType, QueryError>;
88

99
pub fn fill_env(env: &mut VarEnv) {
10-
env.insert(
10+
env.declare_static(
1111
"print".to_string(),
1212
DataType::Function("print".to_string(), qfunctions::print),
1313
);
14-
env.insert(
14+
env.declare_static(
1515
"query_bucket".to_string(),
1616
DataType::Function("query_bucket".to_string(), qfunctions::query_bucket),
1717
);
18-
env.insert(
18+
env.declare_static(
1919
"query_bucket_names".to_string(),
2020
DataType::Function(
2121
"query_bucket_names".to_string(),
2222
qfunctions::query_bucket_names,
2323
),
2424
);
25-
env.insert(
25+
env.declare_static(
2626
"sort_by_duration".to_string(),
2727
DataType::Function("sort_by_duration".to_string(), qfunctions::sort_by_duration),
2828
);
29-
env.insert(
29+
env.declare_static(
3030
"sort_by_timestamp".to_string(),
3131
DataType::Function(
3232
"sort_by_timestamp".to_string(),
3333
qfunctions::sort_by_timestamp,
3434
),
3535
);
36-
env.insert(
36+
env.declare_static(
3737
"sum_durations".to_string(),
3838
DataType::Function("sum_durations".to_string(), qfunctions::sum_durations),
3939
);
40-
env.insert(
40+
env.declare_static(
4141
"limit_events".to_string(),
4242
DataType::Function("limit_events".to_string(), qfunctions::limit_events),
4343
);
44-
env.insert(
44+
env.declare_static(
4545
"contains".to_string(),
4646
DataType::Function("contains".to_string(), qfunctions::contains),
4747
);
48-
env.insert(
48+
env.declare_static(
4949
"flood".to_string(),
5050
DataType::Function("flood".to_string(), qfunctions::flood),
5151
);
52-
env.insert(
52+
env.declare_static(
5353
"find_bucket".to_string(),
5454
DataType::Function("find_bucket".to_string(), qfunctions::find_bucket),
5555
);
56-
env.insert(
56+
env.declare_static(
5757
"merge_events_by_keys".to_string(),
5858
DataType::Function(
5959
"merge_events_by_keys".to_string(),
6060
qfunctions::merge_events_by_keys,
6161
),
6262
);
63-
env.insert(
63+
env.declare_static(
6464
"chunk_events_by_key".to_string(),
6565
DataType::Function(
6666
"chunk_events_by_key".to_string(),
6767
qfunctions::chunk_events_by_key,
6868
),
6969
);
70-
env.insert(
70+
env.declare_static(
7171
"filter_keyvals".to_string(),
7272
DataType::Function("filter_keyvals".to_string(), qfunctions::filter_keyvals),
7373
);
74-
env.insert(
74+
env.declare_static(
7575
"filter_keyvals_regex".to_string(),
7676
DataType::Function(
7777
"filter_keyvals_regex".to_string(),
7878
qfunctions::filter_keyvals_regex,
7979
),
8080
);
81-
env.insert(
81+
env.declare_static(
8282
"filter_period_intersect".to_string(),
8383
DataType::Function(
8484
"filter_period_intersect".to_string(),
8585
qfunctions::filter_period_intersect,
8686
),
8787
);
88-
env.insert(
88+
env.declare_static(
8989
"split_url_events".to_string(),
9090
DataType::Function("split_url_events".to_string(), qfunctions::split_url_events),
9191
);
92-
env.insert(
92+
env.declare_static(
9393
"concat".to_string(),
9494
DataType::Function("concat".to_string(), qfunctions::concat),
9595
);
96-
env.insert(
96+
env.declare_static(
9797
"categorize".to_string(),
9898
DataType::Function("categorize".into(), qfunctions::categorize),
9999
);
100-
env.insert(
100+
env.declare_static(
101101
"tag".to_string(),
102102
DataType::Function("tag".into(), qfunctions::tag),
103103
);
@@ -521,7 +521,7 @@ mod validate {
521521
}
522522

523523
pub fn get_timeinterval(env: &VarEnv) -> Result<TimeInterval, QueryError> {
524-
let interval_str = match env.get("TIMEINTERVAL") {
524+
let interval_str = match env.deprecated_get("TIMEINTERVAL") {
525525
Some(data_ti) => match data_ti {
526526
DataType::String(ti_str) => ti_str,
527527
_ => {

aw-query/src/interpret.rs

+9-25
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,27 @@
11
use std::collections::HashMap;
22

3-
use crate::functions;
4-
53
use aw_datastore::Datastore;
6-
use aw_models::TimeInterval;
74

85
use crate::ast::*;
96
use crate::DataType;
107
use crate::QueryError;
11-
12-
pub type VarEnv = HashMap<String, DataType>;
13-
14-
fn init_env(ti: &TimeInterval) -> VarEnv {
15-
let mut env = HashMap::new();
16-
env.insert("TIMEINTERVAL".to_string(), DataType::String(ti.to_string()));
17-
functions::fill_env(&mut env);
18-
env
19-
}
8+
use crate::VarEnv;
209

2110
pub fn interpret_prog(
2211
p: Program,
23-
ti: &TimeInterval,
12+
env: &mut VarEnv,
2413
ds: &Datastore,
2514
) -> Result<DataType, QueryError> {
26-
let mut env = init_env(ti);
2715
for expr in p.stmts {
28-
interpret_expr(&mut env, ds, expr)?;
16+
interpret_expr(env, ds, expr)?;
2917
}
30-
match env.remove("RETURN") {
18+
match env.take("RETURN") {
3119
Some(ret) => Ok(ret),
3220
None => Err(QueryError::EmptyQuery()),
3321
}
3422
}
3523

36-
fn interpret_expr(
37-
env: &mut HashMap<String, DataType>,
38-
ds: &Datastore,
39-
expr: Expr,
40-
) -> Result<DataType, QueryError> {
24+
fn interpret_expr(env: &mut VarEnv, ds: &Datastore, expr: Expr) -> Result<DataType, QueryError> {
4125
use crate::ast::Expr_::*;
4226
match expr.node {
4327
Add(a, b) => {
@@ -184,9 +168,8 @@ fn interpret_expr(
184168
env.insert(var, val);
185169
Ok(DataType::None())
186170
}
187-
// FIXME: avoid clone, it's slow
188-
Var(var) => match env.get(&var) {
189-
Some(v) => Ok(v.clone()),
171+
Var(var) => match env.take(&var) {
172+
Some(v) => Ok(v),
190173
None => Err(QueryError::VariableNotDefined(var.to_string())),
191174
},
192175
Bool(lit) => Ok(DataType::Bool(lit)),
@@ -195,6 +178,7 @@ fn interpret_expr(
195178
Return(e) => {
196179
let val = interpret_expr(env, ds, *e)?;
197180
// TODO: Once RETURN is deprecated we can fix this
181+
env.declare("RETURN".to_string());
198182
env.insert("RETURN".to_string(), val);
199183
Ok(DataType::None())
200184
}
@@ -215,7 +199,7 @@ fn interpret_expr(
215199
DataType::List(l) => l,
216200
_ => unreachable!(),
217201
};
218-
let var = match env.get(&fname[..]) {
202+
let var = match env.take(&fname[..]) {
219203
Some(v) => v,
220204
None => return Err(QueryError::VariableNotDefined(fname.clone())),
221205
};

aw-query/src/lib.rs

+13-2
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,11 @@ mod lexer;
2121
unused_braces
2222
)]
2323
mod parser;
24+
mod preprocess;
25+
mod varenv;
2426

2527
pub use crate::datatype::DataType;
26-
pub use crate::interpret::VarEnv;
28+
pub use crate::varenv::VarEnv;
2729

2830
// TODO: add line numbers to errors
2931
// (works during lexing, but not during parsing I believe)
@@ -50,6 +52,13 @@ impl fmt::Display for QueryError {
5052
}
5153
}
5254

55+
fn init_env(ti: &TimeInterval) -> VarEnv {
56+
let mut env = VarEnv::new();
57+
env.declare_static("TIMEINTERVAL".to_string(), DataType::String(ti.to_string()));
58+
functions::fill_env(&mut env);
59+
env
60+
}
61+
5362
pub fn query(code: &str, ti: &TimeInterval, ds: &Datastore) -> Result<DataType, QueryError> {
5463
let lexer = lexer::Lexer::new(code);
5564
let program = match parser::parse(lexer) {
@@ -60,5 +69,7 @@ pub fn query(code: &str, ti: &TimeInterval, ds: &Datastore) -> Result<DataType,
6069
return Err(QueryError::ParsingError(format!("{:?}", e)));
6170
}
6271
};
63-
interpret::interpret_prog(program, ti, ds)
72+
let mut env = init_env(ti);
73+
preprocess::preprocess_prog(&program, &mut env, ds)?;
74+
interpret::interpret_prog(program, &mut env, ds)
6475
}

aw-query/src/preprocess.rs

+78
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
use aw_datastore::Datastore;
2+
3+
use crate::ast::*;
4+
use crate::DataType;
5+
use crate::QueryError;
6+
use crate::VarEnv;
7+
8+
pub fn preprocess_prog(p: &Program, env: &mut VarEnv, ds: &Datastore) -> Result<(), QueryError> {
9+
for expr in &p.stmts {
10+
preprocess_expr(env, ds, expr)?;
11+
}
12+
Ok(())
13+
}
14+
15+
fn preprocess_expr(env: &mut VarEnv, ds: &Datastore, expr: &Expr) -> Result<(), QueryError> {
16+
use crate::ast::Expr_::*;
17+
match &expr.node {
18+
Var(ref var) => env.add_ref(var)?,
19+
Add(ref a, ref b) => {
20+
preprocess_expr(env, ds, a)?;
21+
preprocess_expr(env, ds, b)?;
22+
}
23+
Sub(ref a, ref b) => {
24+
preprocess_expr(env, ds, a)?;
25+
preprocess_expr(env, ds, b)?;
26+
}
27+
Mul(ref a, ref b) => {
28+
preprocess_expr(env, ds, a)?;
29+
preprocess_expr(env, ds, b)?;
30+
}
31+
Div(ref a, ref b) => {
32+
preprocess_expr(env, ds, a)?;
33+
preprocess_expr(env, ds, b)?;
34+
}
35+
Mod(ref a, ref b) => {
36+
preprocess_expr(env, ds, a)?;
37+
preprocess_expr(env, ds, b)?;
38+
}
39+
Equal(ref a, ref b) => {
40+
preprocess_expr(env, ds, a)?;
41+
preprocess_expr(env, ds, b)?;
42+
}
43+
Assign(ref var, ref b) => {
44+
preprocess_expr(env, ds, b)?;
45+
env.declare(var.to_string());
46+
}
47+
Function(ref fname, ref args) => {
48+
env.add_ref(fname)?;
49+
preprocess_expr(env, ds, args)?;
50+
}
51+
If(ref ifs) => {
52+
for (cond, block) in ifs {
53+
// TODO: could be optimized?
54+
preprocess_expr(env, ds, cond)?;
55+
for expr in block {
56+
preprocess_expr(env, ds, expr)?;
57+
}
58+
}
59+
}
60+
List(list) => {
61+
for entry in list {
62+
preprocess_expr(env, ds, entry)?;
63+
}
64+
}
65+
Dict(d) => {
66+
for (key, val_uninterpreted) in d {
67+
preprocess_expr(env, ds, val_uninterpreted)?;
68+
}
69+
}
70+
Return(e) => {
71+
preprocess_expr(env, ds, e)?;
72+
}
73+
Bool(_lit) => (),
74+
Number(_lit) => (),
75+
String(_lit) => (),
76+
};
77+
Ok(())
78+
}

0 commit comments

Comments
 (0)