This commit is contained in:
bQUARKz 2026-02-10 10:09:23 +00:00
parent 07e9871b13
commit 7eb2e5d75b
Signed by: bquarkz
SSH Key Fingerprint: SHA256:Z7dgqoglWwoK6j6u4QC87OveEq74WOhFN+gitsxtkf8
6 changed files with 92 additions and 64 deletions

View File

@ -293,8 +293,8 @@ impl BytecodeEmitter {
stack_height = (stack_height - (*arg_count as i32)).max(0); stack_height = (stack_height - (*arg_count as i32)).max(0);
} }
} }
InstrKind::ImportCall { dep_alias, module_path, symbol_name, arg_count } => { InstrKind::ImportCall { dep_alias, module_path, base_name, sig, arg_count } => {
let label = format!("@{}::{}:{}", dep_alias, module_path, symbol_name); let label = format!("@{}::{}:{}#sig{}", dep_alias, module_path, base_name, sig.0);
asm_instrs.push(Asm::Op(OpCode::Call, vec![Operand::Label(label)])); asm_instrs.push(Asm::Op(OpCode::Call, vec![Operand::Label(label)]));
stack_height = (stack_height - (*arg_count as i32)).max(0); stack_height = (stack_height - (*arg_count as i32)).max(0);
} }

View File

@ -4,8 +4,9 @@ use crate::frontends::pbs::ast::*;
use crate::frontends::pbs::contracts::ContractRegistry; use crate::frontends::pbs::contracts::ContractRegistry;
use crate::frontends::pbs::symbols::*; use crate::frontends::pbs::symbols::*;
use crate::frontends::pbs::types::PbsType; use crate::frontends::pbs::types::PbsType;
use crate::ir_core::ids::{FieldId, FunctionId, TypeId, ValueId}; use crate::ir_core::ids::{FieldId, FunctionId, TypeId, ValueId, SigId};
use crate::ir_core::{Block, ConstPool, Function, Instr, InstrKind, Module, Param, Program, Terminator, Type, Signature, global_signature_interner}; 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 prometeu_analysis::{NameInterner, NodeId};
use std::collections::HashMap; use std::collections::HashMap;
@ -44,6 +45,21 @@ pub struct Lowerer<'a> {
} }
impl<'a> Lowerer<'a> { impl<'a> Lowerer<'a> {
fn sig_from_pbs_fn(&self, pbs: &PbsType) -> Option<SigId> {
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] #[inline]
fn hash_tag_u16(s: &str) -> u16 { fn hash_tag_u16(s: &str) -> u16 {
// FNV-1a 16-bit (simple, deterministic, allows small collisions) // FNV-1a 16-bit (simple, deterministic, allows small collisions)
@ -1133,18 +1149,28 @@ impl<'a> Lowerer<'a> {
if parts.len() == 2 { if parts.len() == 2 {
let dep_alias = parts[0].to_string(); let dep_alias = parts[0].to_string();
let module_path = parts[1].to_string(); let module_path = parts[1].to_string();
// Encode arity to disambiguate overloads at link time: symbol/arity // Compute signature id from symbol type
let base = self.interner.resolve(sym.name).to_string(); let base_name = self.interner.resolve(sym.name).to_string();
let symbol_with_arity = format!("{}/{}", base, n.args.len()); if let Some(ty) = &sym.ty {
self.emit(InstrKind::ImportCall( if let Some(sig) = self.sig_from_pbs_fn(ty) {
self.emit(InstrKind::ImportCall {
dep_alias, dep_alias,
module_path, module_path,
symbol_with_arity, base_name,
n.args.len() as u32, sig,
)); arg_count: n.args.len() as u32,
});
return Ok(()); 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(());
}
}
} }
self.error( self.error(
@ -1292,14 +1318,37 @@ impl<'a> Lowerer<'a> {
// Usar o binding real do import para este Service (ex.: Log -> (sdk, log)) // Usar o binding real do import para este Service (ex.: Log -> (sdk, log))
let obj_name_str = obj_name.to_string(); let obj_name_str = obj_name.to_string();
if let Some((dep_alias, module_path)) = self.import_bindings.get(&obj_name_str).cloned() { 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 // Try to find the function symbol in imported value symbols using `Service.method`
let symbol_name = format!("{}/{}", member_name, n.args.len()); let qualified = format!("{}.{}", obj_name, member_name);
self.emit(InstrKind::ImportCall( 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, dep_alias,
module_path, module_path,
symbol_name, base_name: member_name.to_string(),
n.args.len() as u32, 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 { } else {
// Sem binding de import conhecido: erro claro de serviço não importado // Sem binding de import conhecido: erro claro de serviço não importado
self.error( self.error(

View File

@ -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 crate::common::spans::Span;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -23,8 +23,15 @@ pub enum InstrKind {
PushBounded(u32), PushBounded(u32),
/// Placeholder for function calls. /// Placeholder for function calls.
Call(FunctionId, u32), Call(FunctionId, u32),
/// External calls (imports). (dep_alias, module_path, symbol_name, arg_count) /// External calls (imports).
ImportCall(String, String, String, u32), /// 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) /// Host calls (syscalls). (id, return_slots)
HostCall(u32, u32), HostCall(u32, u32),
/// Variable access. /// Variable access.

View File

@ -5,7 +5,7 @@
//! easy to lower into VM-specific bytecode. //! easy to lower into VM-specific bytecode.
use crate::common::spans::Span; 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}; use crate::ir_vm::types::{ConstId, TypeId};
/// An `Instruction` combines an instruction's behavior (`kind`) with its /// An `Instruction` combines an instruction's behavior (`kind`) with its
@ -134,7 +134,8 @@ pub enum InstrKind {
ImportCall { ImportCall {
dep_alias: String, dep_alias: String,
module_path: String, module_path: String,
symbol_name: String, base_name: String,
sig: SigId,
arg_count: u32, arg_count: u32,
}, },
/// Returns from the current function. The return value (if any) should be on top of the stack. /// 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 { InstrKind::ImportCall {
dep_alias: "std".to_string(), dep_alias: "std".to_string(),
module_path: "math".to_string(), module_path: "math".to_string(),
symbol_name: "abs".to_string(), base_name: "abs".to_string(),
sig: SigId(1),
arg_count: 1, arg_count: 1,
}, },
InstrKind::Ret, InstrKind::Ret,
@ -341,7 +343,8 @@ mod tests {
"ImportCall": { "ImportCall": {
"dep_alias": "std", "dep_alias": "std",
"module_path": "math", "module_path": "math",
"symbol_name": "abs", "base_name": "abs",
"sig": 1,
"arg_count": 1 "arg_count": 1
} }
}, },

View File

@ -124,18 +124,17 @@ pub fn lower_function(
arg_count: *arg_count arg_count: *arg_count
}, None)); }, 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 // Pop arguments from type stack
for _ in 0..*arg_count { for _ in 0..*arg_count {
stack_types.pop(); stack_types.pop();
} }
// Push return type (Assume Int for v0 imports if unknown) // Do not assume a return type here; VM semantics should be verified elsewhere.
stack_types.push(ir_core::Type::Int);
vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::ImportCall { vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::ImportCall {
dep_alias: dep_alias.clone(), dep_alias: dep_alias.clone(),
module_path: module_path.clone(), module_path: module_path.clone(),
symbol_name: symbol_name.clone(), base_name: base_name.clone(),
sig: *sig,
arg_count: *arg_count, arg_count: *arg_count,
}, None)); }, None));
} }

View File

@ -15,36 +15,6 @@
## Phase 3 — JVM-like Symbol Identity: Signature-based Overload & Constant-Pool Mindset ## 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)` ### PR-08 (5 pts) — Replace `name/arity` import/export keys with `(name, SigId)`
**Briefing** **Briefing**