def visit_stmt(self, node, src_info = None): #print "visit_stmt", node src_info = self.build_src_info(node) srcAddr = src_addr(src_info) if isinstance(node, ast.If): test = self.visit_expr(node.test) if_true = self.visit_stmt_sequence(node.body, src_info) if_false = self.visit_stmt_sequence(node.orelse, src_info) return LibPar.mk_if(test, if_true, if_false, srcAddr) elif isinstance(node, ast.Assign): assert len(node.targets) == 1 return self.visit_assign(node.targets[0], node.value, src_info) elif isinstance(node, ast.Return): return self.visit_return(node, src_info) elif isinstance(node, ast.While): # infrequently used final iteration, not supported for now assert node.orelse == [] or node.orelse is None block = self.visit_stmt_sequence(node.body) test = self.visit_expr(node.test) return LibPar.mk_whileloop(test, block, srcAddr) elif isinstance(node, ast.Expr): return self.visit_expr(node.value) else: raise RuntimeError("Unsupported statement" + str(node))
def parakeet_value_to_python(val): if val.is_scalar: c_type = parakeet_to_c_types[val.data.scalar.ret_type] result = 0 if c_type == c_bool: result = val.data.scalar.ret_scalar_value.boolean elif c_type == c_int: result = val.data.scalar.ret_scalar_value.int32 elif c_type == c_int64: result = val.data.scalar.ret_scalar_value.int64 elif c_type == c_float: result = val.data.scalar.ret_scalar_value.float32 elif c_type == c_double: result = val.data.scalar.ret_scalar_value.float64 else: raise RuntimeError("Return type not supported by Parakeet: " % str(c_type)) return result else: rank = val.data.array.shape_len SHAPE_TYPE = c_int * rank c_shape = SHAPE_TYPE.from_address(val.data.array.shape) STRIDES_TYPE = c_int * val.data.array.strides_len c_strides = STRIDES_TYPE.from_address(val.data.array.strides) parakeet_elt_type = LibPar.get_array_element_type(val.data.array.ret_type) dtype = parakeet_to_dtype[parakeet_elt_type] addr = val.data.array.data shape = tuple(c_shape) strides = tuple(c_strides) ndarray = array_from_memory(addr, shape, strides, dtype) return ndarray
def build_var(name, src_info = None): #Special case for booleans and None if name == 'True': return build_bool(True, src_info) elif name == 'False': return build_bool(False, src_info) elif name == 'None': return mk_none(src_info) else: return LibPar.mk_var(c_char_p(name), src_addr(src_info))
def __call__(self, *args, **kwds): global_values = self._prep_globals() arg_values, kwd_names, kwd_values = _prep_args(args, kwds) ret = LibPar.run_function( self.parakeet_untyped_id, global_values, c_int(len(global_values)), arg_values, c_int(len(arg_values)), kwd_names, kwd_values, c_int(len(kwd_names))) return self._convert_returned_value(ret)
def visit_assign(self, lhs, rhs, src_info = None): """ On the left-hand-side of an assignment we allow either a variable or a tuple of variables. Anything else should signal an error. The right-hand-side is expected to be an expression (and not a statement). """ def mk_lhs_var(node): return build_var(node.id, self.build_src_info(node)) if isinstance(lhs, ast.Name): vars = [mk_lhs_var(lhs)] elif isinstance(lhs, ast.Tuple): assert all([isinstance(elt, ast.Name) for elt in lhs.elts]) vars = [mk_lhs_var(elt) for elt in lhs.elts] else: raise RuntimeError("Unsupported LHS") rhs = self.visit_expr(rhs) return LibPar.mk_assign(list_to_ctypes_array(vars), len(vars), rhs, src_info)
def mk_call(fn, positional_args, kw_names = [], kw_values = [], src_info=None): """ lower-level helper for building a function call, Assumes function is a Parakeet node and that keyword names have already been converted to character pointers """ assert len(kw_names) == len(kw_values) args_array = list_to_ctypes_array(positional_args) n_args = c_int(len(positional_args)) kw_names_array = list_to_ctypes_array(kw_names, c_char_p) kw_values_array = list_to_ctypes_array(kw_values) n_kwds = c_int(len(kw_names)) srcAddr = src_addr(src_info) #print "mk_call", kw_names_array, kw_values_array # paranode fun, paranode *args, int num_args, # char** keywords, paranode* keyword_values, int num_keyword_args, # source_info_t *src_info return LibPar.mk_call( fn, args_array, n_args, kw_names_array, kw_values_array, n_kwds, srcAddr)
def python_value_to_parakeet(arg): if is_array(arg): rank = len(arg.shape) inputShape = arg.ctypes.shape_as(c_int32) inputStrides = arg.ctypes.strides_as(c_int32) npEltType = arg.dtype.type if ((npEltType not in numpy_to_c_types) or (npEltType not in numpy_to_parakeet_types)): raise Exception("Numpy element type unsupported: " + str(npType)) ctype = numpy_to_c_types[npEltType] parakeetType = numpy_to_parakeet_types[npEltType] dataPtr = arg.ctypes.data_as(POINTER(ctype)) parakeetVal = LibPar.mk_host_array(dataPtr, parakeetType, inputShape, rank, inputStrides, rank, arg.nbytes) return c_void_p(parakeetVal) elif arg is None: return LibPar.mk_none_val() elif np.isscalar(arg) or is_zero_rank_array(arg): # unpack zero rank arrays into scalars if is_zero_rank_array(arg): arg = arg[()] if type(arg) in [int, np.int32]: return LibPar.mk_int32(arg) elif type(arg) == np.int64: return LibPar.mk_int64(arg) elif type(arg)in [float, np.float64]: return LibPar.mk_float64(c_double(arg)) elif type(arg) == np.float32: return LibPar.mk_float32(c_float(arg)) elif type(arg)in [bool, np.bool_]: return LibPar.mk_bool(c_bool(arg)) else: raise Exception ("Unknown type: " + str(type(arg))) else: raise Exception ("Input not supported by Parakeet: " + str(arg))
def register_function(f): print "********************************" print " Registering", f print "********************************" if f in VisitedFunctions: "...already visited" untyped_id = VisitedFunctions[f] global_vars = VisitedFunctionGlobals.get(f, []) return untyped_id, global_vars file_name = f.__code__.co_filename line_offset = f.__code__.co_firstlineno global_refs = f.func_globals argspec = inspect.getargspec(f) assert argspec.varargs is None assert argspec.keywords is None body_source = inspect.getsource(f) #function_source(codeInfo) body_ast = ast.parse(body_source) print body_source print ast_to_str(body_ast) body_ast = ast.fix_missing_locations(body_ast) Converter = ASTConverter(global_refs, argspec.args, file_name, line_offset) parakeet_syntax = Converter.visit_module(body_ast) print "Syntax node", parakeet_syntax for other_fn in Converter.seen_functions: if not VisitedFunctions.has_key(other_fn): register_function(other_fn) global_vars = list(Converter.global_variables) n_globals = len(global_vars) globals_array = list_to_ctypes_array(global_vars,c_char_p) if argspec.defaults is None: default_values = [] positional = argspec.args else: default_values = argspec.defaults positional = argspec.args[:-len(default_values)] positional = map(c_char_p, positional) n_positional = len(positional) n_defaults = len(default_values) positional_args_array = list_to_ctypes_array(positional, c_char_p) default_args = argspec.args[n_positional:] default_args = map(c_char_p, default_args) default_args_array = \ list_to_ctypes_array(default_args, c_char_p) # TODO: Default values are currently RUNTIME value, eek! parakeet_default_values = \ [python_value_to_ast_node(v) for v in default_values] default_values_array = list_to_ctypes_array(parakeet_default_values) # register every function that was seen but not registered fn_name_c_str = c_char_p(global_fn_name(f)) print "Calling register with %d/%d/%d global/positional/default" % (n_globals, n_positional, n_defaults) print "args", default_args_array, len(default_args_array) fun_id = c_int( LibPar.register_untyped_function( fn_name_c_str, globals_array, n_globals, positional_args_array, n_positional, default_args_array, default_values_array, n_defaults, parakeet_syntax)) VisitedFunctions[f] = fun_id VisitedFunctionGlobals[f] = global_vars return fun_id, global_vars
def build_bool(b, src_info = None): if b: return LibPar.mk_bool_paranode(1, src_addr(src_info)) else: return LibPar.mk_bool_paranode(0, src_addr(src_info))
def build_long(l, src_info = None): return LibPar.mk_int64_paranode(l, src_addr(src_info))
def set_vectorize(val): LibPar.set_vectorize(val)
def mk_block(stmts, src_info = None): arr = list_to_ctypes_array(stmts) return LibPar.mk_block(arr, len(stmts), src_addr(src_info))
def mk_tuple(elts, src_info = None): arr = list_to_ctypes_array(elts) return LibPar.mk_tuple(arr, len(arr), src_addr(src_info))
def mk_return(elts, src_info=None): arr = list_to_ctypes_array(elts) if len(elts) > 0 else None return LibPar.mk_return(arr, len(elts), src_addr(src_info))
def ast_prim(sym): return c_void_p(LibPar.get_prim(sym))
def build_float(f, src_info = None): return LibPar.mk_double_paranode(c_double(f), src_addr(src_info))
def _run_adverb(self, adverb_name, args, kwds): fn_id = self.parakeet_untyped_id global_values = self._globals_as_python_values() reserved_keywords = ['axis', 'axes', 'fixed', 'combine_fixed'] if 'axis' in kwds: axes = kwds['axis'] elif 'axes' in kwds: axes = kwds['axes'] else: axes = None if axes is not None: try: iter(axes) except: axes = [axes] fixed = kwds.get('fixed', []) try: iter(fixed) except: fixed = [fixed] #TODO: make keywords work for fixed args fixed_values, _, _ = _prep_args(global_values + fixed, {}) if adverb_name.lower() == "map": combine_provided = False combine_fixed_values = _prep_args([], {}) else: combine_provided = True if combine is None: wrapped_combine = self else: wrapped_combine = PAR(combine) combine_id = wrapped_combine.parakeet_untyped_id combine_globals = wrapped_combine._globals_as_python_values()() combine_fixed = kwds.get('combine_fixed', []) try: iter(combine_fixed) except: combine_fixed = [combine_fixed] combine_fixed_values, _, _ = \ _prep_args(combine_globals + combine_fixed, {}) init = kwds.get('init', []) try: iter(init) except: init = [init] if axes is not None: axes_given = True axes_values = _prep_int_list(axes) n_axes = len(axes_values) else: axes_given = False axes_values = None n_axes = 0 init_values = _prep_value_list(init) filtered_kwds = \ dict([(k,v) for (k,v) in kwds.items() if k not in reserved_keywords]) array_values, array_keywords, array_keyword_values = \ _prep_args(args, filtered_kwds) from ctypes import c_int result = LibPar.run_adverb( adverb_name, fn_id, fixed_values, c_int(len(fixed_values)), combine_id, combine_provided, combine_fixed_values, c_int(len(combine_fixed_values)), init_values, c_int(len(init_values)), axes_given, axes_values, c_int(n_axes), array_values, c_int(len(array_values)), array_keywords, array_keyword_values, c_int(len(array_keywords))) return self._convert_returned_value(result)
def build_none(src_info = None): return LibPar.mk_none(src_addr(src_info))
def set_multithreading(val): LibPar.set_multithreading(val)
def build_int(i, src_info = None): return LibPar.mk_int32_paranode(i, src_addr(src_info))