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