Skip to content

Commit 7de256d

Browse files
authored
deprecated @vararg annotation and added $vararg constant extension (#33)
* deprectaed @vararg annotation and added $vararg constant extension * added DeprecatedInVersion tag to @vararg annotation Co-authored-by: Tom <tomblind@users.noreply.github.com>
1 parent 323a1ce commit 7de256d

File tree

2 files changed

+184
-103
lines changed

2 files changed

+184
-103
lines changed

docs/advanced/compiler-annotations.md

Lines changed: 150 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -306,109 +306,6 @@ declare function myFunction(n: number): [number, number];
306306

307307
Note that if any overloaded signature of a function implementation has the annotation, all array/tuple return values will unpacked in the transpiled output.
308308

309-
## @vararg
310-
311-
**Target elements:** `(declare) interface or type`
312-
313-
Indicates that an array-like type represents a Lua vararg expression (`...`) and should be transpiled to that when used in a spread expression. This is useful for forwarding varargs instead of wrapping them in a table and unpacking them.
314-
315-
**Example**
316-
317-
<SideBySide>
318-
319-
```typescript
320-
function varargWrapUnpack(...args: string[]) {
321-
console.log(...args);
322-
}
323-
```
324-
325-
```lua
326-
function varargWrapUnpack(self, ...)
327-
local args = ({...})
328-
print(unpack(args))
329-
end
330-
```
331-
332-
</SideBySide>
333-
334-
<SideBySide>
335-
336-
```typescript
337-
/** @vararg */
338-
interface Vararg<T> extends Array<T> {}
339-
340-
function varargForward(...args: Vararg<string>) {
341-
console.log(...args);
342-
}
343-
```
344-
345-
```lua
346-
function varargForward(self, ...)
347-
print(...))
348-
end
349-
```
350-
351-
</SideBySide>
352-
353-
This can be used to access the file-scope varargs as well.
354-
355-
**Example**
356-
357-
<SideBySide>
358-
359-
```typescript
360-
declare const arg: Vararg<string>;
361-
console.log(...arg);
362-
const [x, y] = [...arg];
363-
```
364-
365-
```lua
366-
print(...)
367-
local x, y = ...
368-
```
369-
370-
</SideBySide>
371-
372-
To also support tuple-typed rest parameters, you can define the type like this:
373-
374-
**Example**
375-
376-
```typescript
377-
/** @vararg */
378-
type Vararg<T extends unknown[]> = T & { __luaVararg?: never };
379-
380-
function varargForward(...args: Vararg<[string, number]>) {}
381-
```
382-
383-
**_Warning_**
384-
385-
TypeScriptToLua does not check that the vararg expression is valid in the context it is used. If the array is used in a spread operation in an invalid context (such as a nested function), a deoptimization will occur.
386-
387-
**Example**
388-
389-
<SideBySide>
390-
391-
```typescript
392-
function outerFunction(...args: Vararg<string>) {
393-
function innerFunction() {
394-
console.log(...args);
395-
}
396-
innerFunction();
397-
}
398-
```
399-
400-
```lua
401-
function outerFunction(self, ...)
402-
local args = {...}
403-
local function innerFunction(self)
404-
print(unpack(args))
405-
end
406-
innerFunction(_G)
407-
end
408-
```
409-
410-
</SideBySide>
411-
412309
## Deprecated
413310

414311
:::warning
@@ -851,3 +748,153 @@ print(tbl.get(foo)); // print(tbl[foo])
851748
tbl.set(1, "baz"); // tbl[1] = "baz"
852749
print(tbl.length()); // print(#tbl)
853750
```
751+
752+
### @vararg
753+
754+
<DeprecatedInVersion deprecated="0.39.0" removed="TBD" />
755+
756+
**Target elements:** `(declare) interface or type`
757+
758+
Indicates that an array-like type represents a Lua vararg expression (`...`) and should be transpiled to that when used in a spread expression. This is useful for forwarding varargs instead of wrapping them in a table and unpacking them.
759+
760+
**Example**
761+
762+
<SideBySide>
763+
764+
```typescript
765+
function varargWrapUnpack(...args: string[]) {
766+
console.log(...args);
767+
}
768+
```
769+
770+
```lua
771+
function varargWrapUnpack(self, ...)
772+
local args = ({...})
773+
print(unpack(args))
774+
end
775+
```
776+
777+
</SideBySide>
778+
779+
<SideBySide>
780+
781+
```typescript
782+
/** @vararg */
783+
interface Vararg<T> extends Array<T> {}
784+
785+
function varargForward(...args: Vararg<string>) {
786+
console.log(...args);
787+
}
788+
```
789+
790+
```lua
791+
function varargForward(self, ...)
792+
print(...))
793+
end
794+
```
795+
796+
</SideBySide>
797+
798+
This can be used to access the file-scope varargs as well.
799+
800+
**Example**
801+
802+
<SideBySide>
803+
804+
```typescript
805+
declare const arg: Vararg<string>;
806+
console.log(...arg);
807+
const [x, y] = [...arg];
808+
```
809+
810+
```lua
811+
print(...)
812+
local x, y = ...
813+
```
814+
815+
</SideBySide>
816+
817+
To also support tuple-typed rest parameters, you can define the type like this:
818+
819+
**Example**
820+
821+
```typescript
822+
/** @vararg */
823+
type Vararg<T extends unknown[]> = T & { __luaVararg?: never };
824+
825+
function varargForward(...args: Vararg<[string, number]>) {}
826+
```
827+
828+
**_Warning_**
829+
830+
TypeScriptToLua does not check that the vararg expression is valid in the context it is used. If the array is used in a spread operation in an invalid context (such as a nested function), a deoptimization will occur.
831+
832+
**Example**
833+
834+
<SideBySide>
835+
836+
```typescript
837+
function outerFunction(...args: Vararg<string>) {
838+
function innerFunction() {
839+
console.log(...args);
840+
}
841+
innerFunction();
842+
}
843+
```
844+
845+
```lua
846+
function outerFunction(self, ...)
847+
local args = {...}
848+
local function innerFunction(self)
849+
print(unpack(args))
850+
end
851+
innerFunction(_G)
852+
end
853+
```
854+
855+
</SideBySide>
856+
857+
**Upgrade Instructions**
858+
859+
`@vararg` is no longer required to prevent vararg parameters from being wrapped in a table. The ellipsis operator will now automatically be used if the parameter is used in a spread expression.
860+
861+
Example:
862+
863+
<SideBySide>
864+
865+
```ts
866+
function varargForward(...args: string[]) {
867+
console.log(...args);
868+
}
869+
```
870+
871+
```lua
872+
function varargForward(...)
873+
print(...)
874+
end
875+
```
876+
877+
</SideBySide>
878+
879+
However, if the parameter is accessed as an array or tuple, it will be wrapped in a table.
880+
881+
Example:
882+
883+
<SideBySide>
884+
885+
```ts
886+
function varargAccess(...args: string[]) {
887+
console.log(args[0]);
888+
}
889+
```
890+
891+
```lua
892+
function varargAccess(...)
893+
local args = {...}
894+
print(args[1])
895+
end
896+
```
897+
898+
</SideBySide>
899+
900+
Note that are a few cases where the parameter will still be wrapped in a table, even if a spread expression is used, in order to generate correctly functioning Lua.

docs/advanced/language-extensions.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,3 +321,37 @@ declare namespace IdDictionary {
321321
IdDictionary.set(dict, id, "bar");
322322
console.log(IdDictionary.get(dict, id));
323323
```
324+
325+
## $vararg Constant
326+
327+
Lua allows use of the ellipsis operator (`...`) to access command line arguments passed when executing a script file. To access this from Typescript, you can use the `$vararg` constant in a spread expression.
328+
329+
Example:
330+
331+
<SideBySide>
332+
333+
```ts
334+
console.log(...$vararg);
335+
```
336+
337+
```lua
338+
print(...)
339+
```
340+
341+
</SideBySide>
342+
343+
When run:
344+
345+
<SideBySide>
346+
347+
```
348+
> lua myscript.lua foo bar
349+
```
350+
351+
```
352+
foo bar
353+
```
354+
355+
</SideBySide>
356+
357+
Use of `$vararg` is only allowed at file scope, and only in a spread expression (`...$vararg`).

0 commit comments

Comments
 (0)