def split_commas(command: str) -> str: rewrite_match = re.match("(.*)(?:\s|^)(rewrite\s+)([^;,]*?,\s*.*)", command, flags=re.DOTALL) unfold_match = re.match("(.*)(unfold\s+)([^;,]*?),\s*(.*)", command, flags=re.DOTALL) if rewrite_match: prefix, rewrite_command, id_and_rest = rewrite_match.group(1, 2, 3) split = split_by_char_outside_matching("\(", "\)", ",", id_and_rest) if not split: return command first_id, rest = split rest = rest[1:] split = split_by_char_outside_matching("\(", "\)", ";|\.", rest) assert split rewrite_rest, command_rest = split by_match = re.match("(.*)(\sby\s.*)", rewrite_rest) in_match = re.match("(.*)(\sin\s.*)", rewrite_rest) postfix = "" if by_match: if " by " not in first_id: postfix += by_match.group(2) if in_match: if " in " not in first_id: postfix += in_match.group(2) first_command = "(" + rewrite_command + first_id + " " + postfix + ")" result = prefix + first_command + ";" + \ split_commas(rewrite_command + rest) return result elif unfold_match: prefix, unfold_command, first_id, rest = unfold_match.group(1, 2, 3, 4) if re.search("\sin\s", unfold_command + first_id): return command split = split_by_char_outside_matching("\(", "\)", ";|\.", rest) assert split unfold_rest, command_rest = split in_match = re.match("(.*)(\sin\s.*)", unfold_rest) postfix = "" if in_match: if "in" not in first_id: postfix += in_match.group(2) first_command = unfold_command + first_id + " " + postfix return prefix + first_command + ";" + split_commas(unfold_command + rest) else: return command
def desugar_now(command: str) -> str: now_match = re.search(r"\bnow\s+", command) while(now_match): prefix = command[:now_match.start()] after_match = command[now_match.end():] split = split_by_char_outside_matching("[\[(]", "[\])]", r"\.\W|\.$|]|\||\)", after_match) assert split body, postfix = split command = f"{prefix}({body} ; easy){postfix}" now_match = re.search(r"\bnow\s+", command) return command
def desugar_assert_by(cmd: str) -> str: assert_by_match = re.search(r"\b(assert.*)\s+by\s+", cmd) if assert_by_match: prefix = cmd[:assert_by_match.start()] after_match = cmd[assert_by_match.end():] split = split_by_char_outside_matching("[\[(]", "[\])]", r"\.\W|\.$|[|]", after_match) assert split body, postfix = split return f"{prefix}{assert_by_match.group(1)} ; [{body}..|] {postfix}" else: return cmd
def desugar_rewrite_by(cmd: str) -> str: rewrite_by_match = re.search(r"\b(rewrite\s*(?:!|<-)?.*?\s+)by\s+", cmd) if rewrite_by_match: prefix = cmd[:rewrite_by_match.start()] after_match = cmd[rewrite_by_match.end():] split = split_by_char_outside_matching("[\[(]", "[\])]", r"\.\W|\.$|[|]|\)|;", after_match) assert split body, postfix = split postfix = desugar_rewrite_by(postfix) return f"{prefix}{rewrite_by_match.group(1)} ; [|{body} ..] {postfix}" else: return cmd
def truncate_tactic_semicolons(sample: ScrapedTactic) \ -> ScrapedTactic: rl, pt, context, tactic = sample newtac = tactic outer_parens_match = re.fullmatch(r"\((.*)\)", newtac.strip()) if outer_parens_match: newtac = outer_parens_match.group(1) splitresult = split_by_char_outside_matching(r"\(|\[", r"\)|\]", ";", newtac) if splitresult: before_semi, after_semi = splitresult newtac = before_semi.strip() + "." return ScrapedTactic(rl, pt, context, newtac)
def linearize_proof(coq: serapi_instance.SerapiInstance, theorem_name: str, command_batch: List[str], verbose: int = 0, skip_nochange_tac: bool = False) -> Iterable[str]: pending_commands_stack: List[Union[str, List[str], None]] = [] while command_batch: while coq.count_fg_goals() == 0: indentation = " " * (len(pending_commands_stack)) if len(pending_commands_stack) == 0: while command_batch: command = command_batch.pop(0) if "Transparent" in command or \ serapi_instance.ending_proof(command): coq.run_stmt(command) yield command return coq.run_stmt("}") yield indentation + "}" if coq.count_fg_goals() > 0: coq.run_stmt("{") yield indentation + "{" pending_commands = pending_commands_stack[-1] if isinstance(pending_commands, list): next_cmd, *rest_cmd = pending_commands dotdotmatch = re.match( "(.*)<\.\.>", next_cmd, flags=re.DOTALL) for cmd in rest_cmd: dotdotmatch = re.match( "(.*)<\.\.>", cmd, flags=re.DOTALL) if dotdotmatch: continue assert serapi_instance.isValidCommand(cmd), \ f"\"{cmd}\" is not a valid command" if (not rest_cmd) and dotdotmatch: pending_commands_stack[-1] = [next_cmd] assert serapi_instance.isValidCommand(dotdotmatch.group(1)), \ f"\"{dotdotmatch.group(1)}\" is not a valid command" command_batch.insert(0, dotdotmatch.group(1)) else: assert serapi_instance.isValidCommand(next_cmd), \ f"\"{next_cmd}\" is not a valid command" command_batch.insert(0, next_cmd) pending_commands_stack[-1] = rest_cmd if rest_cmd else None pass elif pending_commands: assert serapi_instance.isValidCommand(pending_commands), \ f"\"{command}\" is not a valid command" command_batch.insert(0, pending_commands) else: popped = pending_commands_stack.pop() if isinstance(popped, list) and len(popped) > 0 and len(pending_commands_stack) > 1: if pending_commands_stack[-1] is None: pending_commands_stack[-1] = popped elif isinstance(pending_commands_stack[-1], list): if isinstance(popped, list) and "<..>" in popped[-1]: raise LinearizerCouldNotLinearize pending_commands_stack[-1] = popped + \ pending_commands_stack[-1] command = command_batch.pop(0) assert serapi_instance.isValidCommand(command), \ f"command is \"{command}\", command_batch is {command_batch}" comment_before_command = "" command_proper = command while re.fullmatch("\s*\(\*.*", command_proper, flags=re.DOTALL): next_comment, command_proper = \ split_to_next_matching("\(\*", "\*\)", command_proper) command_proper = command_proper[1:] comment_before_command += next_comment if comment_before_command: yield comment_before_command if re.match("\s*[*+-]+\s*|\s*[{}]\s*", command): continue command = serapi_instance.kill_comments(command_proper) if verbose >= 2: eprint(f"Linearizing command \"{command}\"") if "Ltac" in command: coq.run_stmt(command) yield command continue goal_selector_match = re.fullmatch( r"\s*(\d+)\s*:\s*(.*)\.\s*", command) if goal_selector_match: goal_num = int(goal_selector_match.group(1)) rest = goal_selector_match.group(2) if goal_num < 2: raise LinearizerCouldNotLinearize if pending_commands_stack[-1] is None: completed_rest = rest + "." assert serapi_instance.isValidCommand(rest + "."),\ f"\"{completed_rest}\" is not a valid command in {command}" pending_commands_stack[-1] = ["idtac."] * \ (goal_num - 2) + [completed_rest] elif isinstance(pending_commands_stack[-1], str): pending_cmd = pending_commands_stack[-1] pending_commands_stack[-1] = [pending_cmd] * (goal_num - 2) + \ [rest + " ; " + pending_cmd] + [pending_cmd + "<..>"] else: assert isinstance(pending_commands_stack[-1], list) pending_cmd_lst = pending_commands_stack[-1] try: old_selected_cmd = pending_cmd_lst[goal_num - 2] except IndexError: raise LinearizerCouldNotLinearize match = re.match("(.*)\.$", old_selected_cmd, re.DOTALL) assert match, f"\"{old_selected_cmd}\" doesn't match!" cmd_before_period = unwrap(match).group(1) new_selected_cmd = f"{cmd_before_period} ; {rest}." pending_cmd_lst[goal_num - 2] = new_selected_cmd continue if split_by_char_outside_matching("\(", "\)", "\|\||&&", command): coq.run_stmt(command) yield command continue if re.match("\(", command.strip()): inside_parens, after_parens = split_to_next_matching( '\(', '\)', command) command = inside_parens.strip()[1:-1] + after_parens # Extend this to include "by \(" as an opener if you don't # desugar all the "by"s semi_match = split_by_char_outside_matching("try \(|\(|\{\|", "\)|\|\}", "\s*;\s*", command) if semi_match: base_command, rest = semi_match rest = rest.lstrip()[1:] coq.run_stmt(base_command + ".") indentation = " " * (len(pending_commands_stack) + 1) yield indentation + base_command.strip() + "." if re.match("\(", rest) and not \ split_by_char_outside_matching("\(", "\)", "\|\|", rest): inside_parens, after_parens = split_to_next_matching( '\(', '\)', rest) rest = inside_parens[1:-1] + after_parens bracket_match = re.match("\[", rest.strip()) if bracket_match: bracket_command, rest_after_bracket = \ split_to_next_matching('\[', '\]', rest) rest_after_bracket = rest_after_bracket.lstrip()[1:] clauses = multisplit_matching("\[", "\]", "(?<!\|)\|(?!\|)", bracket_command.strip()[1:-1]) commands_list = [cmd.strip() if cmd.strip().strip(".") != "" else "idtac" + cmd.strip() for cmd in clauses] assert commands_list, command dotdotpat = re.compile(r"(.*)\.\.($|\W)") ending_dotdot_match = dotdotpat.match(commands_list[-1]) if ending_dotdot_match: commands_list = commands_list[:-1] + \ ([ending_dotdot_match.group(1)] * (coq.count_fg_goals() - len(commands_list) + 1)) else: starting_dotdot_match = dotdotpat.match(commands_list[0]) if starting_dotdot_match: starting_tac = starting_dotdot_match.group(1) commands_list = [starting_tac] * (coq.count_fg_goals() - len(commands_list) + 1)\ + commands_list[1:] else: for idx, command_case in enumerate(commands_list[1:-1]): middle_dotdot_match = dotdotpat.match(command_case) if middle_dotdot_match: commands_list = \ commands_list[:idx] + \ [command_case] * (coq.count_fg_goals() - len(commands_list) + 1) + \ commands_list[idx+1:] break if rest_after_bracket.strip(): command_remainders = [cmd + ";" + rest_after_bracket for cmd in commands_list] else: command_remainders = [cmd + "." for cmd in commands_list] assert serapi_instance.isValidCommand(command_remainders[0]), \ f"\"{command_remainders[0]}\" is not a valid command" command_batch.insert(0, command_remainders[0]) if coq.count_fg_goals() > 1: for command in command_remainders[1:]: assert serapi_instance.isValidCommand(command), \ f"\"{command}\" is not a valid command" pending_commands_stack.append(command_remainders[1:]) coq.run_stmt("{") yield indentation + "{" else: if coq.count_fg_goals() > 0: assert serapi_instance.isValidCommand(rest), \ f"\"{rest}\" is not a valid command, from {command}" command_batch.insert(0, rest) if coq.count_fg_goals() > 1: assert serapi_instance.isValidCommand(rest), \ f"\"{rest}\" is not a valid command, from {command}" pending_commands_stack.append(rest) coq.run_stmt("{") yield indentation + "{" elif coq.count_fg_goals() > 0: coq.run_stmt(command) indentation = " " * \ (len(pending_commands_stack) + 1) if command.strip() != "Proof." else "" yield indentation + command.strip() if coq.count_fg_goals() > 1: pending_commands_stack.append(None) coq.run_stmt("{") yield indentation + "{" pass