src/Types.h
author David Anderson <dvander@alliedmods.net>
Sat Nov 17 20:11:05 2012 -0800 (2012-11-17)
changeset 206 3a896e9b57e2
parent 195 c1ba166f3fc4
child 209 5cbec15fadfe
permissions -rw-r--r--
Add test for |do|.
     1 /* vim: set ts=4 sw=4 tw=99 et:
     2  *
     3  * Copyright (C) 2012 David Anderson
     4  *
     5  * This file is part of JITCraft.
     6  *
     7  * JITCraft is free software: you can redistribute it and/or modify it under
     8  * the terms of the GNU General Public License as published by the Free
     9  * Software Foundation, either version 3 of the License, or (at your option)
    10  * any later version.
    11  * 
    12  * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
    13  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    14  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
    15  *
    16  * You should have received a copy of the GNU General Public License along with
    17  * JITCraft. If not, see http://www.gnu.org/licenses/.
    18  */
    19 #ifndef _include_jc_types_h_
    20 #define _include_jc_types_h_
    21 
    22 #include "Heap.h"
    23 #include "Barriers.h"
    24 #include "FixedArray.h"
    25 #include "compiler/Token.h"
    26 
    27 namespace ke {
    28 
    29 class String;
    30 class Descriptor;
    31 class StructMap;
    32 
    33 #define MAX_ARRAY_DEPTH     5
    34 
    35 enum PrimitiveType
    36 {
    37     // A boolean type semantically represents 0 or 1. As an optimization, its
    38     // internal storage type is the same as int32, and any non-zero value
    39     // compares positively to "true".
    40     PrimitiveType_Bool,
    41 
    42     // A character is an arbitrary 8-bit value. Characters are not supported
    43     // as a normal storage class; they may only be used for arrays. When read
    44     // from an array, they are immediately sign extended to 32 bits. Integers
    45     // stored into an char array are truncated to 8 bits.
    46     PrimitiveType_Char,         // signed, 8-bit character
    47 
    48     // Enumerations and untyped variables are stored as signed, 32-bit integers.
    49     PrimitiveType_Int32,
    50 
    51     // Floating point values are 32-bit IEEE-754 floats. This is required ro
    52     // SourcePawn 1 compatibility.
    53     PrimitiveType_Float,
    54 
    55     // This is a native-sized integer type (32-bit on 32-bit systems, 64-bit
    56     // on 64-bit systems), and does not exist in language semantics.
    57     PrimitiveType_Native,
    58 
    59     PrimitiveTypes_Total
    60 };
    61 
    62 class Type : public Object
    63 {
    64   protected:
    65     enum Kind {
    66         // A primitive is a plain-old-data type.
    67         PRIMITIVE,
    68 
    69         // An array is a fixed-length vector of any other type.
    70         ARRAY,
    71         EXTERNAL_ARRAY,
    72 
    73         // A reference type may only be specified on parameters, and
    74         // references may only be computed to primitives or enums.
    75         REFERENCE,
    76 
    77         // A function type encapsulates a function signature.
    78         FUNCTION,
    79 
    80         // Void is an internal type used to specify that a function returns no
    81         // value.
    82         VOID,
    83 
    84         // Enums are plain-old-data with int32 storage. They allow for extra
    85         // type checking that would not be possible with integers.
    86         ENUM,
    87 
    88         // Structs are composite records that may contain primitives, arrays,
    89         // functions, enums, and other structs.
    90         STRUCT,
    91 
    92         // Unchecked is a magic type that has implicit, bitwise coercion to
    93         // int32, float, bool, or an enum.
    94         UNCHECKED
    95     };
    96 
    97   private:
    98     Kind kind() {
    99         return kind_;
   100     }
   101 
   102   public:
   103     static const int DYNAMIC_ARRAY_SIZE = -1;
   104     
   105     static Type *NewVoid(Zone *zone);
   106     static Type *NewUnchecked(Zone *zone);
   107     static Type *NewPrimitive(Zone *zone, PrimitiveType type);
   108     static Type *NewArray(Zone *zone, Handle<Type> contained, int elements, bool isConst);
   109     static Type *NewExternalArray(Zone *zone, Handle<Type> contained);
   110     static Type *NewReference(Zone *zone, Handle<Type> contained, bool isConst);
   111     static Type *NewEnum(Zone *zone, Handle<String> name);
   112 
   113     static bool Compare(Type *left, Type *right);
   114 
   115     static Type *cast(Object *obj) {
   116         assert(!obj ||
   117                obj->is(MapKind_Type) ||
   118                obj->is(MapKind_FunctionType) ||
   119                obj->is(MapKind_StructType));
   120         return (Type *)obj;
   121     }
   122 
   123     bool isPrimitive() {
   124         return kind() == PRIMITIVE;
   125     }
   126     bool isArray() {
   127         return kind() == ARRAY || kind() == EXTERNAL_ARRAY;
   128     }
   129     bool isReference() {
   130         return kind() == REFERENCE;
   131     }
   132     bool isFunction() {
   133         return kind() == FUNCTION;
   134     }
   135     bool isVoid() {
   136         return kind() == VOID;
   137     }
   138     bool isUnchecked() {
   139         return kind() == UNCHECKED;
   140     }
   141     bool isStruct() {
   142         return kind() == STRUCT;
   143     }
   144     PrimitiveType primitive() {
   145         assert(isPrimitive());
   146         return primitive_;
   147     }
   148     bool isPod() {
   149         return isPrimitive() || isEnum() || isUnchecked();
   150     }
   151     PrimitiveType pod() {
   152         assert(isPod());
   153         return isPrimitive()
   154                ? (primitive() == PrimitiveType_Bool)
   155                  ? PrimitiveType_Int32
   156                  : primitive()
   157                : PrimitiveType_Int32;
   158     }
   159     Type *contained() {
   160         assert(isArray() || isReference());
   161         return Type::cast(contained_);
   162     }
   163     bool isFixedLength() {
   164         assert(isArray());
   165         return elements_ > 0;
   166     }
   167     unsigned fixedLength() {
   168         assert(isFixedLength());
   169         return elements_;
   170     }
   171     unsigned levels() {
   172         assert(isArray());
   173         return levels_;
   174     }
   175     bool hasInlineElements() {
   176         assert(isArray());
   177 
   178         // We don't allocate traceable elements inline, since there's no
   179         // point to the optimization; we're going to be allocating lots of
   180         // objects anyway (in theory).
   181         return isFixedLength() && !contained()->isTraceable();
   182     }
   183     Type *innermost() {
   184         assert(isArray());
   185         Type *temp = contained();
   186         while (temp->isArray())
   187             temp = temp->contained();
   188         return temp;
   189     }
   190     bool isFloat() {
   191         return isPrimitive() && primitive() == PrimitiveType_Float;
   192     }
   193     bool isInt32() {
   194         return isPrimitive() && primitive() == PrimitiveType_Int32;
   195     }
   196     bool isInt32OrEnum() {
   197         return isInt32() || isEnum();
   198     }
   199     bool isBool() {
   200         return isPrimitive() && primitive() == PrimitiveType_Bool;
   201     }
   202     bool isCharArray() {
   203         return isArray() &&
   204                contained()->isPrimitive() &&
   205                contained()->primitive() == PrimitiveType_Char;
   206     }
   207     bool isExternalArray() {
   208         return kind() == EXTERNAL_ARRAY;
   209     }
   210     bool isTraceable() {
   211         return !isPrimitive();
   212     }
   213     bool isConst() {
   214         assert(isPrimitive() ||
   215                isArray() ||
   216                isReference());
   217         return const_;
   218     }
   219     bool isEnum() {
   220         return kind() == ENUM;
   221     }
   222 
   223     String *name() {
   224         assert(isEnum() || isStruct());
   225         return name_;
   226     }
   227 
   228     Map *newMap() {
   229         assert(false);
   230         return NULL;
   231     }
   232     void setNewMap(void *p) {
   233         assert(false);
   234     }
   235 
   236     // GC Descriptor.
   237     static inline size_t offsetOfContained() {
   238         return OFFSETOF(Type, contained_);
   239     }
   240     static inline size_t offsetOfName() {
   241         return OFFSETOF(Type, name_);
   242     }
   243     // End GC Descriptor.
   244 
   245   protected:
   246     Kind kind_;
   247     PrimitiveType primitive_;
   248 
   249     // Primitives, arrays, and references.
   250     bool const_;
   251 
   252     // Arrays only.
   253     int32 elements_;
   254     unsigned levels_;
   255 
   256     // Arrays and references only.
   257     Barriered<Type> contained_;
   258 
   259     // Enums and structs only.
   260     Barriered<String> name_;
   261 };
   262 
   263 class StructType : public Type
   264 {
   265   public:
   266     static StructType *New(Zone *zone, Handle<String> name, Handle<FixedArray> fields);
   267 
   268     FixedArray *fields() {
   269         assert(isStruct());
   270         return fields_;
   271     }
   272     Descriptor *lookupField(Handle<String> name, unsigned *index = NULL);
   273 
   274     // Objects of this type can be created with this cached map.
   275     StructMap *newMap() {
   276         return newMap_;
   277     }
   278     void setNewMap(StructMap *map) {
   279         assert(!newMap());
   280         newMap_ = map;
   281     }
   282 
   283     // GC Descriptor.
   284     static inline size_t offsetOfFields() {
   285         return OFFSETOF(StructType, fields_);
   286     }
   287     static inline size_t offsetOfNewMap() {
   288         return OFFSETOF(StructType, newMap_);
   289     }
   290     // End GC Descriptor.
   291 
   292     static StructType *cast(Object *obj) {
   293         assert(!obj || obj->is(MapKind_StructType));
   294         return (StructType *)obj;
   295     }
   296 
   297   private:
   298     // Structs only.
   299     Barriered<FixedArray> fields_;
   300     Barriered<StructMap> newMap_;
   301 };
   302 
   303 class FunctionType : public Type
   304 {
   305   public:
   306     static FunctionType *New(Zone *zone, TokenKind kind);
   307 
   308     Type *parameterAt(size_t i) {
   309         return Type::cast(parameters()->at(i));
   310     }
   311     Type *returnType() {
   312         assert(isFunction());
   313         return returnType_;
   314     }
   315     FixedArray *parameters() {
   316         assert(isFunction());
   317         return parameters_;
   318     }
   319     FixedArray *defaults() {
   320         assert(isFunction());
   321         return defaults_;
   322     }
   323     bool isNative() {
   324         return token_ == TOK_NATIVE;
   325     }
   326     bool isForward() {
   327         return token_ == TOK_FORWARD;
   328     }
   329     bool isNativeVariadic() {
   330         assert(isNative());
   331         return variadicNative_;
   332     }
   333     void setReturnType(Handle<Type> returnType) {
   334         assert(!returnType_);
   335         returnType_ = returnType;
   336     }
   337     void setParameterTypes(Handle<FixedArray> types) {
   338         assert(!parameters_);
   339         parameters_ = types;
   340     }
   341     TokenKind token() {
   342         return token_;
   343     }
   344 
   345     // GC Descriptor.
   346     static inline size_t offsetOfReturnType() {
   347         return OFFSETOF(FunctionType, returnType_);
   348     }
   349     static inline size_t offsetOfParameters() {
   350         return OFFSETOF(FunctionType, parameters_);
   351     }
   352     static inline size_t offsetOfDefaults() {
   353         return OFFSETOF(FunctionType, defaults_);
   354     }
   355     // End GC Descriptor.
   356 
   357     static FunctionType *cast(Object *obj) {
   358         assert(!obj || obj->is(MapKind_FunctionType));
   359         return (FunctionType *)obj;
   360     }
   361 
   362   private:
   363     // Functions only.
   364     Barriered<Type> returnType_;
   365     Barriered<FixedArray> parameters_;
   366     Barriered<FixedArray> defaults_;
   367     TokenKind token_;
   368     bool variadicNative_;
   369 };
   370 
   371 class BoxedPrimitive
   372 {
   373     PrimitiveType type_;
   374     union {
   375         int i_;
   376         float f_;
   377     };
   378 
   379   public:
   380     static BoxedPrimitive Int(int i) {
   381         BoxedPrimitive b;
   382         b.type_ = PrimitiveType_Int32;
   383         b.i_ = i;
   384         return b;
   385     }
   386     static BoxedPrimitive Float(float f) {
   387         BoxedPrimitive b;
   388         b.type_ = PrimitiveType_Float;
   389         b.f_ = f;
   390         return b;
   391     }
   392 
   393     PrimitiveType type() const {
   394         return type_;
   395     }
   396     int toInt() const {
   397         assert(type() == PrimitiveType_Int32);
   398         return i_;
   399     }
   400     float toFloat() const {
   401         assert(type() == PrimitiveType_Float);
   402         return f_;
   403     }
   404 };
   405 
   406 const char *GetTypeName(Type *type);
   407 
   408 }
   409 
   410 #endif // _include_jc_types_h_