corto_int16 corto_valueExpr_getTypeForBinary( corto_type leftType, corto_bool t1ByRef, corto_type rightType, corto_bool t2ByRef, corto_operatorKind _operator, corto_type *operandType, corto_type *resultType) { corto_type castType = NULL; corto_bool equal = FALSE; corto_assert(operandType != NULL, "NULL provided for out-parameter operandType"); corto_assert(resultType != NULL, "NULL provided for out-parameter resultType"); /* If operator is condition result type is a boolean */ if (corto_valueExpr_isOperatorConditional(_operator)) { *resultType = corto_type(corto_bool_o); } /* Get leftType and rightType */ if (!(leftType = corto_valueExpr_getType(leftType, NULL, FALSE))) { goto error; } if (!(rightType = corto_valueExpr_getType(rightType, leftType, t1ByRef))) { goto error; } if (!leftType) { leftType = rightType; } /* If objects are not scoped, verify whether they're equal */ if (!corto_checkAttr(leftType, CORTO_ATTR_NAMED) && !corto_checkAttr(rightType, CORTO_ATTR_NAMED)) { if (corto_compare(leftType, rightType) == CORTO_EQ) { equal = TRUE; } } else { equal = leftType == rightType; } if (_operator == CORTO_DIV) { castType = corto_type(corto_float64_o); } else if (!equal) { /* Can only cast between primitive types */ if ((leftType->kind == CORTO_PRIMITIVE ) && (rightType->kind == CORTO_PRIMITIVE)) { corto_primitive ltype = corto_primitive(leftType), rtype = corto_primitive(rightType); corto_int8 lscore, rscore; corto_int8 lCastScore, rCastScore; lscore = corto_valueExpr_getTypeScore(ltype); rscore = corto_valueExpr_getTypeScore(rtype); lCastScore = corto_valueExpr_getCastScore(ltype); rCastScore = corto_valueExpr_getCastScore(rtype); /* If expression is an assignment, always take type of lvalue. * Otherwise determine based on expressibility score which type to * cast to. */ if (corto_valueExpr_isOperatorAssignment(_operator)) { if (lCastScore == rCastScore) { if (ltype->width != rtype->width) { castType = leftType; } } else { castType = leftType; } } else { if (lCastScore == rCastScore) { if (ltype->width == rtype->width) { /* If width and kind are equal, no conversion is required. */ if (lscore > rscore) { *operandType = leftType; } else if (lscore < rscore) { *operandType = rightType; } } else { /* If lvalue has a larger width than rvalue, cast rvalue to leftType (and vice versa) */ if (ltype->width > rtype->width) { castType = leftType; } else { castType = rightType; } } /* If kinds do not match figure a cast is potentially needed. Figure out which type to cast to */ } else { if (lscore > rscore) { castType = leftType; } else { castType = rightType; } } } } else if (leftType->reference && rightType->reference) { castType = NULL; /* Check if types are compatible */ } else if ((rightType->reference || (t2ByRef)) && !leftType->reference) { if (corto_type_castable(leftType, corto_object_o)) { castType = leftType; } } else { corto_seterr("cannot cast from '%s' to '%s'", corto_fullpath(NULL, leftType), corto_fullpath(NULL, rightType)); goto error; } } else if ((rightType->reference || (t2ByRef)) && !leftType->reference) { if (corto_type_castable(leftType, corto_object_o)) { castType = leftType; } } if (!castType) { castType = leftType; } if (castType) { *operandType = castType; } if (!*resultType) { *resultType = *operandType; } return 0; error: return -1; }
corto_equalityKind _md_DocCompare(md_Doc dst, md_Doc src) { return corto_compare(dst, src); }