mirror of
https://github.com/luau-lang/luau.git
synced 2025-01-08 04:19:09 +00:00
da9d8e8c60
Implements the string interpolation RFC (#165). Adds the string interpolation as per the RFC. ```lua local name = "world" print(`Hello {name}!`) -- Hello world! ``` Co-authored-by: Arseny Kapoulkine <arseny.kapoulkine@gmail.com> Co-authored-by: Alexander McCord <11488393+alexmccord@users.noreply.github.com>
1217 lines
26 KiB
C++
1217 lines
26 KiB
C++
// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details
|
|
#include "Luau/AstJsonEncoder.h"
|
|
|
|
#include "Luau/Ast.h"
|
|
#include "Luau/ParseResult.h"
|
|
#include "Luau/StringUtils.h"
|
|
#include "Luau/Common.h"
|
|
|
|
namespace Luau
|
|
{
|
|
|
|
struct AstJsonEncoder : public AstVisitor
|
|
{
|
|
static constexpr int CHUNK_SIZE = 1024;
|
|
std::vector<std::string> chunks;
|
|
bool comma = false;
|
|
|
|
AstJsonEncoder()
|
|
{
|
|
newChunk();
|
|
}
|
|
|
|
std::string str()
|
|
{
|
|
return join(chunks, "");
|
|
}
|
|
|
|
bool pushComma()
|
|
{
|
|
bool c = comma;
|
|
comma = false;
|
|
return c;
|
|
}
|
|
|
|
void popComma(bool c)
|
|
{
|
|
comma = c;
|
|
}
|
|
|
|
void newChunk()
|
|
{
|
|
chunks.emplace_back();
|
|
chunks.back().reserve(CHUNK_SIZE);
|
|
}
|
|
|
|
void appendChunk(std::string_view sv)
|
|
{
|
|
if (sv.size() > CHUNK_SIZE)
|
|
{
|
|
chunks.emplace_back(sv);
|
|
newChunk();
|
|
return;
|
|
}
|
|
|
|
auto& chunk = chunks.back();
|
|
if (chunk.size() + sv.size() < CHUNK_SIZE)
|
|
{
|
|
chunk.append(sv.data(), sv.size());
|
|
return;
|
|
}
|
|
|
|
size_t prefix = CHUNK_SIZE - chunk.size();
|
|
chunk.append(sv.data(), prefix);
|
|
newChunk();
|
|
|
|
chunks.back().append(sv.data() + prefix, sv.size() - prefix);
|
|
}
|
|
|
|
void writeRaw(std::string_view sv)
|
|
{
|
|
appendChunk(sv);
|
|
}
|
|
|
|
void writeRaw(char c)
|
|
{
|
|
writeRaw(std::string_view{&c, 1});
|
|
}
|
|
|
|
void writeType(std::string_view propValue)
|
|
{
|
|
write("type", propValue);
|
|
}
|
|
|
|
template<typename T>
|
|
void write(std::string_view propName, const T& value)
|
|
{
|
|
if (comma)
|
|
writeRaw(",");
|
|
comma = true;
|
|
writeRaw("\"");
|
|
writeRaw(propName);
|
|
writeRaw("\":");
|
|
write(value);
|
|
}
|
|
|
|
void write(bool b)
|
|
{
|
|
if (b)
|
|
writeRaw("true");
|
|
else
|
|
writeRaw("false");
|
|
}
|
|
|
|
void write(double d)
|
|
{
|
|
char b[32];
|
|
snprintf(b, sizeof(b), "%.17g", d);
|
|
writeRaw(b);
|
|
}
|
|
|
|
void writeString(std::string_view sv)
|
|
{
|
|
// TODO escape more accurately?
|
|
writeRaw("\"");
|
|
|
|
for (char c : sv)
|
|
{
|
|
if (c == '"')
|
|
writeRaw("\\\"");
|
|
else if (c == '\\')
|
|
writeRaw("\\\\");
|
|
else if (c < ' ')
|
|
writeRaw(format("\\u%04x", c));
|
|
else if (c == '\n')
|
|
writeRaw("\\n");
|
|
else
|
|
writeRaw(c);
|
|
}
|
|
|
|
writeRaw("\"");
|
|
}
|
|
|
|
void write(char c)
|
|
{
|
|
writeString(std::string_view(&c, 1));
|
|
}
|
|
void write(int i)
|
|
{
|
|
writeRaw(std::to_string(i));
|
|
}
|
|
void write(long i)
|
|
{
|
|
writeRaw(std::to_string(i));
|
|
}
|
|
void write(long long i)
|
|
{
|
|
writeRaw(std::to_string(i));
|
|
}
|
|
void write(unsigned int i)
|
|
{
|
|
writeRaw(std::to_string(i));
|
|
}
|
|
void write(unsigned long i)
|
|
{
|
|
writeRaw(std::to_string(i));
|
|
}
|
|
void write(unsigned long long i)
|
|
{
|
|
writeRaw(std::to_string(i));
|
|
}
|
|
void write(std::nullptr_t)
|
|
{
|
|
writeRaw("null");
|
|
}
|
|
void write(std::string_view str)
|
|
{
|
|
writeString(str);
|
|
}
|
|
void write(std::optional<AstName> name)
|
|
{
|
|
if (name)
|
|
write(*name);
|
|
else
|
|
writeRaw("null");
|
|
}
|
|
void write(AstName name)
|
|
{
|
|
writeString(name.value ? name.value : "");
|
|
}
|
|
|
|
void write(const Position& position)
|
|
{
|
|
write(position.line);
|
|
writeRaw(",");
|
|
write(position.column);
|
|
}
|
|
|
|
void write(const Location& location)
|
|
{
|
|
writeRaw("\"");
|
|
write(location.begin);
|
|
writeRaw(" - ");
|
|
write(location.end);
|
|
writeRaw("\"");
|
|
}
|
|
|
|
void write(AstLocal* local)
|
|
{
|
|
writeRaw("{");
|
|
bool c = pushComma();
|
|
if (local->annotation != nullptr)
|
|
write("luauType", local->annotation);
|
|
else
|
|
write("luauType", nullptr);
|
|
write("name", local->name);
|
|
writeType("AstLocal");
|
|
write("location", local->location);
|
|
popComma(c);
|
|
writeRaw("}");
|
|
}
|
|
|
|
void writeNode(AstNode* node)
|
|
{
|
|
write("location", node->location);
|
|
}
|
|
|
|
template<typename F>
|
|
void writeNode(AstNode* node, std::string_view name, F&& f)
|
|
{
|
|
writeRaw("{");
|
|
bool c = pushComma();
|
|
writeType(name);
|
|
writeNode(node);
|
|
f();
|
|
popComma(c);
|
|
writeRaw("}");
|
|
}
|
|
|
|
void write(AstNode* node)
|
|
{
|
|
node->visit(this);
|
|
}
|
|
|
|
void write(class AstExprGroup* node)
|
|
{
|
|
writeNode(node, "AstExprGroup", [&]() {
|
|
write("expr", node->expr);
|
|
});
|
|
}
|
|
|
|
void write(class AstExprConstantNil* node)
|
|
{
|
|
writeNode(node, "AstExprConstantNil", []() {});
|
|
}
|
|
|
|
void write(class AstExprConstantBool* node)
|
|
{
|
|
writeNode(node, "AstExprConstantBool", [&]() {
|
|
write("value", node->value);
|
|
});
|
|
}
|
|
|
|
void write(class AstExprConstantNumber* node)
|
|
{
|
|
writeNode(node, "AstExprConstantNumber", [&]() {
|
|
write("value", node->value);
|
|
});
|
|
}
|
|
|
|
void write(class AstExprConstantString* node)
|
|
{
|
|
writeNode(node, "AstExprConstantString", [&]() {
|
|
write("value", node->value);
|
|
});
|
|
}
|
|
|
|
void write(class AstExprLocal* node)
|
|
{
|
|
writeNode(node, "AstExprLocal", [&]() {
|
|
write("local", node->local);
|
|
});
|
|
}
|
|
|
|
void write(class AstExprGlobal* node)
|
|
{
|
|
writeNode(node, "AstExprGlobal", [&]() {
|
|
write("global", node->name);
|
|
});
|
|
}
|
|
|
|
void write(class AstExprVarargs* node)
|
|
{
|
|
writeNode(node, "AstExprVarargs", []() {});
|
|
}
|
|
|
|
template<typename T>
|
|
void write(AstArray<T> arr)
|
|
{
|
|
writeRaw("[");
|
|
bool comma = false;
|
|
for (const auto& a : arr)
|
|
{
|
|
if (comma)
|
|
writeRaw(",");
|
|
else
|
|
comma = true;
|
|
|
|
write(a);
|
|
}
|
|
writeRaw("]");
|
|
}
|
|
|
|
void write(AstArray<char> arr)
|
|
{
|
|
write(std::string_view{arr.data, arr.size});
|
|
}
|
|
|
|
#define PROP(prop) write(#prop, node->prop)
|
|
|
|
void write(class AstExprCall* node)
|
|
{
|
|
writeNode(node, "AstExprCall", [&]() {
|
|
PROP(func);
|
|
PROP(args);
|
|
PROP(self);
|
|
PROP(argLocation);
|
|
});
|
|
}
|
|
|
|
void write(class AstExprIndexName* node)
|
|
{
|
|
writeNode(node, "AstExprIndexName", [&]() {
|
|
PROP(expr);
|
|
PROP(index);
|
|
PROP(indexLocation);
|
|
PROP(op);
|
|
});
|
|
}
|
|
|
|
void write(class AstExprIndexExpr* node)
|
|
{
|
|
writeNode(node, "AstExprIndexExpr", [&]() {
|
|
PROP(expr);
|
|
PROP(index);
|
|
});
|
|
}
|
|
|
|
void write(class AstExprFunction* node)
|
|
{
|
|
writeNode(node, "AstExprFunction", [&]() {
|
|
PROP(generics);
|
|
PROP(genericPacks);
|
|
if (node->self)
|
|
PROP(self);
|
|
PROP(args);
|
|
if (node->returnAnnotation)
|
|
PROP(returnAnnotation);
|
|
PROP(vararg);
|
|
PROP(varargLocation);
|
|
if (node->varargAnnotation)
|
|
PROP(varargAnnotation);
|
|
|
|
PROP(body);
|
|
PROP(functionDepth);
|
|
PROP(debugname);
|
|
PROP(hasEnd);
|
|
});
|
|
}
|
|
|
|
void write(const std::optional<AstTypeList>& typeList)
|
|
{
|
|
if (typeList)
|
|
write(*typeList);
|
|
else
|
|
writeRaw("null");
|
|
}
|
|
|
|
void write(const AstTypeList& typeList)
|
|
{
|
|
writeRaw("{");
|
|
bool c = pushComma();
|
|
writeType("AstTypeList");
|
|
write("types", typeList.types);
|
|
if (typeList.tailType)
|
|
write("tailType", typeList.tailType);
|
|
popComma(c);
|
|
writeRaw("}");
|
|
}
|
|
|
|
void write(const AstGenericType& genericType)
|
|
{
|
|
writeRaw("{");
|
|
bool c = pushComma();
|
|
writeType("AstGenericType");
|
|
write("name", genericType.name);
|
|
if (genericType.defaultValue)
|
|
write("luauType", genericType.defaultValue);
|
|
popComma(c);
|
|
writeRaw("}");
|
|
}
|
|
|
|
void write(const AstGenericTypePack& genericTypePack)
|
|
{
|
|
writeRaw("{");
|
|
bool c = pushComma();
|
|
writeType("AstGenericTypePack");
|
|
write("name", genericTypePack.name);
|
|
if (genericTypePack.defaultValue)
|
|
write("luauType", genericTypePack.defaultValue);
|
|
popComma(c);
|
|
writeRaw("}");
|
|
}
|
|
|
|
void write(AstExprTable::Item::Kind kind)
|
|
{
|
|
switch (kind)
|
|
{
|
|
case AstExprTable::Item::List:
|
|
return writeString("item");
|
|
case AstExprTable::Item::Record:
|
|
return writeString("record");
|
|
case AstExprTable::Item::General:
|
|
return writeString("general");
|
|
}
|
|
}
|
|
|
|
void write(const AstExprTable::Item& item)
|
|
{
|
|
writeRaw("{");
|
|
bool c = pushComma();
|
|
writeType("AstExprTableItem");
|
|
write("kind", item.kind);
|
|
switch (item.kind)
|
|
{
|
|
case AstExprTable::Item::List:
|
|
write("value", item.value);
|
|
break;
|
|
default:
|
|
write("key", item.key);
|
|
write("value", item.value);
|
|
break;
|
|
}
|
|
popComma(c);
|
|
writeRaw("}");
|
|
}
|
|
|
|
void write(class AstExprIfElse* node)
|
|
{
|
|
writeNode(node, "AstExprIfElse", [&]() {
|
|
PROP(condition);
|
|
PROP(hasThen);
|
|
PROP(trueExpr);
|
|
PROP(hasElse);
|
|
PROP(falseExpr);
|
|
});
|
|
}
|
|
|
|
void write(class AstExprInterpString* node)
|
|
{
|
|
writeNode(node, "AstExprInterpString", [&]() {
|
|
PROP(strings);
|
|
PROP(expressions);
|
|
});
|
|
}
|
|
|
|
void write(class AstExprTable* node)
|
|
{
|
|
writeNode(node, "AstExprTable", [&]() {
|
|
PROP(items);
|
|
});
|
|
}
|
|
|
|
void write(AstExprUnary::Op op)
|
|
{
|
|
switch (op)
|
|
{
|
|
case AstExprUnary::Not:
|
|
return writeString("Not");
|
|
case AstExprUnary::Minus:
|
|
return writeString("Minus");
|
|
case AstExprUnary::Len:
|
|
return writeString("Len");
|
|
}
|
|
}
|
|
|
|
void write(class AstExprUnary* node)
|
|
{
|
|
writeNode(node, "AstExprUnary", [&]() {
|
|
PROP(op);
|
|
PROP(expr);
|
|
});
|
|
}
|
|
|
|
void write(AstExprBinary::Op op)
|
|
{
|
|
switch (op)
|
|
{
|
|
case AstExprBinary::Add:
|
|
return writeString("Add");
|
|
case AstExprBinary::Sub:
|
|
return writeString("Sub");
|
|
case AstExprBinary::Mul:
|
|
return writeString("Mul");
|
|
case AstExprBinary::Div:
|
|
return writeString("Div");
|
|
case AstExprBinary::Mod:
|
|
return writeString("Mod");
|
|
case AstExprBinary::Pow:
|
|
return writeString("Pow");
|
|
case AstExprBinary::Concat:
|
|
return writeString("Concat");
|
|
case AstExprBinary::CompareNe:
|
|
return writeString("CompareNe");
|
|
case AstExprBinary::CompareEq:
|
|
return writeString("CompareEq");
|
|
case AstExprBinary::CompareLt:
|
|
return writeString("CompareLt");
|
|
case AstExprBinary::CompareLe:
|
|
return writeString("CompareLe");
|
|
case AstExprBinary::CompareGt:
|
|
return writeString("CompareGt");
|
|
case AstExprBinary::CompareGe:
|
|
return writeString("CompareGe");
|
|
case AstExprBinary::And:
|
|
return writeString("And");
|
|
case AstExprBinary::Or:
|
|
return writeString("Or");
|
|
}
|
|
}
|
|
|
|
void write(class AstExprBinary* node)
|
|
{
|
|
writeNode(node, "AstExprBinary", [&]() {
|
|
PROP(op);
|
|
PROP(left);
|
|
PROP(right);
|
|
});
|
|
}
|
|
|
|
void write(class AstExprTypeAssertion* node)
|
|
{
|
|
writeNode(node, "AstExprTypeAssertion", [&]() {
|
|
PROP(expr);
|
|
PROP(annotation);
|
|
});
|
|
}
|
|
|
|
void write(class AstExprError* node)
|
|
{
|
|
writeNode(node, "AstExprError", [&]() {
|
|
PROP(expressions);
|
|
PROP(messageIndex);
|
|
});
|
|
}
|
|
|
|
void write(class AstStatBlock* node)
|
|
{
|
|
writeNode(node, "AstStatBlock", [&]() {
|
|
writeRaw(",\"body\":[");
|
|
bool comma = false;
|
|
for (AstStat* stat : node->body)
|
|
{
|
|
if (comma)
|
|
writeRaw(",");
|
|
else
|
|
comma = true;
|
|
|
|
write(stat);
|
|
}
|
|
writeRaw("]");
|
|
});
|
|
}
|
|
|
|
void write(class AstStatIf* node)
|
|
{
|
|
writeNode(node, "AstStatIf", [&]() {
|
|
PROP(condition);
|
|
PROP(thenbody);
|
|
if (node->elsebody)
|
|
PROP(elsebody);
|
|
write("hasThen", node->thenLocation.has_value());
|
|
PROP(hasEnd);
|
|
});
|
|
}
|
|
|
|
void write(class AstStatWhile* node)
|
|
{
|
|
writeNode(node, "AstStatWhile", [&]() {
|
|
PROP(condition);
|
|
PROP(body);
|
|
PROP(hasDo);
|
|
PROP(hasEnd);
|
|
});
|
|
}
|
|
|
|
void write(class AstStatRepeat* node)
|
|
{
|
|
writeNode(node, "AstStatRepeat", [&]() {
|
|
PROP(condition);
|
|
PROP(body);
|
|
PROP(hasUntil);
|
|
});
|
|
}
|
|
|
|
void write(class AstStatBreak* node)
|
|
{
|
|
writeNode(node, "AstStatBreak", []() {});
|
|
}
|
|
|
|
void write(class AstStatContinue* node)
|
|
{
|
|
writeNode(node, "AstStatContinue", []() {});
|
|
}
|
|
|
|
void write(class AstStatReturn* node)
|
|
{
|
|
writeNode(node, "AstStatReturn", [&]() {
|
|
PROP(list);
|
|
});
|
|
}
|
|
|
|
void write(class AstStatExpr* node)
|
|
{
|
|
writeNode(node, "AstStatExpr", [&]() {
|
|
PROP(expr);
|
|
});
|
|
}
|
|
|
|
void write(class AstStatLocal* node)
|
|
{
|
|
writeNode(node, "AstStatLocal", [&]() {
|
|
PROP(vars);
|
|
PROP(values);
|
|
});
|
|
}
|
|
|
|
void write(class AstStatFor* node)
|
|
{
|
|
writeNode(node, "AstStatFor", [&]() {
|
|
PROP(var);
|
|
PROP(from);
|
|
PROP(to);
|
|
if (node->step)
|
|
PROP(step);
|
|
PROP(body);
|
|
PROP(hasDo);
|
|
PROP(hasEnd);
|
|
});
|
|
}
|
|
|
|
void write(class AstStatForIn* node)
|
|
{
|
|
writeNode(node, "AstStatForIn", [&]() {
|
|
PROP(vars);
|
|
PROP(values);
|
|
PROP(body);
|
|
PROP(hasIn);
|
|
PROP(hasDo);
|
|
PROP(hasEnd);
|
|
});
|
|
}
|
|
|
|
void write(class AstStatAssign* node)
|
|
{
|
|
writeNode(node, "AstStatAssign", [&]() {
|
|
PROP(vars);
|
|
PROP(values);
|
|
});
|
|
}
|
|
|
|
void write(class AstStatCompoundAssign* node)
|
|
{
|
|
writeNode(node, "AstStatCompoundAssign", [&]() {
|
|
PROP(op);
|
|
PROP(var);
|
|
PROP(value);
|
|
});
|
|
}
|
|
|
|
void write(class AstStatFunction* node)
|
|
{
|
|
writeNode(node, "AstStatFunction", [&]() {
|
|
PROP(name);
|
|
PROP(func);
|
|
});
|
|
}
|
|
|
|
void write(class AstStatLocalFunction* node)
|
|
{
|
|
writeNode(node, "AstStatLocalFunction", [&]() {
|
|
PROP(name);
|
|
PROP(func);
|
|
});
|
|
}
|
|
|
|
void write(class AstStatTypeAlias* node)
|
|
{
|
|
writeNode(node, "AstStatTypeAlias", [&]() {
|
|
PROP(name);
|
|
PROP(generics);
|
|
PROP(genericPacks);
|
|
PROP(type);
|
|
PROP(exported);
|
|
});
|
|
}
|
|
|
|
void write(class AstStatDeclareFunction* node)
|
|
{
|
|
writeNode(node, "AstStatDeclareFunction", [&]() {
|
|
PROP(name);
|
|
PROP(params);
|
|
PROP(retTypes);
|
|
PROP(generics);
|
|
PROP(genericPacks);
|
|
});
|
|
}
|
|
|
|
void write(class AstStatDeclareGlobal* node)
|
|
{
|
|
writeNode(node, "AstStatDeclareGlobal", [&]() {
|
|
PROP(name);
|
|
PROP(type);
|
|
});
|
|
}
|
|
|
|
void write(const AstDeclaredClassProp& prop)
|
|
{
|
|
writeRaw("{");
|
|
bool c = pushComma();
|
|
write("name", prop.name);
|
|
writeType("AstDeclaredClassProp");
|
|
write("luauType", prop.ty);
|
|
popComma(c);
|
|
writeRaw("}");
|
|
}
|
|
|
|
void write(class AstStatDeclareClass* node)
|
|
{
|
|
writeNode(node, "AstStatDeclareClass", [&]() {
|
|
PROP(name);
|
|
if (node->superName)
|
|
write("superName", *node->superName);
|
|
PROP(props);
|
|
});
|
|
}
|
|
|
|
void write(class AstStatError* node)
|
|
{
|
|
writeNode(node, "AstStatError", [&]() {
|
|
PROP(expressions);
|
|
PROP(statements);
|
|
});
|
|
}
|
|
|
|
void write(struct AstTypeOrPack node)
|
|
{
|
|
if (node.type)
|
|
write(node.type);
|
|
else
|
|
write(node.typePack);
|
|
}
|
|
|
|
void write(class AstTypeReference* node)
|
|
{
|
|
writeNode(node, "AstTypeReference", [&]() {
|
|
if (node->prefix)
|
|
PROP(prefix);
|
|
PROP(name);
|
|
PROP(parameters);
|
|
});
|
|
}
|
|
|
|
void write(const AstTableProp& prop)
|
|
{
|
|
writeRaw("{");
|
|
bool c = pushComma();
|
|
|
|
write("name", prop.name);
|
|
writeType("AstTableProp");
|
|
write("location", prop.location);
|
|
write("propType", prop.type);
|
|
|
|
popComma(c);
|
|
writeRaw("}");
|
|
}
|
|
|
|
void write(class AstTypeTable* node)
|
|
{
|
|
writeNode(node, "AstTypeTable", [&]() {
|
|
PROP(props);
|
|
PROP(indexer);
|
|
});
|
|
}
|
|
|
|
void write(struct AstTableIndexer* indexer)
|
|
{
|
|
if (indexer)
|
|
{
|
|
writeRaw("{");
|
|
bool c = pushComma();
|
|
write("location", indexer->location);
|
|
write("indexType", indexer->indexType);
|
|
write("resultType", indexer->resultType);
|
|
popComma(c);
|
|
writeRaw("}");
|
|
}
|
|
else
|
|
{
|
|
writeRaw("null");
|
|
}
|
|
}
|
|
|
|
void write(class AstTypeFunction* node)
|
|
{
|
|
writeNode(node, "AstTypeFunction", [&]() {
|
|
PROP(generics);
|
|
PROP(genericPacks);
|
|
PROP(argTypes);
|
|
PROP(returnTypes);
|
|
});
|
|
}
|
|
|
|
void write(class AstTypeTypeof* node)
|
|
{
|
|
writeNode(node, "AstTypeTypeof", [&]() {
|
|
PROP(expr);
|
|
});
|
|
}
|
|
|
|
void write(class AstTypeUnion* node)
|
|
{
|
|
writeNode(node, "AstTypeUnion", [&]() {
|
|
PROP(types);
|
|
});
|
|
}
|
|
|
|
void write(class AstTypeIntersection* node)
|
|
{
|
|
writeNode(node, "AstTypeIntersection", [&]() {
|
|
PROP(types);
|
|
});
|
|
}
|
|
|
|
void write(class AstTypeError* node)
|
|
{
|
|
writeNode(node, "AstTypeError", [&]() {
|
|
PROP(types);
|
|
PROP(messageIndex);
|
|
});
|
|
}
|
|
|
|
void write(class AstTypePackExplicit* node)
|
|
{
|
|
writeNode(node, "AstTypePackExplicit", [&]() {
|
|
PROP(typeList);
|
|
});
|
|
}
|
|
|
|
void write(class AstTypePackVariadic* node)
|
|
{
|
|
writeNode(node, "AstTypePackVariadic", [&]() {
|
|
PROP(variadicType);
|
|
});
|
|
}
|
|
|
|
void write(class AstTypePackGeneric* node)
|
|
{
|
|
writeNode(node, "AstTypePackGeneric", [&]() {
|
|
PROP(genericName);
|
|
});
|
|
}
|
|
|
|
bool visit(class AstExprGroup* node) override
|
|
{
|
|
write(node);
|
|
return false;
|
|
}
|
|
|
|
bool visit(class AstExprConstantNil* node) override
|
|
{
|
|
write(node);
|
|
return false;
|
|
}
|
|
|
|
bool visit(class AstExprConstantBool* node) override
|
|
{
|
|
write(node);
|
|
return false;
|
|
}
|
|
|
|
bool visit(class AstExprConstantNumber* node) override
|
|
{
|
|
write(node);
|
|
return false;
|
|
}
|
|
|
|
bool visit(class AstExprConstantString* node) override
|
|
{
|
|
write(node);
|
|
return false;
|
|
}
|
|
|
|
bool visit(class AstExprIfElse* node) override
|
|
{
|
|
write(node);
|
|
return false;
|
|
}
|
|
|
|
bool visit(class AstExprInterpString* node) override
|
|
{
|
|
write(node);
|
|
return false;
|
|
}
|
|
|
|
bool visit(class AstExprLocal* node) override
|
|
{
|
|
write(node);
|
|
return false;
|
|
}
|
|
|
|
bool visit(class AstExprGlobal* node) override
|
|
{
|
|
write(node);
|
|
return false;
|
|
}
|
|
|
|
bool visit(class AstExprVarargs* node) override
|
|
{
|
|
write(node);
|
|
return false;
|
|
}
|
|
|
|
bool visit(class AstExprCall* node) override
|
|
{
|
|
write(node);
|
|
return false;
|
|
}
|
|
|
|
bool visit(class AstExprIndexName* node) override
|
|
{
|
|
write(node);
|
|
return false;
|
|
}
|
|
|
|
bool visit(class AstExprIndexExpr* node) override
|
|
{
|
|
write(node);
|
|
return false;
|
|
}
|
|
|
|
bool visit(class AstExprFunction* node) override
|
|
{
|
|
write(node);
|
|
return false;
|
|
}
|
|
|
|
bool visit(class AstExprTable* node) override
|
|
{
|
|
write(node);
|
|
return false;
|
|
}
|
|
|
|
bool visit(class AstExprUnary* node) override
|
|
{
|
|
write(node);
|
|
return false;
|
|
}
|
|
|
|
bool visit(class AstExprBinary* node) override
|
|
{
|
|
write(node);
|
|
return false;
|
|
}
|
|
|
|
bool visit(class AstExprTypeAssertion* node) override
|
|
{
|
|
write(node);
|
|
return false;
|
|
}
|
|
|
|
bool visit(class AstExprError* node) override
|
|
{
|
|
write(node);
|
|
return false;
|
|
}
|
|
|
|
bool visit(class AstStatBlock* node) override
|
|
{
|
|
write(node);
|
|
return false;
|
|
}
|
|
|
|
bool visit(class AstStatIf* node) override
|
|
{
|
|
write(node);
|
|
return false;
|
|
}
|
|
|
|
bool visit(class AstStatWhile* node) override
|
|
{
|
|
write(node);
|
|
return false;
|
|
}
|
|
|
|
bool visit(class AstStatRepeat* node) override
|
|
{
|
|
write(node);
|
|
return false;
|
|
}
|
|
|
|
bool visit(class AstStatBreak* node) override
|
|
{
|
|
write(node);
|
|
return false;
|
|
}
|
|
|
|
bool visit(class AstStatContinue* node) override
|
|
{
|
|
write(node);
|
|
return false;
|
|
}
|
|
|
|
bool visit(class AstStatReturn* node) override
|
|
{
|
|
write(node);
|
|
return false;
|
|
}
|
|
|
|
bool visit(class AstStatExpr* node) override
|
|
{
|
|
write(node);
|
|
return false;
|
|
}
|
|
|
|
bool visit(class AstStatLocal* node) override
|
|
{
|
|
write(node);
|
|
return false;
|
|
}
|
|
|
|
bool visit(class AstStatFor* node) override
|
|
{
|
|
write(node);
|
|
return false;
|
|
}
|
|
|
|
bool visit(class AstStatForIn* node) override
|
|
{
|
|
write(node);
|
|
return false;
|
|
}
|
|
|
|
bool visit(class AstStatAssign* node) override
|
|
{
|
|
write(node);
|
|
return false;
|
|
}
|
|
|
|
bool visit(class AstStatCompoundAssign* node) override
|
|
{
|
|
write(node);
|
|
return false;
|
|
}
|
|
|
|
bool visit(class AstStatFunction* node) override
|
|
{
|
|
write(node);
|
|
return false;
|
|
}
|
|
|
|
bool visit(class AstStatLocalFunction* node) override
|
|
{
|
|
write(node);
|
|
return false;
|
|
}
|
|
|
|
bool visit(class AstStatTypeAlias* node) override
|
|
{
|
|
write(node);
|
|
return false;
|
|
}
|
|
|
|
bool visit(class AstStatDeclareFunction* node) override
|
|
{
|
|
write(node);
|
|
return false;
|
|
}
|
|
|
|
bool visit(class AstStatDeclareGlobal* node) override
|
|
{
|
|
write(node);
|
|
return false;
|
|
}
|
|
|
|
bool visit(class AstStatDeclareClass* node) override
|
|
{
|
|
write(node);
|
|
return false;
|
|
}
|
|
|
|
bool visit(class AstStatError* node) override
|
|
{
|
|
write(node);
|
|
return false;
|
|
}
|
|
|
|
bool visit(class AstTypeReference* node) override
|
|
{
|
|
write(node);
|
|
return false;
|
|
}
|
|
|
|
bool visit(class AstTypeTable* node) override
|
|
{
|
|
write(node);
|
|
return false;
|
|
}
|
|
|
|
bool visit(class AstTypeFunction* node) override
|
|
{
|
|
write(node);
|
|
return false;
|
|
}
|
|
|
|
bool visit(class AstTypeTypeof* node) override
|
|
{
|
|
write(node);
|
|
return false;
|
|
}
|
|
|
|
bool visit(class AstTypeUnion* node) override
|
|
{
|
|
write(node);
|
|
return false;
|
|
}
|
|
|
|
bool visit(class AstTypeIntersection* node) override
|
|
{
|
|
write(node);
|
|
return false;
|
|
}
|
|
|
|
bool visit(class AstTypeError* node) override
|
|
{
|
|
write(node);
|
|
return false;
|
|
}
|
|
|
|
bool visit(class AstTypePack* node) override
|
|
{
|
|
write(node);
|
|
return false;
|
|
}
|
|
|
|
bool visit(class AstTypePackExplicit* node) override
|
|
{
|
|
write(node);
|
|
return false;
|
|
}
|
|
|
|
bool visit(class AstTypePackVariadic* node) override
|
|
{
|
|
write(node);
|
|
return false;
|
|
}
|
|
|
|
bool visit(class AstTypePackGeneric* node) override
|
|
{
|
|
write(node);
|
|
return false;
|
|
}
|
|
|
|
void writeComments(std::vector<Comment> commentLocations)
|
|
{
|
|
bool commentComma = false;
|
|
for (Comment comment : commentLocations)
|
|
{
|
|
if (commentComma)
|
|
{
|
|
writeRaw(",");
|
|
}
|
|
else
|
|
{
|
|
commentComma = true;
|
|
}
|
|
writeRaw("{");
|
|
bool c = pushComma();
|
|
switch (comment.type)
|
|
{
|
|
case Lexeme::Comment:
|
|
writeType("Comment");
|
|
break;
|
|
case Lexeme::BlockComment:
|
|
writeType("BlockComment");
|
|
break;
|
|
case Lexeme::BrokenComment:
|
|
writeType("BrokenComment");
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
write("location", comment.location);
|
|
popComma(c);
|
|
writeRaw("}");
|
|
}
|
|
}
|
|
};
|
|
|
|
std::string toJson(AstNode* node)
|
|
{
|
|
AstJsonEncoder encoder;
|
|
node->visit(&encoder);
|
|
return encoder.str();
|
|
}
|
|
|
|
std::string toJson(AstNode* node, const std::vector<Comment>& commentLocations)
|
|
{
|
|
AstJsonEncoder encoder;
|
|
encoder.writeRaw(R"({"root":)");
|
|
node->visit(&encoder);
|
|
encoder.writeRaw(R"(,"commentLocations":[)");
|
|
encoder.writeComments(commentLocations);
|
|
encoder.writeRaw("]}");
|
|
return encoder.str();
|
|
}
|
|
|
|
} // namespace Luau
|