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