Implemented arithmetic substitution
This commit is contained in:
@@ -8,11 +8,7 @@ pub fn alias(node: Node, shenv: &mut ShEnv) -> ShResult<()> {
|
|||||||
while let Some(arg) = argv_iter.next() {
|
while let Some(arg) = argv_iter.next() {
|
||||||
let arg_raw = shenv.input_slice(arg.span()).to_string();
|
let arg_raw = shenv.input_slice(arg.span()).to_string();
|
||||||
if let Some((alias,body)) = arg_raw.split_once('=') {
|
if let Some((alias,body)) = arg_raw.split_once('=') {
|
||||||
log!(DEBUG, "{:?}",arg.span());
|
|
||||||
log!(DEBUG, arg_raw);
|
|
||||||
log!(DEBUG, body);
|
|
||||||
let clean_body = trim_quotes(&body);
|
let clean_body = trim_quotes(&body);
|
||||||
log!(DEBUG, clean_body);
|
|
||||||
shenv.logic_mut().set_alias(alias, &clean_body);
|
shenv.logic_mut().set_alias(alias, &clean_body);
|
||||||
} else {
|
} else {
|
||||||
return Err(ShErr::full(ShErrKind::SyntaxErr, "Expected an assignment in alias args", shenv.get_input(), arg.span().clone()))
|
return Err(ShErr::full(ShErrKind::SyntaxErr, "Expected an assignment in alias args", shenv.get_input(), arg.span().clone()))
|
||||||
|
|||||||
@@ -14,8 +14,8 @@ pub fn exec_input<S: Into<String>>(input: S, shenv: &mut ShEnv) -> ShResult<()>
|
|||||||
|
|
||||||
let token_stream = expand_aliases(token_stream, shenv);
|
let token_stream = expand_aliases(token_stream, shenv);
|
||||||
for token in &token_stream {
|
for token in &token_stream {
|
||||||
log!(DEBUG, token);
|
log!(TRACE, token);
|
||||||
log!(DEBUG, "{}",token.as_raw(shenv));
|
log!(TRACE, "{}",token.as_raw(shenv));
|
||||||
}
|
}
|
||||||
|
|
||||||
let syn_tree = Parser::new(token_stream,shenv).parse()?;
|
let syn_tree = Parser::new(token_stream,shenv).parse()?;
|
||||||
@@ -43,7 +43,7 @@ impl<'a> Executor<'a> {
|
|||||||
}
|
}
|
||||||
pub fn walk(&mut self) -> ShResult<()> {
|
pub fn walk(&mut self) -> ShResult<()> {
|
||||||
self.shenv.inputman_mut().save_state();
|
self.shenv.inputman_mut().save_state();
|
||||||
log!(DEBUG, "Starting walk");
|
log!(TRACE, "Starting walk");
|
||||||
while let Some(node) = self.ast.next_node() {
|
while let Some(node) = self.ast.next_node() {
|
||||||
if let NdRule::CmdList { cmds } = node.clone().into_rule() {
|
if let NdRule::CmdList { cmds } = node.clone().into_rule() {
|
||||||
log!(TRACE, "{:?}", cmds);
|
log!(TRACE, "{:?}", cmds);
|
||||||
@@ -51,13 +51,13 @@ impl<'a> Executor<'a> {
|
|||||||
} else { unreachable!() }
|
} else { unreachable!() }
|
||||||
}
|
}
|
||||||
self.shenv.inputman_mut().load_state();
|
self.shenv.inputman_mut().load_state();
|
||||||
log!(DEBUG, "passed");
|
log!(TRACE, "passed");
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn exec_list(list: Vec<(Option<CmdGuard>, Node)>, shenv: &mut ShEnv) -> ShResult<()> {
|
fn exec_list(list: Vec<(Option<CmdGuard>, Node)>, shenv: &mut ShEnv) -> ShResult<()> {
|
||||||
log!(DEBUG, "Executing list");
|
log!(TRACE, "Executing list");
|
||||||
let mut list = VecDeque::from(list);
|
let mut list = VecDeque::from(list);
|
||||||
while let Some(cmd_info) = list.fpop() {
|
while let Some(cmd_info) = list.fpop() {
|
||||||
let guard = cmd_info.0;
|
let guard = cmd_info.0;
|
||||||
@@ -104,7 +104,7 @@ fn dispatch_command(mut node: Node, shenv: &mut ShEnv) -> ShResult<()> {
|
|||||||
let mut is_func = false;
|
let mut is_func = false;
|
||||||
let mut is_subsh = false;
|
let mut is_subsh = false;
|
||||||
if let NdRule::Command { ref mut argv, redirs: _ } = node.rule_mut() {
|
if let NdRule::Command { ref mut argv, redirs: _ } = node.rule_mut() {
|
||||||
*argv = expand_argv(argv.to_vec(), shenv);
|
*argv = expand_argv(argv.to_vec(), shenv)?;
|
||||||
let cmd = argv.first().unwrap().as_raw(shenv);
|
let cmd = argv.first().unwrap().as_raw(shenv);
|
||||||
if shenv.logic().get_function(&cmd).is_some() {
|
if shenv.logic().get_function(&cmd).is_some() {
|
||||||
is_func = true;
|
is_func = true;
|
||||||
@@ -112,7 +112,7 @@ fn dispatch_command(mut node: Node, shenv: &mut ShEnv) -> ShResult<()> {
|
|||||||
is_builtin = true;
|
is_builtin = true;
|
||||||
}
|
}
|
||||||
} else if let NdRule::Subshell { body: _, ref mut argv, redirs: _ } = node.rule_mut() {
|
} else if let NdRule::Subshell { body: _, ref mut argv, redirs: _ } = node.rule_mut() {
|
||||||
*argv = expand_argv(argv.to_vec(), shenv);
|
*argv = expand_argv(argv.to_vec(), shenv)?;
|
||||||
is_subsh = true;
|
is_subsh = true;
|
||||||
} else { unreachable!() }
|
} else { unreachable!() }
|
||||||
|
|
||||||
@@ -239,7 +239,7 @@ fn exec_subshell(node: Node, shenv: &mut ShEnv) -> ShResult<()> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn exec_builtin(node: Node, shenv: &mut ShEnv) -> ShResult<()> {
|
fn exec_builtin(node: Node, shenv: &mut ShEnv) -> ShResult<()> {
|
||||||
log!(DEBUG, "Executing builtin");
|
log!(TRACE, "Executing builtin");
|
||||||
let command = if let NdRule::Command { argv, redirs: _ } = node.rule() {
|
let command = if let NdRule::Command { argv, redirs: _ } = node.rule() {
|
||||||
argv.first().unwrap().as_raw(shenv)
|
argv.first().unwrap().as_raw(shenv)
|
||||||
} else { unreachable!() };
|
} else { unreachable!() };
|
||||||
@@ -267,7 +267,7 @@ fn exec_builtin(node: Node, shenv: &mut ShEnv) -> ShResult<()> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn exec_assignment(node: Node, shenv: &mut ShEnv) -> ShResult<()> {
|
fn exec_assignment(node: Node, shenv: &mut ShEnv) -> ShResult<()> {
|
||||||
log!(DEBUG, "Executing assignment");
|
log!(TRACE, "Executing assignment");
|
||||||
let rule = node.into_rule();
|
let rule = node.into_rule();
|
||||||
if let NdRule::Assignment { assignments, cmd } = rule {
|
if let NdRule::Assignment { assignments, cmd } = rule {
|
||||||
log!(TRACE, "Assignments: {:?}", assignments);
|
log!(TRACE, "Assignments: {:?}", assignments);
|
||||||
@@ -298,7 +298,7 @@ fn exec_assignment(node: Node, shenv: &mut ShEnv) -> ShResult<()> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn exec_pipeline(node: Node, shenv: &mut ShEnv) -> ShResult<()> {
|
fn exec_pipeline(node: Node, shenv: &mut ShEnv) -> ShResult<()> {
|
||||||
log!(DEBUG, "Executing pipeline");
|
log!(TRACE, "Executing pipeline");
|
||||||
let rule = node.into_rule();
|
let rule = node.into_rule();
|
||||||
if let NdRule::Pipeline { cmds } = rule {
|
if let NdRule::Pipeline { cmds } = rule {
|
||||||
let mut prev_rpipe: Option<i32> = None;
|
let mut prev_rpipe: Option<i32> = None;
|
||||||
@@ -384,7 +384,7 @@ fn exec_pipeline(node: Node, shenv: &mut ShEnv) -> ShResult<()> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn exec_cmd(node: Node, shenv: &mut ShEnv) -> ShResult<()> {
|
fn exec_cmd(node: Node, shenv: &mut ShEnv) -> ShResult<()> {
|
||||||
log!(DEBUG, "Executing command");
|
log!(TRACE, "Executing command");
|
||||||
let blame = node.span();
|
let blame = node.span();
|
||||||
let rule = node.into_rule();
|
let rule = node.into_rule();
|
||||||
|
|
||||||
@@ -393,11 +393,11 @@ fn exec_cmd(node: Node, shenv: &mut ShEnv) -> ShResult<()> {
|
|||||||
let command = argv.first().unwrap().to_string();
|
let command = argv.first().unwrap().to_string();
|
||||||
if get_bin_path(&command, shenv).is_some() {
|
if get_bin_path(&command, shenv).is_some() {
|
||||||
|
|
||||||
log!(DEBUG, "{:?}",shenv.ctx().flags());
|
log!(TRACE, "{:?}",shenv.ctx().flags());
|
||||||
if shenv.ctx().flags().contains(ExecFlags::NO_FORK) {
|
if shenv.ctx().flags().contains(ExecFlags::NO_FORK) {
|
||||||
log!(TRACE, "Not forking");
|
log!(TRACE, "Not forking");
|
||||||
shenv.collect_redirs(redirs);
|
shenv.collect_redirs(redirs);
|
||||||
log!(DEBUG, "{:?}",shenv.ctx().redirs());
|
log!(TRACE, "{:?}",shenv.ctx().redirs());
|
||||||
if let Err(e) = shenv.ctx_mut().activate_rdrs() {
|
if let Err(e) = shenv.ctx_mut().activate_rdrs() {
|
||||||
eprintln!("{:?}",e);
|
eprintln!("{:?}",e);
|
||||||
exit(1);
|
exit(1);
|
||||||
@@ -411,7 +411,7 @@ fn exec_cmd(node: Node, shenv: &mut ShEnv) -> ShResult<()> {
|
|||||||
log!(TRACE, "Forking");
|
log!(TRACE, "Forking");
|
||||||
match unsafe { fork()? } {
|
match unsafe { fork()? } {
|
||||||
Child => {
|
Child => {
|
||||||
log!(DEBUG, redirs);
|
log!(TRACE, redirs);
|
||||||
shenv.collect_redirs(redirs);
|
shenv.collect_redirs(redirs);
|
||||||
if let Err(e) = shenv.ctx_mut().activate_rdrs() {
|
if let Err(e) = shenv.ctx_mut().activate_rdrs() {
|
||||||
eprintln!("{:?}",e);
|
eprintln!("{:?}",e);
|
||||||
@@ -441,9 +441,9 @@ fn exec_cmd(node: Node, shenv: &mut ShEnv) -> ShResult<()> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn prep_execve(argv: Vec<Token>, shenv: &mut ShEnv) -> (Vec<String>, Vec<String>) {
|
fn prep_execve(argv: Vec<Token>, shenv: &mut ShEnv) -> (Vec<String>, Vec<String>) {
|
||||||
log!(DEBUG, "Preparing execvpe args");
|
log!(TRACE, "Preparing execvpe args");
|
||||||
let argv_s = argv.as_strings(shenv);
|
let argv_s = argv.as_strings(shenv);
|
||||||
log!(DEBUG, argv_s);
|
log!(TRACE, argv_s);
|
||||||
|
|
||||||
let mut envp = vec![];
|
let mut envp = vec![];
|
||||||
let mut env_vars = shenv.vars().env().iter();
|
let mut env_vars = shenv.vars().env().iter();
|
||||||
|
|||||||
@@ -119,7 +119,7 @@ pub fn exec_case(node: Node, shenv: &mut ShEnv) -> ShResult<()> {
|
|||||||
if let NdRule::Case { pat, blocks, redirs } = rule {
|
if let NdRule::Case { pat, blocks, redirs } = rule {
|
||||||
shenv.collect_redirs(redirs);
|
shenv.collect_redirs(redirs);
|
||||||
let mut blocks_iter = blocks.into_iter();
|
let mut blocks_iter = blocks.into_iter();
|
||||||
let pat_raw = expand_token(pat, shenv)
|
let pat_raw = expand_token(pat, shenv)?
|
||||||
.iter()
|
.iter()
|
||||||
.map(|tk| tk.as_raw(shenv))
|
.map(|tk| tk.as_raw(shenv))
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
|
|||||||
@@ -51,7 +51,6 @@ pub fn expand_aliases(tokens: Vec<Token>, shenv: &mut ShEnv) -> Vec<Token> {
|
|||||||
TkRule::Ident if is_command => {
|
TkRule::Ident if is_command => {
|
||||||
is_command = false;
|
is_command = false;
|
||||||
let mut alias_tokens = expand_alias(token.clone(), shenv);
|
let mut alias_tokens = expand_alias(token.clone(), shenv);
|
||||||
log!(DEBUG, alias_tokens);
|
|
||||||
if !alias_tokens.is_empty() {
|
if !alias_tokens.is_empty() {
|
||||||
processed.append(&mut alias_tokens);
|
processed.append(&mut alias_tokens);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
171
src/expand/arithmetic.rs
Normal file
171
src/expand/arithmetic.rs
Normal file
@@ -0,0 +1,171 @@
|
|||||||
|
use crate::prelude::*;
|
||||||
|
|
||||||
|
use super::vars::expand_dquote;
|
||||||
|
|
||||||
|
#[derive(Clone,PartialEq,Debug)]
|
||||||
|
pub enum ExprToken {
|
||||||
|
Number(f64),
|
||||||
|
Operator(Op),
|
||||||
|
OpenParen,
|
||||||
|
CloseParen
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone,PartialEq,Debug)]
|
||||||
|
pub enum Op {
|
||||||
|
Add,
|
||||||
|
Sub,
|
||||||
|
Mul,
|
||||||
|
Div,
|
||||||
|
Mod,
|
||||||
|
Pow
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Op {
|
||||||
|
pub fn precedence(&self) -> u8 {
|
||||||
|
match self {
|
||||||
|
Op::Add | Op::Sub => 1,
|
||||||
|
Op::Mul | Op::Div | Op::Mod => 2,
|
||||||
|
Op::Pow => 3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn is_left_associative(&self) -> bool {
|
||||||
|
*self != Op::Pow
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn tokenize_expr(expr: &str) -> ShResult<Vec<ExprToken>> {
|
||||||
|
let mut chars = expr.chars().peekable();
|
||||||
|
let mut tokens = vec![];
|
||||||
|
|
||||||
|
while let Some(ch) = chars.next() {
|
||||||
|
match ch {
|
||||||
|
'+' => tokens.push(ExprToken::Operator(Op::Add)),
|
||||||
|
'-' => tokens.push(ExprToken::Operator(Op::Sub)),
|
||||||
|
'*' => {
|
||||||
|
if chars.peek() == Some(&'*') {
|
||||||
|
chars.next();
|
||||||
|
tokens.push(ExprToken::Operator(Op::Pow));
|
||||||
|
} else {
|
||||||
|
tokens.push(ExprToken::Operator(Op::Mul));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
'/' => tokens.push(ExprToken::Operator(Op::Div)),
|
||||||
|
'%' => tokens.push(ExprToken::Operator(Op::Mod)),
|
||||||
|
'(' => tokens.push(ExprToken::OpenParen),
|
||||||
|
')' => tokens.push(ExprToken::CloseParen),
|
||||||
|
'0'..='9' => {
|
||||||
|
let mut number = ch.to_string();
|
||||||
|
while let Some(next_ch) = chars.peek() {
|
||||||
|
if next_ch.is_ascii_digit() {
|
||||||
|
number.push(chars.next().unwrap());
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let value = number.parse::<f64>().unwrap();
|
||||||
|
tokens.push(ExprToken::Number(value));
|
||||||
|
}
|
||||||
|
' ' | '\t' => continue, // Skip whitespace
|
||||||
|
_ => return Err(ShErr::simple(ShErrKind::ParseErr, format!("Unexpected character in arithmetic expansion: {}",ch))), // Handle unexpected characters
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(tokens)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn shunting_yard(tokens: Vec<ExprToken>) -> ShResult<Vec<ExprToken>> {
|
||||||
|
let mut sorted = vec![];
|
||||||
|
let mut operators = vec![];
|
||||||
|
|
||||||
|
for token in tokens {
|
||||||
|
match token {
|
||||||
|
ExprToken::Number(_) => sorted.push(token.clone()),
|
||||||
|
ExprToken::Operator(ref op) => {
|
||||||
|
while let Some(top) = operators.last() {
|
||||||
|
if let ExprToken::Operator(top_op) = top {
|
||||||
|
if (op.is_left_associative() && op.precedence() <= top_op.precedence())
|
||||||
|
|| (!op.is_left_associative() && op.precedence() < top_op.precedence())
|
||||||
|
{
|
||||||
|
sorted.push(operators.pop().unwrap())
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
operators.push(token.clone())
|
||||||
|
}
|
||||||
|
ExprToken::OpenParen => operators.push(token.clone()),
|
||||||
|
ExprToken::CloseParen => {
|
||||||
|
while let Some(top) = operators.pop() {
|
||||||
|
if matches!(top, ExprToken::OpenParen) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
sorted.push(top);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while let Some(op) = operators.pop() {
|
||||||
|
if matches!(op, ExprToken::OpenParen | ExprToken::CloseParen) {
|
||||||
|
return Err(ShErr::simple(ShErrKind::ParseErr, "Mismatched parenthesis in arithmetic expansion"))
|
||||||
|
}
|
||||||
|
sorted.push(op);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(sorted)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn eval_rpn(tokens: Vec<ExprToken>) -> ShResult<f64> {
|
||||||
|
let mut stack = vec![];
|
||||||
|
|
||||||
|
for token in tokens {
|
||||||
|
match token {
|
||||||
|
ExprToken::Number(num) => stack.push(num),
|
||||||
|
ExprToken::Operator(op) => {
|
||||||
|
if stack.len() < 2 {
|
||||||
|
return Err(ShErr::simple(ShErrKind::ParseErr, "Not enough operands in arithmetic expansion"))
|
||||||
|
}
|
||||||
|
let rhs = stack.pop().unwrap();
|
||||||
|
let lhs = stack.pop().unwrap();
|
||||||
|
let result = match op {
|
||||||
|
Op::Add => lhs + rhs,
|
||||||
|
Op::Sub => lhs - rhs,
|
||||||
|
Op::Mul => lhs * rhs,
|
||||||
|
Op::Mod => lhs % rhs,
|
||||||
|
Op::Pow => lhs.powf(rhs),
|
||||||
|
Op::Div => {
|
||||||
|
if rhs == 0.0 {
|
||||||
|
return Err(ShErr::simple(ShErrKind::ParseErr, "Attempt to divide by zero in arithmetic expansion"))
|
||||||
|
}
|
||||||
|
lhs / rhs
|
||||||
|
}
|
||||||
|
};
|
||||||
|
stack.push(result);
|
||||||
|
}
|
||||||
|
ExprToken::OpenParen => todo!(),
|
||||||
|
ExprToken::CloseParen => todo!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(stack.pop().unwrap())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn expand_arithmetic(token: Token, shenv: &mut ShEnv) -> ShResult<Token> {
|
||||||
|
// I mean hey it works (I think)
|
||||||
|
let dummy_token = Token::new(TkRule::DQuote, token.span());
|
||||||
|
let expanded = expand_dquote(dummy_token, shenv);
|
||||||
|
token.span().borrow_mut().expanded = false;
|
||||||
|
let expanded_raw = expanded.as_raw(shenv);
|
||||||
|
let arith_raw = expanded_raw.trim_matches('`');
|
||||||
|
|
||||||
|
let expr_tokens = shunting_yard(tokenize_expr(arith_raw)?)?;
|
||||||
|
log!(DEBUG,expr_tokens);
|
||||||
|
let result = eval_rpn(expr_tokens)?.to_string();
|
||||||
|
|
||||||
|
let mut final_expansion = shenv.expand_input(&result, token.span());
|
||||||
|
|
||||||
|
Ok(final_expansion.pop().unwrap_or(token))
|
||||||
|
}
|
||||||
@@ -2,24 +2,26 @@ pub mod vars;
|
|||||||
pub mod tilde;
|
pub mod tilde;
|
||||||
pub mod alias;
|
pub mod alias;
|
||||||
pub mod cmdsub;
|
pub mod cmdsub;
|
||||||
|
pub mod arithmetic;
|
||||||
|
|
||||||
|
use arithmetic::expand_arithmetic;
|
||||||
use vars::{expand_dquote, expand_var};
|
use vars::{expand_dquote, expand_var};
|
||||||
use tilde::expand_tilde;
|
use tilde::expand_tilde;
|
||||||
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
pub fn expand_argv(argv: Vec<Token>, shenv: &mut ShEnv) -> Vec<Token> {
|
pub fn expand_argv(argv: Vec<Token>, shenv: &mut ShEnv) -> ShResult<Vec<Token>> {
|
||||||
let mut processed = vec![];
|
let mut processed = vec![];
|
||||||
for arg in argv {
|
for arg in argv {
|
||||||
log!(DEBUG, "{}",arg.as_raw(shenv));
|
log!(DEBUG, "{}",arg.as_raw(shenv));
|
||||||
log!(DEBUG, processed);
|
log!(DEBUG, processed);
|
||||||
let mut expanded = expand_token(arg, shenv);
|
let mut expanded = expand_token(arg, shenv)?;
|
||||||
processed.append(&mut expanded);
|
processed.append(&mut expanded);
|
||||||
}
|
}
|
||||||
processed
|
Ok(processed)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn expand_token(token: Token, shenv: &mut ShEnv) -> Vec<Token> {
|
pub fn expand_token(token: Token, shenv: &mut ShEnv) -> ShResult<Vec<Token>> {
|
||||||
let mut processed = vec![];
|
let mut processed = vec![];
|
||||||
match token.rule() {
|
match token.rule() {
|
||||||
TkRule::DQuote => {
|
TkRule::DQuote => {
|
||||||
@@ -34,6 +36,10 @@ pub fn expand_token(token: Token, shenv: &mut ShEnv) -> Vec<Token> {
|
|||||||
let tilde_exp = expand_tilde(token.clone(), shenv);
|
let tilde_exp = expand_tilde(token.clone(), shenv);
|
||||||
processed.push(tilde_exp);
|
processed.push(tilde_exp);
|
||||||
}
|
}
|
||||||
|
TkRule::ArithSub => {
|
||||||
|
let arith_exp = expand_arithmetic(token.clone(), shenv)?;
|
||||||
|
processed.push(arith_exp);
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
if token.rule() != TkRule::Ident {
|
if token.rule() != TkRule::Ident {
|
||||||
log!(WARN, "found this in expand_token: {:?}", token.rule());
|
log!(WARN, "found this in expand_token: {:?}", token.rule());
|
||||||
@@ -41,5 +47,5 @@ pub fn expand_token(token: Token, shenv: &mut ShEnv) -> Vec<Token> {
|
|||||||
processed.push(token.clone())
|
processed.push(token.clone())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
processed
|
Ok(processed)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,10 +58,6 @@ pub fn expand_dquote(dquote: Token, shenv: &mut ShEnv) -> Token {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log!(DEBUG, result);
|
|
||||||
|
|
||||||
log!(DEBUG, "{:?}",dquote.span());
|
|
||||||
let token = shenv.expand_input(&result, dquote.span()).pop().unwrap_or(dquote);
|
let token = shenv.expand_input(&result, dquote.span()).pop().unwrap_or(dquote);
|
||||||
log!(DEBUG, "{}",token.as_raw(shenv));
|
|
||||||
token
|
token
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -371,6 +371,7 @@ tkrule_def!(ArithSub, |input: &str| {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
' ' | '\t' | ';' | '\n' => return None,
|
||||||
_ => { /* Continue */ }
|
_ => { /* Continue */ }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -343,7 +343,6 @@ ndrule_def!(ShellCmd, shenv, |tokens: &[Token], shenv: &mut ShEnv| {
|
|||||||
});
|
});
|
||||||
|
|
||||||
ndrule_def!(Case, shenv, |mut tokens: &[Token], shenv: &mut ShEnv| {
|
ndrule_def!(Case, shenv, |mut tokens: &[Token], shenv: &mut ShEnv| {
|
||||||
log!(DEBUG, tokens);
|
|
||||||
let err = |msg: &str, span: Rc<RefCell<Span>>, shenv: &mut ShEnv | {
|
let err = |msg: &str, span: Rc<RefCell<Span>>, shenv: &mut ShEnv | {
|
||||||
ShErr::full(ShErrKind::ParseErr, msg, shenv.get_input(), span)
|
ShErr::full(ShErrKind::ParseErr, msg, shenv.get_input(), span)
|
||||||
};
|
};
|
||||||
@@ -411,7 +410,6 @@ ndrule_def!(Case, shenv, |mut tokens: &[Token], shenv: &mut ShEnv| {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
log!(DEBUG,tokens);
|
|
||||||
tokens_iter = tokens.iter().peekable();
|
tokens_iter = tokens.iter().peekable();
|
||||||
|
|
||||||
if tokens_iter.peek().is_none() {
|
if tokens_iter.peek().is_none() {
|
||||||
@@ -431,14 +429,10 @@ ndrule_def!(Case, shenv, |mut tokens: &[Token], shenv: &mut ShEnv| {
|
|||||||
let block_pat = token.clone();
|
let block_pat = token.clone();
|
||||||
let (used,lists) = get_lists(tokens, shenv);
|
let (used,lists) = get_lists(tokens, shenv);
|
||||||
let mut lists_iter = lists.iter().peekable();
|
let mut lists_iter = lists.iter().peekable();
|
||||||
log!(DEBUG, used);
|
|
||||||
log!(DEBUG, lists);
|
|
||||||
while let Some(list) = lists_iter.next() {
|
while let Some(list) = lists_iter.next() {
|
||||||
node_toks.extend(list.tokens.clone());
|
node_toks.extend(list.tokens.clone());
|
||||||
if lists_iter.peek().is_none() {
|
if lists_iter.peek().is_none() {
|
||||||
log!(DEBUG, list);
|
|
||||||
for token in list.tokens() {
|
for token in list.tokens() {
|
||||||
log!(DEBUG, "{}", token.as_raw(shenv));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(token) = list.tokens().last() {
|
if let Some(token) = list.tokens().last() {
|
||||||
@@ -482,7 +476,6 @@ ndrule_def!(Case, shenv, |mut tokens: &[Token], shenv: &mut ShEnv| {
|
|||||||
redirs.push(redir);
|
redirs.push(redir);
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
log!(DEBUG, token);
|
|
||||||
return Err(err("Expected `esac` or a case block here", node_toks.last().unwrap().span(), shenv))
|
return Err(err("Expected `esac` or a case block here", node_toks.last().unwrap().span(), shenv))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -523,7 +516,6 @@ ndrule_def!(ForLoop, shenv, |mut tokens: &[Token], shenv: &mut ShEnv| {
|
|||||||
} else { return Ok(None) }
|
} else { return Ok(None) }
|
||||||
|
|
||||||
while let Some(token) = tokens_iter.next() {
|
while let Some(token) = tokens_iter.next() {
|
||||||
log!(DEBUG, token);
|
|
||||||
node_toks.push(token.clone());
|
node_toks.push(token.clone());
|
||||||
tokens = &tokens[1..];
|
tokens = &tokens[1..];
|
||||||
match token.rule() {
|
match token.rule() {
|
||||||
@@ -656,7 +648,6 @@ ndrule_def!(ForLoop, shenv, |mut tokens: &[Token], shenv: &mut ShEnv| {
|
|||||||
});
|
});
|
||||||
|
|
||||||
ndrule_def!(IfThen, shenv, |mut tokens: &[Token], shenv: &mut ShEnv| {
|
ndrule_def!(IfThen, shenv, |mut tokens: &[Token], shenv: &mut ShEnv| {
|
||||||
log!(DEBUG,tokens);
|
|
||||||
let err = |msg: &str, span: Rc<RefCell<Span>>, shenv: &mut ShEnv | {
|
let err = |msg: &str, span: Rc<RefCell<Span>>, shenv: &mut ShEnv | {
|
||||||
ShErr::full(ShErrKind::ParseErr, msg, shenv.get_input(), span)
|
ShErr::full(ShErrKind::ParseErr, msg, shenv.get_input(), span)
|
||||||
};
|
};
|
||||||
@@ -666,7 +657,6 @@ ndrule_def!(IfThen, shenv, |mut tokens: &[Token], shenv: &mut ShEnv| {
|
|||||||
let mut redirs = vec![];
|
let mut redirs = vec![];
|
||||||
let mut else_block: Option<Vec<Node>> = None;
|
let mut else_block: Option<Vec<Node>> = None;
|
||||||
|
|
||||||
log!(DEBUG,tokens);
|
|
||||||
if let Some(token) = tokens_iter.next() {
|
if let Some(token) = tokens_iter.next() {
|
||||||
if let TkRule::If = token.rule() {
|
if let TkRule::If = token.rule() {
|
||||||
node_toks.push(token.clone());
|
node_toks.push(token.clone());
|
||||||
@@ -1151,6 +1141,7 @@ ndrule_def!(Command, shenv, |tokens: &[Token], shenv: &mut ShEnv| {
|
|||||||
TkRule::DQuote |
|
TkRule::DQuote |
|
||||||
TkRule::Assign |
|
TkRule::Assign |
|
||||||
TkRule::TildeSub |
|
TkRule::TildeSub |
|
||||||
|
TkRule::ArithSub |
|
||||||
TkRule::VarSub => {
|
TkRule::VarSub => {
|
||||||
argv.push(token.clone());
|
argv.push(token.clone());
|
||||||
}
|
}
|
||||||
@@ -1228,13 +1219,11 @@ ndrule_def!(Assignment, shenv, |tokens: &[Token], shenv: &mut ShEnv| {
|
|||||||
};
|
};
|
||||||
return Ok(Some(node))
|
return Ok(Some(node))
|
||||||
} else {
|
} else {
|
||||||
log!(DEBUG, tokens);
|
|
||||||
if let Some(token) = tokens.next() {
|
if let Some(token) = tokens.next() {
|
||||||
if token.rule() == TkRule::Sep {
|
if token.rule() == TkRule::Sep {
|
||||||
node_toks.push(token.clone());
|
node_toks.push(token.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
log!(DEBUG, node_toks);
|
|
||||||
|
|
||||||
let span = get_span(&node_toks,shenv)?;
|
let span = get_span(&node_toks,shenv)?;
|
||||||
let node = Node {
|
let node = Node {
|
||||||
|
|||||||
@@ -97,7 +97,6 @@ impl<'a> ChildProc {
|
|||||||
} else {
|
} else {
|
||||||
WtStat::Exited(pid, 0)
|
WtStat::Exited(pid, 0)
|
||||||
};
|
};
|
||||||
log!(DEBUG, command);
|
|
||||||
let mut child = Self { pgid: pid, pid, command, stat };
|
let mut child = Self { pgid: pid, pid, command, stat };
|
||||||
if let Some(pgid) = pgid {
|
if let Some(pgid) = pgid {
|
||||||
child.set_pgid(pgid).ok();
|
child.set_pgid(pgid).ok();
|
||||||
@@ -505,7 +504,6 @@ impl JobTab {
|
|||||||
self.fg.as_mut()
|
self.fg.as_mut()
|
||||||
}
|
}
|
||||||
pub fn new_fg<'a>(&mut self, job: Job) -> ShResult<Vec<WtStat>> {
|
pub fn new_fg<'a>(&mut self, job: Job) -> ShResult<Vec<WtStat>> {
|
||||||
log!(DEBUG, "New fg job: {:?}", job);
|
|
||||||
let pgid = job.pgid();
|
let pgid = job.pgid();
|
||||||
self.fg = Some(job);
|
self.fg = Some(job);
|
||||||
attach_tty(pgid)?;
|
attach_tty(pgid)?;
|
||||||
@@ -519,7 +517,6 @@ impl JobTab {
|
|||||||
}
|
}
|
||||||
take_term()?;
|
take_term()?;
|
||||||
let fg = std::mem::take(&mut self.fg);
|
let fg = std::mem::take(&mut self.fg);
|
||||||
log!(DEBUG, "Moving foreground job to background");
|
|
||||||
if let Some(mut job) = fg {
|
if let Some(mut job) = fg {
|
||||||
job.set_stats(stat);
|
job.set_stats(stat);
|
||||||
self.insert_job(job, false)?;
|
self.insert_job(job, false)?;
|
||||||
|
|||||||
@@ -33,7 +33,6 @@ impl ShEnv {
|
|||||||
}
|
}
|
||||||
pub fn source_file(&mut self, path: PathBuf) -> ShResult<()> {
|
pub fn source_file(&mut self, path: PathBuf) -> ShResult<()> {
|
||||||
if path.is_file() {
|
if path.is_file() {
|
||||||
log!(DEBUG, "sourcing {}", path.to_str().unwrap());
|
|
||||||
let mut file = std::fs::File::open(path)?;
|
let mut file = std::fs::File::open(path)?;
|
||||||
let mut buf = String::new();
|
let mut buf = String::new();
|
||||||
file.read_to_string(&mut buf)?;
|
file.read_to_string(&mut buf)?;
|
||||||
@@ -43,14 +42,12 @@ impl ShEnv {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
pub fn source_rc(&mut self) -> ShResult<()> {
|
pub fn source_rc(&mut self) -> ShResult<()> {
|
||||||
log!(DEBUG, "sourcing rc");
|
|
||||||
let path_raw = std::env::var("FERN_RC")?;
|
let path_raw = std::env::var("FERN_RC")?;
|
||||||
let path = PathBuf::from(path_raw);
|
let path = PathBuf::from(path_raw);
|
||||||
self.source_file(path)?;
|
self.source_file(path)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
pub fn expand_input(&mut self, new: &str, repl_span: Rc<RefCell<Span>>) -> Vec<Token> {
|
pub fn expand_input(&mut self, new: &str, repl_span: Rc<RefCell<Span>>) -> Vec<Token> {
|
||||||
log!(DEBUG,repl_span);
|
|
||||||
if repl_span.borrow().expanded {
|
if repl_span.borrow().expanded {
|
||||||
return vec![];
|
return vec![];
|
||||||
}
|
}
|
||||||
@@ -71,10 +68,8 @@ impl ShEnv {
|
|||||||
if let Some(input) = self.input_man.get_input_mut() {
|
if let Some(input) = self.input_man.get_input_mut() {
|
||||||
let old = &input[range.clone()];
|
let old = &input[range.clone()];
|
||||||
let delta: isize = new.len() as isize - old.len() as isize;
|
let delta: isize = new.len() as isize - old.len() as isize;
|
||||||
log!(DEBUG, input);
|
|
||||||
input.replace_range(range, new);
|
input.replace_range(range, new);
|
||||||
let expanded = input.clone();
|
let expanded = input.clone();
|
||||||
log!(DEBUG, expanded);
|
|
||||||
|
|
||||||
for span in self.input_man.spans_mut() {
|
for span in self.input_man.spans_mut() {
|
||||||
let mut span_mut = span.borrow_mut();
|
let mut span_mut = span.borrow_mut();
|
||||||
@@ -87,7 +82,6 @@ impl ShEnv {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.input_man.clamp_all();
|
self.input_man.clamp_all();
|
||||||
log!(DEBUG, new_tokens);
|
|
||||||
if new_tokens.is_empty() {
|
if new_tokens.is_empty() {
|
||||||
let empty = Token::new(
|
let empty = Token::new(
|
||||||
TkRule::Ident,
|
TkRule::Ident,
|
||||||
@@ -156,11 +150,8 @@ impl ShEnv {
|
|||||||
let stderr = ctx.masks().stderr().get_fd();
|
let stderr = ctx.masks().stderr().get_fd();
|
||||||
|
|
||||||
let saved_in = dup(stdin)?;
|
let saved_in = dup(stdin)?;
|
||||||
log!(DEBUG, saved_in);
|
|
||||||
let saved_out = dup(stdout)?;
|
let saved_out = dup(stdout)?;
|
||||||
log!(DEBUG, saved_out);
|
|
||||||
let saved_err = dup(stderr)?;
|
let saved_err = dup(stderr)?;
|
||||||
log!(DEBUG, saved_err);
|
|
||||||
|
|
||||||
let saved_io = shellenv::exec_ctx::SavedIo::save(saved_in, saved_out, saved_err);
|
let saved_io = shellenv::exec_ctx::SavedIo::save(saved_in, saved_out, saved_err);
|
||||||
*ctx.saved_io() = Some(saved_io);
|
*ctx.saved_io() = Some(saved_io);
|
||||||
|
|||||||
Reference in New Issue
Block a user