@@ -571,6 +571,40 @@ def byte_CALL_FUNCTION(self, opcode):
571571 callargs = abstract .Args (posargs = tuple (args ), frame = self )
572572 self ._call_function (func , callargs )
573573
574+ def _unpack_starargs (self , starargs ):
575+ # TODO(b/331853896): This follows vm_utils.ensure_unpacked_starargs, but
576+ # does not yet handle indefinite iterables.
577+ posargs = starargs .get_atomic_value ()
578+ if isinstance (posargs , abstract .FunctionArgTuple ):
579+ # This has already been converted
580+ pass
581+ elif isinstance (posargs , abstract .Tuple ):
582+ posargs = abstract .FunctionArgTuple (self ._ctx , posargs .constant )
583+ elif isinstance (posargs , tuple ):
584+ posargs = abstract .FunctionArgTuple (self ._ctx , posargs )
585+ else :
586+ assert False , f'unexpected posargs type: { posargs } : { type (posargs )} '
587+ return posargs
588+
589+ def _unpack_starstarargs (self , starstarargs ):
590+ kwargs = abstract .get_atomic_constant (starstarargs , dict )
591+ return {abstract .get_atomic_constant (k , str ): v
592+ for k , v in kwargs .items ()}
593+
594+ def byte_CALL_FUNCTION_EX (self , opcode ):
595+ if opcode .arg & _Flags .CALL_FUNCTION_EX_HAS_KWARGS :
596+ starstarargs = self ._stack .pop ()
597+ kwargs = self ._unpack_starstarargs (starstarargs )
598+ else :
599+ kwargs = _EMPTY_MAP
600+ starargs = self ._stack .pop ()
601+ posargs = self ._unpack_starargs (starargs ).constant
602+ func = self ._stack .pop ()
603+ if self ._code .python_version >= (3 , 11 ):
604+ self ._stack .pop_and_discard ()
605+ callargs = abstract .Args (posargs = posargs , kwargs = kwargs , frame = self )
606+ self ._call_function (func , callargs )
607+
574608 def byte_CALL_METHOD (self , opcode ):
575609 args = self ._stack .popn (opcode .arg )
576610 func = self ._stack .pop ()
0 commit comments