mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-12-08 06:09:58 +00:00
93 lines
3.2 KiB
C
93 lines
3.2 KiB
C
|
|
/*
|
||
|
|
* Copyright (c) 2021-2025, Andreas Kling <andreas@ladybird.org>
|
||
|
|
*
|
||
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
||
|
|
*/
|
||
|
|
|
||
|
|
#pragma once
|
||
|
|
|
||
|
|
#include <AK/ByteString.h>
|
||
|
|
#include <LibJS/Bytecode/Executable.h>
|
||
|
|
#include <LibJS/Bytecode/Operand.h>
|
||
|
|
#include <LibJS/Bytecode/Register.h>
|
||
|
|
#include <LibJS/Runtime/BigInt.h>
|
||
|
|
#include <LibJS/Runtime/PrimitiveString.h>
|
||
|
|
#include <LibJS/Runtime/Value.h>
|
||
|
|
|
||
|
|
namespace JS::Bytecode {
|
||
|
|
|
||
|
|
inline ByteString format_operand(StringView name, Operand operand, Bytecode::Executable const& executable)
|
||
|
|
{
|
||
|
|
StringBuilder builder;
|
||
|
|
if (!name.is_empty())
|
||
|
|
builder.appendff("\033[32m{}\033[0m:", name);
|
||
|
|
switch (operand.type()) {
|
||
|
|
case Operand::Type::Register:
|
||
|
|
if (operand.index() == Register::this_value().index()) {
|
||
|
|
builder.appendff("\033[33mthis\033[0m");
|
||
|
|
} else {
|
||
|
|
builder.appendff("\033[33mreg{}\033[0m", operand.index());
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
case Operand::Type::Local:
|
||
|
|
builder.appendff("\033[34m{}~{}\033[0m", executable.local_variable_names[operand.index() - executable.local_index_base].name, operand.index() - executable.local_index_base);
|
||
|
|
break;
|
||
|
|
case Operand::Type::Argument:
|
||
|
|
builder.appendff("\033[34marg{}\033[0m", operand.index() - executable.argument_index_base);
|
||
|
|
break;
|
||
|
|
case Operand::Type::Constant: {
|
||
|
|
builder.append("\033[36m"sv);
|
||
|
|
auto value = executable.constants[operand.index() - executable.number_of_registers];
|
||
|
|
if (value.is_special_empty_value())
|
||
|
|
builder.append("<Empty>"sv);
|
||
|
|
else if (value.is_boolean())
|
||
|
|
builder.appendff("Bool({})", value.as_bool() ? "true"sv : "false"sv);
|
||
|
|
else if (value.is_int32())
|
||
|
|
builder.appendff("Int32({})", value.as_i32());
|
||
|
|
else if (value.is_double())
|
||
|
|
builder.appendff("Double({})", value.as_double());
|
||
|
|
else if (value.is_bigint())
|
||
|
|
builder.appendff("BigInt({})", MUST(value.as_bigint().to_string()));
|
||
|
|
else if (value.is_string())
|
||
|
|
builder.appendff("String(\"{}\")", value.as_string().utf8_string_view());
|
||
|
|
else if (value.is_undefined())
|
||
|
|
builder.append("Undefined"sv);
|
||
|
|
else if (value.is_null())
|
||
|
|
builder.append("Null"sv);
|
||
|
|
else
|
||
|
|
builder.appendff("Value: {}", value);
|
||
|
|
builder.append("\033[0m"sv);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
default:
|
||
|
|
VERIFY_NOT_REACHED();
|
||
|
|
}
|
||
|
|
return builder.to_byte_string();
|
||
|
|
}
|
||
|
|
|
||
|
|
inline ByteString format_operand_list(StringView name, ReadonlySpan<Operand> operands, Bytecode::Executable const& executable)
|
||
|
|
{
|
||
|
|
StringBuilder builder;
|
||
|
|
if (!name.is_empty())
|
||
|
|
builder.appendff("\033[32m{}\033[0m:[", name);
|
||
|
|
for (size_t i = 0; i < operands.size(); ++i) {
|
||
|
|
if (i != 0)
|
||
|
|
builder.append(", "sv);
|
||
|
|
builder.appendff("{}", format_operand(""sv, operands[i], executable));
|
||
|
|
}
|
||
|
|
builder.append("]"sv);
|
||
|
|
return builder.to_byte_string();
|
||
|
|
}
|
||
|
|
|
||
|
|
inline ByteString format_value_list(StringView name, ReadonlySpan<Value> values)
|
||
|
|
{
|
||
|
|
StringBuilder builder;
|
||
|
|
if (!name.is_empty())
|
||
|
|
builder.appendff("\033[32m{}\033[0m:[", name);
|
||
|
|
builder.join(", "sv, values);
|
||
|
|
builder.append("]"sv);
|
||
|
|
return builder.to_byte_string();
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|