PageRenderTime 34ms CodeModel.GetById 15ms app.highlight 15ms RepoModel.GetById 2ms app.codeStats 0ms

/interpreter/tags/at2-build270707/src/edu/vub/at/objects/natives/NATNumber.java

http://ambienttalk.googlecode.com/
Java | 304 lines | 173 code | 34 blank | 97 comment | 23 complexity | 563103623e7d9ec9fdc01f63ff318241 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.exceptions.InterpreterException;
 31import edu.vub.at.exceptions.XIllegalArgument;
 32import edu.vub.at.exceptions.XTypeMismatch;
 33import edu.vub.at.objects.ATBoolean;
 34import edu.vub.at.objects.ATClosure;
 35import edu.vub.at.objects.ATFraction;
 36import edu.vub.at.objects.ATNil;
 37import edu.vub.at.objects.ATNumber;
 38import edu.vub.at.objects.ATNumeric;
 39import edu.vub.at.objects.ATObject;
 40import edu.vub.at.objects.ATTable;
 41import edu.vub.at.objects.coercion.NativeTypeTags;
 42
 43/**
 44 * The native implementation of an AmbientTalk number.
 45 * A number is implemented by a Java int.
 46 * 
 47 * @author smostinc
 48 */
 49public final class NATNumber extends NATNumeric implements ATNumber {
 50	
 51	public static final NATNumber ZERO = new NATNumber(0);
 52	public static final NATNumber ONE = new NATNumber(1);
 53	public static final NATNumber MONE = new NATNumber(-1);
 54	
 55	public final int javaValue;
 56	
 57	/**
 58	 * This method currently serves as a hook for number creation.
 59	 * Currently number objects are not reused, but this might change in the future.
 60	 */
 61	public static final NATNumber atValue(int javaNumber) {
 62		return new NATNumber(javaNumber);
 63	}
 64	
 65	private NATNumber(int javaNumber) {
 66		javaValue = javaNumber;
 67	}
 68
 69    public ATBoolean base__opeql__opeql_(ATObject comparand) {
 70		return NATBoolean.atValue(this.equals(comparand));
 71    }
 72	
 73    public boolean equals(Object comparand) {
 74		return (comparand instanceof NATNumber) &&
 75		       (javaValue == ((NATNumber) comparand).javaValue);
 76    }
 77	
 78	public ATNumber asNumber() throws XTypeMismatch { return this; }
 79	
 80	public NATNumber asNativeNumber() { return this; }
 81	
 82	public NATText meta_print() throws InterpreterException {
 83        return NATText.atValue(String.valueOf(javaValue));
 84	}
 85	
 86    public ATTable meta_typeTags() throws InterpreterException {
 87    	return NATTable.of(NativeTypeTags._NUMBER_, NativeTypeTags._ISOLATE_);
 88    }
 89	
 90	// contract with NATNumeric
 91	protected double getJavaValue() { return javaValue; }
 92	
 93	/* -----------------------------------
 94	 * - base-level interface to numbers -
 95	 * ----------------------------------- */
 96	
 97	// iteration constructs
 98	
 99	/**
100	 * NBR(n).doTimes: { |i| code } => for i = 1 to n do code.eval(i) ; nil
101	 */
102	public ATNil base_doTimes_(ATClosure code) throws InterpreterException {
103		for (int i = 1; i <= javaValue; i++) {
104			code.base_apply(NATTable.atValue(new ATObject[] { NATNumber.atValue(i) }));
105		}
106		return OBJNil._INSTANCE_;
107	}
108	
109	/**
110	 * NBR(start).to: NBR(stop) do: { |i| code } => for i = start to stop do code.eval(i) ; nil
111	 * Also works if stop > start, in which case it becomes a downTo.
112	 * 
113	 * If start = stop, the code is not executed.
114	 */
115	public ATNil base_to_do_(ATNumber end, ATClosure code) throws InterpreterException {
116		return this.base_to_step_do_(end, NATNumber.ONE, code);
117	}
118	
119	/**
120	 * NBR(start).to: NBR(stop) step: NBR(inc) do: { |i| code } =>
121	 *   for i = start; i < stop; i++ do code.eval(i) ; nil
122	 * Also works if stop > start, in which case it becomes a downTo.
123	 */
124	public ATNil base_to_step_do_(ATNumber end, ATNumber inc, ATClosure code) throws InterpreterException {
125		int stop = end.asNativeNumber().javaValue;
126		int step = inc.asNativeNumber().javaValue;
127		int start = javaValue;
128		if (start > stop) {
129			for (int i = start; i > stop; i -= step) {
130				code.base_apply(NATTable.atValue(new ATObject[] { NATNumber.atValue(i) }));
131			}
132		} else {
133			for (int i = start; i < stop; i+= step) {
134				code.base_apply(NATTable.atValue(new ATObject[] { NATNumber.atValue(i) }));
135			}
136		}
137		return OBJNil._INSTANCE_;
138	}
139	
140	/**
141	 * NBR(start) ** NBR(stop) => [ start, ..., stop [
142	 * 
143	 * Example:
144	 *  2 ** 5 => [ 2, 3, 4 ]
145	 *  5 ** 2 => [ 5, 4, 3 ]
146	 */
147	public ATTable base__optms__optms_(ATNumber end) throws InterpreterException {
148		int stop = end.asNativeNumber().javaValue;
149		int start = javaValue;
150		if (start < stop) {
151			ATObject[] tbl = new ATObject[stop - start];
152			for (int i = 0; i < tbl.length; i++) {
153				tbl[i] = NATNumber.atValue(start + i);
154			}
155			return NATTable.atValue(tbl);
156		} else {
157			ATObject[] tbl = new ATObject[start - stop];
158			for (int i = 0; i < tbl.length; i++) {
159				tbl[i] = NATNumber.atValue(start - i);
160			}
161			return NATTable.atValue(tbl);
162		}
163	}
164	
165	/**
166	 * NBR(start) *** NBR(stop) => [ start, ..., stop ]
167	 * 
168	 * Example:
169	 *  2 *** 5 => [ 2, 3, 4, 5 ]
170	 *  5 *** 2 => [ 5, 4, 3, 2 ]
171	 */
172	public ATTable base__optms__optms__optms_(ATNumber end) throws InterpreterException {
173		// x *** y == x ** y+1 iff x < y
174		// x *** y == x ** y-1 iff y > x
175		int stop = end.asNativeNumber().javaValue;
176		if (javaValue <= stop)
177		    return this.base__optms__optms_(end.base_inc().asNumber());
178		else
179			return this.base__optms__optms_(end.base_dec().asNumber());
180	}
181
182	// Number arithmetic operations
183	
184	/**
185	 * NBR(n).inc() => NBR(n+1)
186	 */
187	public ATNumber base_inc() {
188		return NATNumber.atValue(javaValue+1);
189	}
190	
191	/**
192	 * NBR(n).dec() => NBR(n-1)
193	 */
194	public ATNumber base_dec() {
195		return NATNumber.atValue(javaValue-1);
196	}
197	
198	/**
199	 * NBR(n).abs() => NBR(abs(n))
200	 */
201	public ATNumber base_abs() {
202		return NATNumber.atValue(Math.abs(javaValue));
203	}
204	
205	/**
206	 * NBR(start) ?? NBR(stop) => FRC(n) where n chosen randomly in [ start, stop [
207	 */
208	public ATFraction base__opque__opque_(ATNumber nbr) throws InterpreterException {
209		int stop = nbr.asNativeNumber().javaValue;
210		double rnd = Math.random(); // 0 <= rnd < 1.0
211		double frc = (rnd * (stop - javaValue)) + javaValue;
212		return NATFraction.atValue(frc);
213	}
214	
215	/**
216	 * NBR(n) % NBR(r) => NBR(n % r)
217	 */
218	public ATNumber base__oprem_(ATNumber n) throws InterpreterException {
219		return NATNumber.atValue(javaValue % n.asNativeNumber().javaValue);
220	}
221	
222	/**
223	 * NBR(n) /- NBR(d) => NBR(n / d)
224	 */
225	public ATNumber base__opdiv__opmns_(ATNumber n) throws InterpreterException {
226		return NATNumber.atValue(javaValue / n.asNativeNumber().javaValue);
227	}
228	
229	// Numeric arithmetic operations
230	
231	// addition +
232	public ATNumeric base__oppls_(ATNumeric other) throws InterpreterException {
233		return other.base_addNumber(this);
234	}
235	public ATNumeric base_addNumber(ATNumber other) throws InterpreterException {
236		return NATNumber.atValue(other.asNativeNumber().javaValue + javaValue);
237	}
238	public ATNumeric base_addFraction(ATFraction other) throws InterpreterException {
239		return NATFraction.atValue(other.asNativeFraction().javaValue + javaValue);
240	}
241	
242	// subtraction -
243	public ATNumeric base__opmns_(ATNumeric other) throws InterpreterException {
244		return other.base_subtractNumber(this);
245	}
246	public ATNumeric base_subtractNumber(ATNumber other) throws InterpreterException {
247		return NATNumber.atValue(other.asNativeNumber().javaValue - javaValue);
248	}
249	public ATNumeric base_subtractFraction(ATFraction other) throws InterpreterException {
250		return NATFraction.atValue(other.asNativeFraction().javaValue - javaValue);
251	}
252	
253	// multiplication *
254	public ATNumeric base__optms_(ATNumeric other) throws InterpreterException {
255		return other.base_timesNumber(this);
256	}
257	public ATNumeric base_timesNumber(ATNumber other) throws InterpreterException {
258		return NATNumber.atValue(other.asNativeNumber().javaValue * javaValue);
259	}
260	public ATNumeric base_timesFraction(ATFraction other) throws InterpreterException {
261		return NATFraction.atValue(other.asNativeFraction().javaValue * javaValue);
262	}
263	
264	// division /
265	public ATNumeric base__opdiv_(ATNumeric other) throws InterpreterException {
266		return other.base_divideNumber(this);
267	}
268	public ATNumeric base_divideNumber(ATNumber other) throws InterpreterException {
269		if (javaValue == 0)
270			throw new XIllegalArgument("Division by zero: " + other);
271		return NATFraction.atValue((other.asNativeNumber().javaValue * 1.0) / javaValue);
272	}
273	public ATNumeric base_divideFraction(ATFraction other) throws InterpreterException {
274		if (javaValue == 0)
275			throw new XIllegalArgument("Division by zero: " + other);
276		return NATFraction.atValue(other.asNativeFraction().javaValue / javaValue);
277	}
278	
279	// comparison: generalized equality <=>
280	public ATNumeric base__opltx__opeql__opgtx_(ATNumeric other) throws InterpreterException {
281		return other.base_gequalsNumber(this);
282	}
283	public ATNumeric base_gequalsNumber(ATNumber other) throws InterpreterException {
284		int n = other.asNativeNumber().javaValue;
285		if (n < javaValue) {
286			return NATNumber.MONE; // -1
287		} else if (n > javaValue) {
288			return NATNumber.ONE;  // +1
289		} else {
290			return NATNumber.ZERO; // 0
291		}
292	}
293	public ATNumeric base_gequalsFraction(ATFraction other) throws InterpreterException {
294		double n = other.asNativeFraction().javaValue;
295		if (n < javaValue) {
296			return NATNumber.MONE; // -1
297		} else if (n > javaValue) {
298			return NATNumber.ONE;  // +1
299		} else {
300			return NATNumber.ZERO; // 0
301		}
302	}
303	
304}