// checkForNonBoolCondition checks if the condition is of a boolean type, and if not, adds an error to the typechecker
func checkForNonBoolCondition(condition interfaces.Expr, typeCheckArgs interfaces.TypeCheckArgs) {
	typeOfCondition := condition.TypeCheck(typeCheckArgs)

	if typeOfCondition != expr.NewBoolType() && typeOfCondition != expr.NewUnknownType() {
		typeCheckArgs.TypeChecker().AddEncounteredError(errors.NewNonBooleanConditionError(condition, typeOfCondition))
	}
}
// checkIfOperandHasExpectedType checks that an operand's actual type matches it expected type, and if not adds an error to the typechecker
func checkIfOperandHasExpectedType(expr interfaces.Expr, expectedTypes []interfaces.ValueType, typeCheckArgs interfaces.TypeCheckArgs) interfaces.ValueType {
	actualType := expr.TypeCheck(typeCheckArgs)

	if actualType == NewUnknownType() {
		return NewUnknownType()
	}

	if !typeIsInExpectedTypes(actualType, expectedTypes) {
		typeCheckArgs.TypeChecker().AddEncounteredError(errors.NewOperandWithUnexpectedTypeError(expr, expectedTypes, actualType))
	}

	return actualType
}
func (suite *TypeCheckerTestSuite) typeCheckPassedExprAndReturnErrors(expr interfaces.Expr) []error {
	expr.TypeCheck(suite.typeCheckArgs)
	return suite.typeCheckArgs.TypeChecker().EncounteredErrors()
}