Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[IMP] server: unpack_assign handle attributes #268

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 48 additions & 29 deletions server/src/core/python_arch_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ use super::entry_point::EntryPoint;
use super::evaluation::{EvaluationSymbolPtr, EvaluationSymbolWeak};
use super::import_resolver::ImportResult;
use super::odoo::SyncOdoo;
use super::python_utils::AssignTargetType;
use super::symbols::function_symbol::{Argument, ArgumentType};
use super::symbols::symbol_mgr::SectionIndex;

Expand Down Expand Up @@ -487,7 +488,13 @@ impl PythonArchBuilder {
if let Some(ref expr) = assign.value{
self.visit_expr(session, expr);
}
self.sym_stack.last().unwrap().borrow_mut().add_new_variable(session, oyarn!("{}", assign.target.id), &assign.target.range);
match assign.target {
AssignTargetType::Name(ref name_expr) => {
self.sym_stack.last().unwrap().borrow_mut().add_new_variable(session, oyarn!("{}", name_expr.id), &name_expr.range);
},
AssignTargetType::Attribute(ref attr_expr) => {
}
}
}
}

Expand All @@ -497,37 +504,43 @@ impl PythonArchBuilder {
if let Some(ref expr) = assign.value {
self.visit_expr(session, expr);
}
let variable = self.sym_stack.last().unwrap().borrow_mut().add_new_variable(session, oyarn!("{}", assign.target.id), &assign.target.range);
let mut variable = variable.borrow_mut();
if self.file_mode && variable.name() == "__all__" && assign.value.is_some() && variable.parent().is_some() {
let parent = variable.parent().as_ref().unwrap().upgrade();
if parent.is_some() {
let parent = parent.unwrap();
let eval = Evaluation::eval_from_ast(session, &assign.value.as_ref().unwrap(), parent, &assign_stmt.range.start());
variable.as_variable_mut().evaluations = eval.0;
self.diagnostics.extend(eval.1);
if !variable.as_variable().evaluations.is_empty() {
if (*self.sym_stack.last().unwrap()).borrow().is_external() {
// external packages often import symbols from compiled files
// or with meta programmation like globals["var"] = __get_func().
// we don't want to handle that, so just declare __all__ content
// as symbols to not raise any error.
let evaluation = variable.as_variable_mut().evaluations.get(0).unwrap();
match &evaluation.value {
Some(EvaluationValue::LIST(list)) => {
for item in list.iter() {
match item {
Expr::StringLiteral(s) => {
self.__all_symbols_to_add.push((s.value.to_string(), evaluation.range.unwrap()));
},
_ => {}
}
match assign.target {
AssignTargetType::Name(ref name_expr) => {
let variable = self.sym_stack.last().unwrap().borrow_mut().add_new_variable(session, oyarn!("{}", name_expr.id), &name_expr.range);
let mut variable = variable.borrow_mut();
if self.file_mode && variable.name() == "__all__" && assign.value.is_some() && variable.parent().is_some() {
let parent = variable.parent().as_ref().unwrap().upgrade();
if parent.is_some() {
let parent = parent.unwrap();
let eval = Evaluation::eval_from_ast(session, &assign.value.as_ref().unwrap(), parent, &assign_stmt.range.start());
variable.as_variable_mut().evaluations = eval.0;
self.diagnostics.extend(eval.1);
if !variable.as_variable().evaluations.is_empty() {
if (*self.sym_stack.last().unwrap()).borrow().is_external() {
// external packages often import symbols from compiled files
// or with meta programmation like globals["var"] = __get_func().
// we don't want to handle that, so just declare __all__ content
// as symbols to not raise any error.
let evaluation = variable.as_variable_mut().evaluations.get(0).unwrap();
match &evaluation.value {
Some(EvaluationValue::LIST(list)) => {
for item in list.iter() {
match item {
Expr::StringLiteral(s) => {
self.__all_symbols_to_add.push((s.value.to_string(), evaluation.range.unwrap()));
},
_ => {}
}
}
},
_ => {}
}
},
_ => {}
}
}
}
}
},
AssignTargetType::Attribute(ref attr_expr) => {
}
}
}
Expand Down Expand Up @@ -737,7 +750,13 @@ impl PythonArchBuilder {
if let Some(ref expr) = assign.value {
self.visit_expr(session, expr);
}
scope.borrow_mut().add_new_variable(session, oyarn!("{}", assign.target.id), &assign.target.range);
match assign.target{
AssignTargetType::Name(ref name_expr) => {
scope.borrow_mut().add_new_variable(session, oyarn!("{}", name_expr.id), &name_expr.range);
},
AssignTargetType::Attribute(ref attr_expr) => {
}
}
}
let previous_section = SectionIndex::INDEX(scope.borrow().as_symbol_mgr().get_last_index());
scope.borrow_mut().as_mut_symbol_mgr().add_section(
Expand Down
95 changes: 51 additions & 44 deletions server/src/core/python_arch_eval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ use super::evaluation::{ContextValue, EvaluationSymbolPtr, EvaluationSymbolWeak}
use super::file_mgr::FileMgr;
use super::import_resolver::ImportResult;
use super::python_arch_eval_hooks::PythonArchEvalHooks;
use super::python_utils::Assign;
use super::python_utils::{Assign, AssignTargetType};
use super::symbols::function_symbol::FunctionSymbol;


Expand Down Expand Up @@ -437,54 +437,61 @@ impl PythonArchEval {
if let Some(ref expr) = assign.value {
self.visit_expr(session, expr);
}
let variable = self.sym_stack.last().unwrap().borrow().get_positioned_symbol(&OYarn::from(assign.target.id.to_string()), &assign.target.range);
if let Some(variable_rc) = variable {
let parent = variable_rc.borrow().parent().unwrap().upgrade().unwrap().clone();
let (eval, diags) = if let Some(ref annotation) = assign.annotation {
Evaluation::eval_from_ast(session, annotation, parent.clone(), &range.start())
} else if let Some(ref value) = assign.value {
Evaluation::eval_from_ast(session, value, parent.clone(), &range.start())
} else {
panic!("either value or annotation should exists");
};
variable_rc.borrow_mut().evaluations_mut().unwrap().extend(eval);
self.diagnostics.extend(diags);
let mut dep_to_add = vec![];
let mut v_mut = variable_rc.borrow_mut();
let var_name = v_mut.name().clone();
let evaluations = v_mut.evaluations_mut().unwrap();
let mut ix = 0;
while ix < evaluations.len(){
let evaluation = &evaluations[ix];
if let Some(sym) = evaluation.symbol.get_symbol_as_weak(session, &mut None, &mut self.diagnostics, None).weak.upgrade() {
if Rc::ptr_eq(&sym, &variable_rc){
// TODO: investigate deps, and fix cyclic evals
let file_path = parent.borrow().get_file().and_then(|file| file.upgrade()).and_then(|file| file.borrow().paths().first().cloned());
warn!("Found cyclic evaluation symbol: {}, parent: {}, file: {}", var_name, parent.borrow().name(), file_path.unwrap_or(S!("N/A")));
evaluations.remove(ix);
continue;
}
if let Some(file) = sym.borrow().get_file().clone() {
let sym_file = file.upgrade().unwrap().clone();
if !Rc::ptr_eq(&self.file, &sym_file) {
match Rc::ptr_eq(&variable_rc, &sym_file) {
true => {
dep_to_add.push(variable_rc.clone());
},
false => {
dep_to_add.push(sym_file);
match assign.target {
AssignTargetType::Name(ref name_expr) => {
let variable = self.sym_stack.last().unwrap().borrow().get_positioned_symbol(&OYarn::from(name_expr.id.to_string()), &name_expr.range);
if let Some(variable_rc) = variable {
let parent = variable_rc.borrow().parent().unwrap().upgrade().unwrap().clone();
let (eval, diags) = if let Some(ref annotation) = assign.annotation {
Evaluation::eval_from_ast(session, annotation, parent.clone(), &range.start())
} else if let Some(ref value) = assign.value {
Evaluation::eval_from_ast(session, value, parent.clone(), &range.start())
} else {
panic!("either value or annotation should exists");
};
variable_rc.borrow_mut().evaluations_mut().unwrap().extend(eval);
self.diagnostics.extend(diags);
let mut dep_to_add = vec![];
let mut v_mut = variable_rc.borrow_mut();
let var_name = v_mut.name().clone();
let evaluations = v_mut.evaluations_mut().unwrap();
let mut ix = 0;
while ix < evaluations.len(){
let evaluation = &evaluations[ix];
if let Some(sym) = evaluation.symbol.get_symbol_as_weak(session, &mut None, &mut self.diagnostics, None).weak.upgrade() {
if Rc::ptr_eq(&sym, &variable_rc){
// TODO: investigate deps, and fix cyclic evals
let file_path = parent.borrow().get_file().and_then(|file| file.upgrade()).and_then(|file| file.borrow().paths().first().cloned());
warn!("Found cyclic evaluation symbol: {}, parent: {}, file: {}", var_name, parent.borrow().name(), file_path.unwrap_or(S!("N/A")));
evaluations.remove(ix);
continue;
}
if let Some(file) = sym.borrow().get_file().clone() {
let sym_file = file.upgrade().unwrap().clone();
if !Rc::ptr_eq(&self.file, &sym_file) {
match Rc::ptr_eq(&variable_rc, &sym_file) {
true => {
dep_to_add.push(variable_rc.clone());
},
false => {
dep_to_add.push(sym_file);
}
};
}
};
}
}
ix += 1
}
for dep in dep_to_add {
self.file.borrow_mut().add_dependency(&mut dep.borrow_mut(), self.current_step, BuildSteps::ARCH);
}
} else {
debug!("Symbol not found");
}
ix += 1
}
for dep in dep_to_add {
self.file.borrow_mut().add_dependency(&mut dep.borrow_mut(), self.current_step, BuildSteps::ARCH);
},
AssignTargetType::Attribute(ref attr_expr) => {
//TODO
}
} else {
debug!("Symbol not found");
}
}
}
Expand Down
45 changes: 35 additions & 10 deletions server/src/core/python_utils.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
use ruff_python_ast::{Expr, ExprName};
use ruff_python_ast::{Expr, ExprAttribute, ExprName};
use tracing::error;

#[derive(Debug, Clone)]
pub enum AssignTargetType {
Name(ExprName),
Attribute(ExprAttribute),
}

#[derive(Debug, Clone)]
pub struct Assign {
pub target: ExprName,
pub target: AssignTargetType,
pub value: Option<Expr>,
pub annotation: Option<Expr>,
pub index: Option<usize>, //If index is set, it means that value is not unpackable, and that the target should be associated to the 'index' element of value
Expand All @@ -21,7 +27,7 @@ fn _link_tuples(targets: Vec<Expr>, values: Vec<Expr>) -> Vec<Assign> {
Expr::Subscript(_) => {},
Expr::Name(expr) => {
res.push(Assign {
target: expr.clone(),
target: AssignTargetType::Name(expr.clone()),
annotation: None,
value: Some(values.get(index).unwrap().clone()),
index: None,
Expand All @@ -40,7 +46,7 @@ fn _link_tuples(targets: Vec<Expr>, values: Vec<Expr>) -> Vec<Assign> {
match target {
Expr::Name(tar) => {
res.push(Assign {
target: tar.clone(),
target: AssignTargetType::Name(tar.clone()),
annotation: None,
value: Some(value.clone()),
index: Some(index),
Expand All @@ -64,7 +70,7 @@ fn _link_tuples(targets: Vec<Expr>, values: Vec<Expr>) -> Vec<Assign> {
match target {
Expr::Name(tar) => {
res.push(Assign {
target: tar.clone(),
target: AssignTargetType::Name(tar.clone()),
annotation: None,
value: Some(value.clone()),
index: Some(index),
Expand Down Expand Up @@ -95,21 +101,40 @@ pub fn unpack_assign(targets: &Vec<Expr>, annotation: Option<&Expr>, value: Opti

for target in targets.iter() {
match target {
Expr::Attribute(_) => {},
Expr::Attribute(expr) => {
match value {
Some(value) => {
res.push(Assign {
target: AssignTargetType::Attribute(expr.clone()),
annotation: annotation.cloned(),
value: Some(value.clone()),
index: None,
});
},
None => {
res.push(Assign {
target: AssignTargetType::Attribute(expr.clone()),
annotation: annotation.cloned(),
value: None,
index: None,
});
}
}
},
Expr::Subscript(_) => {},
Expr::Name(expr) => {
match value {
Some(value) => {
res.push(Assign {
target: expr.clone(),
target: AssignTargetType::Name(expr.clone()),
annotation: annotation.cloned(),
value: Some(value.clone()),
index: None,
});
},
None => {
res.push(Assign {
target: expr.clone(),
target: AssignTargetType::Name(expr.clone()),
annotation: annotation.cloned(),
value: None,
index: None,
Expand All @@ -134,7 +159,7 @@ pub fn unpack_assign(targets: &Vec<Expr>, annotation: Option<&Expr>, value: Opti
match target {
Expr::Name(tar) => {
res.push(Assign {
target: tar.clone(),
target: AssignTargetType::Name(tar.clone()),
annotation: None,
value: Some(value.clone()),
index: Some(index),
Expand All @@ -161,7 +186,7 @@ pub fn unpack_assign(targets: &Vec<Expr>, annotation: Option<&Expr>, value: Opti
match target {
Expr::Name(tar) => {
res.push(Assign {
target: tar.clone(),
target: AssignTargetType::Name(tar.clone()),
annotation: None,
value: Some(value.clone()),
index: Some(index),
Expand Down
Loading