mirror of
https://github.com/nushell/nushell
synced 2025-01-14 22:24:54 +00:00
add more type helpers and span fixes
This commit is contained in:
parent
ef4af443a5
commit
828585a312
4 changed files with 89 additions and 19 deletions
|
@ -78,7 +78,7 @@ impl<'a> codespan_reporting::files::Files<'a> for ParserWorkingSet<'a> {
|
||||||
if count > line_index {
|
if count > line_index {
|
||||||
break;
|
break;
|
||||||
} else if count == line_index {
|
} else if count == line_index {
|
||||||
start = Some(byte.0);
|
start = Some(byte.0 + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -286,12 +286,15 @@ pub fn report_shell_error(
|
||||||
let config = codespan_reporting::term::Config::default();
|
let config = codespan_reporting::term::Config::default();
|
||||||
|
|
||||||
let diagnostic = match error {
|
let diagnostic = match error {
|
||||||
ShellError::Mismatch(missing, span) => {
|
ShellError::OperatorMismatch(operator, ty1, span1, ty2, span2) => {
|
||||||
let (diag_file_id, diag_range) = convert_span_to_diag(working_set, span)?;
|
let (diag_file_id1, diag_range1) = convert_span_to_diag(working_set, span1)?;
|
||||||
|
let (diag_file_id2, diag_range2) = convert_span_to_diag(working_set, span2)?;
|
||||||
Diagnostic::error()
|
Diagnostic::error()
|
||||||
.with_message("Type mismatch during operation")
|
.with_message(format!("Type mismatch during operation '{}'", operator))
|
||||||
.with_labels(vec![Label::primary(diag_file_id, diag_range)
|
.with_labels(vec![
|
||||||
.with_message(format!("expected {}", missing))])
|
Label::primary(diag_file_id1, diag_range1).with_message(ty1.to_string()),
|
||||||
|
Label::secondary(diag_file_id2, diag_range2).with_message(ty2.to_string()),
|
||||||
|
])
|
||||||
}
|
}
|
||||||
ShellError::Unsupported(span) => {
|
ShellError::Unsupported(span) => {
|
||||||
let (diag_file_id, diag_range) = convert_span_to_diag(working_set, span)?;
|
let (diag_file_id, diag_range) = convert_span_to_diag(working_set, span)?;
|
||||||
|
@ -312,6 +315,13 @@ pub fn report_shell_error(
|
||||||
Label::primary(diag_file_id, diag_range).with_message("variable not found")
|
Label::primary(diag_file_id, diag_range).with_message("variable not found")
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
ShellError::CantConvert(s, span) => {
|
||||||
|
let (diag_file_id, diag_range) = convert_span_to_diag(working_set, span)?;
|
||||||
|
Diagnostic::error()
|
||||||
|
.with_message(format!("Can't convert to {}", s))
|
||||||
|
.with_labels(vec![Label::primary(diag_file_id, diag_range)
|
||||||
|
.with_message(format!("can't convert to {}", s))])
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// println!("DIAG");
|
// println!("DIAG");
|
||||||
|
|
59
src/eval.rs
59
src/eval.rs
|
@ -1,15 +1,17 @@
|
||||||
use std::{cell::RefCell, collections::HashMap, fmt::Display, rc::Rc, time::Instant};
|
use std::{cell::RefCell, collections::HashMap, fmt::Display, rc::Rc, time::Instant};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
parser::Operator, Block, BlockId, Call, Expr, Expression, ParserState, Span, Statement, VarId,
|
parser::Operator, parser_state::Type, Block, BlockId, Call, Expr, Expression, ParserState,
|
||||||
|
Span, Statement, VarId,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum ShellError {
|
pub enum ShellError {
|
||||||
Mismatch(String, Span),
|
OperatorMismatch(String, Type, Span, Type, Span),
|
||||||
Unsupported(Span),
|
Unsupported(Span),
|
||||||
InternalError(String),
|
InternalError(String),
|
||||||
VariableNotFound(Span),
|
VariableNotFound(Span),
|
||||||
|
CantConvert(String, Span),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
@ -27,7 +29,7 @@ impl Value {
|
||||||
pub fn as_string(&self) -> Result<String, ShellError> {
|
pub fn as_string(&self) -> Result<String, ShellError> {
|
||||||
match self {
|
match self {
|
||||||
Value::String { val, .. } => Ok(val.to_string()),
|
Value::String { val, .. } => Ok(val.to_string()),
|
||||||
_ => Err(ShellError::Mismatch("string".into(), self.span())),
|
_ => Err(ShellError::CantConvert("string".into(), self.span())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,6 +44,32 @@ impl Value {
|
||||||
Value::Nothing { span, .. } => *span,
|
Value::Nothing { span, .. } => *span,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn with_span(mut self, new_span: Span) -> Value {
|
||||||
|
match &mut self {
|
||||||
|
Value::Bool { span, .. } => *span = new_span,
|
||||||
|
Value::Int { span, .. } => *span = new_span,
|
||||||
|
Value::Float { span, .. } => *span = new_span,
|
||||||
|
Value::String { span, .. } => *span = new_span,
|
||||||
|
Value::List { span, .. } => *span = new_span,
|
||||||
|
Value::Block { span, .. } => *span = new_span,
|
||||||
|
Value::Nothing { span, .. } => *span = new_span,
|
||||||
|
}
|
||||||
|
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_type(&self) -> Type {
|
||||||
|
match self {
|
||||||
|
Value::Bool { .. } => Type::Bool,
|
||||||
|
Value::Int { .. } => Type::Int,
|
||||||
|
Value::Float { .. } => Type::Float,
|
||||||
|
Value::String { .. } => Type::String,
|
||||||
|
Value::List { .. } => Type::List(Box::new(Type::Unknown)), // FIXME
|
||||||
|
Value::Nothing { .. } => Type::Nothing,
|
||||||
|
Value::Block { .. } => Type::Block,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartialEq for Value {
|
impl PartialEq for Value {
|
||||||
|
@ -80,29 +108,37 @@ impl Display for Value {
|
||||||
|
|
||||||
impl Value {
|
impl Value {
|
||||||
pub fn add(&self, rhs: &Value) -> Result<Value, ShellError> {
|
pub fn add(&self, rhs: &Value) -> Result<Value, ShellError> {
|
||||||
|
let span = crate::parser::span(&[self.span(), rhs.span()]);
|
||||||
|
|
||||||
match (self, rhs) {
|
match (self, rhs) {
|
||||||
(Value::Int { val: lhs, .. }, Value::Int { val: rhs, .. }) => Ok(Value::Int {
|
(Value::Int { val: lhs, .. }, Value::Int { val: rhs, .. }) => Ok(Value::Int {
|
||||||
val: lhs + rhs,
|
val: lhs + rhs,
|
||||||
span: Span::unknown(),
|
span,
|
||||||
}),
|
}),
|
||||||
(Value::Int { val: lhs, .. }, Value::Float { val: rhs, .. }) => Ok(Value::Float {
|
(Value::Int { val: lhs, .. }, Value::Float { val: rhs, .. }) => Ok(Value::Float {
|
||||||
val: *lhs as f64 + *rhs,
|
val: *lhs as f64 + *rhs,
|
||||||
span: Span::unknown(),
|
span,
|
||||||
}),
|
}),
|
||||||
(Value::Float { val: lhs, .. }, Value::Int { val: rhs, .. }) => Ok(Value::Float {
|
(Value::Float { val: lhs, .. }, Value::Int { val: rhs, .. }) => Ok(Value::Float {
|
||||||
val: *lhs + *rhs as f64,
|
val: *lhs + *rhs as f64,
|
||||||
span: Span::unknown(),
|
span,
|
||||||
}),
|
}),
|
||||||
(Value::Float { val: lhs, .. }, Value::Float { val: rhs, .. }) => Ok(Value::Float {
|
(Value::Float { val: lhs, .. }, Value::Float { val: rhs, .. }) => Ok(Value::Float {
|
||||||
val: lhs + rhs,
|
val: lhs + rhs,
|
||||||
span: Span::unknown(),
|
span,
|
||||||
}),
|
}),
|
||||||
(Value::String { val: lhs, .. }, Value::String { val: rhs, .. }) => Ok(Value::String {
|
(Value::String { val: lhs, .. }, Value::String { val: rhs, .. }) => Ok(Value::String {
|
||||||
val: lhs.to_string() + rhs,
|
val: lhs.to_string() + rhs,
|
||||||
span: Span::unknown(),
|
span,
|
||||||
}),
|
}),
|
||||||
|
|
||||||
_ => Err(ShellError::Mismatch("addition".into(), self.span())),
|
_ => Err(ShellError::OperatorMismatch(
|
||||||
|
"+".into(),
|
||||||
|
self.get_type(),
|
||||||
|
self.span(),
|
||||||
|
rhs.get_type(),
|
||||||
|
rhs.span(),
|
||||||
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -193,7 +229,7 @@ pub fn eval_operator(
|
||||||
expr: Expr::Operator(operator),
|
expr: Expr::Operator(operator),
|
||||||
..
|
..
|
||||||
} => Ok(operator.clone()),
|
} => Ok(operator.clone()),
|
||||||
Expression { span, .. } => Err(ShellError::Mismatch("operator".to_string(), *span)),
|
Expression { span, .. } => Err(ShellError::Unsupported(*span)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -280,7 +316,7 @@ fn eval_call(state: &State, stack: Stack, call: &Call) -> Result<Value, ShellErr
|
||||||
Ok(Value::Nothing { span })
|
Ok(Value::Nothing { span })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => Err(ShellError::Mismatch("bool".into(), Span::unknown())),
|
_ => Err(ShellError::CantConvert("bool".into(), result.span())),
|
||||||
}
|
}
|
||||||
} else if decl.signature.name == "build-string" {
|
} else if decl.signature.name == "build-string" {
|
||||||
let mut output = vec![];
|
let mut output = vec![];
|
||||||
|
@ -385,6 +421,7 @@ pub fn eval_expression(
|
||||||
}),
|
}),
|
||||||
Expr::Var(var_id) => stack
|
Expr::Var(var_id) => stack
|
||||||
.get_var(*var_id)
|
.get_var(*var_id)
|
||||||
|
.map(|x| x.with_span(expr.span))
|
||||||
.map_err(move |_| ShellError::VariableNotFound(expr.span)),
|
.map_err(move |_| ShellError::VariableNotFound(expr.span)),
|
||||||
Expr::Call(call) => eval_call(state, stack, call),
|
Expr::Call(call) => eval_call(state, stack, call),
|
||||||
Expr::ExternalCall(_, _) => Err(ShellError::Unsupported(expr.span)),
|
Expr::ExternalCall(_, _) => Err(ShellError::Unsupported(expr.span)),
|
||||||
|
|
|
@ -375,7 +375,7 @@ fn check_call(command: Span, sig: &Signature, call: &Call) -> Option<ParseError>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn span(spans: &[Span]) -> Span {
|
pub(crate) fn span(spans: &[Span]) -> Span {
|
||||||
let length = spans.len();
|
let length = spans.len();
|
||||||
|
|
||||||
if length == 0 {
|
if length == 0 {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::{parser::Block, Declaration, Span};
|
use crate::{parser::Block, Declaration, Span};
|
||||||
use core::panic;
|
use core::panic;
|
||||||
use std::{collections::HashMap, slice::Iter};
|
use std::{collections::HashMap, fmt::Display, slice::Iter};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ParserState {
|
pub struct ParserState {
|
||||||
|
@ -15,6 +15,7 @@ pub struct ParserState {
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
pub enum Type {
|
pub enum Type {
|
||||||
Int,
|
Int,
|
||||||
|
Float,
|
||||||
Bool,
|
Bool,
|
||||||
String,
|
String,
|
||||||
Block,
|
Block,
|
||||||
|
@ -24,10 +25,32 @@ pub enum Type {
|
||||||
Filesize,
|
Filesize,
|
||||||
List(Box<Type>),
|
List(Box<Type>),
|
||||||
Number,
|
Number,
|
||||||
|
Nothing,
|
||||||
Table,
|
Table,
|
||||||
Unknown,
|
Unknown,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Display for Type {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
Type::Block => write!(f, "block"),
|
||||||
|
Type::Bool => write!(f, "bool"),
|
||||||
|
Type::ColumnPath => write!(f, "column path"),
|
||||||
|
Type::Duration => write!(f, "duration"),
|
||||||
|
Type::FilePath => write!(f, "filepath"),
|
||||||
|
Type::Filesize => write!(f, "filesize"),
|
||||||
|
Type::Float => write!(f, "float"),
|
||||||
|
Type::Int => write!(f, "int"),
|
||||||
|
Type::List(l) => write!(f, "list<{}>", l),
|
||||||
|
Type::Nothing => write!(f, "nothing"),
|
||||||
|
Type::Number => write!(f, "number"),
|
||||||
|
Type::String => write!(f, "string"),
|
||||||
|
Type::Table => write!(f, "table"),
|
||||||
|
Type::Unknown => write!(f, "unknown"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub type VarId = usize;
|
pub type VarId = usize;
|
||||||
pub type DeclId = usize;
|
pub type DeclId = usize;
|
||||||
pub type BlockId = usize;
|
pub type BlockId = usize;
|
||||||
|
|
Loading…
Reference in a new issue