Skip to content

Commit 3c33d35

Browse files
committed
backup
1 parent f7dc9e6 commit 3c33d35

1 file changed

Lines changed: 140 additions & 26 deletions

File tree

compiler/codegen/src/compile.rs

Lines changed: 140 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
//! <https://github.com/python/cpython/blob/main/Python/compile.c>
66
//! <https://github.com/micropython/micropython/blob/master/py/compile.c>
77
8+
// spell-checker:ignore starunpack
9+
810
#![deny(clippy::cast_possible_truncation)]
911

1012
use crate::{
@@ -47,8 +49,8 @@ use num_complex::Complex;
4749
use num_traits::{Num, ToPrimitive};
4850
use ruff_python_ast::{
4951
Alias, Arguments, BoolOp, CmpOp, Comprehension, ConversionFlag, DebugText, Decorator, DictItem,
50-
ExceptHandler, ExceptHandlerExceptHandler, Expr, ExprAttribute, ExprBoolOp, ExprFString,
51-
ExprList, ExprName, ExprStarred, ExprSubscript, ExprTuple, ExprUnaryOp, FString,
52+
ExceptHandler, ExceptHandlerExceptHandler, Expr, ExprAttribute, ExprBoolOp, ExprContext,
53+
ExprFString, ExprList, ExprName, ExprStarred, ExprSubscript, ExprTuple, ExprUnaryOp, FString,
5254
FStringElement, FStringElements, FStringFlags, FStringPart, Identifier, Int, Keyword,
5355
MatchCase, ModExpression, ModModule, Operator, Parameters, Pattern, PatternMatchAs,
5456
PatternMatchClass, PatternMatchOr, PatternMatchSequence, PatternMatchSingleton,
@@ -372,7 +374,7 @@ impl<'src> Compiler<'src> {
372374
}
373375
}
374376

375-
/// Type of collection to build in star_unpack_helper
377+
/// Type of collection to build in starunpack_helper
376378
#[derive(Debug, Clone, Copy, PartialEq)]
377379
enum CollectionType {
378380
Tuple,
@@ -381,15 +383,120 @@ enum CollectionType {
381383
}
382384

383385
impl Compiler<'_> {
386+
/// Check if the slice is a two-element slice (no step)
387+
// = is_two_element_slice
388+
fn is_two_element_slice(&self, slice: &Expr) -> bool {
389+
matches!(slice, Expr::Slice(s) if s.step.is_none())
390+
}
391+
392+
/// Compile a slice expression
393+
// = compiler_slice
394+
fn compile_slice(&mut self, slice: &Expr) -> CompileResult<u32> {
395+
match slice {
396+
Expr::Slice(s) => {
397+
// Compile lower
398+
if let Some(lower) = &s.lower {
399+
self.compile_expression(lower)?;
400+
} else {
401+
self.emit_load_const(ConstantData::None);
402+
}
403+
404+
// Compile upper
405+
if let Some(upper) = &s.upper {
406+
self.compile_expression(upper)?;
407+
} else {
408+
self.emit_load_const(ConstantData::None);
409+
}
410+
411+
// Compile step if present
412+
if let Some(step) = &s.step {
413+
self.compile_expression(step)?;
414+
Ok(3) // Three values on stack
415+
} else {
416+
Ok(2) // Two values on stack
417+
}
418+
}
419+
_ => Err(self.error(CodegenErrorType::SyntaxError(
420+
"compile_slice expects a slice expression".to_owned(),
421+
))),
422+
}
423+
}
424+
425+
/// Compile a subscript expression
426+
// = compiler_subscript
427+
fn compile_subscript(
428+
&mut self,
429+
value: &Expr,
430+
slice: &Expr,
431+
ctx: ExprContext,
432+
) -> CompileResult<()> {
433+
// In CPython:
434+
// 1. Check subscripter and index for Load context
435+
// 2. VISIT value
436+
// 3. Handle two-element slice specially
437+
// 4. Otherwise VISIT slice and emit appropriate instruction
438+
439+
// For Load context, CPython does some checks (we skip for now)
440+
// if ctx == ExprContext::Load {
441+
// check_subscripter(value);
442+
// check_index(value, slice);
443+
// }
444+
445+
// VISIT(c, expr, e->v.Subscript.value)
446+
self.compile_expression(value)?;
447+
448+
// Handle two-element slice (for Load/Store, not Del)
449+
if self.is_two_element_slice(slice) && !matches!(ctx, ExprContext::Del) {
450+
let n = self.compile_slice(slice)?;
451+
match ctx {
452+
ExprContext::Load => {
453+
// CPython uses BINARY_SLICE
454+
emit!(self, Instruction::BuildSlice { step: n == 3 });
455+
emit!(self, Instruction::Subscript);
456+
}
457+
ExprContext::Store => {
458+
// CPython uses STORE_SLICE
459+
emit!(self, Instruction::BuildSlice { step: n == 3 });
460+
emit!(self, Instruction::StoreSubscript);
461+
}
462+
_ => unreachable!(),
463+
}
464+
} else {
465+
// VISIT(c, expr, e->v.Subscript.slice)
466+
self.compile_subscript_slice(slice)?;
467+
468+
// Emit appropriate instruction based on context
469+
match ctx {
470+
ExprContext::Load => emit!(self, Instruction::Subscript),
471+
ExprContext::Store => emit!(self, Instruction::StoreSubscript),
472+
ExprContext::Del => emit!(self, Instruction::DeleteSubscript),
473+
ExprContext::Invalid => {
474+
return Err(self.error(CodegenErrorType::SyntaxError(
475+
"Invalid expression context".to_owned(),
476+
)));
477+
}
478+
}
479+
}
480+
481+
Ok(())
482+
}
483+
384484
/// Compile a subscript slice, handling starred expressions in tuples
385-
/// Similar to CPython's handling in compiler_subscript()
485+
// = compiler_subscript() - specifically the VISIT(c, expr, slice) part
386486
fn compile_subscript_slice(&mut self, slice: &Expr) -> CompileResult<()> {
487+
// In CPython, compiler_subscript just does VISIT(c, expr, e->v.Subscript.slice)
488+
// which calls compiler_visit_expr, which in turn calls compiler_tuple for Tuple_kind
489+
// In Load context, compiler_tuple uses starunpack_helper
490+
387491
match slice {
388-
// Tuple with potentially starred elements: C[int, *tuple[str, ...], bool]
389-
Expr::Tuple(ExprTuple { elts, .. }) => {
390-
self.star_unpack_helper(elts, 0, CollectionType::Tuple)?;
391-
}
392-
// Regular expression (including single starred)
492+
// Special handling for tuple in subscript context
493+
// This matches CPython's compiler_tuple behavior for Load context
494+
Expr::Tuple(ExprTuple { elts, ctx, .. }) if matches!(ctx, ExprContext::Load) => {
495+
// Use starunpack_helper to handle potential starred expressions
496+
// This is equivalent to CPython's compiler_tuple calling starunpack_helper
497+
self.starunpack_helper(elts, 0, CollectionType::Tuple)?;
498+
}
499+
// For all other cases (including Store/Del context tuples), compile normally
393500
_ => {
394501
self.compile_expression(slice)?;
395502
}
@@ -405,7 +512,7 @@ impl Compiler<'_> {
405512
/// - collection_type: What type of collection to build (tuple, list, set)
406513
///
407514
// = starunpack_helper in compile.c
408-
fn star_unpack_helper(
515+
fn starunpack_helper(
409516
&mut self,
410517
elts: &[Expr],
411518
pushed: u32,
@@ -1652,10 +1759,10 @@ impl Compiler<'_> {
16521759
let idx = self.name(attr.as_str());
16531760
emit!(self, Instruction::DeleteAttr { idx });
16541761
}
1655-
Expr::Subscript(ExprSubscript { value, slice, .. }) => {
1656-
self.compile_expression(value)?;
1657-
self.compile_subscript_slice(slice)?;
1658-
emit!(self, Instruction::DeleteSubscript);
1762+
Expr::Subscript(ExprSubscript {
1763+
value, slice, ctx, ..
1764+
}) => {
1765+
self.compile_subscript(value, slice, ctx.clone())?;
16591766
}
16601767
Expr::Tuple(ExprTuple { elts, .. }) | Expr::List(ExprList { elts, .. }) => {
16611768
for element in elts {
@@ -4020,10 +4127,10 @@ impl Compiler<'_> {
40204127
fn compile_store(&mut self, target: &Expr) -> CompileResult<()> {
40214128
match &target {
40224129
Expr::Name(ExprName { id, .. }) => self.store_name(id.as_str())?,
4023-
Expr::Subscript(ExprSubscript { value, slice, .. }) => {
4024-
self.compile_expression(value)?;
4025-
self.compile_subscript_slice(slice)?;
4026-
emit!(self, Instruction::StoreSubscript);
4130+
Expr::Subscript(ExprSubscript {
4131+
value, slice, ctx, ..
4132+
}) => {
4133+
self.compile_subscript(value, slice, ctx.clone())?;
40274134
}
40284135
Expr::Attribute(ExprAttribute { value, attr, .. }) => {
40294136
self.check_forbidden_name(attr.as_str(), NameUsage::Store)?;
@@ -4104,7 +4211,14 @@ impl Compiler<'_> {
41044211
self.compile_name(id, NameUsage::Load)?;
41054212
AugAssignKind::Name { id }
41064213
}
4107-
Expr::Subscript(ExprSubscript { value, slice, .. }) => {
4214+
Expr::Subscript(ExprSubscript {
4215+
value,
4216+
slice,
4217+
ctx: _,
4218+
..
4219+
}) => {
4220+
// For augmented assignment, we need to load the value first
4221+
// But we can't use compile_subscript directly because we need DUP_TOP2
41084222
self.compile_expression(value)?;
41094223
self.compile_subscript_slice(slice)?;
41104224
emit!(self, Instruction::Duplicate2);
@@ -4338,10 +4452,10 @@ impl Compiler<'_> {
43384452
// Perform operation:
43394453
self.compile_op(op, false);
43404454
}
4341-
Expr::Subscript(ExprSubscript { value, slice, .. }) => {
4342-
self.compile_expression(value)?;
4343-
self.compile_subscript_slice(slice)?;
4344-
emit!(self, Instruction::Subscript);
4455+
Expr::Subscript(ExprSubscript {
4456+
value, slice, ctx, ..
4457+
}) => {
4458+
self.compile_subscript(value, slice, ctx.clone())?;
43454459
}
43464460
Expr::UnaryOp(ExprUnaryOp { op, operand, .. }) => {
43474461
self.compile_expression(operand)?;
@@ -4372,13 +4486,13 @@ impl Compiler<'_> {
43724486
// self.emit_load_const(compile_constant(value));
43734487
// }
43744488
Expr::List(ExprList { elts, .. }) => {
4375-
self.star_unpack_helper(elts, 0, CollectionType::List)?;
4489+
self.starunpack_helper(elts, 0, CollectionType::List)?;
43764490
}
43774491
Expr::Tuple(ExprTuple { elts, .. }) => {
4378-
self.star_unpack_helper(elts, 0, CollectionType::Tuple)?;
4492+
self.starunpack_helper(elts, 0, CollectionType::Tuple)?;
43794493
}
43804494
Expr::Set(ExprSet { elts, .. }) => {
4381-
self.star_unpack_helper(elts, 0, CollectionType::Set)?;
4495+
self.starunpack_helper(elts, 0, CollectionType::Set)?;
43824496
}
43834497
Expr::Dict(ExprDict { items, .. }) => {
43844498
self.compile_dict(items)?;

0 commit comments

Comments
 (0)