PageRenderTime 36ms CodeModel.GetById 19ms app.highlight 13ms RepoModel.GetById 1ms app.codeStats 1ms

/interpreter/tags/at2dist041108/src/edu/vub/at/objects/natives/NATNumber.java

http://ambienttalk.googlecode.com/
Java | 320 lines | 185 code | 38 blank | 97 comment | 25 complexity | d9f6c9b25ee8f5aeac11777485cb0f25 MD5 | raw file
  1/**
  2 * AmbientTalk/2 Project
  3 * NATNumber.java created on 26-jul-2006 at 16:32:54
  4 * (c) Programming Technology Lab, 2006 - 2007
  5 * Authors: Tom Van Cutsem & Stijn Mostinckx
  6 * 
  7 * Permission is hereby granted, free of charge, to any person
  8 * obtaining a copy of this software and associated documentation
  9 * files (the "Software"), to deal in the Software without
 10 * restriction, including without limitation the rights to use,
 11 * copy, modify, merge, publish, distribute, sublicense, and/or
 12 * sell copies of the Software, and to permit persons to whom the
 13 * Software is furnished to do so, subject to the following
 14 * conditions:
 15 *
 16 * The above copyright notice and this permission notice shall be
 17 * included in all copies or substantial portions of the Software.
 18 *
 19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 20 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 21 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 22 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 23 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 24 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 25 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 26 * OTHER DEALINGS IN THE SOFTWARE.
 27 */
 28package edu.vub.at.objects.natives;
 29
 30import edu.vub.at.eval.Evaluator;
 31import edu.vub.at.exceptions.InterpreterException;
 32import edu.vub.at.exceptions.XIllegalArgument;
 33import edu.vub.at.exceptions.XTypeMismatch;
 34import edu.vub.at.objects.ATBoolean;
 35import edu.vub.at.objects.ATClosure;
 36import edu.vub.at.objects.ATFraction;
 37import edu.vub.at.objects.ATNil;
 38import edu.vub.at.objects.ATNumber;
 39import edu.vub.at.objects.ATNumeric;
 40import edu.vub.at.objects.ATObject;
 41import edu.vub.at.objects.ATTable;
 42import edu.vub.at.objects.coercion.NativeTypeTags;
 43
 44/**
 45 * The native implementation of an AmbientTalk number.
 46 * A number is implemented by a Java int.
 47 * 
 48 * @author smostinc
 49 */
 50public final class NATNumber extends NATNumeric implements ATNumber {
 51	
 52	public static final NATNumber ZERO = new NATNumber(0);
 53	public static final NATNumber ONE = new NATNumber(1);
 54	public static final NATNumber MONE = new NATNumber(-1);
 55	
 56	public final int javaValue;
 57	
 58	/**
 59	 * This method currently serves as a hook for number creation.
 60	 * Currently number objects are not reused, but this might change in the future.
 61	 */
 62	public static final NATNumber atValue(int javaNumber) {
 63		return new NATNumber(javaNumber);
 64	}
 65	
 66	private NATNumber(int javaNumber) {
 67		javaValue = javaNumber;
 68	}
 69
 70    public ATBoolean base__opeql__opeql_(ATObject comparand) throws XTypeMismatch {
 71    	if (comparand.isNativeNumber()) {
 72    		return NATBoolean.atValue(javaValue == comparand.asNativeNumber().javaValue);
 73    	} else {
 74    		return NATBoolean._FALSE_;
 75    	}
 76    }
 77	
 78	public ATNumber asNumber() throws XTypeMismatch { return this; }
 79	
 80	public boolean isNativeNumber() { return true; }
 81	
 82	public NATNumber asNativeNumber() { return this; }
 83	
 84	public NATText meta_print() throws InterpreterException {
 85        return NATText.atValue(String.valueOf(javaValue));
 86	}
 87	
 88    public ATTable meta_typeTags() throws InterpreterException {
 89    	return NATTable.of(NativeTypeTags._NUMBER_, NativeTypeTags._ISOLATE_);
 90    }
 91	
 92	// contract with NATNumeric
 93	protected double getJavaValue() { return javaValue; }
 94	
 95	public int hashCode() { return javaValue; }
 96	
 97	/* -----------------------------------
 98	 * - base-level interface to numbers -
 99	 * ----------------------------------- */
100	
101	// iteration constructs
102	
103	/**
104	 * NBR(n).doTimes: { |i| code } => for i = 1 to n do code.eval(i) ; nil
105	 */
106	public ATNil base_doTimes_(ATClosure code) throws InterpreterException {
107		for (int i = 1; i <= javaValue; i++) {
108			code.base_apply(NATTable.atValue(new ATObject[] { NATNumber.atValue(i) }));
109		}
110		return Evaluator.getNil();
111	}
112	
113	/**
114	 * NBR(start).to: NBR(stop) do: { |i| code } => for i = start to stop do code.eval(i) ; nil
115	 * Also works if stop > start, in which case it becomes a downTo.
116	 * 
117	 * If start = stop, the code is not executed.
118	 */
119	public ATNil base_to_do_(ATNumber end, ATClosure code) throws InterpreterException {
120		return this.base_to_step_do_(end, NATNumber.ONE, code);
121	}
122	
123	/**
124	 * NBR(start).to: NBR(stop) step: NBR(inc) do: { |i| code } =>
125	 *   for i = start; i < stop; i++ do code.eval(i) ; nil
126	 * Also works if stop > start, in which case it becomes a downTo.
127	 */
128	public ATNil base_to_step_do_(ATNumber end, ATNumber inc, ATClosure code) throws InterpreterException {
129		int stop = end.asNativeNumber().javaValue;
130		int step = inc.asNativeNumber().javaValue;
131		int start = javaValue;
132		if (start > stop) {
133			for (int i = start; i > stop; i -= step) {
134				code.base_apply(NATTable.atValue(new ATObject[] { NATNumber.atValue(i) }));
135			}
136		} else {
137			for (int i = start; i < stop; i+= step) {
138				code.base_apply(NATTable.atValue(new ATObject[] { NATNumber.atValue(i) }));
139			}
140		}
141		return Evaluator.getNil();
142	}
143	
144	/**
145	 * NBR(start) ** NBR(stop) => [ start, ..., stop [
146	 * 
147	 * Example:
148	 *  2 ** 5 => [ 2, 3, 4 ]
149	 *  5 ** 2 => [ 5, 4, 3 ]
150	 */
151	public ATTable base__optms__optms_(ATNumber end) throws InterpreterException {
152		int stop = end.asNativeNumber().javaValue;
153		int start = javaValue;
154		if (start < stop) {
155			ATObject[] tbl = new ATObject[stop - start];
156			for (int i = 0; i < tbl.length; i++) {
157				tbl[i] = NATNumber.atValue(start + i);
158			}
159			return NATTable.atValue(tbl);
160		} else {
161			ATObject[] tbl = new ATObject[start - stop];
162			for (int i = 0; i < tbl.length; i++) {
163				tbl[i] = NATNumber.atValue(start - i);
164			}
165			return NATTable.atValue(tbl);
166		}
167	}
168	
169	/**
170	 * NBR(start) *** NBR(stop) => [ start, ..., stop ]
171	 * 
172	 * Example:
173	 *  2 *** 5 => [ 2, 3, 4, 5 ]
174	 *  5 *** 2 => [ 5, 4, 3, 2 ]
175	 */
176	public ATTable base__optms__optms__optms_(ATNumber end) throws InterpreterException {
177		// x *** y == x ** y+1 iff x < y
178		// x *** y == x ** y-1 iff y > x
179		int stop = end.asNativeNumber().javaValue;
180		if (javaValue <= stop)
181		    return this.base__optms__optms_(end.base_inc().asNumber());
182		else
183			return this.base__optms__optms_(end.base_dec().asNumber());
184	}
185
186	// Number arithmetic operations
187	
188	/**
189	 * NBR(n).inc() => NBR(n+1)
190	 */
191	public ATNumber base_inc() {
192		return NATNumber.atValue(javaValue+1);
193	}
194	
195	/**
196	 * NBR(n).dec() => NBR(n-1)
197	 */
198	public ATNumber base_dec() {
199		return NATNumber.atValue(javaValue-1);
200	}
201	
202	/**
203	 * NBR(n).abs() => NBR(abs(n))
204	 */
205	public ATNumber base_abs() {
206		return NATNumber.atValue(Math.abs(javaValue));
207	}
208	
209	public ATNumber base_ceiling() throws InterpreterException {
210		return this;
211	}
212
213	public ATNumber base_floor() throws InterpreterException {
214		return this;
215	}
216
217	public ATNumber base_round() throws InterpreterException {
218		return this;
219	}
220
221	/**
222	 * NBR(start) ?? NBR(stop) => FRC(n) where n chosen randomly in [ start, stop [
223	 */
224	public ATFraction base__opque__opque_(ATNumber nbr) throws InterpreterException {
225		int stop = nbr.asNativeNumber().javaValue;
226		double rnd = Math.random(); // 0 <= rnd < 1.0
227		double frc = (rnd * (stop - javaValue)) + javaValue;
228		return NATFraction.atValue(frc);
229	}
230	
231	/**
232	 * NBR(n) % NBR(r) => NBR(n % r)
233	 */
234	public ATNumber base__oprem_(ATNumber n) throws InterpreterException {
235		return NATNumber.atValue(javaValue % n.asNativeNumber().javaValue);
236	}
237	
238	/**
239	 * NBR(n) /- NBR(d) => NBR(n / d)
240	 */
241	public ATNumber base__opdiv__opmns_(ATNumber n) throws InterpreterException {
242		return NATNumber.atValue(javaValue / n.asNativeNumber().javaValue);
243	}
244	
245	// Numeric arithmetic operations
246	
247	// addition +
248	public ATNumeric base__oppls_(ATNumeric other) throws InterpreterException {
249		return other.base_addNumber(this);
250	}
251	public ATNumeric base_addNumber(ATNumber other) throws InterpreterException {
252		return NATNumber.atValue(other.asNativeNumber().javaValue + javaValue);
253	}
254	public ATNumeric base_addFraction(ATFraction other) throws InterpreterException {
255		return NATFraction.atValue(other.asNativeFraction().javaValue + javaValue);
256	}
257	
258	// subtraction -
259	public ATNumeric base__opmns_(ATNumeric other) throws InterpreterException {
260		return other.base_subtractNumber(this);
261	}
262	public ATNumeric base_subtractNumber(ATNumber other) throws InterpreterException {
263		return NATNumber.atValue(other.asNativeNumber().javaValue - javaValue);
264	}
265	public ATNumeric base_subtractFraction(ATFraction other) throws InterpreterException {
266		return NATFraction.atValue(other.asNativeFraction().javaValue - javaValue);
267	}
268	
269	// multiplication *
270	public ATNumeric base__optms_(ATNumeric other) throws InterpreterException {
271		return other.base_timesNumber(this);
272	}
273	public ATNumeric base_timesNumber(ATNumber other) throws InterpreterException {
274		return NATNumber.atValue(other.asNativeNumber().javaValue * javaValue);
275	}
276	public ATNumeric base_timesFraction(ATFraction other) throws InterpreterException {
277		return NATFraction.atValue(other.asNativeFraction().javaValue * javaValue);
278	}
279	
280	// division /
281	public ATNumeric base__opdiv_(ATNumeric other) throws InterpreterException {
282		return other.base_divideNumber(this);
283	}
284	public ATNumeric base_divideNumber(ATNumber other) throws InterpreterException {
285		if (javaValue == 0)
286			throw new XIllegalArgument("Division by zero: " + other);
287		return NATFraction.atValue((other.asNativeNumber().javaValue * 1.0) / javaValue);
288	}
289	public ATNumeric base_divideFraction(ATFraction other) throws InterpreterException {
290		if (javaValue == 0)
291			throw new XIllegalArgument("Division by zero: " + other);
292		return NATFraction.atValue(other.asNativeFraction().javaValue / javaValue);
293	}
294	
295	// comparison: generalized equality <=>
296	public ATNumeric base__opltx__opeql__opgtx_(ATNumeric other) throws InterpreterException {
297		return other.base_gequalsNumber(this);
298	}
299	public ATNumeric base_gequalsNumber(ATNumber other) throws InterpreterException {
300		int n = other.asNativeNumber().javaValue;
301		if (n < javaValue) {
302			return NATNumber.MONE; // -1
303		} else if (n > javaValue) {
304			return NATNumber.ONE;  // +1
305		} else {
306			return NATNumber.ZERO; // 0
307		}
308	}
309	public ATNumeric base_gequalsFraction(ATFraction other) throws InterpreterException {
310		double n = other.asNativeFraction().javaValue;
311		if (n < javaValue) {
312			return NATNumber.MONE; // -1
313		} else if (n > javaValue) {
314			return NATNumber.ONE;  // +1
315		} else {
316			return NATNumber.ZERO; // 0
317		}
318	}
319	
320}