nushell/src/parser/registry.rs

236 lines
6.7 KiB
Rust
Raw Normal View History

2019-05-28 08:45:18 +02:00
use crate::evaluate::{evaluate_expr, Scope};
2019-06-08 00:35:07 +02:00
use crate::parser::lexer::Spanned;
2019-05-28 08:45:18 +02:00
use crate::prelude::*;
2019-05-26 08:54:41 +02:00
use indexmap::IndexMap;
#[allow(unused)]
2019-05-28 08:45:18 +02:00
#[derive(Debug)]
pub enum NamedType {
Switch,
Mandatory(NamedValue),
Optional(NamedValue),
}
#[derive(Debug)]
pub enum NamedValue {
Single,
Tuple,
#[allow(unused)]
Block,
#[allow(unused)]
Array,
2019-05-26 08:54:41 +02:00
}
#[allow(unused)]
2019-05-28 08:45:18 +02:00
#[derive(Debug, Clone)]
pub enum PositionalType {
Value(String),
Block(String),
}
impl PositionalType {
crate fn name(&self) -> String {
match self {
PositionalType::Value(s) => s.clone(),
PositionalType::Block(s) => s.clone(),
}
}
2019-06-08 00:35:07 +02:00
crate fn evaluate(
&self,
arg: ast::Expression,
scope: &Scope,
) -> Result<Spanned<Value>, ShellError> {
2019-05-28 08:45:18 +02:00
match self {
PositionalType::Value(_) => evaluate_expr(&arg, scope),
PositionalType::Block(_) => match arg {
ast::Expression {
expr: ast::RawExpression::Block(b),
..
2019-06-08 00:35:07 +02:00
} => Ok(Spanned::from_item(Value::block(b.expr), arg.span.clone())),
ast::Expression {
expr: ast::RawExpression::Binary(binary),
..
} => {
// TODO: Use original spans
let mut b = ast::ExpressionBuilder::new();
if let Some(s) = binary.left.as_string() {
2019-06-08 00:35:07 +02:00
Ok(Spanned::from_item(
Value::block(b.binary((
&|b| b.path((&|b| b.var("it"), vec![s.clone()])),
&|_| binary.operator.clone(),
&|_| binary.right.clone(),
))),
arg.span.clone(),
))
2019-05-28 08:45:18 +02:00
} else {
let mut b = ast::ExpressionBuilder::new();
let expr = b.binary((
&|_| binary.left.clone(),
&|_| binary.operator.clone(),
&|_| binary.right.clone(),
));
2019-06-08 00:35:07 +02:00
Ok(Spanned::from_item(Value::block(expr), arg.span.clone()))
2019-05-28 08:45:18 +02:00
}
}
2019-06-08 00:35:07 +02:00
other => {
let span = other.span.clone();
Ok(Spanned::from_item(Value::block(other), span))
}
2019-05-28 08:45:18 +02:00
},
}
}
}
#[derive(Debug)]
2019-05-26 08:54:41 +02:00
pub struct CommandConfig {
crate name: String,
2019-05-28 08:45:18 +02:00
crate mandatory_positional: Vec<PositionalType>,
crate optional_positional: Vec<PositionalType>,
2019-05-26 08:54:41 +02:00
crate rest_positional: bool,
2019-05-28 08:45:18 +02:00
crate named: IndexMap<String, NamedType>,
}
2019-06-04 23:42:31 +02:00
#[derive(Debug, Default)]
pub struct Args {
2019-06-08 00:35:07 +02:00
pub positional: Vec<Spanned<Value>>,
pub named: IndexMap<String, Value>,
}
2019-05-28 08:45:18 +02:00
impl CommandConfig {
crate fn evaluate_args(
&self,
args: impl Iterator<Item = &'expr ast::Expression>,
2019-05-28 08:45:18 +02:00
scope: &Scope,
) -> Result<Args, ShellError> {
2019-06-08 00:35:07 +02:00
let mut positional: Vec<Spanned<Value>> = vec![];
let mut named: IndexMap<String, Value> = IndexMap::default();
let mut args: Vec<ast::Expression> = args.cloned().collect();
for (key, ty) in self.named.iter() {
let index = args.iter().position(|a| a.is_flag(&key));
match (index, ty) {
(Some(i), NamedType::Switch) => {
args.remove(i);
named.insert(key.clone(), Value::boolean(true));
}
(None, NamedType::Switch) => {}
(Some(i), NamedType::Optional(v)) => {
args.remove(i);
named.insert(key.clone(), extract_named(&mut args, i, v)?);
}
(None, NamedType::Optional(_)) => {}
(Some(i), NamedType::Mandatory(v)) => {
args.remove(i);
named.insert(key.clone(), extract_named(&mut args, i, v)?);
}
(None, NamedType::Mandatory(_)) => {
return Err(ShellError::string(&format!(
"Expected mandatory argument {}, but it was missing",
key
)))
}
}
}
let mut args = args.into_iter();
2019-05-28 08:45:18 +02:00
for param in &self.mandatory_positional {
let arg = args.next();
let value = match arg {
None => {
return Err(ShellError::string(format!(
"expected mandatory positional argument {}",
param.name()
)))
}
Some(arg) => param.evaluate(arg.clone(), scope)?,
};
positional.push(value);
2019-05-28 08:45:18 +02:00
}
if self.rest_positional {
2019-06-08 00:35:07 +02:00
let rest: Result<Vec<Spanned<Value>>, _> =
args.map(|i| evaluate_expr(&i, &Scope::empty())).collect();
positional.extend(rest?);
2019-05-28 08:45:18 +02:00
} else {
let rest: Vec<ast::Expression> = args.collect();
if rest.len() > 0 {
return Err(ShellError::string(&format!(
"Too many arguments, extras: {:?}",
rest
)));
2019-05-28 08:45:18 +02:00
}
}
Ok(Args { positional, named })
2019-05-28 08:45:18 +02:00
}
#[allow(unused)]
crate fn signature(&self) -> String {
format!("TODO")
}
2019-05-26 08:54:41 +02:00
}
fn extract_named(
v: &mut Vec<ast::Expression>,
position: usize,
ty: &NamedValue,
) -> Result<Value, ShellError> {
match ty {
NamedValue::Single => {
let expr = v.remove(position);
expect_simple_expr(expr)
}
NamedValue::Tuple => {
let expr = v.remove(position);
let next = v.remove(position);
let list = vec![expect_simple_expr(expr)?, expect_simple_expr(next)?];
Ok(Value::List(list))
}
other => Err(ShellError::string(&format!(
"Unimplemented named argument {:?}",
other
))),
}
}
fn expect_simple_expr(expr: ast::Expression) -> Result<Value, ShellError> {
match &*expr {
ast::RawExpression::Leaf(l) => Ok(match l {
ast::Leaf::Bare(s) => Value::string(s.to_string()),
ast::Leaf::String(s) => Value::string(s),
ast::Leaf::Boolean(b) => Value::boolean(*b),
ast::Leaf::Int(i) => Value::int(*i),
ast::Leaf::Unit(i, unit) => unit.compute(*i),
}),
// TODO: Diagnostic
other => Err(ShellError::string(&format!(
"Expected a value, found {}",
other.print()
))),
}
}
2019-05-26 08:54:41 +02:00
pub trait CommandRegistry {
fn get(&self, name: &str) -> CommandConfig;
}