diff --git a/definitions/luau.luau b/definitions/luau.luau index efee44c1f..a017f8d2d 100644 --- a/definitions/luau.luau +++ b/definitions/luau.luau @@ -576,7 +576,7 @@ function luau.compile(source: string): Bytecode error("not implemented") end -function luau.load(bytecode: Bytecode, chunkname: string?, env: { [any]: any }?): (...any) -> ...any +function luau.load(bytecode: Bytecode, chunkname: string, env: { [any]: any }?): (...any) -> ...any error("not implemented") end diff --git a/examples/compile.luau b/examples/compile.luau index 51872e794..2f7757459 100644 --- a/examples/compile.luau +++ b/examples/compile.luau @@ -1,4 +1,4 @@ -local luau = require("@lute/luau") +local luau = require("@std/luau") local bytecode_container = luau.compile('return "Hello, world!"') diff --git a/examples/linter.luau b/examples/linter.luau index bc0928021..ea44b0fae 100644 --- a/examples/linter.luau +++ b/examples/linter.luau @@ -1,5 +1,5 @@ local fs = require("@std/fs") -local luau = require("@lute/luau") +local luau = require("@std/luau") local pp = require("@batteries/pp") diff --git a/examples/parsing.luau b/examples/parsing.luau index 55c37f6a9..374ce6608 100644 --- a/examples/parsing.luau +++ b/examples/parsing.luau @@ -1,4 +1,4 @@ -local luau = require("@lute/luau") +local luau = require("@std/luau") local pretty = require("@batteries/pp") diff --git a/lute/luau/src/luau.cpp b/lute/luau/src/luau.cpp index 18410577d..a6312717b 100644 --- a/lute/luau/src/luau.cpp +++ b/lute/luau/src/luau.cpp @@ -2664,13 +2664,12 @@ int compile_luau(lua_State* L) int load_luau(lua_State* L) { - const std::string* bytecode_string = static_cast(luaL_checkudata(L, 1, COMPILE_RESULT_TYPE)); - const char* path = luaL_optlstring(L, 2, "=luau.load", nullptr); - std::string chunk_name = path; - if (chunk_name != "=luau.load") - chunk_name.insert(0, "@"); + const std::string* bytecodeString = static_cast(luaL_checkudata(L, 1, COMPILE_RESULT_TYPE)); + const char* chunkname = luaL_checkstring(L, 2); + int envIndex = lua_isnoneornil(L, 3) ? 0 : 3; - luau_load(L, chunk_name.c_str(), bytecode_string->c_str(), bytecode_string->length(), lua_gettop(L) > 2 ? 3 : 0); + if (luau_load(L, chunkname, bytecodeString->c_str(), bytecodeString->length(), envIndex) != 0) + lua_error(L); return 1; } diff --git a/lute/std/libs/luau.luau b/lute/std/libs/luau.luau new file mode 100644 index 000000000..fe9fbcb50 --- /dev/null +++ b/lute/std/libs/luau.luau @@ -0,0 +1,183 @@ +local luteLuau = require("@lute/luau") + +local fs = require("@lute/fs") +local path = require("@std/path") + +local luau = {} + +-- Export all types from luteLuau +export type Position = luteLuau.Position +export type Location = luteLuau.Location + +export type Whitespace = luteLuau.Whitespace +export type SingleLineComment = luteLuau.SingleLineComment +export type MultiLineComment = luteLuau.MultiLineComment + +export type Trivia = luteLuau.Trivia + +export type Token = luteLuau.Token + +export type Eof = luteLuau.Eof + +export type Pair = luteLuau.Pair +export type Punctuated = luteLuau.Punctuated + +export type AstLocal = luteLuau.AstLocal + +export type AstExprGroup = luteLuau.AstExprGroup + +export type AstExprConstantNil = luteLuau.AstExprConstantNil + +export type AstExprConstantBool = luteLuau.AstExprConstantBool + +export type AstExprConstantNumber = luteLuau.AstExprConstantNumber + +export type AstExprConstantString = luteLuau.AstExprConstantString + +export type AstExprLocal = luteLuau.AstExprLocal + +export type AstExprGlobal = luteLuau.AstExprGlobal + +export type AstExprVarargs = luteLuau.AstExprVarargs + +export type AstExprCall = luteLuau.AstExprCall + +export type AstExprIndexName = luteLuau.AstExprIndexName + +export type AstExprIndexExpr = luteLuau.AstExprIndexExpr + +export type AstFunctionBody = luteLuau.AstFunctionBody + +export type AstExprAnonymousFunction = luteLuau.AstExprAnonymousFunction + +export type AstExprTableItem = luteLuau.AstExprTableItem + +export type AstExprTable = luteLuau.AstExprTable + +export type AstExprUnary = luteLuau.AstExprUnary + +export type AstExprBinary = luteLuau.AstExprBinary + +export type AstExprInterpString = luteLuau.AstExprInterpString + +export type AstExprTypeAssertion = luteLuau.AstExprTypeAssertion + +export type AstExprIfElseIfs = luteLuau.AstExprIfElseIfs + +export type AstExprIfElse = luteLuau.AstExprIfElse + +export type AstExpr = luteLuau.AstExpr + +export type AstStatBlock = luteLuau.AstStatBlock + +export type AstStatElseIf = luteLuau.AstStatElseIf + +export type AstStatIf = luteLuau.AstStatIf + +export type AstStatWhile = luteLuau.AstStatWhile + +export type AstStatRepeat = luteLuau.AstStatRepeat + +export type AstStatBreak = luteLuau.AstStatBreak + +export type AstStatContinue = luteLuau.AstStatContinue + +export type AstStatReturn = luteLuau.AstStatReturn + +export type AstStatExpr = luteLuau.AstStatExpr + +export type AstStatLocal = luteLuau.AstStatLocal + +export type AstStatFor = luteLuau.AstStatFor + +export type AstStatForIn = luteLuau.AstStatForIn + +export type AstStatAssign = luteLuau.AstStatAssign + +export type AstStatCompoundAssign = luteLuau.AstStatCompoundAssign + +export type AstAttribute = luteLuau.AstAttribute + +export type AstStatFunction = luteLuau.AstStatFunction + +export type AstStatLocalFunction = luteLuau.AstStatLocalFunction + +export type AstStatTypeAlias = luteLuau.AstStatTypeAlias + +export type AstStatTypeFunction = luteLuau.AstStatTypeFunction + +export type AstStat = luteLuau.AstStat + +export type AstGenericType = luteLuau.AstGenericType + +export type AstGenericTypePack = luteLuau.AstGenericTypePack + +export type AstTypeReference = luteLuau.AstTypeReference + +export type AstTypeSingletonBool = luteLuau.AstTypeSingletonBool + +export type AstTypeSingletonString = luteLuau.AstTypeSingletonString + +export type AstTypeTypeof = luteLuau.AstTypeTypeof + +export type AstTypeGroup = luteLuau.AstTypeGroup + +export type AstTypeOptional = luteLuau.AstTypeOptional + +export type AstTypeUnion = luteLuau.AstTypeUnion + +export type AstTypeIntersection = luteLuau.AstTypeIntersection + +export type AstTypeArray = luteLuau.AstTypeArray + +export type AstTypeTableItem = luteLuau.AstTypeTableItem + +export type AstTypeTable = luteLuau.AstTypeTable + +export type AstTypeFunctionParameter = luteLuau.AstTypeFunctionParameter + +export type AstTypeFunction = luteLuau.AstTypeFunction + +export type AstType = luteLuau.AstType + +export type AstTypePackExplicit = luteLuau.AstTypePackExplicit + +export type AstTypePackGeneric = luteLuau.AstTypePackGeneric + +export type AstTypePackVariadic = luteLuau.AstTypePackVariadic + +export type AstTypePack = luteLuau.AstTypePack + +export type ParseResult = luteLuau.ParseResult + +export type Bytecode = luteLuau.Bytecode + +function luau.parse(source: string): ParseResult + return luteLuau.parse(source) +end + +function luau.parseexpr(source: string): AstExpr + return luteLuau.parseexpr(source) +end + +function luau.compile(source: string): Bytecode + return luteLuau.compile(source) +end + +function luau.load(bytecode: Bytecode, chunkname: string?, env: { [any]: any }?): (...any) -> ...any + return luteLuau.load(bytecode, if chunkname ~= nil then `@{chunkname}` else "=luau.load", env) +end + +function luau.loadbypath(requirePath: path.pathlike): any + local requirePathStr = if typeof(requirePath) == "string" then requirePath else path.format(requirePath) + + local migrationHandle = fs.open(requirePathStr, "r") + + local migrationBytecode = luau.compile(fs.read(migrationHandle)) + + fs.close(migrationHandle) + + return luau.load(migrationBytecode, requirePathStr)() +end + +return luau diff --git a/lute/std/libs/path/posix/init.luau b/lute/std/libs/path/posix/init.luau index bb7f39f0a..8a2b14183 100644 --- a/lute/std/libs/path/posix/init.luau +++ b/lute/std/libs/path/posix/init.luau @@ -110,15 +110,12 @@ function posix.join(...: pathlike): path } end - local path: path - if typeof(parts[1]) == "string" then - path = posix.parse(parts[1]) - else - path = { + local path: path = if typeof(parts[1]) == "string" + then posix.parse(parts[1]) + else { parts = table.clone((parts[1] :: path).parts), absolute = (parts[1] :: path).absolute, } - end for i = 2, #parts do joinHelper(path, parts[i]) diff --git a/lute/std/libs/path/win32/init.luau b/lute/std/libs/path/win32/init.luau index d42b26778..e2ccadb8c 100644 --- a/lute/std/libs/path/win32/init.luau +++ b/lute/std/libs/path/win32/init.luau @@ -144,16 +144,13 @@ function win32.join(...: pathlike): path } end - local path: path - if typeof(parts[1]) == "string" then - path = win32.parse(parts[1]) - else - path = { + local path: path = if typeof(parts[1]) == "string" + then win32.parse(parts[1]) + else { parts = table.clone((parts[1] :: path).parts), kind = (parts[1] :: path).kind, driveLetter = (parts[1] :: path).driveLetter, } - end for i = 2, #parts do joinHelper(path, parts[i]) diff --git a/lute/std/libs/syntax/parser.luau b/lute/std/libs/syntax/parser.luau index 5c76d2620..3ff7035d4 100644 --- a/lute/std/libs/syntax/parser.luau +++ b/lute/std/libs/syntax/parser.luau @@ -1,6 +1,6 @@ --!strict -local luau = require("@lute/luau") +local luau = require("@std/luau") --- Parses Luau source code into an AstStatBlock local function parse(source: string): luau.AstStatBlock diff --git a/lute/std/libs/syntax/printer.luau b/lute/std/libs/syntax/printer.luau index 401841db7..31903ac2e 100644 --- a/lute/std/libs/syntax/printer.luau +++ b/lute/std/libs/syntax/printer.luau @@ -1,5 +1,5 @@ --!strict -local luau = require("@lute/luau") +local luau = require("@std/luau") local visitor = require("./visitor") local function exhaustiveMatch(value: never): never diff --git a/lute/std/libs/syntax/visitor.luau b/lute/std/libs/syntax/visitor.luau index 513b2c53a..53fcf75c8 100644 --- a/lute/std/libs/syntax/visitor.luau +++ b/lute/std/libs/syntax/visitor.luau @@ -1,6 +1,6 @@ --!strict -local luau = require("@lute/luau") +local luau = require("@std/luau") export type Visitor = { visitBlock: (luau.AstStatBlock) -> boolean, diff --git a/tests/loadbypath.test.luau b/tests/loadbypath.test.luau new file mode 100644 index 000000000..3754faa46 --- /dev/null +++ b/tests/loadbypath.test.luau @@ -0,0 +1,68 @@ +local fs = require("@lute/fs") +local process = require("@lute/process") +local path = require("@std/path") +local test = require("@std/test") + +local REQUIRER_CONTENTS = [[ +local args = { ... } +assert(#args == 2, "Expected one argument: path to Luau script to require") + +local luau = require("@std/luau") +local result = luau.loadbypath(args[2]) +print(result) +]] + +local REQUIREE_CONTENTS = [[return "Success"]] + +local lutePath = process.execpath() + +local tmpDirStr = ".tmp" +local tmpDirExists = fs.exists(tmpDirStr) +local testDir = path.join(tmpDirStr, "lute_require_test") +local testDirStr = path.format(testDir) + +test.suite("Lute CLI", function(suite) + suite:beforeall(function() + if not tmpDirExists then + fs.mkdir(tmpDirStr) + end + + if not fs.exists(testDirStr) then + fs.mkdir(testDirStr) + end + end) + + suite:case("help1", function(check) + -- Setup + -- Create files + local requirerPath = path.format(path.join(testDir, "requirer.luau")) + local requirerFile = fs.open(requirerPath, "w+") + fs.write(requirerFile, REQUIRER_CONTENTS) + fs.close(requirerFile) + + local requireePath = path.format(path.join(testDir, "requiree.luau")) + local requireeFile = fs.open(requireePath, "w+") + fs.write(requireeFile, REQUIREE_CONTENTS) + fs.close(requireeFile) + + local result = process.run({ lutePath, requirerPath, requireePath }) + check.eq(result.exitcode, 0) + check.eq(result.stdout, "Success\n") + + -- Cleanup + fs.remove(requirerPath) + fs.remove(requireePath) + end) + + suite:afterall(function() + if fs.exists(testDirStr) then + fs.rmdir(testDirStr) + end + + if not tmpDirExists then + fs.rmdir(tmpDirStr) + end + end) +end) + +test.run() diff --git a/tests/testAstSerializer.test.luau b/tests/testAstSerializer.test.luau index f4dbfb45b..92e2fccde 100644 --- a/tests/testAstSerializer.test.luau +++ b/tests/testAstSerializer.test.luau @@ -1,12 +1,12 @@ local asserts = require("@std/assert") local fs = require("@std/fs") -local luau = require("@lute/luau") +local luau = require("@std/luau") local path = require("@std/path") local test = require("@std/test") local parser = require("@std/syntax/parser") local printer = require("@std/syntax/printer") -local T = require("@lute/luau") +local T = require("@std/luau") local function assertEqualsLocation( assert: asserts.Asserts,