Skip to content

Commit

Permalink
Merge pull request #519 from jinko-core/block-location
Browse files Browse the repository at this point in the history
Parse block location
  • Loading branch information
CohenArthur authored Feb 20, 2022
2 parents 9da644e + 93cc932 commit 7627499
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 18 deletions.
13 changes: 12 additions & 1 deletion src/instruction/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,15 @@
use crate::{
log,
typechecker::{CheckedType, TypeCtx},
Context, Generic, InstrKind, Instruction, ObjectInstance, TypeCheck,
Context, Generic, InstrKind, Instruction, ObjectInstance, SpanTuple, TypeCheck,
};

#[derive(Clone, Default)]
pub struct Block {
instructions: Vec<Box<dyn Instruction>>,
is_statement: bool,
cached_type: Option<CheckedType>,
location: Option<SpanTuple>,
}

impl Block {
Expand All @@ -38,6 +39,7 @@ impl Block {
instructions: Vec::new(),
is_statement: true,
cached_type: None,
location: None,
}
}

Expand Down Expand Up @@ -75,6 +77,11 @@ impl Block {
pub fn set_statement(&mut self, is_statement: bool) {
self.is_statement = is_statement;
}

/// Set block's location
pub fn set_location(&mut self, location: SpanTuple) {
self.location = Some(location)
}
}

impl Instruction for Block {
Expand Down Expand Up @@ -117,6 +124,10 @@ impl Instruction for Block {
true => None,
}
}

fn location(&self) -> Option<&SpanTuple> {
self.location.as_ref()
}
}

impl TypeCheck for Block {
Expand Down
36 changes: 24 additions & 12 deletions src/instruction/if_else.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,10 +93,14 @@ impl TypeCheck for IfElse {
}

if cond_ty != bool_checkedtype {
ctx.error(Error::new(ErrKind::TypeChecker).with_msg(format!(
"if condition should be a boolean, not a `{}`",
cond_ty
)));
ctx.error(
Error::new(ErrKind::TypeChecker)
.with_msg(format!(
"if condition should be a boolean, not a `{}`",
cond_ty
))
.with_loc(self.condition.location().cloned()),
);
}

let if_ty = self.if_body.type_of(ctx);
Expand All @@ -109,20 +113,28 @@ impl TypeCheck for IfElse {
(CheckedType::Void, None) => CheckedType::Void,
(if_ty, Some(else_ty)) => {
if if_ty != else_ty {
ctx.error(Error::new(ErrKind::TypeChecker).with_msg(format!(
"incompatible types for `if` and `else` block: {} and {}",
if_ty, else_ty,
)));
ctx.error(
Error::new(ErrKind::TypeChecker)
.with_msg(format!(
"incompatible types for `if` and `else` block: {} and {}",
if_ty, else_ty,
))
.with_loc(self.if_body.location().cloned()),
);
CheckedType::Error
} else {
if_ty
}
}
(if_ty, None) => {
ctx.error(Error::new(ErrKind::TypeChecker).with_msg(format!(
"`if` block has a return type ({}) but no else block to match it",
if_ty
)));
ctx.error(
Error::new(ErrKind::TypeChecker)
.with_msg(format!(
"`if` block has a return type ({}) but no else block to match it",
if_ty
))
.with_loc(self.if_body.location().cloned()),
);
CheckedType::Error
}
}
Expand Down
10 changes: 9 additions & 1 deletion src/location.rs
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,15 @@ impl SpanTuple {
for (i, line) in input.lines().skip(self.start.line() - 1).enumerate() {
let start_col = match self.start.column {
Column::EndOfLine => 1,
Column::Precise(nz) => nz.get(),
Column::Precise(nz) => {
// If we're gonna be printing multiple lines, print the whole
// start line
if self.start.line() < self.end.line() {
1
} else {
nz.get()
}
}
};
let end_col = match self.end.column {
Column::EndOfLine => line.len(),
Expand Down
25 changes: 21 additions & 4 deletions src/parser/constructs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ fn unit(input: ParseInput) -> ParseResult<ParseInput, Box<dyn Instruction>> {
} else if let Ok((input, _)) = Token::return_tok(input) {
unit_return(input)
} else if let Ok((input, _)) = Token::left_curly_bracket(input) {
unit_block(input)
unit_block(input, start_loc.into())
} else if let Ok((input, _)) = Token::left_parenthesis(input) {
terminated(expr, Token::right_parenthesis)(input)
} else if let Ok(res) = constant(input) {
Expand Down Expand Up @@ -364,8 +364,15 @@ fn unit_return(input: ParseInput) -> ParseResult<ParseInput, Box<dyn Instruction
Ok((input, Box::new(Return::new(expr))))
}

fn unit_block(input: ParseInput) -> ParseResult<ParseInput, Box<dyn Instruction>> {
let (input, block) = inner_block(next(input))?;
fn unit_block(
input: ParseInput,
start_loc: Location,
) -> ParseResult<ParseInput, Box<dyn Instruction>> {
let (input, mut block) = inner_block(next(input))?;
let (input, end_loc) = position(input)?;

block.set_location(SpanTuple::new(input.extra, start_loc, end_loc.into()));

Ok((input, Box::new(block)))
}

Expand Down Expand Up @@ -427,9 +434,19 @@ fn return_type(input: ParseInput) -> ParseResult<ParseInput, Option<TypeId>> {

/// block = '{' next inner_block
pub fn block(input: ParseInput) -> ParseResult<ParseInput, Block> {
let (input, start_loc) = position(input)?;
let (input, _) = Token::left_curly_bracket(input)?;
let input = next(input);
inner_block(input)
let (input, mut block) = inner_block(input)?;
let (input, end_loc) = position(input)?;

block.set_location(SpanTuple::new(
input.extra,
start_loc.into(),
end_loc.into(),
));

Ok((input, block))
}

/// inner_block = '}'
Expand Down

0 comments on commit 7627499

Please sign in to comment.