WIP: Partial implementation of dunder support

This commit is contained in:
Siddhangana 2025-01-31 11:52:20 +08:00
parent 9e12ce442f
commit c4373281c7
4 changed files with 107 additions and 14 deletions

View File

@ -10,10 +10,10 @@ class NameManglingTest:
def __init__(self):
self.core = Core()
self.__var1 = 42
self.__var2__ = 10
self.__ = 99
self.__var1 = 100
self.__var2__ = 200
self.__ = 300
@rpc
def get_var1(self) -> int32:
return self.__var1
@ -28,10 +28,10 @@ class NameManglingTest:
@kernel
def run(self):
assert self.get_var1() == 42
assert self.get_var2() == 10
assert self.get_var3() == 99
assert self.get_var1() == 100
assert self.get_var2() == 200
assert self.get_var3() == 300
#assert self._NameManglingTest__var1 == 100
if __name__ == "__main__":
NameManglingTest().run()
NameManglingTest().run()

View File

@ -630,15 +630,28 @@ impl Nac3 {
{
let defs = top_level.definitions.read();
for def in defs.iter() {
println!("{:?}", def.read());
}
for (class_data, id, is_async) in &rpc_ids {
let mut def = defs[id.0].write();
match &mut *def {
TopLevelDef::Function { codegen_callback, .. } => {
*codegen_callback = Some(rpc_codegen_callback(*is_async));
}
TopLevelDef::Class { methods, .. } => {
TopLevelDef::Class { methods, fields, .. } => {
let (class_def, method_name) = class_data.as_ref().unwrap();
println!("Class definition for: {:?}", class_def);
println!("Fields in the class:");
for (field_name, field_type, mutable) in fields {
println!(
"Field name: {}, Field type: {:?}, Mutable: {}",
field_name, field_type, mutable
);
}
println!("Methods in the class:");
for (name, _, id) in &*methods {
println!("Method: {}", name);
if name != method_name {
continue;
}

View File

@ -187,7 +187,8 @@ impl StaticValue for PythonValue {
name: StrRef,
ctx: &mut CodeGenContext<'ctx, '_>,
) -> Option<ValueEnum<'ctx>> {
{
{
println!("Debug: Entered `get_field` with name `{}` and ID `{}`", name.to_string(), self.id);
let field_to_val = self.resolver.field_to_val.read();
field_to_val.get(&(self.id, name)).cloned()
}
@ -209,10 +210,20 @@ impl StaticValue for PythonValue {
let def_id = { *self.resolver.pyid_to_def.read().get(&ty_id).unwrap() };
let mut mutable = true;
let defs = ctx.top_level.definitions.read();
println!("Debug: defs length: {}", defs.len());
println!("Debug: def_id index: {}", def_id.0);
if let TopLevelDef::Class { fields, .. } = &*defs[def_id.0].read() {
println!("Debug: Accessing TopLevelDef::Class with fields:");
for (field_name, _, is_mutable) in fields {
println!(
"Debug: Field `{}`, Mutable: {}, Comparing with `{}`",
field_name.to_string(),
is_mutable,
name.to_string()
);
if field_name == &name {
mutable = *is_mutable;
println!("Debug: Match found for field `{}`. Mutable: {}", field_name.to_string(), is_mutable);
break;
}
}
@ -946,18 +957,50 @@ impl InnerResolver {
}
}
}
pub fn debug_dump_field_to_val(&self) {
let field_to_val = self.field_to_val.read(); // Access the field_to_val map
println!("Debug: Dumping `field_to_val`...");
for ((id, name), handle) in field_to_val.iter() {
println!(" Field Name: {}, ID: {}, Handle: {:?}", name.to_string(), id, handle);
}
}
pub fn debug_dump_id_to_def(&self) {
let id_to_def = self.id_to_def.read(); // Access the id_to_def map
println!("Debug: Dumping `id_to_def`...");
for (name, def_id) in id_to_def.iter() {
println!(" Identifier: {}, DefinitionId: {:?}", name.to_string(), def_id);
}
}
pub fn debug_dump_id_to_pyval(&self) {
let id_to_pyval = self.id_to_pyval.read(); // Access the id_to_pyval map
println!("Debug: Dumping `id_to_pyval`...");
for (name, (id, obj)) in id_to_pyval.iter() {
println!(" Identifier: {}, ID: {}, PyObject: {:?}", name.to_string(), id, obj);
}
}
pub fn get_class_name(&self, field_id: StrRef, defs: &[Arc<RwLock<TopLevelDef>>]) -> Option<String> {
println!(
"Debug: Resolving field `{}` in get_class_name",
field_id.to_string()
);
let field_to_val = self.field_to_val.read();
let class_id = field_to_val.iter().find_map(|(&(id, ref name), _)| {
println!(
"Debug: Checking field name `{}` with id `{}`",
name.to_string(),
id
);
if *name == field_id {
Some(id)
} else {
None
}
})?;
println!("Debug: Found class id: `{}` for field `{}`", class_id, field_id.to_string());
let id_to_def = self.id_to_def.read();
let def_id = id_to_def.get(&StrRef::from(class_id.to_string()))?;
@ -1540,15 +1583,21 @@ impl SymbolResolver for Resolver {
) -> Option<ValueEnum<'ctx>> {
let (resolved_id, _is_dunder) = if id.to_string().starts_with("__") && !id.to_string().ends_with("__") && !id.to_string().contains('.') {
let inner_resolver = &self.0;
if let Some(class_name) = inner_resolver.get_class_name(id, &ctx.top_level.definitions.read()) {
println!(
"Debug: Mangling dunder variable `{}` with class `{}`",
id.to_string(),
class_name
);
let stripped_class_name = class_name.trim_start_matches('_');
let mangled_id: StrRef = format!("_{}{}", stripped_class_name, id).into();
(mangled_id, true)
} else {
println!("Debug: Could not resolve class name for `{}`", id.to_string());
(id, false)
}
} else {
println!("Debug: Identifier `{}` is not a dunder variable", id.to_string());
(id, false)
};
let sym_value = {
@ -1586,11 +1635,20 @@ impl SymbolResolver for Resolver {
}
fn get_identifier_def(&self, id: StrRef) -> Result<DefinitionId, HashSet<String>> {
println!("Debug: Resolving identifier `{}`", id.to_string());
println!("Debug: Dumping resolver state before reading `id_to_def`:");
self.0.debug_dump_field_to_val();
self.0.debug_dump_id_to_def();
self.0.debug_dump_id_to_pyval();
{
let id_to_def = self.0.id_to_def.read();
id_to_def.get(&id).copied().ok_or_else(String::new)
}
.or_else(|_| {
println!("Debug: Falling back to name_to_pyid for `{}`", id.to_string());
let py_id = self
.0
.name_to_pyid
@ -1601,6 +1659,13 @@ impl SymbolResolver for Resolver {
"`{id}` is not registered with NAC3 (@nac3 decorator missing?)"
)])
})?;
println!("Debug: Dumping resolver state after resolving `{}`:", id.to_string());
self.0.debug_dump_field_to_val();
self.0.debug_dump_id_to_def();
self.0.debug_dump_id_to_pyval();
println!("Debug: Found in pyid_to_def -> {:?}", result);
self.0.id_to_def.write().insert(id, result);
Ok(result)
})

View File

@ -447,6 +447,10 @@ impl TopLevelComposer {
}
let ty_to_be_unified = self.unifier.get_dummy_var().ty;
println!(
"Registering field: name=`{}` in module=`{}` with annotation=`{:?}` at location=`{:?}`",
name, mod_path, annotation, location
);
self.definition_ast_list.push((
RwLock::new(Self::make_top_level_variable_def(
global_var_name,
@ -1179,7 +1183,7 @@ impl TopLevelComposer {
if let ExprKind::Name { id: attr, .. } = &target.node {
if defined_fields.insert(attr.to_string()) {
let dummy_field_type = unifier.get_dummy_var().ty;
let mutable = false;
let annotation = match value {
None => {
// handle Kernel[T], KernelInvariant[T]
@ -1243,6 +1247,10 @@ impl TopLevelComposer {
annotation
}
};
println!(
"Class field registered: name=`{}`, type=`{:?}`, mutable=`{}`",
attr, annotation, mutable
);
let parsed_annotation = parse_ast_to_type_annotation_kinds(
class_resolver,
temp_def_list,
@ -1975,6 +1983,13 @@ impl TopLevelComposer {
&mut None,
)?;
let variable_name = match &*variable_def.read() {
TopLevelDef::Class { name, .. } => name.clone(),
TopLevelDef::Function { simple_name, .. } => simple_name.clone(),
TopLevelDef::Variable { simple_name, .. } => simple_name.clone(),
};
println!("Variable name: {}", variable_name);
unifier.unify(*dummy_ty, ty_from_ty_annotation).map_err(|e| {
HashSet::from([e.at(Some(loc.unwrap())).to_display(unifier).to_string()])
})?;