munificent / craftinginterpreters

Repository for the book "Crafting Interpreters"
http://www.craftinginterpreters.com/
Other
8.75k stars 1.03k forks source link

Better way to resolve 'this' instead of storing it in a new environment? #1009

Open HallofFamer opened 2 years ago

HallofFamer commented 2 years ago

It seems that the way jLox stores 'this' is very inefficient, to get the value of 'this' is slow and especially a problem when writing native methods. I am thinking though, is there a better way to do this? How about we pass the 'this' as an implicit argument? I think even smalltalk does it this way, so this should be feasible for Lox too.

However, it seems quite complicated to achieve this. In the method visitCallExpr(Expr.Call expr), I dont see how to acquire the receiver object information. Maybe I need to change something in the Parser, so the Expr.Call will store the receiver information too? Or maybe store the last evaluated object before the call expression as a property on Interpreter itself?

HallofFamer commented 2 years ago

Hmm I think the difficulty of doing this with Lox is that, Lox does not distinguish between method and function calls, they are all just 'callables'. So a.b() is effectively (a.b)(), which evaluates to an intermediate callable object a.b = c, then evaluates c(). For this reason, backtracking the receiver object a is quite challenging, and may be an expensive process that will not give a better performance than the approach used in the book. I will see if I can come out with a better idea to do this.

yashrathi-git commented 2 years ago

one of the way you could do this is:

we already implemented the bind method in the book. bind method knows the value of this. you could easily modify it to implicitly pass this as the first argument like self in python.

you could store another field implicit_args in the Function instance. by default it's just an empty iterable. but when you call bind it appends the value of this to it. Now simply in your call method you could treat this implicit_args list as the positional arguments you need to pass when calling the Lox Method

I find the python way .i.e by passing self as a positional argument to all methods implicitly much cleaner