Skip to content

Commit fef7bdb

Browse files
committed
fix: Path expression resolution for static method calls
- Add Path->Variable conversion in resolve_in_expr (runtime.rs) - Converts Tensor::arange to Tensor$arange during type resolution - Looks up return type from function_returns map - Registers impl block methods with mangled names - Fix SSA method call resolution for extern types (ssa.rs) - Strip $ prefix from extern type names in resolve_method_to_function - Check both function_symbols and extern_link_names for method lookup - Use consistent TypeName$method naming in lowering.rs - Remove _zynml_ prefix for extern struct methods with bodies - All extern struct methods now use consistent naming - Add missing tensor builtins in ml.zyn - tensor_sum_f32, tensor_mean_f32, tensor_max_f32, tensor_min_f32 - Many other tensor operations for stdlib support - concat alias for f-string desugaring
1 parent 6a8228b commit fef7bdb

4 files changed

Lines changed: 432 additions & 64 deletions

File tree

crates/compiler/src/lowering.rs

Lines changed: 100 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,9 @@ pub struct SymbolTable {
249249
pub effects: indexmap::IndexMap<InternedString, crate::hir::HirId>,
250250
/// Effect handlers by name
251251
pub handlers: indexmap::IndexMap<InternedString, crate::hir::HirId>,
252+
/// External function link names (alias -> ZRTL symbol)
253+
/// e.g., "tensor_add" -> "$Tensor$add"
254+
pub extern_link_names: indexmap::IndexMap<InternedString, String>,
252255
}
253256

254257
/// Import metadata for debugging and error messages
@@ -955,6 +958,9 @@ impl LoweringContext {
955958
// Pre-register impl block methods in symbol table WITH MANGLED NAMES
956959
// This must match the mangling done in lower_impl_block
957960

961+
// Check if implementing type is extern struct
962+
let is_extern_struct = matches!(&impl_block.for_type, zyntax_typed_ast::Type::Extern { .. });
963+
958964
// Get the implementing type name
959965
let type_name = match &impl_block.for_type {
960966
zyntax_typed_ast::Type::Named { id, .. } => {
@@ -982,7 +988,8 @@ impl LoweringContext {
982988
if let Some(type_def) = self.type_registry.get_type_by_name(fresh_name) {
983989
type_def.name
984990
} else {
985-
continue; // Can't resolve type, skip
991+
// For extern struct, use the name directly
992+
*name
986993
}
987994
}
988995
}
@@ -998,12 +1005,16 @@ impl LoweringContext {
9981005

9991006
// Generate mangled name matching lower_impl_block
10001007
let mangled_name = if is_inherent {
1001-
// Inherent method: {TypeName}${method_name}
10021008
let type_name_str = type_name.resolve_global()
10031009
.unwrap_or_else(|| "UnknownType".to_string());
1010+
// Strip $ prefix if present (extern struct names have runtime_prefix)
1011+
let base_type_name = type_name_str.strip_prefix('$').unwrap_or(&type_name_str);
10041012
let method_name_str = method.name.resolve_global()
10051013
.unwrap_or_else(|| "unknown_method".to_string());
1006-
InternedString::new_global(&format!("{}${}", type_name_str, method_name_str))
1014+
1015+
// Use consistent TypeName$method naming for all extern struct methods
1016+
// ZRTL symbols start with $ (e.g., $Tensor$sum_f32), so no collision
1017+
InternedString::new_global(&format!("{}${}", base_type_name, method_name_str))
10071018
} else {
10081019
// Trait method: {TypeName}${TraitName}${method_name}
10091020
self.mangle_trait_method_name(type_name, impl_block.trait_name, method.name)
@@ -1126,7 +1137,10 @@ impl LoweringContext {
11261137
if let Some(ref link_name) = func.link_name {
11271138
let link_name_str = link_name.resolve_global()
11281139
.unwrap_or_else(|| link_name.to_string());
1129-
hir_func.link_name = Some(link_name_str);
1140+
hir_func.link_name = Some(link_name_str.clone());
1141+
1142+
// Register the alias -> link_name mapping for SSA call resolution
1143+
self.symbols.extern_link_names.insert(func.name, link_name_str);
11301144
}
11311145

11321146
// Extern functions have no body - clear the default entry block
@@ -1160,7 +1174,9 @@ impl LoweringContext {
11601174
self.type_registry.clone(),
11611175
self.arena.clone(),
11621176
self.symbols.functions.clone()
1163-
).with_return_type(func.return_type.clone());
1177+
)
1178+
.with_return_type(func.return_type.clone())
1179+
.with_extern_link_names(self.symbols.extern_link_names.clone());
11641180
let ssa = ssa_builder.build_from_typed_cfg(&typed_cfg)?;
11651181

11661182
// Debug: check SSA result
@@ -2169,6 +2185,20 @@ impl LoweringContext {
21692185
let is_inherent = trait_name_str.is_empty();
21702186
eprintln!("[LOWERING] Impl block is_inherent: {}, trait_name: '{}'", is_inherent, trait_name_str);
21712187

2188+
// Check if the implementing type is an extern struct
2189+
// For extern structs, methods should automatically map to ZRTL symbols
2190+
let is_extern_struct = matches!(&implementing_type, Type::Extern { .. });
2191+
let extern_type_name = if let Type::Extern { name, .. } = &implementing_type {
2192+
let name_str = name.resolve_global().unwrap_or_default();
2193+
// The extern type name may have a leading $ (runtime_prefix) - strip it for the base name
2194+
// e.g., "$Tensor" -> "Tensor"
2195+
let base_name = name_str.strip_prefix('$').unwrap_or(&name_str);
2196+
Some(base_name.to_string())
2197+
} else {
2198+
None
2199+
};
2200+
eprintln!("[LOWERING] is_extern_struct: {}, extern_type_name: {:?}", is_extern_struct, extern_type_name);
2201+
21722202
// For trait impls, register the implementation in the type registry
21732203
let trait_id = if !is_inherent {
21742204
let trait_def = self.type_registry.get_trait_by_name(impl_block.trait_name)
@@ -2337,8 +2367,9 @@ impl LoweringContext {
23372367
};
23382368

23392369
// Mangle the method name to include trait and type info
2340-
// Format for inherent: {TypeName}${method_name}
2341-
// Format for trait: {TypeName}${TraitName}${method_name}
2370+
// For extern struct methods WITH bodies (wrappers): use _zynml_{Type}_{method} to avoid ZRTL collision
2371+
// For extern struct methods WITHOUT bodies: auto-map creates external function with ZRTL link
2372+
// For regular structs: {TypeName}${method_name} or {TypeName}${TraitName}${method_name}
23422373
let mangled_name = {
23432374
let type_name = match &implementing_type {
23442375
Type::Named { id, .. } => {
@@ -2348,16 +2379,22 @@ impl LoweringContext {
23482379
method.name // Fallback to original name
23492380
}
23502381
}
2351-
_ => method.name, // For non-named types, use original name
2382+
Type::Extern { name, .. } => *name, // Use the extern struct's name
2383+
_ => method.name, // For other types, use original name
23522384
};
23532385

23542386
// For inherent impls (empty trait name), use simpler mangling
23552387
if is_inherent {
23562388
let type_name_str = type_name.resolve_global()
23572389
.unwrap_or_else(|| "UnknownType".to_string());
2390+
// Strip $ prefix if present (extern struct names have runtime_prefix)
2391+
let base_type_name = type_name_str.strip_prefix('$').unwrap_or(&type_name_str);
23582392
let method_name_str = method.name.resolve_global()
23592393
.unwrap_or_else(|| "unknown_method".to_string());
2360-
let mangled = format!("{}${}", type_name_str, method_name_str);
2394+
2395+
// Use consistent TypeName$method naming for all extern struct methods
2396+
// ZRTL symbols start with $ (e.g., $Tensor$sum_f32), so no collision
2397+
let mangled = format!("{}${}", base_type_name, method_name_str);
23612398
InternedString::new_global(&mangled)
23622399
} else {
23632400
// For trait impls, include trait name
@@ -2381,7 +2418,44 @@ impl LoweringContext {
23812418
new_id
23822419
};
23832420

2384-
// Create a function from the method
2421+
// For extern struct methods WITHOUT a body, create external function declaration
2422+
// that automatically maps to ZRTL symbol: $TypeName$method_name
2423+
// If the method has an explicit body, use that body as an override
2424+
if is_extern_struct && method.body.is_none() {
2425+
if let Some(ref type_name) = extern_type_name {
2426+
let method_name_str = method.name.resolve_global().unwrap_or_default();
2427+
// ZRTL symbol format: $TypeName$method_name (e.g., $Tensor$matmul)
2428+
let zrtl_symbol = format!("${}${}", type_name, method_name_str);
2429+
eprintln!("[LOWERING] Extern struct method: {} -> ZRTL symbol: {} (params: {})",
2430+
mangled_name.resolve_global().unwrap_or_default(), zrtl_symbol, params.len());
2431+
2432+
let func = TypedFunction {
2433+
name: mangled_name,
2434+
annotations: vec![],
2435+
effects: vec![],
2436+
type_params: vec![],
2437+
params,
2438+
return_type: resolved_return_type,
2439+
body: None, // No body - external function
2440+
visibility: zyntax_typed_ast::type_registry::Visibility::Public,
2441+
is_async: method.is_async,
2442+
is_pure: false,
2443+
is_external: true, // Mark as external
2444+
calling_convention: zyntax_typed_ast::type_registry::CallingConvention::Default,
2445+
link_name: Some(InternedString::new_global(&zrtl_symbol)), // Link to ZRTL symbol
2446+
};
2447+
2448+
if let Err(e) = self.lower_function(&func) {
2449+
let method_name_str = mangled_name.resolve_global().unwrap_or_default();
2450+
eprintln!("[LOWERING WARN] Skipping extern method '{}': {:?}", method_name_str, e);
2451+
self.symbols.functions.remove(&mangled_name);
2452+
continue;
2453+
}
2454+
continue; // Skip regular function lowering
2455+
}
2456+
}
2457+
2458+
// Create a function from the method (regular, non-extern struct)
23852459
let func = TypedFunction {
23862460
name: mangled_name, // Use mangled name for trait method
23872461
annotations: vec![],
@@ -3131,9 +3205,24 @@ impl LoweringContext {
31313205
self.lower_function(&func)
31323206
}
31333207

3134-
/// Resolve associated function call (Type::method) to mangled trait method name
3208+
/// Resolve associated function call (Type::method) to mangled method name
31353209
/// Returns None if the function cannot be resolved
31363210
fn resolve_associated_function_to_mangled(&self, type_name: &str, method_name: &str) -> Option<String> {
3211+
// First, check for inherent impl methods (including extern struct methods)
3212+
// Try wrapper method name first: _zynml_{Type}_{method}
3213+
let wrapper_name = format!("_zynml_{}_{}", type_name, method_name);
3214+
let wrapper_interned = InternedString::new_global(&wrapper_name);
3215+
if self.symbols.functions.contains_key(&wrapper_interned) {
3216+
return Some(wrapper_name);
3217+
}
3218+
3219+
// Try standard inherent method: {Type}${method}
3220+
let inherent_name = format!("{}${}", type_name, method_name);
3221+
let inherent_interned = InternedString::new_global(&inherent_name);
3222+
if self.symbols.functions.contains_key(&inherent_interned) {
3223+
return Some(inherent_name);
3224+
}
3225+
31373226
// Search through all trait implementations to find the method
31383227
for (_trait_id, impls) in self.type_registry.iter_implementations() {
31393228
for impl_def in impls {

0 commit comments

Comments
 (0)