diff -r f9c4371d59d4 -r 7721042bdb67 src/compiler/SemanticAnalysis.cpp --- a/src/compiler/SemanticAnalysis.cpp Thu Dec 27 21:07:03 2012 -0800 +++ b/src/compiler/SemanticAnalysis.cpp Fri Dec 28 17:13:51 2012 -0800 @@ -694,13 +694,66 @@ } else { Local actual(zone_, fun->parameterAt(i)); - if (expression->isIndexExpression()) { - // Temporarily disabled. - assert(!actual->isArray()); + + if (expression->isIndexExpression() && arg->isIndex()) { + // If the expression is the form x[y], and this produced a + // normal array indexing operation, then we apply some + // special rules. + if (actual->isReference()) { + // Disabled, since this doesn't have easily definable or + // sensible semantics with SP2 arrays, but we don't want + // to silently break SP1 semantics. cc_.reportError(expression->pos(), Message_CannotComputeIndexRef); return; } + + // As a special rule to account for SP1 semantics, we allow x[y] + // to automatically compute a sliced, read-only array view if + // the desired type is an array of one more dimension than x[y] + // would return. + // + // As an additional restriction, this is only allowed for + // one-level char arrays, to minimize potential issues until + // we determine whether more compatibility is needed. + // + // Internally, for sanity, the dependent array operation does + // not necessarily create a dependent array. For extensible + // arrays, we instead create a duplicate arrary of just the + // sliced portion, rather than deal with the complexity of the + // source array being resized. + // + // Note that we don't really know whether a dependent array + // will be dependent at compile-time, so the dependent type's + // just inherits from the source. + if (actual->isArray()) { + HIndex *index = arg->toIndex(); + Local basetype(zone_, ArrayType::cast(index->base()->type())); + Local atype(zone_, ArrayType::cast(actual)); + + if (atype->isCharArray() && basetype->isCharArray()) { + // There is no possible way this will type check, so + // it's safe to just try something completely + // different. + Local slicetype(zone_); + if (basetype->isFixedLength()) { + // If the base type is fixed length, we need to + // compute a new dynamic array type based on the + // fixed array's contents and qualifiers. + Local contained(zone_, basetype->contained()); + slicetype = zone_->types()->newArray(contained, ArrayType::DYNAMIC_ARRAY_SIZE); + if (!slicetype) + return; + slicetype = zone_->types()->qualify(slicetype, basetype->quals()); + if (!slicetype) + return; + } else { + slicetype = basetype; + } + arg = new (pool_) HNewDependentArray(expression, slicetype, index->base(), index->index()); + given = arg->type(); + } + } } if (actual->isReference()) { @@ -830,10 +883,17 @@ Type * SemanticAnalysis::coercionType(TokenKind token, HIR *left, HIR *right) { - Handle l = left->type(); - Handle r = right->type(); + Local l(zone_, left->type()); + Local r(zone_, right->type()); - if (token >= TOK_PLUS && token <= TOK_SLASH) { + if (l->isPod()) + l = l->unqualified(); + if (r->isPod()) + r = r->unqualified(); + + if ((token >= TOK_PLUS && token <= TOK_SLASH) || + (token >= TOK_EQUALS && token <= TOK_GE)) + { // We allow: [float|int32] + [float|int32] if (l->isFloat() && r->isInt32()) return l; @@ -841,6 +901,11 @@ return r; if (l->isInt32() && r->isInt32()) return l; + + if (l->isChar() && r->isInt32()) + return r; + if (l->isInt32() && r->isChar()) + return l; } // :TODO: remove @@ -1097,23 +1162,36 @@ return; switch (node->token()) { + case TOK_TILDE: + { + if (!hir->type()->isInt32() && !hir->type()->isEnum()) { + char name[255]; + cc_.reportError(node->pos(), Message_InvalidUnaryType, + "~", + GetTypeName(hir->type(), name, sizeof(name))); + } + Local type(zone_, zone_->types()->getPrimitive(PrimitiveType_Int32)); + hir_ = new (pool_) HUnary(node, hir->type(), TOK_TILDE, hir); + return; + } + case TOK_MINUS: { - if (hir->type()->isInt32() || hir->type()->isEnum()) { - Local type(zone_, zone_->types()->getPrimitive(PrimitiveType_Int32)); - hir_ = new (pool_) HUnary(node, type, TOK_MINUS, hir); - return; - } - if (hir->type()->isFloat()) { - hir_ = new (pool_) HUnary(node, hir->type(), TOK_MINUS, hir); - return; - } + if (hir->type()->isInt32() || hir->type()->isEnum()) { + Local type(zone_, zone_->types()->getPrimitive(PrimitiveType_Int32)); + hir_ = new (pool_) HUnary(node, type, TOK_MINUS, hir); + return; + } + if (hir->type()->isFloat()) { + hir_ = new (pool_) HUnary(node, hir->type(), TOK_MINUS, hir); + return; + } - char name[255]; - cc_.reportError(node->pos(), Message_InvalidUnaryType, - "-", - GetTypeName(hir->type(), name, sizeof(name))); - break; + char name[255]; + cc_.reportError(node->pos(), Message_InvalidUnaryType, + "-", + GetTypeName(hir->type(), name, sizeof(name))); + break; } default: @@ -1195,8 +1273,13 @@ BinaryExpression *bin = expr->toBinaryExpression(); if (token == TOK_AND || token == TOK_OR) { - assert(false); - //visitForLogicTest(expr, trueBranch, falseBranch, fallthrough); + Label next; + if (token == TOK_AND) + visitForTest(bin->left(), &next, falseBranch, &next); + else + visitForTest(bin->left(), trueBranch, &next, &next); + __ bind(&next); + visitForTest(bin->right(), trueBranch, falseBranch, fallthrough); return; }