aboutsummaryrefslogtreecommitdiffstats
path: root/lib/dcl
diff options
context:
space:
mode:
authorMarcos Magueta <maguetamarcos@gmail.com>2026-04-27 13:00:30 -0300
committerGitHub <noreply@github.com>2026-04-27 13:00:30 -0300
commit56492ad5f6f09d8c9f337d42803b64d1b9f0668b (patch)
tree0a41825d319fe47e037e2e30ed515c3c2d9b0d7d /lib/dcl
parent12f170f438f5909511da2f26c5d33a85acc1fe64 (diff)
downloadSakura-56492ad5f6f09d8c9f337d42803b64d1b9f0668b.tar.gz
Sakura-56492ad5f6f09d8c9f337d42803b64d1b9f0668b.zip
Introduce Multigroups (#65)
Diffstat (limited to '')
-rw-r--r--lib/dcl/ast.ml2
-rw-r--r--lib/dcl/executor.ml161
-rw-r--r--lib/dcl/sublanguage.ml4
3 files changed, 90 insertions, 77 deletions
diff --git a/lib/dcl/ast.ml b/lib/dcl/ast.ml
index 0b6107f..a55ec19 100644
--- a/lib/dcl/ast.ml
+++ b/lib/dcl/ast.ml
@@ -10,4 +10,6 @@ type statement =
| GetBranchTip of string
| UpdateBranchTip of { name : string; hash : string }
| Merge of { left : string; right : string; strategy : merge_strategy }
+ | Use of string
+ | CreateMultigroup of string
[@@deriving sexp]
diff --git a/lib/dcl/executor.ml b/lib/dcl/executor.ml
index a651067..b83f629 100644
--- a/lib/dcl/executor.ml
+++ b/lib/dcl/executor.ml
@@ -4,24 +4,24 @@ module Make (Storage : Management.Physical.S with type error = string) = struct
module MergeOps = Management.Merge.Make (Storage) (Ops)
type error =
- | ParseError of string
- | BranchError of Error.t
- | BranchNotFound of string
+ | ParseError of string
+ | BranchError of Error.t
+ | BranchNotFound of string
| NoDatabaseAtHash of Conventions.Hash.t
- | StorageError of string
- | MergeError of Error.t
- | Conflict of string
+ | StorageError of string
+ | MergeError of Error.t
+ | Conflict of string
let sexp_of_error e =
let open Sexplib.Sexp in
match e with
- | ParseError s -> List [Atom "parse-error"; Atom s]
- | BranchError s -> List [Atom "branch-error"; Error.sexp_of_error s]
- | BranchNotFound s -> List [Atom "branch-not-found"; Atom s]
- | NoDatabaseAtHash s -> List [Atom "no-database-at-hash"; Atom s]
- | StorageError s -> List [Atom "storage-error"; Atom s]
- | MergeError s -> List [Atom "merge-error"; Error.sexp_of_error s]
- | Conflict s -> List [Atom "conflict"; Atom s]
+ | ParseError s -> List [ Atom "parse-error"; Atom s ]
+ | BranchError s -> List [ Atom "branch-error"; Error.sexp_of_error s ]
+ | BranchNotFound s -> List [ Atom "branch-not-found"; Atom s ]
+ | NoDatabaseAtHash s -> List [ Atom "no-database-at-hash"; Atom s ]
+ | StorageError s -> List [ Atom "storage-error"; Atom s ]
+ | MergeError s -> List [ Atom "merge-error"; Error.sexp_of_error s ]
+ | Conflict s -> List [ Atom "conflict"; Atom s ]
let convert_strategy : Ast.merge_strategy -> Management.Merge.strategy =
function
@@ -29,71 +29,80 @@ module Make (Storage : Management.Physical.S with type error = string) = struct
| Ast.PreferRight -> Management.Merge.PreferRight
| Ast.RevertToAncestor -> Management.Merge.RevertToAncestor
+ type exec_result =
+ | DbResult of Management.Database.t * string
+ | Switch of string
+ | NewMultigroup of string
+
let execute (storage : Storage.t) (db : Management.Database.t)
- (stmt : Ast.statement) : (Management.Database.t * string, error) result =
+ (stmt : Ast.statement) : (exec_result, error) result =
match stmt with
- | Ast.CreateBranch { name; hash } ->
- let tip = match hash with
- | Some h -> h
- | None -> db.Management.Database.hash
- in
- (match Branch.create storage ~name ~tip with
- | Error e -> Error (StorageError e)
- | Ok () -> Ok (db, "Branch " ^ name ^ " created"))
-
- | Ast.Checkout branch_name ->
- (match Branch.get_tip storage branch_name with
- | Error e -> Error (StorageError e)
- | Ok None -> Error (BranchNotFound branch_name)
- | Ok (Some tip) ->
- (match Branch.checkout storage branch_name with
- | Error e -> Error (StorageError e)
- | Ok () ->
- (match Ops.load_database storage tip with
- | Error e -> Error (BranchError e)
- | Ok None -> Error (NoDatabaseAtHash tip)
- | Ok (Some loaded_db) ->
- Ok (loaded_db, "HEAD:" ^ branch_name))))
-
- | Ast.GetHead ->
- (match Branch.get_head storage with
- | Error e -> Error (StorageError e)
- | Ok None -> Ok (db, "HEAD is unset")
- | Ok (Some name) -> Ok (db, "HEAD:" ^ name))
-
- | Ast.GetBranchTip name ->
- (match Branch.get_tip storage name with
- | Error e -> Error (StorageError e)
- | Ok None -> Error (BranchNotFound name)
- | Ok (Some hash) -> Ok (db, "branch:" ^ name ^ "=" ^ hash))
-
- | Ast.UpdateBranchTip { name; hash } ->
- (match Branch.update_tip storage ~name ~tip:hash with
- | Error e -> Error (StorageError e)
- | Ok () -> Ok (db, "Branch " ^ name ^ " updated"))
-
- | Ast.Merge { left; right; strategy } ->
- (match Branch.get_tip storage left, Branch.get_tip storage right with
- | Error e, _ | _, Error e -> Error (StorageError e)
- | Ok None, _ -> Error (BranchNotFound left)
- | _, Ok None -> Error (BranchNotFound right)
- | Ok (Some left_tip), Ok (Some right_tip) ->
- let strat = convert_strategy strategy in
- (match MergeOps.merge ~storage ~strategy:strat ~left_tip ~right_tip with
- | Error e -> Error (MergeError e)
- | Ok (Management.Merge.Failed conflicts) ->
- let msgs = List.map (function
- | Management.Merge.TupleConflict { relation; hash } ->
- "tuple conflict in " ^ relation ^ " (" ^ hash ^ ")"
- | Management.Merge.SchemaConflict r -> "schema conflict in " ^ r
- | Management.Merge.ConstraintConflict r -> "constraint conflict in " ^ r
- ) conflicts in
- Error (Conflict ("Merge failed: " ^ String.concat "; " msgs))
- | Ok (Management.Merge.Clean merged_db) ->
- let _ = Branch.update_tip storage ~name:left
- ~tip:merged_db.Management.Database.hash in
- Ok (merged_db,
- "Merged:" ^ right ^ "→" ^ left)))
+ | Ast.CreateBranch { name; hash } -> (
+ let tip =
+ match hash with Some h -> h | None -> db.Management.Database.hash
+ in
+ match Branch.create storage ~name ~tip with
+ | Error e -> Error (StorageError e)
+ | Ok () -> Ok (DbResult (db, "Branch " ^ name ^ " created")))
+ | Ast.Checkout branch_name -> (
+ match Branch.get_tip storage branch_name with
+ | Error e -> Error (StorageError e)
+ | Ok None -> Error (BranchNotFound branch_name)
+ | Ok (Some tip) -> (
+ match Branch.checkout storage branch_name with
+ | Error e -> Error (StorageError e)
+ | Ok () -> (
+ match Ops.load_database storage tip with
+ | Error e -> Error (BranchError e)
+ | Ok None -> Error (NoDatabaseAtHash tip)
+ | Ok (Some loaded_db) ->
+ Ok (DbResult (loaded_db, "HEAD:" ^ branch_name)))))
+ | Ast.GetHead -> (
+ match Branch.get_head storage with
+ | Error e -> Error (StorageError e)
+ | Ok None -> Ok (DbResult (db, "HEAD is unset"))
+ | Ok (Some name) -> Ok (DbResult (db, "HEAD:" ^ name)))
+ | Ast.GetBranchTip name -> (
+ match Branch.get_tip storage name with
+ | Error e -> Error (StorageError e)
+ | Ok None -> Error (BranchNotFound name)
+ | Ok (Some hash) -> Ok (DbResult (db, "branch:" ^ name ^ "=" ^ hash)))
+ | Ast.UpdateBranchTip { name; hash } -> (
+ match Branch.update_tip storage ~name ~tip:hash with
+ | Error e -> Error (StorageError e)
+ | Ok () -> Ok (DbResult (db, "Branch " ^ name ^ " updated")))
+ | Ast.Merge { left; right; strategy } -> (
+ match (Branch.get_tip storage left, Branch.get_tip storage right) with
+ | Error e, _ | _, Error e -> Error (StorageError e)
+ | Ok None, _ -> Error (BranchNotFound left)
+ | _, Ok None -> Error (BranchNotFound right)
+ | Ok (Some left_tip), Ok (Some right_tip) -> (
+ let strat = convert_strategy strategy in
+ match
+ MergeOps.merge ~storage ~strategy:strat ~left_tip ~right_tip
+ with
+ | Error e -> Error (MergeError e)
+ | Ok (Management.Merge.Failed conflicts) ->
+ let msgs =
+ List.map
+ (function
+ | Management.Merge.TupleConflict { relation; hash } ->
+ "tuple conflict in " ^ relation ^ " (" ^ hash ^ ")"
+ | Management.Merge.SchemaConflict r ->
+ "schema conflict in " ^ r
+ | Management.Merge.ConstraintConflict r ->
+ "constraint conflict in " ^ r)
+ conflicts
+ in
+ Error (Conflict ("Merge failed: " ^ String.concat "; " msgs))
+ | Ok (Management.Merge.Clean merged_db) ->
+ let _ =
+ Branch.update_tip storage ~name:left
+ ~tip:merged_db.Management.Database.hash
+ in
+ Ok (DbResult (merged_db, "Merged:" ^ right ^ "→" ^ left))))
+ | Ast.Use multigroup -> Ok (Switch multigroup)
+ | Ast.CreateMultigroup name -> Ok (NewMultigroup name)
end
module Memory = Make (Management.Physical.Memory)
diff --git a/lib/dcl/sublanguage.ml b/lib/dcl/sublanguage.ml
index eab5ecb..7af0703 100644
--- a/lib/dcl/sublanguage.ml
+++ b/lib/dcl/sublanguage.ml
@@ -16,7 +16,9 @@ module Make (Storage : Management.Physical.S with type error = string) = struct
let execute storage db ast =
match Exec.execute storage db ast with
- | Ok (db, msg) -> Ok (Sublanguage_types.Transition (db, msg))
+ | Ok (Exec.DbResult (db, msg)) -> Ok (Sublanguage_types.Transition (db, msg))
+ | Ok (Exec.Switch multigroup) -> Ok (Sublanguage_types.SessionSwitch multigroup)
+ | Ok (Exec.NewMultigroup name) -> Ok (Sublanguage_types.CreateMultigroup name)
| Error e -> Error e
let sexp_of_error = Exec.sexp_of_error