Skip to content
This repository has been archived by the owner on Jan 2, 2023. It is now read-only.

Commit

Permalink
Fix logic precedence
Browse files Browse the repository at this point in the history
  • Loading branch information
borkdude committed Dec 27, 2022
1 parent 01fd1c8 commit 11c39ef
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 42 deletions.
18 changes: 9 additions & 9 deletions cherry/src/cherry/compiler.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
[squint.compiler-common :as cc :refer [#?(:cljs Exception)
#?(:cljs format)
*aliases* *imported-vars* *public-vars* *repl* comma-list emit emit-args emit-infix
emit-special emit-wrap escape-jsx expr-env infix-operator? prefix-unary?
emit-special emit-return escape-jsx expr-env infix-operator? prefix-unary?
statement suffix-unary?]])
#?(:cljs (:require-macros [cherry.resource :as resource])))

Expand All @@ -35,7 +35,7 @@

(defmethod emit #?(:clj clojure.lang.Keyword :cljs Keyword) [expr env]
(swap! *imported-vars* update "cherry-cljs/lib/cljs_core.js" (fnil conj #{}) 'keyword)
(emit-wrap (str (format "keyword(%s)" (pr-str (subs (str expr) 1)))) env))
(emit-return (str (format "keyword(%s)" (pr-str (subs (str expr) 1)))) env))

(def special-forms (set ['var '. 'if 'funcall 'fn 'fn* 'quote 'set!
'return 'delete 'new 'do 'aget 'while
Expand Down Expand Up @@ -110,7 +110,7 @@
(repeat statement-separator))))

(defmethod emit-special 'quote [_ env [_ form]]
(emit-wrap (emit form (expr-env (assoc env :quote true))) env))
(emit-return (emit form (expr-env (assoc env :quote true))) env))

(defmethod emit-special 'deftype* [_ env [_ t fields pmasks body]]
(let [fields (map munge fields)]
Expand Down Expand Up @@ -154,7 +154,7 @@
(emit test env)
(emit then env)
(emit else env)))
(emit-wrap env))
(emit-return env))
(str (format "if (truth_(%s)) {\n"
(emit test (assoc env :context :expr)))
(emit then env)
Expand Down Expand Up @@ -266,17 +266,17 @@
(symbol "")
tag-name)
tag-name (emit tag-name (expr-env (dissoc env :jsx)))]
(emit-wrap (format "<%s%s>%s</%s>"
(emit-return (format "<%s%s>%s</%s>"
tag-name
(jsx-attrs attrs env)
(let [env (expr-env env)]
(str/join " " (map #(emit % env) elts)))
tag-name) env))
(if (::js (meta expr))
(emit-wrap (format "[%s]"
(emit-return (format "[%s]"
(str/join ", " (emit-args env expr))) env)
(do (swap! *imported-vars* update "cherry-cljs/lib/cljs_core.js" (fnil conj #{}) 'vector)
(emit-wrap (format "vector(%s)"
(emit-return (format "vector(%s)"
(str/join ", " (emit-args env expr))) env)))))

#?(:cljs (derive PersistentArrayMap ::map))
Expand All @@ -302,13 +302,13 @@
(escape-jsx (-> (if map-fn
(format "%s(%s)" map-fn keys)
(format "({ %s })" keys))
(emit-wrap env)) env*)))
(emit-return env)) env*)))

(defmethod emit #?(:clj clojure.lang.PersistentHashSet
:cljs PersistentHashSet)
[expr env]
(swap! *imported-vars* update "cherry-cljs/lib/cljs_core.js" (fnil conj #{}) 'hash_set)
(emit-wrap (format "%s%s" "hash_set"
(emit-return (format "%s%s" "hash_set"
(comma-list (emit-args env expr))) env))

(defn transpile-form [f]
Expand Down
47 changes: 25 additions & 22 deletions compiler-common/src/squint/compiler_common.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
template
substitutions))

(defn emit-wrap [s env]
(defn emit-return [s env]
(if (= :return (:context env))
(format "return %s;" s)
s))
Expand Down Expand Up @@ -66,7 +66,7 @@
(str/replace #"\$$" ""))))

(defmethod emit nil [_ env]
(emit-wrap "null" env))
(emit-return "null" env))

#?(:clj (derive #?(:clj java.lang.Integer) ::number))
#?(:clj (derive #?(:clj java.lang.Long) ::number))
Expand All @@ -85,22 +85,22 @@

(defmethod emit ::number [expr env]
(-> (str expr)
(emit-wrap env)
(emit-return env)
(emit-repl env)
(escape-jsx env)))

(defmethod emit #?(:clj java.lang.String :cljs js/String) [^String expr env]
(-> (if (and (:jsx env)
(not (:jsx-attr env)))
expr
(emit-wrap (pr-str expr) env))
(emit-return (pr-str expr) env))
(emit-repl env)))

(defmethod emit #?(:clj java.lang.Boolean :cljs js/Boolean) [^String expr env]
(-> (if (:jsx-attr env)
(escape-jsx expr env)
(str expr))
(emit-wrap env)
(emit-return env)
(emit-repl env)))

#?(:clj (defmethod emit #?(:clj java.util.regex.Pattern) [expr _env]
Expand All @@ -109,7 +109,7 @@
(defmethod emit :default [expr env]
;; RegExp case moved here:
;; References to the global RegExp object prevents optimization of regular expressions.
(emit-wrap (str expr) env))
(emit-return (str expr) env))

(def prefix-unary-operators '#{!})

Expand Down Expand Up @@ -148,7 +148,7 @@
'+ "+"}]
(str "(" (str/join (str " " (or (substitutions operator) operator) " ")
(emit-args env args)) ")"))
(emit-wrap enc-env)))
(emit-return enc-env)))
(emit-repl enc-env)))))

(def core-vars (atom #{}))
Expand All @@ -164,7 +164,7 @@

(defmethod emit #?(:clj clojure.lang.Symbol :cljs Symbol) [expr env]
(if (:quote env)
(emit-wrap (escape-jsx (emit (list 'cljs.core/symbol
(emit-return (escape-jsx (emit (list 'cljs.core/symbol
(str expr))
(dissoc env :quote))env)
env)
Expand Down Expand Up @@ -195,7 +195,7 @@
(let [m (munged-name expr)]
(str (when *repl*
(str (munge *cljs-ns*) ".")) m)))))]
(-> (emit-wrap (escape-jsx (str expr) env)
(-> (emit-return (escape-jsx (str expr) env)
env)
(emit-repl env))))))

Expand Down Expand Up @@ -350,7 +350,7 @@
(emit-var more env)))

(defn js-await [env more]
(-> (emit-wrap (wrap-await (emit more (expr-env env))) env)
(-> (emit-return (wrap-await (emit more (expr-env env))) env)
(emit-repl env)))

(defmethod emit-special 'js/await [_ env [_await more]]
Expand Down Expand Up @@ -483,13 +483,13 @@

(defn emit-method [env obj method args]
(let [eenv (expr-env env)]
(emit-wrap (str (emit obj eenv) "."
(emit-return (str (emit obj eenv) "."
(str method)
(comma-list (emit-args env args)))
env)))

(defn emit-aget [env var idxs]
(emit-wrap (apply str
(emit-return (apply str
(emit var (expr-env env))
(interleave (repeat "[") (emit-args env idxs) (repeat "]")))
env))
Expand Down Expand Up @@ -517,30 +517,33 @@
(defmethod emit-special 'set! [_type env [_set! var val & more]]
(assert (or (nil? more) (even? (count more))))
(let [eenv (expr-env env)]
(emit-wrap (str (emit var eenv) " = " (emit val eenv) statement-separator
(emit-return (str (emit var eenv) " = " (emit val eenv) statement-separator
#_(when more (str (emit (cons 'set! more) env))))
env)))

(defmethod emit-special 'new [_type env [_new class & args]]
(emit-wrap (str "new " (emit class (expr-env env)) (comma-list (emit-args env args))) env))
(emit-return (str "new " (emit class (expr-env env)) (comma-list (emit-args env args))) env))

(defmethod emit-special 'dec [_type env [_ var]]
(emit-wrap (str "(" (emit var (assoc env :context :expr)) " - " 1 ")") env))
(emit-return (str "(" (emit var (assoc env :context :expr)) " - " 1 ")") env))

(defmethod emit-special 'inc [_type env [_ var]]
(emit-wrap (str "(" (emit var (assoc env :context :expr)) " + " 1 ")") env))
(emit-return (str "(" (emit var (assoc env :context :expr)) " + " 1 ")") env))

#_(defmethod emit-special 'defined? [_type env [_ var]]
(str "typeof " (emit var env) " !== \"undefined\" && " (emit var env) " !== null"))

#_(defmethod emit-special '? [_type env [_ test then else]]
(str (emit test env) " ? " (emit then env) " : " (emit else env)))

(defn wrap-parens [s]
(str "(" s ")"))

(defmethod emit-special 'and [_type env [_ & more]]
(emit-wrap (apply str (interpose " && " (emit-args env more))) env))
(emit-return (wrap-parens (apply str (interpose " && " (emit-args env more)))) env))

(defmethod emit-special 'or [_type env [_ & more]]
(emit-wrap (apply str (interpose " || " (emit-args env more))) env))
(emit-return (wrap-parens (apply str (interpose " || " (emit-args env more)))) env))

(defmethod emit-special 'while [_type env [_while test & body]]
(str "while (" (emit test) ") { \n"
Expand Down Expand Up @@ -605,7 +608,7 @@ break;}" body)
(let [signature (first expr)
body (rest expr)]
(str (emit-function env nil signature body))))
(emit-wrap env))))
(emit-return env))))

(defmethod emit-special 'fn* [_type env [_fn & sigs :as expr]]
(let [async? (:async (meta expr))]
Expand Down Expand Up @@ -653,7 +656,7 @@ break;}" body)
"}\n")))
(not= :statement (:context env))
(wrap-iife))
(emit-wrap outer-env)))))
(emit-return outer-env)))))

#_(defmethod emit-special 'funcall [_type env [fname & args :as _expr]]
(-> (emit-wrap (str
Expand All @@ -676,11 +679,11 @@ break;}" body)
cherry+interop? (and
cherry?
(= "js" ns))]
(-> (emit-wrap (str
(-> (emit-return (str
(emit fname (expr-env env))
;; this is needed when calling keywords, symbols, etc. We could
;; optimize this later by inferring that we're not directly
;; calling a `function`.
;; calling a `function`.
(when (and cherry? (not cherry+interop?)) ".call")
(comma-list (emit-args env
(if cherry?
Expand Down
4 changes: 4 additions & 0 deletions squint/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

[Squint](https://github.com/squint-cljs/squint): ClojureScript syntax to JavaScript compiler

## 0.0.7

[#274](https://github.com/squint-cljs/squint/issues/274): fix logic precedence by wrapping in parens

## 0.0.6

Add preliminary Node.js API in `node.js`
Expand Down
22 changes: 11 additions & 11 deletions squint/src/squint/compiler.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
[squint.compiler-common :as cc :refer [#?(:cljs Exception)
#?(:cljs format)
*aliases* *cljs-ns* *excluded-core-vars* *imported-vars* *public-vars* *repl*
comma-list emit emit-args emit-infix emit-repl emit-special emit-wrap escape-jsx
comma-list emit emit-args emit-infix emit-repl emit-special emit-return escape-jsx
expr-env infix-operator? prefix-unary? statement suffix-unary?]]
[squint.internal.deftype :as deftype]
[squint.internal.destructure :refer [core-let]]
Expand All @@ -28,7 +28,7 @@


(defmethod emit #?(:clj clojure.lang.Keyword :cljs Keyword) [expr env]
(-> (emit-wrap (str (pr-str (subs (str expr) 1))) env)
(-> (emit-return (str (pr-str (subs (str expr) 1))) env)
(emit-repl env)))

(def special-forms (set ['var '. 'if 'funcall 'fn 'fn* 'quote 'set!
Expand Down Expand Up @@ -100,13 +100,13 @@
(str (emit arg) operator))

(defmethod emit-special 'quote [_ env [_ form]]
(emit-wrap (emit form (expr-env (assoc env :quote true))) env))
(emit-return (emit form (expr-env (assoc env :quote true))) env))

(defmethod emit-special 'not [_ env [_ form]]
(emit-wrap (str "!" (emit form (expr-env env))) env))
(emit-return (str "!" (emit form (expr-env env))) env))

(defmethod emit-special 'js/typeof [_ env [_ form]]
(emit-wrap (str "typeof " (emit form (expr-env env))) env))
(emit-return (str "typeof " (emit form (expr-env env))) env))

(defmethod emit-special 'letfn* [_ env [_ form & body]]
(let [bindings (take-nth 2 form)
Expand All @@ -118,7 +118,7 @@
(emit let env)))

(defmethod emit-special 'quote [_ env [_ form]]
(emit-wrap (emit form (expr-env (assoc env :quote true))) env))
(emit-return (emit form (expr-env (assoc env :quote true))) env))

#_(defmethod emit-special 'let* [_type enc-env [_let bindings & body]]
(emit-let enc-env bindings body false))
Expand Down Expand Up @@ -167,7 +167,7 @@
(emit test env)
(emit then env)
(emit else env)))
(emit-wrap env))
(emit-return env))
(str (format "if (%s) {\n"
(emit test (assoc env :context :expr)))
(emit then env)
Expand Down Expand Up @@ -288,14 +288,14 @@
(symbol "")
tag-name)
tag-name (emit tag-name (expr-env (dissoc env :jsx)))]
(emit-wrap (format "<%s%s>%s</%s>"
(emit-return (format "<%s%s>%s</%s>"
tag-name
(jsx-attrs attrs env)
(let [env (expr-env env)]
(str/join " " (map #(emit % env) elts)))
tag-name)
env))
(-> (emit-wrap (format "[%s]"
(-> (emit-return (format "[%s]"
(str/join ", " (emit-args env expr))) env)
(emit-repl env))))

Expand All @@ -314,13 +314,13 @@
(emit (val pair) expr-env)))
keys (str/join ", " (map mk-pair (seq expr)))]
(escape-jsx (-> (format "({ %s })" keys)
(emit-wrap env))
(emit-return env))
env*)))

(defmethod emit #?(:clj clojure.lang.PersistentHashSet
:cljs PersistentHashSet)
[expr env]
(emit-wrap
(emit-return
(format "new Set([%s])"
(str/join ", " (emit-args (expr-env env) expr)))
env))
Expand Down
3 changes: 3 additions & 0 deletions squint/test/squint/compiler_test.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -1214,6 +1214,9 @@
(is (= 2 (jsv! '(do (defn foo [a b] (and a b)) (foo 1 2)))))
(is (= 1 (jsv! '(do (defn foo [a b] (or a b)) (foo 1 2))))))

(deftest logic-precedence
(is (false? (jsv! '(and (or true false) false)))))

(deftest multiple-arity-infix
(is (true? (jsv! '(> 5 4 3 2 1))))
(is (true? (jsv! '(> 5 4 3))))
Expand Down

0 comments on commit 11c39ef

Please sign in to comment.