diff --git a/docs/advanced/compiler-annotations.md b/docs/advanced/compiler-annotations.md index a94b3947..c7a63cd7 100644 --- a/docs/advanced/compiler-annotations.md +++ b/docs/advanced/compiler-annotations.md @@ -137,55 +137,6 @@ local inst = MyConstructor(3) -## @luaIterator - -**Target elements:** `(declare) interface` - -Denotes a type is a Lua iterator. When an object of a type with this annotation is used in a for...of statement, it will transpile directly as a lua iterator in a for...in statement, instead of being treated as a TypeScript iterable. Typically, this is used on an interface that extends `Iterable` or `Array` so that TypeScript will allow it to be used in a for...of statement. - -**Example** - - - - -```typescript -/** @luaIterator */ -type LuaIterable = Iterable; - -declare function myIterator(): LuaIterable; -for (const s of myIterator()) {} -``` - -```lua -for s in myIterator() do end -``` - - - -This can also be combined with [@tupleReturn](#tuplereturn), if the iterator returns multiple values. - -**Example** - - - - -```typescript -/** @luaIterator @tupleReturn */ -type LuaTupleIterable = Iterable; - -declare namespace string { - function gmatch(s: string, pattern: string): LuaTupleIterable; -} - -for (const [a, b] of string.gmatch("foo", "(.)(.)")) {} -``` - -```lua -for a, b in string.gmatch("foo", "(.)(.)") do end -``` - - - ## @luaTable **Target elements:** `type` @@ -797,3 +748,89 @@ for i = 10, 1, -1 do end ``` + +### @luaIterator + + + +**Target elements:** `(declare) interface` + +Denotes a type is a Lua iterator. When an object of a type with this annotation is used in a for...of statement, it will transpile directly as a lua iterator in a for...in statement, instead of being treated as a TypeScript iterable. Typically, this is used on an interface that extends `Iterable` or `Array` so that TypeScript will allow it to be used in a for...of statement. + +**Example** + + + + +```typescript +/** @luaIterator */ +type LuaIterator = Iterable; + +declare function myIterator(): LuaIterator; +for (const s of myIterator()) {} +``` + +```lua +for s in myIterator() do end +``` + + + +This can also be combined with [@tupleReturn](#tuplereturn), if the iterator returns multiple values. + +**Example** + + + + +```typescript +/** @luaIterator @tupleReturn */ +type LuaTupleIterator = Iterable; + +declare namespace string { + function gmatch(s: string, pattern: string): LuaTupleIterator; +} + +for (const [a, b] of string.gmatch("foo", "(.)(.)")) {} +``` + +```lua +for a, b in string.gmatch("foo", "(.)(.)") do end +``` + + + +**Upgrade Instructions** + +Use the [`LuaIterable` and `LuaMultiReturn` language extensions](language-extensions.md#luaiterable-type) instead of a custom annotated types. + + + + +```typescript +declare function myIterator(): LuaIterable; +for (const s of myIterator()) {} +``` + +```lua +for s in myIterator() do end +``` + + + + + + +```typescript +declare namespace string { + function gmatch(s: string, pattern: string): LuaIterable>; +} + +for (const [a, b] of string.gmatch("foo", "(.)(.)")) {} +``` + +```lua +for a, b in string.gmatch("foo", "(.)(.)") do end +``` + + diff --git a/docs/advanced/language-extensions.md b/docs/advanced/language-extensions.md index 04b2db36..05610af0 100644 --- a/docs/advanced/language-extensions.md +++ b/docs/advanced/language-extensions.md @@ -40,7 +40,7 @@ start, ____end = string.find("Hello, world!", "world") Prefer LuaMultiReturn over the similar [@tupleReturn annotation](./compiler-annotations.md#tuplereturn). LuaMultiReturn can do anything tupleReturn can, with the added benefit of being able to distinguish between actual tuple tables and multiple return values in the type system. ::: -### \$multi +### $multi In order to create a function that returns multiple values it needs to return a `LuaMultiReturn<>` type. This is where the `$multi` function comes in. Calling `$multi` in a return statement will create an instance of the `LuaMultiReturn<>` type: @@ -84,6 +84,70 @@ for i = 5, 1, -1 do end +## LuaIterable Type + +Iterators in Lua work quite differently than in Typescript/Javscript, so a special type is needed to use them. + +For example, to declare and use a Lua function that returns an iterator for a set of strings, you can do this: + + + +```ts +declare function myIterator(): LuaIterable; + +for (const s of myIterator()) { + console.log(s); +} +``` + +```lua +for s in myIterator() do + print(s) +end +``` + + + +Some iterators return multiple values each iteration. To declare these, combine `LuaIterable` with [`LuaMultiReturn`](#luamultireturn-type): + + + +```ts +declare function myIterator(): LuaIterable>; + +for (const [a, b] of myIterator()) { + console.log(a, b); +} +``` + +```lua +for a, b in myIterator() do + print(a, b) +end +``` + + + +Lua iterators support passing an invisible state object each iteration. If your iterator type does this, you can declare the state type as a second type parameter: + +```ts +type MyStateType = ... +declare function myIterator(): LuaIterable; +``` + +This is only really required if you need to use the iterator outside of a `for...of` loop. + +```ts +let [iteratorFunction, state, lastValue] = myIterator(); +while (true) { + const value = iteratorFunction(state, lastValue); + console.log(value); + lastValue = value; +} +``` + +See the [Lua Reference Manual](https://www.lua.org/manual/5.3/manual.html#3.3.5) for more information on Lua for loops. + ## Operator Map Types Lua supports overloading operators on types using [metatable methods](https://www.lua.org/manual/5.4/manual.html#2.4) such as `__add`. But, Javascript and Typescript do not support this. In order to use overloaded operators on types that support them, you can declare special mapping functions in TS that will translate to those operators in Lua. @@ -145,7 +209,7 @@ const scaled: Vector = Vector.mul(a, 2); - LuaAddition / LuaAdditionMethod (`a + b`) - LuaSubtraction / LuaSubtractionMethod (`a - b`) - LuaMultiplication / LuaMultiplicationMethod (`a * b`) - - LuaDivision / LuaDivisionMethod (`a /b `) + - LuaDivision / LuaDivisionMethod (`a / b `) - LuaModulo / LuaModuloMethod (`a % b`) - LuaPower / LuaPowerMethod (`a ^ b`) - LuaFloorDivision / LuaFloorDivisionMethod (`a // b`, only when targeting Lua 5.3 or later) @@ -153,7 +217,7 @@ const scaled: Vector = Vector.mul(a, 2); - Bitwise operators (only when targeting Lua 5.3 or later) - LuaBitwiseAnd / LuaBitwiseAndMethod (`a & b`) - LuaBitwiseOr / LuaBitwiseOrMethod (`a | b`) - - LuaBitwiseExclusiveOr / LuaBitwiseExclusiveOrMethod (`a ^ b`) + - LuaBitwiseExclusiveOr / LuaBitwiseExclusiveOrMethod (`a ~ b`) - LuaBitwiseLeftShift / LuaBitwiseLeftShiftMethod (`a << b`) - LuaBitwiseRightShift / LuaBitwiseRightShiftMethod (`a >> b`) - LuaBitwiseNot / LuaBitwiseNotMethod (`~x`)