@@ -2573,47 +2573,246 @@ E_TYPE_EXPAND_RANGE_FUNCTION_DEF(array)
25732573////////////////////////////////
25742574//~ rjf: (Built-In Type Hooks) `list` lens
25752575
2576- typedef struct E_ListGatherArtifact E_ListGatherArtifact ;
2577- struct E_ListGatherArtifact
2578- {
2579- U64 * node_vaddrs ;
2580- U64 node_vaddrs_count ;
2581- };
2582-
25832576internal AC_Artifact
25842577e_list_gather_artifact_create (String8 key , B32 * cancel_signal , B32 * retry_out , U64 * gen_out )
25852578{
2579+ Temp scratch = scratch_begin (0 , 0 );
25862580
2581+ //- rjf: unpack key
2582+ E_Space space = {0 };
2583+ U64 base_off = 0 ;
2584+ U64 member_element_off = 0 ;
2585+ U64 member_size = 0 ;
2586+ E_SpaceRWFunction * space_read = 0 ;
2587+ {
2588+ U64 key_read_off = 0 ;
2589+ key_read_off += str8_deserial_read_struct (key , key_read_off , & space );
2590+ key_read_off += str8_deserial_read_struct (key , key_read_off , & base_off );
2591+ key_read_off += str8_deserial_read_struct (key , key_read_off , & member_element_off );
2592+ key_read_off += str8_deserial_read_struct (key , key_read_off , & member_size );
2593+ key_read_off += str8_deserial_read_struct (key , key_read_off , & space_read );
2594+ }
2595+
2596+ //- rjf: gather chain
2597+ typedef struct HitOffsetNode HitOffsetNode ;
2598+ struct HitOffsetNode
2599+ {
2600+ HitOffsetNode * next ;
2601+ U64 off ;
2602+ };
2603+ typedef struct OffsetChunk OffsetChunk ;
2604+ struct OffsetChunk
2605+ {
2606+ OffsetChunk * next ;
2607+ U64 * v ;
2608+ U64 count ;
2609+ U64 cap ;
2610+ };
2611+ OffsetChunk * first_chunk = 0 ;
2612+ OffsetChunk * last_chunk = 0 ;
2613+ U64 total_count = 0 ;
2614+ {
2615+ U64 hit_slots_count = 4096 ;
2616+ HitOffsetNode * * hit_slots = push_array (scratch .arena , HitOffsetNode * , hit_slots_count );
2617+ for (U64 off = base_off , next_off = 0 ;; off = next_off )
2618+ {
2619+ //- rjf: see if we've cycled
2620+ B32 hit_cycle = 0 ;
2621+ {
2622+ U64 hash = u64_hash_from_str8 (str8_struct (& off ));
2623+ U64 slot_idx = hash %hit_slots_count ;
2624+ for (HitOffsetNode * n = hit_slots [slot_idx ]; n != 0 ; n = n -> next )
2625+ {
2626+ if (n -> off == off )
2627+ {
2628+ hit_cycle = 1 ;
2629+ break ;
2630+ }
2631+ }
2632+ }
2633+
2634+ //- rjf: terminate loop
2635+ B32 terminated = (hit_cycle || off == 0 );
2636+ if (terminated )
2637+ {
2638+ break ;
2639+ }
2640+
2641+ //- rjf: another node -> push offset to chunk list
2642+ OffsetChunk * chunk = last_chunk ;
2643+ if (chunk == 0 || chunk -> count >= chunk -> cap )
2644+ {
2645+ chunk = push_array (scratch .arena , OffsetChunk , 1 );
2646+ SLLQueuePush (first_chunk , last_chunk , chunk );
2647+ chunk -> cap = 1024 ;
2648+ chunk -> v = push_array_no_zero (scratch .arena , U64 , chunk -> cap );
2649+ }
2650+ chunk -> v [chunk -> count ] = off ;
2651+ chunk -> count += 1 ;
2652+ total_count += 1 ;
2653+
2654+ //- rjf: read next offset, advance
2655+ if (!space_read (space , & next_off , r1u64 (off + member_element_off , off + member_element_off + member_size )))
2656+ {
2657+ break ;
2658+ }
2659+ }
2660+ }
2661+
2662+ //- rjf: flatten
2663+ Arena * arena = 0 ;
2664+ U64 node_offs_count = 0 ;
2665+ U64 * node_offs = 0 ;
2666+ if (total_count != 0 )
2667+ {
2668+ arena = arena_alloc ();
2669+ node_offs_count = total_count ;
2670+ node_offs = push_array_no_zero (arena , U64 , node_offs_count );
2671+ {
2672+ U64 idx = 0 ;
2673+ for EachNode (n , OffsetChunk , first_chunk )
2674+ {
2675+ MemoryCopy (node_offs + idx , n -> v , n -> count * sizeof (n -> v [0 ]));
2676+ idx += n -> count ;
2677+ }
2678+ }
2679+ }
2680+
2681+ //- rjf: package
2682+ AC_Artifact artifact = {0 };
2683+ {
2684+ artifact .u64 [0 ] = (U64 )arena ;
2685+ artifact .u64 [1 ] = (U64 )node_offs ;
2686+ artifact .u64 [2 ] = node_offs_count ;
2687+ }
2688+
2689+ scratch_end (scratch );
2690+ return artifact ;
25872691}
25882692
25892693internal void
25902694e_list_gather_artifact_destroy (AC_Artifact artifact )
25912695{
2592-
2696+ Arena * arena = (Arena * )artifact .u64 [0 ];
2697+ if (arena != 0 )
2698+ {
2699+ arena_release (arena );
2700+ }
25932701}
25942702
2595- E_TYPE_EXPAND_INFO_FUNCTION_DEF (list )
2703+ typedef struct E_ListIRExt E_ListIRExt ;
2704+ struct E_ListIRExt
25962705{
2597- E_Type * type = e_type_from_key (eval .irtree .type_key );
2706+ U64 * offs ;
2707+ U64 offs_count ;
2708+ };
2709+
2710+ E_TYPE_IREXT_FUNCTION_DEF (list )
2711+ {
2712+ E_IRExt result = {0 };
2713+ E_Type * type = e_type_from_key (irtree -> type_key );
25982714 String8 next_link_member_name = str8_lit ("next" );
25992715 if (type -> args != 0 && type -> count > 0 )
26002716 {
26012717 next_link_member_name = type -> args [0 ]-> string ;
26022718 }
2603- E_TypeKey node_type_key = e_type_key_unwrap (eval . irtree . type_key , E_TypeUnwrapFlag_All );
2719+ E_TypeKey node_type_key = e_type_key_unwrap (irtree -> type_key , E_TypeUnwrapFlag_All );
26042720 E_Member next_link_member = e_type_member_from_key_name__cached (node_type_key , next_link_member_name );
2721+ E_TypeExpandInfo info = {0 , 0 };
26052722 if (next_link_member .kind != E_MemberKind_DataField )
26062723 {
26072724 // TODO(rjf): error reporting
26082725 }
26092726 else
26102727 {
2728+ Temp scratch = scratch_begin (& arena , 1 );
2729+ Access * access = access_open ();
2730+
2731+ // rjf: evaluate first offset
2732+ E_OpList oplist = e_oplist_from_irtree (scratch .arena , irtree -> root );
2733+ String8 bytecode = e_bytecode_from_oplist (scratch .arena , & oplist );
2734+ E_Interpretation base_off_interpret = e_interpret (bytecode );
26112735
2736+ // rjf: get artifact
2737+ #pragma pack(push, 1)
2738+ struct
2739+ {
2740+ E_Space space ;
2741+ U64 base_off ;
2742+ U64 member_element_off ;
2743+ U64 member_size ;
2744+ E_SpaceRWFunction * space_read ;
2745+ }
2746+ key_data =
2747+ {
2748+ base_off_interpret .space ,
2749+ base_off_interpret .value .u64 ,
2750+ next_link_member .off ,
2751+ e_type_byte_size_from_key (next_link_member .type_key ),
2752+ e_base_ctx -> space_read ,
2753+ };
2754+ #pragma pack(pop)
2755+ AC_Artifact gather_artifact = ac_artifact_from_key (access , str8_struct (& key_data ), e_list_gather_artifact_create , e_list_gather_artifact_destroy , 0 );
2756+ U64 * offs = (U64 * )gather_artifact .u64 [1 ];
2757+ U64 offs_count = gather_artifact .u64 [2 ];
2758+
2759+ // rjf: fill info from artifact
2760+ E_ListIRExt * ext = push_array (arena , E_ListIRExt , 1 );
2761+ ext -> offs = offs ;
2762+ ext -> offs_count = offs_count ;
2763+ result .user_data = ext ;
2764+
2765+ access_close (access );
2766+ scratch_end (scratch );
26122767 }
2613- E_TypeExpandInfo info = {0 , 0 };
2768+ return result ;
2769+ }
2770+
2771+ E_TYPE_EXPAND_INFO_FUNCTION_DEF (list )
2772+ {
2773+ E_ListIRExt * ext = (E_ListIRExt * )eval .irtree .user_data ;
2774+ U64 count = 0 ;
2775+ if (ext != 0 )
2776+ {
2777+ count = ext -> offs_count ;
2778+ }
2779+ E_TypeExpandInfo info = {0 , count };
26142780 return info ;
26152781}
26162782
2783+ E_TYPE_ACCESS_FUNCTION_DEF (list )
2784+ {
2785+ E_IRTreeAndType result = {& e_irnode_nil };
2786+ E_ListIRExt * ext = (E_ListIRExt * )lhs_irtree -> user_data ;
2787+ if (ext != 0 && expr -> kind == E_ExprKind_ArrayIndex )
2788+ {
2789+ Temp scratch = scratch_begin (& arena , 1 );
2790+
2791+ // rjf: compute index
2792+ E_Expr * rhs_expr = expr -> last ;
2793+ E_IRTreeAndType rhs_irtree = e_push_irtree_and_type_from_expr (scratch .arena , overridden , & e_default_identifier_resolution_rule , 0 , 0 , rhs_expr );
2794+ E_OpList rhs_oplist = e_oplist_from_irtree (scratch .arena , rhs_irtree .root );
2795+ String8 rhs_bytecode = e_bytecode_from_oplist (scratch .arena , & rhs_oplist );
2796+ E_Interpretation rhs_interpret = e_interpret (rhs_bytecode );
2797+ U64 idx = rhs_interpret .value .u64 ;
2798+
2799+ // rjf: get offset
2800+ U64 off = 0 ;
2801+ if (idx < ext -> offs_count )
2802+ {
2803+ off = ext -> offs [idx ];
2804+ }
2805+
2806+ // rjf: generate IR tree to compute this offset w/ the node type
2807+ result .root = e_irtree_const_u (arena , off );
2808+ result .type_key = e_type_key_unwrap (lhs_irtree -> type_key , E_TypeUnwrapFlag_AllDecorative );
2809+ result .mode = E_Mode_Offset ;
2810+
2811+ scratch_end (scratch );
2812+ }
2813+ return result ;
2814+ }
2815+
26172816E_TYPE_EXPAND_RANGE_FUNCTION_DEF (list )
26182817{
26192818 U64 read_range_count = dim_1u64 (idx_range );
0 commit comments