From 4bd3484c8556dfb1e63c7b6e1093b6ba525c9604 Mon Sep 17 00:00:00 2001 From: Nilton Constantino Date: Tue, 27 Jan 2026 13:51:12 +0000 Subject: [PATCH] pr 05 --- .../prometeu-compiler/src/backend/lowering.rs | 62 ------------- crates/prometeu-compiler/src/backend/mod.rs | 1 - crates/prometeu-compiler/src/ir_core/instr.rs | 4 +- crates/prometeu-compiler/src/lib.rs | 1 + .../src/lowering/core_to_vm.rs | 85 ++++++++++++++++++ crates/prometeu-compiler/src/lowering/mod.rs | 3 + .../prometeu-compiler/tests/ir_core_tests.rs | 7 +- .../prometeu-compiler/tests/lowering_tests.rs | 87 +++++++++++++++++++ crates/prometeu-compiler/tests/vm_ir_tests.rs | 2 +- 9 files changed, 185 insertions(+), 67 deletions(-) delete mode 100644 crates/prometeu-compiler/src/backend/lowering.rs create mode 100644 crates/prometeu-compiler/src/lowering/core_to_vm.rs create mode 100644 crates/prometeu-compiler/src/lowering/mod.rs create mode 100644 crates/prometeu-compiler/tests/lowering_tests.rs diff --git a/crates/prometeu-compiler/src/backend/lowering.rs b/crates/prometeu-compiler/src/backend/lowering.rs deleted file mode 100644 index 4eecacd2..00000000 --- a/crates/prometeu-compiler/src/backend/lowering.rs +++ /dev/null @@ -1,62 +0,0 @@ -use crate::ir; -use crate::ir_core; -use anyhow::Result; - -pub fn lower_program(program: &ir_core::Program) -> Result { - // For now, we just lower the first module as a smoke test - if let Some(core_module) = program.modules.first() { - let mut vm_module = ir::Module::new(core_module.name.clone()); - vm_module.const_pool = program.const_pool.clone(); - - for core_func in &core_module.functions { - let mut vm_func = ir::Function { - id: core_func.id, - name: core_func.name.clone(), - params: vec![], // TODO: lower params - return_type: ir::Type::Null, // TODO: lower return type - body: vec![], - }; - - for block in &core_func.blocks { - // Label for the block - vm_func.body.push(ir::Instruction::new( - ir::InstrKind::Label(ir::Label(format!("block_{}", block.id))), - None, - )); - - for instr in &block.instrs { - match instr { - ir_core::Instr::PushConst(id) => { - vm_func.body.push(ir::Instruction::new( - ir::InstrKind::PushConst(*id), - None, - )); - } - ir_core::Instr::Call(id) => { - vm_func.body.push(ir::Instruction::new( - ir::InstrKind::Call { func_id: *id, arg_count: 0 }, - None, - )); - } - } - } - - match &block.terminator { - ir_core::Terminator::Return => { - vm_func.body.push(ir::Instruction::new(ir::InstrKind::Ret, None)); - } - ir_core::Terminator::Jump(target) => { - vm_func.body.push(ir::Instruction::new( - ir::InstrKind::Jmp(ir::Label(format!("block_{}", target))), - None, - )); - } - } - } - vm_module.functions.push(vm_func); - } - Ok(vm_module) - } else { - anyhow::bail!("No modules in core program") - } -} diff --git a/crates/prometeu-compiler/src/backend/mod.rs b/crates/prometeu-compiler/src/backend/mod.rs index 715039a6..74987160 100644 --- a/crates/prometeu-compiler/src/backend/mod.rs +++ b/crates/prometeu-compiler/src/backend/mod.rs @@ -1,4 +1,3 @@ -pub mod lowering; pub mod emit_bytecode; pub mod artifacts; diff --git a/crates/prometeu-compiler/src/ir_core/instr.rs b/crates/prometeu-compiler/src/ir_core/instr.rs index be0f12a9..810fed12 100644 --- a/crates/prometeu-compiler/src/ir_core/instr.rs +++ b/crates/prometeu-compiler/src/ir_core/instr.rs @@ -7,5 +7,7 @@ pub enum Instr { /// Placeholder for constant loading. PushConst(ConstId), /// Placeholder for function calls. - Call(FunctionId), + Call(FunctionId, u32), + /// Host calls (syscalls). + Syscall(u32), } diff --git a/crates/prometeu-compiler/src/lib.rs b/crates/prometeu-compiler/src/lib.rs index 45265994..67eb62bf 100644 --- a/crates/prometeu-compiler/src/lib.rs +++ b/crates/prometeu-compiler/src/lib.rs @@ -40,6 +40,7 @@ pub mod common; pub mod ir; pub mod ir_core; +pub mod lowering; pub mod backend; pub mod frontends; pub mod compiler; diff --git a/crates/prometeu-compiler/src/lowering/core_to_vm.rs b/crates/prometeu-compiler/src/lowering/core_to_vm.rs new file mode 100644 index 00000000..9c2df4f8 --- /dev/null +++ b/crates/prometeu-compiler/src/lowering/core_to_vm.rs @@ -0,0 +1,85 @@ +use crate::ir; +use crate::ir_core; +use anyhow::Result; + +/// Lowers a Core IR program into a VM IR module. +pub fn lower_program(program: &ir_core::Program) -> Result { + // For now, we assume a single module program or lower the first one. + // In the future, we might want to lower all modules and link them. + if let Some(core_module) = program.modules.first() { + lower_module(core_module, &program.const_pool) + } else { + anyhow::bail!("No modules in core program") + } +} + +/// Lowers a single Core IR module into a VM IR module. +pub fn lower_module(core_module: &ir_core::Module, const_pool: &ir_core::ConstPool) -> Result { + let mut vm_module = ir::Module::new(core_module.name.clone()); + vm_module.const_pool = const_pool.clone(); + + for core_func in &core_module.functions { + vm_module.functions.push(lower_function(core_func)?); + } + + Ok(vm_module) +} + +/// Lowers a Core IR function into a VM IR function. +pub fn lower_function(core_func: &ir_core::Function) -> Result { + let mut vm_func = ir::Function { + id: core_func.id, + name: core_func.name.clone(), + params: vec![], // Params are not yet represented in Core IR Function + return_type: ir::Type::Null, // Return type is not yet represented in Core IR Function + body: vec![], + }; + + for block in &core_func.blocks { + // Core blocks map to labels in the flat VM IR instruction list. + vm_func.body.push(ir::Instruction::new( + ir::InstrKind::Label(ir::Label(format!("block_{}", block.id))), + None, + )); + + for instr in &block.instrs { + match instr { + ir_core::Instr::PushConst(id) => { + vm_func.body.push(ir::Instruction::new( + ir::InstrKind::PushConst(*id), + None, + )); + } + ir_core::Instr::Call(func_id, arg_count) => { + vm_func.body.push(ir::Instruction::new( + ir::InstrKind::Call { + func_id: *func_id, + arg_count: *arg_count + }, + None, + )); + } + ir_core::Instr::Syscall(id) => { + vm_func.body.push(ir::Instruction::new( + ir::InstrKind::Syscall(*id), + None, + )); + } + } + } + + match &block.terminator { + ir_core::Terminator::Return => { + vm_func.body.push(ir::Instruction::new(ir::InstrKind::Ret, None)); + } + ir_core::Terminator::Jump(target) => { + vm_func.body.push(ir::Instruction::new( + ir::InstrKind::Jmp(ir::Label(format!("block_{}", target))), + None, + )); + } + } + } + + Ok(vm_func) +} diff --git a/crates/prometeu-compiler/src/lowering/mod.rs b/crates/prometeu-compiler/src/lowering/mod.rs new file mode 100644 index 00000000..c69ffd0e --- /dev/null +++ b/crates/prometeu-compiler/src/lowering/mod.rs @@ -0,0 +1,3 @@ +pub mod core_to_vm; + +pub use core_to_vm::lower_program; diff --git a/crates/prometeu-compiler/tests/ir_core_tests.rs b/crates/prometeu-compiler/tests/ir_core_tests.rs index f66c2ef3..aeaf1aaa 100644 --- a/crates/prometeu-compiler/tests/ir_core_tests.rs +++ b/crates/prometeu-compiler/tests/ir_core_tests.rs @@ -17,7 +17,7 @@ fn test_ir_core_manual_construction() { id: 0, instrs: vec![ Instr::PushConst(ConstId(0)), - Instr::Call(FunctionId(11)), + Instr::Call(FunctionId(11), 0), ], terminator: Terminator::Return, }], @@ -51,7 +51,10 @@ fn test_ir_core_manual_construction() { "PushConst": 0 }, { - "Call": 11 + "Call": [ + 11, + 0 + ] } ], "terminator": "Return" diff --git a/crates/prometeu-compiler/tests/lowering_tests.rs b/crates/prometeu-compiler/tests/lowering_tests.rs new file mode 100644 index 00000000..88b98897 --- /dev/null +++ b/crates/prometeu-compiler/tests/lowering_tests.rs @@ -0,0 +1,87 @@ +use prometeu_compiler::ir_core; +use prometeu_compiler::ir_core::*; +use prometeu_compiler::lowering::lower_program; +use prometeu_compiler::ir::*; + +#[test] +fn test_full_lowering() { + let mut const_pool = ConstPool::new(); + const_pool.insert(ConstantValue::Int(100)); // ConstId(0) + + let program = Program { + const_pool, + modules: vec![ir_core::Module { + name: "test_mod".to_string(), + functions: vec![ir_core::Function { + id: FunctionId(1), + name: "main".to_string(), + blocks: vec![ + Block { + id: 0, + instrs: vec![ + Instr::PushConst(ConstId(0)), + Instr::Call(FunctionId(2), 1), + ], + terminator: Terminator::Jump(1), + }, + Block { + id: 1, + instrs: vec![ + Instr::Syscall(42), + ], + terminator: Terminator::Return, + }, + ], + }], + }], + }; + + let vm_module = lower_program(&program).expect("Lowering failed"); + + assert_eq!(vm_module.name, "test_mod"); + let func = &vm_module.functions[0]; + assert_eq!(func.name, "main"); + + // Instructions expected: + // 0: Label block_0 + // 1: PushConst 0 + // 2: Call { func_id: 2, arg_count: 1 } + // 3: Jmp block_1 + // 4: Label block_1 + // 5: Syscall 42 + // 6: Ret + + assert_eq!(func.body.len(), 7); + + match &func.body[0].kind { + InstrKind::Label(Label(l)) => assert_eq!(l, "block_0"), + _ => panic!("Expected label block_0"), + } + match &func.body[1].kind { + InstrKind::PushConst(id) => assert_eq!(id.0, 0), + _ => panic!("Expected PushConst 0"), + } + match &func.body[2].kind { + InstrKind::Call { func_id, arg_count } => { + assert_eq!(func_id.0, 2); + assert_eq!(*arg_count, 1); + } + _ => panic!("Expected Call"), + } + match &func.body[3].kind { + InstrKind::Jmp(Label(l)) => assert_eq!(l, "block_1"), + _ => panic!("Expected Jmp block_1"), + } + match &func.body[4].kind { + InstrKind::Label(Label(l)) => assert_eq!(l, "block_1"), + _ => panic!("Expected label block_1"), + } + match &func.body[5].kind { + InstrKind::Syscall(id) => assert_eq!(*id, 42), + _ => panic!("Expected Syscall 42"), + } + match &func.body[6].kind { + InstrKind::Ret => (), + _ => panic!("Expected Ret"), + } +} diff --git a/crates/prometeu-compiler/tests/vm_ir_tests.rs b/crates/prometeu-compiler/tests/vm_ir_tests.rs index a5f57403..831d9278 100644 --- a/crates/prometeu-compiler/tests/vm_ir_tests.rs +++ b/crates/prometeu-compiler/tests/vm_ir_tests.rs @@ -74,7 +74,7 @@ fn test_vm_ir_serialization() { #[test] fn test_lowering_smoke() { use prometeu_compiler::ir_core; - use prometeu_compiler::backend::lowering::lower_program; + use prometeu_compiler::lowering::lower_program; let mut const_pool = ir_core::ConstPool::new(); const_pool.insert(ir_core::ConstantValue::Int(42));