mirror of
https://github.com/nushell/nushell.git
synced 2025-01-03 13:00:08 +01:00
fix clippy, add strings and concat
This commit is contained in:
parent
a8366ebf15
commit
2eeceae613
@ -6,5 +6,5 @@ edition = "2018"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
reedline = {path = "../reedline"}
|
||||
reedline = {git = "https://github.com/jntrnr/reedline"}
|
||||
nu-ansi-term = "0.32.0"
|
@ -2,6 +2,6 @@ use crate::{BlockId, Signature};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Declaration {
|
||||
pub signature: Signature,
|
||||
pub signature: Box<Signature>,
|
||||
pub body: Option<BlockId>,
|
||||
}
|
||||
|
92
src/eval.rs
92
src/eval.rs
@ -27,6 +27,11 @@ impl Value {
|
||||
val: lhs + rhs,
|
||||
span: Span::unknown(),
|
||||
}),
|
||||
(Value::String { val: lhs, .. }, Value::String { val: rhs, .. }) => Ok(Value::String {
|
||||
val: lhs.to_string() + rhs,
|
||||
span: Span::unknown(),
|
||||
}),
|
||||
|
||||
_ => Ok(Value::Unknown),
|
||||
}
|
||||
}
|
||||
@ -87,56 +92,54 @@ fn eval_call(state: &State, stack: &mut Stack, call: &Call) -> Result<Value, She
|
||||
}
|
||||
let block = state.parser_state.get_block(block_id);
|
||||
eval_block(state, stack, block)
|
||||
} else {
|
||||
if decl.signature.name == "let" {
|
||||
let var_id = call.positional[0]
|
||||
.as_var()
|
||||
.expect("internal error: missing variable");
|
||||
} else if decl.signature.name == "let" {
|
||||
let var_id = call.positional[0]
|
||||
.as_var()
|
||||
.expect("internal error: missing variable");
|
||||
|
||||
let keyword_expr = call.positional[1]
|
||||
.as_keyword()
|
||||
.expect("internal error: missing keyword");
|
||||
let keyword_expr = call.positional[1]
|
||||
.as_keyword()
|
||||
.expect("internal error: missing keyword");
|
||||
|
||||
let rhs = eval_expression(state, stack, keyword_expr)?;
|
||||
let rhs = eval_expression(state, stack, keyword_expr)?;
|
||||
|
||||
println!("Adding: {:?} to {}", rhs, var_id);
|
||||
println!("Adding: {:?} to {}", rhs, var_id);
|
||||
|
||||
stack.add_var(var_id, rhs);
|
||||
Ok(Value::Unknown)
|
||||
} else if decl.signature.name == "if" {
|
||||
let cond = &call.positional[0];
|
||||
let then_block = call.positional[1]
|
||||
.as_block()
|
||||
.expect("internal error: expected block");
|
||||
let else_case = call.positional.get(2);
|
||||
stack.add_var(var_id, rhs);
|
||||
Ok(Value::Unknown)
|
||||
} else if decl.signature.name == "if" {
|
||||
let cond = &call.positional[0];
|
||||
let then_block = call.positional[1]
|
||||
.as_block()
|
||||
.expect("internal error: expected block");
|
||||
let else_case = call.positional.get(2);
|
||||
|
||||
let result = eval_expression(state, stack, cond)?;
|
||||
match result {
|
||||
Value::Bool { val, .. } => {
|
||||
if val {
|
||||
let block = state.parser_state.get_block(then_block);
|
||||
eval_block(state, stack, block)
|
||||
} else if let Some(else_case) = else_case {
|
||||
println!("{:?}", else_case);
|
||||
if let Some(else_expr) = else_case.as_keyword() {
|
||||
if let Some(block_id) = else_expr.as_block() {
|
||||
let block = state.parser_state.get_block(block_id);
|
||||
eval_block(state, stack, block)
|
||||
} else {
|
||||
eval_expression(state, stack, else_expr)
|
||||
}
|
||||
let result = eval_expression(state, stack, cond)?;
|
||||
match result {
|
||||
Value::Bool { val, .. } => {
|
||||
if val {
|
||||
let block = state.parser_state.get_block(then_block);
|
||||
eval_block(state, stack, block)
|
||||
} else if let Some(else_case) = else_case {
|
||||
println!("{:?}", else_case);
|
||||
if let Some(else_expr) = else_case.as_keyword() {
|
||||
if let Some(block_id) = else_expr.as_block() {
|
||||
let block = state.parser_state.get_block(block_id);
|
||||
eval_block(state, stack, block)
|
||||
} else {
|
||||
eval_expression(state, stack, else_case)
|
||||
eval_expression(state, stack, else_expr)
|
||||
}
|
||||
} else {
|
||||
Ok(Value::Unknown)
|
||||
eval_expression(state, stack, else_case)
|
||||
}
|
||||
} else {
|
||||
Ok(Value::Unknown)
|
||||
}
|
||||
_ => Err(ShellError::Mismatch("bool".into(), Span::unknown())),
|
||||
}
|
||||
} else {
|
||||
Ok(Value::Unknown)
|
||||
_ => Err(ShellError::Mismatch("bool".into(), Span::unknown())),
|
||||
}
|
||||
} else {
|
||||
Ok(Value::Unknown)
|
||||
}
|
||||
}
|
||||
|
||||
@ -159,9 +162,9 @@ pub fn eval_expression(
|
||||
Expr::ExternalCall(_, _) => Err(ShellError::Unsupported(expr.span)),
|
||||
Expr::Operator(_) => Ok(Value::Unknown),
|
||||
Expr::BinaryOp(lhs, op, rhs) => {
|
||||
let lhs = eval_expression(state, stack, &lhs)?;
|
||||
let op = eval_operator(state, stack, &op)?;
|
||||
let rhs = eval_expression(state, stack, &rhs)?;
|
||||
let lhs = eval_expression(state, stack, lhs)?;
|
||||
let op = eval_operator(state, stack, op)?;
|
||||
let rhs = eval_expression(state, stack, rhs)?;
|
||||
|
||||
match op {
|
||||
Operator::Plus => lhs.add(&rhs),
|
||||
@ -197,11 +200,8 @@ pub fn eval_block(state: &State, stack: &mut Stack, block: &Block) -> Result<Val
|
||||
let mut last = Ok(Value::Unknown);
|
||||
|
||||
for stmt in &block.stmts {
|
||||
match stmt {
|
||||
Statement::Expression(expression) => {
|
||||
last = Ok(eval_expression(state, stack, expression)?);
|
||||
}
|
||||
_ => {}
|
||||
if let Statement::Expression(expression) = stmt {
|
||||
last = Ok(eval_expression(state, stack, expression)?);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -35,15 +35,14 @@ impl<'a> ParserWorkingSet<'a> {
|
||||
match &expr.expr {
|
||||
Expr::BinaryOp(lhs, op, rhs) => {
|
||||
let mut output = vec![];
|
||||
output.extend(self.flatten_expression(&lhs));
|
||||
output.extend(self.flatten_expression(&op));
|
||||
output.extend(self.flatten_expression(&rhs));
|
||||
output.extend(self.flatten_expression(lhs));
|
||||
output.extend(self.flatten_expression(op));
|
||||
output.extend(self.flatten_expression(rhs));
|
||||
output
|
||||
}
|
||||
Expr::Block(block_id) => self.flatten_block(self.get_block(*block_id)),
|
||||
Expr::Call(call) => {
|
||||
let mut output = vec![];
|
||||
output.push((call.head, FlatShape::InternalCall));
|
||||
let mut output = vec![(call.head, FlatShape::InternalCall)];
|
||||
for positional in &call.positional {
|
||||
output.extend(self.flatten_expression(positional));
|
||||
}
|
||||
|
@ -163,7 +163,13 @@ pub fn lex_item(
|
||||
// synthetic closing characters to the accumulated token.
|
||||
if let Some(block) = block_level.last() {
|
||||
let delim = block.closing();
|
||||
let cause = ParseError::UnexpectedEof((delim as char).to_string(), span);
|
||||
let cause = ParseError::UnexpectedEof(
|
||||
(delim as char).to_string(),
|
||||
Span {
|
||||
start: span.end - 1,
|
||||
end: span.end,
|
||||
},
|
||||
);
|
||||
|
||||
return (span, Some(cause));
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ mod span;
|
||||
mod syntax_highlight;
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
mod type_check;
|
||||
|
||||
pub use declaration::Declaration;
|
||||
pub use eval::{eval_block, eval_expression, Stack, State};
|
||||
|
@ -163,7 +163,7 @@ fn main() -> std::io::Result<()> {
|
||||
println!("Error: {:?}", err);
|
||||
continue;
|
||||
}
|
||||
// println!("Error: {:?}", err);
|
||||
println!("Error: {:?}", err);
|
||||
(output, working_set.render())
|
||||
};
|
||||
|
||||
|
279
src/parser.rs
279
src/parser.rs
@ -173,7 +173,7 @@ pub enum Expr {
|
||||
Table(Vec<Expression>, Vec<Vec<Expression>>),
|
||||
Keyword(Vec<u8>, Box<Expression>),
|
||||
String(String), // FIXME: improve this in the future?
|
||||
Signature(Signature),
|
||||
Signature(Box<Signature>),
|
||||
Garbage,
|
||||
}
|
||||
|
||||
@ -225,7 +225,7 @@ impl Expression {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_signature(&self) -> Option<Signature> {
|
||||
pub fn as_signature(&self) -> Option<Box<Signature>> {
|
||||
match &self.expr {
|
||||
Expr::Signature(sig) => Some(sig.clone()),
|
||||
_ => None,
|
||||
@ -502,10 +502,7 @@ impl<'a> ParserWorkingSet<'a> {
|
||||
if positional.shape == SyntaxShape::Int
|
||||
|| positional.shape == SyntaxShape::Number
|
||||
{
|
||||
if String::from_utf8_lossy(&arg_contents)
|
||||
.parse::<f64>()
|
||||
.is_ok()
|
||||
{
|
||||
if String::from_utf8_lossy(arg_contents).parse::<f64>().is_ok() {
|
||||
return (None, None);
|
||||
} else if let Some(first) = unmatched_short_flags.first() {
|
||||
error = error.or(Some(ParseError::UnknownFlag(*first)));
|
||||
@ -547,21 +544,20 @@ impl<'a> ParserWorkingSet<'a> {
|
||||
|
||||
let mut next_keyword_idx = spans.len();
|
||||
for idx in (positional_idx + 1)..decl.signature.num_positionals() {
|
||||
match decl.signature.get_positional(idx) {
|
||||
Some(PositionalArg {
|
||||
shape: SyntaxShape::Keyword(kw, ..),
|
||||
..
|
||||
}) => {
|
||||
for span_idx in spans_idx..spans.len() {
|
||||
let contents = self.get_span_contents(spans[span_idx]);
|
||||
if let Some(PositionalArg {
|
||||
shape: SyntaxShape::Keyword(kw, ..),
|
||||
..
|
||||
}) = decl.signature.get_positional(idx)
|
||||
{
|
||||
#[allow(clippy::needless_range_loop)]
|
||||
for span_idx in spans_idx..spans.len() {
|
||||
let contents = self.get_span_contents(spans[span_idx]);
|
||||
|
||||
if contents == kw {
|
||||
next_keyword_idx = span_idx - (idx - (positional_idx + 1));
|
||||
break;
|
||||
}
|
||||
if contents == kw {
|
||||
next_keyword_idx = span_idx - (idx - (positional_idx + 1));
|
||||
break;
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
@ -575,8 +571,8 @@ impl<'a> ParserWorkingSet<'a> {
|
||||
let end = [next_keyword_idx, remainder_idx, spans.len()]
|
||||
.iter()
|
||||
.min()
|
||||
.expect("internal error: can't find min")
|
||||
.clone();
|
||||
.copied()
|
||||
.expect("internal error: can't find min");
|
||||
|
||||
// println!(
|
||||
// "{:?}",
|
||||
@ -633,17 +629,19 @@ impl<'a> ParserWorkingSet<'a> {
|
||||
// go ahead and override the current error and tell the user about the missing
|
||||
// keyword/literal.
|
||||
error = Some(ParseError::Mismatch(
|
||||
String::from_utf8_lossy(&keyword).into(),
|
||||
String::from_utf8_lossy(keyword).into(),
|
||||
arg_span,
|
||||
))
|
||||
}
|
||||
|
||||
*spans_idx += 1;
|
||||
if *spans_idx >= spans.len() {
|
||||
error = error.or(Some(ParseError::MissingPositional(
|
||||
String::from_utf8_lossy(&keyword).into(),
|
||||
spans[*spans_idx - 1],
|
||||
)));
|
||||
error = error.or_else(|| {
|
||||
Some(ParseError::MissingPositional(
|
||||
String::from_utf8_lossy(keyword).into(),
|
||||
spans[*spans_idx - 1],
|
||||
))
|
||||
});
|
||||
return (
|
||||
Expression {
|
||||
expr: Expr::Keyword(
|
||||
@ -656,7 +654,7 @@ impl<'a> ParserWorkingSet<'a> {
|
||||
error,
|
||||
);
|
||||
}
|
||||
let (expr, err) = self.parse_multispan_value(&spans, spans_idx, arg);
|
||||
let (expr, err) = self.parse_multispan_value(spans, spans_idx, arg);
|
||||
error = error.or(err);
|
||||
let ty = expr.ty.clone();
|
||||
|
||||
@ -669,11 +667,11 @@ impl<'a> ParserWorkingSet<'a> {
|
||||
error,
|
||||
)
|
||||
}
|
||||
x => {
|
||||
_ => {
|
||||
// All other cases are single-span values
|
||||
let arg_span = spans[*spans_idx];
|
||||
|
||||
let (arg, err) = self.parse_value(arg_span, &shape);
|
||||
let (arg, err) = self.parse_value(arg_span, shape);
|
||||
error = error.or(err);
|
||||
|
||||
(arg, error)
|
||||
@ -756,10 +754,9 @@ impl<'a> ParserWorkingSet<'a> {
|
||||
&& arg.ty != positional.shape.to_type()
|
||||
{
|
||||
let span = span(&spans[orig_idx..spans_idx]);
|
||||
error = error.or(Some(ParseError::TypeMismatch(
|
||||
positional.shape.to_type(),
|
||||
span,
|
||||
)));
|
||||
error = error.or_else(|| {
|
||||
Some(ParseError::TypeMismatch(positional.shape.to_type(), span))
|
||||
});
|
||||
Expression::garbage(span)
|
||||
} else {
|
||||
arg
|
||||
@ -940,8 +937,12 @@ impl<'a> ParserWorkingSet<'a> {
|
||||
// this seems okay to set it to unknown here, but we should double-check
|
||||
let id = self.add_variable(name, Type::Unknown);
|
||||
(
|
||||
Expression::garbage(span),
|
||||
Some(ParseError::VariableNotFound(span)),
|
||||
Expression {
|
||||
expr: Expr::Var(id),
|
||||
span,
|
||||
ty: Type::Unknown,
|
||||
},
|
||||
None,
|
||||
)
|
||||
}
|
||||
} else {
|
||||
@ -978,7 +979,7 @@ impl<'a> ParserWorkingSet<'a> {
|
||||
|
||||
let source = self.get_span_contents(span);
|
||||
|
||||
let (output, err) = lex(&source, start, &[], &[]);
|
||||
let (output, err) = lex(source, start, &[], &[]);
|
||||
error = error.or(err);
|
||||
|
||||
let (output, err) = lite_parse(&output);
|
||||
@ -1001,6 +1002,13 @@ impl<'a> ParserWorkingSet<'a> {
|
||||
|
||||
pub fn parse_string(&mut self, span: Span) -> (Expression, Option<ParseError>) {
|
||||
let bytes = self.get_span_contents(span);
|
||||
let bytes = if (bytes.starts_with(b"\"") && bytes.ends_with(b"\"") && bytes.len() > 1)
|
||||
|| (bytes.starts_with(b"\'") && bytes.ends_with(b"\'") && bytes.len() > 1)
|
||||
{
|
||||
&bytes[1..(bytes.len() - 1)]
|
||||
} else {
|
||||
bytes
|
||||
};
|
||||
|
||||
if let Ok(token) = String::from_utf8(bytes.into()) {
|
||||
(
|
||||
@ -1144,7 +1152,7 @@ impl<'a> ParserWorkingSet<'a> {
|
||||
let span = Span { start, end };
|
||||
let source = self.get_span_contents(span);
|
||||
|
||||
let (output, err) = lex(&source, span.start, &[b'\n', b','], &[b':']);
|
||||
let (output, err) = lex(source, span.start, &[b'\n', b','], &[b':']);
|
||||
error = error.or(err);
|
||||
|
||||
let mut args: Vec<Arg> = vec![];
|
||||
@ -1166,7 +1174,8 @@ impl<'a> ParserWorkingSet<'a> {
|
||||
}
|
||||
ParseMode::TypeMode => {
|
||||
// We're seeing two types for the same thing for some reason, error
|
||||
error = error.or(Some(ParseError::Mismatch("type".into(), span)));
|
||||
error = error
|
||||
.or_else(|| Some(ParseError::Mismatch("type".into(), span)));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -1197,17 +1206,19 @@ impl<'a> ParserWorkingSet<'a> {
|
||||
let short_flag = if !short_flag.starts_with(b"-")
|
||||
|| !short_flag.ends_with(b")")
|
||||
{
|
||||
error = error.or(Some(ParseError::Mismatch(
|
||||
"short flag".into(),
|
||||
span,
|
||||
)));
|
||||
error = error.or_else(|| {
|
||||
Some(ParseError::Mismatch(
|
||||
"short flag".into(),
|
||||
span,
|
||||
))
|
||||
});
|
||||
short_flag
|
||||
} else {
|
||||
&short_flag[1..(short_flag.len() - 1)]
|
||||
};
|
||||
|
||||
let short_flag =
|
||||
String::from_utf8_lossy(&short_flag).to_string();
|
||||
String::from_utf8_lossy(short_flag).to_string();
|
||||
let chars: Vec<char> = short_flag.chars().collect();
|
||||
let long = String::from_utf8_lossy(&flags[0]).to_string();
|
||||
let variable_name = flags[0][2..].to_vec();
|
||||
@ -1224,10 +1235,12 @@ impl<'a> ParserWorkingSet<'a> {
|
||||
var_id: Some(var_id),
|
||||
}));
|
||||
} else {
|
||||
error = error.or(Some(ParseError::Mismatch(
|
||||
"short flag".into(),
|
||||
span,
|
||||
)));
|
||||
error = error.or_else(|| {
|
||||
Some(ParseError::Mismatch(
|
||||
"short flag".into(),
|
||||
span,
|
||||
))
|
||||
});
|
||||
}
|
||||
}
|
||||
} else if contents.starts_with(b"-") && contents.len() > 1 {
|
||||
@ -1239,10 +1252,9 @@ impl<'a> ParserWorkingSet<'a> {
|
||||
let chars: Vec<char> = short_flag.chars().collect();
|
||||
|
||||
if chars.len() > 1 {
|
||||
error = error.or(Some(ParseError::Mismatch(
|
||||
"short flag".into(),
|
||||
span,
|
||||
)));
|
||||
error = error.or_else(|| {
|
||||
Some(ParseError::Mismatch("short flag".into(), span))
|
||||
});
|
||||
|
||||
args.push(Arg::Flag(Flag {
|
||||
arg: None,
|
||||
@ -1272,10 +1284,9 @@ impl<'a> ParserWorkingSet<'a> {
|
||||
let short_flag = &contents[2..];
|
||||
|
||||
let short_flag = if !short_flag.ends_with(b")") {
|
||||
error = error.or(Some(ParseError::Mismatch(
|
||||
"short flag".into(),
|
||||
span,
|
||||
)));
|
||||
error = error.or_else(|| {
|
||||
Some(ParseError::Mismatch("short flag".into(), span))
|
||||
});
|
||||
short_flag
|
||||
} else {
|
||||
&short_flag[..(short_flag.len() - 1)]
|
||||
@ -1289,62 +1300,62 @@ impl<'a> ParserWorkingSet<'a> {
|
||||
match args.last_mut() {
|
||||
Some(Arg::Flag(flag)) => {
|
||||
if flag.short.is_some() {
|
||||
error = error.or(Some(ParseError::Mismatch(
|
||||
"one short flag".into(),
|
||||
span,
|
||||
)));
|
||||
error = error.or_else(|| {
|
||||
Some(ParseError::Mismatch(
|
||||
"one short flag".into(),
|
||||
span,
|
||||
))
|
||||
});
|
||||
} else {
|
||||
flag.short = Some(chars[0]);
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
error = error.or(Some(ParseError::Mismatch(
|
||||
"unknown flag".into(),
|
||||
span,
|
||||
)));
|
||||
error = error.or_else(|| {
|
||||
Some(ParseError::Mismatch(
|
||||
"unknown flag".into(),
|
||||
span,
|
||||
))
|
||||
});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
error = error.or(Some(ParseError::Mismatch(
|
||||
"short flag".into(),
|
||||
span,
|
||||
)));
|
||||
error = error.or_else(|| {
|
||||
Some(ParseError::Mismatch("short flag".into(), span))
|
||||
});
|
||||
}
|
||||
} else if contents.ends_with(b"?") {
|
||||
let contents: Vec<_> = contents[..(contents.len() - 1)].into();
|
||||
let name = String::from_utf8_lossy(&contents).to_string();
|
||||
|
||||
let var_id = self.add_variable(contents, Type::Unknown);
|
||||
|
||||
// Positional arg, optional
|
||||
args.push(Arg::Positional(
|
||||
PositionalArg {
|
||||
desc: String::new(),
|
||||
name,
|
||||
shape: SyntaxShape::Any,
|
||||
var_id: Some(var_id),
|
||||
},
|
||||
false,
|
||||
))
|
||||
} else {
|
||||
if contents.ends_with(b"?") {
|
||||
let contents: Vec<_> =
|
||||
contents[..(contents.len() - 1)].into();
|
||||
let name = String::from_utf8_lossy(&contents).to_string();
|
||||
let name = String::from_utf8_lossy(contents).to_string();
|
||||
let contents_vec = contents.to_vec();
|
||||
|
||||
let var_id =
|
||||
self.add_variable(contents.into(), Type::Unknown);
|
||||
let var_id = self.add_variable(contents_vec, Type::Unknown);
|
||||
|
||||
// Positional arg, optional
|
||||
args.push(Arg::Positional(
|
||||
PositionalArg {
|
||||
desc: String::new(),
|
||||
name,
|
||||
shape: SyntaxShape::Any,
|
||||
var_id: Some(var_id),
|
||||
},
|
||||
false,
|
||||
))
|
||||
} else {
|
||||
let name = String::from_utf8_lossy(contents).to_string();
|
||||
let contents_vec = contents.to_vec();
|
||||
let var_id = self.add_variable(contents_vec, Type::Unknown);
|
||||
|
||||
// Positional arg, required
|
||||
args.push(Arg::Positional(
|
||||
PositionalArg {
|
||||
desc: String::new(),
|
||||
name,
|
||||
shape: SyntaxShape::Any,
|
||||
var_id: Some(var_id),
|
||||
},
|
||||
true,
|
||||
))
|
||||
}
|
||||
// Positional arg, required
|
||||
args.push(Arg::Positional(
|
||||
PositionalArg {
|
||||
desc: String::new(),
|
||||
name,
|
||||
shape: SyntaxShape::Any,
|
||||
var_id: Some(var_id),
|
||||
},
|
||||
true,
|
||||
))
|
||||
}
|
||||
}
|
||||
ParseMode::TypeMode => {
|
||||
@ -1387,13 +1398,13 @@ impl<'a> ParserWorkingSet<'a> {
|
||||
match last {
|
||||
Arg::Flag(flag) => {
|
||||
if !flag.desc.is_empty() {
|
||||
flag.desc.push_str("\n");
|
||||
flag.desc.push('\n');
|
||||
}
|
||||
flag.desc.push_str(&contents);
|
||||
}
|
||||
Arg::Positional(positional, ..) => {
|
||||
if !positional.desc.is_empty() {
|
||||
positional.desc.push_str("\n");
|
||||
positional.desc.push('\n');
|
||||
}
|
||||
positional.desc.push_str(&contents);
|
||||
}
|
||||
@ -1431,7 +1442,7 @@ impl<'a> ParserWorkingSet<'a> {
|
||||
|
||||
(
|
||||
Expression {
|
||||
expr: Expr::Signature(sig),
|
||||
expr: Expr::Signature(Box::new(sig)),
|
||||
span,
|
||||
ty: Type::Unknown,
|
||||
},
|
||||
@ -1471,7 +1482,7 @@ impl<'a> ParserWorkingSet<'a> {
|
||||
let span = Span { start, end };
|
||||
let source = self.get_span_contents(span);
|
||||
|
||||
let (output, err) = lex(&source, span.start, &[b'\n', b','], &[]);
|
||||
let (output, err) = lex(source, span.start, &[b'\n', b','], &[]);
|
||||
error = error.or(err);
|
||||
|
||||
let (output, err) = lite_parse(&output);
|
||||
@ -1533,7 +1544,7 @@ impl<'a> ParserWorkingSet<'a> {
|
||||
|
||||
let source = self.get_span_contents(span);
|
||||
|
||||
let (output, err) = lex(&source, start, &[b'\n', b','], &[]);
|
||||
let (output, err) = lex(source, start, &[b'\n', b','], &[]);
|
||||
error = error.or(err);
|
||||
|
||||
let (output, err) = lite_parse(&output);
|
||||
@ -1625,7 +1636,7 @@ impl<'a> ParserWorkingSet<'a> {
|
||||
|
||||
let source = self.get_span_contents(span);
|
||||
|
||||
let (output, err) = lex(&source, start, &[], &[]);
|
||||
let (output, err) = lex(source, start, &[], &[]);
|
||||
error = error.or(err);
|
||||
|
||||
let (output, err) = lite_parse(&output);
|
||||
@ -1726,7 +1737,7 @@ impl<'a> ParserWorkingSet<'a> {
|
||||
}
|
||||
SyntaxShape::List(elem) => {
|
||||
if bytes.starts_with(b"[") {
|
||||
self.parse_list_expression(span, &elem)
|
||||
self.parse_list_expression(span, elem)
|
||||
} else {
|
||||
(
|
||||
Expression::garbage(span),
|
||||
@ -1919,64 +1930,12 @@ impl<'a> ParserWorkingSet<'a> {
|
||||
(output, error)
|
||||
}
|
||||
|
||||
pub fn math_result_type(
|
||||
&self,
|
||||
lhs: &mut Expression,
|
||||
op: &mut Expression,
|
||||
rhs: &mut Expression,
|
||||
) -> (Type, Option<ParseError>) {
|
||||
match &op.expr {
|
||||
Expr::Operator(operator) => match operator {
|
||||
Operator::Plus => match (&lhs.ty, &rhs.ty) {
|
||||
(Type::Int, Type::Int) => (Type::Int, None),
|
||||
(Type::Unknown, _) => (Type::Unknown, None),
|
||||
(_, Type::Unknown) => (Type::Unknown, None),
|
||||
(Type::Int, _) => {
|
||||
*rhs = Expression::garbage(rhs.span);
|
||||
(
|
||||
Type::Unknown,
|
||||
Some(ParseError::Mismatch("int".into(), rhs.span)),
|
||||
)
|
||||
}
|
||||
(_, Type::Int) => {
|
||||
*lhs = Expression::garbage(lhs.span);
|
||||
(
|
||||
Type::Unknown,
|
||||
Some(ParseError::Mismatch("int".into(), lhs.span)),
|
||||
)
|
||||
}
|
||||
_ => {
|
||||
*op = Expression::garbage(op.span);
|
||||
(
|
||||
Type::Unknown,
|
||||
Some(ParseError::Mismatch("math".into(), op.span)),
|
||||
)
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
*op = Expression::garbage(op.span);
|
||||
(
|
||||
Type::Unknown,
|
||||
Some(ParseError::Mismatch("math".into(), op.span)),
|
||||
)
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
*op = Expression::garbage(op.span);
|
||||
(
|
||||
Type::Unknown,
|
||||
Some(ParseError::Mismatch("operator".into(), op.span)),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_expression(&mut self, spans: &[Span]) -> (Expression, Option<ParseError>) {
|
||||
let bytes = self.get_span_contents(spans[0]);
|
||||
|
||||
match bytes[0] {
|
||||
b'0' | b'1' | b'2' | b'3' | b'4' | b'5' | b'6' | b'7' | b'8' | b'9' | b'(' | b'{'
|
||||
| b'[' | b'$' => self.parse_math_expression(spans),
|
||||
| b'[' | b'$' | b'"' | b'\'' => self.parse_math_expression(spans),
|
||||
_ => self.parse_call(spans),
|
||||
}
|
||||
}
|
||||
@ -2166,7 +2125,7 @@ impl<'a> ParserWorkingSet<'a> {
|
||||
|
||||
self.add_file(fname.into(), contents);
|
||||
|
||||
let (output, err) = lex(&contents, span_offset, &[], &[]);
|
||||
let (output, err) = lex(contents, span_offset, &[], &[]);
|
||||
error = error.or(err);
|
||||
|
||||
let (output, err) = lite_parse(&output);
|
||||
@ -2183,7 +2142,7 @@ impl<'a> ParserWorkingSet<'a> {
|
||||
|
||||
let span_offset = self.next_span_start();
|
||||
|
||||
self.add_file("source".into(), source.into());
|
||||
self.add_file("source".into(), source);
|
||||
|
||||
let (output, err) = lex(source, span_offset, &[], &[]);
|
||||
error = error.or(err);
|
||||
|
@ -347,9 +347,14 @@ impl<'a> ParserWorkingSet<'a> {
|
||||
None
|
||||
}
|
||||
|
||||
pub fn add_variable(&mut self, name: Vec<u8>, ty: Type) -> VarId {
|
||||
pub fn add_variable(&mut self, mut name: Vec<u8>, ty: Type) -> VarId {
|
||||
let next_id = self.next_var_id();
|
||||
|
||||
// correct name if necessary
|
||||
if !name.starts_with(b"$") {
|
||||
name.insert(0, b'$');
|
||||
}
|
||||
|
||||
let last = self
|
||||
.delta
|
||||
.scope
|
||||
|
@ -203,21 +203,15 @@ impl Signature {
|
||||
let mut total = self.required_positional.len() + self.optional_positional.len();
|
||||
|
||||
for positional in &self.required_positional {
|
||||
match positional.shape {
|
||||
SyntaxShape::Keyword(..) => {
|
||||
// Keywords have a required argument, so account for that
|
||||
total += 1;
|
||||
}
|
||||
_ => {}
|
||||
if let SyntaxShape::Keyword(..) = positional.shape {
|
||||
// Keywords have a required argument, so account for that
|
||||
total += 1;
|
||||
}
|
||||
}
|
||||
for positional in &self.optional_positional {
|
||||
match positional.shape {
|
||||
SyntaxShape::Keyword(..) => {
|
||||
// Keywords have a required argument, so account for that
|
||||
total += 1;
|
||||
}
|
||||
_ => {}
|
||||
if let SyntaxShape::Keyword(..) = positional.shape {
|
||||
// Keywords have a required argument, so account for that
|
||||
total += 1;
|
||||
}
|
||||
}
|
||||
total
|
||||
@ -285,10 +279,19 @@ impl Signature {
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<Declaration> for Signature {
|
||||
fn into(self) -> Declaration {
|
||||
impl From<Box<Signature>> for Declaration {
|
||||
fn from(val: Box<Signature>) -> Self {
|
||||
Declaration {
|
||||
signature: self,
|
||||
signature: val,
|
||||
body: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Signature> for Declaration {
|
||||
fn from(val: Signature) -> Self {
|
||||
Declaration {
|
||||
signature: Box::new(val),
|
||||
body: None,
|
||||
}
|
||||
}
|
||||
|
49
src/type_check.rs
Normal file
49
src/type_check.rs
Normal file
@ -0,0 +1,49 @@
|
||||
use crate::{parser::Operator, parser_state::Type, Expr, Expression, ParseError, ParserWorkingSet};
|
||||
|
||||
impl<'a> ParserWorkingSet<'a> {
|
||||
pub fn math_result_type(
|
||||
&self,
|
||||
lhs: &mut Expression,
|
||||
op: &mut Expression,
|
||||
rhs: &mut Expression,
|
||||
) -> (Type, Option<ParseError>) {
|
||||
match &op.expr {
|
||||
Expr::Operator(operator) => match operator {
|
||||
Operator::Plus => match (&lhs.ty, &rhs.ty) {
|
||||
(Type::Int, Type::Int) => (Type::Int, None),
|
||||
(Type::String, Type::String) => (Type::String, None),
|
||||
(Type::Unknown, _) => (Type::Unknown, None),
|
||||
(_, Type::Unknown) => (Type::Unknown, None),
|
||||
(Type::Int, _) => {
|
||||
*rhs = Expression::garbage(rhs.span);
|
||||
(
|
||||
Type::Unknown,
|
||||
Some(ParseError::Mismatch("int".into(), rhs.span)),
|
||||
)
|
||||
}
|
||||
_ => {
|
||||
*op = Expression::garbage(op.span);
|
||||
(
|
||||
Type::Unknown,
|
||||
Some(ParseError::Mismatch("math".into(), op.span)),
|
||||
)
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
*op = Expression::garbage(op.span);
|
||||
(
|
||||
Type::Unknown,
|
||||
Some(ParseError::Mismatch("math".into(), op.span)),
|
||||
)
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
*op = Expression::garbage(op.span);
|
||||
(
|
||||
Type::Unknown,
|
||||
Some(ParseError::Mismatch("operator".into(), op.span)),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user