From 40eeb480099fe238ae03566ae7167003789ea4c7 Mon Sep 17 00:00:00 2001 From: Andrey Orst Date: Mon, 9 Nov 2020 21:30:17 +0300 Subject: fix(macros): fix multimethods which use tables as the dispatch value --- macros/core.fnl | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) (limited to 'macros') diff --git a/macros/core.fnl b/macros/core.fnl index df3f8b8..ad555fb 100644 --- a/macros/core.fnl +++ b/macros/core.fnl @@ -179,6 +179,21 @@ `(let [(res# fennel#) (pcall require :fennel)] (if res# (. fennel#.metadata ,v))))) +(fn eq-fn [] + `(fn eq# [a# b#] + (if (and (= (type a#) :table) (= (type b#) :table)) + (do (var [res# count-a# count-b#] [true 0 0]) + (each [k# v# (pairs a#)] + (set res# (eq# v# (. b# k#))) + (set count-a# (+ count-a# 1)) + (when (not res#) (lua :break))) + (when res# + (each [_# _# (pairs b#)] + (set count-b# (+ count-b# 1))) + (set res# (and res# (= count-a# count-b#)))) + res#) + (= a# b#)))) + (fn* core.defmulti [name & opts] (let [docstring (if (string? (first opts)) (first opts)) @@ -193,14 +208,25 @@ {:__call (fn [_# ...] ,docstring - (let [dispatch-value# (,dispatch-fn ...)] + (let [dispatch-value# (,dispatch-fn ...) + (res# view#) (pcall require :fennelview)] ((or (. multimethods# dispatch-value#) (. multimethods# :default) (error (.. "No method in multimethod '" ,(tostring name) "' for dispatch value: " - dispatch-value#) 2)) ...))) - :multimethods multimethods#})))))) + ((if res# view# tostring) dispatch-value#)) + 2)) ...))) + :multimethods (setmetatable multimethods# + {:__index + (fn [tbl# key#] + (let [eq# ,(eq-fn)] + (var res# nil) + (each [k# v# (pairs tbl#)] + (when (eq# k# key#) + (set res# v#) + (lua :break))) + res#))})})))))) (fn* core.defmethod [multifn dispatch-val & fn-tail] -- cgit v1.2.3