1.1 --- a/jitcraft/SemanticAnalysis.h Thu Jul 12 00:38:00 2012 -0700
1.2 +++ b/jitcraft/SemanticAnalysis.h Sat Jul 14 18:43:34 2012 -0700
1.3 @@ -29,10 +29,123 @@
1.4 Zone *zone_;
1.5 CompileContext &cc_;
1.6 ParseTree *tree_;
1.7 - unsigned loopDepth_;
1.8 Scope *scope_;
1.9 ScopedRoot<Type> function_;
1.10
1.11 + enum ReturnStatus
1.12 + {
1.13 + Returns_Never,
1.14 + Returns_Sometimes,
1.15 + Returns_Always
1.16 + };
1.17 +
1.18 + // Tuple that describes whether a path terminates control flow, and
1.19 + // if it is guaranteed to end in a return.
1.20 + class ControlStatus
1.21 + {
1.22 + bool terminates_;
1.23 + ReturnStatus returns_;
1.24 +
1.25 + public:
1.26 + ControlStatus(bool terminates, ReturnStatus returns)
1.27 + : terminates_(terminates),
1.28 + returns_(returns)
1.29 + {
1.30 + }
1.31 +
1.32 + bool terminates() const {
1.33 + return terminates_;
1.34 + }
1.35 + ReturnStatus returns() const {
1.36 + return returns_;
1.37 + }
1.38 + };
1.39 +
1.40 + // Used to keep track of terminating control flow and return statements
1.41 + // inside control structures.
1.42 + class ControlScope
1.43 + {
1.44 + ReturnStatus returns_;
1.45 + ControlScope **prevp_;
1.46 + ControlScope *prev_;
1.47 + bool terminates_;
1.48 +
1.49 + public:
1.50 + ControlScope(ControlScope **prev)
1.51 + : returns_(Returns_Never),
1.52 + prevp_(prev),
1.53 + prev_(*prev),
1.54 + terminates_(false)
1.55 + {
1.56 + *prevp_ = this;
1.57 + }
1.58 +
1.59 + ControlStatus status() const {
1.60 + return ControlStatus(terminates_, returns_);
1.61 + }
1.62 +
1.63 + // We allow multiple terminators, but only the first one takes effect.
1.64 + // For example, |break; continue;| is legal but the continue is
1.65 + // unreachable.
1.66 + void returns(ReturnStatus status) {
1.67 + if (terminates_)
1.68 + return;
1.69 + if (status > returns_)
1.70 + returns_ = status;
1.71 + }
1.72 + void terminate(ReturnStatus status) {
1.73 + if (terminates_)
1.74 + return;
1.75 + terminates_ = true;
1.76 + returns_ = status;
1.77 + }
1.78 + void merge(const ControlStatus &left, const ControlStatus &right);
1.79 +
1.80 + ~ControlScope()
1.81 + {
1.82 + *prevp_ = prev_;
1.83 + }
1.84 + };
1.85 +
1.86 + class LoopScope
1.87 + {
1.88 + LoopScope **prevp_;
1.89 + LoopScope *prev_;
1.90 + unsigned breaks_;
1.91 + unsigned continues_;
1.92 +
1.93 + public:
1.94 + LoopScope(LoopScope **prev)
1.95 + : prevp_(prev),
1.96 + prev_(*prev),
1.97 + breaks_(0),
1.98 + continues_(0)
1.99 + {
1.100 + *prevp_ = this;
1.101 + }
1.102 +
1.103 + ~LoopScope()
1.104 + {
1.105 + *prevp_ = prev_;
1.106 + }
1.107 +
1.108 + void addBreak() {
1.109 + breaks_++;
1.110 + }
1.111 + void addContinue() {
1.112 + continues_++;
1.113 + }
1.114 + unsigned breaks() const {
1.115 + return breaks_;
1.116 + }
1.117 + unsigned continues() const {
1.118 + return continues_;
1.119 + }
1.120 + };
1.121 +
1.122 + ControlScope *control_;
1.123 + LoopScope *loop_;
1.124 +
1.125 private:
1.126 bool canTest(AstNode *node, Handle<Type> type);
1.127 void unaryTypeError(AstNode *node, TokenKind token, Handle<Type> type);
1.128 @@ -47,14 +160,15 @@
1.129 //
1.130 bool typeCheckArrayAssignment(AstNode *node, Handle<Type> given, Handle<Type> actual, bool forAssign);
1.131 bool typeCheckAssignment(AstNode *node, Handle<Type> given, Handle<Type> actual, bool forAssign);
1.132 -
1.133 bool typeCheckParameter(AstNode *node, Handle<Type> given, Handle<Type> actual);
1.134
1.135 Type *visitForLoad(Expression *expression);
1.136 - Type *visitForRef(Expression *expression);
1.137 bool preanalyze(FunctionStatement *node);
1.138 Type *visitForLValue(Expression *expression);
1.139 Type *visitAndApplyType(Expression *expression);
1.140 + ControlStatus visitForControl(Statement *statement);
1.141 +
1.142 + void markCallResultUsed(CallExpression *call);
1.143
1.144 public:
1.145 SemanticAnalysis(Zone *zone, CompileContext &cc, ParseTree *tree);