Skip to content

Commit

Permalink
added luau.parse
Browse files Browse the repository at this point in the history
  • Loading branch information
plusgiant5 authored and plusgiant5 committed Jan 1, 2025
1 parent 9b591bb commit 96ac9a0
Show file tree
Hide file tree
Showing 8 changed files with 179,173 additions and 18 deletions.
2 changes: 1 addition & 1 deletion runluau-graphics/lib.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ void create_window_thread(lua_State* thread, yield_ready_event_t yield_ready_eve
int width = luaL_checkinteger(thread, 1);
int height = luaL_checkinteger(thread, 2);
const char* title = luaL_optstring(thread, 3, "Window");
double pixel_size = luaL_optnumber(thread, 4, 1);
unsigned int pixel_size = luaL_optunsigned(thread, 4, 1);

int win_width = width * pixel_size;
int win_height = height * pixel_size;
Expand Down
222 changes: 213 additions & 9 deletions runluau-luau/lib.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,33 +2,32 @@

int compile(lua_State* thread) {
wanted_arg_count(1);
size_t source_length;
const char* source_c_str = luaL_checklstring(thread, 1, &source_length);
std::string source = luau::checkstring(thread, 1);
Luau::CompileOptions options;
options.optimizationLevel = 1;
options.debugLevel = 1;
if (lua_gettop(thread) >= 2) {
luaL_checktype(thread, 2, LUA_TTABLE);
if (lua_getfield(thread, 2, "optimizationLevel")) {
unsigned int optimization_level = luaL_checkunsigned(thread, -1);
unsigned int value = luaL_checkunsigned(thread, -1);
lua_pop(thread, 1);
if (optimization_level > 2) {
if (value > 2) {
lua_pushstring(thread, "When compiling, optimizationLevel must be an integer from 0 to 2");
lua_error(thread);
}
options.optimizationLevel = optimization_level;
options.optimizationLevel = value;
}
if (lua_getfield(thread, 2, "debugLevel")) {
unsigned int debug_level = luaL_checkunsigned(thread, -1);
unsigned int value = luaL_checkunsigned(thread, -1);
lua_pop(thread, 1);
if (debug_level > 2) {
if (value > 2) {
lua_pushstring(thread, "When compiling, debugLevel must be an integer from 0 to 2");
lua_error(thread);
}
options.debugLevel = debug_level;
options.debugLevel = value;
}
}
std::string bytecode = Luau::compile(std::string(source_c_str, source_length), options, {});
std::string bytecode = Luau::compile(source, options, {});
if (bytecode.data()[0] == '\0') {
lua_pushlstring(thread, bytecode.data() + 1, bytecode.size() - 1);
lua_error(thread);
Expand All @@ -38,9 +37,214 @@ int compile(lua_State* thread) {
return 1;
}

// `set` functions expect a table at top of stack
inline void set_boolean(lua_State* thread, bool value, const char* field) {
lua_pushboolean(thread, value);
lua_setfield(thread, -2, field);
}
inline void set_unsigned(lua_State* thread, unsigned int value, const char* field) {
lua_pushunsigned(thread, value);
lua_setfield(thread, -2, field);
}
inline void push_size_t(lua_State* thread, size_t value) {
lua_pushnumber(thread, static_cast<lua_Number>(value));
}
inline void set_number(lua_State* thread, lua_Number value, const char* field) {
lua_pushnumber(thread, value);
lua_setfield(thread, -2, field);
}
inline void set_number(lua_State* thread, size_t value, const char* field) {
push_size_t(thread, value);
lua_setfield(thread, -2, field);
}
inline void set_string(lua_State* thread, std::string value, const char* field) {
luau::pushstring(thread, value);
lua_setfield(thread, -2, field);
}
inline std::string position_to_string(Luau::Position pos) {
return std::to_string(pos.line) + ',' + std::to_string(pos.column);
}
inline void set_location(lua_State* thread, Luau::Location location, const char* field = "location") {
set_string(thread, position_to_string(location.begin) + " - " + position_to_string(location.end), field);
}
void push_ast(lua_State* thread, const simdjson::dom::element& element) {
switch (element.type()) {
case simdjson::dom::element_type::OBJECT:
lua_newtable(thread);
for (auto [key, value] : element.get_object()) {
lua_pushlstring(thread, key.data(), key.size());
push_ast(thread, value);
lua_settable(thread, -3);
}
break;
case simdjson::dom::element_type::ARRAY:
{
lua_newtable(thread);
const auto& arr = element.get_array();
for (size_t i = 0; i < arr.size(); ++i) {
push_size_t(thread, i + 1);
push_ast(thread, arr.at(i));
lua_settable(thread, -3);
}
break;
}
case simdjson::dom::element_type::BOOL:
lua_pushboolean(thread, element.get_bool().value_unsafe());
break;
case simdjson::dom::element_type::STRING:
{
const auto& string = element.get_string().value_unsafe();
lua_pushlstring(thread, string.data(), string.size());
break;
}
case simdjson::dom::element_type::DOUBLE:
lua_pushnumber(thread, element.get_double().value_unsafe());
break;
case simdjson::dom::element_type::INT64:
{
const auto& string = std::to_string(element.get_int64().value_unsafe());
lua_pushlstring(thread, string.data(), string.size());
break;
}
case simdjson::dom::element_type::UINT64:
{
const auto& string = std::to_string(element.get_uint64().value_unsafe());
lua_pushlstring(thread, string.data(), string.size());
break;
}
case simdjson::dom::element_type::NULL_VALUE:
lua_pushnil(thread);
break;
default:
[[unlikely]]
lua_pushfstring(thread, "<UNKNOWN TYPE %d>", element.type());
break;
}
}
// This is what ChatGPT is good for
std::string replace_outside_quotes(
const std::string& input_str,
const std::string& search_str,
const std::string& replace_str
) {
std::string result;
result.reserve(input_str.size());

bool in_quotes = false;
int backslash_count = 0;
size_t i = 0;

while (i < input_str.size()) {
char c = input_str[i];

if (in_quotes) {
result.push_back(c);

if (c == '\\') {
backslash_count++;
} else {
if (c == '"' && (backslash_count % 2 == 0)) {
in_quotes = false;
}
backslash_count = 0;
}
++i;
} else {
if (c == '"') {
in_quotes = true;
result.push_back(c);
++i;
backslash_count = 0;
} else {
if (!search_str.empty()
&& i + search_str.size() <= input_str.size()
&& input_str.compare(i, search_str.size(), search_str) == 0) {
result += replace_str;
i += search_str.size();
} else {
result.push_back(c);
++i;
}
}
}
}

return result;
}
bool push_parseresult(lua_State* thread, Luau::ParseResult parsed) {
lua_newtable(thread);

set_number(thread, parsed.lines, "lines");
lua_newtable(thread);
for (size_t i = 0; i < parsed.hotcomments.size(); ++i) {
const auto& hotcomment = parsed.hotcomments[i];
push_size_t(thread, i + 1);
lua_newtable(thread);
set_location(thread, hotcomment.location);
set_string(thread, hotcomment.content, "content");
set_boolean(thread, hotcomment.header, "is_header");
lua_settable(thread, -3);
}
lua_setfield(thread, -2, "hotcomments");
lua_newtable(thread);
for (size_t i = 0; i < parsed.errors.size(); ++i) {
const auto& error = parsed.errors[i];
push_size_t(thread, i + 1);
lua_newtable(thread);
set_location(thread, error.getLocation());
set_string(thread, error.getMessage(), "message");
lua_settable(thread, -3);
}
lua_setfield(thread, -2, "errors");
std::string ast_json = Luau::toJson(parsed.root, parsed.commentLocations);
ast_json = replace_outside_quotes(ast_json, "-Infinity", "\"-Infinity\"");
ast_json = replace_outside_quotes(ast_json, "Infinity", "\"Infinity\"");
ast_json = replace_outside_quotes(ast_json, "NaN", "\"NaN\"");
set_string(thread, ast_json, "ast_json");
simdjson::dom::parser parser;
simdjson::dom::element ast;
simdjson::error_code error = parser.parse(ast_json).get(ast);
if (error) {
lua_pushfstring(thread, "Failed to parse Luau's JSON: %s", simdjson::error_message(error));
lua_error(thread);
return false;
}
push_ast(thread, ast);
lua_setfield(thread, -2, "ast");
return true;
}
int parse(lua_State* thread) {
wanted_arg_count(1);
size_t len;
const char* source = luaL_checklstring(thread, 1, &len);
Luau::ParseOptions options;
if (lua_gettop(thread) >= 2) {
luaL_checktype(thread, 2, LUA_TTABLE);
if (lua_getfield(thread, 2, "allowDeclarationSyntax")) {
unsigned int value = luaL_checkboolean(thread, -1);
lua_pop(thread, 1);
options.allowDeclarationSyntax = value;
}
if (lua_getfield(thread, 2, "captureComments")) {
unsigned int value = luaL_checkboolean(thread, -1);
lua_pop(thread, 1);
options.captureComments = value;
}
}
Luau::Allocator allocator;
Luau::AstNameTable names(allocator);
Luau::ParseResult parsed = Luau::Parser::parse(source, len, names, allocator, options);
if (push_parseresult(thread, parsed)) {
return 1;
} else {
return 0; // errored and already called lua_error
}
}

#define reg(name) {#name, name}
constexpr luaL_Reg library[] = {
reg(compile),
reg(parse),
{NULL, NULL}
};
extern "C" __declspec(dllexport) void register_library(lua_State* thread) {
Expand Down
10 changes: 9 additions & 1 deletion runluau-luau/pch.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,12 @@
#include <stdio.h>
#include <Windows.h>

#include "luau.h"
#include "luau.h"

#include <Luau/Allocator.h>
#include <Luau/Ast.h>
#include <Luau/Parser.h>
#include <Luau/Compiler.h>
#include <Luau/AstJsonEncoder.h>

#include "simdjson.h"
14 changes: 8 additions & 6 deletions runluau-luau/runluau-luau.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -122,14 +122,14 @@
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<LanguageStandard>stdcpp20</LanguageStandard>
<LanguageStandard_C>stdc17</LanguageStandard_C>
<AdditionalIncludeDirectories>../../runluau/shared;%LUAUSRC%\CodeGen\include;%LUAUSRC%\Common\include;%LUAUSRC%\VM\include;%LUAUSRC%\Compiler\include;%LUAUSRC%\Ast\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>../../runluau/shared;%LUAUSRC%\CodeGen\include;%LUAUSRC%\Common\include;%LUAUSRC%\VM\include;%LUAUSRC%\Compiler\include;%LUAUSRC%\Ast\include;%LUAUSRC%\Analysis\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
<AdditionalLibraryDirectories>..\..\runluau\luau\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>luau.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>..\..\runluau\luau\$(Configuration);%LUAUSRC%\out\build\x64-debug;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>luau.lib;Luau.Ast.lib;Luau.Compiler.lib;Luau.Analysis.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalOptions>/NOIMPLIB /NOEXP %(AdditionalOptions)</AdditionalOptions>
</Link>
<PostBuildEvent>
Expand All @@ -149,7 +149,7 @@
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<LanguageStandard>stdcpp20</LanguageStandard>
<LanguageStandard_C>stdc17</LanguageStandard_C>
<AdditionalIncludeDirectories>../../runluau/shared;%LUAUSRC%\CodeGen\include;%LUAUSRC%\Common\include;%LUAUSRC%\VM\include;%LUAUSRC%\Compiler\include;%LUAUSRC%\Ast\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>../../runluau/shared;%LUAUSRC%\CodeGen\include;%LUAUSRC%\Common\include;%LUAUSRC%\VM\include;%LUAUSRC%\Compiler\include;%LUAUSRC%\Ast\include;%LUAUSRC%\Analysis\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<DebugInformationFormat>None</DebugInformationFormat>
</ClCompile>
<Link>
Expand All @@ -158,8 +158,8 @@
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>false</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
<AdditionalDependencies>luau.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>..\..\runluau\luau\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>luau.lib;Luau.Ast.lib;Luau.Compiler.lib;Luau.Analysis.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>..\..\runluau\luau\$(Configuration);%LUAUSRC%\out\build\x64-release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalOptions>/NOIMPLIB /NOEXP %(AdditionalOptions)</AdditionalOptions>
</Link>
<PostBuildEvent>
Expand All @@ -169,6 +169,7 @@
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="pch.h" />
<ClInclude Include="simdjson.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="dllmain.cpp" />
Expand All @@ -179,6 +180,7 @@
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="simdjson.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
Expand Down
6 changes: 6 additions & 0 deletions runluau-luau/runluau-luau.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
<ClInclude Include="pch.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="simdjson.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="dllmain.cpp">
Expand All @@ -29,5 +32,8 @@
<ClCompile Include="lib.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="simdjson.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>
Loading

0 comments on commit 96ac9a0

Please sign in to comment.