@@ -32,7 +32,7 @@ ip: *InternPool,
32
32
// nested scopes with comptime bindings
33
33
bound_type_params : BoundTypeParams = .{},
34
34
resolved_callsites : std .AutoHashMapUnmanaged (Declaration.Param , ? Type ) = .empty ,
35
- resolved_nodes : std .HashMapUnmanaged (NodeWithUri , ? Type , NodeWithUri .Context , std .hash_map .default_max_load_percentage ) = .empty ,
35
+ resolved_nodes : std .HashMapUnmanaged (NodeWithUri , ? Binding , NodeWithUri .Context , std .hash_map .default_max_load_percentage ) = .empty ,
36
36
/// used to detect recursion
37
37
use_trail : NodeSet = .empty ,
38
38
collect_callsite_references : bool ,
@@ -893,13 +893,13 @@ pub fn resolveOrelseType(analyser: *Analyser, lhs: Type, rhs: Type) error{OutOfM
893
893
};
894
894
}
895
895
896
- pub fn resolveAddressOf (analyser : * Analyser , ty : Type ) error {OutOfMemory }! ? Type {
896
+ pub fn resolveAddressOf (analyser : * Analyser , is_const : bool , ty : Type ) error {OutOfMemory }! Type {
897
897
return .{
898
898
.data = .{
899
899
.pointer = .{
900
900
.size = .one ,
901
901
.sentinel = .none ,
902
- .is_const = false ,
902
+ .is_const = is_const ,
903
903
.elem_ty = try analyser .allocType (ty .typeOf (analyser )),
904
904
},
905
905
},
@@ -1515,13 +1515,23 @@ const FindBreaks = struct {
1515
1515
/// Resolves the type of an Ast Node.
1516
1516
/// Returns `null` if the type could not be resolved.
1517
1517
pub fn resolveTypeOfNode (analyser : * Analyser , node_handle : NodeWithHandle ) error {OutOfMemory }! ? Type {
1518
+ const binding = try analyser .resolveBindingOfNode (node_handle ) orelse return null ;
1519
+ return binding .type ;
1520
+ }
1521
+
1522
+ fn resolveTypeOfNodeInternal (analyser : * Analyser , node_handle : NodeWithHandle ) error {OutOfMemory }! ? Type {
1523
+ const binding = try analyser .resolveBindingOfNodeInternal (node_handle ) orelse return null ;
1524
+ return binding .type ;
1525
+ }
1526
+
1527
+ pub fn resolveBindingOfNode (analyser : * Analyser , node_handle : NodeWithHandle ) error {OutOfMemory }! ? Binding {
1518
1528
const tracy_zone = tracy .trace (@src ());
1519
1529
defer tracy_zone .end ();
1520
1530
1521
- return analyser .resolveTypeOfNodeInternal (node_handle );
1531
+ return analyser .resolveBindingOfNodeInternal (node_handle );
1522
1532
}
1523
1533
1524
- fn resolveTypeOfNodeInternal (analyser : * Analyser , node_handle : NodeWithHandle ) error {OutOfMemory }! ? Type {
1534
+ fn resolveBindingOfNodeInternal (analyser : * Analyser , node_handle : NodeWithHandle ) error {OutOfMemory }! ? Binding {
1525
1535
const node_with_uri : NodeWithUri = .{
1526
1536
.node = node_handle .node ,
1527
1537
.uri = node_handle .handle .uri ,
@@ -1533,12 +1543,12 @@ fn resolveTypeOfNodeInternal(analyser: *Analyser, node_handle: NodeWithHandle) e
1533
1543
// we insert null before resolving the type so that a recursive definition doesn't result in an infinite loop
1534
1544
gop .value_ptr .* = null ;
1535
1545
1536
- const ty = try analyser .resolveTypeOfNodeUncached (node_handle );
1537
- if (ty != null ) {
1538
- analyser .resolved_nodes .getPtr (node_with_uri ).?.* = ty ;
1546
+ const binding = try analyser .resolveBindingOfNodeUncached (node_handle );
1547
+ if (binding != null ) {
1548
+ analyser .resolved_nodes .getPtr (node_with_uri ).?.* = binding ;
1539
1549
}
1540
1550
1541
- return ty ;
1551
+ return binding ;
1542
1552
}
1543
1553
1544
1554
fn resolveTypeOfNodeUncached (analyser : * Analyser , node_handle : NodeWithHandle ) error {OutOfMemory }! ? Type {
@@ -1576,23 +1586,6 @@ fn resolveTypeOfNodeUncached(analyser: *Analyser, node_handle: NodeWithHandle) e
1576
1586
1577
1587
return fallback_type ;
1578
1588
},
1579
- .identifier = > {
1580
- const name_token = ast .identifierTokenFromIdentifierNode (tree , node ) orelse return null ;
1581
- const name = offsets .identifierTokenToNameSlice (tree , name_token );
1582
-
1583
- const is_escaped_identifier = tree .source [tree .tokenStart (name_token )] == '@' ;
1584
- if (! is_escaped_identifier ) {
1585
- if (std .mem .eql (u8 , name , "_" )) return null ;
1586
- if (try analyser .resolvePrimitive (name )) | primitive | {
1587
- return Type .fromIP (analyser , analyser .ip .typeOf (primitive ), primitive );
1588
- }
1589
- }
1590
- if (analyser .bound_type_params .resolve (name )) | t | {
1591
- return t .* ;
1592
- }
1593
- const child = try analyser .lookupSymbolGlobal (handle , name , tree .tokenStart (name_token )) orelse return null ;
1594
- return try child .resolveType (analyser );
1595
- },
1596
1589
.call ,
1597
1590
.call_comma ,
1598
1591
.async_call ,
@@ -1809,14 +1802,6 @@ fn resolveTypeOfNodeUncached(analyser: *Analyser, node_handle: NodeWithHandle) e
1809
1802
1810
1803
return try analyser .resolveUnwrapErrorUnionType (base_type , .payload );
1811
1804
},
1812
- .address_of = > {
1813
- const base_type = try analyser .resolveTypeOfNodeInternal (.{
1814
- .node = tree .nodeData (node ).node ,
1815
- .handle = handle ,
1816
- }) orelse return null ;
1817
-
1818
- return try analyser .resolveAddressOf (base_type );
1819
- },
1820
1805
.field_access = > {
1821
1806
const lhs_node , const field_name = tree .nodeData (node_handle .node ).node_and_token ;
1822
1807
@@ -2620,10 +2605,79 @@ fn resolveTypeOfNodeUncached(analyser: *Analyser, node_handle: NodeWithHandle) e
2620
2605
.asm_output ,
2621
2606
.asm_input ,
2622
2607
= > {},
2608
+
2609
+ // TODO: port remaining nodes to resolveBindingOfNodeUncached
2610
+ .identifier ,
2611
+ .address_of ,
2612
+ = > {
2613
+ const binding = try analyser .resolveBindingOfNodeUncached (node_handle ) orelse return null ;
2614
+ return binding .type ;
2615
+ },
2623
2616
}
2624
2617
return null ;
2625
2618
}
2626
2619
2620
+ fn resolveBindingOfNodeUncached (analyser : * Analyser , node_handle : NodeWithHandle ) error {OutOfMemory }! ? Binding {
2621
+ const node = node_handle .node ;
2622
+ const handle = node_handle .handle ;
2623
+ const tree = handle .tree ;
2624
+
2625
+ switch (tree .nodeTag (node )) {
2626
+ .identifier = > {
2627
+ const name_token = ast .identifierTokenFromIdentifierNode (tree , node ) orelse return null ;
2628
+ const name = offsets .identifierTokenToNameSlice (tree , name_token );
2629
+
2630
+ const is_escaped_identifier = tree .source [tree .tokenStart (name_token )] == '@' ;
2631
+ if (! is_escaped_identifier ) {
2632
+ if (std .mem .eql (u8 , name , "_" )) return null ;
2633
+ if (try analyser .resolvePrimitive (name )) | primitive | {
2634
+ return .{
2635
+ .type = Type .fromIP (analyser , analyser .ip .typeOf (primitive ), primitive ),
2636
+ .is_const = true ,
2637
+ };
2638
+ }
2639
+ }
2640
+
2641
+ if (analyser .bound_type_params .resolve (name )) | t | {
2642
+ return .{
2643
+ .type = t .* ,
2644
+ .is_const = true ,
2645
+ };
2646
+ }
2647
+
2648
+ const child = try analyser .lookupSymbolGlobal (handle , name , tree .tokenStart (name_token )) orelse return null ;
2649
+ const child_ty = try child .resolveType (analyser ) orelse return null ;
2650
+ return .{
2651
+ .type = child_ty ,
2652
+ .is_const = child .isConst (),
2653
+ };
2654
+ },
2655
+
2656
+ .address_of = > {
2657
+ const base_binding = try analyser .resolveBindingOfNodeInternal (.{
2658
+ .node = tree .nodeData (node ).node ,
2659
+ .handle = handle ,
2660
+ }) orelse return null ;
2661
+
2662
+ return .{
2663
+ .type = try analyser .resolveAddressOf (base_binding .is_const , base_binding .type ),
2664
+ .is_const = true ,
2665
+ };
2666
+ },
2667
+
2668
+ // TODO: port remaining nodes to resolveBindingOfNodeUncached
2669
+ else = > return .{
2670
+ .type = try analyser .resolveTypeOfNodeUncached (node_handle ) orelse return null ,
2671
+ .is_const = false ,
2672
+ },
2673
+ }
2674
+ }
2675
+
2676
+ pub const Binding = struct {
2677
+ type : Type ,
2678
+ is_const : bool ,
2679
+ };
2680
+
2627
2681
/// Represents a resolved Zig type.
2628
2682
/// This is the return type of `resolveTypeOfNode`.
2629
2683
pub const Type = struct {
0 commit comments