refactor to subcrates

This commit is contained in:
JT 2021-08-11 06:51:08 +12:00
parent f62e3119c4
commit 1355a5dd33
24 changed files with 296 additions and 257 deletions

View File

@ -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]

11
crates/nu-cli/Cargo.toml Normal file
View File

@ -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" }

View File

@ -0,0 +1,122 @@
use std::{cell::RefCell, rc::Rc};
use nu_parser::{ParserState, ParserWorkingSet, Signature, SyntaxShape};
pub fn create_default_context() -> Rc<RefCell<ParserState>> {
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
}

View File

@ -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<Self::Name, codespan_reporting::files::Error> {
Ok(self.get_filename(id))
}
fn source(
&'a self,
id: Self::FileId,
) -> Result<Self::Source, codespan_reporting::files::Error> {
Ok(self.get_file_source(id))
}
fn line_index(
&'a self,
id: Self::FileId,
byte_index: usize,
) -> Result<usize, codespan_reporting::files::Error> {
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<Range<usize>, 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,

7
crates/nu-cli/src/lib.rs Normal file
View File

@ -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;

View File

@ -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};

View File

@ -0,0 +1,7 @@
[package]
name = "nu-engine"
version = "0.1.0"
edition = "2018"
[dependencies]
nu-parser = { path = "../nu-parser" }

View File

@ -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<Value, ShellError> {
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 {

View File

@ -0,0 +1,3 @@
mod eval;
pub use eval::{eval_block, eval_expression, eval_operator, ShellError, Stack, State, Value};

View File

@ -0,0 +1,7 @@
[package]
name = "nu-parser"
version = "0.1.0"
edition = "2018"
[dependencies]
codespan-reporting = "0.11.1"

View File

@ -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<Self::Name, codespan_reporting::files::Error> {
Ok(self.get_filename(id))
}
fn source(
&'a self,
id: Self::FileId,
) -> Result<Self::Source, codespan_reporting::files::Error> {
Ok(self.get_file_source(id))
}
fn line_index(
&'a self,
id: Self::FileId,
byte_index: usize,
) -> Result<usize, codespan_reporting::files::Error> {
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<Range<usize>, 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),
}
}
}

View File

@ -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;

View File

@ -375,7 +375,7 @@ fn check_call(command: Span, sig: &Signature, call: &Call) -> Option<ParseError>
}
}
pub(crate) fn span(spans: &[Span]) -> Span {
pub fn span(spans: &[Span]) -> Span {
let length = spans.len();
if length == 0 {

View File

@ -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;

View File

@ -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(),
};