(vm: &VirtualMachine, expr: &ast::Expr, ctx: ast::ExprContext)
| 302 | } |
| 303 | |
| 304 | fn validate_expr(vm: &VirtualMachine, expr: &ast::Expr, ctx: ast::ExprContext) -> PyResult<()> { |
| 305 | let mut check_ctx = true; |
| 306 | let actual_ctx = match expr { |
| 307 | ast::Expr::Attribute(attr) => attr.ctx, |
| 308 | ast::Expr::Subscript(sub) => sub.ctx, |
| 309 | ast::Expr::Starred(star) => star.ctx, |
| 310 | ast::Expr::Name(name) => { |
| 311 | validate_name(vm, name.id())?; |
| 312 | name.ctx |
| 313 | } |
| 314 | ast::Expr::List(list) => list.ctx, |
| 315 | ast::Expr::Tuple(tuple) => tuple.ctx, |
| 316 | _ => { |
| 317 | if ctx != ast::ExprContext::Load { |
| 318 | return Err(vm.new_value_error(format!( |
| 319 | "expression which can't be assigned to in {} context", |
| 320 | expr_context_name(ctx) |
| 321 | ))); |
| 322 | } |
| 323 | check_ctx = false; |
| 324 | ast::ExprContext::Invalid |
| 325 | } |
| 326 | }; |
| 327 | if check_ctx && actual_ctx != ctx { |
| 328 | return Err(vm.new_value_error(format!( |
| 329 | "expression must have {} context but has {} instead", |
| 330 | expr_context_name(ctx), |
| 331 | expr_context_name(actual_ctx) |
| 332 | ))); |
| 333 | } |
| 334 | |
| 335 | match expr { |
| 336 | ast::Expr::BoolOp(op) => { |
| 337 | if op.values.len() < 2 { |
| 338 | return Err(vm.new_value_error("BoolOp with less than 2 values")); |
| 339 | } |
| 340 | validate_exprs(vm, &op.values, ast::ExprContext::Load, false) |
| 341 | } |
| 342 | ast::Expr::Named(named) => { |
| 343 | if !matches!(&*named.target, ast::Expr::Name(_)) { |
| 344 | return Err(vm.new_type_error("NamedExpr target must be a Name")); |
| 345 | } |
| 346 | validate_expr(vm, &named.value, ast::ExprContext::Load) |
| 347 | } |
| 348 | ast::Expr::BinOp(bin) => { |
| 349 | validate_expr(vm, &bin.left, ast::ExprContext::Load)?; |
| 350 | validate_expr(vm, &bin.right, ast::ExprContext::Load) |
| 351 | } |
| 352 | ast::Expr::UnaryOp(unary) => validate_expr(vm, &unary.operand, ast::ExprContext::Load), |
| 353 | ast::Expr::Lambda(lambda) => { |
| 354 | if let Some(parameters) = &lambda.parameters { |
| 355 | validate_parameters(vm, parameters)?; |
| 356 | } |
| 357 | validate_expr(vm, &lambda.body, ast::ExprContext::Load) |
| 358 | } |
| 359 | ast::Expr::If(ifexp) => { |
| 360 | validate_expr(vm, &ifexp.test, ast::ExprContext::Load)?; |
| 361 | validate_expr(vm, &ifexp.body, ast::ExprContext::Load)?; |
no test coverage detected