diff --git a/crates/prometeu-compiler/src/backend/emit_bytecode.rs b/crates/prometeu-compiler/src/backend/emit_bytecode.rs index afc66d20..124f2bd0 100644 --- a/crates/prometeu-compiler/src/backend/emit_bytecode.rs +++ b/crates/prometeu-compiler/src/backend/emit_bytecode.rs @@ -293,8 +293,8 @@ impl BytecodeEmitter { stack_height = (stack_height - (*arg_count as i32)).max(0); } } - InstrKind::ImportCall { dep_alias, module_path, symbol_name, arg_count } => { - let label = format!("@{}::{}:{}", dep_alias, module_path, symbol_name); + InstrKind::ImportCall { dep_alias, module_path, base_name, sig, arg_count } => { + let label = format!("@{}::{}:{}#sig{}", dep_alias, module_path, base_name, sig.0); asm_instrs.push(Asm::Op(OpCode::Call, vec![Operand::Label(label)])); stack_height = (stack_height - (*arg_count as i32)).max(0); } diff --git a/crates/prometeu-compiler/src/frontends/pbs/lowering.rs b/crates/prometeu-compiler/src/frontends/pbs/lowering.rs index ccce7fe3..bd3ba23f 100644 --- a/crates/prometeu-compiler/src/frontends/pbs/lowering.rs +++ b/crates/prometeu-compiler/src/frontends/pbs/lowering.rs @@ -4,8 +4,9 @@ use crate::frontends::pbs::ast::*; use crate::frontends::pbs::contracts::ContractRegistry; use crate::frontends::pbs::symbols::*; use crate::frontends::pbs::types::PbsType; -use crate::ir_core::ids::{FieldId, FunctionId, TypeId, ValueId}; -use crate::ir_core::{Block, ConstPool, Function, Instr, InstrKind, Module, Param, Program, Terminator, Type, Signature, global_signature_interner}; +use crate::ir_core::ids::{FieldId, FunctionId, TypeId, ValueId, SigId}; +use crate::ir_core::{Block, ConstPool, Function, Instr, InstrKind, Module, Param, Program, Terminator, Type}; +use crate::ir_core::signature::{Signature, global_signature_interner}; use prometeu_analysis::{NameInterner, NodeId}; use std::collections::HashMap; @@ -44,6 +45,21 @@ pub struct Lowerer<'a> { } impl<'a> Lowerer<'a> { + fn sig_from_pbs_fn(&self, pbs: &PbsType) -> Option { + if let PbsType::Function { params, return_type } = pbs { + let mut core_params = Vec::with_capacity(params.len()); + for p in params { + core_params.push(self.convert_pbs_type(p)); + } + let core_ret = self.convert_pbs_type(return_type); + let sig = Signature { params: core_params, return_type: core_ret }; + // Global, deterministic interner across the compiler process + let mut guard = global_signature_interner().lock().unwrap(); + Some(guard.intern(sig)) + } else { + None + } + } #[inline] fn hash_tag_u16(s: &str) -> u16 { // FNV-1a 16-bit (simple, deterministic, allows small collisions) @@ -1133,16 +1149,26 @@ impl<'a> Lowerer<'a> { if parts.len() == 2 { let dep_alias = parts[0].to_string(); let module_path = parts[1].to_string(); - // Encode arity to disambiguate overloads at link time: symbol/arity - let base = self.interner.resolve(sym.name).to_string(); - let symbol_with_arity = format!("{}/{}", base, n.args.len()); - self.emit(InstrKind::ImportCall( - dep_alias, - module_path, - symbol_with_arity, - n.args.len() as u32, - )); - return Ok(()); + // Compute signature id from symbol type + let base_name = self.interner.resolve(sym.name).to_string(); + if let Some(ty) = &sym.ty { + if let Some(sig) = self.sig_from_pbs_fn(ty) { + self.emit(InstrKind::ImportCall { + dep_alias, + module_path, + base_name, + sig, + arg_count: n.args.len() as u32, + }); + return Ok(()); + } + } + self.error( + "E_LOWER_SIGNATURE", + format!("Missing or non-function type for imported symbol '{}' to compute signature id", base_name), + self.arena.span(n.callee), + ); + return Err(()); } } } @@ -1292,14 +1318,37 @@ impl<'a> Lowerer<'a> { // Usar o binding real do import para este Service (ex.: Log -> (sdk, log)) let obj_name_str = obj_name.to_string(); if let Some((dep_alias, module_path)) = self.import_bindings.get(&obj_name_str).cloned() { - // Encode arity to disambiguate overloads at link time: symbol/arity - let symbol_name = format!("{}/{}", member_name, n.args.len()); - self.emit(InstrKind::ImportCall( - dep_alias, - module_path, - symbol_name, - n.args.len() as u32, - )); + // Try to find the function symbol in imported value symbols using `Service.method` + let qualified = format!("{}.{}", obj_name, member_name); + let sig_opt = self + .imported_symbols + .value_symbols + .symbols + .values() + .find(|s| self.interner.resolve(s.name) == qualified) + .and_then(|s| s.ty.as_ref()) + .and_then(|t| self.sig_from_pbs_fn(t)); + + if let Some(sig) = sig_opt { + self.emit(InstrKind::ImportCall { + dep_alias, + module_path, + base_name: member_name.to_string(), + sig, + arg_count: n.args.len() as u32, + }); + } else { + // Fallback: attempt to compute from service method type if exposed in type_constants or error deterministically + self.error( + "E_LOWER_SIGNATURE", + format!( + "Unable to determine signature for imported service method '{}.{}' (missing type info)", + obj_name, member_name + ), + self.arena.span(n.callee), + ); + return Err(()); + } } else { // Sem binding de import conhecido: erro claro de serviço não importado self.error( diff --git a/crates/prometeu-compiler/src/ir_core/instr.rs b/crates/prometeu-compiler/src/ir_core/instr.rs index 621d6411..ee18dac9 100644 --- a/crates/prometeu-compiler/src/ir_core/instr.rs +++ b/crates/prometeu-compiler/src/ir_core/instr.rs @@ -1,4 +1,4 @@ -use super::ids::{ConstId, FieldId, FunctionId, TypeId, ValueId}; +use super::ids::{ConstId, FieldId, FunctionId, TypeId, ValueId, SigId}; use crate::common::spans::Span; use serde::{Deserialize, Serialize}; @@ -23,8 +23,15 @@ pub enum InstrKind { PushBounded(u32), /// Placeholder for function calls. Call(FunctionId, u32), - /// External calls (imports). (dep_alias, module_path, symbol_name, arg_count) - ImportCall(String, String, String, u32), + /// External calls (imports). + /// Carries dependency alias, module path, base function name, precise signature id, and arg count. + ImportCall { + dep_alias: String, + module_path: String, + base_name: String, + sig: SigId, + arg_count: u32, + }, /// Host calls (syscalls). (id, return_slots) HostCall(u32, u32), /// Variable access. diff --git a/crates/prometeu-compiler/src/ir_vm/instr.rs b/crates/prometeu-compiler/src/ir_vm/instr.rs index da116a90..00f90153 100644 --- a/crates/prometeu-compiler/src/ir_vm/instr.rs +++ b/crates/prometeu-compiler/src/ir_vm/instr.rs @@ -5,7 +5,7 @@ //! easy to lower into VM-specific bytecode. use crate::common::spans::Span; -use crate::ir_core::ids::FunctionId; +use crate::ir_core::ids::{FunctionId, SigId}; use crate::ir_vm::types::{ConstId, TypeId}; /// An `Instruction` combines an instruction's behavior (`kind`) with its @@ -134,7 +134,8 @@ pub enum InstrKind { ImportCall { dep_alias: String, module_path: String, - symbol_name: String, + base_name: String, + sig: SigId, arg_count: u32, }, /// Returns from the current function. The return value (if any) should be on top of the stack. @@ -248,7 +249,8 @@ mod tests { InstrKind::ImportCall { dep_alias: "std".to_string(), module_path: "math".to_string(), - symbol_name: "abs".to_string(), + base_name: "abs".to_string(), + sig: SigId(1), arg_count: 1, }, InstrKind::Ret, @@ -341,7 +343,8 @@ mod tests { "ImportCall": { "dep_alias": "std", "module_path": "math", - "symbol_name": "abs", + "base_name": "abs", + "sig": 1, "arg_count": 1 } }, diff --git a/crates/prometeu-compiler/src/lowering/core_to_vm.rs b/crates/prometeu-compiler/src/lowering/core_to_vm.rs index 59bc1171..238e6ac9 100644 --- a/crates/prometeu-compiler/src/lowering/core_to_vm.rs +++ b/crates/prometeu-compiler/src/lowering/core_to_vm.rs @@ -124,18 +124,17 @@ pub fn lower_function( arg_count: *arg_count }, None)); } - ir_core::InstrKind::ImportCall(dep_alias, module_path, symbol_name, arg_count) => { + ir_core::InstrKind::ImportCall { dep_alias, module_path, base_name, sig, arg_count } => { // Pop arguments from type stack for _ in 0..*arg_count { stack_types.pop(); } - // Push return type (Assume Int for v0 imports if unknown) - stack_types.push(ir_core::Type::Int); - + // 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 { dep_alias: dep_alias.clone(), module_path: module_path.clone(), - symbol_name: symbol_name.clone(), + base_name: base_name.clone(), + sig: *sig, arg_count: *arg_count, }, None)); } diff --git a/files/Hard Reset.md b/files/Hard Reset.md index 8ac80c15..cd444a1e 100644 --- a/files/Hard Reset.md +++ b/files/Hard Reset.md @@ -15,36 +15,6 @@ ## Phase 3 — JVM-like Symbol Identity: Signature-based Overload & Constant-Pool Mindset -### PR-07 (5 pts) — Introduce Signature interning (`SigId`) and descriptor canonicalization - -**Briefing** - -Overload must be by signature, not by `name/arity`. - -**Target** - -Create a canonical function descriptor system (JVM-like) and intern signatures. - -**Scope** - -* Add `Signature` model: - - * params types + return type -* Add `SignatureInterner` -> `SigId` -* Add `descriptor()` canonical representation (stable, deterministic). - -**Requirements Checklist** - -* [ ] `SigId` is used as identity in compiler IR. -* [ ] Descriptor is stable and round-trippable. - -**Completion Tests** - -* [ ] `debug(int)->void` and `debug(string)->void` produce different descriptors. -* [ ] Descriptor stability tests. - ---- - ### PR-08 (5 pts) — Replace `name/arity` import/export keys with `(name, SigId)` **Briefing**