mirror of
https://github.com/nushell/nushell
synced 2025-01-14 14:14:13 +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 {
|
||||
break;
|
||||
} 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 diagnostic = match error {
|
||||
ShellError::Mismatch(missing, span) => {
|
||||
let (diag_file_id, diag_range) = convert_span_to_diag(working_set, span)?;
|
||||
ShellError::OperatorMismatch(operator, ty1, span1, ty2, span2) => {
|
||||
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()
|
||||
.with_message("Type mismatch during operation")
|
||||
.with_labels(vec![Label::primary(diag_file_id, diag_range)
|
||||
.with_message(format!("expected {}", missing))])
|
||||
.with_message(format!("Type mismatch during operation '{}'", operator))
|
||||
.with_labels(vec![
|
||||
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) => {
|
||||
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")
|
||||
])
|
||||
}
|
||||
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");
|
||||
|
|
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 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)]
|
||||
pub enum ShellError {
|
||||
Mismatch(String, Span),
|
||||
OperatorMismatch(String, Type, Span, Type, Span),
|
||||
Unsupported(Span),
|
||||
InternalError(String),
|
||||
VariableNotFound(Span),
|
||||
CantConvert(String, Span),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
|
@ -27,7 +29,7 @@ impl Value {
|
|||
pub fn as_string(&self) -> Result<String, ShellError> {
|
||||
match self {
|
||||
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,
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
|
@ -80,29 +108,37 @@ impl Display for Value {
|
|||
|
||||
impl Value {
|
||||
pub fn add(&self, rhs: &Value) -> Result<Value, ShellError> {
|
||||
let span = crate::parser::span(&[self.span(), rhs.span()]);
|
||||
|
||||
match (self, rhs) {
|
||||
(Value::Int { val: lhs, .. }, Value::Int { val: rhs, .. }) => Ok(Value::Int {
|
||||
val: lhs + rhs,
|
||||
span: Span::unknown(),
|
||||
span,
|
||||
}),
|
||||
(Value::Int { val: lhs, .. }, Value::Float { val: rhs, .. }) => Ok(Value::Float {
|
||||
val: *lhs as f64 + *rhs,
|
||||
span: Span::unknown(),
|
||||
span,
|
||||
}),
|
||||
(Value::Float { val: lhs, .. }, Value::Int { val: rhs, .. }) => Ok(Value::Float {
|
||||
val: *lhs + *rhs as f64,
|
||||
span: Span::unknown(),
|
||||
span,
|
||||
}),
|
||||
(Value::Float { val: lhs, .. }, Value::Float { val: rhs, .. }) => Ok(Value::Float {
|
||||
val: lhs + rhs,
|
||||
span: Span::unknown(),
|
||||
span,
|
||||
}),
|
||||
(Value::String { val: lhs, .. }, Value::String { val: rhs, .. }) => Ok(Value::String {
|
||||
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),
|
||||
..
|
||||
} => 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 })
|
||||
}
|
||||
}
|
||||
_ => Err(ShellError::Mismatch("bool".into(), Span::unknown())),
|
||||
_ => Err(ShellError::CantConvert("bool".into(), result.span())),
|
||||
}
|
||||
} else if decl.signature.name == "build-string" {
|
||||
let mut output = vec![];
|
||||
|
@ -385,6 +421,7 @@ pub fn eval_expression(
|
|||
}),
|
||||
Expr::Var(var_id) => stack
|
||||
.get_var(*var_id)
|
||||
.map(|x| x.with_span(expr.span))
|
||||
.map_err(move |_| ShellError::VariableNotFound(expr.span)),
|
||||
Expr::Call(call) => eval_call(state, stack, call),
|
||||
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();
|
||||
|
||||
if length == 0 {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use crate::{parser::Block, Declaration, Span};
|
||||
use core::panic;
|
||||
use std::{collections::HashMap, slice::Iter};
|
||||
use std::{collections::HashMap, fmt::Display, slice::Iter};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ParserState {
|
||||
|
@ -15,6 +15,7 @@ pub struct ParserState {
|
|||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub enum Type {
|
||||
Int,
|
||||
Float,
|
||||
Bool,
|
||||
String,
|
||||
Block,
|
||||
|
@ -24,10 +25,32 @@ pub enum Type {
|
|||
Filesize,
|
||||
List(Box<Type>),
|
||||
Number,
|
||||
Nothing,
|
||||
Table,
|
||||
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 DeclId = usize;
|
||||
pub type BlockId = usize;
|
||||
|
|
Loading…
Reference in a new issue