11import os
22import sys
33from sys import platform
4+ import ast
45from ast import *
56
67################################################################################
910
1011indent_amount = 0
1112
13+ sed = 'sed'
14+
1215def indent_stmt ():
1316 return " " * indent_amount
1417
@@ -232,6 +235,29 @@ def repr_Subscript(self):
232235Subscript .__repr__ = repr_Subscript
233236
234237
238+ def str_FunctionDef (self ):
239+ if isinstance (self .args , ast .arguments ):
240+ params = ',' .join ([a .arg + ':' + str (a .annotation ) for a in self .args .args ])
241+ else :
242+ params = ',' .join ([x + ':' + str (t ) for (x ,t ) in self .args ])
243+ indent ()
244+ if isinstance (self .body , list ):
245+ body = '' .join ([str (s ) for s in self .body ])
246+ elif isinstance (self .body , dict ):
247+ body = ''
248+ for (l ,ss ) in self .body .items ():
249+ body += l + ':\n '
250+ indent ()
251+ body += '' .join ([str (s ) for s in ss ])
252+ dedent ()
253+ dedent ()
254+ return indent_stmt () + 'def ' + self .name + '(' + params + '):\n ' + body
255+ def repr_FunctionDef (self ):
256+ return 'FunctionDef(' + self .name + ',' + repr (self .args ) + ',' + \
257+ repr (self .body ) + ')'
258+ FunctionDef .__str__ = str_FunctionDef
259+ FunctionDef .__repr__ = repr_FunctionDef
260+
235261################################################################################
236262# __eq__ and __hash__ for classes in the ast module
237263################################################################################
@@ -300,6 +326,17 @@ def __str__(self):
300326
301327 def __repr__ (self ):
302328 return 'CProgram(' + repr (self .body ) + ')'
329+
330+ class CProgramDefs :
331+ __match_args__ = ("defs" ,)
332+ def __init__ (self , defs ):
333+ self .defs = defs
334+
335+ def __str__ (self ):
336+ return '\n ' .join ([str (d ) for d in self .defs ]) + '\n '
337+
338+ def __repr__ (self ):
339+ return 'CProgramDefs(' + repr (self .defs ) + ')'
303340
304341class Goto (stmt ):
305342 __match_args__ = ("label" ,)
@@ -352,16 +389,54 @@ def __str__(self):
352389 def __repr__ (self ):
353390 return 'GlobalValue(' + repr (self .name ) + ')'
354391
392+ class Bottom :
393+ def __eq__ (self , other ):
394+ return isinstance (other , Bottom )
395+
355396class TupleType :
356397 __match_args__ = ("types" ,)
357398 def __init__ (self , types ):
358399 self .types = types
359400 def __str__ (self ):
360- return 'tuple ' + str (self .types )
401+ return '( ' + ',' . join ([ str (p ) for p in self .types ]) + ')'
361402 def __repr__ (self ):
362403 return 'TupleType(' + repr (self .types ) + ')'
404+ def __eq__ (self , other ):
405+ if not isinstance (other , TupleType ):
406+ return False
407+ result = True
408+ for (t1 , t2 ) in zip (self .types , other .types ):
409+ result = result and t1 == t2
410+ return result
411+
412+ class FunctionType :
413+ __match_args__ = ("param_types" , "ret_type" )
414+ def __init__ (self , param_types , ret_type ):
415+ self .param_types = param_types
416+ self .ret_type = ret_type
417+ def __str__ (self ):
418+ return '(' + ',' .join ([str (p ) for p in self .param_types ]) + ')' \
419+ + ' -> ' + str (self .ret_type )
420+ def __repr__ (self ):
421+ return 'FunctionType(' + repr (self .param_types ) + ',' \
422+ + repr (self .ret_type ) + ')'
423+ def __eq__ (self , other ):
424+ if not isinstance (other , FunctionType ):
425+ return False
426+ result = True
427+ for (t1 , t2 ) in zip (self .param_types , other .param_types ):
428+ result = result and t1 == t2
429+ return result and self .ret_type == other .ret_type
430+
431+ class FunRef :
432+ __match_args__ = ("name" ,)
433+ def __init__ (self , name ):
434+ self .name = name
435+ def __str__ (self ):
436+ return self .name + '(%rip)'
437+ def __repr__ (self ):
438+ return 'FunRef(' + self .name + ')'
363439
364-
365440################################################################################
366441# Miscellaneous Auxiliary Functions
367442################################################################################
@@ -425,8 +500,8 @@ def test_pass(passname, interp, program_root, ast,
425500 interp (ast )
426501 sys .stdin = stdin
427502 sys .stdout = stdout
428- os .system (" sed -i '$a\\ ' " + program_root + '.out' )
429- os .system (" sed -i '$a\\ ' " + program_root + '.golden' )
503+ os .system (sed + " -i '$a\\ ' " + program_root + '.out' )
504+ os .system (sed + " -i '$a\\ ' " + program_root + '.golden' )
430505 result = os .system ('diff ' + output_file + ' ' + program_root + '.golden' )
431506 if result == 0 :
432507 trace ('compiler ' + compiler_name + ' success on pass ' + passname \
@@ -438,7 +513,9 @@ def test_pass(passname, interp, program_root, ast,
438513 return 0
439514
440515
441- def compile_and_test (compiler , compiler_name , type_check_P , interp_P , interp_C ,
516+ def compile_and_test (compiler , compiler_name ,
517+ type_check_P , interp_P ,
518+ type_check_C , interp_C ,
442519 program_filename ):
443520 total_passes = 0
444521 successful_passes = 0
@@ -448,7 +525,11 @@ def compile_and_test(compiler, compiler_name, type_check_P, interp_P, interp_C,
448525 with open (program_filename ) as source :
449526 program = parse (source .read ())
450527
451- trace ('\n **********\n type check \n **********\n ' )
528+ trace ('\n ***************\n source program \n ***************\n ' )
529+ trace (program )
530+ trace ('' )
531+
532+ trace ('\n ***************\n type check \n ***************\n ' )
452533 type_check_P (program )
453534
454535 if hasattr (compiler , 'shrink' ):
@@ -459,6 +540,26 @@ def compile_and_test(compiler, compiler_name, type_check_P, interp_P, interp_C,
459540 total_passes += 1
460541 successful_passes += \
461542 test_pass ('shrink' , interp_P , program_root , program , compiler_name )
543+
544+ if hasattr (compiler , 'reveal_functions' ):
545+ trace ('\n **********\n reveal functions \n **********\n ' )
546+ type_check_P (program )
547+ program = compiler .reveal_functions (program )
548+ trace (program )
549+ total_passes += 1
550+ successful_passes += \
551+ test_pass ('reveal functions' , interp_P , program_root , program ,
552+ compiler_name )
553+
554+ if hasattr (compiler , 'limit_functions' ):
555+ trace ('\n **********\n limit functions \n **********\n ' )
556+ type_check_P (program )
557+ program = compiler .limit_functions (program )
558+ trace (program )
559+ total_passes += 1
560+ successful_passes += \
561+ test_pass ('limit functions' , interp_P , program_root , program ,
562+ compiler_name )
462563
463564 if hasattr (compiler , 'expose_allocation' ):
464565 trace ('\n **********\n expose allocation \n **********\n ' )
@@ -470,7 +571,7 @@ def compile_and_test(compiler, compiler_name, type_check_P, interp_P, interp_C,
470571 test_pass ('expose allocation' , interp_P , program_root , program ,
471572 compiler_name )
472573
473- trace ('\n **********\n remove \n **********\n ' )
574+ trace ('\n **********\n remove complex operands \n **********\n ' )
474575 program = compiler .remove_complex_operands (program )
475576 trace (program )
476577 trace ("" )
@@ -480,13 +581,17 @@ def compile_and_test(compiler, compiler_name, type_check_P, interp_P, interp_C,
480581 compiler_name )
481582
482583 if hasattr (compiler , 'explicate_control' ):
483- trace ('\n **********\n explicate \n **********\n ' )
584+ trace ('\n **********\n explicate control \n **********\n ' )
484585 program = compiler .explicate_control (program )
485586 trace (program )
486587 total_passes += 1
487588 successful_passes += \
488589 test_pass ('explicate control' , interp_C , program_root , program ,
489590 compiler_name )
591+
592+ if type_check_C :
593+ trace ('\n **********\n type check C \n **********\n ' )
594+ type_check_C (program )
490595
491596 trace ('\n **********\n select \n **********\n ' )
492597 pseudo_x86 = compiler .select_instructions (program )
@@ -546,8 +651,8 @@ def compile_and_test(compiler, compiler_name, type_check_P, interp_P, interp_C,
546651 output_file = program_root + '.out'
547652 os .system ('./a.out < ' + input_file + ' > ' + output_file )
548653
549- os .system (" sed -i '$a\\ ' " + program_root + '.out' )
550- os .system (" sed -i '$a\\ ' " + program_root + '.golden' )
654+ os .system (sed + " -i '$a\\ ' " + program_root + '.out' )
655+ os .system (sed = " -i '$a\\ ' " + program_root + '.golden' )
551656 result = os .system ('diff ' + program_root + '.out ' \
552657 + program_root + '.golden' )
553658 if result == 0 :
@@ -566,7 +671,8 @@ def trace_ast_and_concrete(ast):
566671 trace (repr (ast ))
567672
568673# This function compiles the program without any testing
569- def compile (compiler , compiler_name , type_check_P , program_filename ):
674+ def compile (compiler , compiler_name , type_check_P , type_check_C ,
675+ program_filename ):
570676 program_root = program_filename .split ('.' )[0 ]
571677 with open (program_filename ) as source :
572678 program = parse (source .read ())
@@ -579,6 +685,17 @@ def compile(compiler, compiler_name, type_check_P, program_filename):
579685 trace ('\n **********\n shrink \n **********\n ' )
580686 program = compiler .shrink (program )
581687 trace_ast_and_concrete (program )
688+
689+ if hasattr (compiler , 'reveal_functions' ):
690+ trace ('\n **********\n reveal functions \n **********\n ' )
691+ program = compiler .reveal_functions (program )
692+ trace_ast_and_concrete (program )
693+
694+ if hasattr (compiler , 'expose_allocation' ):
695+ trace ('\n **********\n expose allocation \n **********\n ' )
696+ type_check_P (program )
697+ program = compiler .expose_allocation (program )
698+ trace_ast_and_concrete (program )
582699
583700 trace ('\n **********\n remove \n **********\n ' )
584701 program = compiler .remove_complex_operands (program )
@@ -588,6 +705,9 @@ def compile(compiler, compiler_name, type_check_P, program_filename):
588705 trace ('\n **********\n explicate \n **********\n ' )
589706 program = compiler .explicate_control (program )
590707 trace_ast_and_concrete (program )
708+
709+ if type_check_C :
710+ type_check_C (program )
591711
592712 trace ('\n **********\n select \n **********\n ' )
593713 pseudo_x86 = compiler .select_instructions (program )
@@ -617,18 +737,19 @@ def compile(compiler, compiler_name, type_check_P, program_filename):
617737# checking that the resulting programs produce output that matches the
618738# golden file.
619739def run_one_test (test , lang , compiler , compiler_name ,
620- type_check_P , interp_P , interp_C ):
740+ type_check_P , interp_P , type_check_C , interp_C ):
621741 test_root = test .split ('.' )[0 ]
622742 test_name = test_root .split ('/' )[- 1 ]
623743 return compile_and_test (compiler , compiler_name , type_check_P ,
624- interp_P , interp_C , test )
744+ interp_P , type_check_C , interp_C , test )
625745
626746# Given the name of a language, a compiler, the compiler's name, a
627747# type checker and interpreter for the language, and an interpreter
628748# for the C intermediate language, test the compiler on all the tests
629749# in the directory of for the given language, i.e., all the
630750# python files in ./tests/<language>.
631- def run_tests (lang , compiler , compiler_name , type_check_P , interp_P , interp_C ):
751+ def run_tests (lang , compiler , compiler_name , type_check_P , interp_P ,
752+ type_check_C , interp_C ):
632753 # Collect all the test programs for this language.
633754 homedir = os .getcwd ()
634755 directory = homedir + '/tests/' + lang + '/'
@@ -647,7 +768,7 @@ def run_tests(lang, compiler, compiler_name, type_check_P, interp_P, interp_C):
647768 for test in tests :
648769 (succ_passes , tot_passes , succ_test ) = \
649770 run_one_test (test , lang , compiler , compiler_name ,
650- type_check_P , interp_P , interp_C )
771+ type_check_P , interp_P , type_check_C , interp_C )
651772 successful_passes += succ_passes
652773 total_passes += tot_passes
653774 successful_tests += succ_test
0 commit comments