1.1 --- a/src/SemanticAnalysis.h Mon Sep 17 00:10:01 2012 -0700
1.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
1.3 @@ -1,236 +0,0 @@
1.4 -/* vim: set ts=4 sw=4 tw=99 et:
1.5 - *
1.6 - * Copyright (C) 2012 David Anderson
1.7 - *
1.8 - * This file is part of JITCraft.
1.9 - *
1.10 - * JITCraft is free software: you can redistribute it and/or modify it under
1.11 - * the terms of the GNU General Public License as published by the Free
1.12 - * Software Foundation, either version 3 of the License, or (at your option)
1.13 - * any later version.
1.14 - *
1.15 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
1.16 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1.17 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
1.18 - *
1.19 - * You should have received a copy of the GNU General Public License along with
1.20 - * JITCraft. If not, see http://www.gnu.org/licenses/.
1.21 - */
1.22 -#ifndef _include_semantic_analysis_h_
1.23 -#define _include_semantic_analysis_h_
1.24 -
1.25 -#include <assert.h>
1.26 -#include "AST.h"
1.27 -#include "Types.h"
1.28 -
1.29 -namespace ke {
1.30 -
1.31 -class Box;
1.32 -
1.33 -class SemanticAnalysis : public AstVisitor
1.34 -{
1.35 - Zone *zone_;
1.36 - CompileContext &cc_;
1.37 - ParseTree *tree_;
1.38 - Scope *scope_;
1.39 - NamedFunction *function_;
1.40 -
1.41 - enum ReturnStatus
1.42 - {
1.43 - Returns_Never,
1.44 - Returns_Sometimes,
1.45 - Returns_Always
1.46 - };
1.47 -
1.48 - // Tuple that describes whether a path terminates control flow, and
1.49 - // if it is guaranteed to end in a return.
1.50 - class ControlStatus
1.51 - {
1.52 - bool terminates_;
1.53 - ReturnStatus returns_;
1.54 -
1.55 - public:
1.56 - ControlStatus(bool terminates, ReturnStatus returns)
1.57 - : terminates_(terminates),
1.58 - returns_(returns)
1.59 - {
1.60 - }
1.61 -
1.62 - bool terminates() const {
1.63 - return terminates_;
1.64 - }
1.65 - ReturnStatus returns() const {
1.66 - return returns_;
1.67 - }
1.68 - };
1.69 -
1.70 - // Used to keep track of terminating control flow and return statements
1.71 - // inside control structures.
1.72 - class ControlScope
1.73 - {
1.74 - ReturnStatus returns_;
1.75 - ControlScope **prevp_;
1.76 - ControlScope *prev_;
1.77 - bool terminates_;
1.78 -
1.79 - public:
1.80 - ControlScope(ControlScope **prev)
1.81 - : returns_(Returns_Never),
1.82 - prevp_(prev),
1.83 - prev_(*prev),
1.84 - terminates_(false)
1.85 - {
1.86 - *prevp_ = this;
1.87 - }
1.88 -
1.89 - ControlStatus status() const {
1.90 - return ControlStatus(terminates_, returns_);
1.91 - }
1.92 -
1.93 - // We allow multiple terminators, but only the first one takes effect.
1.94 - // For example, |break; continue;| is legal but the continue is
1.95 - // unreachable.
1.96 - void returns(ReturnStatus status) {
1.97 - if (terminates_)
1.98 - return;
1.99 - if (status > returns_)
1.100 - returns_ = status;
1.101 - }
1.102 - void terminate(ReturnStatus status) {
1.103 - if (terminates_)
1.104 - return;
1.105 - terminates_ = true;
1.106 - returns_ = status;
1.107 - }
1.108 - void merge(const ControlStatus &left, const ControlStatus &right);
1.109 - void inherit(const ControlStatus &other);
1.110 -
1.111 - ~ControlScope()
1.112 - {
1.113 - *prevp_ = prev_;
1.114 - }
1.115 - };
1.116 -
1.117 - class LoopScope
1.118 - {
1.119 - LoopScope **prevp_;
1.120 - LoopScope *prev_;
1.121 - unsigned breaks_;
1.122 - unsigned continues_;
1.123 -
1.124 - public:
1.125 - LoopScope(LoopScope **prev)
1.126 - : prevp_(prev),
1.127 - prev_(*prev),
1.128 - breaks_(0),
1.129 - continues_(0)
1.130 - {
1.131 - *prevp_ = this;
1.132 - }
1.133 -
1.134 - ~LoopScope()
1.135 - {
1.136 - *prevp_ = prev_;
1.137 - }
1.138 -
1.139 - void addBreak() {
1.140 - breaks_++;
1.141 - }
1.142 - void addContinue() {
1.143 - continues_++;
1.144 - }
1.145 - unsigned breaks() const {
1.146 - return breaks_;
1.147 - }
1.148 - unsigned continues() const {
1.149 - return continues_;
1.150 - }
1.151 - };
1.152 -
1.153 - ControlScope *control_;
1.154 - LoopScope *loop_;
1.155 -
1.156 - private:
1.157 - bool canTest(AstNode *node, Handle<Type> type);
1.158 - void typeMismatch(const SourcePosition &pos, Handle<Type> actual, Handle<Type> given);
1.159 - void unaryTypeError(AstNode *node, TokenKind token, Handle<Type> type);
1.160 - void binaryTypeError(AstNode *node, TokenKind token, Handle<Type> left, Handle<Type> right);
1.161 - Type *typeCheckBinary(AstNode *node, TokenKind token, Handle<Type> left, Handle<Type> right);
1.162 -
1.163 - Type *bindType(const SourcePosition &pos, BoundName *name);
1.164 -
1.165 - // These check if one type is compatible with another type, for various
1.166 - // purposes, like:
1.167 - // return (expr) matches function return type
1.168 - // call(a, b) matches expected arg type
1.169 - // a = b matches declared type
1.170 - //
1.171 - bool typeCheckArrayAssignment(const SourcePosition &pos, Handle<Type> given, Handle<Type> actual, bool forAssign);
1.172 - bool typeCheckAssignment(const SourcePosition &pos, Handle<Type> given, Handle<Type> actual, bool forAssign);
1.173 - bool typeCheckParameter(AstNode *node, Handle<Type> given, Handle<Type> actual);
1.174 -
1.175 - Type *visitForLoad(Expression *expression);
1.176 - bool preanalyze(FunctionStatement *node);
1.177 - Type *visitForLValue(Expression *expression);
1.178 - Type *visitAndApplyType(Expression *expression);
1.179 - ControlStatus visitForControl(Statement *statement);
1.180 -
1.181 - bool evaluateDimensions(ExpressionList *exprs, int dims[MAX_ARRAY_DEPTH]);
1.182 - bool inferFixedArrayLiteral(ArrayLiteral *literal,
1.183 - Handle<Type> type,
1.184 - int dims[MAX_ARRAY_DEPTH],
1.185 - unsigned dimcount,
1.186 - unsigned level);
1.187 -
1.188 - // Builds an array type used for parameters, returns, or field entries.
1.189 - Type *buildArrayType(Handle<Type> type, ExpressionList *dimensions, bool isConst);
1.190 -
1.191 - Box *evaluateDefaultParameter(Handle<Type> type, Parameter *parameter);
1.192 - bool checkArgumentCount(Handle<Type> type, unsigned actual);
1.193 - bool buildFunctionArgs(AstNode *node, TokenKind kind, const FunctionSignature &sig,
1.194 - FixedArray **args, FixedArray **defaults);
1.195 -
1.196 - void markCallResultUsed(CallExpression *call);
1.197 -
1.198 - bool determineLiveFunctions();
1.199 -
1.200 - public:
1.201 - SemanticAnalysis(Zone *zone, CompileContext &cc, ParseTree *tree);
1.202 - bool analyze();
1.203 -
1.204 - public:
1.205 - void visit(NameProxy *name);
1.206 - void visit(Assignment *node);
1.207 - void visit(BinaryExpression *node);
1.208 - void visit(ReturnStatement *node);
1.209 - void visit(ForStatement *node);
1.210 - void visit(BlockStatement *node);
1.211 - void visit(VariableDeclaration *node);
1.212 - void visit(IntegerLiteral *node);
1.213 - void visit(ExpressionStatement *node);
1.214 - void visit(FunctionStatement *node);
1.215 - void visit(CallExpression *node);
1.216 - void visit(IfStatement *node);
1.217 - void visit(IndexExpression *node);
1.218 - void visit(EnumStatement *node);
1.219 - void visit(FloatLiteral *node);
1.220 - void visit(WhileStatement *node);
1.221 - void visit(BreakStatement *node);
1.222 - void visit(ContinueStatement *node);
1.223 - void visit(StringLiteral *node);
1.224 - void visit(IncDecExpression *node);
1.225 - void visit(UnaryExpression *node);
1.226 - void visit(TernaryExpression *node);
1.227 - void visit(BooleanLiteral *node);
1.228 - void visit(StructureStatement *node);
1.229 - void visit(FieldExpression *node);
1.230 - void visit(SwitchStatement *node);
1.231 - void visit(FunctionTypeStatement *node);
1.232 - void visit(ArrayLiteral *node);
1.233 -};
1.234 -
1.235 -const char *GetTypeName(Type *type);
1.236 -
1.237 -} // namespace ke
1.238 -
1.239 -#endif // _include_semantic_analysis_h_