"""
        S8 - A modern Smalltalk environment running on the "invisible machine".
        Copyright (C) 2025-today Alejandro F. Reimondo <aleReimondo@smalltalking.net>
        MIT License - See license.txt file

        Version 1.0 - Stable


        For questions and bug reports join us at S8 Facebook group
        https://www.facebook.com/groups/s8smalltalk/
"""
nil = None
class StObject():
        def __init__(self,aHandle=nil):
                if (smalltalk.not_Nil(aHandle)) :
                        setattr(self,"@handle",aHandle)

        def asParameter(self):
                return getattr(self,"@handle",nil)
        def handle(self):
                return getattr(self,"@handle",nil)
        def halt(self):
                # import pdb; pdb.set_trace()
                return self
        def klass(self):
                return self.__class__
        def toString(self):
                return smalltalk.String(self.__str__())
        def __str__(self):
                if ((self) is (nil)) :
                        return "nil"
                h = getattr(self,"@handle",None)
                if (((type(h)) == (str)) or (smalltalk.is_Number(h))) :
                        return str(h)
                if ((type(h)) == (bool)) :
                        if ((h) == (True)) :
                                return "true"
                        return "false"

                return super().__str__()
        def __repr__(self):
                h = getattr(self,"@handle",None)
                if (smalltalk.is_Nil(h)) :
                        return super().__repr__()
                return "smalltalk."\
                        +smalltalk.handleOf(getattr(self.__class__,"$className","???"))\
                        +"("+repr(h)+")"


class SuperForClass(object):
        def __init__(self,type,obj=None):
                # print("SuperForClass[init] type=",type,"obj=",obj)
                self.__type__ = type
                self.__obj__ = obj
        def __get__(self,obj,type=None):
                if (((self.__obj__) is (None)) and ((obj) is not (None))) :
                        return super(self.__type__,obj)
                else:
                        return self

        def __getattr__(self,attr):
                try:
                        return getattr(super(self.__type__,self.__obj__),attr)
                except AttributeError as ex:
                        # print("[SuperForClass]missing@",attr ,"ex=",ex.args)
                        pass

                if (hasattr(smalltalk.Class,attr)) :
                        # print("[SuperForClass]found as Class@",attr)
                        theAttr = getattr(smalltalk.Class,attr)
                        # print("[SuperForClass] got ",theAttr," binding to ",self.__obj__)
                        return theAttr.__func__.__get__(self.__obj__)

                raise AttributeError("%s has no attribute %s." % (self.__type__,attr))


class StMetaType(type):
        def lookup_in_(self,selector,aClass):
                # print("[look]",selector,aClass,"meta=",getattr(self,"$meta","missing"))
                try:
                        result = getattr(self,selector)
                        # print("[look]local",selector,result)
                        if (callable(result)) :
                                return result.__func__.__get__(aClass)
                        return result
                except AttributeError as ex:
                        # print("[look]missing@",item ,"ex=",ex.args)
                        return None

        def __getattribute__(self,item):
                if ((((item[0:2]) == ("__")) or ((item[0]) == ("$"))) or ((item[0]) == ("@"))) :
                        if ((item) == ("__class__")) :
                                return smalltalk.Metaclass
                        return super().__getattribute__(item)

                # print("[meta]"+str(self)+"@"+item,"meta=",getattr(self,"$meta","missing"))
                try:
                        result = super().__getattribute__(item)
                        # print("[meta]super",item)
                        return result.__get__(self)
                except AttributeError as ex:
                        # print("[meta]@",item ,"missing ex=",ex.args)
                        result = None

                parent = "Metaclass"
                delegate = getattr(smalltalk,parent,None)
                if delegate :
                        delegate = delegate(None)
                        # print("[meta]as"+parent)
                        result = getattr(delegate,item,None)
                        if (callable(result)) :
                                result = result.__func__
                                # print("[meta]found("+parent+"@"+item+") src=",result.__method__.src())
                                # print("[meta]calling ",result.__get__(self))
                                return result.__get__(self)


                parent = "Class"
                delegate = getattr(smalltalk,parent,None)
                if delegate :
                        delegate = delegate(None)
                        # print("[meta]as"+parent)
                        result = getattr(delegate,item,None)
                        if (callable(result)) :
                                result = result.__func__
                                # print("[meta]found("+parent+"@"+item+") src=",result.__method__.src())
                                # print("[meta]calling ",result.__get__(self))
                                return result.__get__(self)


                raise AttributeError("%s has no attribute %s." % (self.__name__,item))


class StSystemDictionary():
        def __init__(self):
                setattr(self,"$nativeLanguage","py")
                self.useManager = False
                self.state_("__init__")
                # self.st = self #OBSOLETE

        def __setitem__(self,item,value):
                setattr(self,item,value)
        def superReceiver(self,implementor,receiver):
                meta = getattr(receiver,"$meta",False)
                # print("superReceiver",implementor,receiver ,"meta=",meta,"isClass=",receiver.isClass())
                if meta :
                        return super(implementor,receiver.instanceClass())
                if (self.b(receiver.isClass())) :
                        return SuperForClass(implementor,receiver)
                return super(implementor,receiver)
        def linkRoute(self,receiver,parent):
                # Boot - Extend lookup on classes
                def lookup(self,item):
                        if ((((item[0:2]) == ("__")) or ((item[0]) == ("$"))) or ((item[0]) == ("@"))) :
                                return super(receiver,self).__getattribute__(item)
                        # print("[info]"+str(self)+"@"+item)
                        try:
                                result = super(receiver,self).__getattribute__(item)
                                # print("[info]local@"+item) #,result.__method__.src())

                        except AttributeError as ex:
                                # print("[info]missing@",item)
                                result = None

                        implementor = nil
                        delegate = getattr(smalltalk,parent,None)
                        if result :
                                if ((delegate) is (self)) :
                                        # print("[info]exit ",delegate)
                                        return result.__get__(self)

                                mth = getattr(result,"__method__",nil)
                                if (smalltalk.is_Nil(mth)) :
                                        return result.__get__(self)
                                implementor = getattr(mth,"@classField",nil)
                                # print("[info]implementor=",implementor)
                                if (((implementor) is (self)) or (smalltalk.b(implementor.isClass()))) :
                                        # print("[info] instance method - IGNORED")
                                        implementor = nil

                                if ((((implementor) is (smalltalk.Object)) or ((implementor) is (smalltalk.Metaclass))) or ((implementor) is (smalltalk.Behavior))) :
                                        # print("[info] abstract implementor - IGNORED")
                                        implementor = nil


                        if ((implementor) is (nil)) :
                                # print("[info]as",parent)
                                if (smalltalk.not_Nil(delegate)) :
                                        delegate = delegate(nil)
                                        citem = getattr(delegate,item,None)
                                        if (callable(citem)) :
                                                # print("[info]@"+item+" as "+parent)
                                                # print("[info]calling",citem.__func__.__method__.src())
                                                return citem.__func__.__get__(self)



                        delegate = self.__class__
                        # print("[cls] lookup "+delegate.__name__+"@",item,"implementor=",implementor)
                        citem = delegate.lookup_in_(item,self)
                        if (callable(citem)) :
                                # print("[cls]"+delegate.__name__+"@"+item)
                                # print("[cls]calling",citem.__func__.__method__.src())
                                return citem

                        if result :
                                # print("[info]result@"+item)
                                return result.__get__(self)

                        raise AttributeError("%s has no attribute %s. "% (self.__class__.__name__,item))

                setattr(receiver,"__getattribute__",lookup)
                def removeItem(self,item):
                        # print("[info]-delitem[",item,"] on ",self)
                        if (((item[0]) == ("$")) or ((item[0]) == ("@"))) :
                                old = getattr(self,item,None)
                                if old :
                                        delattr(self,item)

                                return old

                        return super(receiver,self).__delitem__(item)

                setattr(receiver,"__delitem__",removeItem)
        def mapClassName(self,className,category,native=nil,superclass=nil):
                # Boot - Add a new class mapping to the system
                # print("mapClassName",className)
                mi = None
                if (not superclass) :
                        mi = type(className+"$info",(type,),dict())
                        self.linkRoute(mi,"Class")
                        delegate = (mi,)
                else:
                        delegate = (superclass.__class__,)

                mc = StMetaType(className+" class",delegate,{"$meta": True})
                if (self.is_Nil(superclass)) :
                        delegate = ()
                else:
                        delegate = (superclass,)

                if (self.not_Nil(native)) :
                        if ((type(native)) == (tuple)) :
                                delegate = delegate+native
                        else:
                                delegate = delegate+(native,)


                cls = mc(className,delegate,{"$meta": False})
                setattr(mc,"$className",self.stringOf(mc.__name__))
                setattr(mc,"@instanceClass",cls)
                setattr(mc,"@subclasses",nil)
                setattr(mc,"$iVarNames",[])
                setattr(mc,"$methods",dict())
                if (self.not_Nil(superclass)) :
                        setattr(mc,"$superclass",superclass.__class__)

                setattr(cls,"$className",self.stringOf(cls.__name__))
                setattr(cls,"$category",category)
                setattr(cls,"$superclass",superclass)
                setattr(cls,"@subclasses",nil)
                setattr(cls,"$methods",dict())
                setattr(cls,"$comment",nil)
                setattr(self,className,cls)
                return cls
        def available(self,*modules):
                try:
                        for module in modules :
                                self.import_(module)

                except Exception as ex:
                        print(ex)
                        return False

                return True
        def moduleAt(self,module,field):
                result = object
                try:
                        m = self.import_(module)
                        result = getattr(m.field)
                except Exception as ex:
                        print(ex)

                return result
        def state_(self,aState):
                setattr(self,"$state",aState)
        def do_onError_(self,aBlock,errorBlock):
                self.invalidMessage_("do:onError:")
        def is_Nil(self,aValue):
                return ((aValue) is (nil)) or ((aValue) is (None))
        def isNil_(self,aValue):
                return self.b_(self.is_Nil(aValue))
        def not_Nil(self,aValue):
                if (((aValue) is (nil)) or ((aValue) is (None))) :
                        return False
                return True
        def notNil_(self,aValue):
                return self.b_(self.not_Nil(aValue))
        def stringOf(self,nativeString):
                if (not ((type(nativeString)) is (str))) :
                        return self.invalidMessage_("Must be a native string")
                if (hasattr(self,"String")) :
                        return self.String(nativeString)
                return nativeString
        def b(self,aBoolean):
                if (((aBoolean) is (self.true)) or ((aBoolean) is (self.false))) :
                        return (aBoolean) is (self.true)
                return (aBoolean) is (True)
        def b_(self,aBool):
                if (((aBool) is (True)) or ((aBool) is (self.true))) :
                        return self.true
                return self.false
        def asObject_(self,aNativeObject):
                if (self.isObject(aNativeObject)) :
                        return aNativeObject
                if (not (hasattr(self,"Array"))) :
                        return aNativeObject
                h = self.handleOf(aNativeObject)
                if (self.is_Number(h)) :
                        return self.Number(h)
                if (self.is_Nil(h)) :
                        return nil
                t = type(h)
                if ((t) == (bool)) :
                        return self.b_(h)
                if ((t) == (str)) :
                        return self.String(h)
                if (isinstance(h,(list,tuple))) :
                        return self.Array(h)
                if (callable(h)) :
                        return self.BlockClosure(h)
                return aNativeObject
        def asNativeValue_(self,anObject):
                if (self.is_Nil(anObject)) :
                        return None
                if (isinstance(anObject,(self.String,self.Number,self.Boolean))) :
                        return self.handleOf(anObject)
                if (not (hasattr(self,"Array"))) :
                        return anObject
                cls = getattr(anObject,"__class__",None)
                if ((cls) is (self.Array)) :
                        return self.handleOf(anObject)
                return anObject
        def nativeCall(self,anObject,selector,*args):
                func = anObject
                if (self.not_Nil(selector)) :
                        func = getattr(anObject,self.handleOf(selector))

                if (self.isObject(anObject)) :
                        return func(*args)
                handles = []
                for arg in args :
                        handles.append(self.handleOf(arg))

                result = func(*tuple(handles))
                return self.asObject_(result)
        def blk(self,func,argumentCount=nil,info=nil):
                result = self.BlockClosure(func)
                if (not ((argumentCount) is (nil))) :
                        # self.not_Nil(argumentCount):
                        setattr(result,"@argumentCount",argumentCount)

                if (not ((info) is (nil))) :
                        # self.not_Nil(info):
                        setattr(result,"$info",info)

                return result
        def setVarNames(self,aClass,iVarNames,aValue=nil):
                hArray = self.handleOf(iVarNames)
                if (self.is_Nil(hArray)) :
                        hArray = []

                setattr(aClass,"$iVarNames",self.newArray(hArray))
                for iv in hArray :
                        key = "@"+self.handleOf(iv)
                        if (not (hasattr(aClass,key))) :
                                setattr(aClass,key,aValue)


        def setPropertyNames(self,aClass,pNames,aValue=nil):
                hArray = self.handleOf(pNames)
                if (self.is_Nil(hArray)) :
                        hArray = []

                setattr(aClass,"$propertyNames",self.newArray(hArray))
        def setClass(self,aClass,spec):
                print("OBSOLETE - setClass "+spec.className)
                self.obsolete()
        def fnInSpec(self,spec):
                print("OBSOLETE - fnInSpec " + spec.className)
                self.obsolete()
        def classes(self):
                # Boot - Returns an Array with the classes defined in the system
                result = []
                for k in dir(smalltalk) :
                        if (k[0].isupper()) :
                                cls = getattr(smalltalk,k)
                                if ((smalltalk.isObject(cls)) and (smalltalk.b(cls.isClass()))) :
                                        result.append(cls)



                return smalltalk.newArray(result)
        def computeMetaSubclassesOf_(self,aClass):
                result = self.newArray([])
                def addSubMeta(cls):
                        result.add_(cls.__class__)

                array = getattr(aClass,"@subclasses")
                if (array.size().handle() > 0) :
                        for cls in array.handle() :
                                addSubMeta(cls)


                setattr(aClass.__class__,"@subclasses",result)
        def computeSubclasses(self):
                for aClass in self.handleOf(self.classes()) :
                        result = list(aClass.__subclasses__())
                        setattr(aClass,"@subclasses",self.newArray(result))
                        self.computeMetaSubclassesOf_(aClass)

        def subclasses(self,aClass=nil):
                # Boot - Return the subclasses of aClass
                if (self.is_Nil(aClass)) :
                        return smalltalk.subclasses(smalltalk.Smalltalk)
                result = getattr(aClass,"@subclasses",nil)
                if (self.is_Nil(result)) :
                        self.computeSubclasses()

                return getattr(aClass,"@subclasses")
        def allSubclassesDo(self,aClass,aBlock):
                # Boot - Evaluates aBlock with all the subclasses of aClass
                def __blk1__(cls):
                        aBlock(cls)
                        self.allSubclassesDo(cls,aBlock)

                self.subclasses(aClass).do_(self.blk(__blk1__,1))
                return self
        def bindRoots(self,ignored=None):
                # Private - Link the system roots to ensure proper delegation chains
                self.invalidMessage_("bindRoots")
        def isArray_equalTo(self,table1,table2):
                if ((table1) is (table2)) :
                        return True

                return (self.handleOf_or_(table1,1)) == (self.handleOf_or_(table2,2))
        def is_Number(self,x):
                if ((type(x)) is (bool)) :
                        return False
                return isinstance(x,(int,float))
        def isObject_equalTo(self,receiver,anObject):
                if ((receiver) is (anObject)) :
                        return True

                if ((self.is_Nil(receiver)) or (self.is_Nil(anObject))) :
                        return (self.is_Nil(receiver)) and (self.is_Nil(anObject))
                h1 = self.handleOf(receiver)
                h2 = self.handleOf(anObject)
                if (((h1) != (nil)) or ((h2) != (nil))) :
                        if ((h1) == (h2)) :
                                if ((self.is_Number(h1)) and (self.is_Number(h2))) :
                                        return True

                                if ((type(h1)) != (type(h2))) :
                                        return False
                                return True


                if (self.responds_to(receiver,"_eq")) :
                        return (receiver._eq(anObject)) is (self.true)

                if (self.responds_to(anObject,"_eq")) :
                        return (anObject._eq(receiver)) is (self.true)

                return False
        def isObject_equalTo_(self,receiver,anObject):
                return self.b_(self.isObject_equalTo(receiver,anObject))
        def isObject_eqeq(self,receiver,anObject):
                # OBSOLETE
                if ((receiver) is (anObject)) :
                        return True

                if ((self.is_Nil(receiver)) or (self.is_Nil(anObject))) :
                        return (self.is_Nil(receiver)) and (self.is_Nil(anObject))

                return (self.handleOf(receiver)) is (self.handleOf(anObject))
        def isObject_eqeq_(self,receiver,anObject):
                # OBSOLETE
                return self.b_(self.isObject_eqeq(receiver,anObject))
        def object_comma_(self,receiver,anObject):
                h1 = self.handleOf(receiver)
                h2 = self.handleOf(anObject)
                if ((type(h1)) is (str)) :
                        if (self.is_Nil(anObject)) :
                                return self.String(h1+"")
                        if ((type(h2)) is (str)) :
                                return self.String(h1+h2)
                        if (self.isObject(anObject)) :
                                return self.String(h1+self.handleOf(self.to_String(anObject)))
                        return self.String(h1+str(h2))

                if (not (self.isObject(receiver))) :
                        return self.object_comma_(self.to_String(receiver),anObject)
                return receiver._comma(anObject)
        def basic_at_ifAbsent(self,receiver,key,aBlock):
                k = str(self.handleOf(key))
                if ((type(receiver)) == (dict)) :
                        if ((k) in (receiver)) :
                                return receiver[k]
                        return self.callBlock0_(aBlock)

                absent = StObject(nil)
                result = getattr(receiver,k,absent)
                if ((result) is (absent)) :
                        return self.callBlock0_(aBlock)
                return result
        def basic_at_ifAbsent_(self,receiver,key,aBlock):
                h = self.basic_at_ifAbsent(receiver,key,aBlock)
                return self.asObject_(h)
        def basic_at_(self,receiver,key):
                h = self.basic_at_ifAbsent(receiver,key,nil)
                return self.asObject_(h)
        def basic_at_put(self,receiver,key,value):
                k = str(self.handleOf(key))
                if ((type(receiver)) == (dict)) :
                        if ((value) is (None)) :
                                return receiver.pop(k,None)
                        receiver[k] = value
                        return value

                if ((value) is (None)) :
                        if (hasattr(receiver,k)) :
                                if (self.isObject(receiver)) :
                                        delattr(receiver,k)
                                        return value

                                setattr(receiver,k,value)

                        return value

                setattr(receiver,k,value)
                return value
        def basic_at_put_(self,receiver,key,value):
                self.basic_at_put(receiver,key,self.asNativeValue_(value))
                return value
        def callBlock0_(self,aBlock,noBlockValue=nil):
                if ((aBlock) is (nil)) :
                        return noBlockValue
                import types
                if ((type(aBlock)) == (types.FunctionType)) :
                        return aBlock()
                hBlock = aBlock.handle()
                if ((hBlock) is (nil)) :
                        print("Corrupted block",aBlock)
                        return nil

                return hBlock()
        def ifUndefined_do_(self,receiver,aBlock):
                if (self.is_Nil(receiver)) :
                        return self.callBlock0_(aBlock)
                return receiver
        def times_repeat_(self,count,aBlock):
                for i in range(count.asParameter()) :
                        aBlock(self.Number(i+1))

                return count
        def isBoolean_(self,receiver):
                return self.b_((type(self.handleOf(receiver))) is (bool))
        def boolean_and_(self,receiver,option):
                if ((receiver) is (self.false)) :
                        return receiver
                return self.callBlock0_(option)
        def boolean_or_(self,receiver,option):
                if ((receiver) is (self.true)) :
                        return receiver
                return self.callBlock0_(option)
        def booleanNot_(self,receiver):
                if ((receiver) is (self.true)) :
                        return self.false
                if ((receiver) is (self.false)) :
                        return self.true
                aHandle = self.handleOf(receiver)
                if (self.responds_to(receiver,"_8not")) :
                        return receiver._8not()
                return self.b_(not aHandle)
        def asCharacter_(self,receiver):
                if (isinstance(receiver,self.Number)) :
                        return self.String(chr(self.handleOf(receiver)))

                return receiver.asCharacter()
        def to_String(self,receiver):
                if (self.is_Nil(receiver)) :
                        return self.String("nil")
                if (isinstance(receiver,self.Boolean)) :
                        return self.String(str(receiver))
                if (self.responds_to(receiver,"toString")) :
                        return receiver.toString()
                return self.String(str(self.handleOf(receiver)))
        def printString_(self,receiver):
                if ((receiver.__class__) is (self.String)) :
                        return self.String("'"+self.handleOf(receiver)+"'")
                if (self.responds_to(receiver,"printString")) :
                        return receiver.printString()
                return self.String(repr(self.handleOf(receiver)))
        def asString_(self,receiver):
                if (self.responds_to(receiver,"asString")) :
                        return receiver.asString()
                return self.String(str(self.handleOf(receiver)))
        def mustBeNumber_(self,receiver):
                from numbers import Number
                if (isinstance(self.handleOf(receiver),Number)) :
                        return receiver
                return receiver.error_(self.String("Must be a Number"))
        def math_max_(self,receiver,aNumber):
                self.obsolete()
        def math_min_(self,receiver,aNumber):
                self.obsolete()
        def addClass(self,className,superclass,iVarNames=[],category=""):
                # Boot - Register a Class onto the system
                self.debugAddClass(className,superclass,iVarNames,category)
                aClass = getattr(self,className,nil)
                if (self.not_Nil(aClass)) :
                        parent = getattr(aClass,"$superclass",nil)
                        if (self.is_Nil(parent)) :
                                parent = nil
                        else:
                                # invalidate subclasses of parent
                                setattr(parent,"@subclasses",nil)
                                setattr(parent.__class__,"@subclasses",nil)

                        if (self.is_Nil(superclass)) :
                                superclass = nil

                        sameShape = ((superclass) == (parent)) and (self.isArray_equalTo(getattr(aClass,"$iVarNames",[]),iVarNames))
                        if ((sameShape) and ((category) == (getattr(aClass,"$category",nil)))) :
                                self.reshapeClass_(aClass)
                                return aClass

                        self.aboutToChangeClass(aClass,superclass,iVarNames,category)
                        if (not ((parent) is (superclass))) :
                                # move in hierarchy
                                # link to new parent
                                setattr(aClass,"$superclass",superclass)# do we need to move in native hierarchy?
                                aMeta = aClass.__class__
                                if ((aMeta) and (superclass)) :
                                        msuper = getattr(aMeta,"$superclass")
                                        setattr(msuper,"@subclasses",nil)
                                        setattr(aMeta,"$superclass",superclass.__class__)

                                # invalidate subclasses of superclass
                                setattr(superclass,"@subclasses",nil)
                                setattr(superclass.__class__,"@subclasses",nil)

                        setattr(aClass,"$category",(category) or (getattr(aClass,"$category","")))
                        self.setVarNames(aClass,iVarNames,nil)
                        if (not sameShape) :
                                self.classShapeChanged(aClass)

                else:
                        self.aboutToCreateClass(className,superclass,iVarNames,category)
                        self.mapClassName(className,category,nil,superclass)
                        aClass = getattr(self,className)
                        self.setVarNames(aClass,iVarNames,nil)
                        if (self.not_Nil(superclass)) :
                                # invalidate subclasses of superclass
                                setattr(superclass,"@subclasses",nil)
                                setattr(superclass.__class__,"@subclasses",nil)


                self.classChanged(aClass)
                self.reshapeClass_(aClass)
                return aClass
        def renameClass(self,aClass,aString):
                # Boot - Rename aClass to aString
                meta = aClass.__class__
                info = getattr(meta,"$info",None)
                delattr(self,getattr(aClass,"$className"))
                if info :
                        setattr(info,"$className",aString+" class")

                setattr(meta,"$className",aString)
                setattr(self,aString,aClass)
                self.classChanged(aClass)
                return self
        def removeClass(self,aClass):
                # Boot - Remove aClass from system
                deleted = self.String("Deleted-"+self.handleOf(getattr(aClass,"$className")))
                array = getattr(getattr(aClass,"$superclass",nil),"@subclasses",None)
                if array :
                        array.remove_ifAbsent_(aClass,self.BlockClosure.empty())

                meta = aClass.__class__
                info = getattr(meta,"$info",None)
                delattr(self,self.handleOf(getattr(aClass,"$className")))
                if info :
                        setattr(info,"$className",deleted+" class")

                setattr(meta,"$className",deleted)
                self.classChanged(aClass)
                return self
        def metaVarNames(self,aMetaClass,iVarNames):
                # Boot - Set the instance variables of aMetaclass
                if (self.isArray_equalTo(getattr(aMetaClass,"$iVarNames",[]),iVarNames)) :
                        return self.false
                hArray = self.handleOf(iVarNames)
                if (self.is_Nil(hArray)) :
                        hArray = []

                self.setVarNames(aMetaClass,hArray,nil)
                self.classShapeChanged(aMetaClass)
                self.classChanged(aMetaClass)
                return self.true
        def smDo(self,block):
                # Boot - Notify the system about executing aBlock
                if (getattr(self,"useManager",False)) :
                        if (hasattr(self,"SystemManager")) :
                                if (hasattr(self.SystemManager,"currentOrNil")) :
                                        sm = self.SystemManager.currentOrNil()
                                        if (self.not_Nil(sm)) :
                                                return block(sm)




        def classChanged(self,aBehavior):
                self.smDo(lambda sm : sm.classChanged_(aBehavior))
        def classShapeChanged(self,aBehavior):
                self.smDo(lambda sm : sm.classShapeChanged_(aBehavior))
        def aboutToCreateClass(self,className,superclass,iVarNames,category):
                self.smDo(lambda sm : sm.aboutToCreateClass_superclass_iVarNames_category_(className,superclass,iVarNames,category))
        def aboutToChangeClass(self,aClass,superclass,iVarNames,category):
                self.smDo(lambda sm : sm.aboutToChange_superclass_iVarNames_category_(aClass,superclass,iVarNames,category))
        def methodBoundTo(self,method,klass):
                self.smDo(lambda sm : sm.methodBound_to_(method,klass))
                return method
        def aboutToBindTo(self,method,klass):
                self.smDo(lambda sm : sm.aboutToBind_to_(method,klass))
                return method
        def aboutToRemoveFrom(self,method,klass):
                self.smDo(lambda sm : sm.aboutToRemove_from_(method,klass))
                return method
        def methodRemovedFrom(self,method,klass):
                self.smDo(lambda sm : sm.methodRemoved_from_(method,klass))
                return method
        def objectNotFound(self,object,indexOrKey,collection):
                self.smDo(lambda sm : sm.object_at_notFoundIn_(object,indexOrKey,collection))
                return collection
        def whoImplements(self,klass,jsSelector):
                return self.invalidMessage_("whoImplements")
        def superImplementor(self,klass,jsSelector):
                return self.invalidMessage_("superImplementor")
        def instVarAt(self,object,ivName,default=nil):
                key = "$"+ivName
                if (hasattr(object,key)) :
                        return getattr(object,key)
                if (hasattr(object,"@handle")) :
                        h = getattr(object,"@handle")
                        return h[key]

                return default
        def fn_Of(self,klass):
                return getattr(klass,"$fn",nil)
        def prototype_Of(self,klass):
                fn = self.fn_Of(klass)
                if (self.is_Nil(fn)) :
                        return klass
                return getattr(fn,"prototype",nil)
        def methods_Of(self,klass):
                proto = self.prototype_Of(klass)
                return getattr(proto,"$methods",nil)
        def register_method_in_(self,stSelector,aMethod,klass):
                methods = self.methods_Of(klass)
                if (self.not_Nil(methods)) :
                        key = self.handleOf(stSelector)
                        methods[key] = aMethod

        def unregister_in_(self,stSelector,klass):
                methods = self.methods_Of(klass)
                if (self.not_Nil(methods)) :
                        key = self.handleOf(stSelector)
                        methods.pop(key)

        def addMethod(self,jsSelector,method,klass,stSelector=nil):
                self.aboutToBindTo(method,klass)
                fn = self.instVarAt(method,"fn")
                # setattr(fn,"$s8-method",method) # needed? for back refs to method
                fn.__method__ = method
                setattr(klass,self.handleOf(jsSelector),fn)
                setattr(method,"@classField",klass)
                setattr(method,"$fn",fn)
                if ((self.is_Nil(stSelector)) or (not stSelector)) :
                        stSelector = jsSelector.asNativeSelector()

                self.register_method_in_(stSelector,method,klass)
                return self.methodBoundTo(method,klass)
        def bind(self,klass,stSelector,jsSelector,jsFunction,category,stSource,nativeSource=nil,stamp=nil):
                # Boot - Bind an implementation for message stSelector of klass instances
                if ((self.is_Nil(jsSelector)) or (not jsSelector)) :
                        jsSelector = stSelector.replace(":","_")

                stSelector = self.asObject_(stSelector)
                category = self.asObject_(category)
                stSource = self.asObject_(stSource)
                nativeSource = self.asObject_(nativeSource)
                if (self.is_Nil(nativeSource)) :
                        nativeSource = getattr(jsFunction,"$nativeSource",nil)

                stamp = self.asObject_(stamp)
                self.debugBind(klass,stSelector,jsSelector,jsFunction,category,stSource,nativeSource,stamp)
                generation = getattr(self,"$state",nil)
                spec = {
                        "$fn": jsFunction,
                        #"$selector": stSelector,
                        #"$category": category,
                        #"$source": stSource,
                        #"$nativeSource": nativeSource,
                        #"$stamp": stamp,
                        #"$generation": generation,
                }
                if (hasattr(self,"CompiledMethod")) :
                        method = self.CompiledMethod(spec)
                else:
                        method = spec

                setattr(method,"$selector",stSelector)
                setattr(method,"$category",category)
                setattr(method,"$source",stSource)
                setattr(method,"$nativeSource",nativeSource)
                if (self.not_Nil(stamp)) :
                        setattr(method,"$stamp",stamp)

                setattr(method,"$generation",generation)
                if (self.not_Nil(klass)) :
                        self.addMethod(jsSelector,method,klass,stSelector)

                return method
        def removeMethod(self,aClass,aMethod):
                # Boot - Remove aMethod implementation from aClass
                self.aboutToRemoveFrom(aMethod,aClass)
                stSelector = aMethod.selector()
                jsSelector = self.handleOf(stSelector.asSelector())
                self.unregister_in_(stSelector,aClass)
                delattr(aClass,jsSelector)
                return self.methodRemovedFrom(aMethod,aClass)
        def newMethod(self,currentClass,selector,fn,source,nativeSource=nil,stamp=nil):
                return self.bind(nil,selector,nil,fn,nil,source,nativeSource,stamp)
        def readJSObject(self,js):
                return self.invalidMessage_("readJSObject")
        def basen(self,n,bas,numerals="0123456789abcdefghijklmnopqrstuvwxyz"):
                b = self.handleOf(bas)
                def baseN(num):
                        return (((num) == (0)) and (numerals[0])) or (baseN(num // b).lstrip(numerals[0]) + numerals[num % b])

                if (self.handleOf(n) < 0) :
                        return self.invalidMessage_("basen - must be positive")
                return smalltalk.String(baseN(self.handleOf(n)))
        def globalsDo(self,action):
                for k in self.__dict__ :
                        if (k[0].isupper()) :
                                aValue = getattr(self,k,nil)
                                if ((callable(getattr(aValue,"isClass",nil))) and ((aValue.isClass()) is (self.false))) :
                                        action(self.String(k))



                return self
        def launchImage(self,imageName=nil):
                self.useManager = True
                if (self.not_Nil(imageName)) :
                        setattr(self,"$imageFileName",imageName)
                        load(imageName)

                self.state_("launching")
                if (callable(getattr(self,"launch",nil))) :
                        self.launch()

                self.state_("running")
                return self
        def is_kindOf_(self,anObject,aClass):
                if (not (isinstance(aClass,(type,tuple)))) :
                        return self.false
                if (isinstance(anObject,aClass)) :
                        return self.true
                return anObject.isKindOf_(aClass)
        def responds_to(self,anObject,jsSelector):
                selector = self.handleOf(jsSelector)
                if ((type(selector)) != (str)) :
                        return False
                return callable(getattr(anObject,selector,None))
        def responds_to_(self,anObject,aSelector):
                if (not ((type(aSelector)) is (self.String))) :
                        return self.false
                return self.b_(self.responds_to(anObject,aSelector.asSelector()))
        def isObject(self,anObject):
                # return isinstance(anObject,StObject)
                if (isinstance(anObject,StObject)) :
                        return True

                return self.responds_to(anObject,"yourself")
        def handleOf(self,anObject):
                return getattr(anObject,"@handle",anObject)
        def handleOf_or_(self,anObject,default):
                return getattr(anObject,"@handle",default)
        def newHash(self):
                return {}
        def newContext(self):
                return StObject(nil)
        def stObject(self):
                return StObject
        def debugBind(self,klass,stSelector,jsSelector,jsFunction,category,stSource,nativeSource=nil,stamp=nil):
                return self
        def debugAddClass(self,className,superclass,iVarNames,category):
                return self
        def toString(self):
                return self.String("smalltalk")
        def quit(self):
                raise SystemExit
        def version(self):
                import sys
                return sys.version
        def httpContents(self,fileName):
                filename = self.handleOf(fileName)
                import urllib.request
                with urllib.request.urlopen(filename) as f :
                        return self.String(f.read().decode("utf-8",errors="ignore"))

        def folderContents(self,fileName):
                import os
                filename = self.handleOf(fileName)
                result = self.newArray([])
                for each in os.listdir(filename) :
                        fullName = os.path.join(filename,each)
                        if (os.path.isdir(fullName)) :
                                result.add_(self.newArray(["folder",0,each]))
                        else:
                                fSize = os.path.getsize(fullName)
                                result.add_(self.newArray(["file",fSize,each]))


                return result
        def fileContents(self,fileName):
                filename = self.handleOf(fileName)
                if ((filename[:4].lower()) == ("http")) :
                        return self.httpContents(filename)
                import os
                if (os.path.isdir(filename)) :
                        return self.folderContents(filename)
                with open(filename,encoding="utf-8",errors="ignore") as f :
                        return self.String(f.read())

        def fileWrite(self,fileName,contents,mode):
                with open(self.handleOf(fileName),self.handleOf(mode)) as f :
                        f.write(bytes(self.handleOf(contents),encoding="utf8",errors="ignore"))

        def fileIn(self,fileName):
                sName = str(self.handleOf(fileName))
                contents = self.String(sName).fileContents()
                if (smalltalk.is_Nil(contents)) :
                        smalltalk.error_(self.String("Missing file " + sName))

                return contents.fileIn()
        def emmit(self,fileName):
                return smalltalk.emmit_(fileName)
        def fileInJS(self,fileName):
                sName = str(self.handleOf(fileName))
                contents = self.String(sName).fileContents()
                if (smalltalk.is_Nil(contents)) :
                        smalltalk.error_(self.String("Missing file " + sName))

                # was: return smalltalk.eval_(contents)
                locals = dict()
                try:
                        exec(self.handleOf(contents),globals(),locals)
                except Exception as ex:
                        print(ex)

        def exportCategory(self,aString):
                return self.exportCategory_(aString)
        def saveImage(self):
                return smalltalk.saveImage()
        def saveImageAs(self,fileName):
                return smalltalk.saveImageAs_(fileName)
        def isFileOlderThan(self,fileName,referenceFileName):
                try:
                        import os
                        if (os.path.getmtime(self.handleOf(fileName)) < os.path.getmtime(self.handleOf(referenceFileName))) :
                                return self.true

                except FileNotFoundError as ex:
                        # print(ex)
                        pass

                return self.false
        def copyTo(self,anInstance):
                source = self.__dict__
                target = anInstance.__dict__
                for k in source.keys() :
                        target[k] = source[k]

                if False :
                        # True:
                        print("smalltalk replacement with new instance notImplemented. Yet")
                        return self

                return anInstance
        def startup(self):
                self.state_("booting")
                self.state_("singularity")
                self.mapClassName("Object","Kernel",StObject)
                self.mapClassName("Smalltalk","Kernel",StSystemDictionary,self.Object)
                self.mapClassName("Behavior","Kernel",nil,self.Object)
                self.mapClassName("Class","Kernel",nil,self.Behavior)
                self.mapClassName("Metaclass","Kernel",nil,self.Behavior)
                self.mapClassName("CompiledMethod","Kernel",nil,self.Object)
                self.mapClassName("Number","Kernel",nil,self.Object)
                self.mapClassName("BlockClosure","Kernel",nil,self.Object)
                self.mapClassName("Boolean","Kernel",nil,self.Object)
                # self.mapClassName("DateTime","Kernel",Date,self.Object)
                self.mapClassName("UndefinedObject","Kernel",nil,self.Object)
                self.mapClassName("Collection","Kernel",nil,self.Object)
                self.mapClassName("SequenceableCollection","Kernel",nil,self.Collection)
                self.mapClassName("String","Kernel",nil,self.SequenceableCollection)
                self.mapClassName("Array","Kernel",nil,self.SequenceableCollection)
                # self.mapClassName("RegularExpression","Kernel",RegExp,self.Object)
                self.state_("whiteHole")
                self.linkNatives()
                self.reshapeClasses()
                self.state_("wormHole")
                self.bindCore()
                self.state_("startup")
                return self.copyTo(self.Smalltalk(nil)) ,self.UndefinedObject(nil)
        def niy(self):
                import inspect
                text = "NIY #"+inspect.stack()[1].function
                print(text)
                return text
        def niy_(self,msg):
                print("NIY #"+msg)
        def invalidMessage_(self,msg):
                raise Exception("Invalid message #"+str(self.handleOf(msg)))
        def obsolete(self):
                import inspect
                text = "OBSOLETE #"+inspect.stack()[1].function
                print(text)
                return text
        def toObjects(self,list):
                for i in range(0,len(list)) :
                        if ((list[i]) is (None)) :
                                list[i] = nil

                        if ((type(list[i])) is (str)) :
                                list[i] = self.String(list[i])

                        if (self.is_Number(list[i])) :
                                list[i] = self.Number(list[i])


        def reshape_of_(self,field,anObject):
                value = getattr(anObject,field,None)
                if ((value) is (None)) :
                        return
                if ((type(value)) is (str)) :
                        setattr(anObject,field,self.String(value))

                if ((type(value)) is (list)) :
                        self.toObjects(value)
                        setattr(anObject,field,self.newArray(value))

                if ((value.__class__) == (self.Array)) :
                        self.toObjects(self.handleOf(value))

        def reshapeClass_(self,aClass):
                self.reshape_of_("$className",aClass)
                self.reshape_of_("$category",aClass)
                self.reshape_of_("$iVarNames",aClass)

        def reshapeClasses(self):
                # mutate class shapes to my implementation
                for cls in self.__dict__.values() :
                        if ((type(type(cls))) is (StMetaType)) :
                                self.reshapeClass_(cls)
                                self.reshapeClass_(cls.__class__)


        def linkNative_to_(self,instance,aClass):
                # link native species of instance to delegate to aClass implementation
                self.obsolete()
        def arguments_toCall_(self,args,aBlock):
                # Returns arguments adapted to call aBlock
                if (smalltalk.debug()) :
                        print("arguments_toCall_ - ",args)

                count = self.handleOf(self.argumentCount_(aBlock))
                if (self.is_Nil(count)) :
                        return args
                if ((count) == (len(args))) :
                        return args
                largs = self.arrayContents(list(args)[:count])
                while (len(largs) < count) :
                        largs.append(nil)

                return tuple(largs)
        def objects_toCall_(self,anArray,aBlock):
                result = []
                for x in self.handleOf(anArray) :
                        result.append(self.asObject_(x))

                return result
        def makeCallable_(self,aClass):
                # implement callable protocoll for instances of aClass
                st = self
                def callS8Callable(self,*args,**kwargs):
                        hBlock = self.handle()
                        if (st.is_Nil(hBlock)) :
                                print("Corrupted callable",self)
                                return nil

                        return hBlock(*(st.arguments_toCall_(args,self)),**kwargs)

                setattr(aClass,"__call__",callS8Callable)
        def makeStringable_(self,aClass):
                # implement string protocoll for instances of aClass
                st = self
                def stringBlock(self,*args):
                        h = st.handleOf(self)
                        if ((type(h)) is (str)) :
                                return h
                        return super().__str__(self)

                setattr(aClass,"__str__",stringBlock)
        def linkNatives(self):
                # --bind the native linkings
                import sys
                sys.setrecursionlimit(10**6)
                import math
                self.math = math
                self.true = self.Boolean(True)
                self.false = self.Boolean(False)
                self.makeCallable_(self.BlockClosure)
                self.makeStringable_(self.String)
                setattr(self.Object.__class__,"$superclass",self.Class)
                setattr(self.Metaclass.__class__,"@instanceClass",self.Metaclass)
                if (not (hasattr(self,"OverwriteMethods"))) :
                        self.OverwriteMethods = self.true

                if (not (hasattr(self,"DumpOverwritenMethods"))) :
                        self.DumpOverwritenMethods = self.false

                return True
        def bindCore(self):
                # --bind the minimal functions (e.g i/o)
                def stringOf(param):
                        return self.String(self.handleOf(param))

                g = globals()
                def read(fileName):
                        return self.fileContents(stringOf(fileName))

                g["read"] = read
                g["fileContents"] = read
                def fileWrite(fileName,contents,mode):
                        return self.fileWrite(stringOf(fileName),stringOf(contents),stringOf(mode))

                g["fileWrite"] = fileWrite
                def fileIn(fileName):
                        return self.fileIn(stringOf(fileName))

                g["fileIn"] = fileIn
                def fileInJS(fileName):
                        return self.fileInJS(stringOf(fileName))

                g["fileInJS"] = fileInJS
                def doit(aString):
                        return stringOf(aString).doIt()

                g["doit"] = doit
                def exportCategory(aString):
                        return self.Exporter.exportCategory_(stringOf(aString))

                g["exportCategory"] = exportCategory
                def saveImage(ignored):
                        return self.saveImage()

                g["saveImage"] = saveImage
                def saveImageAs(fileName):
                        return self.saveImageAs_(stringOf(fileName))

                g["saveImageAs"] = saveImageAs
                def isFileOlderThan(fileName,referenceFileName):
                        return self.isFileOlderThan(stringOf(fileName),stringOf(referenceFileName))

                g["isFileOlderThan"] = isFileOlderThan
                if (not (hasattr(self,"$imageFileName"))) :
                        setattr(self,"$imageFileName",self.String("s8.image." + getattr(self,"$nativeLanguage")))

                return True
        def newArray(self,object):
                # return a new Array instance with contents in object
                return self.Array((object) or ([]))
        def newConstructor(self,superC):
                # return a new constructor of instances inheriting from superC (constructor)
                # superC can be nil to return a constructor for a root class
                self.invalidMessage_("newConstructor")
        def will_be_(self,anObject,className):
                # return an object that will become an instance of class (named className) when accessed
                self.invalidMessage_("will:be:")
        def become_a_(self,anObject,aClass):
                # mutate object to an instance of aClass
                self.invalidMessage_("become:a:")
        def setProtoOf_to_(self,nativeObject,proto):
                self.invalidMessage_("setProtoOf:to:")
        def klass(self,spec):
                print("OBSOLETE - klass "+spec.className)
                self.obsolete()
        def __f__(self,source,tag=nil):
                if (self.is_Nil(tag)) :
                        fName = "__f__"
                else:
                        fName = tag

                # print("def "+fName,source)
                locals = dict()
                try:
                        exec("def "+fName+source,globals(),locals)
                except Exception as ex:
                        print("def "+fName,source)
                        print(ex)

                delim = '"""'
                if (delim in source) :
                        delim = "'''"

                source = source.replace("\\","\\\\")
                nativeSource = "smalltalk.__f__("+delim+source+delim+',"'+str(tag)+'")'
                setattr(locals[fName],"$nativeSource",nativeSource)
                return locals[fName]
        def import_(self,libraryName):
                hName = self.handleOf(libraryName)
                return self.__f__("():import "+hName+"; return "+hName)()
        def from_import_(self,libraryName,aName):
                hLibName = self.handleOf(libraryName)
                hName = self.handleOf(aName)
                return self.__f__("():from "+hLibName+" import "+hName+"; return "+hName)()
        def if_nil_notNil_(self,anObject,block1,block2):
                if (self.is_Nil(anObject)) :
                        return self.callBlock0_(block1)
                return self.callBlock0_(block2)
        def if_true_false_(self,aBoolean,blk1,blk2):
                if (self.b(aBoolean)) :
                        if (self.not_Nil(blk1)) :
                                return self.callBlock0_(blk1)

                else:
                        if (self.not_Nil(blk2)) :
                                return self.callBlock0_(blk2)


                return nil
        def while_do_(self,condition,aBlock):
                while ((condition()) is (self.true)) :
                        self.callBlock0_(aBlock)

                return nil
        def whileNot_do_(self,condition,aBlock):
                while ((condition()) is (self.false)) :
                        self.callBlock0_(aBlock)

                return nil
        def raise_result_(self,_s8Ret_,result):
                _s8Ret_.result = result
                raise Exception(_s8Ret_)
                return result
        def exceptionResult_(self,__ex):
                _s8Ret_ = __ex.args[0]
                return _s8Ret_.result
        def exception_at(self,__ex,target):
                if (self.is_Nil(__ex)) :
                        return False
                if (not (hasattr(__ex,"args"))) :
                        return False
                arg = __ex.args[0]
                return (arg) == (target)
        def value_withTimeout_(self,aBlock,aNumber):
                from threading import Timer
                t = Timer(aNumber.asParameter(),aBlock.asParameter())
                t.start()
                return t
        def value_withInterval_(self,aBlock,aNumber):
                return self.invalidMessage_("value_withInterval_")
        def argumentCount_(self,aCallable):
                if (smalltalk.debug()) :
                        print("@argumentCount - ",getattr(aCallable,"@argumentCount",nil))

                count = getattr(aCallable,"@argumentCount",nil)
                if ((count) is (nil)) :
                        try:
                                from inspect import signature
                                f = self.handleOf(aCallable)
                                count = len(signature(f).parameters)
                        except Exception as ex:
                                return nil


                return self.Number(count)
        def pool_at_put_(self,pool,aKey,aValue):
                h = getattr(pool,"@hash")
                k = str(self.handleOf(aKey))
                v = pool.wrap_(aValue)
                if ((type(h)) == (dict)) :
                        h[k] = v
                else:
                        setattr(h,k,v)

                return aValue
        def pool_removeKey_(self,pool,aKey):
                h = getattr(pool,"@hash")
                k = str(self.handleOf(aKey))
                if ((type(h)) == (dict)) :
                        h.pop(k,nil)
                else:
                        delattr(h,k)

        def pool_at_ifAbsent_(self,pool,aKey,aBlock):
                h = getattr(pool,"@hash")
                k = str(self.handleOf(aKey))
                if ((type(h)) == (dict)) :
                        if ((k) in (h)) :
                                return self.asObject_(h[k])

                else:
                        if (hasattr(h,k)) :
                                return self.asObject_(getattr(h,k))


                # print("pool key=",k,"missing") # in ",h)
                if (self.is_Nil(aBlock)) :
                        return nil
                # info = getattr(aBlock,"$info","no-info")
                if (callable(aBlock)) :
                        return self.callBlock0_(aBlock)
                return aBlock.evaluate()
        def pool_includesKey_(self,pool,aKey):
                h = getattr(pool,"@hash")
                k = str(self.handleOf(aKey))
                if ((type(h)) == (dict)) :
                        if ((k) in (h)) :
                                return self.true

                else:
                        if (hasattr(h,k)) :
                                return self.true


                return self.false
        def pool_keys(self,pool):
                h = getattr(pool,"@hash")
                if ((type(h)) == (dict)) :
                        return self.newArray(list(h.keys()))
                if ((type(h)) == (list)) :
                        return self.newArray(h)
                h = h.__dict__.keys()
                return self.newArray(list(h))
        def arrayHasNativeContents(self,anArray):
                for each in self.handleOf(anArray) :
                        if (self.isObject(each)) :
                                return False
                        else:
                                return True


                return False
        def arrayContents(self,anArray):
                result = []
                for each in list(self.handleOf(anArray)) :
                        result.append(self.asObject_(each))

                return result
        def arrayHandles(self,anArray):
                result = []
                for each in list(self.handleOf(anArray)) :
                        result.append(self.handleOf(each))

                return result
        def array_at_(self,anArray,anIndex):
                array = self.handleOf(anArray)
                offset = self.handleOf(anIndex) - 1
                if ((offset < 0) or (len(array) <= offset)) :
                        return anArray.objectNotFoundAt_(anIndex)
                return self.asObject_(array[offset])
        def array_at_ifAbsent_(self,anArray,anIndex,aBlock):
                array = self.handleOf(anArray)
                offset = self.handleOf(anIndex) - 1
                if ((offset < 0) or (len(array) <= offset)) :
                        return self.callBlock0_(aBlock)
                return self.asObject_(array[offset])
        def array_at_put_(self,anArray,anIndex,anObject):
                array = self.handleOf(anArray)
                offset = self.handleOf(anIndex) - 1
                if ((offset < 0) or (len(array) < offset)) :
                        return anArray.invalidIndex_(anIndex)
                if ((len(array)) == (offset)) :
                        return anArray.add_(anObject)
                array[offset] = self.asNativeValue_(anObject)
                return anObject
        def array_join_(self,anArray,aString):
                glue = self.handleOf(self.to_String(aString))
                def eachString(each):
                        return self.handleOf(self.to_String(self.asObject_(each)))

                parts = anArray.collect_(self.blk(eachString,1))
                return self.String(glue.join(self.handleOf(parts)))
                # return self.String(glue.join(self.handleOf(anArray)))

        def array_copyWithAll_(self,receiver,anArray):
                result = receiver.shallowCopy()
                result.addAll_(anArray)
                return result
        def array_sort_(self,anArray,aBlock):
                def merge(left, right):
                        if len(left) == 0:
                                return right
                        if len(right) == 0:
                                return left
                        result = []
                        index_left = index_right = 0
                        while len(result) < len(left) + len(right):
                                #if left[index_left] <= right[index_right]:
                                if self.b(aBlock.value_value_(anArray.unwrap_(left[index_left]),anArray.unwrap_(right[index_right]))):
                                        result.append(left[index_left])
                                        index_left += 1
                                else:
                                        result.append(right[index_right])
                                        index_right += 1
                                if index_right == len(right):
                                        result += left[index_left:]
                                        break
                                if index_left == len(left):
                                        result += right[index_right:]
                                        break
                        return result
                def insertion_sort(array, left=0, right=None):
                        if right is None:
                                right = len(array) - 1
                        for i in range(left + 1, right + 1):
                                key_item = array[i]
                                j = i - 1
                                #while j >= left and key_item < array[j]:
                                while j >= left and self.b(aBlock.value_value_(anArray.unwrap_(key_item),anArray.unwrap_(array[j]))):
                                        array[j + 1] = array[j]
                                        j -= 1
                                array[j + 1] = key_item
                        return array
                def timsort(array):
                        min_run = 32
                        n = len(array)
                        for i in range(0, n, min_run):
                                insertion_sort(array, i, min((i + min_run - 1), n - 1))
                        size = min_run
                        while size < n:
                                for start in range(0, n, size * 2):
                                        midpoint = start + size - 1
                                        end = min((start + size * 2 - 1), (n-1))
                                        merged_array = merge(
                                                left=array[start:midpoint + 1],
                                                right=array[midpoint + 1:end + 1])
                                        array[start:start + len(merged_array)] = merged_array
                                size *= 2
                        return array
                if self.is_Nil(aBlock):
                        # def defaultBlock(a,b): return a._lt(b)
                        # aBlock = self.blk(defaultBlock,2)
                        aBlock = self.BlockClosure.defaultSortBlock()
                timsort(self.handleOf(anArray))
                return anArray
        def array_remove_ifAbsent_(self,receiver,anObject,aBlock):
                try:
                        self.handleOf(receiver).remove(self.asNativeValue_(anObject))
                except ValueError as ex:
                        return self.callBlock0_(aBlock)

                return anObject
        def array_atAllPut_(self,receiver,anObject):
                array = self.handleOf(receiver)
                o = self.asNativeValue_(anObject)
                for i in range(len(array)) :
                        array[i] = o

        def hashedSet_privateAdd_(self,aSet,cookie):
                k = str(smalltalk.handleOf(cookie))
                getattr(aSet,"@hash")[k] = cookie
        def hashedSet_privateRemove_(self,aSet,cookie):
                contents = getattr(aSet,"@contents")
                def remotion(each):
                        if (smalltalk.isObject_equalTo(each,cookie)) :
                                contents.remove_(each)
                                raise Exception("done")


                k = str(smalltalk.handleOf(cookie))
                getattr(aSet,"@hash").pop(k,None)
                try:
                        contents.do_(smalltalk.blk(remotion,1))
                except Exception as ex:
                        pass

        def string_isLiteral_(self,receiver):
                s = self.handleOf(receiver)
                l = len(s)
                if ((l) == (0)) :
                        return self.false
                if (self.b(self.String.isBinarySelector_(receiver))) :
                        return self.true
                import re
                p=re.compile("[\w:]*")
                match = p.match(s)
                if ((match) and ((match.end()) == (l))) :
                        return self.true
                return self.false
        def string_match(self,receiver,aRegexp):
                s = self.handleOf(receiver)
                regexp = self.handleOf(aRegexp)
                import re
                p = re.compile(regexp)
                return p.match(s)
        def string_occurrencesOf_(self,receiver,aString):
                s = self.handleOf(aString)
                if ((type(s)) == (str)) :
                        return self.Number(self.handleOf(receiver).count(s))
                else:
                        return self.Number(0)

        def string_startsWith_(self,receiver,aString):
                s = self.handleOf(aString)
                if ((type(s)) == (str)) :
                        return self.b_(self.handleOf(receiver).startswith(s))
                else:
                        return self.false

        def string_asNumber_(self,receiver):
                s = self.handleOf(receiver)
                if ((".") in (s)) :
                        return self.Number(float(s))
                else:
                        return self.Number(int(s))

        def string_asPrivateSelector_(self,receiver):
                s = self.handleOf(receiver)\
                        .replace(":","_").replace("+","_plus")\
                        .replace("-","_minus").replace("*","_star")\
                        .replace("/","_slash").replace("|","_bar")\
                        .replace("&","_amp").replace(">","_gt")\
                        .replace("<","_lt").replace("=","_eq")\
                        .replace(",","_comma").replace("@","_at")\
                        .replace("~","_no").replace("\\","_bk")
                return self.String(s)
        def outerFramesCount(self):
                # DEBUG
                from inspect import getouterframes, currentframe
                return len(getouterframes(currentframe()))
        def asPoolDictionary(self):
                # DEBUG
                result = self.PoolDictionary.new()
                for k in dir(self) :
                        result.at_put_(k,getattr(self,k))

                return result
        def debug_(self,aBoolean):
                # DEBUG
                setattr(self,"DEBUG",aBoolean)
        def startDebug(self):
                # DEBUG
                setattr(self,"DEBUG",self.true)
                print("# DEBUG started")
                # print("# outerFramesCount",self.outerFramesCount())
                # import gc
                # gc.collect()
                # print("# collection finished")
                # gc.set_debug(gc.DEBUG_LEAK)

        def debug(self):
                # DEBUG
                dbg = (getattr(self,"DEBUG",nil)) is (self.true)
                # if dbg: print("# outerFramesCount",self.outerFramesCount())
                return dbg
        def testAll(self):
                # TESTING - Run all tests
                return self.true.testAll()
        def test(self,what):
                # TESTING - Returns the result of running test (or nil)
                f = getattr(smalltalk.true,"test"+str(what),nil)
                if (self.is_Nil(f)) :
                        return nil
                # print("test",what)
                if ((f()) is (smalltalk.true)) :
                        return True

                # print("FAILED test",what)
                print("FAILED",f.__method__.src())
        def testFrom(self,first,last=1000):
                # TESTING - Run from first test
                for i in range(first,last) :
                        try:
                                self.test(i)
                        except Exception as ex:
                                print("test"+str(i),ex.args)


        def t(self,number):
                # TESTING - print the native sources of test method
                test = "test"+str(number)
                print(getattr(self.true,test).__method__.src())


smalltalk = StSystemDictionary()
smalltalk, nil = smalltalk.startup()
