Implement |const| keyword.
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(), node->quals()));
550 // We don't allow array typedefs yet.
551 assert(!type->isArray());
554 int dims[MAX_ARRAY_DEPTH];
555 int levels = evaluateDimensions(node->pos(), type, node->dims(), dims);
559 // Do some extra inference based on the initializer, if present.
560 Expression *init = node->initialization();
562 init->isArrayLiteral() &&
563 init->toArrayLiteral()->isFixed())
565 Local<Type> contained(zone_, type->isArray()
566 ? ArrayType::cast(type)->contained()
568 if (!inferFixedArrayDimensions(init->toArrayLiteral(), contained, dims, levels))
572 // If we got extra dimensions, we need to build a new type.
574 if ((type = buildArrayType(type, node->quals(), dims, node->dims()->length())) == NULL)
579 // If we're in global scope, and we received a |const| qualifier, then
580 // we extend this to array reference as well. This is to sort of mimic
581 // SP1 functionality, but also means that you cannot have changeable
582 // const pointers in global scope.
583 if ((node->quals() & TypeQual_Const) &&
585 link_->scope()->kind() == Scope::GLOBAL)
587 if ((type = zone_->types()->qualify(type, TypeQual_Const)) == NULL)
589 if ((type = zone_->types()->qualify(type, TypeQual_Const)) == NULL)
593 // If the node already has a symbol (meaning it was a global), then
594 // we don't have to do anything more.
596 assert(node->sym()->scope()->kind() == Scope::GLOBAL);
597 node->sym()->setType(type);
601 VariableSymbol *sym = new (pool_) VariableSymbol(link_->scope(), node->name(), node->pos(), type);
602 node->setSymbol(sym);
604 if (Symbol *other = link_->scope()->localLookup(sym->name())) {
605 // Report, but allow errors to continue.
606 cc_.reportError(sym->pos(), Message_RedeclaredName,
607 sym->name()->chars(),
613 link_->scope()->addSymbol(sym);
615 void visitEnumStatement(EnumStatement *node) {
617 void visitFunctionStatement(FunctionStatement *node) {
618 AutoLinkScope argScope(&link_, node->argScope());
619 AutoLinkScope varScope(&link_, node->varScope());
621 Local<FunctionType> type(zone_, node->sym()->type());
622 if (!fillFunctionType(type, node->signature()))
626 node->body()->accept(this);
628 void visitStructureStatement(StructureStatement *node) {
631 void visitFunctionTypeStatement(FunctionTypeStatement *node) {
635 void visitNameProxy(NameProxy *proxy) {
636 Scope *scope = link_->scope();
637 Symbol *sym = scope->lookup(proxy->name());
639 cc_.reportError(proxy->pos(), Message_IdentifierNotFound, proxy->name()->chars());
642 void visitAssignment(Assignment *node) {
643 node->lvalue()->accept(this);
644 node->expression()->accept(this);
646 void visitBinaryExpression(BinaryExpression *node) {
647 node->left()->accept(this);
648 node->right()->accept(this);
650 void visitReturnStatement(ReturnStatement *node) {
651 node->expression()->accept(this);
653 void visitForStatement(ForStatement *node) {
654 AutoLinkScope scope(&link_, node->scope());
656 if (node->initialization())
657 node->initialization()->accept(this);
658 if (node->condition())
659 node->condition()->accept(this);
661 node->update()->accept(this);
662 node->body()->accept(this);
664 void visitBlockStatement(BlockStatement *node) {
665 AutoLinkScope scope(&link_, node->scope());
666 for (size_t i = 0; i < node->statements()->length(); i++)
667 node->statements()->at(i)->accept(this);
669 void visitIntegerLiteral(IntegerLiteral *node) {
671 void visitExpressionStatement(ExpressionStatement *node) {
672 node->expression()->accept(this);
674 void visitCallExpression(CallExpression *node) {
675 node->callee()->accept(this);
676 for (size_t i = 0; i < node->arguments()->length(); i++)
677 node->arguments()->at(i)->accept(this);
679 void visitIfStatement(IfStatement *node) {
680 node->condition()->accept(this);
681 node->ifTrue()->accept(this);
683 node->ifFalse()->accept(this);
685 void visitIndexExpression(IndexExpression *node) {
686 node->left()->accept(this);
687 node->right()->accept(this);
689 void visitFloatLiteral(FloatLiteral *node) {
691 void visitWhileStatement(WhileStatement *node) {
692 node->condition()->accept(this);
693 node->body()->accept(this);
695 void visitBreakStatement(BreakStatement *node) {
697 void visitContinueStatement(ContinueStatement *node) {
699 void visitStringLiteral(StringLiteral *node) {
701 void visitIncDecExpression(IncDecExpression *node) {
702 node->expression()->accept(this);
704 void visitUnaryExpression(UnaryExpression *node) {
706 node->tag()->accept(this);
707 node->expression()->accept(this);
709 void visitTernaryExpression(TernaryExpression *node) {
710 node->condition()->accept(this);
711 node->left()->accept(this);
712 node->right()->accept(this);
714 void visitBooleanLiteral(BooleanLiteral *node) {
716 void visitFieldExpression(FieldExpression *node) {
717 node->left()->accept(this);
719 void visitSwitchStatement(SwitchStatement *node) {
720 node->expression()->accept(this);
721 node->defaultCase()->accept(this);
722 for (size_t i = 0; i < node->cases()->length(); i++) {
723 // We don't test case expressions because they are literals.
724 Case *c = node->cases()->at(i);
725 c->statement()->accept(this);
728 void visitArrayLiteral(ArrayLiteral *node) {
729 for (size_t i = 0; i < node->expressions()->length(); i++)
730 node->expressions()->at(i)->accept(this);
732 void visitImportStatement(ImportStatement *node) {
733 if (node->suffix() == TOK_STAR) {
734 // Import every name.
737 GlobalScope *other = node->source()->globalScope();
738 Symbol *sym = other->findPublic(node->name());
740 cc_.reportError(node->pos(), Message_CannotResolveImport, node->name()->chars());
743 link_->scope()->addSymbol(sym);
748 int evaluateDimensions(const SourcePosition &pos, Handle<Type> typeArg, ExpressionList *exprs, int dims[MAX_ARRAY_DEPTH]) {
750 Local<Type> type(zone_, typeArg);
751 while (type->isArray()) {
752 ArrayType *atype = ArrayType::cast(type);
753 dims[level] = atype->isFixedLength()
754 ? atype->fixedLength()
755 : DYNAMIC_ARRAY_SIZE;
756 type = atype->contained();
763 if (level + exprs->length() > MAX_ARRAY_DEPTH) {
764 cc_.reportError(pos, Message_MaximumArrayDepth);
768 bool hadEmptySize = false;
769 for (size_t i = 0; i < exprs->length(); i++) {
770 Expression *expr = exprs->at(i);
772 dims[i] = INFER_ARRAY_SIZE;
778 if (EvaluateForConstant(expr, &box) && box.type() == PrimitiveType_Int32) {
779 int size = box.toInt();
781 cc_.reportError(expr->pos(), Message_BadArraySize);
790 cc_.reportError(expr->pos(), Message_BadDynamicInitializer);
794 dims[i] = EVAL_ARRAY_SIZE;
797 return level + exprs->length();
800 // This function computes missing dimension sizes based on a literal
801 // initializer. We don't really handle any size rules here; we just
802 // do a really dumb inference.
803 bool inferFixedArrayDimensions(ArrayLiteral *lit, Handle<Type> contained, int dims[MAX_ARRAY_DEPTH], int levels) {
804 for (int i = 0; i < levels; i++) {
805 if (dims[i] == EVAL_ARRAY_SIZE || dims[i] == DYNAMIC_ARRAY_SIZE) {
806 // The following are invalid:
807 // new x[<expr>] = {...}
808 // new Type:x = {...} // where Type is a non-fixed array type
809 cc_.reportError(lit->pos(), Message_CannotInitializeEvalArray);
813 if (dims[i] == INFER_ARRAY_SIZE) {
814 // Character arrays are always dynamic when inferred from string literals.
815 if (i == levels - 1 && contained->isChar())
816 dims[i] = DYNAMIC_ARRAY_SIZE;
818 dims[i] = lit->expressions()->length();
821 if (i != levels - 1) {
822 // Fixed array literals are guaranteed to have at least one expression.
823 Expression *next = lit->expressions()->at(0);
824 if (!next->isArrayLiteral()) {
825 // Whelp... this array is just malformed. Not the best error message
827 cc_.reportError(next->pos(), Message_ArraySizeCannotBeDetermined);
830 lit = next->toArrayLiteral();
837 ArrayType *buildArrayType(Handle<Type> contained, TypeQualifiers quals, int dims[MAX_ARRAY_DEPTH], size_t postlevels) {
838 Local<Type> type(zone_, contained);
840 for (size_t i = postlevels - 1; i < postlevels; i--) {
841 int size = dims[i] > 0
843 : ArrayType::DYNAMIC_ARRAY_SIZE;
845 if ((type = zone_->types()->newArray(contained, size)) == NULL)
847 if ((type = zone_->types()->qualify(type, quals)) == NULL)
850 return ArrayType::cast(type);
853 bool fillFunctionType(Handle<FunctionType> fun, const FunctionSignature &sig) {
854 Local<Type> type(zone_);
855 if (!fun->returnType()) {
856 if ((type = bindType(sig.returnType(), TypeQual_None)) == NULL)
858 fun->setReturnType(type);
861 Local<FixedArray> params(zone_, FixedArray::New(zone_, sig.parameters()->length(), Heap::Tenure_Old));
865 for (size_t i = 0; i < sig.parameters()->length(); i++) {
866 Parameter *param = sig.parameters()->at(i);
867 if ((type = bindType(param->type(), param->quals())) == NULL)
870 assert(!type->isArray());
873 int dims[MAX_ARRAY_DEPTH];
874 int levels = evaluateDimensions(param->pos(), type, param->dims(), dims);
878 // If we got extra dimensions, we need to build a new type.
879 // Unlike variables, we do not infer anything about array
880 // sizes from its default initializer.
882 if ((type = buildArrayType(type, param->quals(), dims, param->dims()->length())) == NULL)
886 if (ArrayType::cast(type)->innermost()->isVoid()) {
887 cc_.reportError(param->type()->pos(), Message_CannotDeclareVoid);
892 if (param->reference()) {
893 if (!type->isPod()) {
894 cc_.reportError(param->pos(), Message_ArrayCantBeReference);
897 if (param->quals() & TypeQual_Const) {
898 cc_.reportError(param->pos(), Message_CannotConstReference);
901 if ((type = zone_->types()->getReference(type, false)) == NULL)
904 if (param->quals() & TypeQual_Const) {
905 if (!type->isArray() && !type->isStruct()) {
906 cc_.reportError(param->pos(), Message_InvalidConstOnFormal);
911 if (type->isVoid()) {
912 cc_.reportError(param->type()->pos(), Message_CannotDeclareVoid);
916 params->set(zone_, i, type);
917 param->sym()->setType(type);
920 fun->setParameterTypes(params);
925 Type *bindType(Expression *expr, TypeQualifiers quals) {
926 Local<Type> type(zone_);
929 // If no type was declared, we return int32.
930 type = zone_->types()->getPrimitive(PrimitiveType_Int32);
934 NameProxy *proxy = expr->asNameProxy();
937 Symbol *sym = proxy->sym();
941 if (!sym->isType()) {
942 cc_.reportError(expr->pos(), Message_IdentifierIsNotAType, sym->name()->chars());
949 return zone_->types()->qualify(type, quals);
954 PoolAllocator &pool_;
956 TranslationUnit *unit_;
957 AutoLinkScope *link_;
961 ke::BindNamesAndTypes(Zone *zone, CompileContext &cc, TranslationUnit *unit)
963 NameBinder binder(zone, cc, unit);
964 return binder.bind();