start expanding eval

This commit is contained in:
JT 2021-07-23 17:14:49 +12:00
parent 8c6feb7e80
commit 3eefa6dec8
6 changed files with 147 additions and 98 deletions

View File

@ -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)] #[derive(Debug)]
pub enum ShellError { pub enum ShellError {
Mismatch(String, Span), Mismatch(String, Span),
Unsupported(Span), Unsupported(Span),
InternalError(String),
} }
pub struct Engine; #[derive(Debug, Clone)]
#[derive(Debug)]
pub enum Value { pub enum Value {
Int { val: i64, span: Span }, Int { val: i64, span: Span },
Unknown, Unknown,
} }
impl Value { impl Value {
pub fn add(&self, rhs: &Value) -> Result<Value, ShellError> { pub fn add(&self, rhs: &Value) -> Result<Value, ShellError> {
match (self, rhs) { match (self, rhs) {
@ -26,71 +26,99 @@ impl Value {
} }
} }
impl Default for Engine { pub struct State<'a> {
fn default() -> Self { pub parser_state: &'a ParserState,
Self::new() }
pub struct Stack {
pub vars: HashMap<VarId, Value>,
}
impl Stack {
pub fn get_var(&self, var_id: VarId) -> Result<Value, ShellError> {
match self.vars.get(&var_id) {
Some(v) => Ok(v.clone()),
_ => Err(ShellError::InternalError("variable not found".into())),
}
} }
} }
impl Engine { pub fn eval_operator(
pub fn new() -> Self { state: &State,
Self stack: &mut Stack,
op: &Expression,
) -> Result<Operator, ShellError> {
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<Operator, ShellError> { fn eval_call(state: &State, stack: &mut Stack, call: &Call) -> Result<Value, ShellError> {
match op { let decl = state.parser_state.get_decl(call.decl_id);
Expression {
expr: Expr::Operator(operator), if let Some(block_id) = decl.body {
.. let block = state.parser_state.get_block(block_id);
} => Ok(operator.clone()), eval_block(state, stack, block)
Expression { span, .. } => Err(ShellError::Mismatch("operator".to_string(), *span)), } else {
} Ok(Value::Unknown)
} }
}
pub fn eval_expression(&self, expr: &Expression) -> Result<Value, ShellError> { pub fn eval_expression(
match expr.expr { state: &State,
Expr::Int(i) => Ok(Value::Int { stack: &mut Stack,
val: i, expr: &Expression,
span: expr.span, ) -> Result<Value, ShellError> {
}), match &expr.expr {
Expr::Var(_) => Err(ShellError::Unsupported(expr.span)), Expr::Int(i) => Ok(Value::Int {
Expr::Call(_) => Err(ShellError::Unsupported(expr.span)), val: *i,
Expr::ExternalCall(_, _) => Err(ShellError::Unsupported(expr.span)), span: expr.span,
Expr::Operator(_) => Err(ShellError::Unsupported(expr.span)), }),
Expr::BinaryOp(_, _, _) => Err(ShellError::Unsupported(expr.span)), Expr::Var(var_id) => stack.get_var(*var_id),
Expr::Subexpression(_) => Err(ShellError::Unsupported(expr.span)), Expr::Call(call) => eval_call(state, stack, call),
Expr::Block(_) => Err(ShellError::Unsupported(expr.span)), Expr::ExternalCall(_, _) => Err(ShellError::Unsupported(expr.span)),
Expr::List(_) => Err(ShellError::Unsupported(expr.span)), Expr::Operator(_) => Ok(Value::Unknown),
Expr::Table(_, _) => Err(ShellError::Unsupported(expr.span)), Expr::BinaryOp(lhs, op, rhs) => {
Expr::Literal(_) => Err(ShellError::Unsupported(expr.span)), let lhs = eval_expression(state, stack, &lhs)?;
Expr::String(_) => Err(ShellError::Unsupported(expr.span)), let op = eval_operator(state, stack, &op)?;
Expr::Signature(_) => Err(ShellError::Unsupported(expr.span)), let rhs = eval_expression(state, stack, &rhs)?;
Expr::Garbage => Err(ShellError::Unsupported(expr.span)),
}
}
pub fn eval_block(&self, block: &Block) -> Result<Value, ShellError> { match op {
let mut last = Ok(Value::Unknown); Operator::Plus => lhs.add(&rhs),
_ => 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),
_ => {}
}
}
_ => {}
},
_ => {}
} }
} }
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<Value, ShellError> {
let mut last = Ok(Value::Unknown);
for stmt in &block.stmts {
match stmt {
Statement::Expression(expression) => {
last = Ok(eval_expression(state, stack, expression)?);
}
_ => {}
}
}
last
}

View File

@ -38,10 +38,7 @@ impl<'a> ParserWorkingSet<'a> {
output.extend(self.flatten_expression(&rhs)); output.extend(self.flatten_expression(&rhs));
output output
} }
Expr::Block(block_id) => self.flatten_block( Expr::Block(block_id) => self.flatten_block(self.get_block(*block_id)),
self.get_block(*block_id)
.expect("internal error: missing block"),
),
Expr::Call(call) => { Expr::Call(call) => {
let mut output = vec![]; let mut output = vec![];
output.push((call.head, FlatShape::InternalCall)); output.push((call.head, FlatShape::InternalCall));
@ -78,10 +75,7 @@ impl<'a> ParserWorkingSet<'a> {
Expr::String(_) => { Expr::String(_) => {
vec![(expr.span, FlatShape::String)] vec![(expr.span, FlatShape::String)]
} }
Expr::Subexpression(block_id) => self.flatten_block( Expr::Subexpression(block_id) => self.flatten_block(self.get_block(*block_id)),
self.get_block(*block_id)
.expect("internal error: missing block"),
),
Expr::Table(headers, cells) => { Expr::Table(headers, cells) => {
let mut output = vec![]; let mut output = vec![];
for e in headers { for e in headers {

View File

@ -13,7 +13,7 @@ mod syntax_highlight;
mod tests; mod tests;
pub use declaration::Declaration; 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 lex::{lex, Token, TokenContents};
pub use lite_parse::{lite_parse, LiteBlock, LiteCommand, LiteStatement}; pub use lite_parse::{lite_parse, LiteBlock, LiteCommand, LiteStatement};
pub use parse_error::ParseError; pub use parse_error::ParseError;

View File

@ -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<()> { fn main() -> std::io::Result<()> {
let parser_state = Rc::new(RefCell::new(ParserState::new())); 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) { 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 parser_state = parser_state.borrow();
let mut working_set = ParserWorkingSet::new(&*parser_state); let mut working_set = ParserWorkingSet::new(&*parser_state);
let (output, err) = working_set.parse_source(path.as_bytes(), false);
println!("{:#?}", output); let file = std::fs::read(&path)?;
println!("error: {:?}", err);
let (block, err) = working_set.parse_file(&path, &file, false);
println!("{}", block.len());
// println!("{:#?}", output);
// println!("error: {:?}", err);
//println!("working set: {:#?}", working_set); //println!("working set: {:#?}", working_set);
@ -128,9 +131,9 @@ fn main() -> std::io::Result<()> {
if s.trim() == "exit" { if s.trim() == "exit" {
break; break;
} }
println!("input: '{}'", s); // println!("input: '{}'", s);
let delta = { let (block, delta) = {
let parser_state = parser_state.borrow(); let parser_state = parser_state.borrow();
let mut working_set = ParserWorkingSet::new(&*parser_state); let mut working_set = ParserWorkingSet::new(&*parser_state);
let (output, err) = working_set.parse_file( let (output, err) = working_set.parse_file(
@ -139,12 +142,24 @@ fn main() -> std::io::Result<()> {
false, false,
); );
println!("{:?}", output); println!("{:?}", output);
println!("Error: {:?}", err); if let Some(err) = err {
working_set.render() println!("Error: {:?}", err);
}
// println!("Error: {:?}", err);
(output, working_set.render())
}; };
ParserState::merge_delta(&mut *parser_state.borrow_mut(), delta); 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 => { Signal::CtrlC => {
println!("Ctrl-c"); println!("Ctrl-c");

View File

@ -561,10 +561,7 @@ impl<'a> ParserWorkingSet<'a> {
call.decl_id = decl_id; call.decl_id = decl_id;
call.head = command_span; call.head = command_span;
let decl = self let decl = self.get_decl(decl_id).clone();
.get_decl(decl_id)
.expect("internal error: bad DeclId")
.clone();
// The index into the positional parameter in the definition // The index into the positional parameter in the definition
let mut positional_idx = 0; let mut positional_idx = 0;

View File

@ -89,16 +89,22 @@ impl ParserState {
self.blocks.len() self.blocks.len()
} }
pub fn get_var(&self, var_id: VarId) -> Option<&Type> { pub fn get_var(&self, var_id: VarId) -> &Type {
self.vars.get(var_id) self.vars
.get(var_id)
.expect("internal error: missing variable")
} }
pub fn get_decl(&self, decl_id: DeclId) -> Option<&Declaration> { pub fn get_decl(&self, decl_id: DeclId) -> &Declaration {
self.decls.get(decl_id) self.decls
.get(decl_id)
.expect("internal error: missing declaration")
} }
pub fn get_block(&self, block_id: BlockId) -> Option<&Block> { pub fn get_block(&self, block_id: BlockId) -> &Block {
self.blocks.get(block_id) self.blocks
.get(block_id)
.expect("internal error: missing block")
} }
pub fn next_span_start(&self) -> usize { pub fn next_span_start(&self) -> usize {
@ -318,30 +324,39 @@ impl<'a> ParserWorkingSet<'a> {
next_id 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(); let num_permanent_vars = self.permanent_state.num_vars();
if var_id < num_permanent_vars { if var_id < num_permanent_vars {
self.permanent_state.get_var(var_id) self.permanent_state.get_var(var_id)
} else { } 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(); let num_permanent_decls = self.permanent_state.num_decls();
if decl_id < num_permanent_decls { if decl_id < num_permanent_decls {
self.permanent_state.get_decl(decl_id) self.permanent_state.get_decl(decl_id)
} else { } 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(); let num_permanent_blocks = self.permanent_state.num_blocks();
if block_id < num_permanent_blocks { if block_id < num_permanent_blocks {
self.permanent_state.get_block(block_id) self.permanent_state.get_block(block_id)
} else { } else {
self.delta.blocks.get(block_id - num_permanent_blocks) self.delta
.blocks
.get(block_id - num_permanent_blocks)
.expect("internal error: missing block")
} }
} }