from .topping import Topping

class ParticleTypesTopping(Topping):
    """Provides a list of all particle types"""

    PROVIDES = [
        "particletypes"
    ]
    DEPENDS = ["identify.particletypes"]

    @staticmethod
    def act(aggregate, classloader, verbose=False):
        particletypes = []
        cf = classloader[aggregate["classes"]["particletypes"]]
        # Method is either <clinit> or a void with no parameters, check both
        # until we find one that loads constants
        for meth in cf.methods.find(args = '', returns = 'V'):
            ops = tuple(meth.code.disassemble())
            if(next(x for x in ops if 'ldc' in x.name), False):
                break
        for idx, op in enumerate(ops):
            if 'ldc' in op.name:
                str_val = op.operands[0].string.value

                # Enum identifiers in older version of MC are all uppercase,
                # these are distinct from the particletype strings we're
                # collecting here.
                if str_val.isupper():
                    continue

                # This instruction sequence is unique to particle type fields
                if ops[idx + 1].name in ('bipush', 'getstatic'):
                    particletypes.append(str_val)

        aggregate['particletypes'] = particletypes

@@ -23,16 +23,17 @@
 opping%0A%0A
+%0A
 class Pa
@@ -126,25 +126,16 @@
 IDES = %5B
-%0A        
 %22particl
@@ -141,21 +141,16 @@
 letypes%22
-%0A    
 %5D%0A    DE
@@ -512,19 +512,17 @@
 ind(args
- = 
+=
 '', retu
@@ -524,19 +524,17 @@
  returns
- = 
+=
 'V'):%0A  
@@ -598,31 +598,31 @@
   if
-(
+ 
 next(
-x for x in ops if
+filter(lambda op:
  'ld
@@ -631,14 +631,20 @@
  in 
-x
+op
 .name
+, ops
 ), F
@@ -672,16 +672,17 @@
   break%0A
+%0A
         

Fix particletypes topping for 1.17