From 3eefa6dec87a26d3142a1f3b83b239121b7b04a5 Mon Sep 17 00:00:00 2001 From: JT Date: Fri, 23 Jul 2021 17:14:49 +1200 Subject: [PATCH] start expanding eval --- src/eval.rs | 148 ++++++++++++++++++++++++++------------------ src/flatten.rs | 10 +-- src/lib.rs | 2 +- src/main.rs | 41 ++++++++---- src/parser.rs | 5 +- src/parser_state.rs | 39 ++++++++---- 6 files changed, 147 insertions(+), 98 deletions(-) diff --git a/src/eval.rs b/src/eval.rs index 3cabc4f75..6531c3b75 100644 --- a/src/eval.rs +++ b/src/eval.rs @@ -1,19 +1,19 @@ -use crate::{parser::Operator, Block, Expr, Expression, Span, Statement}; +use std::collections::HashMap; + +use crate::{parser::Operator, Block, Call, Expr, Expression, ParserState, Span, Statement, VarId}; #[derive(Debug)] pub enum ShellError { Mismatch(String, Span), Unsupported(Span), + InternalError(String), } -pub struct Engine; - -#[derive(Debug)] +#[derive(Debug, Clone)] pub enum Value { Int { val: i64, span: Span }, Unknown, } - impl Value { pub fn add(&self, rhs: &Value) -> Result { match (self, rhs) { @@ -26,71 +26,99 @@ impl Value { } } -impl Default for Engine { - fn default() -> Self { - Self::new() +pub struct State<'a> { + pub parser_state: &'a ParserState, +} + +pub struct Stack { + pub vars: HashMap, +} + +impl Stack { + pub fn get_var(&self, var_id: VarId) -> Result { + match self.vars.get(&var_id) { + Some(v) => Ok(v.clone()), + _ => Err(ShellError::InternalError("variable not found".into())), + } } } -impl Engine { - pub fn new() -> Self { - Self +pub fn eval_operator( + state: &State, + stack: &mut Stack, + op: &Expression, +) -> Result { + match op { + Expression { + expr: Expr::Operator(operator), + .. + } => Ok(operator.clone()), + Expression { span, .. } => Err(ShellError::Mismatch("operator".to_string(), *span)), } +} - pub fn eval_operator(&self, op: &Expression) -> Result { - match op { - Expression { - expr: Expr::Operator(operator), - .. - } => Ok(operator.clone()), - Expression { span, .. } => Err(ShellError::Mismatch("operator".to_string(), *span)), - } +fn eval_call(state: &State, stack: &mut Stack, call: &Call) -> Result { + let decl = state.parser_state.get_decl(call.decl_id); + + if let Some(block_id) = decl.body { + let block = state.parser_state.get_block(block_id); + eval_block(state, stack, block) + } else { + Ok(Value::Unknown) } +} - pub fn eval_expression(&self, expr: &Expression) -> Result { - match expr.expr { - Expr::Int(i) => Ok(Value::Int { - val: i, - span: expr.span, - }), - Expr::Var(_) => Err(ShellError::Unsupported(expr.span)), - Expr::Call(_) => Err(ShellError::Unsupported(expr.span)), - Expr::ExternalCall(_, _) => Err(ShellError::Unsupported(expr.span)), - Expr::Operator(_) => Err(ShellError::Unsupported(expr.span)), - Expr::BinaryOp(_, _, _) => Err(ShellError::Unsupported(expr.span)), - Expr::Subexpression(_) => Err(ShellError::Unsupported(expr.span)), - Expr::Block(_) => Err(ShellError::Unsupported(expr.span)), - Expr::List(_) => Err(ShellError::Unsupported(expr.span)), - Expr::Table(_, _) => Err(ShellError::Unsupported(expr.span)), - Expr::Literal(_) => Err(ShellError::Unsupported(expr.span)), - Expr::String(_) => Err(ShellError::Unsupported(expr.span)), - Expr::Signature(_) => Err(ShellError::Unsupported(expr.span)), - Expr::Garbage => Err(ShellError::Unsupported(expr.span)), - } - } +pub fn eval_expression( + state: &State, + stack: &mut Stack, + expr: &Expression, +) -> Result { + match &expr.expr { + Expr::Int(i) => Ok(Value::Int { + val: *i, + span: expr.span, + }), + Expr::Var(var_id) => stack.get_var(*var_id), + Expr::Call(call) => eval_call(state, stack, call), + Expr::ExternalCall(_, _) => Err(ShellError::Unsupported(expr.span)), + Expr::Operator(_) => Ok(Value::Unknown), + Expr::BinaryOp(lhs, op, rhs) => { + let lhs = eval_expression(state, stack, &lhs)?; + let op = eval_operator(state, stack, &op)?; + let rhs = eval_expression(state, stack, &rhs)?; - pub fn eval_block(&self, block: &Block) -> Result { - let mut last = Ok(Value::Unknown); - - for stmt in &block.stmts { - match stmt { - Statement::Expression(expression) => match &expression.expr { - Expr::BinaryOp(lhs, op, rhs) => { - let lhs = self.eval_expression(&lhs)?; - let op = self.eval_operator(&op)?; - let rhs = self.eval_expression(&rhs)?; - - match op { - Operator::Plus => last = lhs.add(&rhs), - _ => {} - } - } - _ => {} - }, - _ => {} + match op { + Operator::Plus => lhs.add(&rhs), + _ => Ok(Value::Unknown), } } - last + Expr::Subexpression(block_id) => { + let block = state.parser_state.get_block(*block_id); + + eval_block(state, stack, block) + } + Expr::Block(_) => Err(ShellError::Unsupported(expr.span)), + Expr::List(_) => Err(ShellError::Unsupported(expr.span)), + Expr::Table(_, _) => Err(ShellError::Unsupported(expr.span)), + Expr::Literal(_) => Err(ShellError::Unsupported(expr.span)), + Expr::String(_) => Err(ShellError::Unsupported(expr.span)), + Expr::Signature(_) => Err(ShellError::Unsupported(expr.span)), + Expr::Garbage => Err(ShellError::Unsupported(expr.span)), } } + +pub fn eval_block(state: &State, stack: &mut Stack, block: &Block) -> Result { + let mut last = Ok(Value::Unknown); + + for stmt in &block.stmts { + match stmt { + Statement::Expression(expression) => { + last = Ok(eval_expression(state, stack, expression)?); + } + _ => {} + } + } + + last +} diff --git a/src/flatten.rs b/src/flatten.rs index 4a55a8dac..5f228132b 100644 --- a/src/flatten.rs +++ b/src/flatten.rs @@ -38,10 +38,7 @@ impl<'a> ParserWorkingSet<'a> { output.extend(self.flatten_expression(&rhs)); output } - Expr::Block(block_id) => self.flatten_block( - self.get_block(*block_id) - .expect("internal error: missing block"), - ), + Expr::Block(block_id) => self.flatten_block(self.get_block(*block_id)), Expr::Call(call) => { let mut output = vec![]; output.push((call.head, FlatShape::InternalCall)); @@ -78,10 +75,7 @@ impl<'a> ParserWorkingSet<'a> { Expr::String(_) => { vec![(expr.span, FlatShape::String)] } - Expr::Subexpression(block_id) => self.flatten_block( - self.get_block(*block_id) - .expect("internal error: missing block"), - ), + Expr::Subexpression(block_id) => self.flatten_block(self.get_block(*block_id)), Expr::Table(headers, cells) => { let mut output = vec![]; for e in headers { diff --git a/src/lib.rs b/src/lib.rs index 313efe2c1..dd6fa086e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -13,7 +13,7 @@ mod syntax_highlight; mod tests; pub use declaration::Declaration; -pub use eval::Engine; +pub use eval::{eval_block, eval_expression, Stack, State}; pub use lex::{lex, Token, TokenContents}; pub use lite_parse::{lite_parse, LiteBlock, LiteCommand, LiteStatement}; pub use parse_error::ParseError; diff --git a/src/main.rs b/src/main.rs index b227107de..5f2b22661 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,8 @@ -use std::{cell::RefCell, rc::Rc}; +use std::{cell::RefCell, collections::HashMap, rc::Rc}; -use engine_q::{NuHighlighter, ParserState, ParserWorkingSet, Signature, SyntaxShape}; +use engine_q::{ + eval_block, NuHighlighter, ParserState, ParserWorkingSet, Signature, Stack, State, SyntaxShape, +}; fn main() -> std::io::Result<()> { let parser_state = Rc::new(RefCell::new(ParserState::new())); @@ -82,14 +84,15 @@ fn main() -> std::io::Result<()> { } if let Some(path) = std::env::args().nth(1) { - // let file = std::fs::read(&path)?; - // let (output, err) = working_set.parse_file(&path, file); - let parser_state = parser_state.borrow(); let mut working_set = ParserWorkingSet::new(&*parser_state); - let (output, err) = working_set.parse_source(path.as_bytes(), false); - println!("{:#?}", output); - println!("error: {:?}", err); + + let file = std::fs::read(&path)?; + + let (block, err) = working_set.parse_file(&path, &file, false); + println!("{}", block.len()); + // println!("{:#?}", output); + // println!("error: {:?}", err); //println!("working set: {:#?}", working_set); @@ -128,9 +131,9 @@ fn main() -> std::io::Result<()> { if s.trim() == "exit" { break; } - println!("input: '{}'", s); + // println!("input: '{}'", s); - let delta = { + let (block, delta) = { let parser_state = parser_state.borrow(); let mut working_set = ParserWorkingSet::new(&*parser_state); let (output, err) = working_set.parse_file( @@ -139,12 +142,24 @@ fn main() -> std::io::Result<()> { false, ); println!("{:?}", output); - println!("Error: {:?}", err); - working_set.render() + if let Some(err) = err { + println!("Error: {:?}", err); + } + // println!("Error: {:?}", err); + (output, working_set.render()) }; ParserState::merge_delta(&mut *parser_state.borrow_mut(), delta); - // println!("{:#?}", parser_state); + + let mut stack = Stack { + vars: HashMap::new(), + }; + let state = State { + parser_state: &*parser_state.borrow(), + }; + + let output = eval_block(&state, &mut stack, &block); + println!("{:#?}", output); } Signal::CtrlC => { println!("Ctrl-c"); diff --git a/src/parser.rs b/src/parser.rs index 947eda8dd..fda1bcce3 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -561,10 +561,7 @@ impl<'a> ParserWorkingSet<'a> { call.decl_id = decl_id; call.head = command_span; - let decl = self - .get_decl(decl_id) - .expect("internal error: bad DeclId") - .clone(); + let decl = self.get_decl(decl_id).clone(); // The index into the positional parameter in the definition let mut positional_idx = 0; diff --git a/src/parser_state.rs b/src/parser_state.rs index 17cc03c9c..0a4f08d43 100644 --- a/src/parser_state.rs +++ b/src/parser_state.rs @@ -89,16 +89,22 @@ impl ParserState { self.blocks.len() } - pub fn get_var(&self, var_id: VarId) -> Option<&Type> { - self.vars.get(var_id) + pub fn get_var(&self, var_id: VarId) -> &Type { + self.vars + .get(var_id) + .expect("internal error: missing variable") } - pub fn get_decl(&self, decl_id: DeclId) -> Option<&Declaration> { - self.decls.get(decl_id) + pub fn get_decl(&self, decl_id: DeclId) -> &Declaration { + self.decls + .get(decl_id) + .expect("internal error: missing declaration") } - pub fn get_block(&self, block_id: BlockId) -> Option<&Block> { - self.blocks.get(block_id) + pub fn get_block(&self, block_id: BlockId) -> &Block { + self.blocks + .get(block_id) + .expect("internal error: missing block") } pub fn next_span_start(&self) -> usize { @@ -318,30 +324,39 @@ impl<'a> ParserWorkingSet<'a> { next_id } - pub fn get_variable(&self, var_id: VarId) -> Option<&Type> { + pub fn get_variable(&self, var_id: VarId) -> &Type { let num_permanent_vars = self.permanent_state.num_vars(); if var_id < num_permanent_vars { self.permanent_state.get_var(var_id) } else { - self.delta.vars.get(var_id - num_permanent_vars) + self.delta + .vars + .get(var_id - num_permanent_vars) + .expect("internal error: missing variable") } } - pub fn get_decl(&self, decl_id: DeclId) -> Option<&Declaration> { + pub fn get_decl(&self, decl_id: DeclId) -> &Declaration { let num_permanent_decls = self.permanent_state.num_decls(); if decl_id < num_permanent_decls { self.permanent_state.get_decl(decl_id) } else { - self.delta.decls.get(decl_id - num_permanent_decls) + self.delta + .decls + .get(decl_id - num_permanent_decls) + .expect("internal error: missing declaration") } } - pub fn get_block(&self, block_id: BlockId) -> Option<&Block> { + pub fn get_block(&self, block_id: BlockId) -> &Block { let num_permanent_blocks = self.permanent_state.num_blocks(); if block_id < num_permanent_blocks { self.permanent_state.get_block(block_id) } else { - self.delta.blocks.get(block_id - num_permanent_blocks) + self.delta + .blocks + .get(block_id - num_permanent_blocks) + .expect("internal error: missing block") } }