brewery
notashelf /
584d84542ecc0ab897776aad4f346f60919be21e

nixir

public

Import-resolving Nix IR plugin

Star0tarball
clone
ssh://git@git.notashelf.dev:33/notashelf/nixir.git

Commit 584d84542ecc

tarball

NotAShelf <raf@notashelf.dev> · 2026-04-24 20:13 UTC

unverified1 files changed+117-0
irc: add serialization support for patterns and string interpolation

Signed-off-by: NotAShelf <raf@notashelf.dev>
Change-Id: I244ae722016b5b49915e23522a1fb72e6a6a6964
diff --git a/src/irc/serializer.cpp b/src/irc/serializer.cppindex 73051a7..23cd392 100644--- a/src/irc/serializer.cpp+++ b/src/irc/serializer.cpp@@ -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");     }