Split ArrayType from Type.
1 /* vim: set ts=4 sw=4 tw=99 et:
3 * Copyright (C) 2012 David Anderson
5 * This file is part of SourcePawn.
7 * SourcePawn 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)
12 * SourcePawn 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.
16 * You should have received a copy of the GNU General Public License along with
17 * SourcePawn. If not, see http://www.gnu.org/licenses/.
19 #include "../Strings.h"
21 #include "../TypeManager.h"
22 #include "NameBinding.h"
24 #include "ConstantEvaluator.h"
25 #include "../Spaces-inl.h"
26 #include "../Heap-inl.h"
30 // Create symbol tables and symbols for every scope and declaration. For type
31 // declarations and methods, we also pre-allocate a Type object, so that
32 // circular dependencies between types will work.
33 class NamePopulator : public AstVisitor
36 // This class is analagous to a Scope, however, it allows us to create
37 // scopes lazily. If a scope is requested, and the current environment
38 // has no scope, then a scope is created. If no scope is ever requested,
39 // a scope does not need to be created.
43 SymbolEnv(SymbolEnv **prevp, Scope *scope = NULL)
57 void setScope(Scope *scope) {
61 SymbolEnv *prev() const {
80 FunctionScope(FunctionScope **prevp)
90 ReturnStatus returns() const {
93 void returns(ReturnStatus status) {
98 FunctionScope **prevp_;
100 ReturnStatus status_;
104 NamePopulator(Zone *zone, CompileContext &cc, TranslationUnit *unit)
115 ImportScope *importScope = ImportScope::New(pool_);
119 // At the import level, we declare system types.
120 if (!declareSystemTypes(importScope))
123 GlobalScope *globalScope = GlobalScope::New(pool_, importScope);
127 unit_->setImportScope(importScope);
128 unit_->setGlobalScope(globalScope);
130 SymbolEnv env(&env_, globalScope);
132 for (size_t i = 0; i < unit_->tree()->statements()->length(); i++) {
133 Statement *stmt = unit_->tree()->statements()->at(i);
140 bool declareSystemType(ImportScope *scope, const char *name, Handle<Type> type) {
141 Local<String> tag(zone_, zone_->makeSymbol(name));
145 TypeSymbol *sym = new (pool_) TypeSymbol(scope, tag, type);
146 return scope->addSymbol(sym);
149 bool declareSystemType(ImportScope *scope, const char *name, PrimitiveType prim) {
150 Local<Type> primitive(zone_, zone_->types()->getPrimitive(prim));
152 return declareSystemType(scope, name, primitive);
155 bool declareSystemTypes(ImportScope *scope) {
156 if (!declareSystemType(scope, "float", PrimitiveType_Float))
158 if (!declareSystemType(scope, "_", PrimitiveType_Int32))
160 if (!declareSystemType(scope, "int", PrimitiveType_Int32))
162 if (!declareSystemType(scope, "bool", PrimitiveType_Bool))
164 if (!declareSystemType(scope, "char", PrimitiveType_Char))
167 Local<Type> voidType(zone_, zone_->types()->getVoid());
168 if (!declareSystemType(scope, "void", voidType))
174 void visitVariableDeclaration(VariableDeclaration *node) {
175 Scope *scope = env_->scope();
176 if (!scope || scope->kind() != Scope::GLOBAL) {
177 if ((scope = getOrCreateBlockScope()) == NULL)
181 if (scope->kind() == Scope::GLOBAL) {
182 // The symbol must be added now, since it could be an export.
183 VariableSymbol *sym = new (pool_) VariableSymbol(scope, node->name(), node->pos());
184 node->setSymbol(sym);
186 if (!registerName(scope, sym))
189 // We ensure the scope will exist at the name binding phase, but
190 // we don't actually register the variable symbol yet. Otherwise,
191 // when binding the initializer, we could encounter:
194 // And we don't necessarily want this to bind.
197 node->initialization()->accept(this);
199 void visitEnumStatement(EnumStatement *node) {
202 void visitFunctionStatement(FunctionStatement *node) {
203 // We create function types ahead of time, not for any particular
204 // reason. It makes things consistent with FunctionTypeStatement,
205 // which actually does produce a type.
206 Local<FunctionType> type(zone_, FunctionType::New(zone_, node->token()));
210 assert(env_->scope());
212 // Function statements are always named, so add the name to the outer scope.
213 FunctionSymbol *sym = new (pool_) FunctionSymbol(env_->scope(), node->name(), node->pos(), type);
214 if (!registerName(env_->scope(), sym))
217 if (node->token() == TOK_PUBLIC ||
218 node->token() == TOK_FORWARD ||
219 node->token() == TOK_NATIVE)
221 // We're in the global scope, for sure.
222 assert(env_->scope()->kind() == Scope::GLOBAL);
223 GlobalScope *globals = (GlobalScope *)env_->scope();
224 if (!globals->addPublic(sym))
228 node->setSymbol(sym);
230 // Scope for the function's arguments.
231 SymbolEnv argEnv(&env_);
232 if (!registerArguments(node->signature()))
235 // Scope for function body.
236 SymbolEnv localEnv(&env_);
237 FunctionScope fun(&fun_);
239 node->body()->accept(this);
241 // Function statements have quirky semantics around their return
242 // type. For reasonable compatibility with SP1, we use the following
243 // heuristics for when no explicit type is declared.
244 if (!node->signature().returnType()) {
245 Local<Type> type(zone_);
246 if (node->token() == TOK_FORWARD || node->token() == TOK_NATIVE) {
247 // If the function type is a native or forward, we always
248 // assume it returns an int32.
249 type = zone_->types()->getPrimitive(PrimitiveType_Int32);
250 } else if (fun.returns() != ValueReturn) {
251 // This function never returns a value, so mark it as
253 type = zone_->types()->getVoid();
255 // No need to NULL check here, we'll catch OOM later.
256 node->sym()->type()->setReturnType(type);
259 node->setScopes(argEnv.scope(), localEnv.scope());
261 void visitStructureStatement(StructureStatement *node) {
264 void visiFunctionTypeStatementt(FunctionTypeStatement *node) {
268 void visitNameProxy(NameProxy *name) {
270 void visitAssignment(Assignment *node) {
271 node->lvalue()->accept(this);
272 node->expression()->accept(this);
274 void visitBinaryExpression(BinaryExpression *node) {
275 node->left()->accept(this);
276 node->right()->accept(this);
278 void visitReturnStatement(ReturnStatement *node) {
279 if (node->expression())
280 fun_->returns(ValueReturn);
282 fun_->returns(VoidReturn);
284 void visitForStatement(ForStatement *node) {
285 SymbolEnv env(&env_);
287 if (node->initialization())
288 node->initialization()->accept(this);
289 if (node->condition())
290 node->condition()->accept(this);
292 node->update()->accept(this);
293 node->body()->accept(this);
295 node->setScope(env.scope());
297 void visitBlockStatement(BlockStatement *node) {
298 SymbolEnv env(&env_);
300 for (size_t i = 0; i < node->statements()->length(); i++)
301 node->statements()->at(i)->accept(this);
303 node->setScope(env.scope());
305 void visitIntegerLiteral(IntegerLiteral *node) {
307 void visitExpressionStatement(ExpressionStatement *node) {
308 node->expression()->accept(this);
310 void visitCallExpression(CallExpression *node) {
311 node->callee()->accept(this);
312 for (size_t i = 0; i < node->arguments()->length(); i++)
313 node->arguments()->at(i)->accept(this);
315 void visitIfStatement(IfStatement *node) {
316 node->ifTrue()->accept(this);
318 node->ifFalse()->accept(this);
320 void visitIndexExpression(IndexExpression *node) {
323 void visitFloatLiteral(FloatLiteral *node) {
325 void visitWhileStatement(WhileStatement *node) {
326 node->condition()->accept(this);
327 node->body()->accept(this);
329 void visitBreakStatement(BreakStatement *node) {
331 void visitContinueStatement(ContinueStatement *node) {
333 void visitStringLiteral(StringLiteral *node) {
335 void visitIncDecExpression(IncDecExpression *node) {
338 void visitUnaryExpression(UnaryExpression *node) {
341 void visitTernaryExpression(TernaryExpression *node) {
344 void visitBooleanLiteral(BooleanLiteral *node) {
346 void visitFieldExpression(FieldExpression *node) {
348 void visitSwitchStatement(SwitchStatement *node) {
349 if (node->defaultCase())
350 node->defaultCase()->accept(this);
352 for (size_t i = 0; i < node->cases()->length(); i++)
353 node->cases()->at(i)->statement()->accept(this);
355 void visitArrayLiteral(ArrayLiteral *node) {
357 void visitImportStatement(ImportStatement *node) {
361 Scope *getOrCreateBlockScope() {
363 assert(env_->scope()->kind() == Scope::BLOCK);
364 return env_->scope();
367 LocalScope *scope = LocalScope::New(pool_);
371 env_->setScope(scope);
375 bool registerName(Scope *scope, Symbol *sym) {
379 if (Symbol *other = scope->localLookup(sym->name())) {
380 // Report, but allow errors to continue.
381 cc_.reportError(sym->pos(), Message_RedeclaredName,
382 sym->name()->chars(),
388 return scope->addSymbol(sym);
391 bool registerArguments(const FunctionSignature &sig) {
392 if (!sig.parameters()->length())
395 ArgumentScope *argScope = ArgumentScope::New(pool_);
398 env_->setScope(argScope);
400 for (size_t i = 0; i < sig.parameters()->length(); i++) {
401 Parameter *param = sig.parameters()->at(i);
402 VariableSymbol *sym = new (pool_) VariableSymbol(argScope, param->name(), param->pos());
403 if (!registerName(env_->scope(), sym))
405 param->setSymbol(sym);
413 PoolAllocator &pool_;
415 TranslationUnit *unit_;
421 ke::PopulateNamesAndTypes(Zone *zone, CompileContext &cc, TranslationUnit *unit)
423 NamePopulator populator(zone, cc, unit);
424 return populator.analyze();
427 class NameBinder : public AstVisitor
433 AutoLinkScope(AutoLinkScope **prevp, Scope *scope)
441 scope_->setParent(prev_->scope());
446 assert(*prevp_ == this);
450 Scope *scope() const {
455 AutoLinkScope **prevp_;
456 AutoLinkScope *prev_;
461 NameBinder(Zone *zone, CompileContext &cc, TranslationUnit *unit)
471 // Start with the import scope, and collect all imported names.
472 AutoLinkScope importScope(&link_, unit_->importScope());
474 for (size_t i = 0; i < unit_->tree()->imports()->length(); i++)
475 unit_->tree()->imports()->at(i)->accept(this);
477 // Next, enter the global scope and walk all statements.
478 AutoLinkScope globalScope(&link_, unit_->globalScope());
479 for (size_t i = 0; i < unit_->tree()->statements()->length(); i++) {
480 Statement *stmt = unit_->tree()->statements()->at(i);
487 void visitVariableDeclaration(VariableDeclaration *node) {
488 // Bind the initializer before registering the declaration, so that we
489 // can error on bogus initializers (new x = x).
490 node->initialization()->accept(this);
492 Local<Type> type(zone_, bindType(node->type()));
500 // If the node already has a symbol (meaning it was a global), then
501 // we don't have to do anything more.
503 assert(node->sym()->scope()->kind() == Scope::GLOBAL);
504 node->sym()->setType(type);
508 VariableSymbol *sym = new (pool_) VariableSymbol(link_->scope(), node->name(), node->pos(), type);
509 node->setSymbol(sym);
511 if (Symbol *other = link_->scope()->localLookup(sym->name())) {
512 // Report, but allow errors to continue.
513 cc_.reportError(sym->pos(), Message_RedeclaredName,
514 sym->name()->chars(),
520 if (link_->scope()->addSymbol(sym))
523 void visitEnumStatement(EnumStatement *node) {
526 void visitFunctionStatement(FunctionStatement *node) {
527 AutoLinkScope argScope(&link_, node->argScope());
528 AutoLinkScope varScope(&link_, node->varScope());
530 Local<FunctionType> type(zone_, node->sym()->type());
531 if (!fillFunctionType(type, node->signature()))
535 node->body()->accept(this);
537 void visitStructureStatement(StructureStatement *node) {
540 void visitFunctionTypeStatement(FunctionTypeStatement *node) {
544 void visitNameProxy(NameProxy *proxy) {
545 Scope *scope = link_->scope();
546 Symbol *sym = scope->lookup(proxy->name());
548 cc_.reportError(proxy->pos(), Message_IdentifierNotFound, proxy->name()->chars());
551 void visitAssignment(Assignment *node) {
552 node->lvalue()->accept(this);
553 node->expression()->accept(this);
555 void visitBinaryExpression(BinaryExpression *node) {
556 node->left()->accept(this);
557 node->right()->accept(this);
559 void visitReturnStatement(ReturnStatement *node) {
560 node->expression()->accept(this);
562 void visitForStatement(ForStatement *node) {
563 AutoLinkScope scope(&link_, node->scope());
565 if (node->initialization())
566 node->initialization()->accept(this);
567 if (node->condition())
568 node->condition()->accept(this);
570 node->update()->accept(this);
571 node->body()->accept(this);
573 void visitBlockStatement(BlockStatement *node) {
574 AutoLinkScope scope(&link_, node->scope());
575 for (size_t i = 0; i < node->statements()->length(); i++)
576 node->statements()->at(i)->accept(this);
578 void visitIntegerLiteral(IntegerLiteral *node) {
580 void visitExpressionStatement(ExpressionStatement *node) {
581 node->expression()->accept(this);
583 void visitCallExpression(CallExpression *node) {
584 node->callee()->accept(this);
585 for (size_t i = 0; i < node->arguments()->length(); i++)
586 node->arguments()->at(i)->accept(this);
588 void visitIfStatement(IfStatement *node) {
589 node->condition()->accept(this);
590 node->ifTrue()->accept(this);
592 node->ifFalse()->accept(this);
594 void visitIndexExpression(IndexExpression *node) {
595 node->left()->accept(this);
596 node->right()->accept(this);
598 void visitFloatLiteral(FloatLiteral *node) {
600 void visitWhileStatement(WhileStatement *node) {
601 node->condition()->accept(this);
602 node->body()->accept(this);
604 void visitBreakStatement(BreakStatement *node) {
606 void visitContinueStatement(ContinueStatement *node) {
608 void visitStringLiteral(StringLiteral *node) {
610 void visitIncDecExpression(IncDecExpression *node) {
611 node->expression()->accept(this);
613 void visitUnaryExpression(UnaryExpression *node) {
615 node->tag()->accept(this);
616 node->expression()->accept(this);
618 void visitTernaryExpression(TernaryExpression *node) {
619 node->condition()->accept(this);
620 node->left()->accept(this);
621 node->right()->accept(this);
623 void visitBooleanLiteral(BooleanLiteral *node) {
625 void visitFieldExpression(FieldExpression *node) {
626 node->left()->accept(this);
628 void visitSwitchStatement(SwitchStatement *node) {
629 node->expression()->accept(this);
630 node->defaultCase()->accept(this);
631 for (size_t i = 0; i < node->cases()->length(); i++) {
632 // We don't test case expressions because they are literals.
633 Case *c = node->cases()->at(i);
634 c->statement()->accept(this);
637 void visitArrayLiteral(ArrayLiteral *node) {
638 for (size_t i = 0; i < node->expressions()->length(); i++)
639 node->expressions()->at(i)->accept(this);
641 void visitImportStatement(ImportStatement *node) {
642 if (node->suffix() == TOK_STAR) {
643 // Import every name.
646 GlobalScope *other = node->source()->globalScope();
647 Symbol *sym = other->findPublic(node->name());
649 cc_.reportError(node->pos(), Message_CannotResolveImport, node->name()->chars());
652 link_->scope()->addSymbol(sym);
657 bool fillFunctionType(Handle<FunctionType> fun, const FunctionSignature &sig) {
658 Local<Type> type(zone_);
659 if (!fun->returnType()) {
660 if ((type = bindType(sig.returnType())) == NULL)
662 fun->setReturnType(type);
665 Local<FixedArray> params(zone_, FixedArray::New(zone_, sig.parameters()->length(), Heap::Tenure_Old));
669 for (size_t i = 0; i < sig.parameters()->length(); i++) {
670 Parameter *param = sig.parameters()->at(i);
671 if ((type = bindType(param->type())) == NULL)
673 params->set(zone_, i, type);
676 fun->setParameterTypes(params);
681 Type *bindType(Expression *expr) {
683 // If no type was declared, we return int32.
684 return zone_->types()->getPrimitive(PrimitiveType_Int32);
689 NameProxy *proxy = expr->asNameProxy();
692 Symbol *sym = proxy->sym();
696 if (!sym->isType()) {
697 cc_.reportError(expr->pos(), Message_IdentifierIsNotAType, sym->name()->chars());
706 PoolAllocator &pool_;
708 TranslationUnit *unit_;
709 AutoLinkScope *link_;
713 ke::BindNamesAndTypes(Zone *zone, CompileContext &cc, TranslationUnit *unit)
715 NameBinder binder(zone, cc, unit);
716 return binder.bind();