<s> """<STR_LIT>""" <EOL> import coresyntax as S <EOL> import pltools <EOL> from utility import flatten <EOL> import copy <EOL> import coretypes as T <EOL> import itertools <EOL> import inspect <EOL> class SourceGatherer ( S . SyntaxRewrite ) : <EOL> def __init__ ( self , globals ) : <EOL> self . globals = globals <EOL> import copperhead . prelude_impl as PI <EOL> self . prelude_impl = set ( dir ( PI ) ) <EOL> self . PI = PI <EOL> self . env = pltools . Environment ( ) <EOL> self . clean = [ ] <EOL> def gather ( self , suite ) : <EOL> self . sources = [ ] <EOL> self . gathered = set ( ) <EOL> for stmt in suite : <EOL> self . clean . append ( self . rewrite ( stmt ) ) <EOL> while self . sources : <EOL> stmt = self . sources . pop ( <NUM_LIT:0> ) <EOL> self . clean . insert ( <NUM_LIT:0> , self . rewrite ( stmt ) ) <EOL> return list ( flatten ( self . clean ) ) <EOL> def _Procedure ( self , proc ) : <EOL> proc_id = proc . name ( ) . id <EOL> self . env [ proc_id ] = proc_id <EOL> self . env . begin_scope ( ) <EOL> for param in flatten ( proc . formals ( ) ) : <EOL> id = param . id <EOL> self . env [ id ] = id <EOL> self . rewrite_children ( proc ) <EOL> self . env . end_scope ( ) <EOL> return proc <EOL> def _Bind ( self , bind ) : <EOL> destination = bind . binder ( ) <EOL> if isinstance ( destination , S . Tuple ) : <EOL> for dest in flatten ( destination ) : <EOL> self . env [ dest . id ] = dest . id <EOL> else : <EOL> id = destination . id <EOL> self . env [ id ] = id <EOL> self . rewrite_children ( bind ) <EOL> return bind <EOL> def _Name ( self , name ) : <EOL> if not name . id in self . env : <EOL> if name . id in self . globals : <EOL> fn = self . globals [ name . id ] <EOL> if ( fn . __name__ in self . prelude_impl ) : <EOL> if inspect . isbuiltin ( fn ) or inspect . isfunction ( fn ) : <EOL> fn = getattr ( self . PI , fn . __name__ ) <EOL> if hasattr ( fn , '<STR_LIT>' ) and fn . __name__ not in self . gathered : <EOL> self . sources . append ( fn . syntax_tree ) <EOL> self . gathered . add ( fn . __name__ ) <EOL> return name <EOL> def gather_source ( stmt , M ) : <EOL> gatherer = SourceGatherer ( M . globals ) <EOL> gathered = gatherer . gather ( stmt ) <EOL> return gathered <EOL> class IdentifierMarker ( S . SyntaxRewrite ) : <EOL> def __init__ ( self , globals ) : <EOL> self . globals = globals <EOL> self . locals = pltools . Environment ( ) <EOL> import copperhead . prelude_impl as PI <EOL> self . prelude_impl = set ( dir ( PI ) ) <EOL> self . PI = PI <EOL> self . bools = [ "<STR_LIT:True>" , "<STR_LIT:False>" ] <EOL> def _Name ( self , name ) : <EOL> if name . id in self . bools : <EOL> return name <EOL> if name . id in self . globals and name . id not in self . locals : <EOL> if hasattr ( self . globals [ name . id ] , '<STR_LIT>' ) or name . id in self . prelude_impl : <EOL> return S . mark_user ( name ) <EOL> else : <EOL> return name <EOL> else : <EOL> return S . mark_user ( name ) <EOL> def _Procedure ( self , proc ) : <EOL> self . locals . begin_scope ( ) <EOL> for x in proc . formals ( ) : <EOL> for y in flatten ( x ) : <EOL> self . locals [ y . id ] = True <EOL> self . rewrite_children ( proc ) <EOL> self . locals . end_scope ( ) <EOL> proc . variables = map ( S . mark_user , proc . variables ) <EOL> return proc <EOL> def _Lambda ( self , lamb ) : <EOL> return self . _Procedure ( lamb ) <EOL> def _Bind ( self , bind ) : <EOL> self . rewrite_children ( bind ) <EOL> bind . id = self . rewrite ( bind . id ) <EOL> return bind <EOL> def mark_identifiers ( stmt , M ) : <EOL> marker = IdentifierMarker ( M . globals ) <EOL> marked = marker . rewrite ( stmt ) <EOL> def mark_user ( x ) : <EOL> return S . mark_user ( S . Name ( x ) ) . id <EOL> M . entry_points = map ( mark_user , M . entry_points ) <EOL> for x in M . input_types . keys ( ) : <EOL> M . input_types [ mark_user ( x ) ] = M . input_types [ x ] <EOL> del M . input_types [ x ] <EOL> return marked <EOL> class VariadicLowerer ( S . SyntaxRewrite ) : <EOL> def __init__ ( self ) : <EOL> self . applies = set ( [ '<STR_LIT>' ] ) <EOL> self . binders = set ( [ '<STR_LIT>' ] ) <EOL> self . arity = - <NUM_LIT:1> <EOL> def _Bind ( self , bind ) : <EOL> if isinstance ( bind . binder ( ) , S . Tuple ) : <EOL> self . arity = bind . binder ( ) . arity ( ) <EOL> self . rewrite_children ( bind ) <EOL> return bind <EOL> def _Map ( self , ast ) : <EOL> args = ast . parameters <EOL> arity = len ( args ) - <NUM_LIT:1> <EOL> assert ( arity > <NUM_LIT:0> ) <EOL> return S . Apply ( S . Name ( '<STR_LIT>' + str ( arity ) ) , <EOL> args ) <EOL> def _Apply ( self , ast ) : <EOL> fn_id = ast . function ( ) . id <EOL> arity = - <NUM_LIT:1> <EOL> if fn_id in self . applies : <EOL> args = ast . arguments ( ) <EOL> arity = len ( args ) <EOL> elif fn_id in self . binders : <EOL> arity = self . arity <EOL> assert ( arity > <NUM_LIT:0> ) <EOL> if arity > <NUM_LIT:0> : <EOL> return S . Apply ( S . Name ( fn_id + str ( arity ) ) , ast . arguments ( ) ) <EOL> else : <EOL> return ast <EOL> def lower_variadics ( stmt ) : <EOL> rewriter = VariadicLowerer ( ) <EOL> lowered = rewriter . rewrite ( stmt ) <EOL> return lowered <EOL> class SingleAssignmentRewrite ( S . SyntaxRewrite ) : <EOL> def __init__ ( self , env , exceptions , state ) : <EOL> self . env = pltools . Environment ( env ) <EOL> self . exceptions = exceptions <EOL> if state : <EOL> self . serial = state <EOL> else : <EOL> self . serial = itertools . count ( <NUM_LIT:1> ) <EOL> def _Return ( self , stmt ) : <EOL> result = S . Return ( S . substituted_expression ( stmt . value ( ) , self . env ) ) <EOL> return result <EOL> def _Cond ( self , cond ) : <EOL> condition = S . substituted_expression ( cond . parameters [ <NUM_LIT:0> ] , self . env ) <EOL> self . env . begin_scope ( ) <EOL> body = self . rewrite ( cond . body ( ) ) <EOL> self . env . end_scope ( ) <EOL> self . env . begin_scope ( ) <EOL> orelse = self . rewrite ( cond . orelse ( ) ) <EOL> self . env . end_scope ( ) <EOL> return S . Cond ( condition , body , orelse ) <EOL> def _Bind ( self , stmt ) : <EOL> var = stmt . binder ( ) <EOL> varNames = [ x . id for x in flatten ( var ) ] <EOL> operation = S . substituted_expression ( stmt . value ( ) , self . env ) <EOL> for name in varNames : <EOL> if name not in self . exceptions : <EOL> rename = '<STR_LIT>' % ( name , self . serial . next ( ) ) <EOL> else : <EOL> rename = name <EOL> self . env [ name ] = S . Name ( rename ) <EOL> result = S . Bind ( S . substituted_expression ( var , self . env ) , operation ) <EOL> return result <EOL> def _Procedure ( self , stmt ) : <EOL> self . env . begin_scope ( ) <EOL> for var in flatten ( stmt . variables ) : <EOL> self . env [ var . id ] = var <EOL> result = self . rewrite_children ( stmt ) <EOL> self . env . end_scope ( ) <EOL> return result <EOL> def single_assignment_conversion ( stmt , env = { } , exceptions = set ( ) , M = None ) : <EOL> '<STR_LIT>' <EOL> state = None <EOL> if M : <EOL> state = getattr ( M , '<STR_LIT>' , None ) <EOL> rewrite = SingleAssignmentRewrite ( env , exceptions , state ) <EOL> rewritten = rewrite . rewrite ( stmt ) <EOL> if M : <EOL> M . single_conv_state = rewrite . serial <EOL> return rewritten <EOL> class LambdaLifter ( S . SyntaxRewrite ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self ) : <EOL> self . proclist = [ ] <EOL> self . names = pltools . name_supply ( stems = [ '<STR_LIT>' ] , drop_zero = False ) <EOL> def _Lambda ( self , e ) : <EOL> fn = S . Name ( self . names . next ( ) ) <EOL> self . rewrite_children ( e ) <EOL> body = S . Return ( e . parameters [ <NUM_LIT:0> ] ) <EOL> self . proclist . append ( S . Procedure ( fn , e . variables , [ body ] ) ) <EOL> return fn <EOL> def _Procedure ( self , ast ) : <EOL> body = [ ] <EOL> for stmt in ast . parameters : <EOL> stmt = self . rewrite ( stmt ) <EOL> body = body + self . proclist + [ stmt ] <EOL> self . proclist = [ ] <EOL> ast . parameters = body <EOL> return ast <EOL> def lambda_lift ( e ) : <EOL> lift = LambdaLifter ( ) <EOL> eL = lift . rewrite ( e ) <EOL> return lift . proclist + eL <EOL> class ProcedureFlattener ( S . SyntaxRewrite ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self ) : <EOL> self . toplevel = list ( ) <EOL> def _Procedure ( self , e ) : <EOL> self . rewrite_children ( e ) <EOL> e . parameters = filter ( lambda x : x is not None , e . parameters ) <EOL> self . toplevel . append ( e ) <EOL> return None <EOL> def procedure_flatten ( e ) : <EOL> flattener = ProcedureFlattener ( ) <EOL> eF = flattener . rewrite ( e ) <EOL> return flattener . toplevel <EOL> class _ClosureRecursion ( S . SyntaxRewrite ) : <EOL> def __init__ ( self , env ) : <EOL> self . env = env <EOL> def locally_bound ( self , B ) : <EOL> for v in flatten ( B ) : <EOL> self . env [ v . id ] = v . id <EOL> def _Bind ( self , ast ) : <EOL> self . rewrite_children ( ast ) <EOL> binders = [ v for v in S . walk ( ast . binder ( ) ) if isinstance ( v , S . Name ) ] <EOL> self . locally_bound ( binders ) <EOL> return ast <EOL> def _Lambda ( self , ast ) : <EOL> self . env . begin_scope ( ) <EOL> self . locally_bound ( ast . formals ( ) ) <EOL> self . rewrite_children ( ast ) <EOL> self . env . end_scope ( ) <EOL> return ast <EOL> def _Procedure ( self , ast ) : <EOL> self . env . begin_scope ( ) <EOL> self . locally_bound ( ast . variables ) <EOL> self . rewrite_children ( ast ) <EOL> self . env . end_scope ( ) <EOL> return ast <EOL> def _Apply ( self , ast ) : <EOL> if not isinstance ( ast . function ( ) , S . Name ) : <EOL> import pdb <EOL> pdb . set_trace ( ) <EOL> proc_name = ast . function ( ) . id <EOL> if proc_name in self . env and isinstance ( self . env [ proc_name ] , list ) : <EOL> return S . Apply ( ast . function ( ) , <EOL> ast . arguments ( ) + self . env [ proc_name ] ) <EOL> return self . rewrite_children ( ast ) <EOL> def _Name ( self , ast ) : <EOL> x = getattr ( self . env , ast . id , None ) <EOL> if ast . id in self . env and isinstance ( self . env [ ast . id ] , S . Closure ) : <EOL> return S . Closure ( self . env [ ast . id ] . variables , ast ) <EOL> else : <EOL> return ast <EOL> class _ClosureConverter ( _ClosureRecursion ) : <EOL> def __init__ ( self , globals = None ) : <EOL> self . globals = globals or dict ( ) <EOL> self . env = pltools . Environment ( ) <EOL> def _Lambda ( self , e ) : <EOL> _ClosureRecursion . _Lambda ( self , e ) <EOL> formals = [ v . id for v in flatten ( e . formals ( ) ) ] <EOL> free = list ( set ( [ v for v in S . free_variables ( e . body ( ) , formals ) <EOL> if v in self . env ] ) ) <EOL> if free : <EOL> bound = [ S . Name ( "<STR_LIT>" % i ) for i in range ( len ( free ) ) ] <EOL> body = S . substituted_expression ( e . body ( ) , dict ( zip ( free , bound ) ) ) <EOL> e . parameters = [ body ] <EOL> e . variables = e . variables + bound <EOL> return S . Closure ( [ S . Name ( x ) for x in free ] , e ) <EOL> else : <EOL> return e <EOL> def _Procedure ( self , ast ) : <EOL> binders = [ v . id for v in flatten ( ast . variables ) ] <EOL> _ClosureRecursion . _Procedure ( self , ast ) <EOL> free = list ( set ( [ v for v in S . free_variables ( ast . body ( ) , binders ) <EOL> if v in self . env ] ) ) <EOL> if free : <EOL> bound = [ S . Name ( "<STR_LIT>" % i ) for i in range ( len ( free ) ) ] <EOL> ast . variables = ast . variables + bound <EOL> ast . parameters = S . substituted_expression ( ast . parameters , <EOL> dict ( zip ( free , bound ) ) ) <EOL> recursive = _ClosureRecursion ( self . env ) <EOL> self . env [ ast . name ( ) . id ] = bound <EOL> ast . parameters = recursive . rewrite ( ast . parameters ) <EOL> self . env [ ast . name ( ) . id ] = S . Closure ( [ S . Name ( x ) for x in free ] , <EOL> ast . name ( ) ) <EOL> return ast <EOL> def closure_conversion ( ast , globals = None ) : <EOL> """<STR_LIT>""" <EOL> converter = _ClosureConverter ( globals = globals ) <EOL> converted = converter . rewrite ( ast ) <EOL> return converted <EOL> class ExpressionFlattener ( S . SyntaxRewrite ) : <EOL> def __init__ ( self ) : <EOL> self . stmts = [ list ( ) ] <EOL> self . names = pltools . name_supply ( stems = [ '<STR_LIT:e>' ] , drop_zero = False ) <EOL> def top ( self ) : return self . stmts [ - <NUM_LIT:1> ] <EOL> def emit ( self , ast ) : self . top ( ) . append ( ast ) <EOL> def push ( self ) : self . stmts . append ( list ( ) ) <EOL> def pop ( self ) : <EOL> x = self . top ( ) <EOL> self . stmts . pop ( ) <EOL> return x <EOL> def _Lambda ( self , ast ) : <EOL> raise ValueError , "<STR_LIT>" % e <EOL> def _Name ( self , ast ) : return ast <EOL> def _Number ( self , ast ) : return ast <EOL> def _Closure ( self , ast ) : return ast <EOL> def _Expression ( self , e ) : <EOL> subexpressions = e . parameters <EOL> e . parameters = [ ] <EOL> for sub in subexpressions : <EOL> sub = self . rewrite ( sub ) <EOL> if not isinstance ( sub , ( S . Name , S . Literal , S . Closure ) ) : <EOL> tn = S . Name ( self . names . next ( ) ) <EOL> self . emit ( S . Bind ( tn , sub ) ) <EOL> else : <EOL> tn = sub <EOL> e . parameters . append ( tn ) <EOL> return e <EOL> def _Bind ( self , stmt ) : <EOL> e = self . rewrite ( stmt . value ( ) ) <EOL> stmt . parameters = [ e ] <EOL> self . emit ( stmt ) <EOL> return stmt <EOL> def _Return ( self , stmt ) : <EOL> e = self . rewrite ( stmt . value ( ) ) <EOL> if isinstance ( e , S . Name ) : <EOL> stmt . parameters = [ e ] <EOL> self . emit ( stmt ) <EOL> return <EOL> ret = S . Name ( "<STR_LIT:result>" ) <EOL> self . emit ( S . Bind ( ret , e ) ) <EOL> stmt . parameters = [ ret ] <EOL> self . emit ( stmt ) <EOL> def _Cond ( self , stmt ) : <EOL> test = self . rewrite ( stmt . test ( ) ) <EOL> self . push ( ) <EOL> self . rewrite ( stmt . body ( ) ) <EOL> body = self . pop ( ) <EOL> self . push ( ) <EOL> self . rewrite ( stmt . orelse ( ) ) <EOL> orelse = self . pop ( ) <EOL> stmt . parameters = [ test , body , orelse ] <EOL> self . emit ( stmt ) <EOL> def _Procedure ( self , stmt ) : <EOL> self . push ( ) <EOL> self . formals = set ( ( x . id for x in flatten ( stmt . formals ( ) ) ) ) <EOL> self . rewrite_children ( stmt ) <EOL> self . formals = None <EOL> body = self . pop ( ) <EOL> stmt . parameters = body <EOL> self . emit ( stmt ) <EOL> def _default ( self , ast ) : <EOL> if isinstance ( ast , S . Expression ) : <EOL> return self . _Expression ( ast ) <EOL> else : <EOL> raise ValueError , "<STR_LIT>" % ast <EOL> def expression_flatten ( s , M ) : <EOL> flattener = ExpressionFlattener ( ) <EOL> if hasattr ( M , '<STR_LIT>' ) : <EOL> flattener . names = M . flattener_names <EOL> else : <EOL> flattener = ExpressionFlattener ( ) <EOL> M . flattener_names = flattener . names <EOL> flattener . rewrite ( s ) <EOL> return flattener . top ( ) <EOL> class LiteralCaster ( S . SyntaxRewrite ) : <EOL> def __init__ ( self , globals ) : <EOL> self . globals = globals <EOL> def _Procedure ( self , proc ) : <EOL> self . literal_names = set ( ) <EOL> self . rewrite_children ( proc ) <EOL> return proc <EOL> def _Bind ( self , bind ) : <EOL> if isinstance ( bind . value ( ) , S . Number ) : <EOL> self . literal_names . add ( bind . binder ( ) . id ) <EOL> self . rewrite_children ( bind ) <EOL> return bind <EOL> def _Apply ( self , appl ) : <EOL> self . rewrite_children ( appl ) <EOL> fn = appl . function ( ) <EOL> if isinstance ( fn , S . Closure ) : <EOL> return appl <EOL> fn_obj = self . globals . get ( fn . id , None ) <EOL> if not fn_obj : <EOL> return appl <EOL> if not hasattr ( fn_obj , '<STR_LIT>' ) : <EOL> return appl <EOL> fn_type = fn_obj . cu_type <EOL> if isinstance ( fn_type , T . Polytype ) : <EOL> fn_input_types = fn_type . monotype ( ) . input_types ( ) <EOL> else : <EOL> fn_input_types = fn_type . input_types ( ) <EOL> def build_cast ( cast_name , args ) : <EOL> "<STR_LIT>" <EOL> return S . Apply ( S . Name ( cast_name ) , <EOL> args ) <EOL> def insert_cast ( arg_type , arg ) : <EOL> "<STR_LIT>" <EOL> if hasattr ( arg , '<STR_LIT>' ) : <EOL> if arg_type is T . Int : <EOL> return build_cast ( "<STR_LIT>" , [ arg ] ) <EOL> elif arg_type is T . Long : <EOL> return build_cast ( "<STR_LIT>" , [ arg ] ) <EOL> elif arg_type is T . Float : <EOL> return build_cast ( "<STR_LIT>" , [ arg ] ) <EOL> elif arg_type is T . Double : <EOL> return build_cast ( "<STR_LIT>" , [ arg ] ) <EOL> elif isinstance ( arg_type , str ) : <EOL> for in_type , in_arg in zip ( fn_input_types , appl . arguments ( ) ) : <EOL> if not hasattr ( in_arg , '<STR_LIT>' ) : <EOL> if in_type == arg_type : <EOL> return build_cast ( "<STR_LIT>" , [ arg , in_arg ] ) <EOL> elif isinstance ( in_type , T . Seq ) and in_type . unbox ( ) == arg_type : <EOL> return build_cast ( "<STR_LIT>" , [ arg , in_arg ] ) <EOL> return arg <EOL> casted_arguments = map ( insert_cast , fn_input_types , appl . arguments ( ) ) <EOL> appl . parameters [ <NUM_LIT:1> : ] = casted_arguments <EOL> if all ( map ( lambda x : hasattr ( x , '<STR_LIT>' ) , appl . arguments ( ) ) ) : <EOL> appl . literal_expr = True <EOL> return appl <EOL> def _Number ( self , ast ) : <EOL> ast . literal_expr = True <EOL> return ast <EOL> def _Name ( self , ast ) : <EOL> if ast . id in self . literal_names : <EOL> ast . literal_expr = True <EOL> return ast <EOL> def cast_literals ( s , M ) : <EOL> caster = LiteralCaster ( M . globals ) <EOL> casted = caster . rewrite ( s ) <EOL> return expression_flatten ( casted , M ) <EOL> class TupleNamer ( S . SyntaxRewrite ) : <EOL> def _Procedure ( self , proc ) : <EOL> names = pltools . name_supply ( stems = [ '<STR_LIT>' ] , drop_zero = False ) <EOL> disassembly = [ ] <EOL> def make_name ( arg ) : <EOL> if not isinstance ( arg , S . Tuple ) : <EOL> return arg <EOL> else : <EOL> made_name = S . Name ( names . next ( ) ) <EOL> assembled = S . Bind ( S . Tuple ( * [ make_name ( x ) for x in arg ] ) , <EOL> made_name ) <EOL> disassembly . insert ( <NUM_LIT:0> , assembled ) <EOL> return made_name <EOL> new_variables = map ( make_name , proc . formals ( ) ) <EOL> return S . Procedure ( proc . name ( ) , new_variables , disassembly + proc . parameters ) <EOL> def name_tuples ( s ) : <EOL> namer = TupleNamer ( ) <EOL> named = namer . rewrite ( s ) <EOL> return named <EOL> class ReturnFinder ( S . SyntaxVisitor ) : <EOL> def __init__ ( self ) : <EOL> self . in_conditional = False <EOL> self . return_in_conditional = False <EOL> def _Cond ( self , cond ) : <EOL> self . in_conditional = True <EOL> self . visit_children ( cond ) <EOL> self . in_conditional = False <EOL> def _Return ( self , node ) : <EOL> if self . in_conditional : <EOL> self . return_in_conditional = True <EOL> return <EOL> self . return_value = node . value ( ) <EOL> class FunctionInliner ( S . SyntaxRewrite ) : <EOL> def __init__ ( self , M ) : <EOL> self . activeBinding = None <EOL> self . statements = [ ] <EOL> self . procedures = { } <EOL> self . M = M <EOL> def _Bind ( self , binding ) : <EOL> self . activeBinding = binding . binder ( ) <EOL> self . rewrite_children ( binding ) <EOL> self . activeBinding = None <EOL> statements = self . statements <EOL> self . statements = [ ] <EOL> if statements == [ ] : <EOL> return binding <EOL> return statements <EOL> def _Apply ( self , appl ) : <EOL> fn = appl . function ( ) <EOL> if isinstance ( fn , S . Closure ) : <EOL> fn_name = fn . body ( ) . id <EOL> else : <EOL> fn_name = fn . id <EOL> if fn_name in self . procedures : <EOL> instantiatedFunction = self . procedures [ fn_name ] <EOL> functionArguments = instantiatedFunction . variables [ <NUM_LIT:1> : ] <EOL> instantiatedArguments = appl . parameters [ <NUM_LIT:1> : ] <EOL> if isinstance ( fn , S . Closure ) : <EOL> instantiatedArguments . extend ( fn . variables ) <EOL> env = pltools . Environment ( ) <EOL> for ( internal , external ) in zip ( functionArguments , instantiatedArguments ) : <EOL> env [ internal . id ] = external <EOL> return_finder = ReturnFinder ( ) <EOL> return_finder . visit ( instantiatedFunction ) <EOL> if return_finder . return_in_conditional : <EOL> return appl <EOL> env [ return_finder . return_value . id ] = self . activeBinding <EOL> statements = filter ( lambda x : not isinstance ( x , S . Return ) , <EOL> instantiatedFunction . body ( ) ) <EOL> statements = [ S . substituted_expression ( x , env ) for x in statements ] <EOL> singleAssignmentInstantiation = single_assignment_conversion ( statements , exceptions = set ( ( x . id for x in flatten ( self . activeBinding ) ) ) , M = self . M ) <EOL> self . statements = singleAssignmentInstantiation <EOL> return None <EOL> return appl <EOL> def _Cond ( self , cond ) : <EOL> body = list ( flatten ( self . rewrite ( cond . body ( ) ) ) ) <EOL> orelse = list ( flatten ( self . rewrite ( cond . orelse ( ) ) ) ) <EOL> return S . Cond ( cond . test ( ) , body , orelse ) <EOL> def _Procedure ( self , proc ) : <EOL> self . rewrite_children ( proc ) <EOL> proc . parameters = list ( flatten ( proc . parameters ) ) <EOL> procedureName = proc . variables [ <NUM_LIT:0> ] . id <EOL> self . procedures [ procedureName ] = proc <EOL> return proc <EOL> class LiteralOpener ( S . SyntaxRewrite ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self ) : <EOL> self . procedures = { } <EOL> self . name_supply = pltools . name_supply ( stems = [ '<STR_LIT:_>' ] , drop_zero = False ) <EOL> def _Procedure ( self , proc ) : <EOL> self . propagated = [ ] <EOL> self . rewrite_children ( proc ) <EOL> self . procedures [ proc . name ( ) . id ] = proc <EOL> if self . propagated : <EOL> return self . propagated + [ proc ] <EOL> else : <EOL> return proc <EOL> def _Closure ( self , c ) : <EOL> closed_over_literal = any ( map ( lambda x : not isinstance ( x , S . Name ) , <EOL> c . closed_over ( ) ) ) <EOL> if not closed_over_literal : <EOL> return c <EOL> proc_name = c . body ( ) . id <EOL> proc = self . procedures [ proc_name ] <EOL> proc_args = proc . formals ( ) <EOL> closed_args = c . closed_over ( ) <EOL> replaced_args = proc_args [ : - len ( closed_args ) ] <EOL> replaced_closed_over = [ ] <EOL> replacement = { } <EOL> for orig_arg , closed_arg in zip ( proc_args [ - len ( closed_args ) : ] , <EOL> closed_args ) : <EOL> if isinstance ( closed_arg , S . Name ) : <EOL> replaced_args . append ( orig_arg ) <EOL> replaced_closed_over . append ( closed_arg ) <EOL> else : <EOL> replacement [ orig_arg . id ] = closed_arg <EOL> fully_opened = len ( replacement ) == len ( closed_args ) <EOL> replaced_stmts = [ <EOL> S . substituted_expression ( si , replacement ) for si in proc . body ( ) ] <EOL> replaced_name = S . Name ( proc_name + self . name_supply . next ( ) ) <EOL> self . propagated . append ( <EOL> S . Procedure ( <EOL> replaced_name , <EOL> replaced_args , <EOL> replaced_stmts ) ) <EOL> if fully_opened : <EOL> return replaced_name <EOL> else : <EOL> return S . Closure ( replaced_closed_over , <EOL> replaced_name ) <EOL> def procedure_prune ( ast , entries ) : <EOL> needed = set ( entries ) <EOL> for p in ast : <EOL> needed . update ( S . free_variables ( p . body ( ) ) ) <EOL> return [ p for p in ast if p . name ( ) . id in needed ] <EOL> def inline ( s , M ) : <EOL> inliner = FunctionInliner ( M ) <EOL> inlined = list ( flatten ( inliner . rewrite ( s ) ) ) <EOL> literal_opener = LiteralOpener ( ) <EOL> opened = list ( flatten ( literal_opener . rewrite ( inlined ) ) ) <EOL> return opened <EOL> class Unrebinder ( S . SyntaxRewrite ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self ) : <EOL> self . env = pltools . Environment ( ) <EOL> def recursive_record ( self , lhs , rhs ) : <EOL> if isinstance ( lhs , S . Name ) and isinstance ( rhs , S . Name ) : <EOL> self . env [ lhs . id ] = rhs . id <EOL> return True <EOL> elif isinstance ( lhs , S . Tuple ) and isinstance ( rhs , S . Tuple ) : <EOL> recorded = True <EOL> for x , y in zip ( lhs , rhs ) : <EOL> recorded = self . recursive_record ( x , y ) and recorded <EOL> return recorded <EOL> else : <EOL> return False <EOL> def _Bind ( self , b ) : <EOL> self . rewrite_children ( b ) <EOL> lhs = b . binder ( ) <EOL> rhs = b . value ( ) <EOL> extraneous = self . recursive_record ( lhs , rhs ) <EOL> if extraneous : <EOL> return None <EOL> else : <EOL> return b <EOL> def _Name ( self , n ) : <EOL> if n . id in self . env : <EOL> n . id = self . env [ n . id ] <EOL> return n <EOL> def rewrite_suite ( self , suite ) : <EOL> rewritten = map ( self . rewrite , suite ) <EOL> return filter ( lambda xi : xi is not None , rewritten ) <EOL> def _Procedure ( self , p ) : <EOL> stmts = self . rewrite_suite ( p . body ( ) ) <EOL> p . parameters = stmts <EOL> return p <EOL> def _Cond ( self , cond ) : <EOL> body = self . rewrite_suite ( cond . body ( ) ) <EOL> orelse = self . rewrite_suite ( cond . orelse ( ) ) <EOL> return S . Cond ( cond . test ( ) , body , orelse ) <EOL> def unrebind ( ast ) : <EOL> rewritten = Unrebinder ( ) . rewrite ( ast ) <EOL> return rewritten <EOL> class ConditionalProtector ( S . SyntaxRewrite ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self ) : <EOL> pass <EOL> def _If ( self , e ) : <EOL> self . rewrite_children ( e ) <EOL> test = e . test ( ) <EOL> body = S . Lambda ( [ ] , e . body ( ) ) <EOL> orelse = S . Lambda ( [ ] , e . orelse ( ) ) <EOL> e . parameters = [ test , body , orelse ] <EOL> return S . Apply ( e , [ ] ) <EOL> class ArityChecker ( S . SyntaxVisitor ) : <EOL> def _Tuple ( self , tup ) : <EOL> self . visit_children ( tup ) <EOL> if tup . arity ( ) > <NUM_LIT:10> : <EOL> raise SyntaxError , '<STR_LIT>' <EOL> def _Procedure ( self , proc ) : <EOL> self . visit_children ( proc ) <EOL> if len ( proc . formals ( ) ) > <NUM_LIT:10> : <EOL> raise SyntaxError , '<STR_LIT>' <EOL> def arity_check ( ast ) : <EOL> ArityChecker ( ) . visit ( ast ) <EOL> class ReturnChecker ( S . SyntaxVisitor ) : <EOL> def suite_must_return ( self , suite , error ) : <EOL> if not isinstance ( suite [ - <NUM_LIT:1> ] , S . Return ) : <EOL> raise SyntaxError , error <EOL> def _Cond ( self , cond ) : <EOL> cond_error = '<STR_LIT>' <EOL> def check_cond_suite ( suite ) : <EOL> if isinstance ( suite [ <NUM_LIT:0> ] , S . Cond ) : <EOL> self . visit_children ( suite [ <NUM_LIT:0> ] ) <EOL> if len ( suite ) != <NUM_LIT:1> : <EOL> raise SyntaxError , cond_error <EOL> else : <EOL> self . suite_must_return ( suite , cond_error ) <EOL> check_cond_suite ( cond . body ( ) ) <EOL> check_cond_suite ( cond . orelse ( ) ) <EOL> def _Procedure ( self , proc ) : <EOL> proc_error = '<STR_LIT>' <EOL> last = proc . body ( ) [ - <NUM_LIT:1> ] <EOL> if isinstance ( last , S . Cond ) : <EOL> self . visit_children ( proc ) <EOL> else : <EOL> self . suite_must_return ( proc . body ( ) , proc_error ) <EOL> def return_check ( ast ) : <EOL> ReturnChecker ( ) . visit ( ast ) <EOL> class BuiltinChecker ( S . SyntaxVisitor ) : <EOL> def __init__ ( self ) : <EOL> import copperhead . prelude as P <EOL> self . builtins = set ( <EOL> filter ( lambda n : n [ <NUM_LIT:0> ] != '<STR_LIT:_>' , dir ( P ) ) ) <EOL> def _Procedure ( self , proc ) : <EOL> name = proc . name ( ) . id <EOL> if name in self . builtins : <EOL> raise SyntaxError , '<STR_LIT>' % name <EOL> def builtin_check ( ast ) : <EOL> BuiltinChecker ( ) . visit ( ast ) </s>
