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