Skip to content

Class inheritance demonstration

dours edited this page Sep 12, 2022 · 2 revisions

Example 1

Consider this python code

  def myC():
      class c:
          value = 11
          def getValue(self): return self.value
      class d(c): pass
      o = d()
      return o.getValue() == 11

Each class is translated to a function, which returns a new object of the class when called. That is, a constructor for the class. This is done because it is not easy to statically distinguish a function call from a class creation operator in python: they look very similar. Now consider the result of generation of the class d to EO.

[]
  newUID.apply 0 > x__id__
  [] > apply
    [stackUp] > @
      cage result > pResult
      cage 0 > tmp
      [] > result
        goto (((xc).apply).@) > base
        xd > x__class__
        seq > initFields
          base.result.x__class__.x__id__
        base.result > @
      seq (result.initFields) (pResult.write result) (stackUp.forward (return pResult)) > @

First, there is a "standard" header of a function. A function is an object with method apply, which accepts parameters of the function (no parameters in this case). apply contains an inner function, which is used to be called with goto.

[]
  newUID.apply 0 > x__id__
  [] > apply
    [stackUp] > @

Then, the actual construction code. It creates a class object called result, initializes and returns it.

      cage result > pResult
      cage 0 > tmp
      [] > result

Here a constructor of an object of class c is called.

        goto (((xc).apply).@) > base
        xd > x__class__
        seq > initFields
          base.result.x__class__.x__id__

Here we actually delegate to the base object. We need to take field result of base because a constructor uses the wrapper object called return to return its result.

        base.result > @
      seq (result.initFields) (pResult.write result) (stackUp.forward (return pResult)) > @

Example 2 (section 1.4 of the "reducing programs to objects" paper)

Consider this python code:

class Book:
  i = ""
  def __init__(self, i1):
      self.i = i1
      print("New book!")
  def path(self):
      return ("/tmp/" + i + ".txt")
  def move(self, i1): self.i = i1

Here is the EO implementation of this example from the paper:

[] > book
  [i] > new
    cage > id
    seq > @
      id.write i
      []
        [] > path
          sprintf > @
            "/tmp/%s.txt"
            id
        [i] > move
          id.write i > @

Let's now see the generated EO code. Some details of the code are already explained in the section "Example 1". Below I'll try to point out the similarities between the hand coded EO and our generated EO.

write.
  xBook
  []
    newUID.ap 0 > x__id__
    [x] > eq
      x__id__.eq (x.x__id__) > @
# below is a function that returns an object of class Book. 
# same as function "new" in the handcoded example
    [xi1] > ap
      [stackUp] > @
        cage result > pResult
        cage 0 > tmp
# "result" is analogous the anonymous object that "new" returns in the hand-written example
        [] > result
# here is the variable "i" from the python code
          cage 0 > xi
# these variables will store the methods of the class later
          cage 0 > x__init__
          cage 0 > xpath
          cage 0 > xmove
          xBook > x__class__
          seq > initFields
            xi.write (pystring "")
            write.
              x__init__
              []
                [xselfNotCopied xi1NotCopied] > ap
                  [stackUp] > @
                    cage 0 > tmp
                    cage 0 > toReturn
                    xselfNotCopied' > xself
                    xi1NotCopied' > xi1
                    cage 0 > e0
                    seq > @
                      stdout "x__init__\n"
                      xself.<
                      xi1.<
                      mkCopy (xi1) > tmp1
# here we assign "self.i" with a constructor parameter "i"
                      ((xself).xi).write (tmp1.copy)
# here we print the "New book!" message
                      stdout (sprintf "%s\n" ((pystring "New book!").as-string))
                      ((e0).<)
                      stackUp.forward (return 0)
                      123
            write.
              xpath
              []
                [xselfNotCopied] > ap
                  [stackUp] > @
                    cage 0 > tmp
                    cage 0 > toReturn
                    xselfNotCopied' > xself
                    cage 0 > lhs0
                    cage 0 > e1
                    cage 0 > e2
                    seq > @
                      stdout "xpath\n"
                      xself.<
# 3 following lines calculate "/tmp/" + i
                      (e1).write (((pystring "/tmp/").add (xi)))
                      (e1).force
                      ((e1).<)
# 2 following lines calculate "/tmp/" + i + ".txt"
                      (lhs0).write ((pystring ".txt"))
                      (lhs0).force
                      (e2).write (((e1).add (lhs0)))
                      (e2).force
                      ((e2).<)
                      toReturn.write ((e2))
# return the result here
                      stackUp.forward (return toReturn)
# these 2 lines never execute
                      stackUp.forward (return 0)
                      123
            write.
              xmove
              []
                [xselfNotCopied xi1NotCopied] > ap
                  [stackUp] > @
                    cage 0 > tmp
                    cage 0 > toReturn
                    xselfNotCopied' > xself
                    xi1NotCopied' > xi1
                    seq > @
                      stdout "xmove\n"
                      xself.<
                      xi1.<
                      mkCopy (xi1) > tmp2
# here we assign a new value of "i"
                      ((xself).xi).write (tmp2.copy)
                      stackUp.forward (return 0)
                      123
# this line executes our internal initialization of the ojbect
# then calls the constructor (method "__init__" in python)
# then returns the object
        seq (result.initFields) (pResult.write result) ((goto ((result.x__init__.ap pResult xi1).@)).result) (stackUp.forward (return pResult)) > @