src/compiler/SemanticAnalysis.cpp
changeset 234 26e3035cdffc
parent 233 bbb498ccb4ac
child 235 43287eef2fff
     1.1 --- a/src/compiler/SemanticAnalysis.cpp	Sat Dec 22 23:18:57 2012 -0800
     1.2 +++ b/src/compiler/SemanticAnalysis.cpp	Mon Dec 24 02:49:20 2012 -0800
     1.3 @@ -429,31 +429,31 @@
     1.4      PoolScope poolScope(zone_->pool());
     1.5      RootScope rootScope(zone_);
     1.6  
     1.7 +    Local<Type> type(zone_, node->sym()->type());
     1.8 +
     1.9      if (node->initialization()) {
    1.10          HIR *hir = NULL;
    1.11  
    1.12          if ((hir = eval(node->initialization())) == NULL)
    1.13              return;
    1.14 -        if ((hir = coerce(hir, node->sym()->type(), Coerce_Assign)) == NULL)
    1.15 +        if ((hir = coerce(hir, type, Coerce_Assign)) == NULL)
    1.16              return;
    1.17  
    1.18          discharge(hir);
    1.19      } else {
    1.20 -        if (node->sym()->type()->isInt32() ||
    1.21 -            node->sym()->type()->isEnum() ||
    1.22 -            node->sym()->type()->isChar() ||
    1.23 -            node->sym()->type()->isBool())
    1.24 +        if (type->isInt32() || type->isEnum() ||
    1.25 +            type->isChar() || type->isBool())
    1.26          {
    1.27              __ int_(0);
    1.28 -        } else if (node->sym()->type()->isFloat()) {
    1.29 +        } else if (type->isFloat()) {
    1.30              __ float_(0);
    1.31 -        } else if (node->sym()->type()->isArray()) {
    1.32 -            Local<ArrayType> type(zone_, ArrayType::cast(node->sym()->type()));
    1.33 -            Local<ArrayMap> map(zone_, ArrayMap::Attach(zone_, type));
    1.34 +        } else if (type->isArray()) {
    1.35 +            Local<ArrayType> atype(zone_, ArrayType::cast(type));
    1.36 +            Local<ArrayMap> map(zone_, ArrayMap::Attach(zone_, atype));
    1.37              if (!map)
    1.38                  return;
    1.39  
    1.40 -            if (type->isFixedLength()) {
    1.41 +            if (atype->isFixedLength()) {
    1.42                  __ newarray(OP_NEWFIXED, map, InferTenure(node->sym()));
    1.43              } else if (node->dims()) {
    1.44                  assert(false);
    1.45 @@ -461,11 +461,15 @@
    1.46              } else {
    1.47                  __ newarray(OP_NEWEMPTY, map, InferTenure(node->sym()));
    1.48              }
    1.49 +        } else {
    1.50 +            assert(false);
    1.51          }
    1.52      }
    1.53  
    1.54 -    if (!__ allocate(node->sym()))
    1.55 -        return;
    1.56 +    if (node->sym()->scope()->kind() != Scope::GLOBAL) {
    1.57 +        if (!__ allocate(node->sym()))
    1.58 +            return;
    1.59 +    }
    1.60  
    1.61      set(node->sym());
    1.62      __ pop();
    1.63 @@ -613,6 +617,13 @@
    1.64  }
    1.65  
    1.66  void
    1.67 +SemanticAnalysis::visitStringLiteral(StringLiteral *node)
    1.68 +{
    1.69 +    Type *type = zone_->types()->getPrimitive(PrimitiveType_String);
    1.70 +    hir_ = new (pool_) HString(node, type, node->string());
    1.71 +}
    1.72 +
    1.73 +void
    1.74  SemanticAnalysis::visitCallExpression(CallExpression *node)
    1.75  {
    1.76      HIR *callee = eval(node->callee());
    1.77 @@ -804,15 +815,55 @@
    1.78      return left->type();
    1.79  }
    1.80  
    1.81 -bool
    1.82 +HIR *
    1.83  SemanticAnalysis::typeCheckArray(const SourcePosition &pos,
    1.84 -                                 Handle<Type> argGiven,
    1.85 +                                 HIR *from,
    1.86                                   Handle<Type> argActual,
    1.87                                   CoercionKind kind)
    1.88  {
    1.89 +    Local<Type> argGiven(zone_, from->type());
    1.90 +
    1.91 +    // Special case: if we receive a string literal, and this is a char array,
    1.92 +    // we allow a coercion.
    1.93 +    if (from->isString() &&
    1.94 +        argGiven->isString() &&
    1.95 +        argActual->isArray() &&
    1.96 +        ArrayType::cast(argActual)->isCharArray())
    1.97 +    {
    1.98 +        HString *hir = from->toString();
    1.99 +        Local<ArrayType> actual(zone_, ArrayType::cast(argActual));
   1.100 +
   1.101 +        // If assigning or returning, and the desired type is fixed length,
   1.102 +        // make sure there is enough room.
   1.103 +        if ((kind == Coerce_Return || kind == Coerce_Assign) && actual->isFixedLength()) {
   1.104 +            if (hir->string()->length() + 1 > actual->fixedLength()) {
   1.105 +                cc_.reportError(pos, Message_ArrayAssignmentTooBig);
   1.106 +                return NULL;
   1.107 +            }
   1.108 +        }
   1.109 +
   1.110 +        // Transform the string literal into an array literal. We give it the
   1.111 +        // type of the left-hand side. The constness of the destination type
   1.112 +        // will determine whether HArray duplicates it or not.
   1.113 +        Local<ArrayMap> map(zone_, ArrayMap::Attach(zone_, actual));
   1.114 +        if (!map)
   1.115 +            return NULL;
   1.116 +
   1.117 +        Local<Array> array(zone_);
   1.118 +        array = Array::NewString(zone_,
   1.119 +                                 map,
   1.120 +                                 hir->string()->chars(),
   1.121 +                                 hir->string()->length(),
   1.122 +                                 Heap::Tenure_Old);
   1.123 +        if (!array)
   1.124 +            return NULL;
   1.125 +
   1.126 +        return new (pool_) HArray(hir->node(), actual, array);
   1.127 +    }
   1.128 +
   1.129      if (!argGiven->isArray()) {
   1.130          cc_.reportError(pos, Message_ExpectedArray);
   1.131 -        return false;
   1.132 +        return NULL;
   1.133      }
   1.134  
   1.135      Local<ArrayType> actual(zone_, ArrayType::cast(argActual));
   1.136 @@ -820,7 +871,7 @@
   1.137  
   1.138      if (actual->levels() != given->levels()) {
   1.139          cc_.reportError(pos, Message_ArrayDimensionsMismatch);
   1.140 -        return false;
   1.141 +        return NULL;
   1.142      }
   1.143  
   1.144      unsigned level = 1;
   1.145 @@ -829,19 +880,19 @@
   1.146              if (kind == Coerce_Return || kind == Coerce_Assign) {
   1.147                  if (!given->isFixedLength()) {
   1.148                      cc_.reportError(pos, Message_ArrayDimensionSizeMismatch, level);
   1.149 -                    return false;
   1.150 +                    return NULL;
   1.151                  }
   1.152  
   1.153                  if (actual->isCharArray()) {
   1.154                      // String assignment can have a truncated |given|.
   1.155                      if (given->fixedLength() > actual->fixedLength()) {
   1.156                          cc_.reportError(pos, Message_ArrayAssignmentTooBig);
   1.157 -                        return false;
   1.158 +                        return NULL;
   1.159                      }
   1.160                  } else {
   1.161                      if (given->fixedLength() != actual->fixedLength()) {
   1.162                          cc_.reportError(pos, Message_ArrayDimensionSizeMismatch, level);
   1.163 -                        return false;
   1.164 +                        return NULL;
   1.165                      }
   1.166                  }
   1.167              }
   1.168 @@ -863,7 +914,7 @@
   1.169              // Now |x[0]| contains a 3-length array.
   1.170              if (level > 1) {
   1.171                  cc_.reportError(pos, Message_ArrayDimensionSizeMismatch, level);
   1.172 -                return false;
   1.173 +                return NULL;
   1.174              }
   1.175          }
   1.176  
   1.177 @@ -882,7 +933,7 @@
   1.178          return false;
   1.179      }
   1.180  
   1.181 -    return true;
   1.182 +    return from;
   1.183  }
   1.184  
   1.185  HIR *
   1.186 @@ -897,21 +948,18 @@
   1.187  HIR *
   1.188  SemanticAnalysis::coerce(HIR *hir, Handle<Type> to, CoercionKind kind)
   1.189  {
   1.190 -    Handle<Type> from = hir->type();
   1.191 +    Local<Type> from(zone_, hir->type());
   1.192  
   1.193      if (from->isInt32() && to->isFloat())
   1.194          return new (pool_) HConvert(hir->node(), to, OP_CVT_I2F, hir);
   1.195      if (from->isInt32() && to->isBool())
   1.196          return new (pool_) HConvert(hir->node(), to, OP_CVT_I2B, hir);
   1.197  
   1.198 -    if (to->isEnum() && from != to)
   1.199 +    if (to->isEnum() && *from != to)
   1.200          return typeFailure(hir->node()->pos(), from, to);
   1.201      
   1.202 -    if (to->isArray()) {
   1.203 -        if (!typeCheckArray(SourcePosition(), from, to, kind))
   1.204 -            return NULL;
   1.205 -        return hir;
   1.206 -    }
   1.207 +    if (to->isArray())
   1.208 +        return typeCheckArray(SourcePosition(), hir, to, kind);
   1.209      
   1.210      return hir;
   1.211  }
   1.212 @@ -1003,7 +1051,7 @@
   1.213              hir = eval(expr->toUnaryExpression()->expression());
   1.214          if (!hir)
   1.215              return;
   1.216 -        if ((hir = coerce(hir, boolType, Coerce_Assign)) == NULL)
   1.217 +        if ((hir = coerce(hir, boolType, Coerce_Arg)) == NULL)
   1.218              return;
   1.219  
   1.220          discharge(hir);
   1.221 @@ -1033,7 +1081,7 @@
   1.222      HIR *hir = binary(bin, bin->token(), left, right);
   1.223      if (!hir)
   1.224          return;
   1.225 -    if ((hir = coerce(hir, boolType, Coerce_Assign)) == NULL)
   1.226 +    if ((hir = coerce(hir, boolType, Coerce_Arg)) == NULL)
   1.227          return;
   1.228  
   1.229      discharge(hir);