This commit is contained in:
Nilton Constantino 2026-01-28 19:16:41 +00:00
parent 9515bddce8
commit 127ec789bc
No known key found for this signature in database
8 changed files with 86 additions and 14 deletions

View File

@ -41,7 +41,7 @@ pub fn disasm(rom: &[u8]) -> Result<Vec<Instr>, String> {
match opcode { match opcode {
OpCode::PushConst | OpCode::PushI32 | OpCode::Jmp | OpCode::JmpIfFalse | OpCode::JmpIfTrue OpCode::PushConst | OpCode::PushI32 | OpCode::Jmp | OpCode::JmpIfFalse | OpCode::JmpIfTrue
| OpCode::GetGlobal | OpCode::SetGlobal | OpCode::GetLocal | OpCode::SetLocal | OpCode::GetGlobal | OpCode::SetGlobal | OpCode::GetLocal | OpCode::SetLocal
| OpCode::PopN | OpCode::Syscall => { | OpCode::PopN | OpCode::Syscall | OpCode::LoadRef | OpCode::StoreRef => {
let v = read_u32_le(&mut cursor).map_err(|e| e.to_string())?; let v = read_u32_le(&mut cursor).map_err(|e| e.to_string())?;
operands.push(DisasmOperand::U32(v)); operands.push(DisasmOperand::U32(v));
} }

View File

@ -54,7 +54,7 @@ pub enum OpCode {
/// Operand: value (i32) /// Operand: value (i32)
PushI32 = 0x17, PushI32 = 0x17,
/// Removes `n` values from the stack. /// Removes `n` values from the stack.
/// Operand: n (u16) /// Operand: n (u32)
PopN = 0x18, PopN = 0x18,
// --- 6.3 Arithmetic --- // --- 6.3 Arithmetic ---

View File

@ -161,6 +161,13 @@ impl<'a> BytecodeEmitter<'a> {
asm_instrs.push(Asm::Op(OpCode::Syscall, vec![Operand::U32(*id)])); asm_instrs.push(Asm::Op(OpCode::Syscall, vec![Operand::U32(*id)]));
} }
InstrKind::FrameSync => asm_instrs.push(Asm::Op(OpCode::FrameSync, vec![])), InstrKind::FrameSync => asm_instrs.push(Asm::Op(OpCode::FrameSync, vec![])),
InstrKind::Alloc => asm_instrs.push(Asm::Op(OpCode::Alloc, vec![])),
InstrKind::LoadRef(offset) => {
asm_instrs.push(Asm::Op(OpCode::LoadRef, vec![Operand::U32(*offset)]));
}
InstrKind::StoreRef(offset) => {
asm_instrs.push(Asm::Op(OpCode::StoreRef, vec![Operand::U32(*offset)]));
}
} }
let end_idx = asm_instrs.len(); let end_idx = asm_instrs.len();

View File

@ -179,8 +179,15 @@ impl<'a> TypeChecker<'a> {
// In v0, we assume target is a gate. We bind the inner type to the binding. // In v0, we assume target is a gate. We bind the inner type to the binding.
let inner_ty = match target_ty { let inner_ty = match target_ty {
PbsType::Contract(name) if name.starts_with("Gate<") => { PbsType::Contract(name) if name.starts_with("Gate<") => {
// Try to extract type name from Gate<TypeName> // Extract type name from Gate<TypeName>
PbsType::Void // Simplified let inner_name = &name[5..name.len()-1];
match inner_name {
"int" => PbsType::Int,
"float" => PbsType::Float,
"bool" => PbsType::Bool,
"string" => PbsType::String,
_ => PbsType::Void, // Should be PbsType::Struct(inner_name) if we had better info
}
} }
_ => PbsType::Void _ => PbsType::Void
}; };

View File

@ -136,4 +136,13 @@ pub enum InstrKind {
Syscall(u32), Syscall(u32),
/// Special instruction to synchronize with the hardware frame clock. /// Special instruction to synchronize with the hardware frame clock.
FrameSync, FrameSync,
// --- HIP / Memory ---
/// Allocates memory on the heap. Pops size from stack.
Alloc,
/// Reads from heap at reference + offset. Pops reference, pushes value.
LoadRef(u32),
/// Writes to heap at reference + offset. Pops reference and value.
StoreRef(u32),
} }

View File

@ -1,7 +1,7 @@
//! # Prometeu Compiler //! # Prometeu Compiler
//! //!
//! This crate provides the official compiler for the Prometeu ecosystem. //! This crate provides the official compiler for the Prometeu ecosystem.
//! It translates high-level source code (primarily TypeScript/JavaScript) into //! It translates high-level source code (primarily Prometeu Base Script - PBS) into
//! Prometeu ByteCode (.pbc), which runs on the Prometeu Virtual Machine. //! Prometeu ByteCode (.pbc), which runs on the Prometeu Virtual Machine.
//! //!
//! ## Architecture Overview: //! ## Architecture Overview:
@ -9,8 +9,8 @@
//! The compiler follows a multi-stage pipeline: //! The compiler follows a multi-stage pipeline:
//! //!
//! 1. **Frontend (Parsing & Analysis)**: //! 1. **Frontend (Parsing & Analysis)**:
//! - Uses the `oxc` parser to generate an Abstract Syntax Tree (AST). //! - Uses the PBS parser to generate an Abstract Syntax Tree (AST).
//! - Performs semantic analysis and validation (e.g., ensuring only supported TS features are used). //! - Performs semantic analysis and validation.
//! - Lowers the AST into the **Intermediate Representation (IR)**. //! - Lowers the AST into the **Intermediate Representation (IR)**.
//! - *Example*: Converting a `a + b` expression into IR instructions like `Push(a)`, `Push(b)`, `Add`. //! - *Example*: Converting a `a + b` expression into IR instructions like `Push(a)`, `Push(b)`, `Add`.
//! //!
@ -30,7 +30,7 @@
//! //!
//! ```bash //! ```bash
//! # Build a project from a directory //! # Build a project from a directory
//! prometeu-compiler build ./my-game --entry ./src/main.ts --out ./game.pbc //! prometeu-compiler build ./my-game --entry ./src/main.pbs --out ./game.pbc
//! ``` //! ```
//! //!
//! ## Programmatic Entry Point: //! ## Programmatic Entry Point:
@ -67,7 +67,7 @@ pub enum Commands {
/// Path to the project root directory. /// Path to the project root directory.
project_dir: PathBuf, project_dir: PathBuf,
/// Explicit path to the entry file (defaults to src/main.ts). /// Explicit path to the entry file (defaults to src/main.pbs).
#[arg(short, long)] #[arg(short, long)]
entry: Option<PathBuf>, entry: Option<PathBuf>,

View File

@ -71,11 +71,10 @@ pub fn lower_function(core_func: &ir_core::Function) -> Result<ir::Function> {
ir_core::Instr::And => ir::InstrKind::And, ir_core::Instr::And => ir::InstrKind::And,
ir_core::Instr::Or => ir::InstrKind::Or, ir_core::Instr::Or => ir::InstrKind::Or,
ir_core::Instr::Not => ir::InstrKind::Not, ir_core::Instr::Not => ir::InstrKind::Not,
ir_core::Instr::Alloc | ir_core::Instr::Free | ir_core::Instr::ReadGate | ir_core::Instr::WriteGate => { ir_core::Instr::Alloc => ir::InstrKind::Alloc,
// HIP effects are not yet supported in VM IR, so we emit Nop or similar. ir_core::Instr::ReadGate => ir::InstrKind::LoadRef(0),
// For now, let's use Nop. ir_core::Instr::WriteGate => ir::InstrKind::StoreRef(0),
ir::InstrKind::Nop ir_core::Instr::Free => ir::InstrKind::Nop,
}
}; };
vm_func.body.push(ir::Instruction::new(kind, None)); vm_func.body.push(ir::Instruction::new(kind, None));
} }

View File

@ -0,0 +1,50 @@
use prometeu_compiler::compiler;
use prometeu_bytecode::pbc::parse_pbc;
use prometeu_bytecode::disasm::disasm;
use prometeu_bytecode::opcode::OpCode;
use std::fs;
use tempfile::tempdir;
#[test]
fn test_compile_hip_program() {
let dir = tempdir().unwrap();
let project_dir = dir.path();
// Create prometeu.json
fs::write(
project_dir.join("prometeu.json"),
r#"{
"script_fe": "pbs",
"entry": "main.pbs"
}"#,
).unwrap();
// Create main.pbs with HIP effects
let code = "
fn main() {
let x = alloc int;
mutate x as v {
let y = v + 1;
}
}
";
fs::write(project_dir.join("main.pbs"), code).unwrap();
// Compile
let unit = compiler::compile(project_dir).expect("Failed to compile");
// Parse PBC
let pbc = parse_pbc(&unit.rom).expect("Failed to parse PBC");
// Disassemble
let instrs = disasm(&pbc.rom).expect("Failed to disassemble");
// Verify opcodes exist in bytecode
let opcodes: Vec<_> = instrs.iter().map(|i| i.opcode).collect();
assert!(opcodes.contains(&OpCode::Alloc));
assert!(opcodes.contains(&OpCode::LoadRef)); // From ReadGate
assert!(opcodes.contains(&OpCode::StoreRef)); // From WriteGate
assert!(opcodes.contains(&OpCode::Add));
assert!(opcodes.contains(&OpCode::Ret));
}