mirror of
https://github.com/edg-l/edlang.git
synced 2024-09-07 19:35:16 +00:00
feat: more checks on impl blocks
This commit is contained in:
parent
637aa8e229
commit
91fc31b627
|
@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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")]
|
||||
|
|
|
@ -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
lib/edlang_driver/tests/programs/struct_impl.ed
Normal file
21
lib/edlang_driver/tests/programs/struct_impl.ed
Normal file
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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,
|
||||
},
|
||||
}
|
||||
|
|
|
@ -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(),
|
||||
|
@ -1353,26 +1354,65 @@ fn lower_path(
|
|||
}
|
||||
};
|
||||
|
||||
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,
|
||||
});
|
||||
}
|
||||
|
||||
let mut args = Vec::new();
|
||||
|
||||
assert_eq!(
|
||||
args_ty.len() - 1,
|
||||
value.params.len(),
|
||||
"param length mismatch"
|
||||
);
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue