serializer: add HasAttrNode binary encoding

Signed-off-by: NotAShelf <raf@notashelf.dev>
Change-Id: Ifdbd53aafc8291c78c273e2c9092fdf26a6a6964
This commit is contained in:
raf 2026-02-21 20:47:02 +03:00
commit 4b97433642
Signed by: NotAShelf
GPG key ID: 29D95B64378DB4BF

View file

@ -43,6 +43,7 @@ struct Serializer::Impl {
if (node.holds<UnaryOpNode>()) return NodeType::UNARY_OP;
if (node.holds<AttrsetNode>()) return NodeType::ATTRSET;
if (node.holds<SelectNode>()) return NodeType::SELECT;
if (node.holds<HasAttrNode>()) return NodeType::HAS_ATTR;
if (node.holds<WithNode>()) return NodeType::WITH;
if (node.holds<IfNode>()) return NodeType::IF;
if (node.holds<LetNode>()) return NodeType::LET;
@ -100,6 +101,9 @@ struct Serializer::Impl {
} else {
write_u8(0);
}
} else if (auto* n = node.get_if<HasAttrNode>()) {
if (n->expr) write_node(*n->expr);
if (n->attr) write_node(*n->attr);
} else if (auto* n = node.get_if<WithNode>()) {
if (n->attrs) write_node(*n->attrs);
if (n->body) write_node(*n->body);
@ -204,6 +208,122 @@ struct Deserializer::Impl {
pos += len;
return str;
}
std::shared_ptr<Node> read_node() {
NodeType type = static_cast<NodeType>(read_u8());
uint32_t line = read_u32();
switch (type) {
case NodeType::CONST_INT: {
int64_t val = static_cast<int64_t>(read_u64());
return std::make_shared<Node>(ConstIntNode(val, line));
}
case NodeType::CONST_STRING: {
std::string val = read_string();
return std::make_shared<Node>(ConstStringNode(val, line));
}
case NodeType::CONST_PATH: {
std::string val = read_string();
return std::make_shared<Node>(ConstPathNode(val, line));
}
case NodeType::CONST_BOOL: {
bool val = read_u8() != 0;
return std::make_shared<Node>(ConstBoolNode(val, line));
}
case NodeType::CONST_NULL:
return std::make_shared<Node>(ConstNullNode(line));
case NodeType::VAR: {
uint32_t index = read_u32();
return std::make_shared<Node>(VarNode(index, "", line));
}
case NodeType::LAMBDA: {
uint32_t arity = read_u32();
auto body = read_node();
return std::make_shared<Node>(LambdaNode(arity, body, line));
}
case NodeType::APP: {
auto func = read_node();
auto arg = read_node();
return std::make_shared<Node>(AppNode(func, arg, line));
}
case NodeType::BINARY_OP: {
BinaryOp op = static_cast<BinaryOp>(read_u8());
auto left = read_node();
auto right = read_node();
return std::make_shared<Node>(BinaryOpNode(op, left, right, line));
}
case NodeType::UNARY_OP: {
UnaryOp op = static_cast<UnaryOp>(read_u8());
auto operand = read_node();
return std::make_shared<Node>(UnaryOpNode(op, operand, line));
}
case NodeType::ATTRSET: {
bool recursive = read_u8() != 0;
uint32_t num_attrs = read_u32();
AttrsetNode attrs(recursive, line);
for (uint32_t i = 0; i < num_attrs; i++) {
std::string key = read_string();
auto val = read_node();
attrs.attrs.push_back({key, val});
}
return std::make_shared<Node>(std::move(attrs));
}
case NodeType::SELECT: {
auto expr = read_node();
auto attr = read_node();
return std::make_shared<Node>(SelectNode(expr, attr, line));
}
case NodeType::HAS_ATTR: {
auto expr = read_node();
auto attr = read_node();
return std::make_shared<Node>(HasAttrNode(expr, attr, line));
}
case NodeType::WITH: {
auto attrs = read_node();
auto body = read_node();
return std::make_shared<Node>(WithNode(attrs, body, line));
}
case NodeType::IF: {
auto cond = read_node();
auto then_branch = read_node();
auto else_branch = read_node();
return std::make_shared<Node>(IfNode(cond, then_branch, else_branch, line));
}
case NodeType::LET: {
uint32_t num_bindings = read_u32();
std::vector<std::pair<std::string, std::shared_ptr<Node>>> bindings;
for (uint32_t i = 0; i < num_bindings; i++) {
std::string key = read_string();
auto val = read_node();
bindings.push_back({key, val});
}
auto body = read_node();
LetNode let(body, line);
let.bindings = std::move(bindings);
return std::make_shared<Node>(std::move(let));
}
case NodeType::LETREC: {
uint32_t num_bindings = read_u32();
std::vector<std::pair<std::string, std::shared_ptr<Node>>> bindings;
for (uint32_t i = 0; i < num_bindings; i++) {
std::string key = read_string();
auto val = read_node();
bindings.push_back({key, val});
}
auto body = read_node();
LetRecNode letrec(body, line);
letrec.bindings = std::move(bindings);
return std::make_shared<Node>(std::move(letrec));
}
case NodeType::ASSERT: {
auto cond = read_node();
auto body = read_node();
return std::make_shared<Node>(AssertNode(cond, body, line));
}
default:
throw std::runtime_error("Unknown node type in IR");
}
}
};
Deserializer::Deserializer() : pImpl(std::make_unique<Impl>()) {}
@ -256,7 +376,7 @@ IRModule Deserializer::deserialize(const std::vector<uint8_t>& data) {
}
if (pImpl->read_u8()) {
// TODO: deserialize AST
module.entry = pImpl->read_node();
}
return module;