mirror of
https://github.com/nushell/nushell.git
synced 2025-01-11 00:38:23 +01:00
Fix some expects, add subcommand alias
This commit is contained in:
parent
ceea7e5aeb
commit
2f43cc353b
@ -49,13 +49,6 @@ pub fn create_default_context() -> Rc<RefCell<ParserState>> {
|
|||||||
);
|
);
|
||||||
working_set.add_decl(sig.into());
|
working_set.add_decl(sig.into());
|
||||||
|
|
||||||
let sig = Signature::build("sum").required(
|
|
||||||
"arg",
|
|
||||||
SyntaxShape::List(Box::new(SyntaxShape::Number)),
|
|
||||||
"list of numbers",
|
|
||||||
);
|
|
||||||
working_set.add_decl(sig.into());
|
|
||||||
|
|
||||||
let sig = Signature::build("build-string").rest(SyntaxShape::String, "list of string");
|
let sig = Signature::build("build-string").rest(SyntaxShape::String, "list of string");
|
||||||
working_set.add_decl(sig.into());
|
working_set.add_decl(sig.into());
|
||||||
|
|
||||||
|
@ -30,12 +30,12 @@ pub fn report_parsing_error(
|
|||||||
|
|
||||||
let diagnostic =
|
let diagnostic =
|
||||||
match error {
|
match error {
|
||||||
ParseError::Mismatch(missing, span) => {
|
ParseError::Mismatch(expected, found, span) => {
|
||||||
let (diag_file_id, diag_range) = convert_span_to_diag(working_set, span)?;
|
let (diag_file_id, diag_range) = convert_span_to_diag(working_set, span)?;
|
||||||
Diagnostic::error()
|
Diagnostic::error()
|
||||||
.with_message("Type mismatch during operation")
|
.with_message("Type mismatch during operation")
|
||||||
.with_labels(vec![Label::primary(diag_file_id, diag_range)
|
.with_labels(vec![Label::primary(diag_file_id, diag_range)
|
||||||
.with_message(format!("expected {}", missing))])
|
.with_message(format!("expected {}, found {}", expected, found))])
|
||||||
}
|
}
|
||||||
ParseError::ExtraTokens(span) => {
|
ParseError::ExtraTokens(span) => {
|
||||||
let (diag_file_id, diag_range) = convert_span_to_diag(working_set, span)?;
|
let (diag_file_id, diag_range) = convert_span_to_diag(working_set, span)?;
|
||||||
@ -142,12 +142,12 @@ pub fn report_parsing_error(
|
|||||||
Label::primary(diag_file_id, diag_range).with_message("expected type")
|
Label::primary(diag_file_id, diag_range).with_message("expected type")
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
ParseError::TypeMismatch(ty, span) => {
|
ParseError::TypeMismatch(expected, found, span) => {
|
||||||
let (diag_file_id, diag_range) = convert_span_to_diag(working_set, span)?;
|
let (diag_file_id, diag_range) = convert_span_to_diag(working_set, span)?;
|
||||||
Diagnostic::error()
|
Diagnostic::error()
|
||||||
.with_message("Type mismatch")
|
.with_message("Type mismatch")
|
||||||
.with_labels(vec![Label::primary(diag_file_id, diag_range)
|
.with_labels(vec![Label::primary(diag_file_id, diag_range)
|
||||||
.with_message(format!("expected {:?}", ty))])
|
.with_message(format!("expected {:?}, found {:?}", expected, found))])
|
||||||
}
|
}
|
||||||
ParseError::MissingRequiredFlag(name, span) => {
|
ParseError::MissingRequiredFlag(name, span) => {
|
||||||
let (diag_file_id, diag_range) = convert_span_to_diag(working_set, span)?;
|
let (diag_file_id, diag_range) = convert_span_to_diag(working_set, span)?;
|
||||||
@ -178,6 +178,40 @@ pub fn report_parsing_error(
|
|||||||
Label::primary(diag_file_id, diag_range).with_message("non-UTF8 code")
|
Label::primary(diag_file_id, diag_range).with_message("non-UTF8 code")
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
ParseError::Expected(expected, span) => {
|
||||||
|
let (diag_file_id, diag_range) = convert_span_to_diag(working_set, span)?;
|
||||||
|
Diagnostic::error()
|
||||||
|
.with_message("Parse mismatch during operation")
|
||||||
|
.with_labels(vec![Label::primary(diag_file_id, diag_range)
|
||||||
|
.with_message(format!("expected {}", expected))])
|
||||||
|
}
|
||||||
|
ParseError::UnsupportedOperation(op_span, lhs_span, lhs_ty, rhs_span, rhs_ty) => {
|
||||||
|
let (lhs_file_id, lhs_range) = convert_span_to_diag(working_set, lhs_span)?;
|
||||||
|
let (rhs_file_id, rhs_range) = convert_span_to_diag(working_set, rhs_span)?;
|
||||||
|
let (op_file_id, op_range) = convert_span_to_diag(working_set, op_span)?;
|
||||||
|
Diagnostic::error()
|
||||||
|
.with_message("Unsupported operation")
|
||||||
|
.with_labels(vec![
|
||||||
|
Label::primary(op_file_id, op_range)
|
||||||
|
.with_message("doesn't support these values"),
|
||||||
|
Label::secondary(lhs_file_id, lhs_range).with_message(lhs_ty.to_string()),
|
||||||
|
Label::secondary(rhs_file_id, rhs_range).with_message(rhs_ty.to_string()),
|
||||||
|
])
|
||||||
|
}
|
||||||
|
ParseError::ExpectedKeyword(expected, span) => {
|
||||||
|
let (diag_file_id, diag_range) = convert_span_to_diag(working_set, span)?;
|
||||||
|
Diagnostic::error()
|
||||||
|
.with_message("Expected keyword")
|
||||||
|
.with_labels(vec![Label::primary(diag_file_id, diag_range)
|
||||||
|
.with_message(format!("expected {}", expected))])
|
||||||
|
}
|
||||||
|
ParseError::IncompleteParser(span) => {
|
||||||
|
let (diag_file_id, diag_range) = convert_span_to_diag(working_set, span)?;
|
||||||
|
Diagnostic::error()
|
||||||
|
.with_message("Parser incomplete")
|
||||||
|
.with_labels(vec![Label::primary(diag_file_id, diag_range)
|
||||||
|
.with_message("parser support missing for this expression")])
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// println!("DIAG");
|
// println!("DIAG");
|
||||||
|
@ -1,6 +1,36 @@
|
|||||||
|
use crate::parser_state::Type;
|
||||||
|
use crate::ParserWorkingSet;
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
|
|
||||||
use crate::ParserWorkingSet;
|
pub use crate::Span;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum ParseError {
|
||||||
|
ExtraTokens(Span),
|
||||||
|
ExtraPositional(Span),
|
||||||
|
UnexpectedEof(String, Span),
|
||||||
|
Unclosed(String, Span),
|
||||||
|
UnknownStatement(Span),
|
||||||
|
Expected(String, Span),
|
||||||
|
Mismatch(String, String, Span), // expected, found, span
|
||||||
|
UnsupportedOperation(Span, Span, Type, Span, Type),
|
||||||
|
ExpectedKeyword(String, Span),
|
||||||
|
MultipleRestParams(Span),
|
||||||
|
VariableNotFound(Span),
|
||||||
|
UnknownCommand(Span),
|
||||||
|
NonUtf8(Span),
|
||||||
|
UnknownFlag(Span),
|
||||||
|
UnknownType(Span),
|
||||||
|
MissingFlagParam(Span),
|
||||||
|
ShortFlagBatchCantTakeArg(Span),
|
||||||
|
MissingPositional(String, Span),
|
||||||
|
MissingType(Span),
|
||||||
|
TypeMismatch(Type, Type, Span), // expected, found, span
|
||||||
|
MissingRequiredFlag(String, Span),
|
||||||
|
IncompleteMathExpression(Span),
|
||||||
|
UnknownState(String, Span),
|
||||||
|
IncompleteParser(Span),
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a> codespan_reporting::files::Files<'a> for ParserWorkingSet<'a> {
|
impl<'a> codespan_reporting::files::Files<'a> for ParserWorkingSet<'a> {
|
||||||
type FileId = usize;
|
type FileId = usize;
|
||||||
|
@ -3,7 +3,6 @@ mod errors;
|
|||||||
mod flatten;
|
mod flatten;
|
||||||
mod lex;
|
mod lex;
|
||||||
mod lite_parse;
|
mod lite_parse;
|
||||||
mod parse_error;
|
|
||||||
mod parser;
|
mod parser;
|
||||||
mod parser_state;
|
mod parser_state;
|
||||||
mod signature;
|
mod signature;
|
||||||
@ -11,10 +10,10 @@ mod span;
|
|||||||
mod type_check;
|
mod type_check;
|
||||||
|
|
||||||
pub use declaration::Declaration;
|
pub use declaration::Declaration;
|
||||||
|
pub use errors::ParseError;
|
||||||
pub use flatten::FlatShape;
|
pub use flatten::FlatShape;
|
||||||
pub use lex::{lex, Token, TokenContents};
|
pub use lex::{lex, Token, TokenContents};
|
||||||
pub use lite_parse::{lite_parse, LiteBlock};
|
pub use lite_parse::{lite_parse, LiteBlock};
|
||||||
pub use parse_error::ParseError;
|
|
||||||
pub use parser::{
|
pub use parser::{
|
||||||
span, Block, Call, Expr, Expression, Import, Operator, Pipeline, Statement, SyntaxShape,
|
span, Block, Call, Expr, Expression, Import, Operator, Pipeline, Statement, SyntaxShape,
|
||||||
VarDecl,
|
VarDecl,
|
||||||
|
@ -1,26 +0,0 @@
|
|||||||
use crate::parser_state::Type;
|
|
||||||
pub use crate::Span;
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub enum ParseError {
|
|
||||||
ExtraTokens(Span),
|
|
||||||
ExtraPositional(Span),
|
|
||||||
UnexpectedEof(String, Span),
|
|
||||||
Unclosed(String, Span),
|
|
||||||
UnknownStatement(Span),
|
|
||||||
Mismatch(String, Span),
|
|
||||||
MultipleRestParams(Span),
|
|
||||||
VariableNotFound(Span),
|
|
||||||
UnknownCommand(Span),
|
|
||||||
NonUtf8(Span),
|
|
||||||
UnknownFlag(Span),
|
|
||||||
UnknownType(Span),
|
|
||||||
MissingFlagParam(Span),
|
|
||||||
ShortFlagBatchCantTakeArg(Span),
|
|
||||||
MissingPositional(String, Span),
|
|
||||||
MissingType(Span),
|
|
||||||
TypeMismatch(Type, Span),
|
|
||||||
MissingRequiredFlag(String, Span),
|
|
||||||
IncompleteMathExpression(Span),
|
|
||||||
UnknownState(String, Span),
|
|
||||||
}
|
|
@ -1,4 +1,7 @@
|
|||||||
use std::ops::{Index, IndexMut};
|
use std::{
|
||||||
|
fmt::Display,
|
||||||
|
ops::{Index, IndexMut},
|
||||||
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
lex, lite_parse,
|
lex, lite_parse,
|
||||||
@ -132,6 +135,31 @@ pub enum Operator {
|
|||||||
Pow,
|
Pow,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Display for Operator {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
Operator::Equal => write!(f, "=="),
|
||||||
|
Operator::NotEqual => write!(f, "!="),
|
||||||
|
Operator::LessThan => write!(f, "<"),
|
||||||
|
Operator::GreaterThan => write!(f, ">"),
|
||||||
|
Operator::Contains => write!(f, "=~"),
|
||||||
|
Operator::NotContains => write!(f, "!~"),
|
||||||
|
Operator::Plus => write!(f, "+"),
|
||||||
|
Operator::Minus => write!(f, "-"),
|
||||||
|
Operator::Multiply => write!(f, "*"),
|
||||||
|
Operator::Divide => write!(f, "/"),
|
||||||
|
Operator::In => write!(f, "in"),
|
||||||
|
Operator::NotIn => write!(f, "not-in"),
|
||||||
|
Operator::Modulo => write!(f, "mod"),
|
||||||
|
Operator::And => write!(f, "&&"),
|
||||||
|
Operator::Or => write!(f, "||"),
|
||||||
|
Operator::Pow => write!(f, "**"),
|
||||||
|
Operator::LessThanOrEqual => write!(f, "<="),
|
||||||
|
Operator::GreaterThanOrEqual => write!(f, ">="),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Call {
|
pub struct Call {
|
||||||
/// identifier of the declaration to call
|
/// identifier of the declaration to call
|
||||||
@ -629,7 +657,7 @@ impl<'a> ParserWorkingSet<'a> {
|
|||||||
// We won't often override the current error, but as this is a strong indicator
|
// We won't often override the current error, but as this is a strong indicator
|
||||||
// go ahead and override the current error and tell the user about the missing
|
// go ahead and override the current error and tell the user about the missing
|
||||||
// keyword/literal.
|
// keyword/literal.
|
||||||
error = Some(ParseError::Mismatch(
|
error = Some(ParseError::ExpectedKeyword(
|
||||||
String::from_utf8_lossy(keyword).into(),
|
String::from_utf8_lossy(keyword).into(),
|
||||||
arg_span,
|
arg_span,
|
||||||
))
|
))
|
||||||
@ -753,12 +781,14 @@ impl<'a> ParserWorkingSet<'a> {
|
|||||||
self.parse_multispan_value(&spans[..end], &mut spans_idx, &positional.shape);
|
self.parse_multispan_value(&spans[..end], &mut spans_idx, &positional.shape);
|
||||||
error = error.or(err);
|
error = error.or(err);
|
||||||
|
|
||||||
let arg = if positional.shape.to_type() != Type::Unknown
|
let arg = if !Self::type_compatible(&positional.shape.to_type(), &arg.ty) {
|
||||||
&& arg.ty != positional.shape.to_type()
|
|
||||||
{
|
|
||||||
let span = span(&spans[orig_idx..spans_idx]);
|
let span = span(&spans[orig_idx..spans_idx]);
|
||||||
error = error.or_else(|| {
|
error = error.or_else(|| {
|
||||||
Some(ParseError::TypeMismatch(positional.shape.to_type(), span))
|
Some(ParseError::TypeMismatch(
|
||||||
|
positional.shape.to_type(),
|
||||||
|
arg.ty,
|
||||||
|
arg.span,
|
||||||
|
))
|
||||||
});
|
});
|
||||||
Expression::garbage(span)
|
Expression::garbage(span)
|
||||||
} else {
|
} else {
|
||||||
@ -812,8 +842,10 @@ impl<'a> ParserWorkingSet<'a> {
|
|||||||
|
|
||||||
let name = self.get_span_contents(spans[pos]);
|
let name = self.get_span_contents(spans[pos]);
|
||||||
|
|
||||||
|
let cmd_start = pos;
|
||||||
|
|
||||||
if expand_aliases {
|
if expand_aliases {
|
||||||
if let Some(expansion) = self.find_alias(name) {
|
if let Some(expansion) = self.find_alias(&name) {
|
||||||
let orig_span = spans[pos];
|
let orig_span = spans[pos];
|
||||||
//let mut spans = spans.to_vec();
|
//let mut spans = spans.to_vec();
|
||||||
let mut new_spans: Vec<Span> = vec![];
|
let mut new_spans: Vec<Span> = vec![];
|
||||||
@ -855,6 +887,39 @@ impl<'a> ParserWorkingSet<'a> {
|
|||||||
new_name.push(b' ');
|
new_name.push(b' ');
|
||||||
new_name.extend(self.get_span_contents(spans[pos]));
|
new_name.extend(self.get_span_contents(spans[pos]));
|
||||||
|
|
||||||
|
if expand_aliases {
|
||||||
|
if let Some(expansion) = self.find_alias(&new_name) {
|
||||||
|
let orig_span = spans[pos];
|
||||||
|
//let mut spans = spans.to_vec();
|
||||||
|
let mut new_spans: Vec<Span> = vec![];
|
||||||
|
new_spans.extend(&spans[0..cmd_start]);
|
||||||
|
new_spans.extend(expansion);
|
||||||
|
if spans.len() > pos {
|
||||||
|
new_spans.extend(&spans[(pos + 1)..]);
|
||||||
|
}
|
||||||
|
|
||||||
|
let (result, err) = self.parse_call(&new_spans, false);
|
||||||
|
|
||||||
|
let expression = match result {
|
||||||
|
Expression {
|
||||||
|
expr: Expr::Call(mut call),
|
||||||
|
span,
|
||||||
|
ty,
|
||||||
|
} => {
|
||||||
|
call.head = orig_span;
|
||||||
|
Expression {
|
||||||
|
expr: Expr::Call(call),
|
||||||
|
span,
|
||||||
|
ty,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
x => x,
|
||||||
|
};
|
||||||
|
|
||||||
|
return (expression, err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(did) = self.find_decl(&new_name) {
|
if let Some(did) = self.find_decl(&new_name) {
|
||||||
decl_id = did;
|
decl_id = did;
|
||||||
} else {
|
} else {
|
||||||
@ -893,7 +958,11 @@ impl<'a> ParserWorkingSet<'a> {
|
|||||||
} else {
|
} else {
|
||||||
(
|
(
|
||||||
garbage(span),
|
garbage(span),
|
||||||
Some(ParseError::Mismatch("int".into(), span)),
|
Some(ParseError::Mismatch(
|
||||||
|
"int".into(),
|
||||||
|
"incompatible int".into(),
|
||||||
|
span,
|
||||||
|
)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else if let Some(token) = token.strip_prefix("0b") {
|
} else if let Some(token) = token.strip_prefix("0b") {
|
||||||
@ -909,7 +978,11 @@ impl<'a> ParserWorkingSet<'a> {
|
|||||||
} else {
|
} else {
|
||||||
(
|
(
|
||||||
garbage(span),
|
garbage(span),
|
||||||
Some(ParseError::Mismatch("int".into(), span)),
|
Some(ParseError::Mismatch(
|
||||||
|
"int".into(),
|
||||||
|
"incompatible int".into(),
|
||||||
|
span,
|
||||||
|
)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else if let Some(token) = token.strip_prefix("0o") {
|
} else if let Some(token) = token.strip_prefix("0o") {
|
||||||
@ -925,7 +998,11 @@ impl<'a> ParserWorkingSet<'a> {
|
|||||||
} else {
|
} else {
|
||||||
(
|
(
|
||||||
garbage(span),
|
garbage(span),
|
||||||
Some(ParseError::Mismatch("int".into(), span)),
|
Some(ParseError::Mismatch(
|
||||||
|
"int".into(),
|
||||||
|
"incompatible int".into(),
|
||||||
|
span,
|
||||||
|
)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else if let Ok(x) = token.parse::<i64>() {
|
} else if let Ok(x) = token.parse::<i64>() {
|
||||||
@ -940,7 +1017,7 @@ impl<'a> ParserWorkingSet<'a> {
|
|||||||
} else {
|
} else {
|
||||||
(
|
(
|
||||||
garbage(span),
|
garbage(span),
|
||||||
Some(ParseError::Mismatch("int".into(), span)),
|
Some(ParseError::Expected("int".into(), span)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -958,7 +1035,7 @@ impl<'a> ParserWorkingSet<'a> {
|
|||||||
} else {
|
} else {
|
||||||
(
|
(
|
||||||
garbage(span),
|
garbage(span),
|
||||||
Some(ParseError::Mismatch("int".into(), span)),
|
Some(ParseError::Expected("float".into(), span)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -971,7 +1048,7 @@ impl<'a> ParserWorkingSet<'a> {
|
|||||||
} else {
|
} else {
|
||||||
(
|
(
|
||||||
garbage(span),
|
garbage(span),
|
||||||
Some(ParseError::Mismatch("number".into(), span)),
|
Some(ParseError::Expected("number".into(), span)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1242,7 +1319,7 @@ impl<'a> ParserWorkingSet<'a> {
|
|||||||
} else {
|
} else {
|
||||||
(
|
(
|
||||||
garbage(span),
|
garbage(span),
|
||||||
Some(ParseError::Mismatch("string".into(), span)),
|
Some(ParseError::Expected("string".into(), span)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1392,7 +1469,7 @@ impl<'a> ParserWorkingSet<'a> {
|
|||||||
ParseMode::TypeMode => {
|
ParseMode::TypeMode => {
|
||||||
// We're seeing two types for the same thing for some reason, error
|
// We're seeing two types for the same thing for some reason, error
|
||||||
error = error
|
error = error
|
||||||
.or_else(|| Some(ParseError::Mismatch("type".into(), span)));
|
.or_else(|| Some(ParseError::Expected("type".into(), span)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -1424,7 +1501,7 @@ impl<'a> ParserWorkingSet<'a> {
|
|||||||
|| !short_flag.ends_with(b")")
|
|| !short_flag.ends_with(b")")
|
||||||
{
|
{
|
||||||
error = error.or_else(|| {
|
error = error.or_else(|| {
|
||||||
Some(ParseError::Mismatch(
|
Some(ParseError::Expected(
|
||||||
"short flag".into(),
|
"short flag".into(),
|
||||||
span,
|
span,
|
||||||
))
|
))
|
||||||
@ -1453,7 +1530,7 @@ impl<'a> ParserWorkingSet<'a> {
|
|||||||
}));
|
}));
|
||||||
} else {
|
} else {
|
||||||
error = error.or_else(|| {
|
error = error.or_else(|| {
|
||||||
Some(ParseError::Mismatch(
|
Some(ParseError::Expected(
|
||||||
"short flag".into(),
|
"short flag".into(),
|
||||||
span,
|
span,
|
||||||
))
|
))
|
||||||
@ -1470,7 +1547,7 @@ impl<'a> ParserWorkingSet<'a> {
|
|||||||
|
|
||||||
if chars.len() > 1 {
|
if chars.len() > 1 {
|
||||||
error = error.or_else(|| {
|
error = error.or_else(|| {
|
||||||
Some(ParseError::Mismatch("short flag".into(), span))
|
Some(ParseError::Expected("short flag".into(), span))
|
||||||
});
|
});
|
||||||
|
|
||||||
args.push(Arg::Flag(Flag {
|
args.push(Arg::Flag(Flag {
|
||||||
@ -1502,7 +1579,7 @@ impl<'a> ParserWorkingSet<'a> {
|
|||||||
|
|
||||||
let short_flag = if !short_flag.ends_with(b")") {
|
let short_flag = if !short_flag.ends_with(b")") {
|
||||||
error = error.or_else(|| {
|
error = error.or_else(|| {
|
||||||
Some(ParseError::Mismatch("short flag".into(), span))
|
Some(ParseError::Expected("short flag".into(), span))
|
||||||
});
|
});
|
||||||
short_flag
|
short_flag
|
||||||
} else {
|
} else {
|
||||||
@ -1518,7 +1595,7 @@ impl<'a> ParserWorkingSet<'a> {
|
|||||||
Some(Arg::Flag(flag)) => {
|
Some(Arg::Flag(flag)) => {
|
||||||
if flag.short.is_some() {
|
if flag.short.is_some() {
|
||||||
error = error.or_else(|| {
|
error = error.or_else(|| {
|
||||||
Some(ParseError::Mismatch(
|
Some(ParseError::Expected(
|
||||||
"one short flag".into(),
|
"one short flag".into(),
|
||||||
span,
|
span,
|
||||||
))
|
))
|
||||||
@ -1529,7 +1606,7 @@ impl<'a> ParserWorkingSet<'a> {
|
|||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
error = error.or_else(|| {
|
error = error.or_else(|| {
|
||||||
Some(ParseError::Mismatch(
|
Some(ParseError::Expected(
|
||||||
"unknown flag".into(),
|
"unknown flag".into(),
|
||||||
span,
|
span,
|
||||||
))
|
))
|
||||||
@ -1538,7 +1615,7 @@ impl<'a> ParserWorkingSet<'a> {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
error = error.or_else(|| {
|
error = error.or_else(|| {
|
||||||
Some(ParseError::Mismatch("short flag".into(), span))
|
Some(ParseError::Expected("short flag".into(), span))
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else if contents.ends_with(b"?") {
|
} else if contents.ends_with(b"?") {
|
||||||
@ -1832,7 +1909,7 @@ impl<'a> ParserWorkingSet<'a> {
|
|||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
garbage(span),
|
garbage(span),
|
||||||
Some(ParseError::Mismatch("block".into(), span)),
|
Some(ParseError::Expected("block".into(), span)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if bytes.ends_with(b"}") {
|
if bytes.ends_with(b"}") {
|
||||||
@ -1902,7 +1979,7 @@ impl<'a> ParserWorkingSet<'a> {
|
|||||||
_ => {
|
_ => {
|
||||||
return (
|
return (
|
||||||
Expression::garbage(span),
|
Expression::garbage(span),
|
||||||
Some(ParseError::Mismatch("non-[] value".into(), span)),
|
Some(ParseError::Expected("non-[] value".into(), span)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1915,7 +1992,7 @@ impl<'a> ParserWorkingSet<'a> {
|
|||||||
} else {
|
} else {
|
||||||
(
|
(
|
||||||
garbage(span),
|
garbage(span),
|
||||||
Some(ParseError::Mismatch("number".into(), span)),
|
Some(ParseError::Expected("number".into(), span)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1925,7 +2002,7 @@ impl<'a> ParserWorkingSet<'a> {
|
|||||||
} else {
|
} else {
|
||||||
(
|
(
|
||||||
garbage(span),
|
garbage(span),
|
||||||
Some(ParseError::Mismatch("int".into(), span)),
|
Some(ParseError::Expected("int".into(), span)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1938,7 +2015,7 @@ impl<'a> ParserWorkingSet<'a> {
|
|||||||
} else {
|
} else {
|
||||||
(
|
(
|
||||||
Expression::garbage(span),
|
Expression::garbage(span),
|
||||||
Some(ParseError::Mismatch("table".into(), span)),
|
Some(ParseError::Expected("block".into(), span)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1948,7 +2025,7 @@ impl<'a> ParserWorkingSet<'a> {
|
|||||||
} else {
|
} else {
|
||||||
(
|
(
|
||||||
Expression::garbage(span),
|
Expression::garbage(span),
|
||||||
Some(ParseError::Mismatch("signature".into(), span)),
|
Some(ParseError::Expected("signature".into(), span)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1958,7 +2035,7 @@ impl<'a> ParserWorkingSet<'a> {
|
|||||||
} else {
|
} else {
|
||||||
(
|
(
|
||||||
Expression::garbage(span),
|
Expression::garbage(span),
|
||||||
Some(ParseError::Mismatch("list".into(), span)),
|
Some(ParseError::Expected("list".into(), span)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1968,7 +2045,7 @@ impl<'a> ParserWorkingSet<'a> {
|
|||||||
} else {
|
} else {
|
||||||
(
|
(
|
||||||
Expression::garbage(span),
|
Expression::garbage(span),
|
||||||
Some(ParseError::Mismatch("table".into(), span)),
|
Some(ParseError::Expected("table".into(), span)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1991,13 +2068,10 @@ impl<'a> ParserWorkingSet<'a> {
|
|||||||
}
|
}
|
||||||
(
|
(
|
||||||
garbage(span),
|
garbage(span),
|
||||||
Some(ParseError::Mismatch("any shape".into(), span)),
|
Some(ParseError::Expected("any shape".into(), span)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
_ => (
|
_ => (garbage(span), Some(ParseError::IncompleteParser(span))),
|
||||||
garbage(span),
|
|
||||||
Some(ParseError::Mismatch("incomplete parser".into(), span)),
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2026,7 +2100,7 @@ impl<'a> ParserWorkingSet<'a> {
|
|||||||
_ => {
|
_ => {
|
||||||
return (
|
return (
|
||||||
garbage(span),
|
garbage(span),
|
||||||
Some(ParseError::Mismatch("operator".into(), span)),
|
Some(ParseError::Expected("operator".into(), span)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -2167,7 +2241,7 @@ impl<'a> ParserWorkingSet<'a> {
|
|||||||
(None, None)
|
(None, None)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
(None, Some(ParseError::Mismatch("variable".into(), span)))
|
(None, Some(ParseError::Expected("variable".into(), span)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2175,11 +2249,8 @@ impl<'a> ParserWorkingSet<'a> {
|
|||||||
let name = self.get_span_contents(spans[0]);
|
let name = self.get_span_contents(spans[0]);
|
||||||
|
|
||||||
if name == b"def" && spans.len() >= 4 {
|
if name == b"def" && spans.len() >= 4 {
|
||||||
//FIXME: don't use expect here
|
|
||||||
let (name_expr, ..) = self.parse_string(spans[1]);
|
let (name_expr, ..) = self.parse_string(spans[1]);
|
||||||
let name = name_expr
|
let name = name_expr.as_string();
|
||||||
.as_string()
|
|
||||||
.expect("internal error: expected def name");
|
|
||||||
|
|
||||||
self.enter_scope();
|
self.enter_scope();
|
||||||
// FIXME: because parse_signature will update the scope with the variables it sees
|
// FIXME: because parse_signature will update the scope with the variables it sees
|
||||||
@ -2189,11 +2260,11 @@ impl<'a> ParserWorkingSet<'a> {
|
|||||||
// We can't reuse the first time because the variables that are created during parse_signature
|
// We can't reuse the first time because the variables that are created during parse_signature
|
||||||
// are lost when we exit the scope below.
|
// are lost when we exit the scope below.
|
||||||
let (sig, ..) = self.parse_signature(spans[2]);
|
let (sig, ..) = self.parse_signature(spans[2]);
|
||||||
let mut signature = sig
|
let signature = sig.as_signature();
|
||||||
.as_signature()
|
|
||||||
.expect("internal error: expected param list");
|
|
||||||
self.exit_scope();
|
self.exit_scope();
|
||||||
|
|
||||||
|
match (name, signature) {
|
||||||
|
(Some(name), Some(mut signature)) => {
|
||||||
signature.name = name;
|
signature.name = name;
|
||||||
let decl = Declaration {
|
let decl = Declaration {
|
||||||
signature,
|
signature,
|
||||||
@ -2202,6 +2273,9 @@ impl<'a> ParserWorkingSet<'a> {
|
|||||||
|
|
||||||
self.add_decl(decl);
|
self.add_decl(decl);
|
||||||
}
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_def(&mut self, spans: &[Span]) -> (Statement, Option<ParseError>) {
|
pub fn parse_def(&mut self, spans: &[Span]) -> (Statement, Option<ParseError>) {
|
||||||
@ -2211,30 +2285,31 @@ impl<'a> ParserWorkingSet<'a> {
|
|||||||
if name == b"def" && spans.len() >= 4 {
|
if name == b"def" && spans.len() >= 4 {
|
||||||
//FIXME: don't use expect here
|
//FIXME: don't use expect here
|
||||||
let (name_expr, err) = self.parse_string(spans[1]);
|
let (name_expr, err) = self.parse_string(spans[1]);
|
||||||
let name = name_expr
|
|
||||||
.as_string()
|
|
||||||
.expect("internal error: expected def name");
|
|
||||||
error = error.or(err);
|
error = error.or(err);
|
||||||
|
|
||||||
|
self.enter_scope();
|
||||||
|
let (sig, err) = self.parse_signature(spans[2]);
|
||||||
|
error = error.or(err);
|
||||||
|
|
||||||
|
let (block, err) = self.parse_block_expression(spans[3]);
|
||||||
|
error = error.or(err);
|
||||||
|
self.exit_scope();
|
||||||
|
|
||||||
|
let name = name_expr.as_string();
|
||||||
|
|
||||||
|
let signature = sig.as_signature();
|
||||||
|
|
||||||
|
let block_id = block.as_block();
|
||||||
|
|
||||||
|
match (name, signature, block_id) {
|
||||||
|
(Some(name), Some(mut signature), Some(block_id)) => {
|
||||||
let decl_id = self
|
let decl_id = self
|
||||||
.find_decl(name.as_bytes())
|
.find_decl(name.as_bytes())
|
||||||
.expect("internal error: predeclaration failed to add definition");
|
.expect("internal error: predeclaration failed to add definition");
|
||||||
|
|
||||||
self.enter_scope();
|
|
||||||
let (sig, err) = self.parse_signature(spans[2]);
|
|
||||||
let mut signature = sig
|
|
||||||
.as_signature()
|
|
||||||
.expect("internal error: expected param list");
|
|
||||||
signature.name = name;
|
|
||||||
error = error.or(err);
|
|
||||||
|
|
||||||
let (block, err) = self.parse_block_expression(spans[3]);
|
|
||||||
self.exit_scope();
|
|
||||||
|
|
||||||
let block_id = block.as_block().expect("internal error: expected block");
|
|
||||||
error = error.or(err);
|
|
||||||
|
|
||||||
let declaration = self.get_decl_mut(decl_id);
|
let declaration = self.get_decl_mut(decl_id);
|
||||||
|
|
||||||
|
signature.name = name;
|
||||||
declaration.signature = signature;
|
declaration.signature = signature;
|
||||||
declaration.body = Some(block_id);
|
declaration.body = Some(block_id);
|
||||||
|
|
||||||
@ -2257,6 +2332,16 @@ impl<'a> ParserWorkingSet<'a> {
|
|||||||
}),
|
}),
|
||||||
error,
|
error,
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
_ => (
|
||||||
|
Statement::Expression(Expression {
|
||||||
|
expr: Expr::Garbage,
|
||||||
|
span: span(spans),
|
||||||
|
ty: Type::Unknown,
|
||||||
|
}),
|
||||||
|
error,
|
||||||
|
),
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
(
|
(
|
||||||
Statement::Expression(Expression {
|
Statement::Expression(Expression {
|
||||||
@ -2265,7 +2350,7 @@ impl<'a> ParserWorkingSet<'a> {
|
|||||||
ty: Type::Unknown,
|
ty: Type::Unknown,
|
||||||
}),
|
}),
|
||||||
Some(ParseError::UnknownState(
|
Some(ParseError::UnknownState(
|
||||||
"internal error: let statement unparseable".into(),
|
"internal error: definition unparseable".into(),
|
||||||
span(spans),
|
span(spans),
|
||||||
)),
|
)),
|
||||||
)
|
)
|
||||||
@ -2294,7 +2379,7 @@ impl<'a> ParserWorkingSet<'a> {
|
|||||||
|
|
||||||
let replacement = spans[3..].to_vec();
|
let replacement = spans[3..].to_vec();
|
||||||
|
|
||||||
println!("{:?} {:?}", alias_name, replacement);
|
//println!("{:?} {:?}", alias_name, replacement);
|
||||||
|
|
||||||
self.add_alias(alias_name, replacement);
|
self.add_alias(alias_name, replacement);
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,15 @@
|
|||||||
use crate::{parser::Operator, parser_state::Type, Expr, Expression, ParseError, ParserWorkingSet};
|
use crate::{parser::Operator, parser_state::Type, Expr, Expression, ParseError, ParserWorkingSet};
|
||||||
|
|
||||||
impl<'a> ParserWorkingSet<'a> {
|
impl<'a> ParserWorkingSet<'a> {
|
||||||
|
pub fn type_compatible(lhs: &Type, rhs: &Type) -> bool {
|
||||||
|
match (lhs, rhs) {
|
||||||
|
(Type::List(c), Type::List(d)) => ParserWorkingSet::type_compatible(c, d),
|
||||||
|
(Type::Unknown, _) => true,
|
||||||
|
(_, Type::Unknown) => true,
|
||||||
|
(lhs, rhs) => lhs == rhs,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn math_result_type(
|
pub fn math_result_type(
|
||||||
&self,
|
&self,
|
||||||
lhs: &mut Expression,
|
lhs: &mut Expression,
|
||||||
@ -18,7 +27,13 @@ impl<'a> ParserWorkingSet<'a> {
|
|||||||
*op = Expression::garbage(op.span);
|
*op = Expression::garbage(op.span);
|
||||||
(
|
(
|
||||||
Type::Unknown,
|
Type::Unknown,
|
||||||
Some(ParseError::Mismatch("math".into(), op.span)),
|
Some(ParseError::UnsupportedOperation(
|
||||||
|
op.span,
|
||||||
|
lhs.span,
|
||||||
|
lhs.ty.clone(),
|
||||||
|
rhs.span,
|
||||||
|
rhs.ty.clone(),
|
||||||
|
)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -31,30 +46,50 @@ impl<'a> ParserWorkingSet<'a> {
|
|||||||
*rhs = Expression::garbage(rhs.span);
|
*rhs = Expression::garbage(rhs.span);
|
||||||
(
|
(
|
||||||
Type::Unknown,
|
Type::Unknown,
|
||||||
Some(ParseError::Mismatch("int".into(), rhs.span)),
|
Some(ParseError::UnsupportedOperation(
|
||||||
|
op.span,
|
||||||
|
lhs.span,
|
||||||
|
lhs.ty.clone(),
|
||||||
|
rhs.span,
|
||||||
|
rhs.ty.clone(),
|
||||||
|
)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
*op = Expression::garbage(op.span);
|
*op = Expression::garbage(op.span);
|
||||||
(
|
(
|
||||||
Type::Unknown,
|
Type::Unknown,
|
||||||
Some(ParseError::Mismatch("math".into(), op.span)),
|
Some(ParseError::UnsupportedOperation(
|
||||||
|
op.span,
|
||||||
|
lhs.span,
|
||||||
|
lhs.ty.clone(),
|
||||||
|
rhs.span,
|
||||||
|
rhs.ty.clone(),
|
||||||
|
)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
*op = Expression::garbage(op.span);
|
*op = Expression::garbage(op.span);
|
||||||
|
|
||||||
(
|
(
|
||||||
Type::Unknown,
|
Type::Unknown,
|
||||||
Some(ParseError::Mismatch("math".into(), op.span)),
|
Some(ParseError::UnsupportedOperation(
|
||||||
|
op.span,
|
||||||
|
lhs.span,
|
||||||
|
lhs.ty.clone(),
|
||||||
|
rhs.span,
|
||||||
|
rhs.ty.clone(),
|
||||||
|
)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
*op = Expression::garbage(op.span);
|
*op = Expression::garbage(op.span);
|
||||||
|
|
||||||
(
|
(
|
||||||
Type::Unknown,
|
Type::Unknown,
|
||||||
Some(ParseError::Mismatch("operator".into(), op.span)),
|
Some(ParseError::IncompleteMathExpression(op.span)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user