diff --git a/crates/prometeu-compiler/src/codegen/codegen.rs b/crates/prometeu-compiler/src/codegen/codegen.rs index 8e7cb67d..910c44c4 100644 --- a/crates/prometeu-compiler/src/codegen/codegen.rs +++ b/crates/prometeu-compiler/src/codegen/codegen.rs @@ -213,18 +213,58 @@ impl Codegen { Expression::CallExpression(call) => { let name = ast_util::get_callee_name(&call.callee)?; if let Some(syscall_id) = syscall_map::map_syscall(&name) { - if name == "input.btnA" { + if syscall_id == 0xFFFF_FFFF { + // Color.rgb(r, g, b) + if call.arguments.len() != 3 { + return Err(anyhow!("Color.rgb expects 3 arguments at {:?}", call.span)); + } + // We'll emit the bit manipulation logic here or just a special syscall if we had one. + // Since we have bitwise opcodes, let's use them! + // ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3) + + // Argument 0: r + if let Some(expr) = call.arguments[0].as_expression() { + self.compile_expr(expr)?; + self.emit_op(OpCode::PushI32, vec![Operand::I32(3)], call.span); + self.emit_op(OpCode::Shr, vec![], call.span); + self.emit_op(OpCode::PushI32, vec![Operand::I32(11)], call.span); + self.emit_op(OpCode::Shl, vec![], call.span); + } + + // Argument 1: g + if let Some(expr) = call.arguments[1].as_expression() { + self.compile_expr(expr)?; + self.emit_op(OpCode::PushI32, vec![Operand::I32(2)], call.span); + self.emit_op(OpCode::Shr, vec![], call.span); + self.emit_op(OpCode::PushI32, vec![Operand::I32(5)], call.span); + self.emit_op(OpCode::Shl, vec![], call.span); + } + + self.emit_op(OpCode::BitOr, vec![], call.span); + + // Argument 2: b + if let Some(expr) = call.arguments[2].as_expression() { + self.compile_expr(expr)?; + self.emit_op(OpCode::PushI32, vec![Operand::I32(3)], call.span); + self.emit_op(OpCode::Shr, vec![], call.span); + } + + self.emit_op(OpCode::BitOr, vec![], call.span); + + } else if name == "input.btnA" || name == "Input.btnA" { self.emit_op(OpCode::PushI32, vec![Operand::I32(syscall_map::BTN_A as i32)], call.span); - } else if name == "input.btnB" { + self.emit_op(OpCode::Syscall, vec![Operand::U32(syscall_id)], call.span); + } else if name == "input.btnB" || name == "Input.btnB" { self.emit_op(OpCode::PushI32, vec![Operand::I32(syscall_map::BTN_B as i32)], call.span); + self.emit_op(OpCode::Syscall, vec![Operand::U32(syscall_id)], call.span); } else { for arg in &call.arguments { if let Some(expr) = arg.as_expression() { self.compile_expr(expr)?; } } + self.emit_op(OpCode::Syscall, vec![Operand::U32(syscall_id)], call.span); } - self.emit_op(OpCode::Syscall, vec![Operand::U32(syscall_id)], call.span); } else { return Err(anyhow!("Unsupported function call: {} at {:?}", name, call.span)); } @@ -233,8 +273,18 @@ impl Codegen { let obj = ast_util::get_callee_name_from_member_obj(&member.object)?; let prop = member.property.name.to_string(); let full_name = format!("{}.{}", obj, prop); - // If it's used as a value (GetGlobal/GetLocal?), but for now we only support it in calls - return Err(anyhow!("Member expression outside call not supported: {} at {:?}", full_name, member.span)); + + match full_name.as_str() { + "Color.black" | "color.black" => self.emit_op(OpCode::PushI32, vec![Operand::I32(0x0000)], member.span), + "Color.white" | "color.white" => self.emit_op(OpCode::PushI32, vec![Operand::I32(0xffff)], member.span), + "Color.red" | "color.red" => self.emit_op(OpCode::PushI32, vec![Operand::I32(0xf800)], member.span), + "Color.green" | "color.green" => self.emit_op(OpCode::PushI32, vec![Operand::I32(0x07e0)], member.span), + "Color.blue" | "color.blue" => self.emit_op(OpCode::PushI32, vec![Operand::I32(0x001f)], member.span), + "Color.yellow" | "color.yellow" => self.emit_op(OpCode::PushI32, vec![Operand::I32(0xffe0)], member.span), + "Color.cyan" | "color.cyan" => self.emit_op(OpCode::PushI32, vec![Operand::I32(0x07ff)], member.span), + "Color.magenta" | "color.magenta" => self.emit_op(OpCode::PushI32, vec![Operand::I32(0xf81f)], member.span), + _ => return Err(anyhow!("Member expression outside call not supported: {} at {:?}", full_name, member.span)), + } } _ => return Err(anyhow!("Unsupported expression type at {:?}", expr.span())), } diff --git a/crates/prometeu-compiler/src/syscall_map.rs b/crates/prometeu-compiler/src/syscall_map.rs index 50ffae92..fe38f064 100644 --- a/crates/prometeu-compiler/src/syscall_map.rs +++ b/crates/prometeu-compiler/src/syscall_map.rs @@ -21,7 +21,8 @@ pub fn map_syscall(name: &str) -> Option { // Fallback para nomes especiais do compilador match name { - "input.btnA" | "input.btnB" => Some(Syscall::InputGetPad as u32), + "input.btnA" | "input.btnB" | "Input.btnA" | "Input.btnB" => Some(Syscall::InputGetPad as u32), + "Color.rgb" | "color.rgb" => Some(0xFFFF_FFFF), // ID especial para Color.rgb (não é um syscall real) _ => None, } } diff --git a/crates/prometeu-core/src/prometeu_os/syscalls.rs b/crates/prometeu-core/src/prometeu_os/syscalls.rs index f2aef4be..3aba31b1 100644 --- a/crates/prometeu-core/src/prometeu_os/syscalls.rs +++ b/crates/prometeu-core/src/prometeu_os/syscalls.rs @@ -84,27 +84,51 @@ impl Syscall { } pub fn from_name(name: &str) -> Option { - match name { + let name_lower = name.to_lowercase(); + match name_lower.as_str() { "system.has_cart" => Some(Self::SystemHasCart), "system.run_cart" => Some(Self::SystemRunCart), "gfx.clear" => Some(Self::GfxClear), - "gfx.fillRect" | "gfx.draw_rect" => Some(Self::GfxFillRect), - "gfx.drawLine" | "gfx.draw_line" => Some(Self::GfxDrawLine), - "gfx.drawCircle" | "gfx.draw_circle" => Some(Self::GfxDrawCircle), - "gfx.drawDisc" | "gfx.draw_disc" => Some(Self::GfxDrawDisc), - "gfx.drawSquare" | "gfx.draw_square" => Some(Self::GfxDrawSquare), + "gfx.fillrect" | "gfx.draw_rect" => Some(Self::GfxFillRect), + "gfx.drawline" | "gfx.draw_line" => Some(Self::GfxDrawLine), + "gfx.drawcircle" | "gfx.draw_circle" => Some(Self::GfxDrawCircle), + "gfx.drawdisc" | "gfx.draw_disc" => Some(Self::GfxDrawDisc), + "gfx.drawsquare" | "gfx.draw_square" => Some(Self::GfxDrawSquare), "input.get_pad" => Some(Self::InputGetPad), - "audio.playSample" | "audio.play_sample" => Some(Self::AudioPlaySample), + "audio.playsample" | "audio.play_sample" => Some(Self::AudioPlaySample), "fs.open" => Some(Self::FsOpen), "fs.read" => Some(Self::FsRead), "fs.write" => Some(Self::FsWrite), "fs.close" => Some(Self::FsClose), - "fs.listDir" => Some(Self::FsListDir), + "fs.listdir" => Some(Self::FsListDir), "fs.exists" => Some(Self::FsExists), "fs.delete" => Some(Self::FsDelete), "log.write" => Some(Self::LogWrite), - "log.writeTag" => Some(Self::LogWriteTag), - _ => None, + "log.writetag" | "log.write_tag" => Some(Self::LogWriteTag), + _ => { + // Tenta corresponder exatamente se o lowercase falhar (para camelCase original) + match name { + "gfx.fillRect" => Some(Self::GfxFillRect), + "gfx.drawLine" => Some(Self::GfxDrawLine), + "gfx.drawCircle" => Some(Self::GfxDrawCircle), + "gfx.drawDisc" => Some(Self::GfxDrawDisc), + "gfx.drawSquare" => Some(Self::GfxDrawSquare), + "audio.playSample" => Some(Self::AudioPlaySample), + "fs.listDir" => Some(Self::FsListDir), + "log.writeTag" => Some(Self::LogWriteTag), + "Gfx.fillRect" => Some(Self::GfxFillRect), + "Gfx.drawLine" => Some(Self::GfxDrawLine), + "Gfx.drawCircle" => Some(Self::GfxDrawCircle), + "Gfx.drawDisc" => Some(Self::GfxDrawDisc), + "Gfx.drawSquare" => Some(Self::GfxDrawSquare), + "Audio.playSample" => Some(Self::AudioPlaySample), + "Fs.listDir" => Some(Self::FsListDir), + "Log.writeTag" => Some(Self::LogWriteTag), + "System.hasCart" | "System.has_cart" => Some(Self::SystemHasCart), + "System.runCart" | "System.run_cart" => Some(Self::SystemRunCart), + _ => None, + } + } } } }