Skip to content

Notes on getting rid of "NameError: name 'Object_create' is not defined"

Piotr Krzemiński edited this page Sep 27, 2021 · 8 revisions

Iteration 1

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 just ArrayList([])

Iteration 2

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

Clone this wiki locally