From 11a51cf708a8a3c38566983fbb0c380a6352312a Mon Sep 17 00:00:00 2001 From: Scott Richmond Date: Sun, 20 Mar 2022 14:14:15 -0400 Subject: [PATCH] Interpret match expressions --- src/ludus/interpreter.clj | 34 ++++++++++++++++++++++++++++++++-- src/ludus/parser.clj | 12 ++++++------ 2 files changed, 38 insertions(+), 8 deletions(-) diff --git a/src/ludus/interpreter.clj b/src/ludus/interpreter.clj index 245e3cf..f903701 100644 --- a/src/ludus/interpreter.clj +++ b/src/ludus/interpreter.clj @@ -97,6 +97,30 @@ (interpret else-expr ctx) ))) +(defn- interpret-match [ast ctx] + (let [match-expr (:expr ast) + expr (interpret match-expr ctx) + clauses (:clauses ast)] + (loop [clause (first clauses) + clauses (rest clauses)] + (if clause + (let [pattern (:pattern clause) + body (:body clause) + new-ctx (atom {::parent ctx}) + match? (match pattern expr new-ctx) + success (:success match?) + clause-ctx (:ctx match?)] + (if success + (do + (swap! new-ctx #(merge % clause-ctx)) + (interpret body new-ctx)) + (recur (first clauses) (rest clauses)) + )) + (throw (ex-info "Match Error: No match found" {})) + )) + ) + ) + (defn interpret [ast ctx] (case (::ast/type ast) @@ -108,6 +132,8 @@ ::ast/if (interpret-if ast ctx) + ::ast/match (interpret-match ast ctx) + ::ast/block (let [exprs (:exprs ast) inner (pop exprs) @@ -154,8 +180,12 @@ (do (def source " - let (foo, (_, baz)) = (1, (2, 3)) - baz + let foo = (1, 2) + match foo with { + 0 -> :zero + (_, 3) -> :one + & baz -> baz + } ") (println "") diff --git a/src/ludus/parser.clj b/src/ludus/parser.clj index 4857bf5..7e01a5e 100644 --- a/src/ludus/parser.clj +++ b/src/ludus/parser.clj @@ -466,7 +466,7 @@ (let [curr (current parser)] (case (::token/type curr) ::token/rbrace - (assoc parser ::ast {::ast/type ::ast/clauses :clauses clauses}) + (assoc (advance parser) ::ast {::ast/type ::ast/clauses :clauses clauses}) ::token/newline (recur (accept-many #{::token/newline} parser) clauses) @@ -566,10 +566,10 @@ (do (def pp pp/pprint) (def source "match foo with { - _ -> foo - foo () -> bar - () -> baz - }") + 0 -> foo + } + + ") (def lexed (scanner/scan source)) (def tokens (:tokens lexed)) (def p (parser tokens)) @@ -581,7 +581,7 @@ (println "*** *** NEW PARSE *** ***") (-> p - (parse-match) + (parse-script) (::ast) (pp) )