From 6b0bb01fced0081d6fb88b0dc9ac6566afe32b35 Mon Sep 17 00:00:00 2001 From: Daan van Berkel Date: Wed, 14 Dec 2016 16:14:06 +0100 Subject: [PATCH 1/5] First try at oCaml language support This is very much work in progress. Feedback is much appreciated. --- src/klipse/lang/ocaml.cljs | 48 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 src/klipse/lang/ocaml.cljs diff --git a/src/klipse/lang/ocaml.cljs b/src/klipse/lang/ocaml.cljs new file mode 100644 index 00000000..711d73f3 --- /dev/null +++ b/src/klipse/lang/ocaml.cljs @@ -0,0 +1,48 @@ +(ns klipse.lang.ocaml + (:require-macros + [gadjett.core :refer [dbg]] + [purnam.core :refer [!>]] + [cljs.core.async.macros :refer [go]]) + (:require + [klipse.common.registry :refer [codemirror-mode-src register-mode]])) + +(def eval-in-global-scope js/eval); this is the trick to make `eval` work in the global scope: http://perfectionkills.com/global-eval-what-are-the-options/ + +(defn ocaml-to-js [src] + (-> src + (js/ocaml.compile) + (js/JSON.parse) + (aget "js_code"))) + +(defn eval-ocaml [exp _] + (go + (try + (-> exp + ocaml-to-js + eval-in-global-scope) + (catch :default o + (str o))))) + +(defn transpile-ocaml [exp _] + (go + (try + ocaml-to-js + (catch :default o + (str o))))) + +(def eval-opts {:editor-in-mode "text/ocaml" + :editor-out-mode "javascript" + :eval-fn eval-ocaml + :external-csripts [(codemirror-mode-src "ocaml") "http://bloomberg.github.io/bucklescript/js-demo/exports.js"] + ; oCaml does not know a single line comment + }) + +(def transpile-ocaml {:editor-in-mode "text/ocaml" + :editor-out-mode "javascript" + :eval-fn transpile-ocaml + :external-scripts [(codemirror-mode-src "ocaml") "http://bloomberg.github.io/bucklescript/js-demo/exports.js"] + ; oCaml does not know a single line comment + }) + +(register-mode "eval-ocaml" "selector_ocaml" eval-opts) +(register-mode "transpile-ocaml" "selector_transpile_jsx" transpile-ocaml) From 8366f2c0612026a7f953c115479da63e7d646f03 Mon Sep 17 00:00:00 2001 From: Daan van Berkel Date: Wed, 14 Dec 2016 16:27:30 +0100 Subject: [PATCH 2/5] Require oCaml in all.cljs and both plugin.cljs As advised in https://github.com/viebel/klipse/wiki/How-to-add-a-language-to-klipse --- src/klipse/run/all.cljs | 1 + src/klipse/run/plugin/plugin.cljs | 1 + src/klipse/run/plugin_prod/plugin.cljs | 3 ++- 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/klipse/run/all.cljs b/src/klipse/run/all.cljs index 1f4bb900..9002939f 100644 --- a/src/klipse/run/all.cljs +++ b/src/klipse/run/all.cljs @@ -9,4 +9,5 @@ klipse.lang.cpp klipse.lang.server-eval klipse.lang.php + klipse.lang.ocaml klipse.run.app.app)) diff --git a/src/klipse/run/plugin/plugin.cljs b/src/klipse/run/plugin/plugin.cljs index b1febedb..74154be5 100644 --- a/src/klipse/run/plugin/plugin.cljs +++ b/src/klipse/run/plugin/plugin.cljs @@ -13,6 +13,7 @@ klipse.lang.html klipse.lang.server-eval klipse.lang.clojure + klipse.lang.ocaml [klipse.plugin :as plugin])) (js/console.info "settings: " (aget js/window "klipse_settings")) diff --git a/src/klipse/run/plugin_prod/plugin.cljs b/src/klipse/run/plugin_prod/plugin.cljs index 68edc795..be328344 100644 --- a/src/klipse/run/plugin_prod/plugin.cljs +++ b/src/klipse/run/plugin_prod/plugin.cljs @@ -11,8 +11,9 @@ klipse.lang.server-eval klipse.lang.markdown klipse.lang.lambdaway - ; DO NOT include clojure it inflates the build sive and anyway it doesn't work with advanced compilation klipse.lang.clojure + ; DO NOT include clojure it inflates the build size and anyway it doesn't work with advanced compilation klipse.lang.clojure klipse.lang.html + klipse.lang.ocaml [klipse.plugin :as plugin])) (print "settings: " (aget js/window "klipse_settings")) From ee92a24d7e292324c297336b634a5296ecb82bec Mon Sep 17 00:00:00 2001 From: Daan van Berkel Date: Wed, 14 Dec 2016 19:43:45 +0100 Subject: [PATCH 3/5] Reference local copy of BuckleScript compiler --- src/klipse/lang/ocaml.cljs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/klipse/lang/ocaml.cljs b/src/klipse/lang/ocaml.cljs index 711d73f3..4cb1ba1b 100644 --- a/src/klipse/lang/ocaml.cljs +++ b/src/klipse/lang/ocaml.cljs @@ -33,14 +33,14 @@ (def eval-opts {:editor-in-mode "text/ocaml" :editor-out-mode "javascript" :eval-fn eval-ocaml - :external-csripts [(codemirror-mode-src "ocaml") "http://bloomberg.github.io/bucklescript/js-demo/exports.js"] + :external-scripts [(codemirror-mode-src "ocaml") "https://viebel.github.io/klipse/repo/js/ocaml-compiler.js"] ; oCaml does not know a single line comment }) (def transpile-ocaml {:editor-in-mode "text/ocaml" :editor-out-mode "javascript" :eval-fn transpile-ocaml - :external-scripts [(codemirror-mode-src "ocaml") "http://bloomberg.github.io/bucklescript/js-demo/exports.js"] + :external-scripts [(codemirror-mode-src "ocaml") "https://viebel.github.io/klipse/repo/js/ocaml-compiler.js"] ; oCaml does not know a single line comment }) From 943ca047ef93389b7bc4525193a611dea94dcf06 Mon Sep 17 00:00:00 2001 From: Daan van Berkel Date: Wed, 14 Dec 2016 19:53:36 +0100 Subject: [PATCH 4/5] Create a oCaml debug page --- resources/public/ocaml-dbg.html | 31 +++++++++++++++++++++++++++++++ src/klipse/lang/ocaml.cljs | 4 ++-- 2 files changed, 33 insertions(+), 2 deletions(-) create mode 100644 resources/public/ocaml-dbg.html diff --git a/resources/public/ocaml-dbg.html b/resources/public/ocaml-dbg.html new file mode 100644 index 00000000..d8493a2d --- /dev/null +++ b/resources/public/ocaml-dbg.html @@ -0,0 +1,31 @@ + + + + + KLIPSE: a simple and elegant online cljs compiler and evaluator + + + + +
+            
+let rec fib (n: int): int =
+  match n with
+    | 0 -> 0
+    | 1 -> 1
+    | _ -> (fib (n - 1)) + (fib (n - 2))
+
+let () =
+  Js.log (fib 6)
+            
+        
+
+ + + + + diff --git a/src/klipse/lang/ocaml.cljs b/src/klipse/lang/ocaml.cljs index 4cb1ba1b..0e1a5fb4 100644 --- a/src/klipse/lang/ocaml.cljs +++ b/src/klipse/lang/ocaml.cljs @@ -44,5 +44,5 @@ ; oCaml does not know a single line comment }) -(register-mode "eval-ocaml" "selector_ocaml" eval-opts) -(register-mode "transpile-ocaml" "selector_transpile_jsx" transpile-ocaml) +(register-mode "eval-ocaml" "selector_eval_ocaml" eval-opts) +(register-mode "transpile-ocaml" "selector_transpile_ocaml" transpile-ocaml) From 0e769615231e5e4bc77cabff5d2f6e007e442de4 Mon Sep 17 00:00:00 2001 From: Yehonathan Sharvit Date: Wed, 14 Dec 2016 22:04:26 +0200 Subject: [PATCH 5/5] small improvements --- resources/public/ocaml-dbg.html | 16 ++++++++++- src/klipse/lang/ocaml.cljs | 51 ++++++++++++++++++++------------- 2 files changed, 46 insertions(+), 21 deletions(-) diff --git a/resources/public/ocaml-dbg.html b/resources/public/ocaml-dbg.html index d8493a2d..0a321b6e 100644 --- a/resources/public/ocaml-dbg.html +++ b/resources/public/ocaml-dbg.html @@ -9,6 +9,19 @@
             
+let rec fib (n: int): int =
+  match n with
+    | 0 -> 1
+    | 1 -> 1
+    | _ -> (fib (n - 1)) + (fib (n - 2))
+
+let () =
+  Js.log (fib 9)
+            
+        
+

Transpilation

+
+            
 let rec fib (n: int): int =
   match n with
     | 0 -> 0
@@ -22,7 +35,8 @@
         
diff --git a/src/klipse/lang/ocaml.cljs b/src/klipse/lang/ocaml.cljs index 0e1a5fb4..9a760974 100644 --- a/src/klipse/lang/ocaml.cljs +++ b/src/klipse/lang/ocaml.cljs @@ -1,48 +1,59 @@ (ns klipse.lang.ocaml (:require-macros [gadjett.core :refer [dbg]] + [klipse.macros :refer [my-with-redefs]] [purnam.core :refer [!>]] [cljs.core.async.macros :refer [go]]) (:require + [clojure.string :as string] + [cljs.core.async :refer [chan put!]] [klipse.common.registry :refer [codemirror-mode-src register-mode]])) (def eval-in-global-scope js/eval); this is the trick to make `eval` work in the global scope: http://perfectionkills.com/global-eval-what-are-the-options/ (defn ocaml-to-js [src] - (-> src - (js/ocaml.compile) - (js/JSON.parse) - (aget "js_code"))) + (let [{:keys [js_error_msg js_code]} (js->clj (-> (js/ocaml.compile src) + js/JSON.parse) :keywordize-keys true)];TODO - use transit JSON reader + (if js_error_msg [:error js_error_msg] + [:ok js_code]))) (defn eval-ocaml [exp _] - (go - (try - (-> exp - ocaml-to-js - eval-in-global-scope) - (catch :default o - (str o))))) + (let [c (chan)] + (my-with-redefs [js/console.log (fn[& args] + (put! c (string/join " " args)) + (put! c "\n"))] + + (try + (set! js/exports #js {}) + (let [[status res] (ocaml-to-js exp)] + (if (= :error status) (put! c res) + (put! c (-> res + eval-in-global-scope + js/prettyFormat)))) + (catch :default o + (str o)))) + c)) (defn transpile-ocaml [exp _] (go - (try - ocaml-to-js - (catch :default o - (str o))))) + (let [[_ res] (ocaml-to-js exp)] + res))) -(def eval-opts {:editor-in-mode "text/ocaml" +(def eval-opts {:editor-in-mode "text/x-ocaml" :editor-out-mode "javascript" + :beautify? false :eval-fn eval-ocaml - :external-scripts [(codemirror-mode-src "ocaml") "https://viebel.github.io/klipse/repo/js/ocaml-compiler.js"] + :external-scripts [(codemirror-mode-src "mllike") "https://viebel.github.io/klipse/repo/js/ocaml-compiler.js" "https://viebel.github.io/klipse/repo/js/pretty_format.js"] ; oCaml does not know a single line comment }) -(def transpile-ocaml {:editor-in-mode "text/ocaml" +(def transpile-opts {:editor-in-mode "text/x-ocaml" :editor-out-mode "javascript" + :beautify? false :eval-fn transpile-ocaml - :external-scripts [(codemirror-mode-src "ocaml") "https://viebel.github.io/klipse/repo/js/ocaml-compiler.js"] + :external-scripts [(codemirror-mode-src "mllike") "https://viebel.github.io/klipse/repo/js/ocaml-compiler.js"] ; oCaml does not know a single line comment }) (register-mode "eval-ocaml" "selector_eval_ocaml" eval-opts) -(register-mode "transpile-ocaml" "selector_transpile_ocaml" transpile-ocaml) +(register-mode "transpile-ocaml" "selector_transpile_ocaml" transpile-opts)