Skip to content

Commit

Permalink
various fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
maxmindlin committed Aug 21, 2024
1 parent 72e56ea commit a37498f
Show file tree
Hide file tree
Showing 8 changed files with 187 additions and 58 deletions.
16 changes: 16 additions & 0 deletions scout-interpreter/src/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,29 @@ pub type EnvPointer = Arc<Mutex<Env>>;
pub struct Env {
pub store: HashMap<String, Arc<Object>>,
outer: Mutex<Weak<Mutex<Env>>>,
pub globals: Vec<Identifier>,
}

impl Env {
pub async fn add_outer(&mut self, env: EnvPointer) {
*self.outer.get_mut() = Arc::downgrade(&env);
}

pub async fn inherit_globals(&mut self, other: EnvPointer) {
let inner = other.lock().await;
for global in &inner.globals {
// This should be safe because we only add to globals
// and store at the same time.
let val = inner.get(global).await.unwrap();
self.add_global(global, val.clone()).await;
}
}

pub async fn add_global(&mut self, id: &Identifier, obj: Arc<Object>) {
self.set(id, obj).await;
self.globals.push(id.clone());
}

pub fn get<'a>(&'a self, id: &'a Identifier) -> BoxFuture<'a, Option<Arc<Object>>> {
async move {
match self.outer.borrow().lock().await.upgrade() {
Expand Down
24 changes: 18 additions & 6 deletions scout-interpreter/src/eval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ fn eval_statement<'a>(
}
Ok(Arc::new(Object::Null))
}
StmtKind::Assign(lhs, expr) => {
StmtKind::Assign(lhs, expr, global) => {
let val = eval_expression(expr, crawler, env.clone(), results.clone()).await?;
match lhs {
ExprKind::Infix(lhs, t, rhs) if t.kind == TokenKind::LBracket => {
Expand Down Expand Up @@ -243,7 +243,11 @@ fn eval_statement<'a>(
}
}
ExprKind::Ident(ident) => {
env.lock().await.set(ident, val).await;
if !global {
env.lock().await.set(ident, val).await;
} else {
env.lock().await.add_global(ident, val).await;
}
Ok(Arc::new(Object::Null))
}
_ => Err(EvalError::InvalidAssign),
Expand Down Expand Up @@ -287,9 +291,13 @@ fn eval_statement<'a>(

Ok(Arc::new(Object::Null))
}
StmtKind::Func(def) => {
StmtKind::Func(def, global) => {
let lit = Object::Fn(def.params.clone(), def.body.clone());
env.lock().await.set(&def.ident, Arc::new(lit)).await;
if !global {
env.lock().await.set(&def.ident, Arc::new(lit)).await;
} else {
env.lock().await.add_global(&def.ident, Arc::new(lit)).await;
}
Ok(Arc::new(Object::Null))
}
StmtKind::Return(rv) => match rv {
Expand Down Expand Up @@ -330,7 +338,9 @@ fn eval_use_chain<'a>(
let mut parser = Parser::new(lex);
match parser.parse_program() {
Ok(prgm) => {
let module_env = Arc::new(Mutex::new(Env::default()));
let mut new_env = Env::default();
new_env.inherit_globals(env.clone()).await;
let module_env = Arc::new(Mutex::new(new_env));
eval(
NodeKind::Program(prgm),
crawler,
Expand Down Expand Up @@ -359,7 +369,9 @@ fn eval_use_chain<'a>(
} else {
dir_name_raw
};
let mod_env = Arc::new(Mutex::new(Env::default()));
let mut new_env = Env::default();
new_env.inherit_globals(env.clone()).await;
let mod_env = Arc::new(Mutex::new(new_env));
for entry in path.read_dir().unwrap() {
if let Ok(entry) = entry {
let filename = entry
Expand Down
12 changes: 12 additions & 0 deletions scout-interpreter/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use std::{

use env::EnvPointer;
use eval::{eval, EvalError, ScrapeResultsPtr};
use fantoccini::error::CmdError;
use object::Object;
use scout_json::ScoutJSON;
use scout_lexer::Lexer;
Expand Down Expand Up @@ -128,6 +129,11 @@ impl Interpreter {
self.results = ScrapeResultsPtr::default();
}

pub async fn current_url(&self) -> Result<String, InterpreterError> {
let url = self.crawler.current_url().await?;
Ok(url.to_string())
}

pub async fn close(self) {
let _ = self.crawler.close().await;
}
Expand All @@ -139,6 +145,12 @@ impl From<EvalError> for InterpreterError {
}
}

impl From<CmdError> for InterpreterError {
fn from(value: CmdError) -> Self {
InterpreterError::EvalError(EvalError::BrowserError(value))
}
}

impl Drop for GeckDriverProc {
fn drop(&mut self) {
#[cfg(target_os = "windows")]
Expand Down
27 changes: 26 additions & 1 deletion scout-interpreter/src/object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ use serde_json::{json, Value};

use crate::env::EnvPointer;

pub trait ParseObj<T> {
fn parse_obj(&self) -> impl std::future::Future<Output = Result<T, String>> + Send;
}

#[derive(Debug)]
pub enum Object {
Null,
Expand Down Expand Up @@ -85,7 +89,7 @@ impl Object {
out.push_str(" }");
out
}
Str(s) => format!("\"{}\"", s),
Str(s) => format!("{}", s),
Node(_) => "Node".into(),
List(mutex) => {
let inner = mutex.lock().await;
Expand Down Expand Up @@ -250,3 +254,24 @@ pub fn json_to_obj(json: &Value) -> Arc<Object> {
Value::Number(n) => Arc::new(Object::Number(n.as_f64().unwrap_or(f64::NAN))),
}
}

impl ParseObj<Vec<Arc<Object>>> for Object {
async fn parse_obj(&self) -> Result<Vec<Arc<Object>>, String> {
match self {
Object::List(m) => {
let inner = m.lock().await.clone();
Ok(inner)
}
_ => Err("cant turn this type into a vec".to_string()),
}
}
}

impl ParseObj<String> for Object {
async fn parse_obj(&self) -> Result<String, String> {
match self {
Object::Str(s) => Ok(s.clone()),
_ => Err("cant turn this type into a string".to_string()),
}
}
}
2 changes: 1 addition & 1 deletion scout-lexer/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ impl Lexer {
Token::new(Int, lit)
}
}
_ if c.is_alphabetic() => {
_ if is_valid_identifier(c) => {
let lit = self.read_identifier();
match TokenKind::is_to_keyword(&lit) {
Some(t) => Token::new(t, lit),
Expand Down
2 changes: 2 additions & 0 deletions scout-lexer/src/token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ pub enum TokenKind {
And,
Or,
While,
Global,
}

impl TokenKind {
Expand Down Expand Up @@ -87,6 +88,7 @@ impl TokenKind {
"throw" => Some(Throw),
"and" => Some(And),
"or" => Some(Or),
"global" => Some(Global),
_ => None,
}
}
Expand Down
22 changes: 17 additions & 5 deletions scout-parser/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@ pub struct Program {

#[derive(Debug, PartialEq, Clone)]
pub enum StmtKind {
Assign(ExprKind, ExprKind),
Assign(ExprKind, ExprKind, bool),
Crawl(CrawlLiteral),
Expr(ExprKind),
ForLoop(ForLoop),
WhileLoop(ExprKind, Block),
Func(FuncDef),
Func(FuncDef, bool),
Goto(ExprKind),
IfElse(IfElseLiteral),
Return(Option<ExprKind>),
Expand Down Expand Up @@ -330,7 +330,13 @@ impl std::fmt::Display for StmtKind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
use StmtKind::*;
match self {
Assign(lhs, rhs) => write!(f, "{lhs} = {rhs}"),
Assign(lhs, rhs, g) => {
if *g {
write!(f, "global {lhs} = {rhs}")
} else {
write!(f, "{lhs} = {rhs}")
}
}
Crawl(lit) => {
write!(f, "crawl ")?;

Expand All @@ -353,7 +359,13 @@ impl std::fmt::Display for StmtKind {
)
}
WhileLoop(cond, block) => write!(f, "while {cond} do\n{block}end\n"),
Func(def) => write!(f, "{def}"),
Func(def, g) => {
if *g {
write!(f, "global {def}")
} else {
write!(f, "{def}")
}
}
Goto(expr) => write!(f, "goto {expr}"),
IfElse(lit) => {
writeln!(f, "if {} do\n{}", lit.if_lit.cond, lit.if_lit.block)?;
Expand All @@ -379,7 +391,7 @@ impl std::fmt::Display for StmtKind {
if let Some(catch) = c {
write!(f, "catch\n{catch}\n")?;
}
write!(f, "end\n")
writeln!(f, "end")
}
Use(expr) => write!(f, "use {expr}"),
}
Expand Down
Loading

0 comments on commit a37498f

Please sign in to comment.