latest pushes
This commit is contained in:
Binary file not shown.
132
src/bellos.rs
132
src/bellos.rs
@ -447,7 +447,8 @@ impl Interpreter {
|
|||||||
match *node {
|
match *node {
|
||||||
ASTNode::Command { name, args } => self.execute_command(name, args),
|
ASTNode::Command { name, args } => self.execute_command(name, args),
|
||||||
ASTNode::Assignment { name, value } => {
|
ASTNode::Assignment { name, value } => {
|
||||||
self.variables.insert(name, self.expand_variables(&value));
|
let expanded_value = self.expand_variables(&value);
|
||||||
|
self.variables.insert(name, expanded_value);
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
ASTNode::Pipeline(commands) => self.execute_pipeline(commands),
|
ASTNode::Pipeline(commands) => self.execute_pipeline(commands),
|
||||||
@ -467,10 +468,10 @@ impl Interpreter {
|
|||||||
then_block,
|
then_block,
|
||||||
else_block,
|
else_block,
|
||||||
} => {
|
} => {
|
||||||
if self.interpret_node(Box::new(*condition))? == Some(0) {
|
if self.interpret_node(condition)? == Some(0) {
|
||||||
self.interpret_node(Box::new(*then_block))
|
self.interpret_node(then_block)
|
||||||
} else if let Some(else_block) = else_block {
|
} else if let Some(else_block) = else_block {
|
||||||
self.interpret_node(Box::new(*else_block))
|
self.interpret_node(else_block)
|
||||||
} else {
|
} else {
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
@ -507,9 +508,11 @@ impl Interpreter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn execute_command(&mut self, name: String, args: Vec<String>) -> Result<Option<i32>, String> {
|
fn execute_command(&mut self, name: String, args: Vec<String>) -> Result<Option<i32>, String> {
|
||||||
|
let expanded_name = self.expand_variables(&name);
|
||||||
let expanded_args: Vec<String> =
|
let expanded_args: Vec<String> =
|
||||||
args.iter().map(|arg| self.expand_variables(arg)).collect();
|
args.iter().map(|arg| self.expand_variables(arg)).collect();
|
||||||
match name.as_str() {
|
|
||||||
|
match expanded_name.as_str() {
|
||||||
"echo" => {
|
"echo" => {
|
||||||
println!("{}", expanded_args.join(" "));
|
println!("{}", expanded_args.join(" "));
|
||||||
Ok(Some(0))
|
Ok(Some(0))
|
||||||
@ -544,10 +547,9 @@ impl Interpreter {
|
|||||||
Ok(Some(0))
|
Ok(Some(0))
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
if let Some(func) = self.functions.get(&name) {
|
if let Some(func) = self.functions.get(&expanded_name) {
|
||||||
return self.interpret_node(Box::new(func.clone()));
|
return self.interpret_node(Box::new(func.clone()));
|
||||||
}
|
}
|
||||||
let expanded_name = self.expand_variables(&name);
|
|
||||||
match Command::new(&expanded_name).args(&expanded_args).spawn() {
|
match Command::new(&expanded_name).args(&expanded_args).spawn() {
|
||||||
Ok(mut child) => {
|
Ok(mut child) => {
|
||||||
let status = child.wait().map_err(|e| e.to_string())?;
|
let status = child.wait().map_err(|e| e.to_string())?;
|
||||||
@ -559,6 +561,85 @@ impl Interpreter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn evaluate_arithmetic(&self, expr: &str) -> i32 {
|
||||||
|
let tokens: Vec<&str> = expr.split_whitespace().collect();
|
||||||
|
if tokens.len() != 3 {
|
||||||
|
return 0; // Invalid expression
|
||||||
|
}
|
||||||
|
|
||||||
|
let a = self.get_var_value(tokens[0]);
|
||||||
|
let b = self.get_var_value(tokens[2]);
|
||||||
|
|
||||||
|
match tokens[1] {
|
||||||
|
"+" => a + b,
|
||||||
|
"-" => a - b,
|
||||||
|
"*" => a * b,
|
||||||
|
"/" => {
|
||||||
|
if b != 0 {
|
||||||
|
a / b
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"%" => {
|
||||||
|
if b != 0 {
|
||||||
|
a % b
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => 0, // Unsupported operation
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_var_value(&self, var: &str) -> i32 {
|
||||||
|
if let Some(value) = self.variables.get(var) {
|
||||||
|
value.parse().unwrap_or(0)
|
||||||
|
} else if let Ok(value) = env::var(var) {
|
||||||
|
value.parse().unwrap_or(0)
|
||||||
|
} else {
|
||||||
|
var.parse().unwrap_or(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn evaluate_condition(&mut self, condition: &ASTNode) -> Result<bool, String> {
|
||||||
|
match condition {
|
||||||
|
ASTNode::Command { name, args } => {
|
||||||
|
let expanded_args: Vec<String> =
|
||||||
|
args.iter().map(|arg| self.expand_variables(arg)).collect();
|
||||||
|
match name.as_str() {
|
||||||
|
"[" | "test" => {
|
||||||
|
if expanded_args.len() < 3 || expanded_args.last() != Some(&"]".to_string())
|
||||||
|
{
|
||||||
|
return Err("Invalid test condition".to_string());
|
||||||
|
}
|
||||||
|
match expanded_args[1].as_str() {
|
||||||
|
"-eq" => Ok(expanded_args[0] == expanded_args[2]),
|
||||||
|
"-ne" => Ok(expanded_args[0] != expanded_args[2]),
|
||||||
|
"-lt" => Ok(expanded_args[0].parse::<i32>().unwrap_or(0)
|
||||||
|
< expanded_args[2].parse::<i32>().unwrap_or(0)),
|
||||||
|
"-le" => Ok(expanded_args[0].parse::<i32>().unwrap_or(0)
|
||||||
|
<= expanded_args[2].parse::<i32>().unwrap_or(0)),
|
||||||
|
"-gt" => Ok(expanded_args[0].parse::<i32>().unwrap_or(0)
|
||||||
|
> expanded_args[2].parse::<i32>().unwrap_or(0)),
|
||||||
|
"-ge" => Ok(expanded_args[0].parse::<i32>().unwrap_or(0)
|
||||||
|
>= expanded_args[2].parse::<i32>().unwrap_or(0)),
|
||||||
|
"-z" => Ok(expanded_args[0].is_empty()),
|
||||||
|
"-n" => Ok(!expanded_args[0].is_empty()),
|
||||||
|
"=" => Ok(expanded_args[0] == expanded_args[2]),
|
||||||
|
"!=" => Ok(expanded_args[0] != expanded_args[2]),
|
||||||
|
_ => Err(format!("Unsupported test condition: {}", expanded_args[1])),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
let result = self.execute_command(name.clone(), expanded_args)?;
|
||||||
|
Ok(result == Some(0))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => Err("Invalid condition node".to_string()),
|
||||||
|
}
|
||||||
|
}
|
||||||
fn execute_pipeline(&mut self, commands: Vec<ASTNode>) -> Result<Option<i32>, String> {
|
fn execute_pipeline(&mut self, commands: Vec<ASTNode>) -> Result<Option<i32>, String> {
|
||||||
let mut previous_stdout = None;
|
let mut previous_stdout = None;
|
||||||
let mut processes = Vec::new();
|
let mut processes = Vec::new();
|
||||||
@ -611,7 +692,6 @@ impl Interpreter {
|
|||||||
let result = self.capture_output(Box::new(node))?;
|
let result = self.capture_output(Box::new(node))?;
|
||||||
file.write_all(result.as_bytes())
|
file.write_all(result.as_bytes())
|
||||||
.map_err(|e| e.to_string())?;
|
.map_err(|e| e.to_string())?;
|
||||||
print!("{}", result);
|
|
||||||
Ok(Some(0))
|
Ok(Some(0))
|
||||||
}
|
}
|
||||||
"<" => {
|
"<" => {
|
||||||
@ -696,42 +776,6 @@ impl Interpreter {
|
|||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
fn evaluate_arithmetic(&self, expr: &str) -> i32 {
|
|
||||||
// This is a simple implementation. For a more robust solution,
|
|
||||||
// consider using a proper expression parser and evaluator.
|
|
||||||
let tokens: Vec<&str> = expr.split_whitespace().collect();
|
|
||||||
if tokens.len() != 3 {
|
|
||||||
return 0; // Invalid expression
|
|
||||||
}
|
|
||||||
|
|
||||||
let a = self.get_var_value(tokens[0]);
|
|
||||||
let b = self.get_var_value(tokens[2]);
|
|
||||||
|
|
||||||
match tokens[1] {
|
|
||||||
"+" => a + b,
|
|
||||||
"-" => a - b,
|
|
||||||
"*" => a * b,
|
|
||||||
"/" => {
|
|
||||||
if b != 0 {
|
|
||||||
a / b
|
|
||||||
} else {
|
|
||||||
0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => 0, // Unsupported operation
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_var_value(&self, var: &str) -> i32 {
|
|
||||||
if let Some(value) = self.variables.get(var) {
|
|
||||||
value.parse().unwrap_or(0)
|
|
||||||
} else if let Ok(value) = env::var(var) {
|
|
||||||
value.parse().unwrap_or(0)
|
|
||||||
} else {
|
|
||||||
var.parse().unwrap_or(0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn expand_wildcards(&self, pattern: &str) -> Vec<String> {
|
fn expand_wildcards(&self, pattern: &str) -> Vec<String> {
|
||||||
match glob(pattern) {
|
match glob(pattern) {
|
||||||
Ok(paths) => paths
|
Ok(paths) => paths
|
||||||
|
Reference in New Issue
Block a user