PageRenderTime 63ms CodeModel.GetById 14ms app.highlight 44ms RepoModel.GetById 2ms app.codeStats 0ms

/interpreter/tags/at2dist110511/src/edu/vub/at/objects/natives/NATNumeric.java

http://ambienttalk.googlecode.com/
Java | 287 lines | 175 code | 21 blank | 91 comment | 6 complexity | 1836fc5b2b585bfdf6c06973d4c79bb3 MD5 | raw file
  1/**
  2 * AmbientTalk/2 Project
  3 * NATNumeric.java created on 18-aug-2006 at 11:06:11
  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 java.util.HashMap;
 31
 32import edu.vub.at.exceptions.InterpreterException;
 33import edu.vub.at.exceptions.XTypeMismatch;
 34import edu.vub.at.objects.ATBoolean;
 35import edu.vub.at.objects.ATContext;
 36import edu.vub.at.objects.ATFraction;
 37import edu.vub.at.objects.ATMethod;
 38import edu.vub.at.objects.ATNumeric;
 39import edu.vub.at.objects.ATObject;
 40import edu.vub.at.objects.ATTable;
 41import edu.vub.at.objects.ATText;
 42import edu.vub.at.objects.coercion.NativeTypeTags;
 43import edu.vub.at.objects.grammar.ATSymbol;
 44import edu.vub.at.objects.mirrors.DirectNativeMethod;
 45import edu.vub.at.objects.natives.grammar.AGExpression;
 46
 47/**
 48 * A common superclass of both numbers and fractions to factor out common base-level behaviour.
 49 * 
 50 * @author tvc
 51 */
 52public abstract class NATNumeric extends AGExpression implements ATNumeric {
 53
 54	/**
 55	 * Template method that should return the value of the underlying number or fraction as a double
 56	 */
 57	protected abstract double getJavaValue();
 58	
 59	public NATNumeric asNativeNumeric() throws XTypeMismatch {
 60		return this;
 61	}
 62	
 63    public ATTable meta_typeTags() throws InterpreterException {
 64    	return NATTable.of(NativeTypeTags._NUMERIC_);
 65    }
 66    
 67    // numbers and fractions are singletons
 68	public ATObject meta_clone() throws InterpreterException {
 69		return this;
 70	}
 71	
 72	// trigonometric functions
 73	
 74	/**
 75	 * NUM(n).cos() => FRC(Math.cos(n))
 76	 */
 77	public ATFraction base_cos() {
 78		return NATFraction.atValue(Math.cos(getJavaValue()));
 79	}
 80	
 81	/**
 82	 * NUM(n).sin() => FRC(Math.sin(n))
 83	 */
 84	public ATFraction base_sin() {
 85		return NATFraction.atValue(Math.sin(getJavaValue()));
 86	}
 87	
 88	/**
 89	 * NUM(n).tan() => FRC(Math.tan(n))
 90	 */
 91	public ATFraction base_tan() {
 92		return NATFraction.atValue(Math.tan(getJavaValue()));
 93	}
 94
 95	/**
 96	 * NUM(n).log() => FRC(log(e,n))
 97	 */
 98	public ATFraction base_log() {
 99		return NATFraction.atValue(Math.log(getJavaValue()));
100	}
101	
102	/**
103	 * NUM(n).sqrt() => FRC(Math.sqrt(n))
104	 */
105	public ATFraction base_sqrt() {
106		return NATFraction.atValue(Math.sqrt(getJavaValue()));
107	}
108	
109	/**
110	 * NUM(n).expt(NUM(e)) => FRC(Math.pow(n,e))
111	 */
112	public ATFraction base_expt(ATNumeric pow) throws InterpreterException {
113		return NATFraction.atValue(Math.pow(getJavaValue(), pow.asNativeNumeric().getJavaValue()));
114	}
115	
116	// Comparable 'mixin' based on <=>
117	
118	/**
119	 * a < b iff (a <=> b) == -1
120	 */
121	public ATBoolean base__opltx_(ATNumeric other) throws InterpreterException {
122		return NATBoolean.atValue(this.base__opltx__opeql__opgtx_(other).equals(NATNumber.MONE));
123	}
124	/**
125	 * a > b iff (a <=> b) == +1
126	 */
127	public ATBoolean base__opgtx_(ATNumeric other) throws InterpreterException {
128		return NATBoolean.atValue(this.base__opltx__opeql__opgtx_(other).equals(NATNumber.ONE));
129	}
130	/**
131	 * a <= b iff (a <=> b) != +1
132	 */
133	public ATBoolean base__opltx__opeql_(ATNumeric other) throws InterpreterException {
134		return NATBoolean.atValue(! this.base__opltx__opeql__opgtx_(other).equals(NATNumber.ONE));
135	}
136	/**
137	 * a >= b iff (a <=> b) != -1
138	 */
139	public ATBoolean base__opgtx__opeql_(ATNumeric other) throws InterpreterException {
140		return NATBoolean.atValue(! this.base__opltx__opeql__opgtx_(other).equals(NATNumber.MONE));
141	}
142	/**
143	 * a = b iff (a <=> b) == 0
144	 */
145	public ATBoolean base__opeql_(ATNumeric other) throws InterpreterException {
146		return NATBoolean.atValue(this.base__opltx__opeql__opgtx_(other).equals(NATNumber.ZERO));
147	}
148	/**
149	 * a != b iff (a <=> b) != 0
150	 */
151	public ATBoolean base__opnot__opeql_(ATObject other) throws InterpreterException {
152		if (other instanceof ATNumeric) {
153			return NATBoolean.atValue(! this.base__opltx__opeql__opgtx_(other.asNativeNumeric()).equals(NATNumber.ZERO));
154		} else {
155			return NATBoolean._TRUE_;
156		}
157	}
158	
159	/**
160	 * This hashmap stores all native methods of native AmbientTalk numerics.
161	 * It is populated when this class is loaded, and shared between all
162	 * AmbientTalk actors on this VM. This is safe, since {@link DirectNativeMethod}
163	 * instances are all immutable.
164	 */
165	private static final HashMap<String, ATMethod> _meths = new HashMap<String, ATMethod>();
166	
167	// initialize NATNumeric methods
168	static {
169		_meths.put("cos", new DirectNativeMethod("cos") {
170			public ATObject base_apply(ATTable args, ATContext ctx) throws InterpreterException {
171				NATNumeric self = ctx.base_receiver().asNativeNumeric();
172				checkArity(args, 0);
173				return self.base_cos();
174			}
175		});
176		_meths.put("sin", new DirectNativeMethod("sin") {
177			public ATObject base_apply(ATTable args, ATContext ctx) throws InterpreterException {
178				NATNumeric self = ctx.base_receiver().asNativeNumeric();
179				checkArity(args, 0);
180				return self.base_sin();
181			}
182		});
183		_meths.put("tan", new DirectNativeMethod("tan") {
184			public ATObject base_apply(ATTable args, ATContext ctx) throws InterpreterException {
185				NATNumeric self = ctx.base_receiver().asNativeNumeric();
186				checkArity(args, 0);
187				return self.base_tan();
188			}
189		});
190		_meths.put("log", new DirectNativeMethod("log") {
191			public ATObject base_apply(ATTable args, ATContext ctx) throws InterpreterException {
192				NATNumeric self = ctx.base_receiver().asNativeNumeric();
193				checkArity(args, 0);
194				return self.base_log();
195			}
196		});
197		_meths.put("sqrt", new DirectNativeMethod("sqrt") {
198			public ATObject base_apply(ATTable args, ATContext ctx) throws InterpreterException {
199				NATNumeric self = ctx.base_receiver().asNativeNumeric();
200				checkArity(args, 0);
201				return self.base_sqrt();
202			}
203		});
204		_meths.put("expt", new DirectNativeMethod("expt") {
205			public ATObject base_apply(ATTable args, ATContext ctx) throws InterpreterException {
206				NATNumeric self = ctx.base_receiver().asNativeNumeric();
207				checkArity(args, 1);
208				NATNumeric pow = get(args, 1).asNativeNumeric();
209				return self.base_expt(pow);
210			}
211		});
212		_meths.put("<", new DirectNativeMethod("<") {
213			public ATObject base_apply(ATTable args, ATContext ctx) throws InterpreterException {
214				NATNumeric self = ctx.base_receiver().asNativeNumeric();
215				checkArity(args, 1);
216				NATNumeric other = get(args, 1).asNativeNumeric();
217				return self.base__opltx_(other);
218			}
219		});
220		_meths.put(">", new DirectNativeMethod(">") {
221			public ATObject base_apply(ATTable args, ATContext ctx) throws InterpreterException {
222				NATNumeric self = ctx.base_receiver().asNativeNumeric();
223				checkArity(args, 1);
224				NATNumeric other = get(args, 1).asNativeNumeric();
225				return self.base__opgtx_(other);
226			}
227		});
228		_meths.put("<=", new DirectNativeMethod("<=") {
229			public ATObject base_apply(ATTable args, ATContext ctx) throws InterpreterException {
230				NATNumeric self = ctx.base_receiver().asNativeNumeric();
231				checkArity(args, 1);
232				NATNumeric other = get(args, 1).asNativeNumeric();
233				return self.base__opltx__opeql_(other);
234			}
235		});
236		_meths.put(">=", new DirectNativeMethod(">=") {
237			public ATObject base_apply(ATTable args, ATContext ctx) throws InterpreterException {
238				NATNumeric self = ctx.base_receiver().asNativeNumeric();
239				checkArity(args, 1);
240				NATNumeric other = get(args, 1).asNativeNumeric();
241				return self.base__opgtx__opeql_(other);
242			}
243		});
244		_meths.put("=", new DirectNativeMethod("=") {
245			public ATObject base_apply(ATTable args, ATContext ctx) throws InterpreterException {
246				NATNumeric self = ctx.base_receiver().asNativeNumeric();
247				checkArity(args, 1);
248				NATNumeric other = get(args, 1).asNativeNumeric();
249				return self.base__opeql_(other);
250			}
251		});
252		_meths.put("!=", new DirectNativeMethod("!=") {
253			public ATObject base_apply(ATTable args, ATContext ctx) throws InterpreterException {
254				NATNumeric self = ctx.base_receiver().asNativeNumeric();
255				checkArity(args, 1);
256				return self.base__opnot__opeql_(get(args, 1));
257			}
258		});
259	}
260	
261	/**
262	 * Overrides the default AmbientTalk native object behavior of extracting native
263	 * methods based on the 'base_' naming convention. Instead, native AT numbers use
264	 * an explicit hashmap of native methods. This is much faster than the default
265	 * behavior, which requires reflection.
266	 */
267	protected boolean hasLocalMethod(ATSymbol atSelector) throws InterpreterException {
268		if  (_meths.containsKey(atSelector.base_text().asNativeText().javaValue)) {
269			return true;
270		} else {
271			return super.hasLocalMethod(atSelector);
272		}
273	}
274	
275	/**
276	 * @see NATNumeric#hasLocalMethod(ATSymbol)
277	 */
278	protected ATMethod getLocalMethod(ATSymbol selector) throws InterpreterException {
279		ATMethod val = _meths.get(selector.base_text().asNativeText().javaValue);
280		if (val == null) {
281			return super.getLocalMethod(selector);
282			//throw new XSelectorNotFound(selector, this);			
283		}
284		return val;
285	}
286
287}