refactor: first part of moving to results

This commit is contained in:
Daniel Bulant 2021-12-10 17:35:22 +01:00
parent a4fc18f8fe
commit e8b943a8d5
2 changed files with 95 additions and 5 deletions

View file

@ -294,12 +294,15 @@ impl Tree {
Tokens::StringFunction(_) => panic!("Unexpected string function"),
Tokens::ParenthesisStart => panic!("Parenthesis not yet implemented"),
Tokens::SubStart => {
let mut len = 1;
let mut len = 0;
let mut lvl = 1;
self.inc();
for token in &self.tokens[self.i..] {
match token {
Tokens::SubStart => lvl += 1,
Tokens::StringFunction(_) => lvl += 1,
Tokens::ArrayFunction(_) => lvl += 1,
Tokens::ParenthesisStart => lvl += 1,
Tokens::ParenthesisEnd => lvl -= 1,
_ => {}
}
@ -312,9 +315,13 @@ impl Tree {
}
// self.inc();
if lvl != 0 {
panic!("Sub not ended properly");
panic!("Parenthesis do not match");
}
return Value::Expressions(self.parse_sub(self.i + len));
dbg!(&self, len);
let val = Value::Expressions(self.parse_sub(self.i + len));
self.inc();
dbg!(self);
return val;
},
Tokens::Else => buf.push(Value::Literal(token.to_str())),
Tokens::End => buf.push(Value::Literal(token.to_str())),
@ -361,7 +368,7 @@ impl Tree {
} else {
expr = Some(self.parse_call(end));
},
Tokens::ExportSet => panic!("Unexpected token EXPORT_SET (=)"),
Tokens::ExportSet => panic!("Unexpected token EXPORT SET (=)"),
Tokens::Function => return Expression::Function(self.parse_function(end)),
Tokens::FileRead => expr = Some(self.parse_read(expr, end)),
Tokens::FileWrite => expr = Some(self.parse_write(expr, end)),

View file

@ -1,6 +1,6 @@
use std::error::Error;
use std::fs::File;
use std::process::{Command, Stdio};
use std::process::{Child, Command, Stdio};
use std::io;
use std::ops::Deref;
use crate::parser::ast::{AndExpression, CommandValue, Expression, FileSourceExpression, FileTargetExpression, LetExpression, OrExpression, RedirectTargetExpression, Value};
@ -15,6 +15,89 @@ trait GetValue {
fn get(self, ctx: &mut vars::Context) -> Variable;
}
struct ExecResult {
cmd: Option<Command>,
child: Option<Child>
}
impl ExecResult {
fn new(cmd: Option<Command>, child: Option<Child>) -> Self {
Self { cmd, child }
}
/// Spawns the result, running the command (if any). Non-command results won't be spawned (like let statements)
fn spawn(&mut self) -> &mut Self {
if !self.started() {
match &mut self.cmd {
None => {},
Some(cmd) => {
self.child = Some(cmd.spawn().unwrap());
}
}
}
self
}
/// Checks if the result was spawned before by checking the child property. Non-command results won't ever be spawned (like let statements)
fn started(&self) -> bool {
matches!(self.child, Some(_))
}
/// A simple wrapper for redirecting current result (self) into STDIO (files or streams).
///
/// Does spawn the current result
fn redirect_into<T: std::io::Write>(mut self, into: &mut T) -> &mut T {
match &mut self.cmd {
None => {},
Some(cmd) => {
cmd.stdout(Stdio::piped());
self.spawn();
let child = self.child.unwrap();
let mut stdout = child.stdout.unwrap();
io::copy(&mut stdout, into);
}
}
into
}
/// A shorthand for redirecting current result into the next one
///
/// Uses `redirect_from_result` of the next result. Spawns this result, but not the next one.
fn redirect_into_result(&mut self, into: &mut ExecResult) -> &mut Self {
into.redirect_from_result(self);
self
}
/// Redirects the `from` into the current pending result
///
/// Doesn't spawn the current result
fn redirect_from<T: Into<Stdio>>(&mut self, from: T) -> &mut Self {
match &mut self.cmd {
None => {},
Some(cmd) => {
cmd.stdin(from);
}
}
self
}
/// A shortcut for redirecting a previous result into the current one
///
/// Spawns the previous result to obtain the output, but not the current one (self)
fn redirect_from_result(&mut self, into: &mut ExecResult) -> io::Result<&mut Self> {
if matches!(self.cmd, None) {
return Ok(self);
}
match &mut self.cmd {
None => {},
Some(source) => {
source.stdout(Stdio::piped());
match &mut into.cmd {
None => {},
Some(target) => {
target.stdin(source.spawn()?.stdout.unwrap());
}
};
}
}
Ok(self)
}
}
impl GetValue for CommandValue {
fn get(self, ctx: &mut vars::Context) -> Variable {
match self {