def create_get_type_of(var_name, lineno, col_offset, test_unreferenced=True): """ Creates code to get the type of a variable :param var_name: :param lineno: :param col_offset: :param test_unreferenced: :return: """ get_type_of_comment = create_src_comment( "Getting the type of '{0}'".format(var_name), lineno) get_type_of_method = core_language.create_attribute( default_module_type_store_var_name, "get_type_of", line=lineno, column=col_offset) localization = create_localization(lineno, col_offset) if test_unreferenced: get_type_of_call = functions.create_call( get_type_of_method, [localization, core_language.create_str(var_name)]) else: get_type_of_call = functions.create_call(get_type_of_method, [ localization, core_language.create_str(var_name), core_language.create_Name('False') ]) assign_stmts, temp_assign = create_temp_Assign( get_type_of_call, lineno, col_offset, descriptive_var_name=var_name) return flatten_lists(get_type_of_comment, assign_stmts), temp_assign
def create_unsupported_feature_call(localization, feature_name, feature_desc, lineno, col_offset): """ Creates AST nodes to call to the unsupported_python_feature function """ unsupported_feature_func = core_language.create_Name( 'unsupported_python_feature', line=lineno, column=col_offset) unsupported_feature = core_language.create_str(feature_name) unsupported_description = core_language.create_str(feature_desc) return functions.create_call_expression( unsupported_feature_func, [localization, unsupported_feature, unsupported_description])
def create_binary_operator(operator_symbol, left_op, rigth_op, lineno, col_offset, on_aug_assign=False): """ Creates AST Nodes to model a binary operator :param operator_symbol: Name of the operator :param left_op: Left operand (AST Node) :param rigth_op: Right operand (AST Node) :param lineno: Line :param col_offset: Column :param on_aug_assign: Tells if we are into an augment assignment or not :return: List of instructions """ operator_symbol = operator_name_to_symbol(operator_symbol) if on_aug_assign: operator_symbol += "=" op_name = core_language.create_str(operator_symbol) operation_comment = create_src_comment( "Applying the binary operator '{0}'".format(operator_symbol), lineno) operator_call, result_var = create_temp_Assign( operators.create_binary_operator(op_name, left_op, rigth_op, lineno, col_offset), lineno, col_offset, descriptive_var_name="result_" + operator_symbol_to_name(operator_symbol)) return flatten_lists(operation_comment, operator_call), result_var
def create_set_type_of_member(owner_var, member_name, value, lineno, col_offset): """ Creates code to set the type of an object member :param owner_var: :param member_name: :param value: :param lineno: :param col_offset: :return: """ comment = create_src_comment( "Setting the type of the member '{0}' of a type".format(member_name), lineno) localization = create_localization(lineno, col_offset) set_type_of_member_func = core_language.create_attribute( default_module_type_store_var_name, 'set_type_of_member') set_type_of_member_call = functions.create_call_expression( set_type_of_member_func, [ localization, owner_var, core_language.create_str(member_name), value ]) return flatten_lists(comment, set_type_of_member_call)
def create_context_set(func_name, lineno, col_offset, access_parent=True): """ Creates an AST Node that model the call to the type_store.set_context method :param func_name: Name of the function that will do the push to the stack trace :param lineno: Line :param col_offset: Column :param access_parent: Value of the "has access to its parent context" parameter :return: An AST Expr node """ attribute = core_language.create_attribute( stypy_functions.default_module_type_store_var_name, "open_function_context") context_set_call = create_call(attribute, [ core_language.create_str(func_name), core_language.create_num(lineno), core_language.create_num(col_offset), core_language.create_bool(access_parent) ]) left_hand_side = core_language.create_Name( stypy_functions.default_module_type_store_var_name, False) assign_statement = ast.Assign([left_hand_side], context_set_call) return assign_statement
def create_open_ssa_branch(branch_name): """ Creates code to open a new SSA branch :param branch_name: :return: """ attribute = core_language.create_attribute( default_module_type_store_var_name, "open_ssa_branch") clone_call = functions.create_call_expression( attribute, [core_language.create_str(branch_name)]) return clone_call
def assign_as_return_type(value, lineno, col_offset): """ Creates AST nodes to store in default_function_ret_var_name a possible return type """ localization = create_localization(lineno, col_offset) default_function_ret_var = core_language.create_str( default_function_ret_var_name) set_type_of_member_func = core_language.create_attribute( default_module_type_store_var_name, 'set_type_of') return functions.create_call_expression( set_type_of_member_func, [localization, default_function_ret_var, value])
def create_get_type_of_member(owner_var, member_name, lineno, col_offset, test_unreferenced=True): """ Creates code to get the type of an object member :param owner_var: :param member_name: :param lineno: :param col_offset: :param test_unreferenced: :return: """ comment = create_src_comment( "Obtaining the member '{0}' of a type".format(member_name), lineno) localization = create_localization(lineno, col_offset) get_type_of_member_func = core_language.create_attribute( default_module_type_store_var_name, 'get_type_of_member') if not test_unreferenced: get_type_of_member_call = functions.create_call( get_type_of_member_func, [ localization, owner_var, core_language.create_str(member_name), core_language.create_Name('False') ]) else: get_type_of_member_call = functions.create_call( get_type_of_member_func, [localization, owner_var, core_language.create_str(member_name)]) member_stmts, member_var = create_temp_Assign(get_type_of_member_call, lineno, col_offset, member_name) return flatten_lists(comment, member_stmts), member_var
def create_get_type_instance_of(type_name, lineno, col_offset): """ Create code to get an instance of the passed type :param type_name: :param lineno: :param col_offset: :return: """ get_func = core_language.create_Name("get_builtin_python_type_instance") param1 = core_language.create_str(type_name) localization = create_localization(lineno, col_offset) get_list_call = functions.create_call(get_func, [localization, param1]) return create_temp_Assign(get_list_call, lineno, col_offset, type_name.replace(".", "_"))
def create_keyword_dict(keywords): """ Creates a dict with the passed contents :param keywords: :return: """ dict_node = ast.Dict(ctx=ast.Load(), keys=[], values=[]) if keywords is not None: for elem in keywords: dict_node.keys.append(core_language.create_str(elem)) dict_node.values.append(keywords[elem]) return dict_node
def create_open_ssa_context(context_name): """ Creates code to open a new SSA context :param context_name: :return: """ ssa_context_class = core_language.create_Name("SSAContext") attribute = core_language.create_attribute(ssa_context_class, "create_ssa_context") clone_call = functions.create_call( attribute, core_language.create_Name(default_module_type_store_var_name), [core_language.create_str(context_name)]) return create_temp_type_store_Assign(clone_call)
def create_stacktrace_push(func_name, declared_arguments): """ Creates an AST Node that model the call to the localitazion.set_stack_trace method :param func_name: Name of the function that will do the push to the stack trace :param declared_arguments: Arguments of the call :return: An AST Expr node """ # Code to push a new stack trace to handle errors. attribute = core_language.create_attribute("localization", "set_stack_trace") arguments_var = core_language.create_Name("arguments") stack_push_call = create_call(attribute, [ core_language.create_str(func_name), declared_arguments, arguments_var ]) stack_push = ast.Expr() stack_push.value = stack_push_call return stack_push
def create_unary_operator(operator_name, left_op, lineno, col_offset): """ Creates AST Nodes to model an unary operator :param operator_name: Name of the operator :param left_op: operand (AST Node) :param lineno: Line :param col_offset: Column :return: List of instructions """ operator_symbol = operator_name_to_symbol(operator_name) op_name = core_language.create_str(operator_symbol) operation_comment = create_src_comment( "Applying the '{0}' unary operator".format(operator_symbol), lineno) operator_call, result_var = create_temp_Assign( operators.create_unary_operator(op_name, left_op, lineno, col_offset), lineno, col_offset, descriptive_var_name="result_" + operator_symbol_to_name(operator_symbol)) return flatten_lists(operation_comment, operator_call), result_var
def create_set_type_of(var_name, new_value, lineno, col_offset): """ Creates code to set the type of a variable :param var_name: :param new_value: :param lineno: :param col_offset: :return: """ set_type_of_comment = create_src_comment( "Assigning a type to the variable '{0}'".format(var_name), lineno) set_type_of_method = core_language.create_attribute( default_module_type_store_var_name, "set_type_of") localization = create_localization(lineno, col_offset) set_type_of_call = functions.create_call_expression( set_type_of_method, [ localization, core_language.create_str(var_name, lineno, col_offset), new_value ]) return flatten_lists(set_type_of_comment, set_type_of_call)
def obtain_arg_list(args, ismethod=False, isstaticmethod=False): """ Creates an AST List node with the names of the arguments passed to a function :param args: Arguments :param ismethod: Whether to count the first argument (self) or not :param isstaticmethod: Determines if the method is static :return: An AST List """ arg_list = ast.List() arg_list.elts = [] if ismethod and not isstaticmethod: arg_list_contents = args.args[1:] else: arg_list_contents = args.args try: for arg in arg_list_contents: arg_list.elts.append(core_language.create_str(arg.id)) except Exception as ex: print ex return arg_list
def create_arg_number_test(function_def_node, decorators, context=[]): """ Creates an AST Node that model the call to the process_argument_values method. This method is used to check the parameters passed to a function/method in a type inference program :param function_def_node: AST Node with the function definition :param decorators: Decorators of the function :param context: Context passed to the call :return: List of AST nodes that perform the call to the mentioned function and make the necessary tests once it is called """ args_test_resul = core_language.create_Name('arguments', False) # Call to arg test function func = core_language.create_Name('process_argument_values') # Fixed parameters localization_arg = core_language.create_Name('localization') type_store_arg = core_language.create_Name( stypy_functions.default_module_type_store_var_name) # Declaration data arguments # Func name if is_method(context, decorators): if types.type_inspection.is_special_name_method( function_def_node.name): function_name_arg = core_language.create_str( context[-1].name + "." + types.type_inspection.convert_special_name_method( function_def_node.name)) else: function_name_arg = core_language.create_str( context[-1].name + "." + function_def_node.name) type_of_self_arg = core_language.create_Name('type_of_self') else: if types.type_inspection.is_special_name_method( function_def_node.name): function_name_arg = core_language.create_str( types.type_inspection.convert_special_name_method( function_def_node.name)) else: function_name_arg = core_language.create_str( function_def_node.name) type_of_self_arg = core_language.create_Name('None') # Declared param names list param_names_list_arg = obtain_arg_list(function_def_node.args, is_method(context), is_static_method(function_def_node)) # Declared var args parameter name if function_def_node.args.vararg is None: declared_varargs = None else: declared_varargs = function_def_node.args.vararg varargs_param_name = core_language.create_str(declared_varargs) # Declared kwargs parameter name if function_def_node.args.kwarg is None: declared_kwargs = None else: declared_kwargs = function_def_node.args.kwarg kwargs_param_name = core_language.create_str(declared_kwargs) # Call data arguments # Declared defaults list name call_defaults = core_language.create_Name( 'defaults') # function_def_node.args.defaults # Call varargs call_varargs = core_language.create_Name('varargs') # Call kwargs call_kwargs = core_language.create_Name('kwargs') # Store call information into the function object to recursion checks if is_method(context): f_name = function_def_node.name if types.type_inspection.is_special_name_method( function_def_node.name): f_name = types.type_inspection.convert_special_name_method(f_name) f_var_name = core_language.create_attribute( core_language.create_attribute(context[-1].name, f_name), '__dict__') else: if types.type_inspection.is_special_name_method( function_def_node.name): f_var_name = core_language.create_Name( types.type_inspection.convert_special_name_method( function_def_node.name), False) else: f_var_name = core_language.create_Name(function_def_node.name, False) info_storage_instr = [] if function_def_node.name is not '__init__': if is_method(context): subscript_call = create_call_expression( core_language.create_attribute(f_var_name, '__setitem__'), [ core_language.create_str('stypy_localization'), localization_arg ]) info_storage_instr.append(subscript_call) subscript_call = create_call_expression( core_language.create_attribute(f_var_name, '__setitem__'), [ core_language.create_str('stypy_type_of_self'), type_of_self_arg ]) info_storage_instr.append(subscript_call) subscript_call = create_call_expression( core_language.create_attribute(f_var_name, '__setitem__'), [core_language.create_str('stypy_type_store'), type_store_arg]) info_storage_instr.append(subscript_call) subscript_call = create_call_expression( core_language.create_attribute(f_var_name, '__setitem__'), [ core_language.create_str('stypy_function_name'), function_name_arg ]) info_storage_instr.append(subscript_call) subscript_call = create_call_expression( core_language.create_attribute(f_var_name, '__setitem__'), [ core_language.create_str('stypy_param_names_list'), param_names_list_arg ]) info_storage_instr.append(subscript_call) subscript_call = create_call_expression( core_language.create_attribute(f_var_name, '__setitem__'), [ core_language.create_str('stypy_varargs_param_name'), varargs_param_name ]) info_storage_instr.append(subscript_call) subscript_call = create_call_expression( core_language.create_attribute(f_var_name, '__setitem__'), [ core_language.create_str('stypy_kwargs_param_name'), kwargs_param_name ]) info_storage_instr.append(subscript_call) subscript_call = create_call_expression( core_language.create_attribute(f_var_name, '__setitem__'), [ core_language.create_str('stypy_call_defaults'), call_defaults ]) info_storage_instr.append(subscript_call) subscript_call = create_call_expression( core_language.create_attribute(f_var_name, '__setitem__'), [core_language.create_str('stypy_call_varargs'), call_varargs]) info_storage_instr.append(subscript_call) subscript_call = create_call_expression( core_language.create_attribute(f_var_name, '__setitem__'), [core_language.create_str('stypy_call_kwargs'), call_kwargs]) info_storage_instr.append(subscript_call) subscript_call = create_call_expression( core_language.create_attribute(f_var_name, '__setitem__'), [ core_language.create_str('stypy_declared_arg_number'), core_language.create_num(len(function_def_node.args.args)) ]) info_storage_instr.append(subscript_call) else: info_storage_instr.append( core_language.create_Assign( core_language.create_attribute(f_var_name, 'stypy_localization'), localization_arg)) info_storage_instr.append( core_language.create_Assign( core_language.create_attribute(f_var_name, 'stypy_type_of_self'), type_of_self_arg)) info_storage_instr.append( core_language.create_Assign( core_language.create_attribute(f_var_name, 'stypy_type_store'), type_store_arg)) info_storage_instr.append( core_language.create_Assign( core_language.create_attribute(f_var_name, 'stypy_function_name'), function_name_arg)) info_storage_instr.append( core_language.create_Assign( core_language.create_attribute(f_var_name, 'stypy_param_names_list'), param_names_list_arg)) info_storage_instr.append( core_language.create_Assign( core_language.create_attribute(f_var_name, 'stypy_varargs_param_name'), varargs_param_name)) info_storage_instr.append( core_language.create_Assign( core_language.create_attribute(f_var_name, 'stypy_kwargs_param_name'), kwargs_param_name)) info_storage_instr.append( core_language.create_Assign( core_language.create_attribute(f_var_name, 'stypy_call_defaults'), call_defaults)) info_storage_instr.append( core_language.create_Assign( core_language.create_attribute(f_var_name, 'stypy_call_varargs'), call_varargs)) info_storage_instr.append( core_language.create_Assign( core_language.create_attribute(f_var_name, 'stypy_call_kwargs'), call_kwargs)) # Parameter number check call call = create_call(func, [ localization_arg, type_of_self_arg, type_store_arg, function_name_arg, param_names_list_arg, varargs_param_name, kwargs_param_name, call_defaults, call_varargs, call_kwargs ]) assign = core_language.create_Assign(args_test_resul, call) # After parameter number check call argument_errors = core_language.create_Name('arguments') is_error_type = core_language.create_Name('is_error_type') if_test = create_call(is_error_type, argument_errors) if is_constructor(function_def_node): argument_errors = None # core_language.create_Name('None') body = [create_context_unset(), create_return(argument_errors)] if_ = conditional_statements.create_if(if_test, body) return info_storage_instr + [assign, if_]