root/livinglogic.python.xist/src/ll/ul4c.py @ 3455:32328d691b0a

Revision 3455:32328d691b0a, 65.9 KB (checked in by Walter Doerwald <walter@…>, 11 years ago)

Add a function vars() that returns a dictionary with all variables.

Line 
1# -*- coding: utf-8 -*-
2
3## Copyright 2008 by LivingLogic AG, Bayreuth/Germany
4## Copyright 2008 by Walter Dörwald
5##
6## All Rights Reserved
7##
8## See ll/__init__.py for the license
9
10
11from __future__ import division
12
13"""
14:mod:`ll.ul4c` provides templating for XML/HTML as well as any other text-based
15format. A template defines placeholders for data output and basic logic (like
16loops and conditional blocks), that define how the final rendered output will
17look.
18
19:mod:`ll.ul4c` compiles a template to a bytecode format, which makes it possible
20to implement renderers for these templates in multiple programming languages.
21"""
22
23__docformat__ = "reStructuredText"
24
25
26import re, datetime, marshal, StringIO, locale
27
28from ll import spark
29
30
31# Regular expression used for splitting dates
32datesplitter = re.compile("[-T:.]")
33
34
35###
36### Location information
37###
38
39class Location(object):
40    """
41    A :class:`Location` object contains information about the location of a
42    template tag.
43    """
44    __slots__ = ("source", "type", "starttag", "endtag", "startcode", "endcode")
45
46    def __init__(self, source, type, starttag, endtag, startcode, endcode):
47        """
48        Create a new :class:`Location` object. The arguments have the following
49        meaning:
50
51        :var:`source`
52            The complete source string
53
54        :var:`type`
55            The tag type (i.e. ``"for"``, ``"if"``, etc.)
56
57        :var:`starttag`
58            The start position of the start delimiter.
59
60        :var:`endtag`
61            The end position of the end delimiter.
62
63        :var:`startcode`
64            The start position of the tag code.
65
66        :var:`endcode`
67            The end position of the tag code.
68        """
69        self.source = source
70        self.type = type
71        self.starttag = starttag
72        self.endtag = endtag
73        self.startcode = startcode
74        self.endcode = endcode
75
76    @property
77    def code(self):
78        return self.source[self.startcode:self.endcode]
79
80    @property
81    def tag(self):
82        return self.source[self.starttag:self.endtag]
83
84    def __str__(self):
85        lastlinefeed = self.source.rfind("\n", 0, self.starttag)
86        if lastlinefeed >= 0:
87            line = self.source.count("\n", 0, self.starttag)+1
88            col = self.starttag - lastlinefeed
89        else:
90            line = 1
91            col = self.starttag + 1
92        return "%r at %d (line %d, col %d)" % (self.tag, self.starttag+1, line, col)
93
94
95###
96### Exceptions
97###
98
99class Error(Exception):
100    """
101    base class of all exceptions.
102    """
103    def __init__(self, exception=None):
104        self.location = None
105        self.exception = exception
106
107    def __str__(self):
108        return self.format(str(self.exception) if self.exception is not None else "error")
109
110    def decorate(self, location):
111        self.location = location
112        return self
113
114    def format(self, message):
115        if self.exception is not None:
116            name = self.exception.__class__.__name__
117            module = self.exception.__class__.__module__
118            if module != "exceptions":
119                name = "%s.%s" % (module, name)
120            if self.location is not None:
121                return "%s in %s: %s" % (name, self.location, message)
122            else:
123                return "%s: %s" % (name, message)
124        else:
125            if self.location is not None:
126                return "in %s: %s" % (self.location, message)
127            else:
128                return message
129
130
131class LexicalError(Error):
132    def __init__(self, start, end, input):
133        Error.__init__(self)
134        self.start = start
135        self.end = end
136        self.input = input
137
138    def __str__(self):
139        return self.format("Unmatched input %r" % self.input)
140
141
142class SyntaxError(Error):
143    def __init__(self, token):
144        Error.__init__(self)
145        self.token = token
146
147    def __str__(self):
148        return self.format("Lexical error near %r" % str(self.token))
149
150
151class UnterminatedStringError(Error):
152    """
153    Exception that is raised by the parser when a string constant is not
154    terminated.
155    """
156    def __str__(self):
157        return self.format("Unterminated string")
158
159
160class BlockError(Error):
161    """
162    Exception that is raised by the compiler when an illegal block structure is
163    detected (e.g. an ``endif`` without a previous ``if``).
164    """
165
166    def __init__(self, message):
167        Error.__init__(self)
168        self.message = message
169
170    def __str__(self):
171        return self.format(self.message)
172
173
174class UnknownFunctionError(Error):
175    """
176    Exception that is raised by the renderer if the function to be executed by
177    the ``callfunc0``, ``callfunc1``, ``callfunc2`` or ``callfunc3`` opcodes is
178    unknown.
179    """
180
181    def __init__(self, funcname):
182        Error.__init__(self)
183        self.funcname = funcname
184
185    def __str__(self):
186        return self.format("function %r unknown" % self.funcname)
187
188
189class UnknownMethodError(Error):
190    """
191    Exception that is raised by the renderer if the method to be executed by the
192    ``callmeth0``, ``callmeth1``, ``callmeth2``  or ``callmeth3`` opcodes is
193    unknown.
194    """
195
196    def __init__(self, methname):
197        Error.__init__(self)
198        self.methname = methname
199
200    def __str__(self):
201        return self.format("method %r unknown" % self.methname)
202
203
204class UnknownOpcodeError(Error):
205    """
206    Exception that is raised when an unknown opcode is encountered by the renderer.
207    """
208
209    def __init__(self, opcode):
210        Error.__init__(self)
211        self.opcode = opcode
212
213    def __str__(self):
214        return self.format("opcode %r unknown" % self.opcode)
215
216
217class OutOfRegistersError(Error):
218    """
219    Exception that is raised by the compiler when there are no more free
220    registers. This might happen with very complex expressions in tag code.
221    """
222
223    def __str__(self):
224        return self.format("out of registers")
225
226
227###
228### opcode class
229###
230
231class Opcode(object):
232    """
233    An :class:`Opcode` stores an opcode. The type of opcode is stored in the
234    :attr:`code` attribute. Furthermore each opcode has up to five register
235    specifications (for the source or targets of the operation) in the attributes
236    :attr:`r1`, :attr:`r2`, :attr:`r3`, :attr:`r4` and :attr:`r5`. If the opcode
237    requires an additional argument (like a variable name or the value of a
238    constant) this will be stored in the :attr:`arg` attribute.
239
240    The following opcodes are available:
241
242    :const:`None`:
243        Print text. The text is available from ``location.code``.
244
245    ``"print"``:
246        Print the content of register :attr:`r1`. (If the object in the register
247        is not a string, it will be converted to a string first.)
248
249    ``"loadnone"``:
250        Load the constant :const:`None`.
251
252    ``"loadfalse"``:
253        Load the constant :const:`False`.
254
255    ``"loadtrue"``:
256        Load the constant :const:`True`.
257
258    ``"loadstr"``:
259        Load the string :attr:`arg` into the register :attr:`r1`.
260
261    ``"loadint"``:
262        Load the integer value :attr:`arg` into the register :attr:`r1`.
263
264    ``"loadfloat"``:
265        Load the float value :attr:`arg` into the register :attr:`r1`.
266
267    ``"loaddate"``:
268        Load the date value :attr:`arg` into the register :attr:`r1`. :attr:`arg`
269        must be in ISO format (e.g. ``2008-07-02T11:05:55.460464``).
270
271    ``"buildlist"``:
272        Load an empty list into the register :attr:`r1`.
273
274    ``"builddict"``:
275        Load an empty dictionary into the register :attr:`r1`.
276
277    ``"addlist"``
278        Append the object in register :attr:`r2` to the list in register :attr:`r1`.
279   
280    ``"adddict"``
281        Add a new entry to the dictionary in register :attr:`r1`. The object in
282        :attr:`r2` is the key and the object in register :attr:`r3` is the value.
283   
284    ``"loadvar"``:
285        Load the variable named :attr:`arg` into the register :attr:`r1`.
286
287    ``"storevar"``:
288        Store the content of register :attr:`r1` in the variable named :attr:`arg`.
289
290    ``"addvar"``:
291        Add the content of register :attr:`r1` to the variable named :attr:`arg`.
292
293    ``"for"``:
294        Start a loop over the object in the register :attr:`r2` and store the
295        object from each loop iteration in the register :attr:`r1`.
296
297    ``"endfor"``:
298        Ends the innermost running ``for`` loop.
299
300    ``"if"``:
301        Starts a conditional block. If the objects in the register :attr:`r1` is
302        true the block will be executed. The "block" consists of all opcodes after
303        the ``if`` upto the matching ``else`` or ``endif`` opcode.
304
305    ``"else"``:
306        Start the else branch of the previous ``if``.
307
308    ``"endif"``:
309        End a conditional block.
310
311    ``"getattr"``:
312        Get the attribute named :attr:`arg` from the object in register :attr:`r2`
313        and store it in register :attr:`r1`.
314
315    ``"getitem"``:
316        Get an item from the object in register :attr:`r2`. If this object is a
317        list the object in register :attr:`r3` will be used as the index. If it is
318        a dictionary :attr:`r3` will be used as the key. The result will be stored
319        in register :attr:`r1`.
320
321    ``"getslice12"``:
322        Get an slice from the object in register :attr:`r2`. The object in
323        register :attr:`r3` (which must be an ``int`` or :const:`None`) specifies
324        the start index, If this object in register :attr:`r4` specifies the end
325        index. The result will be stored in register :attr:`r1`.
326
327    ``"getslice1"``:
328        Similar to ``getslice12`` except that the end index is always the length
329        of the object.
330
331    ``"getslice2"``:
332        Similar to ``getslice12`` except that the start index is always 0 and the
333        end index is in register :attr:`r3`.
334
335    ``"getslice"``:
336        Similar to ``getslice12`` except that the start index is always 0 and the
337        end index alywas the length of the object.
338
339    ``"not"``:
340        Invert the truth value of the object in register :attr:`r2` and stores the
341        resulting bool in the register :attr:`r1`.
342
343    ``"equals"``:
344        Compare the objects in register :attr:`r2` and :attr:`r3` and store
345        ``True`` in the register :attr:`r1` if they are equal, ``False`` otherwise.
346
347    ``"notequals"``:
348        Compare the objects in register :attr:`r2` and :attr:`r3` and store
349        ``False`` in the register :attr:`r1` if they are equal, ``True`` otherwise.
350
351    ``"contains"``:
352        Test whether the object in register :attr:`r3` contains the object in
353        register :attr:`r2` (either as a key if it's a dictionary or as an item
354        if it's a list or as a substring if it's a string) and store ``True`` into
355        the register :attr:`r1` if it does, ``False`` otherwise.
356
357    ``"notcontains"``:
358        Test whether the object in register :attr:`r3` contains the object in
359        register :attr:`r2` (either as a key if it's a dictionary or as an item
360        if it's a list or as a substring if it's a string) and store ``False`` into
361        the register :attr:`r1` if it does, ``True`` otherwise.
362
363    ``"or"``:
364        Check the truth value of two object in registers :attr:`r2` and :attr:`r3`
365        and store :attr:`r2` in the register :attr:`r1` if it is true, :attr:`r3`
366        otherwise).
367
368    ``"and"``:
369        Check the truth value of two object in registers :attr:`r2` and :attr:`r3`
370        and store :attr:`r3` in the register :attr:`r1` if :attr:`r2` is true,
371        :attr:`r3` otherwise).
372
373    ``"mod"``:
374        Does a modulo operation: Calculates :attr:`r2` modulo :attr:`r3` and stores
375        the result in the register :attr:`r1`.
376
377    ``"callfunc0"``:
378        Call the function named :attr:`arg` without any arguments and store the
379        return value in register :attr:`r1`.
380
381    ``"callfunc1"``:
382        Call the function named :attr:`arg` with the content of register :attr:`r2`
383        as an argument and store the return value in register :attr:`r1`.
384
385    ``"callfunc2"``:
386        Call the function named :attr:`arg` with the contents of register
387        :attr:`r2` and :attr:`r3` as the two arguments and store the return value
388        in register :attr:`r1`.
389
390    ``"callfunc3"``:
391        Call the function named :attr:`arg` with the contents of register
392        :attr:`r2`, :attr:`r3` and :attr:`r4` as the three arguments and store
393        the return value in register :attr:`r1`.
394
395    ``"callmeth0"``:
396        Call the method named :attr:`arg` on the object in register :attr:`r2`
397        and store the return value in register :attr:`r1`.
398
399    ``"callmeth1"``:
400        Call the method named :attr:`arg` on the object in register :attr:`r2`
401        using the object in register :attr:`r3` as to only argument and store the
402        return value in register :attr:`r1`.
403
404    ``"callmeth2"``:
405        Call the method named :attr:`arg` on the object in register :attr:`r2`
406        using the objects in register :attr:`r3` and :attr:`r4` as arguments and
407        store the return value in register :attr:`r1`.
408
409    ``"callmeth3"``:
410        Call the method named :attr:`arg` on the object in register :attr:`r2`
411        using the objects in register :attr:`r3`, :attr:`r4` and :attr:`r5` as
412        arguments and store the return value in register :attr:`r1`.
413
414    ``"render"``:
415        Render the template whose name is in the attribute :attr:`arg`. The
416        content of register :attr:`r1` will be passed as the data object to the
417        template.
418    """
419    __slots__ = ("code", "r1", "r2", "r3", "r4", "r5", "arg", "location", "jump")
420
421    def __init__(self, code, r1=None, r2=None, r3=None, r4=None, r5=None, arg=None, location=None):
422        self.code = code
423        self.r1 = r1
424        self.r2 = r2
425        self.r3 = r3
426        self.r4 = r4
427        self.r5 = r5
428        self.arg = arg
429        self.location = location
430        self.jump = None
431
432    def __repr__(self):
433        v = ["<", self.__class__.__name__, " code=%r" % self.code]
434        for attrname in ("r1", "r2", "r3", "r4", "r5", "arg"):
435            attr = getattr(self, attrname)
436            if attr is not None:
437                v.append(" %s=%r" % (attrname, attr))
438        if self.code is None:
439            v.append(" text=%r" % self.location.code)
440        v.append(" at 0x%x>" % id(self))
441        return "".join(v)
442
443    def __str__(self):
444        if self.code is None:
445            return "print %r" % self.location.code
446        elif self.code == "print":
447            return "print r%r" % self.r1
448        elif self.code == "loadnone":
449            return "r%r = None" % self.r1
450        elif self.code == "loadfalse":
451            return "r%r = False" % self.r1
452        elif self.code == "loadtrue":
453            return "r%r = True" % self.r1
454        elif self.code == "loadstr":
455            return "r%r = %r" % (self.r1, self.arg)
456        elif self.code == "loadint":
457            return "r%r = %s" % (self.r1, self.arg)
458        elif self.code == "loadfloat":
459            return "r%r = %s" % (self.r1, self.arg)
460        elif self.code == "loaddate":
461            return "r%r = %s" % (self.r1, self.arg)
462        elif self.code == "buildlist":
463            return "r%r = []" % (self.r1)
464        elif self.code == "builddict":
465            return "r%r = {}" % (self.r1)
466        elif self.code == "addlist":
467            return "r%r.append(r%r)" % (self.r1, self.r2)
468        elif self.code == "adddict":
469            return "r%r[r%r] = r%r" % (self.r1, self.r2, self.r3)
470        elif self.code == "loadvar":
471            return "r%r = vars[%r]" % (self.r1, self.arg)
472        elif self.code == "storevar":
473            return "vars[%r] = r%r" % (self.arg, self.r1)
474        elif self.code == "addvar":
475            return "vars[%r] += r%r" % (self.arg, self.r1)
476        elif self.code == "subvar":
477            return "vars[%r] -= r%r" % (self.arg, self.r1)
478        elif self.code == "mulvar":
479            return "vars[%r] *= r%r" % (self.arg, self.r1)
480        elif self.code == "truedivvar":
481            return "vars[%r] /= r%r" % (self.arg, self.r1)
482        elif self.code == "floordivvar":
483            return "vars[%r] //= r%r" % (self.arg, self.r1)
484        elif self.code == "modvar":
485            return "vars[%r] %%= r%r" % (self.arg, self.r1)
486        elif self.code == "delvar":
487            return "del vars[%r]" % self.arg
488        elif self.code == "for":
489            return "for r%r in r%r" % (self.r1, self.r2)
490        elif self.code == "endfor":
491            return "endfor"
492        elif self.code == "if":
493            return "if r%r" % self.r1
494        elif self.code == "else":
495            return "else"
496        elif self.code == "endif":
497            return "endif"
498        elif self.code == "getattr":
499            return "r%r = getattr(r%r, %r)" % (self.r1, self.r2, self.arg)
500        elif self.code == "getitem":
501            return "r%r = r%r[r%r]" % (self.r1, self.r2, self.r3)
502        elif self.code == "getslice":
503            return "r%r = r%r[:]" % (self.r1, self.r2)
504        elif self.code == "getslice1":
505            return "r%r = r%r[r%r:]" % (self.r1, self.r2, self.r3)
506        elif self.code == "getslice2":
507            return "r%r = r%r[:r%r]" % (self.r1, self.r2, self.r4)
508        elif self.code == "getslice12":
509            return "r%r = r%r[r%r:r%r]" % (self.r1, self.r2, self.r3, self.r4)
510        elif self.code == "not":
511            return "r%r = not r%r" % (self.r1, self.r2)
512        elif self.code == "equals":
513            return "r%r = r%r == r%r" % (self.r1, self.r2, self.r3)
514        elif self.code == "notequals":
515            return "r%r = r%r != r%r" % (self.r1, self.r2, self.r3)
516        elif self.code == "contains":
517            return "r%r = r%r in r%r" % (self.r1, self.r2, self.r3)
518        elif self.code == "notcontains":
519            return "r%r = r%r not in r%r" % (self.r1, self.r2, self.r3)
520        elif self.code == "add":
521            return "r%r = r%r + r%r" % (self.r1, self.r2, self.r3)
522        elif self.code == "sub":
523            return "r%r = r%r - r%r" % (self.r1, self.r2, self.r3)
524        elif self.code == "mul":
525            return "r%r = r%r * r%r" % (self.r1, self.r2, self.r3)
526        elif self.code == "floordiv":
527            return "r%r = r%r // r%r" % (self.r1, self.r2, self.r3)
528        elif self.code == "trueiv":
529            return "r%r = r%r / r%r" % (self.r1, self.r2, self.r3)
530        elif self.code == "and":
531            return "r%r = r%r and r%r" % (self.r1, self.r2, self.r3)
532        elif self.code == "or":
533            return "r%r = r%r or r%r" % (self.r1, self.r2, self.r3)
534        elif self.code == "mod":
535            return "r%r = r%r %% r%r" % (self.r1, self.r2, self.r3)
536        elif self.code == "callfunc0":
537            return "r%r = %s()" % (self.r1, self.arg)
538        elif self.code == "callfunc1":
539            return "r%r = %s(r%r)" % (self.r1, self.arg, self.r2)
540        elif self.code == "callfunc2":
541            return "r%r = %s(r%r, r%r)" % (self.r1, self.arg, self.r2, self.r3)
542        elif self.code == "callfunc3":
543            return "r%r = %s(r%r, r%r, r%r)" % (self.r1, self.arg, self.r2, self.r3, self.r4)
544        elif self.code == "callmeth0":
545            return "r%r = r%r.%s()" % (self.r1, self.r2, self.arg)
546        elif self.code == "callmeth1":
547            return "r%r = r%r.%s(r%r)" % (self.r1, self.r2, self.arg, self.r3)
548        elif self.code == "callmeth2":
549            return "r%r = r%r.%s(r%r, r%r)" % (self.r1, self.r2, self.arg, self.r3, self.r4)
550        elif self.code == "callmeth3":
551            return "r%r = r%r.%s(r%r, r%r, r%r)" % (self.r1, self.r2, self.arg, self.r3, self.r4, self.r5)
552        elif self.code == "render":
553            return "render %s(r%r)" % (self.arg, self.r1)
554        else:
555            raise UnknownOpcodeError(self.code)
556
557
558class Template(object):
559    def __init__(self):
560        self.startdelim = None
561        self.enddelim = None
562        self.source = None
563        self.opcodes = None
564        # The following is used for converting the opcodes back to executable Python code
565        self._pythonfunction = None
566
567    @classmethod
568    def loads(cls, data):
569        def _readint(term):
570            i = 0
571            while True:
572                c = stream.read(1)
573                if c.isdigit():
574                    i = 10*i+int(c)
575                elif c == term:
576                    return i
577                else:
578                    raise ValueError("invalid terminator, expected %r, got %r" % (term, c))
579
580        def _readstr(term1, term0):
581            i = 0
582            while True:
583                c = stream.read(1)
584                if c.isdigit():
585                    i = 10*i+int(c)
586                elif c == term1:
587                    break
588                elif c == term0:
589                    return None
590                else:
591                    raise ValueError("invalid terminator, expected %r or %r, got %r" % (term1, term0, c))
592            s = stream.read(i)
593            if len(s) != i:
594                raise ValueError("short read")
595            return s
596
597        def _readspec():
598            c = stream.read(1)
599            if c == "-":
600                return None
601            elif c.isdigit():
602                return int(c)
603            else:
604                raise ValueError("invalid register spec %r" % c)
605
606        def _readcr():
607            c = stream.read(1)
608            if c != "\n":
609                raise ValueError("invalid linefeed %r" % c)
610
611        self = cls()
612        stream = StringIO.StringIO(data)
613        header = stream.readline()
614        header = header.rstrip()
615        if header != "ul4":
616            raise ValueError("invalid header, expected 'ul4', got %r" % header)
617        version = stream.readline()
618        version = version.rstrip()
619        if version != "1":
620            raise ValueError("invalid version, expected 1 got, %r" % version)
621        self.startdelim = _readstr(u"<", u"[")
622        _readcr()
623        self.enddelim = _readstr(u">", u"]")
624        _readcr()
625        self.source = _readstr("'", '"')
626        self.opcodes = []
627        _readcr()
628        count = _readint(u"#")
629        _readcr()
630        location = None
631        while count:
632            r1 = _readspec()
633            r2 = _readspec()
634            r3 = _readspec()
635            r4 = _readspec()
636            r5 = _readspec()
637            code = _readstr(":", ".")
638            arg = _readstr(";", ",")
639            locspec = stream.read(1)
640            if locspec == u"^":
641                if location is None:
642                    raise ValueError("no previous location")
643            elif locspec == u"*":
644                location = Location(self.source, _readstr("=", "-"), _readint("("), _readint(")"), _readint("{"), _readint("}"))
645            else:
646                raise ValueError("invalid location spec %r" % locspec)
647            _readcr()
648            count -= 1
649            self.opcodes.append(Opcode(code, r1, r2, r3, r4, r5, arg, location))
650        return self
651
652    @classmethod
653    def load(cls, stream):
654        return cls.loads(stream.read())
655
656    def iterdump(self):
657        def _writeint(term, number):
658            yield unicode(number)
659            yield term
660
661        def _writestr(term1, term0, string):
662            if string:
663                yield str(len(string))
664            if string is None:
665                yield term0
666            else:
667                yield term1
668                yield string
669
670        yield "ul4\n1\n"
671        for p in _writestr("<", "[", self.startdelim): yield p
672        yield "\n"
673        for p in _writestr(">", "]", self.enddelim): yield p
674        yield "\n"
675        for p in _writestr("'", '"', self.source): yield p
676        yield "\n"
677        for p in _writeint("#", len(self.opcodes)): yield p
678        yield "\n"
679        lastlocation = None
680        for opcode in self.opcodes:
681            yield str(opcode.r1) if opcode.r1 is not None else u"-"
682            yield str(opcode.r2) if opcode.r2 is not None else u"-"
683            yield str(opcode.r3) if opcode.r3 is not None else u"-"
684            yield str(opcode.r4) if opcode.r4 is not None else u"-"
685            yield str(opcode.r5) if opcode.r5 is not None else u"-"
686            for p in _writestr(":", ".", opcode.code): yield p
687            for p in _writestr(";", ",", opcode.arg): yield p
688            if opcode.location is not lastlocation:
689                lastlocation = opcode.location
690                yield u"*"
691                for p in _writestr("=", "-", lastlocation.type): yield p
692                for p in _writeint("(", lastlocation.starttag): yield p
693                for p in _writeint(")", lastlocation.endtag): yield p
694                for p in _writeint("{", lastlocation.startcode): yield p
695                for p in _writeint("}", lastlocation.endcode): yield p
696            else:
697                yield "^"
698            yield "\n"
699
700    def dump(self, stream):
701        for part in self.iterdump():
702            stream.write(part)
703
704    def dumps(self):
705        return ''.join(self.iterdump())
706
707    def pythonsource(self, function=None):
708        indent = 0
709        output = []
710
711        def _code(code):
712            output.append("%s%s" % ("\t"*indent, code))
713
714        if function is not None:
715            _code("def %s(templates={}, **variables):" % function)
716            indent += 1
717        _code("import sys, marshal, datetime")
718        _code("from ll.misc import xmlescape")
719        _code("from ll import ul4c")
720        _code("source = %r" % self.source)
721        _code('variables = dict((key.decode("utf-8"), value) for (key, value) in variables.iteritems())') # FIXME: This can be dropped in Python 3.0 where strings are unicode
722        locations = tuple((oc.location.type, oc.location.starttag, oc.location.endtag, oc.location.startcode, oc.location.endcode) for oc in self.opcodes)
723        locations = marshal.dumps(locations)
724        _code("locations = marshal.loads(%r)" % locations)
725        _code("".join("reg%d = " % i for i in xrange(10)) + "None")
726
727        _code("try:")
728        indent += 1
729        _code("startline = sys._getframe().f_lineno+1") # The source line of the first opcode
730        try:
731            lastopcode = None
732            for opcode in self.opcodes:
733                # The following code ensures that each opcode outputs exactly one source code line
734                # This makes it possible in case of an error to find out which opcode produced the error
735                if opcode.code is None:
736                    _code("yield %r" % opcode.location.code)
737                elif opcode.code == "loadstr":
738                    _code("reg%d = %r" % (opcode.r1, opcode.arg))
739                elif opcode.code == "loadint":
740                    _code("reg%d = %s" % (opcode.r1, opcode.arg))
741                elif opcode.code == "loadfloat":
742                    _code("reg%d = %s" % (opcode.r1, opcode.arg))
743                elif opcode.code == "loadnone":
744                    _code("reg%d = None" % opcode.r1)
745                elif opcode.code == "loadfalse":
746                    _code("reg%d = False" % opcode.r1)
747                elif opcode.code == "loadtrue":
748                    _code("reg%d = True" % opcode.r1)
749                elif opcode.code == "loaddate":
750                    _code("reg%d = datetime.datetime(%s)" % (opcode.r1, ", ".join(str(int(p)) for p in datesplitter.split(opcode.arg))))
751                elif opcode.code == "buildlist":
752                    _code("reg%d = []" % opcode.r1)
753                elif opcode.code == "builddict":
754                    _code("reg%d = {}" % opcode.r1)
755                elif opcode.code == "addlist":
756                    _code("reg%d.append(reg%d)" % (opcode.r1, opcode.r2))
757                elif opcode.code == "adddict":
758                    _code("reg%d[reg%d] = reg%d" % (opcode.r1, opcode.r2, opcode.r3))
759                elif opcode.code == "loadvar":
760                    _code("reg%d = variables[%r]" % (opcode.r1, opcode.arg))
761                elif opcode.code == "storevar":
762                    _code("variables[%r] = reg%d" % (opcode.arg, opcode.r1))
763                elif opcode.code == "addvar":
764                    _code("variables[%r] += reg%d" % (opcode.arg, opcode.r1))
765                elif opcode.code == "subvar":
766                    _code("variables[%r] -= reg%d" % (opcode.arg, opcode.r1))
767                elif opcode.code == "mulvar":
768                    _code("variables[%r] *= reg%d" % (opcode.arg, opcode.r1))
769                elif opcode.code == "truedivvar":
770                    _code("variables[%r] /= reg%d" % (opcode.arg, opcode.r1))
771                elif opcode.code == "floordivvar":
772                    _code("variables[%r] //= reg%d" % (opcode.arg, opcode.r1))
773                elif opcode.code == "modvar":
774                    _code("variables[%r] %%= reg%d" % (opcode.arg, opcode.r1))
775                elif opcode.code == "delvar":
776                    _code("del variables[%r]" % opcode.arg)
777                elif opcode.code == "getattr":
778                    _code("reg%d = reg%d[%r]" % (opcode.r1, opcode.r2, opcode.arg))
779                elif opcode.code == "getitem":
780                    _code("reg%d = reg%d[reg%d]" % (opcode.r1, opcode.r2, opcode.r3))
781                elif opcode.code == "getslice12":
782                    _code("reg%d = reg%d[reg%d:reg%d]" % (opcode.r1, opcode.r2, opcode.r3, opcode.r4))
783                elif opcode.code == "getslice1":
784                    _code("reg%d = reg%d[reg%d:]" % (opcode.r1, opcode.r2, opcode.r3))
785                elif opcode.code == "getslice2":
786                    _code("reg%d = reg%d[:reg%d]" % (opcode.r1, opcode.r2, opcode.r3))
787                elif opcode.code == "getslice":
788                    _code("reg%d = reg%d[:]" % (opcode.r1, opcode.r2))
789                elif opcode.code == "print":
790                    _code("if reg%d is not None: yield unicode(reg%d)" % (opcode.r1, opcode.r1))
791                elif opcode.code == "for":
792                    _code("for reg%d in reg%d:" % (opcode.r1, opcode.r2))
793                    indent += 1
794                elif opcode.code == "endfor":
795                    # we don't have to check for empty loops here, as a ``<?for?>`` tag always generates at least one ``storevar`` opcode inside the loop
796                    indent -= 1
797                    _code("# end for")
798                elif opcode.code == "not":
799                    _code("reg%d = not reg%d" % (opcode.r1, opcode.r2))
800                elif opcode.code == "neg":
801                    _code("reg%d = -reg%d" % (opcode.r1, opcode.r2))
802                elif opcode.code == "contains":
803                    _code("reg%d = reg%d in reg%d" % (opcode.r1, opcode.r2, opcode.r3))
804                elif opcode.code == "notcontains":
805                    _code("reg%d = reg%d not in reg%d" % (opcode.r1, opcode.r2, opcode.r3))
806                elif opcode.code == "equals":
807                    _code("reg%d = reg%d == reg%d" % (opcode.r1, opcode.r2, opcode.r3))
808                elif opcode.code == "notequals":
809                    _code("reg%d = reg%d != reg%d" % (opcode.r1, opcode.r2, opcode.r3))
810                elif opcode.code == "add":
811                    _code("reg%d = reg%d + reg%d" % (opcode.r1, opcode.r2, opcode.r3))
812                elif opcode.code == "sub":
813                    _code("reg%d = reg%d - reg%d" % (opcode.r1, opcode.r2, opcode.r3))
814                elif opcode.code == "mul":
815                    _code("reg%d = reg%d * reg%d" % (opcode.r1, opcode.r2, opcode.r3))
816                elif opcode.code == "floordiv":
817                    _code("reg%d = reg%d // reg%d" % (opcode.r1, opcode.r2, opcode.r3))
818                elif opcode.code == "truediv":
819                    _code("reg%d = reg%d / reg%d" % (opcode.r1, opcode.r2, opcode.r3))
820                elif opcode.code == "and":
821                    _code("reg%d = reg%d and reg%d" % (opcode.r1, opcode.r2, opcode.r3))
822                elif opcode.code == "or":
823                    _code("reg%d = reg%d or reg%d" % (opcode.r1, opcode.r2, opcode.r3))
824                elif opcode.code == "mod":
825                    _code("reg%d = reg%d %% reg%d" % (opcode.r1, opcode.r2, opcode.r3))
826                elif opcode.code == "callfunc0":
827                    if opcode.arg == "now":
828                        _code("reg%d = datetime.datetime.now()" % (opcode.r1))
829                    elif opcode.arg == "vars":
830                        _code("reg%d = variables" % opcode.r1)
831                    else:
832                        raise UnknownFunctionError(opcode.arg)
833                elif opcode.code == "callfunc1":
834                    if opcode.arg == "xmlescape":
835                        _code("reg%d = xmlescape(unicode(reg%d)) if reg%d is not None else u''" % (opcode.r1, opcode.r2, opcode.r2))
836                    elif opcode.arg == "str":
837                        _code("reg%d = unicode(reg%d) if reg%d is not None else u''" % (opcode.r1, opcode.r2, opcode.r2))
838                    elif opcode.arg == "int":
839                        _code("reg%d = int(reg%d)" % (opcode.r1, opcode.r2))
840                    elif opcode.arg == "bool":
841                        _code("reg%d = bool(reg%d)" % (opcode.r1, opcode.r2))
842                    elif opcode.arg == "len":
843                        _code("reg%d = len(reg%d)" % (opcode.r1, opcode.r2))
844                    elif opcode.arg == "enumerate":
845                        _code("reg%d = enumerate(reg%d)" % (opcode.r1, opcode.r2))
846                    elif opcode.arg == "isnone":
847                        _code("reg%d = reg%d is None" % (opcode.r1, opcode.r2))
848                    elif opcode.arg == "isstr":
849                        _code("reg%d = isinstance(reg%d, basestring)" % (opcode.r1, opcode.r2))
850                    elif opcode.arg == "isint":
851                        _code("reg%d = isinstance(reg%d, (int, long)) and not isinstance(reg%d, bool)" % (opcode.r1, opcode.r2, opcode.r2))
852                    elif opcode.arg == "isfloat":
853                        _code("reg%d = isinstance(reg%d, float)" % (opcode.r1, opcode.r2))
854                    elif opcode.arg == "isbool":
855                        _code("reg%d = isinstance(reg%d, bool)" % (opcode.r1, opcode.r2))
856                    elif opcode.arg == "isdate":
857                        _code("reg%d = isinstance(reg%d, datetime.datetime)" % (opcode.r1, opcode.r2))
858                    elif opcode.arg == "islist":
859                        _code("reg%d = isinstance(reg%d, (list, tuple))" % (opcode.r1, opcode.r2))
860                    elif opcode.arg == "isdict":
861                        _code("reg%d = isinstance(reg%d, dict)" % (opcode.r1, opcode.r2))
862                    elif opcode.arg == "repr":
863                        _code("reg%d = ul4c._repr(reg%d)" % (opcode.r1, opcode.r2))
864                    elif opcode.arg == "chr":
865                        _code("reg%d = unichr(reg%d)" % (opcode.r1, opcode.r2))
866                    elif opcode.arg == "ord":
867                        _code("reg%d = ord(reg%d)" % (opcode.r1, opcode.r2))
868                    elif opcode.arg == "hex":
869                        _code("reg%d = hex(reg%d)" % (opcode.r1, opcode.r2))
870                    elif opcode.arg == "oct":
871                        _code('reg%d = ul4c._oct(reg%d)' % (opcode.r1, opcode.r2))
872                    elif opcode.arg == "bin":
873                        _code('reg%d = ul4c._bin(reg%d)' % (opcode.r1, opcode.r2))
874                    elif opcode.arg == "sorted":
875                        _code("reg%d = sorted(reg%d)" % (opcode.r1, opcode.r2))
876                    elif opcode.arg == "range":
877                        _code("reg%d = xrange(reg%d)" % (opcode.r1, opcode.r2))
878                    else:
879                        raise UnknownFunctionError(opcode.arg)
880                elif opcode.code == "callfunc2":
881                    if opcode.arg == "range":
882                        _code("reg%d = xrange(reg%d, reg%d)" % (opcode.r1, opcode.r2, opcode.r3))
883                    else:
884                        raise UnknownFunctionError(opcode.arg)
885                elif opcode.code == "callfunc3":
886                    if opcode.arg == "range":
887                        _code("reg%d = xrange(reg%d, reg%d, reg%d)" % (opcode.r1, opcode.r2, opcode.r3, opcode.r4))
888                    else:
889                        raise UnknownFunctionError(opcode.arg)
890                elif opcode.code == "callmeth0":
891                    if opcode.arg in ("split", "rsplit", "strip", "lstrip", "rstrip", "upper", "lower", "isoformat"):
892                        _code("reg%d = reg%d.%s()" % (opcode.r1, opcode.r2, opcode.arg))
893                    elif opcode.arg == "items":
894                        _code("reg%d = reg%d.iteritems()" % (opcode.r1, opcode.r2))
895                    else:
896                        raise UnknownMethodError(opcode.arg)
897                elif opcode.code == "callmeth1":
898                    if opcode.arg in ("split", "rsplit", "strip", "lstrip", "rstrip", "startswith", "endswith", "find"):
899                        _code("reg%d = reg%d.%s(reg%d)" % (opcode.r1, opcode.r2, opcode.arg, opcode.r3))
900                    elif opcode.arg == "format":
901                        _code("reg%d = ul4c._format(reg%d, reg%d)" % (opcode.r1, opcode.r2, opcode.r3))
902                    else:
903                        raise UnknownMethodError(opcode.arg)
904                elif opcode.code == "callmeth2":
905                    if opcode.arg in ("split", "rsplit", "find"):
906                        _code("reg%d = reg%d.%s(reg%d, reg%d)" % (opcode.r1, opcode.r2, opcode.arg, opcode.r3, opcode.r4))
907                    else:
908                        raise UnknownMethodError(opcode.arg)
909                elif opcode.code == "callmeth3":
910                    if opcode.arg == "find":
911                        _code("reg%d = reg%d.%s(reg%d, reg%d, reg%d)" % (opcode.r1, opcode.r2, opcode.arg, opcode.r3, opcode.r4, opcode.r5))
912                    else:
913                        raise UnknownMethodError(opcode.arg)
914                elif opcode.code == "if":
915                    _code("if reg%d:" % opcode.r1)
916                    indent += 1
917                elif opcode.code == "else":
918                    if lastopcode == "if":
919                        output[-1] += " pass"
920                    indent -= 1
921                    _code("else:")
922                    indent += 1
923                elif opcode.code == "endif":
924                    if lastopcode in ("if", "else"):
925                        output[-1] += " pass"
926                    indent -= 1
927                    _code("# end if")
928                elif opcode.code == "render":
929                    _code('for chunk in templates[%r](templates, **dict((key.encode("utf-8"), value) for (key, value) in reg%d.iteritems())): yield chunk' % (opcode.arg, opcode.r1))
930                else:
931                    raise UnknownOpcodeError(opcode.code)
932                lastopcode = opcode.code
933        except Error, exc:
934            exc.decorate(opcode.location)
935            raise
936        except Exception, exc:
937            raise Error(exc).decorate(opcode.location)
938        indent -= 1
939        buildloc = "ul4c.Location(source, *locations[sys.exc_info()[2].tb_lineno-startline])"
940        _code("except ul4c.Error, exc:")
941        indent += 1
942        _code("exc.decorate(%s)" % buildloc)
943        _code("raise")
944        indent -= 1
945        _code("except Exception, exc:")
946        indent += 1
947        _code("raise ul4c.Error(exc).decorate(%s)" % buildloc)
948        return "\n".join(output)
949
950    def pythonfunction(self):
951        if self._pythonfunction is None:
952            code = self.pythonsource("render")
953            ns = {}
954            exec code.encode("utf-8") in ns
955            self._pythonfunction = ns["render"]
956        return self._pythonfunction
957
958    def __call__(self, templates={}, **variables):
959        return self.pythonfunction()(templates, **variables)
960
961    def render(self, templates={}, **variables):
962        return self.pythonfunction()(templates, **variables)
963
964    def renders(self, templates={}, **variables):
965        return "".join(self.render(templates, **variables))
966
967    def format(self, indent="\t"):
968        """
969        Format the list of opcodes. This is a generator yielding lines to be output
970        (but without trailing newlines). :var:`indent` can be used to specify how
971        to indent block (defaulting to ``"\\t"``).
972        """
973        i = 0
974        for opcode in self:
975            if opcode.code in ("else", "endif", "endfor"):
976                i -= 1
977            if opcode.code in ("endif", "endfor"):
978                yield "%s}" % (i*indent)
979            elif opcode.code in ("for", "if"):
980                yield "%s%s {" % (i*indent, opcode)
981            elif opcode.code == "else":
982                yield "%s} else {" % (i*indent)
983            else:
984                yield "%s%s" % (i*indent, opcode)
985            if opcode.code in ("for", "if", "else"):
986                i += 1
987
988    def _tokenize(self, source, startdelim, enddelim):
989        pattern = u"%s(print|code|for|if|elif|else|end|render)(\s*((.|\\n)*?)\s*)?%s" % (re.escape(startdelim), re.escape(enddelim))
990        pos = 0
991        for match in re.finditer(pattern, source):
992            if match.start() != pos:
993                yield Location(source, None, pos, match.start(), pos, match.start())
994            yield Location(source, source[match.start(1):match.end(1)], match.start(), match.end(), match.start(3), match.end(3))
995            pos = match.end()
996        end = len(source)
997        if pos != end:
998            yield Location(source, None, pos, end, pos, end)
999
1000    def _allocreg(self):
1001        try:
1002            return self.registers.pop()
1003        except KeyError:
1004            raise OutOfRegistersError()
1005
1006    def _freereg(self, register):
1007        self.registers.add(register)
1008
1009    def opcode(self, name, r1=None, r2=None, r3=None, r4=None, r5=None, arg=None):
1010        self.opcodes.append(Opcode(name, r1, r2, r3, r4, r5, arg, self.location))
1011
1012    def _compile(self, source, startdelim, enddelim):
1013        self.startdelim = startdelim
1014        self.enddelim = enddelim
1015        scanner = Scanner()
1016        parseexpr = ExprParser(scanner).compile
1017        parsestmt = StmtParser(scanner).compile
1018        parsefor = ForParser(scanner).compile
1019        parserender = RenderParser(scanner).compile
1020
1021        # This stack stores for each nested for/foritem/if/elif/else the following information:
1022        # 1) Which construct we're in (i.e. "if" or "for")
1023        # For ifs:
1024        # 2) How many if's or elif's we have seen (this is used for simulating elif's via nested if's, for each additional elif, we have one more endif to add)
1025        # 3) Whether we've already seen the else
1026        stack = []
1027
1028        self.source = source
1029        self.opcodes = []
1030
1031        for location in self._tokenize(source, startdelim, enddelim):
1032            self.location = location
1033            try:
1034                if location.type is None:
1035                    self.opcode(None)
1036                elif location.type == "print":
1037                    r = parseexpr(self)
1038                    self.opcode("print", r1=r)
1039                elif location.type == "code":
1040                    parsestmt(self)
1041                elif location.type == "if":
1042                    r = parseexpr(self)
1043                    self.opcode("if", r1=r)
1044                    stack.append(("if", 1, False))
1045                elif location.type == "elif":
1046                    if not stack or stack[-1][0] != "if":
1047                        raise BlockError("elif doesn't match any if")
1048                    elif stack[-1][2]:
1049                        raise BlockError("else already seen in elif")
1050                    self.opcode("else")
1051                    r = parseexpr(self)
1052                    self.opcode("if", r1=r)
1053                    stack[-1] = ("if", stack[-1][1]+1, False)
1054                elif location.type == "else":
1055                    if not stack or stack[-1][0] != "if":
1056                        raise BlockError("else doesn't match any if")
1057                    elif stack[-1][2]:
1058                        raise BlockError("duplicate else")
1059                    self.opcode("else")
1060                    stack[-1] = ("if", stack[-1][1], True)
1061                elif location.type == "end":
1062                    if not stack:
1063                        raise BlockError("not in any block")
1064                    code = location.code
1065                    if code:
1066                        if code == "if":
1067                            if stack[-1][0] != "if":
1068                                raise BlockError("endif doesn't match any if")
1069                        elif code == "for":
1070                            if stack[-1][0] != "for":
1071                                raise BlockError("endfor doesn't match any for")
1072                        else:
1073                            raise BlockError("illegal end value %r" % code)
1074                    last = stack.pop()
1075                    if last[0] == "if":
1076                        for i in xrange(last[1]):
1077                            self.opcode("endif")
1078                    else: # last[0] == "for":
1079                        self.opcode("endfor")
1080                elif location.type == "for":
1081                    parsefor(self)
1082                    stack.append(("for",))
1083                elif location.type == "render":
1084                    parserender(self)
1085                else: # Can't happen
1086                    raise ValueError("unknown tag %r" % location.type)
1087            except Error, exc:
1088                exc.decorate(location)
1089                raise
1090            except Exception, exc:
1091                raise Error(exc).decorate(location)
1092            finally:
1093                del self.location
1094        if stack:
1095            raise BlockError("unclosed blocks")
1096
1097    def __str__(self):
1098        return "\n".join(self.format())
1099
1100    def __unicode__(self):
1101        return u"\n".join(self.format())
1102
1103    def __repr__(self):
1104        return "<%s.%s object with %d opcodes at 0x%x>" % (self.__class__.__module__, self.__class__.__name__, len(self.opcodes), id(self))
1105
1106
1107def compile(source, startdelim="<?", enddelim="?>"):
1108    template = Template()
1109    template._compile(source, startdelim, enddelim)
1110    return template
1111
1112load = Template.load
1113loads = Template.loads
1114
1115
1116###
1117### Tokens and nodes for the AST
1118###
1119
1120class Token(object):
1121    def __init__(self, start, end, type):
1122        self.start = start
1123        self.end = end
1124        self.type = type
1125
1126    def __repr__(self):
1127        return "%s(%r, %r, %r)" % (self.__class__.__name__, self.start, self.end, self.type)
1128
1129    def __str__(self):
1130        return self.type
1131
1132
1133class AST(object):
1134    """
1135    Baseclass for all syntax tree nodes.
1136    """
1137
1138    def __init__(self, start, end):
1139        self.start = start
1140        self.end = end
1141
1142
1143class Const(AST):
1144    """
1145    Common baseclass for all constants (used for type testing in constant folding)
1146    """
1147
1148    def __repr__(self):
1149        return "%s(%r, %r)" % (self.__class__.__name__, self.start, self.end)
1150
1151    def compile(self, template):
1152        r = template._allocreg()
1153        template.opcode("load%s" % self.type, r1=r)
1154        return r
1155
1156
1157class None_(Const):
1158    type = "none"
1159    value = None
1160
1161
1162class True_(Const):
1163    type = "true"
1164    value = True
1165
1166
1167class False_(Const):
1168    type = "false"
1169    value = False
1170
1171
1172class Value(Const):
1173    def __init__(self, start, end, value):
1174        Const.__init__(self, start, end)
1175        self.value = value
1176
1177    def __repr__(self):
1178        return "%s(%r, %r, %r)" % (self.__class__.__name__, self.start, self.end, self.value)
1179
1180    def compile(self, template):
1181        r = template._allocreg()
1182        template.opcode("load%s" % self.type, r1=r, arg=unicode(self.value))
1183        return r
1184
1185
1186class Int(Value):
1187    type = "int"
1188
1189
1190class Float(Value):
1191    type = "float"
1192
1193    def compile(self, template):
1194        r = template._allocreg()
1195        template.opcode("load%s" % self.type, r1=r, arg=repr(self.value))
1196        return r
1197
1198
1199class Str(Value):
1200    type = "str"
1201
1202
1203class Date(Value):
1204    type = "date"
1205
1206    def compile(self, template):
1207        r = template._allocreg()
1208        template.opcode("load%s" % self.type, r1=r, arg=self.value.isoformat())
1209        return r
1210
1211
1212class List(AST):
1213    def __init__(self, start, end, *items):
1214        AST.__init__(self, start, end)
1215        self.items = list(items)
1216
1217    def __repr__(self):
1218        return "%s(%r, %r, %s)" % (self.__class__.__name__, self.start, self.end, repr(self.items)[1:-1])
1219
1220    def compile(self, template):
1221        r = template._allocreg()
1222        template.opcode("buildlist", r1=r)
1223        for item in self.items:
1224            ri = item.compile(template)
1225            template.opcode("addlist", r1=r, r2=ri)
1226            template._freereg(ri)
1227        return r
1228
1229
1230class Dict(AST):
1231    def __init__(self, start, end, *items):
1232        AST.__init__(self, start, end)
1233        self.items = list(items)
1234
1235    def __repr__(self):
1236        return "%s(%r, %r, %s)" % (self.__class__.__name__, self.start, self.end, repr(self.items)[1:-1])
1237
1238    def compile(self, template):
1239        r = template._allocreg()
1240        template.opcode("builddict", r1=r)
1241        for (key, value) in self.items:
1242            rk = key.compile(template)
1243            rv = value.compile(template)
1244            template.opcode("adddict", r1=r, r2=rk, r3=rv)
1245            template._freereg(rk)
1246            template._freereg(rv)
1247        return r
1248
1249
1250class Name(AST):
1251    type = "name"
1252
1253    def __init__(self, start, end, name):
1254        AST.__init__(self, start, end)
1255        self.name = name
1256
1257    def __repr__(self):
1258        return "%s(%r, %r, %r)" % (self.__class__.__name__, self.start, self.end, self.name)
1259
1260    def compile(self, template):
1261        r = template._allocreg()
1262        template.opcode("loadvar", r1=r, arg=self.name)
1263        return r
1264
1265
1266class For(AST):
1267    def __init__(self, start, end, iter, cont):
1268        AST.__init__(self, start, end)
1269        self.iter = iter
1270        self.cont = cont
1271
1272    def __repr__(self):
1273        return "%s(%r, %r, %r, %r)" % (self.__class__.__name__, self.start, self.end, self.iter, self.cont)
1274
1275    def compile(self, template):
1276        rc = self.cont.compile(template)
1277        ri = template._allocreg()
1278        template.opcode("for", r1=ri, r2=rc)
1279        if isinstance(self.iter, list):
1280            for (i, iter) in enumerate(self.iter):
1281                rii = template._allocreg()
1282                template.opcode("loadint", r1=rii, arg=str(i))
1283                template.opcode("getitem", r1=rii, r2=ri, r3=rii)
1284                template.opcode("storevar", r1=rii, arg=iter.name)
1285                template._freereg(rii)
1286        else:
1287            template.opcode("storevar", r1=ri, arg=self.iter.name)
1288        template._freereg(ri)
1289        template._freereg(rc)
1290
1291
1292class GetAttr(AST):
1293    def __init__(self, start, end, obj, attr):
1294        AST.__init__(self, start, end)
1295        self.obj = obj
1296        self.attr = attr
1297
1298    def __repr__(self):
1299        return "%s(%r, %r, %r, %r)" % (self.__class__.__name__, self.start, self.end, self.obj, self.attr)
1300
1301    def compile(self, template):
1302        r = self.obj.compile(template)
1303        template.opcode("getattr", r1=r, r2=r, arg=self.attr.name)
1304        return r
1305
1306
1307class GetSlice12(AST):
1308    def __init__(self, start, end, obj, index1, index2):
1309        AST.__init__(self, start, end)
1310        self.obj = obj
1311        self.index1 = index1
1312        self.index2 = index2
1313
1314    def __repr__(self):
1315        return "%s(%r, %r, %r, %r, %r)" % (self.__class__.__name__, self.start, self.end, self.obj, self.index1, self.index2)
1316
1317    def compile(self, template):
1318        r1 = self.obj.compile(template)
1319        r2 = self.index1.compile(template)
1320        r3 = self.index2.compile(template)
1321        template.opcode("getslice12", r1=r1, r2=r1, r3=r2, r4=r3)
1322        template._freereg(r2)
1323        template._freereg(r3)
1324        return r1
1325
1326
1327class Unary(AST):
1328    opcode = None
1329
1330    def __init__(self, start, end, obj):
1331        AST.__init__(self, start, end)
1332        self.obj = obj
1333
1334    def __repr__(self):
1335        return "%s(%r, %r, %r)" % (self.__class__.__name__, self.start, self.end, self.obj)
1336
1337    def compile(self, template):
1338        r = self.obj.compile(template)
1339        template.opcode(self.opcode, r1=r, r2=r)
1340        return r
1341
1342
1343class GetSlice(Unary):
1344    opcode = "getslice"
1345
1346
1347class Not(Unary):
1348    opcode = "not"
1349
1350
1351class Neg(Unary):
1352    opcode = "neg"
1353
1354
1355class Binary(AST):
1356    opcode = None
1357
1358    def __init__(self, start, end, obj1, obj2):
1359        AST.__init__(self, start, end)
1360        self.obj1 = obj1
1361        self.obj2 = obj2
1362
1363    def __repr__(self):
1364        return "%s(%r, %r, %r, %r)" % (self.__class__.__name__, self.start, self.end, self.obj1, self.obj2)
1365
1366    def compile(self, template):
1367        r1 = self.obj1.compile(template)
1368        r2 = self.obj2.compile(template)
1369        template.opcode(self.opcode, r1=r1, r2=r1, r3=r2)
1370        template._freereg(r2)
1371        return r1
1372
1373
1374class GetItem(Binary):
1375    opcode = "getitem"
1376
1377
1378class GetSlice1(Binary):
1379    opcode = "getslice1"
1380
1381
1382class GetSlice2(Binary):
1383    opcode = "getslice2"
1384
1385
1386class Equal(Binary):
1387    opcode = "equals"
1388
1389
1390class NotEqual(Binary):
1391    opcode = "notequals"
1392
1393
1394class Contains(Binary):
1395    opcode = "contains"
1396
1397
1398class NotContains(Binary):
1399    opcode = "notcontains"
1400
1401
1402class Add(Binary):
1403    opcode = "add"
1404
1405
1406class Sub(Binary):
1407    opcode = "sub"
1408
1409
1410class Mul(Binary):
1411    opcode = "mul"
1412
1413
1414class FloorDiv(Binary):
1415    opcode = "floordiv"
1416
1417
1418class TrueDiv(Binary):
1419    opcode = "truediv"
1420
1421
1422class Or(Binary):
1423    opcode = "or"
1424
1425
1426class And(Binary):
1427    opcode = "and"
1428
1429
1430class Mod(Binary):
1431    opcode = "mod"
1432
1433
1434class ChangeVar(AST):
1435    opcode = None
1436
1437    def __init__(self, start, end, name, value):
1438        AST.__init__(self, start, end)
1439        self.name = name
1440        self.value = value
1441
1442    def __repr__(self):
1443        return "%s(%r, %r, %r, %r)" % (self.__class__.__name__, self.start, self.end, self.name, self.value)
1444
1445    def compile(self, template):
1446        r = self.value.compile(template)
1447        template.opcode(self.opcode, r1=r, arg=self.name.name)
1448        template._freereg(r)
1449
1450
1451class StoreVar(ChangeVar):
1452    opcode = "storevar"
1453
1454
1455class AddVar(ChangeVar):
1456    opcode = "addvar"
1457
1458
1459class SubVar(ChangeVar):
1460    opcode = "subvar"
1461
1462
1463class MulVar(ChangeVar):
1464    opcode = "mulvar"
1465
1466
1467class TrueDivVar(ChangeVar):
1468    opcode = "truedivvar"
1469
1470
1471class FloorDivVar(ChangeVar):
1472    opcode = "floordivvar"
1473
1474
1475class ModVar(ChangeVar):
1476    opcode = "modvar"
1477
1478
1479class DelVar(AST):
1480    def __init__(self, start, end, name):
1481        AST.__init__(self, start, end)
1482        self.name = name
1483
1484    def __repr__(self):
1485        return "%s(%r, %r, %r)" % (self.__class__.__name__, self.start, self.end, self.name)
1486
1487    def compile(self, template):
1488        template.opcode("delvar", arg=self.name.name)
1489
1490
1491class CallFunc(AST):
1492    def __init__(self, start, end, name, args):
1493        AST.__init__(self, start, end)
1494        self.name = name
1495        self.args = args
1496
1497    def __repr__(self):
1498        if self.args:
1499            return "%s(%r, %r, %r, %s)" % (self.__class__.__name__, self.start, self.end, self.name, repr(self.args)[1:-1])
1500        else:
1501            return "%s(%r, %r, %r)" % (self.__class__.__name__, self.start, self.end, self.name)
1502
1503    def compile(self, template):
1504        if len(self.args) == 0:
1505            r = template._allocreg()
1506            template.opcode("callfunc0", r1=r, arg=self.name.name)
1507            return r
1508        elif len(self.args) > 3:
1509            raise ValueError("%d arguments not supported" % len(self.args))
1510        else:
1511            rs = [arg.compile(template) for arg in self.args]
1512            template.opcode("callfunc%d" % len(self.args), rs[0], *rs, **dict(arg=self.name.name)) # Replace **dict(arg=) with arg= in Python 2.6?
1513            for i in xrange(1, len(self.args)):
1514                template._freereg(rs[i])
1515            return rs[0]
1516
1517
1518class CallMeth(AST):
1519    def __init__(self, start, end, name, obj, args):
1520        AST.__init__(self, start, end)
1521        self.name = name
1522        self.obj = obj
1523        self.args = args
1524
1525    def __repr__(self):
1526        if self.args:
1527            return "%s(%r, %r, %r, %r, %s)" % (self.__class__.__name__, self.start, self.end, self.name, self.obj, repr(self.args)[1:-1])
1528        else:
1529            return "%s(%r, %r, %r, %r)" % (self.__class__.__name__, self.start, self.end, self.name, self.obj)
1530
1531    def compile(self, template):
1532        if len(self.args) > 3:
1533            raise ValueError("%d arguments not supported" % len(self.args))
1534        ro = self.obj.compile(template)
1535        rs = [arg.compile(template) for arg in self.args]
1536        template.opcode("callmeth%d" % len(self.args), ro, ro, *rs, **dict(arg=self.name.name))
1537        for r in rs:
1538            template._freereg(r)
1539        return ro
1540
1541
1542class Render(AST):
1543    def __init__(self, start, end, name, *variables):
1544        AST.__init__(self, start, end)
1545        self.name = name
1546        self.variables = list(variables)
1547
1548    def __repr__(self):
1549        return "%s(%r, %r, %r, %s)" % (self.__class__.__name__, self.start, self.end, self.name, repr(self.variables)[1:-1])
1550
1551    def compile(self, template):
1552        r = template._allocreg()
1553        template.opcode("builddict", r1=r)
1554        for (key, value) in self.variables:
1555            rv = value.compile(template)
1556            rk = template._allocreg()
1557            template.opcode("loadstr", r1=rk, arg=key.name)
1558            template.opcode("adddict", r1=r, r2=rk, r3=rv)
1559            template._freereg(rk)
1560            template._freereg(rv)
1561        template.opcode("render", r1=r, arg=self.name.name)
1562        template._freereg(r)
1563
1564
1565###
1566### Tokenizer
1567###
1568
1569class Scanner(spark.Scanner):
1570    reflags = re.UNICODE
1571
1572    def tokenize(self, location):
1573        self.collectstr = []
1574        self.rv = []
1575        self.start = 0
1576        try:
1577            spark.Scanner.tokenize(self, location.code)
1578            if self.mode != "default":
1579                raise UnterminatedStringError()
1580        except Error, exc:
1581            exc.decorate(location)
1582            raise
1583        except Exception, exc:
1584            raise Error(exc).decorate(location)
1585        return self.rv
1586
1587    # Must be before the int and float constants
1588    @spark.token("\\d{4}-\\d{2}-\\d{2}T(\\d{2}:\\d{2}(:\\d{2}(\\.\\d{6})?)?)?", "default")
1589    def date(self, start, end, s):
1590        self.rv.append(Date(start, end, datetime.datetime(*map(int, filter(None, datesplitter.split(s))))))
1591
1592    @spark.token("\\(|\\)|\\[|\\]|\\{|\\}|\\.|,|==|\\!=|=|\\+=|\\-=|\\*=|//=|/=|%=|%|:|\\+|-|\\*|//|/", "default")
1593    def token(self, start, end, s):
1594        self.rv.append(Token(start, end, s))
1595
1596    @spark.token("[a-zA-Z_][\\w]*", "default")
1597    def name(self, start, end, s):
1598        if s in ("in", "not", "or", "and", "del"):
1599            self.rv.append(Token(start, end, s))
1600        elif s == "None":
1601            self.rv.append(None_(start, end))
1602        elif s == "True":
1603            self.rv.append(True_(start, end))
1604        elif s == "False":
1605            self.rv.append(False_(start, end))
1606        else:
1607            self.rv.append(Name(start, end, s))
1608
1609    # We don't have negatve numbers, this is handled by constant folding in the AST for unary minus
1610    @spark.token("\\d+\\.\\d*([eE][+-]?\\d+)?", "default")
1611    @spark.token("\\d+(\\.\\d*)?[eE][+-]?\\d+", "default")
1612    def float(self, start, end, s):
1613        self.rv.append(Float(start, end, float(s)))
1614
1615    @spark.token("0[xX][\\da-fA-F]+", "default")
1616    def hexint(self, start, end, s):
1617        self.rv.append(Int(start, end, int(s[2:], 16)))
1618
1619    @spark.token("0[oO][0-7]+", "default")
1620    def octint(self, start, end, s):
1621        self.rv.append(Int(start, end, int(s[2:], 8)))
1622
1623    @spark.token("0[bB][01]+", "default")
1624    def binint(self, start, end, s):
1625        self.rv.append(Int(start, end, int(s[2:], 2)))
1626
1627    @spark.token("\\d+", "default")
1628    def int(self, start, end, s):
1629        self.rv.append(Int(start, end, int(s)))
1630
1631    @spark.token("'", "default")
1632    def beginstr1(self, start, end, s):
1633        self.mode = "str1"
1634        self.start = start
1635
1636    @spark.token('"', "default")
1637    def beginstr2(self, start, end, s):
1638        self.mode = "str2"
1639        self.start = start
1640
1641    @spark.token("'", "str1")
1642    @spark.token('"', "str2")
1643    def endstr(self, start, end, s):
1644        self.rv.append(Str(self.start, end, "".join(self.collectstr)))
1645        self.collectstr = []
1646        self.mode = "default"
1647
1648    @spark.token("\\s+", "default")
1649    def whitespace(self, start, end, s):
1650        pass
1651
1652    @spark.token("\\\\\\\\", "str1", "str2")
1653    def escapedbackslash(self, start, end, s):
1654        self.collectstr.append("\\")
1655
1656    @spark.token("\\\\'", "str1", "str2")
1657    def escapedapos(self, start, end, s):
1658        self.collectstr.append("'")
1659
1660    @spark.token('\\\\"', "str1", "str2")
1661    def escapedquot(self, start, end, s):
1662        self.collectstr.append('"')
1663
1664    @spark.token("\\\\a", "str1", "str2")
1665    def escapedbell(self, start, end, s):
1666        self.collectstr.append("\a")
1667
1668    @spark.token("\\\\b", "str1", "str2")
1669    def escapedbackspace(self, start, end, s):
1670        self.collectstr.append("\b")
1671
1672    @spark.token("\\\\f", "str1", "str2")
1673    def escapedformfeed(self, start, end, s):
1674        self.collectstr.append("\f")
1675
1676    @spark.token("\\\\n", "str1", "str2")
1677    def escapedlinefeed(self, start, end, s):
1678        self.collectstr.append("\n")
1679
1680    @spark.token("\\\\r", "str1", "str2")
1681    def escapedcarriagereturn(self, start, end, s):
1682        self.collectstr.append("\r")
1683
1684    @spark.token("\\\\t", "str1", "str2")
1685    def escapedtab(self, start, end, s):
1686        self.collectstr.append("\t")
1687
1688    @spark.token("\\\\v", "str1", "str2")
1689    def escapedverticaltab(self, start, end, s):
1690        self.collectstr.append("\v")
1691
1692    @spark.token("\\\\e", "str1", "str2")
1693    def escapedescape(self, start, end, s):
1694        self.collectstr.append("\x1b")
1695
1696    @spark.token("\\\\x[0-9a-fA-F]{2}", "str1", "str2")
1697    def escaped8bitchar(self, start, end, s):
1698        self.collectstr.append(unichr(int(s[2:], 16)))
1699
1700    @spark.token("\\\\u[0-9a-fA-F]{4}", "str1", "str2")
1701    def escaped16bitchar(self, start, end, s):
1702        self.collectstr.append(unichr(int(s[2:], 16)))
1703
1704    @spark.token(".|\\n", "str1", "str2")
1705    def text(self, start, end, s):
1706        self.collectstr.append(s)
1707
1708    @spark.token("(.|\\n)+", "default", "str1", "str2")
1709    def default(self, start, end, s):
1710        raise LexicalError(start, end, s)
1711
1712    def error(self, start, end, s):
1713        raise LexicalError(start, end, s)
1714
1715
1716###
1717### Parsers for different types of code
1718###
1719
1720class ExprParser(spark.Parser):
1721    emptyerror = "expression required"
1722    start = "expr0"
1723
1724    def __init__(self, scanner):
1725        spark.Parser.__init__(self)
1726        self.scanner = scanner
1727
1728    def compile(self, template):
1729        location = template.location
1730        if not location.code:
1731            raise ValueError(self.emptyerror)
1732        template.registers = set(xrange(10))
1733        try:
1734            ast = self.parse(self.scanner.tokenize(location))
1735            return ast.compile(template)
1736        except Error, exc:
1737            exc.decorate(location)
1738            raise
1739        except Exception, exc:
1740            raise Error(exc).decorate(location)
1741        finally:
1742            del template.registers
1743
1744    def typestring(self, token):
1745        return token.type
1746
1747    def error(self, token):
1748        raise SyntaxError(token)
1749
1750    def makeconst(self, start, end, value):
1751        if value is None:
1752            return None_(start, end)
1753        elif value is True:
1754            return True_(start, end)
1755        elif value is False:
1756            return False_(start, end)
1757        elif isinstance(value, int):
1758            return Int(start, end, value)
1759        elif isinstance(value, float):
1760            return Float(start, end, value)
1761        elif isinstance(value, basestring):
1762            return Str(start, end, value)
1763        else:
1764            raise TypeError("can't convert %r" % value)
1765
1766    # To implement operator precedence, each expression rule has the precedence in its name. The highest precedence is 11 for atomic expressions.
1767    # Each expression can have only expressions as parts, which have the some or a higher precedence with two exceptions:
1768    #    1) Expressions where there's no ambiguity, like the index for a getitem/getslice or function/method arguments;
1769    #    2) Brackets, which can be used to boost the precedence of an expression to the level of an atomic expression.
1770
1771    @spark.production('expr11 ::= none')
1772    @spark.production('expr11 ::= true')
1773    @spark.production('expr11 ::= false')
1774    @spark.production('expr11 ::= str')
1775    @spark.production('expr11 ::= int')
1776    @spark.production('expr11 ::= float')
1777    @spark.production('expr11 ::= date')
1778    @spark.production('expr11 ::= name')
1779    def expr_atom(self, atom):
1780        return atom
1781
1782    @spark.production('expr11 ::= [ ]')
1783    def expr_emptylist(self, _0, _1):
1784        return List(_0.start, _1.end)
1785
1786    @spark.production('buildlist ::= [ expr0')
1787    def expr_buildlist(self, _0, expr):
1788        return List(_0.start, expr.end, expr)
1789
1790    @spark.production('buildlist ::= buildlist , expr0')
1791    def expr_addlist(self, list, _0, expr):
1792        list.items.append(expr)
1793        list.end = expr.end
1794        return list
1795
1796    @spark.production('expr11 ::= buildlist ]')
1797    def expr_finishlist(self, list, _0):
1798        list.end = _0.end
1799        return list
1800
1801    @spark.production('expr11 ::= buildlist , ]')
1802    def expr_finishlist1(self, list, _0, _1):
1803        list.end = _1.end
1804        return list
1805
1806    @spark.production('expr11 ::= { }')
1807    def expr_emptydict(self, _0, _1):
1808        return Dict(_0.start, _1.end)
1809
1810    @spark.production('builddict ::= { expr0 : expr0')
1811    def expr_builddict(self, _0, exprkey, _1, exprvalue):
1812        return Dict(_0.start, exprvalue.end, (exprkey, exprvalue))
1813
1814    @spark.production('builddict ::= builddict , expr0 : expr0')
1815    def expr_adddict(self, dict, _0, exprkey, _1, exprvalue):
1816        dict.items.append((exprkey, exprvalue))
1817        dict.end = exprvalue.end
1818        return dict
1819
1820    @spark.production('expr11 ::= builddict }')
1821    def expr_finishdict(self, dict, _0):
1822        dict.end = _0.end
1823        return dict
1824
1825    @spark.production('expr11 ::= builddict , }')
1826    def expr_finishdict1(self, dict, _0, _1):
1827        dict.end = _1.end
1828        return dict
1829
1830    @spark.production('expr11 ::= ( expr0 )')
1831    def expr_bracket(self, _0, expr, _1):
1832        return expr
1833
1834    @spark.production('expr10 ::= name ( )')
1835    def expr_callfunc0(self, name, _0, _1):
1836        return CallFunc(name.start, _1.end, name, [])
1837
1838    @spark.production('expr10 ::= name ( expr0 )')
1839    def expr_callfunc1(self, name, _0, arg0, _1):
1840        return CallFunc(name.start, _1.end, name, [arg0])
1841
1842    @spark.production('expr10 ::= name ( expr0 , expr0 )')
1843    def expr_callfunc2(self, name, _0, arg0, _1, arg1, _2):
1844        return CallFunc(name.start, _2.end, name, [arg0, arg1])
1845
1846    @spark.production('expr10 ::= name ( expr0 , expr0 , expr0 )')
1847    def expr_callfunc3(self, name, _0, arg0, _1, arg1, _2, arg2, _3):
1848        return CallFunc(name.start, _3.end, name, [arg0, arg1, arg2])
1849
1850    @spark.production('expr9 ::= expr9 . name')
1851    def expr_getattr(self, expr, _0, name):
1852        return GetAttr(expr.start, name.end, expr, name)
1853
1854    @spark.production('expr9 ::= expr9 . name ( )')
1855    def expr_callmeth0(self, expr, _0, name, _1, _2):
1856        return CallMeth(expr.start, _2.end, name, expr, [])
1857
1858    @spark.production('expr9 ::= expr9 . name ( expr0 )')
1859    def expr_callmeth1(self, expr, _0, name, _1, arg1, _2):
1860        return CallMeth(expr.start, _2.end, name, expr, [arg1])
1861
1862    @spark.production('expr9 ::= expr9 . name ( expr0 , expr0 )')
1863    def expr_callmeth2(self, expr, _0, name, _1, arg1, _2, arg2, _3):
1864        return CallMeth(expr.start, _3.end, name, expr, [arg1, arg2])
1865
1866    @spark.production('expr9 ::= expr9 . name ( expr0 , expr0 , expr0 )')
1867    def expr_callmeth3(self, expr, _0, name, _1, arg1, _2, arg2, _3, arg3, _4):
1868        return CallMeth(expr.start, _4.end, name, expr, [arg1, arg2, arg3])
1869
1870    @spark.production('expr9 ::= expr9 [ expr0 ]')
1871    def expr_getitem(self, expr, _0, key, _1):
1872        if isinstance(expr, Const) and isinstance(key, Const): # Constant folding
1873            return self.makeconst(expr.start, _1.end, expr.value[key.value])
1874        return GetItem(expr.start, _1.end, expr, key)
1875
1876    @spark.production('expr8 ::= expr8 [ expr0 : expr0 ]')
1877    def expr_getslice12(self, expr, _0, index1, _1, index2, _2):
1878        if isinstance(expr, Const) and isinstance(index1, Const) and isinstance(index2, Const): # Constant folding
1879            return self.makeconst(expr.start, _2.end, expr.value[index1.value:index1.value])
1880        return GetSlice12(expr.start, _2.end, expr, index1, index2)
1881
1882    @spark.production('expr8 ::= expr8 [ expr0 : ]')
1883    def expr_getslice1(self, expr, _0, index1, _1, _2):
1884        if isinstance(expr, Const) and isinstance(index1, Const): # Constant folding
1885            return self.makeconst(expr.start, _2.end, expr.value[index1.value:])
1886        return GetSlice1(expr.start, _2.end, expr, index1)
1887
1888    @spark.production('expr8 ::= expr8 [ : expr0 ]')
1889    def expr_getslice2(self, expr, _0, _1, index2, _2):
1890        if isinstance(expr, Const) and isinstance(index2, Const): # Constant folding
1891            return self.makeconst(expr.start, _2.end, expr.value[:index2.value])
1892        return GetSlice2(expr.start, _2.end, expr, index2)
1893
1894    @spark.production('expr8 ::= expr8 [ : ]')
1895    def expr_getslice(self, expr, _0, _1, _2):
1896        if isinstance(expr, Const): # Constant folding
1897            return self.makeconst(expr.start, _2.end, expr.value[:])
1898        return GetSlice(expr.start, _2.end, expr)
1899
1900    @spark.production('expr7 ::= - expr7')
1901    def expr_neg(self, _0, expr):
1902        if isinstance(expr, Const): # Constant folding
1903            return self.makeconst(_0.start, expr.end, -expr.value)
1904        return Neg(_0.start, expr.end, expr)
1905
1906    @spark.production('expr6 ::= expr6 * expr6')
1907    def expr_mul(self, obj1, _0, obj2):
1908        if isinstance(obj1, Const) and isinstance(obj2, Const): # Constant folding
1909            return self.makeconst(obj1.start, obj2.end, obj1.value * obj2.value)
1910        return Mul(obj1.start, obj2.end, obj1, obj2)
1911
1912    @spark.production('expr6 ::= expr6 // expr6')
1913    def expr_floordiv(self, obj1, _0, obj2):
1914        if isinstance(obj1, Const) and isinstance(obj2, Const): # Constant folding
1915            return self.makeconst(obj1.start, obj2.end, obj1.value // obj2.value)
1916        return FloorDiv(obj1.start, obj2.end, obj1, obj2)
1917
1918    @spark.production('expr6 ::= expr6 / expr6')
1919    def expr_truediv(self, obj1, _0, obj2):
1920        if isinstance(obj1, Const) and isinstance(obj2, Const): # Constant folding
1921            return self.makeconst(obj1.start, obj2.end, obj1.value / obj2.value)
1922        return TrueDiv(obj1.start, obj2.end, obj1, obj2)
1923
1924    @spark.production('expr6 ::= expr6 % expr6')
1925    def expr_mod(self, obj1, _0, obj2):
1926        if isinstance(obj1, Const) and isinstance(obj2, Const): # Constant folding
1927            return self.makeconst(obj1.start, obj2.end, obj1.value % obj2.value)
1928        return Mod(obj1.start, obj2.end, obj1, obj2)
1929
1930    @spark.production('expr5 ::= expr5 + expr5')
1931    def expr_add(self, obj1, _0, obj2):
1932        if isinstance(obj1, Const) and isinstance(obj2, Const): # Constant folding
1933            return self.makeconst(obj1.start, obj2.end, obj1.value + obj2.value)
1934        return Add(obj1.start, obj2.end, obj1, obj2)
1935
1936    @spark.production('expr5 ::= expr5 - expr5')
1937    def expr_sub(self, obj1, _0, obj2):
1938        if isinstance(obj1, Const) and isinstance(obj2, Const): # Constant folding
1939            return self.makeconst(obj1.start, obj2.end, obj1.value - obj2.value)
1940        return Sub(obj1.start, obj2.end, obj1, obj2)
1941
1942    @spark.production('expr4 ::= expr4 == expr4')
1943    def expr_equal(self, obj1, _0, obj2):
1944        if isinstance(obj1, Const) and isinstance(obj2, Const): # Constant folding
1945            return self.makeconst(obj1.start, obj2.end, obj1.value == obj2.value)
1946        return Equal(obj1.start, obj2.end, obj1, obj2)
1947
1948    @spark.production('expr4 ::= expr4 != expr4')
1949    def expr_notequal(self, obj1, _0, obj2):
1950        if isinstance(obj1, Const) and isinstance(obj2, Const): # Constant folding
1951            return self.makeconst(obj1.start, obj2.end, obj1.value != obj2.value)
1952        return NotEqual(obj1.start, obj2.end, obj1, obj2)
1953
1954    @spark.production('expr3 ::= expr3 in expr3')
1955    def expr_contains(self, obj, _0, container):
1956        if isinstance(obj, Const) and isinstance(container, Const): # Constant folding
1957            return self.makeconst(obj.start, container.end, obj.value in container.value)
1958        return Contains(obj.start, container.end, obj, container)
1959
1960    @spark.production('expr3 ::= expr3 not in expr3')
1961    def expr_notcontains(self, obj, _0, _1, container):
1962        if isinstance(obj, Const) and isinstance(container, Const): # Constant folding
1963            return self.makeconst(obj.start, container.end, obj.value not in container.value)
1964        return NotContains(obj.start, container.end, obj, container)
1965
1966    @spark.production('expr2 ::= not expr2')
1967    def expr_not(self, _0, expr):
1968        if isinstance(expr1, Const): # Constant folding
1969            return self.makeconst(_0.start, expr.end, not expr.value)
1970        return Not(_0.start, expr.end, expr)
1971
1972    @spark.production('expr1 ::= expr1 and expr1')
1973    def expr_and(self, obj1, _0, obj2):
1974        if isinstance(obj1, Const) and isinstance(obj2, Const): # Constant folding
1975            return self.makeconst(obj1.start, obj2.end, bool(obj1.value and obj2.value))
1976        return And(obj1.start, obj2.end, obj1, obj2)
1977
1978    @spark.production('expr0 ::= expr0 or expr0')
1979    def expr_or(self, obj1, _0, obj2):
1980        if isinstance(obj1, Const) and isinstance(obj2, Const): # Constant folding
1981            return self.makeconst(obj1.start, obj2.end, bool(obj1.value or obj2.value))
1982        return Or(obj1.start, obj2.end, obj1, obj2)
1983
1984    # These rules make operators of different precedences interoperable, by allowing an expression to "drop" its precedence.
1985    @spark.production('expr10 ::= expr11')
1986    @spark.production('expr9 ::= expr10')
1987    @spark.production('expr8 ::= expr9')
1988    @spark.production('expr7 ::= expr8')
1989    @spark.production('expr6 ::= expr7')
1990    @spark.production('expr5 ::= expr6')
1991    @spark.production('expr4 ::= expr5')
1992    @spark.production('expr3 ::= expr4')
1993    @spark.production('expr2 ::= expr3')
1994    @spark.production('expr1 ::= expr2')
1995    @spark.production('expr0 ::= expr1')
1996    def expr_dropprecedence(self, expr):
1997        return expr
1998
1999
2000class ForParser(ExprParser):
2001    emptyerror = "loop expression required"
2002    start = "for"
2003   
2004    @spark.production('for ::= name in expr0')
2005    def for0(self, iter, _0, cont):
2006        return For(iter.start, cont.end, iter, cont)
2007
2008    @spark.production('for ::= ( name , ) in expr0')
2009    def for1(self, _0, iter, _1, _2, _3, cont):
2010        return For(_0.start, cont.end, [iter], cont)
2011
2012    @spark.production('for ::= ( name , name ) in expr0')
2013    def for2a(self, _0, iter1, _1, iter2, _2, _3, cont):
2014        return For(_0.start, cont.end, [iter1, iter2], cont)
2015
2016    @spark.production('for ::= ( name , name , ) in expr0')
2017    def for2b(self, _0, iter1, _1, iter2, _2, _3, _4, cont):
2018        return For(_0.start, cont.end, [iter1, iter2], cont)
2019
2020
2021class StmtParser(ExprParser):
2022    emptyerror = "statement required"
2023    start = "stmt"
2024
2025    @spark.production('stmt ::= name = expr0')
2026    def stmt_assign(self, name, _0, value):
2027        return StoreVar(name.start, value.end, name, value)
2028
2029    @spark.production('stmt ::= name += expr0')
2030    def stmt_iadd(self, name, _0, value):
2031        return AddVar(name.start, value.end, name, value)
2032
2033    @spark.production('stmt ::= name -= expr0')
2034    def stmt_isub(self, name, _0, value):
2035        return SubVar(name.start, value.end, name, value)
2036
2037    @spark.production('stmt ::= name *= expr0')
2038    def stmt_imul(self, name, _0, value):
2039        return MulVar(name.start, value.end, name, value)
2040
2041    @spark.production('stmt ::= name /= expr0')
2042    def stmt_itruediv(self, name, _0, value):
2043        return TrueDivVar(name.start, value.end, name, value)
2044
2045    @spark.production('stmt ::= name //= expr0')
2046    def stmt_ifloordiv(self, name, _0, value):
2047        return FloorDivVar(name.start, value.end, name, value)
2048
2049    @spark.production('stmt ::= name %= expr0')
2050    def stmt_imod(self, name, _0, value):
2051        return ModVar(name.start, value.end, name, value)
2052
2053    @spark.production('stmt ::= del name')
2054    def stmt_del(self, _0, name):
2055        return DelVar(_0.start, name.end, name)
2056
2057
2058class RenderParser(ExprParser):
2059    emptyerror = "render statement required"
2060    start = "render"
2061
2062    @spark.production('render ::= name ( )')
2063    def emptyrender(self, name, _0, _1):
2064        return Render(name.start, _1.end, name)
2065
2066    @spark.production('buildrender ::= name ( name = expr0')
2067    def startrender(self, name, _0, argname, _1, argvalue):
2068        return Render(name.start, argvalue.end, name, (argname, argvalue))
2069
2070    @spark.production('buildrender ::= buildrender , name = expr0')
2071    def buildrender(self, render, _0, argname, _1, argvalue):
2072        render.variables.append((argname, argvalue))
2073        render.end = argvalue.end
2074        return render
2075
2076    @spark.production('render ::= buildrender )')
2077    def finishrender(self, render, _0):
2078        render.end = _0.end
2079        return render
2080
2081    @spark.production('render ::= buildrender , )')
2082    def finishrender1(self, render, _0, _1):
2083        render.end = _1.end
2084        return render
2085
2086
2087###
2088### Helper functions use at template runtime
2089###
2090
2091def _oct(value):
2092    """
2093    Helper for the ``oct`` function.
2094    """
2095    if value == 0:
2096        return "0o0"
2097    elif value < 0:
2098        return "-0o" + oct(value)[2:]
2099    else:
2100        return "0o" + oct(value)[1:]
2101
2102
2103def _bin(value):
2104    """
2105    Helper for the ``bin`` function.
2106    """
2107    if value == 0:
2108        return "0b0"
2109    if value < 0:
2110        value = -value
2111        prefix = "-0b"
2112    else:
2113        prefix = "0b"
2114    v = []
2115    while value:
2116        v.append(str(value&1))
2117        value >>= 1
2118    return prefix+"".join(v)[::-1]
2119
2120
2121def _format(obj, format):
2122    """
2123    Helper for the ``format`` method.
2124    """
2125    if isinstance(obj, datetime.datetime):
2126        if "%f" in format:
2127            format = format.replace("%f", "%06d" % obj.microsecond) # FIXME: This would replace "%%f", which is wrong (wait for Python 2.6)
2128        return obj.strftime(format.encode("utf-8")) # FIXME: We shouldn't have to encode the format string (wait for Python 3.0)
2129    elif obj is None or isinstance(obj, (int, long, float, str, unicode)):
2130        from ll import stringformat
2131        return stringformat.format_builtin_type(obj, format)
2132    else:
2133        return obj.format(format) # This will raise an ``AttributeError``
2134
2135
2136def _repr(obj):
2137    """
2138    Helper for the ``repr`` function.
2139    """
2140    if isinstance(obj, unicode):
2141        return unicode(repr(obj)[1:])
2142    elif isinstance(obj, datetime.datetime):
2143        return unicode(obj.isoformat())
2144    elif isinstance(obj, list):
2145        return u"[%s]" % u", ".join(_repr(item) for item in obj)
2146    elif isinstance(obj, dict):
2147        return u"{%s}" % u", ".join(u"%s: %s" % (_repr(key), _repr(value)) for (key, value) in obj.iteritems())
2148    else:
2149        return unicode(repr(obj))
Note: See TracBrowser for help on using the browser.