diff -r bbb498ccb4ac -r 26e3035cdffc src/compiler/SemanticAnalysis.cpp --- a/src/compiler/SemanticAnalysis.cpp Sat Dec 22 23:18:57 2012 -0800 +++ b/src/compiler/SemanticAnalysis.cpp Mon Dec 24 02:49:20 2012 -0800 @@ -429,31 +429,31 @@ PoolScope poolScope(zone_->pool()); RootScope rootScope(zone_); + Local type(zone_, node->sym()->type()); + if (node->initialization()) { HIR *hir = NULL; if ((hir = eval(node->initialization())) == NULL) return; - if ((hir = coerce(hir, node->sym()->type(), Coerce_Assign)) == NULL) + if ((hir = coerce(hir, type, Coerce_Assign)) == NULL) return; discharge(hir); } else { - if (node->sym()->type()->isInt32() || - node->sym()->type()->isEnum() || - node->sym()->type()->isChar() || - node->sym()->type()->isBool()) + if (type->isInt32() || type->isEnum() || + type->isChar() || type->isBool()) { __ int_(0); - } else if (node->sym()->type()->isFloat()) { + } else if (type->isFloat()) { __ float_(0); - } else if (node->sym()->type()->isArray()) { - Local type(zone_, ArrayType::cast(node->sym()->type())); - Local map(zone_, ArrayMap::Attach(zone_, type)); + } else if (type->isArray()) { + Local atype(zone_, ArrayType::cast(type)); + Local map(zone_, ArrayMap::Attach(zone_, atype)); if (!map) return; - if (type->isFixedLength()) { + if (atype->isFixedLength()) { __ newarray(OP_NEWFIXED, map, InferTenure(node->sym())); } else if (node->dims()) { assert(false); @@ -461,11 +461,15 @@ } else { __ newarray(OP_NEWEMPTY, map, InferTenure(node->sym())); } + } else { + assert(false); } } - if (!__ allocate(node->sym())) - return; + if (node->sym()->scope()->kind() != Scope::GLOBAL) { + if (!__ allocate(node->sym())) + return; + } set(node->sym()); __ pop(); @@ -613,6 +617,13 @@ } void +SemanticAnalysis::visitStringLiteral(StringLiteral *node) +{ + Type *type = zone_->types()->getPrimitive(PrimitiveType_String); + hir_ = new (pool_) HString(node, type, node->string()); +} + +void SemanticAnalysis::visitCallExpression(CallExpression *node) { HIR *callee = eval(node->callee()); @@ -804,15 +815,55 @@ return left->type(); } -bool +HIR * SemanticAnalysis::typeCheckArray(const SourcePosition &pos, - Handle argGiven, + HIR *from, Handle argActual, CoercionKind kind) { + Local argGiven(zone_, from->type()); + + // Special case: if we receive a string literal, and this is a char array, + // we allow a coercion. + if (from->isString() && + argGiven->isString() && + argActual->isArray() && + ArrayType::cast(argActual)->isCharArray()) + { + HString *hir = from->toString(); + Local actual(zone_, ArrayType::cast(argActual)); + + // If assigning or returning, and the desired type is fixed length, + // make sure there is enough room. + if ((kind == Coerce_Return || kind == Coerce_Assign) && actual->isFixedLength()) { + if (hir->string()->length() + 1 > actual->fixedLength()) { + cc_.reportError(pos, Message_ArrayAssignmentTooBig); + return NULL; + } + } + + // Transform the string literal into an array literal. We give it the + // type of the left-hand side. The constness of the destination type + // will determine whether HArray duplicates it or not. + Local map(zone_, ArrayMap::Attach(zone_, actual)); + if (!map) + return NULL; + + Local array(zone_); + array = Array::NewString(zone_, + map, + hir->string()->chars(), + hir->string()->length(), + Heap::Tenure_Old); + if (!array) + return NULL; + + return new (pool_) HArray(hir->node(), actual, array); + } + if (!argGiven->isArray()) { cc_.reportError(pos, Message_ExpectedArray); - return false; + return NULL; } Local actual(zone_, ArrayType::cast(argActual)); @@ -820,7 +871,7 @@ if (actual->levels() != given->levels()) { cc_.reportError(pos, Message_ArrayDimensionsMismatch); - return false; + return NULL; } unsigned level = 1; @@ -829,19 +880,19 @@ if (kind == Coerce_Return || kind == Coerce_Assign) { if (!given->isFixedLength()) { cc_.reportError(pos, Message_ArrayDimensionSizeMismatch, level); - return false; + return NULL; } if (actual->isCharArray()) { // String assignment can have a truncated |given|. if (given->fixedLength() > actual->fixedLength()) { cc_.reportError(pos, Message_ArrayAssignmentTooBig); - return false; + return NULL; } } else { if (given->fixedLength() != actual->fixedLength()) { cc_.reportError(pos, Message_ArrayDimensionSizeMismatch, level); - return false; + return NULL; } } } @@ -863,7 +914,7 @@ // Now |x[0]| contains a 3-length array. if (level > 1) { cc_.reportError(pos, Message_ArrayDimensionSizeMismatch, level); - return false; + return NULL; } } @@ -882,7 +933,7 @@ return false; } - return true; + return from; } HIR * @@ -897,21 +948,18 @@ HIR * SemanticAnalysis::coerce(HIR *hir, Handle to, CoercionKind kind) { - Handle from = hir->type(); + Local from(zone_, hir->type()); if (from->isInt32() && to->isFloat()) return new (pool_) HConvert(hir->node(), to, OP_CVT_I2F, hir); if (from->isInt32() && to->isBool()) return new (pool_) HConvert(hir->node(), to, OP_CVT_I2B, hir); - if (to->isEnum() && from != to) + if (to->isEnum() && *from != to) return typeFailure(hir->node()->pos(), from, to); - if (to->isArray()) { - if (!typeCheckArray(SourcePosition(), from, to, kind)) - return NULL; - return hir; - } + if (to->isArray()) + return typeCheckArray(SourcePosition(), hir, to, kind); return hir; } @@ -1003,7 +1051,7 @@ hir = eval(expr->toUnaryExpression()->expression()); if (!hir) return; - if ((hir = coerce(hir, boolType, Coerce_Assign)) == NULL) + if ((hir = coerce(hir, boolType, Coerce_Arg)) == NULL) return; discharge(hir); @@ -1033,7 +1081,7 @@ HIR *hir = binary(bin, bin->token(), left, right); if (!hir) return; - if ((hir = coerce(hir, boolType, Coerce_Assign)) == NULL) + if ((hir = coerce(hir, boolType, Coerce_Arg)) == NULL) return; discharge(hir);