caValue* tv_get_field(caValue* value, const char* fieldName) { int index = list_find_field_index_by_name(value->value_type, fieldName); if (index < 0) return NULL; return list_get(value, index); }
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; }
bool branch_state_type_is_out_of_date(Branch* branch) { // Alloc an array that tracks, for each field in the existing stateType, // whether we have found a corresponding term for that field. bool* typeFieldFound = NULL; int existingFieldCount = 0; if (branch->stateType != NULL) { existingFieldCount = compound_type_get_field_count(branch->stateType); size_t size = sizeof(bool) * existingFieldCount; typeFieldFound = (bool*) malloc(size); memset(typeFieldFound, 0, size); } // Walk through every term and check whether every unpack_state call is already // mentioned in the state type. for (int i=0; i < branch->length(); i++) { Term* term = branch->get(i); if (term == NULL) continue; if (term->function != FUNCS.unpack_state) continue; // Found an unpack_state call Term* identifyingTerm = term->input(1); // If the branch doesn't yet have a stateType then that's an update. if (branch->stateType == NULL) goto return_true; // Look for the field name int fieldIndex = list_find_field_index_by_name(branch->stateType, unique_name(identifyingTerm)); // If the name isn't found then that's an update if (fieldIndex == -1) goto return_true; // If the type doesn't match then that's an update if (compound_type_get_field_type(branch->stateType, fieldIndex) != declared_type(term)) goto return_true; // Record this field index as 'found' typeFieldFound[fieldIndex] = true; } // If there were any fields in the type that weren't found in the branch, then // that's an update. if (typeFieldFound != NULL) { for (int i=0; i < existingFieldCount; i++) { if (!typeFieldFound[i]) goto return_true; } } // No reason to update, return false. free(typeFieldFound); return false; return_true: free(typeFieldFound); return true; }