-
Notifications
You must be signed in to change notification settings - Fork 5
Class inheritance demonstration
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)) > @
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)) > @