diff --git a/src/eval.rs b/src/eval.rs index edc2bd9ba6..58f1985941 100644 --- a/src/eval.rs +++ b/src/eval.rs @@ -18,9 +18,30 @@ pub enum Value { Int { val: i64, span: Span }, Float { val: f64, span: Span }, String { val: String, span: Span }, - List(Vec), - Block(BlockId), - Unknown, + List { val: Vec, span: Span }, + Block { val: BlockId, span: Span }, + Nothing { span: Span }, +} + +impl Value { + pub fn as_string(&self) -> Result { + match self { + Value::String { val, .. } => Ok(val.to_string()), + _ => Err(ShellError::Mismatch("string".into(), self.span())), + } + } + + pub fn span(&self) -> Span { + match self { + Value::Bool { span, .. } => *span, + Value::Int { span, .. } => *span, + Value::Float { span, .. } => *span, + Value::String { span, .. } => *span, + Value::List { span, .. } => *span, + Value::Block { span, .. } => *span, + Value::Nothing { span, .. } => *span, + } + } } impl PartialEq for Value { @@ -30,8 +51,8 @@ impl PartialEq for Value { (Value::Int { val: lhs, .. }, Value::Int { val: rhs, .. }) => lhs == rhs, (Value::Float { val: lhs, .. }, Value::Float { val: rhs, .. }) => lhs == rhs, (Value::String { val: lhs, .. }, Value::String { val: rhs, .. }) => lhs == rhs, - (Value::List(l1), Value::List(l2)) => l1 == l2, - (Value::Block(b1), Value::Block(b2)) => b1 == b2, + (Value::List { val: l1, .. }, Value::List { val: l2, .. }) => l1 == l2, + (Value::Block { val: b1, .. }, Value::Block { val: b2, .. }) => b1 == b2, _ => false, } } @@ -50,9 +71,9 @@ impl Display for Value { write!(f, "{}", val) } Value::String { val, .. } => write!(f, "{}", val), - Value::List(..) => write!(f, ""), - Value::Block(..) => write!(f, ""), - Value::Unknown => write!(f, ""), + Value::List { .. } => write!(f, ""), + Value::Block { .. } => write!(f, ""), + Value::Nothing { .. } => write!(f, ""), } } } @@ -81,7 +102,7 @@ impl Value { span: Span::unknown(), }), - _ => Ok(Value::Unknown), + _ => Err(ShellError::Mismatch("addition".into(), self.span())), } } } @@ -92,6 +113,7 @@ pub struct State<'a> { pub struct StackFrame { pub vars: HashMap, + pub env_vars: HashMap, pub parent: Option, } @@ -108,6 +130,7 @@ impl Stack { pub fn new() -> Stack { Stack(Rc::new(RefCell::new(StackFrame { vars: HashMap::new(), + env_vars: HashMap::new(), parent: None, }))) } @@ -130,17 +153,28 @@ impl Stack { this.vars.insert(var_id, value); } + pub fn add_env_var(&self, var: String, value: String) { + let mut this = self.0.borrow_mut(); + this.env_vars.insert(var, value); + } + pub fn enter_scope(self) -> Stack { Stack(Rc::new(RefCell::new(StackFrame { vars: HashMap::new(), + env_vars: HashMap::new(), parent: Some(self), }))) } pub fn print_stack(&self) { println!("===frame==="); + println!("vars:"); for (var, val) in &self.0.borrow().vars { - println!("{}: {:?}", var, val); + println!(" {}: {:?}", var, val); + } + println!("env vars:"); + for (var, val) in &self.0.borrow().env_vars { + println!(" {}: {:?}", var, val); } if let Some(parent) = &self.0.borrow().parent { parent.print_stack() @@ -194,7 +228,27 @@ fn eval_call(state: &State, stack: Stack, call: &Call) -> Result Result { + Value::Bool { val, span } => { if val { let block = state.parser_state.get_block(then_block); let stack = stack.enter_scope(); @@ -222,7 +276,7 @@ fn eval_call(state: &State, stack: Stack, call: &Call) -> Result Err(ShellError::Mismatch("bool".into(), Span::unknown())), @@ -250,7 +304,9 @@ fn eval_call(state: &State, stack: Stack, call: &Call) -> Result Result eval_call(state, stack, call), Expr::ExternalCall(_, _) => Err(ShellError::Unsupported(expr.span)), - Expr::Operator(_) => Ok(Value::Unknown), + Expr::Operator(_) => Ok(Value::Nothing { span: expr.span }), Expr::BinaryOp(lhs, op, rhs) => { let lhs = eval_expression(state, stack.clone(), lhs)?; let op = eval_operator(state, stack.clone(), op)?; @@ -321,7 +379,7 @@ pub fn eval_expression( match op { Operator::Plus => lhs.add(&rhs), - _ => Ok(Value::Unknown), + _ => Ok(Value::Nothing { span: expr.span }), } } @@ -331,13 +389,19 @@ pub fn eval_expression( let stack = stack.enter_scope(); eval_block(state, stack, block) } - Expr::Block(block_id) => Ok(Value::Block(*block_id)), + Expr::Block(block_id) => Ok(Value::Block { + val: *block_id, + span: expr.span, + }), Expr::List(x) => { let mut output = vec![]; for expr in x { output.push(eval_expression(state, stack.clone(), expr)?); } - Ok(Value::List(output)) + Ok(Value::List { + val: output, + span: expr.span, + }) } Expr::Table(_, _) => Err(ShellError::Unsupported(expr.span)), Expr::Keyword(_, _, expr) => eval_expression(state, stack, expr), @@ -345,13 +409,15 @@ pub fn eval_expression( val: s.clone(), span: expr.span, }), - Expr::Signature(_) => Ok(Value::Unknown), - Expr::Garbage => Ok(Value::Unknown), + Expr::Signature(_) => Ok(Value::Nothing { span: expr.span }), + Expr::Garbage => Ok(Value::Nothing { span: expr.span }), } } pub fn eval_block(state: &State, stack: Stack, block: &Block) -> Result { - let mut last = Ok(Value::Unknown); + let mut last = Ok(Value::Nothing { + span: Span { start: 0, end: 0 }, + }); for stmt in &block.stmts { if let Statement::Expression(expression) = stmt { diff --git a/src/main.rs b/src/main.rs index 86f8e44c6f..ccba80cb4e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -33,6 +33,15 @@ fn main() -> std::io::Result<()> { ); working_set.add_decl(sig.into()); + let sig = Signature::build("let-env") + .required("var_name", SyntaxShape::String, "variable name") + .required( + "initial_value", + SyntaxShape::Keyword(b"=".to_vec(), Box::new(SyntaxShape::String)), + "equals sign followed by value", + ); + working_set.add_decl(sig.into()); + let sig = Signature::build("alias") .required("var_name", SyntaxShape::Variable, "variable name") .required( @@ -179,6 +188,7 @@ fn main() -> std::io::Result<()> { continue; } else if s.trim() == "stack" { stack.print_stack(); + continue; } // println!("input: '{}'", s);