munificent / craftinginterpreters

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

LexInstance and LexClass should be abstracted the same way LexFunction is abtracted by Callable #94

Closed forax closed 7 years ago

forax commented 7 years ago

Inside the interpreter, all instanceof checks should be done on interfaces.

I would like to implement a compiler from lox to bytecode and to write this compiler in lox itself. For bootstrapping i need to be able to see Java objects as lox objects, but this is not possible because a LoxClass is defined as containing LoxFunction that directly reference the AST.

A good way to see the issue is to ask yourself how to add a field on a String instance, or a function.

forax commented 7 years ago

So after several fun hours, it's technically possible to create a lox to java bridge (step on for bootstraping) without abstracting LoxClass and LoxInstance. see https://github.com/forax/craftinginterpreters/commit/e0a34eeaa2e6e00ea7acf699925e79db8f522a12

munificent commented 7 years ago

Yeah, if Lox were a more full-featured, normal language, I wouldn't make numbers, Booleans, and strings primitives. That way they could have methods defined on them.

However, that makes it a lot harder to incrementally build up the interpreter a concept at a time. The interpreter couldn't even execute 1 + 2 without first introducing classes, instances, method dispatch, etc.

So, in order to get readers to the point where they have something up and running quickly, the language is stratified in some ways and not as holistic as it could be.

virusdaemon commented 4 years ago

@forax: your IndyLox is very clever. I'd like to bend your approach into a "lazy" way of adding Java functionality to Lox without having to add lots of native functions (especially with String functions, exactly as per your substring example! But I've run into trouble compiling, in a way that suggests you've modified other Lox sources?
For example, on your line 151, you call a (non-existent?) Resolver constructor - i.e. without an argument. (I could easily add in the obvious argument, INTERPRETER, but the trouble is I assume your code was running and so I have no idea of how I should interpret it?)

On the following line, I get "error: incompatible types: void cannot be converted to Map<Expr,Integer>". (I mention this just in case it's unrelated, not sure yet)

On line 74, I get <anonymous jlox.IndyLox$2> is not abstract and does not override abstract method call() in Callable... (with the inevitable knock-on error at line 80 "incompatible types: void cannot be converted to Map<Expr,Integer>")

I'm not asking you to debug my stuff! Just wondering if you have any thoughts, given it's originally your code and I assume it ran ok for you? (I'm using Netbeans 8.2 patch 2 and Java 1.8.0_131, if that helps...)

forax commented 4 years ago

Hi, I remember hacking lox for fun just to escape the reality (some personal stuff being too heavy at the time) so sorry but i'm not sure the last version has even compiled :(