mirror of
https://github.com/nushell/nushell
synced 2024-12-29 06:23:11 +00:00
Improve call eval and live check
This commit is contained in:
parent
3eefa6dec8
commit
6fcdc76059
7 changed files with 352 additions and 85 deletions
54
src/eval.rs
54
src/eval.rs
|
@ -1,6 +1,8 @@
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use crate::{parser::Operator, Block, Call, Expr, Expression, ParserState, Span, Statement, VarId};
|
use crate::{
|
||||||
|
parser::Operator, Block, BlockId, Call, Expr, Expression, ParserState, Span, Statement, VarId,
|
||||||
|
};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum ShellError {
|
pub enum ShellError {
|
||||||
|
@ -12,6 +14,9 @@ pub enum ShellError {
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum Value {
|
pub enum Value {
|
||||||
Int { val: i64, span: Span },
|
Int { val: i64, span: Span },
|
||||||
|
String { val: String, span: Span },
|
||||||
|
List(Vec<Value>),
|
||||||
|
Block(BlockId),
|
||||||
Unknown,
|
Unknown,
|
||||||
}
|
}
|
||||||
impl Value {
|
impl Value {
|
||||||
|
@ -38,14 +43,21 @@ impl Stack {
|
||||||
pub fn get_var(&self, var_id: VarId) -> Result<Value, ShellError> {
|
pub fn get_var(&self, var_id: VarId) -> Result<Value, ShellError> {
|
||||||
match self.vars.get(&var_id) {
|
match self.vars.get(&var_id) {
|
||||||
Some(v) => Ok(v.clone()),
|
Some(v) => Ok(v.clone()),
|
||||||
_ => Err(ShellError::InternalError("variable not found".into())),
|
_ => {
|
||||||
|
println!("var_id: {}", var_id);
|
||||||
|
Err(ShellError::InternalError("variable not found".into()))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn add_var(&mut self, var_id: VarId, value: Value) {
|
||||||
|
self.vars.insert(var_id, value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn eval_operator(
|
pub fn eval_operator(
|
||||||
state: &State,
|
_state: &State,
|
||||||
stack: &mut Stack,
|
_stack: &mut Stack,
|
||||||
op: &Expression,
|
op: &Expression,
|
||||||
) -> Result<Operator, ShellError> {
|
) -> Result<Operator, ShellError> {
|
||||||
match op {
|
match op {
|
||||||
|
@ -59,8 +71,19 @@ pub fn eval_operator(
|
||||||
|
|
||||||
fn eval_call(state: &State, stack: &mut Stack, call: &Call) -> Result<Value, ShellError> {
|
fn eval_call(state: &State, stack: &mut Stack, call: &Call) -> Result<Value, ShellError> {
|
||||||
let decl = state.parser_state.get_decl(call.decl_id);
|
let decl = state.parser_state.get_decl(call.decl_id);
|
||||||
|
|
||||||
if let Some(block_id) = decl.body {
|
if let Some(block_id) = decl.body {
|
||||||
|
for (arg, param) in call
|
||||||
|
.positional
|
||||||
|
.iter()
|
||||||
|
.zip(decl.signature.required_positional.iter())
|
||||||
|
{
|
||||||
|
let result = eval_expression(state, stack, arg)?;
|
||||||
|
let var_id = param
|
||||||
|
.var_id
|
||||||
|
.expect("internal error: all custom parameters must have var_ids");
|
||||||
|
|
||||||
|
stack.add_var(var_id, result);
|
||||||
|
}
|
||||||
let block = state.parser_state.get_block(block_id);
|
let block = state.parser_state.get_block(block_id);
|
||||||
eval_block(state, stack, block)
|
eval_block(state, stack, block)
|
||||||
} else {
|
} else {
|
||||||
|
@ -98,13 +121,22 @@ pub fn eval_expression(
|
||||||
|
|
||||||
eval_block(state, stack, block)
|
eval_block(state, stack, block)
|
||||||
}
|
}
|
||||||
Expr::Block(_) => Err(ShellError::Unsupported(expr.span)),
|
Expr::Block(block_id) => Ok(Value::Block(*block_id)),
|
||||||
Expr::List(_) => Err(ShellError::Unsupported(expr.span)),
|
Expr::List(x) => {
|
||||||
|
let mut output = vec![];
|
||||||
|
for expr in x {
|
||||||
|
output.push(eval_expression(state, stack, expr)?);
|
||||||
|
}
|
||||||
|
Ok(Value::List(output))
|
||||||
|
}
|
||||||
Expr::Table(_, _) => Err(ShellError::Unsupported(expr.span)),
|
Expr::Table(_, _) => Err(ShellError::Unsupported(expr.span)),
|
||||||
Expr::Literal(_) => Err(ShellError::Unsupported(expr.span)),
|
Expr::Literal(_) => Ok(Value::Unknown),
|
||||||
Expr::String(_) => Err(ShellError::Unsupported(expr.span)),
|
Expr::String(s) => Ok(Value::String {
|
||||||
Expr::Signature(_) => Err(ShellError::Unsupported(expr.span)),
|
val: s.clone(),
|
||||||
Expr::Garbage => Err(ShellError::Unsupported(expr.span)),
|
span: expr.span,
|
||||||
|
}),
|
||||||
|
Expr::Signature(_) => Ok(Value::Unknown),
|
||||||
|
Expr::Garbage => Ok(Value::Unknown),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,7 @@ impl<'a> ParserWorkingSet<'a> {
|
||||||
match stmt {
|
match stmt {
|
||||||
Statement::Expression(expr) => self.flatten_expression(expr),
|
Statement::Expression(expr) => self.flatten_expression(expr),
|
||||||
Statement::Pipeline(pipeline) => self.flatten_pipeline(pipeline),
|
Statement::Pipeline(pipeline) => self.flatten_pipeline(pipeline),
|
||||||
|
_ => vec![],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
19
src/main.rs
19
src/main.rs
|
@ -65,6 +65,14 @@ fn main() -> std::io::Result<()> {
|
||||||
// .named("--jazz", SyntaxShape::Int, "jazz!!", Some('j'))
|
// .named("--jazz", SyntaxShape::Int, "jazz!!", Some('j'))
|
||||||
// .switch("--rock", "rock!!", Some('r'));
|
// .switch("--rock", "rock!!", Some('r'));
|
||||||
// working_set.add_decl(sig.into());
|
// working_set.add_decl(sig.into());
|
||||||
|
let sig = Signature::build("exit");
|
||||||
|
working_set.add_decl(sig.into());
|
||||||
|
let sig = Signature::build("vars");
|
||||||
|
working_set.add_decl(sig.into());
|
||||||
|
let sig = Signature::build("decls");
|
||||||
|
working_set.add_decl(sig.into());
|
||||||
|
let sig = Signature::build("blocks");
|
||||||
|
working_set.add_decl(sig.into());
|
||||||
|
|
||||||
let sig = Signature::build("add");
|
let sig = Signature::build("add");
|
||||||
working_set.add_decl(sig.into());
|
working_set.add_decl(sig.into());
|
||||||
|
@ -89,7 +97,7 @@ fn main() -> std::io::Result<()> {
|
||||||
|
|
||||||
let file = std::fs::read(&path)?;
|
let file = std::fs::read(&path)?;
|
||||||
|
|
||||||
let (block, err) = working_set.parse_file(&path, &file, false);
|
let (block, _err) = working_set.parse_file(&path, &file, false);
|
||||||
println!("{}", block.len());
|
println!("{}", block.len());
|
||||||
// println!("{:#?}", output);
|
// println!("{:#?}", output);
|
||||||
// println!("error: {:?}", err);
|
// println!("error: {:?}", err);
|
||||||
|
@ -130,6 +138,15 @@ fn main() -> std::io::Result<()> {
|
||||||
Signal::Success(s) => {
|
Signal::Success(s) => {
|
||||||
if s.trim() == "exit" {
|
if s.trim() == "exit" {
|
||||||
break;
|
break;
|
||||||
|
} else if s.trim() == "vars" {
|
||||||
|
parser_state.borrow().print_vars();
|
||||||
|
continue;
|
||||||
|
} else if s.trim() == "decls" {
|
||||||
|
parser_state.borrow().print_decls();
|
||||||
|
continue;
|
||||||
|
} else if s.trim() == "blocks" {
|
||||||
|
parser_state.borrow().print_blocks();
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
// println!("input: '{}'", s);
|
// println!("input: '{}'", s);
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@ pub enum ParseError {
|
||||||
UnknownCommand(Span),
|
UnknownCommand(Span),
|
||||||
NonUtf8(Span),
|
NonUtf8(Span),
|
||||||
UnknownFlag(Span),
|
UnknownFlag(Span),
|
||||||
|
UnknownType(Span),
|
||||||
MissingFlagParam(Span),
|
MissingFlagParam(Span),
|
||||||
ShortFlagBatchCantTakeArg(Span),
|
ShortFlagBatchCantTakeArg(Span),
|
||||||
MissingPositional(String, Span),
|
MissingPositional(String, Span),
|
||||||
|
|
309
src/parser.rs
309
src/parser.rs
|
@ -78,6 +78,38 @@ pub enum SyntaxShape {
|
||||||
Expression,
|
Expression,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl SyntaxShape {
|
||||||
|
pub fn to_type(&self) -> Type {
|
||||||
|
match self {
|
||||||
|
SyntaxShape::Any => Type::Unknown,
|
||||||
|
SyntaxShape::Block => Type::Block,
|
||||||
|
SyntaxShape::ColumnPath => Type::Unknown,
|
||||||
|
SyntaxShape::Duration => Type::Duration,
|
||||||
|
SyntaxShape::Expression => Type::Unknown,
|
||||||
|
SyntaxShape::FilePath => Type::FilePath,
|
||||||
|
SyntaxShape::Filesize => Type::Filesize,
|
||||||
|
SyntaxShape::FullColumnPath => Type::Unknown,
|
||||||
|
SyntaxShape::GlobPattern => Type::String,
|
||||||
|
SyntaxShape::Int => Type::Int,
|
||||||
|
SyntaxShape::List(x) => {
|
||||||
|
let contents = x.to_type();
|
||||||
|
Type::List(Box::new(contents))
|
||||||
|
}
|
||||||
|
SyntaxShape::Literal(..) => Type::Unknown,
|
||||||
|
SyntaxShape::MathExpression => Type::Unknown,
|
||||||
|
SyntaxShape::Number => Type::Number,
|
||||||
|
SyntaxShape::Operator => Type::Unknown,
|
||||||
|
SyntaxShape::Range => Type::Unknown,
|
||||||
|
SyntaxShape::RowCondition => Type::Bool,
|
||||||
|
SyntaxShape::Signature => Type::Unknown,
|
||||||
|
SyntaxShape::String => Type::String,
|
||||||
|
SyntaxShape::Table => Type::Table,
|
||||||
|
SyntaxShape::VarWithOptType => Type::Unknown,
|
||||||
|
SyntaxShape::Variable => Type::Unknown,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub enum Operator {
|
pub enum Operator {
|
||||||
Equal,
|
Equal,
|
||||||
|
@ -148,13 +180,14 @@ pub enum Expr {
|
||||||
pub struct Expression {
|
pub struct Expression {
|
||||||
pub expr: Expr,
|
pub expr: Expr,
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
|
pub ty: Type,
|
||||||
}
|
}
|
||||||
impl Expression {
|
impl Expression {
|
||||||
pub fn garbage(span: Span) -> Expression {
|
pub fn garbage(span: Span) -> Expression {
|
||||||
Expression {
|
Expression {
|
||||||
expr: Expr::Garbage,
|
expr: Expr::Garbage,
|
||||||
span,
|
span,
|
||||||
//ty: Type::Unknown,
|
ty: Type::Unknown,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn precedence(&self) -> usize {
|
pub fn precedence(&self) -> usize {
|
||||||
|
@ -272,6 +305,7 @@ pub struct VarDecl {
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum Statement {
|
pub enum Statement {
|
||||||
|
Declaration(DeclId),
|
||||||
Pipeline(Pipeline),
|
Pipeline(Pipeline),
|
||||||
Expression(Expression),
|
Expression(Expression),
|
||||||
}
|
}
|
||||||
|
@ -359,6 +393,7 @@ impl<'a> ParserWorkingSet<'a> {
|
||||||
Expression {
|
Expression {
|
||||||
expr: Expr::ExternalCall(name, args),
|
expr: Expr::ExternalCall(name, args),
|
||||||
span: span(spans),
|
span: span(spans),
|
||||||
|
ty: Type::Unknown,
|
||||||
},
|
},
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
|
@ -533,6 +568,7 @@ impl<'a> ParserWorkingSet<'a> {
|
||||||
Expression {
|
Expression {
|
||||||
expr: Expr::Literal(literal),
|
expr: Expr::Literal(literal),
|
||||||
span: arg_span,
|
span: arg_span,
|
||||||
|
ty: Type::Unknown,
|
||||||
},
|
},
|
||||||
error,
|
error,
|
||||||
)
|
)
|
||||||
|
@ -678,6 +714,7 @@ impl<'a> ParserWorkingSet<'a> {
|
||||||
Expression {
|
Expression {
|
||||||
expr: Expr::Call(call),
|
expr: Expr::Call(call),
|
||||||
span: span(spans),
|
span: span(spans),
|
||||||
|
ty: Type::Unknown, // FIXME
|
||||||
},
|
},
|
||||||
err,
|
err,
|
||||||
)
|
)
|
||||||
|
@ -693,6 +730,7 @@ impl<'a> ParserWorkingSet<'a> {
|
||||||
Expression {
|
Expression {
|
||||||
expr: Expr::Int(v),
|
expr: Expr::Int(v),
|
||||||
span,
|
span,
|
||||||
|
ty: Type::Int,
|
||||||
},
|
},
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
|
@ -708,6 +746,7 @@ impl<'a> ParserWorkingSet<'a> {
|
||||||
Expression {
|
Expression {
|
||||||
expr: Expr::Int(v),
|
expr: Expr::Int(v),
|
||||||
span,
|
span,
|
||||||
|
ty: Type::Int,
|
||||||
},
|
},
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
|
@ -723,6 +762,7 @@ impl<'a> ParserWorkingSet<'a> {
|
||||||
Expression {
|
Expression {
|
||||||
expr: Expr::Int(v),
|
expr: Expr::Int(v),
|
||||||
span,
|
span,
|
||||||
|
ty: Type::Int,
|
||||||
},
|
},
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
|
@ -737,6 +777,7 @@ impl<'a> ParserWorkingSet<'a> {
|
||||||
Expression {
|
Expression {
|
||||||
expr: Expr::Int(x),
|
expr: Expr::Int(x),
|
||||||
span,
|
span,
|
||||||
|
ty: Type::Int,
|
||||||
},
|
},
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
|
@ -767,6 +808,7 @@ impl<'a> ParserWorkingSet<'a> {
|
||||||
Expression {
|
Expression {
|
||||||
expr: Expr::Var(var_id),
|
expr: Expr::Var(var_id),
|
||||||
span,
|
span,
|
||||||
|
ty: self.get_variable(var_id).clone(),
|
||||||
},
|
},
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
|
@ -784,6 +826,7 @@ impl<'a> ParserWorkingSet<'a> {
|
||||||
Expression {
|
Expression {
|
||||||
expr: Expr::Var(id),
|
expr: Expr::Var(id),
|
||||||
span,
|
span,
|
||||||
|
ty: self.get_variable(id).clone(),
|
||||||
},
|
},
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
|
@ -796,6 +839,7 @@ impl<'a> ParserWorkingSet<'a> {
|
||||||
Expression {
|
Expression {
|
||||||
expr: Expr::Var(id),
|
expr: Expr::Var(id),
|
||||||
span,
|
span,
|
||||||
|
ty: Type::Unknown,
|
||||||
},
|
},
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
|
@ -849,6 +893,7 @@ impl<'a> ParserWorkingSet<'a> {
|
||||||
Expression {
|
Expression {
|
||||||
expr: Expr::Subexpression(block_id),
|
expr: Expr::Subexpression(block_id),
|
||||||
span,
|
span,
|
||||||
|
ty: Type::Unknown, // FIXME
|
||||||
},
|
},
|
||||||
error,
|
error,
|
||||||
)
|
)
|
||||||
|
@ -862,6 +907,7 @@ impl<'a> ParserWorkingSet<'a> {
|
||||||
Expression {
|
Expression {
|
||||||
expr: Expr::String(token),
|
expr: Expr::String(token),
|
||||||
span,
|
span,
|
||||||
|
ty: Type::String,
|
||||||
},
|
},
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
|
@ -874,8 +920,8 @@ impl<'a> ParserWorkingSet<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: Handle error case
|
//TODO: Handle error case
|
||||||
pub fn parse_shape_name(&self, bytes: &[u8]) -> SyntaxShape {
|
pub fn parse_shape_name(&self, bytes: &[u8], span: Span) -> (SyntaxShape, Option<ParseError>) {
|
||||||
match bytes {
|
let result = match bytes {
|
||||||
b"any" => SyntaxShape::Any,
|
b"any" => SyntaxShape::Any,
|
||||||
b"string" => SyntaxShape::String,
|
b"string" => SyntaxShape::String,
|
||||||
b"column-path" => SyntaxShape::ColumnPath,
|
b"column-path" => SyntaxShape::ColumnPath,
|
||||||
|
@ -891,8 +937,10 @@ impl<'a> ParserWorkingSet<'a> {
|
||||||
b"variable" => SyntaxShape::Variable,
|
b"variable" => SyntaxShape::Variable,
|
||||||
b"signature" => SyntaxShape::Signature,
|
b"signature" => SyntaxShape::Signature,
|
||||||
b"expr" => SyntaxShape::Expression,
|
b"expr" => SyntaxShape::Expression,
|
||||||
_ => SyntaxShape::Any,
|
_ => return (SyntaxShape::Any, Some(ParseError::UnknownType(span))),
|
||||||
}
|
};
|
||||||
|
|
||||||
|
(result, None)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_type(&self, bytes: &[u8]) -> Type {
|
pub fn parse_type(&self, bytes: &[u8]) -> Type {
|
||||||
|
@ -919,12 +967,13 @@ impl<'a> ParserWorkingSet<'a> {
|
||||||
let ty = self.parse_type(type_bytes);
|
let ty = self.parse_type(type_bytes);
|
||||||
*spans_idx += 1;
|
*spans_idx += 1;
|
||||||
|
|
||||||
let id = self.add_variable(bytes[0..(bytes.len() - 1)].to_vec(), ty);
|
let id = self.add_variable(bytes[0..(bytes.len() - 1)].to_vec(), ty.clone());
|
||||||
|
|
||||||
(
|
(
|
||||||
Expression {
|
Expression {
|
||||||
expr: Expr::Var(id),
|
expr: Expr::Var(id),
|
||||||
span: span(&spans[*spans_idx - 2..*spans_idx]),
|
span: span(&spans[*spans_idx - 2..*spans_idx]),
|
||||||
|
ty,
|
||||||
},
|
},
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
|
@ -935,6 +984,7 @@ impl<'a> ParserWorkingSet<'a> {
|
||||||
Expression {
|
Expression {
|
||||||
expr: Expr::Var(id),
|
expr: Expr::Var(id),
|
||||||
span: spans[*spans_idx],
|
span: spans[*spans_idx],
|
||||||
|
ty: Type::Unknown,
|
||||||
},
|
},
|
||||||
Some(ParseError::MissingType(spans[*spans_idx])),
|
Some(ParseError::MissingType(spans[*spans_idx])),
|
||||||
)
|
)
|
||||||
|
@ -947,6 +997,7 @@ impl<'a> ParserWorkingSet<'a> {
|
||||||
Expression {
|
Expression {
|
||||||
expr: Expr::Var(id),
|
expr: Expr::Var(id),
|
||||||
span: span(&spans[*spans_idx - 1..*spans_idx]),
|
span: span(&spans[*spans_idx - 1..*spans_idx]),
|
||||||
|
ty: Type::Unknown,
|
||||||
},
|
},
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
|
@ -1023,18 +1074,26 @@ impl<'a> ParserWorkingSet<'a> {
|
||||||
ParseMode::ArgMode => {
|
ParseMode::ArgMode => {
|
||||||
if contents.starts_with(b"--") && contents.len() > 2 {
|
if contents.starts_with(b"--") && contents.len() > 2 {
|
||||||
// Long flag
|
// Long flag
|
||||||
let flags: Vec<_> = contents.split(|x| x == &b'(').collect();
|
let flags: Vec<_> = contents
|
||||||
|
.split(|x| x == &b'(')
|
||||||
|
.map(|x| x.to_vec())
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let long = String::from_utf8_lossy(&flags[0]).to_string();
|
||||||
|
let variable_name = flags[0][2..].to_vec();
|
||||||
|
let var_id = self.add_variable(variable_name, Type::Unknown);
|
||||||
|
|
||||||
if flags.len() == 1 {
|
if flags.len() == 1 {
|
||||||
args.push(Arg::Flag(Flag {
|
args.push(Arg::Flag(Flag {
|
||||||
arg: None,
|
arg: None,
|
||||||
desc: String::new(),
|
desc: String::new(),
|
||||||
long: String::from_utf8_lossy(flags[0]).to_string(),
|
long,
|
||||||
short: None,
|
short: None,
|
||||||
required: false,
|
required: false,
|
||||||
|
var_id: Some(var_id),
|
||||||
}));
|
}));
|
||||||
} else {
|
} else {
|
||||||
let short_flag = flags[1];
|
let short_flag = &flags[1];
|
||||||
let short_flag = if !short_flag.starts_with(b"-")
|
let short_flag = if !short_flag.starts_with(b"-")
|
||||||
|| !short_flag.ends_with(b")")
|
|| !short_flag.ends_with(b")")
|
||||||
{
|
{
|
||||||
|
@ -1048,16 +1107,21 @@ impl<'a> ParserWorkingSet<'a> {
|
||||||
};
|
};
|
||||||
|
|
||||||
let short_flag =
|
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 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();
|
||||||
|
let var_id =
|
||||||
|
self.add_variable(variable_name, Type::Unknown);
|
||||||
|
|
||||||
if chars.len() == 1 {
|
if chars.len() == 1 {
|
||||||
args.push(Arg::Flag(Flag {
|
args.push(Arg::Flag(Flag {
|
||||||
arg: None,
|
arg: None,
|
||||||
desc: String::new(),
|
desc: String::new(),
|
||||||
long: String::from_utf8_lossy(flags[0]).to_string(),
|
long,
|
||||||
short: Some(chars[0]),
|
short: Some(chars[0]),
|
||||||
required: false,
|
required: false,
|
||||||
|
var_id: Some(var_id),
|
||||||
}));
|
}));
|
||||||
} else {
|
} else {
|
||||||
error = error.or(Some(ParseError::Mismatch(
|
error = error.or(Some(ParseError::Mismatch(
|
||||||
|
@ -1086,14 +1150,22 @@ impl<'a> ParserWorkingSet<'a> {
|
||||||
long: String::new(),
|
long: String::new(),
|
||||||
short: None,
|
short: None,
|
||||||
required: false,
|
required: false,
|
||||||
|
var_id: None,
|
||||||
}));
|
}));
|
||||||
} else {
|
} else {
|
||||||
|
let mut encoded_var_name = vec![0u8; 4];
|
||||||
|
let len = chars[0].encode_utf8(&mut encoded_var_name).len();
|
||||||
|
let variable_name = encoded_var_name[0..len].to_vec();
|
||||||
|
let var_id =
|
||||||
|
self.add_variable(variable_name, Type::Unknown);
|
||||||
|
|
||||||
args.push(Arg::Flag(Flag {
|
args.push(Arg::Flag(Flag {
|
||||||
arg: None,
|
arg: None,
|
||||||
desc: String::new(),
|
desc: String::new(),
|
||||||
long: String::new(),
|
long: String::new(),
|
||||||
short: Some(chars[0]),
|
short: Some(chars[0]),
|
||||||
required: false,
|
required: false,
|
||||||
|
var_id: Some(var_id),
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
} else if contents.starts_with(b"(-") {
|
} else if contents.starts_with(b"(-") {
|
||||||
|
@ -1140,24 +1212,35 @@ impl<'a> ParserWorkingSet<'a> {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if contents.ends_with(b"?") {
|
if contents.ends_with(b"?") {
|
||||||
let contents = &contents[..(contents.len() - 1)];
|
let contents: Vec<_> =
|
||||||
|
contents[..(contents.len() - 1)].into();
|
||||||
|
let name = String::from_utf8_lossy(&contents).to_string();
|
||||||
|
|
||||||
|
let var_id =
|
||||||
|
self.add_variable(contents.into(), Type::Unknown);
|
||||||
|
|
||||||
// Positional arg, optional
|
// Positional arg, optional
|
||||||
args.push(Arg::Positional(
|
args.push(Arg::Positional(
|
||||||
PositionalArg {
|
PositionalArg {
|
||||||
desc: String::new(),
|
desc: String::new(),
|
||||||
name: String::from_utf8_lossy(contents).to_string(),
|
name,
|
||||||
shape: SyntaxShape::Any,
|
shape: SyntaxShape::Any,
|
||||||
|
var_id: Some(var_id),
|
||||||
},
|
},
|
||||||
false,
|
false,
|
||||||
))
|
))
|
||||||
} else {
|
} 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
|
// Positional arg, required
|
||||||
args.push(Arg::Positional(
|
args.push(Arg::Positional(
|
||||||
PositionalArg {
|
PositionalArg {
|
||||||
desc: String::new(),
|
desc: String::new(),
|
||||||
name: String::from_utf8_lossy(contents).to_string(),
|
name,
|
||||||
shape: SyntaxShape::Any,
|
shape: SyntaxShape::Any,
|
||||||
|
var_id: Some(var_id),
|
||||||
},
|
},
|
||||||
true,
|
true,
|
||||||
))
|
))
|
||||||
|
@ -1166,13 +1249,21 @@ impl<'a> ParserWorkingSet<'a> {
|
||||||
}
|
}
|
||||||
ParseMode::TypeMode => {
|
ParseMode::TypeMode => {
|
||||||
if let Some(last) = args.last_mut() {
|
if let Some(last) = args.last_mut() {
|
||||||
let syntax_shape = self.parse_shape_name(contents);
|
let (syntax_shape, err) = self.parse_shape_name(contents, span);
|
||||||
|
error = error.or(err);
|
||||||
//TODO check if we're replacing one already
|
//TODO check if we're replacing one already
|
||||||
match last {
|
match last {
|
||||||
Arg::Positional(PositionalArg { shape, .. }, ..) => {
|
Arg::Positional(
|
||||||
|
PositionalArg { shape, var_id, .. },
|
||||||
|
..,
|
||||||
|
) => {
|
||||||
|
self.set_variable_type(var_id.expect("internal error: all custom parameters must have var_ids"), syntax_shape.to_type());
|
||||||
*shape = syntax_shape;
|
*shape = syntax_shape;
|
||||||
}
|
}
|
||||||
Arg::Flag(Flag { arg, .. }) => *arg = Some(syntax_shape),
|
Arg::Flag(Flag { arg, var_id, .. }) => {
|
||||||
|
self.set_variable_type(var_id.expect("internal error: all custom parameters must have var_ids"), syntax_shape.to_type());
|
||||||
|
*arg = Some(syntax_shape)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
parse_mode = ParseMode::ArgMode;
|
parse_mode = ParseMode::ArgMode;
|
||||||
|
@ -1242,6 +1333,7 @@ impl<'a> ParserWorkingSet<'a> {
|
||||||
Expression {
|
Expression {
|
||||||
expr: Expr::Signature(sig),
|
expr: Expr::Signature(sig),
|
||||||
span,
|
span,
|
||||||
|
ty: Type::Unknown,
|
||||||
},
|
},
|
||||||
error,
|
error,
|
||||||
)
|
)
|
||||||
|
@ -1310,6 +1402,7 @@ impl<'a> ParserWorkingSet<'a> {
|
||||||
Expression {
|
Expression {
|
||||||
expr: Expr::List(args),
|
expr: Expr::List(args),
|
||||||
span,
|
span,
|
||||||
|
ty: Type::List(Box::new(Type::Unknown)), // FIXME
|
||||||
},
|
},
|
||||||
error,
|
error,
|
||||||
)
|
)
|
||||||
|
@ -1354,6 +1447,7 @@ impl<'a> ParserWorkingSet<'a> {
|
||||||
Expression {
|
Expression {
|
||||||
expr: Expr::List(vec![]),
|
expr: Expr::List(vec![]),
|
||||||
span,
|
span,
|
||||||
|
ty: Type::Table,
|
||||||
},
|
},
|
||||||
None,
|
None,
|
||||||
),
|
),
|
||||||
|
@ -1393,6 +1487,7 @@ impl<'a> ParserWorkingSet<'a> {
|
||||||
Expression {
|
Expression {
|
||||||
expr: Expr::Table(table_headers, rows),
|
expr: Expr::Table(table_headers, rows),
|
||||||
span,
|
span,
|
||||||
|
ty: Type::Table,
|
||||||
},
|
},
|
||||||
error,
|
error,
|
||||||
)
|
)
|
||||||
|
@ -1448,6 +1543,7 @@ impl<'a> ParserWorkingSet<'a> {
|
||||||
Expression {
|
Expression {
|
||||||
expr: Expr::Block(block_id),
|
expr: Expr::Block(block_id),
|
||||||
span,
|
span,
|
||||||
|
ty: Type::Block,
|
||||||
},
|
},
|
||||||
error,
|
error,
|
||||||
)
|
)
|
||||||
|
@ -1514,6 +1610,7 @@ impl<'a> ParserWorkingSet<'a> {
|
||||||
Expression {
|
Expression {
|
||||||
expr: Expr::Literal(literal),
|
expr: Expr::Literal(literal),
|
||||||
span,
|
span,
|
||||||
|
ty: Type::Unknown,
|
||||||
},
|
},
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
|
@ -1633,6 +1730,7 @@ impl<'a> ParserWorkingSet<'a> {
|
||||||
Expression {
|
Expression {
|
||||||
expr: Expr::Operator(operator),
|
expr: Expr::Operator(operator),
|
||||||
span,
|
span,
|
||||||
|
ty: Type::Unknown,
|
||||||
},
|
},
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
|
@ -1686,20 +1784,24 @@ impl<'a> ParserWorkingSet<'a> {
|
||||||
while expr_stack.len() > 1 {
|
while expr_stack.len() > 1 {
|
||||||
// Collapse the right associated operations first
|
// Collapse the right associated operations first
|
||||||
// so that we can get back to a stack with a lower precedence
|
// so that we can get back to a stack with a lower precedence
|
||||||
let rhs = expr_stack
|
let mut rhs = expr_stack
|
||||||
.pop()
|
.pop()
|
||||||
.expect("internal error: expression stack empty");
|
.expect("internal error: expression stack empty");
|
||||||
let op = expr_stack
|
let mut op = expr_stack
|
||||||
.pop()
|
.pop()
|
||||||
.expect("internal error: expression stack empty");
|
.expect("internal error: expression stack empty");
|
||||||
let lhs = expr_stack
|
let mut lhs = expr_stack
|
||||||
.pop()
|
.pop()
|
||||||
.expect("internal error: expression stack empty");
|
.expect("internal error: expression stack empty");
|
||||||
|
|
||||||
|
let (result_ty, err) = self.math_result_type(&mut lhs, &mut op, &mut rhs);
|
||||||
|
error = error.or(err);
|
||||||
|
|
||||||
let op_span = span(&[lhs.span, rhs.span]);
|
let op_span = span(&[lhs.span, rhs.span]);
|
||||||
expr_stack.push(Expression {
|
expr_stack.push(Expression {
|
||||||
expr: Expr::BinaryOp(Box::new(lhs), Box::new(op), Box::new(rhs)),
|
expr: Expr::BinaryOp(Box::new(lhs), Box::new(op), Box::new(rhs)),
|
||||||
span: op_span,
|
span: op_span,
|
||||||
|
ty: result_ty,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1712,20 +1814,24 @@ impl<'a> ParserWorkingSet<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
while expr_stack.len() != 1 {
|
while expr_stack.len() != 1 {
|
||||||
let rhs = expr_stack
|
let mut rhs = expr_stack
|
||||||
.pop()
|
.pop()
|
||||||
.expect("internal error: expression stack empty");
|
.expect("internal error: expression stack empty");
|
||||||
let op = expr_stack
|
let mut op = expr_stack
|
||||||
.pop()
|
.pop()
|
||||||
.expect("internal error: expression stack empty");
|
.expect("internal error: expression stack empty");
|
||||||
let lhs = expr_stack
|
let mut lhs = expr_stack
|
||||||
.pop()
|
.pop()
|
||||||
.expect("internal error: expression stack empty");
|
.expect("internal error: expression stack empty");
|
||||||
|
|
||||||
|
let (result_ty, err) = self.math_result_type(&mut lhs, &mut op, &mut rhs);
|
||||||
|
error = error.or(err);
|
||||||
|
|
||||||
let binary_op_span = span(&[lhs.span, rhs.span]);
|
let binary_op_span = span(&[lhs.span, rhs.span]);
|
||||||
expr_stack.push(Expression {
|
expr_stack.push(Expression {
|
||||||
expr: Expr::BinaryOp(Box::new(lhs), Box::new(op), Box::new(rhs)),
|
expr: Expr::BinaryOp(Box::new(lhs), Box::new(op), Box::new(rhs)),
|
||||||
span: binary_op_span,
|
span: binary_op_span,
|
||||||
|
ty: result_ty,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1736,6 +1842,58 @@ impl<'a> ParserWorkingSet<'a> {
|
||||||
(output, error)
|
(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>) {
|
pub fn parse_expression(&mut self, spans: &[Span]) -> (Expression, Option<ParseError>) {
|
||||||
let bytes = self.get_span_contents(spans[0]);
|
let bytes = self.get_span_contents(spans[0]);
|
||||||
|
|
||||||
|
@ -1772,60 +1930,69 @@ impl<'a> ParserWorkingSet<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_def(&mut self, spans: &[Span]) -> (Statement, Option<ParseError>) {
|
pub fn parse_def(&mut self, spans: &[Span]) -> (Statement, Option<ParseError>) {
|
||||||
|
let mut error = None;
|
||||||
let name = self.get_span_contents(spans[0]);
|
let name = self.get_span_contents(spans[0]);
|
||||||
|
|
||||||
if name == b"def" {
|
if name == b"def" && spans.len() >= 4 {
|
||||||
if let Some(decl_id) = self.find_decl(b"def") {
|
//FIXME: don't use expect here
|
||||||
let (call, call_span, err) =
|
let (name_expr, err) = self.parse_string(spans[1]);
|
||||||
self.parse_internal_call(spans[0], &spans[1..], decl_id);
|
let name = name_expr
|
||||||
|
.as_string()
|
||||||
|
.expect("internal error: expected def name");
|
||||||
|
error = error.or(err);
|
||||||
|
|
||||||
if err.is_some() {
|
self.enter_scope();
|
||||||
return (
|
let (sig, err) = self.parse_signature(spans[2]);
|
||||||
Statement::Expression(Expression {
|
let mut signature = sig
|
||||||
expr: Expr::Call(call),
|
.as_signature()
|
||||||
span: call_span,
|
.expect("internal error: expected param list");
|
||||||
}),
|
error = error.or(err);
|
||||||
err,
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
let name = call.positional[0]
|
|
||||||
.as_string()
|
|
||||||
.expect("internal error: expected def name");
|
|
||||||
let mut signature = call.positional[1]
|
|
||||||
.as_signature()
|
|
||||||
.expect("internal error: expected param list");
|
|
||||||
let block_id = call.positional[2]
|
|
||||||
.as_block()
|
|
||||||
.expect("internal error: expected block");
|
|
||||||
|
|
||||||
signature.name = name;
|
let (block, err) = self.parse_block_expression(spans[3]);
|
||||||
let decl = Declaration {
|
self.exit_scope();
|
||||||
signature,
|
|
||||||
body: Some(block_id),
|
|
||||||
};
|
|
||||||
|
|
||||||
self.add_decl(decl);
|
let block_id = block.as_block().expect("internal error: expected block");
|
||||||
|
error = error.or(err);
|
||||||
|
|
||||||
return (
|
signature.name = name;
|
||||||
Statement::Expression(Expression {
|
let decl = Declaration {
|
||||||
expr: Expr::Call(call),
|
signature,
|
||||||
span: call_span,
|
body: Some(block_id),
|
||||||
}),
|
};
|
||||||
None,
|
|
||||||
);
|
self.add_decl(decl);
|
||||||
}
|
let def_decl_id = self
|
||||||
}
|
.find_decl(b"def")
|
||||||
|
.expect("internal error: missing def command");
|
||||||
|
|
||||||
|
let call = Box::new(Call {
|
||||||
|
head: spans[0],
|
||||||
|
decl_id: def_decl_id,
|
||||||
|
positional: vec![name_expr, sig, block],
|
||||||
|
named: vec![],
|
||||||
|
});
|
||||||
|
|
||||||
|
(
|
||||||
|
Statement::Expression(Expression {
|
||||||
|
expr: Expr::Call(call),
|
||||||
|
span: span(spans),
|
||||||
|
ty: Type::Unknown,
|
||||||
|
}),
|
||||||
|
error,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
(
|
||||||
|
Statement::Expression(Expression {
|
||||||
|
expr: Expr::Garbage,
|
||||||
|
span: span(spans),
|
||||||
|
ty: Type::Unknown,
|
||||||
|
}),
|
||||||
|
Some(ParseError::UnknownState(
|
||||||
|
"internal error: let statement unparseable".into(),
|
||||||
|
span(spans),
|
||||||
|
)),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
(
|
|
||||||
Statement::Expression(Expression {
|
|
||||||
expr: Expr::Garbage,
|
|
||||||
span: span(spans),
|
|
||||||
}),
|
|
||||||
Some(ParseError::UnknownState(
|
|
||||||
"internal error: let statement unparseable".into(),
|
|
||||||
span(spans),
|
|
||||||
)),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_let(&mut self, spans: &[Span]) -> (Statement, Option<ParseError>) {
|
pub fn parse_let(&mut self, spans: &[Span]) -> (Statement, Option<ParseError>) {
|
||||||
|
@ -1840,6 +2007,7 @@ impl<'a> ParserWorkingSet<'a> {
|
||||||
Statement::Expression(Expression {
|
Statement::Expression(Expression {
|
||||||
expr: Expr::Call(call),
|
expr: Expr::Call(call),
|
||||||
span: call_span,
|
span: call_span,
|
||||||
|
ty: Type::Unknown,
|
||||||
}),
|
}),
|
||||||
err,
|
err,
|
||||||
);
|
);
|
||||||
|
@ -1849,6 +2017,7 @@ impl<'a> ParserWorkingSet<'a> {
|
||||||
Statement::Expression(Expression {
|
Statement::Expression(Expression {
|
||||||
expr: Expr::Garbage,
|
expr: Expr::Garbage,
|
||||||
span: span(spans),
|
span: span(spans),
|
||||||
|
ty: Type::Unknown,
|
||||||
}),
|
}),
|
||||||
Some(ParseError::UnknownState(
|
Some(ParseError::UnknownState(
|
||||||
"internal error: let statement unparseable".into(),
|
"internal error: let statement unparseable".into(),
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use crate::{parser::Block, Declaration, Span};
|
use crate::{parser::Block, Declaration, Span};
|
||||||
|
use core::panic;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -11,9 +12,19 @@ pub struct ParserState {
|
||||||
scope: Vec<ScopeFrame>,
|
scope: Vec<ScopeFrame>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum Type {
|
pub enum Type {
|
||||||
Int,
|
Int,
|
||||||
|
Bool,
|
||||||
|
String,
|
||||||
|
Block,
|
||||||
|
ColumnPath,
|
||||||
|
Duration,
|
||||||
|
FilePath,
|
||||||
|
Filesize,
|
||||||
|
List(Box<Type>),
|
||||||
|
Number,
|
||||||
|
Table,
|
||||||
Unknown,
|
Unknown,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,6 +100,24 @@ impl ParserState {
|
||||||
self.blocks.len()
|
self.blocks.len()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn print_vars(&self) {
|
||||||
|
for var in self.vars.iter().enumerate() {
|
||||||
|
println!("var{}: {:?}", var.0, var.1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn print_decls(&self) {
|
||||||
|
for decl in self.decls.iter().enumerate() {
|
||||||
|
println!("decl{}: {:?}", decl.0, decl.1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn print_blocks(&self) {
|
||||||
|
for block in self.blocks.iter().enumerate() {
|
||||||
|
println!("block{}: {:?}", block.0, block.1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_var(&self, var_id: VarId) -> &Type {
|
pub fn get_var(&self, var_id: VarId) -> &Type {
|
||||||
self.vars
|
self.vars
|
||||||
.get(var_id)
|
.get(var_id)
|
||||||
|
@ -319,11 +348,20 @@ impl<'a> ParserWorkingSet<'a> {
|
||||||
|
|
||||||
last.vars.insert(name, next_id);
|
last.vars.insert(name, next_id);
|
||||||
|
|
||||||
self.delta.vars.insert(next_id, ty);
|
self.delta.vars.push(ty);
|
||||||
|
|
||||||
next_id
|
next_id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_variable_type(&mut self, var_id: VarId, ty: Type) {
|
||||||
|
let num_permanent_vars = self.permanent_state.num_vars();
|
||||||
|
if var_id < num_permanent_vars {
|
||||||
|
panic!("Internal error: attempted to set into permanent state from working set")
|
||||||
|
} else {
|
||||||
|
self.delta.vars[var_id - num_permanent_vars] = ty;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_variable(&self, var_id: VarId) -> &Type {
|
pub fn get_variable(&self, var_id: VarId) -> &Type {
|
||||||
let num_permanent_vars = self.permanent_state.num_vars();
|
let num_permanent_vars = self.permanent_state.num_vars();
|
||||||
if var_id < num_permanent_vars {
|
if var_id < num_permanent_vars {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::{parser::SyntaxShape, Declaration};
|
use crate::{parser::SyntaxShape, Declaration, VarId};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Flag {
|
pub struct Flag {
|
||||||
|
@ -7,6 +7,8 @@ pub struct Flag {
|
||||||
pub arg: Option<SyntaxShape>,
|
pub arg: Option<SyntaxShape>,
|
||||||
pub required: bool,
|
pub required: bool,
|
||||||
pub desc: String,
|
pub desc: String,
|
||||||
|
// For custom commands
|
||||||
|
pub var_id: Option<VarId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
@ -14,6 +16,8 @@ pub struct PositionalArg {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub desc: String,
|
pub desc: String,
|
||||||
pub shape: SyntaxShape,
|
pub shape: SyntaxShape,
|
||||||
|
// For custom commands
|
||||||
|
pub var_id: Option<VarId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
|
@ -75,6 +79,7 @@ impl Signature {
|
||||||
name: name.into(),
|
name: name.into(),
|
||||||
desc: desc.into(),
|
desc: desc.into(),
|
||||||
shape: shape.into(),
|
shape: shape.into(),
|
||||||
|
var_id: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
self
|
self
|
||||||
|
@ -91,6 +96,7 @@ impl Signature {
|
||||||
name: name.into(),
|
name: name.into(),
|
||||||
desc: desc.into(),
|
desc: desc.into(),
|
||||||
shape: shape.into(),
|
shape: shape.into(),
|
||||||
|
var_id: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
self
|
self
|
||||||
|
@ -114,6 +120,7 @@ impl Signature {
|
||||||
arg: Some(shape.into()),
|
arg: Some(shape.into()),
|
||||||
required: false,
|
required: false,
|
||||||
desc: desc.into(),
|
desc: desc.into(),
|
||||||
|
var_id: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
self
|
self
|
||||||
|
@ -137,6 +144,7 @@ impl Signature {
|
||||||
arg: Some(shape.into()),
|
arg: Some(shape.into()),
|
||||||
required: true,
|
required: true,
|
||||||
desc: desc.into(),
|
desc: desc.into(),
|
||||||
|
var_id: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
self
|
self
|
||||||
|
@ -163,6 +171,7 @@ impl Signature {
|
||||||
arg: None,
|
arg: None,
|
||||||
required: false,
|
required: false,
|
||||||
desc: desc.into(),
|
desc: desc.into(),
|
||||||
|
var_id: None,
|
||||||
});
|
});
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue