src/compiler/SemanticAnalysis.cpp
changeset 236 072f1114ea5d
parent 235 43287eef2fff
child 237 c77540a61905
     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()) {