Ian Davis
Ian Davis

Reputation: 21

translating bash pre/post increment/decrement to python

I am attempting to improve a Bash to Python translator.

Bash allows ++ and -- while Python does not. Many people have suggested that ++x can be rewritten as x += 1. But this ignores the requirement that one be able to recover the resulting value of x before or after incrementing / decrementing as part of a potentially complex bash expression eg:

x=$(( ++y + z--)).

I can find no way of converting the above to a python expression, because it appears python does not allow side effects such as assignment within an expression. A fall back would be to write a pre/post function that took a variable or string as input, and altered its external item so passed to the function. But I can't work out how to have a function alter its input parameter variables.

If I knew that the item being operated on was always an atomic value, I might be able to alter it by mapping its string name to the dictionary to recover this value and so modify it. But ++ has to work with anything bash might throw at it: eg ++y[1].

Is there any way of avoiding having to take such complex bash expressions containing assignments, and break them into separate python steps that build up the overall computation performed in bash, statement by statement. This would be pretty ugly.

I just need to implement call by reference somehow in python.

Upvotes: 1

Views: 157

Answers (1)

rici
rici

Reputation: 241671

If you really want the functionality, it would be easy enough to create a Box (MutableCell) type which supported mutating operators like preincrement and postincrement. But it would also be a lot of overhead, particularly since you would have to translate ((i=j)) into i = Box(j.unbox()) (or i.reset(j.unbox()) if you knew i already existed.

Roughly speaking, it would look like this, except with a lot more checking for string vs. number, and appropriate logic in such cases.

class Box(object):
  __slots__ = ["value"]
  def __init__(self, value=None):
    self.value = value
  def unbox(self):
    return self.value
  def reset(self, value=None):
    self.value = value
    return value
  def preincrement(self,inc=1):
    self.value += inc
    return self.value
  def postincrement(self,inc=1):
    tmp = self.value
    self.value += inc
    return tmp

Then you can translate, for example, x[i++] = --z + (t += 2) * u (Yuk!) into:

x[i.postincrement()] = ( Box(z.preincrement(-1)
                       + t.preincrement(2) * u.unbox())

Or you could use x[i.postincrement()].reset( ... ) if you had previously created x as a defaultdict(Box).

But it's really hard to believe that it is worth the overhead.

Upvotes: 1

Related Questions