aardappel / lobster

The Lobster Programming Language
http://strlen.com/lobster
2.21k stars 117 forks source link

Namespaced function fails to resolve external override #284

Open Dheu3 opened 6 months ago

Dheu3 commented 6 months ago
def foo(c:string): print(c)
def foo(c:int): foo("{c}")
foo(0)

Results in 0

def foo(c:string): print(c)
namespace n
def foo(c:int): foo("{c}")
foo(0)

Results in error

aardappel commented 6 months ago
t.lobster(3): error: `n.foo` (1st argument) requires type `int`, got `string`
  in t.lobster(4): n.foo(c:int)

I don't think there's an error here, foo("{c}") prefers to resolve to a call within its current namespace, which it should (and which most languages would do). As such, this call becomes a recursive call.

Try the same thing in e.g. C++ and you'd get a similar error. In C++, you can call ::foo as an explicit way to refer to the global namespace, which Lobster doesn't have.

Dheu3 commented 6 months ago

So, this would be the recommend way for now? I'm ok with that.

namespace m
def foo(c:string): print(c)
namespace n
def foo(c:int): m.foo("{c}")
foo(0)

The actual situation i found this in was more like

namespace m
class a:
    def foo(c:string): print(c)
namespace n
def foo(c:string):
    let z = m.a{}
    z.foo(c)
foo(0)

Which results in error: no version of functionfootakes 2 arguments.

Is there a way to resolve that function?

aardappel commented 6 months ago

Yes, that's the correct way to do it for now.

Your second example works the same, it needs name spacing to reach the other namespace. So, m.foo(z, c) or even z.m.foo(c) should both work. The call does not inherit the namespace from z. like it does in other languages because a) the . in that case is just syntactic sugar, and b) namespace resolution happens in the parser, but knowing the type of z happens in the type checker.

Agree that is not ideal.. we'd need to move it into the type checker.. I'd have to see if there's a way to do that, since currently there isn't.

Dheu3 commented 6 months ago
namespace m
class a:
    def foo(c:string): print(c)
namespace n
def foo(c:string):
    let z = m.a{}
    m.foo(z, c)
foo(0)

Fails with error: unknown field/function reference 'm.foo'

namespace m
class a:
def foo(z:a, c:string): print(c)
namespace n
def foo(c:string):
    let z = m.a{}
    m.foo(z, c)
foo(0)

Does work

aardappel commented 6 months ago

Ah, that is an additional bug, it should namespace methods similarly to standalone functions.