def convert_conditional_blocks(text: str) -> str: edits: List[CodeEdit] = [] for if_declaration in re.finditer(r"if\s*(\(.*\))\s*\{", text): if_condition = if_declaration.group(1) block_end = _block_end(text, if_declaration.end()) next_word = _next_word(text, block_end) edits.append( CodeEdit(if_declaration.start(), if_declaration.end(), f"if {if_condition} then\n")) edits.append(CodeEdit(block_end, block_end + 1, "")) if next_word != "else": edits.append(CodeEdit(block_end, block_end + 1, "end if;")) for else_declaration in re.finditer(r"else\s*\{", text): block_start = else_declaration.end() block_end = _block_end(text, block_start) edits.append( CodeEdit(else_declaration.start(), else_declaration.end(), "else\n")) edits.append(CodeEdit(block_end, block_end + 1, "end if;\n")) return apply_edits(text, edits)
def declare_invoked_function_return_types(text: str) -> str: edits: List[CodeEdit] = [] for block_name in BLOCKS_WHICH_DECLARE_VARIABLES: for block in _find_function_blocks(text, block_name=block_name): declaration_statements = [] content = text[block.block_start:block.block_end] for function_call in re.finditer(r"(new\s)?([^ \n\t]+)\(.*\)", content): if function_call.group(1): continue # new was found try: invoked_function_name = function_call.group(2) invoked_function_declaration = re.search( r"([^ \n\t]+)\s+function\s+" + invoked_function_name + r"\(.*\)", text) if not invoked_function_declaration: print( f"Warning: Function {invoked_function_name} is never declared." ) continue except: continue function_declared_type = invoked_function_declaration.group(1) declaration_statements.append( f"{function_declared_type}::{invoked_function_name};") edits.append( CodeEdit(block.block_start, block.block_start, "\n" + "\n".join(declaration_statements) + "\n")) return apply_edits(text, edits)
def move_variable_declaration_to_start_of_block(text: str) -> str: edits: List[CodeEdit] = [] for block_name in BLOCKS_WHICH_DECLARE_VARIABLES: for declaration in re.finditer(r"^.*" + block_name + r".*(\(.*\))?.*$", text, flags=re.M): block_start = text.index("{", declaration.start()) + 1 block_end = -1 depth = 0 for bracket in re.finditer(r"(\{|\})", text[declaration.start():]): if text[declaration.start():][bracket.start()] == "{": depth += 1 else: depth -= 1 if depth == 0: block_end = declaration.start() + bracket.start() break code_block_str = text[block_start:block_end] variable_declaration_statements = [] other_statements = [] use_statements = [] for statement in code_block_str.split("\n"): inline_assignation_operator = re.search( r"((.|\s)+::([^=]|\s)*)(=?)", statement) if inline_assignation_operator: if "=" not in inline_assignation_operator.group(4): variable_declaration_statements.append( inline_assignation_operator.group(1).strip( " \n\t;") + ";\n") elif inline_assignation_operator.group(1).strip( " \n\t").startswith("do"): variable_declaration_statements.append( inline_assignation_operator.group(1).strip(" \n\t") [2:] + ";\n") assignation_substatement = "do " + statement[ statement.index("::") + 2:] other_statements.append(assignation_substatement) else: variable_declaration_statements.append( inline_assignation_operator.group(1).strip(" \n\t") + ";\n") assignation_substatement = statement[statement. index("::") + 2:] other_statements.append(assignation_substatement) else: if re.findall(r"^\s*use .*$", statement): use_statements.append(statement) else: other_statements.append(statement) edits.append( CodeEdit( block_start, block_end, "\n" + "\n".join(use_statements) + "\n" + "\n".join(variable_declaration_statements) + "\n".join(other_statements) + "\n")) return apply_edits(text, edits)
def add_implicit_none(text: str) -> str: edits: List[CodeEdit] = [] for block_name in BLOCKS_WHICH_DECLARE_VARIABLES: for block in _find_function_blocks(text, block_name): insert_pos = _find_pos_after_last_use_statement(block) edits.append(CodeEdit(insert_pos, insert_pos, "\nimplicit none;\n")) return apply_edits(text, edits)
def add_name_to_unnamed_program_blocks(text: str) -> str: edits: List[CodeEdit] = [] for program_declaration in re.finditer(r"[^\w\d\n]*program\s*\{", text): if _is_inside_string_block(program_declaration.start(), text): continue edits.append( CodeEdit(program_declaration.start(), program_declaration.end(), "\nprogram main {\n")) return apply_edits(text, edits)
def move_function_parameter_type_declaration_to_body(text: str) -> str: edits: List[CodeEdit] = [] for function_declaration in re.finditer( r"^\s*\S+( |\n)+(function|subroutine)( |\n)+[^\(]+( |\n)*\(", text, re.MULTILINE): if _is_inside_string_block(function_declaration.start(), text): continue depth = 1 declaration_closing_parenthesis = None for parenthesis in re.finditer(r"(\(|\))", text[function_declaration.end():]): if text[function_declaration.end():][parenthesis.start()] == '(': depth += 1 else: depth -= 1 if depth == 0: declaration_closing_parenthesis = parenthesis.start( ) + function_declaration.end() break function_opening_curly_bracket = text.index("{", function_declaration.end()) parameter_str = text[function_declaration.end( ):declaration_closing_parenthesis] parameter_declarations: List[VariableDeclaration] = [] parameter = re.search(r"::( |\n)*[^,\) \n]+", parameter_str) while parameter: identifier = parameter_str[parameter.start() + 2:parameter.end()].strip(" \n\t") declared_type = parameter_str[:parameter.start()].strip(", \n\t") parameter_declarations.append( VariableDeclaration(declared_type, identifier)) parameter_str = parameter_str[parameter.end():] parameter = re.search(r"::( |\n)*[^,\) \n]+", parameter_str) edits.append( CodeEdit( function_declaration.start(), declaration_closing_parenthesis + 1, text[function_declaration.start():function_declaration.end()] + ",".join( Stream(parameter_declarations).map(lambda x: x.identifier)) + ")")) edits.append( CodeEdit( function_opening_curly_bracket, function_opening_curly_bracket + 1, "{\n" + "\n".join( Stream(parameter_declarations).map( lambda x: f"{x.type}::{x.identifier}")))) return apply_edits(text, edits)
def translate_case_sensitive_identifier(text: str) -> str: edits: List[CodeEdit] = [] for word in re.finditer("\w+", text): if _is_inside_string_block(word.start(), text): continue if word.group(0).lower() != word.group(0): edits.append( CodeEdit(word.start(), word.end(), _encode_character_case(word.group(0)))) return apply_edits(text, edits)
def replace_object_reference_type_declaration(text: str) -> str: edits: List[CodeEdit] = [] for declaration in re.finditer(r"(\w+),\s*object\s*::\s*(.+)$", text, flags=re.M): if _is_inside_string_block(declaration.start(), text): continue edits.append( CodeEdit( declaration.start(), declaration.end(), f"type({declaration.group(1)}),pointer::{declaration.group(2).strip(',')}" )) return apply_edits(text, edits)
def remove_curly_brackets(text: str) -> str: code_block_stack = [] brackets = re.finditer(r"\{|\}", text) code_edits: List[CodeEdit] = [] for bracket_match in brackets: start_pos, end_pos = bracket_match.start(), bracket_match.end() if _is_inside_string_block(start_pos, text): continue if text[start_pos] == '{': code_block_stack.append(_previous_keyword(text, start_pos)) code_edits.append(CodeEdit(start_pos, end_pos, "\n")) else: ending_block = code_block_stack.pop() code_edits.append( CodeEdit(start_pos, end_pos, f"\nend {ending_block};\n")) return remove_unused_whitespace(apply_edits(text, code_edits))
def inline_pointer_cast_function(text: str) -> str: edits: List[CodeEdit] = [] for cast_call in re.finditer(r"(\w+)\s*=\s*cast\((\w+)\)", text): if _is_inside_string_block(cast_call.start(), text): continue destination_variable = cast_call.group(1) source_pointer = cast_call.group(2) target_symbol_declaration = _find_symbol_declaration( destination_variable, text, cast_call.start()) if target_symbol_declaration.is_gc_object(): edits.append( CodeEdit( cast_call.start(), cast_call.end(), f"""select type(a => {source_pointer}) class is ({target_symbol_declaration.get_object_declared_type()}) {destination_variable} => a end select""")) return apply_edits(text, edits)
def translate_return_statement(text: str) -> str: edits: List[CodeEdit] = [] for function_block in _find_function_blocks(text): content = text[function_block.block_start:function_block.block_end] if "return" not in content: continue for return_statement in re.finditer(r"return\s+(.+);", content): if _is_inside_string_block(return_statement.start(), text): continue returned_value = return_statement.group(1) edits.append( CodeEdit( function_block.block_start + return_statement.start(), function_block.block_start + return_statement.end(), f"{function_block.function_name} = {returned_value};\n" "return;")) return apply_edits(text, edits)