Closed jpolitz closed 11 years ago
Worse, the list and tuple constructors in builtins/ rely on this behavior.
The interpreter part is easy to fix: just make init a normal method call, but since the library has to be modified to avoid the reliance on this behavior I think it could be the moment to implement the real constructor new and let init be what it really is, an initializer, in fact all the class calling logic could be moved from the interpreter to the type.call method, that's the way I've implemented it in my own project.
Something like this
class type(object):
def __call__(cls, *args):
obj = cls.__new__(cls, *args)
if type(obj) is cls:
obj.__init__(*args)
class object has default new static method and init method, like this:
class object:
def __new__(cls, *args):
return ____delta("CObject", cls, None)
def __init__(self, *args):
pass
the rest of builtin classes implement new to create builtin objects. init is rarely needed for them.
Since you are already working in the builtins if you take that part I could do the interpreter and type parts.
2013/2/26 Joe Politz notifications@github.com
Worse, the list and tuple constructors in builtins/ rely on this behavior.
— Reply to this email directly or view it on GitHubhttps://github.com/brownplt/lambda-py/issues/47#issuecomment-14134745 .
Alejandro.
Sounds great! You'll probably need to define a new macro for CObject (you can just call it object), but delta is specifically for CBuiltinPrims.. This is especially nice because it moves special-cased logic out of the interpreter and into core code, so that's awesome.
I'm working my way through changes to list() to make it similar to what I've done to tuple() at the moment; I'm going to keep pressing on through the builtins.
Note that I chose to use a special %-identifier to get tuples to work (%tuple). I'm happy to change this later, but I did the simple thing for expediency's sake, so I'm going to define %list, %dict, %set, as well.
On Tue, Feb 26, 2013 at 5:52 PM, Alejandro Martinez < notifications@github.com> wrote:
The interpreter part is easy to fix: just make init a normal method call, but since the library has to be modified to avoid the reliance on this behavior I think it could be the moment to implement the real constructor new and let init be what it really is, an initializer, in fact all the class calling logic could be moved from the interpreter to the type.call method, that's the way I've implemented it in my own project.
Something like this
class type(object): def call(cls, _args): obj = cls.new(cls, *args) if type(obj) is cls: obj.init(_args)
class object has default new static method and init method, like this:
class object: def new(cls, args): return ____delta("CObject", cls, None) def init(self, args): pass
the rest of builtin classes implement new to create builtin objects. init is rarely needed for them.
Since you are already working in the builtins if you take that part I could do the interpreter and type parts.
2013/2/26 Joe Politz notifications@github.com
Worse, the list and tuple constructors in builtins/ rely on this behavior.
— Reply to this email directly or view it on GitHub< https://github.com/brownplt/lambda-py/issues/47#issuecomment-14134745> .
Alejandro.
— Reply to this email directly or view it on GitHubhttps://github.com/brownplt/lambda-py/issues/47#issuecomment-14145197 .
The problem is not limited to init: any method can play havoc assigning to self:
class O(object):
def m(self):
self = ['why am i a list now']
o = O()
o.m()
assert(type(o) != list)
Here the self aliasing mechanism is causing this, but the background problem is mutator methods in the library depends on this behavior when using immutable representations, for example list.append, this is a birth defect in base code, the new regime just makes it crystal clear...
I've commited most of the changes needed to remove the class call special case, it needs more testing before the removal, but I've done a partial commit since it doesn't broke anything and so the code can be reviewed.
This was fixed in the new regime for addresses and VPointer's https://github.com/brownplt/lambda-py/commit/eebf668cabf57bf9dad47732055d5fd07d58346c
Test that shows the bug in https://github.com/brownplt/lambda-py/blob/scope-rewrite/tests/bugs/assign-to-self.py
Observed behavior: Inside init, assignment to self changes the object being constructed.
Expected behavior: Inside init, self is just like any other variable that happens to be bound to the object being constructed. If you assign to it, locally the self variable changes, but no objects are magically moved around.