├── .gitignore ├── README.md ├── examples ├── dnf ├── dnff ├── eval ├── fib ├── foo ├── fusion ├── ifelse ├── lambda ├── let ├── lists ├── peano └── ski ├── rewrite ├── __init__.py ├── _alex.py ├── _ayacc.py ├── astnodes.py ├── aterm.asdl ├── dsl │ ├── __init__.py │ ├── _dlex.py │ ├── _dyacc.py │ ├── cli.py │ ├── combinators.py │ ├── parse.py │ └── toplevel.py ├── matching.py ├── parse.py ├── plyhacks.py ├── prelude ├── pyast │ ├── Makefile │ ├── Python-ast.h │ ├── Python.asdl │ ├── asdl.py │ ├── asdl_c.py │ ├── ast_utils.py │ ├── nodes.py │ └── spark.py ├── pysdf │ └── Python.sdf ├── terms.py └── tests │ ├── test_dsl.py │ ├── test_free.py │ └── test_parse.py ├── run ├── sample ├── setup.py └── web ├── .gitignore ├── css ├── bootstrap-2.1.0.css ├── bootstrap-2.1.0.min.css ├── bootstrap-responsive-2.1.0.css ├── bootstrap-responsive-2.1.0.min.css └── style.css ├── img ├── glyphicons-halflings-white.png ├── glyphicons-halflings.png ├── glyphicons-white.png └── glyphicons.png ├── index.html └── js └── lib ├── bootstrap-2.1.0.js ├── bootstrap-2.1.0.min.js └── jquery-1.8.0.min.js /.gitignore: -------------------------------------------------------------------------------- 1 | *.sw[po] 2 | *.pyc 3 | 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | pyrewrite 2 | --------- 3 | 4 | Pyrewrite aims to be a micro term rewrite library written in pure Python. 5 | 6 | Pyrewrite has no dependencies other than the Python standard library. 7 | 8 | The broad goal of this project is to build a declarative rewrite engine 9 | in which domain experts and algorithm programmers can collaborate to 10 | develop transformation passses on Blaze expressions at a higher level, 11 | with the end goal being to inform more performant computations and 12 | scheduling. 13 | 14 | Also because Python doesn't have a good term rewriting engine and this 15 | is an essential part to building a vibrant compiler infastructure around 16 | CPython. 17 | 18 | Theory 19 | ------ 20 | 21 | Term rewriting is the procedure for manipulating abstract system 22 | of symbols where the objects are terms, or expressions with nested 23 | sub-expressions. 24 | 25 | The term structure in such a system is usually presented using a 26 | grammar. In contrast to string rewriting systems, whose objects are flat 27 | sequences of symbols, the objects of a term rewriting system form a term 28 | algebra, which can be visualized as a tree of symbols, the structure of 29 | the tree fixed by the signature used to define the terms. 30 | 31 | ``` 32 | t : bt -- basic term 33 | | bt {ty,m1,...} -- annotated term 34 | 35 | bt : C -- constant 36 | | C(t1,...,tn) -- n-ary constructor 37 | | (t1,...,tn) -- n-ary tuple 38 | | [t1,...,tn] -- list 39 | | "ccc" -- quoted string ( explicit double quotes ) 40 | | int -- integer 41 | | real -- floating point number 42 | ``` 43 | 44 | A rewrite rule has the form ``L : l -> r``, where L is the label of the 45 | rule, and the term patterns ``l`` and ``r`` left hand matcher and ``r`` 46 | the right hand builder. 47 | 48 | **Match** and **Build** 49 | 50 | The specification of a rewrite rule system consists of two actions 51 | *matching* and *building*. Matching deconstructs terms into into a 52 | environment object with term objects bound to identifiers in the 53 | context based on deconstruction pattern. 54 | 55 | Building is the dual notation to matching, it constructs term 56 | terms from environments of bindings based a construction pattern. 57 | 58 | **Blocks** 59 | 60 | ``` 61 | E : Impl(x, y) -> Or(Not(x), y) 62 | E : Eq(x, y) -> And(Impl(x, y), Impl(y, x)) 63 | 64 | E : Not(Not(x)) -> x 65 | 66 | E : Not(And(x, y)) -> Or(Not(x), Not(y)) 67 | E : Not(Or(x, y)) -> And(Not(x), Not(y)) 68 | 69 | E : And(Or(x, y), z) -> Or(And(x, z), And(y, z)) 70 | E : And(z, Or(x, y)) -> Or(And(z, x), And(z, y)) 71 | 72 | dnf = repeat(topdown(E) <+ id) 73 | ``` 74 | 75 | Compiles into a rewrite environement with the following 76 | signature: 77 | 78 | ``` 79 | {'E': [ 80 | Impl(, ) => Or(Not(), ) :: 81 | ['x', 'y'] -> ['x', 'y'] 82 | Eq(, ) => And(Impl(, ), Impl(, )) :: 83 | ['x', 'y'] -> ['x', 'y', 'y', 'x'] 84 | Not(Not()) => :: 85 | ['x'] -> ['x'] 86 | Not(And(, )) => Or(Not(), Not()) :: 87 | ['x', 'y'] -> ['x', 'y'] 88 | Not(Or(, )) => And(Not(), Not()) :: 89 | ['x', 'y'] -> ['x', 'y'] 90 | And(Or(, ), ) => Or(And(, ), And(, )) :: 91 | ['x', 'y', 'z'] -> ['x', 'z', 'y', 'z'] 92 | And(, Or(, )) => Or(And(, ), And(, )) :: 93 | ['z', 'x', 'y'] -> ['z', 'x', 'z', 'y'] 94 | ] 95 | , 96 | 'dnf': Repeat(Choice(Topdown(E),function))} 97 | ``` 98 | 99 | **Strategies** 100 | 101 | The application of rules can be a *Normalization* if it is the 102 | exhaustive application of rules. The ``eval`` rule above is normalizing. 103 | 104 | A *normal form* for an expression is a expression where no 105 | subterm can be rewritten. 106 | 107 | ``` 108 | all(s) Apply parameter strategy s to each direct subterm 109 | rec(s) 110 | 111 | s1;s2 Sequential composition 112 | s1<+s2 Deterministic choice first try s1, s2 if fail 113 | s1 B() 134 | foo : B() -> A() 135 | 136 | rule : repeat(foo) 137 | ``` 138 | 139 | A term rewrite system is said to *confluent* when given multiple 140 | possibilities of rule application, all permutations of application 141 | lead to the same result regardless of order. The general problem 142 | of determining whether a term-rewrite system is confluent is very 143 | difficult. 144 | 145 | **Nonlinear Patterns** 146 | 147 | This pattern of this form will match only if all occurrences of the same 148 | variable in the left-hand side pattern bind to the same value. 149 | 150 | ``` 151 | foo: f(x,x) -> x 152 | ``` 153 | 154 | The above matches ``f(1,1)`` but not ``f(1,2)``. 155 | 156 | This behavior differs from Haskell and is is to my knowledge only found 157 | in the Pure programming language. 158 | 159 | **As-Patterns** 160 | 161 | **Recursion** 162 | 163 | Examples 164 | ------- 165 | 166 | **ASDL** 167 | 168 | The Zephyr Abstract Syntax Description Lanuguage (ASDL) is a description 169 | language designed to describe the tree-like data structures in 170 | compilers. Specically it underpins the parser of Python itself ( 171 | see ``Parser/Python.asdl`` ). 172 | 173 | ```cpp 174 | module Python 175 | { 176 | 177 | stmt = FunctionDef(identifier name, arguments args, 178 | | For(expr target, expr iter, stmt* body, stmt* orelse) 179 | | While(expr test, stmt* body, stmt* orelse) 180 | | If(expr test, stmt* body, stmt* orelse) 181 | | With(expr context_expr, expr? optional_vars, stmt* body) 182 | 183 | } 184 | ``` 185 | 186 | **Blaze** 187 | 188 | TODO 189 | 190 | Credits 191 | ------- 192 | 193 | - [StrategoXT](http://strategoxt.org/) project. 194 | 195 | - [Basil project](https://code.google.com/p/basil/) by Jon Riehl 196 | 197 | - [PLT Scheme](http://download.plt-scheme.org/doc/360/html/mzlib/mzlib-Z-H-25.html#node_chap_25) 198 | 199 | - Pure and the paper and "Left-to-right tree pattern matching" by Albert Gräf 200 | 201 | License 202 | ------- 203 | 204 | Copyright (c) 2012, Continuum Analytics, Inc. 205 | All rights reserved. 206 | 207 | Redistribution and use in source and binary forms, with or without 208 | modification, are permitted provided that the following conditions are 209 | met: 210 | 211 | Redistributions of source code must retain the above copyright notice, 212 | this list of conditions and the following disclaimer. 213 | 214 | Redistributions in binary form must reproduce the above copyright 215 | notice, this list of conditions and the following disclaimer in the 216 | documentation and/or other materials provided with the distribution. 217 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 218 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 219 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 220 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 221 | HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 222 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 223 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 224 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 225 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 226 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 227 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 228 | -------------------------------------------------------------------------------- /examples/dnf: -------------------------------------------------------------------------------- 1 | E : Impl(x, y) -> Or(Not(x), y) 2 | E : Eq(x, y) -> And(Impl(x, y), Impl(y, x)) 3 | 4 | E : Not(Not(x)) -> x 5 | 6 | E : Not(And(x, y)) -> Or(Not(x), Not(y)) 7 | E : Not(Or(x, y)) -> And(Not(x), Not(y)) 8 | 9 | E : And(Or(x, y), z) -> Or(And(x, z), And(y, z)) 10 | E : And(z, Or(x, y)) -> Or(And(z, x), And(z, y)) 11 | 12 | dnf = repeat(topdown(E) <+ id) 13 | -------------------------------------------------------------------------------- /examples/dnff: -------------------------------------------------------------------------------- 1 | E : Dnf(Atom(x)) -> Atom(x) 2 | E : Dnf(Not(x)) -> DnfR(Not(Dnf(x))) 3 | E : Dnf(And(x, y)) -> DnfR(And(Dnf(x), Dnf(y))) 4 | E : Dnf(Or(x, y)) -> Or(Dnf(x), Dnf(y)) 5 | E : Dnf(Impl(x, y)) -> Dnf(Or(Not(x), y)) 6 | E : Dnf(Eq(x, y)) -> Dnf(And(Impl(x, y), Impl(y, x))) 7 | 8 | E : DnfR(Not(Not(x))) -> x 9 | E : DnfR(Not(And(x, y))) -> Or(Dnf(Not(x)), Dnf(Not(y))) 10 | E : DnfR(Not(Or(x, y))) -> Dnf(And(Not(x), Not(y))) 11 | D : DnfR(Not(x)) -> Not(x) 12 | 13 | E : DnfR(And(Or(x, y), z)) -> Or(Dnf(And(x, z)), Dnf(And(y, z))) 14 | E : DnfR(And(z, Or(x, y))) -> Or(Dnf(And(z, x)), Dnf(And(z, y))) 15 | D : DnfR(And(x, y)) -> And(x, y) 16 | 17 | dnf = innermost(E <+ D) 18 | -------------------------------------------------------------------------------- /examples/eval: -------------------------------------------------------------------------------- 1 | Eval : Not(True) -> False 2 | Eval : Not(False) -> True 3 | Eval : And(True, x) -> x 4 | Eval : And(x, True) -> x 5 | Eval : And(False, x) -> False 6 | Eval : And(x, False) -> False 7 | Eval : Or(True, x) -> True 8 | Eval : Or(x, True) -> True 9 | Eval : Or(False, x) -> x 10 | Eval : Or(x, False) -> x 11 | Eval : Impl(True, x) -> x 12 | Eval : Impl(x, True) -> True 13 | Eval : Impl(False, x) -> True 14 | Eval : Eq(False, x) -> Not(x) 15 | Eval : Eq(x, False) -> Not(x) 16 | Eval : Eq(True, x) -> x 17 | Eval : Eq(x, True) -> x 18 | 19 | eval = bottomup(repeat(Eval)) 20 | -------------------------------------------------------------------------------- /examples/fib: -------------------------------------------------------------------------------- 1 | fib: f(0) -> 1 2 | fib: f(1) -> 1 3 | fib: f(n) -> f(a) + f(b) where { a = n-1; b = n-2 } 4 | 5 | fibonacci = repeat fib 6 | -------------------------------------------------------------------------------- /examples/foo: -------------------------------------------------------------------------------- 1 | foo : A() -> B() 2 | foo : B() -> A() 3 | 4 | bar : Succ(0) -> 1 5 | bar : Succ(1) -> 2 6 | bar : Succ(x) -> Succ(Succ(x)) 7 | 8 | both : f(x,x) -> 1 9 | both : f(x,y) -> 0 10 | 11 | a0 = foo ; foo 12 | a1 = foo ; foo ; foo 13 | a2 = foo <+ foo ; foo 14 | -------------------------------------------------------------------------------- /examples/fusion: -------------------------------------------------------------------------------- 1 | # both(f,g) = lambda x: f(x) && g(x) 2 | # compose(f,g) = lambda x: f(g(x)) 3 | 4 | fuse: map(f, concat(x,y)) -> 5 | concat(map(f,x), map(f,y)) 6 | 7 | fuse: map(f, map(g, xs)) -> 8 | map(compose(f,g), xs) 9 | 10 | fuse: filter(f, filter(g, xs)) -> 11 | filter(both(f,g), xs) 12 | 13 | fuse: map(f, zipwith(g, xs, ys)) -> 14 | zipwith(compose(f,g),xs,ys) 15 | 16 | fuse: zipwith(f, map(g, xs), map(g, ys)) -> 17 | zipwith(compose(f,g), xs, ys) 18 | -------------------------------------------------------------------------------- /examples/ifelse: -------------------------------------------------------------------------------- 1 | EvalIf : 2 | If(False(), e1, e2) -> e2 3 | 4 | EvalIf : 5 | If(True(), e1, e2) -> e1 6 | 7 | PropIf : 8 | If(B,@F(X),@F(Y)) -> F(If(B,X,Y)) 9 | -------------------------------------------------------------------------------- /examples/lambda: -------------------------------------------------------------------------------- 1 | Beta : 2 | App(Lam(x, e1), e2) -> Let(x, e2, e1) 3 | 4 | Eta : 5 | App(Lam(x, App(Lam(y, x), x), e2)) -> y 6 | 7 | Inline : 8 | Let(x, e1, e2[Var(x)]) -> Let(x, e1, e2[e1]) 9 | -------------------------------------------------------------------------------- /examples/let: -------------------------------------------------------------------------------- 1 | lfold: Let(x, Let(y, e1, e2), e3) -> Let(y, e1, Let(x, e2, e3)) 2 | -------------------------------------------------------------------------------- /examples/lists: -------------------------------------------------------------------------------- 1 | bar: (1, 2, 2) -> (2, 1, 1) 2 | bar: (1, 2, 3) -> (1, 2, 3) 3 | 4 | fizz: [1, 2] -> [2, 1] 5 | fizz: 42 -> 24 6 | fizz: ([], "glorp", 8) -> ("glorp", 8, []) 7 | -------------------------------------------------------------------------------- /examples/peano: -------------------------------------------------------------------------------- 1 | iszero: Zero() -> 1 2 | iszero: Succ(x) -> 0 3 | 4 | a0: add(Zero(),y) -> y 5 | a0: add(Succ(x),y) -> Succ(add(x,y)) 6 | 7 | m0: mul(Zero(),x) -> Zero() 8 | m0: mul(x,Zero()) -> Zero() 9 | m0: mul(Succ(x),y) -> add(y,(mul(x,y))) 10 | 11 | int: Zero() -> 0 12 | int: Succ(x) -> fix toIntegral(x) 13 | 14 | base: Zero -> 0 15 | succ1: Succ(0) -> 1 16 | succ2: Succ(Const(v)) -> Const(nv) where {nv = v + 1} 17 | -------------------------------------------------------------------------------- /examples/ski: -------------------------------------------------------------------------------- 1 | d1: I(x) -> x 2 | d1: K(x,y) -> x 3 | d1: S(x,y,z) -> x(z)(y(z)) 4 | d1: B(x,y,z) -> x(y(z)) 5 | d1: C(x,y,z) -> (x(z))(y) 6 | d1: T(x,y) -> x 7 | d1: F(x,y) -> y 8 | d1: W(x) -> x(x) 9 | 10 | d2: C(@x(y,z)) = @x(z,y) 11 | 12 | ski: S((K(x)),(K(y))) -> K(x(y)) 13 | ski: S((K(x)),(I(y))) -> x 14 | ski: S(K(x)),y) -> B(x,y) 15 | ski: S(x,(K y)) -> C(x,y) 16 | 17 | skir = repeat ski 18 | -------------------------------------------------------------------------------- /rewrite/__init__.py: -------------------------------------------------------------------------------- 1 | from parse import parse 2 | from dsl import dslparse 3 | 4 | aparse = parse 5 | dparse = dslparse 6 | -------------------------------------------------------------------------------- /rewrite/_alex.py: -------------------------------------------------------------------------------- 1 | # _alex.py. This file automatically created by PLY (version 3.4). Don't edit! 2 | _tabversion = '3.4' 3 | _lextokens = {'INT': 1, 'DOUBLE': 1, 'PLACEHOLDER': 1, 'NAME': 1, 'STRING': 1} 4 | _lexreflags = 0 5 | _lexliterals = ',(){}<>[]' 6 | _lexstateinfo = {'INITIAL': 'inclusive'} 7 | _lexstatere = {'INITIAL': [('(?P\\d+\\.(\\d+)?)|(?Pappl|str|int|real|placeholder|appl|list|term)|(?P\\d+)|(?P"([^"\\\\]|\\\\.)*")|(?P[a-zA-Z_][a-zA-Z0-9_]*)', [None, ('t_DOUBLE', 'DOUBLE'), None, ('t_PLACEHOLDER', 'PLACEHOLDER'), ('t_INT', 'INT'), ('t_STRING', 'STRING'), None, (None, 'NAME')])]} 8 | _lexstateignore = {'INITIAL': ' \t\n\r'} 9 | _lexstateerrorf = {'INITIAL': 't_error'} 10 | -------------------------------------------------------------------------------- /rewrite/_ayacc.py: -------------------------------------------------------------------------------- 1 | 2 | # /home/stephen/continuum/pyrewrite/rewrite/_ayacc.py 3 | # This file is automatically generated. Do not edit. 4 | _tabversion = '3.2' 5 | 6 | _lr_method = 'LALR' 7 | 8 | _lr_signature = '\xe1R\r\xa5\x89\xf5\xcb\x0c\xe51\t\x94u\x16\x9e\x1f' 9 | 10 | _lr_action_items = {'STRING':([0,3,9,23,24,26,27,30,39,41,],[1,1,1,1,1,1,1,1,1,1,]),'NAME':([0,3,9,23,24,26,27,30,39,41,],[12,12,12,12,12,12,12,12,12,12,]),'INT':([0,3,9,23,24,26,27,30,39,41,],[13,13,13,13,13,13,13,13,13,13,]),'DOUBLE':([0,3,9,23,24,26,27,30,39,41,],[17,17,17,17,17,17,17,17,17,17,]),'PLACEHOLDER':([5,],[20,]),']':([1,2,4,6,7,8,9,10,11,12,13,15,16,17,21,22,25,28,29,30,37,38,40,45,],[-25,-1,-5,-10,-8,-7,-28,-9,-4,-13,-12,-6,-2,-11,-20,29,-22,-27,-19,-28,-21,-16,-3,-26,]),',':([1,2,3,4,6,7,8,9,10,11,12,13,15,16,17,18,19,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,43,44,45,],[-25,-1,-28,-5,-10,-8,-7,-28,-9,-4,-13,-12,-6,-2,-11,26,-23,-20,30,-28,-28,-22,-28,-28,-27,-19,-28,39,-17,41,-14,26,39,30,-16,-28,-3,-28,39,41,-26,]),'<':([0,3,9,23,24,26,27,30,39,41,],[5,5,5,5,5,5,5,5,5,5,]),')':([1,2,3,4,6,7,8,10,11,12,13,15,16,17,18,19,23,25,26,27,28,29,31,32,35,36,38,39,40,43,45,],[-25,-1,-28,-5,-10,-8,-7,-9,-4,-13,-12,-6,-2,-11,25,-23,-28,-22,-28,-28,-27,-19,38,-17,-24,42,-16,-28,-3,-18,-26,]),'(':([0,3,9,11,12,13,17,20,23,24,26,27,30,39,41,],[3,3,3,23,-13,-12,-11,27,3,3,3,3,3,3,3,]),'{':([0,1,3,4,6,7,8,9,10,11,12,13,15,16,17,23,25,26,27,28,29,30,38,39,45,],[-28,-25,-28,-5,-10,-8,-7,-28,-9,-4,-13,-12,-6,24,-11,-28,-22,-28,-28,-27,-19,-28,-16,-28,-26,]),'>':([20,42,],[28,45,]),'}':([1,4,6,7,8,10,11,12,13,15,17,24,25,28,29,33,34,38,41,44,45,],[-25,-5,-10,-8,-7,-9,-4,-13,-12,-6,-11,-28,-22,-27,-19,40,-14,-16,-28,-15,-26,]),'[':([0,3,9,23,24,26,27,30,39,41,],[9,9,9,9,9,9,9,9,9,9,]),'$end':([0,1,2,4,6,7,8,10,11,12,13,14,15,16,17,25,28,29,38,40,45,],[-28,-25,-1,-5,-10,-8,-7,-9,-4,-13,-12,0,-6,-2,-11,-22,-27,-19,-16,-3,-26,]),} 11 | 12 | _lr_action = { } 13 | for _k, _v in _lr_action_items.items(): 14 | for _x,_y in zip(_v[0],_v[1]): 15 | if not _x in _lr_action: _lr_action[_x] = { } 16 | _lr_action[_x][_k] = _y 17 | del _lr_action_items 18 | 19 | _lr_goto_items = {'tuple_value':([3,26,],[18,35,]),'term':([0,3,9,23,24,26,27,30,39,41,],[11,11,11,11,11,11,11,11,11,11,]),'string':([0,3,9,23,24,26,27,30,39,41,],[7,7,7,7,7,7,7,7,7,7,]),'avalue':([0,3,9,23,26,27,30,39,],[2,2,2,2,2,2,2,2,]),'tuple':([0,3,9,23,24,26,27,30,39,41,],[8,8,8,8,8,8,8,8,8,8,]),'expr':([0,3,9,23,26,27,30,39,],[14,19,21,32,19,32,21,32,]),'list':([0,3,9,23,24,26,27,30,39,41,],[15,15,15,15,15,15,15,15,15,15,]),'value':([0,3,9,23,24,26,27,30,39,41,],[16,16,16,16,34,16,16,16,16,34,]),'appl':([0,3,9,23,24,26,27,30,39,41,],[4,4,4,4,4,4,4,4,4,4,]),'list_value':([9,30,],[22,37,]),'placeholder':([0,3,9,23,24,26,27,30,39,41,],[10,10,10,10,10,10,10,10,10,10,]),'annotation':([24,41,],[33,44,]),'empty':([0,3,9,23,24,26,27,30,39,41,],[6,6,6,6,6,6,6,6,6,6,]),'appl_value':([23,27,39,],[31,36,43,]),} 20 | 21 | _lr_goto = { } 22 | for _k, _v in _lr_goto_items.items(): 23 | for _x,_y in zip(_v[0],_v[1]): 24 | if not _x in _lr_goto: _lr_goto[_x] = { } 25 | _lr_goto[_x][_k] = _y 26 | del _lr_goto_items 27 | _lr_productions = [ 28 | ("S' -> expr","S'",1,None,None,None), 29 | ('expr -> avalue','expr',1,'p_expr1','/home/stephen/continuum/pyrewrite/rewrite/parse.py',116), 30 | ('expr -> value','expr',1,'p_expr1','/home/stephen/continuum/pyrewrite/rewrite/parse.py',117), 31 | ('avalue -> value { annotation }','avalue',4,'p_avalue','/home/stephen/continuum/pyrewrite/rewrite/parse.py',123), 32 | ('value -> term','value',1,'p_value','/home/stephen/continuum/pyrewrite/rewrite/parse.py',127), 33 | ('value -> appl','value',1,'p_value','/home/stephen/continuum/pyrewrite/rewrite/parse.py',128), 34 | ('value -> list','value',1,'p_value','/home/stephen/continuum/pyrewrite/rewrite/parse.py',129), 35 | ('value -> tuple','value',1,'p_value','/home/stephen/continuum/pyrewrite/rewrite/parse.py',130), 36 | ('value -> string','value',1,'p_value','/home/stephen/continuum/pyrewrite/rewrite/parse.py',131), 37 | ('value -> placeholder','value',1,'p_value','/home/stephen/continuum/pyrewrite/rewrite/parse.py',132), 38 | ('value -> empty','value',1,'p_value','/home/stephen/continuum/pyrewrite/rewrite/parse.py',133), 39 | ('term -> DOUBLE','term',1,'p_term_double','/home/stephen/continuum/pyrewrite/rewrite/parse.py',139), 40 | ('term -> INT','term',1,'p_term_int','/home/stephen/continuum/pyrewrite/rewrite/parse.py',143), 41 | ('term -> NAME','term',1,'p_term_term','/home/stephen/continuum/pyrewrite/rewrite/parse.py',147), 42 | ('annotation -> value','annotation',1,'p_annotation1','/home/stephen/continuum/pyrewrite/rewrite/parse.py',155), 43 | ('annotation -> annotation , annotation','annotation',3,'p_annotation2','/home/stephen/continuum/pyrewrite/rewrite/parse.py',159), 44 | ('appl -> term ( appl_value )','appl',4,'p_appl','/home/stephen/continuum/pyrewrite/rewrite/parse.py',165), 45 | ('appl_value -> expr','appl_value',1,'p_appl_value1','/home/stephen/continuum/pyrewrite/rewrite/parse.py',169), 46 | ('appl_value -> appl_value , appl_value','appl_value',3,'p_appl_value2','/home/stephen/continuum/pyrewrite/rewrite/parse.py',176), 47 | ('list -> [ list_value ]','list',3,'p_list','/home/stephen/continuum/pyrewrite/rewrite/parse.py',182), 48 | ('list_value -> expr','list_value',1,'p_list_value1','/home/stephen/continuum/pyrewrite/rewrite/parse.py',186), 49 | ('list_value -> list_value , list_value','list_value',3,'p_list_value2','/home/stephen/continuum/pyrewrite/rewrite/parse.py',193), 50 | ('tuple -> ( tuple_value )','tuple',3,'p_tuple','/home/stephen/continuum/pyrewrite/rewrite/parse.py',199), 51 | ('tuple_value -> expr','tuple_value',1,'p_tuple_value1','/home/stephen/continuum/pyrewrite/rewrite/parse.py',203), 52 | ('tuple_value -> tuple_value , tuple_value','tuple_value',3,'p_tuple_value2','/home/stephen/continuum/pyrewrite/rewrite/parse.py',210), 53 | ('string -> STRING','string',1,'p_string','/home/stephen/continuum/pyrewrite/rewrite/parse.py',216), 54 | ('placeholder -> < PLACEHOLDER ( appl_value ) >','placeholder',6,'p_placeholder1','/home/stephen/continuum/pyrewrite/rewrite/parse.py',222), 55 | ('placeholder -> < PLACEHOLDER >','placeholder',3,'p_placeholder2','/home/stephen/continuum/pyrewrite/rewrite/parse.py',226), 56 | ('empty -> ','empty',0,'p_empty','/home/stephen/continuum/pyrewrite/rewrite/parse.py',232), 57 | ] 58 | -------------------------------------------------------------------------------- /rewrite/astnodes.py: -------------------------------------------------------------------------------- 1 | from collections import namedtuple 2 | 3 | RuleNode = namedtuple( 'Rule', ('label', 'lhs', 'rhs')) 4 | StrategyNode = namedtuple('Strategy', ('label', 'combinator', 'args')) 5 | AsNode = namedtuple('As', ('tag', 'pattern')) 6 | -------------------------------------------------------------------------------- /rewrite/aterm.asdl: -------------------------------------------------------------------------------- 1 | -- ASDL's five builtin types are identifier, int, string, object, bool 2 | 3 | module ATerm 4 | { 5 | term = ATerm(identifier name) 6 | | AReal(object n) 7 | | AInt(object n) 8 | | AStr(string val) 9 | | Appl(term fn, type* args) 10 | | AList(term elt) 11 | 12 | annotation = AAnnotation(term, term) 13 | } 14 | -------------------------------------------------------------------------------- /rewrite/dsl/__init__.py: -------------------------------------------------------------------------------- 1 | from parse import dslparse 2 | from toplevel import module 3 | -------------------------------------------------------------------------------- /rewrite/dsl/_dlex.py: -------------------------------------------------------------------------------- 1 | # _dlex.py. This file automatically created by PLY (version 3.4). Don't edit! 2 | _tabversion = '3.4' 3 | _lextokens = {'NAME': 1, 'INT': 1, 'DOUBLE': 1, 'INCOMB': 1, 'AS': 1, 'ARROW': 1, 'STRING': 1} 4 | _lexreflags = 0 5 | _lexliterals = ';,|:=(){}[]' 6 | _lexstateinfo = {'INITIAL': 'inclusive'} 7 | _lexstatere = {'INITIAL': [('(?P\\n+)|(?P\\d+\\.(\\d+)?)|(?P\\d+)|(?P->)|(?P\\@)|(?P"([^"\\\\]|\\\\.)*")|(?P\\#.*)|(?P[a-zA-Z_][a-zA-Z0-9_]*)|(?Pfail|id|\\<\\+|\\;)', [None, ('t_newline', 'newline'), ('t_DOUBLE', 'DOUBLE'), None, ('t_INT', 'INT'), ('t_ARROW', 'ARROW'), ('t_AS', 'AS'), ('t_STRING', 'STRING'), None, ('t_COMMENT', 'COMMENT'), (None, 'NAME'), (None, 'INCOMB')])]} 8 | _lexstateignore = {'INITIAL': ' \t\r'} 9 | _lexstateerrorf = {'INITIAL': 't_error'} 10 | -------------------------------------------------------------------------------- /rewrite/dsl/_dyacc.py: -------------------------------------------------------------------------------- 1 | 2 | # /home/stephen/continuum/pyrewrite/rewrite/dsl/_dyacc.py 3 | # This file is automatically generated. Do not edit. 4 | _tabversion = '3.2' 5 | 6 | _lr_method = 'LALR' 7 | 8 | _lr_signature = 'o\xdc).WL\x02\xb9\xbb\xdb=\xab\x84j\xd8l' 9 | 10 | _lr_action_items = {'NAME':([0,2,3,4,5,6,7,8,9,12,13,14,15,16,17,18,19,20,21,22,24,25,26,27,28,29,31,34,37,38,39,40,41,42,44,45,46,47,50,51,52,54,55,58,59,60,],[1,-3,-4,1,11,21,27,-1,-2,-20,21,-17,-21,-34,-19,21,21,-16,-24,-23,-18,-15,-22,-24,-6,-12,11,-14,21,50,21,27,27,27,-31,21,-28,21,-24,-13,-5,-10,-7,-25,21,-11,]),'INT':([6,7,13,18,19,37,38,39,40,41,42,45,47,59,],[22,22,22,22,22,22,22,22,22,22,22,22,22,22,]),'(':([1,6,7,13,18,19,20,21,22,26,27,37,38,39,40,41,42,45,47,50,59,],[5,13,13,13,13,13,37,-24,-23,-22,40,13,13,13,13,13,13,13,13,-24,13,]),']':([12,14,15,16,17,18,19,20,21,22,24,25,26,34,35,36,38,44,46,47,50,51,57,58,],[-20,-17,-21,-34,-19,-35,-35,-16,-24,-23,-18,-15,-22,-14,-29,46,-35,-31,-28,-35,-24,-13,-30,-25,]),',':([10,11,12,13,14,15,16,17,18,19,20,21,22,24,25,26,32,33,34,35,36,37,38,43,44,45,46,47,48,49,50,51,56,57,58,59,61,],[31,-9,-20,-35,-17,-21,-34,-19,-35,-35,-16,-24,-23,-18,-15,-22,45,-32,-14,-29,47,-35,-35,31,-31,-35,-28,-35,-26,59,-24,-13,45,47,-25,-35,59,]),'INCOMB':([7,12,14,15,16,17,20,22,24,26,27,28,29,40,41,42,44,46,53,54,55,58,60,],[-35,-20,-17,-21,-34,-19,-16,-23,-18,-22,-24,41,-12,-35,-35,-35,-31,-28,41,41,41,-25,-11,]),')':([10,11,12,13,14,15,16,17,18,20,21,22,24,25,26,27,29,32,33,34,37,38,40,41,43,44,45,46,48,49,50,51,53,54,56,58,59,60,61,],[30,-9,-20,-35,-17,-21,-34,-19,-35,-16,-24,-23,-18,-15,-22,-24,-12,44,-32,-14,-35,-35,-35,-35,-8,-31,-35,-28,-26,58,-24,-13,60,-10,-33,-25,-35,-11,-27,]),'AS':([6,13,18,19,21,37,39,45,47,59,],[18,18,18,18,38,18,18,18,18,18,]),'STRING':([6,7,13,18,19,37,38,39,40,41,42,45,47,59,],[16,16,16,16,16,16,16,16,16,16,16,16,16,16,]),'ARROW':([6,12,14,15,16,17,18,20,21,22,23,24,25,26,34,38,44,46,50,51,58,],[-35,-20,-17,-21,-34,-19,-35,-16,-24,-23,39,-18,-15,-22,-14,-35,-31,-28,-24,-13,-25,]),'DOUBLE':([6,7,13,18,19,37,38,39,40,41,42,45,47,59,],[26,26,26,26,26,26,26,26,26,26,26,26,26,26,]),'[':([6,7,13,18,19,37,38,39,40,41,42,45,47,59,],[19,19,19,19,19,19,19,19,19,19,19,19,19,19,]),':':([1,],[6,]),'=':([1,30,],[7,42,]),'$end':([2,3,4,7,8,9,12,14,15,16,17,18,20,21,22,24,25,26,27,28,29,34,38,39,41,42,44,46,50,51,52,54,55,58,60,],[-3,-4,0,-35,-1,-2,-20,-17,-21,-34,-19,-35,-16,-24,-23,-18,-15,-22,-24,-6,-12,-14,-35,-35,-35,-35,-31,-28,-24,-13,-5,-10,-7,-25,-11,]),} 11 | 12 | _lr_action = { } 13 | for _k, _v in _lr_action_items.items(): 14 | for _x,_y in zip(_v[0],_v[1]): 15 | if not _x in _lr_action: _lr_action[_x] = { } 16 | _lr_action[_x][_k] = _y 17 | del _lr_action_items 18 | 19 | _lr_goto_items = {'strategy_args':([5,31,],[10,43,]),'term':([6,7,13,18,19,37,38,39,40,41,42,45,47,59,],[20,20,20,20,20,20,20,20,20,20,20,20,20,20,]),'string':([6,7,13,18,19,37,38,39,40,41,42,45,47,59,],[12,12,12,12,12,12,12,12,12,12,12,12,12,12,]),'tuple':([6,7,13,18,19,37,38,39,40,41,42,45,47,59,],[17,17,17,17,17,17,17,17,17,17,17,17,17,17,]),'expr':([6,13,18,19,37,39,45,47,59,],[23,33,34,35,48,52,33,35,48,]),'strategy_value':([7,40,41,42,],[28,53,54,55,]),'list':([6,7,13,18,19,37,38,39,40,41,42,45,47,59,],[24,24,24,24,24,24,24,24,24,24,24,24,24,24,]),'rule':([0,4,],[2,8,]),'strategy':([0,4,],[3,9,]),'appl':([6,7,13,18,19,37,38,39,40,41,42,45,47,59,],[14,14,14,14,14,14,14,14,14,14,14,14,14,14,]),'list_value':([19,47,],[36,57,]),'value':([6,7,13,18,19,37,38,39,40,41,42,45,47,59,],[25,29,25,25,25,25,51,25,29,29,29,25,25,25,]),'definitions':([0,],[4,]),'tuple_value':([13,45,],[32,56,]),'empty':([6,7,13,18,19,37,38,39,40,41,42,45,47,59,],[15,15,15,15,15,15,15,15,15,15,15,15,15,15,]),'appl_value':([37,59,],[49,61,]),} 20 | 21 | _lr_goto = { } 22 | for _k, _v in _lr_goto_items.items(): 23 | for _x,_y in zip(_v[0],_v[1]): 24 | if not _x in _lr_goto: _lr_goto[_x] = { } 25 | _lr_goto[_x][_k] = _y 26 | del _lr_goto_items 27 | _lr_productions = [ 28 | ("S' -> definitions","S'",1,None,None,None), 29 | ('definitions -> definitions rule','definitions',2,'p_definitions1','',148), 30 | ('definitions -> definitions strategy','definitions',2,'p_definitions1','',149), 31 | ('definitions -> rule','definitions',1,'p_definitions2','',153), 32 | ('definitions -> strategy','definitions',1,'p_definitions2','',154), 33 | ('rule -> NAME : expr ARROW expr','rule',5,'p_rule','',160), 34 | ('strategy -> NAME = strategy_value','strategy',3,'p_strategy_def1','',166), 35 | ('strategy -> NAME ( strategy_args ) = strategy_value','strategy',6,'p_strategy_def2','',171), 36 | ('strategy_args -> strategy_args , strategy_args','strategy_args',3,'p_strategy_args1','',178), 37 | ('strategy_args -> NAME','strategy_args',1,'p_strategy_args2','',182), 38 | ('strategy_value -> strategy_value INCOMB strategy_value','strategy_value',3,'p_strategy_value1','',188), 39 | ('strategy_value -> NAME ( strategy_value )','strategy_value',4,'p_strategy_value2','',198), 40 | ('strategy_value -> value','strategy_value',1,'p_strategy_value3','',202), 41 | ('expr -> NAME AS value','expr',3,'p_expr1','',209), 42 | ('expr -> AS expr','expr',2,'p_expr2','',214), 43 | ('expr -> value','expr',1,'p_expr3','',218), 44 | ('value -> term','value',1,'p_value','',224), 45 | ('value -> appl','value',1,'p_value','',225), 46 | ('value -> list','value',1,'p_value','',226), 47 | ('value -> tuple','value',1,'p_value','',227), 48 | ('value -> string','value',1,'p_value','',228), 49 | ('value -> empty','value',1,'p_value','',229), 50 | ('term -> DOUBLE','term',1,'p_term_double','',235), 51 | ('term -> INT','term',1,'p_term_int','',239), 52 | ('term -> NAME','term',1,'p_term_term','',243), 53 | ('appl -> term ( appl_value )','appl',4,'p_appl','',249), 54 | ('appl_value -> expr','appl_value',1,'p_appl_value1','',253), 55 | ('appl_value -> appl_value , appl_value','appl_value',3,'p_appl_value2','',260), 56 | ('list -> [ list_value ]','list',3,'p_list','',266), 57 | ('list_value -> expr','list_value',1,'p_list_value1','',270), 58 | ('list_value -> list_value , list_value','list_value',3,'p_list_value2','',277), 59 | ('tuple -> ( tuple_value )','tuple',3,'p_tuple','',283), 60 | ('tuple_value -> expr','tuple_value',1,'p_tuple_value1','',287), 61 | ('tuple_value -> tuple_value , tuple_value','tuple_value',3,'p_tuple_value2','',294), 62 | ('string -> STRING','string',1,'p_string','',300), 63 | ('empty -> ','empty',0,'p_empty','',306), 64 | ] 65 | -------------------------------------------------------------------------------- /rewrite/dsl/cli.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import pprint 3 | import argparse 4 | import readline 5 | import traceback 6 | from functools import partial 7 | 8 | from rewrite import aparse #, match 9 | from rewrite.matching import freev 10 | from toplevel import module, NoMatch 11 | 12 | #------------------------------------------------------------------------ 13 | # Toplevel 14 | #------------------------------------------------------------------------ 15 | 16 | banner = """Pyrewrite 17 | ------------------------------------ 18 | Type :help for for more information. 19 | """ 20 | 21 | help = """ 22 | -- Usage: 23 | 24 | >> f(x,1) 25 | >> ?f(a,b) 26 | [x,y] 27 | >> !rule 28 | 29 | -- Commmands: 30 | 31 | :show 32 | :type 33 | :bindings 34 | :let 35 | :load 36 | :browse 37 | :help 38 | 39 | """ 40 | 41 | def completer(mod, text, state): 42 | opts = [i for i in mod.keys() if i.startswith(text)] 43 | if state < len(opts): 44 | return opts[state] 45 | else: 46 | return None 47 | 48 | prelude = {} 49 | 50 | #------------------------------------------------------------------------ 51 | # Main interpreter loop 52 | #------------------------------------------------------------------------ 53 | 54 | def main(): 55 | parser = argparse.ArgumentParser() 56 | parser.add_argument('module', nargs='?', help='Module') 57 | parser.add_argument('--noprelude', action='store_true', help='Include prelude') 58 | args = parser.parse_args() 59 | 60 | # State 61 | mod = {} 62 | last = None 63 | bindings = {} 64 | 65 | if args.module: 66 | with open(args.module) as fd: 67 | mod = module(fd.read()) 68 | 69 | if not args.noprelude: 70 | mod.update(prelude) 71 | 72 | print banner 73 | readline.parse_and_bind("tab: complete") 74 | readline.set_completer(partial(completer, mod)) 75 | 76 | while True: 77 | try: 78 | line = raw_input('>> ').strip() 79 | except EOFError: 80 | break 81 | 82 | 83 | #----------------------------------------------- 84 | if line.startswith('?'): 85 | at = aparse(line[1:]) 86 | matcher = partial(match, freev(at)) 87 | matched, localbind = matcher(last) 88 | 89 | # TODO: Use dict 90 | #bindings.update(localbind) 91 | 92 | #if matched: 93 | # print bindings 94 | #else: 95 | # print 'failed' 96 | 97 | #----------------------------------------------- 98 | elif line.startswith('!'): 99 | try: 100 | rr = mod[line[1:].strip()] 101 | last = rr.rewrite(last) 102 | print last 103 | except KeyError: 104 | print "No such rule or strategy '%s'" % line[1:] 105 | except NoMatch: 106 | print 'failed' 107 | 108 | #----------------------------------------------- 109 | elif line.startswith(':show') or line.startswith(':s'): 110 | try: 111 | rr = mod[line[1:].strip()] 112 | print rr 113 | except KeyError: 114 | print "No such rule or strategy '%s'" % line[1:] 115 | 116 | #----------------------------------------------- 117 | elif line.startswith(':type') or line.startswith(':t'): 118 | try: 119 | at = aparse(line[2:]) 120 | print type(at).__name__ 121 | except Exception as e: 122 | print e 123 | 124 | #----------------------------------------------- 125 | elif line.startswith(':bindings'): 126 | if bindings: 127 | pprint.pprint(bindings) 128 | continue 129 | 130 | #----------------------------------------------- 131 | elif line.startswith(':let'): 132 | env = module(line[4:], _env=mod) 133 | mod.update(env) 134 | 135 | #----------------------------------------------- 136 | elif line.startswith(':load'): 137 | fname = line[5:].strip() 138 | try: 139 | contents = open(fname).read() 140 | mod.update(module(contents)) 141 | except IOError: 142 | print "No such module", fname 143 | 144 | #----------------------------------------------- 145 | elif line.startswith(':browse'): 146 | pprint.pprint(mod) 147 | 148 | #----------------------------------------------- 149 | elif line.startswith(':help'): 150 | print help 151 | pass 152 | 153 | #----------------------------------------------- 154 | else: 155 | bindings = {} 156 | try: 157 | last = aparse(line) 158 | print last 159 | except EOFError: 160 | pass 161 | except Exception as e: 162 | print traceback.format_exc() 163 | 164 | 165 | if __name__ == '__main__': 166 | main() 167 | -------------------------------------------------------------------------------- /rewrite/dsl/combinators.py: -------------------------------------------------------------------------------- 1 | from functools import wraps 2 | import rewrite.terms as terms 3 | 4 | #------------------------------------------------------------------------ 5 | # Exceptions 6 | #------------------------------------------------------------------------ 7 | 8 | class STFail(Exception): 9 | pass 10 | 11 | #------------------------------------------------------------------------ 12 | # Rewrite Combinators 13 | #------------------------------------------------------------------------ 14 | 15 | Id = lambda s: s 16 | compose = lambda f, g: lambda x: f(g(x)) 17 | 18 | def fix(f): 19 | @wraps(f) 20 | def Yf(*args): 21 | return inner(*args) 22 | inner = f(Yf) 23 | return Yf 24 | 25 | def fail(): 26 | raise STFail() 27 | 28 | class Choice(object): 29 | def __init__(self, left=None, right=None): 30 | self.left = left 31 | self.right = right 32 | assert left and right, 'Must provide two arguments to Choice' 33 | 34 | def __call__(self, t): 35 | try: 36 | return self.left(t) 37 | except STFail: 38 | return self.right(t) 39 | 40 | class Debug(object): 41 | def __init__(self, s): 42 | self.s = s 43 | 44 | def __call__(self, t): 45 | res = self.s(t) 46 | print res 47 | return res 48 | 49 | class Ternary(object): 50 | def __init__(self, s1, s2, s3): 51 | self.s1 = s1 52 | self.s2 = s2 53 | self.s3 = s3 54 | 55 | def __call__(self, t): 56 | try: 57 | val = self.s1(t) 58 | except STFail: 59 | return self.s2(val) 60 | else: 61 | return self.s3(val) 62 | 63 | class Repeat(object): 64 | def __init__(self, p): 65 | self.p = p 66 | 67 | def __call__(self, s): 68 | val = s 69 | while True: 70 | try: 71 | val = self.p(val) 72 | except STFail: 73 | break 74 | return val 75 | 76 | class All(object): 77 | def __init__(self, s): 78 | self.s = s 79 | 80 | def __call__(self, o): 81 | if isinstance(o, terms.AAppl): 82 | return terms.AAppl(o.spine, map(self.s, o.args)) 83 | else: 84 | return o 85 | 86 | class Some(object): 87 | def __init__(self, s): 88 | self.s = s 89 | 90 | def __call__(self, o): 91 | if isinstance(o, AAppl): 92 | largs = [] 93 | for a in o.args: 94 | try: 95 | largs.append(self.s(a)) 96 | except STFail: 97 | largs.append(a) 98 | return AAppl(o.spine, largs) 99 | else: 100 | raise STFail() 101 | 102 | class Seq(object): 103 | def __init__(self, s1, s2): 104 | self.s1 = s1 105 | self.s2 = s2 106 | 107 | def __call__(self, o): 108 | return self.s2(self.s1(o)) 109 | 110 | class Try(object): 111 | def __init__(self, s): 112 | self.s = s 113 | 114 | def __call__(self, o): 115 | try: 116 | return self.s(o) 117 | except STFail: 118 | return o 119 | except Exception: 120 | return o 121 | 122 | class Topdown(object): 123 | def __init__(self, s): 124 | self.s = s 125 | 126 | def __call__(self, o): 127 | val = self.s(o) 128 | return All(self)(val) 129 | 130 | class Bottomup(object): 131 | def __init__(self, s): 132 | self.s = s 133 | 134 | def __call__(self, o): 135 | val = All(self)(o) 136 | return self.s(val) 137 | 138 | class Innermost(object): 139 | def __init__(self, s): 140 | self.s = s 141 | 142 | def __call__(self, o): 143 | return Bottomup(Try(Seq(self.s, self)))(o) 144 | 145 | class SeqL(object): 146 | def __init__(self, *sx): 147 | self.lx = reduce(compose,sx) 148 | 149 | def __call__(self, o): 150 | return self.lx(o) 151 | 152 | class ChoiceL(object): 153 | def __init__(self, *sx): 154 | self.sx = reduce(compose,sx) 155 | 156 | def __call__(self, o): 157 | return self.sx(o) 158 | -------------------------------------------------------------------------------- /rewrite/dsl/parse.py: -------------------------------------------------------------------------------- 1 | import os 2 | import re 3 | import sys 4 | 5 | import rewrite.astnodes as ast 6 | import rewrite.terms as aterm 7 | 8 | # Precompiled modules 9 | try: 10 | import _dlex 11 | import _dyacc 12 | except ImportError: 13 | pass 14 | 15 | from functools import partial 16 | from rewrite.plyhacks import yaccfrom, lexfrom 17 | 18 | #------------------------------------------------------------------------ 19 | # Errors 20 | #------------------------------------------------------------------------ 21 | 22 | syntax_error = """ 23 | 24 | File {filename}, line {lineno} 25 | {line} 26 | {pointer} 27 | 28 | ATermSyntaxError: {msg} 29 | """ 30 | 31 | #------------------------------------------------------------------------ 32 | # Lexer 33 | #------------------------------------------------------------------------ 34 | prefix_combinators = [ 35 | 'rec', 36 | ] 37 | 38 | infix_combinators = [ 39 | 'fail' , 40 | 'id', 41 | '<+', 42 | ';', 43 | ] 44 | 45 | tokens = ( 46 | 'NAME', 'INT', 'DOUBLE', 'ARROW', 'STRING', 'INCOMB', 'AS', 47 | #, 'CLAUSE' 48 | ) 49 | 50 | literals = [ 51 | ';', 52 | ',', 53 | '|', 54 | ':', 55 | '=', 56 | '(', 57 | ')', 58 | '{', 59 | '}', 60 | '[', 61 | ']', 62 | ] 63 | 64 | t_NAME = r'[a-zA-Z_][a-zA-Z0-9_]*' 65 | t_ignore = '\x20\x09\x0D' 66 | 67 | # dynamically generate the regex for the Combinator token from 68 | # the keys of the combinator dictionary 69 | t_INCOMB = '|'.join(map(re.escape, infix_combinators)) 70 | #t_PRECOMB = '|'.join(map(re.escape, prefix_combinators)) 71 | 72 | unquote = re.compile('"(?:[^\']*)\'|"([^"]*)"') 73 | 74 | def t_newline(t): 75 | r'\n+' 76 | t.lexer.lineno += len(t.value) 77 | 78 | def t_DOUBLE(t): 79 | r'\d+\.(\d+)?' 80 | t.value = float(t.value) 81 | return t 82 | 83 | def t_INT(t): 84 | r'\d+' 85 | try: 86 | t.value = int(t.value) 87 | except ValueError: 88 | print("Integer value too large %d", t.value) 89 | t.value = 0 90 | return t 91 | 92 | def t_ARROW(t): 93 | r'->' 94 | return t 95 | 96 | def t_AS(t): 97 | r'\@' 98 | return t 99 | 100 | def t_STRING(t): 101 | r'"([^"\\]|\\.)*"' 102 | t.value = t.value.encode('ascii') 103 | t.value = unquote.findall(t.value)[0] 104 | return t 105 | 106 | #def t_CLAUSE(t): 107 | #r'where' 108 | #return t 109 | 110 | def t_COMMENT(t): 111 | r'\#.*' 112 | pass 113 | 114 | def t_error(t): 115 | print("Unknown token '%s'" % t.value[0]) 116 | t.lexer.skip(1) 117 | 118 | #-------------------------------- 119 | 120 | #------------------------------------------------------------------------ 121 | # Parser 122 | #------------------------------------------------------------------------ 123 | 124 | class RewriteSyntaxError(Exception): 125 | def __init__(self, lineno, col_offset, filename, text, msg=None): 126 | self.lineno = lineno 127 | self.col_offset = col_offset 128 | self.filename = filename 129 | self.text = text 130 | self.msg = msg or 'invalid syntax' 131 | 132 | def __str__(self): 133 | return syntax_error.format( 134 | filename = self.filename, 135 | lineno = self.lineno, 136 | line = self.text, 137 | pointer = ' '*self.col_offset + '^', 138 | msg = self.msg 139 | ) 140 | 141 | start = 'definitions' 142 | 143 | def p_definitions1(p): 144 | '''definitions : definitions rule 145 | | definitions strategy''' 146 | p[0] = p[1] + [p[2]] 147 | 148 | def p_definitions2(p): 149 | '''definitions : rule 150 | | strategy''' 151 | p[0] = [p[1]] 152 | 153 | #-------------------------------- 154 | 155 | def p_rule(p): 156 | '''rule : NAME ':' expr ARROW expr''' 157 | p[0] = ast.RuleNode(p[1],p[3],p[5]) 158 | 159 | #-------------------------------- 160 | 161 | def p_strategy_def1(p): 162 | '''strategy : NAME '=' strategy_value''' 163 | combs, args = p[3] 164 | p[0] = ast.StrategyNode(p[1], combs, args) 165 | 166 | def p_strategy_def2(p): 167 | '''strategy : NAME '(' strategy_args ')' '=' strategy_value''' 168 | combs, args = p[6] 169 | p[0] = ast.StrategyNode(p[1], combs, args) 170 | 171 | #-------------------------------- 172 | 173 | def p_strategy_args1(p): 174 | '''strategy_args : strategy_args ',' strategy_args''' 175 | p[0] = [p[1], p[3]] 176 | 177 | def p_strategy_args2(p): 178 | '''strategy_args : NAME''' 179 | p[0] = p[1] 180 | 181 | #-------------------------------- 182 | 183 | def p_strategy_value1(p): 184 | '''strategy_value : strategy_value INCOMB strategy_value ''' 185 | 186 | if isinstance(p[1], ast.StrategyNode): 187 | p[0] = (p[2], [p[1]] + p[3]) 188 | elif isinstance(p[3], ast.StrategyNode): 189 | p[0] = (p[2], p[1] + [p[3]]) 190 | else: 191 | p[0] = (p[2], [p[1],p[3]]) 192 | 193 | def p_strategy_value2(p): 194 | '''strategy_value : NAME '(' strategy_value ')' ''' 195 | p[0] = (p[1], [p[3]]) 196 | 197 | def p_strategy_value3(p): 198 | '''strategy_value : value''' 199 | p[0] = [p[1]] 200 | 201 | #-------------------------------- 202 | 203 | # tagged as-patterns ( ala Haskell ) 204 | def p_expr1(p): 205 | '''expr : NAME AS value''' 206 | p[0] = ast.AsNode(p[1], p[3]) 207 | 208 | # anonymous as-patterns ( ala Pure ) 209 | def p_expr2(p): 210 | '''expr : AS expr''' 211 | p[0] = ast.AsNode(None, p[2]) 212 | 213 | def p_expr3(p): 214 | '''expr : value''' 215 | p[0] = p[1] 216 | 217 | #-------------------------------- 218 | 219 | def p_value(p): 220 | """value : term 221 | | appl 222 | | list 223 | | tuple 224 | | string 225 | | empty""" 226 | p[0] = p[1] 227 | 228 | #-------------------------------- 229 | 230 | def p_term_double(p): 231 | "term : DOUBLE" 232 | p[0] = aterm.areal(p[1]) 233 | 234 | def p_term_int(p): 235 | "term : INT" 236 | p[0] = aterm.aint(p[1]) 237 | 238 | def p_term_term(p): 239 | "term : NAME" 240 | p[0] = aterm.aterm(p[1], None) 241 | 242 | #-------------------------------- 243 | 244 | def p_appl(p): 245 | "appl : term '(' appl_value ')' " 246 | p[0] = aterm.aappl(p[1], p[3]) 247 | 248 | def p_appl_value1(p): 249 | "appl_value : expr" 250 | if p[1]: 251 | p[0] = [p[1]] 252 | else: 253 | p[0] = [] 254 | 255 | def p_appl_value2(p): 256 | "appl_value : appl_value ',' appl_value" 257 | p[0] = p[1] + p[3] 258 | 259 | #-------------------------------- 260 | 261 | def p_list(p): 262 | "list : '[' list_value ']' " 263 | p[0] = aterm.alist(p[2]) 264 | 265 | def p_list_value1(p): 266 | "list_value : expr" 267 | if p[1]: 268 | p[0] = [p[1]] 269 | else: 270 | p[0] = [] 271 | 272 | def p_list_value2(p): 273 | "list_value : list_value ',' list_value" 274 | p[0] = p[1] + p[3] 275 | 276 | #-------------------------------- 277 | 278 | def p_tuple(p): 279 | "tuple : '(' tuple_value ')' " 280 | p[0] = aterm.atupl(p[2]) 281 | 282 | def p_tuple_value1(p): 283 | "tuple_value : expr" 284 | if p[1]: 285 | p[0] = [p[1]] 286 | else: 287 | p[0] = [] 288 | 289 | def p_tuple_value2(p): 290 | "tuple_value : tuple_value ',' tuple_value" 291 | p[0] = p[1] + p[3] 292 | 293 | #-------------------------------- 294 | 295 | def p_string(p): 296 | "string : STRING" 297 | p[0] = aterm.astr(p[1]) 298 | 299 | #-------------------------------- 300 | 301 | def p_empty(t): 302 | "empty : " 303 | pass 304 | 305 | #-------------------------------- 306 | 307 | def p_error(p): 308 | line = p.lexer.lexdata.split('\n')[p.lineno-1] 309 | offset = sum(map(len, p.lexer.lexdata.split('\n')[0:p.lineno-1])) 310 | column = p.lexpos - offset 311 | 312 | if p: 313 | raise RewriteSyntaxError( 314 | p.lineno, 315 | column, 316 | '', 317 | line, 318 | ) 319 | else: 320 | raise SyntaxError("Syntax error at EOF") 321 | 322 | #------------------------------------------------------------------------ 323 | # DSL Parser 324 | #------------------------------------------------------------------------ 325 | 326 | def load_parser(debug=False): 327 | if debug: 328 | from ply import lex, yacc 329 | path = os.path.abspath(__file__) 330 | dir_path = os.path.dirname(path) 331 | lexer = lex.lex(lextab="_dlex", outputdir=dir_path, optimize=1) 332 | parser = yacc.yacc(tabmodule='_dyacc',outputdir=dir_path, 333 | write_tables=1, debug=0, optimize=0) 334 | return partial(parser.parse, lexer=lexer) 335 | else: 336 | module = sys.modules[__name__] 337 | lexer = lexfrom(module, _dlex) 338 | parser = yaccfrom(module, _dyacc, lexer) 339 | 340 | # curry the lexer into the parser 341 | return partial(parser.parse, lexer=lexer) 342 | 343 | def dslparse(pattern): 344 | parse = load_parser() 345 | return parse(pattern) 346 | -------------------------------------------------------------------------------- /rewrite/dsl/toplevel.py: -------------------------------------------------------------------------------- 1 | from functools import partial 2 | 3 | from rewrite.matching import free, freev, fold, unfold, hylo, NoMatch 4 | import rewrite.astnodes as ast 5 | 6 | from parse import dslparse 7 | import combinators as comb 8 | 9 | def nameof(o): 10 | if isinstance(o, RuleBlock): 11 | return o.label 12 | if isinstance(o, Strategy): 13 | return o.label 14 | else: 15 | return o.__class__.__name__ 16 | 17 | combinators = { 18 | 'fail' : comb.fail, 19 | 'id' : comb.Id, 20 | 'repeat' : comb.Repeat, 21 | 'all' : comb.All, 22 | 'some' : comb.Some, 23 | '<+' : comb.Choice, 24 | ';' : comb.Seq, 25 | 'try' : comb.Try, 26 | 'topdown' : comb.Topdown, 27 | 'bottomup' : comb.Bottomup, 28 | 'innermost' : comb.Innermost, 29 | 'debug' : comb.Debug, 30 | } 31 | 32 | #------------------------------------------------------------------------ 33 | # Strategies 34 | #------------------------------------------------------------------------ 35 | 36 | class Strategy(object): 37 | 38 | def __init__(self, combinator, expr, label): 39 | self.subrules = [a for a in expr] 40 | 41 | try: 42 | self.combinator = combinator(*self.subrules) 43 | except TypeError: 44 | raise TypeError, 'Wrong number of arguments to combinator: %s'\ 45 | % str(combinator) 46 | 47 | self.label = label or repr(self) 48 | 49 | def __call__(self, o): 50 | return self.combinator(o) 51 | 52 | rewrite = __call__ 53 | 54 | def __repr__(self): 55 | return '%s(%s)' % ( 56 | nameof(self.combinator), 57 | ','.join(map(nameof, self.subrules)) 58 | ) 59 | 60 | class Rule(object): 61 | def __init__(self, lpat, rpat, left, right, rr): 62 | self.lpat = lpat 63 | self.rpat = rpat 64 | self.left = left 65 | self.right = right 66 | self.rr = rr 67 | 68 | def rewrite(self, subject): 69 | return self.rr(subject) 70 | 71 | __call__ = rewrite 72 | 73 | def __repr__(self): 74 | return '%r => %r ::\n\t %r -> %r' % \ 75 | (self.left, self.right, self.lpat, self.rpat) 76 | 77 | class RuleBlock(object): 78 | def __init__(self, rules=None, label=None): 79 | self.rules = rules or [] 80 | self.label = label 81 | 82 | def add(self, rule): 83 | self.rules.append(rule) 84 | 85 | def rewrite(self, pattern): 86 | for rule in self.rules: 87 | try: 88 | return rule.rewrite(pattern) 89 | except NoMatch: 90 | continue 91 | raise NoMatch() 92 | 93 | def __call__(self, pattern): 94 | return self.rewrite(pattern) 95 | 96 | def __repr__(self): 97 | out = '[\n' 98 | for rule in self.rules: 99 | out += ' '*4 + repr(rule) + '\n' 100 | out += ']\n' 101 | return out 102 | 103 | #------------------------------------------------------------------------ 104 | # Buld Automata 105 | #------------------------------------------------------------------------ 106 | 107 | def build_strategy(label, env, comb, args): 108 | env = env.copy() 109 | 110 | self = object() # forward declaration since rules can be self-recursive 111 | comb = combinators[comb] 112 | 113 | env.update(combinators) 114 | 115 | sargs = [] 116 | 117 | for arg in args: 118 | # composition of combinators 119 | if isinstance(arg, tuple): 120 | subcomb, subargs = arg 121 | sargs.append(build_strategy(None, env, subcomb, subargs)) 122 | 123 | if isinstance(arg, list): 124 | for iarg in arg: 125 | # look up the corresponding rewrite rule or 126 | # rewrite block and pass the rewrite hook to the 127 | # strategy combinator 128 | rr = env[iarg.term] 129 | sargs.append(rr) 130 | 131 | return Strategy(comb, sargs, label) 132 | 133 | def build_rule(l, r, cons=None): 134 | lpat = [] 135 | rpat = [] 136 | sym = set() 137 | cons = cons or {} 138 | 139 | for pat, bind, ty in free(l): 140 | if bind in sym: 141 | # TODO unify ty 142 | lpat.append(bind) 143 | else: 144 | lpat.append(bind) 145 | sym.add(bind) 146 | 147 | for pat, bind, ty in free(r): 148 | if bind in sym: 149 | rpat.append(bind) 150 | else: 151 | raise Exception('Unbound variable: %s' % pat) 152 | 153 | left = freev(l) 154 | right = freev(r) 155 | 156 | ana = partial(unfold, lpat, left) 157 | cata = partial(fold, rpat, right) 158 | 159 | rr = partial(hylo, ana, cata) 160 | return Rule(lpat, rpat, left, right, rr) 161 | 162 | #------------------------------------------------------------------------ 163 | # Module Constructions 164 | #------------------------------------------------------------------------ 165 | 166 | def module(s, sorts=None, cons=None, _env=None): 167 | defs = dslparse(s) 168 | 169 | if _env: 170 | env = _env.copy() 171 | else: 172 | env = {} 173 | 174 | for df in defs: 175 | 176 | if isinstance(df, ast.RuleNode): 177 | 178 | label, l, r = df 179 | rr = build_rule(l, r, cons) 180 | 181 | if label in env: 182 | env[label].add(rr) 183 | else: 184 | env[label] = RuleBlock([rr], label=label) 185 | 186 | elif isinstance(df, ast.StrategyNode): 187 | label, comb, args = df 188 | 189 | if label in env: 190 | raise Exception, "Strategy definition '%s' already defined" % label 191 | 192 | st = build_strategy(label, env, comb, args) 193 | env[label] = st 194 | 195 | else: 196 | raise NotImplementedError 197 | 198 | return env 199 | -------------------------------------------------------------------------------- /rewrite/matching.py: -------------------------------------------------------------------------------- 1 | from terms import * # TODO: tsk, tsk 2 | import astnodes as ast 3 | 4 | placeholders = { 5 | 'appl' : aappl, 6 | 'str' : astr, 7 | 'int' : aint, 8 | 'real' : areal, 9 | 'term' : (aterm, aappl, astr, aint, areal), 10 | 'placeholder' : aplaceholder, 11 | 'list' : alist 12 | } 13 | 14 | class NoMatch(Exception): 15 | pass 16 | 17 | #------------------------------------------------------------------------ 18 | # Traversal 19 | #------------------------------------------------------------------------ 20 | 21 | def init(xs): 22 | for x in xs: 23 | return x 24 | 25 | def aterm_zip(a, b): 26 | if isinstance(a, (aint, areal, astr)) and isinstance(b, (aint, areal, astr)): 27 | yield a.val == b.val, None 28 | 29 | elif isinstance(a, aterm) and isinstance(b, aterm): 30 | yield a.term == b.term, None 31 | yield a.annotation == b.annotation, None 32 | 33 | elif isinstance(a, aappl) and isinstance(b, aappl): 34 | if len(a.args) == len(b.args): 35 | yield a.spine == b.spine, None 36 | for ai, bi in zip(a.args, b.args): 37 | for aj in aterm_zip(ai,bi): 38 | yield aj 39 | else: 40 | yield False, None 41 | 42 | elif isinstance(a, atupl) and isinstance(b, atupl): 43 | if len(a.args) == len(b.args): 44 | for ai, bi in zip(a.args, b.args): 45 | for aj in aterm_zip(ai,bi): 46 | yield aj 47 | else: 48 | yield False, None 49 | 50 | elif isinstance(a, aplaceholder): 51 | # 52 | if a.args: 53 | if isinstance(b, aappl): 54 | yield True, b.spine 55 | for ai, bi in zip(a.args, b.args): 56 | for a in aterm_zip(ai,bi): 57 | yield a 58 | else: 59 | yield False, None 60 | # 61 | else: 62 | yield isinstance(b, placeholders[a.type]), b 63 | else: 64 | yield False, None 65 | 66 | 67 | # left-to-right substitution 68 | def aterm_splice(a, elts): 69 | 70 | if isinstance(a, aterm): 71 | yield a 72 | 73 | elif isinstance(a, (aint, areal, astr)): 74 | yield a 75 | 76 | elif isinstance(a, aappl): 77 | yield aappl(a.spine, [init(aterm_splice(ai,elts)) for ai in a.args]) 78 | 79 | elif isinstance(a, atupl): 80 | yield atupl([init(aterm_splice(ai,elts)) for ai in a.args]) 81 | 82 | elif isinstance(a, aplaceholder): 83 | # 84 | if a.args: 85 | spine = elts.pop(0) 86 | yield aappl(spine, [init(aterm_splice(ai,elts)) for ai in a.args]) 87 | # 88 | else: 89 | yield elts.pop(0) 90 | else: 91 | raise NotImplementedError 92 | 93 | #------------------------------------------------------------------------ 94 | # Rewriting 95 | #------------------------------------------------------------------------ 96 | 97 | # TODO: warn on nested as pattern 98 | def free(a): 99 | if isinstance(a, (aint, areal, astr)): 100 | pass 101 | 102 | elif isinstance(a, aappl): 103 | for ai in a.args: 104 | for aj in free(ai): 105 | yield aj 106 | 107 | elif isinstance(a, aterm): 108 | yield (a, a.term, aterm) 109 | 110 | elif isinstance(a, (alist,atupl)): 111 | for ai in a.args: 112 | for aj in free(ai): 113 | yield aj 114 | 115 | # ---- 116 | 117 | elif isinstance(a, ast.AsNode): 118 | if a.tag is not None: 119 | yield (a.pattern, a.tag, type(a.pattern)) 120 | else: 121 | if isinstance(a.pattern, aappl): 122 | # detached 123 | head = a.pattern.spine 124 | yield (head, head.term, aterm) 125 | for ai in a.pattern.args: 126 | for aj in free(ai): 127 | yield aj 128 | 129 | else: 130 | raise NotImplementedError 131 | 132 | 133 | def freev(a): 134 | if isinstance(a, (aint, areal, astr)): 135 | return a 136 | 137 | elif isinstance(a, aappl): 138 | return aappl(a.spine, [freev(ai) for ai in a.args]) 139 | 140 | elif isinstance(a, alist): 141 | return alist([freev(ai) for ai in a.args]) 142 | 143 | elif isinstance(a, atupl): 144 | return atupl([freev(ai) for ai in a.args]) 145 | 146 | elif isinstance(a, aterm): 147 | return aplaceholder('term', None) 148 | 149 | # ---- 150 | 151 | elif isinstance(a, ast.AsNode): 152 | # TODO: need to define traversal 153 | if a.tag is not None: 154 | return aplaceholder('term', None) 155 | else: 156 | return aplaceholder('appl', [freev(ai) for ai in a.pattern.args]) 157 | 158 | else: 159 | raise NotImplementedError 160 | 161 | #------------------------------------------------------------------------ 162 | # Rewriting 163 | #------------------------------------------------------------------------ 164 | 165 | def unfold(lpat, p, s): 166 | bindings = {} 167 | li = iter(lpat) 168 | 169 | for matches, capture in aterm_zip(p,s): 170 | if not matches: 171 | raise NoMatch() 172 | elif matches and capture: 173 | bind = next(li) 174 | # check non-linear or nested patterns 175 | if bind in bindings: 176 | if capture == bindings[bind]: 177 | yield (bind, capture) 178 | else: 179 | raise NoMatch() 180 | # flat patterns 181 | else: 182 | bindings[bind] = capture 183 | yield (bind, capture) 184 | 185 | def fold(rpat, subst, cap): 186 | stack = dict(cap) 187 | 188 | vals = [stack[s] for s in rpat] 189 | 190 | return init(aterm_splice(subst,vals)) 191 | 192 | def hylo(ana, cata, s): 193 | return cata(ana(s)) 194 | -------------------------------------------------------------------------------- /rewrite/parse.py: -------------------------------------------------------------------------------- 1 | """ 2 | ATerm parser 3 | 4 | t : bt -- basic term 5 | | bt {ty,m1,...} -- annotated term 6 | 7 | bt : C -- constant 8 | | C(t1,...,tn) -- n-ary constructor 9 | | (t1,...,tn) -- n-ary tuple 10 | | [t1,...,tn] -- list 11 | | "ccc" -- quoted string ( explicit double quotes ) 12 | | int -- integer 13 | | real -- floating point number 14 | 15 | """ 16 | 17 | import os 18 | import re 19 | import sys 20 | from functools import partial 21 | 22 | import terms as aterm 23 | 24 | # Precompiled modules 25 | import _alex 26 | import _ayacc 27 | from plyhacks import yaccfrom, lexfrom 28 | 29 | DEBUG = True 30 | 31 | #------------------------------------------------------------------------ 32 | # Errors 33 | #------------------------------------------------------------------------ 34 | 35 | syntax_error = """ 36 | 37 | File {filename}, line {lineno} 38 | {line} 39 | {pointer} 40 | 41 | ATermSyntaxError: {msg} 42 | """ 43 | 44 | class AtermSyntaxError(Exception): 45 | """ 46 | Makes aterm parse errors look like Python SyntaxError. 47 | """ 48 | def __init__(self, lineno, col_offset, filename, text, msg=None): 49 | self.lineno = lineno 50 | self.col_offset = col_offset 51 | self.filename = filename 52 | self.text = text 53 | self.msg = msg or 'invalid syntax' 54 | 55 | def __str__(self): 56 | return syntax_error.format( 57 | filename = self.filename, 58 | lineno = self.lineno, 59 | line = self.text, 60 | pointer = ' '*self.col_offset + '^', 61 | msg = self.msg 62 | ) 63 | 64 | #------------------------------------------------------------------------ 65 | # Lexer 66 | #------------------------------------------------------------------------ 67 | 68 | tokens = ( 69 | 'NAME', 'INT', 'DOUBLE', 'PLACEHOLDER', 'STRING' 70 | ) 71 | 72 | literals = [ 73 | ',' , 74 | '(' , 75 | ')' , 76 | '{' , 77 | '}' , 78 | '<' , 79 | '>' , 80 | '[' , 81 | ']' , 82 | ] 83 | 84 | t_NAME = r'[a-zA-Z_][a-zA-Z0-9_]*' 85 | t_ignore = '\x20\x09\x0A\x0D' 86 | 87 | unquote = re.compile('"(?:[^\']*)\'|"([^"]*)"') 88 | 89 | def t_DOUBLE(t): 90 | r'\d+\.(\d+)?' 91 | t.value = float(t.value) 92 | return t 93 | 94 | def t_PLACEHOLDER(t): 95 | r'appl|str|int|real|placeholder|appl|list|term' 96 | return t 97 | 98 | def t_INT(t): 99 | r'\d+' 100 | try: 101 | t.value = int(t.value) 102 | except ValueError: 103 | print("Integer value too large %d", t.value) 104 | t.value = 0 105 | return t 106 | 107 | def t_STRING(t): 108 | r'"([^"\\]|\\.)*"' 109 | t.value = t.value.encode('ascii') 110 | t.value = unquote.findall(t.value)[0] 111 | return t 112 | 113 | def t_error(t): 114 | print("Unknown token '%s'" % t.value[0]) 115 | t.lexer.skip(1) 116 | 117 | # Top of the parser 118 | def p_expr1(p): 119 | """expr : avalue 120 | | value""" 121 | p[0] = p[1] 122 | 123 | #-------------------------------- 124 | 125 | def p_avalue(p): 126 | "avalue : value '{' annotation '}'" 127 | p[0] = aterm.aterm(p[1], p[3]) 128 | 129 | def p_value(p): 130 | """value : term 131 | | appl 132 | | list 133 | | tuple 134 | | string 135 | | placeholder 136 | | empty""" 137 | p[0] = p[1] 138 | 139 | #-------------------------------- 140 | 141 | def p_term_double(p): 142 | "term : DOUBLE" 143 | p[0] = aterm.areal(p[1]) 144 | 145 | def p_term_int(p): 146 | "term : INT" 147 | p[0] = aterm.aint(p[1]) 148 | 149 | def p_term_term(p): 150 | "term : NAME" 151 | p[0] = aterm.aterm(p[1], None) 152 | 153 | #-------------------------------- 154 | 155 | # Terms in annotations must not be themselves be annotated, i.e. 156 | # they must be ``value``, not ``avalue``. 157 | def p_annotation1(p): 158 | "annotation : value" 159 | p[0] = (p[1],) 160 | 161 | def p_annotation2(p): 162 | "annotation : annotation ',' annotation" 163 | p[0] = (p[1], p[3]) 164 | 165 | #-------------------------------- 166 | 167 | def p_appl(p): 168 | "appl : term '(' appl_value ')' " 169 | p[0] = aterm.aappl(p[1], p[3]) 170 | 171 | def p_appl_value1(p): 172 | "appl_value : expr" 173 | if p[1]: 174 | p[0] = [p[1]] 175 | else: 176 | p[0] = [] 177 | 178 | def p_appl_value2(p): 179 | "appl_value : appl_value ',' appl_value" 180 | p[0] = p[1] + p[3] 181 | 182 | #-------------------------------- 183 | 184 | def p_list(p): 185 | "list : '[' list_value ']' " 186 | p[0] = aterm.alist(p[2]) 187 | 188 | def p_list_value1(p): 189 | "list_value : expr" 190 | if p[1]: 191 | p[0] = [p[1]] 192 | else: 193 | p[0] = [] 194 | 195 | def p_list_value2(p): 196 | "list_value : list_value ',' list_value" 197 | p[0] = p[1] + p[3] 198 | 199 | #-------------------------------- 200 | 201 | def p_tuple(p): 202 | "tuple : '(' tuple_value ')' " 203 | p[0] = aterm.atupl(p[2]) 204 | 205 | def p_tuple_value1(p): 206 | "tuple_value : expr" 207 | if p[1]: 208 | p[0] = [p[1]] 209 | else: 210 | p[0] = [] 211 | 212 | def p_tuple_value2(p): 213 | "tuple_value : tuple_value ',' tuple_value" 214 | p[0] = p[1] + p[3] 215 | 216 | #-------------------------------- 217 | 218 | def p_string(p): 219 | "string : STRING" 220 | p[0] = aterm.astr(p[1]) 221 | 222 | #-------------------------------- 223 | 224 | def p_placeholder1(p): 225 | "placeholder : '<' PLACEHOLDER '(' appl_value ')' '>'" 226 | p[0] = aterm.aplaceholder(p[2], p[4]) 227 | 228 | def p_placeholder2(p): 229 | "placeholder : '<' PLACEHOLDER '>'" 230 | p[0] = aterm.aplaceholder(p[2], None) 231 | 232 | #-------------------------------- 233 | 234 | def p_empty(t): 235 | "empty : " 236 | pass 237 | 238 | #-------------------------------- 239 | 240 | def p_error(p): 241 | if p: 242 | raise AtermSyntaxError( 243 | p.lineno, 244 | p.lexpos, 245 | '', 246 | p.lexer.lexdata, 247 | ) 248 | else: 249 | raise SyntaxError("Syntax error at EOF") 250 | 251 | #-------------------------------- 252 | 253 | def load_parser(debug=False): 254 | if debug: 255 | from ply import lex, yacc 256 | path = os.path.abspath(__file__) 257 | dir_path = os.path.dirname(path) 258 | lexer = lex.lex(lextab="_alex", outputdir=dir_path, optimize=1) 259 | parser = yacc.yacc(tabmodule='_ayacc',outputdir=dir_path, 260 | write_tables=1, debug=0, optimize=1) 261 | return partial(parser.parse, lexer=lexer) 262 | else: 263 | module = sys.modules[__name__] 264 | lexer = lexfrom(module, _alex) 265 | parser = yaccfrom(module, _ayacc, lexer) 266 | 267 | # curry the lexer into the parser 268 | return partial(parser.parse, lexer=lexer) 269 | 270 | def parse(pattern): 271 | parser = load_parser() 272 | return parser(pattern) 273 | -------------------------------------------------------------------------------- /rewrite/plyhacks.py: -------------------------------------------------------------------------------- 1 | """ 2 | Build a ply lexer, but without the implicit magic and global 3 | state, just load prebuilt ply parser and lexers at roughly the 4 | same cost of loading a Python module. 5 | """ 6 | 7 | import functools 8 | from ply.lex import Lexer, LexerReflect 9 | from ply.yacc import ParserReflect, LRTable, LRParser 10 | 11 | def memoize(obj): 12 | cache = obj.cache = {} 13 | @functools.wraps(obj) 14 | def memoizer(*args, **kwargs): 15 | if args not in cache: 16 | cache[args] = obj(*args, **kwargs) 17 | return cache[args] 18 | return memoizer 19 | 20 | # lexer is passed as argument to ensure that memoization is 21 | # unique for parser/lexer pair. 22 | 23 | @memoize 24 | def yaccfrom(module, tabmodule, lexer): 25 | # Get the module dictionary used for the parser 26 | _items = [(k,getattr(module,k)) for k in dir(module)] 27 | pdict = dict(_items) 28 | 29 | # Collect parser information from the dictionary 30 | pinfo = ParserReflect(pdict) 31 | pinfo.get_all() 32 | 33 | # Read the tables 34 | lr = LRTable() 35 | lr.read_table(tabmodule) 36 | 37 | lr.bind_callables(pinfo.pdict) 38 | return LRParser(lr,pinfo.error_func) 39 | 40 | @memoize 41 | def lexfrom(module, lexmodule): 42 | lexobj = Lexer() 43 | lexobj.lexoptimize = 1 44 | 45 | _items = [(k,getattr(module,k)) for k in dir(module)] 46 | ldict = dict(_items) 47 | 48 | # Collect parser information from the dictionary 49 | linfo = LexerReflect(ldict) 50 | linfo.get_all() 51 | 52 | lexobj.readtab(lexmodule,ldict) 53 | return lexobj 54 | -------------------------------------------------------------------------------- /rewrite/prelude: -------------------------------------------------------------------------------- 1 | # Language defines the base combinators: 2 | # 3 | # fail(s) 4 | # id(s) 5 | # repeat(s) 6 | # not(s) 7 | # rec x(s) 8 | # all(s) 9 | # one(s) 10 | 11 | # s1;s2 12 | # s1<+s2 13 | # s1+s2 14 | # s1 1: 401 | files = sys.argv[1:] 402 | else: 403 | testdir = "tests" 404 | files = glob.glob(testdir + "/*.asdl") 405 | 406 | for file in files: 407 | print file 408 | mod = parse(file) 409 | print "module", mod.name 410 | print len(mod.dfns), "definitions" 411 | if not check(mod): 412 | print "Check failed" 413 | else: 414 | for dfn in mod.dfns: 415 | print dfn.type 416 | -------------------------------------------------------------------------------- /rewrite/pyast/ast_utils.py: -------------------------------------------------------------------------------- 1 | import ast 2 | import pprint 3 | from types import FunctionType, LambdaType 4 | 5 | # backported from Numba 6 | 7 | def ast2tree(node, include_attrs = True): 8 | def _transform(node): 9 | if isinstance(node, ast.AST): 10 | fields = ((a, _transform(b)) 11 | for a, b in ast.iter_fields(node)) 12 | if include_attrs: 13 | attrs = ((a, _transform(getattr(node, a))) 14 | for a in node._attributes 15 | if hasattr(node, a)) 16 | return (node.__class__.__name__, dict(fields), dict(attrs)) 17 | return (node.__class__.__name__, dict(fields)) 18 | elif isinstance(node, list): 19 | return [_transform(x) for x in node] 20 | return node 21 | if not isinstance(node, ast.AST): 22 | raise TypeError('expected AST, got %r' % node.__class__.__name__) 23 | return _transform(node) 24 | 25 | def pformat_ast (node, include_attrs = False, **kws): 26 | return pprint.pformat(ast2tree(node, include_attrs), **kws) 27 | 28 | def dump(node): 29 | print pformat_ast(node) 30 | 31 | def decompile(fn): 32 | from meta.decompiler import decompile_func 33 | assert isinstance(fn, (FunctionType, LambdaType)), \ 34 | 'Can only decompilefunction type' 35 | return pformat_ast(decompile_func(fn)) 36 | -------------------------------------------------------------------------------- /rewrite/pyast/nodes.py: -------------------------------------------------------------------------------- 1 | Python = { 2 | 'Add': (), 3 | 'And': (), 4 | 'Assert': ('test', 'msg'), 5 | 'Assign': ('targets', 'value'), 6 | 'Attribute': ('value', 'attr', 'ctx'), 7 | 'AugAssign': ('target', 'op', 'value'), 8 | 'AugLoad': (), 9 | 'AugStore': (), 10 | 'BinOp': ('left', 'op', 'right'), 11 | 'BitAnd': (), 12 | 'BitOr': (), 13 | 'BitXor': (), 14 | 'BoolOp': ('op', 'values'), 15 | 'Break': (), 16 | 'Call': ('func', 'args', 'keywords', 'starargs', 'kwargs'), 17 | 'ClassDef': ('name', 'bases', 'body', 'decorator_list'), 18 | 'Compare': ('left', 'ops', 'comparators'), 19 | 'Continue': (), 20 | 'Del': (), 21 | 'Delete': ('targets',), 22 | 'Dict': ('keys', 'values'), 23 | 'DictComp': ('key', 'value', 'generators'), 24 | 'Div': (), 25 | 'Ellipsis': (), 26 | 'Eq': (), 27 | 'ExceptHandler': ('type', 'name', 'body'), 28 | 'Exec': ('body', 'globals', 'locals'), 29 | 'Expr': ('value',), 30 | 'Expression': ('body',), 31 | 'ExtSlice': ('dims',), 32 | 'FloorDiv': (), 33 | 'For': ('target', 'iter', 'body', 'orelse'), 34 | 'FunctionDef': ('name', 'args', 'body', 'decorator_list'), 35 | 'GeneratorExp': ('elt', 'generators'), 36 | 'Global': ('names',), 37 | 'Gt': (), 38 | 'GtE': (), 39 | 'If': ('test', 'body', 'orelse'), 40 | 'IfExp': ('test', 'body', 'orelse'), 41 | 'Import': ('names',), 42 | 'ImportFrom': ('module', 'names', 'level'), 43 | 'In': (), 44 | 'Index': ('value',), 45 | 'Interactive': ('body',), 46 | 'Invert': (), 47 | 'Is': (), 48 | 'IsNot': (), 49 | 'LShift': (), 50 | 'Lambda': ('args', 'body'), 51 | 'List': ('elts', 'ctx'), 52 | 'ListComp': ('elt', 'generators'), 53 | 'Load': (), 54 | 'Lt': (), 55 | 'LtE': (), 56 | 'Mod': (), 57 | 'Module': ('body',), 58 | 'Mult': (), 59 | 'Name': ('id', 'ctx'), 60 | 'Not': (), 61 | 'NotEq': (), 62 | 'NotIn': (), 63 | 'Num': ('n',), 64 | 'Or': (), 65 | 'Param': (), 66 | 'Pass': (), 67 | 'Pow': (), 68 | 'Print': ('dest', 'values', 'nl'), 69 | 'RShift': (), 70 | 'Raise': ('type', 'inst', 'tback'), 71 | 'Repr': ('value',), 72 | 'Return': ('value',), 73 | 'Set': ('elts',), 74 | 'SetComp': ('elt', 'generators'), 75 | 'Slice': ('lower', 'upper', 'step'), 76 | 'Store': (), 77 | 'Str': ('s',), 78 | 'Sub': (), 79 | 'Subscript': ('value', 'slice', 'ctx'), 80 | 'Suite': ('body',), 81 | 'TryExcept': ('body', 'handlers', 'orelse'), 82 | 'TryFinally': ('body', 'finalbody'), 83 | 'Tuple': ('elts', 'ctx'), 84 | 'UAdd': (), 85 | 'USub': (), 86 | 'UnaryOp': ('op', 'operand'), 87 | 'While': ('test', 'body', 'orelse'), 88 | 'With': ('context_expr', 'optional_vars', 'body'), 89 | 'Yield': ('value',), 90 | } 91 | -------------------------------------------------------------------------------- /rewrite/pysdf/Python.sdf: -------------------------------------------------------------------------------- 1 | module Python 2 | 3 | %% http://docs.python.org/release/3.2.3/reference/grammar.html 4 | %% 5 | %% hand-written c implementation: 6 | %% http://svn.python.org/projects/python/trunk/Modules/parsermodule.c 7 | exports 8 | 9 | %% # Grammar for Python 10 | 11 | %% # Note: Changing the grammar specified in this file will most likely 12 | %% # require corresponding changes in the parser module 13 | %% # (../Modules/parsermodule.c). If you can't make the changes to 14 | %% # that module yourself, please co-ordinate the required changes 15 | %% # with someone who can; ask around on python-dev for help. Fred 16 | %% # Drake will probably be listening there. 17 | 18 | %% # NOTE WELL: You should also follow all the steps listed in PEP 306, 19 | %% # "How to Change Python's Grammar" 20 | 21 | %% # Start symbols for the grammar: 22 | %% # single_input is a single interactive statement; 23 | %% # file_input is a module or sequence of commands read from an input file; 24 | %% # eval_input is the input for the eval() and input() functions. 25 | %% # NB: compoundStmt in single_input is followed by extra NEWLINE! 26 | 27 | context-free start-symbols 28 | FileInput 29 | 30 | context-free syntax 31 | -> NEWLINE 32 | 33 | Stmt -> FileLine 34 | FileLine* -> FileInput {layout("all(x,1,1.first.col == x.first.col)")} 35 | 36 | %% decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE 37 | %% decorators: decorator+ 38 | %% decorated: decorators (classdef | funcdef) 39 | "def" Name Parameters ResSpec? ":" SimpleStmt -> Funcdef {cons("Funcdef"), 40 | layout("1.last.line == 2.first.line && 2.last.line == 3.first.line && 3.last.line == 4.first.line && 4.last.line == 5.first.line && 5.first.line == 6.first.line")} 41 | "def" Name Parameters ResSpec? ":" Suite -> Funcdef {cons("Funcdef"), 42 | layout("1.last.line == 2.first.line && 2.last.line == 3.first.line && 3.last.line == 4.first.line && 4.last.line == 5.first.line && 5.first.line < 6.first.line && 1.first.col < 6.first.col")} 43 | 44 | "->" Test -> ResSpec 45 | 46 | "(" Typedargslist? ")" -> Parameters {ignore-layout} 47 | (Tfpdef ("=" Test)? ("," Tfpdef ("=" Test)?)* ("," 48 | ("*" (Tfpdef)? ("," Tfpdef ("=" Test)?)* ("," "**" Tfpdef)? | "**" Tfpdef)?)? 49 | | "*" (Tfpdef)? ("," Tfpdef ("=" Test)?)* ("," "**" Tfpdef)? | "**" Tfpdef) -> Typedargslist 50 | Name -> Tfpdef 51 | Name ":" Test -> Tfpdef 52 | 53 | Vfpdef ("=" Test)? ("," Vfpdef ("=" Test)?)* ("," 54 | ("*" (Vfpdef)? ("," Vfpdef ("=" Test)?)* ("," "**" Vfpdef)? | "**" Vfpdef)?)? 55 | | "*" (Vfpdef)? ("," Vfpdef ("=" Test)?)* ("," "**" Vfpdef)? | "**" Vfpdef -> Varargslist 56 | Name -> Vfpdef 57 | 58 | SimpleStmt -> Stmt 59 | CompoundStmt -> Stmt 60 | 61 | {SmallStmt ";"}+ -> SimpleStmt {cons("SimpleStmt")} 62 | {SmallStmt ";"}+ ";" -> SimpleStmt {cons("SimpleStmt")} 63 | 64 | ExprStmt | DelStmt | PassStmt | FlowStmt | ImportStmt | GlobalStmt | NonlocalStmt | AssertStmt -> SmallStmt 65 | {layout("1.first.line == 1.last.line")} 66 | 67 | TestlistStarExpr Augassign YieldExpr -> ExprStmt {cons("AssignAugYieldStmt")} 68 | TestlistStarExpr Augassign Testlist -> ExprStmt {cons("AssignAugTestlistStmt")} 69 | TestlistStarExpr Assign+ -> ExprStmt {cons("AssignEqStmt")} 70 | TestlistStarExpr -> ExprStmt 71 | 72 | 73 | "=" YieldExpr -> Assign {cons("AssignYield")} 74 | "=" TestlistStarExpr -> Assign {cons("AssignTestlist")} 75 | 76 | Test -> TestStarExpr 77 | StarExpr -> TestStarExpr 78 | {TestStarExpr ";"}+ -> TestlistStarExpr {cons("TestlistStarExpr")} 79 | {TestStarExpr ";"}+ "," -> TestlistStarExpr {cons("TestlistStarExpr")} 80 | 81 | %% # For normal assignments, additional restrictions enforced by the interpreter 82 | "del" Exprlist -> DelStmt {cons("DelStmt")} 83 | "pass" -> PassStmt {cons("PassStmt")} 84 | BreakStmt | ContinueStmt | ReturnStmt | RaiseStmt | YieldStmt -> FlowStmt 85 | 86 | "break" -> BreakStmt {cons("BreakStmt")} 87 | "continue" -> ContinueStmt {cons("ContinueStmt")} 88 | "return" Testlist? -> ReturnStmt {cons("ReturnStmt")} 89 | YieldExpr -> YieldStmt {cons("YieldStmt")} 90 | "raise" (Test ("from" Test)?)? -> RaiseStmt {cons("RaiseStmt")} 91 | 92 | context-free syntax %% import stuff 93 | ImportName | ImportFrom -> ImportStmt {cons("ImportStmt")} 94 | "import" DottedAsNames -> ImportName {cons("ImportName")} 95 | 96 | %% # note below: the ("." | "...") is necessary because "..." is tokenized as ELLIPSIS 97 | %% import_from: ("from" (("." | "...")* dottedName | ("." | "...")+) 98 | %% "import" ("*" | "(" importAsNames ")" | importAsNames)) 99 | "from" ("."* DottedName | "."+) "import" ("*" | "(" ImportAsNames ")" | ImportAsNames) -> ImportFrom {cons("ImportFrom")} 100 | Name -> ImportAsName {cons("ImportAsName1")} 101 | Name "as" Name -> ImportAsName {cons("ImportAsName2")} 102 | DottedName -> DottedAsName {cons("DottedAsName1")} 103 | DottedName "as" Name -> DottedAsName {cons("DottedAsName2")} 104 | {ImportAsName ","}+ -> ImportAsNames {cons("ImportAsNames")} 105 | {ImportAsName ","}+ "," -> ImportAsNames {cons("ImportAsNames")} 106 | {DottedAsName ","}+ -> DottedAsNames {cons("DottedAsNames")} 107 | {Name "."}+ -> DottedName {cons("DottedName")} 108 | 109 | context-free syntax 110 | "global" {Name ","}+ -> GlobalStmt {cons("GlobalStmt")} 111 | "nonlocal" {Name ","}+ -> NonlocalStmt {cons("NonlocalStmt")} 112 | "assert" Test -> AssertStmt {cons("AssertStmt1")} 113 | "assert" Test "," Test -> AssertStmt {cons("AssertStmt2")} 114 | 115 | 116 | context-free syntax %% compound stmts 117 | 118 | IfStmt | WhileStmt | ForStmt | TryStmt | WithStmt | Funcdef | Classdef -> CompoundStmt 119 | %% Decorated -> CompoundStmt 120 | 121 | "if" Test ":" SimpleStmt Elif* Else? -> IfStmt {cons("IfStmt"), 122 | layout("1.last.line == 2.first.line && 2.last.line == 3.first.line && 3.last.line == 4.first.line && all(x,5,1.first.col==x.first.col) && 1.first.col == 6.first.col")} 123 | "if" Test ":" Suite Elif* Else? -> IfStmt {cons("IfStmt"), 124 | layout("1.last.line == 2.first.line && 2.last.line == 3.first.line && 3.last.line < 4.first.line && 1.first.col < 4.first.col && all(x,5,1.first.col==x.first.col) && 1.first.col == 6.first.col")} 125 | 126 | "elif" Test ":" SimpleStmt -> Elif {cons("Elif"), 127 | layout("1.last.line == 2.first.line && 2.last.line == 3.first.line && 3.last.line == 4.first.line")} 128 | "elif" Test ":" Suite -> Elif {cons("Elif"), 129 | layout("1.last.line == 2.first.line && 2.last.line == 3.first.line && 3.last.line < 4.first.line && 1.first.col < 4.first.col")} 130 | "else" ":" SimpleStmt -> Else {cons("Else"), 131 | layout("1.last.line == 2.first.line && 2.last.line == 3.first.line")} 132 | "else" ":" Suite -> Else {cons("Else"), layout("1.first.col < 4.first.col"), 133 | layout("1.last.line == 2.first.line && 2.last.line < 3.first.line && 1.first.col < 3.first.col")} 134 | 135 | "while" Test ":" SimpleStmt Else? -> WhileStmt {cons("WhileStmt"), layout("1.first.col == 5.first.col")} 136 | "while" Test ":" NEWLINE Suite Else? -> WhileStmt {cons("WhileStmt"), 137 | layout("1.first.col < 5.first.col && 1.first.col == 6.first.col")} 138 | 139 | "for" Exprlist "in" Testlist ":" SimpleStmt Else? -> ForStmt {cons("ForStmt"), layout("1.first.col == 8.first.col")} 140 | "for" Exprlist "in" Testlist ":" NEWLINE Suite Else? -> ForStmt {cons("ForStmt"), 141 | layout("1.first.col < 7.first.col && 1.first.col == 8.first.col")} 142 | 143 | "try" ":" SimpleStmt Finally? -> TryStmt {cons("TryFinallyStmt"), layout("1.first.col == 4.first.col")} 144 | "try" ":" NEWLINE Suite Finally? -> TryStmt {cons("TryFinallyStmt"), 145 | layout("1.first.col < 4.first.col && 1.first.col == 5.first.col")} 146 | "try" ":" SimpleStmt Except+ Else? Finally? -> TryStmt {cons("TryExceptStmt"), 147 | layout("all(x,4,1.first.col==x.first.col) && 1.first.col == 5.first.col && 1.first.col == 7.first.col")} 148 | "try" ":" NEWLINE Suite Except+ Else? Finally? -> TryStmt {cons("TryExceptStmt"), 149 | layout("1.first.col < 4.first.col && all(x,5,1.first.col==x.first.col) && 1.first.col == 6.first.col && 1.first.col == 7.first.col")} 150 | 151 | "finally" ":" SimpleStmt -> Finally {cons("Finally")} 152 | "finally" ":" NEWLINE Suite -> Finally {cons("Finally"), layout("1.first.col < 4.first.col")} 153 | ExceptClause ":" SimpleStmt -> Except {cons("Except")} 154 | ExceptClause ":" NEWLINE Suite -> Except {cons("Except"), layout("1.first.col < 4.first.col")} 155 | "except" -> ExceptClause {cons("Except0")} 156 | "except" Test -> ExceptClause {cons("Except1")} 157 | "except" Test "as" Name -> ExceptClause {cons("Except2")} 158 | 159 | "with" {WithItem ","}+ ":" SimpleStmt -> WithStmt {cons("WithStmt")} 160 | "with" {WithItem ","}+ ":" NEWLINE Suite -> WithStmt {cons("WithStmt"), layout("1.first.col < 5.first.col")} 161 | Test -> WithItem {cons("WithItem")} 162 | Test "as" Expr -> WithItem {cons("WithItemAs")} 163 | 164 | %% # NB compile.c makes sure that the default except clause is last 165 | 166 | Stmt+ -> Suite {cons("StmtListSuite"), layout("all(x, 1, 1.first.col == x.first.col)")} 167 | 168 | 169 | OrTest -> Test {layout("1.first.line == 1.last.line")} 170 | "---" -> OrTest 171 | OrTest "if" OrTest "else" Test -> Test {cons("OrIfTest")} 172 | Lambdef -> Test {cons("LambDefTest")} 173 | OrTest | LambdefNocond -> TestNocond 174 | "lambda" Varargslist? ":" Test -> Lambdef {cons("Lambdef")} 175 | "lambda" Varargslist? ":" TestNocond -> LambdefNocond 176 | {AndTest "or"}+ -> OrTest {cons("OrTest")} 177 | {NotTest "and"}+ -> AndTest {cons("AndTest")} 178 | "not" NotTest -> NotTest {cons("NotTest")} 179 | Expr -> NotTest 180 | 181 | "*" Expr -> StarExpr {cons("StarExpr")} 182 | Expr -> ExprStarExpr 183 | StarExpr -> ExprStarExpr 184 | "yield" Testlist? -> YieldExpr {cons("YieldExpr")} 185 | 186 | context-free priorities 187 | Atom Trailer* -> Expr {cons("TrailerExpr")} 188 | > Expr "**" Expr -> Expr {cons("PowerExpr")} 189 | > 190 | { right: 191 | Expr "*" Expr -> Expr {cons("MultExpr"), right} 192 | Expr "//" Expr -> Expr {cons("Div2Expr"), right} 193 | Expr "/" Expr -> Expr {cons("DivExpr"), right} 194 | Expr "%" Expr -> Expr {cons("DivExpr"), right} 195 | } 196 | > 197 | { right: 198 | Expr "+" Expr -> Expr {cons("PlusExpr"), right} 199 | Expr "-" Expr -> Expr {cons("MinusExpr"), right} 200 | } 201 | > 202 | {right: 203 | Expr "<<" Expr -> Expr {cons("ShiftLExpr"), right} 204 | Expr ">>" Expr -> Expr {cons("ShiftRExpr"), right} 205 | } 206 | > Expr "&" Expr -> Expr {cons("AndExpr"), right} 207 | > Expr "^" Expr -> Expr {cons("XorExpr"), right} 208 | > Expr "|" Expr -> Expr {cons("OrExpr"), right} 209 | > Expr CompOp Expr -> Expr {cons("ComparisonExpr"), right} 210 | 211 | context-free syntax 212 | Name -> Atom {cons("Name")} 213 | Number -> Atom {cons("Number")} 214 | String -> Atom {cons("String")} 215 | "..." -> Atom {cons("Ellipsis")} 216 | "None" -> Atom {cons("None")} 217 | "True" -> Atom {cons("True")} 218 | "False" -> Atom {cons("False")} 219 | 220 | "(" ")" -> Atom {cons("EmptyParen")} 221 | "(" YieldExpr ")" -> Atom {cons("YieldParen"), ignore-layout} 222 | "(" TestlistComp ")" -> Atom {cons("TestlistCompParen"), ignore-layout} 223 | "[" TestlistComp "]" -> Atom {cons("TestlistCompParenQuestion"), ignore-layout} 224 | "{" "}" -> Atom {cons("EmptyBlock")} 225 | "{" DictSetmaker "}" -> Atom {cons("DictSetmakerBlock"), ignore-layout} 226 | 227 | TestStarExpr CompFor -> TestlistComp {cons("TestlistComp1")} 228 | {TestStarExpr ","}+ -> TestlistComp {cons("TestlistComp2")} 229 | {TestStarExpr ","}+ "," -> TestlistComp {cons("TestlistComp2")} 230 | 231 | "(" Arglist? ")" -> Trailer {cons("ArglistTrailer"), ignore-layout} 232 | "[" Subscriptlist "]" -> Trailer {cons("SubscriptlistTrailer"), ignore-layout} 233 | "." Name -> Trailer {cons("FieldTrailer")} 234 | 235 | {Subscript ","}+ -> Subscriptlist 236 | {Subscript ","}+ "," -> Subscriptlist 237 | 238 | Test -> Subscript 239 | Test? ":" Test? Sliceop? -> Subscript {cons("Subscript")} 240 | ":" Test? -> Sliceop {cons("Sliceop")} 241 | 242 | {ExprStarExpr ","}+ -> Exprlist 243 | {ExprStarExpr ","}+ "," -> Exprlist 244 | 245 | {Test ","}+ -> Testlist 246 | {Test ","}+ "," -> Testlist 247 | 248 | Test CompFor -> DictSetmaker {cons("DictSetmaker1")} 249 | {Test ","}+ -> DictSetmaker {cons("DictSetmaker2")} 250 | {Test ","}+ "," -> DictSetmaker {cons("DictSetmaker3")} 251 | Test ":" Test CompFor -> DictSetmaker {cons("DictSetmaker4")} 252 | Test ":" Test ("," Test ":" Test)* -> DictSetmaker {cons("DictSetmaker5")} 253 | Test ":" Test ("," Test ":" Test)* "," -> DictSetmaker {cons("DictSetmaker6")} 254 | 255 | "class" Name ArglistP? ":" NEWLINE Suite -> Classdef {cons("Classdef"), layout("1.first.col < 6.first.col")} 256 | "(" Arglist? ")" -> ArglistP {bracket, ignore-layout} 257 | 258 | {Argument ","}+ -> Arglist {cons("Arglist")} 259 | {Argument ","}+ "," -> Arglist {cons("Arglist")} 260 | (Argument ',')* '**' Test -> Arglist {cons("Arglist1")} 261 | (Argument ',')* '*' Test (',' Argument)* -> Arglist {cons("Arglist2")} 262 | (Argument ',')* '*' Test (',' Argument)* "," "**" Test -> Arglist {cons("Arglist3")} 263 | 264 | %% # The reason that keywords are Test nodes instead of NAME is that using NAME 265 | %% # results in an ambiguity. ast.c makes sure it"s a NAME. 266 | Test -> Argument {cons("Argument")} 267 | Test CompFor -> Argument {cons("ArgumentFor")} 268 | Name "=" Test -> Argument {cons("ArgumentAssign")} 269 | 270 | CompFor | CompIf -> CompIter 271 | "for" Exprlist "in" OrTest -> CompFor {cons("CompFor")} 272 | "for" Exprlist "in" OrTest CompIter -> CompFor {cons("CompForIter")} 273 | "if" TestNocond -> CompIf {cons("CompIf")} 274 | "if" TestNocond CompIter -> CompIf {cons("CompIfIter")} 275 | 276 | 277 | lexical syntax 278 | "+=" | "-=" | "*=" | "/=" | "%=" | "&=" | "|=" | "^=" | 279 | "<<=" | ">>=" | "**=" | "//=" -> Augassign 280 | 281 | %% # <> isn"t actually a valid comparison operator in Python. It"s here for the 282 | %% # sake of a __future__ import described in PEP 401 283 | "<"|">"|"=="|">="|"<="|"<>"|"!="|"in"|("not" LAYOUT "in")|"is"|("is" LAYOUT "not") -> CompOp 284 | 285 | [a-zA-Z\_][a-zA-Z0-9\_]* -> Name 286 | 287 | "'" ShortStringItem* "'" -> String 288 | "\"" ShortStringItem* "\"" -> String 289 | ~[\n\r\"\'\\] -> ShortStringItem 290 | "\\" ~[\n\r] -> ShortStringItem 291 | 292 | "0" | [1-9][0-9]* -> DecimalInteger 293 | "0" [0-7]+ -> OctInteger 294 | "0" ("x" | "X") [0-9a-fA-F]+ -> HexInteger 295 | 296 | DecimalInteger | OctInteger | HexInteger -> Number 297 | 298 | [\n\r\ \t] -> LAYOUT 299 | [\#] ~[\n\r]* [\n\r] -> LAYOUT 300 | 301 | lexical restrictions 302 | Name -/- [a-zA-Z0-9\_] 303 | DecimalInteger -/- [0-9] 304 | OctInteger -/- [0-7] 305 | HexInteger -/- [0-9a-fA-F] 306 | 307 | context-free restrictions 308 | LAYOUT? -/- [\ \t\n\r] | [\#].~[\n\r] 309 | 310 | lexical syntax 311 | "if" | "elif" | "else" | "while" | "for" | "def" | "return" | "pass" | "yield" 312 | | "break" | "continue" | "raise" -> Name {reject} 313 | -------------------------------------------------------------------------------- /rewrite/terms.py: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------------------ 2 | # Terms 3 | #------------------------------------------------------------------------ 4 | 5 | class ATerm(object): 6 | 7 | def __init__(self, term, annotation=None): 8 | self.term = term 9 | self.annotation = annotation 10 | 11 | def __str__(self): 12 | if self.annotation is not None: 13 | return str(self.term) + arepr([self.annotation], '{', '}') 14 | else: 15 | return str(self.term) 16 | 17 | def __eq__(self, other): 18 | if isinstance(other, ATerm): 19 | return self.term == other.term 20 | else: 21 | return False 22 | 23 | def __ne__(self, other): 24 | return not self == other 25 | 26 | def __repr__(self): 27 | return str(self) 28 | 29 | def __show__(self): 30 | pass 31 | 32 | class AAppl(object): 33 | 34 | def __init__(self, spine, args): 35 | assert isinstance(spine, ATerm) 36 | self.spine = spine 37 | self.args = args 38 | 39 | def __eq__(self, other): 40 | if isinstance(other, AAppl): 41 | return self.spine == other.spine and self.args == other.args 42 | else: 43 | return False 44 | 45 | def __ne__(self, other): 46 | return not self == other 47 | 48 | def __str__(self): 49 | return str(self.spine) + arepr(self.args, '(', ')') 50 | 51 | def __repr__(self): 52 | return str(self) 53 | 54 | def __show__(self): 55 | pass 56 | 57 | class AString(object): 58 | def __init__(self, val): 59 | assert isinstance(val, str) 60 | self.val = val 61 | 62 | def __str__(self): 63 | return '"%s"' % (self.val) 64 | 65 | def __repr__(self): 66 | return str(self) 67 | 68 | class AInt(object): 69 | def __init__(self, val): 70 | self.val = val 71 | 72 | def __str__(self): 73 | return str(self.val) 74 | 75 | def __eq__(self, other): 76 | if isinstance(other, AInt): 77 | return self.val == other.val 78 | else: 79 | return False 80 | 81 | def __ne__(self, other): 82 | return not self == other 83 | 84 | def __repr__(self): 85 | return str(self) 86 | 87 | class AReal(object): 88 | def __init__(self, val): 89 | self.val = val 90 | 91 | def __str__(self): 92 | return str(self.val) 93 | 94 | def __eq__(self, other): 95 | if isinstance(other, AReal): 96 | return self.val == other.val 97 | else: 98 | return False 99 | 100 | def __ne__(self, other): 101 | return not self == other 102 | 103 | def __repr__(self): 104 | return str(self) 105 | 106 | class AList(object): 107 | def __init__(self, args): 108 | assert isinstance(args, list) 109 | self.args = args or [] 110 | 111 | def __str__(self): 112 | return arepr(self.args, '[', ']') 113 | 114 | def __eq__(self, other): 115 | if isinstance(other, AList): 116 | return self.args == other.args 117 | else: 118 | return False 119 | 120 | def __ne__(self, other): 121 | return not self == other 122 | 123 | def __repr__(self): 124 | return str(self) 125 | 126 | class ATuple(object): 127 | def __init__(self, args): 128 | assert isinstance(args, list) 129 | self.args = args or [] 130 | 131 | def __eq__(self, other): 132 | if isinstance(other, ATuple): 133 | return self.args == other.args 134 | else: 135 | return False 136 | 137 | def __ne__(self, other): 138 | return not self == other 139 | 140 | def __str__(self): 141 | return arepr(self.args, '(', ')') 142 | 143 | def __repr__(self): 144 | return str(self) 145 | 146 | class APlaceholder(object): 147 | 148 | def __init__(self, type, args): 149 | self.type = type 150 | self.args = args 151 | 152 | def __str__(self): 153 | if self.args is not None: 154 | return '<%s(%r)>' % (self.type, self.args) 155 | else: 156 | return arepr([self.type], '<', '>') 157 | 158 | def __repr__(self): 159 | return str(self) 160 | 161 | #------------------------------------------------------------------------ 162 | # Pretty Printing 163 | #------------------------------------------------------------------------ 164 | 165 | def arepr(terms, l, r): 166 | """ Concatenate str representations with commas and left and right 167 | characters. """ 168 | return l + ', '.join(map(str, terms)) + r 169 | 170 | #------------------------------------------------------------------------ 171 | # Compatability 172 | #------------------------------------------------------------------------ 173 | 174 | # Goal is to only define the protocol that these need to conform 175 | # to and then allow pluggable backends. 176 | 177 | # - ATerm 178 | # - Python AST 179 | # - SymPy 180 | 181 | aterm = ATerm 182 | aappl = AAppl 183 | aint = AInt 184 | astr = AString 185 | areal = AReal 186 | atupl = ATuple 187 | alist = AList 188 | aplaceholder = APlaceholder 189 | -------------------------------------------------------------------------------- /rewrite/tests/test_dsl.py: -------------------------------------------------------------------------------- 1 | from rewrite import aparse 2 | from rewrite.dsl import dslparse, module 3 | 4 | #------------------------------------------------------------------------ 5 | 6 | simple = """ 7 | foo : A() -> B() 8 | foo : B() -> A() 9 | 10 | bar : Succ(0) -> 1 11 | bar : Succ(1) -> 2 12 | bar : Succ(x) -> Succ(Succ(x)) 13 | 14 | both : f(x,x) -> 1 15 | both : f(x,y) -> 0 16 | 17 | a0 = foo ; foo 18 | a1 = foo ; foo ; foo 19 | a2 = foo <+ foo ; foo 20 | """ 21 | 22 | def test_simple_parse(): 23 | dslparse(simple) 24 | 25 | def test_simple_module(): 26 | module(simple) 27 | 28 | #------------------------------------------------------------------------ 29 | 30 | patterns = """ 31 | EvalIf : 32 | If(False(), e1, e2) -> e2 33 | 34 | EvalIf : 35 | If(True(), e1, e2) -> e1 36 | 37 | PropIf : 38 | If(B,@F(X),@F(Y)) -> F(If(B,X,Y)) 39 | """ 40 | 41 | def test_patterns_parse(): 42 | dslparse(patterns) 43 | 44 | def test_patterns_module(): 45 | mod = module(patterns) 46 | 47 | #------------------------------------------------------------------------ 48 | 49 | simple_rr = """ 50 | foo : A() -> B() 51 | foo : B() -> C() 52 | 53 | bar = foo ; foo 54 | """ 55 | 56 | def test_rewrite_simple(): 57 | a = aparse('A()') 58 | b = aparse('B()') 59 | c = aparse('C()') 60 | 61 | mod = module(simple_rr) 62 | 63 | rule = mod['foo'] 64 | 65 | assert rule(a) == b 66 | assert rule(b) == c 67 | assert rule(rule(a)) == c 68 | 69 | def test_rewrite_simple2(): 70 | a = aparse('A()') 71 | b = aparse('B()') 72 | c = aparse('C()') 73 | 74 | mod = module(simple_rr) 75 | 76 | rule = mod['bar'] 77 | 78 | assert rule(a) == c 79 | 80 | #------------------------------------------------------------------------ 81 | 82 | complex_rr = """ 83 | foo : A(x,y) -> B(y,x) 84 | """ 85 | 86 | def test_rewrite_simple3(): 87 | a = aparse('A(1,2)') 88 | b = aparse('B(2,1)') 89 | 90 | mod = module(complex_rr) 91 | 92 | rule = mod['foo'] 93 | 94 | assert rule(a) == b 95 | 96 | #------------------------------------------------------------------------ 97 | 98 | #simple_bool = """ 99 | #Eval : Not(True) -> False 100 | #Eval : Not(False) -> True 101 | #""" 102 | # 103 | #def test_rewrite_bool(): 104 | # from collections import namedtuple 105 | # 106 | # t = namedtuple('True', ()) 107 | # f = namedtuple('False', ()) 108 | # 109 | # sorts = { 110 | # 'Bool': bool 111 | # } 112 | # 113 | # constructors = { 114 | # 'True' : t, 115 | # 'False' : f, 116 | # } 117 | # 118 | # mod = module(simple_bool, sorts, constructors) 119 | # 120 | # x = aparse('Not(True)') 121 | # 122 | # res = mod['Eval'](x) 123 | -------------------------------------------------------------------------------- /rewrite/tests/test_free.py: -------------------------------------------------------------------------------- 1 | from rewrite import aparse 2 | from rewrite import terms as ast 3 | from rewrite.dsl import dslparse 4 | from rewrite.matching import free, NoMatch 5 | from rewrite.dsl.toplevel import build_rule 6 | 7 | from nose.tools import assert_raises 8 | 9 | def test_linear(): 10 | x = aparse('x') 11 | y = aparse('y') 12 | 13 | a0 = aparse('f(x,y)') 14 | v = free(a0) 15 | 16 | assert list(v) == [ 17 | (x, 'x', ast.aterm), 18 | (y, 'y', ast.aterm) 19 | ] 20 | 21 | def test_nonlinear(): 22 | x = aparse('x') 23 | y = aparse('y') 24 | 25 | a0 = aparse('f(x,x,y)') 26 | v = free(a0) 27 | 28 | assert list(v) == [ 29 | (x, 'x', ast.aterm), 30 | (x, 'x', ast.aterm), 31 | (y, 'y', ast.aterm) 32 | ] 33 | 34 | def test_aspattern1(): 35 | x = aparse('x') 36 | 37 | a0 = dslparse('b: f(a@x) -> a') 38 | v = free(a0[0].lhs) 39 | 40 | assert list(v) == [ 41 | (x, 'a', ast.aterm) 42 | ] 43 | 44 | def test_aspattern2(): 45 | a0 = dslparse('b: @f(x,y) -> a') 46 | v = free(a0[0].lhs) 47 | 48 | f = aparse('f') 49 | x = aparse('x') 50 | y = aparse('y') 51 | 52 | assert list(v) == [ 53 | (f, 'f', ast.aterm), 54 | (x, 'x', ast.aterm), 55 | (y, 'y', ast.aterm) 56 | ] 57 | 58 | def test_aspattern3(): 59 | a0 = dslparse('b: a@f(x,y) -> a') 60 | v = free(a0[0].lhs) 61 | 62 | f = aparse('f(x,y)') 63 | 64 | assert list(v) == [ 65 | (f, 'a', ast.aappl) 66 | ] 67 | 68 | # -------- 69 | 70 | def test_rule1(): 71 | rule = dslparse('b: f(x,y) -> f(x,x,y,x,f(x,y))') 72 | l = rule[0].lhs 73 | r = rule[0].rhs 74 | 75 | rr = build_rule(l,r) 76 | 77 | sub = aparse('f(1,2)') 78 | res = aparse('f(1,1,2,1,f(1,2))') 79 | assert rr(sub) == res 80 | 81 | def test_rule2(): 82 | rule = dslparse('b: a@f(x,y) -> g(a,a(a))') 83 | l = rule[0].lhs 84 | r = rule[0].rhs 85 | 86 | rr = build_rule(l,r) 87 | 88 | sub = aparse('f(1,2)') 89 | res = aparse('g(f(1, 2), a(f(1, 2)))') 90 | assert rr(sub) == res 91 | 92 | def test_rule3(): 93 | rule = dslparse('b: @a(x,y) -> F(a,y,x)') 94 | l = rule[0].lhs 95 | r = rule[0].rhs 96 | 97 | rr = build_rule(l,r) 98 | 99 | sub = aparse('f(1,2)') 100 | res = aparse('F(f,2,1)') 101 | assert rr(sub) == res 102 | 103 | def test_rule4(): 104 | rule = dslparse('b: f(x,x) -> x') 105 | l = rule[0].lhs 106 | r = rule[0].rhs 107 | 108 | rr = build_rule(l,r) 109 | 110 | sub = aparse('f(1,1)') 111 | res = aparse('1') 112 | assert rr(sub) == res 113 | 114 | with assert_raises(NoMatch): 115 | sub = aparse('f(1,2)') 116 | assert rr(sub) == res 117 | 118 | def test_rule5(): 119 | rule = dslparse('b: f(x,g(y,z)) -> (x,y,z)') 120 | l = rule[0].lhs 121 | r = rule[0].rhs 122 | 123 | rr = build_rule(l,r) 124 | 125 | sub = aparse('f(1,g(2,3))') 126 | res = aparse('(1,2,3)') 127 | assert rr(sub) == res 128 | -------------------------------------------------------------------------------- /rewrite/tests/test_parse.py: -------------------------------------------------------------------------------- 1 | from rewrite import parse 2 | 3 | def test_parser_sanity(): 4 | a0 = parse('f') 5 | a1 = parse('f(x)') 6 | a2 = parse('f(x,y)') 7 | a3 = parse('(x,y)') 8 | a4 = parse('f(x,f(x,y))') 9 | a5 = parse('f(1,2,3)') 10 | a6 = parse('f([1,2,3])') 11 | a7 = parse('(1,2,3)') 12 | 13 | assert repr(a0) == 'f' 14 | assert repr(a1) == 'f(x)' 15 | assert repr(a2) == 'f(x, y)' 16 | assert repr(a3) == '(x, y)' 17 | assert repr(a4) == 'f(x, f(x, y))' 18 | assert repr(a5) == 'f(1, 2, 3)' 19 | assert repr(a6) == 'f([1, 2, 3])' 20 | assert repr(a7) == '(1, 2, 3)' 21 | 22 | # test edge case 23 | assert repr(parse('[]')) == '[]' 24 | assert repr(parse('()')) == '()' 25 | 26 | parse('f(x,y){abc, foo}') 27 | parse('f(x,y){abc, foo, awk}') 28 | parse('f(x,y{fizzbang})') 29 | parse('f{x}') 30 | parse('f{[(a,b),(c,d)]}') 31 | 32 | parse('[1,2, 3]') 33 | parse('["foo"]') 34 | parse('[1, 2, 3.14]') 35 | parse('[a,b,c,f(b),f(b,1),1.2,1.3]') 36 | parse('[c,f(b,1),a,b,f(b),1.3,1.2]') 37 | parse('[[1,2],[1]]') 38 | parse('[]{[a,a]}') 39 | parse('f(,,,)') 40 | parse('f(,[])') 41 | parse('') 42 | parse('{[a,b]}') 43 | 44 | parse('Pow(,)') 45 | parse('Mul(Array(),Array())') 46 | parse('Mul(Array,Array)') 47 | parse('Add(2,3{dshape("foo, bar, 2")})') 48 | parse('Add(2{dshape("int")},3.0{dshape("double")})') 49 | 50 | def test_roundtrip(): 51 | a0 = parse(repr(parse('f'))) 52 | a1 = parse(repr(parse('f(x)'))) 53 | a2 = parse(repr(parse('f(x, y)'))) 54 | a3 = parse(repr(parse('(x, y)'))) 55 | a4 = parse(repr(parse('f(x, f(x, y))'))) 56 | a5 = parse(repr(parse('f(1, 2, 3)'))) 57 | a6 = parse(repr(parse('f([1, 2, 3])'))) 58 | a7 = parse(repr(parse('(1, 2, 3)'))) 59 | 60 | assert repr(a0) == 'f' 61 | assert repr(a1) == 'f(x)' 62 | assert repr(a2) == 'f(x, y)' 63 | assert repr(a3) == '(x, y)' 64 | assert repr(a4) == 'f(x, f(x, y))' 65 | assert repr(a5) == 'f(1, 2, 3)' 66 | assert repr(a6) == 'f([1, 2, 3])' 67 | assert repr(a7) == '(1, 2, 3)' 68 | -------------------------------------------------------------------------------- /run: -------------------------------------------------------------------------------- 1 | PYTHONPATH=. python rewrite/dsl/cli.py $1 2 | -------------------------------------------------------------------------------- /sample: -------------------------------------------------------------------------------- 1 | foo : A() -> B() 2 | foo : B() -> A() 3 | foo : Succ(0) -> 1 4 | foo : Succ(1) -> 2 5 | foo : Succ(x) -> Succ(Succ(x)) 6 | 7 | bar = foo ; foo 8 | awk = foo ; foo ; foo 9 | sed = foo ; foo ; foo <+ foo 10 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from distutils.core import setup 2 | 3 | setup( 4 | name = "pyrewrite", 5 | license = "BSD", 6 | author='Continuum Analytics', 7 | author_email='blaze-dev@continuum.io', 8 | description = "Python term rewriting", 9 | packages = ['rewrite', 10 | 'rewrite.tests'], 11 | version = "dev", 12 | #entry_points={ 13 | # 'console_scripts': 14 | # ['pyrewrite = rewrite.dsl.cli:main'] 15 | #} 16 | ) 17 | -------------------------------------------------------------------------------- /web/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store -------------------------------------------------------------------------------- /web/css/bootstrap-responsive-2.1.0.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap Responsive v2.1.0 3 | * 4 | * Copyright 2012 Twitter, Inc 5 | * Licensed under the Apache License v2.0 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * Designed and built with all the love in the world @twitter by @mdo and @fat. 9 | */ 10 | 11 | .clearfix { 12 | *zoom: 1; 13 | } 14 | 15 | .clearfix:before, 16 | .clearfix:after { 17 | display: table; 18 | line-height: 0; 19 | content: ""; 20 | } 21 | 22 | .clearfix:after { 23 | clear: both; 24 | } 25 | 26 | .hide-text { 27 | font: 0/0 a; 28 | color: transparent; 29 | text-shadow: none; 30 | background-color: transparent; 31 | border: 0; 32 | } 33 | 34 | .input-block-level { 35 | display: block; 36 | width: 100%; 37 | min-height: 30px; 38 | -webkit-box-sizing: border-box; 39 | -moz-box-sizing: border-box; 40 | box-sizing: border-box; 41 | } 42 | 43 | .hidden { 44 | display: none; 45 | visibility: hidden; 46 | } 47 | 48 | .visible-phone { 49 | display: none !important; 50 | } 51 | 52 | .visible-tablet { 53 | display: none !important; 54 | } 55 | 56 | .hidden-desktop { 57 | display: none !important; 58 | } 59 | 60 | .visible-desktop { 61 | display: inherit !important; 62 | } 63 | 64 | @media (min-width: 768px) and (max-width: 979px) { 65 | .hidden-desktop { 66 | display: inherit !important; 67 | } 68 | .visible-desktop { 69 | display: none !important ; 70 | } 71 | .visible-tablet { 72 | display: inherit !important; 73 | } 74 | .hidden-tablet { 75 | display: none !important; 76 | } 77 | } 78 | 79 | @media (max-width: 767px) { 80 | .hidden-desktop { 81 | display: inherit !important; 82 | } 83 | .visible-desktop { 84 | display: none !important; 85 | } 86 | .visible-phone { 87 | display: inherit !important; 88 | } 89 | .hidden-phone { 90 | display: none !important; 91 | } 92 | } 93 | 94 | @media (min-width: 1200px) { 95 | .row { 96 | margin-left: -30px; 97 | *zoom: 1; 98 | } 99 | .row:before, 100 | .row:after { 101 | display: table; 102 | line-height: 0; 103 | content: ""; 104 | } 105 | .row:after { 106 | clear: both; 107 | } 108 | [class*="span"] { 109 | float: left; 110 | margin-left: 30px; 111 | } 112 | .container, 113 | .navbar-static-top .container, 114 | .navbar-fixed-top .container, 115 | .navbar-fixed-bottom .container { 116 | width: 1170px; 117 | } 118 | .span12 { 119 | width: 1170px; 120 | } 121 | .span11 { 122 | width: 1070px; 123 | } 124 | .span10 { 125 | width: 970px; 126 | } 127 | .span9 { 128 | width: 870px; 129 | } 130 | .span8 { 131 | width: 770px; 132 | } 133 | .span7 { 134 | width: 670px; 135 | } 136 | .span6 { 137 | width: 570px; 138 | } 139 | .span5 { 140 | width: 470px; 141 | } 142 | .span4 { 143 | width: 370px; 144 | } 145 | .span3 { 146 | width: 270px; 147 | } 148 | .span2 { 149 | width: 170px; 150 | } 151 | .span1 { 152 | width: 70px; 153 | } 154 | .offset12 { 155 | margin-left: 1230px; 156 | } 157 | .offset11 { 158 | margin-left: 1130px; 159 | } 160 | .offset10 { 161 | margin-left: 1030px; 162 | } 163 | .offset9 { 164 | margin-left: 930px; 165 | } 166 | .offset8 { 167 | margin-left: 830px; 168 | } 169 | .offset7 { 170 | margin-left: 730px; 171 | } 172 | .offset6 { 173 | margin-left: 630px; 174 | } 175 | .offset5 { 176 | margin-left: 530px; 177 | } 178 | .offset4 { 179 | margin-left: 430px; 180 | } 181 | .offset3 { 182 | margin-left: 330px; 183 | } 184 | .offset2 { 185 | margin-left: 230px; 186 | } 187 | .offset1 { 188 | margin-left: 130px; 189 | } 190 | .row-fluid { 191 | width: 100%; 192 | *zoom: 1; 193 | } 194 | .row-fluid:before, 195 | .row-fluid:after { 196 | display: table; 197 | line-height: 0; 198 | content: ""; 199 | } 200 | .row-fluid:after { 201 | clear: both; 202 | } 203 | .row-fluid [class*="span"] { 204 | display: block; 205 | float: left; 206 | width: 100%; 207 | min-height: 30px; 208 | margin-left: 2.564102564102564%; 209 | *margin-left: 2.5109110747408616%; 210 | -webkit-box-sizing: border-box; 211 | -moz-box-sizing: border-box; 212 | box-sizing: border-box; 213 | } 214 | .row-fluid [class*="span"]:first-child { 215 | margin-left: 0; 216 | } 217 | .row-fluid .span12 { 218 | width: 100%; 219 | *width: 99.94680851063829%; 220 | } 221 | .row-fluid .span11 { 222 | width: 91.45299145299145%; 223 | *width: 91.39979996362975%; 224 | } 225 | .row-fluid .span10 { 226 | width: 82.90598290598291%; 227 | *width: 82.8527914166212%; 228 | } 229 | .row-fluid .span9 { 230 | width: 74.35897435897436%; 231 | *width: 74.30578286961266%; 232 | } 233 | .row-fluid .span8 { 234 | width: 65.81196581196582%; 235 | *width: 65.75877432260411%; 236 | } 237 | .row-fluid .span7 { 238 | width: 57.26495726495726%; 239 | *width: 57.21176577559556%; 240 | } 241 | .row-fluid .span6 { 242 | width: 48.717948717948715%; 243 | *width: 48.664757228587014%; 244 | } 245 | .row-fluid .span5 { 246 | width: 40.17094017094017%; 247 | *width: 40.11774868157847%; 248 | } 249 | .row-fluid .span4 { 250 | width: 31.623931623931625%; 251 | *width: 31.570740134569924%; 252 | } 253 | .row-fluid .span3 { 254 | width: 23.076923076923077%; 255 | *width: 23.023731587561375%; 256 | } 257 | .row-fluid .span2 { 258 | width: 14.52991452991453%; 259 | *width: 14.476723040552828%; 260 | } 261 | .row-fluid .span1 { 262 | width: 5.982905982905983%; 263 | *width: 5.929714493544281%; 264 | } 265 | .row-fluid .offset12 { 266 | margin-left: 105.12820512820512%; 267 | *margin-left: 105.02182214948171%; 268 | } 269 | .row-fluid .offset12:first-child { 270 | margin-left: 102.56410256410257%; 271 | *margin-left: 102.45771958537915%; 272 | } 273 | .row-fluid .offset11 { 274 | margin-left: 96.58119658119658%; 275 | *margin-left: 96.47481360247316%; 276 | } 277 | .row-fluid .offset11:first-child { 278 | margin-left: 94.01709401709402%; 279 | *margin-left: 93.91071103837061%; 280 | } 281 | .row-fluid .offset10 { 282 | margin-left: 88.03418803418803%; 283 | *margin-left: 87.92780505546462%; 284 | } 285 | .row-fluid .offset10:first-child { 286 | margin-left: 85.47008547008548%; 287 | *margin-left: 85.36370249136206%; 288 | } 289 | .row-fluid .offset9 { 290 | margin-left: 79.48717948717949%; 291 | *margin-left: 79.38079650845607%; 292 | } 293 | .row-fluid .offset9:first-child { 294 | margin-left: 76.92307692307693%; 295 | *margin-left: 76.81669394435352%; 296 | } 297 | .row-fluid .offset8 { 298 | margin-left: 70.94017094017094%; 299 | *margin-left: 70.83378796144753%; 300 | } 301 | .row-fluid .offset8:first-child { 302 | margin-left: 68.37606837606839%; 303 | *margin-left: 68.26968539734497%; 304 | } 305 | .row-fluid .offset7 { 306 | margin-left: 62.393162393162385%; 307 | *margin-left: 62.28677941443899%; 308 | } 309 | .row-fluid .offset7:first-child { 310 | margin-left: 59.82905982905982%; 311 | *margin-left: 59.72267685033642%; 312 | } 313 | .row-fluid .offset6 { 314 | margin-left: 53.84615384615384%; 315 | *margin-left: 53.739770867430444%; 316 | } 317 | .row-fluid .offset6:first-child { 318 | margin-left: 51.28205128205128%; 319 | *margin-left: 51.175668303327875%; 320 | } 321 | .row-fluid .offset5 { 322 | margin-left: 45.299145299145295%; 323 | *margin-left: 45.1927623204219%; 324 | } 325 | .row-fluid .offset5:first-child { 326 | margin-left: 42.73504273504273%; 327 | *margin-left: 42.62865975631933%; 328 | } 329 | .row-fluid .offset4 { 330 | margin-left: 36.75213675213675%; 331 | *margin-left: 36.645753773413354%; 332 | } 333 | .row-fluid .offset4:first-child { 334 | margin-left: 34.18803418803419%; 335 | *margin-left: 34.081651209310785%; 336 | } 337 | .row-fluid .offset3 { 338 | margin-left: 28.205128205128204%; 339 | *margin-left: 28.0987452264048%; 340 | } 341 | .row-fluid .offset3:first-child { 342 | margin-left: 25.641025641025642%; 343 | *margin-left: 25.53464266230224%; 344 | } 345 | .row-fluid .offset2 { 346 | margin-left: 19.65811965811966%; 347 | *margin-left: 19.551736679396257%; 348 | } 349 | .row-fluid .offset2:first-child { 350 | margin-left: 17.094017094017094%; 351 | *margin-left: 16.98763411529369%; 352 | } 353 | .row-fluid .offset1 { 354 | margin-left: 11.11111111111111%; 355 | *margin-left: 11.004728132387708%; 356 | } 357 | .row-fluid .offset1:first-child { 358 | margin-left: 8.547008547008547%; 359 | *margin-left: 8.440625568285142%; 360 | } 361 | input, 362 | textarea, 363 | .uneditable-input { 364 | margin-left: 0; 365 | } 366 | .controls-row [class*="span"] + [class*="span"] { 367 | margin-left: 30px; 368 | } 369 | input.span12, 370 | textarea.span12, 371 | .uneditable-input.span12 { 372 | width: 1156px; 373 | } 374 | input.span11, 375 | textarea.span11, 376 | .uneditable-input.span11 { 377 | width: 1056px; 378 | } 379 | input.span10, 380 | textarea.span10, 381 | .uneditable-input.span10 { 382 | width: 956px; 383 | } 384 | input.span9, 385 | textarea.span9, 386 | .uneditable-input.span9 { 387 | width: 856px; 388 | } 389 | input.span8, 390 | textarea.span8, 391 | .uneditable-input.span8 { 392 | width: 756px; 393 | } 394 | input.span7, 395 | textarea.span7, 396 | .uneditable-input.span7 { 397 | width: 656px; 398 | } 399 | input.span6, 400 | textarea.span6, 401 | .uneditable-input.span6 { 402 | width: 556px; 403 | } 404 | input.span5, 405 | textarea.span5, 406 | .uneditable-input.span5 { 407 | width: 456px; 408 | } 409 | input.span4, 410 | textarea.span4, 411 | .uneditable-input.span4 { 412 | width: 356px; 413 | } 414 | input.span3, 415 | textarea.span3, 416 | .uneditable-input.span3 { 417 | width: 256px; 418 | } 419 | input.span2, 420 | textarea.span2, 421 | .uneditable-input.span2 { 422 | width: 156px; 423 | } 424 | input.span1, 425 | textarea.span1, 426 | .uneditable-input.span1 { 427 | width: 56px; 428 | } 429 | .thumbnails { 430 | margin-left: -30px; 431 | } 432 | .thumbnails > li { 433 | margin-left: 30px; 434 | } 435 | .row-fluid .thumbnails { 436 | margin-left: 0; 437 | } 438 | } 439 | 440 | @media (min-width: 768px) and (max-width: 979px) { 441 | .row { 442 | margin-left: -20px; 443 | *zoom: 1; 444 | } 445 | .row:before, 446 | .row:after { 447 | display: table; 448 | line-height: 0; 449 | content: ""; 450 | } 451 | .row:after { 452 | clear: both; 453 | } 454 | [class*="span"] { 455 | float: left; 456 | margin-left: 20px; 457 | } 458 | .container, 459 | .navbar-static-top .container, 460 | .navbar-fixed-top .container, 461 | .navbar-fixed-bottom .container { 462 | width: 724px; 463 | } 464 | .span12 { 465 | width: 724px; 466 | } 467 | .span11 { 468 | width: 662px; 469 | } 470 | .span10 { 471 | width: 600px; 472 | } 473 | .span9 { 474 | width: 538px; 475 | } 476 | .span8 { 477 | width: 476px; 478 | } 479 | .span7 { 480 | width: 414px; 481 | } 482 | .span6 { 483 | width: 352px; 484 | } 485 | .span5 { 486 | width: 290px; 487 | } 488 | .span4 { 489 | width: 228px; 490 | } 491 | .span3 { 492 | width: 166px; 493 | } 494 | .span2 { 495 | width: 104px; 496 | } 497 | .span1 { 498 | width: 42px; 499 | } 500 | .offset12 { 501 | margin-left: 764px; 502 | } 503 | .offset11 { 504 | margin-left: 702px; 505 | } 506 | .offset10 { 507 | margin-left: 640px; 508 | } 509 | .offset9 { 510 | margin-left: 578px; 511 | } 512 | .offset8 { 513 | margin-left: 516px; 514 | } 515 | .offset7 { 516 | margin-left: 454px; 517 | } 518 | .offset6 { 519 | margin-left: 392px; 520 | } 521 | .offset5 { 522 | margin-left: 330px; 523 | } 524 | .offset4 { 525 | margin-left: 268px; 526 | } 527 | .offset3 { 528 | margin-left: 206px; 529 | } 530 | .offset2 { 531 | margin-left: 144px; 532 | } 533 | .offset1 { 534 | margin-left: 82px; 535 | } 536 | .row-fluid { 537 | width: 100%; 538 | *zoom: 1; 539 | } 540 | .row-fluid:before, 541 | .row-fluid:after { 542 | display: table; 543 | line-height: 0; 544 | content: ""; 545 | } 546 | .row-fluid:after { 547 | clear: both; 548 | } 549 | .row-fluid [class*="span"] { 550 | display: block; 551 | float: left; 552 | width: 100%; 553 | min-height: 30px; 554 | margin-left: 2.7624309392265194%; 555 | *margin-left: 2.709239449864817%; 556 | -webkit-box-sizing: border-box; 557 | -moz-box-sizing: border-box; 558 | box-sizing: border-box; 559 | } 560 | .row-fluid [class*="span"]:first-child { 561 | margin-left: 0; 562 | } 563 | .row-fluid .span12 { 564 | width: 100%; 565 | *width: 99.94680851063829%; 566 | } 567 | .row-fluid .span11 { 568 | width: 91.43646408839778%; 569 | *width: 91.38327259903608%; 570 | } 571 | .row-fluid .span10 { 572 | width: 82.87292817679558%; 573 | *width: 82.81973668743387%; 574 | } 575 | .row-fluid .span9 { 576 | width: 74.30939226519337%; 577 | *width: 74.25620077583166%; 578 | } 579 | .row-fluid .span8 { 580 | width: 65.74585635359117%; 581 | *width: 65.69266486422946%; 582 | } 583 | .row-fluid .span7 { 584 | width: 57.18232044198895%; 585 | *width: 57.12912895262725%; 586 | } 587 | .row-fluid .span6 { 588 | width: 48.61878453038674%; 589 | *width: 48.56559304102504%; 590 | } 591 | .row-fluid .span5 { 592 | width: 40.05524861878453%; 593 | *width: 40.00205712942283%; 594 | } 595 | .row-fluid .span4 { 596 | width: 31.491712707182323%; 597 | *width: 31.43852121782062%; 598 | } 599 | .row-fluid .span3 { 600 | width: 22.92817679558011%; 601 | *width: 22.87498530621841%; 602 | } 603 | .row-fluid .span2 { 604 | width: 14.3646408839779%; 605 | *width: 14.311449394616199%; 606 | } 607 | .row-fluid .span1 { 608 | width: 5.801104972375691%; 609 | *width: 5.747913483013988%; 610 | } 611 | .row-fluid .offset12 { 612 | margin-left: 105.52486187845304%; 613 | *margin-left: 105.41847889972962%; 614 | } 615 | .row-fluid .offset12:first-child { 616 | margin-left: 102.76243093922652%; 617 | *margin-left: 102.6560479605031%; 618 | } 619 | .row-fluid .offset11 { 620 | margin-left: 96.96132596685082%; 621 | *margin-left: 96.8549429881274%; 622 | } 623 | .row-fluid .offset11:first-child { 624 | margin-left: 94.1988950276243%; 625 | *margin-left: 94.09251204890089%; 626 | } 627 | .row-fluid .offset10 { 628 | margin-left: 88.39779005524862%; 629 | *margin-left: 88.2914070765252%; 630 | } 631 | .row-fluid .offset10:first-child { 632 | margin-left: 85.6353591160221%; 633 | *margin-left: 85.52897613729868%; 634 | } 635 | .row-fluid .offset9 { 636 | margin-left: 79.8342541436464%; 637 | *margin-left: 79.72787116492299%; 638 | } 639 | .row-fluid .offset9:first-child { 640 | margin-left: 77.07182320441989%; 641 | *margin-left: 76.96544022569647%; 642 | } 643 | .row-fluid .offset8 { 644 | margin-left: 71.2707182320442%; 645 | *margin-left: 71.16433525332079%; 646 | } 647 | .row-fluid .offset8:first-child { 648 | margin-left: 68.50828729281768%; 649 | *margin-left: 68.40190431409427%; 650 | } 651 | .row-fluid .offset7 { 652 | margin-left: 62.70718232044199%; 653 | *margin-left: 62.600799341718584%; 654 | } 655 | .row-fluid .offset7:first-child { 656 | margin-left: 59.94475138121547%; 657 | *margin-left: 59.838368402492065%; 658 | } 659 | .row-fluid .offset6 { 660 | margin-left: 54.14364640883978%; 661 | *margin-left: 54.037263430116376%; 662 | } 663 | .row-fluid .offset6:first-child { 664 | margin-left: 51.38121546961326%; 665 | *margin-left: 51.27483249088986%; 666 | } 667 | .row-fluid .offset5 { 668 | margin-left: 45.58011049723757%; 669 | *margin-left: 45.47372751851417%; 670 | } 671 | .row-fluid .offset5:first-child { 672 | margin-left: 42.81767955801105%; 673 | *margin-left: 42.71129657928765%; 674 | } 675 | .row-fluid .offset4 { 676 | margin-left: 37.01657458563536%; 677 | *margin-left: 36.91019160691196%; 678 | } 679 | .row-fluid .offset4:first-child { 680 | margin-left: 34.25414364640884%; 681 | *margin-left: 34.14776066768544%; 682 | } 683 | .row-fluid .offset3 { 684 | margin-left: 28.45303867403315%; 685 | *margin-left: 28.346655695309746%; 686 | } 687 | .row-fluid .offset3:first-child { 688 | margin-left: 25.69060773480663%; 689 | *margin-left: 25.584224756083227%; 690 | } 691 | .row-fluid .offset2 { 692 | margin-left: 19.88950276243094%; 693 | *margin-left: 19.783119783707537%; 694 | } 695 | .row-fluid .offset2:first-child { 696 | margin-left: 17.12707182320442%; 697 | *margin-left: 17.02068884448102%; 698 | } 699 | .row-fluid .offset1 { 700 | margin-left: 11.32596685082873%; 701 | *margin-left: 11.219583872105325%; 702 | } 703 | .row-fluid .offset1:first-child { 704 | margin-left: 8.56353591160221%; 705 | *margin-left: 8.457152932878806%; 706 | } 707 | input, 708 | textarea, 709 | .uneditable-input { 710 | margin-left: 0; 711 | } 712 | .controls-row [class*="span"] + [class*="span"] { 713 | margin-left: 20px; 714 | } 715 | input.span12, 716 | textarea.span12, 717 | .uneditable-input.span12 { 718 | width: 710px; 719 | } 720 | input.span11, 721 | textarea.span11, 722 | .uneditable-input.span11 { 723 | width: 648px; 724 | } 725 | input.span10, 726 | textarea.span10, 727 | .uneditable-input.span10 { 728 | width: 586px; 729 | } 730 | input.span9, 731 | textarea.span9, 732 | .uneditable-input.span9 { 733 | width: 524px; 734 | } 735 | input.span8, 736 | textarea.span8, 737 | .uneditable-input.span8 { 738 | width: 462px; 739 | } 740 | input.span7, 741 | textarea.span7, 742 | .uneditable-input.span7 { 743 | width: 400px; 744 | } 745 | input.span6, 746 | textarea.span6, 747 | .uneditable-input.span6 { 748 | width: 338px; 749 | } 750 | input.span5, 751 | textarea.span5, 752 | .uneditable-input.span5 { 753 | width: 276px; 754 | } 755 | input.span4, 756 | textarea.span4, 757 | .uneditable-input.span4 { 758 | width: 214px; 759 | } 760 | input.span3, 761 | textarea.span3, 762 | .uneditable-input.span3 { 763 | width: 152px; 764 | } 765 | input.span2, 766 | textarea.span2, 767 | .uneditable-input.span2 { 768 | width: 90px; 769 | } 770 | input.span1, 771 | textarea.span1, 772 | .uneditable-input.span1 { 773 | width: 28px; 774 | } 775 | } 776 | 777 | @media (max-width: 767px) { 778 | body { 779 | padding-right: 20px; 780 | padding-left: 20px; 781 | } 782 | .navbar-fixed-top, 783 | .navbar-fixed-bottom { 784 | margin-right: -20px; 785 | margin-left: -20px; 786 | } 787 | .container-fluid { 788 | padding: 0; 789 | } 790 | .dl-horizontal dt { 791 | float: none; 792 | width: auto; 793 | clear: none; 794 | text-align: left; 795 | } 796 | .dl-horizontal dd { 797 | margin-left: 0; 798 | } 799 | .container { 800 | width: auto; 801 | } 802 | .row-fluid { 803 | width: 100%; 804 | } 805 | .row, 806 | .thumbnails { 807 | margin-left: 0; 808 | } 809 | .thumbnails > li { 810 | float: none; 811 | margin-left: 0; 812 | } 813 | [class*="span"], 814 | .row-fluid [class*="span"] { 815 | display: block; 816 | float: none; 817 | width: auto; 818 | margin-left: 0; 819 | } 820 | .span12, 821 | .row-fluid .span12 { 822 | width: 100%; 823 | -webkit-box-sizing: border-box; 824 | -moz-box-sizing: border-box; 825 | box-sizing: border-box; 826 | } 827 | .input-large, 828 | .input-xlarge, 829 | .input-xxlarge, 830 | input[class*="span"], 831 | select[class*="span"], 832 | textarea[class*="span"], 833 | .uneditable-input { 834 | display: block; 835 | width: 100%; 836 | min-height: 30px; 837 | -webkit-box-sizing: border-box; 838 | -moz-box-sizing: border-box; 839 | box-sizing: border-box; 840 | } 841 | .input-prepend input, 842 | .input-append input, 843 | .input-prepend input[class*="span"], 844 | .input-append input[class*="span"] { 845 | display: inline-block; 846 | width: auto; 847 | } 848 | .modal { 849 | position: fixed; 850 | top: 20px; 851 | right: 20px; 852 | left: 20px; 853 | width: auto; 854 | margin: 0; 855 | } 856 | .modal.fade.in { 857 | top: auto; 858 | } 859 | } 860 | 861 | @media (max-width: 480px) { 862 | .nav-collapse { 863 | -webkit-transform: translate3d(0, 0, 0); 864 | } 865 | .page-header h1 small { 866 | display: block; 867 | line-height: 20px; 868 | } 869 | input[type="checkbox"], 870 | input[type="radio"] { 871 | border: 1px solid #ccc; 872 | } 873 | .form-horizontal .control-group > label { 874 | float: none; 875 | width: auto; 876 | padding-top: 0; 877 | text-align: left; 878 | } 879 | .form-horizontal .controls { 880 | margin-left: 0; 881 | } 882 | .form-horizontal .control-list { 883 | padding-top: 0; 884 | } 885 | .form-horizontal .form-actions { 886 | padding-right: 10px; 887 | padding-left: 10px; 888 | } 889 | .modal { 890 | top: 10px; 891 | right: 10px; 892 | left: 10px; 893 | } 894 | .modal-header .close { 895 | padding: 10px; 896 | margin: -10px; 897 | } 898 | .carousel-caption { 899 | position: static; 900 | } 901 | } 902 | 903 | @media (max-width: 979px) { 904 | body { 905 | padding-top: 0; 906 | } 907 | .navbar-fixed-top, 908 | .navbar-fixed-bottom { 909 | position: static; 910 | } 911 | .navbar-fixed-top { 912 | margin-bottom: 20px; 913 | } 914 | .navbar-fixed-bottom { 915 | margin-top: 20px; 916 | } 917 | .navbar-fixed-top .navbar-inner, 918 | .navbar-fixed-bottom .navbar-inner { 919 | padding: 5px; 920 | } 921 | .navbar .container { 922 | width: auto; 923 | padding: 0; 924 | } 925 | .navbar .brand { 926 | padding-right: 10px; 927 | padding-left: 10px; 928 | margin: 0 0 0 -5px; 929 | } 930 | .nav-collapse { 931 | clear: both; 932 | } 933 | .nav-collapse .nav { 934 | float: none; 935 | margin: 0 0 10px; 936 | } 937 | .nav-collapse .nav > li { 938 | float: none; 939 | } 940 | .nav-collapse .nav > li > a { 941 | margin-bottom: 2px; 942 | } 943 | .nav-collapse .nav > .divider-vertical { 944 | display: none; 945 | } 946 | .nav-collapse .nav .nav-header { 947 | color: #555555; 948 | text-shadow: none; 949 | } 950 | .nav-collapse .nav > li > a, 951 | .nav-collapse .dropdown-menu a { 952 | padding: 9px 15px; 953 | font-weight: bold; 954 | color: #555555; 955 | -webkit-border-radius: 3px; 956 | -moz-border-radius: 3px; 957 | border-radius: 3px; 958 | } 959 | .nav-collapse .btn { 960 | padding: 4px 10px 4px; 961 | font-weight: normal; 962 | -webkit-border-radius: 4px; 963 | -moz-border-radius: 4px; 964 | border-radius: 4px; 965 | } 966 | .nav-collapse .dropdown-menu li + li a { 967 | margin-bottom: 2px; 968 | } 969 | .nav-collapse .nav > li > a:hover, 970 | .nav-collapse .dropdown-menu a:hover { 971 | background-color: #f2f2f2; 972 | } 973 | .navbar-inverse .nav-collapse .nav > li > a:hover, 974 | .navbar-inverse .nav-collapse .dropdown-menu a:hover { 975 | background-color: #111111; 976 | } 977 | .nav-collapse.in .btn-group { 978 | padding: 0; 979 | margin-top: 5px; 980 | } 981 | .nav-collapse .dropdown-menu { 982 | position: static; 983 | top: auto; 984 | left: auto; 985 | display: block; 986 | float: none; 987 | max-width: none; 988 | padding: 0; 989 | margin: 0 15px; 990 | background-color: transparent; 991 | border: none; 992 | -webkit-border-radius: 0; 993 | -moz-border-radius: 0; 994 | border-radius: 0; 995 | -webkit-box-shadow: none; 996 | -moz-box-shadow: none; 997 | box-shadow: none; 998 | } 999 | .nav-collapse .dropdown-menu:before, 1000 | .nav-collapse .dropdown-menu:after { 1001 | display: none; 1002 | } 1003 | .nav-collapse .dropdown-menu .divider { 1004 | display: none; 1005 | } 1006 | .nav-collapse .navbar-form, 1007 | .nav-collapse .navbar-search { 1008 | float: none; 1009 | padding: 10px 15px; 1010 | margin: 10px 0; 1011 | border-top: 1px solid #f2f2f2; 1012 | border-bottom: 1px solid #f2f2f2; 1013 | -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); 1014 | -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); 1015 | box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); 1016 | } 1017 | .navbar .nav-collapse .nav.pull-right { 1018 | float: none; 1019 | margin-left: 0; 1020 | } 1021 | .nav-collapse, 1022 | .nav-collapse.collapse { 1023 | height: 0; 1024 | overflow: hidden; 1025 | } 1026 | .navbar .btn-navbar { 1027 | display: block; 1028 | } 1029 | .navbar-static .navbar-inner { 1030 | padding-right: 10px; 1031 | padding-left: 10px; 1032 | } 1033 | } 1034 | 1035 | @media (min-width: 980px) { 1036 | .nav-collapse.collapse { 1037 | height: auto !important; 1038 | overflow: visible !important; 1039 | } 1040 | } 1041 | -------------------------------------------------------------------------------- /web/css/bootstrap-responsive-2.1.0.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap Responsive v2.1.0 3 | * 4 | * Copyright 2012 Twitter, Inc 5 | * Licensed under the Apache License v2.0 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * Designed and built with all the love in the world @twitter by @mdo and @fat. 9 | */.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;line-height:0;content:""}.clearfix:after{clear:both}.hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.input-block-level{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.hidden{display:none;visibility:hidden}.visible-phone{display:none!important}.visible-tablet{display:none!important}.hidden-desktop{display:none!important}.visible-desktop{display:inherit!important}@media(min-width:768px) and (max-width:979px){.hidden-desktop{display:inherit!important}.visible-desktop{display:none!important}.visible-tablet{display:inherit!important}.hidden-tablet{display:none!important}}@media(max-width:767px){.hidden-desktop{display:inherit!important}.visible-desktop{display:none!important}.visible-phone{display:inherit!important}.hidden-phone{display:none!important}}@media(min-width:1200px){.row{margin-left:-30px;*zoom:1}.row:before,.row:after{display:table;line-height:0;content:""}.row:after{clear:both}[class*="span"]{float:left;margin-left:30px}.container,.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:1170px}.span12{width:1170px}.span11{width:1070px}.span10{width:970px}.span9{width:870px}.span8{width:770px}.span7{width:670px}.span6{width:570px}.span5{width:470px}.span4{width:370px}.span3{width:270px}.span2{width:170px}.span1{width:70px}.offset12{margin-left:1230px}.offset11{margin-left:1130px}.offset10{margin-left:1030px}.offset9{margin-left:930px}.offset8{margin-left:830px}.offset7{margin-left:730px}.offset6{margin-left:630px}.offset5{margin-left:530px}.offset4{margin-left:430px}.offset3{margin-left:330px}.offset2{margin-left:230px}.offset1{margin-left:130px}.row-fluid{width:100%;*zoom:1}.row-fluid:before,.row-fluid:after{display:table;line-height:0;content:""}.row-fluid:after{clear:both}.row-fluid [class*="span"]{display:block;float:left;width:100%;min-height:30px;margin-left:2.564102564102564%;*margin-left:2.5109110747408616%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="span"]:first-child{margin-left:0}.row-fluid .span12{width:100%;*width:99.94680851063829%}.row-fluid .span11{width:91.45299145299145%;*width:91.39979996362975%}.row-fluid .span10{width:82.90598290598291%;*width:82.8527914166212%}.row-fluid .span9{width:74.35897435897436%;*width:74.30578286961266%}.row-fluid .span8{width:65.81196581196582%;*width:65.75877432260411%}.row-fluid .span7{width:57.26495726495726%;*width:57.21176577559556%}.row-fluid .span6{width:48.717948717948715%;*width:48.664757228587014%}.row-fluid .span5{width:40.17094017094017%;*width:40.11774868157847%}.row-fluid .span4{width:31.623931623931625%;*width:31.570740134569924%}.row-fluid .span3{width:23.076923076923077%;*width:23.023731587561375%}.row-fluid .span2{width:14.52991452991453%;*width:14.476723040552828%}.row-fluid .span1{width:5.982905982905983%;*width:5.929714493544281%}.row-fluid .offset12{margin-left:105.12820512820512%;*margin-left:105.02182214948171%}.row-fluid .offset12:first-child{margin-left:102.56410256410257%;*margin-left:102.45771958537915%}.row-fluid .offset11{margin-left:96.58119658119658%;*margin-left:96.47481360247316%}.row-fluid .offset11:first-child{margin-left:94.01709401709402%;*margin-left:93.91071103837061%}.row-fluid .offset10{margin-left:88.03418803418803%;*margin-left:87.92780505546462%}.row-fluid .offset10:first-child{margin-left:85.47008547008548%;*margin-left:85.36370249136206%}.row-fluid .offset9{margin-left:79.48717948717949%;*margin-left:79.38079650845607%}.row-fluid .offset9:first-child{margin-left:76.92307692307693%;*margin-left:76.81669394435352%}.row-fluid .offset8{margin-left:70.94017094017094%;*margin-left:70.83378796144753%}.row-fluid .offset8:first-child{margin-left:68.37606837606839%;*margin-left:68.26968539734497%}.row-fluid .offset7{margin-left:62.393162393162385%;*margin-left:62.28677941443899%}.row-fluid .offset7:first-child{margin-left:59.82905982905982%;*margin-left:59.72267685033642%}.row-fluid .offset6{margin-left:53.84615384615384%;*margin-left:53.739770867430444%}.row-fluid .offset6:first-child{margin-left:51.28205128205128%;*margin-left:51.175668303327875%}.row-fluid .offset5{margin-left:45.299145299145295%;*margin-left:45.1927623204219%}.row-fluid .offset5:first-child{margin-left:42.73504273504273%;*margin-left:42.62865975631933%}.row-fluid .offset4{margin-left:36.75213675213675%;*margin-left:36.645753773413354%}.row-fluid .offset4:first-child{margin-left:34.18803418803419%;*margin-left:34.081651209310785%}.row-fluid .offset3{margin-left:28.205128205128204%;*margin-left:28.0987452264048%}.row-fluid .offset3:first-child{margin-left:25.641025641025642%;*margin-left:25.53464266230224%}.row-fluid .offset2{margin-left:19.65811965811966%;*margin-left:19.551736679396257%}.row-fluid .offset2:first-child{margin-left:17.094017094017094%;*margin-left:16.98763411529369%}.row-fluid .offset1{margin-left:11.11111111111111%;*margin-left:11.004728132387708%}.row-fluid .offset1:first-child{margin-left:8.547008547008547%;*margin-left:8.440625568285142%}input,textarea,.uneditable-input{margin-left:0}.controls-row [class*="span"]+[class*="span"]{margin-left:30px}input.span12,textarea.span12,.uneditable-input.span12{width:1156px}input.span11,textarea.span11,.uneditable-input.span11{width:1056px}input.span10,textarea.span10,.uneditable-input.span10{width:956px}input.span9,textarea.span9,.uneditable-input.span9{width:856px}input.span8,textarea.span8,.uneditable-input.span8{width:756px}input.span7,textarea.span7,.uneditable-input.span7{width:656px}input.span6,textarea.span6,.uneditable-input.span6{width:556px}input.span5,textarea.span5,.uneditable-input.span5{width:456px}input.span4,textarea.span4,.uneditable-input.span4{width:356px}input.span3,textarea.span3,.uneditable-input.span3{width:256px}input.span2,textarea.span2,.uneditable-input.span2{width:156px}input.span1,textarea.span1,.uneditable-input.span1{width:56px}.thumbnails{margin-left:-30px}.thumbnails>li{margin-left:30px}.row-fluid .thumbnails{margin-left:0}}@media(min-width:768px) and (max-width:979px){.row{margin-left:-20px;*zoom:1}.row:before,.row:after{display:table;line-height:0;content:""}.row:after{clear:both}[class*="span"]{float:left;margin-left:20px}.container,.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:724px}.span12{width:724px}.span11{width:662px}.span10{width:600px}.span9{width:538px}.span8{width:476px}.span7{width:414px}.span6{width:352px}.span5{width:290px}.span4{width:228px}.span3{width:166px}.span2{width:104px}.span1{width:42px}.offset12{margin-left:764px}.offset11{margin-left:702px}.offset10{margin-left:640px}.offset9{margin-left:578px}.offset8{margin-left:516px}.offset7{margin-left:454px}.offset6{margin-left:392px}.offset5{margin-left:330px}.offset4{margin-left:268px}.offset3{margin-left:206px}.offset2{margin-left:144px}.offset1{margin-left:82px}.row-fluid{width:100%;*zoom:1}.row-fluid:before,.row-fluid:after{display:table;line-height:0;content:""}.row-fluid:after{clear:both}.row-fluid [class*="span"]{display:block;float:left;width:100%;min-height:30px;margin-left:2.7624309392265194%;*margin-left:2.709239449864817%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="span"]:first-child{margin-left:0}.row-fluid .span12{width:100%;*width:99.94680851063829%}.row-fluid .span11{width:91.43646408839778%;*width:91.38327259903608%}.row-fluid .span10{width:82.87292817679558%;*width:82.81973668743387%}.row-fluid .span9{width:74.30939226519337%;*width:74.25620077583166%}.row-fluid .span8{width:65.74585635359117%;*width:65.69266486422946%}.row-fluid .span7{width:57.18232044198895%;*width:57.12912895262725%}.row-fluid .span6{width:48.61878453038674%;*width:48.56559304102504%}.row-fluid .span5{width:40.05524861878453%;*width:40.00205712942283%}.row-fluid .span4{width:31.491712707182323%;*width:31.43852121782062%}.row-fluid .span3{width:22.92817679558011%;*width:22.87498530621841%}.row-fluid .span2{width:14.3646408839779%;*width:14.311449394616199%}.row-fluid .span1{width:5.801104972375691%;*width:5.747913483013988%}.row-fluid .offset12{margin-left:105.52486187845304%;*margin-left:105.41847889972962%}.row-fluid .offset12:first-child{margin-left:102.76243093922652%;*margin-left:102.6560479605031%}.row-fluid .offset11{margin-left:96.96132596685082%;*margin-left:96.8549429881274%}.row-fluid .offset11:first-child{margin-left:94.1988950276243%;*margin-left:94.09251204890089%}.row-fluid .offset10{margin-left:88.39779005524862%;*margin-left:88.2914070765252%}.row-fluid .offset10:first-child{margin-left:85.6353591160221%;*margin-left:85.52897613729868%}.row-fluid .offset9{margin-left:79.8342541436464%;*margin-left:79.72787116492299%}.row-fluid .offset9:first-child{margin-left:77.07182320441989%;*margin-left:76.96544022569647%}.row-fluid .offset8{margin-left:71.2707182320442%;*margin-left:71.16433525332079%}.row-fluid .offset8:first-child{margin-left:68.50828729281768%;*margin-left:68.40190431409427%}.row-fluid .offset7{margin-left:62.70718232044199%;*margin-left:62.600799341718584%}.row-fluid .offset7:first-child{margin-left:59.94475138121547%;*margin-left:59.838368402492065%}.row-fluid .offset6{margin-left:54.14364640883978%;*margin-left:54.037263430116376%}.row-fluid .offset6:first-child{margin-left:51.38121546961326%;*margin-left:51.27483249088986%}.row-fluid .offset5{margin-left:45.58011049723757%;*margin-left:45.47372751851417%}.row-fluid .offset5:first-child{margin-left:42.81767955801105%;*margin-left:42.71129657928765%}.row-fluid .offset4{margin-left:37.01657458563536%;*margin-left:36.91019160691196%}.row-fluid .offset4:first-child{margin-left:34.25414364640884%;*margin-left:34.14776066768544%}.row-fluid .offset3{margin-left:28.45303867403315%;*margin-left:28.346655695309746%}.row-fluid .offset3:first-child{margin-left:25.69060773480663%;*margin-left:25.584224756083227%}.row-fluid .offset2{margin-left:19.88950276243094%;*margin-left:19.783119783707537%}.row-fluid .offset2:first-child{margin-left:17.12707182320442%;*margin-left:17.02068884448102%}.row-fluid .offset1{margin-left:11.32596685082873%;*margin-left:11.219583872105325%}.row-fluid .offset1:first-child{margin-left:8.56353591160221%;*margin-left:8.457152932878806%}input,textarea,.uneditable-input{margin-left:0}.controls-row [class*="span"]+[class*="span"]{margin-left:20px}input.span12,textarea.span12,.uneditable-input.span12{width:710px}input.span11,textarea.span11,.uneditable-input.span11{width:648px}input.span10,textarea.span10,.uneditable-input.span10{width:586px}input.span9,textarea.span9,.uneditable-input.span9{width:524px}input.span8,textarea.span8,.uneditable-input.span8{width:462px}input.span7,textarea.span7,.uneditable-input.span7{width:400px}input.span6,textarea.span6,.uneditable-input.span6{width:338px}input.span5,textarea.span5,.uneditable-input.span5{width:276px}input.span4,textarea.span4,.uneditable-input.span4{width:214px}input.span3,textarea.span3,.uneditable-input.span3{width:152px}input.span2,textarea.span2,.uneditable-input.span2{width:90px}input.span1,textarea.span1,.uneditable-input.span1{width:28px}}@media(max-width:767px){body{padding-right:20px;padding-left:20px}.navbar-fixed-top,.navbar-fixed-bottom{margin-right:-20px;margin-left:-20px}.container-fluid{padding:0}.dl-horizontal dt{float:none;width:auto;clear:none;text-align:left}.dl-horizontal dd{margin-left:0}.container{width:auto}.row-fluid{width:100%}.row,.thumbnails{margin-left:0}.thumbnails>li{float:none;margin-left:0}[class*="span"],.row-fluid [class*="span"]{display:block;float:none;width:auto;margin-left:0}.span12,.row-fluid .span12{width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.input-large,.input-xlarge,.input-xxlarge,input[class*="span"],select[class*="span"],textarea[class*="span"],.uneditable-input{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.input-prepend input,.input-append input,.input-prepend input[class*="span"],.input-append input[class*="span"]{display:inline-block;width:auto}.modal{position:fixed;top:20px;right:20px;left:20px;width:auto;margin:0}.modal.fade.in{top:auto}}@media(max-width:480px){.nav-collapse{-webkit-transform:translate3d(0,0,0)}.page-header h1 small{display:block;line-height:20px}input[type="checkbox"],input[type="radio"]{border:1px solid #ccc}.form-horizontal .control-group>label{float:none;width:auto;padding-top:0;text-align:left}.form-horizontal .controls{margin-left:0}.form-horizontal .control-list{padding-top:0}.form-horizontal .form-actions{padding-right:10px;padding-left:10px}.modal{top:10px;right:10px;left:10px}.modal-header .close{padding:10px;margin:-10px}.carousel-caption{position:static}}@media(max-width:979px){body{padding-top:0}.navbar-fixed-top,.navbar-fixed-bottom{position:static}.navbar-fixed-top{margin-bottom:20px}.navbar-fixed-bottom{margin-top:20px}.navbar-fixed-top .navbar-inner,.navbar-fixed-bottom .navbar-inner{padding:5px}.navbar .container{width:auto;padding:0}.navbar .brand{padding-right:10px;padding-left:10px;margin:0 0 0 -5px}.nav-collapse{clear:both}.nav-collapse .nav{float:none;margin:0 0 10px}.nav-collapse .nav>li{float:none}.nav-collapse .nav>li>a{margin-bottom:2px}.nav-collapse .nav>.divider-vertical{display:none}.nav-collapse .nav .nav-header{color:#555;text-shadow:none}.nav-collapse .nav>li>a,.nav-collapse .dropdown-menu a{padding:9px 15px;font-weight:bold;color:#555;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.nav-collapse .btn{padding:4px 10px 4px;font-weight:normal;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.nav-collapse .dropdown-menu li+li a{margin-bottom:2px}.nav-collapse .nav>li>a:hover,.nav-collapse .dropdown-menu a:hover{background-color:#f2f2f2}.navbar-inverse .nav-collapse .nav>li>a:hover,.navbar-inverse .nav-collapse .dropdown-menu a:hover{background-color:#111}.nav-collapse.in .btn-group{padding:0;margin-top:5px}.nav-collapse .dropdown-menu{position:static;top:auto;left:auto;display:block;float:none;max-width:none;padding:0;margin:0 15px;background-color:transparent;border:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.nav-collapse .dropdown-menu:before,.nav-collapse .dropdown-menu:after{display:none}.nav-collapse .dropdown-menu .divider{display:none}.nav-collapse .navbar-form,.nav-collapse .navbar-search{float:none;padding:10px 15px;margin:10px 0;border-top:1px solid #f2f2f2;border-bottom:1px solid #f2f2f2;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1)}.navbar .nav-collapse .nav.pull-right{float:none;margin-left:0}.nav-collapse,.nav-collapse.collapse{height:0;overflow:hidden}.navbar .btn-navbar{display:block}.navbar-static .navbar-inner{padding-right:10px;padding-left:10px}}@media(min-width:980px){.nav-collapse.collapse{height:auto!important;overflow:visible!important}} 10 | -------------------------------------------------------------------------------- /web/css/style.css: -------------------------------------------------------------------------------- 1 | /*Bootstrap Overrides and Custom CSS*/ 2 | 3 | /*Icon CSS pulled from Twitter Bootstrap Docs*/ 4 | .the-icons { 5 | margin-left: 0; 6 | list-style: none; 7 | } 8 | 9 | .the-icons li { 10 | float: left; 11 | width: 25%; 12 | line-height: 25px; 13 | } 14 | 15 | section > ul li { 16 | margin-bottom: 5px; 17 | } -------------------------------------------------------------------------------- /web/img/glyphicons-halflings-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdiehl/pyrewrite/226d139ff361b095d46a58c65bc345cd18443008/web/img/glyphicons-halflings-white.png -------------------------------------------------------------------------------- /web/img/glyphicons-halflings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdiehl/pyrewrite/226d139ff361b095d46a58c65bc345cd18443008/web/img/glyphicons-halflings.png -------------------------------------------------------------------------------- /web/img/glyphicons-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdiehl/pyrewrite/226d139ff361b095d46a58c65bc345cd18443008/web/img/glyphicons-white.png -------------------------------------------------------------------------------- /web/img/glyphicons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdiehl/pyrewrite/226d139ff361b095d46a58c65bc345cd18443008/web/img/glyphicons.png -------------------------------------------------------------------------------- /web/js/lib/bootstrap-2.1.0.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap.js by @fat & @mdo 3 | * Copyright 2012 Twitter, Inc. 4 | * http://www.apache.org/licenses/LICENSE-2.0.txt 5 | */ 6 | !function(a){a(function(){"use strict",a.support.transition=function(){var a=function(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"},c;for(c in b)if(a.style[c]!==undefined)return b[c]}();return a&&{end:a}}()})}(window.jQuery),!function(a){"use strict";var b='[data-dismiss="alert"]',c=function(c){a(c).on("click",b,this.close)};c.prototype.close=function(b){function f(){e.trigger("closed").remove()}var c=a(this),d=c.attr("data-target"),e;d||(d=c.attr("href"),d=d&&d.replace(/.*(?=#[^\s]*$)/,"")),e=a(d),b&&b.preventDefault(),e.length||(e=c.hasClass("alert")?c:c.parent()),e.trigger(b=a.Event("close"));if(b.isDefaultPrevented())return;e.removeClass("in"),a.support.transition&&e.hasClass("fade")?e.on(a.support.transition.end,f):f()},a.fn.alert=function(b){return this.each(function(){var d=a(this),e=d.data("alert");e||d.data("alert",e=new c(this)),typeof b=="string"&&e[b].call(d)})},a.fn.alert.Constructor=c,a(function(){a("body").on("click.alert.data-api",b,c.prototype.close)})}(window.jQuery),!function(a){"use strict";var b=function(b,c){this.$element=a(b),this.options=a.extend({},a.fn.button.defaults,c)};b.prototype.setState=function(a){var b="disabled",c=this.$element,d=c.data(),e=c.is("input")?"val":"html";a+="Text",d.resetText||c.data("resetText",c[e]()),c[e](d[a]||this.options[a]),setTimeout(function(){a=="loadingText"?c.addClass(b).attr(b,b):c.removeClass(b).removeAttr(b)},0)},b.prototype.toggle=function(){var a=this.$element.parent('[data-toggle="buttons-radio"]');a&&a.find(".active").removeClass("active"),this.$element.toggleClass("active")},a.fn.button=function(c){return this.each(function(){var d=a(this),e=d.data("button"),f=typeof c=="object"&&c;e||d.data("button",e=new b(this,f)),c=="toggle"?e.toggle():c&&e.setState(c)})},a.fn.button.defaults={loadingText:"loading..."},a.fn.button.Constructor=b,a(function(){a("body").on("click.button.data-api","[data-toggle^=button]",function(b){var c=a(b.target);c.hasClass("btn")||(c=c.closest(".btn")),c.button("toggle")})})}(window.jQuery),!function(a){"use strict";var b=function(b,c){this.$element=a(b),this.options=c,this.options.slide&&this.slide(this.options.slide),this.options.pause=="hover"&&this.$element.on("mouseenter",a.proxy(this.pause,this)).on("mouseleave",a.proxy(this.cycle,this))};b.prototype={cycle:function(b){return b||(this.paused=!1),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},to:function(b){var c=this.$element.find(".item.active"),d=c.parent().children(),e=d.index(c),f=this;if(b>d.length-1||b<0)return;return this.sliding?this.$element.one("slid",function(){f.to(b)}):e==b?this.pause().cycle():this.slide(b>e?"next":"prev",a(d[b]))},pause:function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition.end&&(this.$element.trigger(a.support.transition.end),this.cycle()),clearInterval(this.interval),this.interval=null,this},next:function(){if(this.sliding)return;return this.slide("next")},prev:function(){if(this.sliding)return;return this.slide("prev")},slide:function(b,c){var d=this.$element.find(".item.active"),e=c||d[b](),f=this.interval,g=b=="next"?"left":"right",h=b=="next"?"first":"last",i=this,j=a.Event("slide",{relatedTarget:e[0]});this.sliding=!0,f&&this.pause(),e=e.length?e:this.$element.find(".item")[h]();if(e.hasClass("active"))return;if(a.support.transition&&this.$element.hasClass("slide")){this.$element.trigger(j);if(j.isDefaultPrevented())return;e.addClass(b),e[0].offsetWidth,d.addClass(g),e.addClass(g),this.$element.one(a.support.transition.end,function(){e.removeClass([b,g].join(" ")).addClass("active"),d.removeClass(["active",g].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger("slid")},0)})}else{this.$element.trigger(j);if(j.isDefaultPrevented())return;d.removeClass("active"),e.addClass("active"),this.sliding=!1,this.$element.trigger("slid")}return f&&this.cycle(),this}},a.fn.carousel=function(c){return this.each(function(){var d=a(this),e=d.data("carousel"),f=a.extend({},a.fn.carousel.defaults,typeof c=="object"&&c),g=typeof c=="string"?c:f.slide;e||d.data("carousel",e=new b(this,f)),typeof c=="number"?e.to(c):g?e[g]():f.interval&&e.cycle()})},a.fn.carousel.defaults={interval:5e3,pause:"hover"},a.fn.carousel.Constructor=b,a(function(){a("body").on("click.carousel.data-api","[data-slide]",function(b){var c=a(this),d,e=a(c.attr("data-target")||(d=c.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,"")),f=!e.data("modal")&&a.extend({},e.data(),c.data());e.carousel(f),b.preventDefault()})})}(window.jQuery),!function(a){"use strict";var b=function(b,c){this.$element=a(b),this.options=a.extend({},a.fn.collapse.defaults,c),this.options.parent&&(this.$parent=a(this.options.parent)),this.options.toggle&&this.toggle()};b.prototype={constructor:b,dimension:function(){var a=this.$element.hasClass("width");return a?"width":"height"},show:function(){var b,c,d,e;if(this.transitioning)return;b=this.dimension(),c=a.camelCase(["scroll",b].join("-")),d=this.$parent&&this.$parent.find("> .accordion-group > .in");if(d&&d.length){e=d.data("collapse");if(e&&e.transitioning)return;d.collapse("hide"),e||d.data("collapse",null)}this.$element[b](0),this.transition("addClass",a.Event("show"),"shown"),a.support.transition&&this.$element[b](this.$element[0][c])},hide:function(){var b;if(this.transitioning)return;b=this.dimension(),this.reset(this.$element[b]()),this.transition("removeClass",a.Event("hide"),"hidden"),this.$element[b](0)},reset:function(a){var b=this.dimension();return this.$element.removeClass("collapse")[b](a||"auto")[0].offsetWidth,this.$element[a!==null?"addClass":"removeClass"]("collapse"),this},transition:function(b,c,d){var e=this,f=function(){c.type=="show"&&e.reset(),e.transitioning=0,e.$element.trigger(d)};this.$element.trigger(c);if(c.isDefaultPrevented())return;this.transitioning=1,this.$element[b]("in"),a.support.transition&&this.$element.hasClass("collapse")?this.$element.one(a.support.transition.end,f):f()},toggle:function(){this[this.$element.hasClass("in")?"hide":"show"]()}},a.fn.collapse=function(c){return this.each(function(){var d=a(this),e=d.data("collapse"),f=typeof c=="object"&&c;e||d.data("collapse",e=new b(this,f)),typeof c=="string"&&e[c]()})},a.fn.collapse.defaults={toggle:!0},a.fn.collapse.Constructor=b,a(function(){a("body").on("click.collapse.data-api","[data-toggle=collapse]",function(b){var c=a(this),d,e=c.attr("data-target")||b.preventDefault()||(d=c.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,""),f=a(e).data("collapse")?"toggle":c.data();c[a(e).hasClass("in")?"addClass":"removeClass"]("collapsed"),a(e).collapse(f)})})}(window.jQuery),!function(a){function d(){e(a(b)).removeClass("open")}function e(b){var c=b.attr("data-target"),d;return c||(c=b.attr("href"),c=c&&c.replace(/.*(?=#[^\s]*$)/,"")),d=a(c),d.length||(d=b.parent()),d}"use strict";var b="[data-toggle=dropdown]",c=function(b){var c=a(b).on("click.dropdown.data-api",this.toggle);a("html").on("click.dropdown.data-api",function(){c.parent().removeClass("open")})};c.prototype={constructor:c,toggle:function(b){var c=a(this),f,g;if(c.is(".disabled, :disabled"))return;return f=e(c),g=f.hasClass("open"),d(),g||(f.toggleClass("open"),c.focus()),!1},keydown:function(b){var c,d,f,g,h,i;if(!/(38|40|27)/.test(b.keyCode))return;c=a(this),b.preventDefault(),b.stopPropagation();if(c.is(".disabled, :disabled"))return;g=e(c),h=g.hasClass("open");if(!h||h&&b.keyCode==27)return c.click();d=a("[role=menu] li:not(.divider) a",g);if(!d.length)return;i=d.index(d.filter(":focus")),b.keyCode==38&&i>0&&i--,b.keyCode==40&&i').appendTo(document.body),this.options.backdrop!="static"&&this.$backdrop.click(a.proxy(this.hide,this)),e&&this.$backdrop[0].offsetWidth,this.$backdrop.addClass("in"),e?this.$backdrop.one(a.support.transition.end,b):b()}else!this.isShown&&this.$backdrop?(this.$backdrop.removeClass("in"),a.support.transition&&this.$element.hasClass("fade")?this.$backdrop.one(a.support.transition.end,a.proxy(this.removeBackdrop,this)):this.removeBackdrop()):b&&b()}},a.fn.modal=function(c){return this.each(function(){var d=a(this),e=d.data("modal"),f=a.extend({},a.fn.modal.defaults,d.data(),typeof c=="object"&&c);e||d.data("modal",e=new b(this,f)),typeof c=="string"?e[c]():f.show&&e.show()})},a.fn.modal.defaults={backdrop:!0,keyboard:!0,show:!0},a.fn.modal.Constructor=b,a(function(){a("body").on("click.modal.data-api",'[data-toggle="modal"]',function(b){var c=a(this),d=c.attr("href"),e=a(c.attr("data-target")||d&&d.replace(/.*(?=#[^\s]+$)/,"")),f=e.data("modal")?"toggle":a.extend({remote:!/#/.test(d)&&d},e.data(),c.data());b.preventDefault(),e.modal(f).one("hide",function(){c.focus()})})})}(window.jQuery),!function(a){"use strict";var b=function(a,b){this.init("tooltip",a,b)};b.prototype={constructor:b,init:function(b,c,d){var e,f;this.type=b,this.$element=a(c),this.options=this.getOptions(d),this.enabled=!0,this.options.trigger=="click"?this.$element.on("click."+this.type,this.options.selector,a.proxy(this.toggle,this)):this.options.trigger!="manual"&&(e=this.options.trigger=="hover"?"mouseenter":"focus",f=this.options.trigger=="hover"?"mouseleave":"blur",this.$element.on(e+"."+this.type,this.options.selector,a.proxy(this.enter,this)),this.$element.on(f+"."+this.type,this.options.selector,a.proxy(this.leave,this))),this.options.selector?this._options=a.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},getOptions:function(b){return b=a.extend({},a.fn[this.type].defaults,b,this.$element.data()),b.delay&&typeof b.delay=="number"&&(b.delay={show:b.delay,hide:b.delay}),b},enter:function(b){var c=a(b.currentTarget)[this.type](this._options).data(this.type);if(!c.options.delay||!c.options.delay.show)return c.show();clearTimeout(this.timeout),c.hoverState="in",this.timeout=setTimeout(function(){c.hoverState=="in"&&c.show()},c.options.delay.show)},leave:function(b){var c=a(b.currentTarget)[this.type](this._options).data(this.type);this.timeout&&clearTimeout(this.timeout);if(!c.options.delay||!c.options.delay.hide)return c.hide();c.hoverState="out",this.timeout=setTimeout(function(){c.hoverState=="out"&&c.hide()},c.options.delay.hide)},show:function(){var a,b,c,d,e,f,g;if(this.hasContent()&&this.enabled){a=this.tip(),this.setContent(),this.options.animation&&a.addClass("fade"),f=typeof this.options.placement=="function"?this.options.placement.call(this,a[0],this.$element[0]):this.options.placement,b=/in/.test(f),a.remove().css({top:0,left:0,display:"block"}).appendTo(b?this.$element:document.body),c=this.getPosition(b),d=a[0].offsetWidth,e=a[0].offsetHeight;switch(b?f.split(" ")[1]:f){case"bottom":g={top:c.top+c.height,left:c.left+c.width/2-d/2};break;case"top":g={top:c.top-e,left:c.left+c.width/2-d/2};break;case"left":g={top:c.top+c.height/2-e/2,left:c.left-d};break;case"right":g={top:c.top+c.height/2-e/2,left:c.left+c.width}}a.css(g).addClass(f).addClass("in")}},setContent:function(){var a=this.tip(),b=this.getTitle();a.find(".tooltip-inner")[this.options.html?"html":"text"](b),a.removeClass("fade in top bottom left right")},hide:function(){function d(){var b=setTimeout(function(){c.off(a.support.transition.end).remove()},500);c.one(a.support.transition.end,function(){clearTimeout(b),c.remove()})}var b=this,c=this.tip();return c.removeClass("in"),a.support.transition&&this.$tip.hasClass("fade")?d():c.remove(),this},fixTitle:function(){var a=this.$element;(a.attr("title")||typeof a.attr("data-original-title")!="string")&&a.attr("data-original-title",a.attr("title")||"").removeAttr("title")},hasContent:function(){return this.getTitle()},getPosition:function(b){return a.extend({},b?{top:0,left:0}:this.$element.offset(),{width:this.$element[0].offsetWidth,height:this.$element[0].offsetHeight})},getTitle:function(){var a,b=this.$element,c=this.options;return a=b.attr("data-original-title")||(typeof c.title=="function"?c.title.call(b[0]):c.title),a},tip:function(){return this.$tip=this.$tip||a(this.options.template)},validate:function(){this.$element[0].parentNode||(this.hide(),this.$element=null,this.options=null)},enable:function(){this.enabled=!0},disable:function(){this.enabled=!1},toggleEnabled:function(){this.enabled=!this.enabled},toggle:function(){this[this.tip().hasClass("in")?"hide":"show"]()},destroy:function(){this.hide().$element.off("."+this.type).removeData(this.type)}},a.fn.tooltip=function(c){return this.each(function(){var d=a(this),e=d.data("tooltip"),f=typeof c=="object"&&c;e||d.data("tooltip",e=new b(this,f)),typeof c=="string"&&e[c]()})},a.fn.tooltip.Constructor=b,a.fn.tooltip.defaults={animation:!0,placement:"top",selector:!1,template:'
',trigger:"hover",title:"",delay:0,html:!0}}(window.jQuery),!function(a){"use strict";var b=function(a,b){this.init("popover",a,b)};b.prototype=a.extend({},a.fn.tooltip.Constructor.prototype,{constructor:b,setContent:function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content > *")[this.options.html?"html":"text"](c),a.removeClass("fade top bottom left right in")},hasContent:function(){return this.getTitle()||this.getContent()},getContent:function(){var a,b=this.$element,c=this.options;return a=b.attr("data-content")||(typeof c.content=="function"?c.content.call(b[0]):c.content),a},tip:function(){return this.$tip||(this.$tip=a(this.options.template)),this.$tip},destroy:function(){this.hide().$element.off("."+this.type).removeData(this.type)}}),a.fn.popover=function(c){return this.each(function(){var d=a(this),e=d.data("popover"),f=typeof c=="object"&&c;e||d.data("popover",e=new b(this,f)),typeof c=="string"&&e[c]()})},a.fn.popover.Constructor=b,a.fn.popover.defaults=a.extend({},a.fn.tooltip.defaults,{placement:"right",trigger:"click",content:"",template:'

'})}(window.jQuery),!function(a){function b(b,c){var d=a.proxy(this.process,this),e=a(b).is("body")?a(window):a(b),f;this.options=a.extend({},a.fn.scrollspy.defaults,c),this.$scrollElement=e.on("scroll.scroll-spy.data-api",d),this.selector=(this.options.target||(f=a(b).attr("href"))&&f.replace(/.*(?=#[^\s]+$)/,"")||"")+" .nav li > a",this.$body=a("body"),this.refresh(),this.process()}"use strict",b.prototype={constructor:b,refresh:function(){var b=this,c;this.offsets=a([]),this.targets=a([]),c=this.$body.find(this.selector).map(function(){var b=a(this),c=b.data("target")||b.attr("href"),d=/^#\w/.test(c)&&a(c);return d&&d.length&&[[d.position().top,c]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){b.offsets.push(this[0]),b.targets.push(this[1])})},process:function(){var a=this.$scrollElement.scrollTop()+this.options.offset,b=this.$scrollElement[0].scrollHeight||this.$body[0].scrollHeight,c=b-this.$scrollElement.height(),d=this.offsets,e=this.targets,f=this.activeTarget,g;if(a>=c)return f!=(g=e.last()[0])&&this.activate(g);for(g=d.length;g--;)f!=e[g]&&a>=d[g]&&(!d[g+1]||a<=d[g+1])&&this.activate(e[g])},activate:function(b){var c,d;this.activeTarget=b,a(this.selector).parent(".active").removeClass("active"),d=this.selector+'[data-target="'+b+'"],'+this.selector+'[href="'+b+'"]',c=a(d).parent("li").addClass("active"),c.parent(".dropdown-menu").length&&(c=c.closest("li.dropdown").addClass("active")),c.trigger("activate")}},a.fn.scrollspy=function(c){return this.each(function(){var d=a(this),e=d.data("scrollspy"),f=typeof c=="object"&&c;e||d.data("scrollspy",e=new b(this,f)),typeof c=="string"&&e[c]()})},a.fn.scrollspy.Constructor=b,a.fn.scrollspy.defaults={offset:10},a(window).on("load",function(){a('[data-spy="scroll"]').each(function(){var b=a(this);b.scrollspy(b.data())})})}(window.jQuery),!function(a){"use strict";var b=function(b){this.element=a(b)};b.prototype={constructor:b,show:function(){var b=this.element,c=b.closest("ul:not(.dropdown-menu)"),d=b.attr("data-target"),e,f,g;d||(d=b.attr("href"),d=d&&d.replace(/.*(?=#[^\s]*$)/,""));if(b.parent("li").hasClass("active"))return;e=c.find(".active a").last()[0],g=a.Event("show",{relatedTarget:e}),b.trigger(g);if(g.isDefaultPrevented())return;f=a(d),this.activate(b.parent("li"),c),this.activate(f,f.parent(),function(){b.trigger({type:"shown",relatedTarget:e})})},activate:function(b,c,d){function g(){e.removeClass("active").find("> .dropdown-menu > .active").removeClass("active"),b.addClass("active"),f?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu")&&b.closest("li.dropdown").addClass("active"),d&&d()}var e=c.find("> .active"),f=d&&a.support.transition&&e.hasClass("fade");f?e.one(a.support.transition.end,g):g(),e.removeClass("in")}},a.fn.tab=function(c){return this.each(function(){var d=a(this),e=d.data("tab");e||d.data("tab",e=new b(this)),typeof c=="string"&&e[c]()})},a.fn.tab.Constructor=b,a(function(){a("body").on("click.tab.data-api",'[data-toggle="tab"], [data-toggle="pill"]',function(b){b.preventDefault(),a(this).tab("show")})})}(window.jQuery),!function(a){"use strict";var b=function(b,c){this.$element=a(b),this.options=a.extend({},a.fn.typeahead.defaults,c),this.matcher=this.options.matcher||this.matcher,this.sorter=this.options.sorter||this.sorter,this.highlighter=this.options.highlighter||this.highlighter,this.updater=this.options.updater||this.updater,this.$menu=a(this.options.menu).appendTo("body"),this.source=this.options.source,this.shown=!1,this.listen()};b.prototype={constructor:b,select:function(){var a=this.$menu.find(".active").attr("data-value");return this.$element.val(this.updater(a)).change(),this.hide()},updater:function(a){return a},show:function(){var b=a.extend({},this.$element.offset(),{height:this.$element[0].offsetHeight});return this.$menu.css({top:b.top+b.height,left:b.left}),this.$menu.show(),this.shown=!0,this},hide:function(){return this.$menu.hide(),this.shown=!1,this},lookup:function(b){var c;return this.query=this.$element.val(),!this.query||this.query.length"+b+""})},render:function(b){var c=this;return b=a(b).map(function(b,d){return b=a(c.options.item).attr("data-value",d),b.find("a").html(c.highlighter(d)),b[0]}),b.first().addClass("active"),this.$menu.html(b),this},next:function(b){var c=this.$menu.find(".active").removeClass("active"),d=c.next();d.length||(d=a(this.$menu.find("li")[0])),d.addClass("active")},prev:function(a){var b=this.$menu.find(".active").removeClass("active"),c=b.prev();c.length||(c=this.$menu.find("li").last()),c.addClass("active")},listen:function(){this.$element.on("blur",a.proxy(this.blur,this)).on("keypress",a.proxy(this.keypress,this)).on("keyup",a.proxy(this.keyup,this)),(a.browser.webkit||a.browser.msie)&&this.$element.on("keydown",a.proxy(this.keydown,this)),this.$menu.on("click",a.proxy(this.click,this)).on("mouseenter","li",a.proxy(this.mouseenter,this))},move:function(a){if(!this.shown)return;switch(a.keyCode){case 9:case 13:case 27:a.preventDefault();break;case 38:a.preventDefault(),this.prev();break;case 40:a.preventDefault(),this.next()}a.stopPropagation()},keydown:function(b){this.suppressKeyPressRepeat=!~a.inArray(b.keyCode,[40,38,9,13,27]),this.move(b)},keypress:function(a){if(this.suppressKeyPressRepeat)return;this.move(a)},keyup:function(a){switch(a.keyCode){case 40:case 38:break;case 9:case 13:if(!this.shown)return;this.select();break;case 27:if(!this.shown)return;this.hide();break;default:this.lookup()}a.stopPropagation(),a.preventDefault()},blur:function(a){var b=this;setTimeout(function(){b.hide()},150)},click:function(a){a.stopPropagation(),a.preventDefault(),this.select()},mouseenter:function(b){this.$menu.find(".active").removeClass("active"),a(b.currentTarget).addClass("active")}},a.fn.typeahead=function(c){return this.each(function(){var d=a(this),e=d.data("typeahead"),f=typeof c=="object"&&c;e||d.data("typeahead",e=new b(this,f)),typeof c=="string"&&e[c]()})},a.fn.typeahead.defaults={source:[],items:8,menu:'',item:'
  • ',minLength:1},a.fn.typeahead.Constructor=b,a(function(){a("body").on("focus.typeahead.data-api",'[data-provide="typeahead"]',function(b){var c=a(this);if(c.data("typeahead"))return;b.preventDefault(),c.typeahead(c.data())})})}(window.jQuery); --------------------------------------------------------------------------------