mirror of
https://github.com/edg-l/edlang.git
synced 2024-11-21 23:48:24 +00:00
struct field
This commit is contained in:
parent
a9cd4eff86
commit
79c1243f0d
|
@ -971,46 +971,9 @@ fn compile_load_operand<'ctx>(
|
|||
locals: &HashMap<usize, PointerValue<'ctx>>,
|
||||
op: &ir::Operand,
|
||||
) -> Result<(BasicValueEnum<'ctx>, TypeInfo), BuilderError> {
|
||||
// todo: implement projection
|
||||
let body = ctx.ctx.program.functions.get(&fn_id).unwrap();
|
||||
Ok(match op {
|
||||
ir::Operand::Copy(place) => {
|
||||
let pointee_ty = compile_basic_type(ctx, &body.locals[place.local].ty);
|
||||
let ptr = *locals.get(&place.local).unwrap();
|
||||
(
|
||||
ctx.builder.build_load(pointee_ty, ptr, "")?,
|
||||
body.locals[place.local].ty.clone(),
|
||||
)
|
||||
}
|
||||
ir::Operand::Move(place) => {
|
||||
let mut ptr = *locals.get(&place.local).unwrap();
|
||||
let mut local_ty = body.locals[place.local].ty.clone();
|
||||
|
||||
for proj in &place.projection {
|
||||
match proj {
|
||||
ir::PlaceElem::Deref => {
|
||||
ptr = ctx
|
||||
.builder
|
||||
.build_load(compile_basic_type(ctx, &local_ty), ptr, "deref")?
|
||||
.into_pointer_value();
|
||||
local_ty = match local_ty.kind {
|
||||
ir::TypeKind::Ptr(inner) => *inner,
|
||||
ir::TypeKind::Ref(_, inner) => *inner,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
ir::PlaceElem::Field { .. } => todo!(),
|
||||
ir::PlaceElem::Index { .. } => todo!(),
|
||||
}
|
||||
}
|
||||
|
||||
let pointee_ty = compile_basic_type(ctx, &local_ty);
|
||||
|
||||
(
|
||||
ctx.builder.build_load(pointee_ty, ptr, "")?,
|
||||
body.locals[place.local].ty.clone(),
|
||||
)
|
||||
}
|
||||
ir::Operand::Copy(place) => compile_load_place(ctx, fn_id, locals, place, true)?,
|
||||
ir::Operand::Move(place) => compile_load_place(ctx, fn_id, locals, place, false)?,
|
||||
ir::Operand::Constant(data) => match &data.kind {
|
||||
ir::ConstKind::Value(value) => (
|
||||
compile_value(ctx, value, &data.type_info)?,
|
||||
|
@ -1021,6 +984,59 @@ fn compile_load_operand<'ctx>(
|
|||
})
|
||||
}
|
||||
|
||||
fn compile_load_place<'ctx>(
|
||||
ctx: &ModuleCompileCtx<'ctx, '_>,
|
||||
fn_id: DefId,
|
||||
locals: &HashMap<usize, PointerValue<'ctx>>,
|
||||
place: &ir::Place,
|
||||
_is_copy: bool,
|
||||
) -> Result<(BasicValueEnum<'ctx>, TypeInfo), BuilderError> {
|
||||
let body = ctx.ctx.program.functions.get(&fn_id).unwrap();
|
||||
let mut ptr = *locals.get(&place.local).unwrap();
|
||||
let mut local_ty = body.locals[place.local].ty.clone();
|
||||
|
||||
for proj in &place.projection {
|
||||
match proj {
|
||||
ir::PlaceElem::Deref => {
|
||||
ptr = ctx
|
||||
.builder
|
||||
.build_load(compile_basic_type(ctx, &local_ty), ptr, "deref")?
|
||||
.into_pointer_value();
|
||||
local_ty = match local_ty.kind {
|
||||
ir::TypeKind::Ptr(inner) => *inner,
|
||||
ir::TypeKind::Ref(_, inner) => *inner,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
ir::PlaceElem::Field { field_idx } => {
|
||||
local_ty = match local_ty.kind {
|
||||
ir::TypeKind::Struct(id) => {
|
||||
let struct_body = ctx.ctx.program.structs.get(&id).unwrap();
|
||||
let ty = struct_body.variants[*field_idx].ty.clone();
|
||||
let field_name = struct_body.variants[*field_idx].name.clone();
|
||||
ptr = ctx.builder.build_struct_gep(
|
||||
compile_basic_type(ctx, &local_ty),
|
||||
ptr,
|
||||
(*field_idx).try_into().unwrap(),
|
||||
&format!("ptr_field_{field_name}"),
|
||||
)?;
|
||||
ty
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
ir::PlaceElem::Index { .. } => todo!(),
|
||||
}
|
||||
}
|
||||
|
||||
let pointee_ty = compile_basic_type(ctx, &local_ty);
|
||||
|
||||
Ok((
|
||||
ctx.builder.build_load(pointee_ty, ptr, "")?,
|
||||
body.locals[place.local].ty.clone(),
|
||||
))
|
||||
}
|
||||
|
||||
fn compile_value<'ctx>(
|
||||
ctx: &ModuleCompileCtx<'ctx, '_>,
|
||||
val: &ValueTree,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Based on a cfg
|
||||
|
||||
use std::collections::{BTreeMap, HashSet};
|
||||
use std::collections::{BTreeMap, HashMap, HashSet};
|
||||
|
||||
use edlang_span::Span;
|
||||
use smallvec::SmallVec;
|
||||
|
@ -94,6 +94,7 @@ pub struct AdtBody {
|
|||
pub is_pub: bool,
|
||||
pub name: String,
|
||||
pub variants: Vec<AdtVariant>,
|
||||
pub name_to_idx: HashMap<String, usize>,
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
|
@ -359,7 +360,7 @@ pub struct Place {
|
|||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum PlaceElem {
|
||||
Deref,
|
||||
Field { field_idx: usize, type_info: usize },
|
||||
Field { field_idx: usize },
|
||||
Index { local: usize },
|
||||
}
|
||||
|
||||
|
|
|
@ -103,6 +103,7 @@ fn lower_struct(mut ctx: BuildCtx, info: &ast::Struct, module_id: DefId) -> Buil
|
|||
is_pub: true, // todo struct pub
|
||||
name: info.name.name.clone(),
|
||||
variants: Vec::new(),
|
||||
name_to_idx: Default::default(),
|
||||
span: info.span,
|
||||
};
|
||||
|
||||
|
@ -113,6 +114,8 @@ fn lower_struct(mut ctx: BuildCtx, info: &ast::Struct, module_id: DefId) -> Buil
|
|||
ty: lower_type(&ctx, &field.r#type, module_id),
|
||||
};
|
||||
body.variants.push(variant);
|
||||
body.name_to_idx
|
||||
.insert(field.name.name.clone(), body.variants.len() - 1);
|
||||
}
|
||||
|
||||
ctx.body.structs.insert(body.def_id, body);
|
||||
|
@ -418,21 +421,6 @@ fn lower_let(builder: &mut BodyBuilder, info: &ast::LetStmt) {
|
|||
fn lower_assign(builder: &mut BodyBuilder, info: &ast::AssignStmt) {
|
||||
let (mut place, mut ty) = lower_path(builder, &info.name);
|
||||
|
||||
if let Some(PlaceElem::Deref) = place.projection.last() {
|
||||
match &ty {
|
||||
TypeKind::Ptr(inner) => {
|
||||
ty = inner.kind.clone();
|
||||
}
|
||||
TypeKind::Ref(is_mut, inner) => {
|
||||
if !is_mut {
|
||||
panic!("trying to mutate non mut ref");
|
||||
}
|
||||
ty = inner.kind.clone();
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
for _ in 0..info.deref_times {
|
||||
match &ty {
|
||||
TypeKind::Ptr(inner) => {
|
||||
|
@ -454,7 +442,7 @@ fn lower_assign(builder: &mut BodyBuilder, info: &ast::AssignStmt) {
|
|||
builder.statements.push(Statement {
|
||||
span: Some(info.name.first.span),
|
||||
kind: StatementKind::Assign(place, rvalue),
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
fn find_expr_type(builder: &mut BodyBuilder, info: &ast::Expression) -> Option<TypeKind> {
|
||||
|
@ -887,7 +875,6 @@ fn lower_value(
|
|||
},
|
||||
ast::ValueExpr::Str { value: _, span: _ } => todo!(),
|
||||
ast::ValueExpr::Path(info) => {
|
||||
// add deref info to path
|
||||
let (place, ty) = lower_path(builder, info);
|
||||
(Operand::Move(place), ty)
|
||||
}
|
||||
|
@ -922,13 +909,26 @@ fn lower_path(builder: &mut BodyBuilder, info: &ast::PathExpr) -> (ir::Place, Ty
|
|||
.name_to_local
|
||||
.get(&info.first.name)
|
||||
.expect("local not found");
|
||||
let ty = builder.body.locals[local].ty.kind.clone();
|
||||
|
||||
let projection = Vec::new();
|
||||
let mut ty = builder.body.locals[local].ty.kind.clone();
|
||||
let mut projection = Vec::new();
|
||||
|
||||
for extra in &info.extra {
|
||||
match extra {
|
||||
ast::PathSegment::Field(_) => todo!(),
|
||||
ast::PathSegment::Field(name) => {
|
||||
// is while fine? auto deref
|
||||
while let TypeKind::Ref(_, inner) = ty {
|
||||
projection.push(PlaceElem::Deref);
|
||||
ty = inner.kind;
|
||||
}
|
||||
|
||||
if let TypeKind::Struct(id) = ty {
|
||||
let struct_body = builder.ctx.body.structs.get(&id).unwrap();
|
||||
let idx = *struct_body.name_to_idx.get(&name.name).unwrap();
|
||||
projection.push(PlaceElem::Field { field_idx: idx });
|
||||
ty = struct_body.variants[idx].ty.kind.clone();
|
||||
}
|
||||
}
|
||||
ast::PathSegment::Index { .. } => todo!(),
|
||||
}
|
||||
}
|
||||
|
@ -936,7 +936,7 @@ fn lower_path(builder: &mut BodyBuilder, info: &ast::PathExpr) -> (ir::Place, Ty
|
|||
(
|
||||
Place {
|
||||
local,
|
||||
projection: projection.into(), // todo, field array deref
|
||||
projection: projection.into(), // todo, array
|
||||
},
|
||||
ty,
|
||||
)
|
||||
|
|
Loading…
Reference in a new issue