1
+ package com .annimon .ownlang .lib .modules .functions ;
2
+
3
+ import com .annimon .ownlang .lib .*;
4
+ import java .util .Iterator ;
5
+
6
+ public final class std_range implements Function {
7
+
8
+ @ Override
9
+ public Value execute (Value ... args ) {
10
+ Arguments .checkRange (1 , 3 , args .length );
11
+
12
+ final long from , to , step ;
13
+ switch (args .length ) {
14
+ default :
15
+ case 1 :
16
+ from = 0 ;
17
+ to = getLong (args [0 ]);
18
+ step = 1 ;
19
+ break ;
20
+ case 2 :
21
+ from = getLong (args [0 ]);
22
+ to = getLong (args [1 ]);
23
+ step = 1 ;
24
+ break ;
25
+ case 3 :
26
+ from = getLong (args [0 ]);
27
+ to = getLong (args [1 ]);
28
+ step = getLong (args [2 ]);
29
+ break ;
30
+ }
31
+ return RangeValue .of (from , to , step );
32
+ }
33
+
34
+ private static long getLong (Value v ) {
35
+ if (v .type () == Types .NUMBER ) {
36
+ return ((NumberValue ) v ).asLong ();
37
+ }
38
+ return v .asInt ();
39
+ }
40
+
41
+ private static class RangeValue extends ArrayValue {
42
+
43
+ public static ArrayValue of (long from , long to , long step ) {
44
+ boolean isInvalid = false ;
45
+ isInvalid = isInvalid || (step == 0 );
46
+ isInvalid = isInvalid || ((step > 0 ) && (from >= to ));
47
+ isInvalid = isInvalid || ((step < 0 ) && (to >= from ));
48
+ if (isInvalid ) return new ArrayValue (0 );
49
+ return new RangeValue (from , to , step );
50
+ }
51
+
52
+ private final long from , to , step ;
53
+ private final int size ;
54
+
55
+ public RangeValue (long from , long to , long step ) {
56
+ super (new Value [0 ]);
57
+ this .from = from ;
58
+ this .to = to ;
59
+ this .step = step ;
60
+ // x = range(0, 10, 2)
61
+ // 0, 2, 4, 6, 8 | 0..10 step 2
62
+ // 0, 3, 6, 9 | 0..10 step 3
63
+ // 0, 4, 8 | 0..10 step 4
64
+ final long base = (from < to ) ? (to - from ) : (from - to );
65
+ final long absStep = (step < 0 ) ? -step : step ;
66
+ this .size = (int ) (base / absStep + (base % absStep == 0 ? 0 : 1 ));
67
+ }
68
+
69
+ @ Override
70
+ public Value [] getCopyElements () {
71
+ final Value [] result = new Value [size ];
72
+ int i = 0 ;
73
+ if (isIntegerRange ()) {
74
+ final int toInt = (int ) to ;
75
+ final int stepInt = (int ) step ;
76
+ for (int value = (int ) from ; value < toInt ; value += stepInt ) {
77
+ result [i ++] = NumberValue .of (value );
78
+ }
79
+ } else {
80
+ for (long value = from ; value < to ; value += step ) {
81
+ result [i ++] = NumberValue .of (value );
82
+ }
83
+ }
84
+ return result ;
85
+ }
86
+
87
+ private boolean isIntegerRange () {
88
+ if (to > 0 ) {
89
+ return (to < Integer .MAX_VALUE ) && (from > Integer .MIN_VALUE && to < Integer .MAX_VALUE );
90
+ }
91
+ return (to > Integer .MIN_VALUE ) && (to > Integer .MIN_VALUE && from < Integer .MAX_VALUE );
92
+ }
93
+
94
+ @ Override
95
+ public int size () {
96
+ return size ;
97
+ }
98
+
99
+ @ Override
100
+ public Value get (int index ) {
101
+ if (isIntegerRange ()) {
102
+ return NumberValue .of ((int ) (from + index * step ));
103
+ }
104
+ return NumberValue .of (from + (long ) index * step );
105
+ }
106
+
107
+ @ Override
108
+ public void set (int index , Value value ) {
109
+ // not implemented
110
+ }
111
+
112
+ @ Override
113
+ public Object raw () {
114
+ return getCopyElements ();
115
+ }
116
+
117
+ @ Override
118
+ public String asString () {
119
+ if (size == 0 ) return "[]" ;
120
+
121
+ final StringBuilder sb = new StringBuilder ();
122
+ sb .append ('[' ).append (from );
123
+ for (long value = from + step ; value < to ; value += step ) {
124
+ sb .append (", " ).append (value );
125
+ }
126
+ sb .append (']' );
127
+ return sb .toString ();
128
+ }
129
+
130
+ @ Override
131
+ public Iterator <Value > iterator () {
132
+ if (isIntegerRange ()) {
133
+ final int toInt = (int ) to ;
134
+ final int stepInt = (int ) step ;
135
+ return new Iterator <Value >() {
136
+
137
+ int value = (int ) from ;
138
+
139
+ @ Override
140
+ public boolean hasNext () {
141
+ return value < toInt ;
142
+ }
143
+
144
+ @ Override
145
+ public Value next () {
146
+ final int result = value ;
147
+ value += stepInt ;
148
+ return NumberValue .of (result );
149
+ }
150
+ };
151
+ }
152
+ return new Iterator <Value >() {
153
+
154
+ long value = from ;
155
+
156
+ @ Override
157
+ public boolean hasNext () {
158
+ return value < to ;
159
+ }
160
+
161
+ @ Override
162
+ public Value next () {
163
+ final long result = value ;
164
+ value += step ;
165
+ return NumberValue .of (result );
166
+ }
167
+ };
168
+ }
169
+
170
+ @ Override
171
+ public int hashCode () {
172
+ int hash = 5 ;
173
+ hash = 59 * hash + (int ) (this .from ^ (this .from >>> 32 ));
174
+ hash = 59 * hash + (int ) (this .to ^ (this .to >>> 32 ));
175
+ hash = 59 * hash + (int ) (this .step ^ (this .step >>> 32 ));
176
+ return hash ;
177
+ }
178
+
179
+ @ Override
180
+ public boolean equals (Object obj ) {
181
+ if (this == obj ) return true ;
182
+ if (obj == null ) return false ;
183
+ if (getClass () != obj .getClass ())
184
+ return false ;
185
+ final RangeValue other = (RangeValue ) obj ;
186
+ if (this .from != other .from ) return false ;
187
+ if (this .to != other .to ) return false ;
188
+ if (this .step != other .step ) return false ;
189
+ return true ;
190
+ }
191
+
192
+ @ Override
193
+ public int compareTo (Value o ) {
194
+ if (o .type () == Types .ARRAY ) {
195
+ final int lengthCompare = Integer .compare (size (), ((ArrayValue ) o ).size ());
196
+ if (lengthCompare != 0 ) return lengthCompare ;
197
+
198
+ if (o instanceof RangeValue ) {
199
+ final RangeValue o2 = ((RangeValue ) o );
200
+ int compareResult ;
201
+ compareResult = Long .compare (this .from , o2 .from );
202
+ if (compareResult != 0 ) return compareResult ;
203
+ compareResult = Long .compare (this .to , o2 .to );
204
+ if (compareResult != 0 ) return compareResult ;
205
+ }
206
+ }
207
+ return asString ().compareTo (o .asString ());
208
+ }
209
+
210
+ @ Override
211
+ public String toString () {
212
+ if (step == 1 ) {
213
+ return String .format ("range(%d, %d)" , from , to );
214
+ }
215
+ return String .format ("range(%d, %d, %d)" , from , to , step );
216
+ }
217
+ }
218
+ }
0 commit comments