Source code for pySym.pyState.Call

import logging
import z3
import ast
from .. import pyState
from copy import copy
import itertools

logger = logging.getLogger("pyState:Call")


def _resolveArgs(state,element):

    ret = []
    # Resolve the args
    for arg in element.args:
        caller_args = state.resolveObject(arg)

        # Normalize
        caller_args = [caller_args] if type(caller_args) is not list else caller_args

        # Check for return object. Return all applicable
        retObjs = [x for x in caller_args if type(x) is pyState.ReturnObject]
        if len(retObjs) > 0:
            return retObjs
        
        ret.append(caller_args)

    return itertools.product(*ret)

def _resolveKeywords(state,element):
    ret = []

    for keyword in element.keywords:
        kws = []
        caller_args = state.resolveObject(keyword.value)

        # Normalize
        caller_args = [caller_args] if type(caller_args) is not list else caller_args
        
        # Check for return object. Return all applicable
        retObjs = [x for x in caller_args if type(x) is pyState.ReturnObject]
        if len(retObjs) > 0:
            return retObjs

        # Add all of these to a list
        for arg in caller_args:
            kw = copy(keyword)
            kw.value = arg.copy()
            kws.append(kw)

        ret.append(kws)

    return itertools.product(*ret)

[docs]def handle(state,element,retObj=None): """Attempt to handle the Python Call element Parameters ---------- state : pyState.State pyState.State object to handle this element under element : ast.Call element from source to be handled retObj : pyState.ReturnObject, optional `retObj` is an optional input to specify a ReturnObject to be used ahead of time. Returns ------- list list contains state objects either generated or discovered through handling this ast. This function handles calls to ast.Call. It is not meant to be called manually via a user. A call will cause a context switch, populate variables, and set other internals. Upon return, the state will be inside the function. Example ------- Example of ast.Call is: test() """ assert type(state) == pyState.State assert type(element) == ast.Call argElements = list(_resolveArgs(state,element)) # Check for return object. Return all applicable retObjs = [x for x in argElements if type(x) is pyState.ReturnObject] if len(retObjs) > 0: return retObjs keywordElements = list(_resolveKeywords(state,copy(element))) # Check for return object. Return all applicable retObjs = [x for x in keywordElements if type(x) is pyState.ReturnObject] if len(retObjs) > 0: return retObjs ret = [] # Yeah, this is a hack. But when we're soft matching, this number can help us identify the right thing. element.col_offset = 31337 # For each possible combination of args for arg in argElements: for keyword in keywordElements: # Set the arg list elm = copy(element) elm.args = arg # Set the kwlist elm.keywords = keyword # Copy state s = state.copy() # Create our return object (temporary ID to be filled in by the Call handle) retObj = pyState.ReturnObject(1,s) # Update state, change call to ReturnObject so we can resolve next time assert pyState.replaceObjectWithObject(s.path[0],element,retObj) # Ensure everything has a correct state for a in elm.args: a.state = s for a in keyword: a.value.state = s # Call ret += [s.Call(elm,retObj=retObj)] return ret