mirror of
https://github.com/edg-l/edlang.git
synced 2024-09-16 15:52:25 +00:00
codegen for impl methods
This commit is contained in:
parent
03a244db41
commit
b94c6a4e7d
|
@ -1,7 +1,8 @@
|
||||||
[workspace]
|
[workspace]
|
||||||
resolver = "2"
|
resolver = "2"
|
||||||
|
|
||||||
members = [ "bin/edlangc", "edb", "lib/edlang_ast", "lib/edlang_check", "lib/edlang_codegen_llvm", "lib/edlang_driver", "lib/edlang_ir", "lib/edlang_lowering","lib/edlang_parser", "lib/edlang_session", "lib/edlang_span"]
|
members = [ "bin/edlangc", "edb", "lib/edlang_ast", "lib/edlang_check", "lib/edlang_codegen_llvm",
|
||||||
|
"lib/edlang_driver", "lib/edlang_ir", "lib/edlang_lowering","lib/edlang_parser", "lib/edlang_session", "lib/edlang_span"]
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
lto = true
|
lto = true
|
||||||
|
|
|
@ -39,6 +39,7 @@ pub struct PathExpr {
|
||||||
pub enum PathSegment {
|
pub enum PathSegment {
|
||||||
Field(Ident),
|
Field(Ident),
|
||||||
Index { value: Expression, span: Span },
|
Index { value: Expression, span: Span },
|
||||||
|
Method { value: FnCallExpr, span: Span },
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
|
|
|
@ -111,6 +111,7 @@ impl Body {
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct AdtBody {
|
pub struct AdtBody {
|
||||||
pub def_id: DefId,
|
pub def_id: DefId,
|
||||||
|
pub mod_id: DefId,
|
||||||
pub is_pub: bool,
|
pub is_pub: bool,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub variants: Vec<AdtVariant>,
|
pub variants: Vec<AdtVariant>,
|
||||||
|
|
|
@ -182,6 +182,7 @@ fn lower_struct(
|
||||||
let body = ctx.body.modules.get(&module_id).unwrap();
|
let body = ctx.body.modules.get(&module_id).unwrap();
|
||||||
*body.symbols.structs.get(&info.name.name).unwrap()
|
*body.symbols.structs.get(&info.name.name).unwrap()
|
||||||
},
|
},
|
||||||
|
mod_id: module_id,
|
||||||
is_pub: true, // todo struct pub
|
is_pub: true, // todo struct pub
|
||||||
name: info.name.name.clone(),
|
name: info.name.name.clone(),
|
||||||
variants: Vec::new(),
|
variants: Vec::new(),
|
||||||
|
@ -591,6 +592,7 @@ fn find_expr_type(builder: &mut BodyBuilder, info: &ast::Expression) -> Option<T
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast::PathSegment::Index { .. } => todo!(),
|
ast::PathSegment::Index { .. } => todo!(),
|
||||||
|
ast::PathSegment::Method { .. } => todo!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1000,6 +1002,8 @@ fn lower_fn_call(
|
||||||
|
|
||||||
let mut args = Vec::new();
|
let mut args = Vec::new();
|
||||||
|
|
||||||
|
assert_eq!(args_ty.len(), info.params.len(), "param length mismatch");
|
||||||
|
|
||||||
for (arg, arg_ty) in info.params.iter().zip(args_ty) {
|
for (arg, arg_ty) in info.params.iter().zip(args_ty) {
|
||||||
let (rvalue, _rvalue_ty, _span) = lower_expr(builder, arg, Some(&arg_ty))?;
|
let (rvalue, _rvalue_ty, _span) = lower_expr(builder, arg, Some(&arg_ty))?;
|
||||||
args.push(rvalue);
|
args.push(rvalue);
|
||||||
|
@ -1256,36 +1260,138 @@ fn lower_path(
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let mut ty = builder.body.locals[local].ty.kind.clone();
|
let mut ty = builder.body.locals[local].ty.kind.clone();
|
||||||
let mut projection = Vec::new();
|
let mut place = Place {
|
||||||
|
local,
|
||||||
|
projection: Default::default(),
|
||||||
|
};
|
||||||
|
|
||||||
for extra in &info.extra {
|
for extra in &info.extra {
|
||||||
match extra {
|
match extra {
|
||||||
ast::PathSegment::Field(name) => {
|
ast::PathSegment::Field(name) => {
|
||||||
// is while fine? auto deref
|
// is while fine? auto deref
|
||||||
while let TypeKind::Ref(_, inner) = ty {
|
while let TypeKind::Ref(_, inner) = ty {
|
||||||
projection.push(PlaceElem::Deref);
|
place.projection.push(PlaceElem::Deref);
|
||||||
ty = inner.kind;
|
ty = inner.kind;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let TypeKind::Struct(id, _name) = ty {
|
if let TypeKind::Struct(id, _name) = ty {
|
||||||
let struct_body = builder.ctx.body.structs.get(&id).unwrap();
|
let struct_body = builder.ctx.body.structs.get(&id).unwrap();
|
||||||
let idx = *struct_body.name_to_idx.get(&name.name).unwrap();
|
let idx = *struct_body.name_to_idx.get(&name.name).unwrap();
|
||||||
projection.push(PlaceElem::Field { field_idx: idx });
|
place.projection.push(PlaceElem::Field { field_idx: idx });
|
||||||
ty = struct_body.variants[idx].ty.kind.clone();
|
ty = struct_body.variants[idx].ty.kind.clone();
|
||||||
|
} else {
|
||||||
|
unimplemented!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast::PathSegment::Index { .. } => todo!(),
|
ast::PathSegment::Index { .. } => todo!(),
|
||||||
|
ast::PathSegment::Method { value, span } => {
|
||||||
|
// is while fine? auto deref
|
||||||
|
while let TypeKind::Ref(_, inner) = ty {
|
||||||
|
place.projection.push(PlaceElem::Deref);
|
||||||
|
ty = inner.kind;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let TypeKind::Struct(id, _name) = &ty {
|
||||||
|
let struct_body = builder.ctx.body.structs.get(id).unwrap();
|
||||||
|
let fn_id = *builder
|
||||||
|
.ctx
|
||||||
|
.body
|
||||||
|
.modules
|
||||||
|
.get(&struct_body.mod_id)
|
||||||
|
.unwrap()
|
||||||
|
.symbols
|
||||||
|
.methods
|
||||||
|
.get(id)
|
||||||
|
.unwrap()
|
||||||
|
.get(&value.name.name)
|
||||||
|
.expect("couldn't find method");
|
||||||
|
|
||||||
|
let (args_ty, ret_ty) = {
|
||||||
|
if let Some(x) = builder.ctx.body.function_signatures.get(&fn_id).cloned() {
|
||||||
|
x
|
||||||
|
} else {
|
||||||
|
let (args, ret) = builder
|
||||||
|
.ctx
|
||||||
|
.unresolved_function_signatures
|
||||||
|
.get(&fn_id)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let args: Vec<_> = args
|
||||||
|
.iter()
|
||||||
|
.map(|x| lower_type(&builder.ctx, x, builder.local_module))
|
||||||
|
.collect::<Result<Vec<_>, LoweringError>>()?;
|
||||||
|
let ret = ret
|
||||||
|
.as_ref()
|
||||||
|
.map(|x| lower_type(&builder.ctx, x, builder.local_module))
|
||||||
|
.unwrap_or(Ok(TypeInfo {
|
||||||
|
span: None,
|
||||||
|
kind: TypeKind::Unit,
|
||||||
|
}))?;
|
||||||
|
builder
|
||||||
|
.ctx
|
||||||
|
.body
|
||||||
|
.function_signatures
|
||||||
|
.insert(fn_id, (args.clone(), ret.clone()));
|
||||||
|
(args, ret)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
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))?;
|
||||||
|
args.push(rvalue);
|
||||||
|
}
|
||||||
|
|
||||||
|
// insert self
|
||||||
|
|
||||||
|
match &args_ty[0].kind {
|
||||||
|
TypeKind::Ptr(is_mut, _) | TypeKind::Ref(is_mut, _) => {
|
||||||
|
args.insert(0, RValue::Ref(*is_mut, Operand::Move(place), *span));
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
args.insert(0, RValue::Use(Operand::Move(place), *span));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let dest_local = builder.add_local(Local::temp(ret_ty.kind.clone()));
|
||||||
|
|
||||||
|
place = Place {
|
||||||
|
local: dest_local,
|
||||||
|
projection: Default::default(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let target_block = builder.body.blocks.len() + 1;
|
||||||
|
|
||||||
|
// todo: check if function is diverging such as exit().
|
||||||
|
let kind = Terminator::Call {
|
||||||
|
func: fn_id,
|
||||||
|
args,
|
||||||
|
destination: place.clone(),
|
||||||
|
target: Some(target_block),
|
||||||
|
};
|
||||||
|
|
||||||
|
let statements = std::mem::take(&mut builder.statements);
|
||||||
|
builder.body.blocks.push(BasicBlock {
|
||||||
|
statements: statements.into(),
|
||||||
|
terminator: kind,
|
||||||
|
terminator_span: Some(*span),
|
||||||
|
});
|
||||||
|
ty = ret_ty.kind;
|
||||||
|
} else {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok((
|
Ok((place, ty, info.span))
|
||||||
Place {
|
|
||||||
local,
|
|
||||||
projection: projection.into(), // todo, array
|
|
||||||
},
|
|
||||||
ty,
|
|
||||||
info.span,
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::only_used_in_recursion)]
|
#[allow(clippy::only_used_in_recursion)]
|
||||||
|
|
|
@ -199,6 +199,10 @@ pub PathSegments: Vec<ast::PathSegment> = {
|
||||||
|
|
||||||
pub(crate) PathSegment: ast::PathSegment = {
|
pub(crate) PathSegment: ast::PathSegment = {
|
||||||
"." <Ident> => ast::PathSegment::Field(<>),
|
"." <Ident> => ast::PathSegment::Field(<>),
|
||||||
|
<lo:@L> "." <value:FnCallExpr> <hi:@R> => ast::PathSegment::Method {
|
||||||
|
value,
|
||||||
|
span: ast::Span::new(lo, hi),
|
||||||
|
},
|
||||||
<lo:@L> "[" <value:Expression> "]" <hi:@R> => ast::PathSegment::Index {
|
<lo:@L> "[" <value:Expression> "]" <hi:@R> => ast::PathSegment::Index {
|
||||||
value,
|
value,
|
||||||
span: ast::Span::new(lo, hi),
|
span: ast::Span::new(lo, hi),
|
||||||
|
|
Loading…
Reference in a new issue