Skip to content

Commit

Permalink
Tree search pattern matcher
Browse files Browse the repository at this point in the history
Signed-off-by: Heinz N. Gies <[email protected]>
  • Loading branch information
Licenser committed Aug 14, 2024
1 parent bc8d948 commit e4d61f8
Show file tree
Hide file tree
Showing 6 changed files with 230 additions and 86 deletions.
1 change: 0 additions & 1 deletion tremor-script/src/script.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,6 @@ impl Script {
// helper.consts.args = args.clone_static();
let mut script = script_raw.up_script(&mut helper)?;
Optimizer::new(&helper).walk_script(&mut script)?;
let script = script;

Ok(Self {
script,
Expand Down
41 changes: 38 additions & 3 deletions tremor-script/src/vm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,42 @@ impl<'run, 'event> Scope<'run, 'event> {
Op::TestArrayIsEmpty => {
self.reg.b1 = self.reg.v1.as_array().map_or(true, Vec::is_empty);
}

Check warning on line 343 in tremor-script/src/vm.rs

View check run for this annotation

Codecov / codecov/patch

tremor-script/src/vm.rs#L326-L343

Added lines #L326 - L343 were not covered by tests
Op::TestEq => {
let rhs = last(&stack, *pc, *cc)?;

Check warning on line 345 in tremor-script/src/vm.rs

View check run for this annotation

Codecov / codecov/patch

tremor-script/src/vm.rs#L345

Added line #L345 was not covered by tests
self.reg.b1 =
exec_binary(mid, mid, crate::ast::BinOpKind::Eq, &self.reg.v1, rhs)?
.try_as_bool()?;

Check warning on line 348 in tremor-script/src/vm.rs

View check run for this annotation

Codecov / codecov/patch

tremor-script/src/vm.rs#L347-L348

Added lines #L347 - L348 were not covered by tests
}
Op::TestNeq => {
let rhs = last(&stack, *pc, *cc)?;

Check warning on line 351 in tremor-script/src/vm.rs

View check run for this annotation

Codecov / codecov/patch

tremor-script/src/vm.rs#L351

Added line #L351 was not covered by tests
self.reg.b1 =
exec_binary(mid, mid, crate::ast::BinOpKind::NotEq, &self.reg.v1, rhs)?
.try_as_bool()?;

Check warning on line 354 in tremor-script/src/vm.rs

View check run for this annotation

Codecov / codecov/patch

tremor-script/src/vm.rs#L353-L354

Added lines #L353 - L354 were not covered by tests
}
Op::TestGt => {
let rhs = last(&stack, *pc, *cc)?;

Check warning on line 357 in tremor-script/src/vm.rs

View check run for this annotation

Codecov / codecov/patch

tremor-script/src/vm.rs#L357

Added line #L357 was not covered by tests
self.reg.b1 =
exec_binary(mid, mid, crate::ast::BinOpKind::Gt, &self.reg.v1, rhs)?
.try_as_bool()?;

Check warning on line 360 in tremor-script/src/vm.rs

View check run for this annotation

Codecov / codecov/patch

tremor-script/src/vm.rs#L359-L360

Added lines #L359 - L360 were not covered by tests
}
Op::TestLt => {
let rhs = last(&stack, *pc, *cc)?;

Check warning on line 363 in tremor-script/src/vm.rs

View check run for this annotation

Codecov / codecov/patch

tremor-script/src/vm.rs#L363

Added line #L363 was not covered by tests
self.reg.b1 =
exec_binary(mid, mid, crate::ast::BinOpKind::Lt, &self.reg.v1, rhs)?
.try_as_bool()?;

Check warning on line 366 in tremor-script/src/vm.rs

View check run for this annotation

Codecov / codecov/patch

tremor-script/src/vm.rs#L365-L366

Added lines #L365 - L366 were not covered by tests
}
Op::TestGte => {
let rhs = last(&stack, *pc, *cc)?;

Check warning on line 369 in tremor-script/src/vm.rs

View check run for this annotation

Codecov / codecov/patch

tremor-script/src/vm.rs#L369

Added line #L369 was not covered by tests
self.reg.b1 =
exec_binary(mid, mid, crate::ast::BinOpKind::Gte, &self.reg.v1, rhs)?
.try_as_bool()?;

Check warning on line 372 in tremor-script/src/vm.rs

View check run for this annotation

Codecov / codecov/patch

tremor-script/src/vm.rs#L371-L372

Added lines #L371 - L372 were not covered by tests
}
Op::TestLte => {
let rhs = last(&stack, *pc, *cc)?;

Check warning on line 375 in tremor-script/src/vm.rs

View check run for this annotation

Codecov / codecov/patch

tremor-script/src/vm.rs#L375

Added line #L375 was not covered by tests
self.reg.b1 =
exec_binary(mid, mid, crate::ast::BinOpKind::Gte, &self.reg.v1, rhs)?
.try_as_bool()?;

Check warning on line 378 in tremor-script/src/vm.rs

View check run for this annotation

Codecov / codecov/patch

tremor-script/src/vm.rs#L377-L378

Added lines #L377 - L378 were not covered by tests
}
Op::TestRecordIsEmpty => {
self.reg.b1 = self
.reg
Expand All @@ -350,10 +386,9 @@ impl<'run, 'event> Scope<'run, 'event> {
}

Check warning on line 386 in tremor-script/src/vm.rs

View check run for this annotation

Codecov / codecov/patch

tremor-script/src/vm.rs#L380-L386

Added lines #L380 - L386 were not covered by tests
// Inspect
Op::InspectLen => {
let v = last(&stack, *pc, *cc)?;
let len = if let Some(v) = v.as_array() {
let len = if let Some(v) = self.reg.v1.as_array() {
v.len()
} else if let Some(v) = v.as_object() {
} else if let Some(v) = self.reg.v1.as_object() {
v.len()

Check warning on line 392 in tremor-script/src/vm.rs

View check run for this annotation

Codecov / codecov/patch

tremor-script/src/vm.rs#L388-L392

Added lines #L388 - L392 were not covered by tests
} else {
return Err("Not an array or object".into());

Check warning on line 394 in tremor-script/src/vm.rs

View check run for this annotation

Codecov / codecov/patch

tremor-script/src/vm.rs#L394

Added line #L394 was not covered by tests
Expand Down
63 changes: 59 additions & 4 deletions tremor-script/src/vm/compiler/impls.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
mod imut_expr;
mod mut_expr;

use tremor_value::Value;

use crate::{
ast::{
ClauseGroup, Comprehension, DefaultCase, Expression, IfElse, Match, Path, PredicateClause,
Expand Down Expand Up @@ -37,7 +39,6 @@ where
let end_dst = compiler.end_dst()?;
let dst = compiler.new_jump_point();
compiler.comment("Predicate Clause");
compiler.emit(Op::CopyV1, &mid);
pattern.compile_to_b(compiler)?;
compiler.comment("Jump to the next pattern");
compiler.emit(Op::JumpFalse { dst }, &mid);
Expand Down Expand Up @@ -106,20 +107,26 @@ where
}
ClauseGroup::SearchTree {
precondition,
tree: _,
tree,
rest,

Check warning on line 111 in tremor-script/src/vm/compiler/impls.rs

View check run for this annotation

Codecov / codecov/patch

tremor-script/src/vm/compiler/impls.rs#L109-L111

Added lines #L109 - L111 were not covered by tests
} => {
if let Some(precondition) = precondition {
compiler.comment("Match Tree Preconditions");
precondition.compile_to_b(compiler)?;
compiler.comment("Jump to next case if precondition is false");
compiler.emit(Op::JumpFalse { dst: next }, &NodeMeta::dummy());
// FIXME
}
compiler.comment("Encode binary search tree");

let tree = tree.into_iter().collect::<Vec<_>>();
traverse_tree(compiler, &tree)?;

Check warning on line 122 in tremor-script/src/vm/compiler/impls.rs

View check run for this annotation

Codecov / codecov/patch

tremor-script/src/vm/compiler/impls.rs#L113-L122

Added lines #L113 - L122 were not covered by tests

if !rest.is_empty() {
compiler.comment("Test remaining matches");
}
for r in rest {
r.compile(compiler)?;

Check warning on line 128 in tremor-script/src/vm/compiler/impls.rs

View check run for this annotation

Codecov / codecov/patch

tremor-script/src/vm/compiler/impls.rs#L124-L128

Added lines #L124 - L128 were not covered by tests
}
todo!("the tree has to go before therest!");
}
ClauseGroup::Combined {
precondition,
Expand Down Expand Up @@ -154,6 +161,54 @@ where
}

Check warning on line 161 in tremor-script/src/vm/compiler/impls.rs

View check run for this annotation

Codecov / codecov/patch

tremor-script/src/vm/compiler/impls.rs#L159-L161

Added lines #L159 - L161 were not covered by tests
}

fn traverse_tree<'script, Ex>(
compiler: &mut Compiler<'script>,
tree: &[(Value<'script>, (Vec<Ex>, Ex))],
) -> Result<()>
where
Ex: Compilable<'script> + Expression,
{
let mid = NodeMeta::dummy();
let (lower, upper) = tree.split_at(tree.len() / 2);

assert!(lower.len() <= upper.len());
let Some(((val, (exprs, last)), upper_rest)) = upper.split_first() else {

Check warning on line 175 in tremor-script/src/vm/compiler/impls.rs

View check run for this annotation

Codecov / codecov/patch

tremor-script/src/vm/compiler/impls.rs#L164-L175

Added lines #L164 - L175 were not covered by tests
// we know that in the case of a odd number the upper half is always larger or equal to the lower half
// so if it is empty we have nothing left to do in the tree
return Ok(());

Check warning on line 178 in tremor-script/src/vm/compiler/impls.rs

View check run for this annotation

Codecov / codecov/patch

tremor-script/src/vm/compiler/impls.rs#L178

Added line #L178 was not covered by tests
};
let gt = compiler.new_jump_point();
let lt = compiler.new_jump_point();
compiler.comment("Binary search tree node");
compiler.emit_const(val.clone(), &mid);
compiler.comment("Test if value is greater than the current node");
compiler.emit(Op::TestGt, &mid);
compiler.emit(Op::JumpTrue { dst: gt }, &mid);
compiler.comment("Test if value is lesser than the current node");
compiler.emit(Op::TestLt, &mid);
compiler.emit(Op::JumpTrue { dst: lt }, &mid);
compiler.comment("Value is equal to the current node");
for e in exprs {

Check warning on line 191 in tremor-script/src/vm/compiler/impls.rs

View check run for this annotation

Codecov / codecov/patch

tremor-script/src/vm/compiler/impls.rs#L180-L191

Added lines #L180 - L191 were not covered by tests
// FIXME: kins of annoying to clone but eh
e.clone().compile(compiler)?;

Check warning on line 193 in tremor-script/src/vm/compiler/impls.rs

View check run for this annotation

Codecov / codecov/patch

tremor-script/src/vm/compiler/impls.rs#L193

Added line #L193 was not covered by tests
} // FIXME: kins of annoying to clone but eh

last.clone().compile(compiler)?;
compiler.comment("We found and executed a match, jump to the end of the match statement");
compiler.emit(
Op::Jump {
dst: compiler.end_dst()?,

Check warning on line 200 in tremor-script/src/vm/compiler/impls.rs

View check run for this annotation

Codecov / codecov/patch

tremor-script/src/vm/compiler/impls.rs#L196-L200

Added lines #L196 - L200 were not covered by tests
},
&mid,
);
compiler.comment("Llesser half of the tree");
compiler.set_jump_target(lt);
traverse_tree(compiler, lower)?;
compiler.set_jump_target(gt);
traverse_tree(compiler, upper_rest)?;
Ok(())
}

Check warning on line 210 in tremor-script/src/vm/compiler/impls.rs

View check run for this annotation

Codecov / codecov/patch

tremor-script/src/vm/compiler/impls.rs#L202-L210

Added lines #L202 - L210 were not covered by tests

impl<'script, Ex> Compilable<'script> for Match<'script, Ex>
where
Ex: Compilable<'script> + Expression,
Expand Down
5 changes: 2 additions & 3 deletions tremor-script/src/vm/compiler/impls/imut_expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -421,8 +421,7 @@ impl<'script> Compilable<'script> for Pattern<'script> {
Pattern::Expr(e) => {
let mid = e.meta().clone();
e.compile(compiler)?;
compiler.emit(Op::Binary { op: BinOpKind::Eq }, &mid);
compiler.emit(Op::LoadRB, &NodeMeta::dummy());
compiler.emit(Op::TestEq, &mid);

Check warning on line 424 in tremor-script/src/vm/compiler/impls/imut_expr.rs

View check run for this annotation

Codecov / codecov/patch

tremor-script/src/vm/compiler/impls/imut_expr.rs#L421-L424

Added lines #L421 - L424 were not covered by tests
}

Pattern::Assign(_) => todo!(),
Expand All @@ -444,7 +443,7 @@ impl<'script> Compilable<'script> for Pattern<'script> {
compiler.emit(Op::LoadRB, &mid);
let end_and_pop = compiler.new_jump_point();

compiler.emit(Op::JumpFalse { dst: end_and_pop }, &mid);
compiler.emit(Op::JumpFalse { dst: dst_next }, &mid);

compiler.comment("Save array for itteration and reverse it");
compiler.emit(Op::CopyV1, &mid);
Expand Down
17 changes: 17 additions & 0 deletions tremor-script/src/vm/op.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,17 @@ pub(crate) enum Op {
TestIsU64,
TestIsI64,
TestIsBytes,
#[allow(dead_code)]
TestEq,
#[allow(dead_code)]
TestNeq,
TestGt,
#[allow(dead_code)]
TestGte,
TestLt,
#[allow(dead_code)]
TestLte,

#[allow(dead_code)]
TestArrayIsEmpty,
TestRecordIsEmpty,
Expand Down Expand Up @@ -190,6 +201,12 @@ impl Display for Op {
Op::TestIsArray => write!(f, "test_is_array"),
Op::TestArrayIsEmpty => write!(f, "test_array_is_empty"),
Op::TestRecordIsEmpty => write!(f, "test_record_is_empty"),
Op::TestEq => write!(f, "test_eq"),
Op::TestNeq => write!(f, "test_neq"),
Op::TestGt => write!(f, "test_gt"),
Op::TestGte => write!(f, "test_gte"),
Op::TestLt => write!(f, "test_lt"),
Op::TestLte => write!(f, "test_lte"),

Check warning on line 209 in tremor-script/src/vm/op.rs

View check run for this annotation

Codecov / codecov/patch

tremor-script/src/vm/op.rs#L196-L209

Added lines #L196 - L209 were not covered by tests

Op::InspectLen => write!(f, "inspect_len"),

Check warning on line 211 in tremor-script/src/vm/op.rs

View check run for this annotation

Codecov / codecov/patch

tremor-script/src/vm/op.rs#L211

Added line #L211 was not covered by tests

Expand Down
Loading

0 comments on commit e4d61f8

Please sign in to comment.