@@ -1350,6 +1350,148 @@ fn resolveIntegerLiteral(analyser: *Analyser, comptime T: type, options: Resolve
13501350 return analyser .ip .toInt (ip_index , T );
13511351}
13521352
1353+ const IntInfo = union (enum ) {
1354+ comptime_int ,
1355+ fixed_int : std.builtin.Type.Int ,
1356+ };
1357+
1358+ fn intInfo (analyser : * Analyser , ty : InternPool.Index ) ? IntInfo {
1359+ const type_tag = analyser .ip .zigTypeTag (ty ) orelse return null ;
1360+ return switch (type_tag ) {
1361+ .comptime_int = > .comptime_int ,
1362+ .int = > .{ .fixed_int = analyser .ip .intInfo (ty , builtin .target ) },
1363+ else = > null ,
1364+ };
1365+ }
1366+
1367+ fn resolveUnaryIntegerExpression (
1368+ analyser : * Analyser ,
1369+ tag : std.zig.Ast.Node.Tag ,
1370+ instance : Type ,
1371+ ) ! ? Type {
1372+ const index = instance .ipIndex () orelse return null ;
1373+ const ty = analyser .ip .typeOf (index );
1374+ const int_info = analyser .intInfo (ty ) orelse return null ;
1375+ var result = try analyser .ip .toBigInt (analyser .gpa , index ) orelse return null ;
1376+ defer result .deinit ();
1377+ switch (tag ) {
1378+ .bit_not = > switch (int_info ) {
1379+ .comptime_int = > return null ,
1380+ .fixed_int = > | info | _ = try result .bitNotWrap (& result , info .signedness , info .bits ),
1381+ },
1382+ .negation = > result .negate (),
1383+ .negation_wrap = > switch (int_info ) {
1384+ .comptime_int = > result .negate (),
1385+ .fixed_int = > | info | {
1386+ // TODO: std.math.big.int does not have a negateWrap method
1387+ _ = info ;
1388+ return null ;
1389+ },
1390+ },
1391+ else = > unreachable ,
1392+ }
1393+ return try analyser .resolveIntegerExpressionResult (ty , result .toConst ());
1394+ }
1395+
1396+ fn resolveBinaryIntegerExpression (
1397+ analyser : * Analyser ,
1398+ tag : std.zig.Ast.Node.Tag ,
1399+ instance : Type ,
1400+ lhs_instance : Type ,
1401+ rhs_instance : Type ,
1402+ ) ! ? Type {
1403+ const lhs_index = lhs_instance .ipIndex () orelse return null ;
1404+ const rhs_index = rhs_instance .ipIndex () orelse return null ;
1405+ const type_of = try instance .typeOf (analyser );
1406+ const ty = type_of .ipIndex () orelse return null ;
1407+ const int_info = analyser .intInfo (ty ) orelse return null ;
1408+ var lhs = try analyser .ip .toBigInt (analyser .gpa , lhs_index ) orelse return null ;
1409+ defer lhs .deinit ();
1410+ var rhs = try analyser .ip .toBigInt (analyser .gpa , rhs_index ) orelse return null ;
1411+ defer rhs .deinit ();
1412+ var result : std.math.big.int.Managed = try .init (analyser .gpa );
1413+ defer result .deinit ();
1414+ switch (tag ) {
1415+ .mul = > try result .mul (& lhs , & rhs ),
1416+ .div = > {
1417+ var temp : std.math.big.int.Managed = try .init (analyser .gpa );
1418+ defer temp .deinit ();
1419+ try result .divTrunc (& temp , & lhs , & rhs );
1420+ },
1421+ .mod = > {
1422+ var temp : std.math.big.int.Managed = try .init (analyser .gpa );
1423+ defer temp .deinit ();
1424+ try temp .divTrunc (& result , & lhs , & rhs );
1425+ },
1426+ .add = > try result .add (& lhs , & rhs ),
1427+ .sub = > try result .sub (& lhs , & rhs ),
1428+ .shl = > try result .shiftLeft (& lhs , rhs .toInt (usize ) catch return null ),
1429+ .shr = > try result .shiftRight (& lhs , rhs .toInt (usize ) catch return null ),
1430+ .bit_and = > try result .bitAnd (& lhs , & rhs ),
1431+ .bit_xor = > try result .bitXor (& lhs , & rhs ),
1432+ .bit_or = > try result .bitOr (& lhs , & rhs ),
1433+ .add_wrap ,
1434+ .sub_wrap ,
1435+ .mul_wrap ,
1436+ .add_sat ,
1437+ .sub_sat ,
1438+ .mul_sat ,
1439+ .shl_sat ,
1440+ = > switch (int_info ) {
1441+ .comptime_int = > switch (tag ) {
1442+ .add_wrap , .add_sat = > try result .add (& lhs , & rhs ),
1443+ .sub_wrap , .sub_sat = > try result .sub (& lhs , & rhs ),
1444+ .mul_wrap , .mul_sat = > try result .mul (& lhs , & rhs ),
1445+ .shl_sat = > try result .shiftLeft (& lhs , rhs .toInt (usize ) catch return null ),
1446+ else = > unreachable ,
1447+ },
1448+ .fixed_int = > | info | switch (tag ) {
1449+ .add_wrap = > _ = try result .addWrap (& lhs , & rhs , info .signedness , info .bits ),
1450+ .sub_wrap = > _ = try result .subWrap (& lhs , & rhs , info .signedness , info .bits ),
1451+ .mul_wrap = > _ = try result .mulWrap (& lhs , & rhs , info .signedness , info .bits ),
1452+ .add_sat = > try result .addSat (& lhs , & rhs , info .signedness , info .bits ),
1453+ .sub_sat = > try result .subSat (& lhs , & rhs , info .signedness , info .bits ),
1454+ .mul_sat = > {
1455+ // std.math.big.int does not have a mulSat method
1456+ try result .mul (& lhs , & rhs );
1457+ try result .saturate (& result , info .signedness , info .bits );
1458+ },
1459+ .shl_sat = > try result .shiftLeftSat (& lhs , rhs .toInt (usize ) catch return null , info .signedness , info .bits ),
1460+ else = > unreachable ,
1461+ },
1462+ },
1463+ else = > unreachable ,
1464+ }
1465+ return try analyser .resolveIntegerExpressionResult (ty , result .toConst ());
1466+ }
1467+
1468+ fn resolveIntegerExpressionResult (
1469+ analyser : * Analyser ,
1470+ ty : InternPool.Index ,
1471+ result : std.math.big.int.Const ,
1472+ ) ! ? Type {
1473+ const int_info = analyser .intInfo (ty ) orelse return null ;
1474+ switch (int_info ) {
1475+ .comptime_int = > {},
1476+ .fixed_int = > | info | {
1477+ if (! result .fitsInTwosComp (info .signedness , info .bits )) {
1478+ return null ;
1479+ }
1480+ },
1481+ }
1482+ const index = index : {
1483+ if (result .positive ) blk : {
1484+ const int = result .toInt (u64 ) catch break :blk ;
1485+ break :index try analyser .ip .get (.{ .int_u64_value = .{ .ty = ty , .int = int } });
1486+ } else blk : {
1487+ const int = result .toInt (i64 ) catch break :blk ;
1488+ break :index try analyser .ip .get (.{ .int_i64_value = .{ .ty = ty , .int = int } });
1489+ }
1490+ break :index try analyser .ip .getBigInt (ty , result );
1491+ };
1492+ return Type .fromIP (analyser , ty , index );
1493+ }
1494+
13531495fn extractArrayData (data : * Type.Data ) ? * Type.Data {
13541496 return switch (data .* ) {
13551497 .array = > data ,
@@ -1869,8 +2011,9 @@ fn resolveTypeOfNodeUncached(analyser: *Analyser, options: ResolveOptions) Error
18692011 const node = node_handle .node ;
18702012 const handle = node_handle .handle ;
18712013 const tree = & handle .tree ;
2014+ const node_tag = tree .nodeTag (node );
18722015
1873- switch (tree . nodeTag ( node ) ) {
2016+ switch (node_tag ) {
18742017 .global_var_decl ,
18752018 .local_var_decl ,
18762019 .simple_var_decl ,
@@ -2670,7 +2813,7 @@ fn resolveTypeOfNodeUncached(analyser: *Analyser, options: ResolveOptions) Error
26702813 = > {
26712814 const ty = try analyser .resolveTypeOfNodeInternal (.of (tree .nodeData (node ).node , handle )) orelse return null ;
26722815 if (ty .is_type_val ) return null ;
2673- return ty .withoutIPIndex (analyser );
2816+ return try analyser . resolveUnaryIntegerExpression ( node_tag , ty ) orelse ty .withoutIPIndex (analyser );
26742817 },
26752818
26762819 .multiline_string_literal = > {
@@ -2815,64 +2958,70 @@ fn resolveTypeOfNodeUncached(analyser: *Analyser, options: ResolveOptions) Error
28152958 .bit_or ,
28162959 = > {
28172960 const lhs , const rhs = tree .nodeData (node ).node_and_node ;
2818- var lhs_ty = try analyser .resolveTypeOfNodeInternal (.of (lhs , handle )) orelse return null ;
2819- if (lhs_ty .is_type_val ) return null ;
2820- var rhs_ty = try analyser .resolveTypeOfNodeInternal (.of (rhs , handle )) orelse return null ;
2821- if (rhs_ty .is_type_val ) return null ;
2822- lhs_ty = lhs_ty .withoutIPIndex (analyser );
2823- rhs_ty = rhs_ty .withoutIPIndex (analyser );
2824- return analyser .resolvePeerTypes (lhs_ty , rhs_ty );
2961+ const lhs_instance = try analyser .resolveTypeOfNodeInternal (.of (lhs , handle )) orelse return null ;
2962+ if (lhs_instance .is_type_val ) return null ;
2963+ const rhs_instance = try analyser .resolveTypeOfNodeInternal (.of (rhs , handle )) orelse return null ;
2964+ if (rhs_instance .is_type_val ) return null ;
2965+ const lhs_no_value = lhs_instance .withoutIPIndex (analyser );
2966+ const rhs_no_value = rhs_instance .withoutIPIndex (analyser );
2967+ const instance = try analyser .resolvePeerTypes (lhs_no_value , rhs_no_value ) orelse return null ;
2968+ return try analyser .resolveBinaryIntegerExpression (node_tag , instance , lhs_instance , rhs_instance ) orelse return instance ;
28252969 },
28262970
28272971 .add = > {
28282972 const lhs , const rhs = tree .nodeData (node ).node_and_node ;
2829- var lhs_ty = try analyser .resolveTypeOfNodeInternal (.of (lhs , handle )) orelse return null ;
2830- if (lhs_ty .is_type_val ) return null ;
2831- var rhs_ty = try analyser .resolveTypeOfNodeInternal (.of (rhs , handle )) orelse return null ;
2832- if (rhs_ty .is_type_val ) return null ;
2833- lhs_ty = lhs_ty .withoutIPIndex (analyser );
2834- rhs_ty = rhs_ty .withoutIPIndex (analyser );
2835- return switch (lhs_ty .data ) {
2973+ const lhs_instance = try analyser .resolveTypeOfNodeInternal (.of (lhs , handle )) orelse return null ;
2974+ if (lhs_instance .is_type_val ) return null ;
2975+ const rhs_instance = try analyser .resolveTypeOfNodeInternal (.of (rhs , handle )) orelse return null ;
2976+ if (rhs_instance .is_type_val ) return null ;
2977+ const lhs_no_value = lhs_instance .withoutIPIndex (analyser );
2978+ const rhs_no_value = rhs_instance .withoutIPIndex (analyser );
2979+ const instance = switch (lhs_no_value .data ) {
28362980 .pointer = > | lhs_info | switch (lhs_info .size ) {
2837- .many , .c = > lhs_ty ,
2981+ .many , .c = > lhs_no_value ,
28382982 else = > null ,
28392983 },
2840- else = > try analyser .resolvePeerTypes (lhs_ty , rhs_ty ),
2841- };
2984+ else = > try analyser .resolvePeerTypes (lhs_no_value , rhs_no_value ),
2985+ } orelse return null ;
2986+ return try analyser .resolveBinaryIntegerExpression (node_tag , instance , lhs_instance , rhs_instance ) orelse return instance ;
28422987 },
28432988
28442989 .sub = > {
28452990 const lhs , const rhs = tree .nodeData (node ).node_and_node ;
2846- var lhs_ty = try analyser .resolveTypeOfNodeInternal (.of (lhs , handle )) orelse return null ;
2847- if (lhs_ty .is_type_val ) return null ;
2848- var rhs_ty = try analyser .resolveTypeOfNodeInternal (.of (rhs , handle )) orelse return null ;
2849- if (rhs_ty .is_type_val ) return null ;
2850- lhs_ty = lhs_ty .withoutIPIndex (analyser );
2851- rhs_ty = rhs_ty .withoutIPIndex (analyser );
2852- return switch (lhs_ty .data ) {
2853- .pointer = > | lhs_info | switch (rhs_ty .data ) {
2854- .pointer = > | rhs_info | {
2991+ const lhs_instance = try analyser .resolveTypeOfNodeInternal (.of (lhs , handle )) orelse return null ;
2992+ if (lhs_instance .is_type_val ) return null ;
2993+ const rhs_instance = try analyser .resolveTypeOfNodeInternal (.of (rhs , handle )) orelse return null ;
2994+ if (rhs_instance .is_type_val ) return null ;
2995+ const lhs_no_value = lhs_instance .withoutIPIndex (analyser );
2996+ const rhs_no_value = rhs_instance .withoutIPIndex (analyser );
2997+ const instance = switch (lhs_no_value .data ) {
2998+ .pointer = > | lhs_info | switch (rhs_no_value .data ) {
2999+ .pointer = > | rhs_info | blk : {
28553000 if (lhs_info .size == .slice ) return null ;
28563001 if (rhs_info .size == .slice ) return null ;
2857- return Type .fromIP (analyser , .usize_type , null );
3002+ break : blk Type .fromIP (analyser , .usize_type , null );
28583003 },
28593004 else = > switch (lhs_info .size ) {
2860- .many , .c = > lhs_ty ,
3005+ .many , .c = > lhs_no_value ,
28613006 else = > null ,
28623007 },
28633008 },
2864- else = > try analyser .resolvePeerTypes (lhs_ty , rhs_ty ),
2865- };
3009+ else = > try analyser .resolvePeerTypes (lhs_no_value , rhs_no_value ),
3010+ } orelse return null ;
3011+ return try analyser .resolveBinaryIntegerExpression (node_tag , instance , lhs_instance , rhs_instance ) orelse return instance ;
28663012 },
28673013
28683014 .shl ,
28693015 .shl_sat ,
28703016 .shr ,
28713017 = > {
2872- const lhs , _ = tree .nodeData (node ).node_and_node ;
2873- const lhs_ty = try analyser .resolveTypeOfNodeInternal (.of (lhs , handle )) orelse return null ;
2874- if (lhs_ty .is_type_val ) return null ;
2875- return lhs_ty .withoutIPIndex (analyser );
3018+ const lhs , const rhs = tree .nodeData (node ).node_and_node ;
3019+ const lhs_instance = try analyser .resolveTypeOfNodeInternal (.of (lhs , handle )) orelse return null ;
3020+ if (lhs_instance .is_type_val ) return null ;
3021+ const lhs_no_value = lhs_instance .withoutIPIndex (analyser );
3022+ const rhs_instance = try analyser .resolveTypeOfNodeInternal (.of (rhs , handle )) orelse return lhs_no_value ;
3023+ if (rhs_instance .is_type_val ) return lhs_no_value ;
3024+ return try analyser .resolveBinaryIntegerExpression (node_tag , lhs_no_value , lhs_instance , rhs_instance ) orelse return lhs_no_value ;
28763025 },
28773026
28783027 .array_mult = > {
0 commit comments