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).
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.
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
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. */
54 /** Array of VM instructions. */
57 /** Array of Proto objects. */
61 * Number of upvalues used by this prototype (and so by all the
62 * functions created from this Proto).
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
74 * <code>true</code> if and only if the function is variadic, that is,
75 * defined with '...' in its parameter list.
80 /** Map from PC to line number. */
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
,
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
;
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
,
156 String
[] upvaluesArg
)
158 this.lineinfo
= lineinfoArg
; sizelineinfo
= lineinfo
.length
;
159 this.locvars
= locvarsArg
; sizelocvars
= locvars
.length
;
160 this.upvalues
= upvaluesArg
; sizeupvalues
= upvalues
.length
;
169 /** Setter for source. */
170 void setSource(String source
)
172 this.source
= source
;
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 */
199 /** Number of Parameters. */
205 /** Maximum Stack Size. */
211 /** Setter for maximum stack size. */
212 void setMaxstacksize(int m
)
217 /** Instruction block (do not modify). */
223 /** Append instruction. */
224 void codeAppend(Lua L
, int pc
, int instruction
, int line
)
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
;
238 void ensureLocvars(Lua L
, int atleast
, int limit
)
240 if (atleast
+ 1 > sizelocvars
)
242 int newsize
= atleast
*2+1 ;
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
) ;
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
) ;
300 /** Set lineinfo record. */
301 void setLineinfo(int pc
, int line
)
306 /** Get linenumber corresponding to pc, or 0 if no info. */
309 if (lineinfo
.length
== 0)
316 /** Array of inner protos (do not modify). */
322 /** Constant array (do not modify). */
328 /** Append constant. */
329 void constantAppend(int idx
, Object o
)
333 Slot
[] newK
= new Slot
[k
.length
*2+1];
334 System
.arraycopy(k
, 0, newK
, 0, k
.length
);
337 k
[idx
] = new Slot(o
);
340 /** Predicate for whether function uses ... in its parameter list. */
346 /** "Setter" for isVararg. Sets it to true. */
352 /** LocVar array (do not modify). */
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
)
373 int[] newArray
= new int[n
];
374 System
.arraycopy(old
, 0, newArray
, 0, n
);
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
);
392 /** Trim k (constant) array to specified size. */
397 Slot
[] newArray
= new Slot
[n
];
398 System
.arraycopy(k
, 0, newArray
, 0, n
);
405 /** Trim p (proto) array to specified size. */
412 Proto
[] newArray
= new Proto
[n
];
413 System
.arraycopy(p
, 0, newArray
, 0, n
);
418 /** Trim locvar array to specified size. */
419 void closeLocvars(int n
)
421 if (n
== locvars
.length
)
425 LocVar
[] newArray
= new LocVar
[n
];
426 System
.arraycopy(locvars
, 0, newArray
, 0, n
);
431 /** Trim upvalues array to size <var>nups</var>. */
434 if (nups
== upvalues
.length
)
438 String
[] newArray
= new String
[nups
];
439 System
.arraycopy(upvalues
, 0, newArray
, 0, nups
);