def test_Subscript(self): sub = ast.Subscript(ast.Name('X', ast.Load()), [], ast.Load()) # Index slice1 = ast.Index(ast.Num(42)) sub.slice = slice1 self.verify(sub, 'X[42]') # Slice slice2 = ast.Slice(None, None, ast.Num(2)) sub.slice = slice2 self.verify(sub, 'X[::2]') # ExtSlice sub.slice = ast.ExtSlice([slice1, slice2]) self.verify(sub, 'X[42,::2]') # Issue #20 expect = ast.Expr(value=ast.Subscript( value=ast.BinOp(left=ast.Name(id='p', ctx=ast.Load()), op=ast.Add(), right=ast.List(elts=[ ast.Num(n=1), ast.Num(n=2), ast.Num(n=3), ast.Num(n=4) ], ctx=ast.Load())), slice=ast.Slice(lower=None, upper=ast.Num(n=4), step=None), ctx=ast.Load())) self.verify(expect, '(p+[1,2,3,4])[:4]')
def test_field_in_pattern_but_not_ast_no_match(self): ast_node = ast.Slice(lower=ast.Name(id="a")) pattern_node = ast.Slice(lower=ast.Name(id="a"), upper=ast.Name(id="b")) matches = anm.match(ast_node, pattern_node) assert not matches
def p_list_range(p): '''list : LBRACKET atom COMMA atom RANGE atom RBRACKET | LBRACKET atom RANGE atom RBRACKET''' if len(p) == 8: p[0] = ast.Subscript( None, ast.Slice(p[2], p[6], ast.BinOp(p[4], ast.Sub, p[2])), ast.Load()) else: p[0] = ast.Subscript(None, ast.Slice(p[2], p[4], ast.Num(1)), ast.Load())
def make_unconcat_slice(axis, lower, upper): dims = [] for i in range(axis): dims.append(ast.Slice(lower=None, upper=None, step=None)) dims.append(ast.Slice(lower=lower, upper=upper, step=None)) dims.append(ast.Ellipsis()) ext_slice = ast.ExtSlice(dims=dims) return ext_slice
def translateRange(n): if len(n.children) == 1: c = n.children[0] assert c.type == 'range2' if c.children[1] is None: return ast.Index(translateExpr(c.children[0])) return ast.Slice(translateExpr(c.children[0]), translateExpr(c.children[1]), None) return ast.Slice(ast.Num(9999), ast.Num(8888), None)
def 片(下限, 上限, 片段): return ast.Slice( lower=下限, upper=上限, step=None, lineno=语法树.取行号(片段), col_offset=语法树.取列号(片段))
def createAst(self, attrOfAst): if not self.closed: raise icon.IconExecException(self, "Unclosed temporary icon") if self.sites.indexIcon.att is None: if not self.hasSite('upperIcon'): raise icon.IconExecException(self, "Missing subscript") indexAst = None else: indexAst = self.sites.indexIcon.att.createAst() if self.hasSite('upperIcon'): if self.sites.upperIcon.att: upperAst = self.sites.upperIcon.att.createAst() else: upperAst = None if self.hasSite('stepIcon') and self.sites.stepIcon.att: stepAst = self.sites.stepIcon.att.createAst() else: stepAst = None slice = ast.Slice(indexAst, upperAst, stepAst) else: slice = ast.Index(value=indexAst) return icon.composeAttrAst( self, ast.Subscript(value=attrOfAst, slice=slice, lineno=self.id, col_offset=0, ctx=nameicons.determineCtx(self)))
def visit_Subscript(self, node): valid_slice = False s = node.slice # if the slice is a negative number, then convert it into a simpler form # so that it can be subsequently parsed the same way as positive numbers if hasattr(s, "value") and isinstance(s.value, ast.UnaryOp): if isinstance(s.value.op, ast.USub) and isinstance( s.value.operand, ast.Num): n = -s.value.operand.n if n != -1: raise Exception( f"Negative index `{n}` not supported. " "Only -1 supported, due to ak.pad_none() padding the end of an array." ) s = ast.Index(value=ast.Num(n)) for attr in ["value", "upper", "lower", "step"]: if isinstance(getattr(s, attr, None), (ast.Constant, ast.Num)): valid_slice = True if valid_slice: if hasattr(s, "value"): upper = s.value.n dimslice = ast.Constant(upper) self.nreducers += 1 elif hasattr(s, "upper"): upper = s.upper.n dimslice = s else: raise Exception(f"Slice node not supported: {s}") absupper = abs(upper) if upper >= 0: clip = True absupper = ast.Constant(absupper + 1) else: clip = False absupper = ast.Constant(absupper) value = ast.Call( func=ast.Name("ak.pad_none"), args=[node.value, absupper], keywords=[ast.keyword("clip", ast.Constant(clip))], ) node = ast.Subscript( value=value, slice=ast.ExtSlice(dims=[ ast.Slice(lower=None, upper=None, step=None), dimslice, ]), ctx=ast.Load(), ) # else: # # for when an index array is used as a slice # # currently will only work if that array has a None # # (https://github.com/scikit-hep/awkward-1.0/issues/708) # new_slice = ast.Call( # func=ast.Name("ak.singletons"), args=[node.slice], keywords=[], # ) # node = ast.Subscript(value=node.value, slice=new_slice, ctx=ast.Load()) self.generic_visit(node) return node
def generate_host_port_vars(service_name, default, var_prefix): """ Generate code for parsing service information from env. variables into two variables: {var_prefix}_HOST - containing the IP/Hostname {var_prefix}_PORT - containing the Port Note that this code currently skips the initial part of the content of the env. variable - either 'udp://' or 'tcp://', which, in terms of *service discovery* is just a noise. """ return ast.Assign( targets=[ ast.Tuple(elts=[ ast.Name(id=var_prefix + '_HOST'), ast.Name(id=var_prefix + '_PORT') ]) ], value=ast.Call(func=ast.Attribute(value=ast.Subscript( value=ast.Call(func=ast.Attribute(value=ast.Name(id='os'), attr='getenv'), args=[ast.Str(s=service_name), ast.Str(s=default)], keywords=[], starargs=None, kwargs=None), slice=ast.Slice(lower=ast.Num(n=6), upper=None, step=None)), attr='rsplit'), args=[ast.Str(s=':'), ast.Num(n=1)], keywords=[], starargs=None, kwargs=None))
def p_subscript(p): '''subscript : "." "." "." | test | ":" | test ":" | ":" test | test ":" test | ":" sliceop | test ":" sliceop | ":" test sliceop | test ":" test sliceop''' if len(p) == 2 and p.get_item(1).type == "test": p[0] = ast.Index(value=p[1], ctx=ast.Load(), lineno=p[1].lineno, col_offset=p[1].col_offset) elif len(p) == 2 and p[1] == ":": p[0] = ast.Slice(lower=None, upper=None, step=None, lineno=p.get_item(1).lineno, col_offset=p.get_item(1).lexpos) return
def _subscript(self, node: ET.Element): subscripts = self.transform_all_subnodes(node, ignored={'section-subscript'}) if not subscripts: assert node.attrib['type'] == 'empty' return ast.Slice(lower=None, upper=None, step=None) if len(subscripts) != 1: self.no_transform(node) assert node.attrib['type'] in ('simple', 'range') return subscripts[0]
def visit_NormalSlice(self, node: NormalSlice, *args, **kwargs) -> C.Slice: lower = self.visit(node.lower, *args, **kwargs) upper = self.visit(node.upper, *args, **kwargs) step = self.visit(node.step, *args, **kwargs) return C.Slice( lower=lower, upper=upper, step=step, )
def _slice_assign(self, start, end): result = self.run([ ast.Assign([ast_store('test')], ast.List([ast.Num(x) for x in range(10)], ast.Load())), ast.Assign([ ast.Subscript( ast_load('test'), ast.Slice(start and ast.Num(start), end and ast.Num(end), None), ast.Store()), ], ast.List([ast.Num(42), ast.Num(43)], ast.Load())), ], 'test', list) return result
def __getitem__(self, key: Union[int, str, slice]) -> 'Expr': key_ast: Union[ast.Index, ast.Slice] if isinstance(key, int): key_ast = ast.Index(ast.Num(n=key)) elif isinstance(key, str): key_ast = ast.Index(ast.Str(s=key)) elif isinstance(key, slice): key_ast = ast.Slice(key.start, key.stop, key.step) else: raise TypeError(f'expected int, str, or slice, got {type(key)}') subscript = ast.Subscript(value=self._expr, slice=key_ast) return Expr(subscript)
def visit_Name(self, node: ast.Name) -> Union[ast.Name, ast.Subscript]: if node.id not in self.__vars_mapper or node.id in self.__functions: return node else: n = self.__vars_mapper[node.id] return ast.Subscript( value=ast.Name(id=self.__name, ctx=ast.Load()), slice=ast.ExtSlice( dims=[ast.Slice(lower=None, upper=None, step=None), ast.Index(value=ast.Num(n=n))]), ctx=node.ctx )
def test_Slice(self): self.verify(ast.Slice(None, None, None), ':') self.verify(ast.Slice(ast.Num(42), None, None), '42:') self.verify(ast.Slice(None, ast.Num(42), None), ':42') self.verify(ast.Slice(None, None, ast.Num(42)), '::42') self.verify(ast.Slice(ast.Num(1), ast.Num(2), None), '1:2') self.verify(ast.Slice(ast.Num(1), None, ast.Num(2)), '1::2')
def p_cellarrayref(self, p): """ expr : expr LBRACE expr_list RBRACE | expr LBRACE RBRACE """ if len(p) == 4: p[0] = self._new_subscript(p, p[1], ast.Slice(None, None, None)) elif len(p[3]) == 1: p[0] = self._new_subscript(p, p[1], ast.Index(p[3][0])) else: p[0] = self._new_subscript(p, p[1], ast.ExtSlice([ ast.Index(i) if not isinstance(i, ast.Slice) else i for i in p[3] ]))
def test_assign_expr_slice(self): assert self.run([ ast.Assign([ast_store('test')], ast.List([ast.Num(x) for x in range(10)], ast.Load())), ast.FunctionDef('f_test', ast.arguments([], None, None, []), [ ast.Return(ast_load('test')), ], []), ast.Assign([ ast.Subscript(ast_call(ast_load('f_test')), ast.Slice(ast.Num(2), ast.Num(8), None), ast.Store()), ], ast.List([ast.Num(42), ast.Num(43)], ast.Load())), ], 'test', list) == [0, 1, 42, 43, 8, 9]
def visit_Name( self, node ): self.generic_visit( node ) if isinstance( node._object, slice ): if node._object.step: raise VerilogTranslationError( 'Slices with steps ([start:stop:step]) are not translatable!\n', node.lineno ) new_node = ast.Slice( ast.Num( node._object.start ), ast.Num( node._object.stop ), None ) return ast.copy_location( new_node, node ) return node
def mockResponseBuilder(self, mockName, methodName, target_start, target_end): return ast.Assign( targets=[ ast.Attribute(value=ast.Attribute(value=ast.Name(id=mockName), attr=methodName), attr='side_effect') ], value=ast.Call(func=ast.Name(id='sideEffectGenerator'), args=[ ast.Subscript( value=ast.Name(id='parameter_list'), slice=ast.Slice( lower=ast.Num(n=target_start), upper=ast.Num(n=target_end), step=None)), ast.Subscript(value=ast.Name(id='args'), slice=ast.Slice( lower=ast.Num(n=target_start), upper=ast.Num(n=target_end), step=None)) ], keywords=[]))
def test_slice(self): tree = ast.Module(body=[ ast.Assign(targets=[ast.Name(id='x', ctx=ast.Store())], value=ast.Call( func=ast.Name(id='f', ctx=ast.Load()), args=[ast.Slice(upper=ast.Constant(value=0))], keywords=[])) ], type_ignores=[]) def f(x): return x d = {"f": f} self._eval(tree, d) assert d['x'] == slice(None, 0, None)
def subscript_action(s, loc, tokens): if 'slice' in tokens: slice = tokens.slice start = slice.start if 'start' in slice else None stop = slice.stop if 'stop' in slice else None if 'step' in slice: step = slice.step[0] else: step = None return ast.Subscript(slice=ast.Slice(lower=start, upper=stop, step=step), ctx=ast.Load()) else: return ast.Subscript(slice=ast.Index(value=tokens[0]), ctx=ast.Load())
def compile_slice_expression(self, expr): expr.pop(0) # index val = self.compile(expr.pop(0)) # target low = None if expr != []: low = self.compile(expr.pop(0)) high = None if expr != []: high = self.compile(expr.pop(0)) return ast.Subscript(lineno=expr.start_line, col_offset=expr.start_column, value=val, slice=ast.Slice(lower=low, upper=high, step=None), ctx=ast.Load())
def visit_Attribute( self, node ): self.generic_visit( node ) if isinstance( node._object, _SignalSlice ): if node._object.slice.step: raise VerilogTranslationError( 'Slices with steps ([start:stop:step]) are not translatable!\n', node.lineno ) new_node = ast.Subscript( node.value, ast.Slice( ast.Num( node._object.slice.start ), ast.Num( node._object.slice.stop ), None ), None, ) new_node._object = node._object return ast.copy_location( new_node, node ) return node
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 visit_Slice(self, sl: ast.Slice) -> VisitSliceReturnT: actions = [] if sl.lower is None: lower_flattened = None else: lower_flattened, lower_actions = self.visit_expr(sl.lower) actions.extend(lower_actions) if sl.upper is None: upper_flattened = None else: upper_flattened, upper_actions = self.visit_expr(sl.upper) actions.extend(upper_actions) if sl.step is None: step_flattened = None else: step_flattened, step_actions = self.visit_expr(sl.step) actions.extend(step_actions) return ast.Slice(lower=lower_flattened, upper=upper_flattened, step=step_flattened), actions
def as_ast(dct): """See https://docs.python.org/2/library/ast.html""" if dct['ast_type'] == "Module": return ast.Module(dct["body"]) elif dct['ast_type'] == "Interactive": return ast.Interactive(dct["body"]) elif dct['ast_type'] == "Expression": return ast.Expression(dct["body"]) elif dct['ast_type'] == "Suite": return ast.Suite(dct["body"]) elif dct['ast_type'] == "FunctionDef": return ast.FunctionDef(dct["name"], dct["args"], dct["body"], dct["decorator_list"]) elif dct['ast_type'] == "ClassDef": return ast.ClassDef(dct["name"], dct["bases"], dct["body"], dct["decorator_list"]) elif dct['ast_type'] == "Return": return ast.Return(dct["value"]) elif dct['ast_type'] == "Delete": return ast.Delete(dct["targets"]) elif dct['ast_type'] == "Assign": return ast.Assign(dct["targets"], dct["value"]) elif dct['ast_type'] == "AugAssign": return ast.AugAssign(dct["target"], dct["op"], dct["value"]) elif dct['ast_type'] == "Print": return ast.Print(dct["dest"], dct["values"], dct["nl"]) elif dct['ast_type'] == "For": return ast.For(dct["target"], dct["iter"], dct["body"], dct["orelse"]) elif dct['ast_type'] == "While": return ast.While(dct["test"], dct["body"], dct["orelse"]) elif dct['ast_type'] == "If": return ast.If(dct["test"], dct["body"], dct["orelse"]) elif dct['ast_type'] == "With": return ast.With(dct["context_expr"], dct["optional_vars"], dct["body"]) elif dct['ast_type'] == "Raise": return ast.Raise(dct["type"], dct["inst"], dct["tback"]) elif dct['ast_type'] == "TryExcept": return ast.TryExcept(dct["body"], dct["handlers"], dct["orelse"]) elif dct['ast_type'] == "TryFinally": return ast.TryFinally(dct["body"], dct["finalbody"]) elif dct['ast_type'] == "Assert": return ast.Assert(dct["test"], dct["msg"]) elif dct['ast_type'] == "Import": return ast.Import(dct["names"]) elif dct['ast_type'] == "ImportFrom": return ast.ImportFrom(dct["module"], dct["names"], dct["level"]) elif dct['ast_type'] == "Exec": return ast.Exec(dct["body"], dct["globals"], dct["locals"]) elif dct['ast_type'] == "Global": return ast.Global(dct["names"]) elif dct['ast_type'] == "Expr": return ast.Expr(dct["value"]) elif dct['ast_type'] == "Pass": return ast.Pass() elif dct['ast_type'] == "Break": return ast.Break() elif dct['ast_type'] == "Continue": return ast.Continue() elif dct['ast_type'] == "BoolOp": return ast.BoolOp(dct["op"], dct["values"]) elif dct['ast_type'] == "BinOp": return ast.BinOp(dct["left"], dct["op"], dct["right"]) elif dct['ast_type'] == "UnaryOp": return ast.UnaryOp(dct["op"], dct["operand"]) elif dct['ast_type'] == "Lambda": return ast.Lambda(dct["args"], dct["body"]) elif dct['ast_type'] == "IfExp": return ast.IfExp(dct["test"], dct["body"], dct["orelse"]) elif dct['ast_type'] == "Dict": return ast.Dict(dct["keys"], dct["values"]) elif dct['ast_type'] == "Set": return ast.Set(dct["elts"]) elif dct['ast_type'] == "ListComp": return ast.ListComp(dct["elt"], dct["generators"]) elif dct['ast_type'] == "SetComp": return ast.SetComp(dct["elt"], dct["generators"]) elif dct['ast_type'] == "DictComp": return ast.DictComp(dct["key"], dct["value"], dct["generators"]) elif dct['ast_type'] == "GeneratorExp": return ast.GeneratorExp(dct["elt"], dct["generators"]) elif dct['ast_type'] == "Yield": return ast.Yield(dct["value"]) elif dct['ast_type'] == "Compare": return ast.Compare(dct["left"], dct["ops"], dct["comparators"]) elif dct['ast_type'] == "Call": return ast.Call(dct["func"], dct["args"], dct["keywords"], dct["starargs"], dct["kwargs"]) elif dct['ast_type'] == "Repr": return ast.Repr(dct["value"]) elif dct['ast_type'] == "Num": return ast.Num(dct["n"]) elif dct['ast_type'] == "Str": # Converting to ASCII return ast.Str(dct["s"].encode('ascii', 'ignore')) elif dct['ast_type'] == "Attribute": return ast.Attribute(dct["value"], dct["attr"], dct["ctx"]) elif dct['ast_type'] == "Subscript": return ast.Subscript(dct["value"], dct["slice"], dct["ctx"]) elif dct['ast_type'] == "Name": return ast.Name(dct["id"], dct["ctx"]) elif dct['ast_type'] == "List": return ast.List(dct["elts"], dct["ctx"]) elif dct['ast_type'] == "Tuple": return ast.Tuple(dct["elts"], dct["ctx"]) elif dct['ast_type'] == "Load": return ast.Load() elif dct['ast_type'] == "Store": return ast.Store() elif dct['ast_type'] == "Del": return ast.Del() elif dct['ast_type'] == "AugLoad": return ast.AugLoad() elif dct['ast_type'] == "AugStore": return ast.AugStore() elif dct['ast_type'] == "Param": return ast.Param() elif dct['ast_type'] == "Ellipsis": return ast.Ellipsis() elif dct['ast_type'] == "Slice": return ast.Slice(dct["lower"], dct["upper"], dct["step"]) elif dct['ast_type'] == "ExtSlice": return ast.ExtSlice(dct["dims"]) elif dct['ast_type'] == "Index": return ast.Index(dct["value"]) elif dct['ast_type'] == "And": return ast.And() elif dct['ast_type'] == "Or": return ast.Or() elif dct['ast_type'] == "Add": return ast.Add() elif dct['ast_type'] == "Sub": return ast.Sub() elif dct['ast_type'] == "Mult": return ast.Mult() elif dct['ast_type'] == "Div": return ast.Div() elif dct['ast_type'] == "Mod": return ast.Mod() elif dct['ast_type'] == "Pow": return ast.Pow() elif dct['ast_type'] == "LShift": return ast.LShift() elif dct['ast_type'] == "RShift": return ast.RShift() elif dct['ast_type'] == "BitOr": return ast.BitOr() elif dct['ast_type'] == "BitXor": return ast.BitXor() elif dct['ast_type'] == "BitAnd": return ast.BitAnd() elif dct['ast_type'] == "FloorDiv": return ast.FloorDiv() elif dct['ast_type'] == "Invert": return ast.Invert() elif dct['ast_type'] == "Not": return ast.Not() elif dct['ast_type'] == "UAdd": return ast.UAdd() elif dct['ast_type'] == "USub": return ast.USub() elif dct['ast_type'] == "Eq": return ast.Eq() elif dct['ast_type'] == "NotEq": return ast.NotEq() elif dct['ast_type'] == "Lt": return ast.Lt() elif dct['ast_type'] == "LtE": return ast.LtE() elif dct['ast_type'] == "Gt": return ast.Gt() elif dct['ast_type'] == "GtE": return ast.GtE() elif dct['ast_type'] == "Is": return ast.Is() elif dct['ast_type'] == "IsNot": return ast.IsNot() elif dct['ast_type'] == "In": return ast.In() elif dct['ast_type'] == "NotIn": return ast.NotIn() elif dct['ast_type'] == "comprehension": return ast.comprehension(dct["target"], dct["iter"], dct["ifs"]) elif dct['ast_type'] == "ExceptHandler": return ast.ExceptHandler(dct["type"], dct["name"], dct["body"]) elif dct['ast_type'] == "arguments": return ast.arguments(dct["args"], dct["vararg"], dct["kwarg"], dct["defaults"]) elif dct['ast_type'] == "keyword": return ast.keyword(dct["arg"], dct["value"]) elif dct['ast_type'] == "alias": return ast.alias(dct["name"], dct["asname"]) else: return dct
def visit_Subscript(self, node: ast.Subscript) -> ast.AST: """Subscript slice operations.g. x[1:] or y[::2]""" self.generic_visit(node) log_header = f"visit_Subscript: {self.src_file}:" idx = None # Subscripts have slice properties with col/lineno, slice itself does not have line/col # Index is also a valid Subscript slice property slice = node.slice if not isinstance(slice, ast.Slice): LOGGER.debug("%s (%s, %s): not a slice node.", log_header, node.lineno, node.col_offset) return node # Built "on the fly" based on the various conditions for operation types # The RangeChange options are added in the later if/else cases slice_mutations: Dict[str, ast.Slice] = { "Slice_UnboundUpper": ast.Slice(lower=slice.upper, upper=None, step=slice.step), "Slice_UnboundLower": ast.Slice(lower=None, upper=slice.lower, step=slice.step), "Slice_Unbounded": ast.Slice(lower=None, upper=None, step=slice.step), } # Unbounded Swap Operation # upper slice range e.g. x[:2] will become x[2:] if slice.lower is None and slice.upper is not None: idx = LocIndex("Slice_Swap", node.lineno, node.col_offset, "Slice_UnboundLower") self.locs.add(idx) # lower slice range e.g. x[1:] will become x[:1] if slice.upper is None and slice.lower is not None: idx = LocIndex("Slice_Swap", node.lineno, node.col_offset, "Slice_UnboundUpper") self.locs.add(idx) # Range Change Operation # range upper bound move towards zero from absolute value e.g. x[2,4] becomes x[2,3] # and x[-4, -3] becomes x[-4, -2]. # More likely to generate useful mutants in the positive case. if slice.lower is not None and slice.upper is not None: if isinstance(slice.upper, ast.Num): idx = LocIndex("Slice_RangeChange", node.lineno, node.col_offset, "Slice_UPosToZero") slice_mutations["Slice_UPosToZero"] = ast.Slice( lower=slice.lower, upper=ast.Num(n=slice.upper.n - 1), step=slice.step) LOGGER.debug("RangeChange UPosToZero: %s", ast.dump(slice_mutations["Slice_UPosToZero"])) self.locs.add(idx) if isinstance(slice.upper, ast.UnaryOp): idx = LocIndex("Slice_RangeChange", node.lineno, node.col_offset, "Slice_UNegToZero") slice_mutations["Slice_UNegToZero"] = ast.Slice( lower=slice.lower, upper=ast.UnaryOp( op=ast.USub(), operand=ast.Num(n=slice.upper.operand.n - 1) # type: ignore ), step=slice.step, ) LOGGER.debug("RangeChange UNegToZero: %s", ast.dump(slice_mutations["Slice_UNegToZero"])) self.locs.add(idx) # Apply Mutation if idx == self.target_idx and not self.readonly: LOGGER.debug("%s mutating idx: %s with %s", log_header, self.target_idx, self.mutation) mutation = slice_mutations[str(self.mutation)] # uses AST.fix_missing_locations since the values of ast.Num and ast.UnaryOp also need # lineno and col-offset values. This is a recursive fix. return ast.fix_missing_locations( ast.copy_location( ast.Subscript(value=node.value, slice=mutation, ctx=node.ctx), node)) LOGGER.debug("%s (%s, %s): no mutations applied.", log_header, node.lineno, node.col_offset) return node
class HaskellASTVisitor(ast.NodeVisitor): _globalVariables = { 'fst': ast.FunctionDef( 'fst', [ast.Name('l', ast.Store())], ast.Subscript(ast.Name('l', ast.Load()), ast.Index(ast.Num(0)), ast.Load()), None), 'snd': ast.FunctionDef( 'snd', [ast.Name('l', ast.Store())], ast.Subscript(ast.Name('l', ast.Load()), ast.Index(ast.Num(1)), ast.Load()), None), 'take': ast.FunctionDef( 'take', [ast.Name('n', ast.Store()), ast.Name('l', ast.Store())], ast.Subscript(ast.Name('l', ast.Load()), ast.Slice(None, ast.Name('n', ast.Load), None), ast.Load()), None), 'drop': ast.FunctionDef( 'drop', [ast.Name('n', ast.Store()), ast.Name('l', ast.Store())], ast.Subscript(ast.Name('l', ast.Load()), ast.Slice(ast.Name('n', ast.Load), None, None), ast.Load()), None), 'reverse': ast.FunctionDef( 'reverse', [ast.Name('l', ast.Store())], ast.Subscript(ast.Name('l', ast.Load()), ast.Slice(None, None, ast.Num(-1)), ast.Load()), None), 'init': ast.FunctionDef( 'init', [ast.Name('l', ast.Store())], ast.Subscript(ast.Name('l', ast.Load()), ast.Slice(None, ast.Num(-1), None), ast.Load()), None), 'tail': ast.FunctionDef( 'tail', [ast.Name('l', ast.Store())], ast.Subscript(ast.Name('l', ast.Load()), ast.Slice(ast.Num(1), None, None), ast.Load()), None), 'last': ast.FunctionDef( 'last', [ast.Name('l', ast.Store())], ast.Subscript(ast.Name('l', ast.Load()), ast.Index(ast.Num(-1)), ast.Load()), None), 'head': ast.FunctionDef( 'head', [ast.Name('l', ast.Store())], ast.Subscript(ast.Name('l', ast.Load()), ast.Index(ast.Num(0)), ast.Load()), None), 'length': ast.FunctionDef( 'length', [ast.Name('l', ast.Store())], ast.Attribute(ast.Name('l', ast.Load()), '!length', ast.Load()), None), 'null': ast.FunctionDef( 'null', [ast.Name('l', ast.Store())], ast.Compare(ast.Name('l', ast.Load()), [ast.Eq], [ast.List([], ast.Store())]), None), 'replicate': ast.FunctionDef( 'replicate', [ast.Name('n', ast.Store()), ast.Name('l', ast.Store())], ast.BinOp(ast.List([ast.Name('l', ast.Load())], ast.Store()), ast.Mult, ast.Name('n', ast.Load())), None), 'cycle': ast.FunctionDef( 'cycle', [ast.Name('l', ast.Store())], ast.List(LoopedList(ast.Name('l', ast.Load())), ast.Store()), None), 'repeat': ast.FunctionDef( 'repeat', [ast.Name('l', ast.Store())], ast.List(LoopedList([ast.Name('l', ast.Load())]), ast.Store()), None), } _funVariablesStack = [] def generic_visit(self, node): return node def visit_Assign(self, node): result = self.visit(node.value) self._globalVariables[node.targets.id] = result return result def visit_Name(self, node): name = None try: name = self._funVariablesStack[0][node.id] except IndexError: name = self._globalVariables.get(node.id, None) except KeyError: name = self._globalVariables.get(node.id, None) return name def visit_BinOp(self, node): operator = node.op result = None if operator == ast.Add: result = self.visit(node.left) + self.visit(node.right) elif operator == ast.Sub: if isinstance(node.left, str): result = ord(self.visit(node.left)) - ord( self.visit(node.right)) else: result = self.visit(node.left) - self.visit(node.right) elif operator == ast.Div: result = self.visit(node.left) / self.visit(node.right) elif operator == ast.Mult: result = self.visit(node.left) * self.visit(node.right) return result def visit_Num(self, node): return self.visit(node.n) if not isinstance(node.n, int) else node.n def visit_BoolOp(self, node): if len(node.values) < 1: return None if node.op == None: return node.values[0] elif node.op == ast.And: return self.visit(node.values[0]) and self.visit(node.values[1]) elif node.op == ast.Or: return self.visit(node.values[0]) or self.visit(node.values[1]) elif node.op == ast.Not: return not self.visit(node.values[0]) def visit_Compare(self, node): operator = node.ops[0] left = self.visit(node.left) right = self.visit(node.comparators[0]) if operator == ast.Gt: return left > right elif operator == ast.GtE: return left >= right elif operator == ast.Lt: return left < right elif operator == ast.LtE: return left <= right elif operator == ast.Eq: return left == right elif operator == ast.NotEq: return left != right def visit_FunctionDef(self, node): if node.name.id in (self._globalVariables.keys() + self._globalVariables.keys()): print "Name already in use" return None self._globalVariables[node.name.id] = node return node.name.id def visit_Call(self, node): fun = self.visit(node.func) parameters = map(lambda x: self.visit(x), node.args) args = map(lambda x: x.id, fun.args) self._funVariablesStack.insert(0, dict(zip(args, parameters))) retval = self.visit(fun.body) self._funVariablesStack.pop(0) return retval def visit_Tuple(self, node): return tuple(map(lambda x: self.visit(x), node.elts)) def visit_List(self, node): if isinstance(node.elts, LoopedList): return LoopedList([self.visit(x) for x in self.visit(node.elts.l)], [self.visit(x) for x in self.visit(node.elts.h)]) else: return map(lambda x: self.visit(x), node.elts) def visit_Subscript(self, node): if node.value is None: (lower, upper, step) = self.visit(node.slice) if isinstance(lower, str): lower = ord(lower) upper = ord(upper) return map(lambda x: chr(x), range(lower, upper + 1, step)) else: return range(lower, upper + 1, step) if isinstance(node.slice, ast.Index): return self.visit(node.value)[self.visit(node.slice)] if isinstance(node.slice, ast.Slice): (lower, upper, step) = self.visit(node.slice) return self.visit(node.value)[lower:upper:step] def visit_Index(self, node): return self.visit(node.value) def visit_If(self, node): if self.visit(node.test): return self.visit(node.body) else: return self.visit(node.orelse) def visit_Slice(self, node): lower = self.visit(node.lower) upper = self.visit(node.upper) step = self.visit(node.step) return [lower, upper, step] def visit_Attribute(self, node): if node.attr == '!length': return len(self.visit(node.value))
def test_ExtSlice(self): slice1 = ast.Index(ast.Num(42)) slice2 = ast.Slice(None, None, ast.Num(6)) self.verify(ast.ExtSlice([slice1, slice2]), '42,::6')