Skip to content

Commit

Permalink
Implementing -eq, -ne, ... but incomplete
Browse files Browse the repository at this point in the history
  • Loading branch information
ryuichiueda committed Sep 22, 2024
1 parent 090f1c4 commit 6eadc27
Show file tree
Hide file tree
Showing 12 changed files with 219 additions and 203 deletions.
6 changes: 3 additions & 3 deletions src/elements/command/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
use crate::{error_message, ShellCore, Feeder};
use super::{Command, Redirect};
use crate::elements::command;
use crate::elements::expr::conditional::{ConditionalExpr, Elem};
use crate::elements::expr::conditional::{ConditionalExpr, CondElem};

#[derive(Debug, Clone)]
pub struct TestCommand {
Expand All @@ -17,8 +17,8 @@ pub struct TestCommand {
impl Command for TestCommand {
fn run(&mut self, core: &mut ShellCore, _: bool) {
match self.cond.clone().unwrap().eval(core) {
Ok(Elem::Ans(true)) => core.data.set_param("?", "0"),
Ok(Elem::Ans(false)) => core.data.set_param("?", "1"),
Ok(CondElem::Ans(true)) => core.data.set_param("?", "0"),
Ok(CondElem::Ans(false)) => core.data.set_param("?", "1"),
Err(err_msg) => {
error_message::print(&err_msg, core, true);
core.data.set_param("?", "2");
Expand Down
36 changes: 18 additions & 18 deletions src/elements/expr/arithmetic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,32 @@
//SPDX-License-Identifier: BSD-3-Clause

mod calculator;
mod elem;
pub mod elem;
mod parser;
mod rev_polish;
mod trenary;
mod word;
pub mod word;
mod int;
mod float;

use crate::{error_message, ShellCore};
use self::calculator::calculate;
use self::elem::Elem;
use self::elem::ArithElem;
use crate::elements::word::Word;

#[derive(Debug, Clone)]
pub struct ArithmeticExpr {
pub text: String,
elements: Vec<Elem>,
elements: Vec<ArithElem>,
output_base: String,
hide_base: bool,
}

impl ArithmeticExpr {
pub fn eval(&mut self, core: &mut ShellCore) -> Option<String> {
match self.eval_elems(core, true) {
Ok(Elem::Integer(n)) => self.ans_to_string(n),
Ok(Elem::Float(f)) => Some(f.to_string()),
Ok(ArithElem::Integer(n)) => self.ans_to_string(n),
Ok(ArithElem::Float(f)) => Some(f.to_string()),
Err(msg) => {
eprintln!("sush: {}: {}", &self.text, msg);
None
Expand All @@ -36,7 +36,7 @@ impl ArithmeticExpr {
}
}

pub fn eval_elems(&mut self, core: &mut ShellCore, permit_empty: bool) -> Result<Elem, String> {
pub fn eval_elems(&mut self, core: &mut ShellCore, permit_empty: bool) -> Result<ArithElem, String> {
if self.elements.len() == 0 && ! permit_empty {
return Err("operand expexted (error token: \")\")".to_string());
}
Expand Down Expand Up @@ -105,7 +105,7 @@ impl ArithmeticExpr {
std::str::from_utf8(&ascii).unwrap().to_string()
}

fn eval_in_cond(&mut self, core: &mut ShellCore) -> Result<Elem, String> {
fn eval_in_cond(&mut self, core: &mut ShellCore) -> Result<ArithElem, String> {
let es = match self.decompose_increments() {
Ok(data) => data,
Err(err_msg) => return Err(err_msg),
Expand All @@ -117,7 +117,7 @@ impl ArithmeticExpr {
}
}

fn preinc_to_unarys(&mut self, ans: &mut Vec<Elem>, pos: usize, inc: i64) -> i64 {
fn preinc_to_unarys(&mut self, ans: &mut Vec<ArithElem>, pos: usize, inc: i64) -> i64 {
let pm = match inc {
1 => "+",
-1 => "-",
Expand All @@ -126,31 +126,31 @@ impl ArithmeticExpr {

match (&ans.last(), &self.elements.iter().nth(pos+1)) {
(_, None)
| (_, Some(&Elem::Word(_, _))) => return inc,
(Some(&Elem::Integer(_)), _)
| (Some(&Elem::Float(_)), _) => ans.push(Elem::BinaryOp(pm.clone())),
_ => ans.push(Elem::UnaryOp(pm.clone())),
| (_, Some(&ArithElem::Word(_, _))) => return inc,
(Some(&ArithElem::Integer(_)), _)
| (Some(&ArithElem::Float(_)), _) => ans.push(ArithElem::BinaryOp(pm.clone())),
_ => ans.push(ArithElem::UnaryOp(pm.clone())),
}
ans.push(Elem::UnaryOp(pm));
ans.push(ArithElem::UnaryOp(pm));
0
}

fn decompose_increments(&mut self) -> Result<Vec<Elem>, String> {
fn decompose_increments(&mut self) -> Result<Vec<ArithElem>, String> {
let mut ans = vec![];
let mut pre_increment = 0;

let len = self.elements.len();
for i in 0..len {
let e = self.elements[i].clone();
pre_increment = match e {
Elem::Word(_, _) => {
ArithElem::Word(_, _) => {
if pre_increment != 0 {
ans.push(Elem::Increment(pre_increment));
ans.push(ArithElem::Increment(pre_increment));
}
ans.push(e);
0
},
Elem::Increment(n) => self.preinc_to_unarys(&mut ans, i, n),
ArithElem::Increment(n) => self.preinc_to_unarys(&mut ans, i, n),
_ => {
ans.push(self.elements[i].clone());
0
Expand Down
54 changes: 27 additions & 27 deletions src/elements/expr/arithmetic/calculator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,27 @@
//SPDX-License-Identifier: BSD-3-Clause

use crate::{error_message, ShellCore};
use super::elem::Elem;
use super::elem::ArithElem;
use super::{elem, float, int, rev_polish, trenary, word};

pub fn pop_operand(stack: &mut Vec<Elem>, core: &mut ShellCore) -> Result<Elem, String> {
pub fn pop_operand(stack: &mut Vec<ArithElem>, core: &mut ShellCore) -> Result<ArithElem, String> {
match stack.pop() {
Some(Elem::Word(w, inc)) => word::to_operand(&w, 0, inc, core),
Some(Elem::InParen(mut a)) => a.eval_elems(core, false),
Some(ArithElem::Word(w, inc)) => word::to_operand(&w, 0, inc, core),
Some(ArithElem::InParen(mut a)) => a.eval_elems(core, false),
Some(elem) => Ok(elem),
None => Err("no operand".to_string()),
}
}

fn bin_operation(op: &str, stack: &mut Vec<Elem>, core: &mut ShellCore) -> Result<(), String> {
fn bin_operation(op: &str, stack: &mut Vec<ArithElem>, core: &mut ShellCore) -> Result<(), String> {
match op {
"=" | "*=" | "/=" | "%=" | "+=" | "-=" | "<<=" | ">>=" | "&=" | "^=" | "|="
=> word::substitution(op, stack, core),
_ => bin_calc_operation(op, stack, core),
}
}

fn bin_calc_operation(op: &str, stack: &mut Vec<Elem>, core: &mut ShellCore) -> Result<(), String> {
fn bin_calc_operation(op: &str, stack: &mut Vec<ArithElem>, core: &mut ShellCore) -> Result<(), String> {
let right = match pop_operand(stack, core) {
Ok(v) => v,
Err(e) => return Err(e),
Expand All @@ -39,30 +39,30 @@ fn bin_calc_operation(op: &str, stack: &mut Vec<Elem>, core: &mut ShellCore) ->
}

return match (left, right) {
(Elem::Float(fl), Elem::Float(fr)) => float::bin_calc(op, fl, fr, stack),
(Elem::Float(fl), Elem::Integer(nr)) => float::bin_calc(op, fl, nr as f64, stack),
(Elem::Integer(nl), Elem::Float(fr)) => float::bin_calc(op, nl as f64, fr, stack),
(Elem::Integer(nl), Elem::Integer(nr)) => int::bin_calc(op, nl, nr, stack),
(ArithElem::Float(fl), ArithElem::Float(fr)) => float::bin_calc(op, fl, fr, stack),
(ArithElem::Float(fl), ArithElem::Integer(nr)) => float::bin_calc(op, fl, nr as f64, stack),
(ArithElem::Integer(nl), ArithElem::Float(fr)) => float::bin_calc(op, nl as f64, fr, stack),
(ArithElem::Integer(nl), ArithElem::Integer(nr)) => int::bin_calc(op, nl, nr, stack),
_ => error_message::internal("invalid operand"),
};
}

fn unary_operation(op: &str, stack: &mut Vec<Elem>, core: &mut ShellCore) -> Result<(), String> {
fn unary_operation(op: &str, stack: &mut Vec<ArithElem>, core: &mut ShellCore) -> Result<(), String> {
let operand = match pop_operand(stack, core) {
Ok(v) => v,
Err(e) => return Err(e),
};

match operand {
Elem::Float(num) => float::unary_calc(op, num, stack),
Elem::Integer(num) => int::unary_calc(op, num ,stack),
ArithElem::Float(num) => float::unary_calc(op, num, stack),
ArithElem::Integer(num) => int::unary_calc(op, num ,stack),
_ => error_message::internal("unknown operand"),
}
}

pub fn calculate(elements: &Vec<Elem>, core: &mut ShellCore) -> Result<Elem, String> {
pub fn calculate(elements: &Vec<ArithElem>, core: &mut ShellCore) -> Result<ArithElem, String> {
if elements.len() == 0 {
return Ok(Elem::Integer(0));
return Ok(ArithElem::Integer(0));
}

let rev_pol = match rev_polish::rearrange(elements) {
Expand All @@ -74,7 +74,7 @@ pub fn calculate(elements: &Vec<Elem>, core: &mut ShellCore) -> Result<Elem, Str
let mut skip_until = String::new();

for e in rev_pol {
if let Elem::BinaryOp(ref op) = e { //for short-circuit evaluation
if let ArithElem::BinaryOp(ref op) = e { //for short-circuit evaluation
if op == &skip_until {
skip_until = "".to_string();
continue;
Expand All @@ -89,15 +89,15 @@ pub fn calculate(elements: &Vec<Elem>, core: &mut ShellCore) -> Result<Elem, Str
*/

let result = match e {
Elem::Integer(_) | Elem::Float(_) | Elem::Word(_, _) | Elem::InParen(_) => {
ArithElem::Integer(_) | ArithElem::Float(_) | ArithElem::Word(_, _) | ArithElem::InParen(_) => {
stack.push(e.clone());
Ok(())
},
Elem::BinaryOp(ref op) => bin_operation(&op, &mut stack, core),
Elem::UnaryOp(ref op) => unary_operation(&op, &mut stack, core),
Elem::Increment(n) => inc(n, &mut stack, core),
Elem::Ternary(left, right) => trenary::operation(&left, &right, &mut stack, core),
Elem::Delimiter(d) => match check_skip(&d, &mut stack, core) {
ArithElem::BinaryOp(ref op) => bin_operation(&op, &mut stack, core),
ArithElem::UnaryOp(ref op) => unary_operation(&op, &mut stack, core),
ArithElem::Increment(n) => inc(n, &mut stack, core),
ArithElem::Ternary(left, right) => trenary::operation(&left, &right, &mut stack, core),
ArithElem::Delimiter(d) => match check_skip(&d, &mut stack, core) {
Ok(s) => {skip_until = s; Ok(())},
Err(e) => Err(e),
},
Expand All @@ -114,15 +114,15 @@ pub fn calculate(elements: &Vec<Elem>, core: &mut ShellCore) -> Result<Elem, Str
pop_operand(&mut stack, core)
}

fn check_skip(op: &str, stack: &mut Vec<Elem>, core: &mut ShellCore) -> Result<String, String> {
fn check_skip(op: &str, stack: &mut Vec<ArithElem>, core: &mut ShellCore) -> Result<String, String> {
let last = pop_operand(stack, core);
let last_result = match &last {
Err(e) => return Err(e.to_string()),
Ok(Elem::Integer(0)) => 0,
Ok(ArithElem::Integer(0)) => 0,
Ok(_) => 1,
};

stack.push(Elem::Integer(last_result));
stack.push(ArithElem::Integer(last_result));

if last_result == 1 && op == "||" {
return Ok("||".to_string());
Expand All @@ -134,9 +134,9 @@ fn check_skip(op: &str, stack: &mut Vec<Elem>, core: &mut ShellCore) -> Result<S
Ok("".to_string())
}

fn inc(inc: i64, stack: &mut Vec<Elem>, core: &mut ShellCore) -> Result<(), String> {
fn inc(inc: i64, stack: &mut Vec<ArithElem>, core: &mut ShellCore) -> Result<(), String> {
match stack.pop() {
Some(Elem::Word(w, inc_post)) => {
Some(ArithElem::Word(w, inc_post)) => {
match word::to_operand(&w, inc, inc_post, core) {
Ok(op) => {
stack.push(op);
Expand Down
30 changes: 15 additions & 15 deletions src/elements/expr/arithmetic/elem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use super::ArithmeticExpr;
use super::Word;

#[derive(Debug, Clone)]
pub enum Elem {
pub enum ArithElem {
UnaryOp(String),
BinaryOp(String),
Integer(i64),
Expand All @@ -17,16 +17,16 @@ pub enum Elem {
Delimiter(String), //delimiter dividing left and right of &&, ||, and ','
}

pub fn op_order(op: &Elem) -> u8 {
pub fn op_order(op: &ArithElem) -> u8 {
match op {
Elem::Increment(_) => 20,
Elem::UnaryOp(s) => {
ArithElem::Increment(_) => 20,
ArithElem::UnaryOp(s) => {
match s.as_str() {
"-" | "+" => 19,
_ => 18,
}
},
Elem::BinaryOp(s) => {
ArithElem::BinaryOp(s) => {
match s.as_str() {
"**" => 17,
"*" | "/" | "%" => 16,
Expand All @@ -43,27 +43,27 @@ pub fn op_order(op: &Elem) -> u8 {
_ => 2, //substitution
}
},
Elem::Ternary(_, _) => 3,
ArithElem::Ternary(_, _) => 3,
_ => 1,
}
}

pub fn to_string(op: &Elem) -> String {
pub fn to_string(op: &ArithElem) -> String {
match op {
Elem::InParen(a) => a.text.to_string(),
Elem::Integer(n) => n.to_string(),
Elem::Float(f) => f.to_string(),
Elem::Word(w, inc) => {
ArithElem::InParen(a) => a.text.to_string(),
ArithElem::Integer(n) => n.to_string(),
ArithElem::Float(f) => f.to_string(),
ArithElem::Word(w, inc) => {
match inc {
1 => w.text.clone() + "++",
-1 => w.text.clone() + "--",
_ => w.text.clone(),
}
},
Elem::UnaryOp(s) => s.clone(),
Elem::BinaryOp(s) => s.clone(),
Elem::Increment(1) => "++".to_string(),
Elem::Increment(-1) => "--".to_string(),
ArithElem::UnaryOp(s) => s.clone(),
ArithElem::BinaryOp(s) => s.clone(),
ArithElem::Increment(1) => "++".to_string(),
ArithElem::Increment(-1) => "--".to_string(),
_ => "".to_string(),
}
}
26 changes: 13 additions & 13 deletions src/elements/expr/arithmetic/float.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,25 @@
//SPDX-License-Identifier: BSD-3-Clause

use crate::{error_message, ShellCore};
use super::{Elem, word};
use super::{ArithElem, word};

pub fn unary_calc(op: &str, num: f64, stack: &mut Vec<Elem>) -> Result<(), String> {
pub fn unary_calc(op: &str, num: f64, stack: &mut Vec<ArithElem>) -> Result<(), String> {
match op {
"+" => stack.push( Elem::Float(num) ),
"-" => stack.push( Elem::Float(-num) ),
"+" => stack.push( ArithElem::Float(num) ),
"-" => stack.push( ArithElem::Float(-num) ),
_ => return Err("not supported operator for float number".to_string()),
}
Ok(())
}

pub fn bin_calc(op: &str, left: f64, right: f64,
stack: &mut Vec<Elem>) -> Result<(), String> {
let bool_to_01 = |b| { if b { Elem::Integer(1) } else { Elem::Integer(0) } };
stack: &mut Vec<ArithElem>) -> Result<(), String> {
let bool_to_01 = |b| { if b { ArithElem::Integer(1) } else { ArithElem::Integer(0) } };

match op {
"+" => stack.push(Elem::Float(left + right)),
"-" => stack.push(Elem::Float(left - right)),
"*" => stack.push(Elem::Float(left * right)),
"+" => stack.push(ArithElem::Float(left + right)),
"-" => stack.push(ArithElem::Float(left - right)),
"*" => stack.push(ArithElem::Float(left * right)),
"<=" => stack.push(bool_to_01( left <= right )),
">=" => stack.push(bool_to_01( left >= right )),
"<" => stack.push(bool_to_01( left < right )),
Expand All @@ -31,12 +31,12 @@ pub fn bin_calc(op: &str, left: f64, right: f64,
if right == 0.0 {
return Err("divided by 0".to_string());
}
stack.push(Elem::Float(left / right));
stack.push(ArithElem::Float(left / right));
},
"**" => {
if right >= 0.0 {
let r = right.try_into().unwrap();
stack.push(Elem::Float(left.powf(r)));
stack.push(ArithElem::Float(left.powf(r)));
}else{
return Err( error_message::exponent(&right.to_string()) );
}
Expand All @@ -48,7 +48,7 @@ pub fn bin_calc(op: &str, left: f64, right: f64,
}

pub fn substitute(op: &str, name: &String, cur: f64, right: f64, core: &mut ShellCore)
-> Result<Elem, String> {
-> Result<ArithElem, String> {
let new_value = match op {
"+=" => cur + right,
"-=" => cur - right,
Expand All @@ -63,7 +63,7 @@ pub fn substitute(op: &str, name: &String, cur: f64, right: f64, core: &mut Shel
};

core.data.set_param(&name, &new_value.to_string());
Ok(Elem::Float(new_value))
Ok(ArithElem::Float(new_value))
}

pub fn parse(s: &str) -> Option<f64> {
Expand Down
Loading

0 comments on commit 6eadc27

Please sign in to comment.