diff --git a/src/ludus/interpreter.clj b/src/ludus/interpreter.clj index 94d56fc..c45df39 100644 --- a/src/ludus/interpreter.clj +++ b/src/ludus/interpreter.clj @@ -109,6 +109,23 @@ (recur (first clauses) (rest clauses)))) (throw (ex-info "Match Error: No match found" {})))))) +(defn- interpret-cond [ast ctx] + (let [clauses (:clauses ast)] + (loop [clause (first clauses) + clauses (rest clauses)] + (if (not clause) + (throw (ex-info "Cond Error: No match found" {})) + (let [test-expr (:test clause) + body (:body clause) + truthy? (boolean (interpret-ast test-expr ctx))] + (if truthy? + (interpret-ast body ctx) + (recur (first clauses) (rest clauses)) + ) + ) + ) + ))) + (defn- interpret-called-kw [kw tuple ctx] ;; TODO: check this statically (if (not (= 1 (:length tuple))) @@ -228,6 +245,8 @@ ::ast/match (interpret-match ast ctx) + ::ast/cond (interpret-cond ast ctx) + ::ast/synthetic (interpret-synthetic ast ctx) ::ast/fn (interpret-fn ast ctx) @@ -286,10 +305,13 @@ (def source " - fn square (x) -> mult (x, x) - - let foo = square (_) + let foo = 2 + match foo with { + 1 -> :one + 2 -> :two + else -> :oops + } ") diff --git a/src/ludus/parser.clj b/src/ludus/parser.clj index e7ce8c0..bac7dba 100644 --- a/src/ludus/parser.clj +++ b/src/ludus/parser.clj @@ -487,7 +487,9 @@ (parse-then (accept ::token/newline ast)))) (defn- parse-match-clause [parser] - (let [pattern (parse-pattern parser) + (let [pattern (if (= ::token/else (token-type parser)) + (-> parser (advance) (assoc ::ast {::ast/type ::ast/placeholder})) + (parse-pattern parser)) rarrow (expect* #{::token/rarrow} "Expected arrow after pattern" pattern)] (if (:success rarrow) (let [body (parse-expr (:parser rarrow))] @@ -531,7 +533,13 @@ (panic parser "Expected with after match expression")))) (defn- parse-cond-clause [parser] - (let [expr (parse-expr parser) + (let [expr (if (= ::token/else (token-type parser)) + (-> parser + (advance) + (assoc ::ast {::ast/type ::ast/atom + :token ::token/else + :value true})) + (parse-expr parser)) rarrow (expect* #{::token/rarrow} "Expected arrow after expression in cond clause" expr)] (if (:success rarrow) (let [body (parse-expr (:parser rarrow))] @@ -543,7 +551,6 @@ (loop [parser (accept-many #{::token/newline} parser) clauses []] (let [curr (current parser)] - (println "parsing a clause: " curr) (case (::token/type curr) ::token/rbrace (if (< 0 (count clauses)) @@ -562,7 +569,6 @@ (expect* #{::token/lbrace} "Expected { after cond" (advance parser))] (if (:success header) (let [clauses (parse-cond-clauses (:parser header))] - (println "Found all the clauses") (assoc clauses ::ast {::ast/type ::ast/cond :clauses (get-in clauses [::ast :clauses])}) ) @@ -711,9 +717,12 @@ (parser) (parse-script))) -(do +(comment (def pp pp/pprint) - (def source "cond {} + (def source "match foo with { + 1 -> :foo + else -> bar + } ") (def lexed (scanner/scan source))