1 /* $Author: hansonr $
2  * $Date: 2007-09-09 21:37:07 -0500 (Sun, 09 Sep 2007) $
3  * $Revision: 8231 $
4  *
5  * Copyright (C) 2002-2005  The Jmol Development Team
6  *
7  * Contact: jmol-developers@lists.sf.net
8  *
9  *  This library is free software; you can redistribute it and/or
10  *  modify it under the terms of the GNU Lesser General Public
11  *  License as published by the Free Software Foundation; either
12  *  version 2.1 of the License, or (at your option) any later version.
13  *
14  *  This library is distributed in the hope that it will be useful,
15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  *  Lesser General Public License for more details.
18  *
19  *  You should have received a copy of the GNU Lesser General Public
20  *  License along with this library; if not, write to the Free Software
21  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
22  */
23 
24 package org.jmol.script;
25 
26 import javajs.util.AU;
27 import javajs.util.Lst;
28 import javajs.util.SB;
29 
30 import java.util.Hashtable;
31 
32 import java.util.Map;
33 
34 import org.jmol.api.JmolScriptFunction;
35 
36 public class ScriptFunction implements JmolScriptFunction {
37 
38   // / functions
39 
40   /**
41    * functions are either local or global (static). The idea there is that a set
42    * of applets might share a set of functions. The default is global; prefix
43    * underscore makes them local.
44    *
45    * functions have contexts. Or, more specifically, contexts may have associated
46    * functions.
47    *
48    * Bob Hanson -- 11.3.29
49    *
50    * includes parallel, catch
51    *
52    */
53 
54   int pt0;
55   int chpt0;
56   int cmdpt0 = -1;
57   protected String typeName;
58   String name;
59   int nParameters;
60   Lst<String> names = new  Lst<String>();
61   int tok;
62 
63   Map<String, String> variables = new Hashtable<String, String>();
isVariable(String ident)64   boolean isVariable(String ident) {
65     return variables.containsKey(ident);
66   }
67 
68   SV returnValue;
69   T[][] aatoken;
70   int[][] lineIndices;
71   short[] lineNumbers;
72   String script;
73 
74   boolean isPrivate;
75 
ScriptFunction()76   public ScriptFunction() {
77     // for reflection with ScriptParallelProcessor
78   }
79 
ScriptFunction(String name, int tok)80   protected ScriptFunction(String name, int tok) {
81     set(name, tok);
82     typeName = T.nameOf(tok);
83   }
84 
set(String name, int tok)85   public void set(String name, int tok) {
86     this.name = name;
87     this.tok = tok;
88   }
89 
setVariables(Map<String, SV> contextVariables, Lst<SV> params)90   void setVariables(Map<String, SV> contextVariables, Lst<SV> params) {
91     int nParams = (params == null ? 0 : params.size());
92     for (int i = names.size(); --i >= 0;) {
93       String name = names.get(i).toLowerCase();
94       SV var = (i < nParameters && i < nParams ? params.get(i) : null);
95       if (var != null && var.tok != T.varray)  // TODO: list type?
96         var = SV.newT(var);
97       contextVariables.put(name, (var == null ?
98           SV.newS("").setName(name) : var));
99     }
100     if (tok != T.trycmd) {
101       contextVariables.put("_argcount", SV.newI(params == null ? 0 : params.size()));
102       contextVariables.put(
103           "_arguments",
104           (params == null ? SV.getVariableAI(new int[] {}) : SV
105               .getVariableList(params)));
106 
107     }
108 
109     contextVariables.put("_retval", SV.newI(tok == T.trycmd ? Integer.MAX_VALUE : 0));
110   }
111 
unsetVariables(Map<String, SV> contextVariables, Lst<SV> params)112   void unsetVariables(Map<String, SV> contextVariables, Lst<SV> params) {
113     // note: this method is never called.
114     // set list values in case they have changed.
115     int nParams = (params == null ? 0 : params.size());
116     int nNames = names.size();
117     if (nParams == 0 || nNames == 0)
118       return;
119     for (int i = 0; i < nNames && i < nParams; i++) {
120       SV global = params.get(i);
121       if (global.tok != T.varray)  // TODO: list type?
122         continue;
123       SV local = contextVariables.get(names.get(i).toLowerCase());
124       if (local.tok != T.varray)  // TODO: list type?
125         continue;
126       global.value = local.value;
127     }
128   }
129 
addVariable(String name, boolean isParameter)130   void addVariable(String name, boolean isParameter) {
131     variables.put(name, name);
132     names.addLast(name);
133     if (isParameter)
134       nParameters++;
135   }
136 
setFunction(ScriptFunction function, String script, int ichCurrentCommand, int pt, short[] lineNumbers, int[][] lineIndices, Lst<T[]> lltoken)137   static void setFunction(ScriptFunction function, String script,
138                           int ichCurrentCommand, int pt, short[] lineNumbers,
139                           int[][] lineIndices, Lst<T[]> lltoken) {
140     int cmdpt0 = function.cmdpt0;
141     int chpt0 = function.chpt0;
142     int nCommands = pt - cmdpt0;
143     function.setScript(script.substring(chpt0, ichCurrentCommand));
144     T[][] aatoken = function.aatoken = new T[nCommands][];
145     function.lineIndices = AU.newInt2(nCommands);
146     function.lineNumbers = new short[nCommands];
147     short line0 = (short) (lineNumbers[cmdpt0] - 1);
148     for (int i = 0; i < nCommands; i++) {
149       function.lineNumbers[i] = (short) (lineNumbers[cmdpt0 + i] - line0);
150       function.lineIndices[i] = new int[] {lineIndices[cmdpt0 + i][0] - chpt0, lineIndices[cmdpt0 + i][1] - chpt0 };
151       //System.out.println("Line " + i + ": " + function.script.substring(function.lineIndices[i][0], function.lineIndices[i][1]));
152       aatoken[i] = lltoken.get(cmdpt0 + i);
153       // adjust intValues, which are pointers into the command stack,
154       // by the 0-point offset of the command pointer
155       // negative less negative;positive less positive
156       if (aatoken[i].length > 0) {
157         T tokenCommand = aatoken[i][0];
158         if (T.tokAttr(tokenCommand.tok, T.flowCommand))
159           tokenCommand.intValue -= (tokenCommand.intValue < 0 ? -cmdpt0
160               : cmdpt0);
161       }
162     }
163     for (int i = pt; --i >= cmdpt0;) {
164       lltoken.removeItemAt(i);
165       lineIndices[i][0] = lineIndices[i][1] = 0;
166     }
167   }
168 
setScript(String s)169   private void setScript(String s) {
170     script = s;
171     if (script != null && script != "" && !script.endsWith("\n"))
172       script += "\n";
173   }
174 
175   @Override
toString()176   public String toString() {
177     SB s = new SB().append("/*\n * ").append(name)
178         .append("\n */\n").append(getSignature()).append(" {\n");
179     if (script != null)
180       s.append(script);
181     s.append("}\n");
182     return s.toString();
183   }
184 
185   @Override
getSignature()186   public String getSignature() {
187     if (typeName == null)
188       return T.nameOf(tok);
189     SB s = new SB().append(typeName)
190       .append(" ").append(name).append("(");
191     for (int i = 0; i < nParameters; i++) {
192       if (i > 0)
193         s.append(", ");
194       s.append(names.get(i));
195     }
196     s.append(")");
197     return s.toString();
198   }
199 
200   @Override
geTokens()201   public Object geTokens() {
202     return aatoken;
203   }
204 
205   @Override
getName()206   public String getName() {
207     return name;
208   }
209 
210   @Override
getTok()211   public int getTok() {
212     return tok;
213   }
214 }
215