Skip to content

Commit

Permalink
feat: adding callables definition
Browse files Browse the repository at this point in the history
  • Loading branch information
BRonen committed Mar 30, 2024
1 parent aaeb252 commit eb6e415
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 16 deletions.
20 changes: 13 additions & 7 deletions src/bronen/kekwisp.clj
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
(ns bronen.kekwisp)

(defn quote? [s] (not= s \"))
(defn quote? [s] (and (not= s \")
(not= s \))
(not= s \space)))

; Lexer

(defn lexer-literal
"Tokenize a literal that begins with a non-digit until finds whitespace and returns the rest"
[chars]
(let [[content rst] (split-with #(not (= % \space)) chars)]
[(drop 1 rst) {:token "literal" :value content}]))
(let [[content rst] (split-with quote? chars)]
[rst {:token "literal" :value content}]))

(defn lexer-number
"Tokenize a string that begins with a digit until finds non-digit and returns the rest"
Expand Down Expand Up @@ -64,7 +66,7 @@
(loop [result []
remaining tokens]
(if (and (not= (count remaining) 0)
(not= (-> remaining (first) (:token)) "rbraces"))
(not= (-> remaining first :token) "rbraces"))
(let [[r rr] (parse remaining)] (recur (conj result r) rr))
(let [rest-without-rbraces (drop 1 remaining)
rest-or-nil (if (empty? rest-without-rbraces)
Expand Down Expand Up @@ -104,12 +106,16 @@
"definition" (do (swap! ctx #(conj % {(:value (nth values 1))
(:value (nth values 2))}))
(when (nth values 3 false) (evaluate (nth values 3) ctx)))
"sum" (apply + (map #(evaluate % ctx) (drop 1 values)))
"sum" (do (println values) (apply + (map #(evaluate % ctx) (drop 1 values))))
"subtraction" (apply - (map #(evaluate % ctx) (drop 1 values)))
"multiplication" (apply * (map #(evaluate % ctx) (drop 1 values)))
"division" (apply / (map #(evaluate % ctx) (drop 1 values)))
"function" (swap! ctx #(conj % {(:value (get values 1))
(:value (get values 2))})))))
"function" {:token "callable"
:value (fn [args]
(let [params (map :value (:value (nth values 1)))
arg-param-map (apply assoc {} (interleave params args))]
(swap! ctx #(conj % arg-param-map))
(evaluate (nth values 2) ctx)))})))

(defn evaluate
"Evaluates a syntax tree"
Expand Down
26 changes: 17 additions & 9 deletions test/bronen/kekwisp_test.clj
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,12 @@
{:token "rbraces"}
{:token "rbraces"}])
[{:token "list"
:value [{:token "string" :value "lorem ipsum"}
{:token "list"
:value [{:token "list"
:value [{:token "literal" :value "println"}
{:token "number" :value 123}]}
{:token "number" :value 234}]}]} nil]))))
:value [{:token "string" :value "lorem ipsum"}
{:token "list"
:value [{:token "list"
:value [{:token "literal" :value "println"}
{:token "number" :value 123}]}
{:token "number" :value 234}]}]} nil]))))

(deftest eval-test
(testing "Should evaluate a syntax tree and return a value"
Expand Down Expand Up @@ -111,6 +111,14 @@
nil))
(is (= @ctx
{"wasd" 123
"ddd" 444})))))


"ddd" 444}))))
(testing "Should evaluate a string that defines a function"
(let [ctx (atom {})
func (-> "(fn (a b) (+ a b))"
(lexer)
(parse)
(first)
(#(evaluate % ctx)))]
(is (= (:token func) "callable"))
(is (= ((:value func) '(2 3)) 5))
(is (= ((:value func) '(2 5)) 7)))))

0 comments on commit eb6e415

Please sign in to comment.