forked from extern/nushell
Add support for positive integer ranges
Including support for variables and subexpressions as range bounds.
This commit is contained in:
@ -1,4 +1,4 @@
|
||||
use super::{Call, Expression, Operator};
|
||||
use super::{Call, Expression, Operator, RangeOperator};
|
||||
use crate::{BlockId, Signature, Span, VarId};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
@ -6,6 +6,11 @@ pub enum Expr {
|
||||
Bool(bool),
|
||||
Int(i64),
|
||||
Float(f64),
|
||||
Range(
|
||||
Option<Box<Expression>>,
|
||||
Option<Box<Expression>>,
|
||||
RangeOperator,
|
||||
),
|
||||
Var(VarId),
|
||||
Call(Box<Call>),
|
||||
ExternalCall(Vec<u8>, Vec<Vec<u8>>),
|
||||
|
@ -7,6 +7,7 @@ pub struct Expression {
|
||||
pub span: Span,
|
||||
pub ty: Type,
|
||||
}
|
||||
|
||||
impl Expression {
|
||||
pub fn garbage(span: Span) -> Expression {
|
||||
Expression {
|
||||
@ -15,6 +16,7 @@ impl Expression {
|
||||
ty: Type::Unknown,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn precedence(&self) -> usize {
|
||||
match &self.expr {
|
||||
Expr::Operator(operator) => {
|
||||
|
@ -1,3 +1,5 @@
|
||||
use crate::Span;
|
||||
|
||||
use std::fmt::Display;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
@ -46,3 +48,24 @@ impl Display for Operator {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||
pub enum RangeInclusion {
|
||||
Inclusive,
|
||||
RightExclusive,
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct RangeOperator {
|
||||
pub inclusion: RangeInclusion,
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
impl Display for RangeOperator {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self.inclusion {
|
||||
RangeInclusion::Inclusive => write!(f, ".."),
|
||||
RangeInclusion::RightExclusive => write!(f, "..<"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ use std::fmt::Display;
|
||||
pub enum Type {
|
||||
Int,
|
||||
Float,
|
||||
Range,
|
||||
Bool,
|
||||
String,
|
||||
Block,
|
||||
@ -31,6 +32,7 @@ impl Display for Type {
|
||||
Type::Filesize => write!(f, "filesize"),
|
||||
Type::Float => write!(f, "float"),
|
||||
Type::Int => write!(f, "int"),
|
||||
Type::Range => write!(f, "range"),
|
||||
Type::List(l) => write!(f, "list<{}>", l),
|
||||
Type::Nothing => write!(f, "nothing"),
|
||||
Type::Number => write!(f, "number"),
|
||||
|
@ -1,5 +1,6 @@
|
||||
use std::{cell::RefCell, fmt::Debug, rc::Rc};
|
||||
|
||||
use crate::ast::RangeInclusion;
|
||||
use crate::{span, BlockId, Span, Type};
|
||||
|
||||
use crate::ShellError;
|
||||
@ -103,6 +104,13 @@ impl IntoRowStream for Vec<Vec<Value>> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct Range {
|
||||
pub from: Value,
|
||||
pub to: Value,
|
||||
pub inclusion: RangeInclusion,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Value {
|
||||
Bool {
|
||||
@ -113,6 +121,10 @@ pub enum Value {
|
||||
val: i64,
|
||||
span: Span,
|
||||
},
|
||||
Range {
|
||||
val: Box<Range>,
|
||||
span: Span,
|
||||
},
|
||||
Float {
|
||||
val: f64,
|
||||
span: Span,
|
||||
@ -161,6 +173,7 @@ impl Value {
|
||||
Value::Bool { span, .. } => *span,
|
||||
Value::Int { span, .. } => *span,
|
||||
Value::Float { span, .. } => *span,
|
||||
Value::Range { span, .. } => *span,
|
||||
Value::String { span, .. } => *span,
|
||||
Value::List { span, .. } => *span,
|
||||
Value::Table { span, .. } => *span,
|
||||
@ -176,6 +189,7 @@ impl Value {
|
||||
Value::Bool { span, .. } => *span = new_span,
|
||||
Value::Int { span, .. } => *span = new_span,
|
||||
Value::Float { span, .. } => *span = new_span,
|
||||
Value::Range { span, .. } => *span = new_span,
|
||||
Value::String { span, .. } => *span = new_span,
|
||||
Value::RowStream { span, .. } => *span = new_span,
|
||||
Value::ValueStream { span, .. } => *span = new_span,
|
||||
@ -193,6 +207,7 @@ impl Value {
|
||||
Value::Bool { .. } => Type::Bool,
|
||||
Value::Int { .. } => Type::Int,
|
||||
Value::Float { .. } => Type::Float,
|
||||
Value::Range { .. } => Type::Range,
|
||||
Value::String { .. } => Type::String,
|
||||
Value::List { .. } => Type::List(Box::new(Type::Unknown)), // FIXME
|
||||
Value::Table { .. } => Type::Table, // FIXME
|
||||
@ -208,6 +223,25 @@ impl Value {
|
||||
Value::Bool { val, .. } => val.to_string(),
|
||||
Value::Int { val, .. } => val.to_string(),
|
||||
Value::Float { val, .. } => val.to_string(),
|
||||
Value::Range { val, .. } => {
|
||||
let vals: Vec<i64> = match (&val.from, &val.to) {
|
||||
(Value::Int { val: from, .. }, Value::Int { val: to, .. }) => {
|
||||
match val.inclusion {
|
||||
RangeInclusion::Inclusive => (*from..=*to).collect(),
|
||||
RangeInclusion::RightExclusive => (*from..*to).collect(),
|
||||
}
|
||||
}
|
||||
_ => Vec::new(),
|
||||
};
|
||||
|
||||
format!(
|
||||
"range: [{}]",
|
||||
vals.iter()
|
||||
.map(|x| x.to_string())
|
||||
.collect::<Vec<String>>()
|
||||
.join(", ".into())
|
||||
)
|
||||
},
|
||||
Value::String { val, .. } => val,
|
||||
Value::ValueStream { stream, .. } => stream.into_string(),
|
||||
Value::List { val, .. } => val
|
||||
|
Reference in New Issue
Block a user