def visit_Subscript(self, node):
self._is_string_symbol = False
name = self.visit(node.value)
if isinstance(node.slice, (ast.Index)):
for arg in self._function_args:
if arg == ("**%s" % name):
self._is_string_symbol = True
index = self.visit(node.slice)
self._is_string_symbol = False
return "%s[%s]" % (name, index)
#return "%s%s" % (name, index)
else:
# ast.Slice
index = self.visit(node.slice)
if ',' in index:
""" [See visit_Slice]
<Python> [8, 9, 10, 11, 12, 13, 14][1:6:2]
<Ruby> [8, 9, 10, 11, 12, 13, 14][1...6].each_slice(2).map(&:first)
"""
indexs = index.split(',')
return "%s[%s].%s" % (name, indexs[0], indexs[1])
else:
return "%s[%s]" % (name, index)
python类Index()的实例源码
def test_subscript(self):
sub = ast.Subscript(ast.Name("x", ast.Store()), ast.Index(ast.Num(3)),
ast.Load())
self.expr(sub, "must have Load context")
x = ast.Name("x", ast.Load())
sub = ast.Subscript(x, ast.Index(ast.Name("y", ast.Store())),
ast.Load())
self.expr(sub, "must have Load context")
s = ast.Name("x", ast.Store())
for args in (s, None, None), (None, s, None), (None, None, s):
sl = ast.Slice(*args)
self.expr(ast.Subscript(x, sl, ast.Load()),
"must have Load context")
sl = ast.ExtSlice([])
self.expr(ast.Subscript(x, sl, ast.Load()), "empty dims on ExtSlice")
sl = ast.ExtSlice([ast.Index(s)])
self.expr(ast.Subscript(x, sl, ast.Load()), "must have Load context")
def make_subscript(varname, idx, ctx=None, lineno=0, col_offset=0):
ctx = ctx or ast.Load()
return ast.Subscript(
value = ast.Name(
id = varname,
ctx = ast.Load(),
lineno = lineno,
col_offset = col_offset,
),
slice = ast.Index(
value = ast.Num(
n = idx,
lineno = lineno,
col_offset = col_offset,
),
lineno = lineno,
col_offset = col_offset,
),
ctx = ctx,
lineno = lineno,
col_offset = col_offset,
)
def test_subscript(self):
sub = ast.Subscript(ast.Name("x", ast.Store()), ast.Index(ast.Num(3)),
ast.Load())
self.expr(sub, "must have Load context")
x = ast.Name("x", ast.Load())
sub = ast.Subscript(x, ast.Index(ast.Name("y", ast.Store())),
ast.Load())
self.expr(sub, "must have Load context")
s = ast.Name("x", ast.Store())
for args in (s, None, None), (None, s, None), (None, None, s):
sl = ast.Slice(*args)
self.expr(ast.Subscript(x, sl, ast.Load()),
"must have Load context")
sl = ast.ExtSlice([])
self.expr(ast.Subscript(x, sl, ast.Load()), "empty dims on ExtSlice")
sl = ast.ExtSlice([ast.Index(s)])
self.expr(ast.Subscript(x, sl, ast.Load()), "must have Load context")
def flatten_subscript(self, node):
value = self.flatten(node.value)
node_type = self.new_type()
if isinstance(node.slice, ast.Index):
index = self.flatten(node.slice.value)
self.nodes.append(('z_index', [value, index], node_type))
else:
lower = self.flatten(node.slice.lower) if node.slice.lower else None
upper = self.flatten(node.slice.upper) if node.slice.upper else None
if lower and upper is None:
upper = lower
elif lower is None and upper:
lower = upper
else:
raise ValueError('hatlog expects only slice like [:x], [x:] or [x:y]')
self.nodes.append(('z_slice', [value, lower, upper], node_type))
return node_type
def test_subscript(self):
sub = ast.Subscript(ast.Name("x", ast.Store()), ast.Index(ast.Num(3)),
ast.Load())
self.expr(sub, "must have Load context")
x = ast.Name("x", ast.Load())
sub = ast.Subscript(x, ast.Index(ast.Name("y", ast.Store())),
ast.Load())
self.expr(sub, "must have Load context")
s = ast.Name("x", ast.Store())
for args in (s, None, None), (None, s, None), (None, None, s):
sl = ast.Slice(*args)
self.expr(ast.Subscript(x, sl, ast.Load()),
"must have Load context")
sl = ast.ExtSlice([])
self.expr(ast.Subscript(x, sl, ast.Load()), "empty dims on ExtSlice")
sl = ast.ExtSlice([ast.Index(s)])
self.expr(ast.Subscript(x, sl, ast.Load()), "must have Load context")
def Call_new(t, x):
"""Translate ``Foo(...)`` to ``new Foo(...)`` if function name starts
with a capital letter.
"""
def getNameString(x):
if isinstance(x, ast.Name):
return x.id
elif isinstance(x, ast.Attribute):
return str(x.attr)
elif isinstance(x, ast.Subscript):
if isinstance(x.slice, ast.Index):
return str(x.slice.value)
NAME_STRING = getNameString(x.func)
if (NAME_STRING and re.search(r'^[A-Z]', NAME_STRING)):
# TODO: generalize args mangling and apply here
# assert not any([x.keywords, x.starargs, x.kwargs])
subj = x
elif isinstance(x.func, ast.Name) and x.func.id == 'new':
subj = x.args[0]
else:
subj = None
if subj:
return Call_default(t, subj, operator='new ')
def syn_Subscript(self, ctx, e):
slice_ = e.slice
if isinstance(slice_, ast.Ellipsis):
raise _errors.TyError("stringing slice cannot be an Ellipsis.", e)
elif isinstance(slice_, ast.ExtSlice):
raise _errors.TyError("stringing slice can only have one dimension.", e)
elif isinstance(slice_, ast.Index):
ctx.ana(slice_.value, _numeric.num)
else: # if isinstance(slice_, ast.Slice):
lower, upper, step = slice_.lower, slice_.upper, slice_.step
if lower is not None:
ctx.ana(lower, _numeric.num)
if upper is not None:
ctx.ana(upper, _numeric.num)
if not _is_None(step):
ctx.ana(step, _numeric.num)
return self
def translate_Subscript(self, ctx, e):
translation = astx.copy_node(e)
translation.value = ctx.translate(e.value)
slice_ = e.slice
slice_translation = astx.copy_node(slice_)
if isinstance(slice_, ast.Index):
slice_translation.value = ctx.translate(slice_.value)
else:
lower, upper, step = slice_.lower, slice_.upper, slice_.step
slice_translation.lower = ctx.translate(lower) if lower is not None else None
slice_translation.upper = ctx.translate(upper) if upper is not None else None
if not _is_None(step):
slice_translation.step = ctx.translate(step)
else:
slice_translation.step = None
translation.slice = slice_translation
return translation
def translate_pat_Call_constructor(self, ctx, pat, scrutinee_trans):
lbl = pat.func.id
tag_loc = ast.Subscript(
value=scrutinee_trans,
slice=ast.Index(value=ast.Num(n=0)))
lbl_condition = ast.Compare(
left=tag_loc,
ops=[ast.Eq()],
comparators=[ast.Str(s=lbl)])
arg = pat.args[0]
arg_scrutinee = ast.Subscript(
value=scrutinee_trans,
slice=ast.Index(value=ast.Num(n=1)))
arg_condition, binding_translations = ctx.translate_pat(arg, arg_scrutinee)
condition = ast.BoolOp(
op=ast.And(),
values=[lbl_condition, arg_condition])
return condition, binding_translations
def visit_Subscript(self, t):
self(t.value)
if isinstance(t.slice, ast.Index):
if isinstance(t.ctx, ast.Load): pass
elif isinstance(t.ctx, ast.Store): pass
else: assert False, "Only loads and stores are supported: %r" % (t,)
self(t.slice.value)
else:
assert False, "Only simple subscripts are supported: %r" % (t,)
def visit_Subscript(self, node, types=None, typ=None):
pp = ProgramPoint(node.lineno, node.col_offset)
if isinstance(node.slice, ast.Index):
target = self.visit(node.value, types, typ)
key = self.visit(node.slice.value, types, typ)
return SubscriptionAccess(pp, target, key)
elif isinstance(node.slice, ast.Slice):
return SliceStmt(pp, self._ensure_stmt_visit(node.value, pp, *args, **kwargs),
self._ensure_stmt_visit(node.slice.lower, pp, *args, **kwargs),
self._ensure_stmt_visit(node.slice.step, pp, *args, **kwargs) if node.slice.step else None,
self._ensure_stmt_visit(node.slice.upper, pp, *args, **kwargs))
else:
raise NotImplementedError(f"The statement {str(type(node.slice))} is not yet translatable to CFG!")
def __getitem__(self, key):
keyname, key, constants = _normalize_arg(key, self._constants)
return __class__(
'%s[%s]' % (self._pname, keyname),
ast.Subscript(
value=self._tree,
slice=ast.Index(value=key),
ctx=ast.Load(),
),
constants,
)
def visit_Subscript(self, node):
if not self.config.constant_folding:
return
if isinstance(node.slice, ast.Slice):
new_node = self.subscript_slice(node)
if new_node is not None:
return new_node
elif isinstance(node.slice, ast.Index):
new_node = self.subscript_index(node)
if new_node is not None:
return new_node
def visit_Subscript(self, node):
super().generic_visit(node)
if (isinstance(node.value, ast.Name) and
node.value.id == "Out" and
isinstance(node.slice, ast.Index) and
isinstance(node.slice.value, ast.Name)):
return ast.copy_location(ast.Subscript(
value=ast.Name(id=node.value.id, ctx=node.value.ctx),
slice=ast.Index(value=ast.Str(s=node.slice.value.id)),
ctx=node.ctx), node)
return node
def subscript_to_tuple(subscript):
'''Convert a subscripted name of the form Name[(i1, ..., in)] to a
tuple ('Name', i1, ..., in).
'''
def err():
raise ValueError('Unexpected kind of slice: {}'.format(astunparse.unparse(subscript)))
# Get subscript name.
if isinstance(subscript.value, ast.Name):
name = subscript.value.id
else:
err()
# Get indices.
if isinstance(subscript.slice, ast.Index):
if isinstance(subscript.slice.value, ast.Num):
indices = [subscript.slice.value]
elif isinstance(subscript.slice.value, ast.Tuple):
indices = subscript.slice.value.elts
else:
err()
else:
err()
# Convert indices to python numbers.
int_indices = []
for i in indices:
if isinstance(i, ast.Num):
int_indices.append(i.n)
else:
err()
return tuple([name] + int_indices)
def extend_subscript_for_input(node, extension):
if isinstance(node.slice, ast.Index):
node = copy.deepcopy(node)
idx = node.slice.value
if isinstance(idx, ast.Tuple):
new_idx = ast.Tuple([extension] + idx.elts, ast.Load())
else:
new_idx = ast.Tuple([extension, idx], ast.Load())
node.slice.value = new_idx
else:
raise Exception("Unhandled node indexing: '%s'" % (unparse(node).rstrip()))
return node
def add_input_indices(root, input_vars, index_var):
class AddInputIndicesVisitor(ast.NodeTransformer):
def visit_Subscript(self, node):
if get_var_name(node) in input_vars:
return extend_subscript_for_input(node, index_var)
return node
def visit_Name(self, node):
if node.id in input_vars:
return ast.Subscript(node, ast.Index(index_var), node.ctx)
return node
vis = AddInputIndicesVisitor()
root = vis.visit(root)
return ast.fix_missing_locations(root)
def generate_io_stmt(input_idx, var_name, value, func_name):
if value is None:
return []
elif isinstance(value, list):
return [ast.Expr(
ast.Call(
ast.Attribute(
ast.Subscript(
ast.Name(var_name, ast.Load()),
ast.Index(
ast.Tuple([ast.Num(input_idx),
ast.Num(val_idx)],
ast.Load())),
ast.Load()),
func_name,
ast.Load()),
[ast.Num(val)],
[], None, None))
for val_idx, val in enumerate(value)
if val is not None]
else:
return [ast.Expr(
ast.Call(
ast.Attribute(
ast.Subscript(
ast.Name(var_name, ast.Load()),
ast.Index(ast.Num(input_idx)),
ast.Load()),
func_name,
ast.Load()),
[ast.Num(value)],
[], None, None))]
def get_index(subscript_node):
index_node = cast(subscript_node.slice, ast.Index)
return name_or_number(index_node.value)
def visit_Subscript(self, node):
func = None
if isinstance(node.value, ast.Call):
call = node.value
if isinstance(call.func, ast.Name):
func = call.func.id
elif isinstance(node.value.func, ast.Attribute):
func = call.func.attr
if func == 'mkstemp':
if isinstance(node.slice, ast.Index):
index = node.slice.value
if isinstance(index, ast.Num) and index.n == 1:
yield self.tag(node, 'mkstemp-file-descriptor-leak')
for t in self.generic_visit(node):
yield t
def __init__(self, operators=None, functions=None, names=None):
"""
Create the evaluator instance. Set up valid operators (+,-, etc)
functions (add, random, get_val, whatever) and names. """
if not operators:
operators = DEFAULT_OPERATORS
if not functions:
functions = DEFAULT_FUNCTIONS
if not names:
names = DEFAULT_NAMES
self.operators = operators
self.functions = functions
self.names = names
self.nodes = {
ast.Num: self._eval_num,
ast.Str: self._eval_str,
ast.Name: self._eval_name,
ast.UnaryOp: self._eval_unaryop,
ast.BinOp: self._eval_binop,
ast.BoolOp: self._eval_boolop,
ast.Compare: self._eval_compare,
ast.IfExp: self._eval_ifexp,
ast.Call: self._eval_call,
ast.keyword: self._eval_keyword,
ast.Subscript: self._eval_subscript,
ast.Attribute: self._eval_attribute,
ast.Index: self._eval_index,
ast.Slice: self._eval_slice,
}
# py3k stuff:
if hasattr(ast, 'NameConstant'):
self.nodes[ast.NameConstant] = self._eval_nameconstant
elif isinstance(self.names, dict) and "None" not in self.names:
self.names["None"] = None
def visit_Subscript(self, node):
pp = ProgramPoint(node.lineno, node.col_offset)
if isinstance(node.slice, ast.Index):
return IndexStmt(pp, self._ensure_stmt_visit(node.value, pp), self._ensure_stmt_visit(node.slice.value, pp))
elif isinstance(node.slice, ast.Slice):
return SliceStmt(pp, self._ensure_stmt_visit(node.value, pp),
self._ensure_stmt_visit(node.slice.lower, pp),
self._ensure_stmt_visit(node.slice.step, pp) if node.slice.step else None,
self._ensure_stmt_visit(node.slice.upper, pp))
else:
raise NotImplementedError(f"The statement {str(type(node.slice))} is not yet translatable to CFG!")
def infer_subscript(node, context, solver):
"""Infer expressions like: x[1], x["a"], x[1:2], x[1:].
Where x may be: a list, dict, tuple, str
Attributes:
node: the subscript node to be inferred
"""
indexed_type = infer(node.value, context, solver)
if isinstance(node.slice, ast.Index):
index_type = infer(node.slice.value, context, solver)
result_type = solver.new_z3_const("index")
solver.add(axioms.index(indexed_type, index_type, result_type, solver.z3_types),
fail_message="Indexing in line {}".format(node.lineno))
return result_type
else: # Slicing
# Some slicing may contain 'None' bounds, ex: a[1:], a[::]. Make Int the default type.
lower_type = upper_type = step_type = solver.z3_types.int
if node.slice.lower:
lower_type = infer(node.slice.lower, context, solver)
if node.slice.upper:
upper_type = infer(node.slice.upper, context, solver)
if node.slice.step:
step_type = infer(node.slice.step, context, solver)
result_type = solver.new_z3_const("slice")
solver.add(axioms.slicing(lower_type, upper_type, step_type, indexed_type, result_type, solver.z3_types),
fail_message="Slicing in line {}".format(node.lineno))
return result_type
def _build_subscript(value1, value2):
return Subscript(
value=value1,
slice=Index(value=value2),
ctx=Load())
def Subscript_default(t, x):
assert isinstance(x.slice, ast.Index)
v = x.slice.value
if isinstance(v, ast.UnaryOp) and isinstance(v.op, ast.USub):
return JSSubscript(
JSCall(JSAttribute(x.value, 'slice'), [v]),
JSNum(0))
return JSSubscript(x.value, v)
def handle_Subscript(state, node, ctx):
state, value_result = _peval_expression(state, node.value, ctx)
state, slice_result = _peval_expression(state, node.slice, ctx)
if is_known_value(value_result) and is_known_value(slice_result):
success, elem = try_call_method(
value_result.value, '__getitem__', args=(slice_result.value,))
if success:
return state, KnownValue(value=elem)
state, new_value = map_reify(state, value_result)
state, new_slice = map_reify(state, slice_result)
if type(new_slice) not in (ast.Index, ast.Slice, ast.ExtSlice):
new_slice = ast.Index(value=new_slice)
return state, replace_fields(node, value=new_value, slice=new_slice)
def init_idx(cls, idx):
if idx != ():
raise typy.TypeFormationError("Index of float_ type must be ().")
return idx
def syn_Subscript(self, ctx, e):
slice_ = e.slice
if not isinstance(slice_, ast.Index):
raise _errors.TyError("Must provide a single label.", slice_)
value = slice_.value
label = _read_label(value)
try:
ty = self.idx[label]
except KeyError:
raise _errors.TyError("Cannot project component labeled " + str(label), e)
value.label = label
return ty
def _labeled_translation(idx_mapping, arg_translation):
lambda_translation = ast.Lambda(
args=ast.arguments(
args=[ast.Name(id='x', ctx=ast.Param())],
vararg=None,
kwarg=None,
defaults=[]),
body=ast.Tuple(
elts=list(
ast.Subscript(
value=ast.Name(
id='x',
ctx=ast.Load()),
slice=ast.Index(
value=ast.Num(n=n)),
ctx=ast.Load())
for n in idx_mapping
),
ctx=ast.Load()
)
)
return ast.Call(
func=lambda_translation,
args=[arg_translation],
keywords=[],
starargs=[],
kwargs=None
)