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 b0735ce32..19e152cd1 100644 --- a/lute/luau/src/luau.cpp +++ b/lute/luau/src/luau.cpp @@ -2644,7 +2644,14 @@ int compile_luau(lua_State* L) std::string bytecode = Luau::compile(std::string(source, source_size), opts); - std::string* userdata = static_cast(lua_newuserdatatagged(L, sizeof(std::string), kCompilerResultTag)); + std::string* userdata = static_cast(lua_newuserdatadtor( + L, + sizeof(std::string), + [](void* ptr) + { + static_cast(ptr)->~basic_string(); + } + )); new (userdata) std::string(std::move(bytecode)); @@ -2656,13 +2663,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/runtime/include/lute/userdatas.h b/lute/runtime/include/lute/userdatas.h index a951dbb36..2986772b5 100644 --- a/lute/runtime/include/lute/userdatas.h +++ b/lute/runtime/include/lute/userdatas.h @@ -1,7 +1,6 @@ #pragma once // all tags count down from 128 -constexpr int kDurationTag = 127; -constexpr int kInstantTag = 126; -constexpr int kCompilerResultTag = 125; -constexpr int kWatchHandleTag = 124; \ No newline at end of file +constexpr int kDurationTag = 127; +constexpr int kInstantTag = 126; +constexpr int kWatchHandleTag = 125; \ No newline at end of file diff --git a/lute/std/libs/luau.luau b/lute/std/libs/luau.luau new file mode 100644 index 000000000..e07ccbb98 --- /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) + print(`got script path: {requirePathStr}`) + local migrationHandle = fs.open(requirePathStr, "r") + print(`opened file handle`) + local migrationBytecode = luau.compile(fs.read(migrationHandle)) + print(`compiled bytecode`) + fs.close(migrationHandle) + print(`closed file handle`) + 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/lute/std/libs/system/init.luau b/lute/std/libs/system/init.luau index 01f02b495..676a5733b 100644 --- a/lute/std/libs/system/init.luau +++ b/lute/std/libs/system/init.luau @@ -23,6 +23,8 @@ return table.freeze({ uptime = system.uptime, cpus = system.cpus, + tmpdir = tmpdir, + -- boolean properties win32 = platforminfo.win32, linux = platforminfo.linux, diff --git a/tests/loadbypath.test.luau b/tests/loadbypath.test.luau new file mode 100644 index 000000000..e0dc40c6f --- /dev/null +++ b/tests/loadbypath.test.luau @@ -0,0 +1,70 @@ +local fs = require("@std/fs") +local luau = require("@std/luau") +local process = require("@std/process") +local path = require("@std/path") +local system = require("@std/system") +local test = require("@std/test") + +-- local REQUIRER_CONTENTS = [[ +-- local args = { ... } +-- assert(#args == 2, "Expected one argument: path to Luau script to require") +-- print(args[2]) +-- ]] + +local REQUIRER_CONTENTS = [[ +local luau = require("@std/luau") +local fs = require("@std/fs") + +local args = { ... } +assert(#args == 2, "Expected one argument: path to Luau script to require") + +local handle = fs.open(args[2], "r") +print("opened file handle") +local contents = fs.read(handle) +print("read file contents") +fs.close(handle) +print("closed file handle") +luau.compile(contents) +print(`SUCCESS`) +]] + +local REQUIREE_CONTENTS = [[return "Success"]] + +local lutePath = process.execpath() +local tmpDir = system.tmpdir() + +test.suite("Lute CLI", function(suite) + suite:case("help1", function(check) + -- Setup + -- Create files + local requirerPath = path.join(tmpDir, "requirer.luau") + local requirerFile = fs.open(requirerPath, "w+") + fs.write(requirerFile, REQUIRER_CONTENTS) + fs.close(requirerFile) + + local requireePath = path.join(tmpDir, "requiree.luau") + local requireeFile = fs.open(requireePath, "w+") + fs.write(requireeFile, REQUIREE_CONTENTS) + fs.close(requireeFile) + + local lutePathStr = path.format(lutePath) + print(`Lute path: {lutePathStr}`) + print(`cwd: {process.cwd()}`) + + for _, f in fs.listdir(tmpDir) do + print(`tmp dir entry: {f.name}`) + end + + local result = process.run({ lutePathStr, path.format(requirerPath), path.format(requireePath) }) + print(`process stderr: {result.stderr}`) + print(`process result: {result.stdout}`) + check.neq(result.stdout:find("SUCCESS"), nil) + check.eq(result.exitcode, 0) + + -- -- Cleanup + fs.remove(requirerPath) + fs.remove(requireePath) + 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,