Changeset 5336:fe802c9b09e9 in livinglogic.python.xist for src/ll/ul4c.py

Show
Ignore:
Timestamp:
02/11/13 13:46:43 (7 years ago)
Author:
Walter Doerwald <walter@…>
Branch:
default
Message:

Merge AST and Tag again.

Expressions are now allowed as the content of <?code tag?>, so they may sit at
the top level in tags.

Have the location object point back to the root template. With this we don't
have to pass along the keepws flag in eval().

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • src/ll/ul4c.py

    r5335 r5336  
    6262    template tag. 
    6363    """ 
    64     __slots__ = ("source", "type", "starttag", "endtag", "startcode", "endcode") 
    65     fields = {"source", "type", "starttag", "endtag", "startcode", "endcode", "tag", "code"} 
    66  
    67     def __init__(self, source=None, type=None, starttag=None, endtag=None, startcode=None, endcode=None): 
     64    __slots__ = ("root", "source", "type", "starttag", "endtag", "startcode", "endcode") 
     65    fields = {"root", "source", "type", "starttag", "endtag", "startcode", "endcode", "tag", "code"} 
     66 
     67    def __init__(self, root=None, source=None, type=None, starttag=None, endtag=None, startcode=None, endcode=None): 
    6868        """ 
    6969        Create a new :class:`Location` object. The arguments have the following 
    7070        meaning: 
    7171 
     72            :var:`root` 
     73                The :class:`Template` object 
     74 
    7275            :var:`source` 
    7376                The complete source string 
     
    8992                The end position of the tag code. 
    9093        """ 
     94        self.root = root 
    9195        self.source = source 
    9296        self.type = type 
     
    119123 
    120124    def ul4ondump(self, encoder): 
     125        encoder.dump(self.root) 
    121126        encoder.dump(self.source) 
    122127        encoder.dump(self.type) 
     
    127132 
    128133    def ul4onload(self, decoder): 
     134        self.root = decoder.load() 
    129135        self.source = decoder.load() 
    130136        self.type = decoder.load() 
     
    155161            else: 
    156162                return "in unnamed template" 
    157         elif isinstance(self.location, Tag): 
    158             return "in tag {}".format(self.location.location) 
    159163        elif isinstance(self.location, AST): 
    160164            return "in expression {}".format(self.location) 
     
    243247 
    244248def handleeval(f): 
    245     def wrapped(self, keepws, vars): 
     249    def wrapped(self, vars): 
    246250        try: 
    247             return (yield from f(self, keepws, vars)) 
     251            return (yield from f(self, vars)) 
    248252        except (BreakException, ContinueException, ReturnException) as ex: 
    249253            raise 
     
    262266 
    263267    # Set of attributes available via :meth:`getitem`. 
    264     fields = {"type"} 
     268    fields = {"type", "location"} 
    265269 
    266270    # "Global" functions and methods. Functions in ``functions`` will be exposed to UL4 code 
    267271    functions = {} 
    268272    methods = {} 
     273 
     274    def __init__(self, location=None): 
     275        self.location = location 
    269276 
    270277    def __getitem__(self, key): 
     
    303310 
    304311    @misc.notimplemented 
    305     def eval(self, keepws, vars): 
     312    def eval(self, vars): 
    306313        """ 
    307314        This evaluates the node. 
     
    311318        :exc:`StopIteration` exception. 
    312319        """ 
     320 
     321    def ul4ondump(self, encoder): 
     322        encoder.dump(self.location) 
     323 
     324    def ul4onload(self, decoder): 
     325        self.location = decoder.load() 
    313326 
    314327    @classmethod 
     
    329342 
    330343 
    331 class Tag(AST): 
    332     """ 
    333     Base class for all syntax tree nodes that are the top level node in a 
    334     template tag. 
    335     """ 
    336     # Set of attributes available via :meth:`getitem`. 
    337     fields = AST.fields.union({"location"}) 
    338  
    339     def __init__(self, location=None): 
    340         self.location = location 
    341  
    342     def ul4ondump(self, encoder): 
    343         encoder.dump(self.location) 
    344  
    345     def ul4onload(self, decoder): 
    346         self.location = decoder.load() 
    347  
    348  
    349344@register("text") 
    350 class Text(Tag): 
     345class Text(AST): 
    351346    """ 
    352347    AST node for literal text. 
    353348    """ 
    354349 
    355     def text(self, keepws): 
     350    def text(self): 
    356351        # If ``keepws`` is true, we output the literal text from the location info. 
    357352        # Otherwise we have to strip linefeeds and indentation 
    358353        text = self.location.code 
    359         if not keepws: 
     354        if not self.location.root.keepws: 
    360355            text = "".join(line.lstrip() for line in text.splitlines()) 
    361356        return text 
     
    365360 
    366361    def _str(self, indent, keepws): 
    367         text = self.text(keepws) 
     362        text = self.text() 
    368363        if text: 
    369364            yield indent*"\t" 
    370365            yield "text {!r}\n".format(text) 
    371366 
    372     def eval(self, keepws, vars): 
    373         yield self.text(keepws) 
     367    def eval(self, vars): 
     368        yield self.text() 
    374369 
    375370 
     
    382377    fields = AST.fields.union({"value"}) 
    383378 
    384     def __init__(self, value=None): 
     379    def __init__(self, location=None, value=None): 
     380        super().__init__(location) 
    385381        self.value = value 
    386382 
     
    388384        yield _repr(self.value) 
    389385 
    390     def eval(self, keepws, vars): 
     386    def eval(self, vars): 
    391387        yield from () 
    392388        return self.value 
    393389 
    394390    def ul4ondump(self, encoder): 
     391        super().ul4ondump(encoder) 
    395392        encoder.dump(self.value) 
    396393 
    397394    def ul4onload(self, decoder): 
     395        super().ul4onload(decoder) 
    398396        self.value = decoder.load() 
    399397 
     
    411409    fields = AST.fields.union({"items"}) 
    412410 
    413     def __init__(self, *items): 
     411    def __init__(self, location=None, *items): 
     412        super().__init__(location) 
    414413        self.items = list(items) 
    415414 
     
    440439 
    441440    @handleeval 
    442     def eval(self, keepws, vars): 
     441    def eval(self, vars): 
    443442        result = [] 
    444443        for item in self.items: 
    445             item = (yield from item.eval(keepws, vars)) 
     444            item = (yield from item.eval(vars)) 
    446445            result.append(item) 
    447446        return result 
    448447 
    449448    def ul4ondump(self, encoder): 
     449        super().ul4ondump(encoder) 
    450450        encoder.dump(self.items) 
    451451 
    452452    def ul4onload(self, decoder): 
     453        super().ul4onload(decoder) 
    453454        self.items = decoder.load() 
    454455 
     
    464465 
    465466 
    466     def __init__(self, item=None, varname=None, container=None, condition=None): 
    467         super().__init__() 
     467    def __init__(self, location=None, item=None, varname=None, container=None, condition=None): 
     468        super().__init__(location) 
    468469        self.item = item 
    469470        self.varname = varname 
     
    514515 
    515516    @handleeval 
    516     def eval(self, keepws, vars): 
    517         container = (yield from self.container.eval(keepws, vars)) 
     517    def eval(self, vars): 
     518        container = (yield from self.container.eval(vars)) 
    518519        vars = collections.ChainMap({}, vars) # Don't let loop variables leak into the surrounding scope 
    519520        result = [] 
    520521        for item in container: 
    521522            _unpackvar(vars, self.varname, item) 
    522             if self.condition is None or (yield from self.condition.eval(keepws, vars)): 
    523                 item = (yield from self.item.eval(keepws, vars)) 
     523            if self.condition is None or (yield from self.condition.eval(vars)): 
     524                item = (yield from self.item.eval(vars)) 
    524525                result.append(item) 
    525526        return result 
    526527 
    527528    def ul4ondump(self, encoder): 
     529        super().ul4ondump(encoder) 
    528530        encoder.dump(self.item) 
    529531        encoder.dump(self.varname) 
     
    532534 
    533535    def ul4onload(self, decoder): 
     536        super().ul4onload(decoder) 
    534537        self.item = decoder.load() 
    535538        self.varname = decoder.load() 
     
    547550    fields = AST.fields.union({"items"}) 
    548551 
    549     def __init__(self, *items): 
     552    def __init__(self, location=None, *items): 
     553        super().__init__(location) 
    550554        self.items = list(items) 
    551555 
     
    577581 
    578582    @handleeval 
    579     def eval(self, keepws, vars): 
     583    def eval(self, vars): 
    580584        result = {} 
    581585        for item in self.items: 
    582             key = (yield from item[0].eval(keepws, vars)) 
    583             value = (yield from item[1].eval(keepws, vars)) 
     586            key = (yield from item[0].eval(vars)) 
     587            value = (yield from item[1].eval(vars)) 
    584588            result[key] = value 
    585589        return result 
    586590 
    587591    def ul4ondump(self, encoder): 
     592        super().ul4ondump(encoder) 
    588593        encoder.dump(self.items) 
    589594 
    590595    def ul4onload(self, decoder): 
     596        super().ul4onload(decoder) 
    591597        self.items = [tuple(item) for item in decoder.load()] 
    592598 
     
    601607    fields = AST.fields.union({"key", "value", "varname", "container", "condition"}) 
    602608 
    603     def __init__(self, key=None, value=None, varname=None, container=None, condition=None): 
     609    def __init__(self, location=None, key=None, value=None, varname=None, container=None, condition=None): 
     610        super().__init__(location) 
    604611        self.key = key 
    605612        self.value = value 
     
    653660 
    654661    @handleeval 
    655     def eval(self, keepws, vars): 
    656         container = (yield from self.container.eval(keepws, vars)) 
     662    def eval(self, vars): 
     663        container = (yield from self.container.eval(vars)) 
    657664        vars = collections.ChainMap({}, vars) # Don't let loop variables leak into the surrounding scope 
    658665        result = {} 
    659666        for item in container: 
    660667            _unpackvar(vars, self.varname, item) 
    661             if self.condition is None or (yield from self.condition.eval(keepws, vars)): 
    662                 key = (yield from self.key.eval(keepws, vars)) 
    663                 value = (yield from self.value.eval(keepws, vars)) 
     668            if self.condition is None or (yield from self.condition.eval(vars)): 
     669                key = (yield from self.key.eval(vars)) 
     670                value = (yield from self.value.eval(vars)) 
    664671                result[key] = value 
    665672        return result 
    666673 
    667674    def ul4ondump(self, encoder): 
     675        super().ul4ondump(encoder) 
    668676        encoder.dump(self.key) 
    669677        encoder.dump(self.value) 
     
    673681 
    674682    def ul4onload(self, decoder): 
     683        super().ul4onload(decoder) 
    675684        self.key = decoder.load() 
    676685        self.value = decoder.load() 
     
    689698    fields = AST.fields.union({"item", "varname", "container", "condition"}) 
    690699 
    691     def __init__(self, item=None, varname=None, container=None, condition=None): 
     700    def __init__(self, location=None, item=None, varname=None, container=None, condition=None): 
     701        super().__init__(location) 
    692702        self.item = item 
    693703        self.varname = varname 
     
    735745 
    736746    @handleeval 
    737     def eval(self, keepws, vars): 
    738         container = (yield from self.container.eval(keepws, vars)) 
     747    def eval(self, vars): 
     748        container = (yield from self.container.eval(vars)) 
    739749        vars = collections.ChainMap({}, vars) # Don't let loop variables leak into the surrounding scope 
    740750        def result(): 
    741751            for item in container: 
    742752                _unpackvar(vars, self.varname, item) 
    743                 if self.condition is None or (yield from self.condition.eval(keepws, vars)): 
    744                     item = (yield from self.item.eval(keepws, vars)) 
     753                if self.condition is None or (yield from self.condition.eval(vars)): 
     754                    item = (yield from self.item.eval(vars)) 
    745755                    yield item 
    746756        return result() 
    747757 
    748758    def ul4ondump(self, encoder): 
     759        super().ul4ondump(encoder) 
    749760        encoder.dump(self.item) 
    750761        encoder.dump(self.varname) 
     
    753764 
    754765    def ul4onload(self, decoder): 
     766        super().ul4onload(decoder) 
    755767        self.item = decoder.load() 
    756768        self.varname = decoder.load() 
     
    768780    fields = AST.fields.union({"name"}) 
    769781 
    770     def __init__(self, name=None): 
     782    def __init__(self, location=None, name=None): 
     783        super().__init__(location) 
    771784        self.name = name 
    772785 
     
    778791 
    779792    @handleeval 
    780     def eval(self, keepws, vars): 
     793    def eval(self, vars): 
    781794        yield from () 
    782795        try: 
     
    789802 
    790803    def ul4ondump(self, encoder): 
     804        super().ul4ondump(encoder) 
    791805        encoder.dump(self.name) 
    792806 
    793807    def ul4onload(self, decoder): 
     808        super().ul4onload(decoder) 
    794809        self.name = decoder.load() 
    795810 
    796811 
    797 class Block(Tag): 
     812class Block(AST): 
    798813    """ 
    799814    Base class for all AST nodes that are blocks. 
    800815 
    801     A block contains a sequence of tags that are executed sequencially. 
     816    A block contains a sequence of AST nodes that are executed sequencially. 
    802817    A block may execute its content zero (e.g. an ``<?if?>`` block) or more times 
    803818    (e.g. a ``<?for?>`` block). 
    804819    """ 
    805820 
    806     fields = Tag.fields.union({"endlocation", "content"}) 
     821    fields = AST.fields.union({"endlocation", "content"}) 
    807822 
    808823    def __init__(self, location=None): 
     
    823838 
    824839    @handleeval 
    825     def eval(self, keepws, vars): 
     840    def eval(self, vars): 
    826841        for node in self.content: 
    827             yield from node.eval(keepws, vars) 
     842            yield from node.eval(vars) 
    828843 
    829844    def ul4ondump(self, encoder): 
     
    875890 
    876891    @handleeval 
    877     def eval(self, keepws, vars): 
     892    def eval(self, vars): 
    878893        for node in self.content: 
    879             if isinstance(node, Else) or (yield from node.condition.eval(keepws, vars)): 
    880                 yield from node.eval(keepws, vars) 
     894            if isinstance(node, Else) or (yield from node.condition.eval(vars)): 
     895                yield from node.eval(vars) 
    881896                break 
    882897 
     
    10511066 
    10521067    @handleeval 
    1053     def eval(self, keepws, vars): 
    1054         container = (yield from self.container.eval(keepws, vars)) 
     1068    def eval(self, vars): 
     1069        container = (yield from self.container.eval(vars)) 
    10551070        vars = collections.ChainMap({}, vars) # Don't let loop variables leak into the surrounding scope 
    10561071        for item in container: 
    10571072            _unpackvar(vars, self.varname, item) 
    10581073            try: 
    1059                 yield from super().eval(keepws, vars) 
     1074                yield from super().eval(vars) 
    10601075            except BreakException: 
    10611076                break 
     
    10651080 
    10661081@register("break") 
    1067 class Break(Tag): 
     1082class Break(AST): 
    10681083    """ 
    10691084    AST node for a ``<?break?>`` inside a ``<?for?>`` block. 
     
    10741089        yield "break\n" 
    10751090 
    1076     def eval(self, keepws, vars): 
     1091    def eval(self, vars): 
    10771092        yield from () 
    10781093        raise BreakException() 
     
    10801095 
    10811096@register("continue") 
    1082 class Continue(Tag): 
     1097class Continue(AST): 
    10831098    """ 
    10841099    AST node for a ``<?continue?>`` inside a ``<?for?>`` block. 
     
    10891104        yield "continue\n" 
    10901105 
    1091     def eval(self, keepws, vars): 
     1106    def eval(self, vars): 
    10921107        yield from () 
    10931108        raise ContinueException() 
     
    11061121    fields = AST.fields.union({"obj", "attrname"}) 
    11071122 
    1108     def __init__(self, obj=None, attrname=None): 
     1123    def __init__(self, location=None, obj=None, attrname=None): 
     1124        super().__init__(location) 
    11091125        self.obj = obj 
    11101126        self.attrname = attrname 
     
    11331149 
    11341150    @handleeval 
    1135     def eval(self, keepws, vars): 
    1136         obj = (yield from self.obj.eval(keepws, vars)) 
     1151    def eval(self, vars): 
     1152        obj = (yield from self.obj.eval(vars)) 
    11371153        try: 
    11381154            return obj[self.attrname] 
     
    11411157 
    11421158    def ul4ondump(self, encoder): 
     1159        super().ul4ondump(encoder) 
    11431160        encoder.dump(self.obj) 
    11441161        encoder.dump(self.attrname) 
    11451162 
    11461163    def ul4onload(self, decoder): 
     1164        super().ul4onload(decoder) 
    11471165        self.obj = decoder.load() 
    11481166        self.attrname = decoder.load() 
     
    11651183    fields = AST.fields.union({"obj", "index1", "index2"}) 
    11661184 
    1167     def __init__(self, obj=None, index1=None, index2=None): 
     1185    def __init__(self, location=None, obj=None, index1=None, index2=None): 
     1186        super().__init__(location) 
    11681187        self.obj = obj 
    11691188        self.index1 = index1 
     
    12011220 
    12021221    @handleeval 
    1203     def eval(self, keepws, vars): 
    1204         obj = (yield from self.obj.eval(keepws, vars)) 
     1222    def eval(self, vars): 
     1223        obj = (yield from self.obj.eval(vars)) 
    12051224        if self.index1 is not None: 
    1206             index1 = (yield from self.index1.eval(keepws, vars)) 
     1225            index1 = (yield from self.index1.eval(vars)) 
    12071226            if self.index2 is not None: 
    1208                 index2 = (yield from self.index2.eval(keepws, vars)) 
     1227                index2 = (yield from self.index2.eval(vars)) 
    12091228                return obj[index1:index2] 
    12101229            else: 
     
    12121231        else: 
    12131232            if self.index2 is not None: 
    1214                 index2 = (yield from self.index2.eval(keepws, vars)) 
     1233                index2 = (yield from self.index2.eval(vars)) 
    12151234                return obj[:index2] 
    12161235            else: 
     
    12181237 
    12191238    def ul4ondump(self, encoder): 
     1239        super().ul4ondump(encoder) 
    12201240        encoder.dump(self.obj) 
    12211241        encoder.dump(self.index1) 
     
    12231243 
    12241244    def ul4onload(self, decoder): 
     1245        super().ul4onload(decoder) 
    12251246        self.obj = decoder.load() 
    12261247        self.index1 = decoder.load() 
     
    12351256    fields = AST.fields.union({"obj"}) 
    12361257 
    1237     def __init__(self, obj=None): 
     1258    def __init__(self, location=None, obj=None): 
     1259        super().__init__(location) 
    12381260        self.obj = obj 
    12391261 
     
    12521274 
    12531275    def ul4ondump(self, encoder): 
     1276        super().ul4ondump(encoder) 
    12541277        encoder.dump(self.obj) 
    12551278 
    12561279    def ul4onload(self, decoder): 
     1280        super().ul4onload(decoder) 
    12571281        self.obj = decoder.load() 
    12581282 
    12591283    @handleeval 
    1260     def eval(self, keepws, vars): 
    1261         obj = (yield from self.obj.eval(keepws, vars)) 
     1284    def eval(self, vars): 
     1285        obj = (yield from self.obj.eval(vars)) 
    12621286        return self.evalfold(obj) 
    12631287 
    12641288    @classmethod 
    1265     def make(cls, obj): 
     1289    def make(cls, location, obj): 
    12661290        if isinstance(obj, Const): 
    12671291            result = cls.evalfold(obj.value) 
    12681292            if not isinstance(result, Undefined): 
    1269                 return Const(result) 
    1270         return cls(obj) 
     1293                return Const(location, result) 
     1294        return cls(location, obj) 
    12711295 
    12721296 
     
    13051329 
    13061330 
    1307 class UnaryTag(Tag): 
    1308     fields = Tag.fields.union({"obj"}) 
    1309  
    1310     def __init__(self, location=None, obj=None): 
     1331@register("print") 
     1332class Print(Unary): 
     1333    """ 
     1334    AST node for a ``<?print?>`` tag. 
     1335    """ 
     1336 
     1337    def _str(self, indent, keepws): 
     1338        yield indent*"\t" 
     1339        yield "print " 
     1340        yield from self.obj._str(indent, keepws) 
     1341        yield "\n" 
     1342 
     1343    @handleeval 
     1344    def eval(self, vars): 
     1345        yield _str((yield from self.obj.eval(vars))) 
     1346 
     1347 
     1348@register("printx") 
     1349class PrintX(Unary): 
     1350    """ 
     1351    AST node for a ``<?printx?>`` tag. 
     1352    """ 
     1353 
     1354    def _str(self, indent, keepws): 
     1355        yield indent*"\t" 
     1356        yield "printx " 
     1357        yield from self.obj._str(indent, keepws) 
     1358        yield "\n" 
     1359 
     1360    @handleeval 
     1361    def eval(self, vars): 
     1362        yield _xmlescape((yield from self.obj.eval(vars))) 
     1363 
     1364 
     1365@register("return") 
     1366class Return(Unary): 
     1367    """ 
     1368    AST node for a ``<?return?>`` tag. 
     1369    """ 
     1370 
     1371    def _str(self, indent, keepws): 
     1372        yield indent*"\t" 
     1373        yield "return " 
     1374        yield from self.obj._str(indent, keepws) 
     1375        yield "\n" 
     1376 
     1377    @handleeval 
     1378    def eval(self, vars): 
     1379        value = (yield from self.obj.eval(vars)) 
     1380        raise ReturnException(value) 
     1381 
     1382 
     1383class Binary(AST): 
     1384    """ 
     1385    Base class for all AST nodes implementing binary operators. 
     1386    """ 
     1387 
     1388    fields = AST.fields.union({"obj1", "obj2"}) 
     1389 
     1390    def __init__(self, location=None, obj1=None, obj2=None): 
    13111391        super().__init__(location) 
    1312         self.obj = obj 
     1392        self.obj1 = obj1 
     1393        self.obj2 = obj2 
    13131394 
    13141395    def __repr__(self): 
    1315         return "<{0.__class__.__module__}.{0.__class__.__qualname__} {0.obj!r} at {1:#x}>".format(self, id(self)) 
     1396        return "<{0.__class__.__module__}.{0.__class__.__qualname__} {0.obj1!r} {0.obj2!r} at {1:#x}>".format(self, id(self)) 
    13161397 
    13171398    def _repr_pretty_(self, p, cycle): 
     
    13211402            with p.group(4, "<{0.__class__.__module__}.{0.__class__.__qualname__}".format(self), ">"): 
    13221403                p.breakable() 
    1323                 p.pretty(self.obj) 
     1404                p.pretty(self.obj1) 
     1405                p.breakable() 
     1406                p.pretty(self.obj2) 
    13241407                p.breakable() 
    13251408                p.text("at {:#x}".format(id(self))) 
     
    13271410    def ul4ondump(self, encoder): 
    13281411        super().ul4ondump(encoder) 
    1329         encoder.dump(self.obj) 
     1412        encoder.dump(self.obj1) 
     1413        encoder.dump(self.obj2) 
    13301414 
    13311415    def ul4onload(self, decoder): 
    13321416        super().ul4onload(decoder) 
    1333         self.obj = decoder.load() 
    1334  
    1335  
    1336 @register("print") 
    1337 class Print(UnaryTag): 
    1338     """ 
    1339     AST node for a ``<?print?>`` tag. 
    1340     """ 
    1341  
    1342     def _str(self, indent, keepws): 
    1343         yield indent*"\t" 
    1344         yield "print " 
    1345         yield from self.obj._str(indent, keepws) 
    1346         yield "\n" 
    1347  
    1348     @handleeval 
    1349     def eval(self, keepws, vars): 
    1350         yield _str((yield from self.obj.eval(keepws, vars))) 
    1351  
    1352  
    1353 @register("printx") 
    1354 class PrintX(UnaryTag): 
    1355     """ 
    1356     AST node for a ``<?printx?>`` tag. 
    1357     """ 
    1358  
    1359     def _str(self, indent, keepws): 
    1360         yield indent*"\t" 
    1361         yield "printx " 
    1362         yield from self.obj._str(indent, keepws) 
    1363         yield "\n" 
    1364  
    1365     @handleeval 
    1366     def eval(self, keepws, vars): 
    1367         yield _xmlescape((yield from self.obj.eval(keepws, vars))) 
    1368  
    1369  
    1370 @register("return") 
    1371 class Return(UnaryTag): 
    1372     """ 
    1373     AST node for a ``<?return?>`` tag. 
    1374     """ 
    1375  
    1376     def _str(self, indent, keepws): 
    1377         yield indent*"\t" 
    1378         yield "return " 
    1379         yield from self.obj._str(indent, keepws) 
    1380         yield "\n" 
    1381  
    1382     @handleeval 
    1383     def eval(self, keepws, vars): 
    1384         value = (yield from self.obj.eval(keepws, vars)) 
    1385         raise ReturnException(value) 
    1386  
    1387  
    1388 class Binary(AST): 
    1389     """ 
    1390     Base class for all AST nodes implementing binary operators. 
    1391     """ 
    1392  
    1393     fields = AST.fields.union({"obj1", "obj2"}) 
    1394  
    1395     def __init__(self, obj1=None, obj2=None): 
    1396         self.obj1 = obj1 
    1397         self.obj2 = obj2 
    1398  
    1399     def __repr__(self): 
    1400         return "<{0.__class__.__module__}.{0.__class__.__qualname__} {0.obj1!r} {0.obj2!r} at {1:#x}>".format(self, id(self)) 
    1401  
    1402     def _repr_pretty_(self, p, cycle): 
    1403         if cycle: 
    1404             p.text("<{0.__class__.__module__}.{0.__class__.__qualname__} ... at {1:#x}>".format(self, id(self))) 
    1405         else: 
    1406             with p.group(4, "<{0.__class__.__module__}.{0.__class__.__qualname__}".format(self), ">"): 
    1407                 p.breakable() 
    1408                 p.pretty(self.obj1) 
    1409                 p.breakable() 
    1410                 p.pretty(self.obj2) 
    1411                 p.breakable() 
    1412                 p.text("at {:#x}".format(id(self))) 
    1413  
    1414     def ul4ondump(self, encoder): 
    1415         encoder.dump(self.obj1) 
    1416         encoder.dump(self.obj2) 
    1417  
    1418     def ul4onload(self, decoder): 
    14191417        self.obj1 = decoder.load() 
    14201418        self.obj2 = decoder.load() 
    14211419 
    14221420    @handleeval 
    1423     def eval(self, keepws, vars): 
    1424         obj1 = (yield from self.obj1.eval(keepws, vars)) 
    1425         obj2 = (yield from self.obj2.eval(keepws, vars)) 
     1421    def eval(self, vars): 
     1422        obj1 = (yield from self.obj1.eval(vars)) 
     1423        obj2 = (yield from self.obj2.eval(vars)) 
    14261424        return self.evalfold(obj1, obj2) 
    14271425 
    14281426    @classmethod 
    1429     def make(cls, obj1, obj2): 
     1427    def make(cls, location, obj1, obj2): 
    14301428        if isinstance(obj1, Const) and isinstance(obj2, Const): 
    14311429            result = cls.evalfold(obj1.value, obj2.value) 
    14321430            if not isinstance(result, Undefined): 
    1433                 return Const(result) 
    1434         return cls(obj1, obj2) 
     1431                return Const(location, result) 
     1432        return cls(location, obj1, obj2) 
    14351433 
    14361434 
     
    17391737 
    17401738    @handleeval 
    1741     def eval(self, keepws, vars): 
    1742         obj1 = (yield from self.obj1.eval(keepws, vars)) 
     1739    def eval(self, vars): 
     1740        obj1 = (yield from self.obj1.eval(vars)) 
    17431741        if not obj1: 
    17441742            return obj1 
    1745         return (yield from self.obj2.eval(keepws, vars)) 
     1743        return (yield from self.obj2.eval(vars)) 
    17461744 
    17471745 
     
    17661764 
    17671765    @handleeval 
    1768     def eval(self, keepws, vars): 
    1769         obj1 = (yield from self.obj1.eval(keepws, vars)) 
     1766    def eval(self, vars): 
     1767        obj1 = (yield from self.obj1.eval(vars)) 
    17701768        if obj1: 
    17711769            return obj1 
    1772         return (yield from self.obj2.eval(keepws, vars)) 
     1770        return (yield from self.obj2.eval(vars)) 
    17731771 
    17741772 
     
    17921790 
    17931791 
    1794 class ChangeVar(Tag): 
     1792class ChangeVar(AST): 
    17951793    """ 
    17961794    Baseclass for all AST nodes that store or modify a variable. 
     
    18011799    """ 
    18021800 
    1803     fields = Tag.fields.union({"varname", "value"}) 
     1801    fields = AST.fields.union({"varname", "value"}) 
    18041802 
    18051803    def __init__(self, location=None, varname=None, value=None): 
     
    18501848 
    18511849    @handleeval 
    1852     def eval(self, keepws, vars): 
    1853         value = (yield from self.value.eval(keepws, vars)) 
     1850    def eval(self, vars): 
     1851        value = (yield from self.value.eval(vars)) 
    18541852        _unpackvar(vars, self.varname, value) 
    18551853 
     
    18691867 
    18701868    @handleeval 
    1871     def eval(self, keepws, vars): 
    1872         value = (yield from self.value.eval(keepws, vars)) 
     1869    def eval(self, vars): 
     1870        value = (yield from self.value.eval(vars)) 
    18731871        vars[self.varname] += value 
    18741872 
     
    18881886 
    18891887    @handleeval 
    1890     def eval(self, keepws, vars): 
    1891         value = (yield from self.value.eval(keepws, vars)) 
     1888    def eval(self, vars): 
     1889        value = (yield from self.value.eval(vars)) 
    18921890        vars[self.varname] -= value 
    18931891 
     
    19071905 
    19081906    @handleeval 
    1909     def eval(self, keepws, vars): 
    1910         value = (yield from self.value.eval(keepws, vars)) 
     1907    def eval(self, vars): 
     1908        value = (yield from self.value.eval(vars)) 
    19111909        vars[self.varname] *= value 
    19121910 
     
    19271925 
    19281926    @handleeval 
    1929     def eval(self, keepws, vars): 
    1930         value = (yield from self.value.eval(keepws, vars)) 
     1927    def eval(self, vars): 
     1928        value = (yield from self.value.eval(vars)) 
    19311929        vars[self.varname] //= value 
    19321930 
     
    19461944 
    19471945    @handleeval 
    1948     def eval(self, keepws, vars): 
    1949         value = (yield from self.value.eval(keepws, vars)) 
     1946    def eval(self, vars): 
     1947        value = (yield from self.value.eval(vars)) 
    19501948        vars[self.varname] /= value 
    19511949 
     
    19651963 
    19661964    @handleeval 
    1967     def eval(self, keepws, vars): 
    1968         value = (yield from self.value.eval(keepws, vars)) 
     1965    def eval(self, vars): 
     1966        value = (yield from self.value.eval(vars)) 
    19691967        vars[self.varname] %= value 
    19701968 
     
    19871985    fields = AST.fields.union({"obj", "args", "kwargs", "remargs", "remkwargs"}) 
    19881986 
    1989     def __init__(self, obj=None): 
     1987    def __init__(self, location=None, obj=None): 
     1988        super().__init__(location) 
    19901989        self.obj = obj 
    19911990        self.args = [] 
     
    20642063 
    20652064    @handleeval 
    2066     def eval(self, keepws, vars): 
    2067         obj = (yield from self.obj.eval(keepws, vars)) 
     2065    def eval(self, vars): 
     2066        obj = (yield from self.obj.eval(vars)) 
    20682067        args = [] 
    20692068        for arg in self.args: 
    2070             arg = (yield from arg.eval(keepws, vars)) 
     2069            arg = (yield from arg.eval(vars)) 
    20712070            args.append(arg) 
    20722071        kwargs = {} 
    20732072        for (argname, arg) in self.kwargs: 
    2074             kwargs[argname] = (yield from arg.eval(keepws, vars)) 
     2073            kwargs[argname] = (yield from arg.eval(vars)) 
    20752074        if self.remargs is not None: 
    2076             args.extend((yield from self.remargs.eval(keepws, vars))) 
     2075            args.extend((yield from self.remargs.eval(vars))) 
    20772076        if self.remkwargs is not None: 
    2078             kwargs.update((yield from self.remkwargs.eval(keepws, vars))) 
     2077            kwargs.update((yield from self.remkwargs.eval(vars))) 
    20792078        result = obj(*args, **kwargs) 
    20802079        if isinstance(result, types.GeneratorType): 
     
    20842083 
    20852084    def ul4ondump(self, encoder): 
     2085        super().ul4ondump(encoder) 
    20862086        encoder.dump(self.obj) 
    20872087        encoder.dump(self.args) 
     
    20912091 
    20922092    def ul4onload(self, decoder): 
     2093        super().ul4onload(decoder) 
    20932094        self.obj = decoder.load() 
    20942095        self.args = decoder.load() 
     
    21162117    fields = AST.fields.union({"obj", "methname", "args", "kwargs", "remargs", "remkwargs"}) 
    21172118 
    2118     def __init__(self, obj=None, methname=None): 
     2119    def __init__(self, location=None, obj=None, methname=None): 
     2120        super().__init__(location) 
    21192121        self.obj = obj 
    21202122        self.methname = methname 
     
    21992201 
    22002202    @handleeval 
    2201     def eval(self, keepws, vars): 
    2202         obj = (yield from self.obj.eval(keepws, vars)) 
     2203    def eval(self, vars): 
     2204        obj = (yield from self.obj.eval(vars)) 
    22032205        args = [] 
    22042206        for arg in self.args: 
    2205             arg = (yield from arg.eval(keepws, vars)) 
     2207            arg = (yield from arg.eval(vars)) 
    22062208            args.append(arg) 
    22072209        kwargs = {} 
    22082210        for (argname, arg) in self.kwargs: 
    2209             kwargs[argname] = (yield from arg.eval(keepws, vars)) 
     2211            kwargs[argname] = (yield from arg.eval(vars)) 
    22102212        if self.remargs is not None: 
    2211             args.extend((yield from self.remargs.eval(keepws, vars))) 
     2213            args.extend((yield from self.remargs.eval(vars))) 
    22122214        if self.remkwargs is not None: 
    2213             kwargs.update((yield from self.remkwargs.eval(keepws, vars))) 
     2215            kwargs.update((yield from self.remkwargs.eval(vars))) 
    22142216        result = self.methods[self.methname](obj, *args, **kwargs) 
    22152217        if isinstance(result, types.GeneratorType): 
     
    22192221 
    22202222    def ul4ondump(self, encoder): 
     2223        super().ul4ondump(encoder) 
    22212224        encoder.dump(self.methname) 
    22222225        encoder.dump(self.obj) 
     
    22272230 
    22282231    def ul4onload(self, decoder): 
     2232        super().ul4onload(decoder) 
    22292233        self.methname = decoder.load() 
    22302234        self.obj = decoder.load() 
     
    23342338 
    23352339    def ul4ondump(self, encoder): 
     2340        # Don't call ``super().ul4ondump()``, as we want the version to be first 
    23362341        encoder.dump(self.version) 
    23372342        encoder.dump(self.source) 
     
    23992404        template code. 
    24002405        """ 
    2401         yield from super().eval(self.keepws, vars) # Bypass ``self.eval()`` which simply stores the object as a local variable 
     2406        yield from super().eval(vars) # Bypass ``self.eval()`` which simply stores the object as a local variable 
    24022407 
    24032408    def renders(self, **vars): 
     
    24142419        """ 
    24152420        try: 
    2416             for output in super().eval(self.keepws, vars): # Bypass ``self.eval()`` which simply stores the object as a local variable 
     2421            for output in super().eval(vars): # Bypass ``self.eval()`` which simply stores the object as a local variable 
    24172422                pass # Ignore all output 
    24182423        except ReturnException as ex: 
     
    24442449        for match in re.finditer(pattern, source): 
    24452450            if match.start() != pos: 
    2446                 yield Location(source, None, pos, match.start(), pos, match.start()) 
     2451                yield Location(self, source, None, pos, match.start(), pos, match.start()) 
    24472452            type = source[match.start(1):match.end(1)] 
    24482453            if type != "note": 
    2449                 yield Location(source, type, match.start(), match.end(), match.start(3), match.end(3)) 
     2454                yield Location(self, source, type, match.start(), match.end(), match.start(3), match.end(3)) 
    24502455            pos = match.end() 
    24512456        end = len(source) 
    24522457        if pos != end: 
    2453             yield Location(source, None, pos, end, pos, end) 
     2458            yield Location(self, source, None, pos, end, pos, end) 
    24542459 
    24552460    def _parser(self, location, error): 
     
    25732578 
    25742579    @handleeval 
    2575     def eval(self, keepws, vars): 
     2580    def eval(self, vars): 
    25762581        yield from () 
    25772582        vars[self.name] = TemplateClosure(self, vars)