<s> from collections import namedtuple <EOL> import numpy as np <EOL> from . . import names , prims <EOL> from . . ndtypes import ( IntT , FloatT , TupleT , FnT , Type , BoolT , NoneT , Float32 , Float64 , Bool , <EOL> ClosureT , ScalarT , PtrT , NoneType , ArrayT , SliceT , TypeValueT ) <EOL> from . . syntax import ( Const , Var , PrimCall , Attribute , TupleProj , Tuple , ArrayView , <EOL> Expr , Closure , TypedFn ) <EOL> import type_mappings <EOL> from base_compiler import BaseCompiler <EOL> CompiledFlatFn = namedtuple ( "<STR_LIT>" , <EOL> ( "<STR_LIT:name>" , "<STR_LIT>" , "<STR_LIT:src>" , <EOL> "<STR_LIT>" , <EOL> "<STR_LIT>" , <EOL> "<STR_LIT>" , <EOL> "<STR_LIT>" ) ) <EOL> _struct_type_names = { } <EOL> _struct_type_decls = { } <EOL> class FnCompiler ( BaseCompiler ) : <EOL> def __init__ ( self , <EOL> module_entry = False , <EOL> struct_type_cache = None , <EOL> ** kwargs ) : <EOL> BaseCompiler . __init__ ( self , ** kwargs ) <EOL> self . declarations = [ ] <EOL> self . extra_objects = set ( [ ] ) <EOL> self . extra_functions = { } <EOL> self . extra_function_signatures = [ ] <EOL> self . module_entry = module_entry <EOL> def add_decl ( self , decl ) : <EOL> if decl not in self . declarations : <EOL> self . declarations . append ( decl ) <EOL> def ptr_struct_type ( self , elt_t ) : <EOL> field_types = [ "<STR_LIT>" % self . to_ctype ( elt_t ) , "<STR_LIT>" ] <EOL> return self . struct_type_from_fields ( field_types , <EOL> struct_name = "<STR_LIT>" % elt_t , <EOL> field_names = [ "<STR_LIT>" , "<STR_LIT>" ] ) <EOL> def array_struct_type ( self , elt_t , rank ) : <EOL> ptr_field_t = self . ptr_struct_type ( elt_t ) <EOL> field_types = [ ptr_field_t , "<STR_LIT>" , "<STR_LIT>" , "<STR_LIT>" , "<STR_LIT>" ] <EOL> field_names = [ "<STR_LIT:data>" , "<STR_LIT>" , "<STR_LIT>" , "<STR_LIT>" , "<STR_LIT:size>" ] <EOL> field_repeats = { } <EOL> field_repeats [ "<STR_LIT>" ] = rank <EOL> field_repeats [ "<STR_LIT>" ] = rank <EOL> return self . struct_type_from_fields ( field_types , "<STR_LIT>" , field_names , field_repeats ) <EOL> def slice_struct_type ( self , start_t = "<STR_LIT>" , stop_t = "<STR_LIT>" , step_t = "<STR_LIT>" ) : <EOL> field_types = [ start_t , stop_t , step_t ] <EOL> field_names = [ "<STR_LIT:start>" , "<STR_LIT>" , "<STR_LIT>" ] <EOL> return self . struct_type_from_fields ( field_types , "<STR_LIT>" , field_names ) <EOL> def struct_type_from_fields ( self , <EOL> field_types , <EOL> struct_name = "<STR_LIT>" , <EOL> field_names = None , <EOL> field_repeats = { } ) : <EOL> if any ( not isinstance ( t , str ) for t in field_types ) : <EOL> field_types = tuple ( self . to_ctype ( t ) if isinstance ( t , Type ) else t <EOL> for t in field_types ) <EOL> else : <EOL> field_types = tuple ( field_types ) <EOL> if field_names is None : <EOL> field_names = tuple ( "<STR_LIT>" % i for i in xrange ( len ( field_types ) ) ) <EOL> else : <EOL> assert len ( field_names ) == len ( field_types ) , "<STR_LIT>" % ( len ( field_types ) , len ( field_names ) ) <EOL> field_names = tuple ( field_names ) <EOL> repeat_set = frozenset ( sorted ( field_repeats . items ( ) ) ) <EOL> key = field_types , struct_name , field_names , repeat_set <EOL> if key in _struct_type_names : <EOL> typename = _struct_type_names [ key ] <EOL> decl = _struct_type_decls [ typename ] <EOL> if decl not in self . declarations : <EOL> self . declarations . append ( decl ) <EOL> return typename <EOL> typename = names . fresh ( struct_name ) . replace ( "<STR_LIT:.>" , "<STR_LIT>" ) <EOL> field_decls = [ ] <EOL> for t , field_name in zip ( field_types , field_names ) : <EOL> if field_name in field_repeats : <EOL> field_decl = "<STR_LIT>" % ( t , field_name , field_repeats [ field_name ] ) <EOL> else : <EOL> field_decl = "<STR_LIT>" % ( t , field_name ) <EOL> field_decls . append ( field_decl ) <EOL> decl = "<STR_LIT>" % ( typename , "<STR_LIT:\n>" . join ( field_decls ) , typename ) <EOL> _struct_type_names [ key ] = typename <EOL> _struct_type_decls [ typename ] = decl <EOL> self . add_decl ( decl ) <EOL> return typename <EOL> def to_ctype ( self , parakeet_type ) : <EOL> if isinstance ( parakeet_type , ( NoneT , ScalarT ) ) : <EOL> return type_mappings . to_ctype ( parakeet_type ) <EOL> elif isinstance ( parakeet_type , TupleT ) : <EOL> return self . struct_type_from_fields ( parakeet_type . elt_types ) <EOL> elif isinstance ( parakeet_type , PtrT ) : <EOL> return self . ptr_struct_type ( parakeet_type . elt_type ) <EOL> elif isinstance ( parakeet_type , ArrayT ) : <EOL> elt_t = parakeet_type . elt_type <EOL> rank = parakeet_type . rank <EOL> return self . array_struct_type ( elt_t , rank ) <EOL> elif isinstance ( parakeet_type , SliceT ) : <EOL> return self . slice_struct_type ( ) <EOL> elif isinstance ( parakeet_type , ClosureT ) : <EOL> return self . struct_type_from_fields ( parakeet_type . arg_types ) <EOL> elif isinstance ( parakeet_type , TypeValueT ) : <EOL> return "<STR_LIT:int>" <EOL> else : <EOL> assert False , "<STR_LIT>" % parakeet_type <EOL> def to_ctypes ( self , ts ) : <EOL> return tuple ( self . to_ctype ( t ) for t in ts ) <EOL> def visit_Slice ( self , expr ) : <EOL> typename = self . to_ctype ( expr . type ) <EOL> start = self . visit_expr ( expr . start ) <EOL> stop = self . visit_expr ( expr . stop ) <EOL> step = self . visit_expr ( expr . step ) <EOL> return self . fresh_var ( typename , "<STR_LIT>" , "<STR_LIT>" % ( start , stop , step ) ) <EOL> def visit_Alloc ( self , expr ) : <EOL> elt_t = expr . elt_type <EOL> nelts = self . fresh_var ( "<STR_LIT>" , "<STR_LIT>" , self . visit_expr ( expr . count ) ) <EOL> bytes_per_elt = elt_t . nbytes <EOL> nbytes = self . mul ( nelts , bytes_per_elt ) <EOL> raw_ptr = "<STR_LIT>" % ( type_mappings . to_ctype ( expr . type ) , nbytes ) <EOL> struct_type = self . to_ctype ( expr . type ) <EOL> return self . fresh_var ( struct_type , "<STR_LIT>" , "<STR_LIT>" % raw_ptr ) <EOL> def visit_Const ( self , expr ) : <EOL> t = expr . type <EOL> c = t . __class__ <EOL> if c == BoolT : <EOL> return "<STR_LIT:1>" if expr . value else "<STR_LIT:0>" <EOL> elif c == NoneT : <EOL> return "<STR_LIT:0>" <EOL> assert isinstance ( t , ScalarT ) , "<STR_LIT>" % ( expr , t ) <EOL> v = expr . value <EOL> if np . isinf ( v ) : <EOL> return "<STR_LIT>" <EOL> elif np . isnan ( v ) : <EOL> return "<STR_LIT>" <EOL> return "<STR_LIT:%s>" % expr . value <EOL> def visit_Var ( self , expr ) : <EOL> return self . name ( expr . name ) <EOL> def visit_Cast ( self , expr ) : <EOL> x = self . visit_expr ( expr . value ) <EOL> ct = self . to_ctype ( expr . type ) <EOL> if isinstance ( expr , ( Const , Var ) ) : <EOL> return "<STR_LIT>" % ( ct , x ) <EOL> else : <EOL> return "<STR_LIT>" % ( ct , x ) <EOL> def visit_PrimCall ( self , expr ) : <EOL> t = expr . type <EOL> args = self . visit_expr_list ( expr . args ) <EOL> for i , arg_expr in enumerate ( expr . args ) : <EOL> if not isinstance ( arg_expr , ( Var , Const ) ) : <EOL> args [ i ] = "<STR_LIT:(>" + args [ i ] + "<STR_LIT:)>" <EOL> p = expr . prim <EOL> if p == prims . add : <EOL> return self . add ( args [ <NUM_LIT:0> ] , args [ <NUM_LIT:1> ] ) <EOL> if p == prims . subtract : <EOL> return self . sub ( args [ <NUM_LIT:0> ] , args [ <NUM_LIT:1> ] ) <EOL> elif p == prims . multiply : <EOL> return self . mul ( args [ <NUM_LIT:0> ] , args [ <NUM_LIT:1> ] ) <EOL> elif p == prims . divide : <EOL> return self . div ( args [ <NUM_LIT:0> ] , args [ <NUM_LIT:1> ] ) <EOL> elif p == prims . negative : <EOL> if t == Bool : <EOL> return "<STR_LIT>" % args [ <NUM_LIT:0> ] <EOL> else : <EOL> return "<STR_LIT>" % args [ <NUM_LIT:0> ] <EOL> elif p == prims . abs : <EOL> x = args [ <NUM_LIT:0> ] <EOL> return "<STR_LIT>" % ( x , x , x ) <EOL> elif p == prims . bitwise_and : <EOL> return "<STR_LIT>" % ( args [ <NUM_LIT:0> ] , args [ <NUM_LIT:1> ] ) <EOL> elif p == prims . bitwise_or : <EOL> return "<STR_LIT>" % ( args [ <NUM_LIT:0> ] , args [ <NUM_LIT:1> ] ) <EOL> elif p == prims . bitwise_not : <EOL> return "<STR_LIT>" % args [ <NUM_LIT:0> ] <EOL> elif p == prims . logical_and : <EOL> return self . and_ ( args [ <NUM_LIT:0> ] , args [ <NUM_LIT:1> ] ) <EOL> elif p == prims . logical_or : <EOL> return self . or_ ( args [ <NUM_LIT:0> ] , args [ <NUM_LIT:1> ] ) <EOL> elif p == prims . logical_not : <EOL> return self . not_ ( args [ <NUM_LIT:0> ] ) <EOL> elif p == prims . equal : <EOL> return self . eq ( args [ <NUM_LIT:0> ] , args [ <NUM_LIT:1> ] , t ) <EOL> elif p == prims . not_equal : <EOL> return self . neq ( args [ <NUM_LIT:0> ] , args [ <NUM_LIT:1> ] , t ) <EOL> elif p == prims . greater : <EOL> return self . gt ( args [ <NUM_LIT:0> ] , args [ <NUM_LIT:1> ] , t ) <EOL> elif p == prims . greater_equal : <EOL> return self . gte ( args [ <NUM_LIT:0> ] , args [ <NUM_LIT:1> ] , t ) <EOL> elif p == prims . less : <EOL> return self . lt ( args [ <NUM_LIT:0> ] , args [ <NUM_LIT:1> ] , t ) <EOL> elif p == prims . less_equal : <EOL> return self . lte ( args [ <NUM_LIT:0> ] , args [ <NUM_LIT:1> ] , t ) <EOL> elif p == prims . remainder : <EOL> x , y = args <EOL> if t == Float32 : return "<STR_LIT>" % ( x , y ) <EOL> elif t == Float64 : return "<STR_LIT>" % ( x , y ) <EOL> assert isinstance ( t , ( BoolT , IntT ) ) , "<STR_LIT>" % t <EOL> rem = self . fresh_var ( t , "<STR_LIT>" , "<STR_LIT>" % ( x , y ) ) <EOL> y_is_negative = self . fresh_var ( t , "<STR_LIT>" , "<STR_LIT>" % y ) <EOL> rem_is_negative = self . fresh_var ( t , "<STR_LIT>" , "<STR_LIT>" % rem ) <EOL> y_nonzero = self . fresh_var ( t , "<STR_LIT>" , "<STR_LIT>" % y ) <EOL> rem_nonzero = self . fresh_var ( t , "<STR_LIT>" , "<STR_LIT>" % rem ) <EOL> neither_zero = self . fresh_var ( t , "<STR_LIT>" , "<STR_LIT>" % ( y_nonzero , rem_nonzero ) ) <EOL> diff_signs = self . fresh_var ( t , "<STR_LIT>" , "<STR_LIT>" % ( y_is_negative , rem_is_negative ) ) <EOL> should_flip = self . fresh_var ( t , "<STR_LIT>" , "<STR_LIT>" % ( neither_zero , diff_signs ) ) <EOL> flipped_rem = self . fresh_var ( t , "<STR_LIT>" , "<STR_LIT>" % ( y , rem ) ) <EOL> return "<STR_LIT>" % ( should_flip , flipped_rem , rem ) <EOL> elif p == prims . fmod : <EOL> if t == Float32 : return "<STR_LIT>" % ( args [ <NUM_LIT:0> ] , args [ <NUM_LIT:1> ] ) <EOL> elif t == Float64 : return "<STR_LIT>" % ( args [ <NUM_LIT:0> ] , args [ <NUM_LIT:1> ] ) <EOL> return "<STR_LIT>" % ( args [ <NUM_LIT:0> ] , args [ <NUM_LIT:1> ] ) <EOL> elif p == prims . maximum : <EOL> x , y = args <EOL> return "<STR_LIT>" % ( x , y , x , y ) <EOL> elif p == prims . minimum : <EOL> x , y = args <EOL> return "<STR_LIT>" % ( x , y , x , y ) <EOL> elif p == prims . power : <EOL> if t == Float32 : <EOL> return "<STR_LIT>" % ( args [ <NUM_LIT:0> ] , args [ <NUM_LIT:1> ] ) <EOL> else : <EOL> return "<STR_LIT>" % ( args [ <NUM_LIT:0> ] , args [ <NUM_LIT:1> ] ) <EOL> elif isinstance ( t , FloatT ) : <EOL> name = p . name <EOL> if name . startswith ( "<STR_LIT>" ) : <EOL> name = "<STR_LIT:a>" + name [ <NUM_LIT:3> : ] <EOL> if t == Float32 : name = name + "<STR_LIT:f>" <EOL> if len ( args ) == <NUM_LIT:1> : <EOL> return "<STR_LIT>" % ( name , args [ <NUM_LIT:0> ] ) <EOL> else : <EOL> assert len ( args ) == <NUM_LIT:2> , "<STR_LIT>" % ( p , len ( args ) , args ) <EOL> return "<STR_LIT>" % ( name , args [ <NUM_LIT:0> ] , args [ <NUM_LIT:1> ] ) <EOL> else : <EOL> assert False , "<STR_LIT>" % p <EOL> def visit_Index ( self , expr ) : <EOL> arr = self . visit_expr ( expr . value ) <EOL> if isinstance ( expr . index . type , ScalarT ) : <EOL> index_exprs = [ expr . index ] <EOL> else : <EOL> assert isinstance ( expr . index . type , TupleT ) , "<STR_LIT>" % ( expr . index , expr . index . type ) <EOL> if isinstance ( expr . index , Tuple ) : <EOL> index_exprs = expr . index . elts <EOL> else : <EOL> index_exprs = [ TupleProj ( expr . index , i , type = t ) <EOL> for i , t in enumerate ( expr . index . type . elt_types ) ] <EOL> assert all ( isinstance ( idx_expr . type , ScalarT ) for idx_expr in index_exprs ) , "<STR_LIT>" % ( index_exprs , ) <EOL> indices = [ self . visit_expr ( idx_expr ) for idx_expr in index_exprs ] <EOL> if isinstance ( expr . value . type , PtrT ) : <EOL> assert len ( indices ) == <NUM_LIT:1> , "<STR_LIT>" % ( len ( indices ) , index_exprs ) <EOL> raw_ptr = "<STR_LIT>" % arr <EOL> offset = indices [ <NUM_LIT:0> ] <EOL> else : <EOL> assert isinstance ( expr . value . type , ArrayT ) <EOL> offset = self . fresh_var ( "<STR_LIT>" , "<STR_LIT>" , "<STR_LIT>" % arr ) <EOL> for i , idx in enumerate ( indices ) : <EOL> stride = "<STR_LIT>" % ( arr , i ) <EOL> self . append ( "<STR_LIT>" % ( offset , idx , stride ) ) <EOL> raw_ptr = "<STR_LIT>" % arr <EOL> return "<STR_LIT>" % ( raw_ptr , offset ) <EOL> def visit_Call ( self , expr ) : <EOL> fn_name = self . get_fn_name ( expr . fn ) <EOL> closure_args = self . get_closure_args ( expr . fn ) <EOL> args = self . visit_expr_list ( expr . args ) <EOL> return "<STR_LIT>" % ( fn_name , "<STR_LIT:U+002CU+0020>" . join ( tuple ( closure_args ) + tuple ( args ) ) ) <EOL> def visit_Select ( self , expr ) : <EOL> cond = self . visit_expr ( expr . cond ) <EOL> true = self . visit_expr ( expr . true_value ) <EOL> false = self . visit_expr ( expr . false_value ) <EOL> return "<STR_LIT>" % ( cond , true , false ) <EOL> def is_pure ( self , expr ) : <EOL> return expr . __class__ in ( Var , Const , PrimCall , Attribute , TupleProj , Tuple , ArrayView ) <EOL> def visit_Assign ( self , stmt ) : <EOL> rhs = self . visit_expr ( stmt . rhs ) <EOL> if stmt . lhs . __class__ is Var : <EOL> lhs = self . visit_expr ( stmt . lhs ) <EOL> return "<STR_LIT>" % ( self . to_ctype ( stmt . lhs . type ) , lhs , rhs ) <EOL> elif stmt . lhs . __class__ is Tuple : <EOL> struct_value = self . fresh_var ( self . to_ctype ( stmt . lhs . type ) , "<STR_LIT>" ) <EOL> self . assign ( struct_value , rhs ) <EOL> for i , lhs_var in enumerate ( stmt . lhs . elts ) : <EOL> assert isinstance ( lhs_var , Var ) , "<STR_LIT>" % lhs_var <EOL> c_name = self . visit_expr ( lhs_var ) <EOL> self . append ( "<STR_LIT>" % ( self . to_ctype ( lhs_var . type ) , c_name , struct_value , i ) ) <EOL> return "<STR_LIT>" <EOL> else : <EOL> lhs = self . visit_expr ( stmt . lhs ) <EOL> return "<STR_LIT>" % ( lhs , rhs ) <EOL> def declare ( self , parakeet_name , parakeet_type , init_value = None ) : <EOL> c_name = self . name ( parakeet_name ) <EOL> t = self . to_ctype ( parakeet_type ) <EOL> if init_value is None : <EOL> self . append ( "<STR_LIT>" % ( t , c_name ) ) <EOL> else : <EOL> self . append ( "<STR_LIT>" % ( t , c_name , init_value ) ) <EOL> def declare_merge_vars ( self , merge ) : <EOL> """<STR_LIT>""" <EOL> for ( name , ( left , _ ) ) in merge . iteritems ( ) : <EOL> self . declare ( name , left . type ) <EOL> def visit_merge_left ( self , merge , fresh_vars = True ) : <EOL> if len ( merge ) == <NUM_LIT:0> : <EOL> return "<STR_LIT>" <EOL> self . push ( ) <EOL> self . comment ( "<STR_LIT>" + str ( merge ) ) <EOL> for ( name , ( left , _ ) ) in merge . iteritems ( ) : <EOL> c_left = self . visit_expr ( left ) <EOL> if fresh_vars : <EOL> self . declare ( name , left . type , c_left ) <EOL> else : <EOL> c_name = self . name ( name ) <EOL> self . append ( "<STR_LIT>" % ( c_name , c_left ) ) <EOL> return self . pop ( ) <EOL> def visit_merge_right ( self , merge ) : <EOL> if len ( merge ) == <NUM_LIT:0> : <EOL> return "<STR_LIT>" <EOL> self . push ( ) <EOL> self . comment ( "<STR_LIT>" + str ( merge ) ) <EOL> for ( name , ( _ , right ) ) in merge . iteritems ( ) : <EOL> c_right = self . visit_expr ( right ) <EOL> self . append ( "<STR_LIT>" % ( self . name ( name ) , c_right ) ) <EOL> return self . pop ( ) <EOL> def visit_NumCores ( self , expr ) : <EOL> return "<STR_LIT:1>" <EOL> def visit_Comment ( self , stmt ) : <EOL> return "<STR_LIT>" + stmt . text <EOL> def visit_PrintString ( self , stmt ) : <EOL> self . printf ( stmt . text ) <EOL> return "<STR_LIT>" <EOL> def visit_SourceExpr ( self , expr ) : <EOL> return expr . text <EOL> def visit_SourceStmt ( self , stmt ) : <EOL> return stmt . text <EOL> def visit_If ( self , stmt ) : <EOL> self . declare_merge_vars ( stmt . merge ) <EOL> cond = self . visit_expr ( stmt . cond ) <EOL> true = self . visit_block ( stmt . true ) + self . visit_merge_left ( stmt . merge , fresh_vars = False ) <EOL> false = self . visit_block ( stmt . false ) + self . visit_merge_right ( stmt . merge ) <EOL> return self . indent ( "<STR_LIT>" % ( cond , self . indent ( true ) , self . indent ( false ) ) ) <EOL> def visit_While ( self , stmt ) : <EOL> decls = self . visit_merge_left ( stmt . merge , fresh_vars = True ) <EOL> cond = self . visit_expr ( stmt . cond ) <EOL> body = self . visit_block ( stmt . body ) + self . visit_merge_right ( stmt . merge ) <EOL> return decls + "<STR_LIT>" % ( cond , body ) <EOL> def visit_ExprStmt ( self , stmt ) : <EOL> return self . visit_expr ( stmt . value ) + "<STR_LIT:;>" <EOL> def visit_ForLoop ( self , stmt ) : <EOL> s = self . visit_merge_left ( stmt . merge , fresh_vars = True ) <EOL> start = self . visit_expr ( stmt . start ) <EOL> stop = self . visit_expr ( stmt . stop ) <EOL> step = self . visit_expr ( stmt . step ) <EOL> var = self . visit_expr ( stmt . var ) <EOL> t = self . to_ctype ( stmt . var . type ) <EOL> body = self . visit_block ( stmt . body ) <EOL> body += self . visit_merge_right ( stmt . merge ) <EOL> body = self . indent ( "<STR_LIT:\n>" + body ) <EOL> s += "<STR_LIT>" <EOL> up_loop = "<STR_LIT>" <EOL> down_loop = "<STR_LIT>" <EOL> if stmt . step . __class__ is Const : <EOL> if stmt . step . value >= <NUM_LIT:0> : <EOL> s += up_loop <EOL> else : <EOL> s += down_loop <EOL> else : <EOL> s += "<STR_LIT>" <EOL> s += up_loop <EOL> s += "<STR_LIT>" <EOL> s += down_loop <EOL> s += "<STR_LIT>" <EOL> return s % locals ( ) <EOL> def visit_Return ( self , stmt ) : <EOL> assert not self . return_by_ref , "<STR_LIT>" % stmt <EOL> if self . return_void : <EOL> return "<STR_LIT>" <EOL> elif isinstance ( stmt . value , Tuple ) : <EOL> struct_type = self . to_ctype ( stmt . value . type ) <EOL> result_elts = "<STR_LIT:U+002CU+0020>" . join ( self . visit_expr ( elt ) for elt in stmt . value . elts ) <EOL> result_value = "<STR_LIT:{>" + result_elts + "<STR_LIT:}>" <EOL> result = self . fresh_var ( struct_type , "<STR_LIT:result>" , result_value ) <EOL> return "<STR_LIT>" % result <EOL> else : <EOL> v = self . visit_expr ( stmt . value ) <EOL> return "<STR_LIT>" % v <EOL> def visit_block ( self , stmts , push = True ) : <EOL> if push : self . push ( ) <EOL> for stmt in stmts : <EOL> s = self . visit_stmt ( stmt ) <EOL> self . append ( s ) <EOL> self . append ( "<STR_LIT:\n>" ) <EOL> return self . indent ( "<STR_LIT:\n>" + self . pop ( ) ) <EOL> def get_fn_name ( self , expr , compiler_kwargs = { } , attributes = [ ] , inline = True ) : <EOL> if expr . __class__ is TypedFn : <EOL> fn = expr <EOL> elif expr . __class__ is Closure : <EOL> fn = expr . fn <EOL> else : <EOL> assert isinstance ( expr . type , ( FnT , ClosureT ) ) , "<STR_LIT>" % ( expr , expr . type ) <EOL> fn = expr . type . fn <EOL> compiler = self . __class__ ( module_entry = False , ** compiler_kwargs ) <EOL> compiled = compiler . compile_flat_source ( fn , attributes = attributes , inline = inline ) <EOL> if compiled . sig not in self . extra_function_signatures : <EOL> for decl in compiled . declarations : <EOL> self . add_decl ( decl ) <EOL> self . extra_objects . update ( compiled . extra_objects ) <EOL> for extra_sig in compiled . extra_function_signatures : <EOL> if extra_sig not in self . extra_function_signatures : <EOL> self . extra_function_signatures . append ( extra_sig ) <EOL> self . extra_functions [ extra_sig ] = compiled . extra_functions [ extra_sig ] <EOL> self . extra_function_signatures . append ( compiled . sig ) <EOL> self . extra_functions [ compiled . sig ] = compiled . src <EOL> for link_flag in compiler . extra_link_flags : <EOL> if link_flag not in self . extra_link_flags : <EOL> self . extra_link_flags . append ( link_flag ) <EOL> for compile_flag in compiler . extra_compile_flags : <EOL> if compile_flag not in self . extra_compile_flags : <EOL> self . extra_compile_flags . append ( compile_flag ) <EOL> return compiled . name <EOL> def get_closure_args ( self , fn ) : <EOL> if isinstance ( fn . type , FnT ) : <EOL> return [ ] <EOL> else : <EOL> assert isinstance ( fn , Closure ) , "<STR_LIT>" % ( fn , fn . type ) <EOL> return self . visit_expr_list ( fn . args ) <EOL> def build_loops ( self , loop_vars , bounds , body ) : <EOL> if len ( loop_vars ) == <NUM_LIT:0> : <EOL> return body <EOL> var = loop_vars [ <NUM_LIT:0> ] <EOL> bound = bounds [ <NUM_LIT:0> ] <EOL> nested = self . build_loops ( loop_vars [ <NUM_LIT:1> : ] , bounds [ <NUM_LIT:1> : ] , body ) <EOL> return """<STR_LIT>""" % ( var , var , bound , var , nested ) <EOL> def visit_TypedFn ( self , expr ) : <EOL> return self . get_fn_name ( expr ) <EOL> def visit_UntypedFn ( self , expr ) : <EOL> return "<STR_LIT:{}>" <EOL> def return_types ( self , fn ) : <EOL> if isinstance ( fn . return_type , TupleT ) : <EOL> return fn . return_type . elt_types <EOL> elif isinstance ( fn . return_type , NoneT ) : <EOL> return [ ] <EOL> else : <EOL> return [ fn . return_type ] <EOL> def visit_flat_fn ( self , fn , return_by_ref = False , attributes = None , inline = True ) : <EOL> if attributes is None : <EOL> attributes = [ ] <EOL> c_fn_name = names . refresh ( fn . name ) . replace ( "<STR_LIT:.>" , "<STR_LIT:_>" ) <EOL> arg_types = [ self . to_ctype ( t ) for t in fn . input_types ] <EOL> arg_names = [ self . name ( old_arg ) for old_arg in fn . arg_names ] <EOL> return_types = self . return_types ( fn ) <EOL> n_return = len ( return_types ) <EOL> if n_return == <NUM_LIT:1> : <EOL> return_type = self . to_ctype ( return_types [ <NUM_LIT:0> ] ) <EOL> self . return_void = ( return_type == NoneType ) <EOL> self . return_by_ref = False <EOL> elif n_return == <NUM_LIT:0> : <EOL> return_type = "<STR_LIT>" <EOL> self . return_void = True <EOL> self . return_by_ref = False <EOL> elif return_by_ref : <EOL> return_type = "<STR_LIT>" <EOL> self . return_void = True <EOL> self . return_by_ref = True <EOL> self . return_var_types = [ self . to_ctype ( t ) for t in return_types ] <EOL> self . return_var_names = [ self . fresh_name ( "<STR_LIT>" % i ) for i in xrange ( n_return ) ] <EOL> arg_types = arg_types + [ "<STR_LIT>" % t for t in self . return_var_types ] <EOL> arg_names = arg_names + self . return_var_names <EOL> else : <EOL> return_type = self . struct_type_from_fields ( return_types ) <EOL> self . return_void = False <EOL> self . return_by_ref = False <EOL> args_str = "<STR_LIT:U+002CU+0020>" . join ( "<STR_LIT>" % ( t , name ) for ( t , name ) in zip ( arg_types , arg_names ) ) <EOL> body_str = self . visit_block ( fn . body ) <EOL> if inline : <EOL> attributes = attributes + [ "<STR_LIT>" ] <EOL> attr_str = "<STR_LIT:U+0020>" . join ( attributes ) <EOL> sig = "<STR_LIT>" % ( return_type , c_fn_name , args_str ) <EOL> src = "<STR_LIT>" % ( attr_str , sig , body_str ) <EOL> return c_fn_name , sig , src <EOL> @ property <EOL> def cache_key ( self ) : <EOL> """<STR_LIT>""" <EOL> return self . __class__ <EOL> _flat_compile_cache = { } <EOL> def compile_flat_source ( self , parakeet_fn , attributes = [ ] , inline = True ) : <EOL> struct_types = set ( t for t in parakeet_fn . type_env . itervalues ( ) <EOL> if isinstance ( t , ( ArrayT , TupleT ) ) ) <EOL> key = parakeet_fn . cache_key , frozenset ( struct_types ) , self . cache_key , tuple ( attributes ) <EOL> if key in self . _flat_compile_cache : <EOL> return self . _flat_compile_cache [ key ] <EOL> name , sig , src = self . visit_flat_fn ( parakeet_fn , attributes = attributes , inline = inline ) <EOL> result = CompiledFlatFn ( <EOL> name = name , <EOL> sig = sig , <EOL> src = src , <EOL> extra_objects = self . extra_objects , <EOL> extra_functions = self . extra_functions , <EOL> extra_function_signatures = self . extra_function_signatures , <EOL> declarations = self . declarations ) <EOL> self . _flat_compile_cache [ key ] = result <EOL> return result </s>
