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;
|
return NodeType::LETREC;
|
||||||
if (node.holds<AssertNode>())
|
if (node.holds<AssertNode>())
|
||||||
return NodeType::ASSERT;
|
return NodeType::ASSERT;
|
||||||
|
if (node.holds<LambdaPatternNode>())
|
||||||
|
return NodeType::LAMBDA_PATTERN;
|
||||||
|
if (node.holds<StringInterpolationNode>())
|
||||||
|
return NodeType::STRING_INTERPOLATION;
|
||||||
return NodeType::ERROR;
|
return NodeType::ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -199,6 +203,53 @@ struct Serializer::Impl {
|
||||||
write_node(*n->cond);
|
write_node(*n->cond);
|
||||||
if (n->body)
|
if (n->body)
|
||||||
write_node(*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();
|
auto body = read_node();
|
||||||
return std::make_shared<Node>(AssertNode(cond, body, line));
|
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:
|
default:
|
||||||
throw std::runtime_error("Unknown node type in IR");
|
throw std::runtime_error("Unknown node type in IR");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue