1 /* $Header: d:/cvsroot/tads/tads3/VMLST.H,v 1.2 1999/05/17 02:52:28 MJRoberts Exp $ */
2 
3 /*
4  *   Copyright (c) 1998, 2002 Michael J. Roberts.  All Rights Reserved.
5  *
6  *   Please see the accompanying license file, LICENSE.TXT, for information
7  *   on using and copying this software.
8  */
9 /*
10 Name
11   vmlst.h - VM dynamic list implementation
12 Function
13 
14 Notes
15 
16 Modified
17   10/29/98 MJRoberts  - Creation
18 */
19 
20 #ifndef VMLST_H
21 #define VMLST_H
22 
23 #include <stdlib.h>
24 #include "vmtype.h"
25 #include "vmobj.h"
26 #include "vmcoll.h"
27 #include "vmglob.h"
28 #include "vmstack.h"
29 
30 
31 class CVmObjList: public CVmObjCollection
32 {
33     friend class CVmMetaclassList;
34 
35 public:
36     /* metaclass registration object */
37     static class CVmMetaclass *metaclass_reg_;
get_metaclass_reg()38     class CVmMetaclass *get_metaclass_reg() const { return metaclass_reg_; }
39 
40     /* am I of the given metaclass? */
is_of_metaclass(class CVmMetaclass * meta)41     virtual int is_of_metaclass(class CVmMetaclass *meta) const
42     {
43         /* try my own metaclass and my base class */
44         return (meta == metaclass_reg_
45                 || CVmObjCollection::is_of_metaclass(meta));
46     }
47 
48     /* create dynamically using stack arguments */
49     static vm_obj_id_t create_from_stack(VMG_ const uchar **pc_ptr,
50                                          uint argc);
51 
52     /*
53      *   Create dynamically from parameters in the stack; we do not remove
54      *   the elements from the stack, but simply create a list from the
55      *   parameters.  'idx' is the parameter index of the first parameter,
56      *   and 'cnt' is the number of parameters to use.
57      */
58     static vm_obj_id_t create_from_params(VMG_ uint idx, uint cnt);
59 
60     /*
61      *   call a static property - we don't have any of our own, so simply
62      *   "inherit" the base class handling
63      */
call_stat_prop(VMG_ vm_val_t * result,const uchar ** pc_ptr,uint * argc,vm_prop_id_t prop)64     static int call_stat_prop(VMG_ vm_val_t *result,
65                               const uchar **pc_ptr, uint *argc,
66                               vm_prop_id_t prop)
67     {
68         return CVmObjCollection::
69             call_stat_prop(vmg_ result, pc_ptr, argc, prop);
70     }
71 
72     /* reserve constant data */
73     virtual void reserve_const_data(VMG_ class CVmConstMapper *mapper,
74                                     vm_obj_id_t self);
75 
76     /* convert to constant data */
77     virtual void convert_to_const_data(VMG_ class CVmConstMapper *mapper,
78                                        vm_obj_id_t self);
79 
80     /* get my datatype when converted to constant data */
get_convert_to_const_data_type()81     virtual vm_datatype_t get_convert_to_const_data_type() const
82       { return VM_LIST; }
83 
84     /* create a list with no initial contents */
85     static vm_obj_id_t create(VMG_ int in_root_set);
86 
87     /*
88      *   create a list with a given number of elements, for construction
89      *   of the list element-by-element
90      */
91     static vm_obj_id_t create(VMG_ int in_root_set, size_t element_count);
92 
93     /*
94      *   create a list from a constant list, for construction of the list
95      *   as a modified copy of an original list
96      */
97     static vm_obj_id_t create(VMG_ int in_root_set, const char *lst);
98 
99     /*
100      *   List construction: set an element.  List contents are immutable,
101      *   so they cannot be changed after the list is constructed.
102      *   However, it is often convenient to construct a list one element
103      *   at a time, so a caller can create the list with the appropriate
104      *   number of elements, then use this routine to set each element of
105      *   the list individually.
106      *
107      *   idx is the index of the element in the list; the first element is
108      *   at index zero.  Note that this routine does *not* allocate
109      *   memory; the list must be pre-allocated to its full number of
110      *   elements.
111      */
112     void cons_set_element(size_t idx, const vm_val_t *val);
113 
114     /* update the list in place so that each value is unique */
115     void cons_uniquify(VMG0_);
116 
117     /*
118      *   Copy an existing list into our list, starting at a given index.  The
119      *   caller must ensure that our list buffer is large enough to
120      *   accommodate the new elements.  The 'orig_list' value must point to a
121      *   standard list constant value: a UINT2 element count prefix followed
122      *   by DATAHOLDER elements.
123      */
124     void cons_copy_elements(size_t start_idx, const char *orig_list);
125 
126     /*
127      *   Copy existing list elements into our list, starting at the given
128      *   index.  The caller must ensure that our list buffer is large enough
129      *   to accommodate the new elements.  The 'ele_array' is an array of
130      *   DATAHOLDER values.
131      */
132     void cons_copy_data(size_t start_idx, const char *ele_array,
133                         size_t ele_count);
134 
135     /*
136      *   Set the length of the list.  This can be used when constructing a
137      *   list, and the actual number of elements is unknown before
138      *   construction is complete (however, the maximum number of elements
139      *   must be known in advance, since this merely sets the length, and
140      *   does NOT reallocate the list -- hence, this call can only be used
141      *   to shrink the list below its allocated size, never to expand it).
142      */
cons_set_len(size_t len)143     void cons_set_len(size_t len)
144         { vmb_put_len(ext_, len); }
145 
146     /* notify of deletion */
147     void notify_delete(VMG_ int in_root_set);
148 
149     /* set a property */
150     void set_prop(VMG_ class CVmUndo *undo,
151                   vm_obj_id_t self, vm_prop_id_t prop, const vm_val_t *val);
152 
153     /* get a property */
154     int get_prop(VMG_ vm_prop_id_t prop, vm_val_t *val,
155                  vm_obj_id_t self, vm_obj_id_t *source_obj, uint *argc);
156 
157     /* undo operations - lists are immutable and hence keep no undo */
notify_new_savept()158     void notify_new_savept() { }
apply_undo(VMG_ struct CVmUndoRecord *)159     void apply_undo(VMG_ struct CVmUndoRecord *) { }
mark_undo_ref(VMG_ struct CVmUndoRecord *)160     void mark_undo_ref(VMG_ struct CVmUndoRecord *) { }
remove_stale_undo_weak_ref(VMG_ struct CVmUndoRecord *)161     void remove_stale_undo_weak_ref(VMG_ struct CVmUndoRecord *) { }
162 
163     /* mark references */
164     void mark_refs(VMG_ uint state);
165 
166     /*
167      *   remove weak references - we keep only normal (strong) references,
168      *   so this routine doesn't need to do anything
169      */
remove_stale_weak_refs(VMG0_)170     void remove_stale_weak_refs(VMG0_) { }
171 
172     /* load from an image file */
load_from_image(VMG_ vm_obj_id_t,const char * ptr,size_t)173     void load_from_image(VMG_ vm_obj_id_t, const char *ptr, size_t)
174         { ext_ = (char *)ptr; }
175 
176     /* rebuild for image file */
177     virtual ulong rebuild_image(VMG_ char *buf, ulong buflen);
178 
179     /* save to a file */
180     void save_to_file(VMG_ class CVmFile *fp);
181 
182     /* restore from a file */
183     void restore_from_file(VMG_ vm_obj_id_t self,
184                            class CVmFile *fp, class CVmObjFixup *fixups);
185 
186     /*
187      *   Add a value to the list.  If the value to add is a list (constant
188      *   or object), we'll append each element of the list to this list;
189      *   otherwise, we'll just append the value itself to the list.  In
190      *   any case, we don't modify this list itself, but create a new list
191      *   object to hold the result.
192      */
193     void add_val(VMG_ vm_val_t *result,
194                  vm_obj_id_t self, const vm_val_t *val);
195 
196     /*
197      *   Index the list
198      */
199     void index_val(VMG_ vm_val_t *result, vm_obj_id_t self,
200                    const vm_val_t *index_val);
201 
202     /*
203      *   Set an indexed element of the list.  Since the contents of a list
204      *   object cannot be changed, we'll return in *new_container a new
205      *   list object that we create with the modified contents.
206      */
207     void set_index_val(VMG_ vm_val_t *new_container, vm_obj_id_t self,
208                        const vm_val_t *index_val, const vm_val_t *new_val);
209 
210     /*
211      *   Subtract a value from the list.  This creates a new list with the
212      *   element matching the given value removed from the original list.
213      *   We do not modify the original list; instead, we create a new list
214      *   object with the new value.
215      */
216     void sub_val(VMG_ vm_val_t *result,
217                  vm_obj_id_t self, const vm_val_t *val);
218 
219     /*
220      *   get as a list - simply return our extension, which is in the
221      *   required portable list format
222      */
get_as_list()223     const char *get_as_list() const { return ext_; }
224 
225     /*
226      *   Check a value for equality.  We will match any constant list that
227      *   contains the same data as our list, and any other list object
228      *   with the same underlying data.
229      */
230     int equals(VMG_ vm_obj_id_t self, const vm_val_t *val, int depth) const;
231 
232     /*
233      *   Static list adder.  This creates a new list object that results
234      *   from appending the given value to the given list constant.  This
235      *   is defined statically so that this code can be shared for adding
236      *   to constant pool lists and adding to CVmObjList objects.
237      *
238      *   'lstval' must point to a constant list.  The first two bytes of
239      *   the list are stored in portable UINT2 format and give the number
240      *   of elements in the list; this is immediately followed by a packed
241      *   array of data holders in portable format.
242      */
243     static void add_to_list(VMG_ vm_val_t *result,
244                             vm_obj_id_t self, const char *lstval,
245                             const vm_val_t *val);
246 
247     /*
248      *   Static list subtraction routine. This creates a new list object
249      *   that results from removing the given value from the list
250      *   constant.  This is defined statically so that this code can be
251      *   shared for subtracting from constant pool lists and subtracting
252      *   from CVmObjList objects.
253      *
254      *   'lstmem' must point to a constant list in the same format as
255      *   required for add_to_list.  If 'lstmem' comes from the constant
256      *   pool, then 'lstval' must be provided to give us the constant pool
257      *   address; otherwise, 'lstval' should be null.
258      */
259     static void sub_from_list(VMG_ vm_val_t *result,
260                               const vm_val_t *lstval, const char *lstmem,
261                               const vm_val_t *val);
262 
263     /*
264      *   Constant list comparison routine.  Compares the given list
265      *   constant (in portable format, with leading UINT2 element count
266      *   prefix followed by the list's elements in portable data holder
267      *   format) to the other value.  Returns true if the other value is a
268      *   list constant or object whose contents match the list constant,
269      *   false if not.
270      *
271      *   If 'lstmem' comes from the constant pool, then 'lstval' must be
272      *   provided to give us the constant pool address; otherwise,
273      *   'lstval' should be null.
274      */
275     static int const_equals(VMG_ const vm_val_t *lstval, const char *lstmem,
276                             const vm_val_t *val, int depth);
277 
278     /*
279      *   Calculate a hash value for the list
280      */
281     uint calc_hash(VMG_ vm_obj_id_t self, int depth) const;
282 
283     /*
284      *   Constant list hash value calculation
285      */
286     static uint const_calc_hash(VMG_ const vm_val_t *self_val,
287                                 const char *lst, int depth);
288 
289     /*
290      *   When we're the right-hand side of a '+' or '-' operation whose
291      *   left-hand side is another collection type that treats these
292      *   operators as concatenation/set subtraction, add/subtract our
293      *   elements individually.
294      */
get_coll_addsub_rhs_ele_cnt(VMG0_)295     size_t get_coll_addsub_rhs_ele_cnt(VMG0_) const
296         { return vmb_get_len(ext_); }
get_coll_addsub_rhs_ele(VMG_ vm_val_t * result,vm_obj_id_t self,size_t idx)297     void get_coll_addsub_rhs_ele(VMG_ vm_val_t *result,
298                                  vm_obj_id_t self, size_t idx)
299         { index_list(vmg_ result, ext_, idx); }
300 
301     /*
302      *   Constant list indexing routine.  Indexes the given constant list
303      *   (which must be in portable format, with leading UINT2 element
304      *   count followed by the list's elements in portable data holder
305      *   format), looking up the value at the index number given by the
306      *   index value, and puts the result in *result.
307      */
308     static void index_list(VMG_ vm_val_t *result,
309                            const char *lst, const vm_val_t *index_val);
310 
311     /* index a list, using a 1-based index */
312     static void index_list(VMG_ vm_val_t *result, const char *lst, uint idx);
313 
314     /* push the indexed element, using a 1-based index */
index_and_push(VMG_ const char * lst,uint idx)315     static void index_and_push(VMG_ const char *lst, uint idx)
316     {
317         vm_val_t *p;
318 
319         /* push a new stack element */
320         p = G_stk->push();
321 
322         /* index the list and store the value directly in the stack */
323         index_list(vmg_ p, lst, idx);
324     }
325 
326     /*
327      *   Constant list set-index routine.  Creates a new list object as a
328      *   copy of this list, with the element at the given index set to the
329      *   given new value.
330      */
331     static void set_index_list(VMG_ vm_val_t *result,
332                                const char *lst, const vm_val_t *index_val,
333                                const vm_val_t *new_val);
334 
335     /*
336      *   Find a value within a list.  If we find the value, we'll set
337      *   *idxp to the index (starting at zero for the first element) of
338      *   the item we found, and we'll return true; if we don't find the
339      *   value, we'll return false.
340      */
341     static int find_in_list(VMG_ const vm_val_t *lst,
342                             const vm_val_t *val, size_t *idxp);
343 
344     /* find the last match for a value */
345     static int find_last_in_list(VMG_ const vm_val_t *lst,
346                                  const vm_val_t *val, size_t *idxp);
347 
348     /*
349      *   Evaluate a property of a constant list value.  Returns true if we
350      *   successfully evaluated the property, false if the property is not
351      *   one of the properties that the list class defines.
352      */
353     static int const_get_prop(VMG_ vm_val_t *retval, const vm_val_t *self_val,
354                               const char *lst, vm_prop_id_t prop,
355                               vm_obj_id_t *srcobj, uint *argc);
356 
357     /* property evaluator - undefined property */
getp_undef(VMG_ vm_val_t *,const vm_val_t *,const char *,uint *)358     static int getp_undef(VMG_ vm_val_t *, const vm_val_t *,
359                           const char *, uint *)
360         { return FALSE; }
361 
362     /* property evaluator - select a subset through a callback */
363     static int getp_subset(VMG_ vm_val_t *retval, const vm_val_t *self_val,
364                            const char *lst, uint *argc);
365 
366     /* property evaluator - apply a callback to each element */
367     static int getp_map(VMG_ vm_val_t *retval, const vm_val_t *self_val,
368                         const char *lst, uint *argc);
369 
370     /* get the length */
371     static int getp_len(VMG_ vm_val_t *retval, const vm_val_t *self_val,
372                         const char *lst, uint *argc);
373 
374     /* sublist */
375     static int getp_sublist(VMG_ vm_val_t *retval, const vm_val_t *self_val,
376                             const char *lst, uint *argc);
377 
378     /* intersect */
379     static int getp_intersect(VMG_ vm_val_t *retval,
380                               const vm_val_t *self_val,
381                               const char *lst, uint *argc);
382 
383     /* indexOf */
384     static int getp_index_of(VMG_ vm_val_t *retval, const vm_val_t *self_val,
385                              const char *lst, uint *argc);
386 
387     /* car */
388     static int getp_car(VMG_ vm_val_t *retval, const vm_val_t *self_val,
389                         const char *lst, uint *argc);
390 
391     /* cdr */
392     static int getp_cdr(VMG_ vm_val_t *retval, const vm_val_t *self_val,
393                         const char *lst, uint *argc);
394 
395     /* indexWhich */
396     static int getp_index_which(VMG_ vm_val_t *retval,
397                                 const vm_val_t *self_val,
398                                 const char *lst, uint *argc);
399 
400     /* forEach */
401     static int getp_for_each(VMG_ vm_val_t *retval, const vm_val_t *self_val,
402                              const char *lst, uint *argc);
403 
404     /* forEachAssoc */
405     static int getp_for_each_assoc(VMG_ vm_val_t *retval,
406                                    const vm_val_t *self_val,
407                                    const char *lst, uint *argc);
408 
409     /* valWhich */
410     static int getp_val_which(VMG_ vm_val_t *retval,
411                               const vm_val_t *self_val,
412                               const char *lst, uint *argc);
413 
414     /* lastIndexOf */
415     static int getp_last_index_of(VMG_ vm_val_t *retval,
416                                   const vm_val_t *self_val,
417                                   const char *lst, uint *argc);
418 
419     /* lastIndexWhich */
420     static int getp_last_index_which(VMG_ vm_val_t *retval,
421                                      const vm_val_t *self_val,
422                                      const char *lst, uint *argc);
423 
424     /* lastValWhich */
425     static int getp_last_val_which(VMG_ vm_val_t *retval,
426                                    const vm_val_t *self_val,
427                                    const char *lst, uint *argc);
428 
429     /* countOf */
430     static int getp_count_of(VMG_ vm_val_t *retval,
431                              const vm_val_t *self_val,
432                              const char *lst, uint *argc);
433 
434     /* countWhich */
435     static int getp_count_which(VMG_ vm_val_t *retval,
436                                 const vm_val_t *self_val,
437                                 const char *lst, uint *argc);
438 
439     /* general routine for indexWhich and lastIndexWhich */
440     static int gen_index_which(VMG_ vm_val_t *retval,
441                                const vm_val_t *self_val,
442                                const char *lst, uint *argc,
443                                int forward);
444 
445     /* getUnique */
446     static int getp_get_unique(VMG_ vm_val_t *retval,
447                                const vm_val_t *self_val,
448                                const char *lst, uint *argc);
449 
450     /* appendUnique */
451     static int getp_append_unique(VMG_ vm_val_t *retval,
452                                   const vm_val_t *self_val,
453                                   const char *lst, uint *argc);
454 
455     /* append */
456     static int getp_append(VMG_ vm_val_t *retval,
457                            const vm_val_t *self_val,
458                            const char *lst, uint *argc);
459 
460     /* sort */
461     static int getp_sort(VMG_ vm_val_t *retval,
462                          const vm_val_t *self_val,
463                          const char *lst, uint *argc);
464 
465     /* insertAt */
466     static int getp_insert_at(VMG_ vm_val_t *retval,
467                               const vm_val_t *self_val,
468                               const char *lst, uint *argc);
469 
470     /* prepend */
471     static int getp_prepend(VMG_ vm_val_t *retval,
472                             const vm_val_t *self_val,
473                             const char *lst, uint *argc);
474 
475     /* property evaluator - remove a single element at a given index */
476     static int getp_remove_element_at(VMG_ vm_val_t *retval,
477                                       const vm_val_t *self_val,
478                                       const char *lst, uint *argc);
479 
480     /* property evaluator - removeRange */
481     static int getp_remove_range(VMG_ vm_val_t *retval,
482                                  const vm_val_t *self_val,
483                                  const char *lst, uint *argc);
484 
485 protected:
486     /* general processor for forEach and forEachAssoc */
487     static int for_each_gen(VMG_ vm_val_t *retval,
488                             const vm_val_t *self_val,
489                             const char *lst, uint *argc,
490                             int send_idx_to_cb);
491 
492     /*
493      *   Compute the intersection of two lists.  Returns a new list with the
494      *   elements that occur in both lists.
495      */
496     static vm_obj_id_t intersect(VMG_ const vm_val_t *lst1,
497                                  const vm_val_t *lst2);
498 
499     /* insert the arguments into the list at the given index */
500     static void insert_elements(VMG_ vm_val_t *retval,
501                                 const vm_val_t *self_val,
502                                 const char *lst, uint argc, int idx);
503 
504     /* remove elements */
505     static void remove_range(VMG_ vm_val_t *retval,
506                              const vm_val_t *self_val,
507                              const char *lst, int start_idx, int del_cnt);
508 
509     /* create an iterator */
510     virtual void new_iterator(VMG_ vm_val_t *retval,
511                               const vm_val_t *self_val);
512 
513     /*
514      *   create a live iterator - for a list, there is no difference
515      *   between snapshot and live iterators, since a list is immutable
516      */
new_live_iterator(VMG_ vm_val_t * retval,const vm_val_t * self_val)517     virtual void new_live_iterator(VMG_ vm_val_t *retval,
518                                    const vm_val_t *self_val)
519         { new_iterator(vmg_ retval, self_val); }
520 
521     /* get the number of elements in the list */
get_ele_count()522     size_t get_ele_count() const { return vmb_get_len(ext_); }
523 
524     /* get an element, given a zero-based index */
get_element(size_t idx,vm_val_t * val)525     void get_element(size_t idx, vm_val_t *val) const
526     {
527         /* get the data from the data holder in our extension */
528         vmb_get_dh(get_element_ptr(idx), val);
529     }
530 
531     /* get the number of elements in a constant list */
get_ele_count_const(const char * lstval)532     static size_t get_ele_count_const(const char *lstval)
533         { return vmb_get_len(lstval); }
534 
535     /* get an element from a constant list, given a zero-based index */
get_element_const(const char * lstval,size_t idx,vm_val_t * val)536     static void get_element_const(const char *lstval, size_t idx,
537                                   vm_val_t *val)
538     {
539         /* get the data from the data holder in the constant list */
540         vmb_get_dh(get_element_ptr_const(lstval, idx), val);
541     }
542 
543     /* given an index, get a pointer to the element's data in the list */
get_element_ptr(size_t idx)544     char *get_element_ptr(size_t idx) const
545     {
546         /*
547          *   figure out where this element's data holder is by skipping
548          *   the count prefix, then skipping past preceding data holders
549          */
550         return ext_ + VMB_LEN + (idx * VMB_DATAHOLDER);
551     }
552 
553     /*
554      *   given an index, and a pointer to a constant list, get a pointer
555      *   to the element's data in the list constant
556      */
get_element_ptr_const(const char * lstval,size_t idx)557     static const char *get_element_ptr_const(const char *lstval, size_t idx)
558     {
559         /*
560          *   figure out where this element's data holder is by skipping
561          *   the count prefix, then skipping past preceding data holders
562          */
563         return lstval + VMB_LEN + (idx * VMB_DATAHOLDER);
564     }
565 
566     /*
567      *   given a pointer to a list element, increment the pointer so that
568      *   it points to the next element
569      */
inc_element_ptr(char ** p)570     static void inc_element_ptr(char **p)
571     {
572         /* add the size of a data holder to the current pointer */
573         *p += VMB_DATAHOLDER;
574     }
575 
576     /* increment a constant element pointer */
inc_const_element_ptr(const char ** p)577     static void inc_const_element_ptr(const char **p)
578     {
579         /* add the size of a data holder to the current pointer */
580         *p += VMB_DATAHOLDER;
581     }
582 
583     /* create a list with no initial contents */
CVmObjList()584     CVmObjList() { ext_ = 0; }
585 
586     /*
587      *   create a list with a given number of elements, for construction
588      *   of the list element-by-element
589      */
590     CVmObjList(VMG_ size_t element_count);
591 
592     /* create a list from a constant list */
593     CVmObjList(VMG_ const char *lst);
594 
595     /*
596      *   Calculate the amount of space we need to store a list of a given
597      *   length.  We require two bytes for the length prefix, plus the
598      *   space for each element.
599      */
calc_alloc(size_t elecnt)600     static size_t calc_alloc(size_t elecnt)
601         { return (VMB_LEN + (elecnt * VMB_DATAHOLDER)); }
602 
603     /* allocate space for the list, given the number of elements */
604     void alloc_list(VMG_ size_t element_count);
605 
606     /* property evaluation function table */
607     static int (*func_table_[])(VMG_ vm_val_t *retval,
608                                 const vm_val_t *self_val,
609                                 const char *lst, uint *argc);
610 };
611 
612 
613 /* ------------------------------------------------------------------------ */
614 /*
615  *   A constant list is exactly like an ordinary list, except that our
616  *   contents come from the constant pool.  We store a pointer directly to
617  *   our constant pool data rather than making a separate copy.  The only
618  *   thing we have to do differently from an ordinary list is that we don't
619  *   delete our extension when we're deleted, since our extension is really
620  *   just a pointer into the constant pool.
621  */
622 class CVmObjListConst: public CVmObjList
623 {
624 public:
625     /* notify of deletion */
notify_delete(VMG_ int)626     void notify_delete(VMG_ int /*in_root_set*/)
627     {
628         /*
629          *   do nothing, since our extension is just a pointer into the
630          *   constant pool
631          */
632     }
633 
634     /* create from constant pool data */
635     static vm_obj_id_t create(VMG_ const char *const_ptr);
636 
637 protected:
638     /* construct from constant pool data */
CVmObjListConst(VMG_ const char * const_ptr)639     CVmObjListConst(VMG_ const char *const_ptr)
640     {
641         /* point our extension directly to the constant pool data */
642         ext_ = (char *)const_ptr;
643     }
644 };
645 
646 /* ------------------------------------------------------------------------ */
647 /*
648  *   Registration table object
649  */
650 class CVmMetaclassList: public CVmMetaclass
651 {
652 public:
653     /* get the global name */
get_meta_name()654     const char *get_meta_name() const { return "list/030007"; }
655 
656     /* create from image file */
create_for_image_load(VMG_ vm_obj_id_t id)657     void create_for_image_load(VMG_ vm_obj_id_t id)
658     {
659         new (vmg_ id) CVmObjList();
660         G_obj_table->set_obj_gc_characteristics(id, TRUE, FALSE);
661     }
662 
663     /* create from restoring from saved state */
create_for_restore(VMG_ vm_obj_id_t id)664     void create_for_restore(VMG_ vm_obj_id_t id)
665     {
666         new (vmg_ id) CVmObjList();
667         G_obj_table->set_obj_gc_characteristics(id, TRUE, FALSE);
668     }
669 
670     /* create dynamically using stack arguments */
create_from_stack(VMG_ const uchar ** pc_ptr,uint argc)671     vm_obj_id_t create_from_stack(VMG_ const uchar **pc_ptr, uint argc)
672         { return CVmObjList::create_from_stack(vmg_ pc_ptr, argc); }
673 
674     /* call a static property */
call_stat_prop(VMG_ vm_val_t * result,const uchar ** pc_ptr,uint * argc,vm_prop_id_t prop)675     int call_stat_prop(VMG_ vm_val_t *result,
676                        const uchar **pc_ptr, uint *argc,
677                        vm_prop_id_t prop)
678     {
679         return CVmObjList::call_stat_prop(vmg_ result, pc_ptr, argc, prop);
680     }
681 
682     /* I'm a Collection object */
get_supermeta_reg()683     CVmMetaclass *get_supermeta_reg() const
684         { return CVmObjCollection::metaclass_reg_; }
685 };
686 
687 #endif /* VMLST_H */
688 
689 /*
690  *   Register the class
691  */
692 VM_REGISTER_METACLASS(CVmObjList)
693 
694