Giter Club home page Giter Club logo

luau's People

Contributors

aatxe avatar alexmccord avatar allanjeremy avatar amaranthinecodices avatar andyfriesen avatar asajeffrey avatar benmactavsin avatar ccuser44 avatar dcope-rbx avatar dekkonot avatar johnnymorganz avatar jsoref avatar kampfkarren avatar khvzak avatar logandark avatar mathematicaldessert avatar metatablecat avatar petrihakkinen avatar rblanckaert avatar rerumu avatar slappy826 avatar snowyshiro avatar someon1e avatar thepotato97 avatar tiffany352 avatar tovaio avatar vegorov-rbx avatar vighnesh-v avatar wheretib avatar zeux avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

luau's Issues

Not possible to declare nested table to be of a certain type

On the luau-lang.org website we have the following documentation that shows how to make a table of a certain type:
image

We're trying to increase the expressiveness of our Enums module that is ubiquitously used throughout our codebase, so we're trying to do something like this:

type NLEnumItem<T> = T
type NLEnumIndex<T> = T
type NLEnum<T1, T2> = { [NLEnumIndex< T1 >]: NLEnumItem< T2 > }
export type SkillUseBasis = number
export type SkillUseBasisEnum = NLEnum<string, SkillUseBasis>

type NLEnums = {
	SkillUseBasis: SkillUseBasisEnum
}

local Enums: NLEnums = {
	SkillUseBasis: SkillUseBasisEnum = {
	Cast = 1,
	Channel = 2,
	Attack = 3,
	Exert = 4
	}
}

but we have the following error:
image

We can bypass the issue by moving the table declaration outside of the Enums declaration:

local SkillUseBasis: SkillUseBasisEnum = {
	Cast = 1,
	Channel = 2,
	Attack = 3,
	Exert = 4
}
local Enums: NLEnums = {
	SkillUseBasis = SkillUseBasis
}

Add Web REPL using Emscripten

As for code tester - we'd love to get this! I think the easiest path is to build Luau REPL using Emscripten to WASM and create an HTML wrapper around it. Pull requests with that functionality are welcome, feel free to create a separate feature request for that.

Originally posted by @zeux in #120 (comment)

Create a demo page similar to Lua's on the doc site.

PR #138 closes this.

Extend table allocation options (e.g. table fill & resize)

Currently, luau implements two very nice functions for table allocation: table.move & table.create
However, luau doesn't offer much support at all for doing our own reallocations of tables, such as filling and shrinking/growing (resizing). table.move and table.create both are useful for allocating new data, and rearranging existing data, however, these still limit the prior two use cases with overhead.

All of these do one-time allocations, and perform bulk table changes, which is important because it allows for reducing the computational cost of a lot of code in a very general way. (Which especially applies to porting many lower level algorithms or assembly langs into luau, but also applies directly to DOD code which benefits the most)

I also got a little carried away with my nerding, decided to embrace it and pretty much wrote a whole entire RFC (a wack one) for this, even though it's probably really excessive. I will probably make a PR since the implementation of the two proposed functions should be quick. Not sure though.

Pretty much an RFC??

Proposed APIs

  • table.resize(table, newSize) - Resizes the input array to the input size
    Possibly just a wrapper to luaH_resizearray with extra sanity and validation?
  • table.fill(table, indexA, indexB, value) - Writes value from indexA, to indexB into the array, resizing it if necessary.

Considered alternatives

I considered table.move for trying to perform resizes, but it will only resize a table to allow for all of the elements being moved to fit (plus it's not particularly elegant). This does not allow us to grow tables, or shrink them (which, in comparison would be a bit ambiguous and could be reasonable to address separate to growing). It also does not allow us to do bulk writes to existing tables without allocation overhead (fill).

While table.create has the desired fill behaviour for tables and could be combined with table.move to get a decently close alternative, it allocates a brand new table, which is probably not something we would really like when we might want to be dynamically resizing a table for DOD, say, a big list of debris data. We basically double the amount of writes, and allocate a new, potentially large table.

Justification of incompleteness

The implementation of both of these behaviours would make the implementations of both other functions possible to write direct pure luau ports of. For example, table.create & table.move both essentially can be thought of as utilizing both underlying features.

This might make the two seem redundant, but I would argue that because all four of these behaviours exist in other places as their own instructions (e.g. WASM) as well as the justification that the reduced overhead is desirable for where any of these functions would be desired to be used.

Because both the table.move & table.create functions don't have direct pure lua ports in luau without requiring excessive allocations, I would argue that this justifies incompleteness, considering that the use cases of the proposed functions are general and used in luau as general utilities, which are non specific.

Example in WASM

There are two cases I found being used in a lot of lower level algorithms which also apply generally, table filling, and table shrinking/growing (resizing), for example, WebAssembly has a comparable table system to lua. This system actually has two instructions that luau has, table.move is essentially a 1:1 implementation of WASM's table.copy instruction, and table.create is essentially a 1:1 implementation of WASM's table.init instruction

WASM offers both the ability to fill, and the ability to (limitedly) resize tables.

Feedback: should we use -Werror & /WX only in CI?

Right now both Makefile and CMakeLists.txt treat warnings as errors unconditionally.

In general we'd like to be warning-free if possible. But due to the multitude of compilers and compiler versions this isn't a guarantee that is going to be easy for us to provide. We'll keep hitting random warnings from random compilers on random architectures.

Right now when a warning like that is encountered, it blocks progress for the users or distributions. Which doesn't seem ideal.
Of course if we simply remove these flags, we'll just start accumulating warnings on our primary supported systems which is not healthy.

Considering adding flags to both build infras to enable warnings-as-errors and keep the off by default, but enable in CI. The downside is that developers may ignore these when developing locally, but the CI will catch it so it's probably fine. Some warnings due to build misconfiguration may be more important than others, so it's not always safe to ignore all of them either...

Looking for feedback. I know different projects have different sensibilities around this.

ltable.h:12:15: error: static_assert expression is not an integral constant expression

It looks like my compiler is having a problem with this code:

static_assert(offsetof(LuaNode, val) == 0, "Unexpected Node memory layout, pointer cast below is incorrect");

It gives these errors:

  ltable.h:12:15: error: static_assert expression is not an integral constant expression
  ltable.h:12:15: note: cast that performs the conversions of a reinterpret_cast is not allowed in a constant expression
  ltable.h:12:15: error: static_assert expression is not an integral constant expression

Due to the build process being magical, I'm not sure exactly which compiler is being used to compile this. Probably MSVC, but I don't know which one (because Windows is Windows).

Meson build system support

Any chance to support meson build system as subproject or pull request with this is approve in master in future?

Missing option LUA_GCCOUNTB

This option for lua_gc seems to be missing:
LUA_GCCOUNTB: Returns the remainder of dividing the current amount of bytes of memory in use by Lua by 1024

It's useful when doing fine-grained Lua memory profiling (e.g. calculating the delta before and after a Lua function call). Is there a reason why it has been removed? Would you accept a pull request that adds it?

Compilation error while running the test suite

As I was working on a PR, I ran into an error while trying to run the test suite:

/usr/include/c++/11.1.0/ostream:773:5: error: no type named ‘type’ in ‘struct std::enable_if<false, std::basic_ostream<char>&>’
In file included from (..)/luau/tests/Fixture.cpp:11:
(..)/luau/extern/doctest.h: In instantiation of ‘struct doctest::detail::has_insertion_operator_impl::check<const std::optional<const Luau::TypeVar*>, void>’:
(..)/luau/extern/doctest.h:881:8:   required from ‘struct doctest::StringMaker<std::optional<const Luau::TypeVar*> >’
(..)/luau/extern/doctest.h:907:35:   required from ‘doctest::String doctest::toString(const T&) [with T = std::optional<const Luau::TypeVar*>; typename doctest::detail::enable_if<(! doctest::detail::is_enum<T>::value), bool>::type <anonymous> = true]’
(..)/luau/extern/doctest.h:1229:53:   required from ‘doctest::detail::Expression_lhs<L>::operator doctest::detail::Result() [with L = std::optional<const Luau::TypeVar*>&]’
(..)/luau/tests/Fixture.cpp:267:5:   required from here

Compiler: g++ (GCC) 11.1.0

Perhaps I am missing some dependency or it's my compiler version. Any idea what could be going wrong?

Improve look and feel of the demo page

The current demo page is somewhat lacking in the looks department and is not very user-friendly. Some of the issues include: lack of tab support in input, no syntax highlighting, and difficult to read output.

I propose that we:

  • Replace input textarea with a rich text box of some sort (e.g. Microsoft's Monaco-Editor)
  • Similarily, replace output textarea with a rich text box. Ignore for time being, textarea is sufficient.

I am not too sure at the moment what the best way to proceed about doing this is. Feedback is very welcome!

Add shebang support

Ignore Unix shebang if it is on the first line of a script, e.g. #!/usr/bin/env luau
It wouldn't ruin any older scripts, as having the first character of a script be # would throw a syntax error.

Add debug.profilebegin and debug.profileend

In Roblox these functions exist for use in Microprofiler. While standalone Luau does not have such Microprofiler, it does have luau --profile option, which generates flame graph of significant function calls.

This flame graph is great for detecting the slowest functions, but there is no easy way how to probe which parts of the function are the slowest. So it would be great if debug.profilebegin and debug.profileend existed, which would add custom labels to the luau CLI generated flame graph.

Documentation: Data types

We now have a documentation page for the libraries (https://luau-lang.org/library). It would be great to get a page that covers data types - ideally including basic commonly used operations (e.g. "this is how you index a string", "this is how you append to the table") and gotchas (ASCII vs Unicode for strings, mixed mode tables, iterating through numeric vs dictionary, 1-based indexing, etc.)

Customizable source path resolution

One of my main use cases for Luau as a tool is in linting Rojo projects.
Having some method of source resolution that allows compatibility with varying project structures in .luaurc or as a command line argument would be really useful, and I can't really use luau-analyze without some custom resolution for require paths.

A possible way to do this would be adding a callback to .luaurc, which should be a luau function that takes in the expression being required, and returns a string file path.

Alternatively, some way to inject game, workspace, and script as environment variables that specifically link to a source file (perhaps requiring a table that has a __tostring metamethod should require the path at that returned string?) would be helpful.

Inconsistency with lua_ref

Given the following program with regular Lua 5.1:

int main()
{
        lua_State* L = luaL_newstate();

        const char* source = "return \"test\"";
        size_t sourceSize = strlen(source);

        luaL_loadbuffer(L, source, sourceSize, "test");
        lua_call(L, 0, 1);

        printf("type = %d\n", lua_type(L, -1));

        int r = luaL_ref(L, LUA_REGISTRYINDEX);
        lua_rawgeti(L, LUA_REGISTRYINDEX, r);

        printf("type = %d\n", lua_type(L, -1));

        lua_close(L);
        return 0;
}

The output is, as one would expect:

type = 4
type = 4

When the following similar program is run on Luau:

int main()
{
	lua_State* L = luaL_newstate();

	const char* source = "return \"test\"";
	size_t sourceSize = strlen(source);

	size_t bytecodeSize;
	char* bytecode = luau_compile(source, sourceSize, nullptr, &bytecodeSize);
	luau_load(L, "test", bytecode, bytecodeSize, 0);
	lua_call(L, 0, 1);

	printf("type = %d\n", lua_type(L, -1));

	int r = lua_ref(L, LUA_REGISTRYINDEX);
	lua_rawgeti(L, LUA_REGISTRYINDEX, r);

	printf("type = %d\n", lua_type(L, -1));

	lua_close(L);
	return 0;
}

The types are suddenly different:

type = 5
type = 6

With 5 being LUA_TSTRING and 6 being LUA_TTABLE.

Perhaps I'm missing something in the difference between lua_ref and luaL_ref, but this seems wrong to me on first sight.

Unused variable prevents compilation

Line 2382 in AST/src/Parser.cpp has an unused variable seenPack, it's set but never used.

https://github.com/Roblox/luau/blob/279855df91d522bb65739631e3ee74e94192b817/Ast/src/Parser.cpp#L2382-L2433

Should this be removed or used in a similar fashion as seen here:
https://github.com/Roblox/luau/blob/279855df91d522bb65739631e3ee74e94192b817/Ast/src/Parser.cpp#L2341-L2354

It currently prevents compilation when using MinGW due to the warning-as-error flag set in CMakeLists.txt.

image

Remove LUALIB_API from method definitions

Now it is to my understanding the LUA_API and LUALIB_API are macros to help aid in the exporting of methods you would likely use. This is extremely handy for say disabling name managing via extern C and exporting in dynamic libraries via declspec to improve interop with other languages without modifying the source code tediously too much.

In most cases this does fine however declspec specifically can only go on method declarations and can't go on definitions with bodies which will cause a C2491 compile error. The main culprit of this seems to be the built-in libraries using LUALIB_API ,luaopen_math being a prime example here.

These macros should only exist on method declarations to make interop more seamless.

Allow outputting the binary bytecode blob from CLI

As a Luau CLI user, I would find it handy if the CLI application had an option to output a binary bytecode blob, so that it would be easier to achieve interoperability between programs. The binary format would be far easier for a 3rd-party program to parse compared to the textual representation that is currently dumped. Of course, this need not be the default behaviour of the CLI.

For example, I could use the Luau CLI like this:
luau --compile --binary script.lua > bytecode.luac
And following this, there would be a bytecode.luac file created, containing the bytecode as given by Luau::Compiler::compile.

Another interesting idea could be to allow the loading and execution of precompiled binary bytecode blobs.

__namecall invoked with incorrect arguments

I'm setting up a metatable like this:

	luaL_newmetatable(L, "moduleMetatable");
	lua_pushstring(L, "__index");
	lua_pushcfunction(L, lua_module_index, nullptr);
	lua_settable(L, -3);
	lua_pushstring(L, "__newindex");
	lua_pushcfunction(L, lua_module_newindex, nullptr);
	lua_settable(L, -3);
	lua_pushstring(L, "__namecall");
	lua_pushcfunction(L, lua_module_namecall, nullptr);
	lua_settable(L, -3);
	lua_setreadonly(L, -1, true);
	lua_pop(L, 1);

...

	lua_pushlightuserdata(L, pointer);
	luaL_getmetatable(L, "moduleMetatable");
	lua_setmetatable(L, -2);
static int lua_module_namecall(lua_State* L)
{
	Type* pointer = static_cast<Type*>(lua_touserdata(L, 1));

	if (const char* methodName = lua_namecallatom(L, nullptr))
	{
	}
}

__index and __newindex are working fine but when __namecall is invoked the arguments are incorrect: I have debugged several runs and every time the arguments seems to have different types and values.
Sometimes the first argument is a bool, sometime a number and even when is a userdata the void* pointer is pointing at a random location.

Change _VERSION to display the version of Luau

currently _VERSION just returns "Luau"

it feels more useful if _VERSION would return the version of luau running like this: "0.503"

this would be much more beneficial for testing / analytics
also being able to find which version of luau would make it way easier to track errors and see if there fixed when a new version of luau is out

Screenshot 2021-11-08 at 10 03 56

right now there's no way for me to tell if the above is luau 0.503 or luau 0.501

I can't really think of any cons to this change but feel free to mention anything

Proposed change:
change the global _VERSION to return "Luau 0.503"
that maintains backwards compatibility with files only checking if the Version contains the string "Luau"

this is how Lua displays _VERSION
Screenshot 2021-11-08 at 10 38 58

"Luau 0.503" basically matches the format for that but it could be shortened to only major and minor builds like "Luau 0.5" or "Luau 0.5x"

the main use case for this is to easily see what version of Luau is running from within Luau

copytoclipboard

hi, i am a big fan on lua and luau, i have a request for a command called "copytoclipboard", it would copy a set piece of text to your clipboard, like copying and pasting, thanks - droid

Are RFCs still restricted to team members now that Luau has been FOSS'd?

Referring to: https://github.com/Roblox/luau/blob/master/rfcs/README.md#process

Note: we currently don't accept community contributions for RFCs, although this will likely change in the future.

I'm not affiliated with Roblox but would like to propose an RFC that has been a long-standing headache with PUC-Rio Lua that I think would benefit something like Luau and would certainly motivate me to switch some of my projects over to it.

Is it still the case that community-contributed RFCs are not being accepted now that Luau has been open-sourced?

Suggest and use a file extension other than `.lua`

As Luau grows as a language, it's gotten less and less compatible with normal Lua 5.1. It seems prudent to start using an extension that isn't .lua to allow tooling to make a distinction between the two languages.

This has some implications for Roblox as it allows .lua files to be loaded both with Run Script and local pluins at the moment, so it cannot be community driven. I'm not sure of the work that goes into this on your end but it would have to be on Roblox to support it.

My suggestion is .luau but anything works as long as it isn't .lua

Reduce reliance on C++ types in the public API

I understand how Luau evolved to contain so much C++, especially as Roblox uses C++ internally for the game engine and many other things.

Whatever is used for the implementation, C++ in the header files specifically raises lots of portability concerns. For example, most languages are simply unable to process C++ templates in any capacity, let alone classes.

I'm trying to create bindings to Luau so that I can use it from Rust, but bindgen famously cannot understand templates at all, and I don't imagine other languages have any solutions either. Furthermore, it's not even possible to use any templated functions or classes because templates require expansion before use.

This problem mostly attributes itself to the 500+ uses of STL types in the header files, specifically AST, Compiler and Analysis, which is pretty much 3/4ths of the project at this point.

  • Analysis is the worst offender, using STL types at least 400 times;
  • AST is next, with slightly over 100 uses;
  • Compiler uses STL types around 30 times;
  • VM uses it 0 times

Using any module other than VM (compiler especially, compiler is quite important) from another programming language is currently extremely difficult, manual, and error-prone with the current API surface. STL types are generally magical and cannot be understood by any language that is not C++, so it's usually best to keep them as implementation details, not exposed in the public API as they are now. Automated tools cannot digest them so all FFI must be done manually by a human which can introduce subtle memory bugs and undefined behavior just like that.

Luau is already in its situation with template types everywhere. Is it even possible to solve this now?

Add a SECURITY.md file

The current way of reporting vulnerabilities is through the hackerone program.

However this isnt immediatly clear so we should add a SECRURITY.md file

Suggestion: Function Hooking

In many popular script utilities (exploits) there were custom functions made for function hooking. While exploiting is obviously not favorable, I personally think that this aspect is actually quite interesting and useful. Unlike how script utilities modify the enviorment of every script, if something like this was implemented it could follow the standard in Luau of only affecting it's own enviorment and functions as opposed to every single script on the client/server, which is obviously a huge security concern. Functions like hookfunction and newcclosure have always been very interesting to me, and I thought it could be a possibility to be very cool!

string.pack not throwing overflow error

So I build luau as normal and ran make test
Screenshot 2021-11-07 at 21 23 15

what's happening is that its expecting string.pack("<I" .. I, -1) to throw an error but it doesn't it actually just returns nothing

after more testing using this simple command line version of what that script is doing
for i = 1, 3 do local umax = bit32.lshift(1, i * 8) - 1 local max = bit32.rshift(umax, 1) local min = -max-1 print("Testing") print("Result = ",pcall(string.pack, "<I" .. i, min)) end

I found that it works as intended in Roblox Studio
Screenshot 2021-11-07 at 21 29 31

but fails in luau
Screenshot 2021-11-07 at 21 31 01

so I'm just assuming the function isn't throwing an overflow error for whatever reason

weirdly enough what I run unpack on the packed string it produces this in luau
Screenshot 2021-11-07 at 21 36 43

whereas in Roblox it well...
Screenshot 2021-11-07 at 21 38 47

again for convenience here is the code for that simple test
for i = 1, 3 do local umax = bit32.lshift(1, i * 8) - 1 local max = bit32.rshift(umax, 1) local min = -max-1 print("Testing") print(string.unpack(string.pack("<I" .. i, min), "<I")) end

compiled using: make config=release luau luau-analyze
compiled version: 0.503 (latest release I just downloaded the repo)

a few things to note:
I tried running make test multiple times always failed
I tried reinstalling the tests still failed
I tried compiling with cmake it still failed

its a pretty weird bug how it works in Roblox tests but not in luau tests

should also mention I'm running macOS Monterey Version 12.0.1 (21A559)
Apple M1 chip

oh and final note is that it fails for all overflow errors not just the <I one I showed off in tests that's just the first one that fails in make test

Native Integers (5.3 backport)

This is a feature in lua 5.3 and beyond, which breaks the number type internally into two new types, integer and float.

Currently, luau numbers are doubles, which offers 53 bits of lossless integer precision. Having the capability for 64 bit computation in luau would extend to a wide variety of algorithms, improving performance in cases where they are required.

Pros:

  1. General support for programs which require 64 bit computation
  2. Better performance for those programs & ease of implementation
  3. Explicit typing capability for integers vs doubles
  4. Doesn't increase memory usage (doubles are already 64 bit)

Cons:

  1. Potentially complex implementation (I am unsure 😎)
  2. Source utilizing 32 bit integers would eliminate any potential to actually benefit from 64 bit precision, potentially requiring changes to guarantee full support
  3. Requires logic to decide when to use a double and when to use an integer, and logic to determine when to convert between the two. (i.e. 3/4 must be a double to be represented, is 4/2, or 10/5 represented as a float? How can this be done performantly?)
  4. The backwards compatability complications addressed by @Halalaluyafail3 below, which lua 5.3 and beyond fails to address

Mechanism for adding new fastcall functions

This isn't too hard in practice, if the user can recompile Luau for their application (they should be compiling and linking it statically anyway!!):

  • First, add a new function to luauF_table in VM/src/lbuiltins.cpp - this will require you to reimplement your function in the luau_FastFunction format - look at the builtins for inspiration:

    static int luauF_abs(lua_State* L, StkId res, TValue* arg0, int nresults, StkId args, int nparams)
    {
        if (nparams >= 1 && nresults <= 1 && ttisnumber(arg0))
        {
            double a1 = nvalue(arg0);
            setnvalue(res, fabs(a1));
            return 1;
        }
    
        return -1;
    }

    And remember to follow the rules listed at the top of lbuiltins.cpp while implementing:

    // luauF functions implement FASTCALL instruction that performs a direct execution of some builtin functions from the VM
    // The rule of thumb is that FASTCALL functions can not call user code, yield, fail, or reallocate stack.
    // If types of the arguments mismatch, luauF_* needs to return -1 and the execution will fall back to the usual call path
    // If luauF_* succeeds, it needs to return *all* requested arguments, filling results with nil as appropriate.
    // On input, nparams refers to the actual number of arguments (0+), whereas nresults contains LUA_MULTRET for arbitrary returns or 0+ for a fixed-length return
    // Because of this, and the fact that "extra" returned values will be ignored, implementations below typically check that nresults
    // is <= expected number, which covers the LUA_MULTRET case.
  • Add a new enum constant to the end of LuauBuiltinFunction in Compiler/include/Luau/Bytecode.h (make sure it matches up with the index of the function in luauF_table)

  • Add a new block to the end of getBuiltinFunctionId in Compiler/src/Compiler.cpp that returns the new constant

  • And do all this before compiling or executing any code (obviously)

Right now, there is exactly one opportunity for third-party code to add a fastcall function - the vector constructor. (The third-party code doesn't get any control over the implementation of this function, however.) Anything else requires reaching into internal implementation details:

  • modifying luauF_table
  • not being able to modify the compiler
  • messing with the bytecode afterwards to add LOP_FASTCALL?? (but you'll also have to change the call strategy a bit as well... this isn't very feasible)

For vectors, CompileOptions.vectorCtor needs to be set to a string containing the function name, and also define vectorLib if your vector constructor lives inside a global table. For Roblox, vectorCtor == "new" and vectorLib == "Vector3".


A bit of a mess. I can make a PR, but this would require exposing implementation details and contracts of fastcall functions to the outside. Let me know if that's acceptable.

disable breakpoints not working

Discussed in #212

luaG_breakpoint() at line 319 the op variable is equal LOP_BREAK also when enable is false:
uint8_t op = enable ? LOP_BREAK : LUAU_INSN_OP(p->code[i]);
should be:
uint8_t op = enable ? LOP_BREAK : LUAU_INSN_OP(p->debuginsn[i]);

Performance benchmarks and comparisons to other compiler projects

The text on performance is nice and all, but doesnt show benches + time differences for the intended use case of sandboxing + jitting.

For many explanation like "Reduced garbage collector" its not evident to me with examples how "competitors" do it. It might make sense to create references or elaborate this as examples.

Free lua_States and threads

I'm tring to embeed the VM, the idea is to create varius lua_States and threads to execute scripts but I cant find how to free states and threads from memory.

I'm missing something or the methods are not exposed?

Support table keys destructuring and spread

Concept

Recently the language has gained support to if-then-else expressions, which shortened the way we deal with conditional values, rather than using if statements. On that note, I'd like to suggest adding support to tables destructuring and spread the same way typescript does with objects.

That way it would not only bring a key into the scope without needing to create a variable for the table and for every key we want to use, but also make our code a lot smaller. Of course, in Luau's case, that would only apply to string indexes, since we can make a tuple via table.unpack and reference the returned values likewise.

Examples

Merging dictionaries

Currently there is not way to destructure string indexed values in a table, and we cannot call unpack to do so, since that's used for number indexed values to return tuples, like said before. If we wanted to do so, we would need to create an utility function for that case. (e.g. merge, assign)

To resolve that problem, we could use ... as the spread operator, just like we do when handling varargs, but instead placing it before a table reference, inside a table.

For example, here we want to create a new table that contains all the keys from t1 and t2:

Current

local t1 = { a = 5 }
local t2 = { b = 10, c = 20 }

local newTbl = {}

local function assign(t)
    for k, v in pairs(t) do
        newTbl[k] = v
    end
end

assign(t1)
assign(t2)

print(newTbl) -- { ["a"] = 5, ["b"] = 10, ["c"] = 20 }

With spread

local t1 = { a = 5 }
local t2 = { b = 10, c = 20 }

print({ ...t1, ...t2 }) -- { ["a"] = 5, ["b"] = 10, ["c"] = 20 }

For the record, we could also do the same above without variables:

{ ...{ a = 5 }, ...{ b = 10, c = 20 } }

Referencing Keys

Let's say we have the functions foo and bar. Both takes as a parameter a destructured table.

  • foo prints the result of the sum of x and y.
  • bar prints the result of x * y * z, but x is the only key that is being directly referenced.
type Point = { x: number, y: number }
type ExtendedPoint = { x: number, y: number, z: number }

Current

local function foo(point: Point)
    print(point.x + point.y)
end

local function bar(point: ExtendedPoint)
    print(point.x * point.y * point.z)
end

foo({ x = 1, y = 2 })
bar({ x = 10, y = 20, z = 30 })

With destructuring

local function foo({ x, y }: Point)
    print(x + y)
end

local function bar({ x, ...rest }: ExtendedPoint)
    print(x * rest.y * rest.z)
end

foo({ x = 1, y = 2 })
bar({ x = 10, y = 20, z = 30 })

Using spread inside a table that is already being destructured, creates a new table that contains all the keys that were not referenced like x.

Nested Tables

local props = {
    a = { name = "fizz" },
    b = { name = "buzz" },
    c = { name = "fizzbuzz" }
}

local {
    a = { name = fizzVar },
    b = { name = buzzVar },
    c = { name = fizzbuzzVar }
} = props

print(fizzVar, buzzVar, fizzbuzzVar) -- fizz buzz fizzbuzz

Key Assignment

In addition, it would also be nice to assign the reference of a key to a new one:

local { foo = a, bar = b, baz = c } = { foo = "luau", bar = 3, baz = true }

assert(a == "luau")
assert(bar == 3) -- Should error, because the key reference was assigned to "b"

This would be a great alternative to creating variables for aliases when working with libraries that returns a dictionary (e.g. roact):

local { Component, createElement = e } = require(Packages.Roact)

local Button = Component:extend("Button")

function Button:render()
    return e("TextButton", ...)
end

Documentation: More comprehensive language tutorial

Would it be possible to add a few examples? Either directly on the main
README, or perhaps better as a small directory that could be distributed
too. Just a few examples, ideally with some comments to semi-advanced
users starting with hello world, over to doing some more useful things
(e. g. handling output, perhaps colours, hashes, arrays ..). Does not
need to include many examples; I assume you may say it is not so
much different to lua, but crystal was once said as "it is just ruby
really" and it's quite a different language nowadays IMO.

Add a note in docs not to use os.difftime

os.difftime is basically t1-t2

and the usage of it is already discoraged because of "provided for compatibility."

However I don't believe this is quite clear enough, and some people may accidentally use difftime because they dont know that it shouldn't be used.

Documentation: Grammar

We need a grammar page which is essentially https://www.lua.org/manual/5.4/manual.html#9 but for Luau.

Float4 vectors

Are there any plans to support float4 natively? I understand float4 does not fit into the tagged value currently. However, there are major use cases for float4s like HDR RGBA colors and quaternions (for representing 3D rotations), which could be much faster with a native float4 type.

I've previously expanded tagged values in Lua 5.1 and 5.4 to contain a float4 vector without significant performance penalty on x64. Eliminating the GC pressure outweighs the slowdown of a few percent that we noticed in our benchmarks. This change increased the tagged value from 16 bytes to 24 bytes. Naturally, Luau perf profile might be different because it is so highly optimized compared to vanilla Lua...

Another alternative is to implement float4s as userdata but that will have potentially heavy GC cost in some applications such as games.

If adding native float4 is not desirable for Roblox, are you open to the idea of supporting it optionally via compile time conditional (i.e. some ifdef)?

Consider using SemVer for versioning

It would be helpful to use semver for Luau's version as this allows for meaningful major (breaking)/minor (feature)/patch (fix) versions and is quite familiar to most developers in the industry.

This would open up the possibility for those using Luau to specify version ranges which gives better expectations over what a project is consuming. For example, if my project consumed Luau ^1.0.0, I would have certainty that I could update Luau and not worry about automatically consuming breaking changes since I would be locked to 1.x.x.

I imagine that given our policy at Roblox, Luau will always be backwards compatible so major versions would likely have a different meaning, however it would be helpful to at least have meaningful minor and patch releases that can be compared between each other.

See this NPM blog post for more info.

luau-analyze reports errors from other files.

When luau-analyze reports errors from a file, it also reports errors from its required modules as if they were from that file.

PS C:\Users\andre\Desktop\test> luau-analyze .
./main.lua(7,1): TypeError: Argument count mismatch. Function expects 1 argument, but none are specified
./main.lua(3,15): TypeError: Type 'number' could not be converted into 'string'
./test.lua(7,1): TypeError: Argument count mismatch. Function expects 1 argument, but none are specified

main.lua requires test.lua, which as an "Argument count mismatch" error, which is reported twice.

The same happens when using --formatter=plain, or when running luau-analyze main.lua,

luau-analyze main.lua --formatter=plain
main.lua:7:1-12: (W0) TypeError: Argument count mismatch. Function expects 1 argument, but none are specified
main.lua:3:15-15: (W0) TypeError: Type 'number' could not be converted into 'string'

It seems that this only happens with Syntax and Type errors.

Tested using pre-built release v0.503 in Windows.

Cannot compile Luau.Repl.CLI on Android device from Termux

When compiling the Luau CLI (Luau.Repl.CLI) from a Android device via Termux, the following error below will appear:

luau/CLI/FileUtils.cpp:156:24: error: use of undeclared identifier 'IFTODT'
                type = IFTODT(st.st_mode);
                       ^
1 error generated.
make[3]: *** [CMakeFiles/Luau.Repl.CLI.dir/build.make:76: CMakeFiles/Luau.Repl.CLI.dir/CLI/FileUtils.cpp.o] Error 1
make[2]: *** [CMakeFiles/Makefile2:261: CMakeFiles/Luau.Repl.CLI.dir/all] Error 2
make[1]: *** [CMakeFiles/Makefile2:268: CMakeFiles/Luau.Repl.CLI.dir/rule] Error 2
make: *** [Makefile:202: Luau.Repl.CLI] Error 2

Screenshot_20211104-235510_Termux

Notes:

  • Luau CLI compiles fine on my laptop (running at x86_64 arch, tested at Linux)
  • The Luau AST, VM, and Compiler libraries can compile normally (only the CLI has this issue)

Device used to compile:
Samsung Galaxy S20 FE SM-G780G
8 GB of RAM
Snapdragon 865 (ARM64)
Android 11 One UI 3.1 (Android security patch level October 1 2021)

Commands used:

git clone https://github.com/Roblox/luau.git
cd luau && mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=RelWithDebInfo
cmake --build . --target Luau.Repl.CLI

EDIT 1: Added more information
EDIT 2: Typo fix

Vector indexing not working from REPL

This is a strange one. For some reason vector indexing behaves erratically from REPL:

$ ./luau
> a = vec(1, 2, 3)
> a.x
stdin:1: attempt to index vector with 'x'
stack backtrace:
stdin:1
> print(a.x)
stdin:1: attempt to index vector with 'x'
stack backtrace:
stdin:1
> a["x"]
1

Note that vectorCtor = "vec" needs to be set in CompileOptions in order to reproduce this.

The problem does not occur if the code is compiled in single chunk:

> a = vec(1, 2, 3); print(a.x)
1

luaL_checkbool()

I'm trying to check if a C function is called with the correct number and type of argument.
I see luaL_checkstring(), luaL_checknumber() but no luaL_checkbool().

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.