1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/src/OldSema.h Sat Nov 17 18:41:01 2012 -0800
1.3 @@ -0,0 +1,237 @@
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 + void visit(ImportStatement *node);
1.234 +};
1.235 +
1.236 +const char *GetTypeName(Type *type);
1.237 +
1.238 +} // namespace ke
1.239 +
1.240 +#endif // _include_semantic_analysis_h_