asherkin@263: /* vim: set ts=4 sw=4 tw=99 et: asherkin@263: * asherkin@263: * Copyright (C) 2012 David Anderson asherkin@263: * asherkin@263: * This file is part of SourcePawn. asherkin@263: * asherkin@263: * SourcePawn is free software: you can redistribute it and/or modify it under asherkin@263: * the terms of the GNU General Public License as published by the Free asherkin@263: * Software Foundation, either version 3 of the License, or (at your option) asherkin@263: * any later version. asherkin@263: * asherkin@263: * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY asherkin@263: * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS asherkin@263: * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. asherkin@263: * asherkin@263: * You should have received a copy of the GNU General Public License along with asherkin@263: * SourcePawn. If not, see http://www.gnu.org/licenses/. asherkin@263: */ asherkin@263: #ifndef _include_sp2_symbol_h_ asherkin@263: #define _include_sp2_symbol_h_ asherkin@263: asherkin@263: #include "../PoolAllocator.h" asherkin@263: #include "../Handles.h" asherkin@263: #include "../Opcodes.h" asherkin@263: #include "../Types.h" asherkin@263: #include "../Strings.h" asherkin@263: asherkin@263: namespace ke { asherkin@263: asherkin@263: class String; asherkin@263: asherkin@263: #define SYMBOL_KINDS(_) \ asherkin@263: /* Any kind of variable or argument produces a VariableSymbol. */ \ asherkin@263: _(Variable) \ asherkin@263: /* A function declaration produces a FunctionSymbol. */ \ asherkin@263: _(Function) \ asherkin@263: /* A named constant produces a ConstantSymbol. */ \ asherkin@263: _(Constant) \ asherkin@263: /* A named type (class struct, typedef, etc) produces a TypeSymbol. */ \ asherkin@263: _(Type) \ asherkin@263: /* An import name. */ \ asherkin@263: _(Import) \ asherkin@263: /* A name implicitly derived from an import. */ \ asherkin@263: _(Implicit) asherkin@263: asherkin@263: #define _(name) class name##Symbol; asherkin@263: SYMBOL_KINDS(_) asherkin@263: #undef _ asherkin@263: asherkin@263: class Scope; asherkin@263: asherkin@263: // A symbol represents the declaration of a named entity. asherkin@263: class Symbol : public PoolObject asherkin@263: { asherkin@263: public: asherkin@263: enum Kind { asherkin@263: # define _(name) k##name, asherkin@263: SYMBOL_KINDS(_) asherkin@263: # undef _ asherkin@263: kTotalSymbolKinds asherkin@263: }; asherkin@263: asherkin@263: public: asherkin@263: Symbol(Scope *scope, Handle name, const SourcePosition &pos) asherkin@263: : scope_(scope), asherkin@263: name_(name), asherkin@263: pos_(pos) asherkin@263: { asherkin@263: } asherkin@263: asherkin@263: virtual Kind kind() const = 0; asherkin@263: asherkin@263: Handle name() const { asherkin@263: return name_; asherkin@263: } asherkin@263: const SourcePosition &pos() const { asherkin@263: return pos_; asherkin@263: } asherkin@263: Handle type() const { asherkin@263: return type_; asherkin@263: } asherkin@263: Scope *scope() const { asherkin@263: return scope_; asherkin@263: } asherkin@263: asherkin@263: public: asherkin@263: #define _(name) \ asherkin@263: bool is##name() const { \ asherkin@263: return (kind() == k##name); \ asherkin@263: } \ asherkin@263: name##Symbol *as##name() { \ asherkin@263: if (is##name()) \ asherkin@263: return to##name(); \ asherkin@263: return NULL; \ asherkin@263: } \ asherkin@263: name##Symbol *to##name() { \ asherkin@263: assert(is##name()); \ asherkin@263: return reinterpret_cast(this); \ asherkin@263: } asherkin@263: SYMBOL_KINDS(_) asherkin@263: #undef _ asherkin@263: asherkin@263: private: asherkin@263: Scope *scope_; asherkin@263: ScopedRoot name_; asherkin@263: SourcePosition pos_; asherkin@263: asherkin@263: protected: asherkin@263: ScopedRoot type_; asherkin@263: }; asherkin@263: asherkin@263: class VariableSymbol : public Symbol asherkin@263: { asherkin@263: public: asherkin@263: enum Storage { asherkin@263: Unknown, asherkin@263: Local, asherkin@263: Arg, asherkin@263: Heap asherkin@263: }; asherkin@263: asherkin@263: public: asherkin@263: VariableSymbol(Scope *scope, Handle name, const SourcePosition &pos) asherkin@263: : Symbol(scope, name, pos), asherkin@263: storage_(Unknown) asherkin@263: { asherkin@263: } asherkin@263: asherkin@263: VariableSymbol(Scope *scope, Handle name, const SourcePosition &pos, Handle type) asherkin@263: : Symbol(scope, name, pos), asherkin@263: storage_(Unknown) asherkin@263: { asherkin@263: type_ = type; asherkin@263: } asherkin@263: asherkin@263: Kind kind() const { asherkin@263: return kVariable; asherkin@263: } asherkin@263: void setType(Type *type) { asherkin@263: assert(!type_); asherkin@263: type_ = type; asherkin@263: } asherkin@263: void allocate(Storage storage, unsigned slot) { asherkin@263: storage_ = storage; asherkin@263: slot_ = slot; asherkin@263: } asherkin@263: Storage storage() const { asherkin@263: return storage_; asherkin@263: } asherkin@263: unsigned slot() const { asherkin@263: assert(storage() != Unknown); asherkin@263: return slot_; asherkin@263: } asherkin@263: asherkin@263: private: asherkin@263: Storage storage_; asherkin@263: unsigned slot_; asherkin@263: }; asherkin@263: asherkin@263: class TypeSymbol : public Symbol asherkin@263: { asherkin@263: public: asherkin@263: TypeSymbol(Scope *scope, Handle name, Handle type, Handle effective) asherkin@263: : Symbol(scope, name, SourcePosition()), asherkin@263: effective_(effective) asherkin@263: { asherkin@263: type_ = type; asherkin@263: } asherkin@263: asherkin@263: Kind kind() const { asherkin@263: return kType; asherkin@263: } asherkin@263: Handle effective() { asherkin@263: return effective_; asherkin@263: } asherkin@263: asherkin@263: private: asherkin@263: ScopedRoot effective_; asherkin@263: }; asherkin@263: asherkin@263: class FunctionSymbol : public Symbol asherkin@263: { asherkin@263: public: asherkin@263: FunctionSymbol(Scope *scope, Handle name, const SourcePosition &pos, Handle type) asherkin@263: : Symbol(scope, name, pos) asherkin@263: { asherkin@263: type_ = type; asherkin@263: } asherkin@263: asherkin@263: Kind kind() const { asherkin@263: return kFunction; asherkin@263: } asherkin@263: FunctionType *type() const { asherkin@263: return FunctionType::cast(type_); asherkin@263: } asherkin@263: }; asherkin@263: asherkin@263: class ConstantSymbol : public Symbol asherkin@263: { asherkin@263: public: asherkin@263: ConstantSymbol(Scope *scope, Handle name, const SourcePosition &pos, Handle type, asherkin@263: const BoxedPrimitive &prim) asherkin@263: : Symbol(scope, name, pos), asherkin@263: value_(prim) asherkin@263: { asherkin@263: type_ = type; asherkin@263: } asherkin@263: asherkin@263: Kind kind() const { asherkin@263: return kConstant; asherkin@263: } asherkin@263: const BoxedPrimitive &value() const { asherkin@263: return value_; asherkin@263: } asherkin@263: asherkin@263: private: asherkin@263: BoxedPrimitive value_; asherkin@263: }; asherkin@263: asherkin@263: class ImportSymbol : public Symbol asherkin@263: { asherkin@263: public: asherkin@263: ImportSymbol(Scope *scope, Handle name, const SourcePosition &pos, Handle type, asherkin@263: unsigned index) asherkin@263: : Symbol(scope, name, pos), asherkin@263: index_(index) asherkin@263: { asherkin@263: type_ = type; asherkin@263: } asherkin@263: asherkin@263: Kind kind() const { asherkin@263: return kImport; asherkin@263: } asherkin@263: unsigned index() const { asherkin@263: return index_; asherkin@263: } asherkin@263: asherkin@263: private: asherkin@263: unsigned index_; asherkin@263: }; asherkin@263: asherkin@263: class ImplicitSymbol : public Symbol asherkin@263: { asherkin@263: public: asherkin@263: ImplicitSymbol(Scope *scope, Handle name, const SourcePosition &pos, Handle type, asherkin@263: unsigned index) asherkin@263: : Symbol(scope, name, pos), asherkin@263: index_(index), asherkin@263: fieldIndex_(unsigned(-1)) asherkin@263: { asherkin@263: type_ = type; asherkin@263: } asherkin@263: asherkin@263: bool bound() const { asherkin@263: return fieldIndex_ != unsigned(-1); asherkin@263: } asherkin@263: Kind kind() const { asherkin@263: return kImplicit; asherkin@263: } asherkin@263: unsigned index() const { asherkin@263: return index_; asherkin@263: } asherkin@263: void bind(unsigned fieldIndex) { asherkin@263: fieldIndex_ = fieldIndex; asherkin@263: } asherkin@263: unsigned fieldIndex() const { asherkin@263: assert(bound()); asherkin@263: return fieldIndex_; asherkin@263: } asherkin@263: asherkin@263: private: asherkin@263: unsigned index_; asherkin@263: unsigned fieldIndex_; asherkin@263: }; asherkin@263: asherkin@263: } asherkin@263: asherkin@263: #endif // _include_sp2_symbol_h_