revising typelib library and method descriptions

This commit is contained in:
Junseo Yoo 2024-07-02 11:13:52 -07:00
parent b87e39c578
commit efa815b920

View file

@ -25,8 +25,10 @@ end
For instance, the `rawget` type function can be written as: For instance, the `rawget` type function can be written as:
```luau ```luau
type function rawget(tbl, prop) type function rawget(tbl, prop)
if (not tbl:istable()) then print("An example of how you could give a warning in type functions!")
error("First parameter of rawget is not a table!") -- fails to reduce
if not typelib.istable(tbl) or not (typelib.isstringsingleton(prop) || typelib.isbooleansingleton(prop)) then
error("The parameters of rawget type function is wrong!") -- fails to reduce
end end
return tbl:getprops()[prop:getvalue()] return tbl:getprops()[prop:getvalue()]
@ -74,7 +76,7 @@ To allow Luau developers to modify the runtime values of types in type functions
Methods under a different type heading (ex: `Singleton`) imply that the methods are only available for those types. At the implementation level, there is a check to make sure that the type-specific methods are being called on the correct types. For instance, `getindexer()` asserts that `istable()` is true. Methods under a different type heading (ex: `Singleton`) imply that the methods are only available for those types. At the implementation level, there is a check to make sure that the type-specific methods are being called on the correct types. For instance, `getindexer()` asserts that `istable()` is true.
#### typelib #### typelib
All attributes of newly created typelib are initialized with empty tables / arrays and `typelib:getnil()`. For instance, `typelib:newtable()` initializes its properties with an empty table and index / index result type as `typelib:getnil()`. All attributes of newly created typelib are initialized with empty tables / arrays and `typelib.getnil()`. For instance, `typelib.newtable()` initializes its properties with an empty table and index / index result type as `typelib.getnil()`.
| Function Declaration | Return Type | Description | | Function Declaration | Return Type | Description |
| ------------- | ------------- | ------------- | | ------------- | ------------- | ------------- |
@ -93,22 +95,26 @@ All attributes of newly created typelib are initialized with empty tables / arra
| `newtable()` | `typelib` | returns a mutable runtime representation of a `table` type | | `newtable()` | `typelib` | returns a mutable runtime representation of a `table` type |
| `newmetatable()` | `typelib` | returns a mutable runtime representation of `Metatable` | | `newmetatable()` | `typelib` | returns a mutable runtime representation of `Metatable` |
| `newfunction()` | `typelib` | returns a mutable runtime representation of a `function` type | | `newfunction()` | `typelib` | returns a mutable runtime representation of a `function` type |
| `isnil()` | `boolean` | returns true if self is a runtime representation of the built-in type `nil` | | `isnil(arg: typelib)` | `boolean` | returns true if the argument is syntactically a runtime representation of the built-in type `nil` |
| `isunknown()` | `boolean` | returns true if self is a runtime representation of the built-in type `unknown` | | `isunknown(arg: typelib)` | `boolean` | returns true if the argument is syntactically a runtime representation of the built-in type `unknown` |
| `isnever()` | `boolean` | returns true if self is a runtime representation of the built-in type `never` | | `isnever(arg: typelib)` | `boolean` | returns true if the argument is syntactically a runtime representation of the built-in type `never` |
| `isany()` | `boolean` | returns true if self is a runtime representation of the built-in type `any` | | `isany(arg: typelib)` | `boolean` | returns true if the argument is syntactically a runtime representation of the built-in type `any` |
| `isnegation()` | `boolean` | returns true if self is a runtime representation of a `Negation` | | `isnegation(arg: typelib)` | `boolean` | returns true if the argument is syntactically a runtime representation of a `Negation` |
| `isboolean()` | `boolean` | returns true if self is a runtime representation of the built-in type`boolean` | | `isboolean(arg: typelib)` | `boolean` | returns true if the argument is syntactically a runtime representation of the built-in type`boolean` |
| `isnumber()` | `boolean` | returns true if self is a runtime representation of the built-in type `number` | | `isnumber(arg: typelib)` | `boolean` | returns true if the argument is syntactically a runtime representation of the built-in type `number` |
| `isstring()` | `boolean` | returns true if self is a runtime representation of the built-in type `string` | | `isstring(arg: typelib)` | `boolean` | returns true if the argument is syntactically a runtime representation of the built-in type `string` |
| `isstringsingleton()` | `boolean` | returns true if self is a runtime representation of a string singleton | | `isstringsingleton(arg: typelib)` | `boolean` | returns true if the argument is syntactically a runtime representation of a string singleton |
| `isbooleansingleton()` | `boolean` | returns true if self is a runtime representation of a boolean singleton | | `isbooleansingleton(arg: typelib)` | `boolean` | returns true if the argument is syntactically a runtime representation of a boolean singleton |
| `isunion()` | `boolean` | returns true if self is a runtime representation of the union type | | `isunion(arg: typelib)` | `boolean` | returns true if the argument is syntactically a runtime representation of the union type |
| `isintersection()` | `boolean` | returns true if self is a runtime representation of the intersection type | | `isintersection(arg: typelib)` | `boolean` | returns true if the argument is syntactically a runtime representation of the intersection type |
| `istable()` | `boolean` | returns true if self is a runtime representation of a `table` type | | `istable(arg: typelib)` | `boolean` | returns true if the argument is syntactically a runtime representation of a `table` type |
| `ismetatable()` | `boolean` | returns true if self is a runtime representation of `Metatable` | | `ismetatable(arg: typelib)` | `boolean` | returns true if the argument is syntactically a runtime representation of `Metatable` |
| `isfunction()` | `boolean` | returns true if self is a runtime representation of a `function` type | | `isfunction(arg: typelib)` | `boolean` | returns true if the argument is syntactically a runtime representation of a `function` type |
| `isclass()` | `boolean` | returns true if self is a runtime representation of a `class` type | | `isclass(arg: typelib)` | `boolean` | returns true if the argument is syntactically a runtime representation of a `class` type |
#### Any
| Function Declaration | Return Type | Description |
| ------------- | ------------- | ------------- |
| `issubtypeof(arg: typelib)` | `boolean` | returns true if self is a subtype or equal to arg in the type hierarchy | | `issubtypeof(arg: typelib)` | `boolean` | returns true if self is a subtype or equal to arg in the type hierarchy |
| `conformsto(arg: typelib)` | `boolean` | returns true if self is equal to arg in the type hierarchy | | `conformsto(arg: typelib)` | `boolean` | returns true if self is equal to arg in the type hierarchy |
@ -116,25 +122,25 @@ All attributes of newly created typelib are initialized with empty tables / arra
| Function Declaration | Return Type | Description | | Function Declaration | Return Type | Description |
| ------------- | ------------- | ------------- | | ------------- | ------------- | ------------- |
| `gettype()` | `typelib` | returns the runtime representation of the type being negated | | `gettype()` | `typelib` | returns the runtime representation of the self's type being negated |
#### String #### String
| Function Declaration | Return Type | Description | | Function Declaration | Return Type | Description |
| ------------- | ------------- | ------------- | | ------------- | ------------- | ------------- |
| `getmetatable()` | `typelib` | returns the runtime representation of `Metatable` | | `getmetatable()` | `typelib` | returns the runtime representation of self's `Metatable` |
#### StringSingleton #### StringSingleton
| Function Declaration | Return Type | Description | | Function Declaration | Return Type | Description |
| ------------- | ------------- | ------------- | | ------------- | ------------- | ------------- |
| `getvalue()` | `string` | returns a string singleton | | `getvalue()` | `string` | returns self's value of a string singleton |
#### BooleanSingleton #### BooleanSingleton
| Function Declaration | Return Type | Description | | Function Declaration | Return Type | Description |
| ------------- | ------------- | ------------- | | ------------- | ------------- | ------------- |
| `getvalue()` | `boolean` | returns either `true` or `false` | | `getvalue()` | `boolean` | returns self's boolean singleton value of either `true` or `false` |
#### Table #### Table
@ -142,7 +148,7 @@ All attributes of newly created typelib are initialized with empty tables / arra
| ------------- | ------------- | ------------- | | ------------- | ------------- | ------------- |
| `addprops(key: typelib, value: typelib)` | `nil` | adds a key, value pair to self's table properties; if the same key exists already, overrides the value | | `addprops(key: typelib, value: typelib)` | `nil` | adds a key, value pair to self's table properties; if the same key exists already, overrides the value |
| `delprops(key: typelib)` | `nil` | removes the key from self's table properties along with the value associated with it; if the key doesn't exist, nothing happens | | `delprops(key: typelib)` | `nil` | removes the key from self's table properties along with the value associated with it; if the key doesn't exist, nothing happens |
| `getprops()` | `{typelib: typelib}` | returns a table of self's table properties (e.g. `{["age"] = 20}` will return `{typelib:getstringsingleton("age") = typelib:getnumber()}`) | | `getprops()` | `{typelib: typelib}` | returns a table of self's table properties (e.g. `{["age"] = 20}` will return `{typelib.getstringsingleton("age") = typelib.getnumber()}`) |
| `settableindexer(indexty: typelib, indexresultty: typelib)` | `nil` | sets self's index type to the first argument and index result type to the second | | `settableindexer(indexty: typelib, indexresultty: typelib)` | `nil` | sets self's index type to the first argument and index result type to the second |
| `getindextype()` | `typelib` | returns self's index type | | `getindextype()` | `typelib` | returns self's index type |
| `getindexresulttype()` | `typelib` | returns self's index result type | | `getindexresulttype()` | `typelib` | returns self's index result type |
@ -171,19 +177,19 @@ All attributes of newly created typelib are initialized with empty tables / arra
| Function Declaration | Return Type | Description | | Function Declaration | Return Type | Description |
| ------------- | ------------- | ------------- | | ------------- | ------------- | ------------- |
| `getoptions()` | `table` | returns an array of types that the union can represent. For instance, `string \| number` returns `{typelib:getstring(), typelib:getnumber()}` | | `getoptions()` | `table` | returns an array of types that the self's union can represent. For instance, `string \| number` returns `{typelib.getstring(), typelib.getnumber()}` |
#### Intersection #### Intersection
| Function Declaration | Return Type | Description | | Function Declaration | Return Type | Description |
| ------------- | ------------- | ------------- | | ------------- | ------------- | ------------- |
| `getparts()` | `table` | returns an array of types represented by the intersection. For instance, `string & number` returns `{typelib:getstring(), typelib:getnumber()}` | | `getparts()` | `table` | returns an array of types represented by self's intersection. For instance, `string & number` returns `{typelib.getstring(), typelib.getnumber()}` |
#### Class #### Class
| Function Declaration | Return Type | Description | | Function Declaration | Return Type | Description |
| ------------- | ------------- | ------------- | | ------------- | ------------- | ------------- |
| `getprops()` | `table` | returns the runtime representation of table of class's properties | | `getprops()` | `{typelib: typelib}` | returns the runtime representation self's properties |
| `getparent()` | `typelib \| nil` | returns the runtime representation of self's parent class if it exists, else nil | | `getparent()` | `typelib \| nil` | returns the runtime representation of self's parent class if it exists, else nil |
| `getmetatable()` | `typelib \| nil` | returns the runtime representation of self's `Metatable` if it exists, else nil | | `getmetatable()` | `typelib \| nil` | returns the runtime representation of self's `Metatable` if it exists, else nil |
| `getindextype()` | `typelib` | returns self's index type | | `getindextype()` | `typelib` | returns self's index type |
@ -210,7 +216,7 @@ The build / analysis times will also be negatively impacted by this feature as r
Currently, the runtime representation of types is a userdata called `typelib`. Another representation is to use the already-existing type in Luau `table`; instead of serializing types into `typelib`, we can serialize them into tables with predefined properties. For instance, the representation for a string singleton `"abc"` could be `{type = "stringSingleton", value = "abc"}`. So instead of writing: Currently, the runtime representation of types is a userdata called `typelib`. Another representation is to use the already-existing type in Luau `table`; instead of serializing types into `typelib`, we can serialize them into tables with predefined properties. For instance, the representation for a string singleton `"abc"` could be `{type = "stringSingleton", value = "abc"}`. So instead of writing:
```luau ```luau
type function isSingleton(t) type function isSingleton(t)
if t:isstringsingleton() then if typelib.isstringsingleton(t) then
return t return t
end end
end end
@ -224,7 +230,7 @@ type function isSingleton(t)
end end
``` ```
In some sense, this design could be considered "cleaner" than introducing an entirely new userdata, but it requires developers to have a deeper understanding of the type runtime representation. For example, under the proposed design, a new table type can be created using `typelib:newtable()`, while under the alternative design, tables must be declared with attributes: `{type = "table", props = {}, indexer = {}}`. This adds complexity to the developer experience and increases the chance of making syntax errors in their program. In some sense, this design could be considered "cleaner" than introducing an entirely new userdata, but it requires developers to have a deeper understanding of the type runtime representation. For example, under the proposed design, a new table type can be created using `typelib.newtable()`, while under the alternative design, tables must be declared with attributes: `{type = "table", props = {}, indexer = {}}`. This adds complexity to the developer experience and increases the chance of making syntax errors in their program.
### More Builtin Type Functions ### More Builtin Type Functions