I haven’t tested all cases yet, but I think there are some shortcuts we can take.
First, breaking up IP addresses into its component parts:
q: (tuple string item 0 of it as integer, tuple string item 1 of it as integer, tuple string item 2 of it as integer, tuple string item 3 of it as integer) of (tuple string of substrings separated by "." of it) of ("192.168.0.1"; "128.168.0.1"; "10.168.0.1"; "1.2.3.4")
A: 192, 168, 0, 1
A: 128, 168, 0, 1
A: 10, 168, 0, 1
A: 1, 2, 3, 4
T: 0.602 ms
Second, we can convert those addresses into hexadecimal and show their bitset representations:
q: (item 0 of it as integer as hexadecimal, item 0 of it, item 1 of it) of (left shift 24 of (item 0 of it as bits) + left shift 16 of (item 1 of it as bits) + left shift 8 of (item 2 of it as bits) + (item 3 of it as bits), it) of (tuple string item 0 of it as integer, tuple string item 1 of it as integer, tuple string item 2 of it as integer, tuple string item 3 of it as integer) of (tuple string of substrings separated by "." of it) of ("192.168.0.1"; "128.168.0.1"; "10.168.0.1"; "1.2.3.4")
A: c0a80001, 11000000101010000000000000000001, ( 192, 168, 0, 1 )
A: 80a80001, 10000000101010000000000000000001, ( 128, 168, 0, 1 )
A: aa80001, 1010101010000000000000000001, ( 10, 168, 0, 1 )
A: 1020304, 1000000100000001100000100, ( 1, 2, 3, 4 )
T: 1.161 ms
I: plural ( string, bit set, ( integer, integer, integer, integer ) )
Now, the shortcut part. If ‘bit 31’ is not set, this would be regarded as a “positive” 32-bit integer. If bit 31 is set, we would have to represent this as a negative integer. The shortcut that I think works is to subtract this from 0, and then again set bit 31. Here we don’t really need to show the hexadecimal values, I’m just leaving it in for illustration:
q: (item 0 of it as integer as hexadecimal, (if not bit 31 of it then it as integer else 0 - (it as integer) of it) of item 0 of it) of (left shift 24 of (item 0 of it as bits) + left shift 16 of (item 1 of it as bits) + left shift 8 of (item 2 of it as bits) + (item 3 of it as bits), it) of (tuple string item 0 of it as integer, tuple string item 1 of it as integer, tuple string item 2 of it as integer, tuple string item 3 of it as integer) of (tuple string of substrings separated by "." of it) of ("192.168.0.1"; "128.168.0.1"; "10.168.0.1"; "1.2.3.4")
A: c0a80001, -3232235521
A: 80a80001, -2158493697
A: aa80001, 178782209
A: 1020304, 16909060
T: 0.690 ms
I: plural ( string, integer )
So we would pass these integer values back as the return code. To convert them back into IP addresses, we would check whether the value is negative; if the integer is positive, just convert it back into hexadecimal, or bit sets, or IP addresses; if the integer is negative, again subtract it from zero (making it positive again) and convert that result to hexadecimal or IP address
q: ((if it > 0 then it else 0 - it) of it as hexadecimal) of (-3232235521; -2158493697; 178782209; 16909060)
A: c0a80001
A: 80a80001
A: aa80001
A: 1020304
T: 2.648 ms
I: plural string
The important things to check are that the hexadecimal values we return in the last query (converting positive/negative integers into hexadecimal) are the same hex values we calculated for the IP address. For the four IPs I tested they match.