Fixed type checking for multidimensional arrays.
2 * Copyright (C) 2012 David Anderson
4 * This file is part of SourcePawn.
6 * SourcePawn is free software: you can redistribute it and/or modify it under
7 * the terms of the GNU General Public License as published by the Free
8 * Software Foundation, either version 3 of the License, or (at your option)
11 * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along with
16 * SourcePawn. If not, see http://www.gnu.org/licenses/.
18 #ifndef _include_sp2_sema_h_
19 #define _include_sp2_sema_h_
24 #include "BytecodeEmitter.h"
28 // Semantic analysis occurs after all names and types have been bound. It
29 // performs the important task of validating the semantics and type safety
32 // The semantic analysis phase also produces bytecode. This occurs on a
33 // statement-by-statement basis. The result of analyzing an expression is a
34 // tree of operations which is then flattened.
35 class SemanticAnalysis : public AstVisitor
38 SemanticAnalysis(Zone *zone, CompileContext &cc, TranslationUnit *unit);
43 SemanticAnalysis(SemanticAnalysis *parent, Handle<FunctionType> fun);
44 Function *compile(FunctionStatement *stmt);
47 void visitFunctionStatement(FunctionStatement *node);
48 void visitBlockStatement(BlockStatement *node);
49 void visitExpressionStatement(ExpressionStatement *node);
50 void visitReturnStatement(ReturnStatement *node);
51 void visitEnumStatement(EnumStatement *node);
53 void visitCallExpression(CallExpression *node);
54 void visitNameProxy(NameProxy *name);
55 void visitIntegerLiteral(IntegerLiteral *node);
56 void visitFloatLiteral(FloatLiteral *node);
57 void visitVariableDeclaration(VariableDeclaration *node);
58 void visitForStatement(ForStatement *node);
59 void visitWhileStatement(WhileStatement *node);
60 void visitAssignment(Assignment *node);
61 void visitBinaryExpression(BinaryExpression *node);
62 void visitBreakStatement(BreakStatement *node);
63 void visitContinueStatement(ContinueStatement *node);
64 void visitIfStatement(IfStatement *node);
65 void visitIndexExpression(IndexExpression *node);
66 void visitIncDecExpression(IncDecExpression *node);
67 void visitStringLiteral(StringLiteral *node);
68 void visitUnaryExpression(UnaryExpression *node);
69 void visitBooleanLiteral(BooleanLiteral *node);
70 void visitFieldExpression(FieldExpression *node);
72 void visitFunctionTypeStatement(FunctionTypeStatement *node);
73 void visitImportStatement(ImportStatement *node);
74 void visitStructureStatement(StructureStatement *node);
75 void visitSwitchStatement(SwitchStatement *node);
77 void visitTernaryExpression(TernaryExpression *node);
78 void visitArrayLiteral(ArrayLiteral *node);
82 bool checkArgumentCount(Handle<FunctionType> type, unsigned actual);
83 void import(HIR *hir, FieldExpression *node);
93 // For a given control flow path, whether it returns.
101 // For a given control flow path, whether it terminates,
102 // and if it terminates, whether it returns.
106 ReturnStatus returns_;
112 ControlStatus(bool terminates, ReturnStatus returns)
113 : terminates_(terminates),
118 bool terminates() const {
121 ReturnStatus returns() const {
128 ReturnStatus returns_;
129 ControlScope **prevp_;
134 ControlScope(ControlScope **prevp)
135 : returns_(Returns_Never),
145 ControlStatus status() {
146 return ControlStatus(terminates_, returns_);
149 void returns(ReturnStatus status) {
150 // We allow multiple terminates, but only the first one takes
151 // effect. For example, |break; continue;| is legal, but the
152 // continue is unreachable.
155 if (status > returns_)
158 void terminate(ReturnStatus status) {
164 void merge(const ControlStatus &left, const ControlStatus &right);
165 void inherit(const ControlStatus &other);
169 void requireLifoStack();
170 ControlStatus visitForControl(Statement *statement);
171 ControlStatus visitLoopBody(Statement *stmt);
172 void visitForTest(Expression *expr,
173 BytecodeEmitter::Label *trueBranch,
174 BytecodeEmitter::Label *falseBranch,
175 BytecodeEmitter::Label *fallthrough);
176 void set(VariableSymbol *sym);
177 HIR *eval(Expression *expr);
178 HIR *binary(AstNode *node, TokenKind token, HIR *left, HIR *right);
179 HIR *coerce(HIR *from, Handle<Type> to, CoercionKind kind);
180 Type *coercionType(TokenKind token, HIR *left, HIR *right);
181 HLValue *lvalue(Expression *expr);
182 void discharge(HIR *hir);
183 HIR *typeFailure(const SourcePosition &pos, Handle<Type> from, Handle<Type> to);
185 HIR *typeCheckArray(const SourcePosition &pos,
187 Handle<ArrayType> argActual,
191 // Used to target break/catch statements.
195 BytecodeEmitter::Label *bk_;
196 BytecodeEmitter::Label *ct_;
203 LoopScope(Scope *scope, BytecodeEmitter::Label *bk, BytecodeEmitter::Label *ct,
210 usesLifoStack_(false),
221 BytecodeEmitter::Label *break_() {
224 BytecodeEmitter::Label *continue_() {
230 void setUsesLifoStack() {
231 usesLifoStack_ = true;
233 bool usesLifoStack() const {
234 return usesLifoStack_;
239 bool breaks() const {
246 PoolAllocator &pool_;
248 TranslationUnit *unit_;
251 BytecodeEmitter emitter_;
252 ScopedRoot<FunctionType> fun_;
254 ControlScope *control_;
259 #endif // _include_sp2_sema_h_