src/compiler/Symbols.h
author Michael Busby <prodigysim@gmail.com>
Mon Jun 10 01:50:18 2013 +0100 (2013-06-10)
changeset 264 70b8f318c379
parent 263 ba85a47ee414
permissions -rw-r--r--
Parse assignment RTL instead of LTR, fixes multiple assignment (bug 5420).
asherkin@263
     1
/* vim: set ts=4 sw=4 tw=99 et:
asherkin@263
     2
 *
asherkin@263
     3
 * Copyright (C) 2012 David Anderson
asherkin@263
     4
 *
asherkin@263
     5
 * This file is part of SourcePawn.
asherkin@263
     6
 *
asherkin@263
     7
 * SourcePawn is free software: you can redistribute it and/or modify it under
asherkin@263
     8
 * the terms of the GNU General Public License as published by the Free
asherkin@263
     9
 * Software Foundation, either version 3 of the License, or (at your option)
asherkin@263
    10
 * any later version.
asherkin@263
    11
 * 
asherkin@263
    12
 * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
asherkin@263
    13
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
asherkin@263
    14
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
asherkin@263
    15
 *
asherkin@263
    16
 * You should have received a copy of the GNU General Public License along with
asherkin@263
    17
 * SourcePawn. If not, see http://www.gnu.org/licenses/.
asherkin@263
    18
 */
asherkin@263
    19
#ifndef _include_sp2_symbol_h_
asherkin@263
    20
#define _include_sp2_symbol_h_
asherkin@263
    21
asherkin@263
    22
#include "../PoolAllocator.h"
asherkin@263
    23
#include "../Handles.h"
asherkin@263
    24
#include "../Opcodes.h"
asherkin@263
    25
#include "../Types.h"
asherkin@263
    26
#include "../Strings.h"
asherkin@263
    27
asherkin@263
    28
namespace ke {
asherkin@263
    29
asherkin@263
    30
class String;
asherkin@263
    31
asherkin@263
    32
#define SYMBOL_KINDS(_) \
asherkin@263
    33
    /* Any kind of variable or argument produces a VariableSymbol. */ \
asherkin@263
    34
    _(Variable)         \
asherkin@263
    35
    /* A function declaration produces a FunctionSymbol. */ \
asherkin@263
    36
    _(Function)         \
asherkin@263
    37
    /* A named constant produces a ConstantSymbol. */ \
asherkin@263
    38
    _(Constant)         \
asherkin@263
    39
    /* A named type (class struct, typedef, etc) produces a TypeSymbol. */ \
asherkin@263
    40
    _(Type)             \
asherkin@263
    41
    /* An import name. */ \
asherkin@263
    42
    _(Import)           \
asherkin@263
    43
    /* A name implicitly derived from an import. */ \
asherkin@263
    44
    _(Implicit)
asherkin@263
    45
asherkin@263
    46
#define _(name)     class name##Symbol;
asherkin@263
    47
SYMBOL_KINDS(_)
asherkin@263
    48
#undef _
asherkin@263
    49
asherkin@263
    50
class Scope;
asherkin@263
    51
asherkin@263
    52
// A symbol represents the declaration of a named entity.
asherkin@263
    53
class Symbol : public PoolObject
asherkin@263
    54
{
asherkin@263
    55
  public:
asherkin@263
    56
    enum Kind {
asherkin@263
    57
#       define _(name) k##name,
asherkin@263
    58
        SYMBOL_KINDS(_)
asherkin@263
    59
#       undef _
asherkin@263
    60
        kTotalSymbolKinds
asherkin@263
    61
    };
asherkin@263
    62
asherkin@263
    63
  public:
asherkin@263
    64
    Symbol(Scope *scope, Handle<String> name, const SourcePosition &pos)
asherkin@263
    65
      : scope_(scope),
asherkin@263
    66
        name_(name),
asherkin@263
    67
        pos_(pos)
asherkin@263
    68
    {
asherkin@263
    69
    }
asherkin@263
    70
asherkin@263
    71
    virtual Kind kind() const = 0;
asherkin@263
    72
asherkin@263
    73
    Handle<String> name() const {
asherkin@263
    74
        return name_;
asherkin@263
    75
    }
asherkin@263
    76
    const SourcePosition &pos() const {
asherkin@263
    77
        return pos_;
asherkin@263
    78
    }
asherkin@263
    79
    Handle<Type> type() const {
asherkin@263
    80
        return type_;
asherkin@263
    81
    }
asherkin@263
    82
    Scope *scope() const {
asherkin@263
    83
        return scope_;
asherkin@263
    84
    }
asherkin@263
    85
asherkin@263
    86
  public:
asherkin@263
    87
#define _(name)                                             \
asherkin@263
    88
    bool is##name() const {                                 \
asherkin@263
    89
        return (kind() == k##name);                         \
asherkin@263
    90
    }                                                       \
asherkin@263
    91
    name##Symbol *as##name() {                              \
asherkin@263
    92
        if (is##name())                                     \
asherkin@263
    93
            return to##name();                              \
asherkin@263
    94
        return NULL;                                        \
asherkin@263
    95
    }                                                       \
asherkin@263
    96
    name##Symbol *to##name() {                              \
asherkin@263
    97
        assert(is##name());                                 \
asherkin@263
    98
        return reinterpret_cast<name##Symbol *>(this);      \
asherkin@263
    99
    }
asherkin@263
   100
    SYMBOL_KINDS(_)
asherkin@263
   101
#undef _
asherkin@263
   102
asherkin@263
   103
  private:
asherkin@263
   104
    Scope *scope_;
asherkin@263
   105
    ScopedRoot<String> name_;
asherkin@263
   106
    SourcePosition pos_;
asherkin@263
   107
asherkin@263
   108
  protected:
asherkin@263
   109
    ScopedRoot<Type> type_;
asherkin@263
   110
};
asherkin@263
   111
asherkin@263
   112
class VariableSymbol : public Symbol
asherkin@263
   113
{
asherkin@263
   114
  public:
asherkin@263
   115
    enum Storage {
asherkin@263
   116
        Unknown,
asherkin@263
   117
        Local,
asherkin@263
   118
        Arg,
asherkin@263
   119
        Heap
asherkin@263
   120
    };
asherkin@263
   121
asherkin@263
   122
  public:
asherkin@263
   123
    VariableSymbol(Scope *scope, Handle<String> name, const SourcePosition &pos)
asherkin@263
   124
      : Symbol(scope, name, pos),
asherkin@263
   125
        storage_(Unknown)
asherkin@263
   126
    {
asherkin@263
   127
    }
asherkin@263
   128
asherkin@263
   129
    VariableSymbol(Scope *scope, Handle<String> name, const SourcePosition &pos, Handle<Type> type)
asherkin@263
   130
      : Symbol(scope, name, pos),
asherkin@263
   131
        storage_(Unknown)
asherkin@263
   132
    {
asherkin@263
   133
        type_ = type;
asherkin@263
   134
    }
asherkin@263
   135
asherkin@263
   136
    Kind kind() const {
asherkin@263
   137
        return kVariable;
asherkin@263
   138
    }
asherkin@263
   139
    void setType(Type *type) {
asherkin@263
   140
        assert(!type_);
asherkin@263
   141
        type_ = type;
asherkin@263
   142
    }
asherkin@263
   143
    void allocate(Storage storage, unsigned slot) {
asherkin@263
   144
        storage_ = storage;
asherkin@263
   145
        slot_ = slot;
asherkin@263
   146
    }
asherkin@263
   147
    Storage storage() const {
asherkin@263
   148
        return storage_;
asherkin@263
   149
    }
asherkin@263
   150
    unsigned slot() const {
asherkin@263
   151
        assert(storage() != Unknown);
asherkin@263
   152
        return slot_;
asherkin@263
   153
    }
asherkin@263
   154
asherkin@263
   155
  private:
asherkin@263
   156
    Storage storage_;
asherkin@263
   157
    unsigned slot_;
asherkin@263
   158
};
asherkin@263
   159
asherkin@263
   160
class TypeSymbol : public Symbol
asherkin@263
   161
{
asherkin@263
   162
  public:
asherkin@263
   163
    TypeSymbol(Scope *scope, Handle<String> name, Handle<Type> type, Handle<Type> effective)
asherkin@263
   164
      : Symbol(scope, name, SourcePosition()),
asherkin@263
   165
        effective_(effective)
asherkin@263
   166
    {
asherkin@263
   167
        type_ = type;
asherkin@263
   168
    }
asherkin@263
   169
asherkin@263
   170
    Kind kind() const {
asherkin@263
   171
        return kType;
asherkin@263
   172
    }
asherkin@263
   173
    Handle<Type> effective() {
asherkin@263
   174
        return effective_;
asherkin@263
   175
    }
asherkin@263
   176
asherkin@263
   177
  private:
asherkin@263
   178
    ScopedRoot<Type> effective_;
asherkin@263
   179
};
asherkin@263
   180
asherkin@263
   181
class FunctionSymbol : public Symbol
asherkin@263
   182
{
asherkin@263
   183
  public:
asherkin@263
   184
    FunctionSymbol(Scope *scope, Handle<String> name, const SourcePosition &pos, Handle<FunctionType> type)
asherkin@263
   185
      : Symbol(scope, name, pos)
asherkin@263
   186
    {
asherkin@263
   187
        type_ = type;
asherkin@263
   188
    }
asherkin@263
   189
asherkin@263
   190
    Kind kind() const {
asherkin@263
   191
        return kFunction;
asherkin@263
   192
    }
asherkin@263
   193
    FunctionType *type() const {
asherkin@263
   194
        return FunctionType::cast(type_);
asherkin@263
   195
    }
asherkin@263
   196
};
asherkin@263
   197
asherkin@263
   198
class ConstantSymbol : public Symbol
asherkin@263
   199
{
asherkin@263
   200
  public:
asherkin@263
   201
    ConstantSymbol(Scope *scope, Handle<String> name, const SourcePosition &pos, Handle<Type> type,
asherkin@263
   202
                   const BoxedPrimitive &prim)
asherkin@263
   203
      : Symbol(scope, name, pos),
asherkin@263
   204
        value_(prim)
asherkin@263
   205
    {
asherkin@263
   206
        type_ = type;
asherkin@263
   207
    }
asherkin@263
   208
asherkin@263
   209
    Kind kind() const {
asherkin@263
   210
        return kConstant;
asherkin@263
   211
    }
asherkin@263
   212
    const BoxedPrimitive &value() const {
asherkin@263
   213
        return value_;
asherkin@263
   214
    }
asherkin@263
   215
asherkin@263
   216
  private:
asherkin@263
   217
    BoxedPrimitive value_;
asherkin@263
   218
};
asherkin@263
   219
asherkin@263
   220
class ImportSymbol : public Symbol
asherkin@263
   221
{
asherkin@263
   222
  public:
asherkin@263
   223
    ImportSymbol(Scope *scope, Handle<String> name, const SourcePosition &pos, Handle<Type> type,
asherkin@263
   224
                 unsigned index)
asherkin@263
   225
      : Symbol(scope, name, pos),
asherkin@263
   226
        index_(index)
asherkin@263
   227
    {
asherkin@263
   228
        type_ = type;
asherkin@263
   229
    }
asherkin@263
   230
asherkin@263
   231
    Kind kind() const {
asherkin@263
   232
        return kImport;
asherkin@263
   233
    }
asherkin@263
   234
    unsigned index() const {
asherkin@263
   235
        return index_;
asherkin@263
   236
    }
asherkin@263
   237
asherkin@263
   238
  private:
asherkin@263
   239
      unsigned index_;
asherkin@263
   240
};
asherkin@263
   241
asherkin@263
   242
class ImplicitSymbol : public Symbol
asherkin@263
   243
{
asherkin@263
   244
  public:
asherkin@263
   245
    ImplicitSymbol(Scope *scope, Handle<String> name, const SourcePosition &pos, Handle<Type> type,
asherkin@263
   246
                 unsigned index)
asherkin@263
   247
      : Symbol(scope, name, pos),
asherkin@263
   248
        index_(index),
asherkin@263
   249
        fieldIndex_(unsigned(-1))
asherkin@263
   250
    {
asherkin@263
   251
        type_ = type;
asherkin@263
   252
    }
asherkin@263
   253
asherkin@263
   254
    bool bound() const {
asherkin@263
   255
        return fieldIndex_ != unsigned(-1);
asherkin@263
   256
    }
asherkin@263
   257
    Kind kind() const {
asherkin@263
   258
        return kImplicit;
asherkin@263
   259
    }
asherkin@263
   260
    unsigned index() const {
asherkin@263
   261
        return index_;
asherkin@263
   262
    }
asherkin@263
   263
    void bind(unsigned fieldIndex) {
asherkin@263
   264
        fieldIndex_ = fieldIndex;
asherkin@263
   265
    }
asherkin@263
   266
    unsigned fieldIndex() const {
asherkin@263
   267
        assert(bound());
asherkin@263
   268
        return fieldIndex_;
asherkin@263
   269
    }
asherkin@263
   270
asherkin@263
   271
  private:
asherkin@263
   272
    unsigned index_;
asherkin@263
   273
    unsigned fieldIndex_;
asherkin@263
   274
};
asherkin@263
   275
asherkin@263
   276
}
asherkin@263
   277
asherkin@263
   278
#endif // _include_sp2_symbol_h_