src/OldSema.h
author David Anderson <dvander@alliedmods.net>
Sat Jan 12 16:35:26 2013 -0800 (2013-01-12)
changeset 260 05de34f712fe
parent 195 c1ba166f3fc4
child 263 ba85a47ee414
permissions -rw-r--r--
Add support for mutually recursive imports.
dvander@195
     1
/* vim: set ts=4 sw=4 tw=99 et:
dvander@195
     2
 *
dvander@195
     3
 * Copyright (C) 2012 David Anderson
dvander@195
     4
 *
dvander@195
     5
 * This file is part of JITCraft.
dvander@195
     6
 *
dvander@195
     7
 * JITCraft is free software: you can redistribute it and/or modify it under
dvander@195
     8
 * the terms of the GNU General Public License as published by the Free
dvander@195
     9
 * Software Foundation, either version 3 of the License, or (at your option)
dvander@195
    10
 * any later version.
dvander@195
    11
 * 
dvander@195
    12
 * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
dvander@195
    13
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
dvander@195
    14
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
dvander@195
    15
 *
dvander@195
    16
 * You should have received a copy of the GNU General Public License along with
dvander@195
    17
 * JITCraft. If not, see http://www.gnu.org/licenses/.
dvander@195
    18
 */
dvander@195
    19
#ifndef _include_semantic_analysis_h_
dvander@195
    20
#define _include_semantic_analysis_h_
dvander@195
    21
dvander@195
    22
#include <assert.h>
dvander@195
    23
#include "AST.h"
dvander@195
    24
#include "../Types.h"
dvander@195
    25
dvander@195
    26
namespace ke {
dvander@195
    27
dvander@195
    28
class Box;
dvander@195
    29
dvander@195
    30
class SemanticAnalysis : public AstVisitor
dvander@195
    31
{
dvander@195
    32
    Zone *zone_;
dvander@195
    33
    CompileContext &cc_;
dvander@195
    34
    ParseTree *tree_;
dvander@195
    35
    Scope *scope_;
dvander@195
    36
    NamedFunction *function_;
dvander@195
    37
dvander@195
    38
    enum ReturnStatus
dvander@195
    39
    {
dvander@195
    40
        Returns_Never,
dvander@195
    41
        Returns_Sometimes,
dvander@195
    42
        Returns_Always
dvander@195
    43
    };
dvander@195
    44
dvander@195
    45
    // Tuple that describes whether a path terminates control flow, and
dvander@195
    46
    // if it is guaranteed to end in a return.
dvander@195
    47
    class ControlStatus
dvander@195
    48
    {
dvander@195
    49
        bool terminates_;
dvander@195
    50
        ReturnStatus returns_;
dvander@195
    51
dvander@195
    52
      public:
dvander@195
    53
        ControlStatus(bool terminates, ReturnStatus returns)
dvander@195
    54
          : terminates_(terminates),
dvander@195
    55
            returns_(returns)
dvander@195
    56
        {
dvander@195
    57
        }
dvander@195
    58
dvander@195
    59
        bool terminates() const {
dvander@195
    60
            return terminates_;
dvander@195
    61
        }
dvander@195
    62
        ReturnStatus returns() const {
dvander@195
    63
            return returns_;
dvander@195
    64
        }
dvander@195
    65
    };
dvander@195
    66
dvander@195
    67
    // Used to keep track of terminating control flow and return statements
dvander@195
    68
    // inside control structures.
dvander@195
    69
    class ControlScope
dvander@195
    70
    {
dvander@195
    71
        ReturnStatus returns_;
dvander@195
    72
        ControlScope **prevp_;
dvander@195
    73
        ControlScope *prev_;
dvander@195
    74
        bool terminates_;
dvander@195
    75
dvander@195
    76
      public:
dvander@195
    77
        ControlScope(ControlScope **prev)
dvander@195
    78
          : returns_(Returns_Never),
dvander@195
    79
            prevp_(prev),
dvander@195
    80
            prev_(*prev),
dvander@195
    81
            terminates_(false)
dvander@195
    82
        {
dvander@195
    83
            *prevp_ = this;
dvander@195
    84
        }
dvander@195
    85
dvander@195
    86
        ControlStatus status() const {
dvander@195
    87
            return ControlStatus(terminates_, returns_);
dvander@195
    88
        }
dvander@195
    89
dvander@195
    90
        // We allow multiple terminators, but only the first one takes effect.
dvander@195
    91
        // For example, |break; continue;| is legal but the continue is
dvander@195
    92
        // unreachable.
dvander@195
    93
        void returns(ReturnStatus status) {
dvander@195
    94
            if (terminates_)
dvander@195
    95
                return;
dvander@195
    96
            if (status > returns_)
dvander@195
    97
                returns_ = status;
dvander@195
    98
        }
dvander@195
    99
        void terminate(ReturnStatus status) {
dvander@195
   100
            if (terminates_)
dvander@195
   101
                return;
dvander@195
   102
            terminates_ = true;
dvander@195
   103
            returns_ = status;
dvander@195
   104
        }
dvander@195
   105
        void merge(const ControlStatus &left, const ControlStatus &right);
dvander@195
   106
        void inherit(const ControlStatus &other);
dvander@195
   107
dvander@195
   108
        ~ControlScope()
dvander@195
   109
        {
dvander@195
   110
            *prevp_ = prev_;
dvander@195
   111
        }
dvander@195
   112
    };
dvander@195
   113
dvander@195
   114
    class LoopScope
dvander@195
   115
    {
dvander@195
   116
        LoopScope **prevp_;
dvander@195
   117
        LoopScope *prev_;
dvander@195
   118
        unsigned breaks_;
dvander@195
   119
        unsigned continues_;
dvander@195
   120
dvander@195
   121
      public:
dvander@195
   122
        LoopScope(LoopScope **prev)
dvander@195
   123
          : prevp_(prev),
dvander@195
   124
            prev_(*prev),
dvander@195
   125
            breaks_(0),
dvander@195
   126
            continues_(0)
dvander@195
   127
        {
dvander@195
   128
            *prevp_ = this;
dvander@195
   129
        }
dvander@195
   130
dvander@195
   131
        ~LoopScope()
dvander@195
   132
        {
dvander@195
   133
            *prevp_ = prev_;
dvander@195
   134
        }
dvander@195
   135
dvander@195
   136
        void addBreak() {
dvander@195
   137
            breaks_++;
dvander@195
   138
        }
dvander@195
   139
        void addContinue() {
dvander@195
   140
            continues_++;
dvander@195
   141
        }
dvander@195
   142
        unsigned breaks() const {
dvander@195
   143
            return breaks_;
dvander@195
   144
        }
dvander@195
   145
        unsigned continues() const {
dvander@195
   146
            return continues_;
dvander@195
   147
        }
dvander@195
   148
    };
dvander@195
   149
dvander@195
   150
    ControlScope *control_;
dvander@195
   151
    LoopScope *loop_;
dvander@195
   152
dvander@195
   153
  private:
dvander@195
   154
    bool canTest(AstNode *node, Handle<Type> type);
dvander@195
   155
    void typeMismatch(const SourcePosition &pos, Handle<Type> actual, Handle<Type> given);
dvander@195
   156
    void unaryTypeError(AstNode *node, TokenKind token, Handle<Type> type);
dvander@195
   157
    void binaryTypeError(AstNode *node, TokenKind token, Handle<Type> left, Handle<Type> right);
dvander@195
   158
    Type *typeCheckBinary(AstNode *node, TokenKind token, Handle<Type> left, Handle<Type> right);
dvander@195
   159
dvander@195
   160
    Type *bindType(const SourcePosition &pos, BoundName *name);
dvander@195
   161
dvander@195
   162
    // These check if one type is compatible with another type, for various
dvander@195
   163
    // purposes, like:
dvander@195
   164
    //      return (expr) matches function return type
dvander@195
   165
    //      call(a, b)    matches expected arg type
dvander@195
   166
    //      a = b         matches declared type
dvander@195
   167
    //
dvander@195
   168
    bool typeCheckArrayAssignment(const SourcePosition &pos, Handle<Type> given, Handle<Type> actual, bool forAssign);
dvander@195
   169
    bool typeCheckAssignment(const SourcePosition &pos, Handle<Type> given, Handle<Type> actual, bool forAssign);
dvander@195
   170
    bool typeCheckParameter(AstNode *node, Handle<Type> given, Handle<Type> actual);
dvander@195
   171
dvander@195
   172
    Type *visitForLoad(Expression *expression);
dvander@195
   173
    bool preanalyze(FunctionStatement *node);
dvander@195
   174
    Type *visitForLValue(Expression *expression);
dvander@195
   175
    Type *visitAndApplyType(Expression *expression);
dvander@195
   176
    ControlStatus visitForControl(Statement *statement);
dvander@195
   177
dvander@195
   178
    bool evaluateDimensions(ExpressionList *exprs, int dims[MAX_ARRAY_DEPTH]);
dvander@195
   179
    bool inferFixedArrayLiteral(ArrayLiteral *literal,
dvander@195
   180
                                Handle<Type> type,
dvander@195
   181
                                int dims[MAX_ARRAY_DEPTH],
dvander@195
   182
                                unsigned dimcount,
dvander@195
   183
                                unsigned level);
dvander@195
   184
dvander@195
   185
    // Builds an array type used for parameters, returns, or field entries.
dvander@195
   186
    Type *buildArrayType(Handle<Type> type, ExpressionList *dimensions, bool isConst);
dvander@195
   187
dvander@195
   188
    Box *evaluateDefaultParameter(Handle<Type> type, Parameter *parameter);
dvander@195
   189
    bool checkArgumentCount(Handle<Type> type, unsigned actual);
dvander@195
   190
    bool buildFunctionArgs(AstNode *node, TokenKind kind, const FunctionSignature &sig,
dvander@195
   191
                           FixedArray **args, FixedArray **defaults);
dvander@195
   192
dvander@195
   193
    void markCallResultUsed(CallExpression *call);
dvander@195
   194
dvander@195
   195
    bool determineLiveFunctions();
dvander@195
   196
dvander@195
   197
  public:
dvander@195
   198
    SemanticAnalysis(Zone *zone, CompileContext &cc, ParseTree *tree);
dvander@195
   199
    bool analyze();
dvander@195
   200
dvander@195
   201
  public:
dvander@195
   202
    void visit(NameProxy *name);
dvander@195
   203
    void visit(Assignment *node);
dvander@195
   204
    void visit(BinaryExpression *node);
dvander@195
   205
    void visit(ReturnStatement *node);
dvander@195
   206
    void visit(ForStatement *node);
dvander@195
   207
    void visit(BlockStatement *node);
dvander@195
   208
    void visit(VariableDeclaration *node);
dvander@195
   209
    void visit(IntegerLiteral *node);
dvander@195
   210
    void visit(ExpressionStatement *node);
dvander@195
   211
    void visit(FunctionStatement *node);
dvander@195
   212
    void visit(CallExpression *node);
dvander@195
   213
    void visit(IfStatement *node);
dvander@195
   214
    void visit(IndexExpression *node);
dvander@195
   215
    void visit(EnumStatement *node);
dvander@195
   216
    void visit(FloatLiteral *node);
dvander@195
   217
    void visit(WhileStatement *node);
dvander@195
   218
    void visit(BreakStatement *node);
dvander@195
   219
    void visit(ContinueStatement *node);
dvander@195
   220
    void visit(StringLiteral *node);
dvander@195
   221
    void visit(IncDecExpression *node);
dvander@195
   222
    void visit(UnaryExpression *node);
dvander@195
   223
    void visit(TernaryExpression *node);
dvander@195
   224
    void visit(BooleanLiteral *node);
dvander@195
   225
    void visit(StructureStatement *node);
dvander@195
   226
    void visit(FieldExpression *node);
dvander@195
   227
    void visit(SwitchStatement *node);
dvander@195
   228
    void visit(FunctionTypeStatement *node);
dvander@195
   229
    void visit(ArrayLiteral *node);
dvander@195
   230
    void visit(ImportStatement *node);
dvander@195
   231
};
dvander@195
   232
dvander@195
   233
const char *GetTypeName(Type *type);
dvander@195
   234
dvander@195
   235
} // namespace ke
dvander@195
   236
dvander@195
   237
#endif // _include_semantic_analysis_h_