src/Types.h
author David Anderson <dvander@alliedmods.net>
Tue Dec 25 16:32:06 2012 -0800 (2012-12-25)
changeset 238 e9bec7549c28
parent 236 072f1114ea5d
child 239 572668ef742b
permissions -rw-r--r--
Preparatory refactoring for const types.
dvander@238
     1
/* vim: set ts=4 sw=4 tw=99 et:
dvander@238
     2
 *
dvander@238
     3
 * Copyright (C) 2012 David Anderson
dvander@238
     4
 *
dvander@238
     5
 * This file is part of JITCraft.
dvander@238
     6
 *
dvander@238
     7
 * JITCraft is free software: you can redistribute it and/or modify it under
dvander@238
     8
 * the terms of the GNU General Public License as published by the Free
dvander@238
     9
 * Software Foundation, either version 3 of the License, or (at your option)
dvander@238
    10
 * any later version.
dvander@238
    11
 * 
dvander@238
    12
 * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
dvander@238
    13
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
dvander@238
    14
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
dvander@238
    15
 *
dvander@238
    16
 * You should have received a copy of the GNU General Public License along with
dvander@238
    17
 * JITCraft. If not, see http://www.gnu.org/licenses/.
dvander@238
    18
 */
dvander@238
    19
#ifndef _include_jc_types_h_
dvander@238
    20
#define _include_jc_types_h_
dvander@238
    21
dvander@238
    22
#include "Heap.h"
dvander@238
    23
#include "Barriers.h"
dvander@238
    24
#include "FixedArray.h"
dvander@238
    25
#include "compiler/Token.h"
dvander@238
    26
dvander@238
    27
namespace ke {
dvander@238
    28
dvander@238
    29
class String;
dvander@238
    30
class Descriptor;
dvander@238
    31
class StructMap;
dvander@238
    32
class ArrayMap;
dvander@238
    33
dvander@238
    34
#define MAX_ARRAY_DEPTH     5
dvander@238
    35
dvander@238
    36
enum PrimitiveType
dvander@238
    37
{
dvander@238
    38
    // A boolean type semantically represents 0 or 1. As an optimization, its
dvander@238
    39
    // internal storage type is the same as int32, and any non-zero value
dvander@238
    40
    // compares positively to "true".
dvander@238
    41
    PrimitiveType_Bool,
dvander@238
    42
dvander@238
    43
    // A character is an arbitrary 8-bit value. Characters are not supported
dvander@238
    44
    // as a normal storage class; they may only be used for arrays. When read
dvander@238
    45
    // from an array, they are immediately sign extended to 32 bits. Integers
dvander@238
    46
    // stored into an char array are truncated to 8 bits.
dvander@238
    47
    PrimitiveType_Char,         // signed, 8-bit character
dvander@238
    48
dvander@238
    49
    // Enumerations and untyped variables are stored as signed, 32-bit integers.
dvander@238
    50
    PrimitiveType_Int32,
dvander@238
    51
dvander@238
    52
    // Floating point values are 32-bit IEEE-754 floats. This is required ro
dvander@238
    53
    // SourcePawn 1 compatibility.
dvander@238
    54
    PrimitiveType_Float,
dvander@238
    55
dvander@238
    56
    // This is a native-sized integer type (32-bit on 32-bit systems, 64-bit
dvander@238
    57
    // on 64-bit systems), and does not exist in language semantics.
dvander@238
    58
    PrimitiveType_Native,
dvander@238
    59
dvander@238
    60
    PrimitiveTypes_Total
dvander@238
    61
};
dvander@238
    62
dvander@238
    63
enum TypeQualifiers
dvander@238
    64
{
dvander@238
    65
    TypeQual_None           = 0,
dvander@238
    66
dvander@238
    67
    // Const qualifier that has not been determined yet.
dvander@238
    68
    TypeQual_UnkConst       = (1 << 0),
dvander@238
    69
dvander@238
    70
    // For simplification, SP2 differentiates between two meanings of const.
dvander@238
    71
    // "StoreConst" means that the value itself may not be changed. For
dvander@238
    72
    // example,
dvander@238
    73
    //     const a = 5;
dvander@238
    74
    //
dvander@238
    75
    // Specifies that the storage of "a" is immutable.
dvander@238
    76
    //
dvander@238
    77
    // In addition, "RefConst" means that the memory at a reference may not
dvander@238
    78
    // be changed. For example,
dvander@238
    79
    //
dvander@238
    80
    //     const char:text[] = "asdfasdfasdf";
dvander@238
    81
    //
dvander@238
    82
    // Specifies a readonly view of a character array, however, |text| itself
dvander@238
    83
    // may be repointed to another readonly character array.
dvander@238
    84
    //
dvander@238
    85
    // The meaning of "const" is inferred based on the scope and type:
dvander@238
    86
    //
dvander@238
    87
    //                   +---------+---------+-------+
dvander@238
    88
    //                   | Array   | Struct  | Other |
dvander@238
    89
    //   +---------------+---------+---------+-------+
dvander@238
    90
    //   | GLOBAL/STATIC | Ref|Str | Ref|Str | Str   |
dvander@238
    91
    //   | LOCAL         | Ref     | Ref|Str | Str   |
dvander@238
    92
    //   +---------------+---------+---------+-------+
dvander@238
    93
    TypeQual_StoreConst     = (1 << 1),
dvander@238
    94
    TypeQual_RefConst       = (1 << 2)
dvander@238
    95
};
dvander@238
    96
dvander@238
    97
class Type : public Object
dvander@238
    98
{
dvander@238
    99
  protected:
dvander@238
   100
    enum Kind {
dvander@238
   101
        // A primitive is a plain-old-data type.
dvander@238
   102
        PRIMITIVE,
dvander@238
   103
dvander@238
   104
        // Void is an internal type used to specify that a function returns no
dvander@238
   105
        // value.
dvander@238
   106
        VOID,
dvander@238
   107
dvander@238
   108
        // Enums are plain-old-data with int32 storage. They allow for extra
dvander@238
   109
        // type checking that would not be possible with integers.
dvander@238
   110
        ENUM,
dvander@238
   111
dvander@238
   112
        // Unchecked is a magic type that has implicit, bitwise coercion to
dvander@238
   113
        // int32, float, bool, or an enum.
dvander@238
   114
        UNCHECKED,
dvander@238
   115
dvander@238
   116
        // ------ Add traceable types below -------
dvander@238
   117
dvander@238
   118
        // An immutable type that is a primitive in terms of language
dvander@238
   119
        // semantics, but gets a special type here to make internal
dvander@238
   120
        // logic easier.
dvander@238
   121
        STRING,
dvander@238
   122
dvander@238
   123
        // An array is a fixed-length vector of any other type.
dvander@238
   124
        ARRAY,
dvander@238
   125
        EXTERNAL_ARRAY,
dvander@238
   126
dvander@238
   127
        // A reference type may only be specified on parameters, and
dvander@238
   128
        // references may only be computed to primitives or enums.
dvander@238
   129
        REFERENCE,
dvander@238
   130
dvander@238
   131
        // A function type encapsulates a function signature.
dvander@238
   132
        FUNCTION,
dvander@238
   133
dvander@238
   134
        // Structs are composite records that may contain primitives, arrays,
dvander@238
   135
        // functions, enums, and other structs.
dvander@238
   136
        STRUCT,
dvander@238
   137
dvander@238
   138
        // Contains type qualifiers, and a back pointer to the actual
dvander@238
   139
        // unqualified type.
dvander@238
   140
        QUALTYPE
dvander@238
   141
    };
dvander@238
   142
dvander@238
   143
    void init(Kind kind);
dvander@238
   144
dvander@238
   145
  private:
dvander@238
   146
    Kind kind() {
dvander@238
   147
        return root_->kind_;
dvander@238
   148
    }
dvander@238
   149
dvander@238
   150
  public:   
dvander@238
   151
    static Type *NewVoid(Zone *zone);
dvander@238
   152
    static Type *NewUnchecked(Zone *zone);
dvander@238
   153
    static Type *NewPrimitive(Zone *zone, PrimitiveType type);
dvander@238
   154
    static Type *NewString(Zone *zone);
dvander@238
   155
dvander@238
   156
    static Type *cast(Object *obj) {
dvander@238
   157
        assert(!obj ||
dvander@238
   158
               obj->is(MapKind_Type) ||
dvander@238
   159
               obj->is(MapKind_FunctionType) ||
dvander@238
   160
               obj->is(MapKind_StructType) ||
dvander@238
   161
               obj->is(MapKind_ArrayType) ||
dvander@238
   162
               obj->is(MapKind_ReferenceType) ||
dvander@238
   163
               obj->is(MapKind_EnumType));
dvander@238
   164
        return (Type *)obj;
dvander@238
   165
    }
dvander@238
   166
dvander@238
   167
    bool isPrimitive() {
dvander@238
   168
        return kind() == PRIMITIVE;
dvander@238
   169
    }
dvander@238
   170
    bool isArray() {
dvander@238
   171
        return kind() == ARRAY || kind() == EXTERNAL_ARRAY;
dvander@238
   172
    }
dvander@238
   173
    bool isReference() {
dvander@238
   174
        return kind() == REFERENCE;
dvander@238
   175
    }
dvander@238
   176
    bool isFunction() {
dvander@238
   177
        return kind() == FUNCTION;
dvander@238
   178
    }
dvander@238
   179
    bool isVoid() {
dvander@238
   180
        return kind() == VOID;
dvander@238
   181
    }
dvander@238
   182
    bool isUnchecked() {
dvander@238
   183
        return kind() == UNCHECKED;
dvander@238
   184
    }
dvander@238
   185
    bool isStruct() {
dvander@238
   186
        return kind() == STRUCT;
dvander@238
   187
    }
dvander@238
   188
    PrimitiveType primitive() {
dvander@238
   189
        assert(isPrimitive());
dvander@238
   190
        return root_->primitive_;
dvander@238
   191
    }
dvander@238
   192
    bool isPod() {
dvander@238
   193
        return (isPrimitive() && !isString()) || isEnum() || isUnchecked();
dvander@238
   194
    }
dvander@238
   195
    PrimitiveType pod() {
dvander@238
   196
        assert(isPod());
dvander@238
   197
        return isPrimitive()
dvander@238
   198
               ? (primitive() == PrimitiveType_Bool)
dvander@238
   199
                 ? PrimitiveType_Int32
dvander@238
   200
                 : primitive()
dvander@238
   201
               : PrimitiveType_Int32;
dvander@238
   202
    }
dvander@238
   203
    bool isChar() {
dvander@238
   204
        return isPrimitive() && primitive() == PrimitiveType_Char;
dvander@238
   205
    }
dvander@238
   206
    bool isFloat() {
dvander@238
   207
        return isPrimitive() && primitive() == PrimitiveType_Float;
dvander@238
   208
    }
dvander@238
   209
    bool isInt32() {
dvander@238
   210
        return isPrimitive() && primitive() == PrimitiveType_Int32;
dvander@238
   211
    }
dvander@238
   212
    bool isInt32OrEnum() {
dvander@238
   213
        return isInt32() || isEnum();
dvander@238
   214
    }
dvander@238
   215
    bool isBool() {
dvander@238
   216
        return isPrimitive() && primitive() == PrimitiveType_Bool;
dvander@238
   217
    }
dvander@238
   218
    bool isString() {
dvander@238
   219
        return kind() == STRING;
dvander@238
   220
    }
dvander@238
   221
    bool isExternalArray() {
dvander@238
   222
        return kind() == EXTERNAL_ARRAY;
dvander@238
   223
    }
dvander@238
   224
    bool isTraceable() {
dvander@238
   225
        return kind() >= STRING;
dvander@238
   226
    }
dvander@238
   227
    bool isEnum() {
dvander@238
   228
        return kind() == ENUM;
dvander@238
   229
    }
dvander@238
   230
    bool hasTypeQualifiers() {
dvander@238
   231
        return kind_ == QUALTYPE;
dvander@238
   232
    }
dvander@238
   233
dvander@238
   234
    TypeQualifiers quals() {
dvander@238
   235
        if (hasTypeQualifiers())
dvander@238
   236
            return TypeQual_None;
dvander@238
   237
        return quals_;
dvander@238
   238
    }
dvander@238
   239
dvander@238
   240
    // GC Descriptor.
dvander@238
   241
    static inline size_t offsetOfRoot() {
dvander@238
   242
        return OFFSETOF(Type, root_);
dvander@238
   243
    }
dvander@238
   244
    // End GC Descriptor.
dvander@238
   245
dvander@238
   246
  protected:
dvander@238
   247
    Kind kind_;
dvander@238
   248
    PrimitiveType primitive_;
dvander@238
   249
    TypeQualifiers quals_;
dvander@238
   250
dvander@238
   251
    // For unqualified types, this points to |this|. For qualified types, it
dvander@238
   252
    // points to the unqualified original type.
dvander@238
   253
    Barriered<Type> root_;
dvander@238
   254
};
dvander@238
   255
dvander@238
   256
class EnumType : public Type
dvander@238
   257
{
dvander@238
   258
  public:
dvander@238
   259
    static EnumType *New(Zone *Zone, Handle<String> name);
dvander@238
   260
dvander@238
   261
    String *name() {
dvander@238
   262
        return name_;
dvander@238
   263
    }
dvander@238
   264
dvander@238
   265
    // GC Descriptor.
dvander@238
   266
    static inline size_t offsetOfName() {
dvander@238
   267
        return OFFSETOF(EnumType, name_);
dvander@238
   268
    }
dvander@238
   269
    // End GC Descriptor.
dvander@238
   270
dvander@238
   271
    static EnumType *cast(Object *obj) {
dvander@238
   272
        assert(!obj || obj->is(MapKind_EnumType));
dvander@238
   273
        return (EnumType *)obj;
dvander@238
   274
    }
dvander@238
   275
dvander@238
   276
  private:
dvander@238
   277
    Barriered<String> name_;
dvander@238
   278
};
dvander@238
   279
dvander@238
   280
class ReferenceType : public Type
dvander@238
   281
{
dvander@238
   282
  public:
dvander@238
   283
    static ReferenceType *New(Zone *zone, Handle<Type> contained);
dvander@238
   284
    
dvander@238
   285
    Type *contained() {
dvander@238
   286
        return contained_;
dvander@238
   287
    }
dvander@238
   288
dvander@238
   289
    // GC Descriptor.
dvander@238
   290
    static inline size_t offsetOfContained() {
dvander@238
   291
        return OFFSETOF(ReferenceType, contained_);
dvander@238
   292
    }
dvander@238
   293
    // End GC Descriptor.
dvander@238
   294
dvander@238
   295
    static ReferenceType *cast(Object *obj) {
dvander@238
   296
        assert(!obj || obj->is(MapKind_ReferenceType));
dvander@238
   297
        return (ReferenceType *)obj;
dvander@238
   298
    }
dvander@238
   299
dvander@238
   300
  private:
dvander@238
   301
    Barriered<Type> contained_;
dvander@238
   302
};
dvander@238
   303
dvander@238
   304
class ArrayType : public Type
dvander@238
   305
{
dvander@238
   306
  public:
dvander@238
   307
    static const int DYNAMIC_ARRAY_SIZE = -1;
dvander@238
   308
dvander@238
   309
    static ArrayType *New(Zone *zone, Handle<Type> contained, int elements);
dvander@238
   310
    static ArrayType *NewExternal(Zone *zone, Handle<Type> contained);
dvander@238
   311
dvander@238
   312
    Type *innermost() {
dvander@238
   313
        Type *temp = contained();
dvander@238
   314
        while (temp->isArray())
dvander@238
   315
            temp = ArrayType::cast(temp)->contained();
dvander@238
   316
        return temp;
dvander@238
   317
    }
dvander@238
   318
dvander@238
   319
    Type *contained() {
dvander@238
   320
        return contained_;
dvander@238
   321
    }
dvander@238
   322
    bool isFixedLength() {
dvander@238
   323
        return elements_ > 0;
dvander@238
   324
    }
dvander@238
   325
    bool isCharArray() {
dvander@238
   326
        return contained()->isPrimitive() &&
dvander@238
   327
               contained()->primitive() == PrimitiveType_Char;
dvander@238
   328
    }
dvander@238
   329
    unsigned fixedLength() {
dvander@238
   330
        assert(isFixedLength());
dvander@238
   331
        return elements_;
dvander@238
   332
    }
dvander@238
   333
    unsigned levels() {
dvander@238
   334
        return levels_;
dvander@238
   335
    }
dvander@238
   336
    bool hasInlineElements() {
dvander@238
   337
        // We don't allocate traceable elements inline, since there's no
dvander@238
   338
        // point to the optimization; we're going to be allocating lots of
dvander@238
   339
        // objects anyway (in theory).
dvander@238
   340
        return isFixedLength() && !contained()->isTraceable();
dvander@238
   341
    }
dvander@238
   342
dvander@238
   343
    // Arrays of this type can be created with this cached map.
dvander@238
   344
    ArrayMap *newMap() {
dvander@238
   345
        return newMap_;
dvander@238
   346
    }
dvander@238
   347
    void setNewMap(ArrayMap *map) {
dvander@238
   348
        assert(!newMap());
dvander@238
   349
        newMap_ = map;
dvander@238
   350
    }
dvander@238
   351
dvander@238
   352
    // GC Descriptor.
dvander@238
   353
    static inline size_t offsetOfContained() {
dvander@238
   354
        return OFFSETOF(ArrayType, contained_);
dvander@238
   355
    }
dvander@238
   356
    static inline size_t offsetOfNewMap() {
dvander@238
   357
        return OFFSETOF(ArrayType, newMap_);
dvander@238
   358
    }
dvander@238
   359
    // End GC Descriptor.
dvander@238
   360
dvander@238
   361
    static ArrayType *cast(Object *obj) {
dvander@238
   362
        assert(!obj || obj->is(MapKind_ArrayType));
dvander@238
   363
        return (ArrayType *)obj;
dvander@238
   364
    }
dvander@238
   365
dvander@238
   366
  private:
dvander@238
   367
    int32 elements_;
dvander@238
   368
    unsigned levels_;
dvander@238
   369
    Barriered<Type> contained_;
dvander@238
   370
    Barriered<ArrayMap> newMap_;
dvander@238
   371
};
dvander@238
   372
dvander@238
   373
class StructType : public Type
dvander@238
   374
{
dvander@238
   375
  public:
dvander@238
   376
    static StructType *New(Zone *zone, Handle<String> name, Handle<FixedArray> fields);
dvander@238
   377
dvander@238
   378
    FixedArray *fields() {
dvander@238
   379
        assert(isStruct());
dvander@238
   380
        return fields_;
dvander@238
   381
    }
dvander@238
   382
    Descriptor *lookupField(Handle<String> name, unsigned *index = NULL);
dvander@238
   383
dvander@238
   384
    // Objects of this type can be created with this cached map.
dvander@238
   385
    StructMap *newMap() {
dvander@238
   386
        return newMap_;
dvander@238
   387
    }
dvander@238
   388
    void setNewMap(StructMap *map) {
dvander@238
   389
        assert(!newMap());
dvander@238
   390
        newMap_ = map;
dvander@238
   391
    }
dvander@238
   392
dvander@238
   393
    String *name() {
dvander@238
   394
        return name_;
dvander@238
   395
    }
dvander@238
   396
dvander@238
   397
    // GC Descriptor.
dvander@238
   398
    static inline size_t offsetOfFields() {
dvander@238
   399
        return OFFSETOF(StructType, fields_);
dvander@238
   400
    }
dvander@238
   401
    static inline size_t offsetOfNewMap() {
dvander@238
   402
        return OFFSETOF(StructType, newMap_);
dvander@238
   403
    }
dvander@238
   404
    static inline size_t offsetOfName() {
dvander@238
   405
        return OFFSETOF(StructType, name_);
dvander@238
   406
    }
dvander@238
   407
    // End GC Descriptor.
dvander@238
   408
dvander@238
   409
    static StructType *cast(Object *obj) {
dvander@238
   410
        assert(!obj || obj->is(MapKind_StructType));
dvander@238
   411
        return (StructType *)obj;
dvander@238
   412
    }
dvander@238
   413
dvander@238
   414
  private:
dvander@238
   415
    // Structs only.
dvander@238
   416
    Barriered<FixedArray> fields_;
dvander@238
   417
    Barriered<StructMap> newMap_;
dvander@238
   418
    Barriered<String> name_;
dvander@238
   419
};
dvander@238
   420
dvander@238
   421
class FunctionType : public Type
dvander@238
   422
{
dvander@238
   423
  public:
dvander@238
   424
    static FunctionType *New(Zone *zone, Handle<String> name, TokenKind kind);
dvander@238
   425
dvander@238
   426
    Type *parameterAt(size_t i) {
dvander@238
   427
        return Type::cast(parameters()->at(i));
dvander@238
   428
    }
dvander@238
   429
    Type *returnType() {
dvander@238
   430
        assert(isFunction());
dvander@238
   431
        return returnType_;
dvander@238
   432
    }
dvander@238
   433
    FixedArray *parameters() {
dvander@238
   434
        assert(isFunction());
dvander@238
   435
        return parameters_;
dvander@238
   436
    }
dvander@238
   437
    FixedArray *defaults() {
dvander@238
   438
        assert(isFunction());
dvander@238
   439
        return defaults_;
dvander@238
   440
    }
dvander@238
   441
    bool isNative() {
dvander@238
   442
        return token_ == TOK_NATIVE;
dvander@238
   443
    }
dvander@238
   444
    bool isForward() {
dvander@238
   445
        return token_ == TOK_FORWARD;
dvander@238
   446
    }
dvander@238
   447
    bool isNativeVariadic() {
dvander@238
   448
        assert(isNative());
dvander@238
   449
        return variadicNative_;
dvander@238
   450
    }
dvander@238
   451
    void setReturnType(Handle<Type> returnType) {
dvander@238
   452
        assert(!returnType_);
dvander@238
   453
        returnType_ = returnType;
dvander@238
   454
    }
dvander@238
   455
    void setParameterTypes(Handle<FixedArray> types) {
dvander@238
   456
        assert(!parameters_);
dvander@238
   457
        parameters_ = types;
dvander@238
   458
    }
dvander@238
   459
    TokenKind token() {
dvander@238
   460
        return token_;
dvander@238
   461
    }
dvander@238
   462
    String *name() {
dvander@238
   463
        return name_;
dvander@238
   464
    }
dvander@238
   465
dvander@238
   466
    // GC Descriptor.
dvander@238
   467
    static inline size_t offsetOfReturnType() {
dvander@238
   468
        return OFFSETOF(FunctionType, returnType_);
dvander@238
   469
    }
dvander@238
   470
    static inline size_t offsetOfParameters() {
dvander@238
   471
        return OFFSETOF(FunctionType, parameters_);
dvander@238
   472
    }
dvander@238
   473
    static inline size_t offsetOfDefaults() {
dvander@238
   474
        return OFFSETOF(FunctionType, defaults_);
dvander@238
   475
    }
dvander@238
   476
    static inline size_t offsetOfName() {
dvander@238
   477
        return OFFSETOF(FunctionType, name_);
dvander@238
   478
    }
dvander@238
   479
    // End GC Descriptor.
dvander@238
   480
dvander@238
   481
    static FunctionType *cast(Object *obj) {
dvander@238
   482
        assert(!obj || obj->is(MapKind_FunctionType));
dvander@238
   483
        return (FunctionType *)obj;
dvander@238
   484
    }
dvander@238
   485
dvander@238
   486
  private:
dvander@238
   487
    // Functions only.
dvander@238
   488
    Barriered<Type> returnType_;
dvander@238
   489
    Barriered<FixedArray> parameters_;
dvander@238
   490
    Barriered<FixedArray> defaults_;
dvander@238
   491
    Barriered<String> name_;
dvander@238
   492
    TokenKind token_;
dvander@238
   493
    bool variadicNative_;
dvander@238
   494
};
dvander@238
   495
dvander@238
   496
class BoxedPrimitive
dvander@238
   497
{
dvander@238
   498
    PrimitiveType type_;
dvander@238
   499
    union {
dvander@238
   500
        int i_;
dvander@238
   501
        float f_;
dvander@238
   502
    };
dvander@238
   503
dvander@238
   504
  public:
dvander@238
   505
    static BoxedPrimitive Int(int i) {
dvander@238
   506
        BoxedPrimitive b;
dvander@238
   507
        b.type_ = PrimitiveType_Int32;
dvander@238
   508
        b.i_ = i;
dvander@238
   509
        return b;
dvander@238
   510
    }
dvander@238
   511
    static BoxedPrimitive Float(float f) {
dvander@238
   512
        BoxedPrimitive b;
dvander@238
   513
        b.type_ = PrimitiveType_Float;
dvander@238
   514
        b.f_ = f;
dvander@238
   515
        return b;
dvander@238
   516
    }
dvander@238
   517
dvander@238
   518
    PrimitiveType type() const {
dvander@238
   519
        return type_;
dvander@238
   520
    }
dvander@238
   521
    int toInt() const {
dvander@238
   522
        assert(type() == PrimitiveType_Int32);
dvander@238
   523
        return i_;
dvander@238
   524
    }
dvander@238
   525
    float toFloat() const {
dvander@238
   526
        assert(type() == PrimitiveType_Float);
dvander@238
   527
        return f_;
dvander@238
   528
    }
dvander@238
   529
};
dvander@238
   530
dvander@238
   531
const char *GetTypeName(Type *type);
dvander@238
   532
dvander@238
   533
}
dvander@238
   534
dvander@238
   535
#endif // _include_jc_types_h_