diff --git a/src/ludus/interpreter.clj b/src/ludus/interpreter.clj index d33cb79..95c09c6 100644 --- a/src/ludus/interpreter.clj +++ b/src/ludus/interpreter.clj @@ -89,6 +89,30 @@ {:success false :reason (str "Could not match " pattern " with " value " at key " kw)} ))))))) +(defn- match-struct [pattern value ctx-vol] + (cond + (not (map? value)) + {:success false :reason "Could not match non-struct value to struct pattern"} + + (not (::data/struct value)) + {:success false :reason "Cannot match non-struct data types a struct pattern"} + + :else + (let [members (:members pattern) + kws (keys members)] + (loop [i (dec (count kws)) ctx {}] + (if (> 0 i) + {:success true :ctx ctx} + (let [kw (nth kws i)] + (if (contains? value kw) + (let [match? (match (kw members) (kw value) ctx-vol)] + (if (:success match?) + (recur (dec i) (merge ctx (:ctx match?))) + {:success false :reason (str "Could not match " pattern " with " value " at key " kw)} + )) + {:success false :reason (str "Could not match " pattern " with " value " at key " kw)} + ))))))) + (defn- match [pattern value ctx-vol] (let [ctx @ctx-vol] (case (::ast/type pattern) @@ -113,6 +137,8 @@ ::ast/hash (match-hashmap pattern value ctx-vol) + ::ast/struct (match-struct pattern value ctx-vol) + (throw (ex-info "Unknown pattern on line " {:pattern pattern}))))) (defn- update-ctx [ctx new-ctx] @@ -461,7 +487,9 @@ (def source " - let #{foo, bar} = @{:foo :bar, :bar nil} + let @{foo, bar} = @{:foo :bar, :bar nil, :baz 42} + + ")