From 6a1cdedcaedecff623a5ff22f6d439325f5dd18d Mon Sep 17 00:00:00 2001 From: Richard Feldman Date: Mon, 24 Nov 2025 23:27:02 -0500 Subject: [PATCH] Fix some more edge cases --- src/canonicalize/Can.zig | 217 ++-- .../nominal/progressive_qualification.md | 1046 +++++++++++++++++ 2 files changed, 1146 insertions(+), 117 deletions(-) create mode 100644 test/snapshots/nominal/progressive_qualification.md diff --git a/src/canonicalize/Can.zig b/src/canonicalize/Can.zig index c7efb1bf83..158a536256 100644 --- a/src/canonicalize/Can.zig +++ b/src/canonicalize/Can.zig @@ -624,6 +624,90 @@ fn introduceTypeNameOnly( try self.exposed_type_texts.put(self.env.gpa, type_text, region); } +/// Recursively introduce nested item aliases into the current scope. +/// Given a type prefix (e.g., "Inner" or "Inner.Deep"), this adds aliases for all items +/// defined in that nested type and all of its nested types. +/// +/// For example, if we're in Outer's scope and Inner has: +/// - Inner.val = 1 +/// - Inner.Deep := [].{ deepVal = 2 } +/// +/// This will add: +/// - "Inner.val" -> pattern for Inner.val +/// - "Inner.Deep.deepVal" -> pattern for Inner.Deep.deepVal +fn introduceNestedItemAliases( + self: *Self, + qualified_parent_idx: Ident.Idx, // Fully qualified parent, e.g., "Module.Outer.Inner" + prefix: []const u8, // User-facing prefix for this scope, e.g., "Inner" + assoc_statements: anytype, +) std.mem.Allocator.Error!void { + for (self.parse_ir.store.statementSlice(assoc_statements)) |assoc_stmt_idx| { + const assoc_stmt = self.parse_ir.store.getStatement(assoc_stmt_idx); + switch (assoc_stmt) { + .decl => |decl| { + const pattern = self.parse_ir.store.getPattern(decl.pattern); + if (pattern == .ident) { + const pattern_ident_tok = pattern.ident.ident_tok; + if (self.parse_ir.tokens.resolveIdentifier(pattern_ident_tok)) |decl_ident| { + // Build fully qualified name (e.g., "Module.Outer.Inner.val") + const qualified_text = self.env.getIdent(qualified_parent_idx); + const decl_text = self.env.getIdent(decl_ident); + const full_qualified_ident_idx = try self.env.insertQualifiedIdent(qualified_text, decl_text); + + // Look up the fully qualified pattern + switch (self.scopeLookup(.ident, full_qualified_ident_idx)) { + .found => |pattern_idx| { + const scope = &self.scopes.items[self.scopes.items.len - 1]; + + // Build prefixed name for this scope (e.g., "Inner.val") + // Need to copy prefix to buffer to avoid invalidation + var prefix_buf: [256]u8 = undefined; + if (prefix.len > prefix_buf.len) continue; + @memcpy(prefix_buf[0..prefix.len], prefix); + const safe_prefix = prefix_buf[0..prefix.len]; + + const decl_text_fresh = self.env.getIdent(decl_ident); + const prefixed_ident_idx = try self.env.insertQualifiedIdent(safe_prefix, decl_text_fresh); + try scope.idents.put(self.env.gpa, prefixed_ident_idx, pattern_idx); + }, + .not_found => {}, + } + } + } + }, + .type_decl => |nested_type_decl| { + // Recursively process nested types + if (nested_type_decl.associated) |nested_assoc| { + const nested_header = self.parse_ir.store.getTypeHeader(nested_type_decl.header) catch continue; + const nested_type_ident = self.parse_ir.tokens.resolveIdentifier(nested_header.name) orelse continue; + + // Build fully qualified name for the nested type + const qualified_text = self.env.getIdent(qualified_parent_idx); + const nested_type_text = self.env.getIdent(nested_type_ident); + const nested_qualified_idx = try self.env.insertQualifiedIdent(qualified_text, nested_type_text); + + // Build new prefix (e.g., "Inner.Deep") + // Need to copy to buffer to avoid invalidation + var new_prefix_buf: [256]u8 = undefined; + if (prefix.len > new_prefix_buf.len) continue; + @memcpy(new_prefix_buf[0..prefix.len], prefix); + + // Re-fetch nested_type_text after insertQualifiedIdent may have reallocated + const nested_type_text_fresh = self.env.getIdent(nested_type_ident); + if (prefix.len + 1 + nested_type_text_fresh.len > new_prefix_buf.len) continue; + new_prefix_buf[prefix.len] = '.'; + @memcpy(new_prefix_buf[prefix.len + 1 ..][0..nested_type_text_fresh.len], nested_type_text_fresh); + const new_prefix = new_prefix_buf[0 .. prefix.len + 1 + nested_type_text_fresh.len]; + + // Recursively introduce items from this nested type + try self.introduceNestedItemAliases(nested_qualified_idx, new_prefix, nested_assoc.statements); + } + }, + else => {}, + } + } +} + /// Process an associated block: introduce all items, set up scope with aliases, and canonicalize /// When skip_first_pass is true, placeholders were already created by a recursive call to /// processAssociatedItemsFirstPass, so we skip directly to scope entry and body processing. @@ -759,42 +843,11 @@ fn processAssociatedBlock( try current_scope.introduceTypeAlias(self.env.gpa, user_qualified_ident_idx, qualified_type_decl_idx); } - // Introduce associated items of nested types into this scope + // Introduce associated items of nested types into this scope (recursively) // Now that nested blocks have been processed, these patterns exist and can be aliased. - // This allows qualified access like "Inner.inner_val" from the parent scope. + // This allows qualified access like "Inner.val" and "Inner.Deep.deepVal" from the parent scope. if (nested_type_decl.associated) |nested_assoc| { - for (self.parse_ir.store.statementSlice(nested_assoc.statements)) |nested_assoc_stmt_idx| { - const nested_assoc_stmt = self.parse_ir.store.getStatement(nested_assoc_stmt_idx); - if (nested_assoc_stmt == .decl) { - const nested_decl = nested_assoc_stmt.decl; - const nested_pattern = self.parse_ir.store.getPattern(nested_decl.pattern); - if (nested_pattern == .ident) { - const nested_pattern_ident_tok = nested_pattern.ident.ident_tok; - if (self.parse_ir.tokens.resolveIdentifier(nested_pattern_ident_tok)) |nested_decl_ident| { - // Build fully qualified name (e.g., "Builtin.Num.Numeral.is_negative") - const qualified_text = self.env.getIdent(qualified_ident_idx); - const nested_decl_text = self.env.getIdent(nested_decl_ident); - const full_qualified_ident_idx = try self.env.insertQualifiedIdent(qualified_text, nested_decl_text); - - // Look up the fully qualified pattern (from parent scope via nesting) - switch (self.scopeLookup(.ident, full_qualified_ident_idx)) { - .found => |pattern_idx| { - const scope = &self.scopes.items[self.scopes.items.len - 1]; - - // Add type-qualified name (e.g., "Inner.inner_val") so parent can - // access nested items via qualified syntax, but NOT unqualified. - // Unqualified access (e.g., just "inner_val") would violate scoping - // rules - nested items should only be accessible within their own - // scope or via qualified access from parent scopes. - const type_qualified_ident_idx = try self.env.insertQualifiedIdent(nested_type_text, nested_decl_text); - try scope.idents.put(self.env.gpa, type_qualified_ident_idx, pattern_idx); - }, - .not_found => {}, - } - } - } - } - } + try self.introduceNestedItemAliases(qualified_ident_idx, nested_type_text, nested_assoc.statements); } }, .decl => { @@ -1201,19 +1254,21 @@ fn processAssociatedItemsSecondPass( } } -/// Register progressively qualified names at each scope level. +/// Register the user-facing fully qualified name in the module scope. /// Given a fully qualified name like "module.Foo.Bar.baz", this registers: /// - "Foo.Bar.baz" in module scope (user-facing fully qualified) -/// - "Bar.baz" in Foo's scope (partially qualified) -/// - "baz" in Bar's scope (unqualified) /// -/// This ensures single-string lookups work correctly at any scope level. -fn registerProgressivelyQualifiedNames( +/// Note: Partially qualified names (e.g., "Bar.baz" for Foo's scope, "baz" for Bar's scope) +/// are NOT registered here. They are registered in processAssociatedBlock when the +/// actual scopes are entered, via the alias registration logic there. +fn registerUserFacingName( self: *Self, fully_qualified_idx: Ident.Idx, item_name_idx: Ident.Idx, pattern_idx: CIR.Pattern.Idx, ) std.mem.Allocator.Error!void { + _ = item_name_idx; + // Get the fully qualified text and strip the module prefix const fully_qualified_text = self.env.getIdent(fully_qualified_idx); const module_prefix = self.env.module_name; @@ -1236,82 +1291,10 @@ fn registerProgressivelyQualifiedNames( @memcpy(buf[0..user_facing_text.len], user_facing_text); const user_text = buf[0..user_facing_text.len]; - // Parse the user-facing text into components: ["Foo", "Bar", "baz"] - var components: [32][]const u8 = undefined; - var num_components: usize = 0; - var start: usize = 0; - for (user_text, 0..) |c, i| { - if (c == '.') { - if (num_components < components.len) { - components[num_components] = user_text[start..i]; - num_components += 1; - } - start = i + 1; - } - } - // Add the last component (the item name) - if (num_components < components.len and start < user_text.len) { - components[num_components] = user_text[start..]; - num_components += 1; - } - - if (num_components == 0) return; - - // Now register at each scope level. - // Walk through scopes from module (index 0) to current, matching with type components. - // For each scope with associated_type_name, we register the suffix starting from that type. - - // First, register the full user-facing name in module scope (index 0) - const full_user_facing_idx = try self.env.insertIdent(base.Ident.for_text(user_text)); - try self.scopes.items[0].idents.put(self.env.gpa, full_user_facing_idx, pattern_idx); - - // Now walk through scopes looking for associated type scopes - // Each associated type scope should get the suffix starting after that type - var scope_idx: usize = 1; - while (scope_idx < self.scopes.items.len) : (scope_idx += 1) { - const scope = &self.scopes.items[scope_idx]; - if (scope.associated_type_name) |type_name_ident| { - const type_name = self.env.getIdent(type_name_ident); - // Find this type name in our components - for (components[0..num_components], 0..) |comp, comp_idx| { - if (std.mem.eql(u8, comp, type_name)) { - // This scope corresponds to component comp_idx - // Register the suffix starting from comp_idx + 1 - if (comp_idx + 1 < num_components) { - // Build the suffix string - var suffix_buf: [512]u8 = undefined; - var suffix_len: usize = 0; - var first = true; - for (components[comp_idx + 1 .. num_components]) |suffix_comp| { - if (!first) { - suffix_buf[suffix_len] = '.'; - suffix_len += 1; - } - if (suffix_len + suffix_comp.len > suffix_buf.len) break; - @memcpy(suffix_buf[suffix_len..][0..suffix_comp.len], suffix_comp); - suffix_len += suffix_comp.len; - first = false; - } - if (suffix_len > 0) { - const suffix_idx = try self.env.insertIdent(base.Ident.for_text(suffix_buf[0..suffix_len])); - try scope.idents.put(self.env.gpa, suffix_idx, pattern_idx); - } - } else if (comp_idx + 1 == num_components) { - // Last component is the item name itself - register unqualified - try scope.idents.put(self.env.gpa, item_name_idx, pattern_idx); - } - break; - } - } - } - } - - // Also ensure the unqualified name is in the innermost associated type scope - // (the scope where this item is being defined) - const current_scope = &self.scopes.items[self.scopes.items.len - 1]; - if (current_scope.associated_type_name != null) { - try current_scope.idents.put(self.env.gpa, item_name_idx, pattern_idx); - } + // Register ONLY the fully qualified user-facing name in the module scope. + // For "Foo.Bar.baz", we register just "Foo.Bar.baz" - not the shorter suffixes. + const user_facing_idx = try self.env.insertIdent(base.Ident.for_text(user_text)); + try self.scopes.items[0].idents.put(self.env.gpa, user_facing_idx, pattern_idx); } /// Register an identifier hierarchically into all active scopes using scope hierarchy information. @@ -1613,7 +1596,7 @@ fn processAssociatedItemsFirstPass( // - Module scope gets "Foo.Bar.baz" (user-facing fully qualified) // - Foo's scope gets "Bar.baz" (partially qualified) // - Bar's scope gets "baz" (unqualified) - try self.registerProgressivelyQualifiedNames(qualified_idx, decl_ident, placeholder_pattern_idx); + try self.registerUserFacingName(qualified_idx, decl_ident, placeholder_pattern_idx); } } }, @@ -1641,7 +1624,7 @@ fn processAssociatedItemsFirstPass( try current_scope.idents.put(self.env.gpa, qualified_idx, placeholder_pattern_idx); // Register progressively qualified names at each scope level per the plan - try self.registerProgressivelyQualifiedNames(qualified_idx, anno_ident, placeholder_pattern_idx); + try self.registerUserFacingName(qualified_idx, anno_ident, placeholder_pattern_idx); } }, else => { diff --git a/test/snapshots/nominal/progressive_qualification.md b/test/snapshots/nominal/progressive_qualification.md new file mode 100644 index 0000000000..1e8772401b --- /dev/null +++ b/test/snapshots/nominal/progressive_qualification.md @@ -0,0 +1,1046 @@ +# META +~~~ini +description=Test progressive qualification of nested associated items per can_plan.md +type=snippet +~~~ +# SOURCE +~~~roc +# ============================================================================ +# Test progressive qualification per can_plan.md +# +# The plan states: +# - Module scope gets "Foo.Bar.baz" (user-facing fully qualified) +# - Foo's scope gets "Bar.baz" (partially qualified) +# - Bar's scope gets "baz" (unqualified) +# ============================================================================ + +# -------------------------------------------------------------------------- +# Test 1: Two-level nesting - access from each scope level +# -------------------------------------------------------------------------- + +Outer := [O].{ + Inner := [I].{ + value = 42 + + # From Inner's scope: unqualified access + fromInner = value + } + + # From Outer's scope: partially qualified access (Inner.value) + fromOuter = Inner.value +} + +# From module scope: fully qualified access (Outer.Inner.value) +fromModule = Outer.Inner.value + +# Verify all access patterns work +test1_inner = Outer.Inner.fromInner # Should be 42 +test1_outer = Outer.fromOuter # Should be 42 +test1_module = fromModule # Should be 42 + +# -------------------------------------------------------------------------- +# Test 2: Three-level nesting - access from each scope level +# -------------------------------------------------------------------------- + +Level1 := [L1].{ + Level2 := [L2].{ + Level3 := [L3].{ + deepValue = 100 + + # From Level3's scope: unqualified + accessFromL3 = deepValue + } + + # From Level2's scope: partial qualification (Level3.deepValue) + accessFromL2 = Level3.deepValue + } + + # From Level1's scope: more qualification (Level2.Level3.deepValue) + accessFromL1 = Level2.Level3.deepValue +} + +# From module scope: full qualification (Level1.Level2.Level3.deepValue) +accessFromModule = Level1.Level2.Level3.deepValue + +# Verify +test2_l3 = Level1.Level2.Level3.accessFromL3 # 100 +test2_l2 = Level1.Level2.accessFromL2 # 100 +test2_l1 = Level1.accessFromL1 # 100 +test2_mod = accessFromModule # 100 + +# -------------------------------------------------------------------------- +# Test 3: Cross-references between siblings at different nesting levels +# -------------------------------------------------------------------------- + +Parent := [P].{ + sharedVal = 999 + + Child1 := [C1].{ + c1Val = 10 + # Access parent's value with partial qualification + useParent = Parent.sharedVal + } + + Child2 := [C2].{ + c2Val = 20 + # Access sibling's value - need to go through parent scope + useSibling = Child1.c1Val + useParent = Parent.sharedVal + } + + # Parent can access both children with partial qualification + sumChildren = Child1.c1Val + Child2.c2Val +} + +test3_c1 = Parent.Child1.useParent # 999 +test3_c2_sib = Parent.Child2.useSibling # 10 +test3_c2_par = Parent.Child2.useParent # 999 +test3_sum = Parent.sumChildren # 30 + +# -------------------------------------------------------------------------- +# Test 4: Name reuse in non-overlapping scopes (no shadowing) +# -------------------------------------------------------------------------- + +TypeA := [TA].{ + helper = 111 + useHelper = helper +} + +TypeB := [TB].{ + helper = 222 + useHelper = helper +} + +# Each type has its own "helper" - no conflict +test4_a = TypeA.useHelper # 111 +test4_b = TypeB.useHelper # 222 +test4_a_direct = TypeA.helper # 111 +test4_b_direct = TypeB.helper # 222 + +# -------------------------------------------------------------------------- +# Test 5: Same nested type names in different parents +# -------------------------------------------------------------------------- + +Parent1 := [P1].{ + Nested := [N1].{ + val = 1 + } +} + +Parent2 := [P2].{ + Nested := [N2].{ + val = 2 + } +} + +# Both Parent1.Nested and Parent2.Nested exist independently +test5_p1 = Parent1.Nested.val # 1 +test5_p2 = Parent2.Nested.val # 2 + +# -------------------------------------------------------------------------- +# Test 6: Inner accessing outer's values (scope chain lookup) +# -------------------------------------------------------------------------- + +Container := [CONT].{ + outerA = 10 + outerB = 20 + + Nested := [NEST].{ + innerVal = 5 + + # Access outer values - these should be visible via scope chain + useOuterA = outerA + useOuterB = outerB + combined = innerVal + outerA + outerB + } +} + +test6_a = Container.Nested.useOuterA # 10 +test6_b = Container.Nested.useOuterB # 20 +test6_combined = Container.Nested.combined # 35 +~~~ +# EXPECTED +NIL +# PROBLEMS +NIL +# TOKENS +~~~zig +UpperIdent,OpColonEqual,OpenSquare,UpperIdent,CloseSquare,Dot,OpenCurly, +UpperIdent,OpColonEqual,OpenSquare,UpperIdent,CloseSquare,Dot,OpenCurly, +LowerIdent,OpAssign,Int, +LowerIdent,OpAssign,LowerIdent, +CloseCurly, +LowerIdent,OpAssign,UpperIdent,NoSpaceDotLowerIdent, +CloseCurly, +LowerIdent,OpAssign,UpperIdent,NoSpaceDotUpperIdent,NoSpaceDotLowerIdent, +LowerIdent,OpAssign,UpperIdent,NoSpaceDotUpperIdent,NoSpaceDotLowerIdent, +LowerIdent,OpAssign,UpperIdent,NoSpaceDotLowerIdent, +LowerIdent,OpAssign,LowerIdent, +UpperIdent,OpColonEqual,OpenSquare,UpperIdent,CloseSquare,Dot,OpenCurly, +UpperIdent,OpColonEqual,OpenSquare,UpperIdent,CloseSquare,Dot,OpenCurly, +UpperIdent,OpColonEqual,OpenSquare,UpperIdent,CloseSquare,Dot,OpenCurly, +LowerIdent,OpAssign,Int, +LowerIdent,OpAssign,LowerIdent, +CloseCurly, +LowerIdent,OpAssign,UpperIdent,NoSpaceDotLowerIdent, +CloseCurly, +LowerIdent,OpAssign,UpperIdent,NoSpaceDotUpperIdent,NoSpaceDotLowerIdent, +CloseCurly, +LowerIdent,OpAssign,UpperIdent,NoSpaceDotUpperIdent,NoSpaceDotUpperIdent,NoSpaceDotLowerIdent, +LowerIdent,OpAssign,UpperIdent,NoSpaceDotUpperIdent,NoSpaceDotUpperIdent,NoSpaceDotLowerIdent, +LowerIdent,OpAssign,UpperIdent,NoSpaceDotUpperIdent,NoSpaceDotLowerIdent, +LowerIdent,OpAssign,UpperIdent,NoSpaceDotLowerIdent, +LowerIdent,OpAssign,LowerIdent, +UpperIdent,OpColonEqual,OpenSquare,UpperIdent,CloseSquare,Dot,OpenCurly, +LowerIdent,OpAssign,Int, +UpperIdent,OpColonEqual,OpenSquare,UpperIdent,CloseSquare,Dot,OpenCurly, +LowerIdent,OpAssign,Int, +LowerIdent,OpAssign,UpperIdent,NoSpaceDotLowerIdent, +CloseCurly, +UpperIdent,OpColonEqual,OpenSquare,UpperIdent,CloseSquare,Dot,OpenCurly, +LowerIdent,OpAssign,Int, +LowerIdent,OpAssign,UpperIdent,NoSpaceDotLowerIdent, +LowerIdent,OpAssign,UpperIdent,NoSpaceDotLowerIdent, +CloseCurly, +LowerIdent,OpAssign,UpperIdent,NoSpaceDotLowerIdent,OpPlus,UpperIdent,NoSpaceDotLowerIdent, +CloseCurly, +LowerIdent,OpAssign,UpperIdent,NoSpaceDotUpperIdent,NoSpaceDotLowerIdent, +LowerIdent,OpAssign,UpperIdent,NoSpaceDotUpperIdent,NoSpaceDotLowerIdent, +LowerIdent,OpAssign,UpperIdent,NoSpaceDotUpperIdent,NoSpaceDotLowerIdent, +LowerIdent,OpAssign,UpperIdent,NoSpaceDotLowerIdent, +UpperIdent,OpColonEqual,OpenSquare,UpperIdent,CloseSquare,Dot,OpenCurly, +LowerIdent,OpAssign,Int, +LowerIdent,OpAssign,LowerIdent, +CloseCurly, +UpperIdent,OpColonEqual,OpenSquare,UpperIdent,CloseSquare,Dot,OpenCurly, +LowerIdent,OpAssign,Int, +LowerIdent,OpAssign,LowerIdent, +CloseCurly, +LowerIdent,OpAssign,UpperIdent,NoSpaceDotLowerIdent, +LowerIdent,OpAssign,UpperIdent,NoSpaceDotLowerIdent, +LowerIdent,OpAssign,UpperIdent,NoSpaceDotLowerIdent, +LowerIdent,OpAssign,UpperIdent,NoSpaceDotLowerIdent, +UpperIdent,OpColonEqual,OpenSquare,UpperIdent,CloseSquare,Dot,OpenCurly, +UpperIdent,OpColonEqual,OpenSquare,UpperIdent,CloseSquare,Dot,OpenCurly, +LowerIdent,OpAssign,Int, +CloseCurly, +CloseCurly, +UpperIdent,OpColonEqual,OpenSquare,UpperIdent,CloseSquare,Dot,OpenCurly, +UpperIdent,OpColonEqual,OpenSquare,UpperIdent,CloseSquare,Dot,OpenCurly, +LowerIdent,OpAssign,Int, +CloseCurly, +CloseCurly, +LowerIdent,OpAssign,UpperIdent,NoSpaceDotUpperIdent,NoSpaceDotLowerIdent, +LowerIdent,OpAssign,UpperIdent,NoSpaceDotUpperIdent,NoSpaceDotLowerIdent, +UpperIdent,OpColonEqual,OpenSquare,UpperIdent,CloseSquare,Dot,OpenCurly, +LowerIdent,OpAssign,Int, +LowerIdent,OpAssign,Int, +UpperIdent,OpColonEqual,OpenSquare,UpperIdent,CloseSquare,Dot,OpenCurly, +LowerIdent,OpAssign,Int, +LowerIdent,OpAssign,LowerIdent, +LowerIdent,OpAssign,LowerIdent, +LowerIdent,OpAssign,LowerIdent,OpPlus,LowerIdent,OpPlus,LowerIdent, +CloseCurly, +CloseCurly, +LowerIdent,OpAssign,UpperIdent,NoSpaceDotUpperIdent,NoSpaceDotLowerIdent, +LowerIdent,OpAssign,UpperIdent,NoSpaceDotUpperIdent,NoSpaceDotLowerIdent, +LowerIdent,OpAssign,UpperIdent,NoSpaceDotUpperIdent,NoSpaceDotLowerIdent, +EndOfFile, +~~~ +# PARSE +~~~clojure +(file + (type-module) + (statements + (s-type-decl + (header (name "Outer") + (args)) + (ty-tag-union + (tags + (ty (name "O")))) + (associated + (s-type-decl + (header (name "Inner") + (args)) + (ty-tag-union + (tags + (ty (name "I")))) + (associated + (s-decl + (p-ident (raw "value")) + (e-int (raw "42"))) + (s-decl + (p-ident (raw "fromInner")) + (e-ident (raw "value"))))) + (s-decl + (p-ident (raw "fromOuter")) + (e-ident (raw "Inner.value"))))) + (s-decl + (p-ident (raw "fromModule")) + (e-ident (raw "Outer.Inner.value"))) + (s-decl + (p-ident (raw "test1_inner")) + (e-ident (raw "Outer.Inner.fromInner"))) + (s-decl + (p-ident (raw "test1_outer")) + (e-ident (raw "Outer.fromOuter"))) + (s-decl + (p-ident (raw "test1_module")) + (e-ident (raw "fromModule"))) + (s-type-decl + (header (name "Level1") + (args)) + (ty-tag-union + (tags + (ty (name "L1")))) + (associated + (s-type-decl + (header (name "Level2") + (args)) + (ty-tag-union + (tags + (ty (name "L2")))) + (associated + (s-type-decl + (header (name "Level3") + (args)) + (ty-tag-union + (tags + (ty (name "L3")))) + (associated + (s-decl + (p-ident (raw "deepValue")) + (e-int (raw "100"))) + (s-decl + (p-ident (raw "accessFromL3")) + (e-ident (raw "deepValue"))))) + (s-decl + (p-ident (raw "accessFromL2")) + (e-ident (raw "Level3.deepValue"))))) + (s-decl + (p-ident (raw "accessFromL1")) + (e-ident (raw "Level2.Level3.deepValue"))))) + (s-decl + (p-ident (raw "accessFromModule")) + (e-ident (raw "Level1.Level2.Level3.deepValue"))) + (s-decl + (p-ident (raw "test2_l3")) + (e-ident (raw "Level1.Level2.Level3.accessFromL3"))) + (s-decl + (p-ident (raw "test2_l2")) + (e-ident (raw "Level1.Level2.accessFromL2"))) + (s-decl + (p-ident (raw "test2_l1")) + (e-ident (raw "Level1.accessFromL1"))) + (s-decl + (p-ident (raw "test2_mod")) + (e-ident (raw "accessFromModule"))) + (s-type-decl + (header (name "Parent") + (args)) + (ty-tag-union + (tags + (ty (name "P")))) + (associated + (s-decl + (p-ident (raw "sharedVal")) + (e-int (raw "999"))) + (s-type-decl + (header (name "Child1") + (args)) + (ty-tag-union + (tags + (ty (name "C1")))) + (associated + (s-decl + (p-ident (raw "c1Val")) + (e-int (raw "10"))) + (s-decl + (p-ident (raw "useParent")) + (e-ident (raw "Parent.sharedVal"))))) + (s-type-decl + (header (name "Child2") + (args)) + (ty-tag-union + (tags + (ty (name "C2")))) + (associated + (s-decl + (p-ident (raw "c2Val")) + (e-int (raw "20"))) + (s-decl + (p-ident (raw "useSibling")) + (e-ident (raw "Child1.c1Val"))) + (s-decl + (p-ident (raw "useParent")) + (e-ident (raw "Parent.sharedVal"))))) + (s-decl + (p-ident (raw "sumChildren")) + (e-binop (op "+") + (e-ident (raw "Child1.c1Val")) + (e-ident (raw "Child2.c2Val")))))) + (s-decl + (p-ident (raw "test3_c1")) + (e-ident (raw "Parent.Child1.useParent"))) + (s-decl + (p-ident (raw "test3_c2_sib")) + (e-ident (raw "Parent.Child2.useSibling"))) + (s-decl + (p-ident (raw "test3_c2_par")) + (e-ident (raw "Parent.Child2.useParent"))) + (s-decl + (p-ident (raw "test3_sum")) + (e-ident (raw "Parent.sumChildren"))) + (s-type-decl + (header (name "TypeA") + (args)) + (ty-tag-union + (tags + (ty (name "TA")))) + (associated + (s-decl + (p-ident (raw "helper")) + (e-int (raw "111"))) + (s-decl + (p-ident (raw "useHelper")) + (e-ident (raw "helper"))))) + (s-type-decl + (header (name "TypeB") + (args)) + (ty-tag-union + (tags + (ty (name "TB")))) + (associated + (s-decl + (p-ident (raw "helper")) + (e-int (raw "222"))) + (s-decl + (p-ident (raw "useHelper")) + (e-ident (raw "helper"))))) + (s-decl + (p-ident (raw "test4_a")) + (e-ident (raw "TypeA.useHelper"))) + (s-decl + (p-ident (raw "test4_b")) + (e-ident (raw "TypeB.useHelper"))) + (s-decl + (p-ident (raw "test4_a_direct")) + (e-ident (raw "TypeA.helper"))) + (s-decl + (p-ident (raw "test4_b_direct")) + (e-ident (raw "TypeB.helper"))) + (s-type-decl + (header (name "Parent1") + (args)) + (ty-tag-union + (tags + (ty (name "P1")))) + (associated + (s-type-decl + (header (name "Nested") + (args)) + (ty-tag-union + (tags + (ty (name "N1")))) + (associated + (s-decl + (p-ident (raw "val")) + (e-int (raw "1"))))))) + (s-type-decl + (header (name "Parent2") + (args)) + (ty-tag-union + (tags + (ty (name "P2")))) + (associated + (s-type-decl + (header (name "Nested") + (args)) + (ty-tag-union + (tags + (ty (name "N2")))) + (associated + (s-decl + (p-ident (raw "val")) + (e-int (raw "2"))))))) + (s-decl + (p-ident (raw "test5_p1")) + (e-ident (raw "Parent1.Nested.val"))) + (s-decl + (p-ident (raw "test5_p2")) + (e-ident (raw "Parent2.Nested.val"))) + (s-type-decl + (header (name "Container") + (args)) + (ty-tag-union + (tags + (ty (name "CONT")))) + (associated + (s-decl + (p-ident (raw "outerA")) + (e-int (raw "10"))) + (s-decl + (p-ident (raw "outerB")) + (e-int (raw "20"))) + (s-type-decl + (header (name "Nested") + (args)) + (ty-tag-union + (tags + (ty (name "NEST")))) + (associated + (s-decl + (p-ident (raw "innerVal")) + (e-int (raw "5"))) + (s-decl + (p-ident (raw "useOuterA")) + (e-ident (raw "outerA"))) + (s-decl + (p-ident (raw "useOuterB")) + (e-ident (raw "outerB"))) + (s-decl + (p-ident (raw "combined")) + (e-binop (op "+") + (e-binop (op "+") + (e-ident (raw "innerVal")) + (e-ident (raw "outerA"))) + (e-ident (raw "outerB")))))))) + (s-decl + (p-ident (raw "test6_a")) + (e-ident (raw "Container.Nested.useOuterA"))) + (s-decl + (p-ident (raw "test6_b")) + (e-ident (raw "Container.Nested.useOuterB"))) + (s-decl + (p-ident (raw "test6_combined")) + (e-ident (raw "Container.Nested.combined"))))) +~~~ +# FORMATTED +~~~roc +# ============================================================================ +# Test progressive qualification per can_plan.md +# +# The plan states: +# - Module scope gets "Foo.Bar.baz" (user-facing fully qualified) +# - Foo's scope gets "Bar.baz" (partially qualified) +# - Bar's scope gets "baz" (unqualified) +# ============================================================================ + +# -------------------------------------------------------------------------- +# Test 1: Two-level nesting - access from each scope level +# -------------------------------------------------------------------------- + +Outer := [O].{ + Inner := [I].{ + value = 42 + fromInner = value + } + fromOuter = Inner.value +} + +# From module scope: fully qualified access (Outer.Inner.value) +fromModule = Outer.Inner.value + +# Verify all access patterns work +test1_inner = Outer.Inner.fromInner # Should be 42 +test1_outer = Outer.fromOuter # Should be 42 +test1_module = fromModule # Should be 42 + +# -------------------------------------------------------------------------- +# Test 2: Three-level nesting - access from each scope level +# -------------------------------------------------------------------------- + +Level1 := [L1].{ + Level2 := [L2].{ + Level3 := [L3].{ + deepValue = 100 + accessFromL3 = deepValue + } + accessFromL2 = Level3.deepValue + } + accessFromL1 = Level2.Level3.deepValue +} + +# From module scope: full qualification (Level1.Level2.Level3.deepValue) +accessFromModule = Level1.Level2.Level3.deepValue + +# Verify +test2_l3 = Level1.Level2.Level3.accessFromL3 # 100 +test2_l2 = Level1.Level2.accessFromL2 # 100 +test2_l1 = Level1.accessFromL1 # 100 +test2_mod = accessFromModule # 100 + +# -------------------------------------------------------------------------- +# Test 3: Cross-references between siblings at different nesting levels +# -------------------------------------------------------------------------- + +Parent := [P].{ + sharedVal = 999 + Child1 := [C1].{ + c1Val = 10 + useParent = Parent.sharedVal + } + Child2 := [C2].{ + c2Val = 20 + useSibling = Child1.c1Val + useParent = Parent.sharedVal + } + sumChildren = Child1.c1Val + Child2.c2Val +} + +test3_c1 = Parent.Child1.useParent # 999 +test3_c2_sib = Parent.Child2.useSibling # 10 +test3_c2_par = Parent.Child2.useParent # 999 +test3_sum = Parent.sumChildren # 30 + +# -------------------------------------------------------------------------- +# Test 4: Name reuse in non-overlapping scopes (no shadowing) +# -------------------------------------------------------------------------- + +TypeA := [TA].{ + helper = 111 + useHelper = helper +} + +TypeB := [TB].{ + helper = 222 + useHelper = helper +} + +# Each type has its own "helper" - no conflict +test4_a = TypeA.useHelper # 111 +test4_b = TypeB.useHelper # 222 +test4_a_direct = TypeA.helper # 111 +test4_b_direct = TypeB.helper # 222 + +# -------------------------------------------------------------------------- +# Test 5: Same nested type names in different parents +# -------------------------------------------------------------------------- + +Parent1 := [P1].{ + Nested := [N1].{ + val = 1 + } +} + +Parent2 := [P2].{ + Nested := [N2].{ + val = 2 + } +} + +# Both Parent1.Nested and Parent2.Nested exist independently +test5_p1 = Parent1.Nested.val # 1 +test5_p2 = Parent2.Nested.val # 2 + +# -------------------------------------------------------------------------- +# Test 6: Inner accessing outer's values (scope chain lookup) +# -------------------------------------------------------------------------- + +Container := [CONT].{ + outerA = 10 + outerB = 20 + Nested := [NEST].{ + innerVal = 5 + useOuterA = outerA + useOuterB = outerB + combined = innerVal + outerA + outerB + } +} + +test6_a = Container.Nested.useOuterA # 10 +test6_b = Container.Nested.useOuterB # 20 +test6_combined = Container.Nested.combined # 35 +~~~ +# CANONICALIZE +~~~clojure +(can-ir + (d-let + (p-assign (ident "progressive_qualification.Outer.Inner.value")) + (e-num (value "42"))) + (d-let + (p-assign (ident "progressive_qualification.Outer.Inner.fromInner")) + (e-lookup-local + (p-assign (ident "progressive_qualification.Outer.Inner.value")))) + (d-let + (p-assign (ident "progressive_qualification.Outer.fromOuter")) + (e-lookup-local + (p-assign (ident "progressive_qualification.Outer.Inner.value")))) + (d-let + (p-assign (ident "progressive_qualification.Level1.Level2.Level3.deepValue")) + (e-num (value "100"))) + (d-let + (p-assign (ident "progressive_qualification.Level1.Level2.Level3.accessFromL3")) + (e-lookup-local + (p-assign (ident "progressive_qualification.Level1.Level2.Level3.deepValue")))) + (d-let + (p-assign (ident "progressive_qualification.Level1.Level2.accessFromL2")) + (e-lookup-local + (p-assign (ident "progressive_qualification.Level1.Level2.Level3.deepValue")))) + (d-let + (p-assign (ident "progressive_qualification.Level1.accessFromL1")) + (e-lookup-local + (p-assign (ident "progressive_qualification.Level1.Level2.Level3.deepValue")))) + (d-let + (p-assign (ident "progressive_qualification.Parent.Child1.c1Val")) + (e-num (value "10"))) + (d-let + (p-assign (ident "progressive_qualification.Parent.Child1.useParent")) + (e-lookup-local + (p-assign (ident "progressive_qualification.Parent.sharedVal")))) + (d-let + (p-assign (ident "progressive_qualification.Parent.Child2.c2Val")) + (e-num (value "20"))) + (d-let + (p-assign (ident "progressive_qualification.Parent.Child2.useSibling")) + (e-lookup-local + (p-assign (ident "progressive_qualification.Parent.Child1.c1Val")))) + (d-let + (p-assign (ident "progressive_qualification.Parent.Child2.useParent")) + (e-lookup-local + (p-assign (ident "progressive_qualification.Parent.sharedVal")))) + (d-let + (p-assign (ident "progressive_qualification.Parent.sharedVal")) + (e-num (value "999"))) + (d-let + (p-assign (ident "progressive_qualification.Parent.sumChildren")) + (e-binop (op "add") + (e-lookup-local + (p-assign (ident "progressive_qualification.Parent.Child1.c1Val"))) + (e-lookup-local + (p-assign (ident "progressive_qualification.Parent.Child2.c2Val"))))) + (d-let + (p-assign (ident "progressive_qualification.TypeA.helper")) + (e-num (value "111"))) + (d-let + (p-assign (ident "progressive_qualification.TypeA.useHelper")) + (e-lookup-local + (p-assign (ident "progressive_qualification.TypeA.helper")))) + (d-let + (p-assign (ident "progressive_qualification.TypeB.helper")) + (e-num (value "222"))) + (d-let + (p-assign (ident "progressive_qualification.TypeB.useHelper")) + (e-lookup-local + (p-assign (ident "progressive_qualification.TypeB.helper")))) + (d-let + (p-assign (ident "progressive_qualification.Parent1.Nested.val")) + (e-num (value "1"))) + (d-let + (p-assign (ident "progressive_qualification.Parent2.Nested.val")) + (e-num (value "2"))) + (d-let + (p-assign (ident "progressive_qualification.Container.Nested.innerVal")) + (e-num (value "5"))) + (d-let + (p-assign (ident "progressive_qualification.Container.Nested.useOuterA")) + (e-lookup-local + (p-assign (ident "progressive_qualification.Container.outerA")))) + (d-let + (p-assign (ident "progressive_qualification.Container.Nested.useOuterB")) + (e-lookup-local + (p-assign (ident "progressive_qualification.Container.outerB")))) + (d-let + (p-assign (ident "progressive_qualification.Container.Nested.combined")) + (e-binop (op "add") + (e-binop (op "add") + (e-lookup-local + (p-assign (ident "progressive_qualification.Container.Nested.innerVal"))) + (e-lookup-local + (p-assign (ident "progressive_qualification.Container.outerA")))) + (e-lookup-local + (p-assign (ident "progressive_qualification.Container.outerB"))))) + (d-let + (p-assign (ident "progressive_qualification.Container.outerA")) + (e-num (value "10"))) + (d-let + (p-assign (ident "progressive_qualification.Container.outerB")) + (e-num (value "20"))) + (d-let + (p-assign (ident "fromModule")) + (e-lookup-local + (p-assign (ident "progressive_qualification.Outer.Inner.value")))) + (d-let + (p-assign (ident "test1_inner")) + (e-lookup-local + (p-assign (ident "progressive_qualification.Outer.Inner.fromInner")))) + (d-let + (p-assign (ident "test1_outer")) + (e-lookup-local + (p-assign (ident "progressive_qualification.Outer.fromOuter")))) + (d-let + (p-assign (ident "test1_module")) + (e-lookup-local + (p-assign (ident "fromModule")))) + (d-let + (p-assign (ident "accessFromModule")) + (e-lookup-local + (p-assign (ident "progressive_qualification.Level1.Level2.Level3.deepValue")))) + (d-let + (p-assign (ident "test2_l3")) + (e-lookup-local + (p-assign (ident "progressive_qualification.Level1.Level2.Level3.accessFromL3")))) + (d-let + (p-assign (ident "test2_l2")) + (e-lookup-local + (p-assign (ident "progressive_qualification.Level1.Level2.accessFromL2")))) + (d-let + (p-assign (ident "test2_l1")) + (e-lookup-local + (p-assign (ident "progressive_qualification.Level1.accessFromL1")))) + (d-let + (p-assign (ident "test2_mod")) + (e-lookup-local + (p-assign (ident "accessFromModule")))) + (d-let + (p-assign (ident "test3_c1")) + (e-lookup-local + (p-assign (ident "progressive_qualification.Parent.Child1.useParent")))) + (d-let + (p-assign (ident "test3_c2_sib")) + (e-lookup-local + (p-assign (ident "progressive_qualification.Parent.Child2.useSibling")))) + (d-let + (p-assign (ident "test3_c2_par")) + (e-lookup-local + (p-assign (ident "progressive_qualification.Parent.Child2.useParent")))) + (d-let + (p-assign (ident "test3_sum")) + (e-lookup-local + (p-assign (ident "progressive_qualification.Parent.sumChildren")))) + (d-let + (p-assign (ident "test4_a")) + (e-lookup-local + (p-assign (ident "progressive_qualification.TypeA.useHelper")))) + (d-let + (p-assign (ident "test4_b")) + (e-lookup-local + (p-assign (ident "progressive_qualification.TypeB.useHelper")))) + (d-let + (p-assign (ident "test4_a_direct")) + (e-lookup-local + (p-assign (ident "progressive_qualification.TypeA.helper")))) + (d-let + (p-assign (ident "test4_b_direct")) + (e-lookup-local + (p-assign (ident "progressive_qualification.TypeB.helper")))) + (d-let + (p-assign (ident "test5_p1")) + (e-lookup-local + (p-assign (ident "progressive_qualification.Parent1.Nested.val")))) + (d-let + (p-assign (ident "test5_p2")) + (e-lookup-local + (p-assign (ident "progressive_qualification.Parent2.Nested.val")))) + (d-let + (p-assign (ident "test6_a")) + (e-lookup-local + (p-assign (ident "progressive_qualification.Container.Nested.useOuterA")))) + (d-let + (p-assign (ident "test6_b")) + (e-lookup-local + (p-assign (ident "progressive_qualification.Container.Nested.useOuterB")))) + (d-let + (p-assign (ident "test6_combined")) + (e-lookup-local + (p-assign (ident "progressive_qualification.Container.Nested.combined")))) + (s-nominal-decl + (ty-header (name "Outer")) + (ty-tag-union + (ty-tag-name (name "O")))) + (s-nominal-decl + (ty-header (name "Level1")) + (ty-tag-union + (ty-tag-name (name "L1")))) + (s-nominal-decl + (ty-header (name "Parent")) + (ty-tag-union + (ty-tag-name (name "P")))) + (s-nominal-decl + (ty-header (name "TypeA")) + (ty-tag-union + (ty-tag-name (name "TA")))) + (s-nominal-decl + (ty-header (name "TypeB")) + (ty-tag-union + (ty-tag-name (name "TB")))) + (s-nominal-decl + (ty-header (name "Parent1")) + (ty-tag-union + (ty-tag-name (name "P1")))) + (s-nominal-decl + (ty-header (name "Parent2")) + (ty-tag-union + (ty-tag-name (name "P2")))) + (s-nominal-decl + (ty-header (name "Container")) + (ty-tag-union + (ty-tag-name (name "CONT")))) + (s-nominal-decl + (ty-header (name "progressive_qualification.Outer.Inner")) + (ty-tag-union + (ty-tag-name (name "I")))) + (s-nominal-decl + (ty-header (name "progressive_qualification.Level1.Level2")) + (ty-tag-union + (ty-tag-name (name "L2")))) + (s-nominal-decl + (ty-header (name "progressive_qualification.Level1.Level2.Level3")) + (ty-tag-union + (ty-tag-name (name "L3")))) + (s-nominal-decl + (ty-header (name "progressive_qualification.Parent.Child1")) + (ty-tag-union + (ty-tag-name (name "C1")))) + (s-nominal-decl + (ty-header (name "progressive_qualification.Parent.Child2")) + (ty-tag-union + (ty-tag-name (name "C2")))) + (s-nominal-decl + (ty-header (name "progressive_qualification.Parent1.Nested")) + (ty-tag-union + (ty-tag-name (name "N1")))) + (s-nominal-decl + (ty-header (name "progressive_qualification.Parent2.Nested")) + (ty-tag-union + (ty-tag-name (name "N2")))) + (s-nominal-decl + (ty-header (name "progressive_qualification.Container.Nested")) + (ty-tag-union + (ty-tag-name (name "NEST"))))) +~~~ +# TYPES +~~~clojure +(inferred-types + (defs + (patt (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (patt (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (patt (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (patt (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (patt (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (patt (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (patt (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (patt (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (patt (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (patt (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (patt (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (patt (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (patt (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (patt (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (patt (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (patt (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (patt (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (patt (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (patt (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (patt (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (patt (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (patt (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (patt (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (patt (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (patt (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (patt (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (patt (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (patt (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (patt (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (patt (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (patt (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (patt (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (patt (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (patt (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (patt (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (patt (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (patt (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (patt (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (patt (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (patt (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (patt (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (patt (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (patt (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (patt (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (patt (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (patt (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (patt (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (patt (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]"))) + (type_decls + (nominal (type "Outer") + (ty-header (name "Outer"))) + (nominal (type "Level1") + (ty-header (name "Level1"))) + (nominal (type "Parent") + (ty-header (name "Parent"))) + (nominal (type "TypeA") + (ty-header (name "TypeA"))) + (nominal (type "TypeB") + (ty-header (name "TypeB"))) + (nominal (type "Parent1") + (ty-header (name "Parent1"))) + (nominal (type "Parent2") + (ty-header (name "Parent2"))) + (nominal (type "Container") + (ty-header (name "Container"))) + (nominal (type "progressive_qualification.Outer.Inner") + (ty-header (name "progressive_qualification.Outer.Inner"))) + (nominal (type "progressive_qualification.Level1.Level2") + (ty-header (name "progressive_qualification.Level1.Level2"))) + (nominal (type "progressive_qualification.Level1.Level2.Level3") + (ty-header (name "progressive_qualification.Level1.Level2.Level3"))) + (nominal (type "progressive_qualification.Parent.Child1") + (ty-header (name "progressive_qualification.Parent.Child1"))) + (nominal (type "progressive_qualification.Parent.Child2") + (ty-header (name "progressive_qualification.Parent.Child2"))) + (nominal (type "progressive_qualification.Parent1.Nested") + (ty-header (name "progressive_qualification.Parent1.Nested"))) + (nominal (type "progressive_qualification.Parent2.Nested") + (ty-header (name "progressive_qualification.Parent2.Nested"))) + (nominal (type "progressive_qualification.Container.Nested") + (ty-header (name "progressive_qualification.Container.Nested")))) + (expressions + (expr (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (expr (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (expr (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (expr (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (expr (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (expr (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (expr (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (expr (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (expr (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (expr (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (expr (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (expr (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (expr (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (expr (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (expr (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (expr (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (expr (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (expr (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (expr (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (expr (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (expr (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (expr (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (expr (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (expr (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (expr (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (expr (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (expr (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (expr (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (expr (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (expr (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (expr (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (expr (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (expr (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (expr (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (expr (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (expr (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (expr (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (expr (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (expr (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (expr (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (expr (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (expr (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (expr (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (expr (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (expr (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (expr (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (expr (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")) + (expr (type "a where [a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)])]")))) +~~~