diff --git a/Cargo.toml b/Cargo.toml index 7808c544cb..ca3f9ac46a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,8 +7,11 @@ edition = "2018" [dependencies] reedline = { git = "https://github.com/jntrnr/reedline", branch = "main" } -nu-ansi-term = "0.32.0" codespan-reporting = "0.11.1" +nu-cli = { path="./crates/nu-cli" } +nu-engine = { path="./crates/nu-engine" } +nu-parser = { path="./crates/nu-parser" } + # mimalloc = { version = "*", default-features = false } [dev-dependencies] diff --git a/crates/nu-cli/Cargo.toml b/crates/nu-cli/Cargo.toml new file mode 100644 index 0000000000..115029612b --- /dev/null +++ b/crates/nu-cli/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "nu-cli" +version = "0.1.0" +edition = "2018" + +[dependencies] +nu-engine = { path = "../nu-engine" } +nu-parser = { path = "../nu-parser" } +codespan-reporting = "0.11.1" +nu-ansi-term = "0.32.0" +reedline = { git = "https://github.com/jntrnr/reedline", branch = "main" } diff --git a/crates/nu-cli/src/default_context.rs b/crates/nu-cli/src/default_context.rs new file mode 100644 index 0000000000..4929ff2e00 --- /dev/null +++ b/crates/nu-cli/src/default_context.rs @@ -0,0 +1,122 @@ +use std::{cell::RefCell, rc::Rc}; + +use nu_parser::{ParserState, ParserWorkingSet, Signature, SyntaxShape}; + +pub fn create_default_context() -> Rc> { + let parser_state = Rc::new(RefCell::new(ParserState::new())); + let delta = { + let parser_state = parser_state.borrow(); + let mut working_set = ParserWorkingSet::new(&*parser_state); + + let sig = + Signature::build("where").required("cond", SyntaxShape::RowCondition, "condition"); + working_set.add_decl(sig.into()); + + let sig = Signature::build("if") + .required("cond", SyntaxShape::Expression, "condition") + .required("then_block", SyntaxShape::Block, "then block") + .optional( + "else", + SyntaxShape::Keyword(b"else".to_vec(), Box::new(SyntaxShape::Expression)), + "optional else followed by else block", + ); + working_set.add_decl(sig.into()); + + let sig = Signature::build("let") + .required("var_name", SyntaxShape::VarWithOptType, "variable name") + .required( + "initial_value", + SyntaxShape::Keyword(b"=".to_vec(), Box::new(SyntaxShape::Expression)), + "equals sign followed by value", + ); + 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("name", SyntaxShape::String, "name of the alias") + .required( + "initial_value", + SyntaxShape::Keyword(b"=".to_vec(), Box::new(SyntaxShape::Expression)), + "equals sign followed by value", + ); + working_set.add_decl(sig.into()); + + let sig = Signature::build("sum").required( + "arg", + SyntaxShape::List(Box::new(SyntaxShape::Number)), + "list of numbers", + ); + working_set.add_decl(sig.into()); + + let sig = Signature::build("build-string").rest(SyntaxShape::String, "list of string"); + working_set.add_decl(sig.into()); + + let sig = Signature::build("def") + .required("def_name", SyntaxShape::String, "definition name") + .required("params", SyntaxShape::Signature, "parameters") + .required("block", SyntaxShape::Block, "body of the definition"); + working_set.add_decl(sig.into()); + + let sig = Signature::build("for") + .required( + "var_name", + SyntaxShape::Variable, + "name of the looping variable", + ) + .required( + "range", + SyntaxShape::Keyword(b"in".to_vec(), Box::new(SyntaxShape::Int)), + "range of the loop", + ) + .required("block", SyntaxShape::Block, "the block to run"); + working_set.add_decl(sig.into()); + + let sig = + Signature::build("benchmark").required("block", SyntaxShape::Block, "the block to run"); + working_set.add_decl(sig.into()); + + // let sig = Signature::build("foo").named("--jazz", SyntaxShape::Int, "jazz!!", Some('j')); + // working_set.add_decl(sig.into()); + + // let sig = Signature::build("bar") + // .named("--jazz", SyntaxShape::Int, "jazz!!", Some('j')) + // .switch("--rock", "rock!!", Some('r')); + // working_set.add_decl(sig.into()); + let sig = Signature::build("exit"); + working_set.add_decl(sig.into()); + let sig = Signature::build("vars"); + working_set.add_decl(sig.into()); + let sig = Signature::build("decls"); + working_set.add_decl(sig.into()); + let sig = Signature::build("blocks"); + working_set.add_decl(sig.into()); + let sig = Signature::build("stack"); + working_set.add_decl(sig.into()); + + let sig = Signature::build("add"); + working_set.add_decl(sig.into()); + let sig = Signature::build("add it"); + working_set.add_decl(sig.into()); + + let sig = Signature::build("add it together") + .required("x", SyntaxShape::Int, "x value") + .required("y", SyntaxShape::Int, "y value"); + working_set.add_decl(sig.into()); + + working_set.render() + }; + + { + ParserState::merge_delta(&mut *parser_state.borrow_mut(), delta); + } + + parser_state +} diff --git a/src/errors.rs b/crates/nu-cli/src/errors.rs similarity index 81% rename from src/errors.rs rename to crates/nu-cli/src/errors.rs index 3cf156fe12..a5c29379e0 100644 --- a/src/errors.rs +++ b/crates/nu-cli/src/errors.rs @@ -1,100 +1,9 @@ use core::ops::Range; -use crate::{ParseError, ParserWorkingSet, ShellError, Span}; use codespan_reporting::diagnostic::{Diagnostic, Label}; use codespan_reporting::term::termcolor::{ColorChoice, StandardStream}; - -impl<'a> codespan_reporting::files::Files<'a> for ParserWorkingSet<'a> { - type FileId = usize; - - type Name = String; - - type Source = String; - - fn name(&'a self, id: Self::FileId) -> Result { - Ok(self.get_filename(id)) - } - - fn source( - &'a self, - id: Self::FileId, - ) -> Result { - Ok(self.get_file_source(id)) - } - - fn line_index( - &'a self, - id: Self::FileId, - byte_index: usize, - ) -> Result { - let source = self.get_file_source(id); - - let mut count = 0; - - for byte in source.bytes().enumerate() { - if byte.0 == byte_index { - // println!("count: {} for file: {} index: {}", count, id, byte_index); - return Ok(count); - } - if byte.1 == b'\n' { - count += 1; - } - } - - // println!("count: {} for file: {} index: {}", count, id, byte_index); - Ok(count) - } - - fn line_range( - &'a self, - id: Self::FileId, - line_index: usize, - ) -> Result, codespan_reporting::files::Error> { - let source = self.get_file_source(id); - - let mut count = 0; - - let mut start = Some(0); - let mut end = None; - - for byte in source.bytes().enumerate() { - #[allow(clippy::comparison_chain)] - if count > line_index { - let start = start.expect("internal error: couldn't find line"); - let end = end.expect("internal error: couldn't find line"); - - // println!( - // "Span: {}..{} for fileid: {} index: {}", - // start, end, id, line_index - // ); - return Ok(start..end); - } else if count == line_index { - end = Some(byte.0 + 1); - } - - #[allow(clippy::comparison_chain)] - if byte.1 == b'\n' { - count += 1; - if count > line_index { - break; - } else if count == line_index { - start = Some(byte.0 + 1); - } - } - } - - match (start, end) { - (Some(start), Some(end)) => { - // println!( - // "Span: {}..{} for fileid: {} index: {}", - // start, end, id, line_index - // ); - Ok(start..end) - } - _ => Err(codespan_reporting::files::Error::FileMissing), - } - } -} +use nu_engine::ShellError; +use nu_parser::{ParseError, ParserWorkingSet, Span}; fn convert_span_to_diag( working_set: &ParserWorkingSet, diff --git a/crates/nu-cli/src/lib.rs b/crates/nu-cli/src/lib.rs new file mode 100644 index 0000000000..7c2e42b92d --- /dev/null +++ b/crates/nu-cli/src/lib.rs @@ -0,0 +1,7 @@ +mod default_context; +mod errors; +mod syntax_highlight; + +pub use default_context::create_default_context; +pub use errors::{report_parsing_error, report_shell_error}; +pub use syntax_highlight::NuHighlighter; diff --git a/src/syntax_highlight.rs b/crates/nu-cli/src/syntax_highlight.rs similarity index 97% rename from src/syntax_highlight.rs rename to crates/nu-cli/src/syntax_highlight.rs index 616626b054..cd0f592b8b 100644 --- a/src/syntax_highlight.rs +++ b/crates/nu-cli/src/syntax_highlight.rs @@ -1,6 +1,5 @@ -use crate::flatten::FlatShape; -use crate::{ParserState, ParserWorkingSet}; use nu_ansi_term::Style; +use nu_parser::{FlatShape, ParserState, ParserWorkingSet}; use reedline::{Highlighter, StyledText}; use std::{cell::RefCell, rc::Rc}; diff --git a/crates/nu-engine/Cargo.toml b/crates/nu-engine/Cargo.toml new file mode 100644 index 0000000000..95747a0dc2 --- /dev/null +++ b/crates/nu-engine/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "nu-engine" +version = "0.1.0" +edition = "2018" + +[dependencies] +nu-parser = { path = "../nu-parser" } \ No newline at end of file diff --git a/src/eval.rs b/crates/nu-engine/src/eval.rs similarity index 98% rename from src/eval.rs rename to crates/nu-engine/src/eval.rs index 14ec7647f4..24c6a453d9 100644 --- a/src/eval.rs +++ b/crates/nu-engine/src/eval.rs @@ -1,8 +1,7 @@ use std::{cell::RefCell, collections::HashMap, fmt::Display, rc::Rc, time::Instant}; -use crate::{ - parser::Operator, parser_state::Type, Block, BlockId, Call, Expr, Expression, ParserState, - Span, Statement, VarId, +use nu_parser::{ + Block, BlockId, Call, Expr, Expression, Operator, ParserState, Span, Statement, Type, VarId, }; #[derive(Debug)] @@ -114,7 +113,7 @@ impl Display for Value { impl Value { pub fn add(&self, op: Span, rhs: &Value) -> Result { - let span = crate::parser::span(&[self.span(), rhs.span()]); + let span = nu_parser::span(&[self.span(), rhs.span()]); match (self, rhs) { (Value::Int { val: lhs, .. }, Value::Int { val: rhs, .. }) => Ok(Value::Int { diff --git a/crates/nu-engine/src/lib.rs b/crates/nu-engine/src/lib.rs new file mode 100644 index 0000000000..01fb48ca0c --- /dev/null +++ b/crates/nu-engine/src/lib.rs @@ -0,0 +1,3 @@ +mod eval; + +pub use eval::{eval_block, eval_expression, eval_operator, ShellError, Stack, State, Value}; diff --git a/crates/nu-parser/Cargo.toml b/crates/nu-parser/Cargo.toml new file mode 100644 index 0000000000..13f8ce4764 --- /dev/null +++ b/crates/nu-parser/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "nu-parser" +version = "0.1.0" +edition = "2018" + +[dependencies] +codespan-reporting = "0.11.1" \ No newline at end of file diff --git a/src/declaration.rs b/crates/nu-parser/src/declaration.rs similarity index 100% rename from src/declaration.rs rename to crates/nu-parser/src/declaration.rs diff --git a/crates/nu-parser/src/errors.rs b/crates/nu-parser/src/errors.rs new file mode 100644 index 0000000000..94cf1df34d --- /dev/null +++ b/crates/nu-parser/src/errors.rs @@ -0,0 +1,95 @@ +use std::ops::Range; + +use crate::ParserWorkingSet; + +impl<'a> codespan_reporting::files::Files<'a> for ParserWorkingSet<'a> { + type FileId = usize; + + type Name = String; + + type Source = String; + + fn name(&'a self, id: Self::FileId) -> Result { + Ok(self.get_filename(id)) + } + + fn source( + &'a self, + id: Self::FileId, + ) -> Result { + Ok(self.get_file_source(id)) + } + + fn line_index( + &'a self, + id: Self::FileId, + byte_index: usize, + ) -> Result { + let source = self.get_file_source(id); + + let mut count = 0; + + for byte in source.bytes().enumerate() { + if byte.0 == byte_index { + // println!("count: {} for file: {} index: {}", count, id, byte_index); + return Ok(count); + } + if byte.1 == b'\n' { + count += 1; + } + } + + // println!("count: {} for file: {} index: {}", count, id, byte_index); + Ok(count) + } + + fn line_range( + &'a self, + id: Self::FileId, + line_index: usize, + ) -> Result, codespan_reporting::files::Error> { + let source = self.get_file_source(id); + + let mut count = 0; + + let mut start = Some(0); + let mut end = None; + + for byte in source.bytes().enumerate() { + #[allow(clippy::comparison_chain)] + if count > line_index { + let start = start.expect("internal error: couldn't find line"); + let end = end.expect("internal error: couldn't find line"); + + // println!( + // "Span: {}..{} for fileid: {} index: {}", + // start, end, id, line_index + // ); + return Ok(start..end); + } else if count == line_index { + end = Some(byte.0 + 1); + } + + #[allow(clippy::comparison_chain)] + if byte.1 == b'\n' { + count += 1; + if count > line_index { + break; + } else if count == line_index { + start = Some(byte.0 + 1); + } + } + } + + match (start, end) { + (Some(start), Some(end)) => { + // println!( + // "Span: {}..{} for fileid: {} index: {}", + // start, end, id, line_index + // ); + Ok(start..end) + } + _ => Err(codespan_reporting::files::Error::FileMissing), + } + } +} diff --git a/src/flatten.rs b/crates/nu-parser/src/flatten.rs similarity index 100% rename from src/flatten.rs rename to crates/nu-parser/src/flatten.rs diff --git a/src/lex.rs b/crates/nu-parser/src/lex.rs similarity index 100% rename from src/lex.rs rename to crates/nu-parser/src/lex.rs diff --git a/crates/nu-parser/src/lib.rs b/crates/nu-parser/src/lib.rs new file mode 100644 index 0000000000..d36f1badd9 --- /dev/null +++ b/crates/nu-parser/src/lib.rs @@ -0,0 +1,24 @@ +mod declaration; +mod errors; +mod flatten; +mod lex; +mod lite_parse; +mod parse_error; +mod parser; +mod parser_state; +mod signature; +mod span; +mod type_check; + +pub use declaration::Declaration; +pub use flatten::FlatShape; +pub use lex::{lex, Token, TokenContents}; +pub use lite_parse::{lite_parse, LiteBlock}; +pub use parse_error::ParseError; +pub use parser::{ + span, Block, Call, Expr, Expression, Import, Operator, Pipeline, Statement, SyntaxShape, + VarDecl, +}; +pub use parser_state::{BlockId, DeclId, ParserDelta, ParserState, ParserWorkingSet, Type, VarId}; +pub use signature::{Flag, PositionalArg, Signature}; +pub use span::Span; diff --git a/src/lite_parse.rs b/crates/nu-parser/src/lite_parse.rs similarity index 100% rename from src/lite_parse.rs rename to crates/nu-parser/src/lite_parse.rs diff --git a/src/parse_error.rs b/crates/nu-parser/src/parse_error.rs similarity index 100% rename from src/parse_error.rs rename to crates/nu-parser/src/parse_error.rs diff --git a/src/parser.rs b/crates/nu-parser/src/parser.rs similarity index 99% rename from src/parser.rs rename to crates/nu-parser/src/parser.rs index ca27f2ce60..6d6bd480ed 100644 --- a/src/parser.rs +++ b/crates/nu-parser/src/parser.rs @@ -375,7 +375,7 @@ fn check_call(command: Span, sig: &Signature, call: &Call) -> Option } } -pub(crate) fn span(spans: &[Span]) -> Span { +pub fn span(spans: &[Span]) -> Span { let length = spans.len(); if length == 0 { diff --git a/src/parser_state.rs b/crates/nu-parser/src/parser_state.rs similarity index 100% rename from src/parser_state.rs rename to crates/nu-parser/src/parser_state.rs diff --git a/src/signature.rs b/crates/nu-parser/src/signature.rs similarity index 100% rename from src/signature.rs rename to crates/nu-parser/src/signature.rs diff --git a/src/span.rs b/crates/nu-parser/src/span.rs similarity index 100% rename from src/span.rs rename to crates/nu-parser/src/span.rs diff --git a/src/type_check.rs b/crates/nu-parser/src/type_check.rs similarity index 100% rename from src/type_check.rs rename to crates/nu-parser/src/type_check.rs diff --git a/src/lib.rs b/src/lib.rs deleted file mode 100644 index 27eaca9a01..0000000000 --- a/src/lib.rs +++ /dev/null @@ -1,29 +0,0 @@ -mod declaration; -mod errors; -mod eval; -mod flatten; -mod lex; -mod lite_parse; -mod parse_error; -mod parser; -mod parser_state; -mod signature; -mod span; -mod syntax_highlight; -#[cfg(test)] -mod tests; -mod type_check; - -pub use declaration::Declaration; -pub use errors::{report_parsing_error, report_shell_error}; -pub use eval::{eval_block, eval_expression, ShellError, Stack, StackFrame, State}; -pub use lex::{lex, Token, TokenContents}; -pub use lite_parse::{lite_parse, LiteBlock, LiteCommand, LiteStatement}; -pub use parse_error::ParseError; -pub use parser::{ - Block, Call, Expr, Expression, Import, Pipeline, Statement, SyntaxShape, VarDecl, -}; -pub use parser_state::{BlockId, DeclId, ParserState, ParserWorkingSet, VarId}; -pub use signature::Signature; -pub use span::Span; -pub use syntax_highlight::NuHighlighter; diff --git a/src/main.rs b/src/main.rs index ab3ab55b59..ed4de134d1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,129 +1,11 @@ -use std::{cell::RefCell, rc::Rc}; - -use engine_q::{ - eval_block, report_parsing_error, report_shell_error, NuHighlighter, ParserState, - ParserWorkingSet, Signature, Stack, State, SyntaxShape, -}; +use nu_cli::{create_default_context, report_parsing_error, report_shell_error, NuHighlighter}; +use nu_engine::eval_block; +use nu_parser::{ParserState, ParserWorkingSet}; fn main() -> std::io::Result<()> { - let parser_state = Rc::new(RefCell::new(ParserState::new())); - let delta = { - let parser_state = parser_state.borrow(); - let mut working_set = ParserWorkingSet::new(&*parser_state); - - let sig = - Signature::build("where").required("cond", SyntaxShape::RowCondition, "condition"); - working_set.add_decl(sig.into()); - - let sig = Signature::build("if") - .required("cond", SyntaxShape::Expression, "condition") - .required("then_block", SyntaxShape::Block, "then block") - .optional( - "else", - SyntaxShape::Keyword(b"else".to_vec(), Box::new(SyntaxShape::Expression)), - "optional else followed by else block", - ); - working_set.add_decl(sig.into()); - - let sig = Signature::build("let") - .required("var_name", SyntaxShape::VarWithOptType, "variable name") - .required( - "initial_value", - SyntaxShape::Keyword(b"=".to_vec(), Box::new(SyntaxShape::Expression)), - "equals sign followed by value", - ); - 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("name", SyntaxShape::String, "name of the alias") - .required( - "initial_value", - SyntaxShape::Keyword(b"=".to_vec(), Box::new(SyntaxShape::Expression)), - "equals sign followed by value", - ); - working_set.add_decl(sig.into()); - - let sig = Signature::build("sum").required( - "arg", - SyntaxShape::List(Box::new(SyntaxShape::Number)), - "list of numbers", - ); - working_set.add_decl(sig.into()); - - let sig = Signature::build("build-string").rest(SyntaxShape::String, "list of string"); - working_set.add_decl(sig.into()); - - let sig = Signature::build("def") - .required("def_name", SyntaxShape::String, "definition name") - .required("params", SyntaxShape::Signature, "parameters") - .required("block", SyntaxShape::Block, "body of the definition"); - working_set.add_decl(sig.into()); - - let sig = Signature::build("for") - .required( - "var_name", - SyntaxShape::Variable, - "name of the looping variable", - ) - .required( - "range", - SyntaxShape::Keyword(b"in".to_vec(), Box::new(SyntaxShape::Int)), - "range of the loop", - ) - .required("block", SyntaxShape::Block, "the block to run"); - working_set.add_decl(sig.into()); - - let sig = - Signature::build("benchmark").required("block", SyntaxShape::Block, "the block to run"); - working_set.add_decl(sig.into()); - - // let sig = Signature::build("foo").named("--jazz", SyntaxShape::Int, "jazz!!", Some('j')); - // working_set.add_decl(sig.into()); - - // let sig = Signature::build("bar") - // .named("--jazz", SyntaxShape::Int, "jazz!!", Some('j')) - // .switch("--rock", "rock!!", Some('r')); - // working_set.add_decl(sig.into()); - let sig = Signature::build("exit"); - working_set.add_decl(sig.into()); - let sig = Signature::build("vars"); - working_set.add_decl(sig.into()); - let sig = Signature::build("decls"); - working_set.add_decl(sig.into()); - let sig = Signature::build("blocks"); - working_set.add_decl(sig.into()); - let sig = Signature::build("stack"); - working_set.add_decl(sig.into()); - - let sig = Signature::build("add"); - working_set.add_decl(sig.into()); - let sig = Signature::build("add it"); - working_set.add_decl(sig.into()); - - let sig = Signature::build("add it together") - .required("x", SyntaxShape::Int, "x value") - .required("y", SyntaxShape::Int, "y value"); - working_set.add_decl(sig.into()); - - working_set.render() - }; - - { - ParserState::merge_delta(&mut *parser_state.borrow_mut(), delta); - } + let parser_state = create_default_context(); if let Some(path) = std::env::args().nth(1) { - let parser_state = parser_state; - let file = std::fs::read(&path)?; let (block, delta) = { @@ -140,11 +22,11 @@ fn main() -> std::io::Result<()> { ParserState::merge_delta(&mut *parser_state.borrow_mut(), delta); - let state = State { + let state = nu_engine::State { parser_state: &*parser_state.borrow(), }; - let stack = Stack::new(); + let stack = nu_engine::Stack::new(); match eval_block(&state, stack, &block) { Ok(value) => { @@ -154,7 +36,7 @@ fn main() -> std::io::Result<()> { let parser_state = parser_state.borrow(); let working_set = ParserWorkingSet::new(&*parser_state); - let _ = engine_q::report_shell_error(&working_set, &err); + let _ = report_shell_error(&working_set, &err); std::process::exit(1); } @@ -175,7 +57,7 @@ fn main() -> std::io::Result<()> { let prompt = DefaultPrompt::new(1); let mut current_line = 1; - let stack = Stack::new(); + let stack = nu_engine::Stack::new(); loop { let input = line_editor.read_line(&prompt); @@ -203,7 +85,7 @@ fn main() -> std::io::Result<()> { ParserState::merge_delta(&mut *parser_state.borrow_mut(), delta); - let state = State { + let state = nu_engine::State { parser_state: &*parser_state.borrow(), };