Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@souenzzo
Last active January 13, 2018 11:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save souenzzo/4c731a34200286fba9f3b3b7f572285c to your computer and use it in GitHub Desktop.
Save souenzzo/4c731a34200286fba9f3b3b7f572285c to your computer and use it in GitHub Desktop.
Trying to represent js code as EDN.
(defn parse-args
[args]
(string/join ", " (for [arg args]
(cond
(map? arg) (let [{:keys [keys]} arg]
(format "{ %s }" (parse-args keys)))
:else arg))))
(defn emit
[x]
(cond
(list? x) (let [[op & args] x]
(cond
('#{const var let} op) (format "%s %s = %s" op (first args) (emit (second args)))
('#{=>} op) (format "((%s) %s %s)" (parse-args (first args)) op (emit (second args)))
('#{function} op) (format "%s %s (%s) { %s }" op (first args)
(parse-args (second args))
(emit (apply list (into '[do] (rest (rest args))))))
('#{+ - == / ===} op) (format "(%s %s %s)" (emit (first args)) op (emit (second args)))
('#{new} op) (format "(%s %s(%s))" op (first args) (string/join ", " (map emit (rest args))))
('#{switch} op) (format "%s %s { %s default: %s }"
op
(emit (first args))
(string/join "\n" (for [[k v] (partition 2 (butlast (rest args)))]
(format "case %s: \n %s; \nbreak;\n" (emit k) (emit v))))
(emit (last args)))
('#{do} op) (string/join ";\n" (concat (map emit args) [""]))
('#{return} op) (format "%s %s" op (string/join ", " (map emit args)))
(and (symbol? op)
(string/starts-with? op ".")) (format "%s%s(%s)" (emit (first args)) op (emit (second args)))
:else (format "(%s(%s))" op (string/join ", " (map emit args)))
))
(keyword? x) (format "'%s'" (name x))
(string? x) (format "\"%s\"" x)
(vector? x) (format "([%s])" (string/join ", " (map emit x)))
(map? x) (format "({%s})" (string/join ", " (for [[k v] x] (string/join ": " [(emit k) (emit v)]))))
:else (format "(%s)" x)))
(deftest code
(let []
(fact
(emit '0) => "(0)"
(emit '(const x 44)) => "const x = (44)"
(emit '(=> [x] x)) => "((x) => (x))"
(emit '(+ 1 2)) => "((1) + (2))"
(emit '(var myFoo (=> [x y] (+ x y)))) => "var myFoo = ((x, y) => ((x) + (y)))"
(emit '(myFoo 1 2)) => "(myFoo((1), (2)))"
(emit '(function myFn [a b] (return (+ a b)))) => "function myFn (a, b) { return ((a) + (b));\n }"
(emit ':aaa) => "'aaa'"
(emit '(const x (+ :xyz 33))) => "const x = ('xyz' + (33))"
(emit '(const f (=> [{:keys [a]}] (+ a 55)))) => "const f = (({ a }) => ((a) + (55)))"
(emit '(const f (=> [] (+ 55 0)))) => "const f = (() => ((55) + (0)))"
(emit '[]) => "([])"
(emit '[1 :a "b" (f c)]) => "([(1), 'a', \"b\", (f((c)))])"
(emit '{:foo 33}) => "({'foo': (33)})"
(emit '(.get x 33)) => "(x).get((33))"
(emit '(.values Object {:a 33})) => "(Object).values(({'a': (33)}))"
(emit '(do 1 2)) => "(1);\n(2);\n"
(emit '(new Set [1 2])) => "(new Set(([(1), (2)])))"
(emit '(function myFn
[a b]
(const x (+ a b))
(.log console x)
(return x)))
=> "function myFn (a, b) { const x = ((a) + (b));\n(console).log((x));\nreturn (x);\n }"
(emit '(switch a b)) => "switch (a) { default: (b) }"
(emit '(switch 3
(+ 1 2) :foo
5)) => "switch (3) { case ((1) + (2)): \n 'foo'; \nbreak;\n default: (5) }"
)
)
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment