From a5914076b049ef086088c0d9604d949f84745162 Mon Sep 17 00:00:00 2001 From: Scott Richmond Date: Wed, 18 May 2022 19:35:41 -0400 Subject: [PATCH] Interpret loop/recur --- src/ludus/interpreter.clj | 44 +++++++++++++++++++++++++++++++-------- 1 file changed, 35 insertions(+), 9 deletions(-) diff --git a/src/ludus/interpreter.clj b/src/ludus/interpreter.clj index bf2ab89..352b70c 100644 --- a/src/ludus/interpreter.clj +++ b/src/ludus/interpreter.clj @@ -248,9 +248,8 @@ {::data/struct true ::data/type ::data/ns ::data/name name} (map-values #(interpret-ast % ctx)) members)] - (do - (vswap! ctx update-ctx {name ns}) - ns))))) + (vswap! ctx update-ctx {name ns}) + ns)))) (defn- interpret-import [ast ctx] (let [path (:path ast) @@ -277,6 +276,33 @@ (vswap! ctx update-ctx {name ref}) ref))) +(defn- interpret-loop [ast ctx] + (let [tuple (interpret-ast (:expr ast) ctx) + clauses (:clauses ast)] + (loop [input tuple] + (let [output (loop [clause (first clauses) + clauses (rest clauses)] + (if clause + (let [pattern (:pattern clause) + body (:body clause) + new-ctx (volatile! {::parent ctx}) + match? (match pattern input new-ctx) + success (:success match?) + clause-ctx (:ctx match?)] + (if success + (do + (vswap! new-ctx #(merge % clause-ctx)) + (interpret-ast body new-ctx)) + (recur (first clauses) (rest clauses)))) + + (throw (ex-info (str "Match Error: No match found in loop for " input) {}))))] + (if (::data/recur output) + (recur (:tuple output)) + output + )) + )) + ) + (defn interpret-ast [ast ctx] (case (::ast/type ast) @@ -306,6 +332,11 @@ ::ast/ref (interpret-ref ast ctx) + ::ast/recur + {::data/recur true :tuple (interpret-ast (:tuple ast) ctx)} + + ::ast/loop (interpret-loop ast ctx) + ::ast/block (let [exprs (:exprs ast) inner (pop exprs) @@ -366,15 +397,10 @@ (println (ex-message e)) (pp/pprint (ex-data e))))) -(do +(comment (def source " - ref foo = nil - ref bar = nil - - eq (foo, bar) - ") (println "")