Abstract Interpretation of Prolog Programs