src/SemanticAnalysis.h
author David Anderson <dvander@alliedmods.net>
Sun Sep 16 21:34:10 2012 -0700 (2012-09-16)
changeset 188 bab29bcec7fe
parent 187 9308d52205a0
child 191 9d17f29fe16a
permissions -rw-r--r--
Restructure Array so the elements vector can be replaced.
     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_semantic_analysis_h_
    20 #define _include_semantic_analysis_h_
    21 
    22 #include <assert.h>
    23 #include "AST.h"
    24 #include "Types.h"
    25 
    26 namespace ke {
    27 
    28 class Box;
    29 
    30 class SemanticAnalysis : public AstVisitor
    31 {
    32     Zone *zone_;
    33     CompileContext &cc_;
    34     ParseTree *tree_;
    35     Scope *scope_;
    36     NamedFunction *function_;
    37 
    38     enum ReturnStatus
    39     {
    40         Returns_Never,
    41         Returns_Sometimes,
    42         Returns_Always
    43     };
    44 
    45     // Tuple that describes whether a path terminates control flow, and
    46     // if it is guaranteed to end in a return.
    47     class ControlStatus
    48     {
    49         bool terminates_;
    50         ReturnStatus returns_;
    51 
    52       public:
    53         ControlStatus(bool terminates, ReturnStatus returns)
    54           : terminates_(terminates),
    55             returns_(returns)
    56         {
    57         }
    58 
    59         bool terminates() const {
    60             return terminates_;
    61         }
    62         ReturnStatus returns() const {
    63             return returns_;
    64         }
    65     };
    66 
    67     // Used to keep track of terminating control flow and return statements
    68     // inside control structures.
    69     class ControlScope
    70     {
    71         ReturnStatus returns_;
    72         ControlScope **prevp_;
    73         ControlScope *prev_;
    74         bool terminates_;
    75 
    76       public:
    77         ControlScope(ControlScope **prev)
    78           : returns_(Returns_Never),
    79             prevp_(prev),
    80             prev_(*prev),
    81             terminates_(false)
    82         {
    83             *prevp_ = this;
    84         }
    85 
    86         ControlStatus status() const {
    87             return ControlStatus(terminates_, returns_);
    88         }
    89 
    90         // We allow multiple terminators, but only the first one takes effect.
    91         // For example, |break; continue;| is legal but the continue is
    92         // unreachable.
    93         void returns(ReturnStatus status) {
    94             if (terminates_)
    95                 return;
    96             if (status > returns_)
    97                 returns_ = status;
    98         }
    99         void terminate(ReturnStatus status) {
   100             if (terminates_)
   101                 return;
   102             terminates_ = true;
   103             returns_ = status;
   104         }
   105         void merge(const ControlStatus &left, const ControlStatus &right);
   106         void inherit(const ControlStatus &other);
   107 
   108         ~ControlScope()
   109         {
   110             *prevp_ = prev_;
   111         }
   112     };
   113 
   114     class LoopScope
   115     {
   116         LoopScope **prevp_;
   117         LoopScope *prev_;
   118         unsigned breaks_;
   119         unsigned continues_;
   120 
   121       public:
   122         LoopScope(LoopScope **prev)
   123           : prevp_(prev),
   124             prev_(*prev),
   125             breaks_(0),
   126             continues_(0)
   127         {
   128             *prevp_ = this;
   129         }
   130 
   131         ~LoopScope()
   132         {
   133             *prevp_ = prev_;
   134         }
   135 
   136         void addBreak() {
   137             breaks_++;
   138         }
   139         void addContinue() {
   140             continues_++;
   141         }
   142         unsigned breaks() const {
   143             return breaks_;
   144         }
   145         unsigned continues() const {
   146             return continues_;
   147         }
   148     };
   149 
   150     ControlScope *control_;
   151     LoopScope *loop_;
   152 
   153   private:
   154     bool canTest(AstNode *node, Handle<Type> type);
   155     void typeMismatch(const SourcePosition &pos, Handle<Type> actual, Handle<Type> given);
   156     void unaryTypeError(AstNode *node, TokenKind token, Handle<Type> type);
   157     void binaryTypeError(AstNode *node, TokenKind token, Handle<Type> left, Handle<Type> right);
   158     Type *typeCheckBinary(AstNode *node, TokenKind token, Handle<Type> left, Handle<Type> right);
   159 
   160     Type *bindType(const SourcePosition &pos, BoundName *name);
   161 
   162     // These check if one type is compatible with another type, for various
   163     // purposes, like:
   164     //      return (expr) matches function return type
   165     //      call(a, b)    matches expected arg type
   166     //      a = b         matches declared type
   167     //
   168     bool typeCheckArrayAssignment(const SourcePosition &pos, Handle<Type> given, Handle<Type> actual, bool forAssign);
   169     bool typeCheckAssignment(const SourcePosition &pos, Handle<Type> given, Handle<Type> actual, bool forAssign);
   170     bool typeCheckParameter(AstNode *node, Handle<Type> given, Handle<Type> actual);
   171 
   172     Type *visitForLoad(Expression *expression);
   173     bool preanalyze(FunctionStatement *node);
   174     Type *visitForLValue(Expression *expression);
   175     Type *visitAndApplyType(Expression *expression);
   176     ControlStatus visitForControl(Statement *statement);
   177 
   178     bool evaluateDimensions(ExpressionList *exprs, int dims[MAX_ARRAY_DEPTH]);
   179     bool inferFixedArrayLiteral(ArrayLiteral *literal,
   180                                 Handle<Type> type,
   181                                 int dims[MAX_ARRAY_DEPTH],
   182                                 unsigned dimcount,
   183                                 unsigned level);
   184 
   185     Box *evaluateDefaultParameter(Handle<Type> type, Parameter *parameter);
   186     bool checkArgumentCount(Handle<Type> type, unsigned actual);
   187     bool buildFunctionArgs(AstNode *node, TokenKind kind, const FunctionSignature &sig,
   188                            FixedArray **args, FixedArray **defaults);
   189 
   190     void markCallResultUsed(CallExpression *call);
   191 
   192     bool determineLiveFunctions();
   193 
   194   public:
   195     SemanticAnalysis(Zone *zone, CompileContext &cc, ParseTree *tree);
   196     bool analyze();
   197 
   198   public:
   199     void visit(NameProxy *name);
   200     void visit(Assignment *node);
   201     void visit(BinaryExpression *node);
   202     void visit(ReturnStatement *node);
   203     void visit(ForStatement *node);
   204     void visit(BlockStatement *node);
   205     void visit(VariableDeclaration *node);
   206     void visit(IntegerLiteral *node);
   207     void visit(ExpressionStatement *node);
   208     void visit(FunctionStatement *node);
   209     void visit(CallExpression *node);
   210     void visit(IfStatement *node);
   211     void visit(IndexExpression *node);
   212     void visit(EnumStatement *node);
   213     void visit(FloatLiteral *node);
   214     void visit(WhileStatement *node);
   215     void visit(BreakStatement *node);
   216     void visit(ContinueStatement *node);
   217     void visit(StringLiteral *node);
   218     void visit(IncDecExpression *node);
   219     void visit(UnaryExpression *node);
   220     void visit(TernaryExpression *node);
   221     void visit(BooleanLiteral *node);
   222     void visit(StructureStatement *node);
   223     void visit(FieldExpression *node);
   224     void visit(SwitchStatement *node);
   225     void visit(FunctionTypeStatement *node);
   226     void visit(ArrayLiteral *node);
   227 };
   228 
   229 const char *GetTypeName(Type *type);
   230 
   231 } // namespace ke
   232 
   233 #endif // _include_semantic_analysis_h_