Skip to content

Commit

Permalink
maps
Browse files Browse the repository at this point in the history
  • Loading branch information
maxmindlin committed Jul 17, 2024
1 parent 5b141ab commit aebbe20
Show file tree
Hide file tree
Showing 7 changed files with 145 additions and 38 deletions.
52 changes: 48 additions & 4 deletions scout-interpreter/src/builtin.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
use std::{env, sync::Arc, thread::sleep, time::Duration};
use std::{collections::HashMap, env, sync::Arc, thread::sleep, time::Duration};

use fantoccini::{
actions::{InputSource, KeyAction, KeyActions},
client,

Check warning on line 5 in scout-interpreter/src/builtin.rs

View workflow job for this annotation

GitHub Actions / test

unused import: `client`
cookies::Cookie,
elements::Element,
key::Key,
};
use futures::{future::BoxFuture, lock::Mutex, FutureExt, TryFutureExt};
use scout_parser::ast::Identifier;

use crate::{object::Object, EvalError, EvalResult, ScrapeResultsPtr};

Expand Down Expand Up @@ -36,13 +39,15 @@ pub enum BuiltinKind {
IsWhitespace,
List,
Push,
Cookies,
SetCookies,
}

impl BuiltinKind {
pub fn is_from(s: &str) -> Option<Self> {
use BuiltinKind::*;
match s {
"is_whitespace" => Some(IsWhitespace),
"isWhitespace" => Some(IsWhitespace),
"url" => Some(Url),
"number" => Some(Number),
"args" => Some(Args),
Expand All @@ -55,10 +60,12 @@ impl BuiltinKind {
"input" => Some(Input),
"contains" => Some(Contains),
"type" => Some(Type),
"key_action" => Some(KeyPress),
"keyAction" => Some(KeyPress),
"sleep" => Some(Sleep),
"list" => Some(List),
"push" => Some(Push),
"cookies" => Some(Cookies),
"setCookies" => Some(SetCookies),
_ => None,
}
}
Expand All @@ -71,6 +78,36 @@ impl BuiltinKind {
) -> EvalResult {
use BuiltinKind::*;
match self {
Cookies => {
let cookies = crawler
.get_all_cookies()
.await?
.iter()
.map(|c| {
(
Identifier::new(c.name().to_string()),
Arc::new(Object::Str(c.value().to_string())),
)
})
.collect::<HashMap<Identifier, Arc<Object>>>();

Ok(Arc::new(Object::Map(Mutex::new(cookies))))
}
SetCookies => {
assert_param_len!(args, 1);
if let Object::Map(m) = &*args[0] {
let inner = m.lock().await;
crawler.delete_all_cookies().await?;
for (key, val) in inner.iter() {
let cookie = Cookie::new(key.name.clone(), val.to_string());
crawler.add_cookie(cookie).await?;
}

Ok(Arc::new(Object::Null))
} else {
Err(EvalError::InvalidFnParams)
}
}
Push => {
assert_param_len!(args, 2);
match (&*args[0], args[1].clone()) {
Expand Down Expand Up @@ -236,7 +273,14 @@ impl BuiltinKind {
_ => Err(EvalError::InvalidFnParams),
},
Object::List(v) => {
let contains = v.lock().await.contains(&args[1]);
let inner = v.lock().await;
let mut contains = false;
for obj in inner.iter() {
if obj.eq(&args[1]).await {
contains = true;
break;
}
}
Ok(Arc::new(Object::Boolean(contains)))
}
_ => Err(EvalError::InvalidFnParams),
Expand Down
31 changes: 29 additions & 2 deletions scout-interpreter/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ pub enum EvalError {
UnknownIdent(Identifier),
UnknownPrefixOp,
UnknownInfixOp,
UnknownKey(Identifier),
UncaughtException,
URLParseError(String),
DuplicateDeclare,
Expand Down Expand Up @@ -230,6 +231,12 @@ fn eval_statement<'a>(
}
Ok(Arc::new(Object::Null))
}
(Object::Map(m), Object::Str(s)) => {
let mut inner = m.lock().await;
let ident = Identifier::new(s.clone());
inner.insert(ident, val);
Ok(Arc::new(Object::Null))
}
_ => Err(EvalError::InvalidIndex),
}
}
Expand Down Expand Up @@ -706,6 +713,17 @@ fn eval_expression<'a>(
},
ExprKind::Str(s) => Ok(Arc::new(Object::Str(s.to_owned()))),
ExprKind::Number(n) => Ok(Arc::new(Object::Number(*n))),
ExprKind::Map(map) => {
let mut out = HashMap::new();

for (key, val) in map.pairs.iter() {
let obj_val =
eval_expression(val, crawler, env.clone(), results.clone()).await?;
out.insert(key.clone(), obj_val);
}

Ok(Arc::new(Object::Map(Mutex::new(out))))
}
ExprKind::Call(ident, params) => {
apply_call(ident, params, crawler, None, env.clone(), results.clone()).await
}
Expand Down Expand Up @@ -786,8 +804,8 @@ async fn eval_infix(

async fn eval_infix_op(lhs: Arc<Object>, op: &TokenKind, rhs: Arc<Object>) -> EvalResult {
match op {
TokenKind::EQ => Ok(Arc::new(Object::Boolean(lhs == rhs))),
TokenKind::NEQ => Ok(Arc::new(Object::Boolean(lhs != rhs))),
TokenKind::EQ => Ok(Arc::new(Object::Boolean(lhs.eq(&rhs).await))),
TokenKind::NEQ => Ok(Arc::new(Object::Boolean(!lhs.eq(&rhs).await))),
TokenKind::Plus => eval_plus_op(lhs, rhs),
TokenKind::Minus => eval_minus_op(lhs, rhs),
TokenKind::Asterisk => eval_asterisk_op(lhs, rhs),
Expand Down Expand Up @@ -828,6 +846,15 @@ async fn eval_index(lhs: Arc<Object>, idx: Arc<Object>) -> EvalResult {
Err(EvalError::IndexOutOfBounds)
}
}
(Object::Map(m), Object::Str(s)) => {
let inner = m.lock().await;
let ident = Identifier::new(s.clone());
let mb_val = inner.get(&ident);
match mb_val {
Some(val) => Ok(val.clone()),
None => Err(EvalError::UnknownIdent(ident)),
}
}
(Object::Str(a), Object::Number(b)) => match a.chars().nth(*b as usize) {
Some(c) => Ok(Arc::new(Object::Str(c.to_string()))),
None => Err(EvalError::IndexOutOfBounds),
Expand Down
87 changes: 58 additions & 29 deletions scout-interpreter/src/object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use crate::env::EnvPointer;
#[derive(Debug)]
pub enum Object {
Null,
Map(HashMap<Identifier, Arc<Object>>),
Map(Mutex<HashMap<Identifier, Arc<Object>>>),
Str(String),
Node(fantoccini::elements::Element),
List(Mutex<Vec<Arc<Object>>>),
Expand Down Expand Up @@ -62,11 +62,15 @@ impl Object {
match self {
Null => "Null".into(),
Map(hash) => {
let mut out = "{{".to_string();
for (i, o) in hash.iter() {
out.push_str(&format!("{}: {} ", i, o));
let inner = hash.lock().await;
let mut out = "{ ".to_string();
for (idx, (i, o)) in inner.iter().enumerate() {
out.push_str(&format!("{}: {}", i, o));
if idx != inner.len() - 1 {
out.push_str(", ");
}
}
out.push_str("}}");
out.push_str(" }");
out
}
Str(s) => format!("\"{}\"", s),
Expand All @@ -92,23 +96,52 @@ impl Object {
}
.boxed()
}
}

impl PartialEq for Object {
fn eq(&self, other: &Self) -> bool {
use Object::*;
match (self, other) {
(Null, Null) => true,
(Map(a), Map(b)) => a == b,
(Str(a), Str(b)) => a == b,
// @TODO: check if this is even correct
(Node(a), Node(b)) => a.element_id() == b.element_id(),
// @TODO: this requires async awaits....
(List(_a), List(_b)) => false,
(Boolean(a), Boolean(b)) => a == b,
(Number(a), Number(b)) => a == b,
_ => false,
pub fn eq<'a>(&'a self, other: &'a Self) -> BoxFuture<'a, bool> {
async move {
use Object::*;
match (self, other) {
(Null, Null) => true,
(Map(a), Map(b)) => {
let a_i = a.lock().await;
let b_i = b.lock().await;
for key in a_i.keys() {
match b_i.get(key) {
Some(obj) => {
if !a_i.get(key).unwrap().eq(obj).await {
return false;
}
}
None => return false,
}
}
true
}
(Str(a), Str(b)) => a == b,
// @TODO: check if this is even correct
(Node(a), Node(b)) => a.element_id() == b.element_id(),
(List(a), List(b)) => {
let a_i = a.lock().await;
let b_i = b.lock().await;

if a_i.len() != b_i.len() {
return false;
}

for idx in 0..(a_i.len() - 1) {
if !a_i[idx].eq(&b_i[idx]).await {
return false;
}
}

true
}
(Boolean(a), Boolean(b)) => a == b,
(Number(a), Number(b)) => a == b,
_ => false,
}
}
.boxed()
}
}

Expand All @@ -117,13 +150,6 @@ impl Display for Object {
use Object::*;
match self {
Null => write!(f, "Null"),
Map(hash) => {
write!(f, "{{")?;
for (i, o) in hash.iter() {
write!(f, "{}: {} ", i, o)?;
}
write!(f, "}}")
}
Str(s) => write!(f, "\"{}\"", s),
Node(_) => write!(f, "Node"),
List(_objs) => write!(f, "list"),
Expand Down Expand Up @@ -155,7 +181,10 @@ impl Object {
// @TODO handle this better
Node(_) => Value::String("Node".to_owned()),
List(list) => self.vec_to_json(list).await,
Map(map) => Value::Object(obj_map_to_json(map).await),
Map(map) => {
let inner = map.lock().await;
Value::Object(obj_map_to_json(&*inner).await)
}
Boolean(b) => Value::Bool(*b),
Number(n) => json!(n),
Fn(_, _) => panic!("cant serialize func"),
Expand All @@ -168,7 +197,7 @@ impl Object {
match self {
Null => false,
Str(s) => !s.is_empty(),
Map(m) => !m.is_empty(),
Map(m) => !m.lock().await.is_empty(),
List(v) => !v.lock().await.is_empty(),
Boolean(b) => *b,
// @TODO: Idk what truthiness of floats should be
Expand Down
2 changes: 1 addition & 1 deletion scout-lib/keys.sct
Original file line number Diff line number Diff line change
Expand Up @@ -59,5 +59,5 @@ COMMAND = "\u{e03d}"
// Executes a key press action with
// the given key unicode value.
def press(code) do
key_action(code)
keyAction(code)
end
4 changes: 2 additions & 2 deletions scout-lib/str.sct
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// from the left start of a given string.
def ltrim(s) do
i = 0
while is_whitespace(s[i]) and i < len(s) do
while isWhitespace(s[i]) and i < len(s) do
i = i + 1
end

Expand All @@ -18,7 +18,7 @@ end
// from the right start of a given string.
def rtrim(s) do
i = len(s) - 1
while is_whitespace(s[i]) and i > 0 do
while isWhitespace(s[i]) and i > 0 do
i = i - 1
end

Expand Down
1 change: 1 addition & 0 deletions scout-parser/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ pub enum ExprKind {
Boolean(bool),
Ident(Identifier),
List(Vec<ExprKind>),
Map(HashLiteral),
Null,

// Selects
Expand Down
6 changes: 6 additions & 0 deletions scout-parser/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ fn map_prefix_fn(kind: &TokenKind) -> Option<PrefixParseFn> {
Str => Some(Parser::parse_str_literal),
Null => Some(Parser::parse_null),
LBracket => Some(Parser::parse_list_literal),
LBrace => Some(Parser::parse_map),
SelectAll => Some(Parser::parse_select_all),
Select => Some(Parser::parse_select),
Bang => Some(Parser::parse_prefix),
Expand Down Expand Up @@ -395,6 +396,11 @@ impl Parser {
Ok(HashLiteral { pairs })
}

fn parse_map(&mut self) -> ParseResult<ExprKind> {
let lit = self.parse_hash_literal()?;
Ok(ExprKind::Map(lit))
}

fn parse_number_literal(&mut self) -> ParseResult<ExprKind> {
Ok(ExprKind::Number(
self.curr
Expand Down

0 comments on commit aebbe20

Please sign in to comment.