Changeset 5002:cdaa543b9417 in livinglogic.python.xist

Show
Ignore:
Timestamp:
09/28/12 16:58:03 (6 years ago)
Author:
Walter Doerwald <walter@…>
Branch:
default
Message:

Allow arbitrary nesting in for loop variable unpacking.

Files:
2 modified

Legend:

Unmodified
Added
Removed
  • src/ll/ul4c.py

    r4989 r5002  
    763763 
    764764 
     765@register("for") 
    765766class For(Block): 
    766767    """ 
    767     Base classes for the two versions of ``<?for?>`` blocks. 
    768     """ 
    769  
    770     fields = Block.fields.union({"container"}) 
    771  
    772     def __init__(self, location=None, container=None): 
     768    AST node for a ``<?for?>`` loop variable. 
     769    """ 
     770 
     771    fields = Block.fields.union({"varname", "container"}) 
     772 
     773    def __init__(self, location=None, varname=None, container=None): 
    773774        super().__init__(location) 
     775        self.varname = varname 
    774776        self.container = container 
    775777 
    776778    def ul4ondump(self, encoder): 
    777779        super().ul4ondump(encoder) 
     780        encoder.dump(self.varname) 
    778781        encoder.dump(self.container) 
    779782 
    780783    def ul4onload(self, decoder): 
    781784        super().ul4onload(decoder) 
     785        self.varname = decoder.load() 
    782786        self.container = decoder.load() 
    783787 
     
    809813        return "".join(v) 
    810814 
    811  
    812 @register("for") 
    813 class ForNormal(For): 
    814     """ 
    815     AST node for a normal ``<?for?>`` block with one loop variable. 
    816     """ 
    817  
    818     fields = For.fields.union({"varname"}) 
    819  
    820     def __init__(self, location=None, container=None, varname=None): 
    821         super().__init__(location, container) 
    822         self.varname = varname 
    823  
    824     def __repr__(self): 
    825         return "{}({!r}, {!r})".format(self.__class__.__name__, self.container, self.varname) 
    826  
    827     def format(self, indent): 
    828         return "{}for {} in {}\n{}".format(indent*"\t", self.varname, self.container.format(indent), super().format(indent)) 
     815    def format(self, indent): 
     816        def formatname(name): 
     817            if isinstance(name, str): 
     818                return name 
     819            elif len(name) == 1: 
     820                return "({},)".format(formatname(name[0])) 
     821            else: 
     822                return "({})".format(", ".join(formatname(name) for name in name)) 
     823        return "{}for {} in {}\n{}".format(indent*"\t", formatname(self.varname), self.container.format(indent), super().format(indent)) 
    829824 
    830825    def formatpython(self, indent): 
    831826        v = ["{i}# <?for?> tag at position {l.starttag}:{l.endtag} ({id})\n".format(i=indent*"\t", id=id(self), l=self.location)] 
    832         v.append("{}for vars[{!r}] in {}:\n".format(indent*"\t", self.varname, self.container.formatpython(indent))) 
     827        def formatname(name): 
     828            if isinstance(name, str): 
     829                return "vars[{!r}]".format(name) 
     830            elif len(name) == 1: 
     831                return "({},)".format(formatname(name[0])) 
     832            else: 
     833                return "({})".format(", ".join(formatname(name) for name in name)) 
     834        v.append("{}for {} in {}:\n".format(indent*"\t", formatname(self.varname), self.container.formatpython(indent))) 
    833835        indent += 1 
    834836        for node in self.content: 
    835837            v.append(node.formatpython(indent)) 
    836838        return "".join(v) 
    837  
    838     def _javavarnames(self): 
    839         return misc.javaexpr(self.varname) 
    840  
    841     def ul4ondump(self, encoder): 
    842         super().ul4ondump(encoder) 
    843         encoder.dump(self.varname) 
    844  
    845     def ul4onload(self, decoder): 
    846         super().ul4onload(decoder) 
    847         self.varname = decoder.load() 
    848  
    849  
    850 @register("foru") 
    851 class ForUnpack(For): 
    852     """ 
    853     AST node for a ``<?for?>`` block where the loop variable is unpacked into 
    854     several variables. 
    855     """ 
    856  
    857     fields = For.fields.union({"varnames"}) 
    858  
    859     def __init__(self, location=None, container=None, *varnames): 
    860         super().__init__(location, container) 
    861         self.varnames = list(varnames) 
    862  
    863     def __repr__(self): 
    864         return "{}({!r}, {})".format(self.__class__.__name__, self.container, repr(self.varnames)[1:-1]) 
    865  
    866     def format(self, indent): 
    867         return "{}for ({}) in {}\n{}".format(indent*"\t", ", ".join(self.varnames), self.container.format(indent), super().format(indent)) 
    868  
    869     def formatpython(self, indent): 
    870         v = ["{i}# <?for?> tag at position {l.starttag}:{l.endtag} ({id})\n".format(i=indent*"\t", id=id(self), l=self.location)] 
    871         v.append("{}for ({}) in {}:\n".format(indent*"\t", " ".join("vars[{!r}],".format(varname) for varname in self.varnames), self.container.formatpython(indent))) 
    872         indent += 1 
    873         for node in self.content: 
    874             v.append(node.formatpython(indent)) 
    875         return "".join(v) 
    876  
    877     def _javavarnames(self): 
    878         return "java.util.Arrays.asList({})".format(", ".join(misc.javaexpr(varname) for varname in self.varnames)) 
    879  
    880     def ul4ondump(self, encoder): 
    881         super().ul4ondump(encoder) 
    882         encoder.dump(self.varnames) 
    883  
    884     def ul4onload(self, decoder): 
    885         super().ul4onload(decoder) 
    886         self.varnames = decoder.load() 
    887839 
    888840 
     
    23692321                                raise BlockError("endif doesn't match any if") 
    23702322                        elif code == "for": 
    2371                             if not isinstance(stack[-1], (For, ForUnpack)): 
     2323                            if not isinstance(stack[-1], For): 
    23722324                                raise BlockError("endfor doesn't match any for") 
    23732325                        elif code == "def": 
     
    23872339                elif location.type == "break": 
    23882340                    for block in reversed(stack): 
    2389                         if isinstance(block, (For, ForUnpack)): 
     2341                        if isinstance(block, For): 
    23902342                            break 
    23912343                        elif isinstance(block, Template): 
     
    23942346                elif location.type == "continue": 
    23952347                    for block in reversed(stack): 
    2396                         if isinstance(block, (For, ForUnpack)): 
     2348                        if isinstance(block, For): 
    23972349                            break 
    23982350                        elif isinstance(block, Template): 
     
    29152867    start = "for" 
    29162868 
    2917     @spark.production('for ::= var in expr0') 
    2918     def for0(self, iter, _0, cont): 
    2919         return ForNormal(self.location, cont, iter.name) 
    2920  
    2921     @spark.production('for ::= ( var , ) in expr0') 
    2922     def for1(self, _0, varname, _1, _2, _3, cont): 
    2923         return ForUnpack(self.location, cont, varname.name) 
    2924  
    2925     @spark.production('buildfor ::= ( var , var') 
    2926     def buildfor(self, _0, varname1, _1, varname2): 
    2927         return ForUnpack(self.location, None, varname1.name, varname2.name) 
    2928  
    2929     @spark.production('buildfor ::= buildfor , var') 
    2930     def addfor(self, for_, _0, varname3): 
    2931         for_.varnames.append(varname3.name) 
    2932         return for_ 
    2933  
    2934     @spark.production('for ::= buildfor ) in expr0') 
    2935     def finishfor(self, for_, _0, _1, cont): 
    2936         for_.container = cont 
    2937         return for_ 
    2938  
    2939     @spark.production('for ::= buildfor , ) in expr0') 
    2940     def finishfor1(self, for_, _0, _1, _2, cont): 
    2941         for_.container = cont 
    2942         return for_ 
     2869    @spark.production('for ::= varname in expr0') 
     2870    def for_(self, varname, _0, cont): 
     2871        return For(self.location, varname, cont) 
     2872 
     2873    @spark.production('varname ::= var') 
     2874    def name(self, var): 
     2875        return var.name 
     2876 
     2877    @spark.production('varname ::= ( varname , )') 
     2878    def name1(self, _0, varname, _1, _2): 
     2879        return (varname,) 
     2880 
     2881    @spark.production('buildvarname ::= ( varname , varname') 
     2882    def buildname(self, _0, varname1, _1, varname2): 
     2883        return (varname1, varname2) 
     2884 
     2885    @spark.production('buildvarname ::= buildvarname , varname') 
     2886    def addname(self, buildvarname, _0, varname): 
     2887        return buildvarname + (varname,) 
     2888 
     2889    @spark.production('varname ::= buildvarname )') 
     2890    def finishname0(self, buildvarname, _0): 
     2891        return buildvarname 
     2892 
     2893    @spark.production('varname ::= buildvarname , )') 
     2894    def finishname1(self, buildvarname, _0, _1): 
     2895        return buildvarname 
    29432896 
    29442897 
  • test/test_ul4.py

    r4966 r5002  
    531531 
    532532@pytest.mark.ul4 
    533 def test_for_nested(r): 
     533def test_for_nested_loop(r): 
    534534    eq('[(1)(2)][(3)(4)]', r('<?for list in data?>[<?for n in list?>(<?print n?>)<?end for?>]<?end for?>', data=[[1, 2], [3, 4]])) 
    535535 
     
    540540        ("spam", "eggs", 17), 
    541541        ("gurk", "hurz", 23), 
    542         ("hinz", "kunz", 42) 
     542        ("hinz", "kunz", 42), 
    543543    ] 
    544544 
     
    546546    eq('(spam,eggs)(gurk,hurz)(hinz,kunz)', r('<?for (a, b) in data?>(<?print a?>,<?print b?>)<?end for?>', data=[item[:2] for item in data])) 
    547547    eq('(spam,eggs,17)(gurk,hurz,23)(hinz,kunz,42)', r('<?for (a, b, c) in data?>(<?print a?>,<?print b?>,<?print c?>)<?end for?>', data=data)) 
     548 
     549 
     550@pytest.mark.ul4 
     551def test_for_nested_unpacking(r): 
     552    data = [ 
     553        (("spam", "eggs"), (17,), None), 
     554        (("gurk", "hurz"), (23,), False), 
     555        (("hinz", "kunz"), (42,), True), 
     556    ] 
     557 
     558    eq('(spam,eggs,17,)(gurk,hurz,23,False)(hinz,kunz,42,True)', r('<?for ((a, b), (c,), d) in data?>(<?print a?>,<?print b?>,<?print c?>,<?print d?>)<?end for?>', data=data)) 
    548559 
    549560