src/compiler/SemanticAnalysis.cpp
changeset 247 7721042bdb67
parent 246 f9c4371d59d4
child 251 ca99a81745fe
     1.1 --- a/src/compiler/SemanticAnalysis.cpp	Thu Dec 27 21:07:03 2012 -0800
     1.2 +++ b/src/compiler/SemanticAnalysis.cpp	Fri Dec 28 17:13:51 2012 -0800
     1.3 @@ -694,13 +694,66 @@
     1.4          } else {
     1.5              Local<Type> actual(zone_, fun->parameterAt(i));
     1.6  
     1.7 -            if (expression->isIndexExpression()) {
     1.8 -                // Temporarily disabled.
     1.9 -                assert(!actual->isArray());
    1.10 +
    1.11 +            if (expression->isIndexExpression() && arg->isIndex()) {
    1.12 +                // If the expression is the form x[y], and this produced a
    1.13 +                // normal array indexing operation, then we apply some 
    1.14 +                // special rules.
    1.15 +
    1.16                  if (actual->isReference()) {
    1.17 +                    // Disabled, since this doesn't have easily definable or
    1.18 +                    // sensible semantics with SP2 arrays, but we don't want
    1.19 +                    // to silently break SP1 semantics.
    1.20                      cc_.reportError(expression->pos(), Message_CannotComputeIndexRef);
    1.21                      return;
    1.22                  }
    1.23 +
    1.24 +                // As a special rule to account for SP1 semantics, we allow x[y]
    1.25 +                // to automatically compute a sliced, read-only array view if
    1.26 +                // the desired type is an array of one more dimension than x[y]
    1.27 +                // would return.
    1.28 +                //
    1.29 +                // As an additional restriction, this is only allowed for
    1.30 +                // one-level char arrays, to minimize potential issues until
    1.31 +                // we determine whether more compatibility is needed.
    1.32 +                //
    1.33 +                // Internally, for sanity, the dependent array operation does
    1.34 +                // not necessarily create a dependent array. For extensible
    1.35 +                // arrays, we instead create a duplicate arrary of just the
    1.36 +                // sliced portion, rather than deal with the complexity of the
    1.37 +                // source array being resized.
    1.38 +                //
    1.39 +                // Note that we don't really know whether a dependent array
    1.40 +                // will be dependent at compile-time, so the dependent type's
    1.41 +                // just inherits from the source.
    1.42 +                if (actual->isArray()) {
    1.43 +                    HIndex *index = arg->toIndex();
    1.44 +                    Local<ArrayType> basetype(zone_, ArrayType::cast(index->base()->type()));
    1.45 +                    Local<ArrayType> atype(zone_, ArrayType::cast(actual));
    1.46 +
    1.47 +                    if (atype->isCharArray() && basetype->isCharArray()) {
    1.48 +                        // There is no possible way this will type check, so
    1.49 +                        // it's safe to just try something completely
    1.50 +                        // different.
    1.51 +                        Local<Type> slicetype(zone_);
    1.52 +                        if (basetype->isFixedLength()) {
    1.53 +                            // If the base type is fixed length, we need to
    1.54 +                            // compute a new dynamic array type based on the
    1.55 +                            // fixed array's contents and qualifiers.
    1.56 +                            Local<Type> contained(zone_, basetype->contained());
    1.57 +                            slicetype = zone_->types()->newArray(contained, ArrayType::DYNAMIC_ARRAY_SIZE);
    1.58 +                            if (!slicetype)
    1.59 +                                return;
    1.60 +                            slicetype = zone_->types()->qualify(slicetype, basetype->quals());
    1.61 +                            if (!slicetype)
    1.62 +                                return;
    1.63 +                        } else {
    1.64 +                            slicetype = basetype;
    1.65 +                        }
    1.66 +                        arg = new (pool_) HNewDependentArray(expression, slicetype, index->base(), index->index());
    1.67 +                        given = arg->type();
    1.68 +                    }
    1.69 +                }
    1.70              }
    1.71  
    1.72              if (actual->isReference()) {
    1.73 @@ -830,10 +883,17 @@
    1.74  Type *
    1.75  SemanticAnalysis::coercionType(TokenKind token, HIR *left, HIR *right)
    1.76  {
    1.77 -    Handle<Type> l = left->type();
    1.78 -    Handle<Type> r = right->type();
    1.79 +    Local<Type> l(zone_, left->type());
    1.80 +    Local<Type> r(zone_, right->type());
    1.81  
    1.82 -    if (token >= TOK_PLUS && token <= TOK_SLASH) {
    1.83 +    if (l->isPod())
    1.84 +        l = l->unqualified();
    1.85 +    if (r->isPod())
    1.86 +        r = r->unqualified();
    1.87 +
    1.88 +    if ((token >= TOK_PLUS && token <= TOK_SLASH) ||
    1.89 +        (token >= TOK_EQUALS && token <= TOK_GE))
    1.90 +    {
    1.91          // We allow: [float|int32] + [float|int32]
    1.92          if (l->isFloat() && r->isInt32())
    1.93              return l;
    1.94 @@ -841,6 +901,11 @@
    1.95              return r;
    1.96          if (l->isInt32() && r->isInt32())
    1.97              return l;
    1.98 +
    1.99 +        if (l->isChar() && r->isInt32())
   1.100 +             return r;
   1.101 +        if (l->isInt32() && r->isChar())
   1.102 +            return l;
   1.103      }
   1.104  
   1.105      // :TODO: remove
   1.106 @@ -1097,23 +1162,36 @@
   1.107          return;
   1.108  
   1.109      switch (node->token()) {
   1.110 +      case TOK_TILDE:
   1.111 +      {
   1.112 +        if (!hir->type()->isInt32() && !hir->type()->isEnum()) {
   1.113 +            char name[255];
   1.114 +            cc_.reportError(node->pos(), Message_InvalidUnaryType,
   1.115 +                            "~",
   1.116 +                            GetTypeName(hir->type(), name, sizeof(name)));
   1.117 +        }
   1.118 +        Local<Type> type(zone_, zone_->types()->getPrimitive(PrimitiveType_Int32));
   1.119 +        hir_ = new (pool_) HUnary(node, hir->type(), TOK_TILDE, hir);
   1.120 +        return;
   1.121 +      }
   1.122 +
   1.123        case TOK_MINUS:
   1.124        {
   1.125 -          if (hir->type()->isInt32() || hir->type()->isEnum()) {
   1.126 -              Local<Type> type(zone_, zone_->types()->getPrimitive(PrimitiveType_Int32));
   1.127 -              hir_ = new (pool_) HUnary(node, type, TOK_MINUS, hir);
   1.128 -              return;
   1.129 -          }
   1.130 -          if (hir->type()->isFloat()) {
   1.131 -              hir_ = new (pool_) HUnary(node, hir->type(), TOK_MINUS, hir);
   1.132 -              return;
   1.133 -          }
   1.134 +        if (hir->type()->isInt32() || hir->type()->isEnum()) {
   1.135 +            Local<Type> type(zone_, zone_->types()->getPrimitive(PrimitiveType_Int32));
   1.136 +            hir_ = new (pool_) HUnary(node, type, TOK_MINUS, hir);
   1.137 +            return;
   1.138 +        }
   1.139 +        if (hir->type()->isFloat()) {
   1.140 +            hir_ = new (pool_) HUnary(node, hir->type(), TOK_MINUS, hir);
   1.141 +            return;
   1.142 +        }
   1.143  
   1.144 -          char name[255];
   1.145 -          cc_.reportError(node->pos(), Message_InvalidUnaryType,
   1.146 -                          "-",
   1.147 -                          GetTypeName(hir->type(), name, sizeof(name)));
   1.148 -          break;
   1.149 +        char name[255];
   1.150 +        cc_.reportError(node->pos(), Message_InvalidUnaryType,
   1.151 +                        "-",
   1.152 +                        GetTypeName(hir->type(), name, sizeof(name)));
   1.153 +        break;
   1.154        }
   1.155  
   1.156        default:
   1.157 @@ -1195,8 +1273,13 @@
   1.158  
   1.159      BinaryExpression *bin = expr->toBinaryExpression();
   1.160      if (token == TOK_AND || token == TOK_OR) {
   1.161 -        assert(false);
   1.162 -        //visitForLogicTest(expr, trueBranch, falseBranch, fallthrough);
   1.163 +        Label next;
   1.164 +        if (token == TOK_AND)
   1.165 +            visitForTest(bin->left(), &next, falseBranch, &next);
   1.166 +        else
   1.167 +            visitForTest(bin->left(), trueBranch, &next, &next);
   1.168 +        __ bind(&next);
   1.169 +        visitForTest(bin->right(), trueBranch, falseBranch, fallthrough);
   1.170          return;
   1.171      }
   1.172