Don't allow declaring void variables.
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 if (node->initialization())
198 node->initialization()->accept(this);
200 void visitEnumStatement(EnumStatement *node) {
201 Local<String> name(zone_, node->name());
202 Local<Type> type(zone_);
204 type = zone_->types()->newEnum(name);
206 type = zone_->types()->getPrimitive(PrimitiveType_Int32);
211 Scope *scope = getGlobalOrCreateBlockScope();
216 TypeSymbol *sym = new (pool_) TypeSymbol(scope, name, type);
217 if (!registerName(scope, sym))
222 for (size_t i = 0; i < node->entries()->length(); i++) {
223 EnumStatement::Entry &entry = node->entries()->at(i);
224 BoxedPrimitive box = BoxedPrimitive::Int(value);
226 if (!EvaluateForConstant(entry.expr, &box) || box.type() != PrimitiveType_Int32) {
227 cc_.reportError(entry.expr->pos(), Message_EnumFieldNotConstant);
231 assert(box.type() == PrimitiveType_Int32);
235 ConstantSymbol *sym = new (pool_) ConstantSymbol(scope, entry.name, entry.pos, type, box);
236 if (!registerName(scope, sym))
242 void visitFunctionStatement(FunctionStatement *node) {
243 // We create function types ahead of time, not for any particular
244 // reason. It makes things consistent with FunctionTypeStatement,
245 // which actually does produce a type.
246 Local<FunctionType> type(zone_, FunctionType::New(zone_, node->name(), node->token()));
250 assert(env_->scope());
252 // Function statements are always named, so add the name to the outer scope.
253 FunctionSymbol *sym = new (pool_) FunctionSymbol(env_->scope(), node->name(), node->pos(), type);
254 if (!registerName(env_->scope(), sym))
257 if (node->token() == TOK_PUBLIC ||
258 node->token() == TOK_FORWARD ||
259 node->token() == TOK_NATIVE)
261 // We're in the global scope, for sure.
262 assert(env_->scope()->kind() == Scope::GLOBAL);
263 GlobalScope *globals = (GlobalScope *)env_->scope();
264 if (!globals->addPublic(sym))
268 node->setSymbol(sym);
270 // Scope for the function's arguments.
271 SymbolEnv argEnv(&env_);
272 if (!registerArguments(node->signature()))
275 // Scope for function body.
276 SymbolEnv localEnv(&env_);
277 FunctionScope fun(&fun_);
279 node->body()->accept(this);
281 // Function statements have quirky semantics around their return
282 // type. For reasonable compatibility with SP1, we use the following
283 // heuristics for when no explicit type is declared.
284 if (!node->signature().returnType()) {
285 Local<Type> type(zone_);
286 if (node->token() == TOK_FORWARD || node->token() == TOK_NATIVE) {
287 // If the function type is a native or forward, we always
288 // assume it returns an int32.
289 type = zone_->types()->getPrimitive(PrimitiveType_Int32);
290 } else if (fun.returns() != ValueReturn) {
291 // This function never returns a value, so mark it as
293 type = zone_->types()->getVoid();
295 // No need to NULL check here, we'll catch OOM later.
296 node->sym()->type()->setReturnType(type);
299 node->setScopes(argEnv.scope(), localEnv.scope());
301 void visitStructureStatement(StructureStatement *node) {
304 void visiFunctionTypeStatementt(FunctionTypeStatement *node) {
308 void visitNameProxy(NameProxy *name) {
310 void visitAssignment(Assignment *node) {
311 node->lvalue()->accept(this);
312 node->expression()->accept(this);
314 void visitBinaryExpression(BinaryExpression *node) {
315 node->left()->accept(this);
316 node->right()->accept(this);
318 void visitReturnStatement(ReturnStatement *node) {
319 if (node->expression())
320 fun_->returns(ValueReturn);
322 fun_->returns(VoidReturn);
324 void visitForStatement(ForStatement *node) {
325 SymbolEnv env(&env_);
327 if (node->initialization())
328 node->initialization()->accept(this);
329 if (node->condition())
330 node->condition()->accept(this);
332 node->update()->accept(this);
333 node->body()->accept(this);
335 node->setScope(env.scope());
337 void visitBlockStatement(BlockStatement *node) {
338 SymbolEnv env(&env_);
340 for (size_t i = 0; i < node->statements()->length(); i++)
341 node->statements()->at(i)->accept(this);
343 node->setScope(env.scope());
345 void visitIntegerLiteral(IntegerLiteral *node) {
347 void visitExpressionStatement(ExpressionStatement *node) {
348 node->expression()->accept(this);
350 void visitCallExpression(CallExpression *node) {
351 node->callee()->accept(this);
352 for (size_t i = 0; i < node->arguments()->length(); i++)
353 node->arguments()->at(i)->accept(this);
355 void visitIfStatement(IfStatement *node) {
356 node->ifTrue()->accept(this);
358 node->ifFalse()->accept(this);
360 void visitIndexExpression(IndexExpression *node) {
361 node->left()->accept(this);
362 node->right()->accept(this);
364 void visitFloatLiteral(FloatLiteral *node) {
366 void visitWhileStatement(WhileStatement *node) {
367 node->condition()->accept(this);
368 node->body()->accept(this);
370 void visitBreakStatement(BreakStatement *node) {
372 void visitContinueStatement(ContinueStatement *node) {
374 void visitStringLiteral(StringLiteral *node) {
376 void visitIncDecExpression(IncDecExpression *node) {
377 node->expression()->accept(this);
379 void visitUnaryExpression(UnaryExpression *node) {
382 void visitTernaryExpression(TernaryExpression *node) {
385 void visitBooleanLiteral(BooleanLiteral *node) {
387 void visitFieldExpression(FieldExpression *node) {
389 void visitSwitchStatement(SwitchStatement *node) {
390 if (node->defaultCase())
391 node->defaultCase()->accept(this);
393 for (size_t i = 0; i < node->cases()->length(); i++)
394 node->cases()->at(i)->statement()->accept(this);
396 void visitArrayLiteral(ArrayLiteral *node) {
398 void visitImportStatement(ImportStatement *node) {
402 Scope *getGlobalOrCreateBlockScope() {
404 assert(env_->scope()->kind() == Scope::BLOCK ||
405 env_->scope()->kind() == Scope::GLOBAL);
406 return env_->scope();
408 return getOrCreateBlockScope();
410 Scope *getOrCreateBlockScope() {
412 assert(env_->scope()->kind() == Scope::BLOCK);
413 return env_->scope();
416 LocalScope *scope = LocalScope::New(pool_);
420 env_->setScope(scope);
424 bool registerName(Scope *scope, Symbol *sym) {
428 if (Symbol *other = scope->localLookup(sym->name())) {
429 // Report, but allow errors to continue.
430 cc_.reportError(sym->pos(), Message_RedeclaredName,
431 sym->name()->chars(),
437 return scope->addSymbol(sym);
440 bool registerArguments(const FunctionSignature &sig) {
441 if (!sig.parameters()->length())
444 ArgumentScope *argScope = ArgumentScope::New(pool_);
447 env_->setScope(argScope);
449 for (size_t i = 0; i < sig.parameters()->length(); i++) {
450 Parameter *param = sig.parameters()->at(i);
451 VariableSymbol *sym = new (pool_) VariableSymbol(argScope, param->name(), param->pos());
452 if (!registerName(env_->scope(), sym))
454 param->setSymbol(sym);
462 PoolAllocator &pool_;
464 TranslationUnit *unit_;
470 ke::PopulateNamesAndTypes(Zone *zone, CompileContext &cc, TranslationUnit *unit)
472 NamePopulator populator(zone, cc, unit);
473 return populator.analyze();
476 static const int INFER_ARRAY_SIZE = 0;
477 static const int EVAL_ARRAY_SIZE = -1;
478 static const int DYNAMIC_ARRAY_SIZE = -2;
480 class NameBinder : public AstVisitor
486 AutoLinkScope(AutoLinkScope **prevp, Scope *scope)
494 scope_->setParent(prev_->scope());
499 assert(*prevp_ == this);
503 Scope *scope() const {
508 AutoLinkScope **prevp_;
509 AutoLinkScope *prev_;
514 NameBinder(Zone *zone, CompileContext &cc, TranslationUnit *unit)
524 // Start with the import scope, and collect all imported names.
525 AutoLinkScope importScope(&link_, unit_->importScope());
527 for (size_t i = 0; i < unit_->tree()->imports()->length(); i++)
528 unit_->tree()->imports()->at(i)->accept(this);
530 // Next, enter the global scope and walk all statements.
531 AutoLinkScope globalScope(&link_, unit_->globalScope());
532 for (size_t i = 0; i < unit_->tree()->statements()->length(); i++) {
533 Statement *stmt = unit_->tree()->statements()->at(i);
540 void visitVariableDeclaration(VariableDeclaration *node) {
541 // Bind the initializer before registering the declaration, so that we
542 // can error on bogus initializers (new x = x).
543 if (node->initialization())
544 node->initialization()->accept(this);
546 Local<Type> type(zone_, bindType(node->type()));
550 if (node->dims() || type->isArray()) {
551 int dims[MAX_ARRAY_DEPTH];
552 int levels = evaluateDimensions(node->pos(), type, node->dims(), dims);
556 // Do some extra inference based on the initializer, if present.
557 Expression *init = node->initialization();
559 init->isArrayLiteral() &&
560 init->toArrayLiteral()->isFixed())
562 Local<Type> contained(zone_, type->isArray()
563 ? ArrayType::cast(type)->contained()
565 if (!inferFixedArrayDimensions(init->toArrayLiteral(), contained, dims, levels))
569 // If we got extra dimensions, we need to build a new type.
571 if ((type = buildArrayType(type, dims, node->dims()->length())) == NULL)
576 // If the node already has a symbol (meaning it was a global), then
577 // we don't have to do anything more.
579 assert(node->sym()->scope()->kind() == Scope::GLOBAL);
580 node->sym()->setType(type);
584 VariableSymbol *sym = new (pool_) VariableSymbol(link_->scope(), node->name(), node->pos(), type);
585 node->setSymbol(sym);
587 if (Symbol *other = link_->scope()->localLookup(sym->name())) {
588 // Report, but allow errors to continue.
589 cc_.reportError(sym->pos(), Message_RedeclaredName,
590 sym->name()->chars(),
596 link_->scope()->addSymbol(sym);
598 void visitEnumStatement(EnumStatement *node) {
600 void visitFunctionStatement(FunctionStatement *node) {
601 AutoLinkScope argScope(&link_, node->argScope());
602 AutoLinkScope varScope(&link_, node->varScope());
604 Local<FunctionType> type(zone_, node->sym()->type());
605 if (!fillFunctionType(type, node->signature()))
609 node->body()->accept(this);
611 void visitStructureStatement(StructureStatement *node) {
614 void visitFunctionTypeStatement(FunctionTypeStatement *node) {
618 void visitNameProxy(NameProxy *proxy) {
619 Scope *scope = link_->scope();
620 Symbol *sym = scope->lookup(proxy->name());
622 cc_.reportError(proxy->pos(), Message_IdentifierNotFound, proxy->name()->chars());
625 void visitAssignment(Assignment *node) {
626 node->lvalue()->accept(this);
627 node->expression()->accept(this);
629 void visitBinaryExpression(BinaryExpression *node) {
630 node->left()->accept(this);
631 node->right()->accept(this);
633 void visitReturnStatement(ReturnStatement *node) {
634 node->expression()->accept(this);
636 void visitForStatement(ForStatement *node) {
637 AutoLinkScope scope(&link_, node->scope());
639 if (node->initialization())
640 node->initialization()->accept(this);
641 if (node->condition())
642 node->condition()->accept(this);
644 node->update()->accept(this);
645 node->body()->accept(this);
647 void visitBlockStatement(BlockStatement *node) {
648 AutoLinkScope scope(&link_, node->scope());
649 for (size_t i = 0; i < node->statements()->length(); i++)
650 node->statements()->at(i)->accept(this);
652 void visitIntegerLiteral(IntegerLiteral *node) {
654 void visitExpressionStatement(ExpressionStatement *node) {
655 node->expression()->accept(this);
657 void visitCallExpression(CallExpression *node) {
658 node->callee()->accept(this);
659 for (size_t i = 0; i < node->arguments()->length(); i++)
660 node->arguments()->at(i)->accept(this);
662 void visitIfStatement(IfStatement *node) {
663 node->condition()->accept(this);
664 node->ifTrue()->accept(this);
666 node->ifFalse()->accept(this);
668 void visitIndexExpression(IndexExpression *node) {
669 node->left()->accept(this);
670 node->right()->accept(this);
672 void visitFloatLiteral(FloatLiteral *node) {
674 void visitWhileStatement(WhileStatement *node) {
675 node->condition()->accept(this);
676 node->body()->accept(this);
678 void visitBreakStatement(BreakStatement *node) {
680 void visitContinueStatement(ContinueStatement *node) {
682 void visitStringLiteral(StringLiteral *node) {
684 void visitIncDecExpression(IncDecExpression *node) {
685 node->expression()->accept(this);
687 void visitUnaryExpression(UnaryExpression *node) {
689 node->tag()->accept(this);
690 node->expression()->accept(this);
692 void visitTernaryExpression(TernaryExpression *node) {
693 node->condition()->accept(this);
694 node->left()->accept(this);
695 node->right()->accept(this);
697 void visitBooleanLiteral(BooleanLiteral *node) {
699 void visitFieldExpression(FieldExpression *node) {
700 node->left()->accept(this);
702 void visitSwitchStatement(SwitchStatement *node) {
703 node->expression()->accept(this);
704 node->defaultCase()->accept(this);
705 for (size_t i = 0; i < node->cases()->length(); i++) {
706 // We don't test case expressions because they are literals.
707 Case *c = node->cases()->at(i);
708 c->statement()->accept(this);
711 void visitArrayLiteral(ArrayLiteral *node) {
712 for (size_t i = 0; i < node->expressions()->length(); i++)
713 node->expressions()->at(i)->accept(this);
715 void visitImportStatement(ImportStatement *node) {
716 if (node->suffix() == TOK_STAR) {
717 // Import every name.
720 GlobalScope *other = node->source()->globalScope();
721 Symbol *sym = other->findPublic(node->name());
723 cc_.reportError(node->pos(), Message_CannotResolveImport, node->name()->chars());
726 link_->scope()->addSymbol(sym);
731 int evaluateDimensions(const SourcePosition &pos, Handle<Type> typeArg, ExpressionList *exprs, int dims[MAX_ARRAY_DEPTH]) {
733 Local<Type> type(zone_, typeArg);
734 while (type->isArray()) {
735 ArrayType *atype = ArrayType::cast(type);
736 dims[level] = atype->isFixedLength()
737 ? atype->fixedLength()
738 : DYNAMIC_ARRAY_SIZE;
739 type = atype->contained();
746 if (level + exprs->length() > MAX_ARRAY_DEPTH) {
747 cc_.reportError(pos, Message_MaximumArrayDepth);
751 bool hadEmptySize = false;
752 for (size_t i = 0; i < exprs->length(); i++) {
753 Expression *expr = exprs->at(i);
755 dims[i] = INFER_ARRAY_SIZE;
761 if (EvaluateForConstant(expr, &box) && box.type() == PrimitiveType_Int32) {
762 int size = box.toInt();
764 cc_.reportError(expr->pos(), Message_BadArraySize);
773 cc_.reportError(expr->pos(), Message_BadDynamicInitializer);
777 dims[i] = EVAL_ARRAY_SIZE;
780 return level + exprs->length();
783 // This function computes missing dimension sizes based on a literal
784 // initializer. We don't really handle any size rules here; we just
785 // do a really dumb inference.
786 bool inferFixedArrayDimensions(ArrayLiteral *lit, Handle<Type> contained, int dims[MAX_ARRAY_DEPTH], int levels) {
787 for (int i = 0; i < levels; i++) {
788 if (dims[i] == EVAL_ARRAY_SIZE || dims[i] == DYNAMIC_ARRAY_SIZE) {
789 // The following are invalid:
790 // new x[<expr>] = {...}
791 // new Type:x = {...} // where Type is a non-fixed array type
792 cc_.reportError(lit->pos(), Message_CannotInitializeEvalArray);
796 if (dims[i] == INFER_ARRAY_SIZE) {
797 // Character arrays are always dynamic when inferred from string literals.
798 if (i == levels - 1 && contained->isChar())
799 dims[i] = DYNAMIC_ARRAY_SIZE;
801 dims[i] = lit->expressions()->length();
804 if (i != levels - 1) {
805 // Fixed array literals are guaranteed to have at least one expression.
806 Expression *next = lit->expressions()->at(0);
807 if (!next->isArrayLiteral()) {
808 // Whelp... this array is just malformed. Not the best error message
810 cc_.reportError(next->pos(), Message_ArraySizeCannotBeDetermined);
813 lit = next->toArrayLiteral();
820 ArrayType *buildArrayType(Handle<Type> contained, int dims[MAX_ARRAY_DEPTH], size_t postlevels) {
821 Local<Type> type(zone_, contained);
822 for (size_t i = postlevels - 1; i < postlevels; i--) {
823 int size = dims[i] > 0
825 : ArrayType::DYNAMIC_ARRAY_SIZE;
827 type = zone_->types()->newArray(contained, size);
831 return ArrayType::cast(type);
834 bool fillFunctionType(Handle<FunctionType> fun, const FunctionSignature &sig) {
835 Local<Type> type(zone_);
836 if (!fun->returnType()) {
837 if ((type = bindType(sig.returnType())) == NULL)
839 fun->setReturnType(type);
842 Local<FixedArray> params(zone_, FixedArray::New(zone_, sig.parameters()->length(), Heap::Tenure_Old));
846 for (size_t i = 0; i < sig.parameters()->length(); i++) {
847 Parameter *param = sig.parameters()->at(i);
848 if ((type = bindType(param->type())) == NULL)
851 if (type->isArray() || param->dims()) {
852 int dims[MAX_ARRAY_DEPTH];
853 int levels = evaluateDimensions(param->pos(), type, param->dims(), dims);
857 // If we got extra dimensions, we need to build a new type.
858 // Unlike variables, we do not infer anything about array
859 // sizes from its default initializer.
861 if ((type = buildArrayType(type, dims, param->dims()->length())) == NULL)
865 if (ArrayType::cast(type)->innermost()->isVoid()) {
866 cc_.reportError(param->type()->pos(), Message_CannotDeclareVoid);
871 if (param->reference()) {
872 if (!type->isPod()) {
873 cc_.reportError(param->pos(), Message_ArrayCantBeReference);
876 if ((type = zone_->types()->getReference(type, false)) == NULL)
880 if (type->isVoid()) {
881 cc_.reportError(param->type()->pos(), Message_CannotDeclareVoid);
885 params->set(zone_, i, type);
886 param->sym()->setType(type);
889 fun->setParameterTypes(params);
894 Type *bindType(Expression *expr) {
896 // If no type was declared, we return int32.
897 return zone_->types()->getPrimitive(PrimitiveType_Int32);
902 NameProxy *proxy = expr->asNameProxy();
905 Symbol *sym = proxy->sym();
909 if (!sym->isType()) {
910 cc_.reportError(expr->pos(), Message_IdentifierIsNotAType, sym->name()->chars());
919 PoolAllocator &pool_;
921 TranslationUnit *unit_;
922 AutoLinkScope *link_;
926 ke::BindNamesAndTypes(Zone *zone, CompileContext &cc, TranslationUnit *unit)
928 NameBinder binder(zone, cc, unit);
929 return binder.bind();