|
29 | 29 | class SimpleLean4SyncExecutor: |
30 | 30 | theorem_regex = r"((((theorem|lemma)[\s]+([^\s:]*))|example)([\S|\s]*?)(:=|=>)[\s]*?)[\s]+" |
31 | 31 | theorem_match = re.compile(theorem_regex, re.MULTILINE) |
32 | | - have_regex = r"(^\s*have\s+([^\s:]*):[=]*([^:]*))(:=\s*by)([\s|\S]*)" |
| 32 | + have_regex = r"(^\s*have\s+([^:]*):([\s|\S]*))(:=\s*by)([\s|\S]*)" |
33 | 33 | have_match = re.compile(have_regex, re.MULTILINE) |
34 | 34 | unsolved_message = "unsolved goals" |
35 | 35 | no_goals = "No goals to be solved" |
@@ -107,6 +107,7 @@ def __init__(self, |
107 | 107 | self._run_exactly = False |
108 | 108 | self._nested_have_counts = 0 |
109 | 109 | self._last_tactic_was_modified = False |
| 110 | + self._last_modified_tactic : str | None = None |
110 | 111 | if self._enable_search: |
111 | 112 | pass |
112 | 113 | pass |
@@ -155,6 +156,7 @@ def reset(self, |
155 | 156 | self._error_messages_since_last_thm = {} |
156 | 157 | self._nested_have_counts = 0 |
157 | 158 | self._last_tactic_was_modified = False |
| 159 | + self._last_modified_tactic : str | None = None |
158 | 160 | if self._enable_search: |
159 | 161 | pass |
160 | 162 | pass |
@@ -239,12 +241,17 @@ def get_current_lemma_name(self) -> Optional[str]: |
239 | 241 |
|
240 | 242 | def _add_last_tactic(self, idx: int, stmt: str): |
241 | 243 | if idx not in self._last_tactics: |
242 | | - stmt = self._have_preprocessing(stmt) |
| 244 | + original_stmt = stmt |
| 245 | + stmt = self._tactic_preprocessing(stmt) |
243 | 246 | indentation = " " * self._nested_have_counts * 2 |
244 | 247 | if self._nested_have_counts > 0: |
245 | 248 | stmt = stmt.lstrip() |
246 | 249 | stmt = indentation + stmt |
247 | | - self._last_tactic_was_modified = True |
| 250 | + self._last_tactic_was_modified = original_stmt != stmt |
| 251 | + if self._last_tactic_was_modified: |
| 252 | + self._last_modified_tactic = stmt |
| 253 | + else: |
| 254 | + self._last_modified_tactic = None |
248 | 255 | self._last_tactics[idx] = stmt |
249 | 256 | self._last_tactic_line_idx = idx |
250 | 257 | # self.logger.info(f"Proofs so far:\n{self._get_tactics_so_far()}") |
@@ -274,9 +281,44 @@ def _have_preprocessing(self, stmt: str) -> str: |
274 | 281 | by = by.rstrip() |
275 | 282 | new_stmt = f"{full_have_stmt}{by}\n{after_tactics_str}" |
276 | 283 | new_stmt = new_stmt.rstrip() |
277 | | - self._last_tactic_was_modified = True |
278 | 284 | return new_stmt |
279 | 285 |
|
| 286 | + def _multiple_goals_tactic_preprocessing(self, stmt: str) -> List[str]: |
| 287 | + # Split the tactics on multiple goals using `<;>` |
| 288 | + initial_space_cnt = len(stmt) - len(stmt.lstrip()) |
| 289 | + stmt_splits = stmt.split("<;>") |
| 290 | + # Initial space cnt |
| 291 | + indentation = " " * initial_space_cnt |
| 292 | + stmt_splits = [ |
| 293 | + indentation + s.strip() for s in stmt_splits |
| 294 | + ] |
| 295 | + return stmt_splits |
| 296 | + |
| 297 | + def _multiline_tactic_preprocessing(self, stmt: str) -> List[str]: |
| 298 | + # Split the tactics with `;` |
| 299 | + initial_space_cnt = len(stmt) - len(stmt.lstrip()) |
| 300 | + stmt_splits = stmt.split(";") |
| 301 | + # Initial space cnt |
| 302 | + indentation = " " * initial_space_cnt |
| 303 | + stmt_splits = [ |
| 304 | + indentation + s.strip() for s in stmt_splits |
| 305 | + ] |
| 306 | + return stmt_splits |
| 307 | + |
| 308 | + def _tactic_preprocessing(self, stmt: str) -> str: |
| 309 | + tactics_multi_goal = self._multiple_goals_tactic_preprocessing(stmt) |
| 310 | + final_multigoal_tactic : List[str] = [] |
| 311 | + for tactic in tactics_multi_goal: |
| 312 | + new_tactics = self._multiline_tactic_preprocessing(tactic) |
| 313 | + final_multiline_tactic : List[str] = [] |
| 314 | + for new_tactic in new_tactics: |
| 315 | + have_stmts = self._have_preprocessing(new_tactic) |
| 316 | + final_multiline_tactic.append(have_stmts) |
| 317 | + multi_line_stmt = ";\n".join(final_multiline_tactic) |
| 318 | + final_multigoal_tactic.append(multi_line_stmt) |
| 319 | + final_stmt = "<;>\n".join(final_multigoal_tactic) |
| 320 | + return final_stmt |
| 321 | + |
280 | 322 | def _get_lean_code_with_tactics(self, idx: int, stmt: str): |
281 | 323 | assert self._last_theorem is not None, "Last theorem should not be None" |
282 | 324 | self._add_last_tactic(idx, stmt) |
|
0 commit comments