Skip to content

Commit e43829b

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

File tree

6 files changed

+234
-47
lines changed

6 files changed

+234
-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

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

0 commit comments

Comments
 (0)