From 1131bb70f2a92f808aa7f919f406964e64c6f637 Mon Sep 17 00:00:00 2001 From: prabhanshuguptagit Date: Wed, 28 Feb 2024 16:36:21 +0530 Subject: [PATCH] WIP implement a few functions --- src/bean/functions.cljs | 183 ++++++++++++++++++++++++++++---------- src/bean/grid.cljs | 8 ++ src/bean/interpreter.cljs | 19 ++-- src/bean/ui/events.cljs | 12 ++- src/bean/ui/main.cljs | 3 +- 5 files changed, 165 insertions(+), 60 deletions(-) diff --git a/src/bean/functions.cljs b/src/bean/functions.cljs index a6678a5..536b51e 100644 --- a/src/bean/functions.cljs +++ b/src/bean/functions.cljs @@ -16,64 +16,151 @@ (reduce str "" args)) (interpreter/eval-asts sheet asts))) -(defn bean-get* [sheet asts & [dirn]] +(defn- make-table-result [sheet table-result new-selection] + (let [new-selection (set new-selection)] + {:matrix (util/map-on-matrix + #(if (get new-selection %) + (util/get-cell (:grid sheet) %) + {:scalar "" :representation ""}) + (area/addresses->address-matrix new-selection)) + :table (merge table-result + {:selection new-selection})})) + +(defn bean-row [sheet asts] (let [ast-results (interpreter/eval-asts sheet asts) error (interpreter/first-error ast-results)] (if-not error (let [table-result (:table (first ast-results)) - label (:scalar (second ast-results)) - existing-selection (:selection table-result) - vget-cells (tables/label-name->cells - sheet - (:name table-result) label dirn) - new-selection (set/intersection - vget-cells - existing-selection)] - (if (tables/label? sheet (:name table-result) label dirn) - {:matrix (util/map-on-matrix - #(if (get new-selection %) - (util/get-cell (:grid sheet) %) - {:scalar "" :representation ""}) - (area/addresses->address-matrix new-selection)) - :table (merge table-result - {:selection new-selection - :selection-dirn dirn})} - (errors/label-not-found - (:scalar (interpreter/eval-ast (second asts) sheet))))) + selection (:selection table-result) + table (tables/get-table sheet (:name table-result)) + [start-r start-c] (:start table) + [end-r end-c] (:end table)] + (make-table-result + sheet + table-result + (apply set/union + (map + (fn [[r c]] + (set + (map + #(do [r %]) + (range start-c (inc end-c))))) + selection)))) error))) -(defn bean-get [sheet asts] - (bean-get* sheet asts)) - -(defn bean-vget [sheet asts] - (bean-get* sheet asts :top)) +(defn bean-col [sheet asts] + (let [ast-results (interpreter/eval-asts sheet asts) + error (interpreter/first-error ast-results)] + (if-not error + (let [table-result (:table (first ast-results)) + selection (:selection table-result) + table (tables/get-table sheet (:name table-result)) + [start-r start-c] (:start table) + [end-r end-c] (:end table)] + (make-table-result + sheet + table-result + (apply set/union + (map + (fn [[r c]] + (set + (map + #(do [% c]) + (range start-r (inc end-r))))) + selection)))) + error))) -(defn bean-hget [sheet asts] - (bean-get* sheet asts :left)) +(defn bean-reduce [sheet asts] + (let [ast-results (interpreter/eval-asts sheet asts) + error (interpreter/first-error ast-results)] + (if-not error + (let [table-result (:table (first ast-results)) + f (:scalar (second ast-results)) + selection (:selection table-result)] + (if (empty? selection) + {:matrix [[{:scalar "" :representation ""}]]} + (apply + reduce + (remove + nil? + [#(if (= (:scalar %2) "") + %1 + (if (= (:scalar %1) "") + %2 + (interpreter/apply-user-f sheet f [%1 %2]))) + (first (next (next ast-results))) + (map #(util/get-cell (:grid sheet) %) selection)])))) + error))) -(defn bean-table [sheet asts] +;; This doesn't work for matrices right now +;; It should: eval-matrix should perhaps return a :selection also +(defn bean-filter [sheet asts] (let [ast-results (interpreter/eval-asts sheet asts) error (interpreter/first-error ast-results)] (if-not error - (if (cell-ref? (first asts)) - (let [[_ [_ a n]] (first asts) - address (util/a1->rc a (js/parseInt n)) - table-name (tables/cell-table address sheet) - table (tables/get-table sheet table-name)] - (if table-name - {:matrix (interpreter/eval-matrix (:start table) - (:end table) - (:grid sheet)) - :table {:name table-name - :selection (area/area->addresses - (select-keys table [:start :end])) - :selection-dirn nil}} - (errors/undefined-table-at (str a n)))) - (errors/invalid-table-args - (str (:scalar (first ast-results))))) + (let [table-result (:table (first ast-results)) + f (:scalar (second ast-results)) + selection (:selection table-result)] + (make-table-result + sheet table-result + (filter + #(:scalar + (interpreter/apply-user-f sheet f + [(util/get-cell (:grid sheet) %)])) + selection))) error))) -(defn bean-error [sheet asts] - (let [str-err (str (:error (interpreter/eval-ast (first asts) sheet)))] - {:scalar str-err - :representation str-err})) + (defn bean-get* [sheet asts & [dirn]] + (let [ast-results (interpreter/eval-asts sheet asts) + error (interpreter/first-error ast-results)] + (if-not error + (let [table-result (:table (first ast-results)) + label (:scalar (second ast-results)) + existing-selection (:selection table-result) + vget-cells (tables/label-name->cells + sheet + (:name table-result) label dirn) + new-selection (set/intersection + vget-cells + existing-selection)] + (if (tables/label? sheet (:name table-result) label dirn) + (make-table-result sheet table-result new-selection) + (errors/label-not-found + (:scalar (interpreter/eval-ast (second asts) sheet))))) + error))) + + (defn bean-get [sheet asts] + (bean-get* sheet asts)) + + (defn bean-vget [sheet asts] + (bean-get* sheet asts :top)) + + (defn bean-hget [sheet asts] + (bean-get* sheet asts :left)) + + (defn bean-table [sheet asts] + (let [ast-results (interpreter/eval-asts sheet asts) + error (interpreter/first-error ast-results)] + (if-not error + (if (cell-ref? (first asts)) + (let [[_ [_ a n]] (first asts) + address (util/a1->rc a (js/parseInt n)) + table-name (tables/cell-table address sheet) + table (tables/get-table sheet table-name)] + (if table-name + {:matrix (interpreter/eval-matrix (:start table) + (:end table) + (:grid sheet)) + :table {:name table-name + :selection (area/area->addresses + (select-keys table [:start :end])) + :selection-dirn nil}} + (errors/undefined-table-at (str a n)))) + (errors/invalid-table-args + (str (:scalar (first ast-results))))) + error))) + + (defn bean-error [sheet asts] + (let [str-err (str (:error (interpreter/eval-ast (first asts) sheet)))] + {:scalar str-err + :representation str-err})) diff --git a/src/bean/grid.cljs b/src/bean/grid.cljs index 8ea36d6..0f60b6e 100644 --- a/src/bean/grid.cljs +++ b/src/bean/grid.cljs @@ -24,6 +24,14 @@ :representation "f"} "table" {:scalar functions/bean-table :representation "f"} + "filter" {:scalar functions/bean-filter + :representation "f"} + "reduce" {:scalar functions/bean-reduce + :representation "f"} + "row" {:scalar functions/bean-row + :representation "f"} + "col" {:scalar functions/bean-col + :representation "f"} "error" {:scalar functions/bean-error :representation "f"}}) diff --git a/src/bean/interpreter.cljs b/src/bean/interpreter.cljs index 8e04ac3..5af9dd2 100644 --- a/src/bean/interpreter.cljs +++ b/src/bean/interpreter.cljs @@ -3,7 +3,7 @@ [bean.errors :as errors] [bean.operators :as operators])) -(defn- ast-result [error-or-val] +(defn ast-result [error-or-val] (if-let [error (:error error-or-val)] (errors/stringified-error error) {:scalar error-or-val @@ -121,14 +121,19 @@ (defn- bound-to-xyz [values] (into {} (map vector ["x" "y" "z"] values))) -(defn- apply-f [sheet f asts] +(defn apply-system-f [sheet f asts] + (f sheet asts)) + +(defn apply-user-f [sheet f args] + (eval-ast f (update-in sheet [:bindings] + merge (bound-to-xyz args)))) + +(defn apply-f [sheet f asts] (let [fn-ast (:scalar f)] (if (fn? fn-ast) - (fn-ast sheet asts) - (eval-ast fn-ast - (update-in sheet [:bindings] - merge (bound-to-xyz - (eval-asts sheet asts))))))) + (apply-system-f sheet fn-ast asts) + (apply-user-f + sheet fn-ast (eval-asts sheet asts))))) (defn eval-cell [cell sheet] (-> (eval-ast (:ast cell) sheet) diff --git a/src/bean/ui/events.cljs b/src/bean/ui/events.cljs index 3cee44f..728f871 100644 --- a/src/bean/ui/events.cljs +++ b/src/bean/ui/events.cljs @@ -31,6 +31,11 @@ :error :evaluated))))) +(rf/reg-event-db + ::refresh-bindings + (fn refresh-bindings [db [_]] + (update-in db [:sheet :bindings] merge grid/default-bindings))) + (rf/reg-event-db ::update-cell (fn update-cell [db [_ address content]] @@ -104,10 +109,9 @@ (rf/reg-event-fx ::select-table (fn select-table [{:keys [db]} [_ table-name]] - (let [{:keys [start]} (get-in db [:sheet :tables table-name])] - (merge - {:db (assoc-in db [:ui :grid :selected-table] table-name)} - (when start {:fx [[:dispatch [::edit-cell start]]]}))))) + (when-let [{:keys [start]} (get-in db [:sheet :tables table-name])] + {:db (assoc-in db [:ui :grid :selected-table] table-name) + :fx [[:dispatch [::edit-cell start]]]}))) (rf/reg-event-fx ::make-table diff --git a/src/bean/ui/main.cljs b/src/bean/ui/main.cljs index 4665b62..dec7323 100644 --- a/src/bean/ui/main.cljs +++ b/src/bean/ui/main.cljs @@ -9,7 +9,8 @@ (routes/start) (r/render [root/routed] - (.getElementById js/document "app"))) + (.getElementById js/document "app")) + (rf/dispatch [::events/refresh-bindings])) (defn ^:export main [] (rf/dispatch-sync [::events/initialize-db])