Added array support back.
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) {
203 void visitFunctionStatement(FunctionStatement *node) {
204 // We create function types ahead of time, not for any particular
205 // reason. It makes things consistent with FunctionTypeStatement,
206 // which actually does produce a type.
207 Local<FunctionType> type(zone_, FunctionType::New(zone_, node->token()));
211 assert(env_->scope());
213 // Function statements are always named, so add the name to the outer scope.
214 FunctionSymbol *sym = new (pool_) FunctionSymbol(env_->scope(), node->name(), node->pos(), type);
215 if (!registerName(env_->scope(), sym))
218 if (node->token() == TOK_PUBLIC ||
219 node->token() == TOK_FORWARD ||
220 node->token() == TOK_NATIVE)
222 // We're in the global scope, for sure.
223 assert(env_->scope()->kind() == Scope::GLOBAL);
224 GlobalScope *globals = (GlobalScope *)env_->scope();
225 if (!globals->addPublic(sym))
229 node->setSymbol(sym);
231 // Scope for the function's arguments.
232 SymbolEnv argEnv(&env_);
233 if (!registerArguments(node->signature()))
236 // Scope for function body.
237 SymbolEnv localEnv(&env_);
238 FunctionScope fun(&fun_);
240 node->body()->accept(this);
242 // Function statements have quirky semantics around their return
243 // type. For reasonable compatibility with SP1, we use the following
244 // heuristics for when no explicit type is declared.
245 if (!node->signature().returnType()) {
246 Local<Type> type(zone_);
247 if (node->token() == TOK_FORWARD || node->token() == TOK_NATIVE) {
248 // If the function type is a native or forward, we always
249 // assume it returns an int32.
250 type = zone_->types()->getPrimitive(PrimitiveType_Int32);
251 } else if (fun.returns() != ValueReturn) {
252 // This function never returns a value, so mark it as
254 type = zone_->types()->getVoid();
256 // No need to NULL check here, we'll catch OOM later.
257 node->sym()->type()->setReturnType(type);
260 node->setScopes(argEnv.scope(), localEnv.scope());
262 void visitStructureStatement(StructureStatement *node) {
265 void visiFunctionTypeStatementt(FunctionTypeStatement *node) {
269 void visitNameProxy(NameProxy *name) {
271 void visitAssignment(Assignment *node) {
272 node->lvalue()->accept(this);
273 node->expression()->accept(this);
275 void visitBinaryExpression(BinaryExpression *node) {
276 node->left()->accept(this);
277 node->right()->accept(this);
279 void visitReturnStatement(ReturnStatement *node) {
280 if (node->expression())
281 fun_->returns(ValueReturn);
283 fun_->returns(VoidReturn);
285 void visitForStatement(ForStatement *node) {
286 SymbolEnv env(&env_);
288 if (node->initialization())
289 node->initialization()->accept(this);
290 if (node->condition())
291 node->condition()->accept(this);
293 node->update()->accept(this);
294 node->body()->accept(this);
296 node->setScope(env.scope());
298 void visitBlockStatement(BlockStatement *node) {
299 SymbolEnv env(&env_);
301 for (size_t i = 0; i < node->statements()->length(); i++)
302 node->statements()->at(i)->accept(this);
304 node->setScope(env.scope());
306 void visitIntegerLiteral(IntegerLiteral *node) {
308 void visitExpressionStatement(ExpressionStatement *node) {
309 node->expression()->accept(this);
311 void visitCallExpression(CallExpression *node) {
312 node->callee()->accept(this);
313 for (size_t i = 0; i < node->arguments()->length(); i++)
314 node->arguments()->at(i)->accept(this);
316 void visitIfStatement(IfStatement *node) {
317 node->ifTrue()->accept(this);
319 node->ifFalse()->accept(this);
321 void visitIndexExpression(IndexExpression *node) {
322 node->left()->accept(this);
323 node->right()->accept(this);
325 void visitFloatLiteral(FloatLiteral *node) {
327 void visitWhileStatement(WhileStatement *node) {
328 node->condition()->accept(this);
329 node->body()->accept(this);
331 void visitBreakStatement(BreakStatement *node) {
333 void visitContinueStatement(ContinueStatement *node) {
335 void visitStringLiteral(StringLiteral *node) {
337 void visitIncDecExpression(IncDecExpression *node) {
340 void visitUnaryExpression(UnaryExpression *node) {
343 void visitTernaryExpression(TernaryExpression *node) {
346 void visitBooleanLiteral(BooleanLiteral *node) {
348 void visitFieldExpression(FieldExpression *node) {
350 void visitSwitchStatement(SwitchStatement *node) {
351 if (node->defaultCase())
352 node->defaultCase()->accept(this);
354 for (size_t i = 0; i < node->cases()->length(); i++)
355 node->cases()->at(i)->statement()->accept(this);
357 void visitArrayLiteral(ArrayLiteral *node) {
359 void visitImportStatement(ImportStatement *node) {
363 Scope *getOrCreateBlockScope() {
365 assert(env_->scope()->kind() == Scope::BLOCK);
366 return env_->scope();
369 LocalScope *scope = LocalScope::New(pool_);
373 env_->setScope(scope);
377 bool registerName(Scope *scope, Symbol *sym) {
381 if (Symbol *other = scope->localLookup(sym->name())) {
382 // Report, but allow errors to continue.
383 cc_.reportError(sym->pos(), Message_RedeclaredName,
384 sym->name()->chars(),
390 return scope->addSymbol(sym);
393 bool registerArguments(const FunctionSignature &sig) {
394 if (!sig.parameters()->length())
397 ArgumentScope *argScope = ArgumentScope::New(pool_);
400 env_->setScope(argScope);
402 for (size_t i = 0; i < sig.parameters()->length(); i++) {
403 Parameter *param = sig.parameters()->at(i);
404 VariableSymbol *sym = new (pool_) VariableSymbol(argScope, param->name(), param->pos());
405 if (!registerName(env_->scope(), sym))
407 param->setSymbol(sym);
415 PoolAllocator &pool_;
417 TranslationUnit *unit_;
423 ke::PopulateNamesAndTypes(Zone *zone, CompileContext &cc, TranslationUnit *unit)
425 NamePopulator populator(zone, cc, unit);
426 return populator.analyze();
429 static const int INFER_ARRAY_SIZE = 0;
430 static const int EVAL_ARRAY_SIZE = -1;
431 static const int DYNAMIC_ARRAY_SIZE = -2;
433 class NameBinder : public AstVisitor
439 AutoLinkScope(AutoLinkScope **prevp, Scope *scope)
447 scope_->setParent(prev_->scope());
452 assert(*prevp_ == this);
456 Scope *scope() const {
461 AutoLinkScope **prevp_;
462 AutoLinkScope *prev_;
467 NameBinder(Zone *zone, CompileContext &cc, TranslationUnit *unit)
477 // Start with the import scope, and collect all imported names.
478 AutoLinkScope importScope(&link_, unit_->importScope());
480 for (size_t i = 0; i < unit_->tree()->imports()->length(); i++)
481 unit_->tree()->imports()->at(i)->accept(this);
483 // Next, enter the global scope and walk all statements.
484 AutoLinkScope globalScope(&link_, unit_->globalScope());
485 for (size_t i = 0; i < unit_->tree()->statements()->length(); i++) {
486 Statement *stmt = unit_->tree()->statements()->at(i);
493 void visitVariableDeclaration(VariableDeclaration *node) {
494 // Bind the initializer before registering the declaration, so that we
495 // can error on bogus initializers (new x = x).
496 if (node->initialization())
497 node->initialization()->accept(this);
499 Local<Type> type(zone_, bindType(node->type()));
503 if (node->dims() || type->isArray()) {
504 int dims[MAX_ARRAY_DEPTH];
505 int levels = evaluateDimensions(node->pos(), type, node->dims(), dims);
509 // Do some extra inference based on the initializer, if present.
510 Expression *init = node->initialization();
512 init->isArrayLiteral() &&
513 init->toArrayLiteral()->isFixed())
515 Local<Type> contained(zone_, type->isArray()
516 ? ArrayType::cast(type)->contained()
518 if (!inferFixedArrayDimensions(init->toArrayLiteral(), contained, dims, levels))
522 // If we got extra dimensions, we need to build a new type.
524 if ((type = buildArrayType(type, dims, node->dims()->length())) == NULL)
529 // If the node already has a symbol (meaning it was a global), then
530 // we don't have to do anything more.
532 assert(node->sym()->scope()->kind() == Scope::GLOBAL);
533 node->sym()->setType(type);
537 VariableSymbol *sym = new (pool_) VariableSymbol(link_->scope(), node->name(), node->pos(), type);
538 node->setSymbol(sym);
540 if (Symbol *other = link_->scope()->localLookup(sym->name())) {
541 // Report, but allow errors to continue.
542 cc_.reportError(sym->pos(), Message_RedeclaredName,
543 sym->name()->chars(),
549 if (link_->scope()->addSymbol(sym))
552 void visitEnumStatement(EnumStatement *node) {
555 void visitFunctionStatement(FunctionStatement *node) {
556 AutoLinkScope argScope(&link_, node->argScope());
557 AutoLinkScope varScope(&link_, node->varScope());
559 Local<FunctionType> type(zone_, node->sym()->type());
560 if (!fillFunctionType(type, node->signature()))
564 node->body()->accept(this);
566 void visitStructureStatement(StructureStatement *node) {
569 void visitFunctionTypeStatement(FunctionTypeStatement *node) {
573 void visitNameProxy(NameProxy *proxy) {
574 Scope *scope = link_->scope();
575 Symbol *sym = scope->lookup(proxy->name());
577 cc_.reportError(proxy->pos(), Message_IdentifierNotFound, proxy->name()->chars());
580 void visitAssignment(Assignment *node) {
581 node->lvalue()->accept(this);
582 node->expression()->accept(this);
584 void visitBinaryExpression(BinaryExpression *node) {
585 node->left()->accept(this);
586 node->right()->accept(this);
588 void visitReturnStatement(ReturnStatement *node) {
589 node->expression()->accept(this);
591 void visitForStatement(ForStatement *node) {
592 AutoLinkScope scope(&link_, node->scope());
594 if (node->initialization())
595 node->initialization()->accept(this);
596 if (node->condition())
597 node->condition()->accept(this);
599 node->update()->accept(this);
600 node->body()->accept(this);
602 void visitBlockStatement(BlockStatement *node) {
603 AutoLinkScope scope(&link_, node->scope());
604 for (size_t i = 0; i < node->statements()->length(); i++)
605 node->statements()->at(i)->accept(this);
607 void visitIntegerLiteral(IntegerLiteral *node) {
609 void visitExpressionStatement(ExpressionStatement *node) {
610 node->expression()->accept(this);
612 void visitCallExpression(CallExpression *node) {
613 node->callee()->accept(this);
614 for (size_t i = 0; i < node->arguments()->length(); i++)
615 node->arguments()->at(i)->accept(this);
617 void visitIfStatement(IfStatement *node) {
618 node->condition()->accept(this);
619 node->ifTrue()->accept(this);
621 node->ifFalse()->accept(this);
623 void visitIndexExpression(IndexExpression *node) {
624 node->left()->accept(this);
625 node->right()->accept(this);
627 void visitFloatLiteral(FloatLiteral *node) {
629 void visitWhileStatement(WhileStatement *node) {
630 node->condition()->accept(this);
631 node->body()->accept(this);
633 void visitBreakStatement(BreakStatement *node) {
635 void visitContinueStatement(ContinueStatement *node) {
637 void visitStringLiteral(StringLiteral *node) {
639 void visitIncDecExpression(IncDecExpression *node) {
640 node->expression()->accept(this);
642 void visitUnaryExpression(UnaryExpression *node) {
644 node->tag()->accept(this);
645 node->expression()->accept(this);
647 void visitTernaryExpression(TernaryExpression *node) {
648 node->condition()->accept(this);
649 node->left()->accept(this);
650 node->right()->accept(this);
652 void visitBooleanLiteral(BooleanLiteral *node) {
654 void visitFieldExpression(FieldExpression *node) {
655 node->left()->accept(this);
657 void visitSwitchStatement(SwitchStatement *node) {
658 node->expression()->accept(this);
659 node->defaultCase()->accept(this);
660 for (size_t i = 0; i < node->cases()->length(); i++) {
661 // We don't test case expressions because they are literals.
662 Case *c = node->cases()->at(i);
663 c->statement()->accept(this);
666 void visitArrayLiteral(ArrayLiteral *node) {
667 for (size_t i = 0; i < node->expressions()->length(); i++)
668 node->expressions()->at(i)->accept(this);
670 void visitImportStatement(ImportStatement *node) {
671 if (node->suffix() == TOK_STAR) {
672 // Import every name.
675 GlobalScope *other = node->source()->globalScope();
676 Symbol *sym = other->findPublic(node->name());
678 cc_.reportError(node->pos(), Message_CannotResolveImport, node->name()->chars());
681 link_->scope()->addSymbol(sym);
686 int evaluateDimensions(const SourcePosition &pos, Handle<Type> typeArg, ExpressionList *exprs, int dims[MAX_ARRAY_DEPTH]) {
688 Local<Type> type(zone_, typeArg);
689 while (type->isArray()) {
690 ArrayType *atype = ArrayType::cast(type);
691 dims[level] = atype->isFixedLength()
692 ? atype->fixedLength()
693 : DYNAMIC_ARRAY_SIZE;
694 type = atype->contained();
701 if (level + exprs->length() > MAX_ARRAY_DEPTH) {
702 cc_.reportError(pos, Message_MaximumArrayDepth);
706 bool hadEmptySize = false;
707 for (size_t i = 0; i < exprs->length(); i++) {
708 Expression *expr = exprs->at(i);
710 dims[i] = INFER_ARRAY_SIZE;
716 if (EvaluateForConstant(expr, &box) && box.type() == PrimitiveType_Int32) {
717 int size = box.toInt();
719 cc_.reportError(expr->pos(), Message_BadArraySize);
728 cc_.reportError(expr->pos(), Message_BadDynamicInitializer);
732 dims[i] = EVAL_ARRAY_SIZE;
735 return level + exprs->length();
738 // This function computes missing dimension sizes based on a literal
739 // initializer. We don't really handle any size rules here; we just
740 // do a really dumb inference.
741 bool inferFixedArrayDimensions(ArrayLiteral *lit, Handle<Type> contained, int dims[MAX_ARRAY_DEPTH], int levels) {
742 for (int i = 0; i < levels; i++) {
743 if (dims[i] == EVAL_ARRAY_SIZE || dims[i] == DYNAMIC_ARRAY_SIZE) {
744 // The following are invalid:
745 // new x[<expr>] = {...}
746 // new Type:x = {...} // where Type is a non-fixed array type
747 cc_.reportError(lit->pos(), Message_CannotInitializeEvalArray);
751 if (dims[i] == INFER_ARRAY_SIZE) {
752 // Character arrays are always dynamic when inferred from string literals.
753 if (i == levels - 1 && contained->isChar())
754 dims[i] = DYNAMIC_ARRAY_SIZE;
756 dims[i] = lit->expressions()->length();
759 if (i != levels - 1) {
760 // Fixed array literals are guaranteed to have at least one expression.
761 Expression *next = lit->expressions()->at(0);
762 if (!next->isArrayLiteral()) {
763 // Whelp... this array is just malformed. Not the best error message
765 cc_.reportError(next->pos(), Message_ArraySizeCannotBeDetermined);
768 lit = next->toArrayLiteral();
775 ArrayType *buildArrayType(Handle<Type> contained, int dims[MAX_ARRAY_DEPTH], size_t postlevels) {
776 Local<Type> type(zone_, contained);
777 for (size_t i = postlevels - 1; i < postlevels; i--) {
778 int size = dims[i] > 0
780 : ArrayType::DYNAMIC_ARRAY_SIZE;
782 type = zone_->types()->newArray(contained, size);
786 return ArrayType::cast(type);
789 bool fillFunctionType(Handle<FunctionType> fun, const FunctionSignature &sig) {
790 Local<Type> type(zone_);
791 if (!fun->returnType()) {
792 if ((type = bindType(sig.returnType())) == NULL)
794 fun->setReturnType(type);
797 Local<FixedArray> params(zone_, FixedArray::New(zone_, sig.parameters()->length(), Heap::Tenure_Old));
801 for (size_t i = 0; i < sig.parameters()->length(); i++) {
802 Parameter *param = sig.parameters()->at(i);
803 if ((type = bindType(param->type())) == NULL)
805 params->set(zone_, i, type);
808 fun->setParameterTypes(params);
813 Type *bindType(Expression *expr) {
815 // If no type was declared, we return int32.
816 return zone_->types()->getPrimitive(PrimitiveType_Int32);
821 NameProxy *proxy = expr->asNameProxy();
824 Symbol *sym = proxy->sym();
828 if (!sym->isType()) {
829 cc_.reportError(expr->pos(), Message_IdentifierIsNotAType, sym->name()->chars());
838 PoolAllocator &pool_;
840 TranslationUnit *unit_;
841 AutoLinkScope *link_;
845 ke::BindNamesAndTypes(Zone *zone, CompileContext &cc, TranslationUnit *unit)
847 NameBinder binder(zone, cc, unit);
848 return binder.bind();