use crate::compiler::{CompileCtx, Compiler}; use oxide_bytecode::opcode::{self, OpCode}; use oxide_parser::Expression; impl Compiler { pub(crate) fn count_identifier_expression(&self, expr: &Expression, ctx: &mut CompileCtx) { let Expression::Identifier(ident) = expr else { return; }; let name = ident.name.as_str(); for up in &ctx.current_upvalue_captures { if up.name == name { ctx.alloc_reg(); ctx.count_instr(); return; } } if ctx.scopes.symbols.lookup_is_captured(name) { ctx.alloc_reg(); ctx.count_instr(); return; } if CompileCtx::is_known_builtin(name) { let _ = ctx.lookup_or_builtin(name); } ctx.alloc_reg(); ctx.projected_pc += 1; } pub(crate) fn emit_identifier_expression( &self, ident: &oxide_parser::IdentifierReference, ctx: &mut CompileCtx, ) -> Result { let name = ident.name.as_str(); for (uv_idx, up) in ctx.current_upvalue_captures.iter().enumerate() { if up.name == name { let r = ctx.alloc_reg(); let idx = uv_idx as u8; ctx.emit(opcode::encode(OpCode::LOAD_UPVALUE, r, idx, 0)); return Ok(r); } } if ctx.scopes.symbols.lookup_is_captured(name) { let cell_idx = ctx .scopes .cell_registry .iter() .find(|(n, _)| n == name) .map(|(_, idx)| *idx) .unwrap_or(0); let r = ctx.alloc_reg(); if let Some((binding, _)) = ctx.scopes.symbols.lookup_any_binding(name) { ctx.emit(opcode::encode(OpCode::CELL_GET, r, binding.reg, cell_idx)); } else { ctx.emit(opcode::encode(OpCode::CELL_GET, r, 0, cell_idx)); } return Ok(r); } let var_reg = ctx.lookup_or_builtin(name)?; let r = ctx.alloc_reg(); ctx.emit(opcode::encode(OpCode::LOAD_VAR, r, var_reg, 0)); Ok(r) } }