1.1 --- a/src/compiler/NameBinding.cpp Sat Nov 17 23:13:39 2012 -0800
1.2 +++ b/src/compiler/NameBinding.cpp Sun Nov 18 14:53:23 2012 -0800
1.3 @@ -194,7 +194,8 @@
1.4 // And we don't necessarily want this to bind.
1.5 }
1.6
1.7 - node->initialization()->accept(this);
1.8 + if (node->initialization())
1.9 + node->initialization()->accept(this);
1.10 }
1.11 void visitEnumStatement(EnumStatement *node) {
1.12 assert(false);
1.13 @@ -318,7 +319,8 @@
1.14 node->ifFalse()->accept(this);
1.15 }
1.16 void visitIndexExpression(IndexExpression *node) {
1.17 - assert(false);
1.18 + node->left()->accept(this);
1.19 + node->right()->accept(this);
1.20 }
1.21 void visitFloatLiteral(FloatLiteral *node) {
1.22 }
1.23 @@ -424,6 +426,10 @@
1.24 return populator.analyze();
1.25 }
1.26
1.27 +static const int INFER_ARRAY_SIZE = 0;
1.28 +static const int EVAL_ARRAY_SIZE = -1;
1.29 +static const int DYNAMIC_ARRAY_SIZE = -2;
1.30 +
1.31 class NameBinder : public AstVisitor
1.32 {
1.33 public:
1.34 @@ -487,14 +493,37 @@
1.35 void visitVariableDeclaration(VariableDeclaration *node) {
1.36 // Bind the initializer before registering the declaration, so that we
1.37 // can error on bogus initializers (new x = x).
1.38 - node->initialization()->accept(this);
1.39 + if (node->initialization())
1.40 + node->initialization()->accept(this);
1.41
1.42 Local<Type> type(zone_, bindType(node->type()));
1.43 if (!type)
1.44 return;
1.45
1.46 - if (node->dims()) {
1.47 -
1.48 + if (node->dims() || type->isArray()) {
1.49 + int dims[MAX_ARRAY_DEPTH];
1.50 + int levels = evaluateDimensions(node->pos(), type, node->dims(), dims);
1.51 + if (levels < 0)
1.52 + return;
1.53 +
1.54 + // Do some extra inference based on the initializer, if present.
1.55 + Expression *init = node->initialization();
1.56 + if (init &&
1.57 + init->isArrayLiteral() &&
1.58 + init->toArrayLiteral()->isFixed())
1.59 + {
1.60 + Local<Type> contained(zone_, type->isArray()
1.61 + ? ArrayType::cast(type)->contained()
1.62 + : type);
1.63 + if (!inferFixedArrayDimensions(init->toArrayLiteral(), contained, dims, levels))
1.64 + return;
1.65 + }
1.66 +
1.67 + // If we got extra dimensions, we need to build a new type.
1.68 + if (node->dims()) {
1.69 + if ((type = buildArrayType(type, dims, node->dims()->length())) == NULL)
1.70 + return;
1.71 + }
1.72 }
1.73
1.74 // If the node already has a symbol (meaning it was a global), then
1.75 @@ -654,6 +683,109 @@
1.76 }
1.77
1.78 private:
1.79 + int evaluateDimensions(const SourcePosition &pos, Handle<Type> typeArg, ExpressionList *exprs, int dims[MAX_ARRAY_DEPTH]) {
1.80 + unsigned level = 0;
1.81 + Local<Type> type(zone_, typeArg);
1.82 + while (type->isArray()) {
1.83 + ArrayType *atype = ArrayType::cast(type);
1.84 + dims[level] = atype->isFixedLength()
1.85 + ? atype->fixedLength()
1.86 + : DYNAMIC_ARRAY_SIZE;
1.87 + type = atype->contained();
1.88 + level++;
1.89 + }
1.90 +
1.91 + if (!exprs)
1.92 + return level;
1.93 +
1.94 + if (level + exprs->length() > MAX_ARRAY_DEPTH) {
1.95 + cc_.reportError(pos, Message_MaximumArrayDepth);
1.96 + return -1;
1.97 + }
1.98 +
1.99 + bool hadEmptySize = false;
1.100 + for (size_t i = 0; i < exprs->length(); i++) {
1.101 + Expression *expr = exprs->at(i);
1.102 + if (!expr) {
1.103 + dims[i] = INFER_ARRAY_SIZE;
1.104 + hadEmptySize = true;
1.105 + continue;
1.106 + }
1.107 +
1.108 + BoxedPrimitive box;
1.109 + if (EvaluateForConstant(expr, &box) && box.type() == PrimitiveType_Int32) {
1.110 + int size = box.toInt();
1.111 + if (size <= 0) {
1.112 + cc_.reportError(expr->pos(), Message_BadArraySize);
1.113 + return false;
1.114 + }
1.115 +
1.116 + dims[i] = size;
1.117 + continue;
1.118 + }
1.119 +
1.120 + if (hadEmptySize) {
1.121 + cc_.reportError(expr->pos(), Message_BadDynamicInitializer);
1.122 + return false;
1.123 + }
1.124 +
1.125 + dims[i] = EVAL_ARRAY_SIZE;
1.126 + }
1.127 +
1.128 + return level + exprs->length();
1.129 + }
1.130 +
1.131 + // This function computes missing dimension sizes based on a literal
1.132 + // initializer. We don't really handle any size rules here; we just
1.133 + // do a really dumb inference.
1.134 + bool inferFixedArrayDimensions(ArrayLiteral *lit, Handle<Type> contained, int dims[MAX_ARRAY_DEPTH], int levels) {
1.135 + for (int i = 0; i < levels; i++) {
1.136 + if (dims[i] == EVAL_ARRAY_SIZE || dims[i] == DYNAMIC_ARRAY_SIZE) {
1.137 + // The following are invalid:
1.138 + // new x[<expr>] = {...}
1.139 + // new Type:x = {...} // where Type is a non-fixed array type
1.140 + cc_.reportError(lit->pos(), Message_CannotInitializeEvalArray);
1.141 + return false;
1.142 + }
1.143 +
1.144 + if (dims[i] == INFER_ARRAY_SIZE) {
1.145 + // Character arrays are always dynamic when inferred from string literals.
1.146 + if (i == levels - 1 && contained->isChar())
1.147 + dims[i] = DYNAMIC_ARRAY_SIZE;
1.148 + else
1.149 + dims[i] = lit->expressions()->length();
1.150 + }
1.151 +
1.152 + if (i != levels - 1) {
1.153 + // Fixed array literals are guaranteed to have at least one expression.
1.154 + Expression *next = lit->expressions()->at(0);
1.155 + if (!next->isArrayLiteral()) {
1.156 + // Whelp... this array is just malformed. Not the best error message
1.157 + // but whatever.
1.158 + cc_.reportError(next->pos(), Message_ArraySizeCannotBeDetermined);
1.159 + return false;
1.160 + }
1.161 + lit = next->toArrayLiteral();
1.162 + }
1.163 + }
1.164 +
1.165 + return true;
1.166 + }
1.167 +
1.168 + ArrayType *buildArrayType(Handle<Type> contained, int dims[MAX_ARRAY_DEPTH], size_t postlevels) {
1.169 + Local<Type> type(zone_, contained);
1.170 + for (size_t i = postlevels - 1; i < postlevels; i--) {
1.171 + int size = dims[i] > 0
1.172 + ? dims[i]
1.173 + : ArrayType::DYNAMIC_ARRAY_SIZE;
1.174 +
1.175 + type = zone_->types()->newArray(contained, size);
1.176 + if (!type)
1.177 + return NULL;
1.178 + }
1.179 + return ArrayType::cast(type);
1.180 + }
1.181 +
1.182 bool fillFunctionType(Handle<FunctionType> fun, const FunctionSignature &sig) {
1.183 Local<Type> type(zone_);
1.184 if (!fun->returnType()) {