teal-language / tl

The compiler for Teal, a typed dialect of Lua
MIT License
2.16k stars 111 forks source link

Support for types and variables to have the same name #802

Open gyxos-logan opened 2 months ago

gyxos-logan commented 2 months ago

Great work on Teal! I've been using it for a few months now on a Defold project. I've got a set of annotations working with one main workaround. In Defolds case the ideal declaration would be something like:

global type hash = number
global hash: function(s: string): hash

This produces an error: cannot redeclare global with a different type: previous type of hash is type number

Doing some other tests it looks like it could be possible as global hash: function(s: string): hash on it's own produces an error unknown type hash, which suggests these are semi separate already.

I'm unsure of the internals of Teal as to how easy or hard it would be, and whether it's something that is wanted?

hishamhm commented 2 months ago

Great work on Teal! I've been using it for a few months now on a Defold project.

Thanks!! That's great to hear!

which suggests these are semi separate already

They are separate things, but they live in the same namespace. The original motivation for having them share the same namespace was mainly because record declarations work both as a new type and as a new concrete table; think OOP models where the record table serves as the "class object", or prototype-based object systems like the one you see in JavaScript, which is also a common pattern in Lua.

A simple workaround which may serve you would be to separate your names through a naming convention:

global type Hash = number
global hash: function(s: string): Hash

In my own Teal code I usually declare types as PascalCase and functions as snake_case.

gyxos-logan commented 2 months ago

Thanks for the quick response! Yes definitely could use the PascalCase style.

After I posted this I was thinking about records! And how they are both a type and a variable and why that is probably why things aren't separate. I'm sure you've considered and discussed this many times already - so just adding my ideas / two cents.

Assuming a split of types and variables into separate namespaces - but keep records existing in both. Using interfaces would mean you could redefine the built-in lua table like so:

stdlib.d.tl

global type table = {any:any}

global interface Table
   ...
end

global table: Table

or if you could inline interfaces I feel this would be quite clean:

global type table = {any:any}

global table: interface
   ...
end

This would allow you to remove any special code around how tables are both a record and a type - bivariant I think I saw it called? Not sure how enticing that idea is, and whether there is other areas that this effects.

Of course I have no idea how much work the initial step of just splitting into separate namespaces would be - I would be happy to have a look at it given some direction and whether it's interesting to the Teal project?