aboutsummaryrefslogtreecommitdiff
path: root/src/sheet.ml
diff options
context:
space:
mode:
Diffstat (limited to 'src/sheet.ml')
-rwxr-xr-xsrc/sheet.ml101
1 files changed, 60 insertions, 41 deletions
diff --git a/src/sheet.ml b/src/sheet.ml
index 67b1ee1..3dc83a0 100755
--- a/src/sheet.ml
+++ b/src/sheet.ml
@@ -10,22 +10,12 @@ type search = [
module Raw = struct
- module Map = Map.Make(struct
- type t = cell
- let compare (x1, y1) (x2, y2) = Pervasives.compare (y1, x1) (y2, x2)
- end)
-
type content = {
expr : Expression.t; (** The expression *)
value : ScTypes.result option; (** The content evaluated *)
sink : Cell.Set.t; (** All the cell which references this one *)
}
- (** The sheet is a map which always contains evaluated values. When a cell is
- updated, all the cell which references this value are also updated.
- *)
- and t = content Map.t
-
(** An empty cell which does contains nothing *)
let empty_cell = {
expr = Expression.Undefined;
@@ -33,17 +23,21 @@ module Raw = struct
sink = Cell.Set.empty;
}
+ (** Internaly, we use an array to store the data. Each array as a fixed size
+ of 8×8 cells, and each array is stored in a tree. *)
+ module Map = PageMap.SplayMap(struct type t = content let default = empty_cell end)
+
+ type t = Map.t
+
+
+ (** The sheet is a map which always contains evaluated values. When a cell is
+ updated, all the cell which references this value are also updated.
+ *)
let empty = Map.empty
- let get_value id t = begin
- try (Map.find id t).value
- with Not_found -> None
- end
+ let get_value id t = (Map.find id t).value
- let get_expr id t = begin
- try (Map.find id t).expr
- with Not_found -> empty_cell.expr
- end
+ let get_expr id t = (Map.find id t).expr
(** Extract a value from a reference.
This function is given to the evaluator for getting the values from a reference.
@@ -75,7 +69,9 @@ module Raw = struct
end
(** Parse all the successors from an element, apply a function to each of
- them, and return them *)
+ them, and return them.
+
+ The function is too long and should be rewriten… *)
let rec traverse (f:(cell -> content -> t -> t option)) source (init, t) = begin
let exception Cycle of Cell.Set.t * t in
@@ -130,7 +126,6 @@ module Raw = struct
*)
let remove_ref cell t = begin
try let c = Map.find cell t in
-
(* Remove all the refs which points to the removed cell *)
let sink' = Cell.Set.filter ((<>) id) c.sink in
if Cell.Set.is_empty sink' && not (Expression.is_defined c.expr) then (
@@ -143,15 +138,18 @@ module Raw = struct
begin try
let c = Map.find id t in
let t' =
- (** Remove the references from each sources *)
+ (** Remove the references from each cell pointed by the expression *)
let sources = Expression.collect_sources c.expr in
Cell.Set.fold remove_ref sources t in
- (** If there is no references on the cell, remove it *)
- if Cell.Set.is_empty c.sink then (
- Map.remove id t', None)
+ (* Removing the references to itself, keep all the other references
+ pointing to it (they are not affected) *)
+ let sink' = Cell.Set.filter ((<>) id) c.sink in
+ (** If there is no more references on the cell, remove it *)
+ if Cell.Set.is_empty sink' then
+ Map.remove id t', None
else (
- let c = { empty_cell with sink = c.sink } in
+ let c = { empty_cell with sink = sink' } in
Map.add id c t', (Some c)
)
with Not_found -> t, None
@@ -166,7 +164,7 @@ module Raw = struct
traverse update content (Cell.Set.singleton id, t)
end
- let add_element id f t = begin
+ let add_element id content_builder t = begin
(** Add the references in each sources.
If the sources does not exists, create it.
@@ -179,12 +177,13 @@ module Raw = struct
Map.add cell c' t
end in
+ (* Remove the cell and update all the sink. *)
let t', cell = remove_element id t in
let cell' = match cell with
| None -> empty_cell
| Some x -> x in
- let content = f cell' t' in
+ let content = content_builder cell' t' in
let sources = Expression.collect_sources content.expr in
let updated = Map.add id content t'
@@ -199,10 +198,11 @@ module Raw = struct
if not (Expression.is_defined expression) then
(Cell.Set.empty, t)
else
- let f cell t = { cell with
- expr = expression ;
- value = Some (Expression.eval expression (get_ref id t))
- } in
+ let f cell t = begin
+ { cell with
+ expr = expression ;
+ value = Some (Expression.eval expression (get_ref id t)) }
+ end in
add_element id f t
end
@@ -219,9 +219,12 @@ module Raw = struct
let search pattern t = begin
let exception Found of (int * int) in
- let _search key content = if content.value = pattern then raise (Found key) in
+ let _search key content () =
+ if content.value = pattern then raise (Found key) in
+
try
- Map.iter _search t;
+ (* Iteration*)
+ Map.fold _search t ();
None
with Found key -> Some key
end
@@ -243,17 +246,27 @@ module Raw = struct
end
type yank = cell * Raw.content
+type history = ((cell * Expression.t) list) list
type t = {
selected: Selection.t; (* The selected cell *)
data: Raw.t;
- history: t list; (* Unlimited history *)
- yank: (cell * Raw.content) list
+ history: history; (* Unlimited history *)
+ yank: yank list
}
-let undo t = begin match t.history with
+let undo t = begin
+ match t.history with
| [] -> None
- | hd::tl -> Some { hd with selected = t.selected }
+ | hd::tl ->
+ let data = List.fold_left (
+ fun data (id, expression) ->
+ if Expression.is_defined expression then
+ snd @@ Raw.add id expression data
+ else
+ snd @@ Raw.remove id data
+ ) t.data hd in
+ Some { t with data = data; history = tl}
end
let move direction t =
@@ -263,7 +276,7 @@ let move direction t =
| Actions.Right quant -> Tools.Tuple2.replace1 ((fst position) + quant) position
| Actions.Up quant -> Tools.Tuple2.replace2 (max 1 ((snd position) - quant)) position
| Actions.Down quant -> Tools.Tuple2.replace2 ((snd position) + quant) position
- | Actions.Absolute (x, y)-> (x, y)
+ | Actions.Absolute (x, y) -> (x, y)
end in
if position = position' then
None
@@ -271,11 +284,12 @@ let move direction t =
Some {t with selected = Selection.create position'}
let delete t = begin
+ let history = Selection.fold (fun acc id -> (id, Raw.get_expr id t.data)::acc) [] t.selected in
let count, data' = Selection.fold (fun (count, c) t ->
(count + 1, snd @@ Raw.remove t c)) (0, t.data) t.selected in
let t' = { t with
data = data';
- history = t::t.history
+ history = history::t.history
} in
t', count
end
@@ -302,19 +316,24 @@ let paste t = begin
(* Origin of first cell *)
let (shift_x, shift_y) as shift = Selection.extract t.selected in
+ let history' = List.map (fun ((x, y), content) ->
+ let id = shift_x + x, shift_y + y in
+ id, Raw.get_expr id t.data) t.yank in
+
let _paste (count, t) ((x, y), content) = begin
count + 1, snd @@ Raw.paste (shift_x + x, shift_y + y) shift content t
end in
let count, data' = List.fold_left _paste (0, t.data) t.yank in
- let t' = { t with data = data'; history = t::t.history } in
+ let t' = { t with data = data'; history = history'::t.history } in
t', count
end
let add expression t = begin
let id = Selection.extract t.selected in
+ let prev_expression = Raw.get_expr id t.data in
let cells, data' = Raw.add id expression t.data in
- cells, { t with data = data'; history = t::t.history}
+ cells, { t with data = data'; history = [id, prev_expression]::t.history }
end
let search action t = begin match action with