nac3artiq: implements #33

This commit is contained in:
pca006132 2021-10-07 15:57:45 +08:00
parent 62673cf608
commit 08947d20c2
1 changed files with 103 additions and 16 deletions

View File

@ -16,6 +16,7 @@ use pyo3::{
}; };
use rustpython_parser::ast::StrRef; use rustpython_parser::ast::StrRef;
use std::{ use std::{
cell::RefCell,
collections::{HashMap, HashSet}, collections::{HashMap, HashSet},
sync::Arc, sync::Arc,
}; };
@ -109,6 +110,46 @@ impl Resolver {
.collect(); .collect();
let types = types?; let types = types?;
Ok(types.map(|types| unifier.add_ty(TypeEnum::TTuple { ty: types }))) Ok(types.map(|types| unifier.add_ty(TypeEnum::TTuple { ty: types })))
} else if let Some(def_id) = self.pyid_to_def.read().get(&ty_id) {
let def = defs[def_id.0].read();
if let TopLevelDef::Class {
object_id,
type_vars,
fields,
methods,
..
} = &*def
{
if type_vars.is_empty() {
let mut fields_ty = HashMap::new();
for method in methods.iter() {
fields_ty.insert(method.0, method.1);
}
for field in fields.iter() {
let name: String = field.0.into();
let field_data = obj.getattr(&name)?;
let ty = self
.get_obj_type(field_data, helper, unifier, defs, primitives)?
.unwrap_or(primitives.none);
if unifier.unify(ty, field.1).is_err() {
// field type mismatch
return Ok(None);
}
fields_ty.insert(field.0, ty);
}
Ok(Some(unifier.add_ty(TypeEnum::TObj {
obj_id: *object_id,
fields: RefCell::new(fields_ty),
params: Default::default(),
})))
} else {
// type var is not supported for now
Ok(None)
}
} else {
// only object is supported, functions are not supported
Ok(None)
}
} else { } else {
Ok(None) Ok(None)
} }
@ -142,20 +183,10 @@ impl Resolver {
let id: u64 = helper.id_fn.call1((obj,))?.extract()?; let id: u64 = helper.id_fn.call1((obj,))?.extract()?;
let id_str = id.to_string(); let id_str = id.to_string();
let len: usize = helper.len_fn.call1((obj,))?.extract()?; let len: usize = helper.len_fn.call1((obj,))?.extract()?;
if len == 0 { let ty = if len == 0 {
let int32 = ctx.ctx.i32_type(); ctx.primitives.int32
return Ok(Some( } else {
ctx.ctx self.get_list_elem_type(
.struct_type(
&[int32.into(), int32.ptr_type(AddressSpace::Generic).into()],
false,
)
.const_zero()
.into(),
));
}
let ty = self
.get_list_elem_type(
obj, obj,
len, len,
helper, helper,
@ -163,7 +194,8 @@ impl Resolver {
&ctx.top_level.definitions.read(), &ctx.top_level.definitions.read(),
&ctx.primitives, &ctx.primitives,
)? )?
.unwrap(); .unwrap()
};
let ty = ctx.get_llvm_type(ty); let ty = ctx.get_llvm_type(ty);
let arr_ty = ctx.ctx.struct_type( let arr_ty = ctx.ctx.struct_type(
&[ &[
@ -293,9 +325,64 @@ impl Resolver {
.add_global(ty, Some(AddressSpace::Generic), &id_str); .add_global(ty, Some(AddressSpace::Generic), &id_str);
global.set_initializer(&val); global.set_initializer(&val);
Ok(Some(global.as_pointer_value().into())) Ok(Some(global.as_pointer_value().into()))
} else {
let id: u64 = helper.id_fn.call1((obj,))?.extract()?;
let id_str = id.to_string();
let top_level_defs = ctx.top_level.definitions.read();
let ty = self
.get_obj_type(
obj,
helper,
&mut ctx.unifier,
&top_level_defs,
&ctx.primitives,
)?
.unwrap();
let ty = ctx
.get_llvm_type(ty)
.into_pointer_type()
.get_element_type()
.into_struct_type()
.as_basic_type_enum();
{
let mut global_value_ids = self.global_value_ids.lock();
if global_value_ids.contains(&id) {
let global = ctx.module.get_global(&id_str).unwrap_or_else(|| {
ctx.module
.add_global(ty, Some(AddressSpace::Generic), &id_str)
});
return Ok(Some(global.as_pointer_value().into()));
} else {
global_value_ids.insert(id);
}
}
// should be classes
let definition = top_level_defs
.get(self.pyid_to_def.read().get(&ty_id).unwrap().0)
.unwrap()
.read();
if let TopLevelDef::Class { fields, .. } = &*definition {
let values: Result<Option<Vec<_>>, _> = fields
.iter()
.map(|(name, _)| {
self.get_obj_value(obj.getattr(&name.to_string())?, helper, ctx)
})
.collect();
let values = values?;
if let Some(values) = values {
let val = ctx.ctx.const_struct(&values, false);
let global = ctx
.module
.add_global(ty, Some(AddressSpace::Generic), &id_str);
global.set_initializer(&val);
Ok(Some(global.as_pointer_value().into()))
} else { } else {
Ok(None) Ok(None)
} }
} else {
unreachable!()
}
}
} }
} }