From c9ccffa067b56292b68e989099e2a2347486b737 Mon Sep 17 00:00:00 2001 From: Scott Richmond Date: Mon, 4 Dec 2023 00:41:57 -0500 Subject: [PATCH] Basically wire the things up! --- src/ludus/data.cljc | 3 ++- src/ludus/interpreter.cljc | 25 ++++++++++++----------- src/ludus/node.cljc | 42 ++++++++++++++++++++++++++++++++++++++ src/ludus/node.cljs | 16 --------------- src/ludus/postlude.ld | 11 ++++++++++ src/ludus/prelude.cljc | 8 +++++++- src/ludus/prelude.ld | 40 +++++++++++++++++++++++++++--------- 7 files changed, 105 insertions(+), 40 deletions(-) create mode 100644 src/ludus/node.cljc delete mode 100644 src/ludus/node.cljs create mode 100644 src/ludus/postlude.ld diff --git a/src/ludus/data.cljc b/src/ludus/data.cljc index fa91073..dcddd0b 100644 --- a/src/ludus/data.cljc +++ b/src/ludus/data.cljc @@ -1 +1,2 @@ -(ns ludus.data) \ No newline at end of file +(ns ludus.data) + diff --git a/src/ludus/interpreter.cljc b/src/ludus/interpreter.cljc index d147cf7..e2804c2 100644 --- a/src/ludus/interpreter.cljc +++ b/src/ludus/interpreter.cljc @@ -895,7 +895,7 @@ interpreted (interpret-ast parsed base-ctx) namespace (dissoc interpreted ::data/type ::data/name ::data/struct) context (ns->ctx namespace)] - ;(println context) + (println "Prelude fully loaded.") context)) ; ;; TODO: update this to use new parser pipeline & new AST representation @@ -939,17 +939,18 @@ {:result :error :ctx (volatile! orig-ctx)}))))) (defn interpret-safe [source parsed ctx] - (try - (let [base-ctx (volatile! {::parent (volatile! (merge ludus-prelude ctx))})] - (interpret-ast parsed base-ctx)) - (catch #?(:clj Throwable :cljs js/Object) e - (println "Ludus panicked!") - (println "On line" (get-in (ex-data e) [:ast :token :line])) - (println ">>> " (get-line source (get-in (ex-data e) [:ast :token :line]))) - (println (ex-message e)) - (pp/pprint (ex-data e)) - (throw e) - ))) + (let [base-ctx (volatile! {::parent (volatile! (merge ludus-prelude ctx))})] + (try + (println "Running source: " source) + (interpret-ast parsed base-ctx) + (catch #?(:clj Throwable :cljs js/Object) e + (println "Ludus panicked!") + (println "On line" (get-in (ex-data e) [:ast :token :line])) + (println ">>> " (get-line source (get-in (ex-data e) [:ast :token :line]))) + (println (ex-message e)) + (pp/pprint (ex-data e)) + (throw e) + )))) ;; repl (comment diff --git a/src/ludus/node.cljc b/src/ludus/node.cljc new file mode 100644 index 0000000..27f6830 --- /dev/null +++ b/src/ludus/node.cljc @@ -0,0 +1,42 @@ +(ns ludus.node + (:require [ludus.interpreter :as i] + [ludus.grammar :as g] + [ludus.parser :as p] + [ludus.scanner :as s] + [ludus.prelude :as pre] + [ludus.show :as show] + [ludus.base :as base] + [ludus.data :as data] + ) + ) + +(declare ld->clj) + +(defn cljify [[k v]] [k (ld->clj v)]) + +(defn ld->clj [value] + (case (base/get-type value) + (:nil :number :string :boolean :keyword :set) value + + (:list :tuple) (into [] (map ld->clj) (rest value)) + + (:dict :struct :ns) (into {} (map cljify) (dissoc value ::data/dict ::data/struct ::data/type ::data/name)) + + :ref (ld->clj @(::value value)) + + :fn (throw (ex-info (str "Cannot export functions from Ludus to Clojure. You tried exporting " (show/show value)) {})))) + +(defn run [source] + (let [user_scanned (s/scan source) + user_tokens (:tokens user_scanned) + user_parsed (p/apply-parser g/script user_tokens) + user_result (i/interpret-safe source user_parsed {}) + post_scanned (s/scan pre/postlude) + post_tokens (:tokens post_scanned) + post_parsed (p/apply-parser g/script post_tokens) + post_result (i/interpret-safe source post_parsed {}) + ludus_result (assoc post_result :result user_result) + clj_result (ld->clj ludus_result) + ] + #?(:clj clj_result :cljs (clj->js clj_result)) + )) \ No newline at end of file diff --git a/src/ludus/node.cljs b/src/ludus/node.cljs deleted file mode 100644 index f25d418..0000000 --- a/src/ludus/node.cljs +++ /dev/null @@ -1,16 +0,0 @@ -(ns ludus.node - (:require [ludus.interpreter :as i] - [ludus.grammar :as g] - [ludus.parser :as p] - [ludus.scanner :as s]) - ) - -(defn run [source] - (let [scanned (s/scan source) - tokens (:tokens scanned) - parsed (p/apply-parser g/script tokens) - result (i/interpret-safe source parsed {})] - (clj->js {:result result - :errors [] - :console [] - :draw []}))) \ No newline at end of file diff --git a/src/ludus/postlude.ld b/src/ludus/postlude.ld new file mode 100644 index 0000000..6350e58 --- /dev/null +++ b/src/ludus/postlude.ld @@ -0,0 +1,11 @@ +& this file runs after any given interpretation +& the goal is to output any global state + +if turtle_state() :visible? then render_turtle! () else nil + +#{ + & :result result is provided elsewhere + :errors [] & if we get here there are no errors + :console deref (console) + :draw deref (p5_calls) +} \ No newline at end of file diff --git a/src/ludus/prelude.cljc b/src/ludus/prelude.cljc index 9f5ab42..5775776 100644 --- a/src/ludus/prelude.cljc +++ b/src/ludus/prelude.cljc @@ -6,4 +6,10 @@ #?( :clj (slurp "src/ludus/prelude.ld") :cljs (r/inline "./prelude.ld") - )) \ No newline at end of file + )) + +(def postlude + #?( + :clj (slurp "src/ludus/postlude.ld") + :cljs (r/inline "./postlude.ld") + )) \ No newline at end of file diff --git a/src/ludus/prelude.ld b/src/ludus/prelude.ld index a2275cc..21f27f0 100644 --- a/src/ludus/prelude.ld +++ b/src/ludus/prelude.ld @@ -125,9 +125,24 @@ fn append { (xs as :set, x) -> base :conj (xs, x) } +ref console = [] + +fn add_msg! { + "Adds a message to the console." + (msgs) -> { + let strs = map (show, msgs) + let msg = fold (concat, strs, "") + update! (console, append (_, msg)) + :ok + } +} + fn print! { "Sends a text representation of Ludus values to the console." - (...args) -> base :print (args) + (...args) -> { + base :print (args) + add_msg! (args) + } } fn show { @@ -694,23 +709,26 @@ let turtle_angle = 0.375 let turtle_color = (100, 100, 100, 100) fn render_turtle! () -> { - let state = do turtle_state > deref > last + let state = do turtle_states > deref > last if state :visible? then { add_call! ((:push)) let (r, g, b, a) = turtle_color add_call! ((:fill, r, g, b, a)) add_call! ((:noStroke)) - let #{heading, position} = state + let #{heading, :position (x, y)} = state + add_call! ((:translate, x, y)) add_call! ((:rotate, turn/deg (heading))) add_call! ((:beginShape)) - let head_unit = heading/vec (heading) + let head_unit = heading/vector (heading) let first = mult (head_unit, turtle_radius) - let second = rotate (first, turtle_angle) - let third = rotate (first, neg (turtle_angle)) - add_call! ((:vertex, first)) - add_call! ((:vertex, second)) - add_call! ((:vertx, third)) + let (x1, y1) = first + let (x2, y2) = rotate (first, turtle_angle) + let (x3, y3) = rotate (first, neg (turtle_angle)) + add_call! ((:vertex, x1, y1)) + add_call! ((:vertex, x2, y2)) + add_call! ((:vertex, x3, y3)) + add_call! ((:endShape)) add_call! ((:pop)) :ok } @@ -911,6 +929,7 @@ ns prelude { inc dec print! + console show prn! type @@ -991,4 +1010,5 @@ ns prelude { heading/vector turtle_state p5_calls, turtle_states, turtle_commands -} \ No newline at end of file + render_turtle! +}