nushell/src/parser/registry.rs

338 lines
8.8 KiB
Rust
Raw Normal View History

2019-07-24 00:22:11 +02:00
// TODO: Temporary redirect
crate use crate::context::CommandRegistry;
2019-06-22 03:36:57 +02:00
use crate::evaluate::{evaluate_baseline_expr, Scope};
2019-08-01 03:58:42 +02:00
use crate::parser::{hir, hir::SyntaxType, parse_command, CallNode};
2019-05-28 08:45:18 +02:00
use crate::prelude::*;
2019-06-22 03:36:57 +02:00
use derive_new::new;
2019-05-26 08:54:41 +02:00
use indexmap::IndexMap;
2019-06-22 03:36:57 +02:00
use log::trace;
2019-07-02 09:56:20 +02:00
use serde::{Deserialize, Serialize};
2019-06-22 03:36:57 +02:00
use std::fmt;
2019-05-26 08:54:41 +02:00
#[allow(unused)]
2019-07-16 09:08:35 +02:00
#[derive(Debug, Serialize, Deserialize, Clone)]
2019-05-28 08:45:18 +02:00
pub enum NamedType {
Switch,
2019-07-15 23:16:27 +02:00
Mandatory(SyntaxType),
Optional(SyntaxType),
2019-05-26 08:54:41 +02:00
}
#[allow(unused)]
2019-07-02 09:56:20 +02:00
#[derive(Debug, Clone, Serialize, Deserialize)]
2019-05-28 08:45:18 +02:00
pub enum PositionalType {
2019-07-15 23:16:27 +02:00
Mandatory(String, SyntaxType),
Optional(String, SyntaxType),
2019-05-28 08:45:18 +02:00
}
impl PositionalType {
2019-07-15 23:16:27 +02:00
pub fn mandatory(name: &str, ty: SyntaxType) -> PositionalType {
PositionalType::Mandatory(name.to_string(), ty)
}
pub fn mandatory_any(name: &str) -> PositionalType {
PositionalType::Mandatory(name.to_string(), SyntaxType::Any)
2019-07-13 04:07:06 +02:00
}
2019-07-16 21:10:25 +02:00
pub fn mandatory_block(name: &str) -> PositionalType {
PositionalType::Mandatory(name.to_string(), SyntaxType::Block)
}
2019-07-16 09:25:48 +02:00
pub fn optional(name: &str, ty: SyntaxType) -> PositionalType {
PositionalType::Optional(name.to_string(), ty)
}
pub fn optional_any(name: &str) -> PositionalType {
PositionalType::Optional(name.to_string(), SyntaxType::Any)
}
2019-07-16 09:08:35 +02:00
#[allow(unused)]
2019-07-15 23:16:27 +02:00
crate fn to_coerce_hint(&self) -> Option<SyntaxType> {
2019-05-28 08:45:18 +02:00
match self {
2019-07-15 23:16:27 +02:00
PositionalType::Mandatory(_, SyntaxType::Block)
| PositionalType::Optional(_, SyntaxType::Block) => Some(SyntaxType::Block),
_ => None,
2019-05-28 08:45:18 +02:00
}
}
crate fn name(&self) -> &str {
match self {
PositionalType::Mandatory(s, _) => s,
PositionalType::Optional(s, _) => s,
}
}
2019-07-15 23:16:27 +02:00
crate fn syntax_type(&self) -> SyntaxType {
match *self {
PositionalType::Mandatory(_, t) => t,
PositionalType::Optional(_, t) => t,
}
}
2019-05-28 08:45:18 +02:00
}
2019-08-02 21:15:07 +02:00
#[derive(Debug, Serialize, Deserialize, Clone, new)]
pub struct Signature {
2019-07-02 09:56:20 +02:00
pub name: String,
2019-08-02 21:15:07 +02:00
#[new(default)]
2019-07-13 04:07:06 +02:00
pub positional: Vec<PositionalType>,
2019-08-02 21:15:07 +02:00
#[new(value = "false")]
2019-07-02 09:56:20 +02:00
pub rest_positional: bool,
2019-08-02 21:15:07 +02:00
#[new(default)]
2019-07-02 09:56:20 +02:00
pub named: IndexMap<String, NamedType>,
2019-08-02 21:15:07 +02:00
#[new(value = "false")]
2019-07-02 09:56:20 +02:00
pub is_filter: bool,
2019-05-28 08:45:18 +02:00
}
2019-08-02 21:15:07 +02:00
impl Signature {
pub fn build(name: impl Into<String>) -> Signature {
Signature::new(name.into())
2019-07-24 06:10:48 +02:00
}
2019-08-02 21:15:07 +02:00
pub fn required(mut self, name: impl Into<String>, ty: impl Into<SyntaxType>) -> Signature {
2019-07-24 06:10:48 +02:00
self.positional
.push(PositionalType::Mandatory(name.into(), ty.into()));
self
}
2019-08-02 21:15:07 +02:00
pub fn optional(mut self, name: impl Into<String>, ty: impl Into<SyntaxType>) -> Signature {
2019-07-24 06:10:48 +02:00
self.positional
.push(PositionalType::Optional(name.into(), ty.into()));
self
}
2019-08-02 21:15:07 +02:00
pub fn named(mut self, name: impl Into<String>, ty: impl Into<SyntaxType>) -> Signature {
self.named
.insert(name.into(), NamedType::Optional(ty.into()));
self
}
pub fn required_named(
mut self,
name: impl Into<String>,
ty: impl Into<SyntaxType>,
) -> Signature {
self.named
.insert(name.into(), NamedType::Mandatory(ty.into()));
self
}
pub fn switch(mut self, name: impl Into<String>) -> Signature {
self.named.insert(name.into(), NamedType::Switch);
2019-07-24 06:10:48 +02:00
self
}
2019-08-02 21:15:07 +02:00
pub fn filter(mut self) -> Signature {
self.is_filter = true;
self
}
pub fn rest(mut self) -> Signature {
self.rest_positional = true;
self
}
2019-07-24 06:10:48 +02:00
}
#[derive(Debug, Default, new, Serialize, Deserialize, Clone)]
2019-07-24 00:22:11 +02:00
pub struct EvaluatedArgs {
2019-08-01 03:58:42 +02:00
pub positional: Option<Vec<Tagged<Value>>>,
pub named: Option<IndexMap<String, Tagged<Value>>>,
2019-06-22 03:36:57 +02:00
}
#[derive(new)]
2019-07-24 00:22:11 +02:00
pub struct DebugEvaluatedPositional<'a> {
2019-08-01 03:58:42 +02:00
positional: &'a Option<Vec<Tagged<Value>>>,
2019-06-22 03:36:57 +02:00
}
2019-07-24 00:22:11 +02:00
impl fmt::Debug for DebugEvaluatedPositional<'a> {
2019-06-22 03:36:57 +02:00
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match &self.positional {
None => write!(f, "None"),
Some(positional) => f
.debug_list()
2019-07-09 06:31:26 +02:00
.entries(positional.iter().map(|p| p.debug()))
2019-06-22 03:36:57 +02:00
.finish(),
}
}
}
#[derive(new)]
2019-07-24 00:22:11 +02:00
pub struct DebugEvaluatedNamed<'a> {
2019-08-01 03:58:42 +02:00
named: &'a Option<IndexMap<String, Tagged<Value>>>,
2019-06-22 03:36:57 +02:00
}
2019-07-24 00:22:11 +02:00
impl fmt::Debug for DebugEvaluatedNamed<'a> {
2019-06-22 03:36:57 +02:00
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match &self.named {
None => write!(f, "None"),
Some(named) => f
.debug_map()
2019-07-09 06:31:26 +02:00
.entries(named.iter().map(|(k, v)| (k, v.debug())))
2019-06-22 03:36:57 +02:00
.finish(),
}
}
}
2019-07-24 00:22:11 +02:00
pub struct DebugEvaluatedArgs<'a> {
args: &'a EvaluatedArgs,
2019-06-22 03:36:57 +02:00
}
2019-07-24 00:22:11 +02:00
impl fmt::Debug for DebugEvaluatedArgs<'a> {
2019-06-22 03:36:57 +02:00
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut s = f.debug_struct("Args");
2019-07-24 00:22:11 +02:00
s.field(
"positional",
&DebugEvaluatedPositional::new(&self.args.positional),
);
s.field("named", &DebugEvaluatedNamed::new(&self.args.named));
2019-06-22 03:36:57 +02:00
s.finish()
}
}
2019-07-24 00:22:11 +02:00
impl EvaluatedArgs {
pub fn debug(&'a self) -> DebugEvaluatedArgs<'a> {
DebugEvaluatedArgs { args: self }
2019-06-22 03:36:57 +02:00
}
2019-08-01 03:58:42 +02:00
pub fn nth(&self, pos: usize) -> Option<&Tagged<Value>> {
2019-06-22 03:36:57 +02:00
match &self.positional {
None => None,
Some(array) => array.iter().nth(pos),
}
}
2019-08-01 03:58:42 +02:00
pub fn expect_nth(&self, pos: usize) -> Result<&Tagged<Value>, ShellError> {
2019-06-22 03:36:57 +02:00
match &self.positional {
None => Err(ShellError::unimplemented("Better error: expect_nth")),
Some(array) => match array.iter().nth(pos) {
None => Err(ShellError::unimplemented("Better error: expect_nth")),
Some(item) => Ok(item),
},
}
}
pub fn len(&self) -> usize {
match &self.positional {
None => 0,
Some(array) => array.len(),
}
}
pub fn has(&self, name: &str) -> bool {
match &self.named {
None => false,
Some(named) => named.contains_key(name),
}
}
2019-08-01 03:58:42 +02:00
pub fn get(&self, name: &str) -> Option<&Tagged<Value>> {
2019-06-22 03:36:57 +02:00
match &self.named {
None => None,
Some(named) => named.get(name),
}
}
pub fn positional_iter(&'a self) -> PositionalIter<'a> {
match &self.positional {
None => PositionalIter::Empty,
Some(v) => {
let iter = v.iter();
PositionalIter::Array(iter)
}
}
}
}
pub enum PositionalIter<'a> {
Empty,
2019-08-01 03:58:42 +02:00
Array(std::slice::Iter<'a, Tagged<Value>>),
2019-06-22 03:36:57 +02:00
}
impl Iterator for PositionalIter<'a> {
2019-08-01 03:58:42 +02:00
type Item = &'a Tagged<Value>;
2019-06-22 03:36:57 +02:00
fn next(&mut self) -> Option<Self::Item> {
match self {
PositionalIter::Empty => None,
PositionalIter::Array(iter) => iter.next(),
}
}
}
2019-08-02 21:15:07 +02:00
impl Signature {
2019-07-24 00:22:11 +02:00
crate fn parse_args(
2019-05-28 08:45:18 +02:00
&self,
2019-08-01 03:58:42 +02:00
call: &Tagged<CallNode>,
2019-07-24 00:22:11 +02:00
registry: &CommandRegistry,
2019-06-22 22:46:16 +02:00
source: &Text,
2019-07-24 00:22:11 +02:00
) -> Result<hir::Call, ShellError> {
2019-06-22 03:36:57 +02:00
let args = parse_command(self, registry, call, source)?;
2019-06-22 03:36:57 +02:00
trace!("parsed args: {:?}", args);
2019-07-24 00:22:11 +02:00
Ok(args)
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
}
2019-07-24 00:22:11 +02:00
crate fn evaluate_args(
call: &hir::Call,
registry: &CommandRegistry,
2019-06-22 03:36:57 +02:00
scope: &Scope,
2019-06-22 22:46:16 +02:00
source: &Text,
2019-07-24 00:22:11 +02:00
) -> Result<EvaluatedArgs, ShellError> {
let positional: Result<Option<Vec<_>>, _> = call
2019-06-22 03:36:57 +02:00
.positional()
.as_ref()
.map(|p| {
p.iter()
2019-07-24 00:22:11 +02:00
.map(|e| evaluate_baseline_expr(e, &CommandRegistry::empty(), scope, source))
2019-06-22 03:36:57 +02:00
.collect()
})
.transpose();
let positional = positional?;
2019-08-09 06:51:21 +02:00
let named: Result<Option<IndexMap<String, Tagged<Value>>>, ShellError> = call
2019-06-22 03:36:57 +02:00
.named()
.as_ref()
.map(|n| {
let mut results = IndexMap::new();
for (name, value) in n.named.iter() {
match value {
hir::named::NamedValue::PresentSwitch(span) => {
results.insert(
name.clone(),
Tagged::from_simple_spanned_item(Value::boolean(true), *span),
2019-06-22 03:36:57 +02:00
);
}
hir::named::NamedValue::Value(expr) => {
results.insert(
name.clone(),
evaluate_baseline_expr(expr, registry, scope, source)?,
);
}
2019-06-22 03:36:57 +02:00
_ => {}
};
}
2019-06-22 03:36:57 +02:00
Ok(results)
})
.transpose();
2019-06-22 03:36:57 +02:00
let named = named?;
2019-07-24 00:22:11 +02:00
Ok(EvaluatedArgs::new(positional, named))
2019-05-26 08:54:41 +02:00
}