Ver código fonte

Add spans to function calls

David Peter 2 anos atrás
pai
commit
4d283dc579

+ 27 - 3
numbat/src/ast.rs

@@ -43,7 +43,30 @@ pub enum Expression {
         rhs: Box<Expression>,
         span_op: Option<Span>, // not available for implicit multiplication and unicode exponents
     },
-    FunctionCall(String, Vec<Expression>),
+    FunctionCall(Span, String, Vec<Expression>),
+}
+impl Expression {
+    pub fn full_span(&self) -> Span {
+        match self {
+            Expression::Scalar(span, _) => *span,
+            Expression::Identifier(span, _) => *span,
+            Expression::UnitIdentifier(span, _, _, _) => *span,
+            Expression::Negate(span, expr) => span.extend(&expr.full_span()),
+            Expression::BinaryOperator {
+                op: _,
+                lhs,
+                rhs,
+                span_op,
+            } => {
+                let mut span = lhs.full_span().extend(&rhs.full_span());
+                if let Some(span_op) = span_op {
+                    span = span.extend(&span_op);
+                }
+                span
+            }
+            Expression::FunctionCall(_, _, _) => todo!(),
+        }
+    }
 }
 
 #[cfg(test)]
@@ -262,7 +285,7 @@ impl PrettyPrint for Expression {
                 rhs,
                 span_op: _,
             } => pretty_print_binop(op, lhs, rhs),
-            FunctionCall(name, args) => {
+            FunctionCall(_, name, args) => {
                 m::identifier(name)
                     + m::operator("(")
                     + itertools::Itertools::intersperse(
@@ -569,7 +592,8 @@ impl ReplaceSpans for Expression {
                 rhs: Box::new(rhs.replace_spans()),
                 span_op: Some(Span::dummy()),
             },
-            Expression::FunctionCall(name, args) => Expression::FunctionCall(
+            Expression::FunctionCall(_, name, args) => Expression::FunctionCall(
+                Span::dummy(),
                 name.clone(),
                 args.iter().map(|a| a.replace_spans()).collect(),
             ),

+ 18 - 7
numbat/src/parser.rs

@@ -514,9 +514,9 @@ impl<'a> Parser<'a> {
         self.postfix_apply()
     }
 
-    fn function_name_from_primary(&self, primary: Expression) -> Result<String> {
+    fn function_name_from_primary(&self, primary: &Expression) -> Result<String> {
         if let Expression::Identifier(_, name) = primary {
-            Ok(name)
+            Ok(name.clone())
         } else {
             Err(ParseError::new(
                 ParseErrorKind::CanOnlyCallIdentifier,
@@ -539,7 +539,9 @@ impl<'a> Parser<'a> {
     pub fn postfix_apply(&mut self) -> Result<Expression> {
         let mut expr = self.conversion()?;
         while self.match_exact(TokenKind::PostfixApply).is_some() {
-            expr = Expression::FunctionCall(self.identifier()?, vec![expr]);
+            let identifier = self.identifier()?;
+
+            expr = Expression::FunctionCall(self.last().unwrap().span, identifier, vec![expr]);
         }
         Ok(expr)
     }
@@ -626,9 +628,10 @@ impl<'a> Parser<'a> {
         let mut expr = self.unary()?;
 
         while self.match_exact(TokenKind::Modulo).is_some() {
+            let op_span = self.last().unwrap().span;
             let rhs = self.modulo()?;
 
-            expr = Expression::FunctionCall("mod".into(), vec![expr, rhs]);
+            expr = Expression::FunctionCall(op_span, "mod".into(), vec![expr, rhs]);
         }
 
         Ok(expr)
@@ -715,10 +718,14 @@ impl<'a> Parser<'a> {
         let primary = self.primary()?;
 
         if self.match_exact(TokenKind::LeftParen).is_some() {
-            let function_name = self.function_name_from_primary(primary)?;
+            let function_name = self.function_name_from_primary(&primary)?;
 
             let args = self.arguments()?;
-            return Ok(Expression::FunctionCall(function_name, args));
+            return Ok(Expression::FunctionCall(
+                primary.full_span(),
+                function_name,
+                args,
+            ));
         }
         Ok(primary)
     }
@@ -1480,7 +1487,11 @@ mod tests {
     fn postfix_apply() {
         parse_as_expression(
             &["1 + 1 // foo"],
-            Expression::FunctionCall("foo".into(), vec![binop!(scalar!(1.0), Add, scalar!(1.0))]),
+            Expression::FunctionCall(
+                Span::dummy(),
+                "foo".into(),
+                vec![binop!(scalar!(1.0), Add, scalar!(1.0))],
+            ),
         );
     }
 

+ 2 - 1
numbat/src/prefix_transformer.rs

@@ -59,7 +59,8 @@ impl Transformer {
                 rhs: Box::new(self.transform_expression(*rhs)),
                 span_op,
             },
-            Expression::FunctionCall(name, args) => Expression::FunctionCall(
+            Expression::FunctionCall(span, name, args) => Expression::FunctionCall(
+                span,
                 name,
                 args.into_iter()
                     .map(|arg| self.transform_expression(arg))

+ 1 - 1
numbat/src/typechecker.rs

@@ -210,7 +210,7 @@ impl TypeChecker {
 
                 typed_ast::Expression::BinaryOperator(op, Box::new(lhs), Box::new(rhs), type_)
             }
-            ast::Expression::FunctionCall(function_name, args) => {
+            ast::Expression::FunctionCall(_, function_name, args) => {
                 let (type_parameters, parameter_types, is_variadic, return_type) = self
                     .function_signatures
                     .get(&function_name)