diff --git a/src/instruction/method_call.rs b/src/instruction/method_call.rs index 938a98dc..fb475ed8 100644 --- a/src/instruction/method_call.rs +++ b/src/instruction/method_call.rs @@ -4,13 +4,14 @@ use crate::generics::{self, Generic}; use crate::instruction::FunctionCall; use crate::typechecker::{CheckedType, TypeCtx}; -use crate::{log, Context, InstrKind, Instruction, ObjectInstance, TypeCheck}; +use crate::{log, Context, InstrKind, Instruction, ObjectInstance, SpanTuple, TypeCheck}; #[derive(Clone)] pub struct MethodCall { var: Box, method: FunctionCall, cached_type: Option, + location: Option, } impl MethodCall { @@ -20,8 +21,13 @@ impl MethodCall { var, method, cached_type: None, + location: None, } } + + pub fn set_location(&mut self, location: SpanTuple) { + self.location = Some(location) + } } impl Instruction for MethodCall { @@ -39,6 +45,9 @@ impl Instruction for MethodCall { // FIXME: No clone here let mut call = self.method.clone(); + if let Some(loc) = &self.location { + call.set_location(loc.clone()) + }; call.add_arg_front(self.var.clone()); @@ -48,12 +57,19 @@ impl Instruction for MethodCall { call.execute(ctx) } + + fn location(&self) -> Option<&SpanTuple> { + self.location.as_ref() + } } impl TypeCheck for MethodCall { fn resolve_type(&mut self, ctx: &mut TypeCtx) -> CheckedType { let mut call = self.method.clone(); call.add_arg_front(self.var.clone()); + if let Some(loc) = &self.location { + call.set_location(loc.clone()) + }; call.type_of(ctx) } @@ -71,6 +87,9 @@ impl Generic for MethodCall { fn expand(&self, ctx: &mut Context) { let mut call = self.method.clone(); call.add_arg_front(self.var.clone()); + if let Some(loc) = &self.location { + call.set_location(loc.clone()) + }; log!("generic expanding method call: {}", self.method.name()); @@ -83,6 +102,9 @@ impl Generic for MethodCall { let mut call = self.method.clone(); call.add_arg_front(self.var.clone()); + if let Some(loc) = &self.location { + call.set_location(loc.clone()) + }; log!("generic resolving method call: {}", self.method.name()); diff --git a/src/parser/constructs.rs b/src/parser/constructs.rs index 6170fc7c..10126645 100644 --- a/src/parser/constructs.rs +++ b/src/parser/constructs.rs @@ -127,8 +127,9 @@ fn term(input: ParseInput) -> ParseResult> { /// factor = next unit factor_rest fn factor(input: ParseInput) -> ParseResult> { let input = next(input); + let (input, start_loc) = position(input)?; let (input, unit) = unit(input)?; - factor_rest(input, unit) + factor_rest(input, unit, start_loc.into()) } /// factor_rest = '.' IDENTIFIER next method_or_field factor_rest @@ -136,13 +137,14 @@ fn factor(input: ParseInput) -> ParseResult> { fn factor_rest( input: ParseInput, expr: Box, + start_loc: Location, ) -> ParseResult> { match Token::dot(input) { Ok((input, _)) => { let (input, id) = Token::identifier(input)?; let input = next(input); - let (input, expr) = method_or_field(input, expr, id)?; - factor_rest(input, expr) + let (input, expr) = method_or_field(input, expr, id, start_loc.clone())?; + factor_rest(input, expr, start_loc) } _ => Ok((input, expr)), } @@ -154,11 +156,14 @@ fn method_or_field( input: ParseInput, expr: Box, id: String, + start_loc: Location, ) -> ParseResult> { if let Ok((input, _)) = Token::left_parenthesis(input) { let input = next(input); let (input, args) = args(input)?; - let method_call = MethodCall::new(expr, FunctionCall::new(id, vec![], args)); + let (input, end_loc) = position(input)?; + let mut method_call = MethodCall::new(expr, FunctionCall::new(id, vec![], args)); + method_call.set_location(SpanTuple::new(input.extra, start_loc, end_loc.into())); Ok((input, Box::new(method_call))) } else if let Ok((input, _)) = Token::left_bracket(input) { let input = next(input); @@ -167,7 +172,9 @@ fn method_or_field( let (input, _) = Token::left_parenthesis(input)?; let input = next(input); let (input, args) = args(input)?; - let method_call = MethodCall::new(expr, FunctionCall::new(id, generics, args)); + let (input, end_loc) = position(input)?; + let mut method_call = MethodCall::new(expr, FunctionCall::new(id, generics, args)); + method_call.set_location(SpanTuple::new(input.extra, start_loc, end_loc.into())); Ok((input, Box::new(method_call))) } else { Ok((input, Box::new(FieldAccess::new(expr, id))))