diff --git a/core/global.d.ts b/core/global.d.ts index 23efda4..fe56b5d 100644 --- a/core/global.d.ts +++ b/core/global.d.ts @@ -25,7 +25,11 @@ declare const _G: typeof globalThis; * otherwise, returns all its arguments. In case of error, `message` is the * error object; when absent, it defaults to "assertion failed!" */ -declare function assert(v: any, message?: string): asserts v; +declare function assert(v: V): Exclude; +declare function assert( + v: V, + ...args: A +): LuaMultiReturn<[Exclude, ...A]>; /** * This function is a generic interface to the garbage collector. It performs @@ -109,7 +113,7 @@ declare function error(message: string, level?: number): never; * metatable has a __metatable field, returns the associated value. Otherwise, * returns the metatable of the given object. */ -declare function getmetatable(object: T): LuaMetatable | undefined; +declare function getmetatable(object: T): LuaMetatable | undefined; /** * Returns three values (an iterator function, the table t, and 0) so that the @@ -153,6 +157,9 @@ declare function next(table: object, index?: any): LuaMultiReturn<[any, any] | [ * See function next for the caveats of modifying the table during its * traversal. */ +declare function pairs( + t: LuaTable +): LuaIterable>; declare function pairs(t: T): LuaIterable>; /** @@ -234,10 +241,17 @@ declare function select(index: '#', ...args: T[]): number; * * This function returns table. */ -declare function setmetatable( +declare function setmetatable< + T extends object, + TIndex extends object | ((this: T, key: any) => any) | undefined = undefined +>( table: T, - metatable: LuaMetatable | null | undefined -): T & TIndex; + metatable?: LuaMetatable | null +): TIndex extends (this: T, key: infer TKey) => infer TValue + ? T & { [K in TKey & string]: TValue } + : TIndex extends object + ? T & TIndex + : T; /** * When called with no base, tonumber tries to convert its argument to a number. diff --git a/core/io.d.ts b/core/io.d.ts index 9edabba..9c35097 100644 --- a/core/io.d.ts +++ b/core/io.d.ts @@ -61,9 +61,7 @@ declare namespace io { filename?: string, ...formats: T ): LuaIterable< - LuaMultiReturn< - [] extends T ? [string] : { [P in keyof T]: T[P] extends 'n' ? number : string } - > + LuaMultiReturn<[] extends T ? [string] : { [P in keyof T]: FileReadFormatToType }> >; /** @@ -100,12 +98,31 @@ declare namespace io { * you can use to read data from this program (if mode is "r", the default) or * to write data to this program (if mode is "w"). */ - function popen(prog: string, mode?: 'r' | 'w'): LuaFile; + function popen(prog: string, mode?: 'r' | 'w'): LuaMultiReturn<[LuaFile] | [undefined, string]>; /** * Equivalent to io.input():read(···). */ - const read: LuaFile['read']; + function read(): io.FileReadFormatToType | undefined; + function read(format: T): io.FileReadFormatToType | undefined; + function read( + ...formats: T + ): LuaMultiReturn<{ [P in keyof T]?: io.FileReadFormatToType }>; + + /** + * Predefined file handle for standard error stream. The I/O library never closes this file. + */ + const stderr: LuaFile; + + /** + * Predefined file handle for standard input stream. The I/O library never closes this file. + */ + const stdin: LuaFile; + + /** + * Predefined file handle for standard output stream. The I/O library never closes this file. + */ + const stdout: LuaFile; /** * In case of success, returns a handle for a temporary file. This file is @@ -125,6 +142,8 @@ declare namespace io { * Equivalent to io.output():write(···). */ function write(...args: (string | number)[]): LuaMultiReturn<[LuaFile] | [undefined, string]>; + + type FileReadFormatToType = T extends FileReadNumberFormat ? number : string; } interface LuaFile { @@ -157,12 +176,10 @@ interface LuaFile { * In case of errors this function raises the error, instead of returning an * error code. */ - lines( + lines( ...formats: T ): LuaIterable< - LuaMultiReturn< - [] extends T ? [string] : { [P in keyof T]: T[P] extends 'n' ? number : string } - > + LuaMultiReturn<[] extends T ? [string] : { [P in keyof T]: io.FileReadFormatToType }> >; /** @@ -193,9 +210,11 @@ interface LuaFile { * * The formats "l" and "L" should be used only for text files. */ - read( + read(): io.FileReadFormatToType | undefined; + read(format: T): io.FileReadFormatToType | undefined; + read( ...formats: T - ): LuaMultiReturn<{ [P in keyof T]?: T[P] extends 'n' ? number : string }>; + ): LuaMultiReturn<{ [P in keyof T]?: io.FileReadFormatToType }>; /** * Sets and geionts the file position, measured from the beginning of the diff --git a/core/metatable.d.ts b/core/metatable.d.ts index fb411e5..7636dea 100644 --- a/core/metatable.d.ts +++ b/core/metatable.d.ts @@ -1,6 +1,6 @@ // Based on https://www.lua.org/manual/5.3/manual.html#2.4 -interface LuaMetatable { +interface LuaMetatable any) | undefined> { /** * the addition (+) operation. If any operand for an addition is not a number * (nor a string coercible to a number), Lua will try to call a metamethod. @@ -102,7 +102,7 @@ interface LuaMetatable { * this table with key. (This indexing is regular, not raw, and therefore can * trigger another metamethod.) */ - __index?: TIndex | ((this: T, key: any, value: any) => any); + __index?: TIndex; /** * The indexing assignment table[key] = value. Like the index event, this diff --git a/core/string.d.ts b/core/string.d.ts index 5310dad..0a10e5d 100644 --- a/core/string.d.ts +++ b/core/string.d.ts @@ -179,6 +179,11 @@ declare namespace string { */ function match(s: string, pattern: string, init?: number): LuaMultiReturn; + /** + * Returns a string that is the concatenation of `n` copies of the string `s`. + */ + function rep(s: string, n: number): string; + /** * Returns a string that is the string s reversed. */ diff --git a/special/5.1-only.d.ts b/special/5.1-only.d.ts index ef13f0f..aeeadce 100644 --- a/special/5.1-only.d.ts +++ b/special/5.1-only.d.ts @@ -96,4 +96,8 @@ declare namespace debug { ): LuaMultiReturn<[string, any]>; } -type FileReadFormat = '*n' | '*a' | '*l' | number; +declare namespace io { + type FileReadNumberFormat = '*n'; + type FileReadLineFormat = '*l'; + type FileReadFormat = FileReadNumberFormat | FileReadLineFormat | '*a' | number; +} diff --git a/special/5.2-or-jit.d.ts b/special/5.2-or-jit.d.ts index c2c8b88..5d3e3b8 100644 --- a/special/5.2-or-jit.d.ts +++ b/special/5.2-or-jit.d.ts @@ -1 +1,5 @@ -type FileReadFormat = '*n' | '*a' | '*l' | '*L' | number; +declare namespace io { + type FileReadNumberFormat = '*n'; + type FileReadLineFormat = '*l'; + type FileReadFormat = FileReadNumberFormat | FileReadLineFormat | '*a' | '*L' | number; +} diff --git a/special/5.3-plus.d.ts b/special/5.3-plus.d.ts index aec91af..802a43b 100644 --- a/special/5.3-plus.d.ts +++ b/special/5.3-plus.d.ts @@ -227,4 +227,8 @@ interface LuaMetatable { __shr?(this: T, operand: any): any; } -type FileReadFormat = 'n' | 'a' | 'l' | 'L' | number; +declare namespace io { + type FileReadNumberFormat = 'n'; + type FileReadLineFormat = 'l'; + type FileReadFormat = FileReadNumberFormat | FileReadLineFormat | 'a' | 'L' | number; +} diff --git a/test/__snapshots__/global.spec.ts.snap b/test/__snapshots__/global.spec.ts.snap index d84335f..ecc346b 100644 --- a/test/__snapshots__/global.spec.ts.snap +++ b/test/__snapshots__/global.spec.ts.snap @@ -4,11 +4,28 @@ exports[`Lua version 5.1 / global assert 1`] = `"assert({bla = \\"not false\\"}) exports[`Lua version 5.1 / global assert 2`] = `"assert(false, \\"assert message\\")"`; +exports[`Lua version 5.1 / global assert with multi-return 1`] = ` +"v, a, b = assert({bla = \\"not false\\"}, {foo = \\"FOO\\"}, {bar = \\"BAR\\"}) +bla = v.bla +foo = a.foo +bar = b.bar" +`; + +exports[`Lua version 5.1 / global assert with return 1`] = ` +"v = assert({bla = \\"not false\\"}) +bla = v.bla" +`; + exports[`Lua version 5.1 / global getmetatable 1`] = ` "metatable = getmetatable({}) add = metatable.__add" `; +exports[`Lua version 5.1 / global getmetatable on string 1`] = ` +"metatable = getmetatable(\\"foo\\") +index = metatable.__index" +`; + exports[`Lua version 5.1 / global ipairs 1`] = ` "for i, v in ipairs({1, 2, 3}) do print(i, v) @@ -25,6 +42,18 @@ exports[`Lua version 5.1 / global pairs 1`] = ` end" `; +exports[`Lua version 5.1 / global pairs with LuaTable 1`] = ` +"tbl = {} +tbl.foo = \\"bar\\" +tbl.baz = \\"bur\\" +takesStr = function(____, str) +end +for k, v in pairs(tbl) do + takesStr(_G, k) + takesStr(_G, v) +end" +`; + exports[`Lua version 5.1 / global pcall 1`] = ` "success, resultOrMessage = pcall( function(a) return true end, @@ -52,6 +81,27 @@ exports[`Lua version 5.1 / global select destructured 1`] = `"b, c = select(2, \ exports[`Lua version 5.1 / global select with # 1`] = `"count = select(\\"#\\", \\"a\\", \\"b\\", \\"c\\")"`; +exports[`Lua version 5.1 / global setmetatable with function index 1`] = ` +"tbl = setmetatable( + {}, + { + __index = function(____, key) return tostring(key) .. \\"bar\\" end + } +) +takesStr = function(____, s) +end +takesStr(_G, tbl.foo)" +`; + +exports[`Lua version 5.1 / global setmetatable with no index 1`] = `"tbl = setmetatable({})"`; + +exports[`Lua version 5.1 / global setmetatable with table index 1`] = ` +"tbl = setmetatable({}, {__index = {foo = \\"bar\\"}}) +takesStr = function(____, s) +end +takesStr(_G, tbl.foo)" +`; + exports[`Lua version 5.1 / global tonumber 1`] = `"number = tonumber(\\"213.4\\")"`; exports[`Lua version 5.1 / global tonumber with base 1`] = `"number = tonumber(\\"213.4\\", 5)"`; @@ -64,11 +114,28 @@ exports[`Lua version 5.2 / global assert 1`] = `"assert({bla = \\"not false\\"}) exports[`Lua version 5.2 / global assert 2`] = `"assert(false, \\"assert message\\")"`; +exports[`Lua version 5.2 / global assert with multi-return 1`] = ` +"v, a, b = assert({bla = \\"not false\\"}, {foo = \\"FOO\\"}, {bar = \\"BAR\\"}) +bla = v.bla +foo = a.foo +bar = b.bar" +`; + +exports[`Lua version 5.2 / global assert with return 1`] = ` +"v = assert({bla = \\"not false\\"}) +bla = v.bla" +`; + exports[`Lua version 5.2 / global getmetatable 1`] = ` "metatable = getmetatable({}) add = metatable.__add" `; +exports[`Lua version 5.2 / global getmetatable on string 1`] = ` +"metatable = getmetatable(\\"foo\\") +index = metatable.__index" +`; + exports[`Lua version 5.2 / global ipairs 1`] = ` "for i, v in ipairs({1, 2, 3}) do print(i, v) @@ -85,6 +152,18 @@ exports[`Lua version 5.2 / global pairs 1`] = ` end" `; +exports[`Lua version 5.2 / global pairs with LuaTable 1`] = ` +"tbl = {} +tbl.foo = \\"bar\\" +tbl.baz = \\"bur\\" +takesStr = function(____, str) +end +for k, v in pairs(tbl) do + takesStr(_G, k) + takesStr(_G, v) +end" +`; + exports[`Lua version 5.2 / global pcall 1`] = ` "success, resultOrMessage = pcall( function(a) return true end, @@ -112,6 +191,27 @@ exports[`Lua version 5.2 / global select destructured 1`] = `"b, c = select(2, \ exports[`Lua version 5.2 / global select with # 1`] = `"count = select(\\"#\\", \\"a\\", \\"b\\", \\"c\\")"`; +exports[`Lua version 5.2 / global setmetatable with function index 1`] = ` +"tbl = setmetatable( + {}, + { + __index = function(____, key) return tostring(key) .. \\"bar\\" end + } +) +takesStr = function(____, s) +end +takesStr(_G, tbl.foo)" +`; + +exports[`Lua version 5.2 / global setmetatable with no index 1`] = `"tbl = setmetatable({})"`; + +exports[`Lua version 5.2 / global setmetatable with table index 1`] = ` +"tbl = setmetatable({}, {__index = {foo = \\"bar\\"}}) +takesStr = function(____, s) +end +takesStr(_G, tbl.foo)" +`; + exports[`Lua version 5.2 / global tonumber 1`] = `"number = tonumber(\\"213.4\\")"`; exports[`Lua version 5.2 / global tonumber with base 1`] = `"number = tonumber(\\"213.4\\", 5)"`; @@ -124,11 +224,28 @@ exports[`Lua version 5.3 / global assert 1`] = `"assert({bla = \\"not false\\"}) exports[`Lua version 5.3 / global assert 2`] = `"assert(false, \\"assert message\\")"`; +exports[`Lua version 5.3 / global assert with multi-return 1`] = ` +"v, a, b = assert({bla = \\"not false\\"}, {foo = \\"FOO\\"}, {bar = \\"BAR\\"}) +bla = v.bla +foo = a.foo +bar = b.bar" +`; + +exports[`Lua version 5.3 / global assert with return 1`] = ` +"v = assert({bla = \\"not false\\"}) +bla = v.bla" +`; + exports[`Lua version 5.3 / global getmetatable 1`] = ` "metatable = getmetatable({}) add = metatable.__add" `; +exports[`Lua version 5.3 / global getmetatable on string 1`] = ` +"metatable = getmetatable(\\"foo\\") +index = metatable.__index" +`; + exports[`Lua version 5.3 / global ipairs 1`] = ` "for i, v in ipairs({1, 2, 3}) do print(i, v) @@ -145,6 +262,18 @@ exports[`Lua version 5.3 / global pairs 1`] = ` end" `; +exports[`Lua version 5.3 / global pairs with LuaTable 1`] = ` +"tbl = {} +tbl.foo = \\"bar\\" +tbl.baz = \\"bur\\" +takesStr = function(____, str) +end +for k, v in pairs(tbl) do + takesStr(_G, k) + takesStr(_G, v) +end" +`; + exports[`Lua version 5.3 / global pcall 1`] = ` "success, resultOrMessage = pcall( function(a) return true end, @@ -172,6 +301,27 @@ exports[`Lua version 5.3 / global select destructured 1`] = `"b, c = select(2, \ exports[`Lua version 5.3 / global select with # 1`] = `"count = select(\\"#\\", \\"a\\", \\"b\\", \\"c\\")"`; +exports[`Lua version 5.3 / global setmetatable with function index 1`] = ` +"tbl = setmetatable( + {}, + { + __index = function(____, key) return tostring(key) .. \\"bar\\" end + } +) +takesStr = function(____, s) +end +takesStr(_G, tbl.foo)" +`; + +exports[`Lua version 5.3 / global setmetatable with no index 1`] = `"tbl = setmetatable({})"`; + +exports[`Lua version 5.3 / global setmetatable with table index 1`] = ` +"tbl = setmetatable({}, {__index = {foo = \\"bar\\"}}) +takesStr = function(____, s) +end +takesStr(_G, tbl.foo)" +`; + exports[`Lua version 5.3 / global tonumber 1`] = `"number = tonumber(\\"213.4\\")"`; exports[`Lua version 5.3 / global tonumber with base 1`] = `"number = tonumber(\\"213.4\\", 5)"`; @@ -184,11 +334,28 @@ exports[`Lua version 5.4 / global assert 1`] = `"assert({bla = \\"not false\\"}) exports[`Lua version 5.4 / global assert 2`] = `"assert(false, \\"assert message\\")"`; +exports[`Lua version 5.4 / global assert with multi-return 1`] = ` +"v, a, b = assert({bla = \\"not false\\"}, {foo = \\"FOO\\"}, {bar = \\"BAR\\"}) +bla = v.bla +foo = a.foo +bar = b.bar" +`; + +exports[`Lua version 5.4 / global assert with return 1`] = ` +"v = assert({bla = \\"not false\\"}) +bla = v.bla" +`; + exports[`Lua version 5.4 / global getmetatable 1`] = ` "metatable = getmetatable({}) add = metatable.__add" `; +exports[`Lua version 5.4 / global getmetatable on string 1`] = ` +"metatable = getmetatable(\\"foo\\") +index = metatable.__index" +`; + exports[`Lua version 5.4 / global ipairs 1`] = ` "for i, v in ipairs({1, 2, 3}) do print(i, v) @@ -205,6 +372,18 @@ exports[`Lua version 5.4 / global pairs 1`] = ` end" `; +exports[`Lua version 5.4 / global pairs with LuaTable 1`] = ` +"tbl = {} +tbl.foo = \\"bar\\" +tbl.baz = \\"bur\\" +takesStr = function(____, str) +end +for k, v in pairs(tbl) do + takesStr(_G, k) + takesStr(_G, v) +end" +`; + exports[`Lua version 5.4 / global pcall 1`] = ` "success, resultOrMessage = pcall( function(a) return true end, @@ -232,6 +411,27 @@ exports[`Lua version 5.4 / global select destructured 1`] = `"b, c = select(2, \ exports[`Lua version 5.4 / global select with # 1`] = `"count = select(\\"#\\", \\"a\\", \\"b\\", \\"c\\")"`; +exports[`Lua version 5.4 / global setmetatable with function index 1`] = ` +"tbl = setmetatable( + {}, + { + __index = function(____, key) return tostring(key) .. \\"bar\\" end + } +) +takesStr = function(____, s) +end +takesStr(_G, tbl.foo)" +`; + +exports[`Lua version 5.4 / global setmetatable with no index 1`] = `"tbl = setmetatable({})"`; + +exports[`Lua version 5.4 / global setmetatable with table index 1`] = ` +"tbl = setmetatable({}, {__index = {foo = \\"bar\\"}}) +takesStr = function(____, s) +end +takesStr(_G, tbl.foo)" +`; + exports[`Lua version 5.4 / global tonumber 1`] = `"number = tonumber(\\"213.4\\")"`; exports[`Lua version 5.4 / global tonumber with base 1`] = `"number = tonumber(\\"213.4\\", 5)"`; @@ -244,11 +444,28 @@ exports[`Lua version JIT / global assert 1`] = `"assert({bla = \\"not false\\"}) exports[`Lua version JIT / global assert 2`] = `"assert(false, \\"assert message\\")"`; +exports[`Lua version JIT / global assert with multi-return 1`] = ` +"v, a, b = assert({bla = \\"not false\\"}, {foo = \\"FOO\\"}, {bar = \\"BAR\\"}) +bla = v.bla +foo = a.foo +bar = b.bar" +`; + +exports[`Lua version JIT / global assert with return 1`] = ` +"v = assert({bla = \\"not false\\"}) +bla = v.bla" +`; + exports[`Lua version JIT / global getmetatable 1`] = ` "metatable = getmetatable({}) add = metatable.__add" `; +exports[`Lua version JIT / global getmetatable on string 1`] = ` +"metatable = getmetatable(\\"foo\\") +index = metatable.__index" +`; + exports[`Lua version JIT / global ipairs 1`] = ` "for i, v in ipairs({1, 2, 3}) do print(i, v) @@ -265,6 +482,18 @@ exports[`Lua version JIT / global pairs 1`] = ` end" `; +exports[`Lua version JIT / global pairs with LuaTable 1`] = ` +"tbl = {} +tbl.foo = \\"bar\\" +tbl.baz = \\"bur\\" +takesStr = function(____, str) +end +for k, v in pairs(tbl) do + takesStr(_G, k) + takesStr(_G, v) +end" +`; + exports[`Lua version JIT / global pcall 1`] = ` "success, resultOrMessage = pcall( function(a) return true end, @@ -292,6 +521,27 @@ exports[`Lua version JIT / global select destructured 1`] = `"b, c = select(2, \ exports[`Lua version JIT / global select with # 1`] = `"count = select(\\"#\\", \\"a\\", \\"b\\", \\"c\\")"`; +exports[`Lua version JIT / global setmetatable with function index 1`] = ` +"tbl = setmetatable( + {}, + { + __index = function(____, key) return tostring(key) .. \\"bar\\" end + } +) +takesStr = function(____, s) +end +takesStr(_G, tbl.foo)" +`; + +exports[`Lua version JIT / global setmetatable with no index 1`] = `"tbl = setmetatable({})"`; + +exports[`Lua version JIT / global setmetatable with table index 1`] = ` +"tbl = setmetatable({}, {__index = {foo = \\"bar\\"}}) +takesStr = function(____, s) +end +takesStr(_G, tbl.foo)" +`; + exports[`Lua version JIT / global tonumber 1`] = `"number = tonumber(\\"213.4\\")"`; exports[`Lua version JIT / global tonumber with base 1`] = `"number = tonumber(\\"213.4\\", 5)"`; diff --git a/test/__snapshots__/io.spec.ts.snap b/test/__snapshots__/io.spec.ts.snap new file mode 100644 index 0000000..e44aaf4 --- /dev/null +++ b/test/__snapshots__/io.spec.ts.snap @@ -0,0 +1,531 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Lua version 5.1 / file close 1`] = `"file:close()"`; + +exports[`Lua version 5.1 / file flush 1`] = `"file:flush()"`; + +exports[`Lua version 5.1 / file lines 1`] = ` +"for line in file:lines() do + print(line) +end" +`; + +exports[`Lua version 5.1 / file read multi 1`] = ` +"foo, bar = file:read(\\"*l\\", \\"*n\\") +takesString(_G, foo) +takesNumber(_G, bar)" +`; + +exports[`Lua version 5.1 / file read one 1`] = ` +"foo = file:read(\\"*l\\") +takesString(_G, foo)" +`; + +exports[`Lua version 5.1 / file read zero 1`] = ` +"foo = file:read() +takesString(_G, foo)" +`; + +exports[`Lua version 5.1 / file seek 1`] = `"pos, err = file:seek()"`; + +exports[`Lua version 5.1 / file seek offset 1`] = `"pos, err = file:seek(\\"cur\\", 1)"`; + +exports[`Lua version 5.1 / file seek whence 1`] = `"pos, err = file:seek(\\"cur\\")"`; + +exports[`Lua version 5.1 / file setvbuf 1`] = `"file:setvbuf(\\"no\\")"`; + +exports[`Lua version 5.1 / file setvbuf with size 1`] = `"file:setvbuf(\\"line\\", 10)"`; + +exports[`Lua version 5.1 / file write 1`] = `"f, err = file:write(\\"foo\\", \\"bar\\")"`; + +exports[`Lua version 5.1 / io close 1`] = `"io.close()"`; + +exports[`Lua version 5.1 / io close file 1`] = `"io.close(file)"`; + +exports[`Lua version 5.1 / io flush 1`] = `"io.flush()"`; + +exports[`Lua version 5.1 / io input 1`] = `"inp = io.input()"`; + +exports[`Lua version 5.1 / io input with file handle 1`] = `"inp = io.input(file)"`; + +exports[`Lua version 5.1 / io input with filename 1`] = `"inp = io.input(\\"foo.bar\\")"`; + +exports[`Lua version 5.1 / io lines 1`] = ` +"for line in io.lines() do + print(line) +end" +`; + +exports[`Lua version 5.1 / io lines with filename 1`] = ` +"for line in io.lines(\\"foo.bar\\") do + print(line) +end" +`; + +exports[`Lua version 5.1 / io open 1`] = `"f, err = io.open(\\"foo.bar\\")"`; + +exports[`Lua version 5.1 / io open with mode flag 1`] = `"f, err = io.open(\\"foo.bar\\", \\"r\\")"`; + +exports[`Lua version 5.1 / io output 1`] = `"inp = io.output()"`; + +exports[`Lua version 5.1 / io output with file handle 1`] = `"inp = io.output(file)"`; + +exports[`Lua version 5.1 / io output with filename 1`] = `"inp = io.output(\\"foo.bar\\")"`; + +exports[`Lua version 5.1 / io popen 1`] = `"proc, err = io.popen(\\"echo foobar\\")"`; + +exports[`Lua version 5.1 / io read multi 1`] = ` +"foo, bar = io.read(\\"*l\\", \\"*n\\") +takesString(_G, foo) +takesNumber(_G, bar)" +`; + +exports[`Lua version 5.1 / io read one 1`] = ` +"foo = io.read(\\"*l\\") +takesString(_G, foo)" +`; + +exports[`Lua version 5.1 / io read zero 1`] = ` +"foo = io.read() +takesString(_G, foo)" +`; + +exports[`Lua version 5.1 / io stderr 1`] = `"io.stderr:write(\\"foobar\\")"`; + +exports[`Lua version 5.1 / io stdin 1`] = `"input = io.stdin:read()"`; + +exports[`Lua version 5.1 / io stdout 1`] = `"io.stdout:write(\\"foobar\\")"`; + +exports[`Lua version 5.1 / io tmpfile 1`] = `"file = io.tmpfile()"`; + +exports[`Lua version 5.1 / io type 1`] = ` +"print( + io.type(file) +)" +`; + +exports[`Lua version 5.1 / io write 1`] = `"f, err = io.write(\\"foobar\\")"`; + +exports[`Lua version 5.2 / file close 1`] = `"file:close()"`; + +exports[`Lua version 5.2 / file flush 1`] = `"file:flush()"`; + +exports[`Lua version 5.2 / file lines 1`] = ` +"for line in file:lines() do + print(line) +end" +`; + +exports[`Lua version 5.2 / file read multi 1`] = ` +"foo, bar = file:read(\\"*l\\", \\"*n\\") +takesString(_G, foo) +takesNumber(_G, bar)" +`; + +exports[`Lua version 5.2 / file read one 1`] = ` +"foo = file:read(\\"*l\\") +takesString(_G, foo)" +`; + +exports[`Lua version 5.2 / file read zero 1`] = ` +"foo = file:read() +takesString(_G, foo)" +`; + +exports[`Lua version 5.2 / file seek 1`] = `"pos, err = file:seek()"`; + +exports[`Lua version 5.2 / file seek offset 1`] = `"pos, err = file:seek(\\"cur\\", 1)"`; + +exports[`Lua version 5.2 / file seek whence 1`] = `"pos, err = file:seek(\\"cur\\")"`; + +exports[`Lua version 5.2 / file setvbuf 1`] = `"file:setvbuf(\\"no\\")"`; + +exports[`Lua version 5.2 / file setvbuf with size 1`] = `"file:setvbuf(\\"line\\", 10)"`; + +exports[`Lua version 5.2 / file write 1`] = `"f, err = file:write(\\"foo\\", \\"bar\\")"`; + +exports[`Lua version 5.2 / io close 1`] = `"io.close()"`; + +exports[`Lua version 5.2 / io close file 1`] = `"io.close(file)"`; + +exports[`Lua version 5.2 / io flush 1`] = `"io.flush()"`; + +exports[`Lua version 5.2 / io input 1`] = `"inp = io.input()"`; + +exports[`Lua version 5.2 / io input with file handle 1`] = `"inp = io.input(file)"`; + +exports[`Lua version 5.2 / io input with filename 1`] = `"inp = io.input(\\"foo.bar\\")"`; + +exports[`Lua version 5.2 / io lines 1`] = ` +"for line in io.lines() do + print(line) +end" +`; + +exports[`Lua version 5.2 / io lines with filename 1`] = ` +"for line in io.lines(\\"foo.bar\\") do + print(line) +end" +`; + +exports[`Lua version 5.2 / io open 1`] = `"f, err = io.open(\\"foo.bar\\")"`; + +exports[`Lua version 5.2 / io open with mode flag 1`] = `"f, err = io.open(\\"foo.bar\\", \\"r\\")"`; + +exports[`Lua version 5.2 / io output 1`] = `"inp = io.output()"`; + +exports[`Lua version 5.2 / io output with file handle 1`] = `"inp = io.output(file)"`; + +exports[`Lua version 5.2 / io output with filename 1`] = `"inp = io.output(\\"foo.bar\\")"`; + +exports[`Lua version 5.2 / io popen 1`] = `"proc, err = io.popen(\\"echo foobar\\")"`; + +exports[`Lua version 5.2 / io read multi 1`] = ` +"foo, bar = io.read(\\"*l\\", \\"*n\\") +takesString(_G, foo) +takesNumber(_G, bar)" +`; + +exports[`Lua version 5.2 / io read one 1`] = ` +"foo = io.read(\\"*l\\") +takesString(_G, foo)" +`; + +exports[`Lua version 5.2 / io read zero 1`] = ` +"foo = io.read() +takesString(_G, foo)" +`; + +exports[`Lua version 5.2 / io stderr 1`] = `"io.stderr:write(\\"foobar\\")"`; + +exports[`Lua version 5.2 / io stdin 1`] = `"input = io.stdin:read()"`; + +exports[`Lua version 5.2 / io stdout 1`] = `"io.stdout:write(\\"foobar\\")"`; + +exports[`Lua version 5.2 / io tmpfile 1`] = `"file = io.tmpfile()"`; + +exports[`Lua version 5.2 / io type 1`] = ` +"print( + io.type(file) +)" +`; + +exports[`Lua version 5.2 / io write 1`] = `"f, err = io.write(\\"foobar\\")"`; + +exports[`Lua version 5.3 / file close 1`] = `"file:close()"`; + +exports[`Lua version 5.3 / file flush 1`] = `"file:flush()"`; + +exports[`Lua version 5.3 / file lines 1`] = ` +"for line in file:lines() do + print(line) +end" +`; + +exports[`Lua version 5.3 / file read multi 1`] = ` +"foo, bar = file:read(\\"l\\", \\"n\\") +takesString(_G, foo) +takesNumber(_G, bar)" +`; + +exports[`Lua version 5.3 / file read one 1`] = ` +"foo = file:read(\\"l\\") +takesString(_G, foo)" +`; + +exports[`Lua version 5.3 / file read zero 1`] = ` +"foo = file:read() +takesString(_G, foo)" +`; + +exports[`Lua version 5.3 / file seek 1`] = `"pos, err = file:seek()"`; + +exports[`Lua version 5.3 / file seek offset 1`] = `"pos, err = file:seek(\\"cur\\", 1)"`; + +exports[`Lua version 5.3 / file seek whence 1`] = `"pos, err = file:seek(\\"cur\\")"`; + +exports[`Lua version 5.3 / file setvbuf 1`] = `"file:setvbuf(\\"no\\")"`; + +exports[`Lua version 5.3 / file setvbuf with size 1`] = `"file:setvbuf(\\"line\\", 10)"`; + +exports[`Lua version 5.3 / file write 1`] = `"f, err = file:write(\\"foo\\", \\"bar\\")"`; + +exports[`Lua version 5.3 / io close 1`] = `"io.close()"`; + +exports[`Lua version 5.3 / io close file 1`] = `"io.close(file)"`; + +exports[`Lua version 5.3 / io flush 1`] = `"io.flush()"`; + +exports[`Lua version 5.3 / io input 1`] = `"inp = io.input()"`; + +exports[`Lua version 5.3 / io input with file handle 1`] = `"inp = io.input(file)"`; + +exports[`Lua version 5.3 / io input with filename 1`] = `"inp = io.input(\\"foo.bar\\")"`; + +exports[`Lua version 5.3 / io lines 1`] = ` +"for line in io.lines() do + print(line) +end" +`; + +exports[`Lua version 5.3 / io lines with filename 1`] = ` +"for line in io.lines(\\"foo.bar\\") do + print(line) +end" +`; + +exports[`Lua version 5.3 / io open 1`] = `"f, err = io.open(\\"foo.bar\\")"`; + +exports[`Lua version 5.3 / io open with mode flag 1`] = `"f, err = io.open(\\"foo.bar\\", \\"r\\")"`; + +exports[`Lua version 5.3 / io output 1`] = `"inp = io.output()"`; + +exports[`Lua version 5.3 / io output with file handle 1`] = `"inp = io.output(file)"`; + +exports[`Lua version 5.3 / io output with filename 1`] = `"inp = io.output(\\"foo.bar\\")"`; + +exports[`Lua version 5.3 / io popen 1`] = `"proc, err = io.popen(\\"echo foobar\\")"`; + +exports[`Lua version 5.3 / io read multi 1`] = ` +"foo, bar = io.read(\\"l\\", \\"n\\") +takesString(_G, foo) +takesNumber(_G, bar)" +`; + +exports[`Lua version 5.3 / io read one 1`] = ` +"foo = io.read(\\"l\\") +takesString(_G, foo)" +`; + +exports[`Lua version 5.3 / io read zero 1`] = ` +"foo = io.read() +takesString(_G, foo)" +`; + +exports[`Lua version 5.3 / io stderr 1`] = `"io.stderr:write(\\"foobar\\")"`; + +exports[`Lua version 5.3 / io stdin 1`] = `"input = io.stdin:read()"`; + +exports[`Lua version 5.3 / io stdout 1`] = `"io.stdout:write(\\"foobar\\")"`; + +exports[`Lua version 5.3 / io tmpfile 1`] = `"file = io.tmpfile()"`; + +exports[`Lua version 5.3 / io type 1`] = ` +"print( + io.type(file) +)" +`; + +exports[`Lua version 5.3 / io write 1`] = `"f, err = io.write(\\"foobar\\")"`; + +exports[`Lua version 5.4 / file close 1`] = `"file:close()"`; + +exports[`Lua version 5.4 / file flush 1`] = `"file:flush()"`; + +exports[`Lua version 5.4 / file lines 1`] = ` +"for line in file:lines() do + print(line) +end" +`; + +exports[`Lua version 5.4 / file read multi 1`] = ` +"foo, bar = file:read(\\"l\\", \\"n\\") +takesString(_G, foo) +takesNumber(_G, bar)" +`; + +exports[`Lua version 5.4 / file read one 1`] = ` +"foo = file:read(\\"l\\") +takesString(_G, foo)" +`; + +exports[`Lua version 5.4 / file read zero 1`] = ` +"foo = file:read() +takesString(_G, foo)" +`; + +exports[`Lua version 5.4 / file seek 1`] = `"pos, err = file:seek()"`; + +exports[`Lua version 5.4 / file seek offset 1`] = `"pos, err = file:seek(\\"cur\\", 1)"`; + +exports[`Lua version 5.4 / file seek whence 1`] = `"pos, err = file:seek(\\"cur\\")"`; + +exports[`Lua version 5.4 / file setvbuf 1`] = `"file:setvbuf(\\"no\\")"`; + +exports[`Lua version 5.4 / file setvbuf with size 1`] = `"file:setvbuf(\\"line\\", 10)"`; + +exports[`Lua version 5.4 / file write 1`] = `"f, err = file:write(\\"foo\\", \\"bar\\")"`; + +exports[`Lua version 5.4 / io close 1`] = `"io.close()"`; + +exports[`Lua version 5.4 / io close file 1`] = `"io.close(file)"`; + +exports[`Lua version 5.4 / io flush 1`] = `"io.flush()"`; + +exports[`Lua version 5.4 / io input 1`] = `"inp = io.input()"`; + +exports[`Lua version 5.4 / io input with file handle 1`] = `"inp = io.input(file)"`; + +exports[`Lua version 5.4 / io input with filename 1`] = `"inp = io.input(\\"foo.bar\\")"`; + +exports[`Lua version 5.4 / io lines 1`] = ` +"for line in io.lines() do + print(line) +end" +`; + +exports[`Lua version 5.4 / io lines with filename 1`] = ` +"for line in io.lines(\\"foo.bar\\") do + print(line) +end" +`; + +exports[`Lua version 5.4 / io open 1`] = `"f, err = io.open(\\"foo.bar\\")"`; + +exports[`Lua version 5.4 / io open with mode flag 1`] = `"f, err = io.open(\\"foo.bar\\", \\"r\\")"`; + +exports[`Lua version 5.4 / io output 1`] = `"inp = io.output()"`; + +exports[`Lua version 5.4 / io output with file handle 1`] = `"inp = io.output(file)"`; + +exports[`Lua version 5.4 / io output with filename 1`] = `"inp = io.output(\\"foo.bar\\")"`; + +exports[`Lua version 5.4 / io popen 1`] = `"proc, err = io.popen(\\"echo foobar\\")"`; + +exports[`Lua version 5.4 / io read multi 1`] = ` +"foo, bar = io.read(\\"l\\", \\"n\\") +takesString(_G, foo) +takesNumber(_G, bar)" +`; + +exports[`Lua version 5.4 / io read one 1`] = ` +"foo = io.read(\\"l\\") +takesString(_G, foo)" +`; + +exports[`Lua version 5.4 / io read zero 1`] = ` +"foo = io.read() +takesString(_G, foo)" +`; + +exports[`Lua version 5.4 / io stderr 1`] = `"io.stderr:write(\\"foobar\\")"`; + +exports[`Lua version 5.4 / io stdin 1`] = `"input = io.stdin:read()"`; + +exports[`Lua version 5.4 / io stdout 1`] = `"io.stdout:write(\\"foobar\\")"`; + +exports[`Lua version 5.4 / io tmpfile 1`] = `"file = io.tmpfile()"`; + +exports[`Lua version 5.4 / io type 1`] = ` +"print( + io.type(file) +)" +`; + +exports[`Lua version 5.4 / io write 1`] = `"f, err = io.write(\\"foobar\\")"`; + +exports[`Lua version JIT / file close 1`] = `"file:close()"`; + +exports[`Lua version JIT / file flush 1`] = `"file:flush()"`; + +exports[`Lua version JIT / file lines 1`] = ` +"for line in file:lines() do + print(line) +end" +`; + +exports[`Lua version JIT / file read multi 1`] = ` +"foo, bar = file:read(\\"*l\\", \\"*n\\") +takesString(_G, foo) +takesNumber(_G, bar)" +`; + +exports[`Lua version JIT / file read one 1`] = ` +"foo = file:read(\\"*l\\") +takesString(_G, foo)" +`; + +exports[`Lua version JIT / file read zero 1`] = ` +"foo = file:read() +takesString(_G, foo)" +`; + +exports[`Lua version JIT / file seek 1`] = `"pos, err = file:seek()"`; + +exports[`Lua version JIT / file seek offset 1`] = `"pos, err = file:seek(\\"cur\\", 1)"`; + +exports[`Lua version JIT / file seek whence 1`] = `"pos, err = file:seek(\\"cur\\")"`; + +exports[`Lua version JIT / file setvbuf 1`] = `"file:setvbuf(\\"no\\")"`; + +exports[`Lua version JIT / file setvbuf with size 1`] = `"file:setvbuf(\\"line\\", 10)"`; + +exports[`Lua version JIT / file write 1`] = `"f, err = file:write(\\"foo\\", \\"bar\\")"`; + +exports[`Lua version JIT / io close 1`] = `"io.close()"`; + +exports[`Lua version JIT / io close file 1`] = `"io.close(file)"`; + +exports[`Lua version JIT / io flush 1`] = `"io.flush()"`; + +exports[`Lua version JIT / io input 1`] = `"inp = io.input()"`; + +exports[`Lua version JIT / io input with file handle 1`] = `"inp = io.input(file)"`; + +exports[`Lua version JIT / io input with filename 1`] = `"inp = io.input(\\"foo.bar\\")"`; + +exports[`Lua version JIT / io lines 1`] = ` +"for line in io.lines() do + print(line) +end" +`; + +exports[`Lua version JIT / io lines with filename 1`] = ` +"for line in io.lines(\\"foo.bar\\") do + print(line) +end" +`; + +exports[`Lua version JIT / io open 1`] = `"f, err = io.open(\\"foo.bar\\")"`; + +exports[`Lua version JIT / io open with mode flag 1`] = `"f, err = io.open(\\"foo.bar\\", \\"r\\")"`; + +exports[`Lua version JIT / io output 1`] = `"inp = io.output()"`; + +exports[`Lua version JIT / io output with file handle 1`] = `"inp = io.output(file)"`; + +exports[`Lua version JIT / io output with filename 1`] = `"inp = io.output(\\"foo.bar\\")"`; + +exports[`Lua version JIT / io popen 1`] = `"proc, err = io.popen(\\"echo foobar\\")"`; + +exports[`Lua version JIT / io read multi 1`] = ` +"foo, bar = io.read(\\"*l\\", \\"*n\\") +takesString(_G, foo) +takesNumber(_G, bar)" +`; + +exports[`Lua version JIT / io read one 1`] = ` +"foo = io.read(\\"*l\\") +takesString(_G, foo)" +`; + +exports[`Lua version JIT / io read zero 1`] = ` +"foo = io.read() +takesString(_G, foo)" +`; + +exports[`Lua version JIT / io stderr 1`] = `"io.stderr:write(\\"foobar\\")"`; + +exports[`Lua version JIT / io stdin 1`] = `"input = io.stdin:read()"`; + +exports[`Lua version JIT / io stdout 1`] = `"io.stdout:write(\\"foobar\\")"`; + +exports[`Lua version JIT / io tmpfile 1`] = `"file = io.tmpfile()"`; + +exports[`Lua version JIT / io type 1`] = ` +"print( + io.type(file) +)" +`; + +exports[`Lua version JIT / io write 1`] = `"f, err = io.write(\\"foobar\\")"`; diff --git a/test/__snapshots__/string.spec.ts.snap b/test/__snapshots__/string.spec.ts.snap index 8b0631e..38517fc 100644 --- a/test/__snapshots__/string.spec.ts.snap +++ b/test/__snapshots__/string.spec.ts.snap @@ -70,6 +70,8 @@ exports[`Lua version 5.1 / string string.match 1`] = ` exports[`Lua version 5.1 / string string.match destructured 1`] = `"match1, match2 = string.match(\\"hello world\\", \\"l\\")"`; +exports[`Lua version 5.1 / string string.rep 1`] = `"str = string.rep(\\"foo\\", 3)"`; + exports[`Lua version 5.2 / string string.byte 1`] = `"b = string.byte(\\"d\\")"`; exports[`Lua version 5.2 / string string.byte multiple 1`] = `"a, b, c, d = string.byte(\\"abcd\\", 1, 4)"`; @@ -140,6 +142,8 @@ exports[`Lua version 5.2 / string string.match 1`] = ` exports[`Lua version 5.2 / string string.match destructured 1`] = `"match1, match2 = string.match(\\"hello world\\", \\"l\\")"`; +exports[`Lua version 5.2 / string string.rep 1`] = `"str = string.rep(\\"foo\\", 3)"`; + exports[`Lua version 5.3 / string string.byte 1`] = `"b = string.byte(\\"d\\")"`; exports[`Lua version 5.3 / string string.byte multiple 1`] = `"a, b, c, d = string.byte(\\"abcd\\", 1, 4)"`; @@ -210,6 +214,8 @@ exports[`Lua version 5.3 / string string.match 1`] = ` exports[`Lua version 5.3 / string string.match destructured 1`] = `"match1, match2 = string.match(\\"hello world\\", \\"l\\")"`; +exports[`Lua version 5.3 / string string.rep 1`] = `"str = string.rep(\\"foo\\", 3)"`; + exports[`Lua version 5.4 / string string.byte 1`] = `"b = string.byte(\\"d\\")"`; exports[`Lua version 5.4 / string string.byte multiple 1`] = `"a, b, c, d = string.byte(\\"abcd\\", 1, 4)"`; @@ -280,6 +286,8 @@ exports[`Lua version 5.4 / string string.match 1`] = ` exports[`Lua version 5.4 / string string.match destructured 1`] = `"match1, match2 = string.match(\\"hello world\\", \\"l\\")"`; +exports[`Lua version 5.4 / string string.rep 1`] = `"str = string.rep(\\"foo\\", 3)"`; + exports[`Lua version JIT / string string.byte 1`] = `"b = string.byte(\\"d\\")"`; exports[`Lua version JIT / string string.byte multiple 1`] = `"a, b, c, d = string.byte(\\"abcd\\", 1, 4)"`; @@ -349,3 +357,5 @@ exports[`Lua version JIT / string string.match 1`] = ` `; exports[`Lua version JIT / string string.match destructured 1`] = `"match1, match2 = string.match(\\"hello world\\", \\"l\\")"`; + +exports[`Lua version JIT / string string.rep 1`] = `"str = string.rep(\\"foo\\", 3)"`; diff --git a/test/global.spec.ts b/test/global.spec.ts index f74e8a2..7b55c96 100644 --- a/test/global.spec.ts +++ b/test/global.spec.ts @@ -12,6 +12,32 @@ describeForEachLuaTarget('global', (target) => { expect(lua).toMatchSnapshot(); }); + test('assert with return', () => { + const lua = tstl( + target, + ` + const v = assert({ bla: "not false"}); + const bla = v.bla; + ` + ); + + expect(lua).toMatchSnapshot(); + }); + + test('assert with multi-return', () => { + const lua = tstl( + target, + ` + const [v, a, b] = assert({ bla: "not false"}, { foo: "FOO" }, { bar: "BAR" }); + const bla = v.bla; + const foo = a.foo; + const bar = b.bar; + ` + ); + + expect(lua).toMatchSnapshot(); + }); + test('assert', () => { const lua = tstl( target, @@ -35,6 +61,18 @@ describeForEachLuaTarget('global', (target) => { expect(lua).toMatchSnapshot(); }); + test('getmetatable on string', () => { + const lua = tstl( + target, + ` + const metatable = getmetatable("foo"); + const index = metatable!.__index; + ` + ); + + expect(lua).toMatchSnapshot(); + }); + test('ipairs', () => { const lua = tstl( target, @@ -83,6 +121,24 @@ describeForEachLuaTarget('global', (target) => { expect(lua).toMatchSnapshot(); }); + test('pairs with LuaTable', () => { + const lua = tstl( + target, + ` + const tbl = new LuaTable(); + tbl.set("foo", "bar"); + tbl.set("baz", "bur"); + const takesStr = (str: string) => {}; + for (const [k, v] of pairs(tbl)) { + takesStr(k); + takesStr(v); + } + ` + ); + + expect(lua).toMatchSnapshot(); + }); + test('pcall', () => { const lua = tstl( target, @@ -149,6 +205,43 @@ describeForEachLuaTarget('global', (target) => { expect(lua).toMatchSnapshot(); }); + test('setmetatable with table index', () => { + const lua = tstl( + target, + ` + const tbl = setmetatable({}, {__index: {foo: "bar"}}); + const takesStr = (s: string) => {}; + takesStr(tbl.foo); + ` + ); + + expect(lua).toMatchSnapshot(); + }); + + test('setmetatable with function index', () => { + const lua = tstl( + target, + ` + const tbl = setmetatable({}, {__index: (key: string) => key + "bar"}); + const takesStr = (s: string) => {}; + takesStr(tbl.foo); + ` + ); + + expect(lua).toMatchSnapshot(); + }); + + test('setmetatable with no index', () => { + const lua = tstl( + target, + ` + const tbl = setmetatable({}); + ` + ); + + expect(lua).toMatchSnapshot(); + }); + test('tonumber', () => { const lua = tstl( target, diff --git a/test/io.spec.ts b/test/io.spec.ts new file mode 100644 index 0000000..be52338 --- /dev/null +++ b/test/io.spec.ts @@ -0,0 +1,451 @@ +import { LuaTarget } from 'typescript-to-lua'; +import { describeForEachLuaTarget, tstl } from './test-utils'; + +describeForEachLuaTarget('io', (target) => { + test('close', () => { + const lua = tstl( + target, + ` + io.close(); + ` + ); + + expect(lua).toMatchSnapshot(); + }); + + test('close file', () => { + const lua = tstl( + target, + ` + declare const file: LuaFile; + io.close(file); + ` + ); + + expect(lua).toMatchSnapshot(); + }); + + test('flush', () => { + const lua = tstl( + target, + ` + io.flush(); + ` + ); + + expect(lua).toMatchSnapshot(); + }); + + test('input', () => { + const lua = tstl( + target, + ` + const inp = io.input(); + ` + ); + + expect(lua).toMatchSnapshot(); + }); + + test('input with filename', () => { + const lua = tstl( + target, + ` + const inp = io.input("foo.bar"); + ` + ); + + expect(lua).toMatchSnapshot(); + }); + + test('input with file handle', () => { + const lua = tstl( + target, + ` + declare const file: LuaFile; + const inp = io.input(file); + ` + ); + + expect(lua).toMatchSnapshot(); + }); + + test('lines', () => { + const lua = tstl( + target, + ` + for (const [line] of io.lines()) { + print(line); + } + ` + ); + + expect(lua).toMatchSnapshot(); + }); + + test('lines with filename', () => { + const lua = tstl( + target, + ` + for (const [line] of io.lines("foo.bar")) { + print(line); + } + ` + ); + + expect(lua).toMatchSnapshot(); + }); + + test('open', () => { + const lua = tstl( + target, + ` + const [f, err] = io.open("foo.bar"); + ` + ); + + expect(lua).toMatchSnapshot(); + }); + + test('open with mode flag', () => { + const lua = tstl( + target, + ` + const [f, err] = io.open("foo.bar", "r"); + ` + ); + + expect(lua).toMatchSnapshot(); + }); + + test('output', () => { + const lua = tstl( + target, + ` + const inp = io.output(); + ` + ); + + expect(lua).toMatchSnapshot(); + }); + + test('output with filename', () => { + const lua = tstl( + target, + ` + const inp = io.output("foo.bar"); + ` + ); + + expect(lua).toMatchSnapshot(); + }); + + test('output with file handle', () => { + const lua = tstl( + target, + ` + declare const file: LuaFile; + const inp = io.output(file); + ` + ); + + expect(lua).toMatchSnapshot(); + }); + + test('popen', () => { + const lua = tstl( + target, + ` + const [proc, err] = io.popen("echo foobar"); + ` + ); + + expect(lua).toMatchSnapshot(); + }); + + test('read zero', () => { + const lua = tstl( + target, + ` + const foo = io.read(); + declare function takesString(str: string): void; + takesString(foo); + ` + ); + + expect(lua).toMatchSnapshot(); + }); + + test('read one', () => { + const useOldFormat = + [LuaTarget.Lua51, LuaTarget.Lua52, LuaTarget.LuaJIT, LuaTarget.Universal].indexOf( + target + ) >= 0; + const lineFormat = useOldFormat ? '*l' : 'l'; + const lua = tstl( + target, + ` + const foo = io.read("${lineFormat}"); + declare function takesString(str: string): void; + takesString(foo); + ` + ); + + expect(lua).toMatchSnapshot(); + }); + + test('read multi', () => { + const useOldFormat = + [LuaTarget.Lua51, LuaTarget.Lua52, LuaTarget.LuaJIT, LuaTarget.Universal].indexOf( + target + ) >= 0; + const numberFormat = useOldFormat ? '*n' : 'n'; + const lineFormat = useOldFormat ? '*l' : 'l'; + const lua = tstl( + target, + ` + const [foo, bar] = io.read("${lineFormat}", "${numberFormat}"); + declare function takesString(str: string): void; + declare function takesNumber(num: number): void; + takesString(foo); + takesNumber(bar); + ` + ); + + expect(lua).toMatchSnapshot(); + }); + + test('stderr', () => { + const lua = tstl( + target, + ` + io.stderr.write("foobar"); + ` + ); + + expect(lua).toMatchSnapshot(); + }); + + test('stdin', () => { + const lua = tstl( + target, + ` + const input = io.stdin.read(); + ` + ); + + expect(lua).toMatchSnapshot(); + }); + + test('stdout', () => { + const lua = tstl( + target, + ` + io.stdout.write("foobar"); + ` + ); + + expect(lua).toMatchSnapshot(); + }); + + test('tmpfile', () => { + const lua = tstl( + target, + ` + const file = io.tmpfile(); + ` + ); + + expect(lua).toMatchSnapshot(); + }); + + test('type', () => { + const lua = tstl( + target, + ` + declare const file: LuaFile; + print(io.type(file)); + ` + ); + + expect(lua).toMatchSnapshot(); + }); + + test('write', () => { + const lua = tstl( + target, + ` + const [f, err] = io.write("foobar"); + ` + ); + + expect(lua).toMatchSnapshot(); + }); +}); + +describeForEachLuaTarget('file', (target) => { + test('close', () => { + const lua = tstl( + target, + ` + declare const file: LuaFile; + file.close(); + ` + ); + + expect(lua).toMatchSnapshot(); + }); + + test('flush', () => { + const lua = tstl( + target, + ` + declare const file: LuaFile; + file.flush(); + ` + ); + + expect(lua).toMatchSnapshot(); + }); + + test('lines', () => { + const lua = tstl( + target, + ` + declare const file: LuaFile; + for (const [line] of file.lines()) { + print(line); + } + ` + ); + + expect(lua).toMatchSnapshot(); + }); + + test('read zero', () => { + const lua = tstl( + target, + ` + declare const file: LuaFile; + const foo = file.read(); + declare function takesString(str: string): void; + takesString(foo); + ` + ); + + expect(lua).toMatchSnapshot(); + }); + + test('read one', () => { + const useOldFormat = + [LuaTarget.Lua51, LuaTarget.Lua52, LuaTarget.LuaJIT, LuaTarget.Universal].indexOf( + target + ) >= 0; + const lineFormat = useOldFormat ? '*l' : 'l'; + const lua = tstl( + target, + ` + declare const file: LuaFile; + const foo = file.read("${lineFormat}"); + declare function takesString(str: string): void; + takesString(foo); + ` + ); + + expect(lua).toMatchSnapshot(); + }); + + test('read multi', () => { + const useOldFormat = + [LuaTarget.Lua51, LuaTarget.Lua52, LuaTarget.LuaJIT, LuaTarget.Universal].indexOf( + target + ) >= 0; + const numberFormat = useOldFormat ? '*n' : 'n'; + const lineFormat = useOldFormat ? '*l' : 'l'; + const lua = tstl( + target, + ` + declare const file: LuaFile; + const [foo, bar] = file.read("${lineFormat}", "${numberFormat}"); + declare function takesString(str: string): void; + declare function takesNumber(num: number): void; + takesString(foo); + takesNumber(bar); + ` + ); + + expect(lua).toMatchSnapshot(); + }); + + test('seek', () => { + const lua = tstl( + target, + ` + declare const file: LuaFile; + const [pos, err] = file.seek(); + ` + ); + + expect(lua).toMatchSnapshot(); + }); + + test('seek whence', () => { + const lua = tstl( + target, + ` + declare const file: LuaFile; + const [pos, err] = file.seek("cur"); + ` + ); + + expect(lua).toMatchSnapshot(); + }); + + test('seek offset', () => { + const lua = tstl( + target, + ` + declare const file: LuaFile; + const [pos, err] = file.seek("cur", 1); + ` + ); + + expect(lua).toMatchSnapshot(); + }); + + test('setvbuf', () => { + const lua = tstl( + target, + ` + declare const file: LuaFile; + file.setvbuf("no"); + ` + ); + + expect(lua).toMatchSnapshot(); + }); + + test('setvbuf with size', () => { + const lua = tstl( + target, + ` + declare const file: LuaFile; + file.setvbuf("line", 10); + ` + ); + + expect(lua).toMatchSnapshot(); + }); + + test('write', () => { + const lua = tstl( + target, + ` + declare const file: LuaFile; + const [f, err] = file.write("foo", "bar"); + ` + ); + + expect(lua).toMatchSnapshot(); + }); +}); diff --git a/test/string.spec.ts b/test/string.spec.ts index 5854b71..e02341a 100644 --- a/test/string.spec.ts +++ b/test/string.spec.ts @@ -182,4 +182,15 @@ describeForEachLuaTarget('string', (target) => { expect(lua).toMatchSnapshot(); }); + + test('string.rep', () => { + const lua = tstl( + target, + ` + const str = string.rep("foo", 3); + ` + ); + + expect(lua).toMatchSnapshot(); + }); });