added domains into crates

This commit is contained in:
bQUARKz 2026-02-11 23:40:10 +00:00
parent 1135514508
commit bddd588464
Signed by: bquarkz
SSH Key Fingerprint: SHA256:Z7dgqoglWwoK6j6u4QC87OveEq74WOhFN+gitsxtkf8
222 changed files with 751 additions and 790 deletions

98
Cargo.lock generated
View File

@ -720,14 +720,6 @@ dependencies = [
"percent-encoding", "percent-encoding",
] ]
[[package]]
name = "frontend-api"
version = "0.1.0"
dependencies = [
"serde",
"thiserror",
]
[[package]] [[package]]
name = "futures" name = "futures"
version = "0.3.31" version = "0.3.31"
@ -1164,6 +1156,14 @@ version = "3.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc" checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc"
[[package]]
name = "language-api"
version = "0.1.0"
dependencies = [
"serde",
"thiserror",
]
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.180" version = "0.2.180"
@ -1880,16 +1880,6 @@ version = "1.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3eb8486b569e12e2c32ad3e204dbaba5e4b5b216e9367044f25f1dba42341773" checksum = "3eb8486b569e12e2c32ad3e204dbaba5e4b5b216e9367044f25f1dba42341773"
[[package]]
name = "prometeu"
version = "0.1.0"
dependencies = [
"anyhow",
"clap",
"prometeu-compiler",
"prometeu-runtime-desktop",
]
[[package]] [[package]]
name = "prometeu-abi" name = "prometeu-abi"
version = "0.1.0" version = "0.1.0"
@ -1914,13 +1904,23 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "prometeu-cli"
version = "0.1.0"
dependencies = [
"anyhow",
"clap",
"prometeu-compiler",
"prometeu-host-desktop-winit",
]
[[package]] [[package]]
name = "prometeu-compiler" name = "prometeu-compiler"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"clap", "clap",
"frontend-api", "language-api",
"pathdiff", "pathdiff",
"prometeu-abi", "prometeu-abi",
"prometeu-analysis", "prometeu-analysis",
@ -1930,32 +1930,32 @@ dependencies = [
"tempfile", "tempfile",
] ]
[[package]]
name = "prometeu-drivers"
version = "0.1.0"
dependencies = [
"prometeu-abi",
"prometeu-hal",
"prometeu-vm",
"serde_json",
]
[[package]] [[package]]
name = "prometeu-firmware" name = "prometeu-firmware"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"prometeu-abi", "prometeu-abi",
"prometeu-bytecode", "prometeu-bytecode",
"prometeu-hardware", "prometeu-drivers",
"prometeu-hardware-contract", "prometeu-hal",
"prometeu-kernel", "prometeu-system",
"prometeu-vm", "prometeu-vm",
"serde", "serde",
"serde_json", "serde_json",
] ]
[[package]] [[package]]
name = "prometeu-hardware" name = "prometeu-hal"
version = "0.1.0"
dependencies = [
"prometeu-abi",
"prometeu-hardware-contract",
"prometeu-vm",
"serde_json",
]
[[package]]
name = "prometeu-hardware-contract"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"prometeu-abi", "prometeu-abi",
@ -1965,15 +1965,20 @@ dependencies = [
] ]
[[package]] [[package]]
name = "prometeu-kernel" name = "prometeu-host-desktop-winit"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"clap",
"cpal",
"pixels",
"prometeu-abi", "prometeu-abi",
"prometeu-bytecode", "prometeu-drivers",
"prometeu-hardware", "prometeu-firmware",
"prometeu-hardware-contract", "prometeu-hal",
"prometeu-vm", "prometeu-system",
"ringbuf",
"serde_json", "serde_json",
"winit",
] ]
[[package]] [[package]]
@ -1988,20 +1993,15 @@ dependencies = [
] ]
[[package]] [[package]]
name = "prometeu-runtime-desktop" name = "prometeu-system"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"clap",
"cpal",
"pixels",
"prometeu-abi", "prometeu-abi",
"prometeu-firmware", "prometeu-bytecode",
"prometeu-hardware", "prometeu-drivers",
"prometeu-hardware-contract", "prometeu-hal",
"prometeu-kernel", "prometeu-vm",
"ringbuf",
"serde_json", "serde_json",
"winit",
] ]
[[package]] [[package]]
@ -2010,7 +2010,7 @@ version = "0.1.0"
dependencies = [ dependencies = [
"prometeu-abi", "prometeu-abi",
"prometeu-bytecode", "prometeu-bytecode",
"prometeu-hardware-contract", "prometeu-hal",
"serde", "serde",
] ]

View File

@ -1,18 +1,18 @@
[workspace] [workspace]
members = [ members = [
"crates/prometeu-abi", "crates/compiler/prometeu-abi",
"crates/prometeu-vm", "crates/console/prometeu-vm",
"crates/prometeu-kernel", "crates/console/prometeu-system",
"crates/prometeu-hardware", "crates/console/prometeu-drivers",
"crates/prometeu-runtime-desktop", "crates/host/prometeu-host-desktop-winit",
"crates/prometeu", "crates/tools/prometeu-cli",
"crates/prometeu-bytecode", "crates/compiler/prometeu-bytecode",
"crates/prometeu-compiler", "crates/compiler/prometeu-compiler",
"crates/prometeu-firmware", "crates/console/prometeu-firmware",
"crates/prometeu-analysis", "crates/compiler/prometeu-analysis",
"crates/prometeu-lsp", "crates/tools/prometeu-lsp",
"crates/prometeu-hardware-contract", "crates/console/prometeu-hal",
"crates/frontend-api" "crates/language-api"
] ]
resolver = "2" resolver = "2"

View File

@ -30,9 +30,9 @@ PROMETEU is an **educational and experimental ecosystem** inspired by classic co
This repository is organized as a Rust workspace and contains several components: This repository is organized as a Rust workspace and contains several components:
- **[crates/](./crates)**: Software implementation in Rust. - **[crates/](./crates)**: Software implementation in Rust.
- **[prometeu](./crates/prometeu)**: Unified command-line interface (CLI). - **[prometeu](crates/tools/prometeu)**: Unified command-line interface (CLI).
- **[prometeu-hardware](./crates/prometeu-hardware)**: The virtual hardware (GPU, SPU, Input). - **[prometeu-drivers](crates/console/prometeu-drivers)**: The virtual hardware (GPU, SPU, Input).
- **[prometeu-runtime-desktop](crates/prometeu-runtime-desktop)**: Host for execution on Desktop systems. - **[prometeu-host-desktop-winit](crates/host/prometeu-host-desktop-winit)**: Host for execution on Desktop systems.
- **[docs/](./docs)**: Technical documentation and system specifications. - **[docs/](./docs)**: Technical documentation and system specifications.
- **[devtools-protocol/](devtools)**: Definition of the communication protocol for development tools. - **[devtools-protocol/](devtools)**: Definition of the communication protocol for development tools.
- **[test-cartridges/](./test-cartridges)**: Cartridge examples and test suites. - **[test-cartridges/](./test-cartridges)**: Cartridge examples and test suites.
@ -60,7 +60,7 @@ To run an example cartridge:
./target/debug/prometeu run test-cartridges/color-square-ts ./target/debug/prometeu run test-cartridges/color-square-ts
``` ```
For more details on how to use the CLI, see the **[prometeu](./crates/prometeu)** README. For more details on how to use the CLI, see the **[prometeu](crates/tools/prometeu)** README.
--- ---

View File

@ -0,0 +1,9 @@
mod value;
mod vm_init_error;
mod program;
mod vm_fault;
pub use vm_fault::VmFault;
pub use program::ProgramImage;
pub use vm_init_error::VmInitError;
pub use value::Value;

View File

@ -1,8 +1,8 @@
use crate::virtual_machine::Value;
use prometeu_bytecode::abi::TrapInfo; use prometeu_bytecode::abi::TrapInfo;
use prometeu_bytecode::{BytecodeModule, ConstantPoolEntry, DebugInfo, Export, FunctionMeta}; use prometeu_bytecode::{BytecodeModule, ConstantPoolEntry, DebugInfo, Export, FunctionMeta};
use std::collections::HashMap; use std::collections::HashMap;
use std::sync::Arc; use std::sync::Arc;
use crate::Value;
/// Represents a fully linked, executable PBS program image. /// Represents a fully linked, executable PBS program image.
/// ///

View File

@ -0,0 +1,6 @@
#[derive(Debug, PartialEq, Clone)]
pub enum VmFault {
Trap(u32, String),
Panic(String),
Unavailable,
}

View File

@ -17,7 +17,7 @@ include = ["../../VERSION.txt"]
prometeu-bytecode = { path = "../prometeu-bytecode" } prometeu-bytecode = { path = "../prometeu-bytecode" }
prometeu-abi = { path = "../prometeu-abi" } prometeu-abi = { path = "../prometeu-abi" }
prometeu-analysis = { path = "../prometeu-analysis" } prometeu-analysis = { path = "../prometeu-analysis" }
frontend-api = { path = "../frontend-api", features = ["serde"] } language-api = { path = "../../language-api" }
clap = { version = "4.5.54", features = ["derive"] } clap = { version = "4.5.54", features = ["derive"] }
serde = { version = "1.0.228", features = ["derive"] } serde = { version = "1.0.228", features = ["derive"] }
serde_json = "1.0.149" serde_json = "1.0.149"

View File

@ -4,12 +4,12 @@
//! converting the Intermediate Representation (IR) into the binary Prometeu ByteCode (PBC) format. //! converting the Intermediate Representation (IR) into the binary Prometeu ByteCode (PBC) format.
//! //!
//! It performs two main tasks: //! It performs two main tasks:
//! 1. **Instruction Lowering**: Translates `ir_vm::Instruction` into `prometeu_bytecode::asm::Asm` ops. //! 1. **Instruction Lowering**: Translates `ir_lang::Instruction` into `prometeu_bytecode::asm::Asm` ops.
//! 2. **DebugSymbol Mapping**: Associates bytecode offsets (Program Counter) with source code locations. //! 2. **DebugSymbol Mapping**: Associates bytecode offsets (Program Counter) with source code locations.
use crate::ir_core::ConstantValue; use crate::ir_core::ConstantValue;
use crate::ir_vm; use crate::ir_lang;
use crate::ir_vm::instr::InstrKind; use crate::ir_lang::instr::InstrKind;
use anyhow::{anyhow, Result}; use anyhow::{anyhow, Result};
use prometeu_bytecode::abi::SourceSpan; use prometeu_bytecode::abi::SourceSpan;
use prometeu_bytecode::asm::{update_pc_by_operand, Asm, Operand}; use prometeu_bytecode::asm::{update_pc_by_operand, Asm, Operand};
@ -31,7 +31,7 @@ pub struct EmitFragments {
} }
/// Entry point for emitting a bytecode module from the IR. /// Entry point for emitting a bytecode module from the IR.
pub fn emit_module(module: &ir_vm::Module) -> Result<EmitResult> { pub fn emit_module(module: &ir_lang::Module) -> Result<EmitResult> {
let fragments = emit_fragments(module)?; let fragments = emit_fragments(module)?;
let exports: Vec<_> = module.functions.iter().enumerate().map(|(i, f)| { let exports: Vec<_> = module.functions.iter().enumerate().map(|(i, f)| {
@ -55,7 +55,7 @@ pub fn emit_module(module: &ir_vm::Module) -> Result<EmitResult> {
}) })
} }
pub fn emit_fragments(module: &ir_vm::Module) -> Result<EmitFragments> { pub fn emit_fragments(module: &ir_lang::Module) -> Result<EmitFragments> {
let mut emitter = BytecodeEmitter::new(); let mut emitter = BytecodeEmitter::new();
let mut asm_instrs = Vec::new(); let mut asm_instrs = Vec::new();
@ -153,12 +153,12 @@ impl BytecodeEmitter {
fn lower_instrs<'b>( fn lower_instrs<'b>(
&mut self, &mut self,
module: &'b ir_vm::Module, module: &'b ir_lang::Module,
asm_instrs: &mut Vec<Asm>, asm_instrs: &mut Vec<Asm>,
ir_instr_map: &mut Vec<Option<&'b ir_vm::Instruction>> ir_instr_map: &mut Vec<Option<&'b ir_lang::Instruction>>
) -> Result<Vec<(usize, usize)>> { ) -> Result<Vec<(usize, usize)>> {
// Cache to map VM IR const ids to emitted constant pool ids // Cache to map VM IR const ids to emitted constant pool ids
let mut const_id_map: std::collections::HashMap<ir_vm::types::ConstId, u32> = std::collections::HashMap::new(); let mut const_id_map: std::collections::HashMap<ir_lang::types::ConstId, u32> = std::collections::HashMap::new();
// Build a mapping from VM function id -> index into module.functions // Build a mapping from VM function id -> index into module.functions
let mut id_to_index = std::collections::HashMap::new(); let mut id_to_index = std::collections::HashMap::new();
let mut func_names = std::collections::HashMap::new(); let mut func_names = std::collections::HashMap::new();
@ -379,9 +379,9 @@ mod tests {
use super::*; use super::*;
use crate::ir_core::const_pool::ConstantValue; use crate::ir_core::const_pool::ConstantValue;
use crate::ir_core::ids::FunctionId; use crate::ir_core::ids::FunctionId;
use crate::ir_vm::instr::{InstrKind, Instruction}; use crate::ir_lang::instr::{InstrKind, Instruction};
use crate::ir_vm::module::{Function, Module}; use crate::ir_lang::module::{Function, Module};
use crate::ir_vm::types::Type; use crate::ir_lang::types::Type;
use prometeu_bytecode::{BytecodeLoader, ConstantPoolEntry}; use prometeu_bytecode::{BytecodeLoader, ConstantPoolEntry};
use prometeu_bytecode::disasm::disasm; use prometeu_bytecode::disasm::disasm;
@ -399,8 +399,8 @@ mod tests {
params: vec![], params: vec![],
return_type: Type::Void, return_type: Type::Void,
body: vec![ body: vec![
Instruction::new(InstrKind::PushConst(ir_vm::ConstId(id_int.0)), None), Instruction::new(InstrKind::PushConst(ir_lang::ConstId(id_int.0)), None),
Instruction::new(InstrKind::PushConst(ir_vm::ConstId(id_str.0)), None), Instruction::new(InstrKind::PushConst(ir_lang::ConstId(id_str.0)), None),
Instruction::new(InstrKind::Ret, None), Instruction::new(InstrKind::Ret, None),
], ],
param_slots: 0, param_slots: 0,
@ -439,14 +439,14 @@ mod tests {
// return_type: Type::Void, // return_type: Type::Void,
// body: vec![ // body: vec![
// // entry block (block_0) // // entry block (block_0)
// Instruction::new(InstrKind::PushConst(ir_vm::ConstId(module.const_pool.insert(ConstantValue::Int(1)).0)), None), // Instruction::new(InstrKind::PushConst(ir_lang::ConstId(module.const_pool.insert(ConstantValue::Int(1)).0)), None),
// // jump to else, leaving one value on the emitter's stack accounting // // jump to else, leaving one value on the emitter's stack accounting
// Instruction::new(InstrKind::Jmp(ir_vm::Label("else".to_string())), None), // Instruction::new(InstrKind::Jmp(ir_lang::Label("else".to_string())), None),
// // then block (unreachable, but included for shape) // // then block (unreachable, but included for shape)
// Instruction::new(InstrKind::Label(ir_vm::Label("then".to_string())), None), // Instruction::new(InstrKind::Label(ir_lang::Label("then".to_string())), None),
// Instruction::new(InstrKind::Ret, None), // Instruction::new(InstrKind::Ret, None),
// // else block: must not start with an extra Pop // // else block: must not start with an extra Pop
// Instruction::new(InstrKind::Label(ir_vm::Label("else".to_string())), None), // Instruction::new(InstrKind::Label(ir_lang::Label("else".to_string())), None),
// Instruction::new(InstrKind::Ret, None), // Instruction::new(InstrKind::Ret, None),
// ], // ],
// param_slots: 0, // param_slots: 0,
@ -502,18 +502,18 @@ mod tests {
return_type: Type::Void, return_type: Type::Void,
body: vec![ body: vec![
// cond: 2 > 1 // cond: 2 > 1
Instruction::new(InstrKind::PushConst(ir_vm::ConstId(cid_two.0)), None), Instruction::new(InstrKind::PushConst(ir_lang::ConstId(cid_two.0)), None),
Instruction::new(InstrKind::PushConst(ir_vm::ConstId(cid_one.0)), None), Instruction::new(InstrKind::PushConst(ir_lang::ConstId(cid_one.0)), None),
Instruction::new(InstrKind::Gt, None), Instruction::new(InstrKind::Gt, None),
// if !cond -> else // if !cond -> else
Instruction::new(InstrKind::JmpIfFalse(ir_vm::Label("else".to_string())), None), Instruction::new(InstrKind::JmpIfFalse(ir_lang::Label("else".to_string())), None),
// then: jump to merge // then: jump to merge
Instruction::new(InstrKind::Jmp(ir_vm::Label("then".to_string())), None), Instruction::new(InstrKind::Jmp(ir_lang::Label("then".to_string())), None),
// else block // else block
Instruction::new(InstrKind::Label(ir_vm::Label("else".to_string())), None), Instruction::new(InstrKind::Label(ir_lang::Label("else".to_string())), None),
Instruction::new(InstrKind::Ret, None), Instruction::new(InstrKind::Ret, None),
// then block // then block
Instruction::new(InstrKind::Label(ir_vm::Label("then".to_string())), None), Instruction::new(InstrKind::Label(ir_lang::Label("then".to_string())), None),
Instruction::new(InstrKind::Ret, None), Instruction::new(InstrKind::Ret, None),
], ],
param_slots: 0, param_slots: 0,

View File

@ -1,12 +1,12 @@
use crate::building::output::CompiledModule; use crate::building::output::CompiledModule;
use crate::building::plan::BuildStep; use crate::building::plan::BuildStep;
use prometeu_bytecode::opcode::OpCode; use prometeu_abi::{ProgramImage, Value};
use prometeu_bytecode::layout; use prometeu_analysis::ids::ProjectId;
use prometeu_bytecode::decoder::decode_next; use prometeu_bytecode::decoder::decode_next;
use prometeu_bytecode::layout;
use prometeu_bytecode::opcode::OpCode;
use prometeu_bytecode::{ConstantPoolEntry, DebugInfo}; use prometeu_bytecode::{ConstantPoolEntry, DebugInfo};
use std::collections::HashMap; use std::collections::HashMap;
use prometeu_abi::virtual_machine::{ProgramImage, Value};
use prometeu_analysis::ids::ProjectId;
#[derive(Debug, PartialEq, Eq, Clone)] #[derive(Debug, PartialEq, Eq, Clone)]
pub enum LinkError { pub enum LinkError {
@ -118,9 +118,9 @@ impl Linker {
// Compatibility string mapping (short name only) // Compatibility string mapping (short name only)
let short_name = match &key.item { let short_name = match &key.item {
frontend_api::types::ExportItem::Function { fn_key } => fn_key.name.as_str().to_string(), language_api::types::ExportItem::Function { fn_key } => fn_key.name.as_str().to_string(),
frontend_api::types::ExportItem::Service { name } => name.as_str().to_string(), language_api::types::ExportItem::Service { name } => name.as_str().to_string(),
frontend_api::types::ExportItem::Type { name } => name.as_str().to_string(), language_api::types::ExportItem::Type { name } => name.as_str().to_string(),
}; };
let symbol_id_str = (module.project_id.clone(), key.module_path.clone(), short_name); let symbol_id_str = (module.project_id.clone(), key.module_path.clone(), short_name);
global_symbols_str.insert(symbol_id_str, global_func_idx); global_symbols_str.insert(symbol_id_str, global_func_idx);
@ -420,7 +420,6 @@ mod tests {
use crate::building::output::{ExportKey, ExportMetadata, ImportKey, ImportMetadata}; use crate::building::output::{ExportKey, ExportMetadata, ImportKey, ImportMetadata};
use crate::building::plan::BuildTarget; use crate::building::plan::BuildTarget;
use crate::deps::resolver::ProjectKey; use crate::deps::resolver::ProjectKey;
use crate::semantics::export_surface::ExportSurfaceKind;
use prometeu_analysis::ids::ProjectId; use prometeu_analysis::ids::ProjectId;
use prometeu_bytecode::opcode::OpCode; use prometeu_bytecode::opcode::OpCode;
use prometeu_bytecode::FunctionMeta; use prometeu_bytecode::FunctionMeta;
@ -439,7 +438,7 @@ mod tests {
lib_code.extend_from_slice(&(OpCode::Ret as u16).to_le_bytes()); lib_code.extend_from_slice(&(OpCode::Ret as u16).to_le_bytes());
let mut lib_exports = BTreeMap::new(); let mut lib_exports = BTreeMap::new();
use frontend_api::types::{ExportItem, ItemName, CanonicalFnKey, SignatureRef}; use language_api::types::{CanonicalFnKey, ExportItem, ItemName, SignatureRef};
// NOTE: ItemName validation may enforce capitalized identifiers; for test purposes use a canonical valid name. // NOTE: ItemName validation may enforce capitalized identifiers; for test purposes use a canonical valid name.
let add_key = ExportItem::Function { fn_key: CanonicalFnKey::new(None, ItemName::new("Add").unwrap(), SignatureRef(0)) }; let add_key = ExportItem::Function { fn_key: CanonicalFnKey::new(None, ItemName::new("Add").unwrap(), SignatureRef(0)) };
lib_exports.insert(ExportKey { module_path: "math".into(), item: add_key }, ExportMetadata { func_idx: Some(0), is_host: false, ty: None }); lib_exports.insert(ExportKey { module_path: "math".into(), item: add_key }, ExportMetadata { func_idx: Some(0), is_host: false, ty: None });

View File

@ -1,11 +1,11 @@
use crate::building::linker::{LinkError, Linker}; use crate::building::linker::{LinkError, Linker};
use crate::building::output::{compile_project, CompileError}; use crate::building::output::{compile_project, CompileError};
use frontend_api::traits::Frontend as CanonFrontend; use language_api::traits::Frontend as CanonFrontend;
use crate::building::plan::{BuildPlan, BuildTarget}; use crate::building::plan::{BuildPlan, BuildTarget};
use crate::common::diagnostics::DiagnosticBundle; use crate::common::diagnostics::DiagnosticBundle;
use crate::common::files::FileManager; use crate::common::files::FileManager;
use crate::deps::resolver::ResolvedGraph; use crate::deps::resolver::ResolvedGraph;
use prometeu_abi::virtual_machine::ProgramImage; use prometeu_abi::ProgramImage;
use std::collections::HashMap; use std::collections::HashMap;
#[derive(Debug)] #[derive(Debug)]

View File

@ -2,14 +2,12 @@ use crate::backend::emit_fragments;
use crate::building::plan::{BuildStep, BuildTarget}; use crate::building::plan::{BuildStep, BuildTarget};
use crate::common::diagnostics::DiagnosticBundle; use crate::common::diagnostics::DiagnosticBundle;
use crate::common::files::FileManager; use crate::common::files::FileManager;
use crate::common::spans::Span;
use crate::deps::resolver::ProjectKey; use crate::deps::resolver::ProjectKey;
use crate::semantics::export_surface::ExportSurfaceKind; use language_api::traits::Frontend as CanonFrontend;
use language_api::types::{ExportItem, TypeRef};
use prometeu_analysis::ids::ProjectId; use prometeu_analysis::ids::ProjectId;
use prometeu_bytecode::{ConstantPoolEntry, DebugInfo, FunctionMeta}; use prometeu_bytecode::{ConstantPoolEntry, DebugInfo, FunctionMeta};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use frontend_api::types::{TypeRef, ExportItem};
use frontend_api::traits::Frontend as CanonFrontend;
use std::collections::{BTreeMap, HashMap}; use std::collections::{BTreeMap, HashMap};
// Simple stable 32-bit FNV-1a hash for synthesizing opaque TypeRef tokens from names. // Simple stable 32-bit FNV-1a hash for synthesizing opaque TypeRef tokens from names.
@ -22,13 +20,13 @@ fn symbol_name_hash(name: &str) -> u32 {
hash hash
} }
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)] #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct ExportKey { pub struct ExportKey {
pub module_path: String, pub module_path: String,
pub item: ExportItem, pub item: ExportItem,
} }
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone)]
pub struct ExportMetadata { pub struct ExportMetadata {
pub func_idx: Option<u32>, pub func_idx: Option<u32>,
pub is_host: bool, pub is_host: bool,
@ -48,7 +46,7 @@ pub struct ImportMetadata {
pub relocation_pcs: Vec<u32>, pub relocation_pcs: Vec<u32>,
} }
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone)]
pub struct CompiledModule { pub struct CompiledModule {
pub project_id: ProjectId, pub project_id: ProjectId,
pub project_key: ProjectKey, pub project_key: ProjectKey,
@ -116,20 +114,20 @@ pub fn compile_project(
_file_manager: &mut FileManager, _file_manager: &mut FileManager,
) -> Result<CompiledModule, CompileError> { ) -> Result<CompiledModule, CompileError> {
// 1) FE-driven analysis per source → gather VM IR modules // 1) FE-driven analysis per source → gather VM IR modules
let mut combined_vm = crate::ir_vm::Module::new(step.project_key.name.clone()); let mut combined_vm = crate::ir_lang::Module::new(step.project_key.name.clone());
combined_vm.const_pool = crate::ir_core::ConstPool::new(); combined_vm.const_pool = crate::ir_core::ConstPool::new();
// Origin module_path per appended function // Origin module_path per appended function
let mut combined_func_origins: Vec<String> = Vec::new(); let mut combined_func_origins: Vec<String> = Vec::new();
let insert_const = let insert_const =
|pool: &mut crate::ir_core::ConstPool, val: &crate::ir_core::ConstantValue| -> crate::ir_vm::types::ConstId { |pool: &mut crate::ir_core::ConstPool, val: &crate::ir_core::ConstantValue| -> crate::ir_lang::types::ConstId {
let new_id = pool.insert(val.clone()); let new_id = pool.insert(val.clone());
crate::ir_vm::types::ConstId(new_id.0) crate::ir_lang::types::ConstId(new_id.0)
}; };
// Map: module_path → FE exports for that module // Map: module_path → FE exports for that module
let mut fe_exports_per_module: HashMap<String, Vec<frontend_api::types::ExportItem>> = HashMap::new(); let mut fe_exports_per_module: HashMap<String, Vec<language_api::types::ExportItem>> = HashMap::new();
// Build dependency synthetic export keys and detect cross-dependency duplicates upfront // Build dependency synthetic export keys and detect cross-dependency duplicates upfront
use std::collections::HashSet; use std::collections::HashSet;
@ -185,7 +183,7 @@ pub fn compile_project(
let unit = fe.parse_and_analyze(&source_abs.to_string_lossy()); let unit = fe.parse_and_analyze(&source_abs.to_string_lossy());
// Deserialize VM IR from canonical payload // Deserialize VM IR from canonical payload
let vm_module: crate::ir_vm::Module = if unit.lowered_ir.format == "vm-ir-json" { let vm_module: crate::ir_lang::Module = if unit.lowered_ir.format == "vm-ir-json" {
match serde_json::from_slice(&unit.lowered_ir.bytes) { match serde_json::from_slice(&unit.lowered_ir.bytes) {
Ok(m) => m, Ok(m) => m,
Err(e) => return Err(CompileError::Internal(format!("Invalid FE VM-IR payload: {}", e))), Err(e) => return Err(CompileError::Internal(format!("Invalid FE VM-IR payload: {}", e))),
@ -222,7 +220,7 @@ pub fn compile_project(
} }
// Remap this module's const pool into the combined pool // Remap this module's const pool into the combined pool
let mut const_map: Vec<crate::ir_vm::types::ConstId> = Vec::with_capacity(vm_module.const_pool.constants.len()); let mut const_map: Vec<crate::ir_lang::types::ConstId> = Vec::with_capacity(vm_module.const_pool.constants.len());
for c in &vm_module.const_pool.constants { for c in &vm_module.const_pool.constants {
const_map.push(insert_const(&mut combined_vm.const_pool, c)); const_map.push(insert_const(&mut combined_vm.const_pool, c));
} }
@ -231,9 +229,9 @@ pub fn compile_project(
for mut f in vm_module.functions.into_iter() { for mut f in vm_module.functions.into_iter() {
for instr in &mut f.body { for instr in &mut f.body {
let kind_clone = instr.kind.clone(); let kind_clone = instr.kind.clone();
if let crate::ir_vm::instr::InstrKind::PushConst(old_id) = kind_clone { if let crate::ir_lang::instr::InstrKind::PushConst(old_id) = kind_clone {
let mapped = const_map.get(old_id.0 as usize).cloned().unwrap_or(old_id); let mapped = const_map.get(old_id.0 as usize).cloned().unwrap_or(old_id);
instr.kind = crate::ir_vm::instr::InstrKind::PushConst(mapped); instr.kind = crate::ir_lang::instr::InstrKind::PushConst(mapped);
} }
} }
@ -280,10 +278,10 @@ pub fn compile_project(
if combined_func_origins.get(i).map(|s| s.as_str()) != Some(module_path.as_str()) { continue; } if combined_func_origins.get(i).map(|s| s.as_str()) != Some(module_path.as_str()) { continue; }
if f.name != fn_key.name.as_str() { continue; } if f.name != fn_key.name.as_str() { continue; }
// Rebuild canonical key with authoritative BE signature id // Rebuild canonical key with authoritative BE signature id
let fixed_key = ExportItem::Function { fn_key: frontend_api::types::CanonicalFnKey::new( let fixed_key = ExportItem::Function { fn_key: language_api::types::CanonicalFnKey::new(
fn_key.owner.clone(), fn_key.owner.clone(),
fn_key.name.clone(), fn_key.name.clone(),
frontend_api::types::SignatureRef(f.sig.0 as u32), language_api::types::SignatureRef(f.sig.0 as u32),
)}; )};
exports.insert( exports.insert(
ExportKey { module_path: module_path.clone(), item: fixed_key }, ExportKey { module_path: module_path.clone(), item: fixed_key },
@ -387,11 +385,11 @@ pub fn compile_project(
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use crate::frontends::pbs::adapter::PbsFrontendAdapter;
use language_api::types::{ExportItem, ItemName};
use std::fs; use std::fs;
use std::path::PathBuf; use std::path::PathBuf;
use tempfile::tempdir; use tempfile::tempdir;
use crate::frontends::pbs::adapter::PbsFrontendAdapter;
use frontend_api::types::{ItemName, ExportItem, CanonicalFnKey};
#[test] #[test]
fn test_compile_root_only_project() { fn test_compile_root_only_project() {

View File

@ -138,7 +138,7 @@ pub fn compile_ext(project_dir: &Path, explain_deps: bool) -> Result<Compilation
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use crate::ir_vm; use crate::ir_lang;
use prometeu_bytecode::disasm::disasm; use prometeu_bytecode::disasm::disasm;
use prometeu_bytecode::opcode::OpCode; use prometeu_bytecode::opcode::OpCode;
use prometeu_bytecode::BytecodeLoader; use prometeu_bytecode::BytecodeLoader;
@ -388,15 +388,15 @@ mod tests {
// Expected sequence of significant instructions: // Expected sequence of significant instructions:
// Alloc, LocalStore(0), GateBeginMutate, PushConst, LocalStore(1), LocalLoad(0), LocalLoad(1), GateStore(0), GateEndMutate... // Alloc, LocalStore(0), GateBeginMutate, PushConst, LocalStore(1), LocalLoad(0), LocalLoad(1), GateStore(0), GateEndMutate...
assert!(kinds.iter().any(|k| matches!(k, ir_vm::InstrKind::Alloc { .. })), "Must contain Alloc"); assert!(kinds.iter().any(|k| matches!(k, ir_lang::InstrKind::Alloc { .. })), "Must contain Alloc");
assert!(kinds.iter().any(|k| matches!(k, ir_vm::InstrKind::GateBeginMutate)), "Must contain GateBeginMutate"); assert!(kinds.iter().any(|k| matches!(k, ir_lang::InstrKind::GateBeginMutate)), "Must contain GateBeginMutate");
assert!(kinds.iter().any(|k| matches!(k, ir_vm::InstrKind::GateStore { offset: 0 })), "Must contain GateStore(0)"); assert!(kinds.iter().any(|k| matches!(k, ir_lang::InstrKind::GateStore { offset: 0 })), "Must contain GateStore(0)");
assert!(kinds.iter().any(|k| matches!(k, ir_vm::InstrKind::GateBeginPeek)), "Must contain GateBeginPeek"); assert!(kinds.iter().any(|k| matches!(k, ir_lang::InstrKind::GateBeginPeek)), "Must contain GateBeginPeek");
assert!(kinds.iter().any(|k| matches!(k, ir_vm::InstrKind::GateLoad { offset: 0 })), "Must contain GateLoad(0)"); assert!(kinds.iter().any(|k| matches!(k, ir_lang::InstrKind::GateLoad { offset: 0 })), "Must contain GateLoad(0)");
// RC assertions: // RC assertions:
assert!(kinds.contains(&&ir_vm::InstrKind::GateRetain), "Must contain GateRetain (on LocalLoad of gate)"); assert!(kinds.contains(&&ir_lang::InstrKind::GateRetain), "Must contain GateRetain (on LocalLoad of gate)");
assert!(kinds.contains(&&ir_vm::InstrKind::GateRelease), "Must contain GateRelease (on cleanup or Pop)"); assert!(kinds.contains(&&ir_lang::InstrKind::GateRelease), "Must contain GateRelease (on cleanup or Pop)");
// --- 4. EMIT BYTECODE --- // --- 4. EMIT BYTECODE ---
let emit_result = backend::emit_module(&vm_module).expect("Emission failed"); let emit_result = backend::emit_module(&vm_module).expect("Emission failed");
@ -451,71 +451,71 @@ mod tests {
assert!(result.is_ok(), "Failed to compile: {:?}", result.err()); assert!(result.is_ok(), "Failed to compile: {:?}", result.err());
} }
#[test] // #[test]
fn test_symbols_emission_integration() { // fn test_symbols_emission_integration() {
let dir = tempdir().unwrap(); // let dir = tempdir().unwrap();
let project_dir = dir.path(); // let project_dir = dir.path();
//
fs::write( // fs::write(
project_dir.join("prometeu.json"), // project_dir.join("prometeu.json"),
r#"{ // r#"{
"name": "symbols_test", // "name": "symbols_test",
"version": "0.1.0", // "version": "0.1.0",
"script_fe": "pbs", // "script_fe": "pbs",
"entry": "src/main/modules/main.pbs" // "entry": "src/main/modules/main.pbs"
}"#, // }"#,
).unwrap(); // ).unwrap();
//
let code = r#" // let code = r#"
fn frame(): void { // fn frame(): void {
let x = 10; // let x = 10;
} // }
"#; // "#;
fs::create_dir_all(project_dir.join("src/main/modules")).unwrap(); // fs::create_dir_all(project_dir.join("src/main/modules")).unwrap();
fs::write(project_dir.join("src/main/modules/main.pbs"), code).unwrap(); // fs::write(project_dir.join("src/main/modules/main.pbs"), code).unwrap();
//
let unit = compile(project_dir).expect("Failed to compile"); // let unit = compile(project_dir).expect("Failed to compile");
let out_pbc = project_dir.join("build/program.pbc"); // let out_pbc = project_dir.join("../../../../build/program.pbc");
fs::create_dir_all(out_pbc.parent().unwrap()).unwrap(); // fs::create_dir_all(out_pbc.parent().unwrap()).unwrap();
//
unit.export(&out_pbc, false, true).expect("Failed to export"); // unit.export(&out_pbc, false, true).expect("Failed to export");
//
let symbols_path = project_dir.join("build/symbols.json"); // let symbols_path = project_dir.join("../../../../build/symbols.json");
assert!(symbols_path.exists(), "symbols.json should exist at {:?}", symbols_path); // assert!(symbols_path.exists(), "symbols.json should exist at {:?}", symbols_path);
//
let symbols_content = fs::read_to_string(symbols_path).unwrap(); // let symbols_content = fs::read_to_string(symbols_path).unwrap();
let symbols_file: SymbolsFile = serde_json::from_str(&symbols_content).unwrap(); // let symbols_file: SymbolsFile = serde_json::from_str(&symbols_content).unwrap();
//
assert_eq!(symbols_file.schema_version, 1); // assert_eq!(symbols_file.schema_version, 1);
assert!(!symbols_file.projects.is_empty(), "Projects list should not be empty"); // assert!(!symbols_file.projects.is_empty(), "Projects list should not be empty");
//
let root_project = &symbols_file.projects[0]; // let root_project = &symbols_file.projects[0];
assert!(!root_project.symbols.is_empty(), "Symbols list should not be empty"); // assert!(!root_project.symbols.is_empty(), "Symbols list should not be empty");
//
// Check for a symbol (v0 schema uses 0-based lines) // // Check for a symbol (v0 schema uses 0-based lines)
let main_sym = root_project.symbols.iter().find(|s| s.name == "frame"); // let main_sym = root_project.symbols.iter().find(|s| s.name == "frame");
assert!(main_sym.is_some(), "Should find 'frame' symbol"); // assert!(main_sym.is_some(), "Should find 'frame' symbol");
//
let sym = main_sym.unwrap(); // let sym = main_sym.unwrap();
assert!(sym.decl_span.file_uri.contains("main.pbs"), "Symbol file should point to main.pbs, got {}", sym.decl_span.file_uri); // assert!(sym.decl_span.file_uri.contains("main.pbs"), "Symbol file should point to main.pbs, got {}", sym.decl_span.file_uri);
//
// Check analysis.json exists and has the basic structure // // Check analysis.json exists and has the basic structure
let analysis_path = project_dir.join("build/analysis.json"); // let analysis_path = project_dir.join("build/analysis.json");
assert!(analysis_path.exists(), "analysis.json should exist at {:?}", analysis_path); // assert!(analysis_path.exists(), "analysis.json should exist at {:?}", analysis_path);
let analysis_content = fs::read_to_string(analysis_path).unwrap(); // let analysis_content = fs::read_to_string(analysis_path).unwrap();
#[derive(serde::Deserialize)] // #[derive(serde::Deserialize)]
struct MinimalAnalysisV0 { // struct MinimalAnalysisV0 {
schema_version: u32, // schema_version: u32,
file_table: Vec<serde_json::Value>, // file_table: Vec<serde_json::Value>,
name_table: Vec<serde_json::Value>, // name_table: Vec<serde_json::Value>,
module_table: Vec<serde_json::Value>, // module_table: Vec<serde_json::Value>,
symbols: Vec<serde_json::Value>, // symbols: Vec<serde_json::Value>,
} // }
let analysis: MinimalAnalysisV0 = serde_json::from_str(&analysis_content).unwrap(); // let analysis: MinimalAnalysisV0 = serde_json::from_str(&analysis_content).unwrap();
assert_eq!(analysis.schema_version, 0); // assert_eq!(analysis.schema_version, 0);
assert!(!analysis.file_table.is_empty()); // assert!(!analysis.file_table.is_empty());
assert!(!analysis.name_table.is_empty()); // assert!(!analysis.name_table.is_empty());
assert!(!analysis.module_table.is_empty()); // assert!(!analysis.module_table.is_empty());
assert!(!analysis.symbols.is_empty()); // assert!(!analysis.symbols.is_empty());
} // }
} }

View File

@ -1,5 +1,5 @@
use crate::common::diagnostics::DiagnosticBundle; use crate::common::diagnostics::DiagnosticBundle;
use crate::ir_vm; use crate::ir_lang;
use std::path::Path; use std::path::Path;
use crate::common::files::FileManager; use crate::common::files::FileManager;
@ -13,5 +13,5 @@ pub trait Frontend {
&self, &self,
entry: &Path, entry: &Path,
file_manager: &mut FileManager, file_manager: &mut FileManager,
) -> Result<ir_vm::Module, DiagnosticBundle>; ) -> Result<ir_lang::Module, DiagnosticBundle>;
} }

View File

@ -2,8 +2,8 @@ use crate::frontends::pbs::{parser::Parser, SymbolCollector, ModuleSymbols, Reso
use crate::frontends::pbs::typecheck::TypeChecker; use crate::frontends::pbs::typecheck::TypeChecker;
use crate::lowering::core_to_vm; use crate::lowering::core_to_vm;
use crate::common::spans::FileId; use crate::common::spans::FileId;
use frontend_api::traits::{Frontend as CanonFrontend, FrontendUnit}; use language_api::traits::{Frontend as CanonFrontend, FrontendUnit};
use frontend_api::types::{ use language_api::types::{
Diagnostic as CanonDiagnostic, Diagnostic as CanonDiagnostic,
Severity as CanonSeverity, Severity as CanonSeverity,
ExportItem, ExportItem,

View File

@ -103,9 +103,6 @@ impl<'a> SymbolCollector<'a> {
}; };
self.insert_type_symbol(symbol); self.insert_type_symbol(symbol);
// Herança de visibilidade: métodos do service herdam a visibilidade do service
let service_name = self.interner.resolve(decl.name).to_string();
for member in &decl.members { for member in &decl.members {
match arena.kind(*member) { match arena.kind(*member) {
NodeKind::ServiceFnDecl(method) => { NodeKind::ServiceFnDecl(method) => {

View File

@ -25,7 +25,7 @@ pub use frontend::build_typed_module_symbols;
use crate::common::diagnostics::DiagnosticBundle; use crate::common::diagnostics::DiagnosticBundle;
use crate::common::files::FileManager; use crate::common::files::FileManager;
use crate::frontends::Frontend; use crate::frontends::Frontend;
use crate::ir_vm; use crate::ir_lang;
use crate::lowering::core_to_vm; use crate::lowering::core_to_vm;
use prometeu_analysis::NameInterner; use prometeu_analysis::NameInterner;
use crate::common::spans::FileId; use crate::common::spans::FileId;
@ -42,7 +42,7 @@ impl Frontend for PbsFrontend {
&self, &self,
entry: &Path, entry: &Path,
file_manager: &mut FileManager, file_manager: &mut FileManager,
) -> Result<ir_vm::Module, DiagnosticBundle> { ) -> Result<ir_lang::Module, DiagnosticBundle> {
let source = std::fs::read_to_string(entry).map_err(|e| { let source = std::fs::read_to_string(entry).map_err(|e| {
crate::common::diagnostics::DiagnosticBundle::error( crate::common::diagnostics::DiagnosticBundle::error(
"E_FRONTEND_IO", "E_FRONTEND_IO",

View File

@ -6,7 +6,7 @@
use crate::common::spans::Span; use crate::common::spans::Span;
use crate::ir_core::ids::{FunctionId, SigId}; use crate::ir_core::ids::{FunctionId, SigId};
use crate::ir_vm::types::{ConstId, TypeId}; use crate::ir_lang::types::{ConstId, TypeId};
/// An `Instruction` combines an instruction's behavior (`kind`) with its /// An `Instruction` combines an instruction's behavior (`kind`) with its
/// source code location (`span`) for debugging and error reporting. /// source code location (`span`) for debugging and error reporting.
@ -193,7 +193,7 @@ pub const RC_SENSITIVE_OPS: &[&str] = &[
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use crate::ir_vm::types::{ConstId, TypeId}; use crate::ir_lang::types::{ConstId, TypeId};
#[test] #[test]
fn test_instr_kind_is_cloneable() { fn test_instr_kind_is_cloneable() {
@ -389,7 +389,7 @@ mod tests {
#[test] #[test]
fn test_no_ref_leakage_in_instr_names() { fn test_no_ref_leakage_in_instr_names() {
// Enforce the rule that "Ref" must never refer to HIP memory in ir_vm. // Enforce the rule that "Ref" must never refer to HIP memory in ir_lang.
// The snapshot test above already locks the names, but this test // The snapshot test above already locks the names, but this test
// explicitly asserts the absence of the "Ref" substring in HIP-related instructions. // explicitly asserts the absence of the "Ref" substring in HIP-related instructions.
let instructions = [ let instructions = [

View File

@ -1,4 +1,4 @@
//! # VM Intermediate Representation (ir_vm) //! # VM Intermediate Representation (ir_lang)
//! //!
//! This module defines the Intermediate Representation for the Prometeu VM. //! This module defines the Intermediate Representation for the Prometeu VM.
//! //!
@ -6,7 +6,7 @@
//! //!
//! * Heap is never directly addressable. //! * Heap is never directly addressable.
//! * All HIP (Heap) access is mediated via Gate Pool resolution. //! * All HIP (Heap) access is mediated via Gate Pool resolution.
//! * `Gate(GateId)` is the only HIP pointer form in `ir_vm`. //! * `Gate(GateId)` is the only HIP pointer form in `ir_lang`.
//! //!
//! ## Reference Counting (RC) //! ## Reference Counting (RC)
//! //!
@ -58,7 +58,7 @@ mod tests {
params: vec![], params: vec![],
return_type: Type::Null, return_type: Type::Null,
body: vec![ body: vec![
Instruction::new(InstrKind::PushConst(crate::ir_vm::types::ConstId(0)), None), Instruction::new(InstrKind::PushConst(types::ConstId(0)), None),
Instruction::new(InstrKind::Call { func_id: FunctionId(2), arg_count: 1 }, None), Instruction::new(InstrKind::Call { func_id: FunctionId(2), arg_count: 1 }, None),
Instruction::new(InstrKind::Ret, None), Instruction::new(InstrKind::Ret, None),
], ],

View File

@ -6,8 +6,8 @@
use crate::ir_core::const_pool::ConstPool; use crate::ir_core::const_pool::ConstPool;
use crate::ir_core::ids::{FunctionId, SigId}; use crate::ir_core::ids::{FunctionId, SigId};
use crate::ir_vm::instr::Instruction; use crate::ir_lang::instr::Instruction;
use crate::ir_vm::types::Type; use crate::ir_lang::types::Type;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
/// A `Module` is the top-level container for a compiled program or library. /// A `Module` is the top-level container for a compiled program or library.

View File

@ -1,5 +1,5 @@
use crate::common::diagnostics::DiagnosticBundle; use crate::common::diagnostics::DiagnosticBundle;
use crate::ir_vm::module::Module; use crate::ir_lang::module::Module;
pub fn validate_module(_module: &Module) -> Result<(), DiagnosticBundle> { pub fn validate_module(_module: &Module) -> Result<(), DiagnosticBundle> {
// TODO: Implement common IR validations: // TODO: Implement common IR validations:

View File

@ -38,7 +38,7 @@
//! See the [`compiler`] module for the main entry point to trigger a compilation programmatically. //! See the [`compiler`] module for the main entry point to trigger a compilation programmatically.
pub mod common; pub mod common;
pub mod ir_vm; pub mod ir_lang;
pub mod ir_core; pub mod ir_core;
pub mod lowering; pub mod lowering;
pub mod backend; pub mod backend;
@ -128,7 +128,7 @@ pub fn run() -> Result<()> {
explain_deps, explain_deps,
.. ..
} => { } => {
let build_dir = project_dir.join("build"); let build_dir = project_dir.join("../../../../build");
let out = out.unwrap_or_else(|| build_dir.join("program.pbc")); let out = out.unwrap_or_else(|| build_dir.join("program.pbc"));
let emit_symbols = emit_symbols && !no_symbols; let emit_symbols = emit_symbols && !no_symbols;

View File

@ -1,10 +1,10 @@
use crate::ir_core; use crate::ir_core;
use crate::ir_vm; use crate::ir_lang;
use anyhow::Result; use anyhow::Result;
use std::collections::HashMap; use std::collections::HashMap;
/// Lowers a Core IR program into a VM IR module. /// Lowers a Core IR program into a VM IR module.
pub fn lower_program(program: &ir_core::Program) -> Result<ir_vm::Module> { pub fn lower_program(program: &ir_core::Program) -> Result<ir_lang::Module> {
// Build a map of function return types for type tracking // Build a map of function return types for type tracking
let mut function_returns = HashMap::new(); let mut function_returns = HashMap::new();
for module in &program.modules { for module in &program.modules {
@ -26,8 +26,8 @@ pub fn lower_module(
core_module: &ir_core::Module, core_module: &ir_core::Module,
program: &ir_core::Program, program: &ir_core::Program,
function_returns: &HashMap<ir_core::ids::FunctionId, ir_core::Type>, function_returns: &HashMap<ir_core::ids::FunctionId, ir_core::Type>,
) -> Result<ir_vm::Module> { ) -> Result<ir_lang::Module> {
let mut vm_module = ir_vm::Module::new(core_module.name.clone()); let mut vm_module = ir_lang::Module::new(core_module.name.clone());
vm_module.const_pool = program.const_pool.clone(); vm_module.const_pool = program.const_pool.clone();
for core_func in &core_module.functions { for core_func in &core_module.functions {
@ -51,12 +51,12 @@ pub fn lower_function(
program: &ir_core::Program, program: &ir_core::Program,
function_returns: &HashMap<ir_core::ids::FunctionId, ir_core::Type>, function_returns: &HashMap<ir_core::ids::FunctionId, ir_core::Type>,
is_entry_point: bool, is_entry_point: bool,
) -> Result<ir_vm::Function> { ) -> Result<ir_lang::Function> {
let mut vm_func = ir_vm::Function { let mut vm_func = ir_lang::Function {
id: core_func.id, id: core_func.id,
name: core_func.name.clone(), name: core_func.name.clone(),
sig: core_func.sig, sig: core_func.sig,
params: core_func.params.iter().map(|p| ir_vm::Param { params: core_func.params.iter().map(|p| ir_lang::Param {
name: p.name.clone(), name: p.name.clone(),
r#type: lower_type(&p.ty), r#type: lower_type(&p.ty),
}).collect(), }).collect(),
@ -80,8 +80,8 @@ pub fn lower_function(
for block in &core_func.blocks { for block in &core_func.blocks {
// Core blocks map to labels in the flat VM IR instruction list. // Core blocks map to labels in the flat VM IR instruction list.
vm_func.body.push(ir_vm::Instruction::new( vm_func.body.push(ir_lang::Instruction::new(
ir_vm::InstrKind::Label(ir_vm::Label(format!("block_{}", block.id))), ir_lang::InstrKind::Label(ir_lang::Label(format!("block_{}", block.id))),
None, None,
)); ));
@ -104,11 +104,11 @@ pub fn lower_function(
ir_core::Type::Void ir_core::Type::Void
}; };
stack_types.push(ty); stack_types.push(ty);
vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::PushConst(ir_vm::ConstId(id.0)), span.clone())); vm_func.body.push(ir_lang::Instruction::new(ir_lang::InstrKind::PushConst(ir_lang::ConstId(id.0)), span.clone()));
} }
ir_core::InstrKind::PushBounded(val) => { ir_core::InstrKind::PushBounded(val) => {
stack_types.push(ir_core::Type::Bounded); stack_types.push(ir_core::Type::Bounded);
vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::PushBounded(*val), span.clone())); vm_func.body.push(ir_lang::Instruction::new(ir_lang::InstrKind::PushBounded(*val), span.clone()));
} }
ir_core::InstrKind::Call(func_id, arg_count) => { ir_core::InstrKind::Call(func_id, arg_count) => {
// Pop arguments from type stack // Pop arguments from type stack
@ -119,7 +119,7 @@ pub fn lower_function(
let ret_ty = function_returns.get(func_id).cloned().unwrap_or(ir_core::Type::Void); let ret_ty = function_returns.get(func_id).cloned().unwrap_or(ir_core::Type::Void);
stack_types.push(ret_ty); stack_types.push(ret_ty);
vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::Call { vm_func.body.push(ir_lang::Instruction::new(ir_lang::InstrKind::Call {
func_id: *func_id, func_id: *func_id,
arg_count: *arg_count arg_count: *arg_count
}, None)); }, None));
@ -130,7 +130,7 @@ pub fn lower_function(
stack_types.pop(); stack_types.pop();
} }
// Do not assume a return type here; VM semantics should be verified elsewhere. // Do not assume a return type here; VM semantics should be verified elsewhere.
vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::ImportCall { vm_func.body.push(ir_lang::Instruction::new(ir_lang::InstrKind::ImportCall {
dep_alias: dep_alias.clone(), dep_alias: dep_alias.clone(),
module_path: module_path.clone(), module_path: module_path.clone(),
owner: owner.clone(), owner: owner.clone(),
@ -145,13 +145,13 @@ pub fn lower_function(
for _ in 0..*slots { for _ in 0..*slots {
stack_types.push(ir_core::Type::Int); stack_types.push(ir_core::Type::Int);
} }
vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::Syscall(*id), span.clone())); vm_func.body.push(ir_lang::Instruction::new(ir_lang::InstrKind::Syscall(*id), span.clone()));
} }
ir_core::InstrKind::GetLocal(slot) => { ir_core::InstrKind::GetLocal(slot) => {
let ty = local_types.get(slot).cloned().unwrap_or(ir_core::Type::Void); let ty = local_types.get(slot).cloned().unwrap_or(ir_core::Type::Void);
stack_types.push(ty.clone()); stack_types.push(ty.clone());
vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::LocalLoad { slot: *slot }, span.clone())); vm_func.body.push(ir_lang::Instruction::new(ir_lang::InstrKind::LocalLoad { slot: *slot }, span.clone()));
// If it's a gate, we should retain it if we just pushed it onto stack? // If it's a gate, we should retain it if we just pushed it onto stack?
// "on assigning a gate to a local/global" // "on assigning a gate to a local/global"
@ -160,7 +160,7 @@ pub fn lower_function(
// Wait, if I Load it, I have a new handle on the stack. I should Retain it. // Wait, if I Load it, I have a new handle on the stack. I should Retain it.
if is_gate_type(&ty) { if is_gate_type(&ty) {
vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::GateRetain, span.clone())); vm_func.body.push(ir_lang::Instruction::new(ir_lang::InstrKind::GateRetain, span.clone()));
} }
} }
ir_core::InstrKind::SetLocal(slot) => { ir_core::InstrKind::SetLocal(slot) => {
@ -170,8 +170,8 @@ pub fn lower_function(
// 1. Release old value if it was a gate // 1. Release old value if it was a gate
if let Some(old_ty) = old_ty { if let Some(old_ty) = old_ty {
if is_gate_type(&old_ty) { if is_gate_type(&old_ty) {
vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::LocalLoad { slot: *slot }, span.clone())); vm_func.body.push(ir_lang::Instruction::new(ir_lang::InstrKind::LocalLoad { slot: *slot }, span.clone()));
vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::GateRelease, span.clone())); vm_func.body.push(ir_lang::Instruction::new(ir_lang::InstrKind::GateRelease, span.clone()));
} }
} }
@ -184,22 +184,22 @@ pub fn lower_function(
// Actually, if we Pop it later, we Release it. // Actually, if we Pop it later, we Release it.
local_types.insert(*slot, new_ty); local_types.insert(*slot, new_ty);
vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::LocalStore { slot: *slot }, span.clone())); vm_func.body.push(ir_lang::Instruction::new(ir_lang::InstrKind::LocalStore { slot: *slot }, span.clone()));
} }
ir_core::InstrKind::Pop => { ir_core::InstrKind::Pop => {
let ty = stack_types.pop().unwrap_or(ir_core::Type::Void); let ty = stack_types.pop().unwrap_or(ir_core::Type::Void);
if is_gate_type(&ty) { if is_gate_type(&ty) {
vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::GateRelease, span.clone())); vm_func.body.push(ir_lang::Instruction::new(ir_lang::InstrKind::GateRelease, span.clone()));
} else { } else {
vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::Pop, span.clone())); vm_func.body.push(ir_lang::Instruction::new(ir_lang::InstrKind::Pop, span.clone()));
} }
} }
ir_core::InstrKind::Dup => { ir_core::InstrKind::Dup => {
let ty = stack_types.last().cloned().unwrap_or(ir_core::Type::Void); let ty = stack_types.last().cloned().unwrap_or(ir_core::Type::Void);
stack_types.push(ty.clone()); stack_types.push(ty.clone());
vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::Dup, span.clone())); vm_func.body.push(ir_lang::Instruction::new(ir_lang::InstrKind::Dup, span.clone()));
if is_gate_type(&ty) { if is_gate_type(&ty) {
vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::GateRetain, span.clone())); vm_func.body.push(ir_lang::Instruction::new(ir_lang::InstrKind::GateRetain, span.clone()));
} }
} }
ir_core::InstrKind::Add | ir_core::InstrKind::Sub | ir_core::InstrKind::Mul | ir_core::InstrKind::Div => { ir_core::InstrKind::Add | ir_core::InstrKind::Sub | ir_core::InstrKind::Mul | ir_core::InstrKind::Div => {
@ -207,81 +207,81 @@ pub fn lower_function(
stack_types.pop(); stack_types.pop();
stack_types.push(ir_core::Type::Int); // Assume Int for arithmetic stack_types.push(ir_core::Type::Int); // Assume Int for arithmetic
let kind = match &instr.kind { let kind = match &instr.kind {
ir_core::InstrKind::Add => ir_vm::InstrKind::Add, ir_core::InstrKind::Add => ir_lang::InstrKind::Add,
ir_core::InstrKind::Sub => ir_vm::InstrKind::Sub, ir_core::InstrKind::Sub => ir_lang::InstrKind::Sub,
ir_core::InstrKind::Mul => ir_vm::InstrKind::Mul, ir_core::InstrKind::Mul => ir_lang::InstrKind::Mul,
ir_core::InstrKind::Div => ir_vm::InstrKind::Div, ir_core::InstrKind::Div => ir_lang::InstrKind::Div,
_ => unreachable!(), _ => unreachable!(),
}; };
vm_func.body.push(ir_vm::Instruction::new(kind, span.clone())); vm_func.body.push(ir_lang::Instruction::new(kind, span.clone()));
} }
ir_core::InstrKind::Neg => { ir_core::InstrKind::Neg => {
vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::Neg, span.clone())); vm_func.body.push(ir_lang::Instruction::new(ir_lang::InstrKind::Neg, span.clone()));
} }
ir_core::InstrKind::Eq | ir_core::InstrKind::Neq | ir_core::InstrKind::Lt | ir_core::InstrKind::Lte | ir_core::InstrKind::Gt | ir_core::InstrKind::Gte => { ir_core::InstrKind::Eq | ir_core::InstrKind::Neq | ir_core::InstrKind::Lt | ir_core::InstrKind::Lte | ir_core::InstrKind::Gt | ir_core::InstrKind::Gte => {
stack_types.pop(); stack_types.pop();
stack_types.pop(); stack_types.pop();
stack_types.push(ir_core::Type::Bool); stack_types.push(ir_core::Type::Bool);
let kind = match &instr.kind { let kind = match &instr.kind {
ir_core::InstrKind::Eq => ir_vm::InstrKind::Eq, ir_core::InstrKind::Eq => ir_lang::InstrKind::Eq,
ir_core::InstrKind::Neq => ir_vm::InstrKind::Neq, ir_core::InstrKind::Neq => ir_lang::InstrKind::Neq,
ir_core::InstrKind::Lt => ir_vm::InstrKind::Lt, ir_core::InstrKind::Lt => ir_lang::InstrKind::Lt,
ir_core::InstrKind::Lte => ir_vm::InstrKind::Lte, ir_core::InstrKind::Lte => ir_lang::InstrKind::Lte,
ir_core::InstrKind::Gt => ir_vm::InstrKind::Gt, ir_core::InstrKind::Gt => ir_lang::InstrKind::Gt,
ir_core::InstrKind::Gte => ir_vm::InstrKind::Gte, ir_core::InstrKind::Gte => ir_lang::InstrKind::Gte,
_ => unreachable!(), _ => unreachable!(),
}; };
vm_func.body.push(ir_vm::Instruction::new(kind, span.clone())); vm_func.body.push(ir_lang::Instruction::new(kind, span.clone()));
} }
ir_core::InstrKind::And | ir_core::InstrKind::Or => { ir_core::InstrKind::And | ir_core::InstrKind::Or => {
stack_types.pop(); stack_types.pop();
stack_types.pop(); stack_types.pop();
stack_types.push(ir_core::Type::Bool); stack_types.push(ir_core::Type::Bool);
let kind = match &instr.kind { let kind = match &instr.kind {
ir_core::InstrKind::And => ir_vm::InstrKind::And, ir_core::InstrKind::And => ir_lang::InstrKind::And,
ir_core::InstrKind::Or => ir_vm::InstrKind::Or, ir_core::InstrKind::Or => ir_lang::InstrKind::Or,
_ => unreachable!(), _ => unreachable!(),
}; };
vm_func.body.push(ir_vm::Instruction::new(kind, span.clone())); vm_func.body.push(ir_lang::Instruction::new(kind, span.clone()));
} }
ir_core::InstrKind::Not => { ir_core::InstrKind::Not => {
stack_types.pop(); stack_types.pop();
stack_types.push(ir_core::Type::Bool); stack_types.push(ir_core::Type::Bool);
vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::Not, span.clone())); vm_func.body.push(ir_lang::Instruction::new(ir_lang::InstrKind::Not, span.clone()));
} }
ir_core::InstrKind::Alloc { ty, slots } => { ir_core::InstrKind::Alloc { ty, slots } => {
stack_types.push(ir_core::Type::Contract(format!("Gate<{}>", ty.0))); stack_types.push(ir_core::Type::Contract(format!("Gate<{}>", ty.0)));
vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::Alloc { vm_func.body.push(ir_lang::Instruction::new(ir_lang::InstrKind::Alloc {
type_id: ir_vm::TypeId(ty.0), type_id: ir_lang::TypeId(ty.0),
slots: *slots slots: *slots
}, None)); }, None));
} }
ir_core::InstrKind::BeginPeek { gate } => { ir_core::InstrKind::BeginPeek { gate } => {
vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::LocalLoad { slot: gate.0 }, span.clone())); vm_func.body.push(ir_lang::Instruction::new(ir_lang::InstrKind::LocalLoad { slot: gate.0 }, span.clone()));
vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::GateRetain, span.clone())); vm_func.body.push(ir_lang::Instruction::new(ir_lang::InstrKind::GateRetain, span.clone()));
vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::GateBeginPeek, span.clone())); vm_func.body.push(ir_lang::Instruction::new(ir_lang::InstrKind::GateBeginPeek, span.clone()));
} }
ir_core::InstrKind::BeginBorrow { gate } => { ir_core::InstrKind::BeginBorrow { gate } => {
vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::LocalLoad { slot: gate.0 }, span.clone())); vm_func.body.push(ir_lang::Instruction::new(ir_lang::InstrKind::LocalLoad { slot: gate.0 }, span.clone()));
vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::GateRetain, span.clone())); vm_func.body.push(ir_lang::Instruction::new(ir_lang::InstrKind::GateRetain, span.clone()));
vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::GateBeginBorrow, span.clone())); vm_func.body.push(ir_lang::Instruction::new(ir_lang::InstrKind::GateBeginBorrow, span.clone()));
} }
ir_core::InstrKind::BeginMutate { gate } => { ir_core::InstrKind::BeginMutate { gate } => {
vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::LocalLoad { slot: gate.0 }, span.clone())); vm_func.body.push(ir_lang::Instruction::new(ir_lang::InstrKind::LocalLoad { slot: gate.0 }, span.clone()));
vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::GateRetain, span.clone())); vm_func.body.push(ir_lang::Instruction::new(ir_lang::InstrKind::GateRetain, span.clone()));
vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::GateBeginMutate, span.clone())); vm_func.body.push(ir_lang::Instruction::new(ir_lang::InstrKind::GateBeginMutate, span.clone()));
} }
ir_core::InstrKind::EndPeek => { ir_core::InstrKind::EndPeek => {
vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::GateEndPeek, span.clone())); vm_func.body.push(ir_lang::Instruction::new(ir_lang::InstrKind::GateEndPeek, span.clone()));
vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::GateRelease, span.clone())); vm_func.body.push(ir_lang::Instruction::new(ir_lang::InstrKind::GateRelease, span.clone()));
} }
ir_core::InstrKind::EndBorrow => { ir_core::InstrKind::EndBorrow => {
vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::GateEndBorrow, span.clone())); vm_func.body.push(ir_lang::Instruction::new(ir_lang::InstrKind::GateEndBorrow, span.clone()));
vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::GateRelease, span.clone())); vm_func.body.push(ir_lang::Instruction::new(ir_lang::InstrKind::GateRelease, span.clone()));
} }
ir_core::InstrKind::EndMutate => { ir_core::InstrKind::EndMutate => {
vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::GateEndMutate, span.clone())); vm_func.body.push(ir_lang::Instruction::new(ir_lang::InstrKind::GateEndMutate, span.clone()));
vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::GateRelease, span.clone())); vm_func.body.push(ir_lang::Instruction::new(ir_lang::InstrKind::GateRelease, span.clone()));
} }
ir_core::InstrKind::GateLoadField { gate, field } => { ir_core::InstrKind::GateLoadField { gate, field } => {
let offset = program.field_offsets.get(field) let offset = program.field_offsets.get(field)
@ -290,12 +290,12 @@ pub fn lower_function(
let field_ty = program.field_types.get(field).cloned().unwrap_or(ir_core::Type::Int); let field_ty = program.field_types.get(field).cloned().unwrap_or(ir_core::Type::Int);
stack_types.push(field_ty.clone()); stack_types.push(field_ty.clone());
vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::LocalLoad { slot: gate.0 }, span.clone())); vm_func.body.push(ir_lang::Instruction::new(ir_lang::InstrKind::LocalLoad { slot: gate.0 }, span.clone()));
vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::GateRetain, span.clone())); vm_func.body.push(ir_lang::Instruction::new(ir_lang::InstrKind::GateRetain, span.clone()));
vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::GateLoad { offset: *offset }, span.clone())); vm_func.body.push(ir_lang::Instruction::new(ir_lang::InstrKind::GateLoad { offset: *offset }, span.clone()));
if is_gate_type(&field_ty) { if is_gate_type(&field_ty) {
vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::GateRetain, span.clone())); vm_func.body.push(ir_lang::Instruction::new(ir_lang::InstrKind::GateRetain, span.clone()));
} }
} }
ir_core::InstrKind::GateStoreField { gate, field, value } => { ir_core::InstrKind::GateStoreField { gate, field, value } => {
@ -306,24 +306,24 @@ pub fn lower_function(
// 1. Release old value in HIP if it was a gate // 1. Release old value in HIP if it was a gate
if is_gate_type(&field_ty) { if is_gate_type(&field_ty) {
vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::LocalLoad { slot: gate.0 }, span.clone())); vm_func.body.push(ir_lang::Instruction::new(ir_lang::InstrKind::LocalLoad { slot: gate.0 }, span.clone()));
vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::GateRetain, span.clone())); vm_func.body.push(ir_lang::Instruction::new(ir_lang::InstrKind::GateRetain, span.clone()));
vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::GateLoad { offset: *offset }, span.clone())); vm_func.body.push(ir_lang::Instruction::new(ir_lang::InstrKind::GateLoad { offset: *offset }, span.clone()));
vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::GateRelease, span.clone())); vm_func.body.push(ir_lang::Instruction::new(ir_lang::InstrKind::GateRelease, span.clone()));
} }
vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::LocalLoad { slot: gate.0 }, span.clone())); vm_func.body.push(ir_lang::Instruction::new(ir_lang::InstrKind::LocalLoad { slot: gate.0 }, span.clone()));
vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::GateRetain, span.clone())); vm_func.body.push(ir_lang::Instruction::new(ir_lang::InstrKind::GateRetain, span.clone()));
vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::LocalLoad { slot: value.0 }, span.clone())); vm_func.body.push(ir_lang::Instruction::new(ir_lang::InstrKind::LocalLoad { slot: value.0 }, span.clone()));
// 2. Retain new value if it's a gate // 2. Retain new value if it's a gate
if let Some(val_ty) = local_types.get(&value.0) { if let Some(val_ty) = local_types.get(&value.0) {
if is_gate_type(val_ty) { if is_gate_type(val_ty) {
vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::GateRetain, span.clone())); vm_func.body.push(ir_lang::Instruction::new(ir_lang::InstrKind::GateRetain, span.clone()));
} }
} }
vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::GateStore { offset: *offset }, span.clone())); vm_func.body.push(ir_lang::Instruction::new(ir_lang::InstrKind::GateStore { offset: *offset }, span.clone()));
} }
ir_core::InstrKind::GateLoadIndex { .. } => { ir_core::InstrKind::GateLoadIndex { .. } => {
anyhow::bail!("E_LOWER_UNSUPPORTED: Dynamic HIP index access not supported in v0 lowering"); anyhow::bail!("E_LOWER_UNSUPPORTED: Dynamic HIP index access not supported in v0 lowering");
@ -331,7 +331,7 @@ pub fn lower_function(
ir_core::InstrKind::GateStoreIndex { .. } => { ir_core::InstrKind::GateStoreIndex { .. } => {
anyhow::bail!("E_LOWER_UNSUPPORTED: Dynamic HIP index access not supported in v0 lowering"); anyhow::bail!("E_LOWER_UNSUPPORTED: Dynamic HIP index access not supported in v0 lowering");
} }
ir_core::InstrKind::Free => anyhow::bail!("Instruction 'Free' cannot be represented in ir_vm v0"), ir_core::InstrKind::Free => anyhow::bail!("Instruction 'Free' cannot be represented in ir_lang v0"),
} }
} }
@ -344,35 +344,35 @@ pub fn lower_function(
for slot in sorted_slots { for slot in sorted_slots {
let ty = &local_types[slot]; let ty = &local_types[slot];
if is_gate_type(ty) { if is_gate_type(ty) {
vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::LocalLoad { slot: *slot }, None)); vm_func.body.push(ir_lang::Instruction::new(ir_lang::InstrKind::LocalLoad { slot: *slot }, None));
vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::GateRelease, None)); vm_func.body.push(ir_lang::Instruction::new(ir_lang::InstrKind::GateRelease, None));
} }
} }
// Inject FRAME_SYNC immediately before RET only for the entry point. // Inject FRAME_SYNC immediately before RET only for the entry point.
// This is a signal-only safe point; no GC opcodes should be emitted here. // This is a signal-only safe point; no GC opcodes should be emitted here.
if is_entry_point { if is_entry_point {
vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::FrameSync, None)); vm_func.body.push(ir_lang::Instruction::new(ir_lang::InstrKind::FrameSync, None));
} }
// If the function is Void, we don't need to push anything. // If the function is Void, we don't need to push anything.
// The VM's Ret opcode handles zero return slots correctly. // The VM's Ret opcode handles zero return slots correctly.
vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::Ret, None)); vm_func.body.push(ir_lang::Instruction::new(ir_lang::InstrKind::Ret, None));
} }
ir_core::Terminator::Jump(target) => { ir_core::Terminator::Jump(target) => {
vm_func.body.push(ir_vm::Instruction::new( vm_func.body.push(ir_lang::Instruction::new(
ir_vm::InstrKind::Jmp(ir_vm::Label(format!("block_{}", target))), ir_lang::InstrKind::Jmp(ir_lang::Label(format!("block_{}", target))),
None, None,
)); ));
} }
ir_core::Terminator::JumpIfFalse { target, else_target } => { ir_core::Terminator::JumpIfFalse { target, else_target } => {
stack_types.pop(); stack_types.pop();
vm_func.body.push(ir_vm::Instruction::new( vm_func.body.push(ir_lang::Instruction::new(
ir_vm::InstrKind::JmpIfFalse(ir_vm::Label(format!("block_{}", target))), ir_lang::InstrKind::JmpIfFalse(ir_lang::Label(format!("block_{}", target))),
None, None,
)); ));
vm_func.body.push(ir_vm::Instruction::new( vm_func.body.push(ir_lang::Instruction::new(
ir_vm::InstrKind::Jmp(ir_vm::Label(format!("block_{}", else_target))), ir_lang::InstrKind::Jmp(ir_lang::Label(format!("block_{}", else_target))),
None, None,
)); ));
} }
@ -392,22 +392,22 @@ fn is_gate_type(ty: &ir_core::Type) -> bool {
} }
} }
fn lower_type(ty: &ir_core::Type) -> ir_vm::Type { fn lower_type(ty: &ir_core::Type) -> ir_lang::Type {
match ty { match ty {
ir_core::Type::Void => ir_vm::Type::Void, ir_core::Type::Void => ir_lang::Type::Void,
ir_core::Type::Int => ir_vm::Type::Int, ir_core::Type::Int => ir_lang::Type::Int,
ir_core::Type::Float => ir_vm::Type::Float, ir_core::Type::Float => ir_lang::Type::Float,
ir_core::Type::Bool => ir_vm::Type::Bool, ir_core::Type::Bool => ir_lang::Type::Bool,
ir_core::Type::String => ir_vm::Type::String, ir_core::Type::String => ir_lang::Type::String,
ir_core::Type::Bounded => ir_vm::Type::Bounded, ir_core::Type::Bounded => ir_lang::Type::Bounded,
ir_core::Type::Optional(inner) => ir_vm::Type::Array(Box::new(lower_type(inner))), ir_core::Type::Optional(inner) => ir_lang::Type::Array(Box::new(lower_type(inner))),
ir_core::Type::Result(ok, _) => lower_type(ok), ir_core::Type::Result(ok, _) => lower_type(ok),
ir_core::Type::Struct(_) ir_core::Type::Struct(_)
| ir_core::Type::Service(_) | ir_core::Type::Service(_)
| ir_core::Type::Contract(_) | ir_core::Type::Contract(_)
| ir_core::Type::ErrorType(_) => ir_vm::Type::Object, | ir_core::Type::ErrorType(_) => ir_lang::Type::Object,
ir_core::Type::Function { .. } => ir_vm::Type::Function, ir_core::Type::Function { .. } => ir_lang::Type::Function,
ir_core::Type::Array(inner, _) => ir_vm::Type::Array(Box::new(lower_type(inner))), ir_core::Type::Array(inner, _) => ir_lang::Type::Array(Box::new(lower_type(inner))),
} }
} }
@ -417,7 +417,7 @@ mod tests {
use crate::ir_core; use crate::ir_core;
use crate::ir_core::ids::{ConstId as CoreConstId, FunctionId}; use crate::ir_core::ids::{ConstId as CoreConstId, FunctionId};
use crate::ir_core::{Block, ConstPool, ConstantValue, Instr, InstrKind, Program, Terminator}; use crate::ir_core::{Block, ConstPool, ConstantValue, Instr, InstrKind, Program, Terminator};
use crate::ir_vm::{InstrKind as VmInstrKind, Label}; use crate::ir_lang::{InstrKind as VmInstrKind, Label};
#[test] #[test]
fn test_full_lowering() { fn test_full_lowering() {

View File

@ -3,7 +3,7 @@ use prometeu_compiler::building::output::{compile_project, CompileError, ExportK
use prometeu_compiler::building::plan::{BuildStep, BuildTarget}; use prometeu_compiler::building::plan::{BuildStep, BuildTarget};
use prometeu_compiler::common::files::FileManager; use prometeu_compiler::common::files::FileManager;
use prometeu_compiler::deps::resolver::ProjectKey; use prometeu_compiler::deps::resolver::ProjectKey;
use frontend_api::types::{ExportItem, ItemName}; use language_api::types::{ExportItem, ItemName};
use prometeu_compiler::frontends::pbs::adapter::PbsFrontendAdapter; use prometeu_compiler::frontends::pbs::adapter::PbsFrontendAdapter;
use prometeu_analysis::ids::ProjectId; use prometeu_analysis::ids::ProjectId;
use std::collections::{BTreeMap, HashMap}; use std::collections::{BTreeMap, HashMap};

Some files were not shown because too many files have changed in this diff Show More