mirror of
https://github.com/edg-l/edlang.git
synced 2024-11-22 16:08:24 +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_code("ParamCountMismatch")
|
||||||
.with_label(
|
.with_label(
|
||||||
Label::new((path, span.into()))
|
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()),
|
.with_color(colors.next()),
|
||||||
)
|
)
|
||||||
.finish()
|
.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/factorial.ed"), "factorial", false, 24, &[] ; "factorial")]
|
||||||
#[test_case(include_str!("programs/refs.ed"), "refs", false, 2, &[] ; "refs")]
|
#[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.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(include_str!("programs/casts.ed"), "casts", false, 2, &[] ; "casts")]
|
||||||
#[test_case(TEST_ADD, "test_add", false, 2, &[] ; "test_add")]
|
#[test_case(TEST_ADD, "test_add", false, 2, &[] ; "test_add")]
|
||||||
#[test_case(TEST_SUB, "test_sub", false, 1, &[] ; "test_sub")]
|
#[test_case(TEST_SUB, "test_sub", false, 1, &[] ; "test_sub")]
|
||||||
|
|
|
@ -7,6 +7,6 @@ pub fn main() -> i64 {
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn hello(a: &mut i32) {
|
pub fn hello(a: &mut i64) {
|
||||||
*a = 2;
|
*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,
|
needs: usize,
|
||||||
file_id: 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 mut ty = builder.body.locals[local].ty.kind.clone();
|
||||||
|
let mutable = builder.body.locals[local].mutable;
|
||||||
let mut place = Place {
|
let mut place = Place {
|
||||||
local,
|
local,
|
||||||
projection: Default::default(),
|
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();
|
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..]) {
|
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);
|
args.push(rvalue);
|
||||||
}
|
}
|
||||||
|
|
||||||
// insert self
|
// insert self
|
||||||
|
|
||||||
match &args_ty[0].kind {
|
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));
|
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));
|
args.insert(0, RValue::Use(Operand::Move(place), *span));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue