pr 08
This commit is contained in:
parent
07e9871b13
commit
7eb2e5d75b
@ -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);
|
||||
}
|
||||
|
||||
@ -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<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]
|
||||
fn hash_tag_u16(s: &str) -> u16 {
|
||||
// FNV-1a 16-bit (simple, deterministic, allows small collisions)
|
||||
@ -1133,18 +1149,28 @@ 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(
|
||||
// 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,
|
||||
symbol_with_arity,
|
||||
n.args.len() as u32,
|
||||
));
|
||||
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(());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.error(
|
||||
@ -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(
|
||||
// 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,
|
||||
symbol_name,
|
||||
n.args.len() as u32,
|
||||
));
|
||||
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(
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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
|
||||
}
|
||||
},
|
||||
|
||||
@ -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));
|
||||
}
|
||||
|
||||
@ -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**
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user