Why is it not possible to create a practical Perl to Python source code converter?

It would be nice if there existed a program that automatically transforms Perl code to Python code, making the resultant Python program as readable and maintainable as the original one, let alone working the same way.

The most obvious solution would just invoke perl via Python utils:

#!/usr/bin/python
os.exec("tail -n -2 "+__file__+" | perl -")
...the rest of file is the original perl program...

However, the resultant code is hardly a Python code, it's essentially a Perl code. The potential converter should convert Perl constructs and idioms to easy-to-read Python code, it should retain variable and subroutine names (i.e. the result should not look obfuscated) and should not shatter the wrokflow too much.

Such a conversion is obviously very hard. The hardness of the conversion depends on the number of Perl features and syntactical constructs, which do not have easy-to-read, unobfuscated Python equivalents. I believe that the large amount of such features renders such automatic conversion impossible practically (while theoretical possibility exists).

So, could you please name Perl idioms and syntax features that can't be expressed in Python as concise as in the original Perl code?

Edit: some people linked Python-to-Perl conventers and deduced, on this basis, that it should be easy to write Perl-to-Python as well. However, I'm sure that converting to Python is in greater demand; still this converter is not yet written--while the reverse has already been! Which only makes my confidence in impossibility of writing a good converter to Python more solid.

Answers


Just to expand on some of the other lists here, these are a few Perl constructs that are probably very clumsy in python (if possible).

  • dynamic scope (via the local keyword)
  • typeglob manipulation (multiple variables with the same name)
  • formats (they have a syntax all their own)
  • closures over mutable variables
  • pragmas
  • lvalue subroutines (mysub() = 5; type code)
  • source filters
  • context (list vs scalar, and the way that called code can inspect this with wantarray)
  • type coercion / dynamic typing
  • any program that uses string eval

The list goes on an on, and someone could try to create a mapping between all of the analogous constructs, but in the end it will be a failure for one simple reason.

Perl can not be statically parsed. The definitions in Perl code (particularly those in BEGIN blocks) change the way the compiler is going to interpret the remaining code. So for non-trivial programs, conversion from Perl => Python suffers from the halting problem.

There is no way to know exactly how all of the program will be compiled until the program has finished running, and it is theoretically possible to create a Perl program that will compile differently every time it is run. Meaning that one Perl program could map to an infinite number of Python programs, the correct of which is only know after running the original program in the perl interpreter.


Your best Perl to Python converter is probably 23 years old, just graduated university and is looking for a job.


Why Perl is not Python.

  1. Perl has statements which Python more-or-less totally lacks. While you can probably contrive matching statements, the syntax will be so utterly unlike Perl as to make it difficult to call it a "translation". You'd really have to cook up some fancy Python stuff to make it as terse as the original Perl.

  2. Perl has run-time semantics which are so unlike Python as to make translation very challenging. We'll look at just one example below.

  3. Perl has data structures which are enough different from Python that translation is hard.

  4. Perl threads don't share data by default. Only selected data elements can be shared. Python threads have more common "shared everything" data.

One example of #2 should be enough.

Perl:

do_something || die()

Where do_something is any statement of any kind.

To automagically translate this into Python you'd have to wrap every || die() statement in

try:
   python_version_of_do_something
except OrdinaryStatementFailure, e:
   die()
   sys.exit()

Where the more common formulation

Perl

do_something

Would become this using simple -- unthinking -- translation of the source

try:
   python_version_of_do_something
except OrdinaryStatementFailure, e:
   pass

And, of course,

Perl

do_this || do_that || die()

Is even more complex to translate into Python.

And

Perl

do_this && do_that || die()

really push the envelope. My Perl is rusty, so I can't recall the precise semantics of this kind of thing. But you have to totally understand the semantics to work out a Pythonic implementation.

The Python examples are not good Python. To write good Python requires "thinking", something an automatic translated can't do.

And every Perl construct would have to be "wrapped" like that in order to get the original Perl semantics into a Pythonic form.

Now, do a similar analysis for every feature of Perl.


It is not impossible, it would just take a lot of work.

By the way, there is Perthon, a Python-to-Perl translator. It just seems like nobody is willing to make one that goes the other way.

EDIT: I think I might I've found the reason why a Python to Perl translator is much easier to implement. It's because Python lets you fiddle with a script's AST. See parser module.


Perl can experimentally be built to collect additional information (for instance, comments) during compilation of perl code and even emit the results as XML. There doesn't appear to be any documentation of this outside the source, except for: http://search.cpan.org/perldoc/perl5100delta#MAD

This should be helpful in building a translator. I'd expect you to get 80% of the way there fairly easily, 95% with great difficulty, and never much better than that. There are too many things that don't map well.


Fundamentally, these are two different languages. Converting from one to another and have the result be mostly readable would mean that the software would have to be able to recognize and generate code idioms, and be able to do some static analysis.

The meaning of a program may be exactly defined by the language definition, but the programmer did not necessarily require all the details. A C programmer testing if the value a printf() returned is negative is checking for an error condition, and doesn't typically care about the exact value. if (printf("%s","...") < 0) exit(); can be translated into Perl as print "..." or die();. These statements may not mean exactly the same thing, but they'll typically be what the programmer means, and to create idiomatic C or Perl code from idiomatic Perl or C code the translator must take this into account.

Since different computer languages tend to have different slightly semantics for similar things, it's typically impossible to translate one language into another and come up with the exact same meaning in readable form. To create readable code, the translator needs to understand what the programmer was intending to do, and that's real difficult.

In addition, it would be easier to translate from Python to Perl rather than Perl to Python. Python is intended as a straightforward language with clear standard ways to do things, while Perl is an unduly complex language with the motto "There's More Than One Way To Do It." Translating a Python expression into one of the innumerable corresponding Perl expressions is easier than figuring out what the Perl programmer meant and expressing it in Python.


  • Python scope and namespace are different from Perl.

  • In Python, everything is an object. In Perl, everything under the hood seems to be a list/hash/scalar/reference/function. This induces different design approaches and idioms.

  • Perl has anonymous code blocks and can generate closures on the fly with some branches. I am pretty sure that is not a python feature.

I do think that a very smart chap could statically analyze the bulk of Perl and produce a program that takes small Perl programs and output Python programs that do the same job.

I am much more doubtful about the feasibility of large and/or gnarly Perl translation. Some of us write some really funky code at times.... :)


This is impossible just because you can't even properly parse perl code. See Perl Cannot Be Parsed: A Formal Proof for more details.


The B set of modules by Malcolm Beattie would be the only sane starting point for something like this, though I'm with other answers in that this would be a difficult problem to solve. In general, translating the sense of one high-level language into another high-level language requires a high-level translator, and, for the time being, that can mean only a human.

The difficulty of this problem, for any pair of languages, is due to fundamental differences in the nature of the languages in question, such as runtime semantics and common idioms, not to mention libraries.


The reason it is close to impossible to create a generic translator from one high-level language to another, is that the program only describe HOW and not WHY (this is the reason for comments in the source code).

In order to create a meaningful program in another highlevel language you (or the translator program) needs to know WHY to be able to create the best possible program. If you cannot do that, all you can do is essentially to create a Python interpreter for the compiled version of the Perl program.

In other words, to do this properly you need to go outside the box, and this is very hard for a computer.


NullUserException basically summed it up - it certainly can be done; it would just be an enormous amount of effort to do so. Some language conversion utilities I've seen compile to an intermediate language (such as .NET's CIL) and then decompile that to the desired language. I have not seen any for Perl to Python. You can, however, find a Python to Perl converter here, though that's likely of little use to you unless you're trying to create your own, in which case it may provide some helpful reference.

Edit: if you just need the exact functionality in a Python script, PyPerl may be of some use to you.


Need Your Help

How to set font size of SKLabelNode to fit in fixed size (Swift)

swift sprite-kit sklabelnode

I have a square (200X200) with a SKLabelNode in it. The label shows score and it my be reach a large number. I want fit the number in the square.

Observable which does not pass anything in onNext()

java rx-java

I would need an Observable, for example to provide a system clock, which does not need to pass anything in onNext(). I couldn't find a signature that would allow me to do that.