Skip to content

Commit

Permalink
cleanup handling of unsupported commands (Skip)
Browse files Browse the repository at this point in the history
  • Loading branch information
gares committed Sep 26, 2024
1 parent 51ad5ad commit dbe099b
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 38 deletions.
9 changes: 3 additions & 6 deletions language-server/dm/executionManager.ml
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ let is_diagnostics_enabled () = !options.enableDiagnostics
let get_options () = !options

type prepared_task =
| PSkip of { id: sentence_id; error: Pp.t option }
| PSkip of skip
| PExec of executable_sentence
| PRestart of { id : sentence_id; to_ : sentence_id }
| PQuery of executable_sentence
Expand Down Expand Up @@ -657,11 +657,8 @@ let execute st (vs, events, interrupted) task =
end else
try
match task with
| PSkip { id; error = err } ->
let v = match err with
| None -> success vs
| Some msg -> error None None msg vs
in
| PSkip { id; error = e } ->
let v = error None None e vs in
let st = update st id v in
(st, vs, events, false, exec_error_id_of_outcome v id)
| PExec { id; ast; synterp; error_recovery } ->
Expand Down
103 changes: 72 additions & 31 deletions language-server/dm/scheduler.ml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ type error_recovery_strategy =

type restart = { id : sentence_id; to_ : sentence_id }

type skip = { id: sentence_id; error: Pp.t }

type executable_sentence = {
id : sentence_id;
ast : Synterp.vernac_control_entry;
Expand All @@ -33,7 +35,7 @@ type executable_sentence = {
}

type task =
| Skip of { id: sentence_id; error: Pp.t option }
| Skip of skip
| Exec of executable_sentence
| Restart of restart
| OpaqueProof of { terminator: executable_sentence;
Expand All @@ -48,12 +50,17 @@ type task =
| ModuleWithSignature of ast list
*)

type executable_sentence_or_restart =
(* like a sub type of task, restricted what we can put in a proof *)
type proof_command =
| E of executable_sentence
| R of restart
| S of skip

let id_of_proof_command = function
| S { id } | E { id } | R { id } -> id

type proof_block = {
proof_sentences : executable_sentence_or_restart list;
proof_sentences : proof_command list;
opener_id : sentence_id;
}

Expand All @@ -79,19 +86,29 @@ let initial_schedule = {
dependencies = SM.empty;
}

let push_executable_proof_sentence ex_sentence block =
let push_Exec_in_block ex_sentence block =
{ block with proof_sentences = E ex_sentence :: block.proof_sentences }

let push_ex_sentence ex_sentence st =
let push_Exec ex_sentence st =
match st.proof_blocks with
| [] -> { st with document_scope = ex_sentence.id :: st.document_scope }
| l::q -> { st with proof_blocks = push_executable_proof_sentence ex_sentence l :: q }
| [] -> { st with document_scope = ex_sentence.id :: st.document_scope }, Exec ex_sentence
| l::q -> { st with proof_blocks = push_Exec_in_block ex_sentence l :: q }, Exec ex_sentence

let push_restart_command id to_ block = { block with proof_sentences = R { id; to_ } :: block.proof_sentences }
let push_restart id st =
let push_Restart_in_block r block = { block with proof_sentences = R r :: block.proof_sentences }
let push_Restart id st =
match st.proof_blocks with
| [] -> st, Skip { id; error = Some (Pp.str "Restart can only be used inside a proof.")}
| l::q -> { st with proof_blocks = push_restart_command id l.opener_id l :: q }, Restart { id; to_ = l.opener_id }
| [] -> st, Skip { id; error = (Pp.str "Restart can only be used inside a proof.")}
| l :: q ->
let r = { id; to_ = l.opener_id } in
{ st with proof_blocks = push_Restart_in_block r l :: q }, Restart r

let push_Skip_in_block s block = { block with proof_sentences = S s :: block.proof_sentences }
let push_Skip st id error =
let v = { id; error } in
match st.proof_blocks with
| [] -> st, Skip v
| l::q -> { st with proof_blocks = push_Skip_in_block v l :: q }, Skip v


(* Not sure what the base_id for nested lemmas should be, e.g.
Lemma foo : X.
Expand All @@ -106,27 +123,28 @@ let base_id st =
| block :: l ->
begin match block.proof_sentences with
| [] -> aux l
| S { id } :: _ -> Some id
| E { id } :: _ -> Some id
| R { to_ } :: _ -> Some to_
end
in
aux st.proof_blocks

let open_proof_block ex_sentence st =
let st = push_ex_sentence ex_sentence st in
let st, ex = push_Exec ex_sentence st in
let block = { proof_sentences = []; opener_id = ex_sentence.id } in
{ st with proof_blocks = block :: st.proof_blocks }
{ st with proof_blocks = block :: st.proof_blocks }, ex

let extrude_side_effect ex_sentence st =
let document_scope = ex_sentence.id :: st.document_scope in
let proof_blocks = List.map (push_executable_proof_sentence ex_sentence) st.proof_blocks in
{ st with document_scope; proof_blocks }
let proof_blocks = List.map (push_Exec_in_block ex_sentence) st.proof_blocks in
{ st with document_scope; proof_blocks }, Exec ex_sentence

let flatten_proof_block st =
match st.proof_blocks with
| [] -> st
| [block] ->
let document_scope = CList.uniquize @@ List.map (function E { id } -> id | R { id } -> id) block.proof_sentences @ st.document_scope in
let document_scope = CList.uniquize @@ List.map id_of_proof_command block.proof_sentences @ st.document_scope in
{ st with document_scope; proof_blocks = [] }
| block1 :: block2 :: tl -> (* Nested proofs. TODO check if we want to extrude one level or directly to document scope *)
let proof_sentences = CList.uniquize @@ block1.proof_sentences @ block2.proof_sentences in
Expand Down Expand Up @@ -176,7 +194,7 @@ let find_proof_using_annotation { proof_sentences } =
let is_opaque_flat_proof terminator section_depth block =
let open Vernacextend in
let has_side_effect = function
| R _ -> true
| R _ | S _ -> true
| E { classif } -> match classif with
| VtStartProof _ | VtSideff _ | VtQed _ | VtProofMode _ | VtMeta -> true
| VtProofStep _ | VtQuery -> false
Expand All @@ -194,41 +212,64 @@ let push_state id ast synterp classif st =
let ex_sentence = { id; ast; classif; synterp; error_recovery = RSkip } in
match classif with
| VtStartProof _ ->
base_id st, open_proof_block ex_sentence st, Exec ex_sentence
let base = base_id st in
let st, task = open_proof_block ex_sentence st in
base, st, task
| VtQed terminator_type ->
log "scheduling a qed";
begin match st.proof_blocks with
| [] -> (* can happen on ill-formed documents *)
base_id st, push_ex_sentence ex_sentence st, Exec ex_sentence
let base = base_id st in
let st, task = push_Exec ex_sentence st in
base, st, task
| block :: pop ->
(* TODO do not delegate if command with side effect inside the proof or nested lemmas *)
match is_opaque_flat_proof terminator_type st.section_depth block with
| Some proof_using ->
log "opaque proof";
let terminator = { ex_sentence with error_recovery = RAdmitted } in
let tasks = List.rev_map (function E x -> x | R _ -> assert false) block.proof_sentences in
let tasks = List.rev_map (function E x -> x | R _ | S _ -> assert false) block.proof_sentences in
let st = { st with proof_blocks = pop } in
base_id st, push_ex_sentence ex_sentence st, OpaqueProof { terminator; opener_id = block.opener_id; tasks; proof_using }
let base = base_id st in
let st, _task = push_Exec ex_sentence st in
base, st, OpaqueProof { terminator; opener_id = block.opener_id; tasks; proof_using }
| None ->
log "not an opaque proof";
let st = flatten_proof_block st in
base_id st, push_ex_sentence ex_sentence st, Exec ex_sentence
let base = base_id st in
let st, task = push_Exec ex_sentence st in
base, st, task
end
| VtQuery -> (* queries have no impact, we don't push them *)
base_id st, st, Query ex_sentence
| VtProofStep _ ->
base_id st, push_ex_sentence ex_sentence st, Exec ex_sentence
let base = base_id st in
let st, task = push_Exec ex_sentence st in
base, st, task
| VtSideff _ ->
base_id st, extrude_side_effect ex_sentence st, Exec ex_sentence
let base = base_id st in
let st, task = extrude_side_effect ex_sentence st in
base, st, task
| VtMeta ->
begin match ast.CAst.v.expr with
| Vernacexpr.(VernacSynPure VernacRestart) ->
let v = ast.CAst.v in
begin match v.expr, v.control with
| Vernacexpr.(VernacSynPure VernacRestart), [] ->
let base = base_id st in
let st, task = push_Restart ex_sentence.id st in
base, st, task
| Vernacexpr.(VernacSynPure VernacRestart), _ :: _ ->
let base = base_id st in
let st, task = push_Skip st id (Pp.str "Restart cannot be decorated by controls like Time, Fail, etc...") in
base, st, task
| _ ->
let base = base_id st in
let st, t = push_restart ex_sentence.id st in
base, st, t (* TOOD: control *)
| _ -> base_id st, push_ex_sentence ex_sentence st, Skip { id; error = Some (Pp.str "Unsupported command") }
let st, task = push_Skip st id (Pp.str "Unsupported navigation command") in
base, st, task
end
| VtProofMode _ -> base_id st, push_ex_sentence ex_sentence st, Skip { id; error = Some (Pp.str "Unsupported command") }
| VtProofMode _ ->
let base = base_id st in
let st, task = push_Skip st id (Pp.str "Unsupported command") in
base, st, task

let string_of_task (task_id,(base_id,task)) =
let s = match task with
Expand All @@ -241,7 +282,7 @@ let string_of_task (task_id,(base_id,task)) =
Format.sprintf "[%s] : [%s] -> %s" (Stateid.to_string task_id) (Option.cata Stateid.to_string "init" base_id) s

let _string_of_state st =
let scopes = (List.map (fun b -> List.map (function E { id } -> id | R { id } -> id) b.proof_sentences) st.proof_blocks) @ [st.document_scope] in
let scopes = (List.map (fun b -> List.map id_of_proof_command b.proof_sentences) st.proof_blocks) @ [st.document_scope] in
String.concat "|" (List.map (fun l -> String.concat " " (List.map Stateid.to_string l)) scopes)

let schedule_sentence (id, (ast, classif, synterp_st)) st schedule =
Expand Down
4 changes: 3 additions & 1 deletion language-server/dm/scheduler.mli
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ type error_recovery_strategy =

type restart = { id : sentence_id; to_ : sentence_id }

type skip = { id: sentence_id; error: Pp.t }

type executable_sentence = {
id : sentence_id;
ast : Synterp.vernac_control_entry;
Expand All @@ -38,7 +40,7 @@ type executable_sentence = {
}

type task =
| Skip of { id: sentence_id; error: Pp.t option }
| Skip of skip
| Exec of executable_sentence
| Restart of restart
| OpaqueProof of { terminator: executable_sentence;
Expand Down

0 comments on commit dbe099b

Please sign in to comment.