namespace GL {
namespace SL {
+const DumpTree::Colors DumpTree::no_colors =
+{ "", "", "", "", "", "", "" };
+
+const DumpTree::Colors DumpTree::default_colors =
+{
+ "\033[0m", // default
+ "\033[38;5;250m", // tree
+ "\033[38;5;244m", // location
+ "\033[38;5;146m", // label
+ "\033[38;5;194m", // type
+ "\033[38;5;230m", // name
+ "\033[38;5;210m" // error
+};
+
+DumpTree::DumpTree(bool use_colors):
+ colors(use_colors ? default_colors : no_colors)
+{ }
+
string DumpTree::apply(Stage &stage)
{
formatted = format("Stage: %s\n", Stage::get_stage_name(stage.type));
append(format("Version: %d.%02d", stage.required_features.glsl_version.major, stage.required_features.glsl_version.minor));
for(const auto &kvp: stage.types)
- append(format("Type: %%%d %s", get_label(*kvp.second), kvp.first));
+ append(format("Type: %s %s%s%s", get_label(*kvp.second), colors.type_color, kvp.first, colors.default_color));
for(const auto &kvp: stage.interface_blocks)
- append(format("Interface block: %%%d %s", get_label(*kvp.second), kvp.first));
+ append(format("Interface block: %s %s", get_label(*kvp.second), format_name(kvp.first)));
for(const auto &kvp: stage.functions)
- append(format("Function: %%%d %s", get_label(*kvp.second), kvp.first));
+ append(format("Function: %s %s", get_label(*kvp.second), format_name(kvp.first)));
last_branch();
stage.content.visit(*this);
void DumpTree::append(const string &line)
{
+ formatted += colors.tree_color;
StringCodec::Utf8::Encoder enc;
for(auto i=tree.begin(); i!=tree.end(); )
{
enc.encode_char(*i++, formatted);
enc.encode_char((i==tree.end() ? REACH : EMPTY), formatted);
}
+ formatted += colors.default_color;
formatted += line;
formatted += '\n';
}
void DumpTree::append(const Node &node, const string &line)
{
- append(format("<%d:%d> %s", node.source, node.line, line));
+ string location;
+ if(node.source==BUILTIN_SOURCE)
+ location = "builtin";
+ else if(node.source==INTERNAL_SOURCE)
+ location = "internal";
+ else if(node.source==GENERATED_SOURCE)
+ location = "generated";
+ else
+ location = format("%s:%s", node.source, node.line);
+ append(format("%s<%s>%s %s", colors.location_color, location, colors.default_color, line));
}
void DumpTree::append_subtree(const vector<Branch> &branches)
tree.back() = BRANCH;
}
-unsigned DumpTree::get_label(const Node &node)
+std::string DumpTree::get_label(const Node &node)
{
unsigned &label = node_labels[&node];
if(!label)
label = node_labels.size();
- return label;
+ return format("%s%%%d%s", colors.label_color, label, colors.default_color);
}
string DumpTree::format_type(TypeDeclaration *type)
{
- return (type ? type->name : "?");
+ return type ? format_type(type->name) : format("%s?%s", colors.error_color, colors.default_color);
+}
+
+string DumpTree::format_type(const string &type)
+{
+ return format("%s%s%s", colors.type_color, type, colors.default_color);
+}
+
+string DumpTree::format_name(const string &name)
+{
+ return format("%s%s%s", colors.name_color, name, colors.default_color);
}
template<typename T>
begin_sub();
for(const auto &kvp: block.variables)
- append(format("Variable: %%%d %s %s", get_label(*kvp.second), kvp.second->type, kvp.first));
+ append(format("Variable: %s %s %s", get_label(*kvp.second), format_type(kvp.second->type), format_name(kvp.first)));
for(auto i=block.body.cbegin(); i!=block.body.cend(); )
{
{
string text;
if(var.declaration)
- text += format("%%%d ", get_label(*var.declaration));
- text += format("%s (var) -> %s", var.name, format_type(var.type));
+ text += format("%s ", get_label(*var.declaration));
+ text += format("%s (var) -> %s", format_name(var.name), format_type(var.type));
append(var, text);
}
{
string text;
if(iface.declaration)
- text += format("%%%d ", get_label(*iface.declaration));
- text += format("%s (iface) -> %s", iface.name, format_type(iface.type));
+ text += format("%s ", get_label(*iface.declaration));
+ text += format("%s (iface) -> %s", format_name(iface.name), format_type(iface.type));
append(iface, text);
}
{
string text = "Member access:";
if(memacc.declaration)
- text += format(" %%%d", get_label(*memacc.declaration));
- text += format(" .%s (%d) -> %s", memacc.member, memacc.index, format_type(memacc.type));
+ text += format(" %s", get_label(*memacc.declaration));
+ text += format(" .%s (%d) -> %s", format_name(memacc.member), memacc.index, format_type(memacc.type));
append(memacc, text);
append_subtree(*memacc.left);
}
begin_sub();
if(assign.target.declaration)
{
- string text = format("Target: %%%d", get_label(*assign.target.declaration));
+ string text = format("Target: %s", get_label(*assign.target.declaration));
static const char swizzle[4] = { 'x', 'y', 'z', 'w' };
for(unsigned i=0; i<assign.target.chain_len; ++i)
{
string head = "Function call: ";
if(call.declaration)
- head += format("%%%d ", get_label(*call.declaration));
- head += call.name;
+ head += format("%s ", get_label(*call.declaration));
+ head += format_name(call.name);
if(call.constructor)
head += " (constructor)";
head += format(" -> %s", format_type(call.type));
void DumpTree::visit(BasicTypeDeclaration &type)
{
- append(type, format("%%%d typedef %s", get_label(type), type.name));
+ append(type, format("%s typedef %s", get_label(type), format_type(type.name)));
vector<Branch> branches;
if(type.base_type)
- branches.emplace_back(format("%s: %%%d %s", (type.kind==BasicTypeDeclaration::ALIAS ? "Alias of" : "Base"), get_label(*type.base_type), type.base_type->name));
+ branches.emplace_back(format("%s: %s %s", (type.kind==BasicTypeDeclaration::ALIAS ? "Alias of" : "Base"), get_label(*type.base_type), format_type(type.base_type->name)));
if(type.kind==BasicTypeDeclaration::VECTOR)
branches.emplace_back(format("Vector: %d", type.size));
else if(type.kind==BasicTypeDeclaration::MATRIX)
{
static const char *const dims[] = { "1D", "2D", "3D", "Cube" };
- append(type, format("%%%d typedef %s", get_label(type), type.name));
+ append(type, format("%s typedef %s", get_label(type), format_type(type.name)));
vector<Branch> branches;
branches.emplace_back(format("Dimensions: %s%s", dims[type.dimensions-1], (type.array ? " array" : "")));
if(type.base_type)
- branches.emplace_back(format("Element type: %%%d %s", get_label(*type.base_type), type.base_type->name));
+ branches.emplace_back(format("Element type: %s %s", get_label(*type.base_type), format_type(type.base_type->name)));
if(type.shadow)
branches.emplace_back("Shadow");
append_subtree(branches);
void DumpTree::visit(StructDeclaration &strct)
{
- append(strct, format("%%%d struct %s", get_label(strct), strct.name));
+ append(strct, format("%s struct %s", get_label(strct), strct.name));
append_subtree(strct.members);
}
void DumpTree::visit(VariableDeclaration &var)
{
- string decl = format("%%%d ", get_label(var));
+ string decl = format("%s ", get_label(var));
if(var.constant)
decl += "const ";
if(!var.interpolation.empty())
decl += format("%s ", var.interface);
if(!var.precision.empty())
decl += format("%s ", var.precision);
- decl += format("%s %s", var.type, var.name);
+ decl += format("%s %s", format_type(var.type), format_name(var.name));
if(var.source==BUILTIN_SOURCE)
decl += " (builtin)";
else if(var.linked_declaration)
vector<Branch> branches;
if(var.type_declaration)
- branches.push_back(format("Type: %%%d %s", get_label(*var.type_declaration), var.type_declaration->name));
+ branches.emplace_back(format("Type: %s %s", get_label(*var.type_declaration), format_type(var.type_declaration->name)));
if(var.layout)
- branches.push_back(var.layout.get());
+ branches.emplace_back(var.layout.get());
if(var.array)
{
if(var.array_size)
branches.emplace_back("Array []", var.array_size.get());
else
- branches.push_back("Array []");
+ branches.emplace_back("Array []");
}
if(var.init_expression)
- branches.push_back(var.init_expression.get());
+ branches.emplace_back(var.init_expression.get());
append_subtree(branches);
}
void DumpTree::visit(InterfaceBlock &iface)
{
- string head = format("%%%d %s %s", get_label(iface), iface.interface, iface.block_name);
+ string head = format("%s %s %s", get_label(iface), iface.interface, format_name(iface.block_name));
if(!iface.instance_name.empty())
- head += format(" %s", iface.instance_name);
+ head += format(" %s", format_name(iface.instance_name));
if(iface.array)
head += "[]";
if(iface.source==BUILTIN_SOURCE)
vector<Branch> branches;
if(iface.type_declaration)
- branches.push_back(format("Type: %%%d %s", get_label(*iface.type_declaration), iface.type_declaration->name));
+ branches.emplace_back(format("Type: %s %s", get_label(*iface.type_declaration), format_type(iface.type_declaration->name)));
if(iface.layout)
- branches.push_back(iface.layout.get());
+ branches.emplace_back(iface.layout.get());
if(iface.members)
- branches.push_back(iface.members.get());
+ branches.emplace_back(iface.members.get());
append_subtree(branches);
}
void DumpTree::visit(FunctionDeclaration &func)
{
- string text = format("%%%d %s %s%s", get_label(func), func.return_type, func.name, (func.signature.empty() ? "(?)" : func.signature));
+ string text = format("%s %s %s%s", get_label(func), format_type(func.return_type), format_name(func.name), (func.signature.empty() ? "(?)" : func.signature));
if(func.source==BUILTIN_SOURCE)
text += " (builtin)";
else if(!func.definition)
begin_sub();
if(func.return_type_declaration)
- append(format("Return type: %%%d %s", get_label(*func.return_type_declaration), func.return_type_declaration->name));
+ append(format("Return type: %s %s", get_label(*func.return_type_declaration), format_type(func.return_type_declaration)));
for(const RefPtr<VariableDeclaration> &p: func.parameters)
p->visit(*this);
last_branch();
if(func.definition==&func)
func.body.visit(*this);
else if(func.definition)
- append(format("Definition: %%%d", get_label(*func.definition)));
+ append(format("Definition: %s", get_label(*func.definition)));
end_sub();
}