irc: add serialization support for patterns and string interpolation
Signed-off-by: NotAShelf <raf@notashelf.dev> Change-Id: I244ae722016b5b49915e23522a1fb72e6a6a6964
This commit is contained in:
parent
0a5920adaf
commit
584d84542e
1 changed files with 117 additions and 0 deletions
|
|
@ -74,6 +74,10 @@ struct Serializer::Impl {
|
|||
return NodeType::LETREC;
|
||||
if (node.holds<AssertNode>())
|
||||
return NodeType::ASSERT;
|
||||
if (node.holds<LambdaPatternNode>())
|
||||
return NodeType::LAMBDA_PATTERN;
|
||||
if (node.holds<StringInterpolationNode>())
|
||||
return NodeType::STRING_INTERPOLATION;
|
||||
return NodeType::ERROR;
|
||||
}
|
||||
|
||||
|
|
@ -199,6 +203,53 @@ struct Serializer::Impl {
|
|||
write_node(*n->cond);
|
||||
if (n->body)
|
||||
write_node(*n->body);
|
||||
} else if (auto* n = node.get_if<LambdaPatternNode>()) {
|
||||
// Required fields
|
||||
write_u32(n->required_fields.size());
|
||||
for (const auto& field : n->required_fields) {
|
||||
write_string(field.name);
|
||||
write_u8(0); // No default
|
||||
}
|
||||
|
||||
// Optional fields
|
||||
write_u32(n->optional_fields.size());
|
||||
for (const auto& field : n->optional_fields) {
|
||||
write_string(field.name);
|
||||
if (field.default_value && *field.default_value) {
|
||||
write_u8(1);
|
||||
write_node(**field.default_value);
|
||||
} else {
|
||||
write_u8(0);
|
||||
}
|
||||
}
|
||||
|
||||
// At-binding
|
||||
if (n->at_binding) {
|
||||
write_u8(1);
|
||||
write_string(*n->at_binding);
|
||||
} else {
|
||||
write_u8(0);
|
||||
}
|
||||
|
||||
// Allow extra
|
||||
write_u8(n->allow_extra ? 1 : 0);
|
||||
|
||||
// Body
|
||||
if (n->body)
|
||||
write_node(*n->body);
|
||||
} else if (auto* n = node.get_if<StringInterpolationNode>()) {
|
||||
write_u32(n->parts.size());
|
||||
|
||||
for (const auto& part : n->parts) {
|
||||
write_u8(static_cast<uint8_t>(part.type));
|
||||
|
||||
if (part.type == StringPart::Type::LITERAL) {
|
||||
write_string(part.literal);
|
||||
} else { // EXPR
|
||||
if (part.expr)
|
||||
write_node(*part.expr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -430,6 +481,72 @@ struct Deserializer::Impl {
|
|||
auto body = read_node();
|
||||
return std::make_shared<Node>(AssertNode(cond, body, line));
|
||||
}
|
||||
case NodeType::LAMBDA_PATTERN: {
|
||||
// Read required fields
|
||||
uint32_t num_required = read_u32();
|
||||
std::vector<PatternField> required_fields;
|
||||
required_fields.reserve(num_required);
|
||||
for (uint32_t i = 0; i < num_required; i++) {
|
||||
std::string name = read_string();
|
||||
read_u8(); // Discard has_default (always 0)
|
||||
required_fields.emplace_back(name, std::nullopt);
|
||||
}
|
||||
|
||||
// Read optional fields
|
||||
uint32_t num_optional = read_u32();
|
||||
std::vector<PatternField> optional_fields;
|
||||
optional_fields.reserve(num_optional);
|
||||
for (uint32_t i = 0; i < num_optional; i++) {
|
||||
std::string name = read_string();
|
||||
uint8_t has_default = read_u8();
|
||||
std::optional<std::shared_ptr<Node>> default_val;
|
||||
if (has_default) {
|
||||
default_val = read_node();
|
||||
}
|
||||
optional_fields.emplace_back(name, default_val);
|
||||
}
|
||||
|
||||
// Read at-binding
|
||||
std::optional<std::string> at_binding;
|
||||
if (read_u8()) {
|
||||
at_binding = read_string();
|
||||
}
|
||||
|
||||
// Read allow_extra
|
||||
bool allow_extra = read_u8() != 0;
|
||||
|
||||
// Read body
|
||||
auto body = read_node();
|
||||
|
||||
// Construct node
|
||||
LambdaPatternNode lambda_pattern(body, line);
|
||||
lambda_pattern.required_fields = std::move(required_fields);
|
||||
lambda_pattern.optional_fields = std::move(optional_fields);
|
||||
lambda_pattern.at_binding = at_binding;
|
||||
lambda_pattern.allow_extra = allow_extra;
|
||||
|
||||
return std::make_shared<Node>(std::move(lambda_pattern));
|
||||
}
|
||||
case NodeType::STRING_INTERPOLATION: {
|
||||
uint32_t num_parts = read_u32();
|
||||
std::vector<StringPart> parts;
|
||||
parts.reserve(num_parts);
|
||||
|
||||
for (uint32_t i = 0; i < num_parts; i++) {
|
||||
uint8_t type_byte = read_u8();
|
||||
StringPart::Type type = static_cast<StringPart::Type>(type_byte);
|
||||
|
||||
if (type == StringPart::Type::LITERAL) {
|
||||
std::string literal = read_string();
|
||||
parts.push_back(StringPart::make_literal(std::move(literal)));
|
||||
} else { // EXPR
|
||||
auto expr = read_node();
|
||||
parts.push_back(StringPart::make_expr(expr));
|
||||
}
|
||||
}
|
||||
|
||||
return std::make_shared<Node>(StringInterpolationNode(std::move(parts), line));
|
||||
}
|
||||
default:
|
||||
throw std::runtime_error("Unknown node type in IR");
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue