-
Notifications
You must be signed in to change notification settings - Fork 1
Notes on getting rid of "NameError: name 'Object_create' is not defined"
For such code:
fun box(): String {
val list = ArrayList<Int>()
return "OK"
}
Currently this is generated:
def ArrayList_init__Init_(_this):
ArrayList.__init__(self, kotlin_Array_kotlin_Any__(js('[]')))
return _this
def ArrayList_init__Create_():
return ArrayList_init__Init_(Object_create())
class ArrayList(AbstractMutableList, MutableList, RandomAccess):
def __init__(self, array):
AbstractMutableList.__init__(self)
self.array = array
self.isReadOnly = False
# other methods
def box():
list1 = ArrayList_init__Create_()
return 'OK'
and fails with
File "/home/piotr/repos/kotlin-python/python/experiments/out_ir.py", line 13373, in box
list1 = ArrayList_init__Create_()
File "/home/piotr/repos/kotlin-python/python/experiments/out_ir.py", line 8122, in ArrayList_init__Create_
return ArrayList_init__Init_(Object_create())
NameError: name 'Object_create' is not defined
This can be generated instead (works properly):
def ArrayList_init__Init_():
return ArrayList([])
def ArrayList_init__Create_():
return ArrayList_init__Init_()
# Below - unchanged
class ArrayList(AbstractMutableList, MutableList, RandomAccess):
def __init__(self, array):
AbstractMutableList.__init__(self)
self.array = array
self.isReadOnly = False
# other methods
def box():
list1 = ArrayList_init__Create_()
return 'OK'
with these steps:
- when calling, if any argument is
Object_create()
, just omit it - in function, if any argument is
_this
, omit it in its args and when returning value - in function, if
self
is not known, remove it from any calls -
kotlin_Array_kotlin_Any__(js('[]'))
should be replaced with just[]
- replace alls of
ArrayList.__init__([])
with justArrayList([])
See this lowering - it needs to be adjusted: https://github.com/krzema12/kotlin-python/blob/python-backend/compiler/ir/backend.py/src/org/jetbrains/kotlin/ir/backend/py/lower/SecondaryCtorLowering.kt
The problem boils down to translating class constructors. Let's assume such Kotlin code:
class DummyText(val text: String) {
constructor(text: String, length: Int):
this(text.substring(0, length)) {}
constructor(length: Int, repeat: Int = 1):
this("Lorem ipsum dolor sit amet".substring(0, length).repeat(repeat))
}
fun main() {
val dummyText1 = DummyText("Hello world!")
println(dummyText1.text)
val dummyText2 = DummyText("Hello world too long!", 5)
println(dummyText2.text)
val dummyText3 = DummyText(10)
println(dummyText3.text)
val dummyText4 = DummyText(10, 3)
println(dummyText4.text)
}
which produces such output:
Hello world!
Hello
Lorem ipsu
Lorem ipsuLorem ipsuLorem ipsu
The task now is to design a corresponding Python code to which this Kotlin code could be translated.
Right now the compiler produces such Python:
def DummyText_init__Init_(text, length, _this):
DummyText.__init__(self, kotlin_String(INVOKE(substring(text), 0, length)))
return _this
def DummyText_init__Create_(text, length):
return DummyText_init__Init_(text, length, Object_create())
def DummyText_init__Init__0(length, repeat, _this):
DummyText.__init__(self, repeat_0(kotlin_String(INVOKE(substring('Lorem ipsum dolor sit amet'), 0, length)), repeat))
return _this
def DummyText_init__Create__0(length, repeat):
return DummyText_init__Init__0(length, repeat, Object_create())
def DummyText_init__Init__1(length, repeat, _mask0, _marker, _this):
if not (_mask0 & 2 == 0):
repeat = 1
DummyText_init__Init__0(length, repeat, _this)
return _this
def DummyText_init__Create__1(length, repeat, _mask0, _marker):
return DummyText_init__Init__1(length, repeat, _mask0, _marker, Object_create())
class DummyText(Any):
def __init__(self, text):
self.text = text
def _get_text__0_k_(self):
return self.text
def equals(self, other):
pass
def hashCode(self):
pass
def toString(self):
pass
# ...
dummyText1 = DummyText('Hello world!')
println(dummyText1.text)
dummyText2 = DummyText_init__Create_('Hello world too long!', 5)
println(dummyText2.text)
dummyText3 = DummyText_init__Create__1(10, 0, 2, None)
println(dummyText3.text)
dummyText4 = DummyText_init__Create__0(10, 3)
println(dummyText4.text)
where this could be generated instead (don't pay attention to logic inside constructors - I just made it work for demo purposes; focus on function signatures):
def DummyText_init__Init_(text, length):
return DummyText(text[0:length])
def DummyText_init__Create_(text, length):
return DummyText_init__Init_(text, length)
def DummyText_init__Init__0(length, repeat):
return DummyText('Lorem ipsum dolor sit amet'[0:length]*repeat)
def DummyText_init__Create__0(length, repeat):
return DummyText_init__Init__0(length, repeat)
def DummyText_init__Init__1(length, repeat, _mask0, _marker):
if not (_mask0 & 2 == 0):
repeat = 1
return DummyText_init__Init__0(length, repeat)
def DummyText_init__Create__1(length, repeat, _mask0, _marker):
return DummyText_init__Init__1(length, repeat, _mask0, _marker)
class DummyText(Any):
def __init__(self, text):
self.text = text
def _get_text__0_k_(self):
return self.text
def equals(self, other):
pass
def hashCode(self):
pass
def toString(self):
pass
# ...
dummyText1 = DummyText('Hello world!')
print(dummyText1.text)
dummyText2 = DummyText_init__Create_('Hello world too long!', 5)
print(dummyText2.text)
dummyText3 = DummyText_init__Create__1(10, 0, 2, None)
print(dummyText3.text)
dummyText4 = DummyText_init__Create__0(10, 3)
print(dummyText4.text)
Working on it here: https://github.com/krzema12/kotlin-python/pull/37