~ubuntu-branches/ubuntu/wily/gargoyle-free/wily-proposed

« back to all changes in this revision

Viewing changes to tads/tads3/vmtype.h

  • Committer: Bazaar Package Importer
  • Author(s): Sylvain Beucler
  • Date: 2009-09-11 20:09:43 UTC
  • Revision ID: james.westby@ubuntu.com-20090911200943-idgzoyupq6650zpn
Tags: upstream-2009-08-25
ImportĀ upstreamĀ versionĀ 2009-08-25

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $Header: d:/cvsroot/tads/tads3/VMTYPE.H,v 1.3 1999/05/17 02:52:29 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
  vmtype.h - VM types
 
12
Function
 
13
  
 
14
Notes
 
15
  
 
16
Modified
 
17
  10/21/98 MJRoberts  - Creation
 
18
*/
 
19
 
 
20
#ifndef VMTYPE_H
 
21
#define VMTYPE_H
 
22
 
 
23
#include <string.h>
 
24
#include <stdlib.h>
 
25
 
 
26
#include "t3std.h"
 
27
#include "vmerr.h"
 
28
#include "vmerrnum.h"
 
29
#include "vmglob.h"
 
30
 
 
31
 
 
32
/*
 
33
 *   Constant pool/code offset.  This is an address of an object in the
 
34
 *   pool.  Pool offsets are 32-bit values.  
 
35
 */
 
36
typedef uint32 pool_ofs_t;
 
37
 
 
38
/*
 
39
 *   Savepoint ID's are stored in a single byte; since we store many
 
40
 *   copies of savepoint ID's (since they need to be stored with each undo
 
41
 *   list head), we want to save some space on this type.  This limits us
 
42
 *   to 256 simultaneous savepoints, but this should be more than we
 
43
 *   actually want to keep around anyway, because of the amount of memory
 
44
 *   it would consume to try to keep more than that around.  
 
45
 */
 
46
typedef uchar vm_savept_t;
 
47
const vm_savept_t VM_SAVEPT_MAX = 255;
 
48
 
 
49
/* 
 
50
 *   Object ID type.  VM_INVALID_OBJ is a distinguished value that serves
 
51
 *   as an invalid object ID (a null pointer, effectively); no object can
 
52
 *   ever have this ID.  
 
53
 */
 
54
typedef uint32 vm_obj_id_t;
 
55
const vm_obj_id_t VM_INVALID_OBJ = 0;
 
56
 
 
57
/*
 
58
 *   Property ID.  Property ID's are 16-bit values.  VM_INVALID_PROP is a
 
59
 *   distinguished value that serves as an invalid property ID, which can
 
60
 *   be used to indicate the absence of a property value.  
 
61
 */
 
62
typedef uint16 vm_prop_id_t;
 
63
const vm_prop_id_t VM_INVALID_PROP = 0;
 
64
 
 
65
/*
 
66
 *   Maximum recursion depth for recursive equality tests and hash
 
67
 *   calculations.
 
68
 *   
 
69
 *   When we're comparing or hashing a tree of references by value, such as
 
70
 *   when we're comparing two vectors or hashing a vector, we'll keep track
 
71
 *   of the recursion depth of our tree traversal.  If we reach this depth,
 
72
 *   we'll throw an error on the assumption that the tree contains cycles and
 
73
 *   thus cannot be hashed or compared by value.  This depth is chosen to be
 
74
 *   large enough that it's unlikely we'll exceed it with acyclical trees,
 
75
 *   but small enough that we probably won't blow the C++ stack before we
 
76
 *   reach this depth.  
 
77
 */
 
78
const int VM_MAX_TREE_DEPTH_EQ = 256;
 
79
 
 
80
/*
 
81
 *   Datatypes
 
82
 */
 
83
enum vm_datatype_t
 
84
{
 
85
    /* nil - doubles as a null pointer and a boolean false */
 
86
    VM_NIL = 1,
 
87
 
 
88
    /* true - boolean true */
 
89
    VM_TRUE,
 
90
 
 
91
    /* 
 
92
     *   Stack pointer (this is used to store a pointer to the enclosing
 
93
     *   frame in a stack frame).  This is a native machine pointer.  
 
94
     */
 
95
    VM_STACK,
 
96
 
 
97
    /* 
 
98
     *   Code pointer (this is used to store a pointer to the return
 
99
     *   address in a stack frame, for example).  This is a native machine
 
100
     *   pointer.  This differs from VM_CODEOFS in that this is a native
 
101
     *   machine pointer.  
 
102
     */
 
103
    VM_CODEPTR,
 
104
 
 
105
    /* object reference */
 
106
    VM_OBJ,
 
107
 
 
108
    /* property ID */
 
109
    VM_PROP,
 
110
 
 
111
    /* 32-bit signed integer */
 
112
    VM_INT,
 
113
    
 
114
    /* 
 
115
     *   string constant value - the value is an offset into the constant
 
116
     *   pool of the string descriptor 
 
117
     */
 
118
    VM_SSTRING,
 
119
    
 
120
    /* 
 
121
     *   self-printing string value - the value is an offset into the
 
122
     *   constant pool of the string descriptor 
 
123
     */
 
124
    VM_DSTRING,
 
125
 
 
126
    /* 
 
127
     *   list constant - the value is an offset into the constant pool of
 
128
     *   the list descriptor 
 
129
     */
 
130
    VM_LIST,
 
131
 
 
132
    /* 
 
133
     *   byte-code constant offset - this is an offset into the byte-code
 
134
     *   pool.  This differs from VM_CODEPTR in that this is an offset in
 
135
     *   the byte-code constant pool rather than a native machine pointer.
 
136
     *   
 
137
     */
 
138
    VM_CODEOFS,
 
139
 
 
140
    /*
 
141
     *   function pointer - this is represented as an offset into the
 
142
     *   byte-code pool.  This differs from VM_CODEOFS in that the code
 
143
     *   referenced by a VM_CODEOFS value is generally invoked directly
 
144
     *   whenever the value is evaluated, whereas VM_FUNCPTR values are
 
145
     *   used to convey function pointers, so the underlying code is not
 
146
     *   executed implicitly on evaluation of such a value but must be
 
147
     *   explicitly invoked. 
 
148
     */
 
149
    VM_FUNCPTR,
 
150
 
 
151
    /*
 
152
     *   This is a special pseudo-type used to indicate that a value is
 
153
     *   not present.  This differs from nil, in that nil is a null
 
154
     *   reference or false value, whereas this indicates that there's no
 
155
     *   specified value at all.  This is used, for example, to indicate
 
156
     *   in an undo record that a property did not previously exist. 
 
157
     */
 
158
    VM_EMPTY,
 
159
 
 
160
    /*
 
161
     *   This is a special pseudo-type used to indicate that evaluating an
 
162
     *   expression requires executing system code.  The value stored is a
 
163
     *   pointer to a constant CVmNativeCodeDesc object, which describes a
 
164
     *   native code method.  
 
165
     */
 
166
    VM_NATIVE_CODE,
 
167
 
 
168
    /*
 
169
     *   Enumerated constant 
 
170
     */
 
171
    VM_ENUM,
 
172
 
 
173
    /*
 
174
     *   First invalid type ID.  Tools (such as compilers and debuggers)
 
175
     *   can use this ID and any higher ID values to flag their own
 
176
     *   internal types.  
 
177
     */
 
178
    VM_FIRST_INVALID_TYPE
 
179
};
 
180
 
 
181
/* macro to create a private type constant for internal use in a tool */
 
182
#define VM_MAKE_INTERNAL_TYPE(idx) \
 
183
    ((vm_datatype_t)(((int)VM_FIRST_INVALID_TYPE) + (idx)))
 
184
 
 
185
/*
 
186
 *   Value container.  Local variables, stack locations, and other value
 
187
 *   holders use this structure to store a value and its type.  
 
188
 */
 
189
struct vm_val_t
 
190
{
 
191
    vm_datatype_t typ;
 
192
    union
 
193
    {
 
194
        /* stack/code pointer */
 
195
        void *ptr;
 
196
 
 
197
        /* object reference */
 
198
        vm_obj_id_t obj;
 
199
 
 
200
        /* property ID */
 
201
        vm_prop_id_t prop;
 
202
 
 
203
        /* 32-bit integer */
 
204
        int32 intval;
 
205
 
 
206
        /* enumerated constant */
 
207
        uint32 enumval;
 
208
 
 
209
        /* sstring/dstring/list constant pool offset/pcode pool offset */
 
210
        pool_ofs_t ofs;
 
211
 
 
212
        /* native code descriptor */
 
213
        const class CVmNativeCodeDesc *native_desc;
 
214
    } val;
 
215
 
 
216
    /* set various types of values */
 
217
    void set_empty() { typ = VM_EMPTY; }
 
218
    void set_nil() { typ = VM_NIL; }
 
219
    void set_true() { typ = VM_TRUE; }
 
220
    void set_stack(void *ptr) { typ = VM_STACK; val.ptr = ptr; }
 
221
    void set_codeptr(void *ptr) { typ = VM_CODEPTR; val.ptr = ptr; }
 
222
    void set_obj(vm_obj_id_t obj) { typ = VM_OBJ; val.obj = obj; }
 
223
    void set_nil_obj() { typ = VM_NIL; val.obj = VM_INVALID_OBJ; }
 
224
    void set_propid(vm_prop_id_t prop) { typ = VM_PROP; val.prop = prop; }
 
225
    void set_int(int32 intval) { typ = VM_INT; val.intval = intval; }
 
226
    void set_enum(uint32 enumval) { typ = VM_ENUM; val.enumval = enumval; }
 
227
    void set_sstring(pool_ofs_t ofs) { typ = VM_SSTRING; val.ofs = ofs; }
 
228
    void set_dstring(pool_ofs_t ofs) { typ = VM_DSTRING; val.ofs = ofs; }
 
229
    void set_list(pool_ofs_t ofs) { typ = VM_LIST; val.ofs = ofs; }
 
230
    void set_codeofs(pool_ofs_t ofs) { typ = VM_CODEOFS; val.ofs = ofs; }
 
231
    void set_fnptr(pool_ofs_t ofs) { typ = VM_FUNCPTR; val.ofs = ofs; }
 
232
    void set_native(const class CVmNativeCodeDesc *desc)
 
233
        { typ = VM_NATIVE_CODE; val.native_desc = desc; }
 
234
 
 
235
    /* 
 
236
     *   set an object or nil value: if the object ID is VM_INVALID_OBJ,
 
237
     *   we'll set the type to nil 
 
238
     */
 
239
    void set_obj_or_nil(vm_obj_id_t obj)
 
240
    {
 
241
        /* set the object value initially */
 
242
        typ = VM_OBJ;
 
243
        val.obj = obj;
 
244
 
 
245
        /* if the object is invalid, set the type to nil */
 
246
        if (obj == VM_INVALID_OBJ)
 
247
            typ = VM_NIL;
 
248
    }
 
249
 
 
250
    /* set to an integer giving the datatype of the given value */
 
251
    void set_datatype(VMG_ const vm_val_t *val);
 
252
 
 
253
    /* set to nil if 'val' is zero, true if 'val' is non-zero */
 
254
    void set_logical(int v) { typ = (v != 0 ? VM_TRUE : VM_NIL); }
 
255
 
 
256
    /* determine if the value is logical (nil or true) */
 
257
    int is_logical() const { return (typ == VM_NIL || typ == VM_TRUE); }
 
258
 
 
259
    /* 
 
260
     *   Get a logical as numeric TRUE or FALSE.  This does not perform
 
261
     *   any type checking; the caller must ensure that the value is
 
262
     *   either true or nil, or this may return meaningless results.  
 
263
     */
 
264
    int get_logical() const { return (typ == VM_TRUE); }
 
265
 
 
266
    /*
 
267
     *   Get the underlying string constant value.  If the value does not
 
268
     *   have an underlying string constant (because it is of a type that
 
269
     *   does not store a string value), this will return null. 
 
270
     */
 
271
    const char *get_as_string(VMG0_) const;
 
272
 
 
273
    /*
 
274
     *   Get the underlying list constant value.  If the value does not
 
275
     *   have an underlying list constant (because it is of a type that
 
276
     *   does not store list data), this returns null. 
 
277
     */
 
278
    const char *get_as_list(VMG0_) const;
 
279
 
 
280
    /*
 
281
     *   Get the effective number of elements from this value when the
 
282
     *   value is used as the right-hand side of a '+' or '-' operator
 
283
     *   whose left-hand side implies that the operation involved is a set
 
284
     *   operation (this is the case is the left-hand side is of certain
 
285
     *   collection types, such as list, array, or vector); and get the
 
286
     *   nth element in that context.  Most types of values contribute
 
287
     *   only one element to these operations, but some collection types
 
288
     *   supply their elements individually, rather than the collection
 
289
     *   itself, for these operations.  'idx' is the 1-based index of the
 
290
     *   element to retrieve.  
 
291
     */
 
292
    size_t get_coll_addsub_rhs_ele_cnt(VMG0_) const;
 
293
    void get_coll_addsub_rhs_ele(VMG_ size_t idx, vm_val_t *result) const;
 
294
 
 
295
    /*
 
296
     *   Convert a numeric value to an integer value.  If the value isn't
 
297
     *   numeric, throws an error. 
 
298
     */
 
299
    void num_to_logical()
 
300
    {
 
301
        /* check the type */
 
302
        if (typ == VM_INT)
 
303
        {
 
304
            /* it's an integer - treat 0 as nil, all else as true */
 
305
            typ = (val.intval == 0 ? VM_NIL : VM_TRUE);
 
306
        }
 
307
        else
 
308
        {
 
309
            /* it's not a number - throw an error */
 
310
            err_throw(VMERR_NO_LOG_CONV);
 
311
        }
 
312
    }
 
313
 
 
314
    /* determine if the value is some kind of number */
 
315
    int is_numeric() const { return (typ == VM_INT); }
 
316
 
 
317
    /*
 
318
     *   Convert a numeric value to an integer.  If the value is not
 
319
     *   numeric, we'll throw an error. 
 
320
     */
 
321
    int32 num_to_int() const
 
322
    {
 
323
        /* check the type */
 
324
        if (typ == VM_INT)
 
325
        {
 
326
            /* it's an integer already - return the value directly */
 
327
            return val.intval;
 
328
        }
 
329
        else
 
330
        {
 
331
            /* 
 
332
             *   other types are not numeric and can't be directly
 
333
             *   converted to integer by arithmetic conversion
 
334
             */
 
335
            err_throw(VMERR_NUM_VAL_REQD);
 
336
 
 
337
            /* the compiler might not know we'll never get here */
 
338
            AFTER_ERR_THROW(return 0;)
 
339
        }
 
340
    }
 
341
 
 
342
    /* 
 
343
     *   determine if the numeric value is zero; throws an error if the
 
344
     *   value is not numeric 
 
345
     */
 
346
    int num_is_zero() const
 
347
    {
 
348
        /* check the type */
 
349
        if (typ == VM_INT)
 
350
        {
 
351
            /* check the integer value to see if it's zero */
 
352
            return (val.intval == 0);
 
353
        }
 
354
        else
 
355
        {
 
356
            /* it's not a number */
 
357
            err_throw(VMERR_NUM_VAL_REQD);
 
358
 
 
359
            /* in case the compiler doesn't know we'll never get here */
 
360
            AFTER_ERR_THROW(return 0;)
 
361
        }
 
362
    }
 
363
 
 
364
    /*
 
365
     *   Determine if this value equals a given value.  The nature of the
 
366
     *   match depends on the type of this value:
 
367
     *   
 
368
     *   integers, property ID's, code offsets: the types and values must
 
369
     *   match exactly.
 
370
     *   
 
371
     *   string and list constants: the other value must either be the same
 
372
     *   type of constant, or an object that has an underlying value of the
 
373
     *   same type; and the contents of the strings or lists must match.
 
374
     *   
 
375
     *   objects: the match depends on the type of the object.  We invoke the
 
376
     *   object's virtual equals() routine to make this determination.
 
377
     *   
 
378
     *   'depth' has the same meaning as in calc_hash().  
 
379
     */
 
380
    int equals(VMG_ const vm_val_t *v) const { return equals(vmg_ v, 0); }
 
381
    int equals(VMG_ const vm_val_t *val, int depth) const;
 
382
 
 
383
    /*
 
384
     *   Calculate a hash for the value.  The meaning of the hash varies by
 
385
     *   type, but is stable for a given value.  'depth' is a recursion depth
 
386
     *   counter, with the same meaning as in CVmObject::calc_hash().  
 
387
     */
 
388
    uint calc_hash(VMG0_) const { return calc_hash(vmg_ 0); }
 
389
    uint calc_hash(VMG_ int depth) const;
 
390
 
 
391
    /*
 
392
     *   Compare this value to the given value.  Returns a value greater than
 
393
     *   zero if this value is greater than 'val', a value less than zero if
 
394
     *   this value is less than 'val', or 0 if the two values are equal.
 
395
     *   Throws an error if the two values are not comparable.
 
396
     *   
 
397
     *   By far the most common type of comparison is between integers, so we
 
398
     *   test in-line to see if we have two integer values, and if so, use a
 
399
     *   fast in-line comparison.  If we don't have two integers, we'll use
 
400
     *   our full out-of-line test, which will look at other more interesting
 
401
     *   type combinations.  
 
402
     */
 
403
    int compare_to(VMG_ const vm_val_t *b) const
 
404
    {
 
405
        if (typ == VM_INT && b->typ == VM_INT)
 
406
            return (val.intval > b->val.intval
 
407
                    ? 1 : val.intval < b->val.intval ? -1 : 0);
 
408
        else
 
409
            return gen_compare_to(vmg_ b);
 
410
    }
 
411
 
 
412
    /*
 
413
     *   relative value comparisons 
 
414
     */
 
415
 
 
416
    /* self > b */
 
417
    int is_gt(VMG_ const vm_val_t *b) const
 
418
    {
 
419
        if (typ == VM_INT && b->typ == VM_INT)
 
420
            return val.intval > b->val.intval;
 
421
        else
 
422
            return gen_compare_to(vmg_ b) > 0;
 
423
    }
 
424
 
 
425
    /* self >= b */
 
426
    int is_ge(VMG_ const vm_val_t *b) const
 
427
    {
 
428
        if (typ == VM_INT && b->typ == VM_INT)
 
429
            return val.intval >= b->val.intval;
 
430
        else
 
431
            return gen_compare_to(vmg_ b) >= 0;
 
432
    }
 
433
 
 
434
    /* self < b */
 
435
    int is_lt(VMG_ const vm_val_t *b) const
 
436
    {
 
437
        if (typ == VM_INT && b->typ == VM_INT)
 
438
            return val.intval < b->val.intval;
 
439
        else
 
440
            return gen_compare_to(vmg_ b) < 0;
 
441
    }
 
442
 
 
443
    /* self <= b */
 
444
    int is_le(VMG_ const vm_val_t *b) const
 
445
    {
 
446
        if (typ == VM_INT && b->typ == VM_INT)
 
447
            return val.intval <= b->val.intval;
 
448
        else
 
449
            return gen_compare_to(vmg_ b) <= 0;
 
450
    }
 
451
 
 
452
private:
 
453
    /* out-of-line comparison, used when we don't have two integers */
 
454
    int gen_compare_to(VMG_ const vm_val_t *val) const;
 
455
};
 
456
 
 
457
/* ------------------------------------------------------------------------ */
 
458
/*
 
459
 *   Native code descriptor.  This describes a native method call of an
 
460
 *   intrinsic class object.  
 
461
 */
 
462
class CVmNativeCodeDesc
 
463
{
 
464
public:
 
465
    /* create a descriptor with an exact number of arguments */
 
466
    CVmNativeCodeDesc(int argc)
 
467
    {
 
468
        /* remember the parameters - there are no optional arguments */
 
469
        min_argc_ = argc;
 
470
        opt_argc_ = 0;
 
471
        varargs_ = FALSE;
 
472
    }
 
473
 
 
474
    /* create a descriptor with optional arguments (but not varargs) */
 
475
    CVmNativeCodeDesc(int min_argc, int opt_argc)
 
476
    {
 
477
        /* remember the parameters */
 
478
        min_argc_ = min_argc;
 
479
        opt_argc_ = opt_argc;
 
480
        varargs_ = FALSE;
 
481
    }
 
482
 
 
483
    /* create a descriptor with optional arguments and/or varargs */
 
484
    CVmNativeCodeDesc(int min_argc, int opt_argc, int varargs)
 
485
    {
 
486
        /* remember the parameters */
 
487
        min_argc_ = min_argc;
 
488
        opt_argc_ = opt_argc;
 
489
        varargs_ = varargs;
 
490
    }
 
491
 
 
492
    /* check the given number of arguments for validity */
 
493
    int args_ok(int argc) const
 
494
    {
 
495
        /* 
 
496
         *   the actual parameters must number at least the minimum, and
 
497
         *   cannot exceed the maximum (i.e., the minimum plus the
 
498
         *   optionals) unless we have varargs, in which case there is no
 
499
         *   maximum 
 
500
         */
 
501
        return (argc >= min_argc_
 
502
                && (varargs_ || argc <= min_argc_ + opt_argc_));
 
503
    }
 
504
 
 
505
    /* minimum argument count */
 
506
    int min_argc_;
 
507
 
 
508
    /* number of optional named arguments beyond the minimum */
 
509
    int opt_argc_;
 
510
 
 
511
    /* 
 
512
     *   true -> varargs: any number of arguments greater than or equal to
 
513
     *   min_argc_ are valid
 
514
     */
 
515
    int varargs_;
 
516
};
 
517
 
 
518
/* ------------------------------------------------------------------------ */
 
519
/*
 
520
 *   String handling - these routines are provided as covers to allow for
 
521
 *   easier adjustment for Unicode or other encodings.  Don't include these
 
522
 *   if we're compiling interface routines for the HTML TADS environment,
 
523
 *   since HTML TADS has its own similar definitions for these, and we don't
 
524
 *   need these for interface code.
 
525
 *   
 
526
 *   NOTE: The purpose of this macro is to indicate that we're being
 
527
 *   #included by an HTML TADS source file - that is, the current compile run
 
528
 *   is for an htmltads/xxx.cpp file.  Do NOT #define this macro when
 
529
 *   compiling tads3/xxx.cpp files.  The tads3/xxx.cpp files have absolutely
 
530
 *   no explicit dependencies on the htmltads subsystem and thus don't
 
531
 *   #include the htmltads headers that would provide the conflicting
 
532
 *   interface definitions for these functions.  The conflict is in the other
 
533
 *   direction: some of the htmltads source files explicitly depend on tads3
 
534
 *   headers, so they indirectly #include this header.  So, this macro needs
 
535
 *   to be defined only when compiling htmltads/xxx.cpp files.  
 
536
 */
 
537
#ifdef T3_COMPILING_FOR_HTML
 
538
#include "tadshtml.h"
 
539
#else
 
540
 
 
541
inline size_t get_strlen(const textchar_t *str) { return strlen(str); }
 
542
inline void do_strcpy(textchar_t *dst, const textchar_t *src)
 
543
    { strcpy(dst, src); }
 
544
 
 
545
#endif /* T3_COMPILING_FOR_HTML */
 
546
 
 
547
/* ------------------------------------------------------------------------ */
 
548
/*
 
549
 *   Portable Binary Representations.  When we store certain types of
 
550
 *   information in memory, we store it in a format that is identical to
 
551
 *   the format we use in portable binary files; using this format allows
 
552
 *   us to read and write binary files as byte images, without any
 
553
 *   interpretation, which greatly improves I/O performance in many cases.
 
554
 */
 
555
 
 
556
/*
 
557
 *   Portable binary LENGTH indicator.  This is used to store length
 
558
 *   prefixes for strings, lists, and similar objects.  We use a UINT2
 
559
 *   (16-bit unsigned integer) for this type of value.  
 
560
 */
 
561
const size_t VMB_LEN = 2;
 
562
inline void vmb_put_len(char *buf, size_t len) { oswp2(buf, len); }
 
563
inline size_t vmb_get_len(const char *buf) { return osrp2(buf); }
 
564
 
 
565
/*
 
566
 *   Portable binary unsigned 2-byte integer 
 
567
 */
 
568
const size_t VMB_UINT2 = 2;
 
569
inline void vmb_put_uint2(char *buf, uint16 i) { oswp2(buf, i); }
 
570
inline uint16 vmb_get_uint2(const char *buf) { return osrp2(buf); }
 
571
 
 
572
/*
 
573
 *   Portable binary object ID. 
 
574
 */
 
575
const size_t VMB_OBJECT_ID = 4;
 
576
inline void vmb_put_objid(char *buf, vm_obj_id_t obj) { oswp4(buf, obj); }
 
577
inline vm_obj_id_t vmb_get_objid(const char *buf) { return t3rp4u(buf); }
 
578
 
 
579
/*
 
580
 *   Portable binary property ID 
 
581
 */
 
582
const size_t VMB_PROP_ID = 2;
 
583
inline void vmb_put_propid(char *buf, vm_obj_id_t prop) { oswp2(buf, prop); }
 
584
inline vm_prop_id_t vmb_get_propid(const char *buf) { return osrp2(buf); }
 
585
 
 
586
/*
 
587
 *   Portable data holder.  This is used to store varying-type data items;
 
588
 *   for example, this is used to store an element in a list, or the value
 
589
 *   of a property in an object.  This type of value stores a one-byte
 
590
 *   prefix indicating the type of the value, and a four-byte area in
 
591
 *   which the value is stored.  The actual use of the four-byte value
 
592
 *   area depends on the type.  
 
593
 */
 
594
const size_t VMB_DATAHOLDER = 5;
 
595
 
 
596
/* offset from a portable data holder pointer to the data value */
 
597
const size_t VMB_DH_DATAOFS = 1;
 
598
 
 
599
/* store a portable dataholder from a vm_val_t */
 
600
void vmb_put_dh(char *buf, const vm_val_t *val);
 
601
 
 
602
/* store a nil value in a portable dataholder */
 
603
inline void vmb_put_dh_nil(char *buf) { buf[0] = VM_NIL; }
 
604
 
 
605
/* store an object value in a portable dataholder */
 
606
inline void vmb_put_dh_obj(char *buf, vm_obj_id_t obj)
 
607
    { buf[0] = VM_OBJ; vmb_put_objid(buf + 1, obj); }
 
608
 
 
609
/* store a property value in a portable dataholder */
 
610
inline void vmb_put_dh_prop(char *buf, vm_prop_id_t prop)
 
611
    { buf[0] = VM_PROP; vmb_put_propid(buf + 1, prop); }
 
612
 
 
613
/* get the value portion of a vm_val_t from a portable dataholder */
 
614
void vmb_get_dh_val(const char *buf, vm_val_t *val);
 
615
 
 
616
/* get the type from a portable dataholder */
 
617
inline vm_datatype_t vmb_get_dh_type(const char *buf)
 
618
    { return (vm_datatype_t)buf[0]; }
 
619
 
 
620
/* get a vm_val_t from a portable dataholder */
 
621
inline void vmb_get_dh(const char *buf, vm_val_t *val)
 
622
    { val->typ = vmb_get_dh_type(buf); vmb_get_dh_val(buf, val); }
 
623
 
 
624
/* get an object value from a portable dataholder */
 
625
inline vm_obj_id_t vmb_get_dh_obj(const char *buf)
 
626
    { return (vm_obj_id_t)t3rp4u(buf+1); }
 
627
 
 
628
/* get an integer value from a portable dataholder */
 
629
inline int32 vmb_get_dh_int(const char *buf)
 
630
    { return (int32)osrp4(buf+1); }
 
631
 
 
632
/* get a property ID value from a portable dataholder */
 
633
inline vm_prop_id_t vmb_get_dh_prop(const char *buf)
 
634
    { return (vm_prop_id_t)osrp2(buf+1); }
 
635
 
 
636
/* get a constant offset value from a portable dataholder */
 
637
inline pool_ofs_t vmb_get_dh_ofs(const char *buf)
 
638
    { return (pool_ofs_t)t3rp4u(buf+1); }
 
639
 
 
640
 
 
641
#endif /* VMTYPE_H */
 
642