Exemple #1
0
    void tv_static_type_query(Type* type, StaticTypeQuery* query)
    {
        Term* subject = query->subject;
        Type* subjectType = query->subjectType;

        // If the type doesn't have a specific size, then accept any list.
        if (!list_type_has_specific_size(&type->parameter)) {
            if (is_list_based_type(subjectType))
                return query->succeed();
            else
                return query->fail();
        }

        caValue* expectedElementTypes = list_get_type_list_from_type(type);

        // Special case when looking at a call to list(); look at inputs instead of
        // looking at the result.
        if (subject && subject->function == FUNCS.list)
        {
            if (subject->numInputs() != circa_count(expectedElementTypes))
                return query->fail();

            for (int i=0; i < circa_count(expectedElementTypes); i++)
                if (!circa::term_output_always_satisfies_type(
                            subject->input(i), as_type(circa_index(expectedElementTypes, i))))
                    return query->fail();

            return query->succeed();
        }

        // Look at the subject's type.
        if (!list_type_has_specific_size(&subjectType->parameter))
            return query->fail();

        caValue* subjectElementTypes = list_get_type_list_from_type(subjectType);

        bool anyUnableToDetermine = false;

        for (int i=0; i < circa_count(expectedElementTypes); i++) {
            if (i >= circa_count(subjectElementTypes))
                return query->fail();

            StaticTypeQuery::Result result = run_static_type_query(
                    as_type(circa_index(expectedElementTypes,i)),
                    as_type(circa_index(subjectElementTypes,i)));

            // If any of these fail, then fail.
            if (result == StaticTypeQuery::FAIL)
                return query->fail();

            if (result == StaticTypeQuery::UNABLE_TO_DETERMINE)
                anyUnableToDetermine = true;
        }

        if (anyUnableToDetermine)
            return query->unableToDetermine();
        else
            return query->succeed();
    }
Exemple #2
0
Type* List__append_specializeType(Term* term)
{
    Term* listInput = term->input(0);
    switch (list_get_parameter_type(&listInput->type->parameter)) {
    case sym_Untyped:
        return listInput->type;
    case sym_UniformListType:
    {
        Type* listElementType = list_get_repeated_type_from_type(listInput->type);
        Type* commonType = find_common_type(listElementType, term->input(1)->type);
        if (commonType == listElementType)
            return listInput->type;
        else
            return create_typed_unsized_list_type(commonType);
    }
    case sym_AnonStructType:
    case sym_StructType:
    {    
        List elementTypes;
        copy(list_get_type_list_from_type(listInput->type), &elementTypes);
        set_type(elementTypes.append(), term->input(1)->type);
        return create_typed_unsized_list_type(find_common_type(&elementTypes));
    }
    case sym_Invalid:
    default:
        return TYPES.any;
    }
}
Exemple #3
0
Type* get_field_specializeType(Term* caller)
{
    Type* head = caller->input(0)->type;

    for (int nameIndex=1; nameIndex < caller->numInputs(); nameIndex++) {

        // Abort if input type is not correct
        if (!is_string(term_value(caller->input(1))))
            return TYPES.any;

        if (!is_list_based_type(head))
            return TYPES.any;

        Value* name = term_value(caller->input(1));

        int fieldIndex = list_find_field_index_by_name(head, name);

        if (fieldIndex == -1)
            return TYPES.any;

        head = as_type(get_index(list_get_type_list_from_type(head),fieldIndex));
    }

    return head;
}
Exemple #4
0
    void tv_initialize(Type* type, caValue* value)
    {
        ca_assert(value->value_data.ptr == NULL);

        // If the parameter has a fixed size list, then initialize to that.
        if (list_type_has_specific_size(&type->parameter)) {
            caValue* typeList = list_get_type_list_from_type(type);
            int count = list_length(typeList);

            list_resize(value, count);
            for (int i=0; i < count; i++)
                make(as_type(list_get(typeList, i)), list_get(value, i));
        }
    }
Exemple #5
0
Type* infer_type_of_get_index(Term* input)
{
    if (input == NULL)
        return &ANY_T;

    switch (list_get_parameter_type(&input->type->parameter)) {
    case LIST_UNTYPED:
        return &ANY_T;
    case LIST_TYPED_UNSIZED:
        return list_get_repeated_type_from_type(input->type);
    case LIST_TYPED_SIZED:
    case LIST_TYPED_SIZED_NAMED:
        return find_common_type(list_get_type_list_from_type(input->type));
    case LIST_INVALID_PARAMETER:
    default:
        return &ANY_T;
    }
}
Type* infer_type_of_get_index(Term* input)
{
    if (input == NULL)
        return TYPES.any;

    switch (list_get_parameter_type(&input->type->parameter)) {
    case name_Untyped:
        return TYPES.any;
    case name_UniformListType:
        return list_get_repeated_type_from_type(input->type);
    case name_StructType:
    case name_AnonStructType:
        return find_common_type(list_get_type_list_from_type(input->type));
    case name_Invalid:
    default:
        return TYPES.any;
    }
}
Exemple #7
0
    void tv_cast(CastResult* result, caValue* value, Type* type, bool checkOnly)
    {
        if (!is_list(value)) {
            result->success = false;
            return;
        }

        int sourceLength = list_length(value);

        // If the requested type doesn't have a specific size restriction, then
        // the input data is fine as-is.
        if (!list_type_has_specific_size(&type->parameter)) {
            if (!checkOnly)
                value->value_type = type;
            return;
        }

        List& destTypes = *List::checkCast(list_get_type_list_from_type(type));

        // Check for correct number of elements.
        if (sourceLength != destTypes.length()) {
            result->success = false;
            return;
        }

        if (!checkOnly) {
            INCREMENT_STAT(Touch_ListCast);
            list_touch(value);
            value->value_type = type;
        }

        for (int i=0; i < sourceLength; i++) {
            caValue* sourceElement = list_get(value, i);
            Type* expectedType = as_type(destTypes[i]);

            INCREMENT_STAT(Cast_ListCastElement);
            cast(result, sourceElement, expectedType, checkOnly);

            if (!result->success)
                return;
        }
    }