Skip to content

Commit 3a95a2f

Browse files
hyperpolymathclaude
andcommitted
feat(extractors): add premise extraction for isabelle/hol4/fstar/agda/idris2/mizar/tlaps/why3/acl2 (Stage 1c)
Add targeted premise extraction logic for 9 additional provers: - Isabelle/HOL: extract from using/metis/rule/erule/drule/frule clauses - HOL4: extract from metis_tac/rw/fs/simp_tac bracket notation [theorem1, theorem2] - F*: extract from by/using clauses with lemma names - Agda: extract qualified module names (e.g., Relation.Binary.PropositionalEquality.refl) - Idris2: extract from exact/apply/with patterns (parity with Lean4) - Mizar: extract from by THEOREM_NAME:N and from SCHEME_NAME patterns - TLAPS: extract from BY DEF theorem_name and PROVE ... BY patterns - Why3: extract from use import module_name clauses - ACL2: extract from :use/:in-theory/:enable/:disable hint clauses All extractors use try/catch guards for regex robustness. Unique premises per example to prevent duplication. Dispatch updated to route all 9 provers through specialized extraction functions. ROADMAP milestone: Stage 1c (28 of 50 extractors with premise gaps). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 3fb6c6b commit 3a95a2f

1 file changed

Lines changed: 331 additions & 5 deletions

File tree

src/julia/extract_training_data.jl

Lines changed: 331 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,20 @@ function extract_from_file(prover::String, filepath::String)::Vector{ProofExampl
7979
examples = extract_pvs_proofs(filepath, content)
8080
elseif prover == "HOL4"
8181
examples = extract_hol4_proofs(filepath, content)
82+
elseif prover == "Isabelle"
83+
examples = extract_isabelle_proofs(filepath, content)
84+
elseif prover == "Agda"
85+
examples = extract_agda_proofs(filepath, content)
86+
elseif prover == "Idris2"
87+
examples = extract_idris2_proofs(filepath, content)
88+
elseif prover == "Mizar"
89+
examples = extract_mizar_proofs(filepath, content)
90+
elseif prover == "TLAPS"
91+
examples = extract_tlaps_proofs(filepath, content)
92+
elseif prover == "Why3"
93+
examples = extract_why3_proofs(filepath, content)
94+
elseif prover == "F*"
95+
examples = extract_fstar_proofs(filepath, content)
8296
else
8397
# Generic extraction for other provers
8498
examples = extract_generic_proofs(prover, filepath, content)
@@ -182,13 +196,28 @@ function extract_acl2_proofs(filepath::String, content::String)::Vector{ProofExa
182196
push!(hints, strip(hint_block.captures[1]))
183197
end
184198

199+
# Extract premises from :use, :in-theory, :enable, :disable clauses
200+
premises = String[]
201+
try
202+
# Pattern: :use (:instance theorem-name ...) or :use theorem-name
203+
for use_match in eachmatch(r":use\s*\(?:?instance\s+([a-z][a-z0-9\-]*)", hint_block !== nothing ? hint_block.captures[1] : "")
204+
push!(premises, use_match.captures[1])
205+
end
206+
# Pattern: :enable theorem-name or :in-theory (enable theorem-name)
207+
for enable_match in eachmatch(r":(?:in-theory\s*\(|enable\s+)([a-z][a-z0-9\-]*)", hint_block !== nothing ? hint_block.captures[1] : "")
208+
push!(premises, enable_match.captures[1])
209+
end
210+
catch
211+
# If regex fails, leave premises empty
212+
end
213+
185214
push!(examples, ProofExample(
186215
"ACL2",
187216
filepath,
188217
theorem_name,
189218
formula,
190219
hints,
191-
String[], # ACL2 premises extracted differently
220+
unique(premises),
192221
true
193222
))
194223
end
@@ -225,26 +254,323 @@ function extract_pvs_proofs(filepath::String, content::String)::Vector{ProofExam
225254
end
226255

227256
"""
228-
Extract HOL4 proofs
257+
Extract Isabelle/HOL proofs
258+
"""
259+
function extract_isabelle_proofs(filepath::String, content::String)::Vector{ProofExample}
260+
examples = ProofExample[]
261+
262+
# Match theorem/lemma declarations with proof blocks
263+
for m in eachmatch(r"(theorem|lemma)\s+([A-Za-z_][A-Za-z0-9_\"]*)\s*:([^=]+)=\s*(.+?)(?:\n(?:theorem|lemma|end|definition)|\Z)"s, content)
264+
theorem_name = m.captures[2]
265+
goal = strip(m.captures[3])
266+
proof_block = m.captures[4]
267+
268+
# Extract tactics from proof
269+
tactics = [strip(t) for t in split(proof_block, r"<;>|;|\n") if !isempty(strip(t))]
270+
271+
# Extract premises: using, metis, apply (rule), apply (erule), apply (drule), apply (frule)
272+
premises = String[]
273+
try
274+
for tactic in tactics
275+
# Pattern: using theorem_name or metis theorem_name1 theorem_name2
276+
for premise_match in eachmatch(r"(?:using|metis|rule|erule|drule|frule)\s+([A-Za-z_][A-Za-z0-9_\.]*)", tactic)
277+
push!(premises, premise_match.captures[1])
278+
end
279+
# Pattern: apply (rule theorem_name) or by (metis theorem_name)
280+
if occursin(r"apply\s*\((?:rule|erule|drule|frule)", tactic)
281+
for rule_match in eachmatch(r"apply\s*\((?:rule|erule|drule|frule)\s+([A-Za-z_][A-Za-z0-9_\.]*)", tactic)
282+
push!(premises, rule_match.captures[1])
283+
end
284+
end
285+
end
286+
catch
287+
# If regex fails, continue with empty premises
288+
end
289+
290+
push!(examples, ProofExample(
291+
"Isabelle",
292+
filepath,
293+
theorem_name,
294+
goal,
295+
tactics,
296+
unique(premises),
297+
true
298+
))
299+
end
300+
301+
return examples
302+
end
303+
304+
"""
305+
Extract Agda proofs (qualified names and definition references)
306+
"""
307+
function extract_agda_proofs(filepath::String, content::String)::Vector{ProofExample}
308+
examples = ProofExample[]
309+
310+
# Match function/theorem declarations with where clauses
311+
for m in eachmatch(r"([A-Za-z_][A-Za-z0-9_]*)\s*:\s*([^\s=]+(?:\s*→[^\s=]+)*)\s*(?:where|=)"s, content)
312+
theorem_name = m.captures[1]
313+
goal = strip(m.captures[2])
314+
315+
# Extract qualified names (e.g., Relation.Binary.PropositionalEquality.refl)
316+
premises = String[]
317+
try
318+
for qual_match in eachmatch(r"([A-Za-z][A-Za-z0-9_]*(?:\.[A-Za-z][A-Za-z0-9_]*)+)", content[m.offset:min(m.offset+500, end)])
319+
push!(premises, qual_match.captures[1])
320+
end
321+
catch
322+
# Continue with empty premises
323+
end
324+
325+
tactics = String["where"] # Agda uses where clauses
326+
327+
push!(examples, ProofExample(
328+
"Agda",
329+
filepath,
330+
theorem_name,
331+
goal,
332+
tactics,
333+
unique(premises),
334+
true
335+
))
336+
end
337+
338+
return examples
339+
end
340+
341+
"""
342+
Extract Idris2 proofs (similar to Lean: exact, apply, with patterns)
343+
"""
344+
function extract_idris2_proofs(filepath::String, content::String)::Vector{ProofExample}
345+
examples = ProofExample[]
346+
347+
# Match theorem/lemma declarations
348+
for m in eachmatch(r"(theorem|lemma)\s+([A-Za-z_][A-Za-z0-9_]*)\s*:([^:=]+):=\s*by\s*(.+?)(?:\n\n|\n(?:theorem|lemma)|\Z)"s, content)
349+
theorem_name = m.captures[2]
350+
goal = strip(m.captures[3])
351+
proof_block = m.captures[4]
352+
353+
# Extract tactics
354+
tactics = [strip(t) for t in split(proof_block, r"<;>|;|\n") if !isempty(strip(t))]
355+
356+
# Extract premises: exact theorem_name, apply theorem_name, with theorem_name
357+
premises = String[]
358+
try
359+
for tactic in tactics
360+
for premise_match in eachmatch(r"(?:exact|apply|with)\s+([A-Za-z_][A-Za-z0-9_\.]*)", tactic)
361+
push!(premises, premise_match.captures[1])
362+
end
363+
end
364+
catch
365+
# Continue with empty premises
366+
end
367+
368+
push!(examples, ProofExample(
369+
"Idris2",
370+
filepath,
371+
theorem_name,
372+
goal,
373+
tactics,
374+
unique(premises),
375+
true
376+
))
377+
end
378+
379+
return examples
380+
end
381+
382+
"""
383+
Extract Mizar proofs (THEOREM references with justifications)
384+
"""
385+
function extract_mizar_proofs(filepath::String, content::String)::Vector{ProofExample}
386+
examples = ProofExample[]
387+
388+
# Match theorem/definition declarations
389+
for m in eachmatch(r"(theorem|definition)\s+([A-Z_][A-Z0-9_]*)\s*:([^;]+);"s, content)
390+
theorem_name = m.captures[2]
391+
goal = strip(m.captures[3])
392+
393+
# Extract premises from "by THEOREM_NAME:1" and "from SCHEME_NAME(...)" patterns
394+
premises = String[]
395+
try
396+
for by_match in eachmatch(r"by\s+([A-Z_][A-Z0-9_]*(?::[0-9]+)?)", goal)
397+
push!(premises, by_match.captures[1])
398+
end
399+
for from_match in eachmatch(r"from\s+([A-Z_][A-Z0-9_]*)", goal)
400+
push!(premises, from_match.captures[1])
401+
end
402+
catch
403+
# Continue with empty premises
404+
end
405+
406+
push!(examples, ProofExample(
407+
"Mizar",
408+
filepath,
409+
theorem_name,
410+
goal,
411+
String["by"], # Mizar proofs use "by" justifications
412+
unique(premises),
413+
true
414+
))
415+
end
416+
417+
return examples
418+
end
419+
420+
"""
421+
Extract TLAPS (TLA+) proofs
422+
"""
423+
function extract_tlaps_proofs(filepath::String, content::String)::Vector{ProofExample}
424+
examples = ProofExample[]
425+
426+
# Match theorem declarations
427+
for m in eachmatch(r"(THEOREM|LEMMA)\s+([A-Za-z_][A-Za-z0-9_]*)\s*(?:==|<=>)\s*(.+?)(?:\n(?:THEOREM|LEMMA|PROOF)|\Z)"s, content)
428+
theorem_name = m.captures[2]
429+
goal = strip(m.captures[3])
430+
431+
# Extract premises from <1>1 BY DEF theorem_name and PROVE ... BY theorem_name
432+
premises = String[]
433+
try
434+
for by_match in eachmatch(r"BY(?:\s+DEF)?\s+([A-Za-z_][A-Za-z0-9_]*)", goal)
435+
push!(premises, by_match.captures[1])
436+
end
437+
for prove_match in eachmatch(r"PROVE\s+[^B]*BY\s+([A-Za-z_][A-Za-z0-9_]*)", goal)
438+
push!(premises, prove_match.captures[1])
439+
end
440+
catch
441+
# Continue with empty premises
442+
end
443+
444+
push!(examples, ProofExample(
445+
"TLAPS",
446+
filepath,
447+
theorem_name,
448+
goal,
449+
String["BY"],
450+
unique(premises),
451+
true
452+
))
453+
end
454+
455+
return examples
456+
end
457+
458+
"""
459+
Extract Why3 proofs (use/import and by clauses)
460+
"""
461+
function extract_why3_proofs(filepath::String, content::String)::Vector{ProofExample}
462+
examples = ProofExample[]
463+
464+
# Match lemma/theorem declarations
465+
for m in eachmatch(r"(lemma|theorem)\s+([a-z_][a-z0-9_]*)\s*:(.+?)(?:proof|by|end)"is, content)
466+
theorem_name = m.captures[2]
467+
goal = strip(m.captures[3])
468+
469+
# Extract premises from "use import module_name" and "by <term>"
470+
premises = String[]
471+
try
472+
for use_match in eachmatch(r"use\s+(?:import\s+)?([A-Za-z_][A-Za-z0-9_\.]*)", goal)
473+
push!(premises, use_match.captures[1])
474+
end
475+
catch
476+
# Continue with empty premises
477+
end
478+
479+
push!(examples, ProofExample(
480+
"Why3",
481+
filepath,
482+
theorem_name,
483+
goal,
484+
String["by"],
485+
unique(premises),
486+
true
487+
))
488+
end
489+
490+
return examples
491+
end
492+
493+
"""
494+
Extract F* proofs (by and using clauses with lemma names)
495+
"""
496+
function extract_fstar_proofs(filepath::String, content::String)::Vector{ProofExample}
497+
examples = ProofExample[]
498+
499+
# Match val/lemma declarations
500+
for m in eachmatch(r"(?:val|lemma)\s+([a-z_][a-z0-9_]*)\s*:(.+?)(?:=|by)"is, content)
501+
theorem_name = m.captures[1]
502+
goal = strip(m.captures[2])
503+
504+
# Extract premises from "by lemma_name" and "using lemma_name"
505+
premises = String[]
506+
try
507+
for premise_match in eachmatch(r"(?:by|using)\s+([A-Za-z_][A-Za-z0-9_\.]*)", goal)
508+
push!(premises, premise_match.captures[1])
509+
end
510+
catch
511+
# Continue with empty premises
512+
end
513+
514+
push!(examples, ProofExample(
515+
"F*",
516+
filepath,
517+
theorem_name,
518+
goal,
519+
String["by"],
520+
unique(premises),
521+
true
522+
))
523+
end
524+
525+
return examples
526+
end
527+
528+
"""
529+
Extract HOL4 proofs (with premise extraction from tactic brackets)
229530
"""
230531
function extract_hol4_proofs(filepath::String, content::String)::Vector{ProofExample}
231532
examples = ProofExample[]
232533

233534
# Match store_thm or prove calls
234-
for m in eachmatch(r"(store_thm|prove)\s*\(\s*[`\"]([^`\"]*)[`\"],\s*`([^`]*)`"s, content)
535+
for m in eachmatch(r"(store_thm|prove)\s*\(\s*[`\"]([^`\"]*)[`\"],\s*`([^`]*)`\s*,\s*(.+?)\)"s, content)
235536
theorem_name = strip(m.captures[2])
236537
goal = strip(m.captures[3])
538+
tactic_block = m.captures[4]
237539

238540
# Extract tactics (simplified)
239-
tactics = String["REWRITE_TAC"] # Common HOL4 tactic
541+
tactics = [strip(t) for t in split(tactic_block, r">>|THEN") if !isempty(strip(t))]
542+
if isempty(tactics)
543+
tactics = String["REWRITE_TAC"]
544+
end
545+
546+
# Extract premises from tactic arguments: metis_tac [theorem1, theorem2], rw [theorem1], fs [theorem1]
547+
premises = String[]
548+
try
549+
for tactic_match in eachmatch(r"\b(?:metis_tac|rw|fs|simp_tac|METIS_TAC)\s*\[([^\]]+)\]", tactic_block)
550+
# Extract individual theorem names from bracket contents
551+
bracket_content = tactic_match.captures[1]
552+
for item in split(bracket_content, r",\s*")
553+
item = strip(item)
554+
# Extract theorem name (remove any type annotations or arguments)
555+
if !isempty(item)
556+
theorem_ref = match(r"([A-Za-z_][A-Za-z0-9_\.]*)", item)
557+
if theorem_ref !== nothing
558+
push!(premises, theorem_ref.captures[1])
559+
end
560+
end
561+
end
562+
end
563+
catch
564+
# Continue with empty premises
565+
end
240566

241567
push!(examples, ProofExample(
242568
"HOL4",
243569
filepath,
244570
theorem_name,
245571
goal,
246572
tactics,
247-
String[],
573+
unique(premises),
248574
true
249575
))
250576
end

0 commit comments

Comments
 (0)