2011-07-08 02:16:46 -07:00
use std ;
use rustc ;
2011-05-20 21:06:05 -04:00
import std ::fs ;
import std ::getopts ;
import std ::getopts ::optopt ;
import std ::getopts ::opt_present ;
import std ::getopts ::opt_str ;
2011-07-14 17:10:47 -07:00
import std ::ioivec ;
import std ::ioivec ::stdout ;
2011-05-20 21:06:05 -04:00
import std ::vec ;
2011-07-08 02:16:46 -07:00
import std ::ivec ;
import std ::str ;
2011-07-10 16:03:01 -07:00
import std ::uint ;
2011-07-12 11:49:04 -07:00
import std ::option ;
2011-05-20 21:06:05 -04:00
2011-07-08 02:16:46 -07:00
import rustc ::syntax ::ast ;
2011-07-10 16:03:01 -07:00
import rustc ::syntax ::fold ;
import rustc ::syntax ::walk ;
import rustc ::syntax ::codemap ;
2011-07-12 11:49:04 -07:00
import rustc ::syntax ::parse ::parser ;
2011-07-10 16:03:01 -07:00
import rustc ::syntax ::print ::pprust ;
2011-07-12 11:49:04 -07:00
/*
// Imports for "the rest of driver::compile_input"
2011-07-08 02:16:46 -07:00
import driver = rustc ::driver ::rustc ; // see https://github.com/graydon/rust/issues/624
2011-07-10 16:03:01 -07:00
import rustc ::back ::link ;
import rustc ::driver ::rustc ::time ;
2011-07-08 02:16:46 -07:00
import rustc ::driver ::session ;
2011-05-20 21:06:05 -04:00
2011-07-10 16:03:01 -07:00
import rustc ::metadata ::creader ;
import rustc ::metadata ::cstore ;
import rustc ::syntax ::parse ::parser ;
import rustc ::syntax ::parse ::token ;
import rustc ::front ;
import rustc ::front ::attr ;
import rustc ::middle ;
import rustc ::middle ::trans ;
import rustc ::middle ::resolve ;
import rustc ::middle ::ty ;
import rustc ::middle ::typeck ;
import rustc ::middle ::tstate ::ck ;
import rustc ::syntax ::print ::pp ;
import rustc ::util ::ppaux ;
import rustc ::lib ::llvm ;
* /
2011-05-20 21:06:05 -04:00
2011-07-12 11:49:04 -07:00
fn read_whole_file ( & str filename ) -> str {
2011-07-14 17:10:47 -07:00
str ::unsafe_from_bytes_ivec ( ioivec ::file_reader ( filename ) . read_whole_stream ( ) )
2011-07-12 11:49:04 -07:00
}
2011-07-13 17:12:38 -07:00
fn write_file ( & str filename , & str content ) {
2011-07-25 14:04:38 -07:00
ioivec ::file_writer ( filename , ~ [ ioivec ::create ,
ioivec ::truncate ] ) . write_str ( content ) ;
2011-07-13 17:12:38 -07:00
}
2011-07-10 16:03:01 -07:00
fn file_contains ( & str filename , & str needle ) -> bool {
2011-07-12 11:49:04 -07:00
auto contents = read_whole_file ( filename ) ;
2011-07-10 16:03:01 -07:00
ret str ::find ( contents , needle ) ! = - 1 ;
}
2011-07-12 11:49:04 -07:00
fn contains ( & str haystack , & str needle ) -> bool { str ::find ( haystack , needle ) ! = - 1 }
2011-07-10 16:03:01 -07:00
fn find_rust_files ( & mutable str [ ] files , str path ) {
if ( str ::ends_with ( path , " .rs " ) ) {
if ( file_contains ( path , " xfail-stage1 " ) ) {
//log_err "Skipping " + path + " because it is marked as xfail-stage1";
} else {
files + = ~ [ path ] ;
}
} else if ( fs ::file_is_dir ( path ) & & str ::find ( path , " compile-fail " ) = = - 1 ) {
for ( str p in fs ::list_dir ( path ) ) {
find_rust_files ( files , p ) ;
}
}
}
2011-07-12 11:49:04 -07:00
fn safe_to_steal ( ast ::expr_ e ) -> bool {
alt ( e ) {
// pretty-printer precedence issues -- https://github.com/graydon/rust/issues/670
case ( ast ::expr_unary ( _ , _ ) ) { false }
case ( ast ::expr_lit ( ? lit ) ) {
alt ( lit . node ) {
case ( ast ::lit_str ( _ , _ ) ) { true }
case ( ast ::lit_char ( _ ) ) { true }
case ( ast ::lit_int ( _ ) ) { false }
case ( ast ::lit_uint ( _ ) ) { false }
case ( ast ::lit_mach_int ( _ , _ ) ) { false }
case ( ast ::lit_float ( _ ) ) { false }
case ( ast ::lit_mach_float ( _ , _ ) ) { false }
case ( ast ::lit_nil ) { true }
case ( ast ::lit_bool ( _ ) ) { true }
}
}
case ( ast ::expr_cast ( _ , _ ) ) { false }
case ( ast ::expr_send ( _ , _ ) ) { false }
case ( ast ::expr_recv ( _ , _ ) ) { false }
case ( ast ::expr_assert ( _ ) ) { false }
case ( ast ::expr_binary ( _ , _ , _ ) ) { false }
case ( ast ::expr_assign ( _ , _ ) ) { false }
case ( ast ::expr_assign_op ( _ , _ , _ ) ) { false }
2011-07-12 12:07:03 -07:00
// https://github.com/graydon/rust/issues/676
2011-07-12 11:49:04 -07:00
case ( ast ::expr_ret ( option ::none ) ) { false }
case ( ast ::expr_put ( option ::none ) ) { false }
case ( _ ) { true }
}
}
2011-07-10 16:03:01 -07:00
fn steal_exprs ( & ast ::crate crate ) -> ast ::expr [ ] {
let @ mutable ast ::expr [ ] exprs = @ mutable ~ [ ] ;
2011-07-12 11:49:04 -07:00
// "Stash" is not type-parameterized because of the need for safe_to_steal
fn stash_expr ( @ mutable ast ::expr [ ] es , & @ ast ::expr e ) { if ( safe_to_steal ( e . node ) ) { * es + = ~ [ * e ] ; } else { /* now my indices are wrong :( */ } }
2011-07-10 16:03:01 -07:00
auto v = rec ( visit_expr_pre = bind stash_expr ( exprs , _ ) with walk ::default_visitor ( ) ) ;
walk ::walk_crate ( v , crate ) ;
* exprs
}
// https://github.com/graydon/rust/issues/652
fn safe_to_replace ( ast ::expr_ e ) -> bool {
alt ( e ) {
case ( ast ::expr_if ( _ , _ , _ ) ) { false }
case ( ast ::expr_block ( _ ) ) { false }
case ( _ ) { true }
}
}
// Replace the |i|th expr (in fold order) of |crate| with |newexpr|.
fn replace_expr_in_crate ( & ast ::crate crate , uint i , ast ::expr_ newexpr ) -> ast ::crate {
let @ mutable uint j = @ mutable 0 u ;
fn fold_expr_rep ( @ mutable uint j_ , uint i_ , & ast ::expr_ newexpr_ , & ast ::expr_ original , fold ::ast_fold fld ) -> ast ::expr_ {
* j_ + = 1 u ;
if ( i_ + 1 u = = * j_ & & safe_to_replace ( original ) ) {
newexpr_
} else {
fold ::noop_fold_expr ( original , fld )
}
}
auto afp = rec ( fold_expr = bind fold_expr_rep ( j , i , newexpr , _ , _ ) with * fold ::default_ast_fold ( ) ) ;
auto af = fold ::make_fold ( afp ) ;
let @ ast ::crate crate2 = @ af . fold_crate ( crate ) ;
fold ::dummy_out ( af ) ; // work around a leak (https://github.com/graydon/rust/issues/651)
* crate2
}
iter under ( uint n ) -> uint { let uint i = 0 u ; while ( i < n ) { put i ; i + = 1 u ; } }
2011-07-14 17:10:47 -07:00
fn devnull ( ) -> ioivec ::writer { std ::ioivec ::string_writer ( ) . get_writer ( ) }
2011-07-10 16:03:01 -07:00
2011-07-14 17:10:47 -07:00
fn as_str ( fn ( ioivec ::writer ) f ) -> str { auto w = std ::ioivec ::string_writer ( ) ; f ( w . get_writer ( ) ) ; w . get_str ( ) }
2011-07-12 11:49:04 -07:00
2011-07-25 14:04:38 -07:00
/*
2011-07-12 11:49:04 -07:00
fn pp_variants ( & ast ::crate crate , & codemap ::codemap cmap , & str filename ) {
2011-07-10 16:03:01 -07:00
auto exprs = steal_exprs ( crate ) ;
auto exprsL = ivec ::len ( exprs ) ;
if ( exprsL < 100 u ) {
for each ( uint i in under ( uint ::min ( exprsL , 20 u ) ) ) {
log_err " Replacing... " + pprust ::expr_to_str ( @ exprs . ( i ) ) ;
for each ( uint j in under ( uint ::min ( exprsL , 5 u ) ) ) {
log_err " With... " + pprust ::expr_to_str ( @ exprs . ( j ) ) ;
auto crate2 = @ replace_expr_in_crate ( crate , i , exprs . ( j ) . node ) ;
2011-07-12 11:49:04 -07:00
check_roundtrip ( crate2 , cmap , filename + " .4.rs " ) ;
2011-07-10 16:03:01 -07:00
}
2011-05-20 21:06:05 -04:00
}
}
2011-07-08 02:16:46 -07:00
}
2011-07-25 14:04:38 -07:00
* /
2011-05-20 21:06:05 -04:00
2011-07-25 14:04:38 -07:00
fn check_roundtrip ( @ ast ::crate cr1 , & codemap ::codemap cm1 , & str filename , & str str1 ) {
auto str2 = as_str ( bind pprust ::print_crate ( cm1 , cr1 , filename ,
ioivec ::string_reader ( str1 ) , _ ,
pprust ::no_ann ( ) ) ) ;
2011-07-12 11:49:04 -07:00
if ( true
2011-07-25 14:04:38 -07:00
& & ! contains ( str2 , " ][] " ) // https://github.com/graydon/rust/issues/669
& & ! contains ( str2 , " ][mutable] " ) // https://github.com/graydon/rust/issues/669
& & ! contains ( str2 , " ][mutable ] " ) // https://github.com/graydon/rust/issues/669
& & ! contains ( str2 , " self " ) // crazy rules enforced by parser rather than typechecker?
& & ! contains ( str2 , " spawn " ) // more precedence issues
& & ! contains ( str2 , " bind " ) // more precedence issues?
2011-07-12 11:49:04 -07:00
) {
2011-07-25 14:04:38 -07:00
auto cm2 = codemap ::new_codemap ( ) ;
auto cr2 = parser ::parse_crate_from_source_str ( filename , str2 , ~ [ ] , cm2 ) ;
2011-07-12 11:49:04 -07:00
// should compare crates at this point, but it's easier to compare strings
2011-07-25 14:04:38 -07:00
auto str3 = as_str ( bind pprust ::print_crate ( cm2 , cr2 , filename , ioivec ::string_reader ( str2 ) ,
_ , pprust ::no_ann ( ) ) ) ;
2011-07-12 11:49:04 -07:00
if ( ! str ::is_ascii ( str3 ) ) {
2011-07-13 17:12:38 -07:00
log_err " Non-ASCII in " + filename ; // why does non-ASCII work correctly with "rustc --pretty normal" but not here???
2011-07-25 14:04:38 -07:00
} else if ( str2 ! = str3 ) {
write_file ( " round-trip-a.rs " , str2 ) ;
write_file ( " round-trip-b.rs " , str3 ) ;
2011-07-13 17:12:38 -07:00
std ::run ::run_program ( " kdiff3 " , [ " round-trip-a.rs " , " round-trip-b.rs " ] ) ;
fail " Mismatch " ;
2011-07-12 11:49:04 -07:00
}
}
}
2011-07-08 02:16:46 -07:00
fn main ( vec [ str ] args ) {
2011-07-13 17:12:38 -07:00
if ( vec ::len ( args ) ! = 2 u ) {
log_err #fmt ( " usage: %s <testdir> " , args . ( 0 ) ) ;
ret ;
}
2011-07-08 02:16:46 -07:00
auto files = ~ [ ] ;
2011-07-13 17:12:38 -07:00
auto root = args . ( 1 ) ;
2011-07-10 16:03:01 -07:00
find_rust_files ( files , root ) ; // not using time here because that currently screws with passing-a-mutable-array
2011-07-13 17:12:38 -07:00
log_err #fmt ( " %u files " , ivec ::len ( files ) ) ;
2011-05-20 21:06:05 -04:00
2011-07-08 02:16:46 -07:00
for ( str file in files ) {
2011-07-10 16:03:01 -07:00
log_err " === " + file + " === " ;
2011-07-25 14:04:38 -07:00
auto cm1 = codemap ::new_codemap ( ) ;
auto str1 = read_whole_file ( file ) ;
auto cr1 = parser ::parse_crate_from_source_str ( file , str1 , ~ [ ] , cm1 ) ;
if ( ! contains ( str1 , " #macro " ) // https://github.com/graydon/rust/issues/671
2011-07-12 11:49:04 -07:00
& & ! str ::ends_with ( file , " block-expr-precedence.rs " ) // https://github.com/graydon/rust/issues/674
& & ! str ::ends_with ( file , " syntax-extension-fmt.rs " ) // an issue where -2147483648 gains an extra negative sign each time through, which i can't reproduce using "rustc --pretty normal"???
) {
2011-07-25 14:04:38 -07:00
check_roundtrip ( cr1 , cm1 , file , str1 ) ;
2011-07-12 11:49:04 -07:00
}
//pprust::print_crate(cm, crate, file, devnull(), pprust::no_ann());
2011-07-12 12:07:03 -07:00
// Currently hits https://github.com/graydon/rust/issues/675
2011-07-12 11:49:04 -07:00
//pp_variants(*crate, cm, file);
2011-07-08 02:16:46 -07:00
}
2011-05-20 21:06:05 -04:00
}
// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End: