Back to index

wims  3.65+svn20090927
Symbols.java
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2008 Mihai Preda.
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *      http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 
00017 package org.javia.arity;
00018 
00019 import java.util.Hashtable;
00020 import java.util.Stack;
00021 import java.util.Vector;
00022 
00056 public class Symbols {
00060     public Symbols() {
00061         for (int i = 0; i < builtin.length; ++i) {
00062             Symbol s = builtin[i];
00063             symbols.put(s, s);
00064         }
00065         try {
00066             for (int i = 0; i < defines.length; ++i) {
00067                 define(compile(defines[i]));
00068             }
00069         } catch (SyntaxException e) {
00070             throw new Error(""+e); //never
00071         }
00072     }
00073 
00080     public static boolean isDefinition(String source) {
00081         return source.indexOf('=') != -1;
00082     }
00083 
00093     public synchronized double eval(String expression) throws SyntaxException {
00094         return getCompiler().eval(this, expression);
00095     }
00096 
00123     public synchronized FunctionAndName compile(String source) throws SyntaxException {
00124         return getCompiler().compile(this, source);
00125     }
00126 
00132     synchronized public void define(String name, Function function) {
00133         if (function instanceof Constant) {            
00134             addConstant(name, ((Constant) function).eval());
00135         } else {
00136             add(new Symbol(name, function));
00137         }
00138     }
00139 
00144     synchronized public void define(FunctionAndName funAndName) {
00145         if (funAndName.name != null) {
00146             define(funAndName.name, funAndName.function);
00147         }
00148     }
00149     
00150 
00156     synchronized public void addConstant(String name, double value) {
00157         add(new Symbol(name, value));
00158     }
00159 
00166     synchronized public void pushFrame() {
00167         frames.push(delta);
00168         delta = null;
00169     }
00170 
00177     synchronized public void popFrame() {
00178         if (delta != null) {
00179             for (int i = delta.size() - 1; i >= 0; --i) {
00180                 Symbol previous = (Symbol) delta.elementAt(i);
00181                 if (previous.isEmpty()) {
00182                     symbols.remove(previous);
00183                 } else {
00184                     symbols.put(previous, previous);
00185                 }
00186             }
00187         }
00188         delta = (Vector) frames.pop();
00189     }
00190 
00191 
00192 
00193     //--- non-public below
00194 
00195     private final static Symbol builtin[];
00196     private static Symbol shell = new Symbol(null, 0);
00197     private static ThreadLocal compilers = new ThreadLocal();
00198     
00199     private static Compiler getCompiler() {
00200         Compiler compiler;
00201         if ((compiler = (Compiler) compilers.get()) == null) {
00202             compilers.set(compiler = new Compiler());
00203         }
00204         return compiler;
00205     }
00206 
00207     private Hashtable symbols = new Hashtable(); //Hashtable<Symbol, Symbol>
00208     private Vector delta = null;                 //Vector<Symbol>
00209     private Stack frames = new Stack();          //Stack<Vector>
00210 
00211     static {
00212         Vector vect = new Vector();
00213         int arity;
00214         for (byte i = 0; i < VM.BYTECODE_END; ++i) {
00215             if ((arity = VM.builtinArity[i]) >= 0) {
00216                 vect.addElement(new Symbol(VM.opcodeName[i], arity, i));
00217             }
00218         }
00219 
00220         final String IMPLICIT_ARGS[] = {"x", "y", "z"};
00221         for (byte i = 0; i < IMPLICIT_ARGS.length; ++i) {
00222             vect.addElement(new Symbol(IMPLICIT_ARGS[i], Symbol.CONST_ARITY, (byte)(VM.LOAD0 + i)));
00223         }
00224 
00225         vect.addElement(new Symbol("pi", Math.PI));
00226         vect.addElement(new Symbol("\u03c0", Math.PI));
00227         vect.addElement(new Symbol("e", Math.E));
00228 
00229         vect.addElement(new Symbol("Inf", Double.POSITIVE_INFINITY));
00230         vect.addElement(new Symbol("Infinity", Double.POSITIVE_INFINITY));
00231         vect.addElement(new Symbol("NaN", Double.NaN));
00232 
00233         int size = vect.size();
00234         builtin = new Symbol[size];
00235         vect.copyInto(builtin);
00236     }
00237 
00238     private static final String defines[] = {
00239         "ln(x)    = log(x)",
00240         "log2(x)  = log(x) * 1.4426950408889634074",  //*log2(e)
00241         "log10(x) = log(x) * 0.43429448190325182765", //*log10(e)
00242         "lg(x)    = log10(x)",
00243         "lb(x)    = log2(x)",
00244         "log(x, base) = log(x) / log(base)"
00245     };
00246     
00247     void addArguments(String args[]) {
00248         for (int i = 0; i < args.length; ++i) {
00249             add(new Symbol(args[i], Symbol.CONST_ARITY, (byte)(VM.LOAD0 + i)));
00250         }
00251     }
00252 
00253     void add(Symbol s) {
00254         Object previous = symbols.put(s, s);
00255         if (delta == null) {
00256             delta = new Vector();
00257         }
00258         delta.addElement(previous != null ? previous : Symbol.newEmpty(s));
00259     }
00260 
00261     synchronized Symbol lookup(String name, int arity) {
00262         return (Symbol) symbols.get(shell.setKey(name, arity));
00263     }
00264 }