Skip to content

Commit

Permalink
feat: more checks on impl blocks
Browse files Browse the repository at this point in the history
  • Loading branch information
edg-l committed May 7, 2024
1 parent 637aa8e commit 91fc31b
Show file tree
Hide file tree
Showing 6 changed files with 116 additions and 12 deletions.
38 changes: 36 additions & 2 deletions lib/edlang_check/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,10 +193,44 @@ pub fn lowering_error_to_report(
.with_code("ParamCountMismatch")
.with_label(
Label::new((path, span.into()))
.with_message(format!("function call parameter count mismatch: has {}, needs {}.", has_args, needs))
.with_message(format!(
"function call parameter count mismatch: has {}, needs {}.",
has_args, needs
))
.with_color(colors.next()),
)
.finish()
},
}
LoweringError::NotMutable { span, file_id } => {
let path = session.file_paths[file_id].display().to_string();
Report::build(ReportKind::Error, path.clone(), span.lo)
.with_code("NotMutable")
.with_label(
Label::new((path, span.into()))
.with_message("can't mutate this value because it's not declared mutable")
.with_color(colors.next()),
)
.finish()
}
LoweringError::NotMutableSelf {
span,
path_span,
file_id,
} => {
let path = session.file_paths[file_id].display().to_string();
Report::build(ReportKind::Error, path.clone(), span.lo)
.with_code("NotMutableSelf")
.with_label(
Label::new((path.clone(), path_span.into()))
.with_message("this value is not declared mutable")
.with_color(colors.next()),
)
.with_label(
Label::new((path, span.into()))
.with_message("this method requires a mutable 'self'")
.with_color(colors.next()),
)
.finish()
}
}
}
1 change: 1 addition & 0 deletions lib/edlang_driver/tests/programs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ mod common;
#[test_case(include_str!("programs/factorial.ed"), "factorial", false, 24, &[] ; "factorial")]
#[test_case(include_str!("programs/refs.ed"), "refs", false, 2, &[] ; "refs")]
#[test_case(include_str!("programs/struct.ed"), "struct", false, 5, &[] ; "r#struct")]
#[test_case(include_str!("programs/struct_impl.ed"), "struct_impl", false, 6, &[] ; "struct_impl")]
#[test_case(include_str!("programs/casts.ed"), "casts", false, 2, &[] ; "casts")]
#[test_case(TEST_ADD, "test_add", false, 2, &[] ; "test_add")]
#[test_case(TEST_SUB, "test_sub", false, 1, &[] ; "test_sub")]
Expand Down
2 changes: 1 addition & 1 deletion lib/edlang_driver/tests/programs/refs.ed
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@ pub fn main() -> i64 {
return a;
}

pub fn hello(a: &mut i32) {
pub fn hello(a: &mut i64) {
*a = 2;
}
21 changes: 21 additions & 0 deletions lib/edlang_driver/tests/programs/struct_impl.ed
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
extern fn printf(a: &str);

fn main() -> u32 {
let x: A = A {
a: 2
};

let y: u32 = x.hello(4);

return y;
}

struct A {
a: u32,
}

impl A {
pub fn hello(self: &A, x: u32) -> u32 {
return self.a + x;
}
}
8 changes: 8 additions & 0 deletions lib/edlang_lowering/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,12 @@ pub enum LoweringError {
needs: usize,
file_id: usize,
},
#[error("can't mutate this value because it's not declared mutable")]
NotMutable { span: Span, file_id: usize },
#[error("this method requires a mutable 'self'")]
NotMutableSelf {
span: Span,
path_span: Span,
file_id: usize,
},
}
58 changes: 49 additions & 9 deletions lib/edlang_lowering/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1277,6 +1277,7 @@ fn lower_path(
)?;

let mut ty = builder.body.locals[local].ty.kind.clone();
let mutable = builder.body.locals[local].mutable;
let mut place = Place {
local,
projection: Default::default(),
Expand Down Expand Up @@ -1353,26 +1354,65 @@ fn lower_path(
}
};

let mut args = Vec::new();
if args_ty.len() - 1 != value.params.len() {
return Err(LoweringError::ParamCountMismatch {
span: value.span,
has_args: value.params.len(),
needs: args_ty.len(),
file_id: builder.file_id,
});
}

assert_eq!(
args_ty.len() - 1,
value.params.len(),
"param length mismatch"
);
let mut args = Vec::new();

for (arg, arg_ty) in value.params.iter().zip(&args_ty[1..]) {
let (rvalue, _rvalue_ty, _span) = lower_expr(builder, arg, Some(arg_ty))?;
let (rvalue, rvalue_ty, arg_span) = lower_expr(builder, arg, Some(arg_ty))?;

if rvalue_ty != arg_ty.kind {
return Err(LoweringError::UnexpectedType {
span: arg_span,
found: rvalue_ty,
expected: arg_ty.clone(),
file_id: builder.file_id,
});
}

args.push(rvalue);
}

// insert self

match &args_ty[0].kind {
TypeKind::Ptr(is_mut, _) | TypeKind::Ref(is_mut, _) => {
TypeKind::Ptr(is_mut, inner_ty) | TypeKind::Ref(is_mut, inner_ty) => {
if ty != inner_ty.kind {
return Err(LoweringError::UnexpectedType {
span: info.span,
found: inner_ty.kind.clone(),
expected: args_ty[0].clone(),
file_id: builder.file_id,
});
}

if !mutable && *is_mut {
return Err(LoweringError::NotMutableSelf {
span: value.span,
path_span: info.span,
file_id: builder.file_id,
});
}

args.insert(0, RValue::Ref(*is_mut, Operand::Move(place), *span));
}
_ => {
expected_ty => {
if ty != *expected_ty {
return Err(LoweringError::UnexpectedType {
span: value.span,
found: ty.clone(),
expected: args_ty[0].clone(),
file_id: builder.file_id,
});
}

args.insert(0, RValue::Use(Operand::Move(place), *span));
}
}
Expand Down

0 comments on commit 91fc31b

Please sign in to comment.