use crate::bytecode::codegen::CodegenCtx;
use crate::bytecode::expr_gen::convert::push_default_value;
use crate::classfile::MethodWriter;
use crate::hir::{Body, Expr, ExprId};
use crate::ty::Ty;
use rust_asm::opcodes;
use ustr::Ustr;
pub(super) fn emit_name(mw: &mut MethodWriter, ctx: &CodegenCtx, name: Ustr) {
if let Some(slot) = ctx.get_local(name) {
if let Some(ty) = ctx.local_ty(name) {
mw.visit_var_insn(crate::bytecode::local_var::load_opcode(&ty), slot);
}
} else if let Some(ty) = ctx.field_ty(name) {
if ctx.field_is_static(name) {
mw.visit_field_insn(
opcodes::GETSTATIC,
ctx.class_name.as_str(),
name.as_str(),
&ty.descriptor(),
);
} else if let Some(outer_field) = ctx.outer_fields.get(&name)
&& outer_field.access_flags & crate::classfile::ACC_STATIC != 0
{
let owner = ctx
.outer_this
.as_ref()
.map(|outer_this| outer_this.ty.internal_name())
.or_else(|| ctx.enclosing_static_owner.map(|owner| owner.to_string()));
let Some(owner) = owner else {
push_default_value(mw, &ty);
return;
};
mw.visit_field_insn(
opcodes::GETSTATIC,
&owner,
outer_field.name.as_str(),
&outer_field.ty.descriptor(),
);
} else if let Some(outer_field) = ctx.outer_fields.get(&name)
&& let Some(outer_this) = &ctx.outer_this
{
mw.visit_var_insn(opcodes::ALOAD, 0);
mw.visit_field_insn(
opcodes::GETFIELD,
ctx.class_name.as_str(),
outer_this.field_name.as_str(),
&outer_this.ty.descriptor(),
);
mw.visit_field_insn(
opcodes::GETFIELD,
&outer_this.ty.internal_name(),
outer_field.name.as_str(),
&outer_field.ty.descriptor(),
);
} else if let Some(owner) = ctx.enclosing_static_owner
&& let Some(field_ref) = ctx
.catalog
.resolve_static_field(owner.as_str(), name.as_str())
{
mw.visit_field_insn(
opcodes::GETSTATIC,
&field_ref.owner,
&field_ref.name,
&field_ref.descriptor,
);
} else {
mw.visit_var_insn(opcodes::ALOAD, 0);
mw.visit_field_insn(
opcodes::GETFIELD,
ctx.class_name.as_str(),
name.as_str(),
&ty.descriptor(),
);
}
} else {
push_default_value(mw, &Ty::Int);
}
}
pub(super) fn is_current_instance(body: &Body, expr_id: ExprId) -> bool {
matches!(body.exprs[expr_id], Expr::This)
}
pub(super) fn is_super(body: &Body, expr_id: ExprId) -> bool {
matches!(body.exprs[expr_id], Expr::Super)
}
pub(super) fn static_class_name(body: &Body, expr_id: ExprId) -> Option<&str> {
match &body.exprs[expr_id] {
Expr::ClassName(name) => Some(name.as_str()),
_ => None,
}
}