1.1 --- a/src/compiler/SemanticAnalysis.cpp Mon Dec 24 02:56:02 2012 -0800
1.2 +++ b/src/compiler/SemanticAnalysis.cpp Mon Dec 24 16:09:13 2012 -0800
1.3 @@ -436,7 +436,7 @@
1.4
1.5 if ((hir = eval(node->initialization())) == NULL)
1.6 return;
1.7 - if ((hir = coerce(hir, type, Coerce_Assign)) == NULL)
1.8 + if ((hir = coerce(hir, type, Coerce_Decl)) == NULL)
1.9 return;
1.10
1.11 discharge(hir);
1.12 @@ -455,8 +455,23 @@
1.13
1.14 if (atype->isFixedLength()) {
1.15 __ newarray(OP_NEWFIXED, map, InferTenure(node->sym()));
1.16 - } else if (node->dims()) {
1.17 - assert(false);
1.18 + } else if (node->dims()->at(0)) {
1.19 + // This may not be true if we allow typedefing, so :TODO:
1.20 + // figure out proper semantics.
1.21 + assert(node->dims()->length() == atype->levels());
1.22 +
1.23 + Local<Type> i32(zone_, zone_->types()->getPrimitive(PrimitiveType_Int32));
1.24 + for (size_t i = 0; i < node->dims()->length(); i++) {
1.25 + Expression *expr = node->dims()->at(i);
1.26 + if (expr) {
1.27 + HIR *hir = eval(expr);
1.28 + if (!hir || ((hir = coerce(hir, i32, Coerce_Arg)) == NULL))
1.29 + return;
1.30 + discharge(hir);
1.31 + } else {
1.32 + __ int_(0);
1.33 + }
1.34 + }
1.35 __ newarray(OP_NEWSIZED, map, InferTenure(node->sym()));
1.36 } else {
1.37 __ newarray(OP_NEWEMPTY, map, InferTenure(node->sym()));
1.38 @@ -833,9 +848,7 @@
1.39 HString *hir = from->toString();
1.40 Local<ArrayType> actual(zone_, ArrayType::cast(argActual));
1.41
1.42 - // If assigning or returning, and the desired type is fixed length,
1.43 - // make sure there is enough room.
1.44 - if ((kind == Coerce_Return || kind == Coerce_Assign) && actual->isFixedLength()) {
1.45 + if (actual->isFixedLength()) {
1.46 if (hir->string()->length() + 1 > actual->fixedLength()) {
1.47 cc_.reportError(pos, Message_ArrayAssignmentTooBig);
1.48 return NULL;
1.49 @@ -858,7 +871,25 @@
1.50 if (!array)
1.51 return NULL;
1.52
1.53 - return new (pool_) HArray(hir->node(), actual, array);
1.54 + // Since we're creating a canonical copy of the char array, we have to
1.55 + // be careful that it doesn't get mutated. There are two cases where
1.56 + // we know it can't be mutated, and therefore don't need to specify
1.57 + // that it be cloned after pushing it onto the stack.
1.58 + //
1.59 + // (1) The array type is const.
1.60 + // (2) The array type is fixed-length, and the coercion is for
1.61 + // assignment, meaning it will be immediately copied.
1.62 + //
1.63 + // We treat declaration separately from assignment, since for
1.64 + // declaration we can just immediately use the cloned version.
1.65 + bool shouldDuplicate = true;
1.66 + if (actual->isConst() ||
1.67 + (actual->isFixedLength() && kind == Coerce_Assign))
1.68 + {
1.69 + shouldDuplicate = false;
1.70 + }
1.71 +
1.72 + return new (pool_) HArray(hir->node(), actual, array, shouldDuplicate);
1.73 }
1.74
1.75 if (!argGiven->isArray()) {
1.76 @@ -877,23 +908,21 @@
1.77 unsigned level = 1;
1.78 while (true) {
1.79 if (actual->isFixedLength()) {
1.80 - if (kind == Coerce_Return || kind == Coerce_Assign) {
1.81 - if (!given->isFixedLength()) {
1.82 - cc_.reportError(pos, Message_ArrayDimensionSizeMismatch, level);
1.83 + if (!given->isFixedLength()) {
1.84 + cc_.reportError(pos, Message_ArrayDimensionSizeMismatch, level);
1.85 + return NULL;
1.86 + }
1.87 +
1.88 + if (actual->isCharArray()) {
1.89 + // String assignment can have a truncated |given|.
1.90 + if (given->fixedLength() > actual->fixedLength()) {
1.91 + cc_.reportError(pos, Message_ArrayAssignmentTooBig);
1.92 return NULL;
1.93 }
1.94 -
1.95 - if (actual->isCharArray()) {
1.96 - // String assignment can have a truncated |given|.
1.97 - if (given->fixedLength() > actual->fixedLength()) {
1.98 - cc_.reportError(pos, Message_ArrayAssignmentTooBig);
1.99 - return NULL;
1.100 - }
1.101 - } else {
1.102 - if (given->fixedLength() != actual->fixedLength()) {
1.103 - cc_.reportError(pos, Message_ArrayDimensionSizeMismatch, level);
1.104 - return NULL;
1.105 - }
1.106 + } else {
1.107 + if (given->fixedLength() != actual->fixedLength()) {
1.108 + cc_.reportError(pos, Message_ArrayDimensionSizeMismatch, level);
1.109 + return NULL;
1.110 }
1.111 }
1.112 } else if (given->isFixedLength()) {