New Lua functions
[jpcrr.git] / mnj / lua / Proto.java
blob4d331015ade0f81e87f8a7b14651e1c0cde4fc7d
1 /* $Header: //info.ravenbrook.com/project/jili/version/1.1/code/mnj/lua/Proto.java#1 $
2 * Copyright (c) 2006 Nokia Corporation and/or its subsidiary(-ies).
3 * All rights reserved.
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject
11 * to the following conditions:
13 * The above copyright notice and this permission notice shall be
14 * included in all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
20 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
21 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 package mnj.lua;
27 /**
28 * Models a function prototype. This class is internal to Jill and
29 * should not be used by clients. This is the analogue of the PUC-Rio
30 * type <code>Proto</code>, hence the name.
31 * A function prototype represents the constant part of a function, that
32 * is, a function without closures (upvalues) and without an
33 * environment. It's a handle for a block of VM instructions and
34 * ancillary constants.
36 * For convenience some private arrays are exposed. Modifying these
37 * arrays is punishable by death. (Java has no convenient constant
38 * array datatype)
40 final class Proto
42 /** Interned 0-element array. */
43 private static final int[] ZERO_INT_ARRAY = new int[0];
44 private static final LocVar[] ZERO_LOCVAR_ARRAY = new LocVar[0];
45 private static final Slot[] ZERO_CONSTANT_ARRAY = new Slot[0];
46 private static final Proto[] ZERO_PROTO_ARRAY = new Proto[0];
47 private static final String[] ZERO_STRING_ARRAY = new String[0];
49 // Generally the fields are named following the PUC-Rio implementation
50 // and so are unusually terse.
51 /** Array of constants. */
52 Slot[] k;
53 int sizek;
54 /** Array of VM instructions. */
55 int[] code;
56 int sizecode;
57 /** Array of Proto objects. */
58 Proto[] p;
59 int sizep;
60 /**
61 * Number of upvalues used by this prototype (and so by all the
62 * functions created from this Proto).
64 int nups;
65 /**
66 * Number of formal parameters used by this prototype, and so the
67 * number of argument received by a function created from this Proto.
68 * In a function defined to be variadic then this is the number of
69 * fixed parameters, the number appearing before '...' in the parameter
70 * list.
72 int numparams;
73 /**
74 * <code>true</code> if and only if the function is variadic, that is,
75 * defined with '...' in its parameter list.
77 boolean isVararg;
78 int maxstacksize;
79 // Debug info
80 /** Map from PC to line number. */
81 int[] lineinfo;
82 int sizelineinfo;
83 LocVar[] locvars;
84 int sizelocvars ;
85 String[] upvalues;
86 int sizeupvalues;
87 String source;
88 int linedefined;
89 int lastlinedefined;
91 /**
92 * Proto synthesized by {@link Loader}.
93 * All the arrays that are passed to the constructor are
94 * referenced by the instance. Avoid unintentional sharing. All
95 * arrays must be non-null and all int parameters must not be
96 * negative. Generally, this constructor is used by {@link Loader}
97 * since that has all the relevant arrays already constructed (as
98 * opposed to the compiler).
99 * @param constant array of constants.
100 * @param code array of VM instructions.
101 * @param nups number of upvalues (used by this function).
102 * @param numparams number of fixed formal parameters.
103 * @param isVararg whether '...' is used.
104 * @param maxstacksize number of stack slots required when invoking.
105 * @throws NullPointerException if any array arguments are null.
106 * @throws IllegalArgumentException if nups or numparams is negative.
108 Proto(Slot[] constant,
109 int[] code,
110 Proto[] proto,
111 int nups,
112 int numparams,
113 boolean isVararg,
114 int maxstacksize)
116 if (null == constant || null == code || null == proto)
118 throw new NullPointerException();
120 if (nups < 0 || numparams < 0 || maxstacksize < 0)
122 throw new IllegalArgumentException();
124 this.k = constant; sizek = k.length ;
125 this.code = code; sizecode = code.length ;
126 this.p = proto; this.sizep = proto.length ;
127 this.nups = nups;
128 this.numparams = numparams;
129 this.isVararg = isVararg;
130 this.maxstacksize = maxstacksize;
134 * Blank Proto in preparation for compilation.
136 Proto(String source, int maxstacksize)
138 this.maxstacksize = maxstacksize;
139 // maxstacksize = 2; // register 0/1 are always valid.
140 // :todo: Consider removing size* members
141 this.source = source;
142 this.k = ZERO_CONSTANT_ARRAY; this.sizek = 0 ;
143 this.code = ZERO_INT_ARRAY; this.sizecode = 0 ;
144 this.p = ZERO_PROTO_ARRAY; this.sizep = 0;
145 this.lineinfo = ZERO_INT_ARRAY; this.sizelineinfo = 0;
146 this.locvars = ZERO_LOCVAR_ARRAY; this.sizelocvars = 0 ;
147 this.upvalues = ZERO_STRING_ARRAY; this.sizeupvalues = 0;
151 * Augment with debug info. All the arguments are referenced by the
152 * instance after the method has returned, so try not to share them.
154 void debug(int[] lineinfoArg,
155 LocVar[] locvarsArg,
156 String[] upvaluesArg)
158 this.lineinfo = lineinfoArg; sizelineinfo = lineinfo.length;
159 this.locvars = locvarsArg; sizelocvars = locvars.length;
160 this.upvalues = upvaluesArg; sizeupvalues = upvalues.length;
163 /** Gets source. */
164 String source()
166 return source;
169 /** Setter for source. */
170 void setSource(String source)
172 this.source = source;
175 int linedefined()
177 return linedefined;
179 void setLinedefined(int linedefined)
181 this.linedefined = linedefined;
184 int lastlinedefined()
186 return lastlinedefined;
188 void setLastlinedefined(int lastlinedefined)
190 this.lastlinedefined = lastlinedefined;
193 /** Gets Number of Upvalues */
194 int nups()
196 return nups;
199 /** Number of Parameters. */
200 int numparams()
202 return numparams;
205 /** Maximum Stack Size. */
206 int maxstacksize()
208 return maxstacksize;
211 /** Setter for maximum stack size. */
212 void setMaxstacksize(int m)
214 maxstacksize = m;
217 /** Instruction block (do not modify). */
218 int[] code()
220 return code;
223 /** Append instruction. */
224 void codeAppend(Lua L, int pc, int instruction, int line)
226 ensureCode(L, pc);
227 code[pc] = instruction;
229 if (pc >= lineinfo.length)
231 int[] newLineinfo = new int[lineinfo.length*2+1];
232 System.arraycopy(lineinfo, 0, newLineinfo, 0, lineinfo.length);
233 lineinfo = newLineinfo;
235 lineinfo[pc] = line;
238 void ensureLocvars(Lua L, int atleast, int limit)
240 if (atleast + 1 > sizelocvars)
242 int newsize = atleast*2+1 ;
243 if (newsize > limit)
244 newsize = limit ;
245 if (atleast + 1 > newsize)
246 L.gRunerror("too many local variables") ;
247 LocVar [] newlocvars = new LocVar [newsize] ;
248 System.arraycopy(locvars, 0, newlocvars, 0, sizelocvars) ;
249 for (int i = sizelocvars ; i < newsize ; i++)
250 newlocvars[i] = new LocVar() ;
251 locvars = newlocvars ;
252 sizelocvars = newsize ;
256 void ensureProtos(Lua L, int atleast)
258 if (atleast + 1 > sizep)
260 int newsize = atleast*2+1 ;
261 if (newsize > Lua.MAXARG_Bx)
262 newsize = Lua.MAXARG_Bx ;
263 if (atleast + 1 > newsize)
264 L.gRunerror("constant table overflow") ;
265 Proto [] newprotos = new Proto [newsize] ;
266 System.arraycopy(p, 0, newprotos, 0, sizep) ;
267 p = newprotos ;
268 sizep = newsize ;
272 void ensureUpvals(Lua L, int atleast)
274 if (atleast + 1 > sizeupvalues)
276 int newsize = atleast*2+1 ;
277 if (atleast + 1 > newsize)
278 L.gRunerror("upvalues overflow") ;
279 String [] newupvalues = new String [newsize] ;
280 System.arraycopy(upvalues, 0, newupvalues, 0, sizeupvalues) ;
281 upvalues = newupvalues ;
282 sizeupvalues = newsize ;
286 void ensureCode(Lua L, int atleast)
288 if (atleast + 1 > sizecode)
290 int newsize = atleast*2+1 ;
291 if (atleast + 1 > newsize)
292 L.gRunerror("code overflow") ;
293 int [] newcode = new int [newsize] ;
294 System.arraycopy(code, 0, newcode, 0, sizecode) ;
295 code = newcode ;
296 sizecode = newsize ;
300 /** Set lineinfo record. */
301 void setLineinfo(int pc, int line)
303 lineinfo[pc] = line;
306 /** Get linenumber corresponding to pc, or 0 if no info. */
307 int getline(int pc)
309 if (lineinfo.length == 0)
311 return 0;
313 return lineinfo[pc];
316 /** Array of inner protos (do not modify). */
317 Proto[] proto()
319 return p;
322 /** Constant array (do not modify). */
323 Slot[] constant()
325 return k;
328 /** Append constant. */
329 void constantAppend(int idx, Object o)
331 if (idx >= k.length)
333 Slot[] newK = new Slot[k.length*2+1];
334 System.arraycopy(k, 0, newK, 0, k.length);
335 k = newK;
337 k[idx] = new Slot(o);
340 /** Predicate for whether function uses ... in its parameter list. */
341 boolean isVararg()
343 return isVararg;
346 /** "Setter" for isVararg. Sets it to true. */
347 void setIsVararg()
349 isVararg = true;
352 /** LocVar array (do not modify). */
353 LocVar[] locvars()
355 return locvars;
358 // All the trim functions, below, check for the redundant case of
359 // trimming to the length that they already are. Because they are
360 // initially allocated as interned zero-length arrays this also means
361 // that no unnecesary zero-length array objects are allocated.
364 * Trim an int array to specified size.
365 * @return the trimmed array.
367 private int[] trimInt(int[] old, int n)
369 if (n == old.length)
371 return old;
373 int[] newArray = new int[n];
374 System.arraycopy(old, 0, newArray, 0, n);
375 return newArray;
378 /** Trim code array to specified size. */
379 void closeCode(int n)
381 code = trimInt(code, n);
382 sizecode = code.length ;
385 /** Trim lineinfo array to specified size. */
386 void closeLineinfo(int n)
388 lineinfo = trimInt(lineinfo, n);
389 sizelineinfo = n;
392 /** Trim k (constant) array to specified size. */
393 void closeK(int n)
395 if (k.length > n)
397 Slot[] newArray = new Slot[n];
398 System.arraycopy(k, 0, newArray, 0, n);
399 k = newArray;
401 sizek = n ;
402 return;
405 /** Trim p (proto) array to specified size. */
406 void closeP(int n)
408 if (n == p.length)
410 return;
412 Proto[] newArray = new Proto[n];
413 System.arraycopy(p, 0, newArray, 0, n);
414 p = newArray;
415 sizep = n ;
418 /** Trim locvar array to specified size. */
419 void closeLocvars(int n)
421 if (n == locvars.length)
423 return;
425 LocVar[] newArray = new LocVar[n];
426 System.arraycopy(locvars, 0, newArray, 0, n);
427 locvars = newArray;
428 sizelocvars = n;
431 /** Trim upvalues array to size <var>nups</var>. */
432 void closeUpvalues()
434 if (nups == upvalues.length)
436 return;
438 String[] newArray = new String[nups];
439 System.arraycopy(upvalues, 0, newArray, 0, nups);
440 upvalues = newArray;
441 sizeupvalues = nups;