Skip to content

Commit

Permalink
refactor: update lexer match; remove interval from variable in favor …
Browse files Browse the repository at this point in the history
…of symbol Object; (gorules#93)
  • Loading branch information
stefan-gorules authored Oct 6, 2023
1 parent 615d554 commit 16a16c1
Show file tree
Hide file tree
Showing 4 changed files with 151 additions and 106 deletions.
37 changes: 14 additions & 23 deletions core/expression/src/lexer/codes.rs
Original file line number Diff line number Diff line change
@@ -1,27 +1,18 @@
#[macro_export]
macro_rules! token_type {
("space") => { ' ' | '\n' | '\t' };
("quote") => { '\'' | '"' };
("digit") => { '0'..='9' };
("bracket") => { '(' | ')' | '[' | ']' };
("cmp_operator") => { '>' | '<' | '!' | '=' };
("operator") => { '#' | ',' | '?' | ':' | '+' | '-' | '/' | '*' | '^' | '%' };
("alpha") => { 'A'..='Z' | 'a'..='z' | '$' | '_' };
("alphanumeric") => { 'A'..='Z' | 'a'..='z' | '0'..='9' | '$' | '_' };
}

#[macro_export]
macro_rules! is_token_type {
($str: expr, "space") => {
matches!($str, ' ' | '\n' | '\t')
};
($str: expr, "quote") => {
matches!($str, '\'' | '"')
};
($str: expr, "digit") => {
matches!($str, '0'..='9')
};
($str: expr, "bracket") => {
matches!($str, '(' | ')' | '[' | ']')
};
($str: expr, "cmp_operator") => {
matches!($str, '>' | '<' | '!' | '=')
};
($str: expr, "operator") => {
matches!($str, '#' | ',' | '?' | ':' | '+' | '-' | '/' | '*' | '^' | '%')
};
($str: expr, "alpha") => {
matches!($str, 'A'..='Z' | 'a'..='z' | '$' | '_')
};
($str: expr, "alphanumeric") => {
matches!($str, 'A'..='Z' | 'a'..='z' | '0'..='9' | '$' | '_')
($str: expr, $t: tt) => {
matches!($str, crate::token_type!($t))
};
}
20 changes: 10 additions & 10 deletions core/expression/src/lexer/lexer.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
use std::cell::RefCell;
use std::rc::Rc;

use crate::is_token_type;
use crate::lexer::cursor::{Cursor, CursorItem};
use crate::lexer::error::LexerError;
use crate::lexer::error::LexerError::{UnexpectedEof, UnmatchedSymbol};
use crate::lexer::token::{Token, TokenKind};
use crate::{is_token_type, token_type};

type TokenSlice<'a> = Rc<RefCell<Vec<Token<'a>>>>;

Expand Down Expand Up @@ -54,17 +54,17 @@ impl<'a> Scanner<'a> {
pub fn scan(&self) -> VoidResult {
while let Some((i, s)) = self.cursor.peek() {
match s {
_ if is_token_type!(s, "space") => {
token_type!("space") => {
self.cursor.next();
Ok(())
}
_ if is_token_type!(s, "quote") => self.string(),
_ if is_token_type!(s, "digit") => self.number(),
_ if is_token_type!(s, "bracket") => self.bracket(),
_ if is_token_type!(s, "cmp_operator") => self.operator(),
_ if is_token_type!(s, "operator") => self.simple_operator(),
token_type!("quote") => self.string(),
token_type!("digit") => self.number(),
token_type!("bracket") => self.bracket(),
token_type!("cmp_operator") => self.cmp_operator(),
token_type!("operator") => self.operator(),
'.' => self.dot(),
_ if is_token_type!(s, "alpha") => self.identifier(),
token_type!("alpha") => self.identifier(),

_ => Err(UnmatchedSymbol {
symbol: s,
Expand Down Expand Up @@ -178,7 +178,7 @@ impl<'a> Scanner<'a> {
Ok(())
}

fn operator(&self) -> VoidResult {
fn cmp_operator(&self) -> VoidResult {
let (start, _) = self.next()?;
let mut end = start;

Expand All @@ -195,7 +195,7 @@ impl<'a> Scanner<'a> {
Ok(())
}

fn simple_operator(&self) -> VoidResult {
fn operator(&self) -> VoidResult {
let (start, _) = self.next()?;

self.push(Token {
Expand Down
70 changes: 60 additions & 10 deletions core/expression/src/opcodes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ use bumpalo::Bump;
use chrono::NaiveDateTime;
use hashbrown::hash_map::DefaultHashBuilder;
use hashbrown::BumpWrapper;
use rust_decimal::prelude::ToPrimitive;
use rust_decimal::Decimal;
use serde_json::{Map, Number, Value};

use crate::helpers::date_time;
use crate::vm::VMError;
use crate::vm::VMError::{OpcodeErr, ParseDateTimeErr};
use rust_decimal::prelude::ToPrimitive;
use rust_decimal::Decimal;
use serde_json::{Map, Number, Value};

#[derive(Debug)]
pub enum Variable<'a> {
Expand All @@ -20,12 +20,6 @@ pub enum Variable<'a> {
String(&'a str),
Array(&'a [&'a Variable<'a>]),
Object(hashbrown::HashMap<&'a str, &'a Variable<'a>, DefaultHashBuilder, BumpWrapper<'a>>),
Interval {
left_bracket: &'a str,
right_bracket: &'a str,
left: &'a Variable<'a>,
right: &'a Variable<'a>,
},
}

impl<'a> Variable<'a> {
Expand Down Expand Up @@ -64,6 +58,13 @@ impl<'a> Variable<'a> {
Value::Null => Variable::Null,
}
}

pub(crate) fn as_str(&self) -> Option<&'a str> {
match self {
Variable::String(str) => Some(str),
_ => None,
}
}
}

#[derive(Debug)]
Expand Down Expand Up @@ -161,7 +162,6 @@ impl TryFrom<&Variable<'_>> for Value {

Ok(Value::Object(t))
}
_ => Err(()),
}
}
}
Expand Down Expand Up @@ -189,3 +189,53 @@ impl TryFrom<&Variable<'_>> for NaiveDateTime {
}
}
}

pub(crate) struct IntervalObject<'a> {
pub(crate) left_bracket: &'a str,
pub(crate) right_bracket: &'a str,
pub(crate) left: &'a Variable<'a>,
pub(crate) right: &'a Variable<'a>,
}

impl<'a> IntervalObject<'a> {
pub(crate) fn cast_to_object(&self, bump: &'a Bump) -> Variable<'a> {
let mut tree: hashbrown::HashMap<&'a str, &'a Variable, _, _> =
hashbrown::HashMap::new_in(BumpWrapper(bump));

tree.insert("_symbol", &Variable::String("Interval"));
tree.insert(
"left_bracket",
bump.alloc(Variable::String(self.left_bracket)),
);
tree.insert(
"right_bracket",
bump.alloc(Variable::String(self.right_bracket)),
);
tree.insert("left", self.left);
tree.insert("right", self.right);

Variable::Object(tree)
}

pub(crate) fn try_from_object(var: &'a Variable<'a>) -> Option<IntervalObject> {
let Variable::Object(tree) = var else {
return None;
};

if tree.get("_symbol")?.as_str()? != "Interval" {
return None;
}

let left_bracket = tree.get("left_bracket")?.as_str()?;
let right_bracket = tree.get("right_bracket")?.as_str()?;
let left = tree.get("left")?;
let right = tree.get("right")?;

Some(Self {
left_bracket,
right_bracket,
right,
left,
})
}
}
130 changes: 67 additions & 63 deletions core/expression/src/vm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ use rust_decimal_macros::dec;
use thiserror::Error;

use crate::helpers::{date_time, date_time_end_of, date_time_start_of, time};
use crate::opcodes::Variable::{Array, Bool, Interval, Null, Number, Object, String};
use crate::opcodes::{Opcode, Variable};
use crate::opcodes::Variable::{Array, Bool, Null, Number, Object, String};
use crate::opcodes::{IntervalObject, Opcode, Variable};
use crate::vm::VMError::{OpcodeErr, OpcodeOutOfBounds, ParseDateTimeErr, StackOutOfBounds};

const NULL_VAR: &'static Variable = &Null;
Expand Down Expand Up @@ -256,63 +256,63 @@ impl<'a> VM<'a> {

self.stack.push(self.bump.alloc(Bool(is_in)));
}
(
Number(v),
Interval {
left_bracket,
right_bracket,
left,
right,
},
) => match (left, right) {
(Number(l), Number(r)) => {
let mut is_open = false;

let first = match *left_bracket {
"[" => l <= v,
"(" => l < v,
"]" => {
is_open = true;
l >= v
}
")" => {
is_open = true;
l > v
}
_ => {
return Err(OpcodeErr {
opcode: "In".into(),
message: "Unsupported bracket".into(),
})
}
};

let second = match *right_bracket {
"]" => r >= v,
")" => r > v,
"[" => r <= v,
"(" => r < v,
_ => {
return Err(OpcodeErr {
opcode: "In".into(),
message: "Unsupported bracket".into(),
})
}
};

let open_stmt = is_open && (first || second);
let closed_stmt = !is_open && first && second;

self.stack
.push(self.bump.alloc(Bool(open_stmt || closed_stmt)));
}
_ => {
return Err(OpcodeErr {
(Number(v), Object(_)) => {
let interval =
IntervalObject::try_from_object(b).ok_or_else(|| OpcodeErr {
opcode: "In".into(),
message: "Unsupported type".into(),
})
message: "Failed to deconstruct interval".into(),
})?;

match (interval.left, interval.right) {
(Number(l), Number(r)) => {
let mut is_open = false;

let first = match interval.left_bracket {
"[" => l <= v,
"(" => l < v,
"]" => {
is_open = true;
l >= v
}
")" => {
is_open = true;
l > v
}
_ => {
return Err(OpcodeErr {
opcode: "In".into(),
message: "Unsupported bracket".into(),
})
}
};

let second = match interval.right_bracket {
"]" => r >= v,
")" => r > v,
"[" => r <= v,
"(" => r < v,
_ => {
return Err(OpcodeErr {
opcode: "In".into(),
message: "Unsupported bracket".into(),
})
}
};

let open_stmt = is_open && (first || second);
let closed_stmt = !is_open && first && second;

self.stack
.push(self.bump.alloc(Bool(open_stmt || closed_stmt)));
}
_ => {
return Err(OpcodeErr {
opcode: "In".into(),
message: "Unsupported type".into(),
})
}
}
},
}
(String(a), Array(arr)) => {
let is_in = arr.iter().any(|b| match b {
String(b) => a == b,
Expand Down Expand Up @@ -812,12 +812,16 @@ impl<'a> VM<'a> {
let a = self.pop()?;

match (a, b) {
(Number(_), Number(_)) => self.stack.push(self.bump.alloc(Interval {
left_bracket,
right_bracket,
left: a,
right: b,
})),
(Number(_), Number(_)) => {
let interval = IntervalObject {
left_bracket,
right_bracket,
left: a,
right: b,
};

self.push(interval.cast_to_object(self.bump));
}
_ => {
return Err(OpcodeErr {
opcode: "Interval".into(),
Expand Down

0 comments on commit 16a16c1

Please sign in to comment.