Add support for positive integer ranges

Including support for variables and subexpressions as range bounds.
This commit is contained in:
Jakub Žádník
2021-09-05 00:52:57 +03:00
parent 2794556eaa
commit 0b412cd6b3
9 changed files with 277 additions and 5 deletions

View File

@ -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>>),

View File

@ -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) => {

View File

@ -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, "..<"),
}
}
}

View File

@ -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"),

View File

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