brewery
notashelf /
2c9ad890b293837f959e0c9cb5aa77f7b8a2f508

nixir

public

Import-resolving Nix IR plugin

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

Commit 2c9ad890b293

tarball

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

unverified75 files changed+478-438
tests: move fixtures to dedicated dir

Signed-off-by: NotAShelf <raf@notashelf.dev>
Change-Id: I9d6ce6a264780f215b1b57d947b5264c6a6a6964
diff --git a/tests/ancient_let.nix b/tests/ancient_let.nixdeleted file mode 100644index 3d4cfec..0000000--- a/tests/ancient_let.nix+++ /dev/null@@ -1,8 +0,0 @@-# Test ancient let syntax: let { bindings; body = expr; }-# This is equivalent to: let bindings in expr, but has been deprecated-# in newer Nix versions.-let {-  x = 10;-  y = 20;-  body = x + y;-}diff --git a/tests/attrset.nix b/tests/attrset.nixdeleted file mode 100644index 18425c5..0000000--- a/tests/attrset.nix+++ /dev/null@@ -1,8 +0,0 @@-# Attrset test-{-  name = "test";-  value = 123;-  nested = {-    inner = true;-  };-}diff --git a/tests/attrset_var.nix b/tests/attrset_var.nixdeleted file mode 100644index 6f9db40..0000000--- a/tests/attrset_var.nix+++ /dev/null@@ -1,3 +0,0 @@-let-  x = 10;-in {a = x;}diff --git a/tests/block_comments.nix b/tests/block_comments.nixdeleted file mode 100644index b5de60f..0000000--- a/tests/block_comments.nix+++ /dev/null@@ -1,12 +0,0 @@-# Test block comments /* */-/* This is a block comment */-let-  x = 42; /* inline block comment */-  /* Multi-line-     block-     comment */-  y = 100;-in-/* Comment before expression */-x + y-/* Trailing comment */diff --git a/tests/comparison.nix b/tests/comparison.nixdeleted file mode 100644index a73c226..0000000--- a/tests/comparison.nix+++ /dev/null@@ -1,8 +0,0 @@-# Test comparison operators-let-  a = 10;-  b = 20;-in-  if a < b-  then true-  else falsediff --git a/tests/dynamic_attrs.nix b/tests/dynamic_attrs.nixdeleted file mode 100644index 3c32fd5..0000000--- a/tests/dynamic_attrs.nix+++ /dev/null@@ -1,15 +0,0 @@-# Test dynamic attribute names-# Note: Full dynamic attrs require runtime evaluation-# For now, testing that syntax is recognized-let-  key = "mykey";-in {-  # Static attribute for comparison-  static = "value";--  # Dynamic attribute name (basic string interpolation)-  # "${key}" = "dynamic_value";--  # For now, use workaround with static names-  mykey = "works";-}diff --git a/tests/fixtures/ancient_let.nix b/tests/fixtures/ancient_let.nixnew file mode 100644index 0000000..3d4cfec--- /dev/null+++ b/tests/fixtures/ancient_let.nix@@ -0,0 +1,8 @@+# Test ancient let syntax: let { bindings; body = expr; }+# This is equivalent to: let bindings in expr, but has been deprecated+# in newer Nix versions.+let {+  x = 10;+  y = 20;+  body = x + y;+}diff --git a/tests/fixtures/attrset.nix b/tests/fixtures/attrset.nixnew file mode 100644index 0000000..18425c5--- /dev/null+++ b/tests/fixtures/attrset.nix@@ -0,0 +1,8 @@+# Attrset test+{+  name = "test";+  value = 123;+  nested = {+    inner = true;+  };+}diff --git a/tests/fixtures/attrset_var.nix b/tests/fixtures/attrset_var.nixnew file mode 100644index 0000000..6f9db40--- /dev/null+++ b/tests/fixtures/attrset_var.nix@@ -0,0 +1,3 @@+let+  x = 10;+in {a = x;}diff --git a/tests/fixtures/block_comments.nix b/tests/fixtures/block_comments.nixnew file mode 100644index 0000000..301297d--- /dev/null+++ b/tests/fixtures/block_comments.nix@@ -0,0 +1,24 @@+# Test block comments /* */+/*+This is a block comment+*/+let+  x = 42;+  /*+  inline block comment+  */+  /*+  Multi-line+  block+  comment+  */+  y = 100;+in+  /*+  Comment before expression+  */+  x + y+/*+Trailing comment+*/+diff --git a/tests/fixtures/comparison.nix b/tests/fixtures/comparison.nixnew file mode 100644index 0000000..a73c226--- /dev/null+++ b/tests/fixtures/comparison.nix@@ -0,0 +1,8 @@+# Test comparison operators+let+  a = 10;+  b = 20;+in+  if a < b+  then true+  else falsediff --git a/tests/fixtures/dynamic_attr_full.nix b/tests/fixtures/dynamic_attr_full.nixnew file mode 100644index 0000000..3c7b39b--- /dev/null+++ b/tests/fixtures/dynamic_attr_full.nix@@ -0,0 +1,14 @@+# Test dynamic attribute names+let+  key = "mykey";+  value = 42;+in {+  # Dynamic attribute with string interpolation+  "${key}" = value;++  # Another dynamic attribute+  "${key}_suffix" = value + 1;++  # Static attribute for comparison+  static = 100;+}diff --git a/tests/fixtures/dynamic_attrs.nix b/tests/fixtures/dynamic_attrs.nixnew file mode 100644index 0000000..3c32fd5--- /dev/null+++ b/tests/fixtures/dynamic_attrs.nix@@ -0,0 +1,15 @@+# Test dynamic attribute names+# Note: Full dynamic attrs require runtime evaluation+# For now, testing that syntax is recognized+let+  key = "mykey";+in {+  # Static attribute for comparison+  static = "value";++  # Dynamic attribute name (basic string interpolation)+  # "${key}" = "dynamic_value";++  # For now, use workaround with static names+  mykey = "works";+}diff --git a/tests/fixtures/float_test.nix b/tests/fixtures/float_test.nixnew file mode 100644index 0000000..c239c60--- /dev/null+++ b/tests/fixtures/float_test.nix@@ -0,0 +1 @@+1.5diff --git a/tests/fixtures/home_path.nix b/tests/fixtures/home_path.nixnew file mode 100644index 0000000..ccfb107--- /dev/null+++ b/tests/fixtures/home_path.nix@@ -0,0 +1,11 @@+# Test home-relative paths+# Note: This will resolve to the actual home directory at evaluation time+let+  # Example home path (will be expanded by evaluator)+  config = ~/..config;+  file = ~/.bashrc;+in {+  # These are just path values that will be expanded+  configPath = config;+  filePath = file;+}diff --git a/tests/fixtures/if.nix b/tests/fixtures/if.nixnew file mode 100644index 0000000..7e48f38--- /dev/null+++ b/tests/fixtures/if.nix@@ -0,0 +1,4 @@+# Conditional test+if true+then 1+else 2diff --git a/tests/fixtures/import_lookup.nix b/tests/fixtures/import_lookup.nixnew file mode 100644index 0000000..448b1ea--- /dev/null+++ b/tests/fixtures/import_lookup.nix@@ -0,0 +1,3 @@+# Test import with lookup path+# Common pattern: import <nixpkgs> { }+import <nixpkgs>diff --git a/tests/fixtures/import_simple.nix b/tests/fixtures/import_simple.nixnew file mode 100644index 0000000..1e024cc--- /dev/null+++ b/tests/fixtures/import_simple.nix@@ -0,0 +1,9 @@+# Test import expression+# Import evaluates the file and returns its value+# Import a file that returns a simple value (42)+import ./simple.nix+# Can also import lookup paths:+# import <nixpkgs> { }+# Import with path expressions:+# import (./dir + "/file.nix")+diff --git a/tests/fixtures/indented_string.nix b/tests/fixtures/indented_string.nixnew file mode 100644index 0000000..16c6026--- /dev/null+++ b/tests/fixtures/indented_string.nix@@ -0,0 +1,31 @@+# Test indented strings (multi-line strings with '' delimiters)+let+  # Simple indented string+  simple = ''+    Hello+    World+  '';++  # Indented string with interpolation+  name = "Nix";+  greeting = ''+    Welcome to ${name}!+    This is indented.+  '';++  # Escape sequences+  escapes = ''+    Literal dollar: ''$+    Literal quotes: '''+    Regular text+  '';++  # Shell script example (common use case)+  script = ''+    #!/bin/bash+    echo "Running script"+    ls -la+  '';+in {+  inherit simple greeting escapes script;+}diff --git a/tests/fixtures/inherit.nix b/tests/fixtures/inherit.nixnew file mode 100644index 0000000..3382979--- /dev/null+++ b/tests/fixtures/inherit.nix@@ -0,0 +1,20 @@+# Test inherit keyword+let+  x = 10;+  y = 20;+  attrs = {+    a = 1;+    b = 2;+    c = 3;+  };+in {+  # Basic inherit from outer scope+  inherit x y;++  # Inherit from expression+  inherit (attrs) a b;++  # Mixed+  z = 30;+  inherit (attrs) c;+}diff --git a/tests/fixtures/inherit_from.nix b/tests/fixtures/inherit_from.nixnew file mode 100644index 0000000..31c2a00--- /dev/null+++ b/tests/fixtures/inherit_from.nix@@ -0,0 +1,3 @@+let+  attrs = {a = 1;};+in {inherit (attrs) a;}diff --git a/tests/fixtures/inherit_simple.nix b/tests/fixtures/inherit_simple.nixnew file mode 100644index 0000000..2806435--- /dev/null+++ b/tests/fixtures/inherit_simple.nix@@ -0,0 +1,3 @@+let+  x = 10;+in {inherit x;}diff --git a/tests/fixtures/lambda_pattern.nix b/tests/fixtures/lambda_pattern.nixnew file mode 100644index 0000000..6fd3910--- /dev/null+++ b/tests/fixtures/lambda_pattern.nix@@ -0,0 +1,61 @@+# Test lambda patterns+let+  # Basic destructuring+  f1 = {+    a,+    b,+  }:+    a + b;++  # With default values+  f2 = {+    a,+    b ? 10,+  }:+    a + b;++  # With ellipsis (extra fields allowed)+  f3 = {a, ...}: a * 2;++  # Named pattern with ellipsis to allow extra fields+  f4 = arg @ {+    a,+    b,+    ...+  }:+    a + b + arg.c;++  # Simple lambda (not a pattern)+  f5 = x: x + 1;+in {+  # Test basic destructuring+  test1 = f1 {+    a = 3;+    b = 4;+  };++  # Test with defaults (provide both)+  test2a = f2 {+    a = 5;+    b = 6;+  };++  # Test with defaults (use default for b)+  test2b = f2 {a = 5;};++  # Test ellipsis (extra field ignored)+  test3 = f3 {+    a = 7;+    extra = 999;+  };++  # Test named pattern+  test4 = f4 {+    a = 1;+    b = 2;+    c = 3;+  };++  # Test simple lambda+  test5 = f5 10;+}diff --git a/tests/fixtures/let.nix b/tests/fixtures/let.nixnew file mode 100644index 0000000..04b80ce--- /dev/null+++ b/tests/fixtures/let.nix@@ -0,0 +1,6 @@+# Let binding test+let+  x = 10;+  y = 20;+in+  xdiff --git a/tests/fixtures/list_concat.nix b/tests/fixtures/list_concat.nixnew file mode 100644index 0000000..a1b09f1--- /dev/null+++ b/tests/fixtures/list_concat.nix@@ -0,0 +1,15 @@+# Test list concatenation operator +++let+  list1 = [1 2 3];+  list2 = [4 5 6];+  empty = [];+in {+  # Basic concatenation+  combined = list1 ++ list2;++  # Concatenate with empty list+  with_empty = list1 ++ empty;++  # Nested concatenation+  triple = [1] ++ [2] ++ [3];+}diff --git a/tests/fixtures/list_simple.nix b/tests/fixtures/list_simple.nixnew file mode 100644index 0000000..7167967--- /dev/null+++ b/tests/fixtures/list_simple.nix@@ -0,0 +1,8 @@+# Test basic list support+let+  x = [1 2 3];+  y = [4 5 6];+  z = x ++ y; # List concatenation+in {+  inherit x y z;+}diff --git a/tests/fixtures/logical.nix b/tests/fixtures/logical.nixnew file mode 100644index 0000000..bae055f--- /dev/null+++ b/tests/fixtures/logical.nix@@ -0,0 +1,10 @@+# Test logical operators+let+  x = true;+  y = false;+in+  if x && y+  then 1+  else if x || y+  then 2+  else 3diff --git a/tests/fixtures/lookup_path.nix b/tests/fixtures/lookup_path.nixnew file mode 100644index 0000000..a770360--- /dev/null+++ b/tests/fixtures/lookup_path.nix@@ -0,0 +1,8 @@+# Test lookup path syntax+# Lookup paths resolve via NIX_PATH environment variable+# Example: <nixpkgs> -> /nix/var/nix/profiles/per-user/root/channels/nixpkgs+# Simple lookup path+<nixpkgs>+# Nested lookup path (common pattern)+# <nixpkgs/lib>+diff --git a/tests/fixtures/lookup_path_nested.nix b/tests/fixtures/lookup_path_nested.nixnew file mode 100644index 0000000..0478b00--- /dev/null+++ b/tests/fixtures/lookup_path_nested.nix@@ -0,0 +1,3 @@+# Test nested lookup path+# Common pattern in Nix: <nixpkgs/lib> or <nixpkgs/pkgs/stdenv>+<nixpkgs/lib>diff --git a/tests/fixtures/merge.nix b/tests/fixtures/merge.nixnew file mode 100644index 0000000..221d0f6--- /dev/null+++ b/tests/fixtures/merge.nix@@ -0,0 +1,2 @@+# Test attrset merge operator (//)+{a = {x = 1;} // {y = 2;};}diff --git a/tests/fixtures/nested_attrs.nix b/tests/fixtures/nested_attrs.nixnew file mode 100644index 0000000..874d08b--- /dev/null+++ b/tests/fixtures/nested_attrs.nix@@ -0,0 +1,13 @@+# Test nested attribute paths+{+  # Simple nested path+  a.b.c = 42;++  # Multiple nested paths+  x.y = 1;+  x.z = 2;++  # Mix of nested and non-nested+  foo = "bar";+  nested.deep.value = 100;+}diff --git a/tests/fixtures/operators.nix b/tests/fixtures/operators.nixnew file mode 100644index 0000000..c9e383b--- /dev/null+++ b/tests/fixtures/operators.nix@@ -0,0 +1,6 @@+# Test arithmetic operators+let+  x = 10;+  y = 5;+in+  (x + y) * 2diff --git a/tests/fixtures/or_in_attrset.nix b/tests/fixtures/or_in_attrset.nixnew file mode 100644index 0000000..d1ab7f9--- /dev/null+++ b/tests/fixtures/or_in_attrset.nix@@ -0,0 +1,6 @@+# Test 'or' in attrset context+let+  attrs = {a = 1;};+in {+  test = attrs.a or 999;+}diff --git a/tests/fixtures/or_simple.nix b/tests/fixtures/or_simple.nixnew file mode 100644index 0000000..d4de5be--- /dev/null+++ b/tests/fixtures/or_simple.nix@@ -0,0 +1,5 @@+# Simplest 'or' test+let+  x = {a = 1;};+in+  x.a or 2diff --git a/tests/fixtures/path_concat.nix b/tests/fixtures/path_concat.nixnew file mode 100644index 0000000..682175c--- /dev/null+++ b/tests/fixtures/path_concat.nix@@ -0,0 +1,13 @@+# Test path concatenation+let+  # Path + string = path+  p1 = ./foo + "/bar";++  # String + path = path+  p2 = "/prefix" + ./suffix;++  # Path + path = path+  p3 = ./dir + ./file;+in {+  inherit p1 p2 p3;+}diff --git a/tests/fixtures/precedence.nix b/tests/fixtures/precedence.nixnew file mode 100644index 0000000..3535775--- /dev/null+++ b/tests/fixtures/precedence.nix@@ -0,0 +1,12 @@+# Test operator precedence+let+  a = 1 + 2 * 3; # Should be 1 + (2 * 3) = 7+  b = 10 - 5 - 2; # Should be (10 - 5) - 2 = 3+  c = true && false || true; # Should be (true && false) || true = true+  d = 1 < 2 && 3 > 2; # Should be (1 < 2) && (3 > 2) = true+in {+  a = a;+  b = b;+  c = c;+  d = d;+}diff --git a/tests/fixtures/select_or_default.nix b/tests/fixtures/select_or_default.nixnew file mode 100644index 0000000..6144ff5--- /dev/null+++ b/tests/fixtures/select_or_default.nix@@ -0,0 +1,19 @@+# Test selection with 'or' default+let+  attrs = {+    a = 1;+    b = 2;+  };+in {+  # Attribute exists - should use value from attrs+  has_attr = attrs.a or 999;++  # Attribute doesn't exist - should use default+  missing_attr = attrs.c or 100;++  # Nested default expression+  nested = attrs.d or (attrs.a + attrs.b);++  # Default with literal+  with_string = attrs.name or "default_name";+}diff --git a/tests/fixtures/shortcircuit.nix b/tests/fixtures/shortcircuit.nixnew file mode 100644index 0000000..2326f2c--- /dev/null+++ b/tests/fixtures/shortcircuit.nix@@ -0,0 +1,10 @@+# Test short-circuit evaluation+let+  alwaysFalse = false;+  alwaysTrue = true;+  x = 10;+in {+  and_false = alwaysFalse && alwaysTrue;+  or_true = alwaysTrue || alwaysFalse;+  impl_false = alwaysFalse -> alwaysFalse;+}diff --git a/tests/fixtures/shortcircuit2.nix b/tests/fixtures/shortcircuit2.nixnew file mode 100644index 0000000..b75cf38--- /dev/null+++ b/tests/fixtures/shortcircuit2.nix@@ -0,0 +1,6 @@+# Test short-circuit evaluation+{+  and_false = false && true;+  or_true = true || false;+  impl_false = false -> false;+}diff --git a/tests/fixtures/simple.nix b/tests/fixtures/simple.nixnew file mode 100644index 0000000..68e636c--- /dev/null+++ b/tests/fixtures/simple.nix@@ -0,0 +1,2 @@+# Simple constant test+42diff --git a/tests/fixtures/simple_op.nix b/tests/fixtures/simple_op.nixnew file mode 100644index 0000000..e0ef584--- /dev/null+++ b/tests/fixtures/simple_op.nix@@ -0,0 +1 @@+1 + 2diff --git a/tests/fixtures/string_interp.nix b/tests/fixtures/string_interp.nixnew file mode 100644index 0000000..9edc11b--- /dev/null+++ b/tests/fixtures/string_interp.nix@@ -0,0 +1,20 @@+# Test string interpolation+let+  name = "world";+  x = 42;+  bool_val = true;+in {+  # Simple interpolation+  greeting = "Hello ${name}!";++  # Multiple interpolations+  multi = "x is ${x} and name is ${name}";++  # Expression evaluation in interpolation+  computed = "x + 10 = ${x + 10}";++  bool_check = "${bool_val} is true!";++  # Just a string, no interpolation+  plain = "plain text";+}diff --git a/tests/fixtures/unary.nix b/tests/fixtures/unary.nixnew file mode 100644index 0000000..b8e0e3e--- /dev/null+++ b/tests/fixtures/unary.nix@@ -0,0 +1,8 @@+# Test unary operators+let+  x = 10;+  y = true;+in {+  neg = -x;+  not = !y;+}diff --git a/tests/fixtures/uri_test.nix b/tests/fixtures/uri_test.nixnew file mode 100644index 0000000..ad93389--- /dev/null+++ b/tests/fixtures/uri_test.nix@@ -0,0 +1,3 @@+https://example.com/path?query=1+#frag+diff --git a/tests/float_test.nix b/tests/float_test.nixdeleted file mode 100644index c239c60..0000000--- a/tests/float_test.nix+++ /dev/null@@ -1 +0,0 @@-1.5diff --git a/tests/home_path.nix b/tests/home_path.nixdeleted file mode 100644index ccfb107..0000000--- a/tests/home_path.nix+++ /dev/null@@ -1,11 +0,0 @@-# Test home-relative paths-# Note: This will resolve to the actual home directory at evaluation time-let-  # Example home path (will be expanded by evaluator)-  config = ~/..config;-  file = ~/.bashrc;-in {-  # These are just path values that will be expanded-  configPath = config;-  filePath = file;-}diff --git a/tests/if.nix b/tests/if.nixdeleted file mode 100644index 7e48f38..0000000--- a/tests/if.nix+++ /dev/null@@ -1,4 +0,0 @@-# Conditional test-if true-then 1-else 2diff --git a/tests/import_lookup.nix b/tests/import_lookup.nixdeleted file mode 100644index 448b1ea..0000000--- a/tests/import_lookup.nix+++ /dev/null@@ -1,3 +0,0 @@-# Test import with lookup path-# Common pattern: import <nixpkgs> { }-import <nixpkgs>diff --git a/tests/import_simple.nix b/tests/import_simple.nixdeleted file mode 100644index 023b49d..0000000--- a/tests/import_simple.nix+++ /dev/null@@ -1,11 +0,0 @@-# Test import expression-# Import evaluates the file and returns its value--# Import a file that returns a simple value (42)-import ./simple.nix--# Can also import lookup paths:-# import <nixpkgs> { }--# Import with path expressions:-# import (./dir + "/file.nix")diff --git a/tests/indented_string.nix b/tests/indented_string.nixdeleted file mode 100644index 16c6026..0000000--- a/tests/indented_string.nix+++ /dev/null@@ -1,31 +0,0 @@-# Test indented strings (multi-line strings with '' delimiters)-let-  # Simple indented string-  simple = ''-    Hello-    World-  '';--  # Indented string with interpolation-  name = "Nix";-  greeting = ''-    Welcome to ${name}!-    This is indented.-  '';--  # Escape sequences-  escapes = ''-    Literal dollar: ''$-    Literal quotes: '''-    Regular text-  '';--  # Shell script example (common use case)-  script = ''-    #!/bin/bash-    echo "Running script"-    ls -la-  '';-in {-  inherit simple greeting escapes script;-}diff --git a/tests/inherit.nix b/tests/inherit.nixdeleted file mode 100644index 3382979..0000000--- a/tests/inherit.nix+++ /dev/null@@ -1,20 +0,0 @@-# Test inherit keyword-let-  x = 10;-  y = 20;-  attrs = {-    a = 1;-    b = 2;-    c = 3;-  };-in {-  # Basic inherit from outer scope-  inherit x y;--  # Inherit from expression-  inherit (attrs) a b;--  # Mixed-  z = 30;-  inherit (attrs) c;-}diff --git a/tests/inherit_from.nix b/tests/inherit_from.nixdeleted file mode 100644index 31c2a00..0000000--- a/tests/inherit_from.nix+++ /dev/null@@ -1,3 +0,0 @@-let-  attrs = {a = 1;};-in {inherit (attrs) a;}diff --git a/tests/inherit_simple.nix b/tests/inherit_simple.nixdeleted file mode 100644index 2806435..0000000--- a/tests/inherit_simple.nix+++ /dev/null@@ -1,3 +0,0 @@-let-  x = 10;-in {inherit x;}diff --git a/tests/lambda_pattern.nix b/tests/lambda_pattern.nixdeleted file mode 100644index 6fd3910..0000000--- a/tests/lambda_pattern.nix+++ /dev/null@@ -1,61 +0,0 @@-# Test lambda patterns-let-  # Basic destructuring-  f1 = {-    a,-    b,-  }:-    a + b;--  # With default values-  f2 = {-    a,-    b ? 10,-  }:-    a + b;--  # With ellipsis (extra fields allowed)-  f3 = {a, ...}: a * 2;--  # Named pattern with ellipsis to allow extra fields-  f4 = arg @ {-    a,-    b,-    ...-  }:-    a + b + arg.c;--  # Simple lambda (not a pattern)-  f5 = x: x + 1;-in {-  # Test basic destructuring-  test1 = f1 {-    a = 3;-    b = 4;-  };--  # Test with defaults (provide both)-  test2a = f2 {-    a = 5;-    b = 6;-  };--  # Test with defaults (use default for b)-  test2b = f2 {a = 5;};--  # Test ellipsis (extra field ignored)-  test3 = f3 {-    a = 7;-    extra = 999;-  };--  # Test named pattern-  test4 = f4 {-    a = 1;-    b = 2;-    c = 3;-  };--  # Test simple lambda-  test5 = f5 10;-}diff --git a/tests/let.nix b/tests/let.nixdeleted file mode 100644index 04b80ce..0000000--- a/tests/let.nix+++ /dev/null@@ -1,6 +0,0 @@-# Let binding test-let-  x = 10;-  y = 20;-in-  xdiff --git a/tests/list_concat.nix b/tests/list_concat.nixdeleted file mode 100644index a1b09f1..0000000--- a/tests/list_concat.nix+++ /dev/null@@ -1,15 +0,0 @@-# Test list concatenation operator ++-let-  list1 = [1 2 3];-  list2 = [4 5 6];-  empty = [];-in {-  # Basic concatenation-  combined = list1 ++ list2;--  # Concatenate with empty list-  with_empty = list1 ++ empty;--  # Nested concatenation-  triple = [1] ++ [2] ++ [3];-}diff --git a/tests/logical.nix b/tests/logical.nixdeleted file mode 100644index bae055f..0000000--- a/tests/logical.nix+++ /dev/null@@ -1,10 +0,0 @@-# Test logical operators-let-  x = true;-  y = false;-in-  if x && y-  then 1-  else if x || y-  then 2-  else 3diff --git a/tests/lookup_path.nix b/tests/lookup_path.nixdeleted file mode 100644index e8bb4ca..0000000--- a/tests/lookup_path.nix+++ /dev/null@@ -1,9 +0,0 @@-# Test lookup path syntax-# Lookup paths resolve via NIX_PATH environment variable-# Example: <nixpkgs> -> /nix/var/nix/profiles/per-user/root/channels/nixpkgs--# Simple lookup path-<nixpkgs>--# Nested lookup path (common pattern)-# <nixpkgs/lib>diff --git a/tests/lookup_path_nested.nix b/tests/lookup_path_nested.nixdeleted file mode 100644index 0478b00..0000000--- a/tests/lookup_path_nested.nix+++ /dev/null@@ -1,3 +0,0 @@-# Test nested lookup path-# Common pattern in Nix: <nixpkgs/lib> or <nixpkgs/pkgs/stdenv>-<nixpkgs/lib>diff --git a/tests/merge.nix b/tests/merge.nixdeleted file mode 100644index 221d0f6..0000000--- a/tests/merge.nix+++ /dev/null@@ -1,2 +0,0 @@-# Test attrset merge operator (//)-{a = {x = 1;} // {y = 2;};}diff --git a/tests/nested_attrs.nix b/tests/nested_attrs.nixdeleted file mode 100644index 874d08b..0000000--- a/tests/nested_attrs.nix+++ /dev/null@@ -1,13 +0,0 @@-# Test nested attribute paths-{-  # Simple nested path-  a.b.c = 42;--  # Multiple nested paths-  x.y = 1;-  x.z = 2;--  # Mix of nested and non-nested-  foo = "bar";-  nested.deep.value = 100;-}diff --git a/tests/operators.nix b/tests/operators.nixdeleted file mode 100644index c9e383b..0000000--- a/tests/operators.nix+++ /dev/null@@ -1,6 +0,0 @@-# Test arithmetic operators-let-  x = 10;-  y = 5;-in-  (x + y) * 2diff --git a/tests/or_in_attrset.nix b/tests/or_in_attrset.nixdeleted file mode 100644index 406149b..0000000--- a/tests/or_in_attrset.nix+++ /dev/null@@ -1,6 +0,0 @@-# Test 'or' in attrset context-let-  attrs = { a = 1; };-in {-  test = attrs.a or 999;-}diff --git a/tests/or_simple.nix b/tests/or_simple.nixdeleted file mode 100644index 6025a4d..0000000--- a/tests/or_simple.nix+++ /dev/null@@ -1,4 +0,0 @@-# Simplest 'or' test-let-  x = { a = 1; };-in x.a or 2diff --git a/tests/path_concat.nix b/tests/path_concat.nixdeleted file mode 100644index 682175c..0000000--- a/tests/path_concat.nix+++ /dev/null@@ -1,13 +0,0 @@-# Test path concatenation-let-  # Path + string = path-  p1 = ./foo + "/bar";--  # String + path = path-  p2 = "/prefix" + ./suffix;--  # Path + path = path-  p3 = ./dir + ./file;-in {-  inherit p1 p2 p3;-}diff --git a/tests/precedence.nix b/tests/precedence.nixdeleted file mode 100644index 3535775..0000000--- a/tests/precedence.nix+++ /dev/null@@ -1,12 +0,0 @@-# Test operator precedence-let-  a = 1 + 2 * 3; # Should be 1 + (2 * 3) = 7-  b = 10 - 5 - 2; # Should be (10 - 5) - 2 = 3-  c = true && false || true; # Should be (true && false) || true = true-  d = 1 < 2 && 3 > 2; # Should be (1 < 2) && (3 > 2) = true-in {-  a = a;-  b = b;-  c = c;-  d = d;-}diff --git a/tests/regression_test.cpp b/tests/regression_test.cppindex 1b4c4ce..f9f9914 100644--- a/tests/regression_test.cpp+++ b/tests/regression_test.cpp@@ -1,3 +1,4 @@+#include "irc/parser.h" #include "irc/serializer.h" #include "irc/types.h" #include <cassert>@@ -7,21 +8,21 @@ using namespace nix_irc;  int failures = 0; -#define TEST_CHECK(cond, msg)                                                  \-  do {                                                                         \-    if (!(cond)) {                                                             \-      std::cerr << "  FAIL: " << msg << std::endl;                             \-      failures++;                                                              \-    } else {                                                                   \-      std::cout << "  PASS: " << msg << std::endl;                             \-    }                                                                          \+#define TEST_CHECK(cond, msg)                                                                      \+  do {                                                                                             \+    if (!(cond)) {                                                                                 \+      std::cerr << "  FAIL: " << msg << std::endl;                                                 \+      failures++;                                                                                  \+    } else {                                                                                       \+      std::cout << "  PASS: " << msg << std::endl;                                                 \+    }                                                                                              \   } while (0)  #define TEST_PASS(msg) std::cout << "  PASS: " << msg << std::endl-#define TEST_FAIL(msg)                                                         \-  do {                                                                         \-    std::cerr << "  FAIL: " << msg << std::endl;                               \-    failures++;                                                                \+#define TEST_FAIL(msg)                                                                             \+  do {                                                                                             \+    std::cerr << "  FAIL: " << msg << std::endl;                                                   \+    failures++;                                                                                    \   } while (0)  void test_enum_compatibility() {@@ -30,33 +31,28 @@ void test_enum_compatibility() {   if (static_cast<uint8_t>(NodeType::WITH) == 0x32) {     std::cout << "  PASS: WITH has correct value 0x32" << std::endl;   } else {-    std::cerr << "  FAIL: WITH should be 0x32, got "-              << static_cast<uint8_t>(NodeType::WITH) << std::endl;+    std::cerr << "  FAIL: WITH should be 0x32, got " << static_cast<uint8_t>(NodeType::WITH)+              << std::endl;   }    if (static_cast<uint8_t>(NodeType::HAS_ATTR) == 0x34) {-    std::cout << "  PASS: HAS_ATTR has value 0x34 (new slot after WITH bump)"-              << std::endl;+    std::cout << "  PASS: HAS_ATTR has value 0x34 (new slot after WITH bump)" << std::endl;   } else if (static_cast<uint8_t>(NodeType::HAS_ATTR) == 0x33 &&              static_cast<uint8_t>(NodeType::WITH) == 0x32) {     std::cout << "  PASS: HAS_ATTR has value 0x33 (restored original with WITH "                  "at 0x32)"               << std::endl;   } else {-    std::cerr << "  FAIL: HAS_ATTR value is "-              << static_cast<uint8_t>(NodeType::HAS_ATTR)+    std::cerr << "  FAIL: HAS_ATTR value is " << static_cast<uint8_t>(NodeType::HAS_ATTR)               << " (expected 0x34 or 0x33 with WITH=0x32)" << std::endl;   }    if (IR_VERSION == 2) {-    std::cout << "  PASS: IR_VERSION bumped to 2 for breaking change"-              << std::endl;+    std::cout << "  PASS: IR_VERSION bumped to 2 for breaking change" << std::endl;   } else if (static_cast<uint8_t>(NodeType::WITH) == 0x32) {-    std::cout << "  PASS: IR_VERSION unchanged but WITH restored to 0x32"-              << std::endl;+    std::cout << "  PASS: IR_VERSION unchanged but WITH restored to 0x32" << std::endl;   } else {-    std::cerr << "  FAIL: Either bump IR_VERSION or fix enum values"-              << std::endl;+    std::cerr << "  FAIL: Either bump IR_VERSION or fix enum values" << std::endl;   } } @@ -80,19 +76,16 @@ void test_serializer_select_with_default() {   Deserializer deser;   auto loaded = deser.deserialize(bytes); -  auto *loaded_select = loaded.entry->get_if<SelectNode>();-  if (loaded_select && loaded_select->default_expr &&-      *loaded_select->default_expr) {-    auto *def_val = (*loaded_select->default_expr)->get_if<ConstIntNode>();+  auto* loaded_select = loaded.entry->get_if<SelectNode>();+  if (loaded_select && loaded_select->default_expr && *loaded_select->default_expr) {+    auto* def_val = (*loaded_select->default_expr)->get_if<ConstIntNode>();     if (def_val && def_val->value == 100) {-      std::cout << "  PASS: SELECT with default_expr round-trips correctly"-                << std::endl;+      std::cout << "  PASS: SELECT with default_expr round-trips correctly" << std::endl;     } else {       std::cerr << "  FAIL: default_expr value incorrect" << std::endl;     }   } else {-    std::cerr << "  FAIL: default_expr not deserialized (missing u8 flag read)"-              << std::endl;+    std::cerr << "  FAIL: default_expr not deserialized (missing u8 flag read)" << std::endl;   } } @@ -114,11 +107,9 @@ void test_serializer_select_without_default() {   Deserializer deser;   auto loaded = deser.deserialize(bytes); -  auto *loaded_select = loaded.entry->get_if<SelectNode>();-  if (loaded_select &&-      (!loaded_select->default_expr || !*loaded_select->default_expr)) {-    std::cout << "  PASS: SELECT without default_expr round-trips correctly"-              << std::endl;+  auto* loaded_select = loaded.entry->get_if<SelectNode>();+  if (loaded_select && (!loaded_select->default_expr || !*loaded_select->default_expr)) {+    std::cout << "  PASS: SELECT without default_expr round-trips correctly" << std::endl;   } else {     std::cerr << "  FAIL: default_expr should be null/absent" << std::endl;   }@@ -127,34 +118,53 @@ void test_serializer_select_without_default() { void test_parser_brace_depth_in_strings() {   std::cout << "> Parser brace depth handling in strings..." << std::endl; -  std::string test_input = R"(-        let s = "test}"; in ${s}-    )";+  std::string test_input = R"(let s = "test}"; in s)"; -  std::cout << "  Test input contains '}' inside string - should not end "-               "interpolation"-            << std::endl;-  std::cout << "  NOTE: This test requires running through actual parser"-            << std::endl;+  try {+    Parser parser;+    auto ast = parser.parse(test_input);+    TEST_PASS("Brace inside string does not confuse parser");+  } catch (const std::exception& e) {+    TEST_FAIL("Parser should handle '}' inside strings");+  } }  void test_parser_has_ellipsis_usage() {   std::cout << "> Parser has_ellipsis usage..." << std::endl; -  std::cout << "  NOTE: LambdaNode should have strict_pattern field when "-               "has_ellipsis is false"-            << std::endl;-  std::cout << "  This requires checking the parser output for strict patterns"-            << std::endl;+  std::string with_ellipsis = "{ a, ... }: a";+  std::string without_ellipsis = "{ a, b }: a + b";++  try {+    Parser parser1;+    auto ast1 = parser1.parse(with_ellipsis);+    TEST_PASS("Pattern with ellipsis parses correctly");++    Parser parser2;+    auto ast2 = parser2.parse(without_ellipsis);+    TEST_PASS("Pattern without ellipsis parses correctly");+  } catch (const std::exception& e) {+    TEST_FAIL("Pattern parsing failed");+  } }  void test_parser_expect_in_speculative_parsing() {   std::cout << "> Parser expect() in speculative parsing..." << std::endl; -  std::cout << "  NOTE: try_parse_lambda should not throw on non-lambda input"-            << std::endl;-  std::cout << "  This requires testing parser with invalid lambda patterns"-            << std::endl;+  std::string not_a_lambda = "1 + 2";+  std::string actual_lambda = "x: x + 1";++  try {+    Parser parser1;+    auto ast1 = parser1.parse(not_a_lambda);+    TEST_PASS("Non-lambda input does not cause parser to throw");++    Parser parser2;+    auto ast2 = parser2.parse(actual_lambda);+    TEST_PASS("Actual lambda parses correctly");+  } catch (const std::exception& e) {+    TEST_FAIL("Parser should handle both lambda and non-lambda input");+  } }  void test_lookup_path_node() {@@ -170,10 +180,9 @@ void test_lookup_path_node() {   Deserializer deser;   auto loaded = deser.deserialize(bytes); -  auto *loaded_lookup = loaded.entry->get_if<ConstLookupPathNode>();+  auto* loaded_lookup = loaded.entry->get_if<ConstLookupPathNode>();   TEST_CHECK(loaded_lookup != nullptr, "Deserialized node is ConstLookupPathNode");-  TEST_CHECK(loaded_lookup && loaded_lookup->value == "nixpkgs",-             "Lookup path value is 'nixpkgs'");+  TEST_CHECK(loaded_lookup && loaded_lookup->value == "nixpkgs", "Lookup path value is 'nixpkgs'"); }  void test_import_node() {@@ -190,16 +199,14 @@ void test_import_node() {   Deserializer deser;   auto loaded = deser.deserialize(bytes); -  auto *loaded_import = loaded.entry->get_if<ImportNode>();+  auto* loaded_import = loaded.entry->get_if<ImportNode>();   TEST_CHECK(loaded_import != nullptr, "Deserialized node is ImportNode");-  TEST_CHECK(loaded_import && loaded_import->path != nullptr,-             "Import node has path");+  TEST_CHECK(loaded_import && loaded_import->path != nullptr, "Import node has path");    if (loaded_import && loaded_import->path) {-    auto *path_node = loaded_import->path->get_if<ConstPathNode>();+    auto* path_node = loaded_import->path->get_if<ConstPathNode>();     TEST_CHECK(path_node != nullptr, "Import path is ConstPathNode");-    TEST_CHECK(path_node && path_node->value == "./test.nix",-               "Import path value is './test.nix'");+    TEST_CHECK(path_node && path_node->value == "./test.nix", "Import path value is './test.nix'");   } } @@ -217,14 +224,13 @@ void test_import_with_lookup_path() {   Deserializer deser;   auto loaded = deser.deserialize(bytes); -  auto *loaded_import = loaded.entry->get_if<ImportNode>();+  auto* loaded_import = loaded.entry->get_if<ImportNode>();   TEST_CHECK(loaded_import != nullptr, "Deserialized node is ImportNode");    if (loaded_import && loaded_import->path) {-    auto *lookup_node = loaded_import->path->get_if<ConstLookupPathNode>();+    auto* lookup_node = loaded_import->path->get_if<ConstLookupPathNode>();     TEST_CHECK(lookup_node != nullptr, "Import path is ConstLookupPathNode");-    TEST_CHECK(lookup_node && lookup_node->value == "nixpkgs",-               "Lookup path value is 'nixpkgs'");+    TEST_CHECK(lookup_node && lookup_node->value == "nixpkgs", "Lookup path value is 'nixpkgs'");   } } @@ -241,7 +247,7 @@ void test_uri_node() {   Deserializer deser;   auto loaded = deser.deserialize(bytes); -  auto *loaded_uri = loaded.entry->get_if<ConstURINode>();+  auto* loaded_uri = loaded.entry->get_if<ConstURINode>();   TEST_CHECK(loaded_uri != nullptr, "Deserialized node is ConstURINode");   TEST_CHECK(loaded_uri && loaded_uri->value == "https://example.com",              "URI value is 'https://example.com'");@@ -260,10 +266,9 @@ void test_float_node() {   Deserializer deser;   auto loaded = deser.deserialize(bytes); -  auto *loaded_float = loaded.entry->get_if<ConstFloatNode>();+  auto* loaded_float = loaded.entry->get_if<ConstFloatNode>();   TEST_CHECK(loaded_float != nullptr, "Deserialized node is ConstFloatNode");-  TEST_CHECK(loaded_float && loaded_float->value > 3.14 &&-                 loaded_float->value < 3.15,+  TEST_CHECK(loaded_float && loaded_float->value > 3.14 && loaded_float->value < 3.15,              "Float value is approximately 3.14159"); } diff --git a/tests/select_or_default.nix b/tests/select_or_default.nixdeleted file mode 100644index df91875..0000000--- a/tests/select_or_default.nix+++ /dev/null@@ -1,16 +0,0 @@-# Test selection with 'or' default-let-  attrs = { a = 1; b = 2; };-in {-  # Attribute exists - should use value from attrs-  has_attr = attrs.a or 999;--  # Attribute doesn't exist - should use default-  missing_attr = attrs.c or 100;--  # Nested default expression-  nested = attrs.d or (attrs.a + attrs.b);--  # Default with literal-  with_string = attrs.name or "default_name";-}diff --git a/tests/shortcircuit.nix b/tests/shortcircuit.nixdeleted file mode 100644index 2326f2c..0000000--- a/tests/shortcircuit.nix+++ /dev/null@@ -1,10 +0,0 @@-# Test short-circuit evaluation-let-  alwaysFalse = false;-  alwaysTrue = true;-  x = 10;-in {-  and_false = alwaysFalse && alwaysTrue;-  or_true = alwaysTrue || alwaysFalse;-  impl_false = alwaysFalse -> alwaysFalse;-}diff --git a/tests/shortcircuit2.nix b/tests/shortcircuit2.nixdeleted file mode 100644index b75cf38..0000000--- a/tests/shortcircuit2.nix+++ /dev/null@@ -1,6 +0,0 @@-# Test short-circuit evaluation-{-  and_false = false && true;-  or_true = true || false;-  impl_false = false -> false;-}diff --git a/tests/simple.nix b/tests/simple.nixdeleted file mode 100644index 68e636c..0000000--- a/tests/simple.nix+++ /dev/null@@ -1,2 +0,0 @@-# Simple constant test-42diff --git a/tests/simple_op.nix b/tests/simple_op.nixdeleted file mode 100644index e0ef584..0000000--- a/tests/simple_op.nix+++ /dev/null@@ -1 +0,0 @@-1 + 2diff --git a/tests/string_interp.nix b/tests/string_interp.nixdeleted file mode 100644index 9edc11b..0000000--- a/tests/string_interp.nix+++ /dev/null@@ -1,20 +0,0 @@-# Test string interpolation-let-  name = "world";-  x = 42;-  bool_val = true;-in {-  # Simple interpolation-  greeting = "Hello ${name}!";--  # Multiple interpolations-  multi = "x is ${x} and name is ${name}";--  # Expression evaluation in interpolation-  computed = "x + 10 = ${x + 10}";--  bool_check = "${bool_val} is true!";--  # Just a string, no interpolation-  plain = "plain text";-}diff --git a/tests/unary.nix b/tests/unary.nixdeleted file mode 100644index b8e0e3e..0000000--- a/tests/unary.nix+++ /dev/null@@ -1,8 +0,0 @@-# Test unary operators-let-  x = 10;-  y = true;-in {-  neg = -x;-  not = !y;-}diff --git a/tests/uri_test.nix b/tests/uri_test.nixdeleted file mode 100644index ad93389..0000000--- a/tests/uri_test.nix+++ /dev/null@@ -1,3 +0,0 @@-https://example.com/path?query=1-#frag-