Пример #1
0
TEST(TestDeclaration, testLet)
{
    PARSE_STATEMENT(L"let a : Int[] = [1, 2, 3]");
    ValueBindingsPtr c;
    IdentifierPtr id;
    ValueBindingPtr a;
    ArrayLiteralPtr value;
    ArrayTypePtr type;
    TypeIdentifierPtr Int;
    ASSERT_NOT_NULL(c = std::dynamic_pointer_cast<ValueBindings>(root));
    ASSERT_TRUE(c->isReadOnly());
    ASSERT_EQ(1, c->numBindings());
    ASSERT_NOT_NULL(a = c->get(0));
    ASSERT_NOT_NULL(id = std::dynamic_pointer_cast<Identifier>(a->getName()));
    ASSERT_EQ(L"a", id->getIdentifier());
    ASSERT_NOT_NULL(type = std::dynamic_pointer_cast<ArrayType>(a->getDeclaredType()));
    ASSERT_NOT_NULL(Int = std::dynamic_pointer_cast<TypeIdentifier>(type->getInnerType()));
    ASSERT_EQ(L"Int", Int->getName());

    ASSERT_NOT_NULL(value = std::dynamic_pointer_cast<ArrayLiteral>(c->get(0)->getInitializer()));
    ASSERT_EQ(3, value->numElements());
    ASSERT_EQ(L"1", std::dynamic_pointer_cast<IntegerLiteral>(value->getElement(0))->valueAsString);
    ASSERT_EQ(L"2", std::dynamic_pointer_cast<IntegerLiteral>(value->getElement(1))->valueAsString);
    ASSERT_EQ(L"3", std::dynamic_pointer_cast<IntegerLiteral>(value->getElement(2))->valueAsString);

}
Пример #2
0
void
ArrayIndexNode::computeType (LContext &lcontext, const SymbolInfoPtr &initInfo)
{
    if (!array || !index)
	return;

    array->computeType (lcontext, initInfo);
    index->computeType (lcontext, initInfo);

    if (!array->type || !index->type)
	return;

    ArrayTypePtr arrayType = array->type.cast<ArrayType>();

    if (!arrayType)
    {
	string name = "";
	if( NameNodePtr arrayName =  array.cast<NameNode>() )
	{
	    name = arrayName->name;
	    MESSAGE_LE (lcontext, ERR_NON_ARR_IND, array->lineNumber,
			"Applied [] operator to non-array (" << name << " "
			"is of type " << array->type->asString() << ").");
	}
	else
	{
	    MESSAGE_LE (lcontext, ERR_NON_ARR_IND, array->lineNumber,
			"Applied [] operator to non-array of type " 
			<< array->type->asString() << ".");
	}
	type = lcontext.newIntType();
	return;
    }

    IntTypePtr intType = lcontext.newIntType ();

    if (!intType->canPromoteFrom (index->type))
    {
	string name = "";
	if( NameNodePtr arrayName =  array.cast<NameNode>() )
	    name = arrayName->name;

	MESSAGE_LE (lcontext, ERR_ARR_IND_TYPE, array->lineNumber,
	    "Index into array " << name << " is not an iteger "
	    "(index is of type " << index->type->asString() << ").");

	type = lcontext.newIntType();
	return;
    }

    type = arrayType->elementType();
}
Пример #3
0
TypePtr arrayType(TypePtr elementType, int size) {
    int h = pointerHash(elementType.ptr()) + size;
    h &= arrayTypes.size() - 1;
    vector<ArrayTypePtr>::iterator i, end;
    for (i = arrayTypes[h].begin(), end = arrayTypes[h].end();
         i != end; ++i) {
        ArrayType *t = i->ptr();
        if ((t->elementType == elementType) && (t->size == size))
            return t;
    }
    ArrayTypePtr t = new ArrayType(elementType, size);
    arrayTypes[h].push_back(t);
    return t.ptr();
}
Пример #4
0
ExprNodePtr
SizeNode::evaluate (LContext &lcontext)
{
    obj = obj->evaluate(lcontext);
    ArrayTypePtr arrayType = obj->type.cast<ArrayType>();
    if( !arrayType)
    {
	return lcontext.newIntLiteralNode (lineNumber, 1);
    }
    else if( arrayType->size() != 0 )
    {
	return lcontext.newIntLiteralNode (lineNumber, arrayType->size());
    }
    return this;
}
Пример #5
0
ExprNodePtr
ArrayIndexNode::evaluate (LContext &lcontext)
{
    IntTypePtr intType = lcontext.newIntType ();

    array = array->evaluate (lcontext);
    index = index->evaluate (lcontext);


    if( IntLiteralNodePtr literal = index.cast<IntLiteralNode>())
    {
	if(literal->value < 0)
	{
	    string name = "";
	    if( NameNodePtr arrayName =  array.cast<NameNode>() )
		name = arrayName->name;
	    
	    MESSAGE_LE (lcontext, ERR_ARR_IND_TYPE, array->lineNumber,
			"Index into array " << name << " is negative "
			"(" << literal->value << ").");
	}

	ArrayTypePtr arrayType = array->type.cast<ArrayType>();
	if(!arrayType)
	    return this;
	if( literal->value >= arrayType->size() && arrayType->size() != 0)
	{
	    string name = "";
	    if( NameNodePtr arrayName =  array.cast<NameNode>() )
		name = arrayName->name;
	    
	    MESSAGE_LE (lcontext, ERR_ARR_IND_TYPE, array->lineNumber,
			"Index into array " << name << " is out of range "
			"(index = " << literal->value << ", "
			"array size = " << arrayType->size() << ").");
	}


    }

    if (index->type && !intType->isSameTypeAs (index->type))
	index = intType->castValue (lcontext, index);

    return this;
}
Пример #6
0
FunctionCallPtr
Interpreter::newFunctionCall (const std::string &functionName)
{
    Lock lock (_data->mutex);
    
    //
    // Calling a CTL function with variable-size array arguments
    // from C++ is not supported.
    //

    const SymbolInfoPtr info = symtab().lookupSymbol (functionName);

    if (!info)
	THROW (ArgExc, "Cannot find CTL function " << functionName << ".");

    if (!info->isFunction())
	THROW (TypeExc, "CTL object " << functionName << " is not a function "
			"(it is of type " << info->type()->asString() << ").");

    const FunctionTypePtr fType = info->type();
    const ParamVector &parameters = fType->parameters();

    for (int i = parameters.size() - 1; i >= 0; --i)
    {
	const Param &param = parameters[i];
        ArrayTypePtr aType = param.type.cast<ArrayType>();

        if(aType)
        {
            SizeVector sizes;
            aType->sizes (sizes);
	    
            for (int j = 0; j < sizes.size(); j++)
            {
                if (sizes[j] == 0)
                    THROW (ArgExc, "CTL function " << functionName << " "
				   "has a variable-size array "
				   "argument, " << param.name << ", and can "
				   "only be called by another CTL function.");
            }
        }
    }
    
    return newFunctionCallInternal (info, functionName);
}
Пример #7
0
/*!
 * dictionary-type → [­type­:­type­]­
 * array-type → [­type­]­
 */
TypeNodePtr Parser::parseCollectionType()
{
    Token token;
    expect(L"[", token);
    TypeNodePtr type = this->parseType();
    if(match(L":"))
    {
        //it's a dictionary type
        TypeNodePtr valueType = parseType();
        expect(L"]");
        DictionaryTypePtr ret = nodeFactory->createDictionaryType(token.state);
        ret->setKeyType(type);
        ret->setValueType(valueType);
        return ret;
    }
    else
    {
        //it's an array type
        expect(L"]");
        ArrayTypePtr ret = nodeFactory->createArrayType(token.state);
        ret->setInnerType(type);
        return ret;
    }
}
Пример #8
0
void NodeSerializer::visitArrayType(const ArrayTypePtr& node)
{
    append(L"[");
    node->getInnerType()->accept(this);
    append(L"]");
}
Пример #9
0
TypeNodePtr Parser::parseType()
{
    Token token;
    TypeNodePtr ret = NULL;
    expect_next(token);
    restore(token);

    if(token == TokenType::OpenParen)
    {
        ret = parseTupleType();
    }
    else if(token.type == TokenType::Identifier && token.identifier.keyword == Keyword::_)
    {
        ret = parseTypeIdentifier();
    }
    else if(token.type == TokenType::Identifier && token.identifier.keyword == Keyword::SelfType)
    {
        ret = parseTypeIdentifier();
    }
    else if(token.getKeyword() == Keyword::Protocol)
    {
        ret = parseProtocolComposition();
    }
    else if(token == TokenType::OpenBracket)
    {
        ret = parseCollectionType();
    }
    else
    {
        unexpected(token);
    }
    do
    {
        if(!next(token))
            break;
        
        //type chaining
        if(token == L"->")
        {
            //function-type → type->type
            TupleTypePtr argType = std::dynamic_pointer_cast<TupleType>(ret);
            if(!argType)
            {
                //wrap ret as a tuple type
                argType = nodeFactory->createTupleType(*ret->getSourceInfo());
                argType->add(false, L"", ret);
            }
            TypeNodePtr retType = parseType();
            FunctionTypePtr func = nodeFactory->createFunctionType(token.state);
            func->setArgumentsType(argType);
            func->setReturnType(retType);
            ret = func;
            continue;
        }
        if(token == TokenType::OpenBracket)
        {
            expect(L"]");
            ArrayTypePtr array = nodeFactory->createArrayType(token.state);
            array->setInnerType(ret);
            ret = array;
            continue;
        }
        if(token == L"?")
        {
            //optional-type → type?
            OptionalTypePtr type = nodeFactory->createOptionalType(token.state);
            type->setInnerType(ret);
            ret = type;
            continue;
        }
        if(token == L"!")
        {
            //implicitly-unwrapped-optional-type → type!
            ImplicitlyUnwrappedOptionalPtr type = nodeFactory->createImplicitlyUnwrappedOptional(token.state);
            type->setInnerType(ret);
            ret = type;
            continue;
        }
        // ‌ metatype-type → type.Type  type.Protocol
        //TODO meta type is not supported
        restore(token);
        break;
    }while(true);
    return ret;
}