11use std:: {
2- error:: Error ,
32fs:: File ,
43io:: Write ,
54process:: { Command , Stdio } ,
65} ;
76
8- use crate :: constants:: TEMP_FILE ;
9-
107use crate :: config:: Config ;
118
129pub enum StatementType {
@@ -41,6 +38,7 @@ pub struct Program {
4138pub functions : Vec < String > ,
4239pub last_push : StatementType ,
4340pub argv : String ,
41+ pub ident : u32 ,
4442}
4543
4644impl Default for Program {
@@ -52,17 +50,40 @@ impl Default for Program {
5250defines : Default :: default ( ) ,
5351argv : Default :: default ( ) ,
5452last_push : Default :: default ( ) ,
53+ ident : rand:: random ( ) ,
5554}
5655}
5756}
5857
58+ impl Drop for Program {
59+ fn drop ( & mut self ) {
60+ let _ = std:: fs:: remove_file ( self . executable_file_name ( ) ) ;
61+ let _ = std:: fs:: remove_file ( self . source_file_name ( ) ) ;
62+ }
63+ }
64+
5965impl Program {
6066pub fn new ( ) -> Self {
67+ let ident = rand:: random :: < u32 > ( ) ;
6168Self {
62- ..Default :: default ( )
69+ includes : Default :: default ( ) ,
70+ functions : Default :: default ( ) ,
71+ statements : Default :: default ( ) ,
72+ defines : Default :: default ( ) ,
73+ argv : Default :: default ( ) ,
74+ last_push : Default :: default ( ) ,
75+ ident,
6376}
6477}
6578
79+ pub fn source_file_name ( & self ) -> String {
80+ format ! ( "{}.c" , self . ident. to_string( ) )
81+ }
82+
83+ pub fn executable_file_name ( & self ) -> String {
84+ format ! ( "./{}.out" , self . ident. to_string( ) )
85+ }
86+
6687pub fn push ( & mut self , stmt : & str , stmt_type : StatementType ) {
6788match stmt_type {
6889StatementType :: Def => self . defines . push ( String :: from ( stmt) ) ,
@@ -152,23 +173,22 @@ int main(int argc, char **argv) {{
152173let source = self . generate_source_code ( false ) ;
153174
154175// create temp file
155- let mut temp_source_file = match File :: create ( TEMP_FILE ) {
156- Err ( why) => panic ! ( "Could not create temp file [{}]" , why. description( ) ) ,
157- Ok ( file) => file,
158- } ;
176+ let mut temp_source_file =
177+ File :: create ( self . source_file_name ( ) ) . map_err ( |err| err. to_string ( ) ) ?;
159178
160179// write source to a temp file
161- match temp_source_file. write_all ( source. as_bytes ( ) ) {
162- Err ( why) => panic ! ( "Could not write to temp file: [{}]" , why. description( ) ) ,
163- Ok ( _) => ( ) ,
164- }
180+ let _ = temp_source_file
181+ . write_all ( source. as_bytes ( ) )
182+ . map_err ( |err| err. to_string ( ) ) ?;
165183
166184// spawn a compiler
167185let cc = config. cc . clone ( ) ;
168- let compile_handle = match Command :: new ( cc) . arg ( TEMP_FILE ) . output ( ) {
169- Err ( why) => panic ! ( "Failed spawn compiler: {}" , why. description( ) ) ,
170- Ok ( handle) => handle,
171- } ;
186+ let compile_handle = Command :: new ( cc)
187+ . arg ( self . source_file_name ( ) )
188+ . arg ( "-o" )
189+ . arg ( self . executable_file_name ( ) )
190+ . output ( )
191+ . map_err ( |e| e. to_string ( ) ) ?;
172192
173193let compile_stderr = String :: from_utf8_lossy ( & compile_handle. stderr ) ;
174194if compile_stderr. len ( ) > 0 && compile_stderr. contains ( "error:" ) {
@@ -177,21 +197,14 @@ int main(int argc, char **argv) {{
177197
178198// execute the binary
179199let args: Vec < & str > = self . argv . split_whitespace ( ) . collect ( ) ;
180- let child = match Command :: new ( String :: from ( "./a.out" ) )
200+ let child = Command :: new ( self . executable_file_name ( ) )
181201. args ( args)
182202. stdout ( Stdio :: piped ( ) )
183203. stderr ( Stdio :: piped ( ) )
184204. spawn ( )
185- {
186- Ok ( child) => child,
187- Err ( why) => panic ! ( "Failed to Execute: {}" , why. description( ) ) ,
188- } ;
205+ . map_err ( |e| e. to_string ( ) ) ?;
189206
190- let handle = match child. wait_with_output ( ) {
191- Ok ( handle) => handle,
192- Err ( why) => panic ! ( "Failed to Execute: {}" , why. description( ) ) ,
193- } ;
194- Ok ( handle)
207+ child. wait_with_output ( ) . map_err ( |e| e. to_string ( ) )
195208}
196209}
197210
@@ -249,10 +262,11 @@ mod tests {
249262fn argv ( ) {
250263let ( mut p, c) = create_dummy_program ( ) ;
251264p. push (
252- r#"for (int i = 0; i < argc; i++) {printf("argv[%d] = %s\n", i, argv[i]);}"# ,
265+ r#"for (int i = 0; i < argc; i++) { printf("argv[%d] = %s\n", i, argv[i]); }"# ,
253266StatementType :: Stmt ,
254267) ;
255268let handle = p. run ( & c) ;
269+
256270assert ! ( String :: from_utf8_lossy( & handle. unwrap( ) . stdout) . contains( "argv[0]" ) ) ;
257271}
258272
0 commit comments