Source code: com/voytechs/jnetstream/npl/ArrayDimensionNode.java
1 /*
2 * File: ArrayDimensionNode.java
3 * Auth: Mark Bednarczyk
4 * Date: DATE
5 * Id: $Id: ArrayDimensionNode.java,v 1.1.1.1 2003/09/22 16:32:20 voytechs Exp $
6 ********************************************
7 Copyright (C) 2003 Mark Bednarczyk
8
9 This program is free software; you can redistribute it and/or
10 modify it under the terms of the GNU General Public License
11 as published by the Free Software Foundation; either version 2
12 of the License, or (at your option) any later version.
13
14 This program 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
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 ********************************************
23 * $Log: ArrayDimensionNode.java,v $
24 * Revision 1.1.1.1 2003/09/22 16:32:20 voytechs
25 * Initial import.
26 *
27 */
28 package com.voytechs.jnetstream.npl;
29
30 import java.lang.*;
31 import java.util.*;
32
33 /**
34 * Support class that allows muti-dimensional array manipulation.
35 * Since array references can have dynamic code associated with array lookup,
36 * a number of convenience functions are performed by the class.
37 * 1) Bounds checking for MAX and MIN bounds for all dimensions.
38 * 2) Node traversal for each dimension
39 * 3) Scalar array size computation which also needs to be done at run time
40 * because of dynamic code.
41 */
42 public class ArrayDimensionNode
43 extends NodeList {
44
45 /* Internal attributes */
46 private static final boolean debug = false;
47
48 private boolean constantDimension = false;
49 private int scalarSize = -1; // Indicates we haven't initialized yet.
50
51 /**
52 *
53 * @param
54 * @exception
55 */
56 public ArrayDimensionNode() {
57 }
58
59
60 /**
61 * Returns the scalar equivelent value of the entire array.
62 * Since the value has to be evaluated dynamically, there some caching of the
63 * value is done to improve performance.
64 */
65 public int toScalar(ArrayDimensionNode dim)
66 throws NodeException {
67
68 if(constantDimension) {
69 if(scalarSize == -1)
70 scalarSize = calculateScalarSize(this, dim);
71
72 return(scalarSize);
73 }
74
75 return(calculateScalarSize(this, dim));
76 }
77
78 public int toScalar()
79 throws NodeException {
80
81 return(calculateArraySize());
82 }
83
84
85 /**
86 * Calculates the scalar dimension of the entire array. This is how many
87 * elements the array takes overall.
88 *
89 * @param max Maximim multidimensional boundaries of the array.
90 * @param dim the value to convert to scalar based on max as the array sizes.
91 */
92 public int calculateScalarSize(ArrayDimensionNode dim) throws NodeException { return(calculateScalarSize(this, dim)); }
93 protected static int calculateScalarSize(ArrayDimensionNode max, ArrayDimensionNode dim)
94 throws NodeException {
95
96 if(max.size() != dim.size())
97 throw new NodeException("Array sizes don't match. Can not compute Scalar size.", max);
98
99 int s = 0;
100 int m = 1;
101
102 for(int i = dim.size() -1; i >= 0; i --) {
103 s += m * dim.getInt(i);
104 m *= max.getInt(i);
105 }
106
107 return(s);
108 }
109
110 public int calculateArraySize() throws NodeException { return(calculateArraySize(this, 0)); }
111 protected static int calculateArraySize(ArrayDimensionNode max, int level)
112 throws NodeException {
113
114 int s = 1;
115 for(int i = level; i < max.size(); i ++)
116 s *= max.getInt(i);
117
118 return(s);
119 }
120
121 public String createLabel(int scalar)
122 throws NodeException {
123
124 String q = "";
125 int r = 0;
126
127 for(int i = 1; i < size(); i ++) {
128
129 r = scalar / calculateArraySize(this, i);
130
131 scalar -= r * calculateArraySize(this, i);
132
133
134 q += "[" + r + "]";
135 }
136
137 q += "[" + scalar + "]";
138
139 return(q);
140 }
141
142
143 /**
144 * Checks that "dim" is within allocated limits of the array dimension.
145 *
146 * @return true if within limits, false if not.
147 * @exception NodeException since we are also excecuting dynamic expression code.
148 */
149 public boolean checkBoundary(ArrayDimensionNode dim)
150 throws NodeException {
151
152 if(size() != dim.size())
153 return(false);
154
155 /**
156 * Now compare each element of the dimension and make sure we
157 * always bigger. For Array dereferencing, we should be the Reference
158 * with static IntNode() object for each dimension. This should be taken
159 * care of by the Interpreter. The linker is not able to execute dynamic code
160 * at this point to calculate the static array sizes.
161 */
162 for(int i = 0; i < size(); i ++) {
163 if(getInt(i) <= dim.getInt(i))
164 return(false);
165 }
166
167 return(true);
168 }
169
170 /**
171 * This method evaluates the code to its NodeInt equivelent and
172 * creates a new Dimension object with static values. This is needed
173 * for when arrays are first instantiated, the dynamic code can only be
174 * run once, otherwise array dimensions could suddenly change on us.
175 * Make sure this method is called only when all the reference have been resolved
176 * and context loaded with primitives. Otherwise an NodeException will be thrown if
177 * references can not be properly dereferenced.
178 *
179 * @exception NodeException if reference(s) can not be derefereced to a primitive. Becarefull when
180 * evaluating in linkers and such where the dynamic runtime structures aren't ready yet. Can use the
181 * canOptimize() function. If top level node can be optimized, this usually means that there are no
182 * references in the code to be evaluated.
183 */
184 public ArrayDimensionNode evaluateToStatic()
185 throws NodeException {
186 ArrayDimensionNode dim = new ArrayDimensionNode();
187
188 for(int i = 0; i < size(); i ++) {
189 dim.add(new IntNodeImpl(getInt(i)));
190 }
191
192 dim.constantDimension = true;
193
194 return(dim);
195 }
196
197 /**
198 * Test function for ArrayDimensionNode
199 * @param args command line arguments
200 */
201 public static void main(String [] args) {
202
203 ArrayDimensionNode max = new ArrayDimensionNode();
204 max.add(new IntNodeImpl(3));
205 max.add(new IntNodeImpl(4));
206 max.add(new IntNodeImpl(5));
207
208 ArrayDimensionNode dim = new ArrayDimensionNode();
209 dim.add(new IntNodeImpl(2));
210 dim.add(new IntNodeImpl(3));
211 dim.add(new IntNodeImpl(20));
212
213 try {
214 System.out.println("max=" + max.calculateArraySize());
215 System.out.println("dim=" + ArrayDimensionNode.calculateScalarSize(max, dim));
216
217 for(int i = 0; i < max.toScalar(); i ++) {
218 System.out.println("dim.label=" + max.createLabel(i));
219 }
220 }
221 catch(NodeException ne) {
222 ne.printStackTrace();
223 }
224 }
225
226 } /* END OF: ArrayDimensionNode */