eclipse-archived / ceylon

The Ceylon compiler, language module, and command line tools
http://ceylon-lang.org
Apache License 2.0
398 stars 62 forks source link

Code compiles but causes JS Runtime error. #7428

Open yannis218 opened 6 years ago

yannis218 commented 6 years ago

I am experimenting with Ceylon and have produced some code that compiles OK but produces a runtime error. I am using Ceylon 1.3.3, Eclipse (Oxygen.3a). I am compiling into Javascript, which I am running in Waterfox 56.2.3 (64-bit) via an HTML file that does:

require(['test/1.0.0/test-1.0.0' ], function(app) { app.run(); });

The code (trimmed down and abbreviated) is:

object obj1 {
    shared class Item { shared new make() {} }
    shared Item make() { return (if (true) then Item.make else Item.make)(); }
}

shared void run() { obj1.make(); }

The runtime error I get is:

TypeError: this.Item$obj1 is undefined
Stack trace:
Item$obj1$c_make@file:///home/me/eclipse-workspace/test/modules/test/1.0.0/test-1.0.0.js:35:30
$init$obj1/</obj1$.make@file:///home/me/eclipse-workspace/test/modules/test/1.0.0/test-1.0.0.js:23:9
run@file:///home/me/eclipse-workspace/test/modules/test/1.0.0/test-1.0.0.js:73:1
@file:///home/me/eclipse-workspace/test/test.html:23:56
...

The error does not occur if I change the code to:

object obj1 {
    shared class Item { shared new make() {} }
    shared Item make() { return (if (true) then obj1.Item.make else obj1.Item.make)(); }
} //                                            ^^^^^               ^^^^^

shared void run() { obj1.make(); }

or of course:

object obj1 {
    shared class Item { shared new make() {} }
    shared Item make() { return Item.make(); }
}

shared void run() { obj1.make(); }

Surely the code should either work or not compile.

gavinking commented 6 years ago

So the difference in the compiled code is:

var obj1$ = this;
return (true ? obj1$.Item$obj1$c_make : obj1$.Item$obj1$c_make)();  //bad

Vs:

var obj1$ = this;
return (true ? ($4 = ($5 = obj1()), m$1.f3$($4, $4.Item$obj1$c_make)) : 
               ($6 = ($7 = obj1()), m$1.f3$($6, $6.Item$obj1$c_make)))();  //OK

So it appears to be some sort of scoping problem where this doesn't refer to quite the right thing.

gavinking commented 6 years ago

Note that the bug only affects expressions like Item.make. It does not occur forthis.Item.make.

gavinking commented 6 years ago

I guess it's because there is no new anywhere, so this is pointing to the wrong thing.

gavinking commented 6 years ago

The problem is in FunctionHelper.generateCallable(), I'm just trying to coax it into generating the right code.

gavinking commented 6 years ago

I've fixed this, I believe, but still need to add a test.