Skip to content

[WIP] 🐕‍🦺 Cooltt Server v2.0 #289

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 39 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
1bab8ff
Add socket communication code for a cooltt display server
TOTBWF Aug 10, 2021
856f19b
Add syntax for "Probe Holes"
TOTBWF Aug 10, 2021
bc5b903
Use a 'ref' to hold the cooltt server handle
TOTBWF Aug 10, 2021
331d422
Add 'probe_goal' family of tactics
TOTBWF Aug 10, 2021
2eb241f
Add server communication inside elaborator
TOTBWF Aug 10, 2021
bba9713
Server initialization + command line args
TOTBWF Aug 10, 2021
e42d970
Fix issue with emacs mode + extra args
TOTBWF Aug 10, 2021
115b838
Update protocol to perform more heavy lifting on the cooltt side
TOTBWF Aug 26, 2021
f2b3c71
Update zsh completion
favonia Aug 27, 2021
d79782d
Merge remote-tracking branch 'origin/main' into cooltt-server
TOTBWF Sep 2, 2021
5a8aeb1
Replace ProbeHole with Visualize
TOTBWF Sep 2, 2021
c30a940
Update syntax highlighting
TOTBWF Sep 2, 2021
10e4fff
Add ability to pass in server hostname, rework options handling a bit
TOTBWF Sep 2, 2021
a568129
Update message format to track changes to coolttviz
TOTBWF Sep 22, 2021
36717bd
Fix Test Suite
TOTBWF Sep 23, 2021
3d8480a
Remove old server code
TOTBWF Nov 24, 2021
2777db2
Add a message queue for emitting metadata from the refiner
TOTBWF Nov 24, 2021
2beea3a
Thread through a null job queue into the refiner
TOTBWF Nov 24, 2021
b03d146
Start implementing LSP server
TOTBWF Nov 25, 2021
af99c13
Fix some issues with the core lsp impl
TOTBWF Nov 25, 2021
3435bfa
Add 'Executor.ml' for running server actions
TOTBWF Nov 25, 2021
0b24b1c
Add emacs config for lsp integration
TOTBWF Nov 25, 2021
10e5aaf
Pull 'elaborate_typed_term' into the elaborator
TOTBWF Nov 25, 2021
c5f6839
Remove job queue in favor of metadata list
TOTBWF Nov 25, 2021
1306aac
Update main.ml with server command
TOTBWF Nov 25, 2021
a72fd57
Add type hovers
TOTBWF Nov 25, 2021
f018ff6
Tweak printing for subtypes with trivial cofibrations
TOTBWF Nov 25, 2021
f2b74ff
[WIP] Start working on holes/commands
TOTBWF Nov 28, 2021
26c8989
Add segment trees
favonia Nov 29, 2021
ea21988
Remove stupid parentheses
favonia Nov 29, 2021
a9e2309
Refactor and clean up code
favonia Nov 29, 2021
425b0f0
Add a README
favonia Nov 29, 2021
6ad5196
Add visualize code action
TOTBWF Nov 30, 2021
75cb430
Wire up code actions
TOTBWF Nov 30, 2021
45042be
Fix minor bug in SegmentTree
TOTBWF Nov 30, 2021
16ddd81
Add some extra stuff to the segment tree API
TOTBWF Nov 30, 2021
75e8550
Add pp_range
TOTBWF Nov 30, 2021
34fcefa
Rework how metadata is stored
TOTBWF Nov 30, 2021
0b0db06
Remove IntervalTree
TOTBWF Nov 30, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions src/basis/SegmentTree.ml
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,12 @@ end
module type S = functor (Pos: POSITION) ->
sig
type !+'a t
val of_list : (Pos.range * 'a) list -> 'a t
val lookup : Pos.t -> 'a t -> 'a option
val containing : Pos.t -> 'a t -> 'a list
val of_list : (Pos.range * 'a) list -> 'a t
val empty : 'a t

val pp : (Format.formatter -> Pos.range -> unit) -> (Format.formatter -> 'a -> unit) -> Format.formatter -> 'a t -> unit
end

module Make : S = functor (Pos : POSITION) ->
Expand All @@ -32,9 +36,13 @@ struct
| Some (r, v) ->
if Pos.compare r.stop pos >= 0 then Some v else None

let containing pos t =
(* FIXME: This is suboptimal *)
CCList.of_iter @@ SegTree.values @@ SegTree.filter (fun range _ -> range.start <= pos && pos <= range.stop) t
Comment on lines +39 to +41
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This might not be correct, because the "same" span can show up as multiple segments, and "shadowed" spans will not even be in the tree.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would suggest eventually removing containing completely---or we have to rethink the entire framework.


let of_sorted_list l =
let rec loop tree stack l =
match l, stack with
match stack, l with
| _, [] -> SegTree.add_list tree stack
| [], x :: l -> loop tree [x] l
| ((xk, xv) as x) :: stack, ((yk, _) as y :: l) ->
Expand All @@ -58,4 +66,8 @@ struct

let of_list l =
of_sorted_list (CCList.sort (CCOrd.(>|=) Range.compare fst) l)

let empty = SegTree.empty

let pp pp_range pp_elem : Format.formatter -> 'a t -> unit = SegTree.pp pp_range pp_elem
end
6 changes: 5 additions & 1 deletion src/basis/SegmentTree.mli
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,12 @@ end
module type S = functor (Pos: POSITION) ->
sig
type !+'a t
val of_list : ((Pos.t * Pos.t) * 'a) list -> 'a t
val lookup : Pos.t -> 'a t -> 'a option
val containing : Pos.t -> 'a t -> 'a list
val of_list : (Pos.range * 'a) list -> 'a t
val empty : 'a t

val pp : (Format.formatter -> Pos.range -> unit) -> (Format.formatter -> 'a -> unit) -> Format.formatter -> 'a t -> unit
end

module Make : S
13 changes: 0 additions & 13 deletions src/core/RefineMetadata.ml

This file was deleted.

6 changes: 3 additions & 3 deletions src/core/RefineMonad.ml
Original file line number Diff line number Diff line change
Expand Up @@ -174,14 +174,14 @@ let emit_tp loc tp =
| Some loc ->
let* env = read in
let* qtp = quote_tp tp in
modify (St.add_metadata (Metadata.TypeAt (loc, Env.pp_env env, qtp)))
modify (St.add_type_at loc (Env.pp_env env) qtp)
| None ->
ret ()

let emit_hole ctx tp =
let* env = read in
match Env.location env with
| Some loc ->
let hole = Metadata.Hole { ctx; tp } in
modify (St.add_metadata (Metadata.HoleAt (loc, Env.pp_env env, hole)))
let hole = St.Metadata.Hole { ctx; tp } in
modify (St.add_hole loc hole)
| None -> ret ()
33 changes: 27 additions & 6 deletions src/core/RefineState.ml
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,40 @@ open CodeUnit

module IDMap = Map.Make (CodeUnitID)
module D = Domain
module Metadata = RefineMetadata
module S = Syntax

module Metadata = struct
type hole = Hole of { ctx : (Ident.t * S.tp) list; tp : S.tp }

type t = { holes : (LexingUtil.span * hole) list;
type_spans : (LexingUtil.span * Pp.env * S.tp) list
}

let init : t = { holes = []; type_spans = [] }

let holes metadata = metadata.holes

let type_spans metadata = metadata.type_spans

let add_hole span hole t = { t with holes = (span, hole) :: t.holes }

let add_type_at span env tp t = { t with type_spans = (span, env, tp) :: t.type_spans }
end


type t = { code_units : CodeUnit.t IDMap.t;
(** The binding namespace for each code unit. *)
namespaces : (Global.t Namespace.t) IDMap.t;
(** The import namespace for each code unit. *)
import_namespaces : (Global.t Namespace.t) IDMap.t;
(** A message queue for emitting events that occured during refinement. *)
metadata : Metadata.t list
metadata : Metadata.t
}

let init =
{ code_units = IDMap.empty;
namespaces = IDMap.empty;
import_namespaces = IDMap.empty;
metadata = []
metadata = Metadata.init
}

let get_unit id st =
Expand Down Expand Up @@ -74,8 +92,11 @@ let get_import path st =
let is_imported path st =
IDMap.mem path st.code_units

let add_metadata data st =
{ st with metadata = data :: st.metadata }
let add_hole span hole st =
{ st with metadata = Metadata.add_hole span hole st.metadata }

let add_type_at span env tp st =
{ st with metadata = Metadata.add_type_at span env tp st.metadata }

let get_metadata st =
st.metadata
15 changes: 13 additions & 2 deletions src/core/RefineState.mli
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
open Basis
open CodeUnit
module D = Domain
module S = Syntax

type t

Expand All @@ -25,6 +26,16 @@ val is_imported : id -> t -> bool
(** Create and add a new code unit. *)
val init_unit : id -> t -> t

val add_metadata : RefineMetadata.t -> t -> t

val get_metadata : t -> RefineMetadata.t list
module Metadata : sig
type hole = Hole of { ctx : (Ident.t * S.tp) list; tp : S.tp }

type t

val holes : t -> (LexingUtil.span * hole) list
val type_spans : t -> (LexingUtil.span * Pp.env * S.tp) list
end

val add_hole : LexingUtil.span -> Metadata.hole -> t -> t
val add_type_at : LexingUtil.span -> Pp.env -> S.tp -> t -> t
val get_metadata : t -> Metadata.t
118 changes: 118 additions & 0 deletions src/server/Actions.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
open Basis
open Bwd
open Frontend
open Core
open CodeUnit
open Cubical

module S = Syntax
module D = Domain

open Lsp.Types
module Json = Lsp.Import.Json

module LwtIO = Lwt_io

open LspLwt.Notation

(* FIXME: This should live elsewhere, we use this a lot. *)
let ppenv_bind env ident =
Pp.Env.bind env @@ Ident.to_string_opt ident

module Visualize = struct
let command_name = "cooltt.visualize"
let action_kind = CodeActionKind.Other "cooltt.visualize.hole"

let serialize_label (str : string) (pos : (string * float) list) : Json.t =
`Assoc [
"position", `Assoc (List.map (fun (nm, d) -> (nm, `Float d)) pos);
"txt", `String str
]

let dim_tm : S.t -> float =
function
| S.Dim0 -> -. 1.0
| S.Dim1 -> 1.0
| _ -> failwith "dim_tm: bad dim"

let rec dim_from_cof (dims : (string option) bwd) (cof : S.t) : (string * float) list list =
match cof with
| S.Cof (Cof.Eq (S.Var v, r)) ->
let axis = Option.get @@ Bwd.nth dims v in
let d = dim_tm r in
[[(axis, d)]]
| S.Cof (Cof.Join cofs) -> List.concat_map (dim_from_cof dims) cofs
| S.Cof (Cof.Meet cofs) -> [List.concat @@ List.concat_map (dim_from_cof dims) cofs]
| _ -> failwith "dim_from_cof: bad cof"

let boundary_labels dims env bdry =
let rec go env dims (bdry, cons) =
match cons with
| S.CofSplit branches ->
let (_x, envx) = ppenv_bind env `Anon in
List.concat_map (go envx (Snoc (dims, None))) branches
| _ ->
let (_x, envx) = ppenv_bind env `Anon in
let lbl = Format.asprintf "%a" (S.pp envx) cons in
List.map (serialize_label lbl) @@ dim_from_cof (Snoc (dims, None)) bdry
in
match bdry with
| S.CofSplit branches ->
let (_x, envx) = ppenv_bind env `Anon in
List.concat_map (go envx dims) branches
| _ -> []

let serialize_boundary ctx goal : Json.t option =
let rec go dims env =
function
| [] ->
begin
match goal with
| S.Sub (_, _, bdry) ->
let dim_names = Bwd.to_list @@ Bwd.filter_map (Option.map (fun name -> `String name)) dims in
let labels = boundary_labels dims env bdry in
let context = Format.asprintf "%a" (S.pp_sequent ~lbl:None ctx) goal in
let msg = `Assoc [
("dims", `List dim_names);
("labels", `List labels);
("context", `String context)
]
in Some (`Assoc ["DisplayGoal", msg])
| _ -> None
end
| (var, var_tp) :: ctx ->
let (dim_name, envx) = ppenv_bind env var in
match var_tp with
| S.TpDim -> go (Snoc (dims, Some dim_name)) envx ctx
| _ -> go (Snoc (dims, None)) envx ctx
in go Emp Pp.Env.emp ctx

let create ctx goal =
serialize_boundary ctx goal |> Option.map @@ fun json ->
let command = Command.create
~title:"visualize"
~command:command_name
~arguments:[json]
()
in CodeAction.create
~title:"visualize hole"
~kind:action_kind
~command
()

let execute arguments =
match arguments with
| Some [arg] ->
(* FIXME: Handle the visualizer socket better *)
let host = Unix.gethostbyname "localhost" in
let host_entry = Array.get host.h_addr_list 0 in
let addr = Unix.ADDR_INET (host_entry, 3001) in
let* (ic, oc) = LwtIO.open_connection addr in
let* _ = LwtIO.write oc (Json.to_string arg) in
let* _ = LwtIO.flush oc in
let* _ = LwtIO.close ic in
LwtIO.close oc
| _ ->
(* FIXME: Handle this better *)
Lwt.return ()
end
11 changes: 11 additions & 0 deletions src/server/Actions.mli
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
open Basis
open Core
open CodeUnit

module Json = Lsp.Import.Json

module Visualize : sig
val command_name : string
val create : (Ident.t * Syntax.tp) list -> Syntax.tp -> Lsp.Types.CodeAction.t option
val execute : Json.t list option -> unit Lwt.t
end
2 changes: 1 addition & 1 deletion src/server/Executor.ml
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ let elab_decl (st : state) (decl : CS.decl) =
print_ident st ident
| _ -> Lwt.return st

let elaborate_file (lib : Bantorra.Manager.library) (path : string) : (Diagnostic.t list * Metadata.t list) Lwt.t =
let elaborate_file (lib : Bantorra.Manager.library) (path : string) : (Diagnostic.t list * ST.Metadata.t) Lwt.t =
let open LspLwt.Notation in
let* sign = parse_file path in
let unit_id = CodeUnitID.file path in
Expand Down
2 changes: 1 addition & 1 deletion src/server/Executor.mli
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
open Basis
open Core

val elaborate_file : Bantorra.Manager.library -> string -> (Lsp.Types.Diagnostic.t list * RefineMetadata.t list) Lwt.t
val elaborate_file : Bantorra.Manager.library -> string -> (Lsp.Types.Diagnostic.t list * RefineState.Metadata.t) Lwt.t
48 changes: 0 additions & 48 deletions src/server/IntervalTree.ml

This file was deleted.

20 changes: 0 additions & 20 deletions src/server/IntervalTree.mli

This file was deleted.

Loading