dan-da/py2php

genexpr & listcomp

Closed this issue · 16 comments

Hey, any chance you can implement these? I'd do it but I don't really understand wtf python is doing in these scenarios

py2php/py2php

Lines 1500 to 1506 in e0b6a21

def _genexpr(self, node, current_klass):
buf = '/* py2php.fixme genexpr unsupported. */'
return buf
def _listcomp(self, node, current_klass):
buf = '/* py2php.fixme listcomp unsupported. */'
return buf

They come up against things like..

        fit = ((b.fitness(width, height),  b) for b in self._open_bins)
        fit = (b for b in fit if b[0] is not None)
        rectangles = [r for r in self]
        if len(rectangles) <= 1:
            return
            sides = sorted(side for rect in self._rectangles for side in rect)
            max_height = sum(max(r[0], r[1]) for r in self._rectangles)
            min_width = max(min(r[0], r[1]) for r in self._rectangles)

etc etc... trying to run against this project: https://github.com/secnot/rectpack/

thx for the suggestion. I just added support for generator expressions in c2d5713. There is a test case in tests/genexpr.py.

List comprehension expressions should be similar, I hope.

I added support for list comprehension in 72a3f8f.

There are some cases where the generated php will throw an error if a variable is referenced from outside the expression. This is because in PHP these are implemented as anonymous generator functions. That's tricky to deal with and I don't have a good solution in mind yet. Examples of this type of failing usage are presented but commented out in the testcase files.

may revisit later. closing this.

ha! I figured out an easy way to fix variable scoping for the disabled test cases. The fix is in e08dc16.

thanks! I'll try it out right now!

I'm getting an error from it now... I don't know how to find what line in the PHP causes the problem, but here is the error output

$ ./py2php ../python/rectpack/enclose.py
<?php
Traceback (most recent call last):
  File "./py2php", line 1859, in <module>
    print translate(file_name, module_name),
  File "./py2php", line 1690, in translate
    t = Translator(module_name, mod, output)
  File "./py2php", line 102, in __init__
    buf += self._class(child)
  File "./py2php", line 708, in _class
    buf += self._method(child, current_klass, class_name)
  File "./py2php", line 795, in _method
    buf += self._function(node, True, staticmethod)
  File "./py2php", line 247, in _function
    buf += self._stmt(child, None)
  File "./py2php", line 882, in _stmt
    buf += self._assign(node, current_klass)
  File "./py2php", line 1084, in _assign
    rhs = self.expr(node.expr, current_klass)
  File "./py2php", line 1664, in expr
    return self._listcomp(node, current_klass)
  File "./py2php", line 1552, in _listcomp
    buf += self._listcompfor(node.quals[0], node.expr, node.quals, current_klass)
  File "./py2php", line 1575, in _listcompfor
    buf += self._listcompif(if_cond, current_klass)
  File "./py2php", line 1587, in _listcompif
    return "if " + self._compare(node.test, current_klass)
  File "./py2php", line 1194, in _compare
    for nodeop in node.ops:
AttributeError: Not instance has no attribute 'ops'

hmm, that's failing in the new list comprehension code. Is the python source code online? Can you post a link to it, or attach the file or the line(s) that fail?

not surprisingly, real world code has more complex cases than the tests I come up with.

Yeah here are the two files that crashed

https://github.com/secnot/rectpack/blob/master/rectpack/enclose.py
https://github.com/secnot/rectpack/blob/master/rectpack/guillotine.py

others in the same path seem to have successfully fully encoded

I just committed a fix. enclose.py works now. I haven't tried guillotine.py yet.

confirmed guillotine.py is working.

awesome! thanks so much!

bedtime here. please let me know if you are able to translate all the files successfully or have other issues. I would be curious to hear how your porting project goes in the end, as I've received very little feedback to date.

yeah I'll letcha know how it turns out, thanks!
I did miss one more "fixme"

function float2dec($ft,$decimal_digits) {
// py2php.fixme "with" unsupported.
}

in the packer.py

# Float to Decimal helper
def float2dec(ft, decimal_digits):
    """
    Convert float (or int) to Decimal (rounding up) with the
    requested number of decimal digits.

    Arguments:
        ft (float, int): Number to convert
        decimal (int): Number of digits after decimal point

    Return:
        Decimal: Number converted to decima
    """
    with decimal.localcontext() as ctx:
        ctx.rounding = decimal.ROUND_UP
        places = decimal.Decimal(10)**(-decimal_digits)
        return decimal.Decimal.from_float(float(ft)).quantize(places)

oooh man I didn't even think of all the dependency libraries that need to get converted as well... this'll be interesting... haha

haha, that's the last py2php.fixme. you've found code that certainly exercises a lot python functionality. I'll check it out tomorrow. I'm not sure how difficult 'with' would be to support/emulate, since I don't believe php has a native construct for it.

yes, deps can be a showstopper. code translation is best used for "pure" standalone projects. often one can find similar libraries in your target language and substitute instead.

hah of course it'd be the most difficult possible :) thanks!

it's using things like itertools and operator. I'm looking into them... some seem not needed